vfio/pci: Fix bootindex
[qemu/ar7.git] / target-mips / translate.c
blobd1de35ad30e26fed645daaef14160cb666439f1e
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;
4755 tcg_gen_shri_tl(t0, t1, lsb);
4756 if (msb != 31) {
4757 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
4758 } else {
4759 tcg_gen_ext32s_tl(t0, t0);
4761 break;
4762 #if defined(TARGET_MIPS64)
4763 case OPC_DEXTM:
4764 tcg_gen_shri_tl(t0, t1, lsb);
4765 if (msb != 31) {
4766 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
4768 break;
4769 case OPC_DEXTU:
4770 tcg_gen_shri_tl(t0, t1, lsb + 32);
4771 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4772 break;
4773 case OPC_DEXT:
4774 tcg_gen_shri_tl(t0, t1, lsb);
4775 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4776 break;
4777 #endif
4778 case OPC_INS:
4779 if (lsb > msb)
4780 goto fail;
4781 gen_load_gpr(t0, rt);
4782 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4783 tcg_gen_ext32s_tl(t0, t0);
4784 break;
4785 #if defined(TARGET_MIPS64)
4786 case OPC_DINSM:
4787 gen_load_gpr(t0, rt);
4788 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb + 32 - lsb + 1);
4789 break;
4790 case OPC_DINSU:
4791 gen_load_gpr(t0, rt);
4792 tcg_gen_deposit_tl(t0, t0, t1, lsb + 32, msb - lsb + 1);
4793 break;
4794 case OPC_DINS:
4795 gen_load_gpr(t0, rt);
4796 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4797 break;
4798 #endif
4799 default:
4800 fail:
4801 MIPS_INVAL("bitops");
4802 generate_exception(ctx, EXCP_RI);
4803 tcg_temp_free(t0);
4804 tcg_temp_free(t1);
4805 return;
4807 gen_store_gpr(t0, rt);
4808 tcg_temp_free(t0);
4809 tcg_temp_free(t1);
4812 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4814 TCGv t0;
4816 if (rd == 0) {
4817 /* If no destination, treat it as a NOP. */
4818 MIPS_DEBUG("NOP");
4819 return;
4822 t0 = tcg_temp_new();
4823 gen_load_gpr(t0, rt);
4824 switch (op2) {
4825 case OPC_WSBH:
4827 TCGv t1 = tcg_temp_new();
4829 tcg_gen_shri_tl(t1, t0, 8);
4830 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4831 tcg_gen_shli_tl(t0, t0, 8);
4832 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4833 tcg_gen_or_tl(t0, t0, t1);
4834 tcg_temp_free(t1);
4835 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4837 break;
4838 case OPC_SEB:
4839 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4840 break;
4841 case OPC_SEH:
4842 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4843 break;
4844 #if defined(TARGET_MIPS64)
4845 case OPC_DSBH:
4847 TCGv t1 = tcg_temp_new();
4849 tcg_gen_shri_tl(t1, t0, 8);
4850 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4851 tcg_gen_shli_tl(t0, t0, 8);
4852 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4853 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4854 tcg_temp_free(t1);
4856 break;
4857 case OPC_DSHD:
4859 TCGv t1 = tcg_temp_new();
4861 tcg_gen_shri_tl(t1, t0, 16);
4862 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4863 tcg_gen_shli_tl(t0, t0, 16);
4864 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4865 tcg_gen_or_tl(t0, t0, t1);
4866 tcg_gen_shri_tl(t1, t0, 32);
4867 tcg_gen_shli_tl(t0, t0, 32);
4868 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4869 tcg_temp_free(t1);
4871 break;
4872 #endif
4873 default:
4874 MIPS_INVAL("bsfhl");
4875 generate_exception(ctx, EXCP_RI);
4876 tcg_temp_free(t0);
4877 return;
4879 tcg_temp_free(t0);
4882 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4883 int imm2)
4885 TCGv t0;
4886 TCGv t1;
4887 if (rd == 0) {
4888 /* Treat as NOP. */
4889 return;
4891 t0 = tcg_temp_new();
4892 t1 = tcg_temp_new();
4893 gen_load_gpr(t0, rs);
4894 gen_load_gpr(t1, rt);
4895 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4896 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4897 if (opc == OPC_LSA) {
4898 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4901 tcg_temp_free(t1);
4902 tcg_temp_free(t0);
4904 return;
4907 static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt,
4908 int bp)
4910 TCGv t0;
4911 if (rd == 0) {
4912 /* Treat as NOP. */
4913 return;
4915 t0 = tcg_temp_new();
4916 gen_load_gpr(t0, rt);
4917 if (bp == 0) {
4918 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4919 } else {
4920 TCGv t1 = tcg_temp_new();
4921 gen_load_gpr(t1, rs);
4922 switch (opc) {
4923 case OPC_ALIGN:
4925 TCGv_i64 t2 = tcg_temp_new_i64();
4926 tcg_gen_concat_tl_i64(t2, t1, t0);
4927 tcg_gen_shri_i64(t2, t2, 8 * (4 - bp));
4928 gen_move_low32(cpu_gpr[rd], t2);
4929 tcg_temp_free_i64(t2);
4931 break;
4932 #if defined(TARGET_MIPS64)
4933 case OPC_DALIGN:
4934 tcg_gen_shli_tl(t0, t0, 8 * bp);
4935 tcg_gen_shri_tl(t1, t1, 8 * (8 - bp));
4936 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
4937 break;
4938 #endif
4940 tcg_temp_free(t1);
4943 tcg_temp_free(t0);
4946 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
4948 TCGv t0;
4949 if (rd == 0) {
4950 /* Treat as NOP. */
4951 return;
4953 t0 = tcg_temp_new();
4954 gen_load_gpr(t0, rt);
4955 switch (opc) {
4956 case OPC_BITSWAP:
4957 gen_helper_bitswap(cpu_gpr[rd], t0);
4958 break;
4959 #if defined(TARGET_MIPS64)
4960 case OPC_DBITSWAP:
4961 gen_helper_dbitswap(cpu_gpr[rd], t0);
4962 break;
4963 #endif
4965 tcg_temp_free(t0);
4968 #ifndef CONFIG_USER_ONLY
4969 /* CP0 (MMU and control) */
4970 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4972 TCGv_i64 t0 = tcg_temp_new_i64();
4973 TCGv_i64 t1 = tcg_temp_new_i64();
4975 tcg_gen_ext_tl_i64(t0, arg);
4976 tcg_gen_ld_i64(t1, cpu_env, off);
4977 #if defined(TARGET_MIPS64)
4978 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4979 #else
4980 tcg_gen_concat32_i64(t1, t1, t0);
4981 #endif
4982 tcg_gen_st_i64(t1, cpu_env, off);
4983 tcg_temp_free_i64(t1);
4984 tcg_temp_free_i64(t0);
4987 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4989 TCGv_i64 t0 = tcg_temp_new_i64();
4990 TCGv_i64 t1 = tcg_temp_new_i64();
4992 tcg_gen_ext_tl_i64(t0, arg);
4993 tcg_gen_ld_i64(t1, cpu_env, off);
4994 tcg_gen_concat32_i64(t1, t1, t0);
4995 tcg_gen_st_i64(t1, cpu_env, off);
4996 tcg_temp_free_i64(t1);
4997 tcg_temp_free_i64(t0);
5000 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5002 TCGv_i64 t0 = tcg_temp_new_i64();
5004 tcg_gen_ld_i64(t0, cpu_env, off);
5005 #if defined(TARGET_MIPS64)
5006 tcg_gen_shri_i64(t0, t0, 30);
5007 #else
5008 tcg_gen_shri_i64(t0, t0, 32);
5009 #endif
5010 gen_move_low32(arg, t0);
5011 tcg_temp_free_i64(t0);
5014 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5016 TCGv_i64 t0 = tcg_temp_new_i64();
5018 tcg_gen_ld_i64(t0, cpu_env, off);
5019 tcg_gen_shri_i64(t0, t0, 32 + shift);
5020 gen_move_low32(arg, t0);
5021 tcg_temp_free_i64(t0);
5024 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
5026 TCGv_i32 t0 = tcg_temp_new_i32();
5028 tcg_gen_ld_i32(t0, cpu_env, off);
5029 tcg_gen_ext_i32_tl(arg, t0);
5030 tcg_temp_free_i32(t0);
5033 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
5035 tcg_gen_ld_tl(arg, cpu_env, off);
5036 tcg_gen_ext32s_tl(arg, arg);
5039 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
5041 TCGv_i32 t0 = tcg_temp_new_i32();
5043 tcg_gen_trunc_tl_i32(t0, arg);
5044 tcg_gen_st_i32(t0, cpu_env, off);
5045 tcg_temp_free_i32(t0);
5048 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
5050 tcg_gen_ext32s_tl(arg, arg);
5051 tcg_gen_st_tl(arg, cpu_env, off);
5054 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5056 const char *rn = "invalid";
5058 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
5059 goto mfhc0_read_zero;
5062 switch (reg) {
5063 case 2:
5064 switch (sel) {
5065 case 0:
5066 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5067 rn = "EntryLo0";
5068 break;
5069 default:
5070 goto mfhc0_read_zero;
5072 break;
5073 case 3:
5074 switch (sel) {
5075 case 0:
5076 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5077 rn = "EntryLo1";
5078 break;
5079 default:
5080 goto mfhc0_read_zero;
5082 break;
5083 case 17:
5084 switch (sel) {
5085 case 0:
5086 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
5087 ctx->CP0_LLAddr_shift);
5088 rn = "LLAddr";
5089 break;
5090 default:
5091 goto mfhc0_read_zero;
5093 break;
5094 case 28:
5095 switch (sel) {
5096 case 0:
5097 case 2:
5098 case 4:
5099 case 6:
5100 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5101 rn = "TagLo";
5102 break;
5103 default:
5104 goto mfhc0_read_zero;
5106 break;
5107 default:
5108 goto mfhc0_read_zero;
5111 (void)rn; /* avoid a compiler warning */
5112 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5113 return;
5115 mfhc0_read_zero:
5116 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5117 tcg_gen_movi_tl(arg, 0);
5120 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5122 const char *rn = "invalid";
5123 uint64_t mask = ctx->PAMask >> 36;
5125 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
5126 goto mthc0_nop;
5129 switch (reg) {
5130 case 2:
5131 switch (sel) {
5132 case 0:
5133 tcg_gen_andi_tl(arg, arg, mask);
5134 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5135 rn = "EntryLo0";
5136 break;
5137 default:
5138 goto mthc0_nop;
5140 break;
5141 case 3:
5142 switch (sel) {
5143 case 0:
5144 tcg_gen_andi_tl(arg, arg, mask);
5145 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5146 rn = "EntryLo1";
5147 break;
5148 default:
5149 goto mthc0_nop;
5151 break;
5152 case 17:
5153 switch (sel) {
5154 case 0:
5155 /* LLAddr is read-only (the only exception is bit 0 if LLB is
5156 supported); the CP0_LLAddr_rw_bitmask does not seem to be
5157 relevant for modern MIPS cores supporting MTHC0, therefore
5158 treating MTHC0 to LLAddr as NOP. */
5159 rn = "LLAddr";
5160 break;
5161 default:
5162 goto mthc0_nop;
5164 break;
5165 case 28:
5166 switch (sel) {
5167 case 0:
5168 case 2:
5169 case 4:
5170 case 6:
5171 tcg_gen_andi_tl(arg, arg, mask);
5172 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5173 rn = "TagLo";
5174 break;
5175 default:
5176 goto mthc0_nop;
5178 break;
5179 default:
5180 goto mthc0_nop;
5183 (void)rn; /* avoid a compiler warning */
5184 mthc0_nop:
5185 LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
5188 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5190 if (ctx->insn_flags & ISA_MIPS32R6) {
5191 tcg_gen_movi_tl(arg, 0);
5192 } else {
5193 tcg_gen_movi_tl(arg, ~0);
5197 #define CP0_CHECK(c) \
5198 do { \
5199 if (!(c)) { \
5200 goto cp0_unimplemented; \
5202 } while (0)
5204 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5206 const char *rn = "invalid";
5208 if (sel != 0)
5209 check_insn(ctx, ISA_MIPS32);
5211 switch (reg) {
5212 case 0:
5213 switch (sel) {
5214 case 0:
5215 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5216 rn = "Index";
5217 break;
5218 case 1:
5219 CP0_CHECK(ctx->insn_flags & ASE_MT);
5220 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5221 rn = "MVPControl";
5222 break;
5223 case 2:
5224 CP0_CHECK(ctx->insn_flags & ASE_MT);
5225 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5226 rn = "MVPConf0";
5227 break;
5228 case 3:
5229 CP0_CHECK(ctx->insn_flags & ASE_MT);
5230 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5231 rn = "MVPConf1";
5232 break;
5233 default:
5234 goto cp0_unimplemented;
5236 break;
5237 case 1:
5238 switch (sel) {
5239 case 0:
5240 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5241 gen_helper_mfc0_random(arg, cpu_env);
5242 rn = "Random";
5243 break;
5244 case 1:
5245 CP0_CHECK(ctx->insn_flags & ASE_MT);
5246 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5247 rn = "VPEControl";
5248 break;
5249 case 2:
5250 CP0_CHECK(ctx->insn_flags & ASE_MT);
5251 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5252 rn = "VPEConf0";
5253 break;
5254 case 3:
5255 CP0_CHECK(ctx->insn_flags & ASE_MT);
5256 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5257 rn = "VPEConf1";
5258 break;
5259 case 4:
5260 CP0_CHECK(ctx->insn_flags & ASE_MT);
5261 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5262 rn = "YQMask";
5263 break;
5264 case 5:
5265 CP0_CHECK(ctx->insn_flags & ASE_MT);
5266 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5267 rn = "VPESchedule";
5268 break;
5269 case 6:
5270 CP0_CHECK(ctx->insn_flags & ASE_MT);
5271 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5272 rn = "VPEScheFBack";
5273 break;
5274 case 7:
5275 CP0_CHECK(ctx->insn_flags & ASE_MT);
5276 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5277 rn = "VPEOpt";
5278 break;
5279 default:
5280 goto cp0_unimplemented;
5282 break;
5283 case 2:
5284 switch (sel) {
5285 case 0:
5287 TCGv_i64 tmp = tcg_temp_new_i64();
5288 tcg_gen_ld_i64(tmp, cpu_env,
5289 offsetof(CPUMIPSState, CP0_EntryLo0));
5290 #if defined(TARGET_MIPS64)
5291 if (ctx->rxi) {
5292 /* Move RI/XI fields to bits 31:30 */
5293 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5294 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5296 #endif
5297 gen_move_low32(arg, tmp);
5298 tcg_temp_free_i64(tmp);
5300 rn = "EntryLo0";
5301 break;
5302 case 1:
5303 CP0_CHECK(ctx->insn_flags & ASE_MT);
5304 gen_helper_mfc0_tcstatus(arg, cpu_env);
5305 rn = "TCStatus";
5306 break;
5307 case 2:
5308 CP0_CHECK(ctx->insn_flags & ASE_MT);
5309 gen_helper_mfc0_tcbind(arg, cpu_env);
5310 rn = "TCBind";
5311 break;
5312 case 3:
5313 CP0_CHECK(ctx->insn_flags & ASE_MT);
5314 gen_helper_mfc0_tcrestart(arg, cpu_env);
5315 rn = "TCRestart";
5316 break;
5317 case 4:
5318 CP0_CHECK(ctx->insn_flags & ASE_MT);
5319 gen_helper_mfc0_tchalt(arg, cpu_env);
5320 rn = "TCHalt";
5321 break;
5322 case 5:
5323 CP0_CHECK(ctx->insn_flags & ASE_MT);
5324 gen_helper_mfc0_tccontext(arg, cpu_env);
5325 rn = "TCContext";
5326 break;
5327 case 6:
5328 CP0_CHECK(ctx->insn_flags & ASE_MT);
5329 gen_helper_mfc0_tcschedule(arg, cpu_env);
5330 rn = "TCSchedule";
5331 break;
5332 case 7:
5333 CP0_CHECK(ctx->insn_flags & ASE_MT);
5334 gen_helper_mfc0_tcschefback(arg, cpu_env);
5335 rn = "TCScheFBack";
5336 break;
5337 default:
5338 goto cp0_unimplemented;
5340 break;
5341 case 3:
5342 switch (sel) {
5343 case 0:
5345 TCGv_i64 tmp = tcg_temp_new_i64();
5346 tcg_gen_ld_i64(tmp, cpu_env,
5347 offsetof(CPUMIPSState, CP0_EntryLo1));
5348 #if defined(TARGET_MIPS64)
5349 if (ctx->rxi) {
5350 /* Move RI/XI fields to bits 31:30 */
5351 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5352 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5354 #endif
5355 gen_move_low32(arg, tmp);
5356 tcg_temp_free_i64(tmp);
5358 rn = "EntryLo1";
5359 break;
5360 default:
5361 goto cp0_unimplemented;
5363 break;
5364 case 4:
5365 switch (sel) {
5366 case 0:
5367 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5368 tcg_gen_ext32s_tl(arg, arg);
5369 rn = "Context";
5370 break;
5371 case 1:
5372 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5373 rn = "ContextConfig";
5374 goto cp0_unimplemented;
5375 // break;
5376 case 2:
5377 CP0_CHECK(ctx->ulri);
5378 tcg_gen_ld32s_tl(arg, cpu_env,
5379 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5380 rn = "UserLocal";
5381 break;
5382 default:
5383 goto cp0_unimplemented;
5385 break;
5386 case 5:
5387 switch (sel) {
5388 case 0:
5389 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5390 rn = "PageMask";
5391 break;
5392 case 1:
5393 check_insn(ctx, ISA_MIPS32R2);
5394 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5395 rn = "PageGrain";
5396 break;
5397 default:
5398 goto cp0_unimplemented;
5400 break;
5401 case 6:
5402 switch (sel) {
5403 case 0:
5404 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5405 rn = "Wired";
5406 break;
5407 case 1:
5408 check_insn(ctx, ISA_MIPS32R2);
5409 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5410 rn = "SRSConf0";
5411 break;
5412 case 2:
5413 check_insn(ctx, ISA_MIPS32R2);
5414 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5415 rn = "SRSConf1";
5416 break;
5417 case 3:
5418 check_insn(ctx, ISA_MIPS32R2);
5419 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5420 rn = "SRSConf2";
5421 break;
5422 case 4:
5423 check_insn(ctx, ISA_MIPS32R2);
5424 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5425 rn = "SRSConf3";
5426 break;
5427 case 5:
5428 check_insn(ctx, ISA_MIPS32R2);
5429 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5430 rn = "SRSConf4";
5431 break;
5432 default:
5433 goto cp0_unimplemented;
5435 break;
5436 case 7:
5437 switch (sel) {
5438 case 0:
5439 check_insn(ctx, ISA_MIPS32R2);
5440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5441 rn = "HWREna";
5442 break;
5443 default:
5444 goto cp0_unimplemented;
5446 break;
5447 case 8:
5448 switch (sel) {
5449 case 0:
5450 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5451 tcg_gen_ext32s_tl(arg, arg);
5452 rn = "BadVAddr";
5453 break;
5454 case 1:
5455 CP0_CHECK(ctx->bi);
5456 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5457 rn = "BadInstr";
5458 break;
5459 case 2:
5460 CP0_CHECK(ctx->bp);
5461 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5462 rn = "BadInstrP";
5463 break;
5464 default:
5465 goto cp0_unimplemented;
5467 break;
5468 case 9:
5469 switch (sel) {
5470 case 0:
5471 /* Mark as an IO operation because we read the time. */
5472 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5473 gen_io_start();
5475 gen_helper_mfc0_count(arg, cpu_env);
5476 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5477 gen_io_end();
5479 /* Break the TB to be able to take timer interrupts immediately
5480 after reading count. */
5481 ctx->bstate = BS_STOP;
5482 rn = "Count";
5483 break;
5484 /* 6,7 are implementation dependent */
5485 default:
5486 goto cp0_unimplemented;
5488 break;
5489 case 10:
5490 switch (sel) {
5491 case 0:
5492 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5493 tcg_gen_ext32s_tl(arg, arg);
5494 rn = "EntryHi";
5495 break;
5496 default:
5497 goto cp0_unimplemented;
5499 break;
5500 case 11:
5501 switch (sel) {
5502 case 0:
5503 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5504 rn = "Compare";
5505 break;
5506 /* 6,7 are implementation dependent */
5507 default:
5508 goto cp0_unimplemented;
5510 break;
5511 case 12:
5512 switch (sel) {
5513 case 0:
5514 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5515 rn = "Status";
5516 break;
5517 case 1:
5518 check_insn(ctx, ISA_MIPS32R2);
5519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5520 rn = "IntCtl";
5521 break;
5522 case 2:
5523 check_insn(ctx, ISA_MIPS32R2);
5524 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5525 rn = "SRSCtl";
5526 break;
5527 case 3:
5528 check_insn(ctx, ISA_MIPS32R2);
5529 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5530 rn = "SRSMap";
5531 break;
5532 default:
5533 goto cp0_unimplemented;
5535 break;
5536 case 13:
5537 switch (sel) {
5538 case 0:
5539 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5540 rn = "Cause";
5541 break;
5542 default:
5543 goto cp0_unimplemented;
5545 break;
5546 case 14:
5547 switch (sel) {
5548 case 0:
5549 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5550 tcg_gen_ext32s_tl(arg, arg);
5551 rn = "EPC";
5552 break;
5553 default:
5554 goto cp0_unimplemented;
5556 break;
5557 case 15:
5558 switch (sel) {
5559 case 0:
5560 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5561 rn = "PRid";
5562 break;
5563 case 1:
5564 check_insn(ctx, ISA_MIPS32R2);
5565 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5566 rn = "EBase";
5567 break;
5568 default:
5569 goto cp0_unimplemented;
5571 break;
5572 case 16:
5573 switch (sel) {
5574 case 0:
5575 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5576 rn = "Config";
5577 break;
5578 case 1:
5579 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5580 rn = "Config1";
5581 break;
5582 case 2:
5583 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5584 rn = "Config2";
5585 break;
5586 case 3:
5587 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5588 rn = "Config3";
5589 break;
5590 case 4:
5591 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5592 rn = "Config4";
5593 break;
5594 case 5:
5595 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5596 rn = "Config5";
5597 break;
5598 /* 6,7 are implementation dependent */
5599 case 6:
5600 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5601 rn = "Config6";
5602 break;
5603 case 7:
5604 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5605 rn = "Config7";
5606 break;
5607 default:
5608 goto cp0_unimplemented;
5610 break;
5611 case 17:
5612 switch (sel) {
5613 case 0:
5614 gen_helper_mfc0_lladdr(arg, cpu_env);
5615 rn = "LLAddr";
5616 break;
5617 default:
5618 goto cp0_unimplemented;
5620 break;
5621 case 18:
5622 switch (sel) {
5623 case 0 ... 7:
5624 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5625 rn = "WatchLo";
5626 break;
5627 default:
5628 goto cp0_unimplemented;
5630 break;
5631 case 19:
5632 switch (sel) {
5633 case 0 ...7:
5634 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5635 rn = "WatchHi";
5636 break;
5637 default:
5638 goto cp0_unimplemented;
5640 break;
5641 case 20:
5642 switch (sel) {
5643 case 0:
5644 #if defined(TARGET_MIPS64)
5645 check_insn(ctx, ISA_MIPS3);
5646 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5647 tcg_gen_ext32s_tl(arg, arg);
5648 rn = "XContext";
5649 break;
5650 #endif
5651 default:
5652 goto cp0_unimplemented;
5654 break;
5655 case 21:
5656 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5657 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5658 switch (sel) {
5659 case 0:
5660 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5661 rn = "Framemask";
5662 break;
5663 default:
5664 goto cp0_unimplemented;
5666 break;
5667 case 22:
5668 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5669 rn = "'Diagnostic"; /* implementation dependent */
5670 break;
5671 case 23:
5672 switch (sel) {
5673 case 0:
5674 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5675 rn = "Debug";
5676 break;
5677 case 1:
5678 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5679 rn = "TraceControl";
5680 // break;
5681 case 2:
5682 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5683 rn = "TraceControl2";
5684 // break;
5685 case 3:
5686 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5687 rn = "UserTraceData";
5688 // break;
5689 case 4:
5690 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5691 rn = "TraceBPC";
5692 // break;
5693 default:
5694 goto cp0_unimplemented;
5696 break;
5697 case 24:
5698 switch (sel) {
5699 case 0:
5700 /* EJTAG support */
5701 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5702 tcg_gen_ext32s_tl(arg, arg);
5703 rn = "DEPC";
5704 break;
5705 default:
5706 goto cp0_unimplemented;
5708 break;
5709 case 25:
5710 switch (sel) {
5711 case 0:
5712 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5713 rn = "Performance0";
5714 break;
5715 case 1:
5716 // gen_helper_mfc0_performance1(arg);
5717 rn = "Performance1";
5718 // break;
5719 case 2:
5720 // gen_helper_mfc0_performance2(arg);
5721 rn = "Performance2";
5722 // break;
5723 case 3:
5724 // gen_helper_mfc0_performance3(arg);
5725 rn = "Performance3";
5726 // break;
5727 case 4:
5728 // gen_helper_mfc0_performance4(arg);
5729 rn = "Performance4";
5730 // break;
5731 case 5:
5732 // gen_helper_mfc0_performance5(arg);
5733 rn = "Performance5";
5734 // break;
5735 case 6:
5736 // gen_helper_mfc0_performance6(arg);
5737 rn = "Performance6";
5738 // break;
5739 case 7:
5740 // gen_helper_mfc0_performance7(arg);
5741 rn = "Performance7";
5742 // break;
5743 default:
5744 goto cp0_unimplemented;
5746 break;
5747 case 26:
5748 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5749 rn = "ECC";
5750 break;
5751 case 27:
5752 switch (sel) {
5753 case 0 ... 3:
5754 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5755 rn = "CacheErr";
5756 break;
5757 default:
5758 goto cp0_unimplemented;
5760 break;
5761 case 28:
5762 switch (sel) {
5763 case 0:
5764 case 2:
5765 case 4:
5766 case 6:
5768 TCGv_i64 tmp = tcg_temp_new_i64();
5769 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5770 gen_move_low32(arg, tmp);
5771 tcg_temp_free_i64(tmp);
5773 rn = "TagLo";
5774 break;
5775 case 1:
5776 case 3:
5777 case 5:
5778 case 7:
5779 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5780 rn = "DataLo";
5781 break;
5782 default:
5783 goto cp0_unimplemented;
5785 break;
5786 case 29:
5787 switch (sel) {
5788 case 0:
5789 case 2:
5790 case 4:
5791 case 6:
5792 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5793 rn = "TagHi";
5794 break;
5795 case 1:
5796 case 3:
5797 case 5:
5798 case 7:
5799 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5800 rn = "DataHi";
5801 break;
5802 default:
5803 goto cp0_unimplemented;
5805 break;
5806 case 30:
5807 switch (sel) {
5808 case 0:
5809 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5810 tcg_gen_ext32s_tl(arg, arg);
5811 rn = "ErrorEPC";
5812 break;
5813 default:
5814 goto cp0_unimplemented;
5816 break;
5817 case 31:
5818 switch (sel) {
5819 case 0:
5820 /* EJTAG support */
5821 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5822 rn = "DESAVE";
5823 break;
5824 case 2 ... 7:
5825 CP0_CHECK(ctx->kscrexist & (1 << sel));
5826 tcg_gen_ld_tl(arg, cpu_env,
5827 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5828 tcg_gen_ext32s_tl(arg, arg);
5829 rn = "KScratch";
5830 break;
5831 default:
5832 goto cp0_unimplemented;
5834 break;
5835 default:
5836 goto cp0_unimplemented;
5838 (void)rn; /* avoid a compiler warning */
5839 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5840 return;
5842 cp0_unimplemented:
5843 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5844 gen_mfc0_unimplemented(ctx, arg);
5847 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5849 const char *rn = "invalid";
5851 if (sel != 0)
5852 check_insn(ctx, ISA_MIPS32);
5854 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5855 gen_io_start();
5858 switch (reg) {
5859 case 0:
5860 switch (sel) {
5861 case 0:
5862 gen_helper_mtc0_index(cpu_env, arg);
5863 rn = "Index";
5864 break;
5865 case 1:
5866 CP0_CHECK(ctx->insn_flags & ASE_MT);
5867 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5868 rn = "MVPControl";
5869 break;
5870 case 2:
5871 CP0_CHECK(ctx->insn_flags & ASE_MT);
5872 /* ignored */
5873 rn = "MVPConf0";
5874 break;
5875 case 3:
5876 CP0_CHECK(ctx->insn_flags & ASE_MT);
5877 /* ignored */
5878 rn = "MVPConf1";
5879 break;
5880 default:
5881 goto cp0_unimplemented;
5883 break;
5884 case 1:
5885 switch (sel) {
5886 case 0:
5887 /* ignored */
5888 rn = "Random";
5889 break;
5890 case 1:
5891 CP0_CHECK(ctx->insn_flags & ASE_MT);
5892 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5893 rn = "VPEControl";
5894 break;
5895 case 2:
5896 CP0_CHECK(ctx->insn_flags & ASE_MT);
5897 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5898 rn = "VPEConf0";
5899 break;
5900 case 3:
5901 CP0_CHECK(ctx->insn_flags & ASE_MT);
5902 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5903 rn = "VPEConf1";
5904 break;
5905 case 4:
5906 CP0_CHECK(ctx->insn_flags & ASE_MT);
5907 gen_helper_mtc0_yqmask(cpu_env, arg);
5908 rn = "YQMask";
5909 break;
5910 case 5:
5911 CP0_CHECK(ctx->insn_flags & ASE_MT);
5912 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5913 rn = "VPESchedule";
5914 break;
5915 case 6:
5916 CP0_CHECK(ctx->insn_flags & ASE_MT);
5917 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5918 rn = "VPEScheFBack";
5919 break;
5920 case 7:
5921 CP0_CHECK(ctx->insn_flags & ASE_MT);
5922 gen_helper_mtc0_vpeopt(cpu_env, arg);
5923 rn = "VPEOpt";
5924 break;
5925 default:
5926 goto cp0_unimplemented;
5928 break;
5929 case 2:
5930 switch (sel) {
5931 case 0:
5932 gen_helper_mtc0_entrylo0(cpu_env, arg);
5933 rn = "EntryLo0";
5934 break;
5935 case 1:
5936 CP0_CHECK(ctx->insn_flags & ASE_MT);
5937 gen_helper_mtc0_tcstatus(cpu_env, arg);
5938 rn = "TCStatus";
5939 break;
5940 case 2:
5941 CP0_CHECK(ctx->insn_flags & ASE_MT);
5942 gen_helper_mtc0_tcbind(cpu_env, arg);
5943 rn = "TCBind";
5944 break;
5945 case 3:
5946 CP0_CHECK(ctx->insn_flags & ASE_MT);
5947 gen_helper_mtc0_tcrestart(cpu_env, arg);
5948 rn = "TCRestart";
5949 break;
5950 case 4:
5951 CP0_CHECK(ctx->insn_flags & ASE_MT);
5952 gen_helper_mtc0_tchalt(cpu_env, arg);
5953 rn = "TCHalt";
5954 break;
5955 case 5:
5956 CP0_CHECK(ctx->insn_flags & ASE_MT);
5957 gen_helper_mtc0_tccontext(cpu_env, arg);
5958 rn = "TCContext";
5959 break;
5960 case 6:
5961 CP0_CHECK(ctx->insn_flags & ASE_MT);
5962 gen_helper_mtc0_tcschedule(cpu_env, arg);
5963 rn = "TCSchedule";
5964 break;
5965 case 7:
5966 CP0_CHECK(ctx->insn_flags & ASE_MT);
5967 gen_helper_mtc0_tcschefback(cpu_env, arg);
5968 rn = "TCScheFBack";
5969 break;
5970 default:
5971 goto cp0_unimplemented;
5973 break;
5974 case 3:
5975 switch (sel) {
5976 case 0:
5977 gen_helper_mtc0_entrylo1(cpu_env, arg);
5978 rn = "EntryLo1";
5979 break;
5980 default:
5981 goto cp0_unimplemented;
5983 break;
5984 case 4:
5985 switch (sel) {
5986 case 0:
5987 gen_helper_mtc0_context(cpu_env, arg);
5988 rn = "Context";
5989 break;
5990 case 1:
5991 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5992 rn = "ContextConfig";
5993 goto cp0_unimplemented;
5994 // break;
5995 case 2:
5996 CP0_CHECK(ctx->ulri);
5997 tcg_gen_st_tl(arg, cpu_env,
5998 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5999 rn = "UserLocal";
6000 break;
6001 default:
6002 goto cp0_unimplemented;
6004 break;
6005 case 5:
6006 switch (sel) {
6007 case 0:
6008 gen_helper_mtc0_pagemask(cpu_env, arg);
6009 rn = "PageMask";
6010 break;
6011 case 1:
6012 check_insn(ctx, ISA_MIPS32R2);
6013 gen_helper_mtc0_pagegrain(cpu_env, arg);
6014 rn = "PageGrain";
6015 ctx->bstate = BS_STOP;
6016 break;
6017 default:
6018 goto cp0_unimplemented;
6020 break;
6021 case 6:
6022 switch (sel) {
6023 case 0:
6024 gen_helper_mtc0_wired(cpu_env, arg);
6025 rn = "Wired";
6026 break;
6027 case 1:
6028 check_insn(ctx, ISA_MIPS32R2);
6029 gen_helper_mtc0_srsconf0(cpu_env, arg);
6030 rn = "SRSConf0";
6031 break;
6032 case 2:
6033 check_insn(ctx, ISA_MIPS32R2);
6034 gen_helper_mtc0_srsconf1(cpu_env, arg);
6035 rn = "SRSConf1";
6036 break;
6037 case 3:
6038 check_insn(ctx, ISA_MIPS32R2);
6039 gen_helper_mtc0_srsconf2(cpu_env, arg);
6040 rn = "SRSConf2";
6041 break;
6042 case 4:
6043 check_insn(ctx, ISA_MIPS32R2);
6044 gen_helper_mtc0_srsconf3(cpu_env, arg);
6045 rn = "SRSConf3";
6046 break;
6047 case 5:
6048 check_insn(ctx, ISA_MIPS32R2);
6049 gen_helper_mtc0_srsconf4(cpu_env, arg);
6050 rn = "SRSConf4";
6051 break;
6052 default:
6053 goto cp0_unimplemented;
6055 break;
6056 case 7:
6057 switch (sel) {
6058 case 0:
6059 check_insn(ctx, ISA_MIPS32R2);
6060 gen_helper_mtc0_hwrena(cpu_env, arg);
6061 ctx->bstate = BS_STOP;
6062 rn = "HWREna";
6063 break;
6064 default:
6065 goto cp0_unimplemented;
6067 break;
6068 case 8:
6069 switch (sel) {
6070 case 0:
6071 /* ignored */
6072 rn = "BadVAddr";
6073 break;
6074 case 1:
6075 /* ignored */
6076 rn = "BadInstr";
6077 break;
6078 case 2:
6079 /* ignored */
6080 rn = "BadInstrP";
6081 break;
6082 default:
6083 goto cp0_unimplemented;
6085 break;
6086 case 9:
6087 switch (sel) {
6088 case 0:
6089 gen_helper_mtc0_count(cpu_env, arg);
6090 rn = "Count";
6091 break;
6092 /* 6,7 are implementation dependent */
6093 default:
6094 goto cp0_unimplemented;
6096 break;
6097 case 10:
6098 switch (sel) {
6099 case 0:
6100 gen_helper_mtc0_entryhi(cpu_env, arg);
6101 rn = "EntryHi";
6102 break;
6103 default:
6104 goto cp0_unimplemented;
6106 break;
6107 case 11:
6108 switch (sel) {
6109 case 0:
6110 gen_helper_mtc0_compare(cpu_env, arg);
6111 rn = "Compare";
6112 break;
6113 /* 6,7 are implementation dependent */
6114 default:
6115 goto cp0_unimplemented;
6117 break;
6118 case 12:
6119 switch (sel) {
6120 case 0:
6121 save_cpu_state(ctx, 1);
6122 gen_helper_mtc0_status(cpu_env, arg);
6123 /* BS_STOP isn't good enough here, hflags may have changed. */
6124 gen_save_pc(ctx->pc + 4);
6125 ctx->bstate = BS_EXCP;
6126 rn = "Status";
6127 break;
6128 case 1:
6129 check_insn(ctx, ISA_MIPS32R2);
6130 gen_helper_mtc0_intctl(cpu_env, arg);
6131 /* Stop translation as we may have switched the execution mode */
6132 ctx->bstate = BS_STOP;
6133 rn = "IntCtl";
6134 break;
6135 case 2:
6136 check_insn(ctx, ISA_MIPS32R2);
6137 gen_helper_mtc0_srsctl(cpu_env, arg);
6138 /* Stop translation as we may have switched the execution mode */
6139 ctx->bstate = BS_STOP;
6140 rn = "SRSCtl";
6141 break;
6142 case 3:
6143 check_insn(ctx, ISA_MIPS32R2);
6144 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6145 /* Stop translation as we may have switched the execution mode */
6146 ctx->bstate = BS_STOP;
6147 rn = "SRSMap";
6148 break;
6149 default:
6150 goto cp0_unimplemented;
6152 break;
6153 case 13:
6154 switch (sel) {
6155 case 0:
6156 save_cpu_state(ctx, 1);
6157 gen_helper_mtc0_cause(cpu_env, arg);
6158 rn = "Cause";
6159 break;
6160 default:
6161 goto cp0_unimplemented;
6163 break;
6164 case 14:
6165 switch (sel) {
6166 case 0:
6167 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
6168 rn = "EPC";
6169 break;
6170 default:
6171 goto cp0_unimplemented;
6173 break;
6174 case 15:
6175 switch (sel) {
6176 case 0:
6177 /* ignored */
6178 rn = "PRid";
6179 break;
6180 case 1:
6181 check_insn(ctx, ISA_MIPS32R2);
6182 gen_helper_mtc0_ebase(cpu_env, arg);
6183 rn = "EBase";
6184 break;
6185 default:
6186 goto cp0_unimplemented;
6188 break;
6189 case 16:
6190 switch (sel) {
6191 case 0:
6192 gen_helper_mtc0_config0(cpu_env, arg);
6193 rn = "Config";
6194 /* Stop translation as we may have switched the execution mode */
6195 ctx->bstate = BS_STOP;
6196 break;
6197 case 1:
6198 /* ignored, read only */
6199 rn = "Config1";
6200 break;
6201 case 2:
6202 gen_helper_mtc0_config2(cpu_env, arg);
6203 rn = "Config2";
6204 /* Stop translation as we may have switched the execution mode */
6205 ctx->bstate = BS_STOP;
6206 break;
6207 case 3:
6208 gen_helper_mtc0_config3(cpu_env, arg);
6209 rn = "Config3";
6210 /* Stop translation as we may have switched the execution mode */
6211 ctx->bstate = BS_STOP;
6212 break;
6213 case 4:
6214 gen_helper_mtc0_config4(cpu_env, arg);
6215 rn = "Config4";
6216 ctx->bstate = BS_STOP;
6217 break;
6218 case 5:
6219 gen_helper_mtc0_config5(cpu_env, arg);
6220 rn = "Config5";
6221 /* Stop translation as we may have switched the execution mode */
6222 ctx->bstate = BS_STOP;
6223 break;
6224 /* 6,7 are implementation dependent */
6225 case 6:
6226 /* ignored */
6227 rn = "Config6";
6228 break;
6229 case 7:
6230 /* ignored */
6231 rn = "Config7";
6232 break;
6233 default:
6234 rn = "Invalid config selector";
6235 goto cp0_unimplemented;
6237 break;
6238 case 17:
6239 switch (sel) {
6240 case 0:
6241 gen_helper_mtc0_lladdr(cpu_env, arg);
6242 rn = "LLAddr";
6243 break;
6244 default:
6245 goto cp0_unimplemented;
6247 break;
6248 case 18:
6249 switch (sel) {
6250 case 0 ... 7:
6251 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6252 rn = "WatchLo";
6253 break;
6254 default:
6255 goto cp0_unimplemented;
6257 break;
6258 case 19:
6259 switch (sel) {
6260 case 0 ... 7:
6261 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6262 rn = "WatchHi";
6263 break;
6264 default:
6265 goto cp0_unimplemented;
6267 break;
6268 case 20:
6269 switch (sel) {
6270 case 0:
6271 #if defined(TARGET_MIPS64)
6272 check_insn(ctx, ISA_MIPS3);
6273 gen_helper_mtc0_xcontext(cpu_env, arg);
6274 rn = "XContext";
6275 break;
6276 #endif
6277 default:
6278 goto cp0_unimplemented;
6280 break;
6281 case 21:
6282 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6283 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6284 switch (sel) {
6285 case 0:
6286 gen_helper_mtc0_framemask(cpu_env, arg);
6287 rn = "Framemask";
6288 break;
6289 default:
6290 goto cp0_unimplemented;
6292 break;
6293 case 22:
6294 /* ignored */
6295 rn = "Diagnostic"; /* implementation dependent */
6296 break;
6297 case 23:
6298 switch (sel) {
6299 case 0:
6300 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6301 /* BS_STOP isn't good enough here, hflags may have changed. */
6302 gen_save_pc(ctx->pc + 4);
6303 ctx->bstate = BS_EXCP;
6304 rn = "Debug";
6305 break;
6306 case 1:
6307 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6308 rn = "TraceControl";
6309 /* Stop translation as we may have switched the execution mode */
6310 ctx->bstate = BS_STOP;
6311 // break;
6312 case 2:
6313 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6314 rn = "TraceControl2";
6315 /* Stop translation as we may have switched the execution mode */
6316 ctx->bstate = BS_STOP;
6317 // break;
6318 case 3:
6319 /* Stop translation as we may have switched the execution mode */
6320 ctx->bstate = BS_STOP;
6321 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6322 rn = "UserTraceData";
6323 /* Stop translation as we may have switched the execution mode */
6324 ctx->bstate = BS_STOP;
6325 // break;
6326 case 4:
6327 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6328 /* Stop translation as we may have switched the execution mode */
6329 ctx->bstate = BS_STOP;
6330 rn = "TraceBPC";
6331 // break;
6332 default:
6333 goto cp0_unimplemented;
6335 break;
6336 case 24:
6337 switch (sel) {
6338 case 0:
6339 /* EJTAG support */
6340 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
6341 rn = "DEPC";
6342 break;
6343 default:
6344 goto cp0_unimplemented;
6346 break;
6347 case 25:
6348 switch (sel) {
6349 case 0:
6350 gen_helper_mtc0_performance0(cpu_env, arg);
6351 rn = "Performance0";
6352 break;
6353 case 1:
6354 // gen_helper_mtc0_performance1(arg);
6355 rn = "Performance1";
6356 // break;
6357 case 2:
6358 // gen_helper_mtc0_performance2(arg);
6359 rn = "Performance2";
6360 // break;
6361 case 3:
6362 // gen_helper_mtc0_performance3(arg);
6363 rn = "Performance3";
6364 // break;
6365 case 4:
6366 // gen_helper_mtc0_performance4(arg);
6367 rn = "Performance4";
6368 // break;
6369 case 5:
6370 // gen_helper_mtc0_performance5(arg);
6371 rn = "Performance5";
6372 // break;
6373 case 6:
6374 // gen_helper_mtc0_performance6(arg);
6375 rn = "Performance6";
6376 // break;
6377 case 7:
6378 // gen_helper_mtc0_performance7(arg);
6379 rn = "Performance7";
6380 // break;
6381 default:
6382 goto cp0_unimplemented;
6384 break;
6385 case 26:
6386 /* ignored */
6387 rn = "ECC";
6388 break;
6389 case 27:
6390 switch (sel) {
6391 case 0 ... 3:
6392 /* ignored */
6393 rn = "CacheErr";
6394 break;
6395 default:
6396 goto cp0_unimplemented;
6398 break;
6399 case 28:
6400 switch (sel) {
6401 case 0:
6402 case 2:
6403 case 4:
6404 case 6:
6405 gen_helper_mtc0_taglo(cpu_env, arg);
6406 rn = "TagLo";
6407 break;
6408 case 1:
6409 case 3:
6410 case 5:
6411 case 7:
6412 gen_helper_mtc0_datalo(cpu_env, arg);
6413 rn = "DataLo";
6414 break;
6415 default:
6416 goto cp0_unimplemented;
6418 break;
6419 case 29:
6420 switch (sel) {
6421 case 0:
6422 case 2:
6423 case 4:
6424 case 6:
6425 gen_helper_mtc0_taghi(cpu_env, arg);
6426 rn = "TagHi";
6427 break;
6428 case 1:
6429 case 3:
6430 case 5:
6431 case 7:
6432 gen_helper_mtc0_datahi(cpu_env, arg);
6433 rn = "DataHi";
6434 break;
6435 default:
6436 rn = "invalid sel";
6437 goto cp0_unimplemented;
6439 break;
6440 case 30:
6441 switch (sel) {
6442 case 0:
6443 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
6444 rn = "ErrorEPC";
6445 break;
6446 default:
6447 goto cp0_unimplemented;
6449 break;
6450 case 31:
6451 switch (sel) {
6452 case 0:
6453 /* EJTAG support */
6454 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6455 rn = "DESAVE";
6456 break;
6457 case 2 ... 7:
6458 CP0_CHECK(ctx->kscrexist & (1 << sel));
6459 tcg_gen_st_tl(arg, cpu_env,
6460 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6461 rn = "KScratch";
6462 break;
6463 default:
6464 goto cp0_unimplemented;
6466 /* Stop translation as we may have switched the execution mode */
6467 ctx->bstate = BS_STOP;
6468 break;
6469 default:
6470 goto cp0_unimplemented;
6472 (void)rn; /* avoid a compiler warning */
6473 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6474 /* For simplicity assume that all writes can cause interrupts. */
6475 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6476 gen_io_end();
6477 ctx->bstate = BS_STOP;
6479 return;
6481 cp0_unimplemented:
6482 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6485 #if defined(TARGET_MIPS64)
6486 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6488 const char *rn = "invalid";
6490 if (sel != 0)
6491 check_insn(ctx, ISA_MIPS64);
6493 switch (reg) {
6494 case 0:
6495 switch (sel) {
6496 case 0:
6497 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6498 rn = "Index";
6499 break;
6500 case 1:
6501 CP0_CHECK(ctx->insn_flags & ASE_MT);
6502 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6503 rn = "MVPControl";
6504 break;
6505 case 2:
6506 CP0_CHECK(ctx->insn_flags & ASE_MT);
6507 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6508 rn = "MVPConf0";
6509 break;
6510 case 3:
6511 CP0_CHECK(ctx->insn_flags & ASE_MT);
6512 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6513 rn = "MVPConf1";
6514 break;
6515 default:
6516 goto cp0_unimplemented;
6518 break;
6519 case 1:
6520 switch (sel) {
6521 case 0:
6522 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6523 gen_helper_mfc0_random(arg, cpu_env);
6524 rn = "Random";
6525 break;
6526 case 1:
6527 CP0_CHECK(ctx->insn_flags & ASE_MT);
6528 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6529 rn = "VPEControl";
6530 break;
6531 case 2:
6532 CP0_CHECK(ctx->insn_flags & ASE_MT);
6533 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6534 rn = "VPEConf0";
6535 break;
6536 case 3:
6537 CP0_CHECK(ctx->insn_flags & ASE_MT);
6538 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6539 rn = "VPEConf1";
6540 break;
6541 case 4:
6542 CP0_CHECK(ctx->insn_flags & ASE_MT);
6543 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6544 rn = "YQMask";
6545 break;
6546 case 5:
6547 CP0_CHECK(ctx->insn_flags & ASE_MT);
6548 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6549 rn = "VPESchedule";
6550 break;
6551 case 6:
6552 CP0_CHECK(ctx->insn_flags & ASE_MT);
6553 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6554 rn = "VPEScheFBack";
6555 break;
6556 case 7:
6557 CP0_CHECK(ctx->insn_flags & ASE_MT);
6558 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6559 rn = "VPEOpt";
6560 break;
6561 default:
6562 goto cp0_unimplemented;
6564 break;
6565 case 2:
6566 switch (sel) {
6567 case 0:
6568 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6569 rn = "EntryLo0";
6570 break;
6571 case 1:
6572 CP0_CHECK(ctx->insn_flags & ASE_MT);
6573 gen_helper_mfc0_tcstatus(arg, cpu_env);
6574 rn = "TCStatus";
6575 break;
6576 case 2:
6577 CP0_CHECK(ctx->insn_flags & ASE_MT);
6578 gen_helper_mfc0_tcbind(arg, cpu_env);
6579 rn = "TCBind";
6580 break;
6581 case 3:
6582 CP0_CHECK(ctx->insn_flags & ASE_MT);
6583 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6584 rn = "TCRestart";
6585 break;
6586 case 4:
6587 CP0_CHECK(ctx->insn_flags & ASE_MT);
6588 gen_helper_dmfc0_tchalt(arg, cpu_env);
6589 rn = "TCHalt";
6590 break;
6591 case 5:
6592 CP0_CHECK(ctx->insn_flags & ASE_MT);
6593 gen_helper_dmfc0_tccontext(arg, cpu_env);
6594 rn = "TCContext";
6595 break;
6596 case 6:
6597 CP0_CHECK(ctx->insn_flags & ASE_MT);
6598 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6599 rn = "TCSchedule";
6600 break;
6601 case 7:
6602 CP0_CHECK(ctx->insn_flags & ASE_MT);
6603 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6604 rn = "TCScheFBack";
6605 break;
6606 default:
6607 goto cp0_unimplemented;
6609 break;
6610 case 3:
6611 switch (sel) {
6612 case 0:
6613 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6614 rn = "EntryLo1";
6615 break;
6616 default:
6617 goto cp0_unimplemented;
6619 break;
6620 case 4:
6621 switch (sel) {
6622 case 0:
6623 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6624 rn = "Context";
6625 break;
6626 case 1:
6627 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6628 rn = "ContextConfig";
6629 goto cp0_unimplemented;
6630 // break;
6631 case 2:
6632 CP0_CHECK(ctx->ulri);
6633 tcg_gen_ld_tl(arg, cpu_env,
6634 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6635 rn = "UserLocal";
6636 break;
6637 default:
6638 goto cp0_unimplemented;
6640 break;
6641 case 5:
6642 switch (sel) {
6643 case 0:
6644 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6645 rn = "PageMask";
6646 break;
6647 case 1:
6648 check_insn(ctx, ISA_MIPS32R2);
6649 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6650 rn = "PageGrain";
6651 break;
6652 default:
6653 goto cp0_unimplemented;
6655 break;
6656 case 6:
6657 switch (sel) {
6658 case 0:
6659 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6660 rn = "Wired";
6661 break;
6662 case 1:
6663 check_insn(ctx, ISA_MIPS32R2);
6664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6665 rn = "SRSConf0";
6666 break;
6667 case 2:
6668 check_insn(ctx, ISA_MIPS32R2);
6669 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6670 rn = "SRSConf1";
6671 break;
6672 case 3:
6673 check_insn(ctx, ISA_MIPS32R2);
6674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6675 rn = "SRSConf2";
6676 break;
6677 case 4:
6678 check_insn(ctx, ISA_MIPS32R2);
6679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6680 rn = "SRSConf3";
6681 break;
6682 case 5:
6683 check_insn(ctx, ISA_MIPS32R2);
6684 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6685 rn = "SRSConf4";
6686 break;
6687 default:
6688 goto cp0_unimplemented;
6690 break;
6691 case 7:
6692 switch (sel) {
6693 case 0:
6694 check_insn(ctx, ISA_MIPS32R2);
6695 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6696 rn = "HWREna";
6697 break;
6698 default:
6699 goto cp0_unimplemented;
6701 break;
6702 case 8:
6703 switch (sel) {
6704 case 0:
6705 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6706 rn = "BadVAddr";
6707 break;
6708 case 1:
6709 CP0_CHECK(ctx->bi);
6710 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6711 rn = "BadInstr";
6712 break;
6713 case 2:
6714 CP0_CHECK(ctx->bp);
6715 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6716 rn = "BadInstrP";
6717 break;
6718 default:
6719 goto cp0_unimplemented;
6721 break;
6722 case 9:
6723 switch (sel) {
6724 case 0:
6725 /* Mark as an IO operation because we read the time. */
6726 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6727 gen_io_start();
6729 gen_helper_mfc0_count(arg, cpu_env);
6730 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6731 gen_io_end();
6733 /* Break the TB to be able to take timer interrupts immediately
6734 after reading count. */
6735 ctx->bstate = BS_STOP;
6736 rn = "Count";
6737 break;
6738 /* 6,7 are implementation dependent */
6739 default:
6740 goto cp0_unimplemented;
6742 break;
6743 case 10:
6744 switch (sel) {
6745 case 0:
6746 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6747 rn = "EntryHi";
6748 break;
6749 default:
6750 goto cp0_unimplemented;
6752 break;
6753 case 11:
6754 switch (sel) {
6755 case 0:
6756 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6757 rn = "Compare";
6758 break;
6759 /* 6,7 are implementation dependent */
6760 default:
6761 goto cp0_unimplemented;
6763 break;
6764 case 12:
6765 switch (sel) {
6766 case 0:
6767 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6768 rn = "Status";
6769 break;
6770 case 1:
6771 check_insn(ctx, ISA_MIPS32R2);
6772 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6773 rn = "IntCtl";
6774 break;
6775 case 2:
6776 check_insn(ctx, ISA_MIPS32R2);
6777 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6778 rn = "SRSCtl";
6779 break;
6780 case 3:
6781 check_insn(ctx, ISA_MIPS32R2);
6782 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6783 rn = "SRSMap";
6784 break;
6785 default:
6786 goto cp0_unimplemented;
6788 break;
6789 case 13:
6790 switch (sel) {
6791 case 0:
6792 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6793 rn = "Cause";
6794 break;
6795 default:
6796 goto cp0_unimplemented;
6798 break;
6799 case 14:
6800 switch (sel) {
6801 case 0:
6802 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6803 rn = "EPC";
6804 break;
6805 default:
6806 goto cp0_unimplemented;
6808 break;
6809 case 15:
6810 switch (sel) {
6811 case 0:
6812 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6813 rn = "PRid";
6814 break;
6815 case 1:
6816 check_insn(ctx, ISA_MIPS32R2);
6817 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6818 rn = "EBase";
6819 break;
6820 default:
6821 goto cp0_unimplemented;
6823 break;
6824 case 16:
6825 switch (sel) {
6826 case 0:
6827 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6828 rn = "Config";
6829 break;
6830 case 1:
6831 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6832 rn = "Config1";
6833 break;
6834 case 2:
6835 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6836 rn = "Config2";
6837 break;
6838 case 3:
6839 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6840 rn = "Config3";
6841 break;
6842 case 4:
6843 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6844 rn = "Config4";
6845 break;
6846 case 5:
6847 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6848 rn = "Config5";
6849 break;
6850 /* 6,7 are implementation dependent */
6851 case 6:
6852 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6853 rn = "Config6";
6854 break;
6855 case 7:
6856 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6857 rn = "Config7";
6858 break;
6859 default:
6860 goto cp0_unimplemented;
6862 break;
6863 case 17:
6864 switch (sel) {
6865 case 0:
6866 gen_helper_dmfc0_lladdr(arg, cpu_env);
6867 rn = "LLAddr";
6868 break;
6869 default:
6870 goto cp0_unimplemented;
6872 break;
6873 case 18:
6874 switch (sel) {
6875 case 0 ... 7:
6876 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6877 rn = "WatchLo";
6878 break;
6879 default:
6880 goto cp0_unimplemented;
6882 break;
6883 case 19:
6884 switch (sel) {
6885 case 0 ... 7:
6886 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6887 rn = "WatchHi";
6888 break;
6889 default:
6890 goto cp0_unimplemented;
6892 break;
6893 case 20:
6894 switch (sel) {
6895 case 0:
6896 check_insn(ctx, ISA_MIPS3);
6897 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6898 rn = "XContext";
6899 break;
6900 default:
6901 goto cp0_unimplemented;
6903 break;
6904 case 21:
6905 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6906 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6907 switch (sel) {
6908 case 0:
6909 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6910 rn = "Framemask";
6911 break;
6912 default:
6913 goto cp0_unimplemented;
6915 break;
6916 case 22:
6917 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6918 rn = "'Diagnostic"; /* implementation dependent */
6919 break;
6920 case 23:
6921 switch (sel) {
6922 case 0:
6923 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6924 rn = "Debug";
6925 break;
6926 case 1:
6927 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6928 rn = "TraceControl";
6929 // break;
6930 case 2:
6931 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6932 rn = "TraceControl2";
6933 // break;
6934 case 3:
6935 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6936 rn = "UserTraceData";
6937 // break;
6938 case 4:
6939 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6940 rn = "TraceBPC";
6941 // break;
6942 default:
6943 goto cp0_unimplemented;
6945 break;
6946 case 24:
6947 switch (sel) {
6948 case 0:
6949 /* EJTAG support */
6950 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6951 rn = "DEPC";
6952 break;
6953 default:
6954 goto cp0_unimplemented;
6956 break;
6957 case 25:
6958 switch (sel) {
6959 case 0:
6960 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6961 rn = "Performance0";
6962 break;
6963 case 1:
6964 // gen_helper_dmfc0_performance1(arg);
6965 rn = "Performance1";
6966 // break;
6967 case 2:
6968 // gen_helper_dmfc0_performance2(arg);
6969 rn = "Performance2";
6970 // break;
6971 case 3:
6972 // gen_helper_dmfc0_performance3(arg);
6973 rn = "Performance3";
6974 // break;
6975 case 4:
6976 // gen_helper_dmfc0_performance4(arg);
6977 rn = "Performance4";
6978 // break;
6979 case 5:
6980 // gen_helper_dmfc0_performance5(arg);
6981 rn = "Performance5";
6982 // break;
6983 case 6:
6984 // gen_helper_dmfc0_performance6(arg);
6985 rn = "Performance6";
6986 // break;
6987 case 7:
6988 // gen_helper_dmfc0_performance7(arg);
6989 rn = "Performance7";
6990 // break;
6991 default:
6992 goto cp0_unimplemented;
6994 break;
6995 case 26:
6996 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6997 rn = "ECC";
6998 break;
6999 case 27:
7000 switch (sel) {
7001 /* ignored */
7002 case 0 ... 3:
7003 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7004 rn = "CacheErr";
7005 break;
7006 default:
7007 goto cp0_unimplemented;
7009 break;
7010 case 28:
7011 switch (sel) {
7012 case 0:
7013 case 2:
7014 case 4:
7015 case 6:
7016 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
7017 rn = "TagLo";
7018 break;
7019 case 1:
7020 case 3:
7021 case 5:
7022 case 7:
7023 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7024 rn = "DataLo";
7025 break;
7026 default:
7027 goto cp0_unimplemented;
7029 break;
7030 case 29:
7031 switch (sel) {
7032 case 0:
7033 case 2:
7034 case 4:
7035 case 6:
7036 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7037 rn = "TagHi";
7038 break;
7039 case 1:
7040 case 3:
7041 case 5:
7042 case 7:
7043 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7044 rn = "DataHi";
7045 break;
7046 default:
7047 goto cp0_unimplemented;
7049 break;
7050 case 30:
7051 switch (sel) {
7052 case 0:
7053 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7054 rn = "ErrorEPC";
7055 break;
7056 default:
7057 goto cp0_unimplemented;
7059 break;
7060 case 31:
7061 switch (sel) {
7062 case 0:
7063 /* EJTAG support */
7064 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7065 rn = "DESAVE";
7066 break;
7067 case 2 ... 7:
7068 CP0_CHECK(ctx->kscrexist & (1 << sel));
7069 tcg_gen_ld_tl(arg, cpu_env,
7070 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7071 rn = "KScratch";
7072 break;
7073 default:
7074 goto cp0_unimplemented;
7076 break;
7077 default:
7078 goto cp0_unimplemented;
7080 (void)rn; /* avoid a compiler warning */
7081 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7082 return;
7084 cp0_unimplemented:
7085 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7086 gen_mfc0_unimplemented(ctx, arg);
7089 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7091 const char *rn = "invalid";
7093 if (sel != 0)
7094 check_insn(ctx, ISA_MIPS64);
7096 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7097 gen_io_start();
7100 switch (reg) {
7101 case 0:
7102 switch (sel) {
7103 case 0:
7104 gen_helper_mtc0_index(cpu_env, arg);
7105 rn = "Index";
7106 break;
7107 case 1:
7108 CP0_CHECK(ctx->insn_flags & ASE_MT);
7109 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7110 rn = "MVPControl";
7111 break;
7112 case 2:
7113 CP0_CHECK(ctx->insn_flags & ASE_MT);
7114 /* ignored */
7115 rn = "MVPConf0";
7116 break;
7117 case 3:
7118 CP0_CHECK(ctx->insn_flags & ASE_MT);
7119 /* ignored */
7120 rn = "MVPConf1";
7121 break;
7122 default:
7123 goto cp0_unimplemented;
7125 break;
7126 case 1:
7127 switch (sel) {
7128 case 0:
7129 /* ignored */
7130 rn = "Random";
7131 break;
7132 case 1:
7133 CP0_CHECK(ctx->insn_flags & ASE_MT);
7134 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7135 rn = "VPEControl";
7136 break;
7137 case 2:
7138 CP0_CHECK(ctx->insn_flags & ASE_MT);
7139 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7140 rn = "VPEConf0";
7141 break;
7142 case 3:
7143 CP0_CHECK(ctx->insn_flags & ASE_MT);
7144 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7145 rn = "VPEConf1";
7146 break;
7147 case 4:
7148 CP0_CHECK(ctx->insn_flags & ASE_MT);
7149 gen_helper_mtc0_yqmask(cpu_env, arg);
7150 rn = "YQMask";
7151 break;
7152 case 5:
7153 CP0_CHECK(ctx->insn_flags & ASE_MT);
7154 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7155 rn = "VPESchedule";
7156 break;
7157 case 6:
7158 CP0_CHECK(ctx->insn_flags & ASE_MT);
7159 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7160 rn = "VPEScheFBack";
7161 break;
7162 case 7:
7163 CP0_CHECK(ctx->insn_flags & ASE_MT);
7164 gen_helper_mtc0_vpeopt(cpu_env, arg);
7165 rn = "VPEOpt";
7166 break;
7167 default:
7168 goto cp0_unimplemented;
7170 break;
7171 case 2:
7172 switch (sel) {
7173 case 0:
7174 gen_helper_dmtc0_entrylo0(cpu_env, arg);
7175 rn = "EntryLo0";
7176 break;
7177 case 1:
7178 CP0_CHECK(ctx->insn_flags & ASE_MT);
7179 gen_helper_mtc0_tcstatus(cpu_env, arg);
7180 rn = "TCStatus";
7181 break;
7182 case 2:
7183 CP0_CHECK(ctx->insn_flags & ASE_MT);
7184 gen_helper_mtc0_tcbind(cpu_env, arg);
7185 rn = "TCBind";
7186 break;
7187 case 3:
7188 CP0_CHECK(ctx->insn_flags & ASE_MT);
7189 gen_helper_mtc0_tcrestart(cpu_env, arg);
7190 rn = "TCRestart";
7191 break;
7192 case 4:
7193 CP0_CHECK(ctx->insn_flags & ASE_MT);
7194 gen_helper_mtc0_tchalt(cpu_env, arg);
7195 rn = "TCHalt";
7196 break;
7197 case 5:
7198 CP0_CHECK(ctx->insn_flags & ASE_MT);
7199 gen_helper_mtc0_tccontext(cpu_env, arg);
7200 rn = "TCContext";
7201 break;
7202 case 6:
7203 CP0_CHECK(ctx->insn_flags & ASE_MT);
7204 gen_helper_mtc0_tcschedule(cpu_env, arg);
7205 rn = "TCSchedule";
7206 break;
7207 case 7:
7208 CP0_CHECK(ctx->insn_flags & ASE_MT);
7209 gen_helper_mtc0_tcschefback(cpu_env, arg);
7210 rn = "TCScheFBack";
7211 break;
7212 default:
7213 goto cp0_unimplemented;
7215 break;
7216 case 3:
7217 switch (sel) {
7218 case 0:
7219 gen_helper_dmtc0_entrylo1(cpu_env, arg);
7220 rn = "EntryLo1";
7221 break;
7222 default:
7223 goto cp0_unimplemented;
7225 break;
7226 case 4:
7227 switch (sel) {
7228 case 0:
7229 gen_helper_mtc0_context(cpu_env, arg);
7230 rn = "Context";
7231 break;
7232 case 1:
7233 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7234 rn = "ContextConfig";
7235 goto cp0_unimplemented;
7236 // break;
7237 case 2:
7238 CP0_CHECK(ctx->ulri);
7239 tcg_gen_st_tl(arg, cpu_env,
7240 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7241 rn = "UserLocal";
7242 break;
7243 default:
7244 goto cp0_unimplemented;
7246 break;
7247 case 5:
7248 switch (sel) {
7249 case 0:
7250 gen_helper_mtc0_pagemask(cpu_env, arg);
7251 rn = "PageMask";
7252 break;
7253 case 1:
7254 check_insn(ctx, ISA_MIPS32R2);
7255 gen_helper_mtc0_pagegrain(cpu_env, arg);
7256 rn = "PageGrain";
7257 break;
7258 default:
7259 goto cp0_unimplemented;
7261 break;
7262 case 6:
7263 switch (sel) {
7264 case 0:
7265 gen_helper_mtc0_wired(cpu_env, arg);
7266 rn = "Wired";
7267 break;
7268 case 1:
7269 check_insn(ctx, ISA_MIPS32R2);
7270 gen_helper_mtc0_srsconf0(cpu_env, arg);
7271 rn = "SRSConf0";
7272 break;
7273 case 2:
7274 check_insn(ctx, ISA_MIPS32R2);
7275 gen_helper_mtc0_srsconf1(cpu_env, arg);
7276 rn = "SRSConf1";
7277 break;
7278 case 3:
7279 check_insn(ctx, ISA_MIPS32R2);
7280 gen_helper_mtc0_srsconf2(cpu_env, arg);
7281 rn = "SRSConf2";
7282 break;
7283 case 4:
7284 check_insn(ctx, ISA_MIPS32R2);
7285 gen_helper_mtc0_srsconf3(cpu_env, arg);
7286 rn = "SRSConf3";
7287 break;
7288 case 5:
7289 check_insn(ctx, ISA_MIPS32R2);
7290 gen_helper_mtc0_srsconf4(cpu_env, arg);
7291 rn = "SRSConf4";
7292 break;
7293 default:
7294 goto cp0_unimplemented;
7296 break;
7297 case 7:
7298 switch (sel) {
7299 case 0:
7300 check_insn(ctx, ISA_MIPS32R2);
7301 gen_helper_mtc0_hwrena(cpu_env, arg);
7302 ctx->bstate = BS_STOP;
7303 rn = "HWREna";
7304 break;
7305 default:
7306 goto cp0_unimplemented;
7308 break;
7309 case 8:
7310 switch (sel) {
7311 case 0:
7312 /* ignored */
7313 rn = "BadVAddr";
7314 break;
7315 case 1:
7316 /* ignored */
7317 rn = "BadInstr";
7318 break;
7319 case 2:
7320 /* ignored */
7321 rn = "BadInstrP";
7322 break;
7323 default:
7324 goto cp0_unimplemented;
7326 break;
7327 case 9:
7328 switch (sel) {
7329 case 0:
7330 gen_helper_mtc0_count(cpu_env, arg);
7331 rn = "Count";
7332 break;
7333 /* 6,7 are implementation dependent */
7334 default:
7335 goto cp0_unimplemented;
7337 /* Stop translation as we may have switched the execution mode */
7338 ctx->bstate = BS_STOP;
7339 break;
7340 case 10:
7341 switch (sel) {
7342 case 0:
7343 gen_helper_mtc0_entryhi(cpu_env, arg);
7344 rn = "EntryHi";
7345 break;
7346 default:
7347 goto cp0_unimplemented;
7349 break;
7350 case 11:
7351 switch (sel) {
7352 case 0:
7353 gen_helper_mtc0_compare(cpu_env, arg);
7354 rn = "Compare";
7355 break;
7356 /* 6,7 are implementation dependent */
7357 default:
7358 goto cp0_unimplemented;
7360 /* Stop translation as we may have switched the execution mode */
7361 ctx->bstate = BS_STOP;
7362 break;
7363 case 12:
7364 switch (sel) {
7365 case 0:
7366 save_cpu_state(ctx, 1);
7367 gen_helper_mtc0_status(cpu_env, arg);
7368 /* BS_STOP isn't good enough here, hflags may have changed. */
7369 gen_save_pc(ctx->pc + 4);
7370 ctx->bstate = BS_EXCP;
7371 rn = "Status";
7372 break;
7373 case 1:
7374 check_insn(ctx, ISA_MIPS32R2);
7375 gen_helper_mtc0_intctl(cpu_env, arg);
7376 /* Stop translation as we may have switched the execution mode */
7377 ctx->bstate = BS_STOP;
7378 rn = "IntCtl";
7379 break;
7380 case 2:
7381 check_insn(ctx, ISA_MIPS32R2);
7382 gen_helper_mtc0_srsctl(cpu_env, arg);
7383 /* Stop translation as we may have switched the execution mode */
7384 ctx->bstate = BS_STOP;
7385 rn = "SRSCtl";
7386 break;
7387 case 3:
7388 check_insn(ctx, ISA_MIPS32R2);
7389 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7390 /* Stop translation as we may have switched the execution mode */
7391 ctx->bstate = BS_STOP;
7392 rn = "SRSMap";
7393 break;
7394 default:
7395 goto cp0_unimplemented;
7397 break;
7398 case 13:
7399 switch (sel) {
7400 case 0:
7401 save_cpu_state(ctx, 1);
7402 /* Mark as an IO operation because we may trigger a software
7403 interrupt. */
7404 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7405 gen_io_start();
7407 gen_helper_mtc0_cause(cpu_env, arg);
7408 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7409 gen_io_end();
7411 /* Stop translation as we may have triggered an intetrupt */
7412 ctx->bstate = BS_STOP;
7413 rn = "Cause";
7414 break;
7415 default:
7416 goto cp0_unimplemented;
7418 break;
7419 case 14:
7420 switch (sel) {
7421 case 0:
7422 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7423 rn = "EPC";
7424 break;
7425 default:
7426 goto cp0_unimplemented;
7428 break;
7429 case 15:
7430 switch (sel) {
7431 case 0:
7432 /* ignored */
7433 rn = "PRid";
7434 break;
7435 case 1:
7436 check_insn(ctx, ISA_MIPS32R2);
7437 gen_helper_mtc0_ebase(cpu_env, arg);
7438 rn = "EBase";
7439 break;
7440 default:
7441 goto cp0_unimplemented;
7443 break;
7444 case 16:
7445 switch (sel) {
7446 case 0:
7447 gen_helper_mtc0_config0(cpu_env, arg);
7448 rn = "Config";
7449 /* Stop translation as we may have switched the execution mode */
7450 ctx->bstate = BS_STOP;
7451 break;
7452 case 1:
7453 /* ignored, read only */
7454 rn = "Config1";
7455 break;
7456 case 2:
7457 gen_helper_mtc0_config2(cpu_env, arg);
7458 rn = "Config2";
7459 /* Stop translation as we may have switched the execution mode */
7460 ctx->bstate = BS_STOP;
7461 break;
7462 case 3:
7463 gen_helper_mtc0_config3(cpu_env, arg);
7464 rn = "Config3";
7465 /* Stop translation as we may have switched the execution mode */
7466 ctx->bstate = BS_STOP;
7467 break;
7468 case 4:
7469 /* currently ignored */
7470 rn = "Config4";
7471 break;
7472 case 5:
7473 gen_helper_mtc0_config5(cpu_env, arg);
7474 rn = "Config5";
7475 /* Stop translation as we may have switched the execution mode */
7476 ctx->bstate = BS_STOP;
7477 break;
7478 /* 6,7 are implementation dependent */
7479 default:
7480 rn = "Invalid config selector";
7481 goto cp0_unimplemented;
7483 break;
7484 case 17:
7485 switch (sel) {
7486 case 0:
7487 gen_helper_mtc0_lladdr(cpu_env, arg);
7488 rn = "LLAddr";
7489 break;
7490 default:
7491 goto cp0_unimplemented;
7493 break;
7494 case 18:
7495 switch (sel) {
7496 case 0 ... 7:
7497 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7498 rn = "WatchLo";
7499 break;
7500 default:
7501 goto cp0_unimplemented;
7503 break;
7504 case 19:
7505 switch (sel) {
7506 case 0 ... 7:
7507 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7508 rn = "WatchHi";
7509 break;
7510 default:
7511 goto cp0_unimplemented;
7513 break;
7514 case 20:
7515 switch (sel) {
7516 case 0:
7517 check_insn(ctx, ISA_MIPS3);
7518 gen_helper_mtc0_xcontext(cpu_env, arg);
7519 rn = "XContext";
7520 break;
7521 default:
7522 goto cp0_unimplemented;
7524 break;
7525 case 21:
7526 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7527 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7528 switch (sel) {
7529 case 0:
7530 gen_helper_mtc0_framemask(cpu_env, arg);
7531 rn = "Framemask";
7532 break;
7533 default:
7534 goto cp0_unimplemented;
7536 break;
7537 case 22:
7538 /* ignored */
7539 rn = "Diagnostic"; /* implementation dependent */
7540 break;
7541 case 23:
7542 switch (sel) {
7543 case 0:
7544 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7545 /* BS_STOP isn't good enough here, hflags may have changed. */
7546 gen_save_pc(ctx->pc + 4);
7547 ctx->bstate = BS_EXCP;
7548 rn = "Debug";
7549 break;
7550 case 1:
7551 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7552 /* Stop translation as we may have switched the execution mode */
7553 ctx->bstate = BS_STOP;
7554 rn = "TraceControl";
7555 // break;
7556 case 2:
7557 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7558 /* Stop translation as we may have switched the execution mode */
7559 ctx->bstate = BS_STOP;
7560 rn = "TraceControl2";
7561 // break;
7562 case 3:
7563 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7564 /* Stop translation as we may have switched the execution mode */
7565 ctx->bstate = BS_STOP;
7566 rn = "UserTraceData";
7567 // break;
7568 case 4:
7569 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7570 /* Stop translation as we may have switched the execution mode */
7571 ctx->bstate = BS_STOP;
7572 rn = "TraceBPC";
7573 // break;
7574 default:
7575 goto cp0_unimplemented;
7577 break;
7578 case 24:
7579 switch (sel) {
7580 case 0:
7581 /* EJTAG support */
7582 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7583 rn = "DEPC";
7584 break;
7585 default:
7586 goto cp0_unimplemented;
7588 break;
7589 case 25:
7590 switch (sel) {
7591 case 0:
7592 gen_helper_mtc0_performance0(cpu_env, arg);
7593 rn = "Performance0";
7594 break;
7595 case 1:
7596 // gen_helper_mtc0_performance1(cpu_env, arg);
7597 rn = "Performance1";
7598 // break;
7599 case 2:
7600 // gen_helper_mtc0_performance2(cpu_env, arg);
7601 rn = "Performance2";
7602 // break;
7603 case 3:
7604 // gen_helper_mtc0_performance3(cpu_env, arg);
7605 rn = "Performance3";
7606 // break;
7607 case 4:
7608 // gen_helper_mtc0_performance4(cpu_env, arg);
7609 rn = "Performance4";
7610 // break;
7611 case 5:
7612 // gen_helper_mtc0_performance5(cpu_env, arg);
7613 rn = "Performance5";
7614 // break;
7615 case 6:
7616 // gen_helper_mtc0_performance6(cpu_env, arg);
7617 rn = "Performance6";
7618 // break;
7619 case 7:
7620 // gen_helper_mtc0_performance7(cpu_env, arg);
7621 rn = "Performance7";
7622 // break;
7623 default:
7624 goto cp0_unimplemented;
7626 break;
7627 case 26:
7628 /* ignored */
7629 rn = "ECC";
7630 break;
7631 case 27:
7632 switch (sel) {
7633 case 0 ... 3:
7634 /* ignored */
7635 rn = "CacheErr";
7636 break;
7637 default:
7638 goto cp0_unimplemented;
7640 break;
7641 case 28:
7642 switch (sel) {
7643 case 0:
7644 case 2:
7645 case 4:
7646 case 6:
7647 gen_helper_mtc0_taglo(cpu_env, arg);
7648 rn = "TagLo";
7649 break;
7650 case 1:
7651 case 3:
7652 case 5:
7653 case 7:
7654 gen_helper_mtc0_datalo(cpu_env, arg);
7655 rn = "DataLo";
7656 break;
7657 default:
7658 goto cp0_unimplemented;
7660 break;
7661 case 29:
7662 switch (sel) {
7663 case 0:
7664 case 2:
7665 case 4:
7666 case 6:
7667 gen_helper_mtc0_taghi(cpu_env, arg);
7668 rn = "TagHi";
7669 break;
7670 case 1:
7671 case 3:
7672 case 5:
7673 case 7:
7674 gen_helper_mtc0_datahi(cpu_env, arg);
7675 rn = "DataHi";
7676 break;
7677 default:
7678 rn = "invalid sel";
7679 goto cp0_unimplemented;
7681 break;
7682 case 30:
7683 switch (sel) {
7684 case 0:
7685 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7686 rn = "ErrorEPC";
7687 break;
7688 default:
7689 goto cp0_unimplemented;
7691 break;
7692 case 31:
7693 switch (sel) {
7694 case 0:
7695 /* EJTAG support */
7696 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7697 rn = "DESAVE";
7698 break;
7699 case 2 ... 7:
7700 CP0_CHECK(ctx->kscrexist & (1 << sel));
7701 tcg_gen_st_tl(arg, cpu_env,
7702 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7703 rn = "KScratch";
7704 break;
7705 default:
7706 goto cp0_unimplemented;
7708 /* Stop translation as we may have switched the execution mode */
7709 ctx->bstate = BS_STOP;
7710 break;
7711 default:
7712 goto cp0_unimplemented;
7714 (void)rn; /* avoid a compiler warning */
7715 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7716 /* For simplicity assume that all writes can cause interrupts. */
7717 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7718 gen_io_end();
7719 ctx->bstate = BS_STOP;
7721 return;
7723 cp0_unimplemented:
7724 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7726 #endif /* TARGET_MIPS64 */
7728 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7729 int u, int sel, int h)
7731 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7732 TCGv t0 = tcg_temp_local_new();
7734 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7735 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7736 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7737 tcg_gen_movi_tl(t0, -1);
7738 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7739 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7740 tcg_gen_movi_tl(t0, -1);
7741 else if (u == 0) {
7742 switch (rt) {
7743 case 1:
7744 switch (sel) {
7745 case 1:
7746 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7747 break;
7748 case 2:
7749 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7750 break;
7751 default:
7752 goto die;
7753 break;
7755 break;
7756 case 2:
7757 switch (sel) {
7758 case 1:
7759 gen_helper_mftc0_tcstatus(t0, cpu_env);
7760 break;
7761 case 2:
7762 gen_helper_mftc0_tcbind(t0, cpu_env);
7763 break;
7764 case 3:
7765 gen_helper_mftc0_tcrestart(t0, cpu_env);
7766 break;
7767 case 4:
7768 gen_helper_mftc0_tchalt(t0, cpu_env);
7769 break;
7770 case 5:
7771 gen_helper_mftc0_tccontext(t0, cpu_env);
7772 break;
7773 case 6:
7774 gen_helper_mftc0_tcschedule(t0, cpu_env);
7775 break;
7776 case 7:
7777 gen_helper_mftc0_tcschefback(t0, cpu_env);
7778 break;
7779 default:
7780 gen_mfc0(ctx, t0, rt, sel);
7781 break;
7783 break;
7784 case 10:
7785 switch (sel) {
7786 case 0:
7787 gen_helper_mftc0_entryhi(t0, cpu_env);
7788 break;
7789 default:
7790 gen_mfc0(ctx, t0, rt, sel);
7791 break;
7793 case 12:
7794 switch (sel) {
7795 case 0:
7796 gen_helper_mftc0_status(t0, cpu_env);
7797 break;
7798 default:
7799 gen_mfc0(ctx, t0, rt, sel);
7800 break;
7802 case 13:
7803 switch (sel) {
7804 case 0:
7805 gen_helper_mftc0_cause(t0, cpu_env);
7806 break;
7807 default:
7808 goto die;
7809 break;
7811 break;
7812 case 14:
7813 switch (sel) {
7814 case 0:
7815 gen_helper_mftc0_epc(t0, cpu_env);
7816 break;
7817 default:
7818 goto die;
7819 break;
7821 break;
7822 case 15:
7823 switch (sel) {
7824 case 1:
7825 gen_helper_mftc0_ebase(t0, cpu_env);
7826 break;
7827 default:
7828 goto die;
7829 break;
7831 break;
7832 case 16:
7833 switch (sel) {
7834 case 0 ... 7:
7835 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7836 break;
7837 default:
7838 goto die;
7839 break;
7841 break;
7842 case 23:
7843 switch (sel) {
7844 case 0:
7845 gen_helper_mftc0_debug(t0, cpu_env);
7846 break;
7847 default:
7848 gen_mfc0(ctx, t0, rt, sel);
7849 break;
7851 break;
7852 default:
7853 gen_mfc0(ctx, t0, rt, sel);
7855 } else switch (sel) {
7856 /* GPR registers. */
7857 case 0:
7858 gen_helper_1e0i(mftgpr, t0, rt);
7859 break;
7860 /* Auxiliary CPU registers */
7861 case 1:
7862 switch (rt) {
7863 case 0:
7864 gen_helper_1e0i(mftlo, t0, 0);
7865 break;
7866 case 1:
7867 gen_helper_1e0i(mfthi, t0, 0);
7868 break;
7869 case 2:
7870 gen_helper_1e0i(mftacx, t0, 0);
7871 break;
7872 case 4:
7873 gen_helper_1e0i(mftlo, t0, 1);
7874 break;
7875 case 5:
7876 gen_helper_1e0i(mfthi, t0, 1);
7877 break;
7878 case 6:
7879 gen_helper_1e0i(mftacx, t0, 1);
7880 break;
7881 case 8:
7882 gen_helper_1e0i(mftlo, t0, 2);
7883 break;
7884 case 9:
7885 gen_helper_1e0i(mfthi, t0, 2);
7886 break;
7887 case 10:
7888 gen_helper_1e0i(mftacx, t0, 2);
7889 break;
7890 case 12:
7891 gen_helper_1e0i(mftlo, t0, 3);
7892 break;
7893 case 13:
7894 gen_helper_1e0i(mfthi, t0, 3);
7895 break;
7896 case 14:
7897 gen_helper_1e0i(mftacx, t0, 3);
7898 break;
7899 case 16:
7900 gen_helper_mftdsp(t0, cpu_env);
7901 break;
7902 default:
7903 goto die;
7905 break;
7906 /* Floating point (COP1). */
7907 case 2:
7908 /* XXX: For now we support only a single FPU context. */
7909 if (h == 0) {
7910 TCGv_i32 fp0 = tcg_temp_new_i32();
7912 gen_load_fpr32(ctx, fp0, rt);
7913 tcg_gen_ext_i32_tl(t0, fp0);
7914 tcg_temp_free_i32(fp0);
7915 } else {
7916 TCGv_i32 fp0 = tcg_temp_new_i32();
7918 gen_load_fpr32h(ctx, fp0, rt);
7919 tcg_gen_ext_i32_tl(t0, fp0);
7920 tcg_temp_free_i32(fp0);
7922 break;
7923 case 3:
7924 /* XXX: For now we support only a single FPU context. */
7925 gen_helper_1e0i(cfc1, t0, rt);
7926 break;
7927 /* COP2: Not implemented. */
7928 case 4:
7929 case 5:
7930 /* fall through */
7931 default:
7932 goto die;
7934 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7935 gen_store_gpr(t0, rd);
7936 tcg_temp_free(t0);
7937 return;
7939 die:
7940 tcg_temp_free(t0);
7941 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7942 generate_exception(ctx, EXCP_RI);
7945 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7946 int u, int sel, int h)
7948 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7949 TCGv t0 = tcg_temp_local_new();
7951 gen_load_gpr(t0, rt);
7952 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7953 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7954 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7955 /* NOP */ ;
7956 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7957 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7958 /* NOP */ ;
7959 else if (u == 0) {
7960 switch (rd) {
7961 case 1:
7962 switch (sel) {
7963 case 1:
7964 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7965 break;
7966 case 2:
7967 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7968 break;
7969 default:
7970 goto die;
7971 break;
7973 break;
7974 case 2:
7975 switch (sel) {
7976 case 1:
7977 gen_helper_mttc0_tcstatus(cpu_env, t0);
7978 break;
7979 case 2:
7980 gen_helper_mttc0_tcbind(cpu_env, t0);
7981 break;
7982 case 3:
7983 gen_helper_mttc0_tcrestart(cpu_env, t0);
7984 break;
7985 case 4:
7986 gen_helper_mttc0_tchalt(cpu_env, t0);
7987 break;
7988 case 5:
7989 gen_helper_mttc0_tccontext(cpu_env, t0);
7990 break;
7991 case 6:
7992 gen_helper_mttc0_tcschedule(cpu_env, t0);
7993 break;
7994 case 7:
7995 gen_helper_mttc0_tcschefback(cpu_env, t0);
7996 break;
7997 default:
7998 gen_mtc0(ctx, t0, rd, sel);
7999 break;
8001 break;
8002 case 10:
8003 switch (sel) {
8004 case 0:
8005 gen_helper_mttc0_entryhi(cpu_env, t0);
8006 break;
8007 default:
8008 gen_mtc0(ctx, t0, rd, sel);
8009 break;
8011 case 12:
8012 switch (sel) {
8013 case 0:
8014 gen_helper_mttc0_status(cpu_env, t0);
8015 break;
8016 default:
8017 gen_mtc0(ctx, t0, rd, sel);
8018 break;
8020 case 13:
8021 switch (sel) {
8022 case 0:
8023 gen_helper_mttc0_cause(cpu_env, t0);
8024 break;
8025 default:
8026 goto die;
8027 break;
8029 break;
8030 case 15:
8031 switch (sel) {
8032 case 1:
8033 gen_helper_mttc0_ebase(cpu_env, t0);
8034 break;
8035 default:
8036 goto die;
8037 break;
8039 break;
8040 case 23:
8041 switch (sel) {
8042 case 0:
8043 gen_helper_mttc0_debug(cpu_env, t0);
8044 break;
8045 default:
8046 gen_mtc0(ctx, t0, rd, sel);
8047 break;
8049 break;
8050 default:
8051 gen_mtc0(ctx, t0, rd, sel);
8053 } else switch (sel) {
8054 /* GPR registers. */
8055 case 0:
8056 gen_helper_0e1i(mttgpr, t0, rd);
8057 break;
8058 /* Auxiliary CPU registers */
8059 case 1:
8060 switch (rd) {
8061 case 0:
8062 gen_helper_0e1i(mttlo, t0, 0);
8063 break;
8064 case 1:
8065 gen_helper_0e1i(mtthi, t0, 0);
8066 break;
8067 case 2:
8068 gen_helper_0e1i(mttacx, t0, 0);
8069 break;
8070 case 4:
8071 gen_helper_0e1i(mttlo, t0, 1);
8072 break;
8073 case 5:
8074 gen_helper_0e1i(mtthi, t0, 1);
8075 break;
8076 case 6:
8077 gen_helper_0e1i(mttacx, t0, 1);
8078 break;
8079 case 8:
8080 gen_helper_0e1i(mttlo, t0, 2);
8081 break;
8082 case 9:
8083 gen_helper_0e1i(mtthi, t0, 2);
8084 break;
8085 case 10:
8086 gen_helper_0e1i(mttacx, t0, 2);
8087 break;
8088 case 12:
8089 gen_helper_0e1i(mttlo, t0, 3);
8090 break;
8091 case 13:
8092 gen_helper_0e1i(mtthi, t0, 3);
8093 break;
8094 case 14:
8095 gen_helper_0e1i(mttacx, t0, 3);
8096 break;
8097 case 16:
8098 gen_helper_mttdsp(cpu_env, t0);
8099 break;
8100 default:
8101 goto die;
8103 break;
8104 /* Floating point (COP1). */
8105 case 2:
8106 /* XXX: For now we support only a single FPU context. */
8107 if (h == 0) {
8108 TCGv_i32 fp0 = tcg_temp_new_i32();
8110 tcg_gen_trunc_tl_i32(fp0, t0);
8111 gen_store_fpr32(ctx, fp0, rd);
8112 tcg_temp_free_i32(fp0);
8113 } else {
8114 TCGv_i32 fp0 = tcg_temp_new_i32();
8116 tcg_gen_trunc_tl_i32(fp0, t0);
8117 gen_store_fpr32h(ctx, fp0, rd);
8118 tcg_temp_free_i32(fp0);
8120 break;
8121 case 3:
8122 /* XXX: For now we support only a single FPU context. */
8123 save_cpu_state(ctx, 1);
8125 TCGv_i32 fs_tmp = tcg_const_i32(rd);
8127 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8128 tcg_temp_free_i32(fs_tmp);
8130 /* Stop translation as we may have changed hflags */
8131 ctx->bstate = BS_STOP;
8132 break;
8133 /* COP2: Not implemented. */
8134 case 4:
8135 case 5:
8136 /* fall through */
8137 default:
8138 goto die;
8140 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8141 tcg_temp_free(t0);
8142 return;
8144 die:
8145 tcg_temp_free(t0);
8146 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8147 generate_exception(ctx, EXCP_RI);
8150 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
8152 const char *opn = "ldst";
8154 check_cp0_enabled(ctx);
8155 switch (opc) {
8156 case OPC_MFC0:
8157 if (rt == 0) {
8158 /* Treat as NOP. */
8159 return;
8161 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8162 opn = "mfc0";
8163 break;
8164 case OPC_MTC0:
8166 TCGv t0 = tcg_temp_new();
8168 gen_load_gpr(t0, rt);
8169 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
8170 tcg_temp_free(t0);
8172 opn = "mtc0";
8173 break;
8174 #if defined(TARGET_MIPS64)
8175 case OPC_DMFC0:
8176 check_insn(ctx, ISA_MIPS3);
8177 if (rt == 0) {
8178 /* Treat as NOP. */
8179 return;
8181 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8182 opn = "dmfc0";
8183 break;
8184 case OPC_DMTC0:
8185 check_insn(ctx, ISA_MIPS3);
8187 TCGv t0 = tcg_temp_new();
8189 gen_load_gpr(t0, rt);
8190 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
8191 tcg_temp_free(t0);
8193 opn = "dmtc0";
8194 break;
8195 #endif
8196 case OPC_MFHC0:
8197 check_mvh(ctx);
8198 if (rt == 0) {
8199 /* Treat as NOP. */
8200 return;
8202 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8203 opn = "mfhc0";
8204 break;
8205 case OPC_MTHC0:
8206 check_mvh(ctx);
8208 TCGv t0 = tcg_temp_new();
8209 gen_load_gpr(t0, rt);
8210 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8211 tcg_temp_free(t0);
8213 opn = "mthc0";
8214 break;
8215 case OPC_MFTR:
8216 check_insn(ctx, ASE_MT);
8217 if (rd == 0) {
8218 /* Treat as NOP. */
8219 return;
8221 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8222 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8223 opn = "mftr";
8224 break;
8225 case OPC_MTTR:
8226 check_insn(ctx, ASE_MT);
8227 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8228 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8229 opn = "mttr";
8230 break;
8231 case OPC_TLBWI:
8232 opn = "tlbwi";
8233 if (!env->tlb->helper_tlbwi)
8234 goto die;
8235 gen_helper_tlbwi(cpu_env);
8236 break;
8237 case OPC_TLBINV:
8238 opn = "tlbinv";
8239 if (ctx->ie >= 2) {
8240 if (!env->tlb->helper_tlbinv) {
8241 goto die;
8243 gen_helper_tlbinv(cpu_env);
8244 } /* treat as nop if TLBINV not supported */
8245 break;
8246 case OPC_TLBINVF:
8247 opn = "tlbinvf";
8248 if (ctx->ie >= 2) {
8249 if (!env->tlb->helper_tlbinvf) {
8250 goto die;
8252 gen_helper_tlbinvf(cpu_env);
8253 } /* treat as nop if TLBINV not supported */
8254 break;
8255 case OPC_TLBWR:
8256 opn = "tlbwr";
8257 if (!env->tlb->helper_tlbwr)
8258 goto die;
8259 gen_helper_tlbwr(cpu_env);
8260 break;
8261 case OPC_TLBP:
8262 opn = "tlbp";
8263 if (!env->tlb->helper_tlbp)
8264 goto die;
8265 gen_helper_tlbp(cpu_env);
8266 break;
8267 case OPC_TLBR:
8268 opn = "tlbr";
8269 if (!env->tlb->helper_tlbr)
8270 goto die;
8271 gen_helper_tlbr(cpu_env);
8272 break;
8273 case OPC_ERET: /* OPC_ERETNC */
8274 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8275 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8276 MIPS_DEBUG("CTI in delay / forbidden slot");
8277 goto die;
8278 } else {
8279 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8280 if (ctx->opcode & (1 << bit_shift)) {
8281 /* OPC_ERETNC */
8282 opn = "eretnc";
8283 check_insn(ctx, ISA_MIPS32R5);
8284 gen_helper_eretnc(cpu_env);
8285 } else {
8286 /* OPC_ERET */
8287 opn = "eret";
8288 check_insn(ctx, ISA_MIPS2);
8289 gen_helper_eret(cpu_env);
8291 ctx->bstate = BS_EXCP;
8293 break;
8294 case OPC_DERET:
8295 opn = "deret";
8296 check_insn(ctx, ISA_MIPS32);
8297 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8298 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8299 MIPS_DEBUG("CTI in delay / forbidden slot");
8300 goto die;
8302 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8303 MIPS_INVAL(opn);
8304 generate_exception(ctx, EXCP_RI);
8305 } else {
8306 gen_helper_deret(cpu_env);
8307 ctx->bstate = BS_EXCP;
8309 break;
8310 case OPC_WAIT:
8311 opn = "wait";
8312 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8313 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8314 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8315 MIPS_DEBUG("CTI in delay / forbidden slot");
8316 goto die;
8318 /* If we get an exception, we want to restart at next instruction */
8319 ctx->pc += 4;
8320 save_cpu_state(ctx, 1);
8321 ctx->pc -= 4;
8322 gen_helper_wait(cpu_env);
8323 ctx->bstate = BS_EXCP;
8324 break;
8325 default:
8326 die:
8327 MIPS_INVAL(opn);
8328 generate_exception(ctx, EXCP_RI);
8329 return;
8331 (void)opn; /* avoid a compiler warning */
8332 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
8334 #endif /* !CONFIG_USER_ONLY */
8336 /* CP1 Branches (before delay slot) */
8337 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8338 int32_t cc, int32_t offset)
8340 target_ulong btarget;
8341 const char *opn = "cp1 cond branch";
8342 TCGv_i32 t0 = tcg_temp_new_i32();
8344 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8345 MIPS_DEBUG("CTI in delay / forbidden slot");
8346 generate_exception(ctx, EXCP_RI);
8347 goto out;
8350 if (cc != 0)
8351 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8353 btarget = ctx->pc + 4 + offset;
8355 switch (op) {
8356 case OPC_BC1F:
8357 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8358 tcg_gen_not_i32(t0, t0);
8359 tcg_gen_andi_i32(t0, t0, 1);
8360 tcg_gen_extu_i32_tl(bcond, t0);
8361 opn = "bc1f";
8362 goto not_likely;
8363 case OPC_BC1FL:
8364 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8365 tcg_gen_not_i32(t0, t0);
8366 tcg_gen_andi_i32(t0, t0, 1);
8367 tcg_gen_extu_i32_tl(bcond, t0);
8368 opn = "bc1fl";
8369 goto likely;
8370 case OPC_BC1T:
8371 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8372 tcg_gen_andi_i32(t0, t0, 1);
8373 tcg_gen_extu_i32_tl(bcond, t0);
8374 opn = "bc1t";
8375 goto not_likely;
8376 case OPC_BC1TL:
8377 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8378 tcg_gen_andi_i32(t0, t0, 1);
8379 tcg_gen_extu_i32_tl(bcond, t0);
8380 opn = "bc1tl";
8381 likely:
8382 ctx->hflags |= MIPS_HFLAG_BL;
8383 break;
8384 case OPC_BC1FANY2:
8386 TCGv_i32 t1 = tcg_temp_new_i32();
8387 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8388 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8389 tcg_gen_nand_i32(t0, t0, t1);
8390 tcg_temp_free_i32(t1);
8391 tcg_gen_andi_i32(t0, t0, 1);
8392 tcg_gen_extu_i32_tl(bcond, t0);
8394 opn = "bc1any2f";
8395 goto not_likely;
8396 case OPC_BC1TANY2:
8398 TCGv_i32 t1 = tcg_temp_new_i32();
8399 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8400 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8401 tcg_gen_or_i32(t0, t0, t1);
8402 tcg_temp_free_i32(t1);
8403 tcg_gen_andi_i32(t0, t0, 1);
8404 tcg_gen_extu_i32_tl(bcond, t0);
8406 opn = "bc1any2t";
8407 goto not_likely;
8408 case OPC_BC1FANY4:
8410 TCGv_i32 t1 = tcg_temp_new_i32();
8411 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8412 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8413 tcg_gen_and_i32(t0, t0, t1);
8414 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8415 tcg_gen_and_i32(t0, t0, t1);
8416 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8417 tcg_gen_nand_i32(t0, t0, t1);
8418 tcg_temp_free_i32(t1);
8419 tcg_gen_andi_i32(t0, t0, 1);
8420 tcg_gen_extu_i32_tl(bcond, t0);
8422 opn = "bc1any4f";
8423 goto not_likely;
8424 case OPC_BC1TANY4:
8426 TCGv_i32 t1 = tcg_temp_new_i32();
8427 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8428 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8429 tcg_gen_or_i32(t0, t0, t1);
8430 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8431 tcg_gen_or_i32(t0, t0, t1);
8432 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8433 tcg_gen_or_i32(t0, t0, t1);
8434 tcg_temp_free_i32(t1);
8435 tcg_gen_andi_i32(t0, t0, 1);
8436 tcg_gen_extu_i32_tl(bcond, t0);
8438 opn = "bc1any4t";
8439 not_likely:
8440 ctx->hflags |= MIPS_HFLAG_BC;
8441 break;
8442 default:
8443 MIPS_INVAL(opn);
8444 generate_exception (ctx, EXCP_RI);
8445 goto out;
8447 (void)opn; /* avoid a compiler warning */
8448 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
8449 ctx->hflags, btarget);
8450 ctx->btarget = btarget;
8451 ctx->hflags |= MIPS_HFLAG_BDS32;
8452 out:
8453 tcg_temp_free_i32(t0);
8456 /* R6 CP1 Branches */
8457 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8458 int32_t ft, int32_t offset,
8459 int delayslot_size)
8461 target_ulong btarget;
8462 const char *opn = "cp1 cond branch";
8463 TCGv_i64 t0 = tcg_temp_new_i64();
8465 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8466 #ifdef MIPS_DEBUG_DISAS
8467 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8468 "\n", ctx->pc);
8469 #endif
8470 generate_exception(ctx, EXCP_RI);
8471 goto out;
8474 gen_load_fpr64(ctx, t0, ft);
8475 tcg_gen_andi_i64(t0, t0, 1);
8477 btarget = addr_add(ctx, ctx->pc + 4, offset);
8479 switch (op) {
8480 case OPC_BC1EQZ:
8481 tcg_gen_xori_i64(t0, t0, 1);
8482 opn = "bc1eqz";
8483 ctx->hflags |= MIPS_HFLAG_BC;
8484 break;
8485 case OPC_BC1NEZ:
8486 /* t0 already set */
8487 opn = "bc1nez";
8488 ctx->hflags |= MIPS_HFLAG_BC;
8489 break;
8490 default:
8491 MIPS_INVAL(opn);
8492 generate_exception(ctx, EXCP_RI);
8493 goto out;
8496 tcg_gen_trunc_i64_tl(bcond, t0);
8498 (void)opn; /* avoid a compiler warning */
8499 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
8500 ctx->hflags, btarget);
8501 ctx->btarget = btarget;
8503 switch (delayslot_size) {
8504 case 2:
8505 ctx->hflags |= MIPS_HFLAG_BDS16;
8506 break;
8507 case 4:
8508 ctx->hflags |= MIPS_HFLAG_BDS32;
8509 break;
8512 out:
8513 tcg_temp_free_i64(t0);
8516 /* Coprocessor 1 (FPU) */
8518 #define FOP(func, fmt) (((fmt) << 21) | (func))
8520 enum fopcode {
8521 OPC_ADD_S = FOP(0, FMT_S),
8522 OPC_SUB_S = FOP(1, FMT_S),
8523 OPC_MUL_S = FOP(2, FMT_S),
8524 OPC_DIV_S = FOP(3, FMT_S),
8525 OPC_SQRT_S = FOP(4, FMT_S),
8526 OPC_ABS_S = FOP(5, FMT_S),
8527 OPC_MOV_S = FOP(6, FMT_S),
8528 OPC_NEG_S = FOP(7, FMT_S),
8529 OPC_ROUND_L_S = FOP(8, FMT_S),
8530 OPC_TRUNC_L_S = FOP(9, FMT_S),
8531 OPC_CEIL_L_S = FOP(10, FMT_S),
8532 OPC_FLOOR_L_S = FOP(11, FMT_S),
8533 OPC_ROUND_W_S = FOP(12, FMT_S),
8534 OPC_TRUNC_W_S = FOP(13, FMT_S),
8535 OPC_CEIL_W_S = FOP(14, FMT_S),
8536 OPC_FLOOR_W_S = FOP(15, FMT_S),
8537 OPC_SEL_S = FOP(16, FMT_S),
8538 OPC_MOVCF_S = FOP(17, FMT_S),
8539 OPC_MOVZ_S = FOP(18, FMT_S),
8540 OPC_MOVN_S = FOP(19, FMT_S),
8541 OPC_SELEQZ_S = FOP(20, FMT_S),
8542 OPC_RECIP_S = FOP(21, FMT_S),
8543 OPC_RSQRT_S = FOP(22, FMT_S),
8544 OPC_SELNEZ_S = FOP(23, FMT_S),
8545 OPC_MADDF_S = FOP(24, FMT_S),
8546 OPC_MSUBF_S = FOP(25, FMT_S),
8547 OPC_RINT_S = FOP(26, FMT_S),
8548 OPC_CLASS_S = FOP(27, FMT_S),
8549 OPC_MIN_S = FOP(28, FMT_S),
8550 OPC_RECIP2_S = FOP(28, FMT_S),
8551 OPC_MINA_S = FOP(29, FMT_S),
8552 OPC_RECIP1_S = FOP(29, FMT_S),
8553 OPC_MAX_S = FOP(30, FMT_S),
8554 OPC_RSQRT1_S = FOP(30, FMT_S),
8555 OPC_MAXA_S = FOP(31, FMT_S),
8556 OPC_RSQRT2_S = FOP(31, FMT_S),
8557 OPC_CVT_D_S = FOP(33, FMT_S),
8558 OPC_CVT_W_S = FOP(36, FMT_S),
8559 OPC_CVT_L_S = FOP(37, FMT_S),
8560 OPC_CVT_PS_S = FOP(38, FMT_S),
8561 OPC_CMP_F_S = FOP (48, FMT_S),
8562 OPC_CMP_UN_S = FOP (49, FMT_S),
8563 OPC_CMP_EQ_S = FOP (50, FMT_S),
8564 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8565 OPC_CMP_OLT_S = FOP (52, FMT_S),
8566 OPC_CMP_ULT_S = FOP (53, FMT_S),
8567 OPC_CMP_OLE_S = FOP (54, FMT_S),
8568 OPC_CMP_ULE_S = FOP (55, FMT_S),
8569 OPC_CMP_SF_S = FOP (56, FMT_S),
8570 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8571 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8572 OPC_CMP_NGL_S = FOP (59, FMT_S),
8573 OPC_CMP_LT_S = FOP (60, FMT_S),
8574 OPC_CMP_NGE_S = FOP (61, FMT_S),
8575 OPC_CMP_LE_S = FOP (62, FMT_S),
8576 OPC_CMP_NGT_S = FOP (63, FMT_S),
8578 OPC_ADD_D = FOP(0, FMT_D),
8579 OPC_SUB_D = FOP(1, FMT_D),
8580 OPC_MUL_D = FOP(2, FMT_D),
8581 OPC_DIV_D = FOP(3, FMT_D),
8582 OPC_SQRT_D = FOP(4, FMT_D),
8583 OPC_ABS_D = FOP(5, FMT_D),
8584 OPC_MOV_D = FOP(6, FMT_D),
8585 OPC_NEG_D = FOP(7, FMT_D),
8586 OPC_ROUND_L_D = FOP(8, FMT_D),
8587 OPC_TRUNC_L_D = FOP(9, FMT_D),
8588 OPC_CEIL_L_D = FOP(10, FMT_D),
8589 OPC_FLOOR_L_D = FOP(11, FMT_D),
8590 OPC_ROUND_W_D = FOP(12, FMT_D),
8591 OPC_TRUNC_W_D = FOP(13, FMT_D),
8592 OPC_CEIL_W_D = FOP(14, FMT_D),
8593 OPC_FLOOR_W_D = FOP(15, FMT_D),
8594 OPC_SEL_D = FOP(16, FMT_D),
8595 OPC_MOVCF_D = FOP(17, FMT_D),
8596 OPC_MOVZ_D = FOP(18, FMT_D),
8597 OPC_MOVN_D = FOP(19, FMT_D),
8598 OPC_SELEQZ_D = FOP(20, FMT_D),
8599 OPC_RECIP_D = FOP(21, FMT_D),
8600 OPC_RSQRT_D = FOP(22, FMT_D),
8601 OPC_SELNEZ_D = FOP(23, FMT_D),
8602 OPC_MADDF_D = FOP(24, FMT_D),
8603 OPC_MSUBF_D = FOP(25, FMT_D),
8604 OPC_RINT_D = FOP(26, FMT_D),
8605 OPC_CLASS_D = FOP(27, FMT_D),
8606 OPC_MIN_D = FOP(28, FMT_D),
8607 OPC_RECIP2_D = FOP(28, FMT_D),
8608 OPC_MINA_D = FOP(29, FMT_D),
8609 OPC_RECIP1_D = FOP(29, FMT_D),
8610 OPC_MAX_D = FOP(30, FMT_D),
8611 OPC_RSQRT1_D = FOP(30, FMT_D),
8612 OPC_MAXA_D = FOP(31, FMT_D),
8613 OPC_RSQRT2_D = FOP(31, FMT_D),
8614 OPC_CVT_S_D = FOP(32, FMT_D),
8615 OPC_CVT_W_D = FOP(36, FMT_D),
8616 OPC_CVT_L_D = FOP(37, FMT_D),
8617 OPC_CMP_F_D = FOP (48, FMT_D),
8618 OPC_CMP_UN_D = FOP (49, FMT_D),
8619 OPC_CMP_EQ_D = FOP (50, FMT_D),
8620 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8621 OPC_CMP_OLT_D = FOP (52, FMT_D),
8622 OPC_CMP_ULT_D = FOP (53, FMT_D),
8623 OPC_CMP_OLE_D = FOP (54, FMT_D),
8624 OPC_CMP_ULE_D = FOP (55, FMT_D),
8625 OPC_CMP_SF_D = FOP (56, FMT_D),
8626 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8627 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8628 OPC_CMP_NGL_D = FOP (59, FMT_D),
8629 OPC_CMP_LT_D = FOP (60, FMT_D),
8630 OPC_CMP_NGE_D = FOP (61, FMT_D),
8631 OPC_CMP_LE_D = FOP (62, FMT_D),
8632 OPC_CMP_NGT_D = FOP (63, FMT_D),
8634 OPC_CVT_S_W = FOP(32, FMT_W),
8635 OPC_CVT_D_W = FOP(33, FMT_W),
8636 OPC_CVT_S_L = FOP(32, FMT_L),
8637 OPC_CVT_D_L = FOP(33, FMT_L),
8638 OPC_CVT_PS_PW = FOP(38, FMT_W),
8640 OPC_ADD_PS = FOP(0, FMT_PS),
8641 OPC_SUB_PS = FOP(1, FMT_PS),
8642 OPC_MUL_PS = FOP(2, FMT_PS),
8643 OPC_DIV_PS = FOP(3, FMT_PS),
8644 OPC_ABS_PS = FOP(5, FMT_PS),
8645 OPC_MOV_PS = FOP(6, FMT_PS),
8646 OPC_NEG_PS = FOP(7, FMT_PS),
8647 OPC_MOVCF_PS = FOP(17, FMT_PS),
8648 OPC_MOVZ_PS = FOP(18, FMT_PS),
8649 OPC_MOVN_PS = FOP(19, FMT_PS),
8650 OPC_ADDR_PS = FOP(24, FMT_PS),
8651 OPC_MULR_PS = FOP(26, FMT_PS),
8652 OPC_RECIP2_PS = FOP(28, FMT_PS),
8653 OPC_RECIP1_PS = FOP(29, FMT_PS),
8654 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8655 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8657 OPC_CVT_S_PU = FOP(32, FMT_PS),
8658 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8659 OPC_CVT_S_PL = FOP(40, FMT_PS),
8660 OPC_PLL_PS = FOP(44, FMT_PS),
8661 OPC_PLU_PS = FOP(45, FMT_PS),
8662 OPC_PUL_PS = FOP(46, FMT_PS),
8663 OPC_PUU_PS = FOP(47, FMT_PS),
8664 OPC_CMP_F_PS = FOP (48, FMT_PS),
8665 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8666 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8667 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8668 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8669 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8670 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8671 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8672 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8673 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8674 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8675 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8676 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8677 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8678 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8679 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8682 enum r6_f_cmp_op {
8683 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8684 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8685 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8686 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8687 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8688 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8689 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8690 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8691 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8692 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8693 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8694 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8695 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8696 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8697 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8698 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8699 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8700 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8701 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8702 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8703 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8704 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8706 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8707 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8708 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8709 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8710 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8711 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8712 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8713 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8714 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8715 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8716 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8717 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8718 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8719 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8720 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8721 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8722 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8723 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8724 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8725 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8726 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8727 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8729 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8731 const char *opn = "cp1 move";
8732 TCGv t0 = tcg_temp_new();
8734 switch (opc) {
8735 case OPC_MFC1:
8737 TCGv_i32 fp0 = tcg_temp_new_i32();
8739 gen_load_fpr32(ctx, fp0, fs);
8740 tcg_gen_ext_i32_tl(t0, fp0);
8741 tcg_temp_free_i32(fp0);
8743 gen_store_gpr(t0, rt);
8744 opn = "mfc1";
8745 break;
8746 case OPC_MTC1:
8747 gen_load_gpr(t0, rt);
8749 TCGv_i32 fp0 = tcg_temp_new_i32();
8751 tcg_gen_trunc_tl_i32(fp0, t0);
8752 gen_store_fpr32(ctx, fp0, fs);
8753 tcg_temp_free_i32(fp0);
8755 opn = "mtc1";
8756 break;
8757 case OPC_CFC1:
8758 gen_helper_1e0i(cfc1, t0, fs);
8759 gen_store_gpr(t0, rt);
8760 opn = "cfc1";
8761 break;
8762 case OPC_CTC1:
8763 gen_load_gpr(t0, rt);
8764 save_cpu_state(ctx, 1);
8766 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8768 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8769 tcg_temp_free_i32(fs_tmp);
8771 /* Stop translation as we may have changed hflags */
8772 ctx->bstate = BS_STOP;
8773 opn = "ctc1";
8774 break;
8775 #if defined(TARGET_MIPS64)
8776 case OPC_DMFC1:
8777 gen_load_fpr64(ctx, t0, fs);
8778 gen_store_gpr(t0, rt);
8779 opn = "dmfc1";
8780 break;
8781 case OPC_DMTC1:
8782 gen_load_gpr(t0, rt);
8783 gen_store_fpr64(ctx, t0, fs);
8784 opn = "dmtc1";
8785 break;
8786 #endif
8787 case OPC_MFHC1:
8789 TCGv_i32 fp0 = tcg_temp_new_i32();
8791 gen_load_fpr32h(ctx, fp0, fs);
8792 tcg_gen_ext_i32_tl(t0, fp0);
8793 tcg_temp_free_i32(fp0);
8795 gen_store_gpr(t0, rt);
8796 opn = "mfhc1";
8797 break;
8798 case OPC_MTHC1:
8799 gen_load_gpr(t0, rt);
8801 TCGv_i32 fp0 = tcg_temp_new_i32();
8803 tcg_gen_trunc_tl_i32(fp0, t0);
8804 gen_store_fpr32h(ctx, fp0, fs);
8805 tcg_temp_free_i32(fp0);
8807 opn = "mthc1";
8808 break;
8809 default:
8810 MIPS_INVAL(opn);
8811 generate_exception (ctx, EXCP_RI);
8812 goto out;
8814 (void)opn; /* avoid a compiler warning */
8815 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
8817 out:
8818 tcg_temp_free(t0);
8821 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8823 TCGLabel *l1;
8824 TCGCond cond;
8825 TCGv_i32 t0;
8827 if (rd == 0) {
8828 /* Treat as NOP. */
8829 return;
8832 if (tf)
8833 cond = TCG_COND_EQ;
8834 else
8835 cond = TCG_COND_NE;
8837 l1 = gen_new_label();
8838 t0 = tcg_temp_new_i32();
8839 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8840 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8841 tcg_temp_free_i32(t0);
8842 if (rs == 0) {
8843 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8844 } else {
8845 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8847 gen_set_label(l1);
8850 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
8851 int tf)
8853 int cond;
8854 TCGv_i32 t0 = tcg_temp_new_i32();
8855 TCGLabel *l1 = gen_new_label();
8857 if (tf)
8858 cond = TCG_COND_EQ;
8859 else
8860 cond = TCG_COND_NE;
8862 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8863 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8864 gen_load_fpr32(ctx, t0, fs);
8865 gen_store_fpr32(ctx, t0, fd);
8866 gen_set_label(l1);
8867 tcg_temp_free_i32(t0);
8870 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8872 int cond;
8873 TCGv_i32 t0 = tcg_temp_new_i32();
8874 TCGv_i64 fp0;
8875 TCGLabel *l1 = gen_new_label();
8877 if (tf)
8878 cond = TCG_COND_EQ;
8879 else
8880 cond = TCG_COND_NE;
8882 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8883 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8884 tcg_temp_free_i32(t0);
8885 fp0 = tcg_temp_new_i64();
8886 gen_load_fpr64(ctx, fp0, fs);
8887 gen_store_fpr64(ctx, fp0, fd);
8888 tcg_temp_free_i64(fp0);
8889 gen_set_label(l1);
8892 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8893 int cc, int tf)
8895 int cond;
8896 TCGv_i32 t0 = tcg_temp_new_i32();
8897 TCGLabel *l1 = gen_new_label();
8898 TCGLabel *l2 = gen_new_label();
8900 if (tf)
8901 cond = TCG_COND_EQ;
8902 else
8903 cond = TCG_COND_NE;
8905 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8906 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8907 gen_load_fpr32(ctx, t0, fs);
8908 gen_store_fpr32(ctx, t0, fd);
8909 gen_set_label(l1);
8911 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8912 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8913 gen_load_fpr32h(ctx, t0, fs);
8914 gen_store_fpr32h(ctx, t0, fd);
8915 tcg_temp_free_i32(t0);
8916 gen_set_label(l2);
8919 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8920 int fs)
8922 TCGv_i32 t1 = tcg_const_i32(0);
8923 TCGv_i32 fp0 = tcg_temp_new_i32();
8924 TCGv_i32 fp1 = tcg_temp_new_i32();
8925 TCGv_i32 fp2 = tcg_temp_new_i32();
8926 gen_load_fpr32(ctx, fp0, fd);
8927 gen_load_fpr32(ctx, fp1, ft);
8928 gen_load_fpr32(ctx, fp2, fs);
8930 switch (op1) {
8931 case OPC_SEL_S:
8932 tcg_gen_andi_i32(fp0, fp0, 1);
8933 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8934 break;
8935 case OPC_SELEQZ_S:
8936 tcg_gen_andi_i32(fp1, fp1, 1);
8937 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8938 break;
8939 case OPC_SELNEZ_S:
8940 tcg_gen_andi_i32(fp1, fp1, 1);
8941 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8942 break;
8943 default:
8944 MIPS_INVAL("gen_sel_s");
8945 generate_exception (ctx, EXCP_RI);
8946 break;
8949 gen_store_fpr32(ctx, fp0, fd);
8950 tcg_temp_free_i32(fp2);
8951 tcg_temp_free_i32(fp1);
8952 tcg_temp_free_i32(fp0);
8953 tcg_temp_free_i32(t1);
8956 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8957 int fs)
8959 TCGv_i64 t1 = tcg_const_i64(0);
8960 TCGv_i64 fp0 = tcg_temp_new_i64();
8961 TCGv_i64 fp1 = tcg_temp_new_i64();
8962 TCGv_i64 fp2 = tcg_temp_new_i64();
8963 gen_load_fpr64(ctx, fp0, fd);
8964 gen_load_fpr64(ctx, fp1, ft);
8965 gen_load_fpr64(ctx, fp2, fs);
8967 switch (op1) {
8968 case OPC_SEL_D:
8969 tcg_gen_andi_i64(fp0, fp0, 1);
8970 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8971 break;
8972 case OPC_SELEQZ_D:
8973 tcg_gen_andi_i64(fp1, fp1, 1);
8974 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8975 break;
8976 case OPC_SELNEZ_D:
8977 tcg_gen_andi_i64(fp1, fp1, 1);
8978 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8979 break;
8980 default:
8981 MIPS_INVAL("gen_sel_d");
8982 generate_exception (ctx, EXCP_RI);
8983 break;
8986 gen_store_fpr64(ctx, fp0, fd);
8987 tcg_temp_free_i64(fp2);
8988 tcg_temp_free_i64(fp1);
8989 tcg_temp_free_i64(fp0);
8990 tcg_temp_free_i64(t1);
8993 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8994 int ft, int fs, int fd, int cc)
8996 const char *opn = "farith";
8997 const char *condnames[] = {
8998 "c.f",
8999 "c.un",
9000 "c.eq",
9001 "c.ueq",
9002 "c.olt",
9003 "c.ult",
9004 "c.ole",
9005 "c.ule",
9006 "c.sf",
9007 "c.ngle",
9008 "c.seq",
9009 "c.ngl",
9010 "c.lt",
9011 "c.nge",
9012 "c.le",
9013 "c.ngt",
9015 const char *condnames_abs[] = {
9016 "cabs.f",
9017 "cabs.un",
9018 "cabs.eq",
9019 "cabs.ueq",
9020 "cabs.olt",
9021 "cabs.ult",
9022 "cabs.ole",
9023 "cabs.ule",
9024 "cabs.sf",
9025 "cabs.ngle",
9026 "cabs.seq",
9027 "cabs.ngl",
9028 "cabs.lt",
9029 "cabs.nge",
9030 "cabs.le",
9031 "cabs.ngt",
9033 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
9034 uint32_t func = ctx->opcode & 0x3f;
9035 switch (op1) {
9036 case OPC_ADD_S:
9038 TCGv_i32 fp0 = tcg_temp_new_i32();
9039 TCGv_i32 fp1 = tcg_temp_new_i32();
9041 gen_load_fpr32(ctx, fp0, fs);
9042 gen_load_fpr32(ctx, fp1, ft);
9043 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
9044 tcg_temp_free_i32(fp1);
9045 gen_store_fpr32(ctx, fp0, fd);
9046 tcg_temp_free_i32(fp0);
9048 opn = "add.s";
9049 optype = BINOP;
9050 break;
9051 case OPC_SUB_S:
9053 TCGv_i32 fp0 = tcg_temp_new_i32();
9054 TCGv_i32 fp1 = tcg_temp_new_i32();
9056 gen_load_fpr32(ctx, fp0, fs);
9057 gen_load_fpr32(ctx, fp1, ft);
9058 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
9059 tcg_temp_free_i32(fp1);
9060 gen_store_fpr32(ctx, fp0, fd);
9061 tcg_temp_free_i32(fp0);
9063 opn = "sub.s";
9064 optype = BINOP;
9065 break;
9066 case OPC_MUL_S:
9068 TCGv_i32 fp0 = tcg_temp_new_i32();
9069 TCGv_i32 fp1 = tcg_temp_new_i32();
9071 gen_load_fpr32(ctx, fp0, fs);
9072 gen_load_fpr32(ctx, fp1, ft);
9073 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
9074 tcg_temp_free_i32(fp1);
9075 gen_store_fpr32(ctx, fp0, fd);
9076 tcg_temp_free_i32(fp0);
9078 opn = "mul.s";
9079 optype = BINOP;
9080 break;
9081 case OPC_DIV_S:
9083 TCGv_i32 fp0 = tcg_temp_new_i32();
9084 TCGv_i32 fp1 = tcg_temp_new_i32();
9086 gen_load_fpr32(ctx, fp0, fs);
9087 gen_load_fpr32(ctx, fp1, ft);
9088 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
9089 tcg_temp_free_i32(fp1);
9090 gen_store_fpr32(ctx, fp0, fd);
9091 tcg_temp_free_i32(fp0);
9093 opn = "div.s";
9094 optype = BINOP;
9095 break;
9096 case OPC_SQRT_S:
9098 TCGv_i32 fp0 = tcg_temp_new_i32();
9100 gen_load_fpr32(ctx, fp0, fs);
9101 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
9102 gen_store_fpr32(ctx, fp0, fd);
9103 tcg_temp_free_i32(fp0);
9105 opn = "sqrt.s";
9106 break;
9107 case OPC_ABS_S:
9109 TCGv_i32 fp0 = tcg_temp_new_i32();
9111 gen_load_fpr32(ctx, fp0, fs);
9112 gen_helper_float_abs_s(fp0, fp0);
9113 gen_store_fpr32(ctx, fp0, fd);
9114 tcg_temp_free_i32(fp0);
9116 opn = "abs.s";
9117 break;
9118 case OPC_MOV_S:
9120 TCGv_i32 fp0 = tcg_temp_new_i32();
9122 gen_load_fpr32(ctx, fp0, fs);
9123 gen_store_fpr32(ctx, fp0, fd);
9124 tcg_temp_free_i32(fp0);
9126 opn = "mov.s";
9127 break;
9128 case OPC_NEG_S:
9130 TCGv_i32 fp0 = tcg_temp_new_i32();
9132 gen_load_fpr32(ctx, fp0, fs);
9133 gen_helper_float_chs_s(fp0, fp0);
9134 gen_store_fpr32(ctx, fp0, fd);
9135 tcg_temp_free_i32(fp0);
9137 opn = "neg.s";
9138 break;
9139 case OPC_ROUND_L_S:
9140 check_cp1_64bitmode(ctx);
9142 TCGv_i32 fp32 = tcg_temp_new_i32();
9143 TCGv_i64 fp64 = tcg_temp_new_i64();
9145 gen_load_fpr32(ctx, fp32, fs);
9146 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
9147 tcg_temp_free_i32(fp32);
9148 gen_store_fpr64(ctx, fp64, fd);
9149 tcg_temp_free_i64(fp64);
9151 opn = "round.l.s";
9152 break;
9153 case OPC_TRUNC_L_S:
9154 check_cp1_64bitmode(ctx);
9156 TCGv_i32 fp32 = tcg_temp_new_i32();
9157 TCGv_i64 fp64 = tcg_temp_new_i64();
9159 gen_load_fpr32(ctx, fp32, fs);
9160 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
9161 tcg_temp_free_i32(fp32);
9162 gen_store_fpr64(ctx, fp64, fd);
9163 tcg_temp_free_i64(fp64);
9165 opn = "trunc.l.s";
9166 break;
9167 case OPC_CEIL_L_S:
9168 check_cp1_64bitmode(ctx);
9170 TCGv_i32 fp32 = tcg_temp_new_i32();
9171 TCGv_i64 fp64 = tcg_temp_new_i64();
9173 gen_load_fpr32(ctx, fp32, fs);
9174 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
9175 tcg_temp_free_i32(fp32);
9176 gen_store_fpr64(ctx, fp64, fd);
9177 tcg_temp_free_i64(fp64);
9179 opn = "ceil.l.s";
9180 break;
9181 case OPC_FLOOR_L_S:
9182 check_cp1_64bitmode(ctx);
9184 TCGv_i32 fp32 = tcg_temp_new_i32();
9185 TCGv_i64 fp64 = tcg_temp_new_i64();
9187 gen_load_fpr32(ctx, fp32, fs);
9188 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
9189 tcg_temp_free_i32(fp32);
9190 gen_store_fpr64(ctx, fp64, fd);
9191 tcg_temp_free_i64(fp64);
9193 opn = "floor.l.s";
9194 break;
9195 case OPC_ROUND_W_S:
9197 TCGv_i32 fp0 = tcg_temp_new_i32();
9199 gen_load_fpr32(ctx, fp0, fs);
9200 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
9201 gen_store_fpr32(ctx, fp0, fd);
9202 tcg_temp_free_i32(fp0);
9204 opn = "round.w.s";
9205 break;
9206 case OPC_TRUNC_W_S:
9208 TCGv_i32 fp0 = tcg_temp_new_i32();
9210 gen_load_fpr32(ctx, fp0, fs);
9211 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
9212 gen_store_fpr32(ctx, fp0, fd);
9213 tcg_temp_free_i32(fp0);
9215 opn = "trunc.w.s";
9216 break;
9217 case OPC_CEIL_W_S:
9219 TCGv_i32 fp0 = tcg_temp_new_i32();
9221 gen_load_fpr32(ctx, fp0, fs);
9222 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
9223 gen_store_fpr32(ctx, fp0, fd);
9224 tcg_temp_free_i32(fp0);
9226 opn = "ceil.w.s";
9227 break;
9228 case OPC_FLOOR_W_S:
9230 TCGv_i32 fp0 = tcg_temp_new_i32();
9232 gen_load_fpr32(ctx, fp0, fs);
9233 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
9234 gen_store_fpr32(ctx, fp0, fd);
9235 tcg_temp_free_i32(fp0);
9237 opn = "floor.w.s";
9238 break;
9239 case OPC_SEL_S:
9240 check_insn(ctx, ISA_MIPS32R6);
9241 gen_sel_s(ctx, op1, fd, ft, fs);
9242 opn = "sel.s";
9243 break;
9244 case OPC_SELEQZ_S:
9245 check_insn(ctx, ISA_MIPS32R6);
9246 gen_sel_s(ctx, op1, fd, ft, fs);
9247 opn = "seleqz.s";
9248 break;
9249 case OPC_SELNEZ_S:
9250 check_insn(ctx, ISA_MIPS32R6);
9251 gen_sel_s(ctx, op1, fd, ft, fs);
9252 opn = "selnez.s";
9253 break;
9254 case OPC_MOVCF_S:
9255 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9256 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9257 opn = "movcf.s";
9258 break;
9259 case OPC_MOVZ_S:
9260 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9262 TCGLabel *l1 = gen_new_label();
9263 TCGv_i32 fp0;
9265 if (ft != 0) {
9266 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9268 fp0 = tcg_temp_new_i32();
9269 gen_load_fpr32(ctx, fp0, fs);
9270 gen_store_fpr32(ctx, fp0, fd);
9271 tcg_temp_free_i32(fp0);
9272 gen_set_label(l1);
9274 opn = "movz.s";
9275 break;
9276 case OPC_MOVN_S:
9277 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9279 TCGLabel *l1 = gen_new_label();
9280 TCGv_i32 fp0;
9282 if (ft != 0) {
9283 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9284 fp0 = tcg_temp_new_i32();
9285 gen_load_fpr32(ctx, fp0, fs);
9286 gen_store_fpr32(ctx, fp0, fd);
9287 tcg_temp_free_i32(fp0);
9288 gen_set_label(l1);
9291 opn = "movn.s";
9292 break;
9293 case OPC_RECIP_S:
9294 check_cop1x(ctx);
9296 TCGv_i32 fp0 = tcg_temp_new_i32();
9298 gen_load_fpr32(ctx, fp0, fs);
9299 gen_helper_float_recip_s(fp0, cpu_env, fp0);
9300 gen_store_fpr32(ctx, fp0, fd);
9301 tcg_temp_free_i32(fp0);
9303 opn = "recip.s";
9304 break;
9305 case OPC_RSQRT_S:
9306 check_cop1x(ctx);
9308 TCGv_i32 fp0 = tcg_temp_new_i32();
9310 gen_load_fpr32(ctx, fp0, fs);
9311 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
9312 gen_store_fpr32(ctx, fp0, fd);
9313 tcg_temp_free_i32(fp0);
9315 opn = "rsqrt.s";
9316 break;
9317 case OPC_MADDF_S:
9318 check_insn(ctx, ISA_MIPS32R6);
9320 TCGv_i32 fp0 = tcg_temp_new_i32();
9321 TCGv_i32 fp1 = tcg_temp_new_i32();
9322 TCGv_i32 fp2 = tcg_temp_new_i32();
9323 gen_load_fpr32(ctx, fp0, fs);
9324 gen_load_fpr32(ctx, fp1, ft);
9325 gen_load_fpr32(ctx, fp2, fd);
9326 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
9327 gen_store_fpr32(ctx, fp2, fd);
9328 tcg_temp_free_i32(fp2);
9329 tcg_temp_free_i32(fp1);
9330 tcg_temp_free_i32(fp0);
9331 opn = "maddf.s";
9333 break;
9334 case OPC_MSUBF_S:
9335 check_insn(ctx, ISA_MIPS32R6);
9337 TCGv_i32 fp0 = tcg_temp_new_i32();
9338 TCGv_i32 fp1 = tcg_temp_new_i32();
9339 TCGv_i32 fp2 = tcg_temp_new_i32();
9340 gen_load_fpr32(ctx, fp0, fs);
9341 gen_load_fpr32(ctx, fp1, ft);
9342 gen_load_fpr32(ctx, fp2, fd);
9343 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
9344 gen_store_fpr32(ctx, fp2, fd);
9345 tcg_temp_free_i32(fp2);
9346 tcg_temp_free_i32(fp1);
9347 tcg_temp_free_i32(fp0);
9348 opn = "msubf.s";
9350 break;
9351 case OPC_RINT_S:
9352 check_insn(ctx, ISA_MIPS32R6);
9354 TCGv_i32 fp0 = tcg_temp_new_i32();
9355 gen_load_fpr32(ctx, fp0, fs);
9356 gen_helper_float_rint_s(fp0, cpu_env, fp0);
9357 gen_store_fpr32(ctx, fp0, fd);
9358 tcg_temp_free_i32(fp0);
9359 opn = "rint.s";
9361 break;
9362 case OPC_CLASS_S:
9363 check_insn(ctx, ISA_MIPS32R6);
9365 TCGv_i32 fp0 = tcg_temp_new_i32();
9366 gen_load_fpr32(ctx, fp0, fs);
9367 gen_helper_float_class_s(fp0, fp0);
9368 gen_store_fpr32(ctx, fp0, fd);
9369 tcg_temp_free_i32(fp0);
9370 opn = "class.s";
9372 break;
9373 case OPC_MIN_S: /* OPC_RECIP2_S */
9374 if (ctx->insn_flags & ISA_MIPS32R6) {
9375 /* OPC_MIN_S */
9376 TCGv_i32 fp0 = tcg_temp_new_i32();
9377 TCGv_i32 fp1 = tcg_temp_new_i32();
9378 TCGv_i32 fp2 = tcg_temp_new_i32();
9379 gen_load_fpr32(ctx, fp0, fs);
9380 gen_load_fpr32(ctx, fp1, ft);
9381 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
9382 gen_store_fpr32(ctx, fp2, fd);
9383 tcg_temp_free_i32(fp2);
9384 tcg_temp_free_i32(fp1);
9385 tcg_temp_free_i32(fp0);
9386 opn = "min.s";
9387 } else {
9388 /* OPC_RECIP2_S */
9389 check_cp1_64bitmode(ctx);
9391 TCGv_i32 fp0 = tcg_temp_new_i32();
9392 TCGv_i32 fp1 = tcg_temp_new_i32();
9394 gen_load_fpr32(ctx, fp0, fs);
9395 gen_load_fpr32(ctx, fp1, ft);
9396 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9397 tcg_temp_free_i32(fp1);
9398 gen_store_fpr32(ctx, fp0, fd);
9399 tcg_temp_free_i32(fp0);
9401 opn = "recip2.s";
9403 break;
9404 case OPC_MINA_S: /* OPC_RECIP1_S */
9405 if (ctx->insn_flags & ISA_MIPS32R6) {
9406 /* OPC_MINA_S */
9407 TCGv_i32 fp0 = tcg_temp_new_i32();
9408 TCGv_i32 fp1 = tcg_temp_new_i32();
9409 TCGv_i32 fp2 = tcg_temp_new_i32();
9410 gen_load_fpr32(ctx, fp0, fs);
9411 gen_load_fpr32(ctx, fp1, ft);
9412 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9413 gen_store_fpr32(ctx, fp2, fd);
9414 tcg_temp_free_i32(fp2);
9415 tcg_temp_free_i32(fp1);
9416 tcg_temp_free_i32(fp0);
9417 opn = "mina.s";
9418 } else {
9419 /* OPC_RECIP1_S */
9420 check_cp1_64bitmode(ctx);
9422 TCGv_i32 fp0 = tcg_temp_new_i32();
9424 gen_load_fpr32(ctx, fp0, fs);
9425 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9426 gen_store_fpr32(ctx, fp0, fd);
9427 tcg_temp_free_i32(fp0);
9429 opn = "recip1.s";
9431 break;
9432 case OPC_MAX_S: /* OPC_RSQRT1_S */
9433 if (ctx->insn_flags & ISA_MIPS32R6) {
9434 /* OPC_MAX_S */
9435 TCGv_i32 fp0 = tcg_temp_new_i32();
9436 TCGv_i32 fp1 = tcg_temp_new_i32();
9437 gen_load_fpr32(ctx, fp0, fs);
9438 gen_load_fpr32(ctx, fp1, ft);
9439 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9440 gen_store_fpr32(ctx, fp1, fd);
9441 tcg_temp_free_i32(fp1);
9442 tcg_temp_free_i32(fp0);
9443 opn = "max.s";
9444 } else {
9445 /* OPC_RSQRT1_S */
9446 check_cp1_64bitmode(ctx);
9448 TCGv_i32 fp0 = tcg_temp_new_i32();
9450 gen_load_fpr32(ctx, fp0, fs);
9451 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9452 gen_store_fpr32(ctx, fp0, fd);
9453 tcg_temp_free_i32(fp0);
9455 opn = "rsqrt1.s";
9457 break;
9458 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9459 if (ctx->insn_flags & ISA_MIPS32R6) {
9460 /* OPC_MAXA_S */
9461 TCGv_i32 fp0 = tcg_temp_new_i32();
9462 TCGv_i32 fp1 = tcg_temp_new_i32();
9463 gen_load_fpr32(ctx, fp0, fs);
9464 gen_load_fpr32(ctx, fp1, ft);
9465 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9466 gen_store_fpr32(ctx, fp1, fd);
9467 tcg_temp_free_i32(fp1);
9468 tcg_temp_free_i32(fp0);
9469 opn = "maxa.s";
9470 } else {
9471 /* OPC_RSQRT2_S */
9472 check_cp1_64bitmode(ctx);
9474 TCGv_i32 fp0 = tcg_temp_new_i32();
9475 TCGv_i32 fp1 = tcg_temp_new_i32();
9477 gen_load_fpr32(ctx, fp0, fs);
9478 gen_load_fpr32(ctx, fp1, ft);
9479 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9480 tcg_temp_free_i32(fp1);
9481 gen_store_fpr32(ctx, fp0, fd);
9482 tcg_temp_free_i32(fp0);
9484 opn = "rsqrt2.s";
9486 break;
9487 case OPC_CVT_D_S:
9488 check_cp1_registers(ctx, fd);
9490 TCGv_i32 fp32 = tcg_temp_new_i32();
9491 TCGv_i64 fp64 = tcg_temp_new_i64();
9493 gen_load_fpr32(ctx, fp32, fs);
9494 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9495 tcg_temp_free_i32(fp32);
9496 gen_store_fpr64(ctx, fp64, fd);
9497 tcg_temp_free_i64(fp64);
9499 opn = "cvt.d.s";
9500 break;
9501 case OPC_CVT_W_S:
9503 TCGv_i32 fp0 = tcg_temp_new_i32();
9505 gen_load_fpr32(ctx, fp0, fs);
9506 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
9507 gen_store_fpr32(ctx, fp0, fd);
9508 tcg_temp_free_i32(fp0);
9510 opn = "cvt.w.s";
9511 break;
9512 case OPC_CVT_L_S:
9513 check_cp1_64bitmode(ctx);
9515 TCGv_i32 fp32 = tcg_temp_new_i32();
9516 TCGv_i64 fp64 = tcg_temp_new_i64();
9518 gen_load_fpr32(ctx, fp32, fs);
9519 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
9520 tcg_temp_free_i32(fp32);
9521 gen_store_fpr64(ctx, fp64, fd);
9522 tcg_temp_free_i64(fp64);
9524 opn = "cvt.l.s";
9525 break;
9526 case OPC_CVT_PS_S:
9527 check_ps(ctx);
9529 TCGv_i64 fp64 = tcg_temp_new_i64();
9530 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9531 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9533 gen_load_fpr32(ctx, fp32_0, fs);
9534 gen_load_fpr32(ctx, fp32_1, ft);
9535 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9536 tcg_temp_free_i32(fp32_1);
9537 tcg_temp_free_i32(fp32_0);
9538 gen_store_fpr64(ctx, fp64, fd);
9539 tcg_temp_free_i64(fp64);
9541 opn = "cvt.ps.s";
9542 break;
9543 case OPC_CMP_F_S:
9544 case OPC_CMP_UN_S:
9545 case OPC_CMP_EQ_S:
9546 case OPC_CMP_UEQ_S:
9547 case OPC_CMP_OLT_S:
9548 case OPC_CMP_ULT_S:
9549 case OPC_CMP_OLE_S:
9550 case OPC_CMP_ULE_S:
9551 case OPC_CMP_SF_S:
9552 case OPC_CMP_NGLE_S:
9553 case OPC_CMP_SEQ_S:
9554 case OPC_CMP_NGL_S:
9555 case OPC_CMP_LT_S:
9556 case OPC_CMP_NGE_S:
9557 case OPC_CMP_LE_S:
9558 case OPC_CMP_NGT_S:
9559 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9560 if (ctx->opcode & (1 << 6)) {
9561 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9562 opn = condnames_abs[func-48];
9563 } else {
9564 gen_cmp_s(ctx, func-48, ft, fs, cc);
9565 opn = condnames[func-48];
9567 optype = CMPOP;
9568 break;
9569 case OPC_ADD_D:
9570 check_cp1_registers(ctx, fs | ft | fd);
9572 TCGv_i64 fp0 = tcg_temp_new_i64();
9573 TCGv_i64 fp1 = tcg_temp_new_i64();
9575 gen_load_fpr64(ctx, fp0, fs);
9576 gen_load_fpr64(ctx, fp1, ft);
9577 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9578 tcg_temp_free_i64(fp1);
9579 gen_store_fpr64(ctx, fp0, fd);
9580 tcg_temp_free_i64(fp0);
9582 opn = "add.d";
9583 optype = BINOP;
9584 break;
9585 case OPC_SUB_D:
9586 check_cp1_registers(ctx, fs | ft | fd);
9588 TCGv_i64 fp0 = tcg_temp_new_i64();
9589 TCGv_i64 fp1 = tcg_temp_new_i64();
9591 gen_load_fpr64(ctx, fp0, fs);
9592 gen_load_fpr64(ctx, fp1, ft);
9593 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9594 tcg_temp_free_i64(fp1);
9595 gen_store_fpr64(ctx, fp0, fd);
9596 tcg_temp_free_i64(fp0);
9598 opn = "sub.d";
9599 optype = BINOP;
9600 break;
9601 case OPC_MUL_D:
9602 check_cp1_registers(ctx, fs | ft | fd);
9604 TCGv_i64 fp0 = tcg_temp_new_i64();
9605 TCGv_i64 fp1 = tcg_temp_new_i64();
9607 gen_load_fpr64(ctx, fp0, fs);
9608 gen_load_fpr64(ctx, fp1, ft);
9609 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9610 tcg_temp_free_i64(fp1);
9611 gen_store_fpr64(ctx, fp0, fd);
9612 tcg_temp_free_i64(fp0);
9614 opn = "mul.d";
9615 optype = BINOP;
9616 break;
9617 case OPC_DIV_D:
9618 check_cp1_registers(ctx, fs | ft | fd);
9620 TCGv_i64 fp0 = tcg_temp_new_i64();
9621 TCGv_i64 fp1 = tcg_temp_new_i64();
9623 gen_load_fpr64(ctx, fp0, fs);
9624 gen_load_fpr64(ctx, fp1, ft);
9625 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9626 tcg_temp_free_i64(fp1);
9627 gen_store_fpr64(ctx, fp0, fd);
9628 tcg_temp_free_i64(fp0);
9630 opn = "div.d";
9631 optype = BINOP;
9632 break;
9633 case OPC_SQRT_D:
9634 check_cp1_registers(ctx, fs | fd);
9636 TCGv_i64 fp0 = tcg_temp_new_i64();
9638 gen_load_fpr64(ctx, fp0, fs);
9639 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9640 gen_store_fpr64(ctx, fp0, fd);
9641 tcg_temp_free_i64(fp0);
9643 opn = "sqrt.d";
9644 break;
9645 case OPC_ABS_D:
9646 check_cp1_registers(ctx, fs | fd);
9648 TCGv_i64 fp0 = tcg_temp_new_i64();
9650 gen_load_fpr64(ctx, fp0, fs);
9651 gen_helper_float_abs_d(fp0, fp0);
9652 gen_store_fpr64(ctx, fp0, fd);
9653 tcg_temp_free_i64(fp0);
9655 opn = "abs.d";
9656 break;
9657 case OPC_MOV_D:
9658 check_cp1_registers(ctx, fs | fd);
9660 TCGv_i64 fp0 = tcg_temp_new_i64();
9662 gen_load_fpr64(ctx, fp0, fs);
9663 gen_store_fpr64(ctx, fp0, fd);
9664 tcg_temp_free_i64(fp0);
9666 opn = "mov.d";
9667 break;
9668 case OPC_NEG_D:
9669 check_cp1_registers(ctx, fs | fd);
9671 TCGv_i64 fp0 = tcg_temp_new_i64();
9673 gen_load_fpr64(ctx, fp0, fs);
9674 gen_helper_float_chs_d(fp0, fp0);
9675 gen_store_fpr64(ctx, fp0, fd);
9676 tcg_temp_free_i64(fp0);
9678 opn = "neg.d";
9679 break;
9680 case OPC_ROUND_L_D:
9681 check_cp1_64bitmode(ctx);
9683 TCGv_i64 fp0 = tcg_temp_new_i64();
9685 gen_load_fpr64(ctx, fp0, fs);
9686 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
9687 gen_store_fpr64(ctx, fp0, fd);
9688 tcg_temp_free_i64(fp0);
9690 opn = "round.l.d";
9691 break;
9692 case OPC_TRUNC_L_D:
9693 check_cp1_64bitmode(ctx);
9695 TCGv_i64 fp0 = tcg_temp_new_i64();
9697 gen_load_fpr64(ctx, fp0, fs);
9698 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
9699 gen_store_fpr64(ctx, fp0, fd);
9700 tcg_temp_free_i64(fp0);
9702 opn = "trunc.l.d";
9703 break;
9704 case OPC_CEIL_L_D:
9705 check_cp1_64bitmode(ctx);
9707 TCGv_i64 fp0 = tcg_temp_new_i64();
9709 gen_load_fpr64(ctx, fp0, fs);
9710 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
9711 gen_store_fpr64(ctx, fp0, fd);
9712 tcg_temp_free_i64(fp0);
9714 opn = "ceil.l.d";
9715 break;
9716 case OPC_FLOOR_L_D:
9717 check_cp1_64bitmode(ctx);
9719 TCGv_i64 fp0 = tcg_temp_new_i64();
9721 gen_load_fpr64(ctx, fp0, fs);
9722 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
9723 gen_store_fpr64(ctx, fp0, fd);
9724 tcg_temp_free_i64(fp0);
9726 opn = "floor.l.d";
9727 break;
9728 case OPC_ROUND_W_D:
9729 check_cp1_registers(ctx, fs);
9731 TCGv_i32 fp32 = tcg_temp_new_i32();
9732 TCGv_i64 fp64 = tcg_temp_new_i64();
9734 gen_load_fpr64(ctx, fp64, fs);
9735 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
9736 tcg_temp_free_i64(fp64);
9737 gen_store_fpr32(ctx, fp32, fd);
9738 tcg_temp_free_i32(fp32);
9740 opn = "round.w.d";
9741 break;
9742 case OPC_TRUNC_W_D:
9743 check_cp1_registers(ctx, fs);
9745 TCGv_i32 fp32 = tcg_temp_new_i32();
9746 TCGv_i64 fp64 = tcg_temp_new_i64();
9748 gen_load_fpr64(ctx, fp64, fs);
9749 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
9750 tcg_temp_free_i64(fp64);
9751 gen_store_fpr32(ctx, fp32, fd);
9752 tcg_temp_free_i32(fp32);
9754 opn = "trunc.w.d";
9755 break;
9756 case OPC_CEIL_W_D:
9757 check_cp1_registers(ctx, fs);
9759 TCGv_i32 fp32 = tcg_temp_new_i32();
9760 TCGv_i64 fp64 = tcg_temp_new_i64();
9762 gen_load_fpr64(ctx, fp64, fs);
9763 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
9764 tcg_temp_free_i64(fp64);
9765 gen_store_fpr32(ctx, fp32, fd);
9766 tcg_temp_free_i32(fp32);
9768 opn = "ceil.w.d";
9769 break;
9770 case OPC_FLOOR_W_D:
9771 check_cp1_registers(ctx, fs);
9773 TCGv_i32 fp32 = tcg_temp_new_i32();
9774 TCGv_i64 fp64 = tcg_temp_new_i64();
9776 gen_load_fpr64(ctx, fp64, fs);
9777 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
9778 tcg_temp_free_i64(fp64);
9779 gen_store_fpr32(ctx, fp32, fd);
9780 tcg_temp_free_i32(fp32);
9782 opn = "floor.w.d";
9783 break;
9784 case OPC_SEL_D:
9785 check_insn(ctx, ISA_MIPS32R6);
9786 gen_sel_d(ctx, op1, fd, ft, fs);
9787 opn = "sel.d";
9788 break;
9789 case OPC_SELEQZ_D:
9790 check_insn(ctx, ISA_MIPS32R6);
9791 gen_sel_d(ctx, op1, fd, ft, fs);
9792 opn = "seleqz.d";
9793 break;
9794 case OPC_SELNEZ_D:
9795 check_insn(ctx, ISA_MIPS32R6);
9796 gen_sel_d(ctx, op1, fd, ft, fs);
9797 opn = "selnez.d";
9798 break;
9799 case OPC_MOVCF_D:
9800 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9801 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9802 opn = "movcf.d";
9803 break;
9804 case OPC_MOVZ_D:
9805 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9807 TCGLabel *l1 = gen_new_label();
9808 TCGv_i64 fp0;
9810 if (ft != 0) {
9811 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9813 fp0 = tcg_temp_new_i64();
9814 gen_load_fpr64(ctx, fp0, fs);
9815 gen_store_fpr64(ctx, fp0, fd);
9816 tcg_temp_free_i64(fp0);
9817 gen_set_label(l1);
9819 opn = "movz.d";
9820 break;
9821 case OPC_MOVN_D:
9822 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9824 TCGLabel *l1 = gen_new_label();
9825 TCGv_i64 fp0;
9827 if (ft != 0) {
9828 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9829 fp0 = tcg_temp_new_i64();
9830 gen_load_fpr64(ctx, fp0, fs);
9831 gen_store_fpr64(ctx, fp0, fd);
9832 tcg_temp_free_i64(fp0);
9833 gen_set_label(l1);
9836 opn = "movn.d";
9837 break;
9838 case OPC_RECIP_D:
9839 check_cp1_64bitmode(ctx);
9841 TCGv_i64 fp0 = tcg_temp_new_i64();
9843 gen_load_fpr64(ctx, fp0, fs);
9844 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9845 gen_store_fpr64(ctx, fp0, fd);
9846 tcg_temp_free_i64(fp0);
9848 opn = "recip.d";
9849 break;
9850 case OPC_RSQRT_D:
9851 check_cp1_64bitmode(ctx);
9853 TCGv_i64 fp0 = tcg_temp_new_i64();
9855 gen_load_fpr64(ctx, fp0, fs);
9856 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9857 gen_store_fpr64(ctx, fp0, fd);
9858 tcg_temp_free_i64(fp0);
9860 opn = "rsqrt.d";
9861 break;
9862 case OPC_MADDF_D:
9863 check_insn(ctx, ISA_MIPS32R6);
9865 TCGv_i64 fp0 = tcg_temp_new_i64();
9866 TCGv_i64 fp1 = tcg_temp_new_i64();
9867 TCGv_i64 fp2 = tcg_temp_new_i64();
9868 gen_load_fpr64(ctx, fp0, fs);
9869 gen_load_fpr64(ctx, fp1, ft);
9870 gen_load_fpr64(ctx, fp2, fd);
9871 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9872 gen_store_fpr64(ctx, fp2, fd);
9873 tcg_temp_free_i64(fp2);
9874 tcg_temp_free_i64(fp1);
9875 tcg_temp_free_i64(fp0);
9876 opn = "maddf.d";
9878 break;
9879 case OPC_MSUBF_D:
9880 check_insn(ctx, ISA_MIPS32R6);
9882 TCGv_i64 fp0 = tcg_temp_new_i64();
9883 TCGv_i64 fp1 = tcg_temp_new_i64();
9884 TCGv_i64 fp2 = tcg_temp_new_i64();
9885 gen_load_fpr64(ctx, fp0, fs);
9886 gen_load_fpr64(ctx, fp1, ft);
9887 gen_load_fpr64(ctx, fp2, fd);
9888 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9889 gen_store_fpr64(ctx, fp2, fd);
9890 tcg_temp_free_i64(fp2);
9891 tcg_temp_free_i64(fp1);
9892 tcg_temp_free_i64(fp0);
9893 opn = "msubf.d";
9895 break;
9896 case OPC_RINT_D:
9897 check_insn(ctx, ISA_MIPS32R6);
9899 TCGv_i64 fp0 = tcg_temp_new_i64();
9900 gen_load_fpr64(ctx, fp0, fs);
9901 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9902 gen_store_fpr64(ctx, fp0, fd);
9903 tcg_temp_free_i64(fp0);
9904 opn = "rint.d";
9906 break;
9907 case OPC_CLASS_D:
9908 check_insn(ctx, ISA_MIPS32R6);
9910 TCGv_i64 fp0 = tcg_temp_new_i64();
9911 gen_load_fpr64(ctx, fp0, fs);
9912 gen_helper_float_class_d(fp0, fp0);
9913 gen_store_fpr64(ctx, fp0, fd);
9914 tcg_temp_free_i64(fp0);
9915 opn = "class.d";
9917 break;
9918 case OPC_MIN_D: /* OPC_RECIP2_D */
9919 if (ctx->insn_flags & ISA_MIPS32R6) {
9920 /* OPC_MIN_D */
9921 TCGv_i64 fp0 = tcg_temp_new_i64();
9922 TCGv_i64 fp1 = tcg_temp_new_i64();
9923 gen_load_fpr64(ctx, fp0, fs);
9924 gen_load_fpr64(ctx, fp1, ft);
9925 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9926 gen_store_fpr64(ctx, fp1, fd);
9927 tcg_temp_free_i64(fp1);
9928 tcg_temp_free_i64(fp0);
9929 opn = "min.d";
9930 } else {
9931 /* OPC_RECIP2_D */
9932 check_cp1_64bitmode(ctx);
9934 TCGv_i64 fp0 = tcg_temp_new_i64();
9935 TCGv_i64 fp1 = tcg_temp_new_i64();
9937 gen_load_fpr64(ctx, fp0, fs);
9938 gen_load_fpr64(ctx, fp1, ft);
9939 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9940 tcg_temp_free_i64(fp1);
9941 gen_store_fpr64(ctx, fp0, fd);
9942 tcg_temp_free_i64(fp0);
9944 opn = "recip2.d";
9946 break;
9947 case OPC_MINA_D: /* OPC_RECIP1_D */
9948 if (ctx->insn_flags & ISA_MIPS32R6) {
9949 /* OPC_MINA_D */
9950 TCGv_i64 fp0 = tcg_temp_new_i64();
9951 TCGv_i64 fp1 = tcg_temp_new_i64();
9952 gen_load_fpr64(ctx, fp0, fs);
9953 gen_load_fpr64(ctx, fp1, ft);
9954 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9955 gen_store_fpr64(ctx, fp1, fd);
9956 tcg_temp_free_i64(fp1);
9957 tcg_temp_free_i64(fp0);
9958 opn = "mina.d";
9959 } else {
9960 /* OPC_RECIP1_D */
9961 check_cp1_64bitmode(ctx);
9963 TCGv_i64 fp0 = tcg_temp_new_i64();
9965 gen_load_fpr64(ctx, fp0, fs);
9966 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9967 gen_store_fpr64(ctx, fp0, fd);
9968 tcg_temp_free_i64(fp0);
9970 opn = "recip1.d";
9972 break;
9973 case OPC_MAX_D: /* OPC_RSQRT1_D */
9974 if (ctx->insn_flags & ISA_MIPS32R6) {
9975 /* OPC_MAX_D */
9976 TCGv_i64 fp0 = tcg_temp_new_i64();
9977 TCGv_i64 fp1 = tcg_temp_new_i64();
9978 gen_load_fpr64(ctx, fp0, fs);
9979 gen_load_fpr64(ctx, fp1, ft);
9980 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9981 gen_store_fpr64(ctx, fp1, fd);
9982 tcg_temp_free_i64(fp1);
9983 tcg_temp_free_i64(fp0);
9984 opn = "max.d";
9985 } else {
9986 /* OPC_RSQRT1_D */
9987 check_cp1_64bitmode(ctx);
9989 TCGv_i64 fp0 = tcg_temp_new_i64();
9991 gen_load_fpr64(ctx, fp0, fs);
9992 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9993 gen_store_fpr64(ctx, fp0, fd);
9994 tcg_temp_free_i64(fp0);
9996 opn = "rsqrt1.d";
9998 break;
9999 case OPC_MAXA_D: /* OPC_RSQRT2_D */
10000 if (ctx->insn_flags & ISA_MIPS32R6) {
10001 /* OPC_MAXA_D */
10002 TCGv_i64 fp0 = tcg_temp_new_i64();
10003 TCGv_i64 fp1 = tcg_temp_new_i64();
10004 gen_load_fpr64(ctx, fp0, fs);
10005 gen_load_fpr64(ctx, fp1, ft);
10006 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
10007 gen_store_fpr64(ctx, fp1, fd);
10008 tcg_temp_free_i64(fp1);
10009 tcg_temp_free_i64(fp0);
10010 opn = "maxa.d";
10011 } else {
10012 /* OPC_RSQRT2_D */
10013 check_cp1_64bitmode(ctx);
10015 TCGv_i64 fp0 = tcg_temp_new_i64();
10016 TCGv_i64 fp1 = tcg_temp_new_i64();
10018 gen_load_fpr64(ctx, fp0, fs);
10019 gen_load_fpr64(ctx, fp1, ft);
10020 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
10021 tcg_temp_free_i64(fp1);
10022 gen_store_fpr64(ctx, fp0, fd);
10023 tcg_temp_free_i64(fp0);
10025 opn = "rsqrt2.d";
10027 break;
10028 case OPC_CMP_F_D:
10029 case OPC_CMP_UN_D:
10030 case OPC_CMP_EQ_D:
10031 case OPC_CMP_UEQ_D:
10032 case OPC_CMP_OLT_D:
10033 case OPC_CMP_ULT_D:
10034 case OPC_CMP_OLE_D:
10035 case OPC_CMP_ULE_D:
10036 case OPC_CMP_SF_D:
10037 case OPC_CMP_NGLE_D:
10038 case OPC_CMP_SEQ_D:
10039 case OPC_CMP_NGL_D:
10040 case OPC_CMP_LT_D:
10041 case OPC_CMP_NGE_D:
10042 case OPC_CMP_LE_D:
10043 case OPC_CMP_NGT_D:
10044 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10045 if (ctx->opcode & (1 << 6)) {
10046 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
10047 opn = condnames_abs[func-48];
10048 } else {
10049 gen_cmp_d(ctx, func-48, ft, fs, cc);
10050 opn = condnames[func-48];
10052 optype = CMPOP;
10053 break;
10054 case OPC_CVT_S_D:
10055 check_cp1_registers(ctx, fs);
10057 TCGv_i32 fp32 = tcg_temp_new_i32();
10058 TCGv_i64 fp64 = tcg_temp_new_i64();
10060 gen_load_fpr64(ctx, fp64, fs);
10061 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
10062 tcg_temp_free_i64(fp64);
10063 gen_store_fpr32(ctx, fp32, fd);
10064 tcg_temp_free_i32(fp32);
10066 opn = "cvt.s.d";
10067 break;
10068 case OPC_CVT_W_D:
10069 check_cp1_registers(ctx, fs);
10071 TCGv_i32 fp32 = tcg_temp_new_i32();
10072 TCGv_i64 fp64 = tcg_temp_new_i64();
10074 gen_load_fpr64(ctx, fp64, fs);
10075 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
10076 tcg_temp_free_i64(fp64);
10077 gen_store_fpr32(ctx, fp32, fd);
10078 tcg_temp_free_i32(fp32);
10080 opn = "cvt.w.d";
10081 break;
10082 case OPC_CVT_L_D:
10083 check_cp1_64bitmode(ctx);
10085 TCGv_i64 fp0 = tcg_temp_new_i64();
10087 gen_load_fpr64(ctx, fp0, fs);
10088 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
10089 gen_store_fpr64(ctx, fp0, fd);
10090 tcg_temp_free_i64(fp0);
10092 opn = "cvt.l.d";
10093 break;
10094 case OPC_CVT_S_W:
10096 TCGv_i32 fp0 = tcg_temp_new_i32();
10098 gen_load_fpr32(ctx, fp0, fs);
10099 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
10100 gen_store_fpr32(ctx, fp0, fd);
10101 tcg_temp_free_i32(fp0);
10103 opn = "cvt.s.w";
10104 break;
10105 case OPC_CVT_D_W:
10106 check_cp1_registers(ctx, fd);
10108 TCGv_i32 fp32 = tcg_temp_new_i32();
10109 TCGv_i64 fp64 = tcg_temp_new_i64();
10111 gen_load_fpr32(ctx, fp32, fs);
10112 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
10113 tcg_temp_free_i32(fp32);
10114 gen_store_fpr64(ctx, fp64, fd);
10115 tcg_temp_free_i64(fp64);
10117 opn = "cvt.d.w";
10118 break;
10119 case OPC_CVT_S_L:
10120 check_cp1_64bitmode(ctx);
10122 TCGv_i32 fp32 = tcg_temp_new_i32();
10123 TCGv_i64 fp64 = tcg_temp_new_i64();
10125 gen_load_fpr64(ctx, fp64, fs);
10126 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
10127 tcg_temp_free_i64(fp64);
10128 gen_store_fpr32(ctx, fp32, fd);
10129 tcg_temp_free_i32(fp32);
10131 opn = "cvt.s.l";
10132 break;
10133 case OPC_CVT_D_L:
10134 check_cp1_64bitmode(ctx);
10136 TCGv_i64 fp0 = tcg_temp_new_i64();
10138 gen_load_fpr64(ctx, fp0, fs);
10139 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
10140 gen_store_fpr64(ctx, fp0, fd);
10141 tcg_temp_free_i64(fp0);
10143 opn = "cvt.d.l";
10144 break;
10145 case OPC_CVT_PS_PW:
10146 check_ps(ctx);
10148 TCGv_i64 fp0 = tcg_temp_new_i64();
10150 gen_load_fpr64(ctx, fp0, fs);
10151 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
10152 gen_store_fpr64(ctx, fp0, fd);
10153 tcg_temp_free_i64(fp0);
10155 opn = "cvt.ps.pw";
10156 break;
10157 case OPC_ADD_PS:
10158 check_ps(ctx);
10160 TCGv_i64 fp0 = tcg_temp_new_i64();
10161 TCGv_i64 fp1 = tcg_temp_new_i64();
10163 gen_load_fpr64(ctx, fp0, fs);
10164 gen_load_fpr64(ctx, fp1, ft);
10165 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
10166 tcg_temp_free_i64(fp1);
10167 gen_store_fpr64(ctx, fp0, fd);
10168 tcg_temp_free_i64(fp0);
10170 opn = "add.ps";
10171 break;
10172 case OPC_SUB_PS:
10173 check_ps(ctx);
10175 TCGv_i64 fp0 = tcg_temp_new_i64();
10176 TCGv_i64 fp1 = tcg_temp_new_i64();
10178 gen_load_fpr64(ctx, fp0, fs);
10179 gen_load_fpr64(ctx, fp1, ft);
10180 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
10181 tcg_temp_free_i64(fp1);
10182 gen_store_fpr64(ctx, fp0, fd);
10183 tcg_temp_free_i64(fp0);
10185 opn = "sub.ps";
10186 break;
10187 case OPC_MUL_PS:
10188 check_ps(ctx);
10190 TCGv_i64 fp0 = tcg_temp_new_i64();
10191 TCGv_i64 fp1 = tcg_temp_new_i64();
10193 gen_load_fpr64(ctx, fp0, fs);
10194 gen_load_fpr64(ctx, fp1, ft);
10195 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
10196 tcg_temp_free_i64(fp1);
10197 gen_store_fpr64(ctx, fp0, fd);
10198 tcg_temp_free_i64(fp0);
10200 opn = "mul.ps";
10201 break;
10202 case OPC_ABS_PS:
10203 check_ps(ctx);
10205 TCGv_i64 fp0 = tcg_temp_new_i64();
10207 gen_load_fpr64(ctx, fp0, fs);
10208 gen_helper_float_abs_ps(fp0, fp0);
10209 gen_store_fpr64(ctx, fp0, fd);
10210 tcg_temp_free_i64(fp0);
10212 opn = "abs.ps";
10213 break;
10214 case OPC_MOV_PS:
10215 check_ps(ctx);
10217 TCGv_i64 fp0 = tcg_temp_new_i64();
10219 gen_load_fpr64(ctx, fp0, fs);
10220 gen_store_fpr64(ctx, fp0, fd);
10221 tcg_temp_free_i64(fp0);
10223 opn = "mov.ps";
10224 break;
10225 case OPC_NEG_PS:
10226 check_ps(ctx);
10228 TCGv_i64 fp0 = tcg_temp_new_i64();
10230 gen_load_fpr64(ctx, fp0, fs);
10231 gen_helper_float_chs_ps(fp0, fp0);
10232 gen_store_fpr64(ctx, fp0, fd);
10233 tcg_temp_free_i64(fp0);
10235 opn = "neg.ps";
10236 break;
10237 case OPC_MOVCF_PS:
10238 check_ps(ctx);
10239 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10240 opn = "movcf.ps";
10241 break;
10242 case OPC_MOVZ_PS:
10243 check_ps(ctx);
10245 TCGLabel *l1 = gen_new_label();
10246 TCGv_i64 fp0;
10248 if (ft != 0)
10249 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10250 fp0 = tcg_temp_new_i64();
10251 gen_load_fpr64(ctx, fp0, fs);
10252 gen_store_fpr64(ctx, fp0, fd);
10253 tcg_temp_free_i64(fp0);
10254 gen_set_label(l1);
10256 opn = "movz.ps";
10257 break;
10258 case OPC_MOVN_PS:
10259 check_ps(ctx);
10261 TCGLabel *l1 = gen_new_label();
10262 TCGv_i64 fp0;
10264 if (ft != 0) {
10265 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10266 fp0 = tcg_temp_new_i64();
10267 gen_load_fpr64(ctx, fp0, fs);
10268 gen_store_fpr64(ctx, fp0, fd);
10269 tcg_temp_free_i64(fp0);
10270 gen_set_label(l1);
10273 opn = "movn.ps";
10274 break;
10275 case OPC_ADDR_PS:
10276 check_ps(ctx);
10278 TCGv_i64 fp0 = tcg_temp_new_i64();
10279 TCGv_i64 fp1 = tcg_temp_new_i64();
10281 gen_load_fpr64(ctx, fp0, ft);
10282 gen_load_fpr64(ctx, fp1, fs);
10283 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
10284 tcg_temp_free_i64(fp1);
10285 gen_store_fpr64(ctx, fp0, fd);
10286 tcg_temp_free_i64(fp0);
10288 opn = "addr.ps";
10289 break;
10290 case OPC_MULR_PS:
10291 check_ps(ctx);
10293 TCGv_i64 fp0 = tcg_temp_new_i64();
10294 TCGv_i64 fp1 = tcg_temp_new_i64();
10296 gen_load_fpr64(ctx, fp0, ft);
10297 gen_load_fpr64(ctx, fp1, fs);
10298 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
10299 tcg_temp_free_i64(fp1);
10300 gen_store_fpr64(ctx, fp0, fd);
10301 tcg_temp_free_i64(fp0);
10303 opn = "mulr.ps";
10304 break;
10305 case OPC_RECIP2_PS:
10306 check_ps(ctx);
10308 TCGv_i64 fp0 = tcg_temp_new_i64();
10309 TCGv_i64 fp1 = tcg_temp_new_i64();
10311 gen_load_fpr64(ctx, fp0, fs);
10312 gen_load_fpr64(ctx, fp1, ft);
10313 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
10314 tcg_temp_free_i64(fp1);
10315 gen_store_fpr64(ctx, fp0, fd);
10316 tcg_temp_free_i64(fp0);
10318 opn = "recip2.ps";
10319 break;
10320 case OPC_RECIP1_PS:
10321 check_ps(ctx);
10323 TCGv_i64 fp0 = tcg_temp_new_i64();
10325 gen_load_fpr64(ctx, fp0, fs);
10326 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
10327 gen_store_fpr64(ctx, fp0, fd);
10328 tcg_temp_free_i64(fp0);
10330 opn = "recip1.ps";
10331 break;
10332 case OPC_RSQRT1_PS:
10333 check_ps(ctx);
10335 TCGv_i64 fp0 = tcg_temp_new_i64();
10337 gen_load_fpr64(ctx, fp0, fs);
10338 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
10339 gen_store_fpr64(ctx, fp0, fd);
10340 tcg_temp_free_i64(fp0);
10342 opn = "rsqrt1.ps";
10343 break;
10344 case OPC_RSQRT2_PS:
10345 check_ps(ctx);
10347 TCGv_i64 fp0 = tcg_temp_new_i64();
10348 TCGv_i64 fp1 = tcg_temp_new_i64();
10350 gen_load_fpr64(ctx, fp0, fs);
10351 gen_load_fpr64(ctx, fp1, ft);
10352 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
10353 tcg_temp_free_i64(fp1);
10354 gen_store_fpr64(ctx, fp0, fd);
10355 tcg_temp_free_i64(fp0);
10357 opn = "rsqrt2.ps";
10358 break;
10359 case OPC_CVT_S_PU:
10360 check_cp1_64bitmode(ctx);
10362 TCGv_i32 fp0 = tcg_temp_new_i32();
10364 gen_load_fpr32h(ctx, fp0, fs);
10365 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
10366 gen_store_fpr32(ctx, fp0, fd);
10367 tcg_temp_free_i32(fp0);
10369 opn = "cvt.s.pu";
10370 break;
10371 case OPC_CVT_PW_PS:
10372 check_ps(ctx);
10374 TCGv_i64 fp0 = tcg_temp_new_i64();
10376 gen_load_fpr64(ctx, fp0, fs);
10377 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
10378 gen_store_fpr64(ctx, fp0, fd);
10379 tcg_temp_free_i64(fp0);
10381 opn = "cvt.pw.ps";
10382 break;
10383 case OPC_CVT_S_PL:
10384 check_cp1_64bitmode(ctx);
10386 TCGv_i32 fp0 = tcg_temp_new_i32();
10388 gen_load_fpr32(ctx, fp0, fs);
10389 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
10390 gen_store_fpr32(ctx, fp0, fd);
10391 tcg_temp_free_i32(fp0);
10393 opn = "cvt.s.pl";
10394 break;
10395 case OPC_PLL_PS:
10396 check_ps(ctx);
10398 TCGv_i32 fp0 = tcg_temp_new_i32();
10399 TCGv_i32 fp1 = tcg_temp_new_i32();
10401 gen_load_fpr32(ctx, fp0, fs);
10402 gen_load_fpr32(ctx, fp1, ft);
10403 gen_store_fpr32h(ctx, fp0, fd);
10404 gen_store_fpr32(ctx, fp1, fd);
10405 tcg_temp_free_i32(fp0);
10406 tcg_temp_free_i32(fp1);
10408 opn = "pll.ps";
10409 break;
10410 case OPC_PLU_PS:
10411 check_ps(ctx);
10413 TCGv_i32 fp0 = tcg_temp_new_i32();
10414 TCGv_i32 fp1 = tcg_temp_new_i32();
10416 gen_load_fpr32(ctx, fp0, fs);
10417 gen_load_fpr32h(ctx, fp1, ft);
10418 gen_store_fpr32(ctx, fp1, fd);
10419 gen_store_fpr32h(ctx, fp0, fd);
10420 tcg_temp_free_i32(fp0);
10421 tcg_temp_free_i32(fp1);
10423 opn = "plu.ps";
10424 break;
10425 case OPC_PUL_PS:
10426 check_ps(ctx);
10428 TCGv_i32 fp0 = tcg_temp_new_i32();
10429 TCGv_i32 fp1 = tcg_temp_new_i32();
10431 gen_load_fpr32h(ctx, fp0, fs);
10432 gen_load_fpr32(ctx, fp1, ft);
10433 gen_store_fpr32(ctx, fp1, fd);
10434 gen_store_fpr32h(ctx, fp0, fd);
10435 tcg_temp_free_i32(fp0);
10436 tcg_temp_free_i32(fp1);
10438 opn = "pul.ps";
10439 break;
10440 case OPC_PUU_PS:
10441 check_ps(ctx);
10443 TCGv_i32 fp0 = tcg_temp_new_i32();
10444 TCGv_i32 fp1 = tcg_temp_new_i32();
10446 gen_load_fpr32h(ctx, fp0, fs);
10447 gen_load_fpr32h(ctx, fp1, ft);
10448 gen_store_fpr32(ctx, fp1, fd);
10449 gen_store_fpr32h(ctx, fp0, fd);
10450 tcg_temp_free_i32(fp0);
10451 tcg_temp_free_i32(fp1);
10453 opn = "puu.ps";
10454 break;
10455 case OPC_CMP_F_PS:
10456 case OPC_CMP_UN_PS:
10457 case OPC_CMP_EQ_PS:
10458 case OPC_CMP_UEQ_PS:
10459 case OPC_CMP_OLT_PS:
10460 case OPC_CMP_ULT_PS:
10461 case OPC_CMP_OLE_PS:
10462 case OPC_CMP_ULE_PS:
10463 case OPC_CMP_SF_PS:
10464 case OPC_CMP_NGLE_PS:
10465 case OPC_CMP_SEQ_PS:
10466 case OPC_CMP_NGL_PS:
10467 case OPC_CMP_LT_PS:
10468 case OPC_CMP_NGE_PS:
10469 case OPC_CMP_LE_PS:
10470 case OPC_CMP_NGT_PS:
10471 if (ctx->opcode & (1 << 6)) {
10472 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10473 opn = condnames_abs[func-48];
10474 } else {
10475 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10476 opn = condnames[func-48];
10478 optype = CMPOP;
10479 break;
10480 default:
10481 MIPS_INVAL(opn);
10482 generate_exception (ctx, EXCP_RI);
10483 return;
10485 (void)opn; /* avoid a compiler warning */
10486 switch (optype) {
10487 case BINOP:
10488 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
10489 break;
10490 case CMPOP:
10491 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
10492 break;
10493 default:
10494 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
10495 break;
10499 /* Coprocessor 3 (FPU) */
10500 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10501 int fd, int fs, int base, int index)
10503 const char *opn = "extended float load/store";
10504 int store = 0;
10505 TCGv t0 = tcg_temp_new();
10507 if (base == 0) {
10508 gen_load_gpr(t0, index);
10509 } else if (index == 0) {
10510 gen_load_gpr(t0, base);
10511 } else {
10512 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10514 /* Don't do NOP if destination is zero: we must perform the actual
10515 memory access. */
10516 switch (opc) {
10517 case OPC_LWXC1:
10518 check_cop1x(ctx);
10520 TCGv_i32 fp0 = tcg_temp_new_i32();
10522 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10523 tcg_gen_trunc_tl_i32(fp0, t0);
10524 gen_store_fpr32(ctx, fp0, fd);
10525 tcg_temp_free_i32(fp0);
10527 opn = "lwxc1";
10528 break;
10529 case OPC_LDXC1:
10530 check_cop1x(ctx);
10531 check_cp1_registers(ctx, fd);
10533 TCGv_i64 fp0 = tcg_temp_new_i64();
10534 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10535 gen_store_fpr64(ctx, fp0, fd);
10536 tcg_temp_free_i64(fp0);
10538 opn = "ldxc1";
10539 break;
10540 case OPC_LUXC1:
10541 check_cp1_64bitmode(ctx);
10542 tcg_gen_andi_tl(t0, t0, ~0x7);
10544 TCGv_i64 fp0 = tcg_temp_new_i64();
10546 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10547 gen_store_fpr64(ctx, fp0, fd);
10548 tcg_temp_free_i64(fp0);
10550 opn = "luxc1";
10551 break;
10552 case OPC_SWXC1:
10553 check_cop1x(ctx);
10555 TCGv_i32 fp0 = tcg_temp_new_i32();
10556 gen_load_fpr32(ctx, fp0, fs);
10557 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10558 tcg_temp_free_i32(fp0);
10560 opn = "swxc1";
10561 store = 1;
10562 break;
10563 case OPC_SDXC1:
10564 check_cop1x(ctx);
10565 check_cp1_registers(ctx, fs);
10567 TCGv_i64 fp0 = tcg_temp_new_i64();
10568 gen_load_fpr64(ctx, fp0, fs);
10569 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10570 tcg_temp_free_i64(fp0);
10572 opn = "sdxc1";
10573 store = 1;
10574 break;
10575 case OPC_SUXC1:
10576 check_cp1_64bitmode(ctx);
10577 tcg_gen_andi_tl(t0, t0, ~0x7);
10579 TCGv_i64 fp0 = tcg_temp_new_i64();
10580 gen_load_fpr64(ctx, fp0, fs);
10581 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10582 tcg_temp_free_i64(fp0);
10584 opn = "suxc1";
10585 store = 1;
10586 break;
10588 tcg_temp_free(t0);
10589 (void)opn; (void)store; /* avoid compiler warnings */
10590 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
10591 regnames[index], regnames[base]);
10594 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10595 int fd, int fr, int fs, int ft)
10597 const char *opn = "flt3_arith";
10599 switch (opc) {
10600 case OPC_ALNV_PS:
10601 check_ps(ctx);
10603 TCGv t0 = tcg_temp_local_new();
10604 TCGv_i32 fp = tcg_temp_new_i32();
10605 TCGv_i32 fph = tcg_temp_new_i32();
10606 TCGLabel *l1 = gen_new_label();
10607 TCGLabel *l2 = gen_new_label();
10609 gen_load_gpr(t0, fr);
10610 tcg_gen_andi_tl(t0, t0, 0x7);
10612 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10613 gen_load_fpr32(ctx, fp, fs);
10614 gen_load_fpr32h(ctx, fph, fs);
10615 gen_store_fpr32(ctx, fp, fd);
10616 gen_store_fpr32h(ctx, fph, fd);
10617 tcg_gen_br(l2);
10618 gen_set_label(l1);
10619 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10620 tcg_temp_free(t0);
10621 #ifdef TARGET_WORDS_BIGENDIAN
10622 gen_load_fpr32(ctx, fp, fs);
10623 gen_load_fpr32h(ctx, fph, ft);
10624 gen_store_fpr32h(ctx, fp, fd);
10625 gen_store_fpr32(ctx, fph, fd);
10626 #else
10627 gen_load_fpr32h(ctx, fph, fs);
10628 gen_load_fpr32(ctx, fp, ft);
10629 gen_store_fpr32(ctx, fph, fd);
10630 gen_store_fpr32h(ctx, fp, fd);
10631 #endif
10632 gen_set_label(l2);
10633 tcg_temp_free_i32(fp);
10634 tcg_temp_free_i32(fph);
10636 opn = "alnv.ps";
10637 break;
10638 case OPC_MADD_S:
10639 check_cop1x(ctx);
10641 TCGv_i32 fp0 = tcg_temp_new_i32();
10642 TCGv_i32 fp1 = tcg_temp_new_i32();
10643 TCGv_i32 fp2 = tcg_temp_new_i32();
10645 gen_load_fpr32(ctx, fp0, fs);
10646 gen_load_fpr32(ctx, fp1, ft);
10647 gen_load_fpr32(ctx, fp2, fr);
10648 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10649 tcg_temp_free_i32(fp0);
10650 tcg_temp_free_i32(fp1);
10651 gen_store_fpr32(ctx, fp2, fd);
10652 tcg_temp_free_i32(fp2);
10654 opn = "madd.s";
10655 break;
10656 case OPC_MADD_D:
10657 check_cop1x(ctx);
10658 check_cp1_registers(ctx, fd | fs | ft | fr);
10660 TCGv_i64 fp0 = tcg_temp_new_i64();
10661 TCGv_i64 fp1 = tcg_temp_new_i64();
10662 TCGv_i64 fp2 = tcg_temp_new_i64();
10664 gen_load_fpr64(ctx, fp0, fs);
10665 gen_load_fpr64(ctx, fp1, ft);
10666 gen_load_fpr64(ctx, fp2, fr);
10667 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10668 tcg_temp_free_i64(fp0);
10669 tcg_temp_free_i64(fp1);
10670 gen_store_fpr64(ctx, fp2, fd);
10671 tcg_temp_free_i64(fp2);
10673 opn = "madd.d";
10674 break;
10675 case OPC_MADD_PS:
10676 check_ps(ctx);
10678 TCGv_i64 fp0 = tcg_temp_new_i64();
10679 TCGv_i64 fp1 = tcg_temp_new_i64();
10680 TCGv_i64 fp2 = tcg_temp_new_i64();
10682 gen_load_fpr64(ctx, fp0, fs);
10683 gen_load_fpr64(ctx, fp1, ft);
10684 gen_load_fpr64(ctx, fp2, fr);
10685 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10686 tcg_temp_free_i64(fp0);
10687 tcg_temp_free_i64(fp1);
10688 gen_store_fpr64(ctx, fp2, fd);
10689 tcg_temp_free_i64(fp2);
10691 opn = "madd.ps";
10692 break;
10693 case OPC_MSUB_S:
10694 check_cop1x(ctx);
10696 TCGv_i32 fp0 = tcg_temp_new_i32();
10697 TCGv_i32 fp1 = tcg_temp_new_i32();
10698 TCGv_i32 fp2 = tcg_temp_new_i32();
10700 gen_load_fpr32(ctx, fp0, fs);
10701 gen_load_fpr32(ctx, fp1, ft);
10702 gen_load_fpr32(ctx, fp2, fr);
10703 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10704 tcg_temp_free_i32(fp0);
10705 tcg_temp_free_i32(fp1);
10706 gen_store_fpr32(ctx, fp2, fd);
10707 tcg_temp_free_i32(fp2);
10709 opn = "msub.s";
10710 break;
10711 case OPC_MSUB_D:
10712 check_cop1x(ctx);
10713 check_cp1_registers(ctx, fd | fs | ft | fr);
10715 TCGv_i64 fp0 = tcg_temp_new_i64();
10716 TCGv_i64 fp1 = tcg_temp_new_i64();
10717 TCGv_i64 fp2 = tcg_temp_new_i64();
10719 gen_load_fpr64(ctx, fp0, fs);
10720 gen_load_fpr64(ctx, fp1, ft);
10721 gen_load_fpr64(ctx, fp2, fr);
10722 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
10723 tcg_temp_free_i64(fp0);
10724 tcg_temp_free_i64(fp1);
10725 gen_store_fpr64(ctx, fp2, fd);
10726 tcg_temp_free_i64(fp2);
10728 opn = "msub.d";
10729 break;
10730 case OPC_MSUB_PS:
10731 check_ps(ctx);
10733 TCGv_i64 fp0 = tcg_temp_new_i64();
10734 TCGv_i64 fp1 = tcg_temp_new_i64();
10735 TCGv_i64 fp2 = tcg_temp_new_i64();
10737 gen_load_fpr64(ctx, fp0, fs);
10738 gen_load_fpr64(ctx, fp1, ft);
10739 gen_load_fpr64(ctx, fp2, fr);
10740 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10741 tcg_temp_free_i64(fp0);
10742 tcg_temp_free_i64(fp1);
10743 gen_store_fpr64(ctx, fp2, fd);
10744 tcg_temp_free_i64(fp2);
10746 opn = "msub.ps";
10747 break;
10748 case OPC_NMADD_S:
10749 check_cop1x(ctx);
10751 TCGv_i32 fp0 = tcg_temp_new_i32();
10752 TCGv_i32 fp1 = tcg_temp_new_i32();
10753 TCGv_i32 fp2 = tcg_temp_new_i32();
10755 gen_load_fpr32(ctx, fp0, fs);
10756 gen_load_fpr32(ctx, fp1, ft);
10757 gen_load_fpr32(ctx, fp2, fr);
10758 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10759 tcg_temp_free_i32(fp0);
10760 tcg_temp_free_i32(fp1);
10761 gen_store_fpr32(ctx, fp2, fd);
10762 tcg_temp_free_i32(fp2);
10764 opn = "nmadd.s";
10765 break;
10766 case OPC_NMADD_D:
10767 check_cop1x(ctx);
10768 check_cp1_registers(ctx, fd | fs | ft | fr);
10770 TCGv_i64 fp0 = tcg_temp_new_i64();
10771 TCGv_i64 fp1 = tcg_temp_new_i64();
10772 TCGv_i64 fp2 = tcg_temp_new_i64();
10774 gen_load_fpr64(ctx, fp0, fs);
10775 gen_load_fpr64(ctx, fp1, ft);
10776 gen_load_fpr64(ctx, fp2, fr);
10777 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10778 tcg_temp_free_i64(fp0);
10779 tcg_temp_free_i64(fp1);
10780 gen_store_fpr64(ctx, fp2, fd);
10781 tcg_temp_free_i64(fp2);
10783 opn = "nmadd.d";
10784 break;
10785 case OPC_NMADD_PS:
10786 check_ps(ctx);
10788 TCGv_i64 fp0 = tcg_temp_new_i64();
10789 TCGv_i64 fp1 = tcg_temp_new_i64();
10790 TCGv_i64 fp2 = tcg_temp_new_i64();
10792 gen_load_fpr64(ctx, fp0, fs);
10793 gen_load_fpr64(ctx, fp1, ft);
10794 gen_load_fpr64(ctx, fp2, fr);
10795 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10796 tcg_temp_free_i64(fp0);
10797 tcg_temp_free_i64(fp1);
10798 gen_store_fpr64(ctx, fp2, fd);
10799 tcg_temp_free_i64(fp2);
10801 opn = "nmadd.ps";
10802 break;
10803 case OPC_NMSUB_S:
10804 check_cop1x(ctx);
10806 TCGv_i32 fp0 = tcg_temp_new_i32();
10807 TCGv_i32 fp1 = tcg_temp_new_i32();
10808 TCGv_i32 fp2 = tcg_temp_new_i32();
10810 gen_load_fpr32(ctx, fp0, fs);
10811 gen_load_fpr32(ctx, fp1, ft);
10812 gen_load_fpr32(ctx, fp2, fr);
10813 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10814 tcg_temp_free_i32(fp0);
10815 tcg_temp_free_i32(fp1);
10816 gen_store_fpr32(ctx, fp2, fd);
10817 tcg_temp_free_i32(fp2);
10819 opn = "nmsub.s";
10820 break;
10821 case OPC_NMSUB_D:
10822 check_cop1x(ctx);
10823 check_cp1_registers(ctx, fd | fs | ft | fr);
10825 TCGv_i64 fp0 = tcg_temp_new_i64();
10826 TCGv_i64 fp1 = tcg_temp_new_i64();
10827 TCGv_i64 fp2 = tcg_temp_new_i64();
10829 gen_load_fpr64(ctx, fp0, fs);
10830 gen_load_fpr64(ctx, fp1, ft);
10831 gen_load_fpr64(ctx, fp2, fr);
10832 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10833 tcg_temp_free_i64(fp0);
10834 tcg_temp_free_i64(fp1);
10835 gen_store_fpr64(ctx, fp2, fd);
10836 tcg_temp_free_i64(fp2);
10838 opn = "nmsub.d";
10839 break;
10840 case OPC_NMSUB_PS:
10841 check_ps(ctx);
10843 TCGv_i64 fp0 = tcg_temp_new_i64();
10844 TCGv_i64 fp1 = tcg_temp_new_i64();
10845 TCGv_i64 fp2 = tcg_temp_new_i64();
10847 gen_load_fpr64(ctx, fp0, fs);
10848 gen_load_fpr64(ctx, fp1, ft);
10849 gen_load_fpr64(ctx, fp2, fr);
10850 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10851 tcg_temp_free_i64(fp0);
10852 tcg_temp_free_i64(fp1);
10853 gen_store_fpr64(ctx, fp2, fd);
10854 tcg_temp_free_i64(fp2);
10856 opn = "nmsub.ps";
10857 break;
10858 default:
10859 MIPS_INVAL(opn);
10860 generate_exception (ctx, EXCP_RI);
10861 return;
10863 (void)opn; /* avoid a compiler warning */
10864 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
10865 fregnames[fs], fregnames[ft]);
10868 static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
10870 TCGv t0;
10872 #if !defined(CONFIG_USER_ONLY)
10873 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10874 Therefore only check the ISA in system mode. */
10875 check_insn(ctx, ISA_MIPS32R2);
10876 #endif
10877 t0 = tcg_temp_new();
10879 switch (rd) {
10880 case 0:
10881 save_cpu_state(ctx, 1);
10882 gen_helper_rdhwr_cpunum(t0, cpu_env);
10883 gen_store_gpr(t0, rt);
10884 break;
10885 case 1:
10886 save_cpu_state(ctx, 1);
10887 gen_helper_rdhwr_synci_step(t0, cpu_env);
10888 gen_store_gpr(t0, rt);
10889 break;
10890 case 2:
10891 save_cpu_state(ctx, 1);
10892 gen_helper_rdhwr_cc(t0, cpu_env);
10893 gen_store_gpr(t0, rt);
10894 break;
10895 case 3:
10896 save_cpu_state(ctx, 1);
10897 gen_helper_rdhwr_ccres(t0, cpu_env);
10898 gen_store_gpr(t0, rt);
10899 break;
10900 case 29:
10901 #if defined(CONFIG_USER_ONLY)
10902 tcg_gen_ld_tl(t0, cpu_env,
10903 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10904 gen_store_gpr(t0, rt);
10905 break;
10906 #else
10907 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10908 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10909 tcg_gen_ld_tl(t0, cpu_env,
10910 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10911 gen_store_gpr(t0, rt);
10912 } else {
10913 generate_exception(ctx, EXCP_RI);
10915 break;
10916 #endif
10917 default: /* Invalid */
10918 MIPS_INVAL("rdhwr");
10919 generate_exception(ctx, EXCP_RI);
10920 break;
10922 tcg_temp_free(t0);
10925 static inline void clear_branch_hflags(DisasContext *ctx)
10927 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10928 if (ctx->bstate == BS_NONE) {
10929 save_cpu_state(ctx, 0);
10930 } else {
10931 /* it is not safe to save ctx->hflags as hflags may be changed
10932 in execution time by the instruction in delay / forbidden slot. */
10933 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10937 static void gen_branch(DisasContext *ctx, int insn_bytes)
10939 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10940 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10941 /* Branches completion */
10942 clear_branch_hflags(ctx);
10943 ctx->bstate = BS_BRANCH;
10944 /* FIXME: Need to clear can_do_io. */
10945 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10946 case MIPS_HFLAG_FBNSLOT:
10947 MIPS_DEBUG("forbidden slot");
10948 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10949 break;
10950 case MIPS_HFLAG_B:
10951 /* unconditional branch */
10952 MIPS_DEBUG("unconditional branch");
10953 if (proc_hflags & MIPS_HFLAG_BX) {
10954 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10956 gen_goto_tb(ctx, 0, ctx->btarget);
10957 break;
10958 case MIPS_HFLAG_BL:
10959 /* blikely taken case */
10960 MIPS_DEBUG("blikely branch taken");
10961 gen_goto_tb(ctx, 0, ctx->btarget);
10962 break;
10963 case MIPS_HFLAG_BC:
10964 /* Conditional branch */
10965 MIPS_DEBUG("conditional branch");
10967 TCGLabel *l1 = gen_new_label();
10969 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10970 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10971 gen_set_label(l1);
10972 gen_goto_tb(ctx, 0, ctx->btarget);
10974 break;
10975 case MIPS_HFLAG_BR:
10976 /* unconditional branch to register */
10977 MIPS_DEBUG("branch to register");
10978 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10979 TCGv t0 = tcg_temp_new();
10980 TCGv_i32 t1 = tcg_temp_new_i32();
10982 tcg_gen_andi_tl(t0, btarget, 0x1);
10983 tcg_gen_trunc_tl_i32(t1, t0);
10984 tcg_temp_free(t0);
10985 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10986 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10987 tcg_gen_or_i32(hflags, hflags, t1);
10988 tcg_temp_free_i32(t1);
10990 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10991 } else {
10992 tcg_gen_mov_tl(cpu_PC, btarget);
10994 if (ctx->singlestep_enabled) {
10995 save_cpu_state(ctx, 0);
10996 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
10998 tcg_gen_exit_tb(0);
10999 break;
11000 default:
11001 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
11002 abort();
11007 /* Compact Branches */
11008 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
11009 int rs, int rt, int32_t offset)
11011 int bcond_compute = 0;
11012 TCGv t0 = tcg_temp_new();
11013 TCGv t1 = tcg_temp_new();
11014 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
11016 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11017 #ifdef MIPS_DEBUG_DISAS
11018 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11019 "\n", ctx->pc);
11020 #endif
11021 generate_exception(ctx, EXCP_RI);
11022 goto out;
11025 /* Load needed operands and calculate btarget */
11026 switch (opc) {
11027 /* compact branch */
11028 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11029 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11030 gen_load_gpr(t0, rs);
11031 gen_load_gpr(t1, rt);
11032 bcond_compute = 1;
11033 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11034 if (rs <= rt && rs == 0) {
11035 /* OPC_BEQZALC, OPC_BNEZALC */
11036 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11038 break;
11039 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11040 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11041 gen_load_gpr(t0, rs);
11042 gen_load_gpr(t1, rt);
11043 bcond_compute = 1;
11044 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11045 break;
11046 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11047 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11048 if (rs == 0 || rs == rt) {
11049 /* OPC_BLEZALC, OPC_BGEZALC */
11050 /* OPC_BGTZALC, OPC_BLTZALC */
11051 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11053 gen_load_gpr(t0, rs);
11054 gen_load_gpr(t1, rt);
11055 bcond_compute = 1;
11056 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11057 break;
11058 case OPC_BC:
11059 case OPC_BALC:
11060 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11061 break;
11062 case OPC_BEQZC:
11063 case OPC_BNEZC:
11064 if (rs != 0) {
11065 /* OPC_BEQZC, OPC_BNEZC */
11066 gen_load_gpr(t0, rs);
11067 bcond_compute = 1;
11068 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
11069 } else {
11070 /* OPC_JIC, OPC_JIALC */
11071 TCGv tbase = tcg_temp_new();
11072 TCGv toffset = tcg_temp_new();
11074 gen_load_gpr(tbase, rt);
11075 tcg_gen_movi_tl(toffset, offset);
11076 gen_op_addr_add(ctx, btarget, tbase, toffset);
11077 tcg_temp_free(tbase);
11078 tcg_temp_free(toffset);
11080 break;
11081 default:
11082 MIPS_INVAL("Compact branch/jump");
11083 generate_exception(ctx, EXCP_RI);
11084 goto out;
11087 if (bcond_compute == 0) {
11088 /* Uncoditional compact branch */
11089 switch (opc) {
11090 case OPC_JIALC:
11091 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11092 /* Fallthrough */
11093 case OPC_JIC:
11094 ctx->hflags |= MIPS_HFLAG_BR;
11095 break;
11096 case OPC_BALC:
11097 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
11098 /* Fallthrough */
11099 case OPC_BC:
11100 ctx->hflags |= MIPS_HFLAG_B;
11101 break;
11102 default:
11103 MIPS_INVAL("Compact branch/jump");
11104 generate_exception(ctx, EXCP_RI);
11105 goto out;
11108 /* Generating branch here as compact branches don't have delay slot */
11109 gen_branch(ctx, 4);
11110 } else {
11111 /* Conditional compact branch */
11112 TCGLabel *fs = gen_new_label();
11113 save_cpu_state(ctx, 0);
11115 switch (opc) {
11116 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11117 if (rs == 0 && rt != 0) {
11118 /* OPC_BLEZALC */
11119 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11120 } else if (rs != 0 && rt != 0 && rs == rt) {
11121 /* OPC_BGEZALC */
11122 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11123 } else {
11124 /* OPC_BGEUC */
11125 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
11127 break;
11128 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11129 if (rs == 0 && rt != 0) {
11130 /* OPC_BGTZALC */
11131 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11132 } else if (rs != 0 && rt != 0 && rs == rt) {
11133 /* OPC_BLTZALC */
11134 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11135 } else {
11136 /* OPC_BLTUC */
11137 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
11139 break;
11140 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11141 if (rs == 0 && rt != 0) {
11142 /* OPC_BLEZC */
11143 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11144 } else if (rs != 0 && rt != 0 && rs == rt) {
11145 /* OPC_BGEZC */
11146 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11147 } else {
11148 /* OPC_BGEC */
11149 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
11151 break;
11152 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11153 if (rs == 0 && rt != 0) {
11154 /* OPC_BGTZC */
11155 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11156 } else if (rs != 0 && rt != 0 && rs == rt) {
11157 /* OPC_BLTZC */
11158 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11159 } else {
11160 /* OPC_BLTC */
11161 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
11163 break;
11164 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11165 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11166 if (rs >= rt) {
11167 /* OPC_BOVC, OPC_BNVC */
11168 TCGv t2 = tcg_temp_new();
11169 TCGv t3 = tcg_temp_new();
11170 TCGv t4 = tcg_temp_new();
11171 TCGv input_overflow = tcg_temp_new();
11173 gen_load_gpr(t0, rs);
11174 gen_load_gpr(t1, rt);
11175 tcg_gen_ext32s_tl(t2, t0);
11176 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
11177 tcg_gen_ext32s_tl(t3, t1);
11178 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
11179 tcg_gen_or_tl(input_overflow, input_overflow, t4);
11181 tcg_gen_add_tl(t4, t2, t3);
11182 tcg_gen_ext32s_tl(t4, t4);
11183 tcg_gen_xor_tl(t2, t2, t3);
11184 tcg_gen_xor_tl(t3, t4, t3);
11185 tcg_gen_andc_tl(t2, t3, t2);
11186 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
11187 tcg_gen_or_tl(t4, t4, input_overflow);
11188 if (opc == OPC_BOVC) {
11189 /* OPC_BOVC */
11190 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
11191 } else {
11192 /* OPC_BNVC */
11193 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
11195 tcg_temp_free(input_overflow);
11196 tcg_temp_free(t4);
11197 tcg_temp_free(t3);
11198 tcg_temp_free(t2);
11199 } else if (rs < rt && rs == 0) {
11200 /* OPC_BEQZALC, OPC_BNEZALC */
11201 if (opc == OPC_BEQZALC) {
11202 /* OPC_BEQZALC */
11203 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
11204 } else {
11205 /* OPC_BNEZALC */
11206 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
11208 } else {
11209 /* OPC_BEQC, OPC_BNEC */
11210 if (opc == OPC_BEQC) {
11211 /* OPC_BEQC */
11212 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
11213 } else {
11214 /* OPC_BNEC */
11215 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
11218 break;
11219 case OPC_BEQZC:
11220 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
11221 break;
11222 case OPC_BNEZC:
11223 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
11224 break;
11225 default:
11226 MIPS_INVAL("Compact conditional branch/jump");
11227 generate_exception(ctx, EXCP_RI);
11228 goto out;
11231 /* Generating branch here as compact branches don't have delay slot */
11232 gen_goto_tb(ctx, 1, ctx->btarget);
11233 gen_set_label(fs);
11235 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
11236 MIPS_DEBUG("Compact conditional branch");
11239 out:
11240 tcg_temp_free(t0);
11241 tcg_temp_free(t1);
11244 /* ISA extensions (ASEs) */
11245 /* MIPS16 extension to MIPS32 */
11247 /* MIPS16 major opcodes */
11248 enum {
11249 M16_OPC_ADDIUSP = 0x00,
11250 M16_OPC_ADDIUPC = 0x01,
11251 M16_OPC_B = 0x02,
11252 M16_OPC_JAL = 0x03,
11253 M16_OPC_BEQZ = 0x04,
11254 M16_OPC_BNEQZ = 0x05,
11255 M16_OPC_SHIFT = 0x06,
11256 M16_OPC_LD = 0x07,
11257 M16_OPC_RRIA = 0x08,
11258 M16_OPC_ADDIU8 = 0x09,
11259 M16_OPC_SLTI = 0x0a,
11260 M16_OPC_SLTIU = 0x0b,
11261 M16_OPC_I8 = 0x0c,
11262 M16_OPC_LI = 0x0d,
11263 M16_OPC_CMPI = 0x0e,
11264 M16_OPC_SD = 0x0f,
11265 M16_OPC_LB = 0x10,
11266 M16_OPC_LH = 0x11,
11267 M16_OPC_LWSP = 0x12,
11268 M16_OPC_LW = 0x13,
11269 M16_OPC_LBU = 0x14,
11270 M16_OPC_LHU = 0x15,
11271 M16_OPC_LWPC = 0x16,
11272 M16_OPC_LWU = 0x17,
11273 M16_OPC_SB = 0x18,
11274 M16_OPC_SH = 0x19,
11275 M16_OPC_SWSP = 0x1a,
11276 M16_OPC_SW = 0x1b,
11277 M16_OPC_RRR = 0x1c,
11278 M16_OPC_RR = 0x1d,
11279 M16_OPC_EXTEND = 0x1e,
11280 M16_OPC_I64 = 0x1f
11283 /* I8 funct field */
11284 enum {
11285 I8_BTEQZ = 0x0,
11286 I8_BTNEZ = 0x1,
11287 I8_SWRASP = 0x2,
11288 I8_ADJSP = 0x3,
11289 I8_SVRS = 0x4,
11290 I8_MOV32R = 0x5,
11291 I8_MOVR32 = 0x7
11294 /* RRR f field */
11295 enum {
11296 RRR_DADDU = 0x0,
11297 RRR_ADDU = 0x1,
11298 RRR_DSUBU = 0x2,
11299 RRR_SUBU = 0x3
11302 /* RR funct field */
11303 enum {
11304 RR_JR = 0x00,
11305 RR_SDBBP = 0x01,
11306 RR_SLT = 0x02,
11307 RR_SLTU = 0x03,
11308 RR_SLLV = 0x04,
11309 RR_BREAK = 0x05,
11310 RR_SRLV = 0x06,
11311 RR_SRAV = 0x07,
11312 RR_DSRL = 0x08,
11313 RR_CMP = 0x0a,
11314 RR_NEG = 0x0b,
11315 RR_AND = 0x0c,
11316 RR_OR = 0x0d,
11317 RR_XOR = 0x0e,
11318 RR_NOT = 0x0f,
11319 RR_MFHI = 0x10,
11320 RR_CNVT = 0x11,
11321 RR_MFLO = 0x12,
11322 RR_DSRA = 0x13,
11323 RR_DSLLV = 0x14,
11324 RR_DSRLV = 0x16,
11325 RR_DSRAV = 0x17,
11326 RR_MULT = 0x18,
11327 RR_MULTU = 0x19,
11328 RR_DIV = 0x1a,
11329 RR_DIVU = 0x1b,
11330 RR_DMULT = 0x1c,
11331 RR_DMULTU = 0x1d,
11332 RR_DDIV = 0x1e,
11333 RR_DDIVU = 0x1f
11336 /* I64 funct field */
11337 enum {
11338 I64_LDSP = 0x0,
11339 I64_SDSP = 0x1,
11340 I64_SDRASP = 0x2,
11341 I64_DADJSP = 0x3,
11342 I64_LDPC = 0x4,
11343 I64_DADDIU5 = 0x5,
11344 I64_DADDIUPC = 0x6,
11345 I64_DADDIUSP = 0x7
11348 /* RR ry field for CNVT */
11349 enum {
11350 RR_RY_CNVT_ZEB = 0x0,
11351 RR_RY_CNVT_ZEH = 0x1,
11352 RR_RY_CNVT_ZEW = 0x2,
11353 RR_RY_CNVT_SEB = 0x4,
11354 RR_RY_CNVT_SEH = 0x5,
11355 RR_RY_CNVT_SEW = 0x6,
11358 static int xlat (int r)
11360 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11362 return map[r];
11365 static void gen_mips16_save (DisasContext *ctx,
11366 int xsregs, int aregs,
11367 int do_ra, int do_s0, int do_s1,
11368 int framesize)
11370 TCGv t0 = tcg_temp_new();
11371 TCGv t1 = tcg_temp_new();
11372 TCGv t2 = tcg_temp_new();
11373 int args, astatic;
11375 switch (aregs) {
11376 case 0:
11377 case 1:
11378 case 2:
11379 case 3:
11380 case 11:
11381 args = 0;
11382 break;
11383 case 4:
11384 case 5:
11385 case 6:
11386 case 7:
11387 args = 1;
11388 break;
11389 case 8:
11390 case 9:
11391 case 10:
11392 args = 2;
11393 break;
11394 case 12:
11395 case 13:
11396 args = 3;
11397 break;
11398 case 14:
11399 args = 4;
11400 break;
11401 default:
11402 generate_exception(ctx, EXCP_RI);
11403 return;
11406 switch (args) {
11407 case 4:
11408 gen_base_offset_addr(ctx, t0, 29, 12);
11409 gen_load_gpr(t1, 7);
11410 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11411 /* Fall through */
11412 case 3:
11413 gen_base_offset_addr(ctx, t0, 29, 8);
11414 gen_load_gpr(t1, 6);
11415 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11416 /* Fall through */
11417 case 2:
11418 gen_base_offset_addr(ctx, t0, 29, 4);
11419 gen_load_gpr(t1, 5);
11420 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11421 /* Fall through */
11422 case 1:
11423 gen_base_offset_addr(ctx, t0, 29, 0);
11424 gen_load_gpr(t1, 4);
11425 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11428 gen_load_gpr(t0, 29);
11430 #define DECR_AND_STORE(reg) do { \
11431 tcg_gen_movi_tl(t2, -4); \
11432 gen_op_addr_add(ctx, t0, t0, t2); \
11433 gen_load_gpr(t1, reg); \
11434 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
11435 } while (0)
11437 if (do_ra) {
11438 DECR_AND_STORE(31);
11441 switch (xsregs) {
11442 case 7:
11443 DECR_AND_STORE(30);
11444 /* Fall through */
11445 case 6:
11446 DECR_AND_STORE(23);
11447 /* Fall through */
11448 case 5:
11449 DECR_AND_STORE(22);
11450 /* Fall through */
11451 case 4:
11452 DECR_AND_STORE(21);
11453 /* Fall through */
11454 case 3:
11455 DECR_AND_STORE(20);
11456 /* Fall through */
11457 case 2:
11458 DECR_AND_STORE(19);
11459 /* Fall through */
11460 case 1:
11461 DECR_AND_STORE(18);
11464 if (do_s1) {
11465 DECR_AND_STORE(17);
11467 if (do_s0) {
11468 DECR_AND_STORE(16);
11471 switch (aregs) {
11472 case 0:
11473 case 4:
11474 case 8:
11475 case 12:
11476 case 14:
11477 astatic = 0;
11478 break;
11479 case 1:
11480 case 5:
11481 case 9:
11482 case 13:
11483 astatic = 1;
11484 break;
11485 case 2:
11486 case 6:
11487 case 10:
11488 astatic = 2;
11489 break;
11490 case 3:
11491 case 7:
11492 astatic = 3;
11493 break;
11494 case 11:
11495 astatic = 4;
11496 break;
11497 default:
11498 generate_exception(ctx, EXCP_RI);
11499 return;
11502 if (astatic > 0) {
11503 DECR_AND_STORE(7);
11504 if (astatic > 1) {
11505 DECR_AND_STORE(6);
11506 if (astatic > 2) {
11507 DECR_AND_STORE(5);
11508 if (astatic > 3) {
11509 DECR_AND_STORE(4);
11514 #undef DECR_AND_STORE
11516 tcg_gen_movi_tl(t2, -framesize);
11517 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11518 tcg_temp_free(t0);
11519 tcg_temp_free(t1);
11520 tcg_temp_free(t2);
11523 static void gen_mips16_restore (DisasContext *ctx,
11524 int xsregs, int aregs,
11525 int do_ra, int do_s0, int do_s1,
11526 int framesize)
11528 int astatic;
11529 TCGv t0 = tcg_temp_new();
11530 TCGv t1 = tcg_temp_new();
11531 TCGv t2 = tcg_temp_new();
11533 tcg_gen_movi_tl(t2, framesize);
11534 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11536 #define DECR_AND_LOAD(reg) do { \
11537 tcg_gen_movi_tl(t2, -4); \
11538 gen_op_addr_add(ctx, t0, t0, t2); \
11539 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11540 gen_store_gpr(t1, reg); \
11541 } while (0)
11543 if (do_ra) {
11544 DECR_AND_LOAD(31);
11547 switch (xsregs) {
11548 case 7:
11549 DECR_AND_LOAD(30);
11550 /* Fall through */
11551 case 6:
11552 DECR_AND_LOAD(23);
11553 /* Fall through */
11554 case 5:
11555 DECR_AND_LOAD(22);
11556 /* Fall through */
11557 case 4:
11558 DECR_AND_LOAD(21);
11559 /* Fall through */
11560 case 3:
11561 DECR_AND_LOAD(20);
11562 /* Fall through */
11563 case 2:
11564 DECR_AND_LOAD(19);
11565 /* Fall through */
11566 case 1:
11567 DECR_AND_LOAD(18);
11570 if (do_s1) {
11571 DECR_AND_LOAD(17);
11573 if (do_s0) {
11574 DECR_AND_LOAD(16);
11577 switch (aregs) {
11578 case 0:
11579 case 4:
11580 case 8:
11581 case 12:
11582 case 14:
11583 astatic = 0;
11584 break;
11585 case 1:
11586 case 5:
11587 case 9:
11588 case 13:
11589 astatic = 1;
11590 break;
11591 case 2:
11592 case 6:
11593 case 10:
11594 astatic = 2;
11595 break;
11596 case 3:
11597 case 7:
11598 astatic = 3;
11599 break;
11600 case 11:
11601 astatic = 4;
11602 break;
11603 default:
11604 generate_exception(ctx, EXCP_RI);
11605 return;
11608 if (astatic > 0) {
11609 DECR_AND_LOAD(7);
11610 if (astatic > 1) {
11611 DECR_AND_LOAD(6);
11612 if (astatic > 2) {
11613 DECR_AND_LOAD(5);
11614 if (astatic > 3) {
11615 DECR_AND_LOAD(4);
11620 #undef DECR_AND_LOAD
11622 tcg_gen_movi_tl(t2, framesize);
11623 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11624 tcg_temp_free(t0);
11625 tcg_temp_free(t1);
11626 tcg_temp_free(t2);
11629 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11630 int is_64_bit, int extended)
11632 TCGv t0;
11634 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11635 generate_exception(ctx, EXCP_RI);
11636 return;
11639 t0 = tcg_temp_new();
11641 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11642 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11643 if (!is_64_bit) {
11644 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11647 tcg_temp_free(t0);
11650 #if defined(TARGET_MIPS64)
11651 static void decode_i64_mips16 (DisasContext *ctx,
11652 int ry, int funct, int16_t offset,
11653 int extended)
11655 switch (funct) {
11656 case I64_LDSP:
11657 check_insn(ctx, ISA_MIPS3);
11658 check_mips_64(ctx);
11659 offset = extended ? offset : offset << 3;
11660 gen_ld(ctx, OPC_LD, ry, 29, offset);
11661 break;
11662 case I64_SDSP:
11663 check_insn(ctx, ISA_MIPS3);
11664 check_mips_64(ctx);
11665 offset = extended ? offset : offset << 3;
11666 gen_st(ctx, OPC_SD, ry, 29, offset);
11667 break;
11668 case I64_SDRASP:
11669 check_insn(ctx, ISA_MIPS3);
11670 check_mips_64(ctx);
11671 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11672 gen_st(ctx, OPC_SD, 31, 29, offset);
11673 break;
11674 case I64_DADJSP:
11675 check_insn(ctx, ISA_MIPS3);
11676 check_mips_64(ctx);
11677 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11678 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11679 break;
11680 case I64_LDPC:
11681 check_insn(ctx, ISA_MIPS3);
11682 check_mips_64(ctx);
11683 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11684 generate_exception(ctx, EXCP_RI);
11685 } else {
11686 offset = extended ? offset : offset << 3;
11687 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11689 break;
11690 case I64_DADDIU5:
11691 check_insn(ctx, ISA_MIPS3);
11692 check_mips_64(ctx);
11693 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11694 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11695 break;
11696 case I64_DADDIUPC:
11697 check_insn(ctx, ISA_MIPS3);
11698 check_mips_64(ctx);
11699 offset = extended ? offset : offset << 2;
11700 gen_addiupc(ctx, ry, offset, 1, extended);
11701 break;
11702 case I64_DADDIUSP:
11703 check_insn(ctx, ISA_MIPS3);
11704 check_mips_64(ctx);
11705 offset = extended ? offset : offset << 2;
11706 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11707 break;
11710 #endif
11712 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11714 int extend = cpu_lduw_code(env, ctx->pc + 2);
11715 int op, rx, ry, funct, sa;
11716 int16_t imm, offset;
11718 ctx->opcode = (ctx->opcode << 16) | extend;
11719 op = (ctx->opcode >> 11) & 0x1f;
11720 sa = (ctx->opcode >> 22) & 0x1f;
11721 funct = (ctx->opcode >> 8) & 0x7;
11722 rx = xlat((ctx->opcode >> 8) & 0x7);
11723 ry = xlat((ctx->opcode >> 5) & 0x7);
11724 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11725 | ((ctx->opcode >> 21) & 0x3f) << 5
11726 | (ctx->opcode & 0x1f));
11728 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11729 counterparts. */
11730 switch (op) {
11731 case M16_OPC_ADDIUSP:
11732 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11733 break;
11734 case M16_OPC_ADDIUPC:
11735 gen_addiupc(ctx, rx, imm, 0, 1);
11736 break;
11737 case M16_OPC_B:
11738 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11739 /* No delay slot, so just process as a normal instruction */
11740 break;
11741 case M16_OPC_BEQZ:
11742 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11743 /* No delay slot, so just process as a normal instruction */
11744 break;
11745 case M16_OPC_BNEQZ:
11746 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11747 /* No delay slot, so just process as a normal instruction */
11748 break;
11749 case M16_OPC_SHIFT:
11750 switch (ctx->opcode & 0x3) {
11751 case 0x0:
11752 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11753 break;
11754 case 0x1:
11755 #if defined(TARGET_MIPS64)
11756 check_mips_64(ctx);
11757 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11758 #else
11759 generate_exception(ctx, EXCP_RI);
11760 #endif
11761 break;
11762 case 0x2:
11763 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11764 break;
11765 case 0x3:
11766 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11767 break;
11769 break;
11770 #if defined(TARGET_MIPS64)
11771 case M16_OPC_LD:
11772 check_insn(ctx, ISA_MIPS3);
11773 check_mips_64(ctx);
11774 gen_ld(ctx, OPC_LD, ry, rx, offset);
11775 break;
11776 #endif
11777 case M16_OPC_RRIA:
11778 imm = ctx->opcode & 0xf;
11779 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11780 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11781 imm = (int16_t) (imm << 1) >> 1;
11782 if ((ctx->opcode >> 4) & 0x1) {
11783 #if defined(TARGET_MIPS64)
11784 check_mips_64(ctx);
11785 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11786 #else
11787 generate_exception(ctx, EXCP_RI);
11788 #endif
11789 } else {
11790 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11792 break;
11793 case M16_OPC_ADDIU8:
11794 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11795 break;
11796 case M16_OPC_SLTI:
11797 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11798 break;
11799 case M16_OPC_SLTIU:
11800 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11801 break;
11802 case M16_OPC_I8:
11803 switch (funct) {
11804 case I8_BTEQZ:
11805 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11806 break;
11807 case I8_BTNEZ:
11808 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11809 break;
11810 case I8_SWRASP:
11811 gen_st(ctx, OPC_SW, 31, 29, imm);
11812 break;
11813 case I8_ADJSP:
11814 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11815 break;
11816 case I8_SVRS:
11817 check_insn(ctx, ISA_MIPS32);
11819 int xsregs = (ctx->opcode >> 24) & 0x7;
11820 int aregs = (ctx->opcode >> 16) & 0xf;
11821 int do_ra = (ctx->opcode >> 6) & 0x1;
11822 int do_s0 = (ctx->opcode >> 5) & 0x1;
11823 int do_s1 = (ctx->opcode >> 4) & 0x1;
11824 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11825 | (ctx->opcode & 0xf)) << 3;
11827 if (ctx->opcode & (1 << 7)) {
11828 gen_mips16_save(ctx, xsregs, aregs,
11829 do_ra, do_s0, do_s1,
11830 framesize);
11831 } else {
11832 gen_mips16_restore(ctx, xsregs, aregs,
11833 do_ra, do_s0, do_s1,
11834 framesize);
11837 break;
11838 default:
11839 generate_exception(ctx, EXCP_RI);
11840 break;
11842 break;
11843 case M16_OPC_LI:
11844 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11845 break;
11846 case M16_OPC_CMPI:
11847 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11848 break;
11849 #if defined(TARGET_MIPS64)
11850 case M16_OPC_SD:
11851 check_insn(ctx, ISA_MIPS3);
11852 check_mips_64(ctx);
11853 gen_st(ctx, OPC_SD, ry, rx, offset);
11854 break;
11855 #endif
11856 case M16_OPC_LB:
11857 gen_ld(ctx, OPC_LB, ry, rx, offset);
11858 break;
11859 case M16_OPC_LH:
11860 gen_ld(ctx, OPC_LH, ry, rx, offset);
11861 break;
11862 case M16_OPC_LWSP:
11863 gen_ld(ctx, OPC_LW, rx, 29, offset);
11864 break;
11865 case M16_OPC_LW:
11866 gen_ld(ctx, OPC_LW, ry, rx, offset);
11867 break;
11868 case M16_OPC_LBU:
11869 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11870 break;
11871 case M16_OPC_LHU:
11872 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11873 break;
11874 case M16_OPC_LWPC:
11875 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11876 break;
11877 #if defined(TARGET_MIPS64)
11878 case M16_OPC_LWU:
11879 check_insn(ctx, ISA_MIPS3);
11880 check_mips_64(ctx);
11881 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11882 break;
11883 #endif
11884 case M16_OPC_SB:
11885 gen_st(ctx, OPC_SB, ry, rx, offset);
11886 break;
11887 case M16_OPC_SH:
11888 gen_st(ctx, OPC_SH, ry, rx, offset);
11889 break;
11890 case M16_OPC_SWSP:
11891 gen_st(ctx, OPC_SW, rx, 29, offset);
11892 break;
11893 case M16_OPC_SW:
11894 gen_st(ctx, OPC_SW, ry, rx, offset);
11895 break;
11896 #if defined(TARGET_MIPS64)
11897 case M16_OPC_I64:
11898 decode_i64_mips16(ctx, ry, funct, offset, 1);
11899 break;
11900 #endif
11901 default:
11902 generate_exception(ctx, EXCP_RI);
11903 break;
11906 return 4;
11909 static inline bool is_uhi(int sdbbp_code)
11911 #ifdef CONFIG_USER_ONLY
11912 return false;
11913 #else
11914 return semihosting_enabled() && sdbbp_code == 1;
11915 #endif
11918 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11920 int rx, ry;
11921 int sa;
11922 int op, cnvt_op, op1, offset;
11923 int funct;
11924 int n_bytes;
11926 op = (ctx->opcode >> 11) & 0x1f;
11927 sa = (ctx->opcode >> 2) & 0x7;
11928 sa = sa == 0 ? 8 : sa;
11929 rx = xlat((ctx->opcode >> 8) & 0x7);
11930 cnvt_op = (ctx->opcode >> 5) & 0x7;
11931 ry = xlat((ctx->opcode >> 5) & 0x7);
11932 op1 = offset = ctx->opcode & 0x1f;
11934 n_bytes = 2;
11936 switch (op) {
11937 case M16_OPC_ADDIUSP:
11939 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11941 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11943 break;
11944 case M16_OPC_ADDIUPC:
11945 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11946 break;
11947 case M16_OPC_B:
11948 offset = (ctx->opcode & 0x7ff) << 1;
11949 offset = (int16_t)(offset << 4) >> 4;
11950 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11951 /* No delay slot, so just process as a normal instruction */
11952 break;
11953 case M16_OPC_JAL:
11954 offset = cpu_lduw_code(env, ctx->pc + 2);
11955 offset = (((ctx->opcode & 0x1f) << 21)
11956 | ((ctx->opcode >> 5) & 0x1f) << 16
11957 | offset) << 2;
11958 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11959 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11960 n_bytes = 4;
11961 break;
11962 case M16_OPC_BEQZ:
11963 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11964 ((int8_t)ctx->opcode) << 1, 0);
11965 /* No delay slot, so just process as a normal instruction */
11966 break;
11967 case M16_OPC_BNEQZ:
11968 gen_compute_branch(ctx, OPC_BNE, 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_SHIFT:
11973 switch (ctx->opcode & 0x3) {
11974 case 0x0:
11975 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11976 break;
11977 case 0x1:
11978 #if defined(TARGET_MIPS64)
11979 check_insn(ctx, ISA_MIPS3);
11980 check_mips_64(ctx);
11981 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11982 #else
11983 generate_exception(ctx, EXCP_RI);
11984 #endif
11985 break;
11986 case 0x2:
11987 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11988 break;
11989 case 0x3:
11990 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11991 break;
11993 break;
11994 #if defined(TARGET_MIPS64)
11995 case M16_OPC_LD:
11996 check_insn(ctx, ISA_MIPS3);
11997 check_mips_64(ctx);
11998 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
11999 break;
12000 #endif
12001 case M16_OPC_RRIA:
12003 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
12005 if ((ctx->opcode >> 4) & 1) {
12006 #if defined(TARGET_MIPS64)
12007 check_insn(ctx, ISA_MIPS3);
12008 check_mips_64(ctx);
12009 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12010 #else
12011 generate_exception(ctx, EXCP_RI);
12012 #endif
12013 } else {
12014 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12017 break;
12018 case M16_OPC_ADDIU8:
12020 int16_t imm = (int8_t) ctx->opcode;
12022 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12024 break;
12025 case M16_OPC_SLTI:
12027 int16_t imm = (uint8_t) ctx->opcode;
12028 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12030 break;
12031 case M16_OPC_SLTIU:
12033 int16_t imm = (uint8_t) ctx->opcode;
12034 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12036 break;
12037 case M16_OPC_I8:
12039 int reg32;
12041 funct = (ctx->opcode >> 8) & 0x7;
12042 switch (funct) {
12043 case I8_BTEQZ:
12044 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
12045 ((int8_t)ctx->opcode) << 1, 0);
12046 break;
12047 case I8_BTNEZ:
12048 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
12049 ((int8_t)ctx->opcode) << 1, 0);
12050 break;
12051 case I8_SWRASP:
12052 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
12053 break;
12054 case I8_ADJSP:
12055 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
12056 ((int8_t)ctx->opcode) << 3);
12057 break;
12058 case I8_SVRS:
12059 check_insn(ctx, ISA_MIPS32);
12061 int do_ra = ctx->opcode & (1 << 6);
12062 int do_s0 = ctx->opcode & (1 << 5);
12063 int do_s1 = ctx->opcode & (1 << 4);
12064 int framesize = ctx->opcode & 0xf;
12066 if (framesize == 0) {
12067 framesize = 128;
12068 } else {
12069 framesize = framesize << 3;
12072 if (ctx->opcode & (1 << 7)) {
12073 gen_mips16_save(ctx, 0, 0,
12074 do_ra, do_s0, do_s1, framesize);
12075 } else {
12076 gen_mips16_restore(ctx, 0, 0,
12077 do_ra, do_s0, do_s1, framesize);
12080 break;
12081 case I8_MOV32R:
12083 int rz = xlat(ctx->opcode & 0x7);
12085 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
12086 ((ctx->opcode >> 5) & 0x7);
12087 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
12089 break;
12090 case I8_MOVR32:
12091 reg32 = ctx->opcode & 0x1f;
12092 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
12093 break;
12094 default:
12095 generate_exception(ctx, EXCP_RI);
12096 break;
12099 break;
12100 case M16_OPC_LI:
12102 int16_t imm = (uint8_t) ctx->opcode;
12104 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
12106 break;
12107 case M16_OPC_CMPI:
12109 int16_t imm = (uint8_t) ctx->opcode;
12110 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
12112 break;
12113 #if defined(TARGET_MIPS64)
12114 case M16_OPC_SD:
12115 check_insn(ctx, ISA_MIPS3);
12116 check_mips_64(ctx);
12117 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
12118 break;
12119 #endif
12120 case M16_OPC_LB:
12121 gen_ld(ctx, OPC_LB, ry, rx, offset);
12122 break;
12123 case M16_OPC_LH:
12124 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
12125 break;
12126 case M16_OPC_LWSP:
12127 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
12128 break;
12129 case M16_OPC_LW:
12130 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
12131 break;
12132 case M16_OPC_LBU:
12133 gen_ld(ctx, OPC_LBU, ry, rx, offset);
12134 break;
12135 case M16_OPC_LHU:
12136 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
12137 break;
12138 case M16_OPC_LWPC:
12139 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
12140 break;
12141 #if defined (TARGET_MIPS64)
12142 case M16_OPC_LWU:
12143 check_insn(ctx, ISA_MIPS3);
12144 check_mips_64(ctx);
12145 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
12146 break;
12147 #endif
12148 case M16_OPC_SB:
12149 gen_st(ctx, OPC_SB, ry, rx, offset);
12150 break;
12151 case M16_OPC_SH:
12152 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
12153 break;
12154 case M16_OPC_SWSP:
12155 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
12156 break;
12157 case M16_OPC_SW:
12158 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
12159 break;
12160 case M16_OPC_RRR:
12162 int rz = xlat((ctx->opcode >> 2) & 0x7);
12163 int mips32_op;
12165 switch (ctx->opcode & 0x3) {
12166 case RRR_ADDU:
12167 mips32_op = OPC_ADDU;
12168 break;
12169 case RRR_SUBU:
12170 mips32_op = OPC_SUBU;
12171 break;
12172 #if defined(TARGET_MIPS64)
12173 case RRR_DADDU:
12174 mips32_op = OPC_DADDU;
12175 check_insn(ctx, ISA_MIPS3);
12176 check_mips_64(ctx);
12177 break;
12178 case RRR_DSUBU:
12179 mips32_op = OPC_DSUBU;
12180 check_insn(ctx, ISA_MIPS3);
12181 check_mips_64(ctx);
12182 break;
12183 #endif
12184 default:
12185 generate_exception(ctx, EXCP_RI);
12186 goto done;
12189 gen_arith(ctx, mips32_op, rz, rx, ry);
12190 done:
12193 break;
12194 case M16_OPC_RR:
12195 switch (op1) {
12196 case RR_JR:
12198 int nd = (ctx->opcode >> 7) & 0x1;
12199 int link = (ctx->opcode >> 6) & 0x1;
12200 int ra = (ctx->opcode >> 5) & 0x1;
12202 if (nd) {
12203 check_insn(ctx, ISA_MIPS32);
12206 if (link) {
12207 op = OPC_JALR;
12208 } else {
12209 op = OPC_JR;
12212 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
12213 (nd ? 0 : 2));
12215 break;
12216 case RR_SDBBP:
12217 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
12218 gen_helper_do_semihosting(cpu_env);
12219 } else {
12220 /* XXX: not clear which exception should be raised
12221 * when in debug mode...
12223 check_insn(ctx, ISA_MIPS32);
12224 generate_exception(ctx, EXCP_DBp);
12226 break;
12227 case RR_SLT:
12228 gen_slt(ctx, OPC_SLT, 24, rx, ry);
12229 break;
12230 case RR_SLTU:
12231 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
12232 break;
12233 case RR_BREAK:
12234 generate_exception(ctx, EXCP_BREAK);
12235 break;
12236 case RR_SLLV:
12237 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
12238 break;
12239 case RR_SRLV:
12240 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
12241 break;
12242 case RR_SRAV:
12243 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
12244 break;
12245 #if defined (TARGET_MIPS64)
12246 case RR_DSRL:
12247 check_insn(ctx, ISA_MIPS3);
12248 check_mips_64(ctx);
12249 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
12250 break;
12251 #endif
12252 case RR_CMP:
12253 gen_logic(ctx, OPC_XOR, 24, rx, ry);
12254 break;
12255 case RR_NEG:
12256 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
12257 break;
12258 case RR_AND:
12259 gen_logic(ctx, OPC_AND, rx, rx, ry);
12260 break;
12261 case RR_OR:
12262 gen_logic(ctx, OPC_OR, rx, rx, ry);
12263 break;
12264 case RR_XOR:
12265 gen_logic(ctx, OPC_XOR, rx, rx, ry);
12266 break;
12267 case RR_NOT:
12268 gen_logic(ctx, OPC_NOR, rx, ry, 0);
12269 break;
12270 case RR_MFHI:
12271 gen_HILO(ctx, OPC_MFHI, 0, rx);
12272 break;
12273 case RR_CNVT:
12274 check_insn(ctx, ISA_MIPS32);
12275 switch (cnvt_op) {
12276 case RR_RY_CNVT_ZEB:
12277 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12278 break;
12279 case RR_RY_CNVT_ZEH:
12280 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12281 break;
12282 case RR_RY_CNVT_SEB:
12283 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12284 break;
12285 case RR_RY_CNVT_SEH:
12286 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12287 break;
12288 #if defined (TARGET_MIPS64)
12289 case RR_RY_CNVT_ZEW:
12290 check_insn(ctx, ISA_MIPS64);
12291 check_mips_64(ctx);
12292 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12293 break;
12294 case RR_RY_CNVT_SEW:
12295 check_insn(ctx, ISA_MIPS64);
12296 check_mips_64(ctx);
12297 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12298 break;
12299 #endif
12300 default:
12301 generate_exception(ctx, EXCP_RI);
12302 break;
12304 break;
12305 case RR_MFLO:
12306 gen_HILO(ctx, OPC_MFLO, 0, rx);
12307 break;
12308 #if defined (TARGET_MIPS64)
12309 case RR_DSRA:
12310 check_insn(ctx, ISA_MIPS3);
12311 check_mips_64(ctx);
12312 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
12313 break;
12314 case RR_DSLLV:
12315 check_insn(ctx, ISA_MIPS3);
12316 check_mips_64(ctx);
12317 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
12318 break;
12319 case RR_DSRLV:
12320 check_insn(ctx, ISA_MIPS3);
12321 check_mips_64(ctx);
12322 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
12323 break;
12324 case RR_DSRAV:
12325 check_insn(ctx, ISA_MIPS3);
12326 check_mips_64(ctx);
12327 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
12328 break;
12329 #endif
12330 case RR_MULT:
12331 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
12332 break;
12333 case RR_MULTU:
12334 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
12335 break;
12336 case RR_DIV:
12337 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
12338 break;
12339 case RR_DIVU:
12340 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
12341 break;
12342 #if defined (TARGET_MIPS64)
12343 case RR_DMULT:
12344 check_insn(ctx, ISA_MIPS3);
12345 check_mips_64(ctx);
12346 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
12347 break;
12348 case RR_DMULTU:
12349 check_insn(ctx, ISA_MIPS3);
12350 check_mips_64(ctx);
12351 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
12352 break;
12353 case RR_DDIV:
12354 check_insn(ctx, ISA_MIPS3);
12355 check_mips_64(ctx);
12356 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
12357 break;
12358 case RR_DDIVU:
12359 check_insn(ctx, ISA_MIPS3);
12360 check_mips_64(ctx);
12361 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
12362 break;
12363 #endif
12364 default:
12365 generate_exception(ctx, EXCP_RI);
12366 break;
12368 break;
12369 case M16_OPC_EXTEND:
12370 decode_extended_mips16_opc(env, ctx);
12371 n_bytes = 4;
12372 break;
12373 #if defined(TARGET_MIPS64)
12374 case M16_OPC_I64:
12375 funct = (ctx->opcode >> 8) & 0x7;
12376 decode_i64_mips16(ctx, ry, funct, offset, 0);
12377 break;
12378 #endif
12379 default:
12380 generate_exception(ctx, EXCP_RI);
12381 break;
12384 return n_bytes;
12387 /* microMIPS extension to MIPS32/MIPS64 */
12390 * microMIPS32/microMIPS64 major opcodes
12392 * 1. MIPS Architecture for Programmers Volume II-B:
12393 * The microMIPS32 Instruction Set (Revision 3.05)
12395 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
12397 * 2. MIPS Architecture For Programmers Volume II-A:
12398 * The MIPS64 Instruction Set (Revision 3.51)
12401 enum {
12402 POOL32A = 0x00,
12403 POOL16A = 0x01,
12404 LBU16 = 0x02,
12405 MOVE16 = 0x03,
12406 ADDI32 = 0x04,
12407 R6_LUI = 0x04,
12408 AUI = 0x04,
12409 LBU32 = 0x05,
12410 SB32 = 0x06,
12411 LB32 = 0x07,
12413 POOL32B = 0x08,
12414 POOL16B = 0x09,
12415 LHU16 = 0x0a,
12416 ANDI16 = 0x0b,
12417 ADDIU32 = 0x0c,
12418 LHU32 = 0x0d,
12419 SH32 = 0x0e,
12420 LH32 = 0x0f,
12422 POOL32I = 0x10,
12423 POOL16C = 0x11,
12424 LWSP16 = 0x12,
12425 POOL16D = 0x13,
12426 ORI32 = 0x14,
12427 POOL32F = 0x15,
12428 POOL32S = 0x16, /* MIPS64 */
12429 DADDIU32 = 0x17, /* MIPS64 */
12431 POOL32C = 0x18,
12432 LWGP16 = 0x19,
12433 LW16 = 0x1a,
12434 POOL16E = 0x1b,
12435 XORI32 = 0x1c,
12436 JALS32 = 0x1d,
12437 BOVC = 0x1d,
12438 BEQC = 0x1d,
12439 BEQZALC = 0x1d,
12440 ADDIUPC = 0x1e,
12441 PCREL = 0x1e,
12442 BNVC = 0x1f,
12443 BNEC = 0x1f,
12444 BNEZALC = 0x1f,
12446 R6_BEQZC = 0x20,
12447 JIC = 0x20,
12448 POOL16F = 0x21,
12449 SB16 = 0x22,
12450 BEQZ16 = 0x23,
12451 BEQZC16 = 0x23,
12452 SLTI32 = 0x24,
12453 BEQ32 = 0x25,
12454 BC = 0x25,
12455 SWC132 = 0x26,
12456 LWC132 = 0x27,
12458 /* 0x29 is reserved */
12459 RES_29 = 0x29,
12460 R6_BNEZC = 0x28,
12461 JIALC = 0x28,
12462 SH16 = 0x2a,
12463 BNEZ16 = 0x2b,
12464 BNEZC16 = 0x2b,
12465 SLTIU32 = 0x2c,
12466 BNE32 = 0x2d,
12467 BALC = 0x2d,
12468 SDC132 = 0x2e,
12469 LDC132 = 0x2f,
12471 /* 0x31 is reserved */
12472 RES_31 = 0x31,
12473 BLEZALC = 0x30,
12474 BGEZALC = 0x30,
12475 BGEUC = 0x30,
12476 SWSP16 = 0x32,
12477 B16 = 0x33,
12478 BC16 = 0x33,
12479 ANDI32 = 0x34,
12480 J32 = 0x35,
12481 BGTZC = 0x35,
12482 BLTZC = 0x35,
12483 BLTC = 0x35,
12484 SD32 = 0x36, /* MIPS64 */
12485 LD32 = 0x37, /* MIPS64 */
12487 /* 0x39 is reserved */
12488 RES_39 = 0x39,
12489 BGTZALC = 0x38,
12490 BLTZALC = 0x38,
12491 BLTUC = 0x38,
12492 SW16 = 0x3a,
12493 LI16 = 0x3b,
12494 JALX32 = 0x3c,
12495 JAL32 = 0x3d,
12496 BLEZC = 0x3d,
12497 BGEZC = 0x3d,
12498 BGEC = 0x3d,
12499 SW32 = 0x3e,
12500 LW32 = 0x3f
12503 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
12504 enum {
12505 ADDIUPC_00 = 0x00,
12506 ADDIUPC_07 = 0x07,
12507 AUIPC = 0x1e,
12508 ALUIPC = 0x1f,
12509 LWPC_08 = 0x08,
12510 LWPC_0F = 0x0F,
12513 /* POOL32A encoding of minor opcode field */
12515 enum {
12516 /* These opcodes are distinguished only by bits 9..6; those bits are
12517 * what are recorded below. */
12518 SLL32 = 0x0,
12519 SRL32 = 0x1,
12520 SRA = 0x2,
12521 ROTR = 0x3,
12522 SELEQZ = 0x5,
12523 SELNEZ = 0x6,
12525 SLLV = 0x0,
12526 SRLV = 0x1,
12527 SRAV = 0x2,
12528 ROTRV = 0x3,
12529 ADD = 0x4,
12530 ADDU32 = 0x5,
12531 SUB = 0x6,
12532 SUBU32 = 0x7,
12533 MUL = 0x8,
12534 AND = 0x9,
12535 OR32 = 0xa,
12536 NOR = 0xb,
12537 XOR32 = 0xc,
12538 SLT = 0xd,
12539 SLTU = 0xe,
12541 MOVN = 0x0,
12542 R6_MUL = 0x0,
12543 MOVZ = 0x1,
12544 MUH = 0x1,
12545 MULU = 0x2,
12546 MUHU = 0x3,
12547 LWXS = 0x4,
12548 R6_DIV = 0x4,
12549 MOD = 0x5,
12550 R6_DIVU = 0x6,
12551 MODU = 0x7,
12553 /* The following can be distinguished by their lower 6 bits. */
12554 INS = 0x0c,
12555 LSA = 0x0f,
12556 ALIGN = 0x1f,
12557 EXT = 0x2c,
12558 POOL32AXF = 0x3c
12561 /* POOL32AXF encoding of minor opcode field extension */
12564 * 1. MIPS Architecture for Programmers Volume II-B:
12565 * The microMIPS32 Instruction Set (Revision 3.05)
12567 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12569 * 2. MIPS Architecture for Programmers VolumeIV-e:
12570 * The MIPS DSP Application-Specific Extension
12571 * to the microMIPS32 Architecture (Revision 2.34)
12573 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12576 enum {
12577 /* bits 11..6 */
12578 TEQ = 0x00,
12579 TGE = 0x08,
12580 TGEU = 0x10,
12581 TLT = 0x20,
12582 TLTU = 0x28,
12583 TNE = 0x30,
12585 MFC0 = 0x03,
12586 MTC0 = 0x0b,
12588 /* begin of microMIPS32 DSP */
12590 /* bits 13..12 for 0x01 */
12591 MFHI_ACC = 0x0,
12592 MFLO_ACC = 0x1,
12593 MTHI_ACC = 0x2,
12594 MTLO_ACC = 0x3,
12596 /* bits 13..12 for 0x2a */
12597 MADD_ACC = 0x0,
12598 MADDU_ACC = 0x1,
12599 MSUB_ACC = 0x2,
12600 MSUBU_ACC = 0x3,
12602 /* bits 13..12 for 0x32 */
12603 MULT_ACC = 0x0,
12604 MULTU_ACC = 0x1,
12606 /* end of microMIPS32 DSP */
12608 /* bits 15..12 for 0x2c */
12609 BITSWAP = 0x0,
12610 SEB = 0x2,
12611 SEH = 0x3,
12612 CLO = 0x4,
12613 CLZ = 0x5,
12614 RDHWR = 0x6,
12615 WSBH = 0x7,
12616 MULT = 0x8,
12617 MULTU = 0x9,
12618 DIV = 0xa,
12619 DIVU = 0xb,
12620 MADD = 0xc,
12621 MADDU = 0xd,
12622 MSUB = 0xe,
12623 MSUBU = 0xf,
12625 /* bits 15..12 for 0x34 */
12626 MFC2 = 0x4,
12627 MTC2 = 0x5,
12628 MFHC2 = 0x8,
12629 MTHC2 = 0x9,
12630 CFC2 = 0xc,
12631 CTC2 = 0xd,
12633 /* bits 15..12 for 0x3c */
12634 JALR = 0x0,
12635 JR = 0x0, /* alias */
12636 JALRC = 0x0,
12637 JRC = 0x0,
12638 JALR_HB = 0x1,
12639 JALRC_HB = 0x1,
12640 JALRS = 0x4,
12641 JALRS_HB = 0x5,
12643 /* bits 15..12 for 0x05 */
12644 RDPGPR = 0xe,
12645 WRPGPR = 0xf,
12647 /* bits 15..12 for 0x0d */
12648 TLBP = 0x0,
12649 TLBR = 0x1,
12650 TLBWI = 0x2,
12651 TLBWR = 0x3,
12652 TLBINV = 0x4,
12653 TLBINVF = 0x5,
12654 WAIT = 0x9,
12655 IRET = 0xd,
12656 DERET = 0xe,
12657 ERET = 0xf,
12659 /* bits 15..12 for 0x15 */
12660 DMT = 0x0,
12661 DVPE = 0x1,
12662 EMT = 0x2,
12663 EVPE = 0x3,
12665 /* bits 15..12 for 0x1d */
12666 DI = 0x4,
12667 EI = 0x5,
12669 /* bits 15..12 for 0x2d */
12670 SYNC = 0x6,
12671 SYSCALL = 0x8,
12672 SDBBP = 0xd,
12674 /* bits 15..12 for 0x35 */
12675 MFHI32 = 0x0,
12676 MFLO32 = 0x1,
12677 MTHI32 = 0x2,
12678 MTLO32 = 0x3,
12681 /* POOL32B encoding of minor opcode field (bits 15..12) */
12683 enum {
12684 LWC2 = 0x0,
12685 LWP = 0x1,
12686 LDP = 0x4,
12687 LWM32 = 0x5,
12688 CACHE = 0x6,
12689 LDM = 0x7,
12690 SWC2 = 0x8,
12691 SWP = 0x9,
12692 SDP = 0xc,
12693 SWM32 = 0xd,
12694 SDM = 0xf
12697 /* POOL32C encoding of minor opcode field (bits 15..12) */
12699 enum {
12700 LWL = 0x0,
12701 SWL = 0x8,
12702 LWR = 0x1,
12703 SWR = 0x9,
12704 PREF = 0x2,
12705 /* 0xa is reserved */
12706 LL = 0x3,
12707 SC = 0xb,
12708 LDL = 0x4,
12709 SDL = 0xc,
12710 LDR = 0x5,
12711 SDR = 0xd,
12712 /* 0x6 is reserved */
12713 LWU = 0xe,
12714 LLD = 0x7,
12715 SCD = 0xf
12718 /* POOL32F encoding of minor opcode field (bits 5..0) */
12720 enum {
12721 /* These are the bit 7..6 values */
12722 ADD_FMT = 0x0,
12724 SUB_FMT = 0x1,
12726 MUL_FMT = 0x2,
12728 DIV_FMT = 0x3,
12730 /* These are the bit 8..6 values */
12731 MOVN_FMT = 0x0,
12732 RSQRT2_FMT = 0x0,
12733 MOVF_FMT = 0x0,
12734 RINT_FMT = 0x0,
12735 SELNEZ_FMT = 0x0,
12737 MOVZ_FMT = 0x1,
12738 LWXC1 = 0x1,
12739 MOVT_FMT = 0x1,
12740 CLASS_FMT = 0x1,
12741 SELEQZ_FMT = 0x1,
12743 PLL_PS = 0x2,
12744 SWXC1 = 0x2,
12745 SEL_FMT = 0x2,
12747 PLU_PS = 0x3,
12748 LDXC1 = 0x3,
12750 MOVN_FMT_04 = 0x4,
12751 PUL_PS = 0x4,
12752 SDXC1 = 0x4,
12753 RECIP2_FMT = 0x4,
12755 MOVZ_FMT_05 = 0x05,
12756 PUU_PS = 0x5,
12757 LUXC1 = 0x5,
12759 CVT_PS_S = 0x6,
12760 SUXC1 = 0x6,
12761 ADDR_PS = 0x6,
12762 PREFX = 0x6,
12763 MADDF_FMT = 0x6,
12765 MULR_PS = 0x7,
12766 MSUBF_FMT = 0x7,
12768 MADD_S = 0x01,
12769 MADD_D = 0x09,
12770 MADD_PS = 0x11,
12771 ALNV_PS = 0x19,
12772 MSUB_S = 0x21,
12773 MSUB_D = 0x29,
12774 MSUB_PS = 0x31,
12776 NMADD_S = 0x02,
12777 NMADD_D = 0x0a,
12778 NMADD_PS = 0x12,
12779 NMSUB_S = 0x22,
12780 NMSUB_D = 0x2a,
12781 NMSUB_PS = 0x32,
12783 MIN_FMT = 0x3,
12784 MAX_FMT = 0xb,
12785 MINA_FMT = 0x23,
12786 MAXA_FMT = 0x2b,
12787 POOL32FXF = 0x3b,
12789 CABS_COND_FMT = 0x1c, /* MIPS3D */
12790 C_COND_FMT = 0x3c,
12792 CMP_CONDN_S = 0x5,
12793 CMP_CONDN_D = 0x15
12796 /* POOL32Fxf encoding of minor opcode extension field */
12798 enum {
12799 CVT_L = 0x04,
12800 RSQRT_FMT = 0x08,
12801 FLOOR_L = 0x0c,
12802 CVT_PW_PS = 0x1c,
12803 CVT_W = 0x24,
12804 SQRT_FMT = 0x28,
12805 FLOOR_W = 0x2c,
12806 CVT_PS_PW = 0x3c,
12807 CFC1 = 0x40,
12808 RECIP_FMT = 0x48,
12809 CEIL_L = 0x4c,
12810 CTC1 = 0x60,
12811 CEIL_W = 0x6c,
12812 MFC1 = 0x80,
12813 CVT_S_PL = 0x84,
12814 TRUNC_L = 0x8c,
12815 MTC1 = 0xa0,
12816 CVT_S_PU = 0xa4,
12817 TRUNC_W = 0xac,
12818 MFHC1 = 0xc0,
12819 ROUND_L = 0xcc,
12820 MTHC1 = 0xe0,
12821 ROUND_W = 0xec,
12823 MOV_FMT = 0x01,
12824 MOVF = 0x05,
12825 ABS_FMT = 0x0d,
12826 RSQRT1_FMT = 0x1d,
12827 MOVT = 0x25,
12828 NEG_FMT = 0x2d,
12829 CVT_D = 0x4d,
12830 RECIP1_FMT = 0x5d,
12831 CVT_S = 0x6d
12834 /* POOL32I encoding of minor opcode field (bits 25..21) */
12836 enum {
12837 BLTZ = 0x00,
12838 BLTZAL = 0x01,
12839 BGEZ = 0x02,
12840 BGEZAL = 0x03,
12841 BLEZ = 0x04,
12842 BNEZC = 0x05,
12843 BGTZ = 0x06,
12844 BEQZC = 0x07,
12845 TLTI = 0x08,
12846 BC1EQZC = 0x08,
12847 TGEI = 0x09,
12848 BC1NEZC = 0x09,
12849 TLTIU = 0x0a,
12850 BC2EQZC = 0x0a,
12851 TGEIU = 0x0b,
12852 BC2NEZC = 0x0a,
12853 TNEI = 0x0c,
12854 R6_SYNCI = 0x0c,
12855 LUI = 0x0d,
12856 TEQI = 0x0e,
12857 SYNCI = 0x10,
12858 BLTZALS = 0x11,
12859 BGEZALS = 0x13,
12860 BC2F = 0x14,
12861 BC2T = 0x15,
12862 BPOSGE64 = 0x1a,
12863 BPOSGE32 = 0x1b,
12864 /* These overlap and are distinguished by bit16 of the instruction */
12865 BC1F = 0x1c,
12866 BC1T = 0x1d,
12867 BC1ANY2F = 0x1c,
12868 BC1ANY2T = 0x1d,
12869 BC1ANY4F = 0x1e,
12870 BC1ANY4T = 0x1f
12873 /* POOL16A encoding of minor opcode field */
12875 enum {
12876 ADDU16 = 0x0,
12877 SUBU16 = 0x1
12880 /* POOL16B encoding of minor opcode field */
12882 enum {
12883 SLL16 = 0x0,
12884 SRL16 = 0x1
12887 /* POOL16C encoding of minor opcode field */
12889 enum {
12890 NOT16 = 0x00,
12891 XOR16 = 0x04,
12892 AND16 = 0x08,
12893 OR16 = 0x0c,
12894 LWM16 = 0x10,
12895 SWM16 = 0x14,
12896 JR16 = 0x18,
12897 JRC16 = 0x1a,
12898 JALR16 = 0x1c,
12899 JALR16S = 0x1e,
12900 MFHI16 = 0x20,
12901 MFLO16 = 0x24,
12902 BREAK16 = 0x28,
12903 SDBBP16 = 0x2c,
12904 JRADDIUSP = 0x30
12907 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
12909 enum {
12910 R6_NOT16 = 0x00,
12911 R6_AND16 = 0x01,
12912 R6_LWM16 = 0x02,
12913 R6_JRC16 = 0x03,
12914 MOVEP = 0x04,
12915 MOVEP_07 = 0x07,
12916 R6_XOR16 = 0x08,
12917 R6_OR16 = 0x09,
12918 R6_SWM16 = 0x0a,
12919 JALRC16 = 0x0b,
12920 MOVEP_0C = 0x0c,
12921 MOVEP_0F = 0x0f,
12922 JRCADDIUSP = 0x13,
12923 R6_BREAK16 = 0x1b,
12924 R6_SDBBP16 = 0x3b
12927 /* POOL16D encoding of minor opcode field */
12929 enum {
12930 ADDIUS5 = 0x0,
12931 ADDIUSP = 0x1
12934 /* POOL16E encoding of minor opcode field */
12936 enum {
12937 ADDIUR2 = 0x0,
12938 ADDIUR1SP = 0x1
12941 static int mmreg (int r)
12943 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12945 return map[r];
12948 /* Used for 16-bit store instructions. */
12949 static int mmreg2 (int r)
12951 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12953 return map[r];
12956 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12957 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12958 #define uMIPS_RS2(op) uMIPS_RS(op)
12959 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12960 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12961 #define uMIPS_RS5(op) (op & 0x1f)
12963 /* Signed immediate */
12964 #define SIMM(op, start, width) \
12965 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12966 << (32-width)) \
12967 >> (32-width))
12968 /* Zero-extended immediate */
12969 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12971 static void gen_addiur1sp(DisasContext *ctx)
12973 int rd = mmreg(uMIPS_RD(ctx->opcode));
12975 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12978 static void gen_addiur2(DisasContext *ctx)
12980 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12981 int rd = mmreg(uMIPS_RD(ctx->opcode));
12982 int rs = mmreg(uMIPS_RS(ctx->opcode));
12984 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12987 static void gen_addiusp(DisasContext *ctx)
12989 int encoded = ZIMM(ctx->opcode, 1, 9);
12990 int decoded;
12992 if (encoded <= 1) {
12993 decoded = 256 + encoded;
12994 } else if (encoded <= 255) {
12995 decoded = encoded;
12996 } else if (encoded <= 509) {
12997 decoded = encoded - 512;
12998 } else {
12999 decoded = encoded - 768;
13002 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
13005 static void gen_addius5(DisasContext *ctx)
13007 int imm = SIMM(ctx->opcode, 1, 4);
13008 int rd = (ctx->opcode >> 5) & 0x1f;
13010 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
13013 static void gen_andi16(DisasContext *ctx)
13015 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
13016 31, 32, 63, 64, 255, 32768, 65535 };
13017 int rd = mmreg(uMIPS_RD(ctx->opcode));
13018 int rs = mmreg(uMIPS_RS(ctx->opcode));
13019 int encoded = ZIMM(ctx->opcode, 0, 4);
13021 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
13024 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
13025 int base, int16_t offset)
13027 const char *opn = "ldst_multiple";
13028 TCGv t0, t1;
13029 TCGv_i32 t2;
13031 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13032 generate_exception(ctx, EXCP_RI);
13033 return;
13036 t0 = tcg_temp_new();
13038 gen_base_offset_addr(ctx, t0, base, offset);
13040 t1 = tcg_const_tl(reglist);
13041 t2 = tcg_const_i32(ctx->mem_idx);
13043 save_cpu_state(ctx, 1);
13044 switch (opc) {
13045 case LWM32:
13046 gen_helper_lwm(cpu_env, t0, t1, t2);
13047 opn = "lwm";
13048 break;
13049 case SWM32:
13050 gen_helper_swm(cpu_env, t0, t1, t2);
13051 opn = "swm";
13052 break;
13053 #ifdef TARGET_MIPS64
13054 case LDM:
13055 gen_helper_ldm(cpu_env, t0, t1, t2);
13056 opn = "ldm";
13057 break;
13058 case SDM:
13059 gen_helper_sdm(cpu_env, t0, t1, t2);
13060 opn = "sdm";
13061 break;
13062 #endif
13064 (void)opn;
13065 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
13066 tcg_temp_free(t0);
13067 tcg_temp_free(t1);
13068 tcg_temp_free_i32(t2);
13072 static void gen_pool16c_insn(DisasContext *ctx)
13074 int rd = mmreg((ctx->opcode >> 3) & 0x7);
13075 int rs = mmreg(ctx->opcode & 0x7);
13077 switch (((ctx->opcode) >> 4) & 0x3f) {
13078 case NOT16 + 0:
13079 case NOT16 + 1:
13080 case NOT16 + 2:
13081 case NOT16 + 3:
13082 gen_logic(ctx, OPC_NOR, rd, rs, 0);
13083 break;
13084 case XOR16 + 0:
13085 case XOR16 + 1:
13086 case XOR16 + 2:
13087 case XOR16 + 3:
13088 gen_logic(ctx, OPC_XOR, rd, rd, rs);
13089 break;
13090 case AND16 + 0:
13091 case AND16 + 1:
13092 case AND16 + 2:
13093 case AND16 + 3:
13094 gen_logic(ctx, OPC_AND, rd, rd, rs);
13095 break;
13096 case OR16 + 0:
13097 case OR16 + 1:
13098 case OR16 + 2:
13099 case OR16 + 3:
13100 gen_logic(ctx, OPC_OR, rd, rd, rs);
13101 break;
13102 case LWM16 + 0:
13103 case LWM16 + 1:
13104 case LWM16 + 2:
13105 case LWM16 + 3:
13107 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13108 int offset = ZIMM(ctx->opcode, 0, 4);
13110 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
13111 29, offset << 2);
13113 break;
13114 case SWM16 + 0:
13115 case SWM16 + 1:
13116 case SWM16 + 2:
13117 case SWM16 + 3:
13119 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13120 int offset = ZIMM(ctx->opcode, 0, 4);
13122 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
13123 29, offset << 2);
13125 break;
13126 case JR16 + 0:
13127 case JR16 + 1:
13129 int reg = ctx->opcode & 0x1f;
13131 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
13133 break;
13134 case JRC16 + 0:
13135 case JRC16 + 1:
13137 int reg = ctx->opcode & 0x1f;
13138 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
13139 /* Let normal delay slot handling in our caller take us
13140 to the branch target. */
13142 break;
13143 case JALR16 + 0:
13144 case JALR16 + 1:
13145 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
13146 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13147 break;
13148 case JALR16S + 0:
13149 case JALR16S + 1:
13150 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
13151 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13152 break;
13153 case MFHI16 + 0:
13154 case MFHI16 + 1:
13155 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
13156 break;
13157 case MFLO16 + 0:
13158 case MFLO16 + 1:
13159 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
13160 break;
13161 case BREAK16:
13162 generate_exception(ctx, EXCP_BREAK);
13163 break;
13164 case SDBBP16:
13165 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
13166 gen_helper_do_semihosting(cpu_env);
13167 } else {
13168 /* XXX: not clear which exception should be raised
13169 * when in debug mode...
13171 check_insn(ctx, ISA_MIPS32);
13172 generate_exception(ctx, EXCP_DBp);
13174 break;
13175 case JRADDIUSP + 0:
13176 case JRADDIUSP + 1:
13178 int imm = ZIMM(ctx->opcode, 0, 5);
13179 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13180 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13181 /* Let normal delay slot handling in our caller take us
13182 to the branch target. */
13184 break;
13185 default:
13186 generate_exception(ctx, EXCP_RI);
13187 break;
13191 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
13192 int enc_rs)
13194 int rd, rs, re, rt;
13195 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
13196 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
13197 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
13198 rd = rd_enc[enc_dest];
13199 re = re_enc[enc_dest];
13200 rs = rs_rt_enc[enc_rs];
13201 rt = rs_rt_enc[enc_rt];
13202 if (rs) {
13203 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
13204 } else {
13205 tcg_gen_movi_tl(cpu_gpr[rd], 0);
13207 if (rt) {
13208 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
13209 } else {
13210 tcg_gen_movi_tl(cpu_gpr[re], 0);
13214 static void gen_pool16c_r6_insn(DisasContext *ctx)
13216 int rt = mmreg((ctx->opcode >> 7) & 0x7);
13217 int rs = mmreg((ctx->opcode >> 4) & 0x7);
13219 switch (ctx->opcode & 0xf) {
13220 case R6_NOT16:
13221 gen_logic(ctx, OPC_NOR, rt, rs, 0);
13222 break;
13223 case R6_AND16:
13224 gen_logic(ctx, OPC_AND, rt, rt, rs);
13225 break;
13226 case R6_LWM16:
13228 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13229 int offset = extract32(ctx->opcode, 4, 4);
13230 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
13232 break;
13233 case R6_JRC16: /* JRCADDIUSP */
13234 if ((ctx->opcode >> 4) & 1) {
13235 /* JRCADDIUSP */
13236 int imm = extract32(ctx->opcode, 5, 5);
13237 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13238 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13239 } else {
13240 /* JRC16 */
13241 int rs = extract32(ctx->opcode, 5, 5);
13242 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
13244 break;
13245 case MOVEP ... MOVEP_07:
13246 case MOVEP_0C ... MOVEP_0F:
13248 int enc_dest = uMIPS_RD(ctx->opcode);
13249 int enc_rt = uMIPS_RS2(ctx->opcode);
13250 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
13251 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
13253 break;
13254 case R6_XOR16:
13255 gen_logic(ctx, OPC_XOR, rt, rt, rs);
13256 break;
13257 case R6_OR16:
13258 gen_logic(ctx, OPC_OR, rt, rt, rs);
13259 break;
13260 case R6_SWM16:
13262 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13263 int offset = extract32(ctx->opcode, 4, 4);
13264 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
13266 break;
13267 case JALRC16: /* BREAK16, SDBBP16 */
13268 switch (ctx->opcode & 0x3f) {
13269 case JALRC16:
13270 case JALRC16 + 0x20:
13271 /* JALRC16 */
13272 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
13273 31, 0, 0);
13274 break;
13275 case R6_BREAK16:
13276 /* BREAK16 */
13277 generate_exception(ctx, EXCP_BREAK);
13278 break;
13279 case R6_SDBBP16:
13280 /* SDBBP16 */
13281 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13282 generate_exception(ctx, EXCP_RI);
13283 } else {
13284 generate_exception(ctx, EXCP_DBp);
13286 break;
13288 break;
13289 default:
13290 generate_exception(ctx, EXCP_RI);
13291 break;
13295 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
13297 TCGv t0 = tcg_temp_new();
13298 TCGv t1 = tcg_temp_new();
13300 gen_load_gpr(t0, base);
13302 if (index != 0) {
13303 gen_load_gpr(t1, index);
13304 tcg_gen_shli_tl(t1, t1, 2);
13305 gen_op_addr_add(ctx, t0, t1, t0);
13308 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13309 gen_store_gpr(t1, rd);
13311 tcg_temp_free(t0);
13312 tcg_temp_free(t1);
13315 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
13316 int base, int16_t offset)
13318 const char *opn = "ldst_pair";
13319 TCGv t0, t1;
13321 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
13322 generate_exception(ctx, EXCP_RI);
13323 return;
13326 t0 = tcg_temp_new();
13327 t1 = tcg_temp_new();
13329 gen_base_offset_addr(ctx, t0, base, offset);
13331 switch (opc) {
13332 case LWP:
13333 if (rd == base) {
13334 generate_exception(ctx, EXCP_RI);
13335 return;
13337 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13338 gen_store_gpr(t1, rd);
13339 tcg_gen_movi_tl(t1, 4);
13340 gen_op_addr_add(ctx, t0, t0, t1);
13341 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13342 gen_store_gpr(t1, rd+1);
13343 opn = "lwp";
13344 break;
13345 case SWP:
13346 gen_load_gpr(t1, rd);
13347 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13348 tcg_gen_movi_tl(t1, 4);
13349 gen_op_addr_add(ctx, t0, t0, t1);
13350 gen_load_gpr(t1, rd+1);
13351 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13352 opn = "swp";
13353 break;
13354 #ifdef TARGET_MIPS64
13355 case LDP:
13356 if (rd == base) {
13357 generate_exception(ctx, EXCP_RI);
13358 return;
13360 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13361 gen_store_gpr(t1, rd);
13362 tcg_gen_movi_tl(t1, 8);
13363 gen_op_addr_add(ctx, t0, t0, t1);
13364 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13365 gen_store_gpr(t1, rd+1);
13366 opn = "ldp";
13367 break;
13368 case SDP:
13369 gen_load_gpr(t1, rd);
13370 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13371 tcg_gen_movi_tl(t1, 8);
13372 gen_op_addr_add(ctx, t0, t0, t1);
13373 gen_load_gpr(t1, rd+1);
13374 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13375 opn = "sdp";
13376 break;
13377 #endif
13379 (void)opn; /* avoid a compiler warning */
13380 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
13381 tcg_temp_free(t0);
13382 tcg_temp_free(t1);
13385 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
13387 int extension = (ctx->opcode >> 6) & 0x3f;
13388 int minor = (ctx->opcode >> 12) & 0xf;
13389 uint32_t mips32_op;
13391 switch (extension) {
13392 case TEQ:
13393 mips32_op = OPC_TEQ;
13394 goto do_trap;
13395 case TGE:
13396 mips32_op = OPC_TGE;
13397 goto do_trap;
13398 case TGEU:
13399 mips32_op = OPC_TGEU;
13400 goto do_trap;
13401 case TLT:
13402 mips32_op = OPC_TLT;
13403 goto do_trap;
13404 case TLTU:
13405 mips32_op = OPC_TLTU;
13406 goto do_trap;
13407 case TNE:
13408 mips32_op = OPC_TNE;
13409 do_trap:
13410 gen_trap(ctx, mips32_op, rs, rt, -1);
13411 break;
13412 #ifndef CONFIG_USER_ONLY
13413 case MFC0:
13414 case MFC0 + 32:
13415 check_cp0_enabled(ctx);
13416 if (rt == 0) {
13417 /* Treat as NOP. */
13418 break;
13420 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
13421 break;
13422 case MTC0:
13423 case MTC0 + 32:
13424 check_cp0_enabled(ctx);
13426 TCGv t0 = tcg_temp_new();
13428 gen_load_gpr(t0, rt);
13429 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
13430 tcg_temp_free(t0);
13432 break;
13433 #endif
13434 case 0x2a:
13435 switch (minor & 3) {
13436 case MADD_ACC:
13437 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
13438 break;
13439 case MADDU_ACC:
13440 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
13441 break;
13442 case MSUB_ACC:
13443 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
13444 break;
13445 case MSUBU_ACC:
13446 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
13447 break;
13448 default:
13449 goto pool32axf_invalid;
13451 break;
13452 case 0x32:
13453 switch (minor & 3) {
13454 case MULT_ACC:
13455 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
13456 break;
13457 case MULTU_ACC:
13458 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
13459 break;
13460 default:
13461 goto pool32axf_invalid;
13463 break;
13464 case 0x2c:
13465 switch (minor) {
13466 case BITSWAP:
13467 check_insn(ctx, ISA_MIPS32R6);
13468 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
13469 break;
13470 case SEB:
13471 gen_bshfl(ctx, OPC_SEB, rs, rt);
13472 break;
13473 case SEH:
13474 gen_bshfl(ctx, OPC_SEH, rs, rt);
13475 break;
13476 case CLO:
13477 mips32_op = OPC_CLO;
13478 goto do_cl;
13479 case CLZ:
13480 mips32_op = OPC_CLZ;
13481 do_cl:
13482 check_insn(ctx, ISA_MIPS32);
13483 gen_cl(ctx, mips32_op, rt, rs);
13484 break;
13485 case RDHWR:
13486 gen_rdhwr(ctx, rt, rs);
13487 break;
13488 case WSBH:
13489 gen_bshfl(ctx, OPC_WSBH, rs, rt);
13490 break;
13491 case MULT:
13492 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13493 mips32_op = OPC_MULT;
13494 goto do_mul;
13495 case MULTU:
13496 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13497 mips32_op = OPC_MULTU;
13498 goto do_mul;
13499 case DIV:
13500 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13501 mips32_op = OPC_DIV;
13502 goto do_div;
13503 case DIVU:
13504 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13505 mips32_op = OPC_DIVU;
13506 goto do_div;
13507 do_div:
13508 check_insn(ctx, ISA_MIPS32);
13509 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13510 break;
13511 case MADD:
13512 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13513 mips32_op = OPC_MADD;
13514 goto do_mul;
13515 case MADDU:
13516 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13517 mips32_op = OPC_MADDU;
13518 goto do_mul;
13519 case MSUB:
13520 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13521 mips32_op = OPC_MSUB;
13522 goto do_mul;
13523 case MSUBU:
13524 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13525 mips32_op = OPC_MSUBU;
13526 do_mul:
13527 check_insn(ctx, ISA_MIPS32);
13528 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13529 break;
13530 default:
13531 goto pool32axf_invalid;
13533 break;
13534 case 0x34:
13535 switch (minor) {
13536 case MFC2:
13537 case MTC2:
13538 case MFHC2:
13539 case MTHC2:
13540 case CFC2:
13541 case CTC2:
13542 generate_exception_err(ctx, EXCP_CpU, 2);
13543 break;
13544 default:
13545 goto pool32axf_invalid;
13547 break;
13548 case 0x3c:
13549 switch (minor) {
13550 case JALR: /* JALRC */
13551 case JALR_HB: /* JALRC_HB */
13552 if (ctx->insn_flags & ISA_MIPS32R6) {
13553 /* JALRC, JALRC_HB */
13554 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13555 } else {
13556 /* JALR, JALR_HB */
13557 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13558 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13560 break;
13561 case JALRS:
13562 case JALRS_HB:
13563 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13564 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13565 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13566 break;
13567 default:
13568 goto pool32axf_invalid;
13570 break;
13571 case 0x05:
13572 switch (minor) {
13573 case RDPGPR:
13574 check_cp0_enabled(ctx);
13575 check_insn(ctx, ISA_MIPS32R2);
13576 gen_load_srsgpr(rs, rt);
13577 break;
13578 case WRPGPR:
13579 check_cp0_enabled(ctx);
13580 check_insn(ctx, ISA_MIPS32R2);
13581 gen_store_srsgpr(rs, rt);
13582 break;
13583 default:
13584 goto pool32axf_invalid;
13586 break;
13587 #ifndef CONFIG_USER_ONLY
13588 case 0x0d:
13589 switch (minor) {
13590 case TLBP:
13591 mips32_op = OPC_TLBP;
13592 goto do_cp0;
13593 case TLBR:
13594 mips32_op = OPC_TLBR;
13595 goto do_cp0;
13596 case TLBWI:
13597 mips32_op = OPC_TLBWI;
13598 goto do_cp0;
13599 case TLBWR:
13600 mips32_op = OPC_TLBWR;
13601 goto do_cp0;
13602 case TLBINV:
13603 mips32_op = OPC_TLBINV;
13604 goto do_cp0;
13605 case TLBINVF:
13606 mips32_op = OPC_TLBINVF;
13607 goto do_cp0;
13608 case WAIT:
13609 mips32_op = OPC_WAIT;
13610 goto do_cp0;
13611 case DERET:
13612 mips32_op = OPC_DERET;
13613 goto do_cp0;
13614 case ERET:
13615 mips32_op = OPC_ERET;
13616 do_cp0:
13617 gen_cp0(env, ctx, mips32_op, rt, rs);
13618 break;
13619 default:
13620 goto pool32axf_invalid;
13622 break;
13623 case 0x1d:
13624 switch (minor) {
13625 case DI:
13626 check_cp0_enabled(ctx);
13628 TCGv t0 = tcg_temp_new();
13630 save_cpu_state(ctx, 1);
13631 gen_helper_di(t0, cpu_env);
13632 gen_store_gpr(t0, rs);
13633 /* Stop translation as we may have switched the execution mode */
13634 ctx->bstate = BS_STOP;
13635 tcg_temp_free(t0);
13637 break;
13638 case EI:
13639 check_cp0_enabled(ctx);
13641 TCGv t0 = tcg_temp_new();
13643 save_cpu_state(ctx, 1);
13644 gen_helper_ei(t0, cpu_env);
13645 gen_store_gpr(t0, rs);
13646 /* Stop translation as we may have switched the execution mode */
13647 ctx->bstate = BS_STOP;
13648 tcg_temp_free(t0);
13650 break;
13651 default:
13652 goto pool32axf_invalid;
13654 break;
13655 #endif
13656 case 0x2d:
13657 switch (minor) {
13658 case SYNC:
13659 /* NOP */
13660 break;
13661 case SYSCALL:
13662 generate_exception(ctx, EXCP_SYSCALL);
13663 ctx->bstate = BS_STOP;
13664 break;
13665 case SDBBP:
13666 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
13667 gen_helper_do_semihosting(cpu_env);
13668 } else {
13669 check_insn(ctx, ISA_MIPS32);
13670 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13671 generate_exception(ctx, EXCP_RI);
13672 } else {
13673 generate_exception(ctx, EXCP_DBp);
13676 break;
13677 default:
13678 goto pool32axf_invalid;
13680 break;
13681 case 0x01:
13682 switch (minor & 3) {
13683 case MFHI_ACC:
13684 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
13685 break;
13686 case MFLO_ACC:
13687 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
13688 break;
13689 case MTHI_ACC:
13690 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
13691 break;
13692 case MTLO_ACC:
13693 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
13694 break;
13695 default:
13696 goto pool32axf_invalid;
13698 break;
13699 case 0x35:
13700 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13701 switch (minor) {
13702 case MFHI32:
13703 gen_HILO(ctx, OPC_MFHI, 0, rs);
13704 break;
13705 case MFLO32:
13706 gen_HILO(ctx, OPC_MFLO, 0, rs);
13707 break;
13708 case MTHI32:
13709 gen_HILO(ctx, OPC_MTHI, 0, rs);
13710 break;
13711 case MTLO32:
13712 gen_HILO(ctx, OPC_MTLO, 0, rs);
13713 break;
13714 default:
13715 goto pool32axf_invalid;
13717 break;
13718 default:
13719 pool32axf_invalid:
13720 MIPS_INVAL("pool32axf");
13721 generate_exception(ctx, EXCP_RI);
13722 break;
13726 /* Values for microMIPS fmt field. Variable-width, depending on which
13727 formats the instruction supports. */
13729 enum {
13730 FMT_SD_S = 0,
13731 FMT_SD_D = 1,
13733 FMT_SDPS_S = 0,
13734 FMT_SDPS_D = 1,
13735 FMT_SDPS_PS = 2,
13737 FMT_SWL_S = 0,
13738 FMT_SWL_W = 1,
13739 FMT_SWL_L = 2,
13741 FMT_DWL_D = 0,
13742 FMT_DWL_W = 1,
13743 FMT_DWL_L = 2
13746 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
13748 int extension = (ctx->opcode >> 6) & 0x3ff;
13749 uint32_t mips32_op;
13751 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
13752 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
13753 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
13755 switch (extension) {
13756 case FLOAT_1BIT_FMT(CFC1, 0):
13757 mips32_op = OPC_CFC1;
13758 goto do_cp1;
13759 case FLOAT_1BIT_FMT(CTC1, 0):
13760 mips32_op = OPC_CTC1;
13761 goto do_cp1;
13762 case FLOAT_1BIT_FMT(MFC1, 0):
13763 mips32_op = OPC_MFC1;
13764 goto do_cp1;
13765 case FLOAT_1BIT_FMT(MTC1, 0):
13766 mips32_op = OPC_MTC1;
13767 goto do_cp1;
13768 case FLOAT_1BIT_FMT(MFHC1, 0):
13769 mips32_op = OPC_MFHC1;
13770 goto do_cp1;
13771 case FLOAT_1BIT_FMT(MTHC1, 0):
13772 mips32_op = OPC_MTHC1;
13773 do_cp1:
13774 gen_cp1(ctx, mips32_op, rt, rs);
13775 break;
13777 /* Reciprocal square root */
13778 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
13779 mips32_op = OPC_RSQRT_S;
13780 goto do_unaryfp;
13781 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
13782 mips32_op = OPC_RSQRT_D;
13783 goto do_unaryfp;
13785 /* Square root */
13786 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
13787 mips32_op = OPC_SQRT_S;
13788 goto do_unaryfp;
13789 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
13790 mips32_op = OPC_SQRT_D;
13791 goto do_unaryfp;
13793 /* Reciprocal */
13794 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
13795 mips32_op = OPC_RECIP_S;
13796 goto do_unaryfp;
13797 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
13798 mips32_op = OPC_RECIP_D;
13799 goto do_unaryfp;
13801 /* Floor */
13802 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
13803 mips32_op = OPC_FLOOR_L_S;
13804 goto do_unaryfp;
13805 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
13806 mips32_op = OPC_FLOOR_L_D;
13807 goto do_unaryfp;
13808 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
13809 mips32_op = OPC_FLOOR_W_S;
13810 goto do_unaryfp;
13811 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
13812 mips32_op = OPC_FLOOR_W_D;
13813 goto do_unaryfp;
13815 /* Ceiling */
13816 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
13817 mips32_op = OPC_CEIL_L_S;
13818 goto do_unaryfp;
13819 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
13820 mips32_op = OPC_CEIL_L_D;
13821 goto do_unaryfp;
13822 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
13823 mips32_op = OPC_CEIL_W_S;
13824 goto do_unaryfp;
13825 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
13826 mips32_op = OPC_CEIL_W_D;
13827 goto do_unaryfp;
13829 /* Truncation */
13830 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
13831 mips32_op = OPC_TRUNC_L_S;
13832 goto do_unaryfp;
13833 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
13834 mips32_op = OPC_TRUNC_L_D;
13835 goto do_unaryfp;
13836 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
13837 mips32_op = OPC_TRUNC_W_S;
13838 goto do_unaryfp;
13839 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
13840 mips32_op = OPC_TRUNC_W_D;
13841 goto do_unaryfp;
13843 /* Round */
13844 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
13845 mips32_op = OPC_ROUND_L_S;
13846 goto do_unaryfp;
13847 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
13848 mips32_op = OPC_ROUND_L_D;
13849 goto do_unaryfp;
13850 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
13851 mips32_op = OPC_ROUND_W_S;
13852 goto do_unaryfp;
13853 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
13854 mips32_op = OPC_ROUND_W_D;
13855 goto do_unaryfp;
13857 /* Integer to floating-point conversion */
13858 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
13859 mips32_op = OPC_CVT_L_S;
13860 goto do_unaryfp;
13861 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
13862 mips32_op = OPC_CVT_L_D;
13863 goto do_unaryfp;
13864 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
13865 mips32_op = OPC_CVT_W_S;
13866 goto do_unaryfp;
13867 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
13868 mips32_op = OPC_CVT_W_D;
13869 goto do_unaryfp;
13871 /* Paired-foo conversions */
13872 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
13873 mips32_op = OPC_CVT_S_PL;
13874 goto do_unaryfp;
13875 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
13876 mips32_op = OPC_CVT_S_PU;
13877 goto do_unaryfp;
13878 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
13879 mips32_op = OPC_CVT_PW_PS;
13880 goto do_unaryfp;
13881 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
13882 mips32_op = OPC_CVT_PS_PW;
13883 goto do_unaryfp;
13885 /* Floating-point moves */
13886 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
13887 mips32_op = OPC_MOV_S;
13888 goto do_unaryfp;
13889 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
13890 mips32_op = OPC_MOV_D;
13891 goto do_unaryfp;
13892 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
13893 mips32_op = OPC_MOV_PS;
13894 goto do_unaryfp;
13896 /* Absolute value */
13897 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
13898 mips32_op = OPC_ABS_S;
13899 goto do_unaryfp;
13900 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
13901 mips32_op = OPC_ABS_D;
13902 goto do_unaryfp;
13903 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
13904 mips32_op = OPC_ABS_PS;
13905 goto do_unaryfp;
13907 /* Negation */
13908 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
13909 mips32_op = OPC_NEG_S;
13910 goto do_unaryfp;
13911 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
13912 mips32_op = OPC_NEG_D;
13913 goto do_unaryfp;
13914 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
13915 mips32_op = OPC_NEG_PS;
13916 goto do_unaryfp;
13918 /* Reciprocal square root step */
13919 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
13920 mips32_op = OPC_RSQRT1_S;
13921 goto do_unaryfp;
13922 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
13923 mips32_op = OPC_RSQRT1_D;
13924 goto do_unaryfp;
13925 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
13926 mips32_op = OPC_RSQRT1_PS;
13927 goto do_unaryfp;
13929 /* Reciprocal step */
13930 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
13931 mips32_op = OPC_RECIP1_S;
13932 goto do_unaryfp;
13933 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
13934 mips32_op = OPC_RECIP1_S;
13935 goto do_unaryfp;
13936 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13937 mips32_op = OPC_RECIP1_PS;
13938 goto do_unaryfp;
13940 /* Conversions from double */
13941 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13942 mips32_op = OPC_CVT_D_S;
13943 goto do_unaryfp;
13944 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13945 mips32_op = OPC_CVT_D_W;
13946 goto do_unaryfp;
13947 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13948 mips32_op = OPC_CVT_D_L;
13949 goto do_unaryfp;
13951 /* Conversions from single */
13952 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13953 mips32_op = OPC_CVT_S_D;
13954 goto do_unaryfp;
13955 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13956 mips32_op = OPC_CVT_S_W;
13957 goto do_unaryfp;
13958 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13959 mips32_op = OPC_CVT_S_L;
13960 do_unaryfp:
13961 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13962 break;
13964 /* Conditional moves on floating-point codes */
13965 case COND_FLOAT_MOV(MOVT, 0):
13966 case COND_FLOAT_MOV(MOVT, 1):
13967 case COND_FLOAT_MOV(MOVT, 2):
13968 case COND_FLOAT_MOV(MOVT, 3):
13969 case COND_FLOAT_MOV(MOVT, 4):
13970 case COND_FLOAT_MOV(MOVT, 5):
13971 case COND_FLOAT_MOV(MOVT, 6):
13972 case COND_FLOAT_MOV(MOVT, 7):
13973 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13974 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13975 break;
13976 case COND_FLOAT_MOV(MOVF, 0):
13977 case COND_FLOAT_MOV(MOVF, 1):
13978 case COND_FLOAT_MOV(MOVF, 2):
13979 case COND_FLOAT_MOV(MOVF, 3):
13980 case COND_FLOAT_MOV(MOVF, 4):
13981 case COND_FLOAT_MOV(MOVF, 5):
13982 case COND_FLOAT_MOV(MOVF, 6):
13983 case COND_FLOAT_MOV(MOVF, 7):
13984 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13985 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13986 break;
13987 default:
13988 MIPS_INVAL("pool32fxf");
13989 generate_exception(ctx, EXCP_RI);
13990 break;
13994 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
13996 int32_t offset;
13997 uint16_t insn;
13998 int rt, rs, rd, rr;
13999 int16_t imm;
14000 uint32_t op, minor, mips32_op;
14001 uint32_t cond, fmt, cc;
14003 insn = cpu_lduw_code(env, ctx->pc + 2);
14004 ctx->opcode = (ctx->opcode << 16) | insn;
14006 rt = (ctx->opcode >> 21) & 0x1f;
14007 rs = (ctx->opcode >> 16) & 0x1f;
14008 rd = (ctx->opcode >> 11) & 0x1f;
14009 rr = (ctx->opcode >> 6) & 0x1f;
14010 imm = (int16_t) ctx->opcode;
14012 op = (ctx->opcode >> 26) & 0x3f;
14013 switch (op) {
14014 case POOL32A:
14015 minor = ctx->opcode & 0x3f;
14016 switch (minor) {
14017 case 0x00:
14018 minor = (ctx->opcode >> 6) & 0xf;
14019 switch (minor) {
14020 case SLL32:
14021 mips32_op = OPC_SLL;
14022 goto do_shifti;
14023 case SRA:
14024 mips32_op = OPC_SRA;
14025 goto do_shifti;
14026 case SRL32:
14027 mips32_op = OPC_SRL;
14028 goto do_shifti;
14029 case ROTR:
14030 mips32_op = OPC_ROTR;
14031 do_shifti:
14032 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
14033 break;
14034 case SELEQZ:
14035 check_insn(ctx, ISA_MIPS32R6);
14036 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
14037 break;
14038 case SELNEZ:
14039 check_insn(ctx, ISA_MIPS32R6);
14040 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
14041 break;
14042 default:
14043 goto pool32a_invalid;
14045 break;
14046 case 0x10:
14047 minor = (ctx->opcode >> 6) & 0xf;
14048 switch (minor) {
14049 /* Arithmetic */
14050 case ADD:
14051 mips32_op = OPC_ADD;
14052 goto do_arith;
14053 case ADDU32:
14054 mips32_op = OPC_ADDU;
14055 goto do_arith;
14056 case SUB:
14057 mips32_op = OPC_SUB;
14058 goto do_arith;
14059 case SUBU32:
14060 mips32_op = OPC_SUBU;
14061 goto do_arith;
14062 case MUL:
14063 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14064 mips32_op = OPC_MUL;
14065 do_arith:
14066 gen_arith(ctx, mips32_op, rd, rs, rt);
14067 break;
14068 /* Shifts */
14069 case SLLV:
14070 mips32_op = OPC_SLLV;
14071 goto do_shift;
14072 case SRLV:
14073 mips32_op = OPC_SRLV;
14074 goto do_shift;
14075 case SRAV:
14076 mips32_op = OPC_SRAV;
14077 goto do_shift;
14078 case ROTRV:
14079 mips32_op = OPC_ROTRV;
14080 do_shift:
14081 gen_shift(ctx, mips32_op, rd, rs, rt);
14082 break;
14083 /* Logical operations */
14084 case AND:
14085 mips32_op = OPC_AND;
14086 goto do_logic;
14087 case OR32:
14088 mips32_op = OPC_OR;
14089 goto do_logic;
14090 case NOR:
14091 mips32_op = OPC_NOR;
14092 goto do_logic;
14093 case XOR32:
14094 mips32_op = OPC_XOR;
14095 do_logic:
14096 gen_logic(ctx, mips32_op, rd, rs, rt);
14097 break;
14098 /* Set less than */
14099 case SLT:
14100 mips32_op = OPC_SLT;
14101 goto do_slt;
14102 case SLTU:
14103 mips32_op = OPC_SLTU;
14104 do_slt:
14105 gen_slt(ctx, mips32_op, rd, rs, rt);
14106 break;
14107 default:
14108 goto pool32a_invalid;
14110 break;
14111 case 0x18:
14112 minor = (ctx->opcode >> 6) & 0xf;
14113 switch (minor) {
14114 /* Conditional moves */
14115 case MOVN: /* MUL */
14116 if (ctx->insn_flags & ISA_MIPS32R6) {
14117 /* MUL */
14118 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
14119 } else {
14120 /* MOVN */
14121 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
14123 break;
14124 case MOVZ: /* MUH */
14125 if (ctx->insn_flags & ISA_MIPS32R6) {
14126 /* MUH */
14127 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
14128 } else {
14129 /* MOVZ */
14130 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
14132 break;
14133 case MULU:
14134 check_insn(ctx, ISA_MIPS32R6);
14135 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
14136 break;
14137 case MUHU:
14138 check_insn(ctx, ISA_MIPS32R6);
14139 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
14140 break;
14141 case LWXS: /* DIV */
14142 if (ctx->insn_flags & ISA_MIPS32R6) {
14143 /* DIV */
14144 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
14145 } else {
14146 /* LWXS */
14147 gen_ldxs(ctx, rs, rt, rd);
14149 break;
14150 case MOD:
14151 check_insn(ctx, ISA_MIPS32R6);
14152 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
14153 break;
14154 case R6_DIVU:
14155 check_insn(ctx, ISA_MIPS32R6);
14156 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
14157 break;
14158 case MODU:
14159 check_insn(ctx, ISA_MIPS32R6);
14160 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
14161 break;
14162 default:
14163 goto pool32a_invalid;
14165 break;
14166 case INS:
14167 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
14168 return;
14169 case LSA:
14170 check_insn(ctx, ISA_MIPS32R6);
14171 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
14172 extract32(ctx->opcode, 9, 2));
14173 break;
14174 case ALIGN:
14175 check_insn(ctx, ISA_MIPS32R6);
14176 gen_align(ctx, OPC_ALIGN, rd, rs, rt,
14177 extract32(ctx->opcode, 9, 2));
14178 break;
14179 case EXT:
14180 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
14181 return;
14182 case POOL32AXF:
14183 gen_pool32axf(env, ctx, rt, rs);
14184 break;
14185 case 0x07:
14186 generate_exception(ctx, EXCP_BREAK);
14187 break;
14188 default:
14189 pool32a_invalid:
14190 MIPS_INVAL("pool32a");
14191 generate_exception(ctx, EXCP_RI);
14192 break;
14194 break;
14195 case POOL32B:
14196 minor = (ctx->opcode >> 12) & 0xf;
14197 switch (minor) {
14198 case CACHE:
14199 check_cp0_enabled(ctx);
14200 /* Treat as no-op. */
14201 break;
14202 case LWC2:
14203 case SWC2:
14204 /* COP2: Not implemented. */
14205 generate_exception_err(ctx, EXCP_CpU, 2);
14206 break;
14207 #ifdef TARGET_MIPS64
14208 case LDP:
14209 case SDP:
14210 check_insn(ctx, ISA_MIPS3);
14211 check_mips_64(ctx);
14212 /* Fallthrough */
14213 #endif
14214 case LWP:
14215 case SWP:
14216 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14217 break;
14218 #ifdef TARGET_MIPS64
14219 case LDM:
14220 case SDM:
14221 check_insn(ctx, ISA_MIPS3);
14222 check_mips_64(ctx);
14223 /* Fallthrough */
14224 #endif
14225 case LWM32:
14226 case SWM32:
14227 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14228 break;
14229 default:
14230 MIPS_INVAL("pool32b");
14231 generate_exception(ctx, EXCP_RI);
14232 break;
14234 break;
14235 case POOL32F:
14236 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
14237 minor = ctx->opcode & 0x3f;
14238 check_cp1_enabled(ctx);
14239 switch (minor) {
14240 case ALNV_PS:
14241 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14242 mips32_op = OPC_ALNV_PS;
14243 goto do_madd;
14244 case MADD_S:
14245 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14246 mips32_op = OPC_MADD_S;
14247 goto do_madd;
14248 case MADD_D:
14249 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14250 mips32_op = OPC_MADD_D;
14251 goto do_madd;
14252 case MADD_PS:
14253 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14254 mips32_op = OPC_MADD_PS;
14255 goto do_madd;
14256 case MSUB_S:
14257 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14258 mips32_op = OPC_MSUB_S;
14259 goto do_madd;
14260 case MSUB_D:
14261 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14262 mips32_op = OPC_MSUB_D;
14263 goto do_madd;
14264 case MSUB_PS:
14265 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14266 mips32_op = OPC_MSUB_PS;
14267 goto do_madd;
14268 case NMADD_S:
14269 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14270 mips32_op = OPC_NMADD_S;
14271 goto do_madd;
14272 case NMADD_D:
14273 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14274 mips32_op = OPC_NMADD_D;
14275 goto do_madd;
14276 case NMADD_PS:
14277 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14278 mips32_op = OPC_NMADD_PS;
14279 goto do_madd;
14280 case NMSUB_S:
14281 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14282 mips32_op = OPC_NMSUB_S;
14283 goto do_madd;
14284 case NMSUB_D:
14285 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14286 mips32_op = OPC_NMSUB_D;
14287 goto do_madd;
14288 case NMSUB_PS:
14289 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14290 mips32_op = OPC_NMSUB_PS;
14291 do_madd:
14292 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
14293 break;
14294 case CABS_COND_FMT:
14295 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14296 cond = (ctx->opcode >> 6) & 0xf;
14297 cc = (ctx->opcode >> 13) & 0x7;
14298 fmt = (ctx->opcode >> 10) & 0x3;
14299 switch (fmt) {
14300 case 0x0:
14301 gen_cmpabs_s(ctx, cond, rt, rs, cc);
14302 break;
14303 case 0x1:
14304 gen_cmpabs_d(ctx, cond, rt, rs, cc);
14305 break;
14306 case 0x2:
14307 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
14308 break;
14309 default:
14310 goto pool32f_invalid;
14312 break;
14313 case C_COND_FMT:
14314 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14315 cond = (ctx->opcode >> 6) & 0xf;
14316 cc = (ctx->opcode >> 13) & 0x7;
14317 fmt = (ctx->opcode >> 10) & 0x3;
14318 switch (fmt) {
14319 case 0x0:
14320 gen_cmp_s(ctx, cond, rt, rs, cc);
14321 break;
14322 case 0x1:
14323 gen_cmp_d(ctx, cond, rt, rs, cc);
14324 break;
14325 case 0x2:
14326 gen_cmp_ps(ctx, cond, rt, rs, cc);
14327 break;
14328 default:
14329 goto pool32f_invalid;
14331 break;
14332 case CMP_CONDN_S:
14333 check_insn(ctx, ISA_MIPS32R6);
14334 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14335 break;
14336 case CMP_CONDN_D:
14337 check_insn(ctx, ISA_MIPS32R6);
14338 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14339 break;
14340 case POOL32FXF:
14341 gen_pool32fxf(ctx, rt, rs);
14342 break;
14343 case 0x00:
14344 /* PLL foo */
14345 switch ((ctx->opcode >> 6) & 0x7) {
14346 case PLL_PS:
14347 mips32_op = OPC_PLL_PS;
14348 goto do_ps;
14349 case PLU_PS:
14350 mips32_op = OPC_PLU_PS;
14351 goto do_ps;
14352 case PUL_PS:
14353 mips32_op = OPC_PUL_PS;
14354 goto do_ps;
14355 case PUU_PS:
14356 mips32_op = OPC_PUU_PS;
14357 goto do_ps;
14358 case CVT_PS_S:
14359 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14360 mips32_op = OPC_CVT_PS_S;
14361 do_ps:
14362 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14363 break;
14364 default:
14365 goto pool32f_invalid;
14367 break;
14368 case MIN_FMT:
14369 check_insn(ctx, ISA_MIPS32R6);
14370 switch ((ctx->opcode >> 9) & 0x3) {
14371 case FMT_SDPS_S:
14372 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
14373 break;
14374 case FMT_SDPS_D:
14375 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
14376 break;
14377 default:
14378 goto pool32f_invalid;
14380 break;
14381 case 0x08:
14382 /* [LS][WDU]XC1 */
14383 switch ((ctx->opcode >> 6) & 0x7) {
14384 case LWXC1:
14385 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14386 mips32_op = OPC_LWXC1;
14387 goto do_ldst_cp1;
14388 case SWXC1:
14389 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14390 mips32_op = OPC_SWXC1;
14391 goto do_ldst_cp1;
14392 case LDXC1:
14393 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14394 mips32_op = OPC_LDXC1;
14395 goto do_ldst_cp1;
14396 case SDXC1:
14397 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14398 mips32_op = OPC_SDXC1;
14399 goto do_ldst_cp1;
14400 case LUXC1:
14401 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14402 mips32_op = OPC_LUXC1;
14403 goto do_ldst_cp1;
14404 case SUXC1:
14405 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14406 mips32_op = OPC_SUXC1;
14407 do_ldst_cp1:
14408 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
14409 break;
14410 default:
14411 goto pool32f_invalid;
14413 break;
14414 case MAX_FMT:
14415 check_insn(ctx, ISA_MIPS32R6);
14416 switch ((ctx->opcode >> 9) & 0x3) {
14417 case FMT_SDPS_S:
14418 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
14419 break;
14420 case FMT_SDPS_D:
14421 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
14422 break;
14423 default:
14424 goto pool32f_invalid;
14426 break;
14427 case 0x18:
14428 /* 3D insns */
14429 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14430 fmt = (ctx->opcode >> 9) & 0x3;
14431 switch ((ctx->opcode >> 6) & 0x7) {
14432 case RSQRT2_FMT:
14433 switch (fmt) {
14434 case FMT_SDPS_S:
14435 mips32_op = OPC_RSQRT2_S;
14436 goto do_3d;
14437 case FMT_SDPS_D:
14438 mips32_op = OPC_RSQRT2_D;
14439 goto do_3d;
14440 case FMT_SDPS_PS:
14441 mips32_op = OPC_RSQRT2_PS;
14442 goto do_3d;
14443 default:
14444 goto pool32f_invalid;
14446 break;
14447 case RECIP2_FMT:
14448 switch (fmt) {
14449 case FMT_SDPS_S:
14450 mips32_op = OPC_RECIP2_S;
14451 goto do_3d;
14452 case FMT_SDPS_D:
14453 mips32_op = OPC_RECIP2_D;
14454 goto do_3d;
14455 case FMT_SDPS_PS:
14456 mips32_op = OPC_RECIP2_PS;
14457 goto do_3d;
14458 default:
14459 goto pool32f_invalid;
14461 break;
14462 case ADDR_PS:
14463 mips32_op = OPC_ADDR_PS;
14464 goto do_3d;
14465 case MULR_PS:
14466 mips32_op = OPC_MULR_PS;
14467 do_3d:
14468 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14469 break;
14470 default:
14471 goto pool32f_invalid;
14473 break;
14474 case 0x20:
14475 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
14476 cc = (ctx->opcode >> 13) & 0x7;
14477 fmt = (ctx->opcode >> 9) & 0x3;
14478 switch ((ctx->opcode >> 6) & 0x7) {
14479 case MOVF_FMT: /* RINT_FMT */
14480 if (ctx->insn_flags & ISA_MIPS32R6) {
14481 /* RINT_FMT */
14482 switch (fmt) {
14483 case FMT_SDPS_S:
14484 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
14485 break;
14486 case FMT_SDPS_D:
14487 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
14488 break;
14489 default:
14490 goto pool32f_invalid;
14492 } else {
14493 /* MOVF_FMT */
14494 switch (fmt) {
14495 case FMT_SDPS_S:
14496 gen_movcf_s(ctx, rs, rt, cc, 0);
14497 break;
14498 case FMT_SDPS_D:
14499 gen_movcf_d(ctx, rs, rt, cc, 0);
14500 break;
14501 case FMT_SDPS_PS:
14502 check_ps(ctx);
14503 gen_movcf_ps(ctx, rs, rt, cc, 0);
14504 break;
14505 default:
14506 goto pool32f_invalid;
14509 break;
14510 case MOVT_FMT: /* CLASS_FMT */
14511 if (ctx->insn_flags & ISA_MIPS32R6) {
14512 /* CLASS_FMT */
14513 switch (fmt) {
14514 case FMT_SDPS_S:
14515 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14516 break;
14517 case FMT_SDPS_D:
14518 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14519 break;
14520 default:
14521 goto pool32f_invalid;
14523 } else {
14524 /* MOVT_FMT */
14525 switch (fmt) {
14526 case FMT_SDPS_S:
14527 gen_movcf_s(ctx, rs, rt, cc, 1);
14528 break;
14529 case FMT_SDPS_D:
14530 gen_movcf_d(ctx, rs, rt, cc, 1);
14531 break;
14532 case FMT_SDPS_PS:
14533 check_ps(ctx);
14534 gen_movcf_ps(ctx, rs, rt, cc, 1);
14535 break;
14536 default:
14537 goto pool32f_invalid;
14540 break;
14541 case PREFX:
14542 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14543 break;
14544 default:
14545 goto pool32f_invalid;
14547 break;
14548 #define FINSN_3ARG_SDPS(prfx) \
14549 switch ((ctx->opcode >> 8) & 0x3) { \
14550 case FMT_SDPS_S: \
14551 mips32_op = OPC_##prfx##_S; \
14552 goto do_fpop; \
14553 case FMT_SDPS_D: \
14554 mips32_op = OPC_##prfx##_D; \
14555 goto do_fpop; \
14556 case FMT_SDPS_PS: \
14557 check_ps(ctx); \
14558 mips32_op = OPC_##prfx##_PS; \
14559 goto do_fpop; \
14560 default: \
14561 goto pool32f_invalid; \
14563 case MINA_FMT:
14564 check_insn(ctx, ISA_MIPS32R6);
14565 switch ((ctx->opcode >> 9) & 0x3) {
14566 case FMT_SDPS_S:
14567 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14568 break;
14569 case FMT_SDPS_D:
14570 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14571 break;
14572 default:
14573 goto pool32f_invalid;
14575 break;
14576 case MAXA_FMT:
14577 check_insn(ctx, ISA_MIPS32R6);
14578 switch ((ctx->opcode >> 9) & 0x3) {
14579 case FMT_SDPS_S:
14580 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14581 break;
14582 case FMT_SDPS_D:
14583 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14584 break;
14585 default:
14586 goto pool32f_invalid;
14588 break;
14589 case 0x30:
14590 /* regular FP ops */
14591 switch ((ctx->opcode >> 6) & 0x3) {
14592 case ADD_FMT:
14593 FINSN_3ARG_SDPS(ADD);
14594 break;
14595 case SUB_FMT:
14596 FINSN_3ARG_SDPS(SUB);
14597 break;
14598 case MUL_FMT:
14599 FINSN_3ARG_SDPS(MUL);
14600 break;
14601 case DIV_FMT:
14602 fmt = (ctx->opcode >> 8) & 0x3;
14603 if (fmt == 1) {
14604 mips32_op = OPC_DIV_D;
14605 } else if (fmt == 0) {
14606 mips32_op = OPC_DIV_S;
14607 } else {
14608 goto pool32f_invalid;
14610 goto do_fpop;
14611 default:
14612 goto pool32f_invalid;
14614 break;
14615 case 0x38:
14616 /* cmovs */
14617 switch ((ctx->opcode >> 6) & 0x7) {
14618 case MOVN_FMT: /* SELNEZ_FMT */
14619 if (ctx->insn_flags & ISA_MIPS32R6) {
14620 /* SELNEZ_FMT */
14621 switch ((ctx->opcode >> 9) & 0x3) {
14622 case FMT_SDPS_S:
14623 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
14624 break;
14625 case FMT_SDPS_D:
14626 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
14627 break;
14628 default:
14629 goto pool32f_invalid;
14631 } else {
14632 /* MOVN_FMT */
14633 FINSN_3ARG_SDPS(MOVN);
14635 break;
14636 case MOVN_FMT_04:
14637 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14638 FINSN_3ARG_SDPS(MOVN);
14639 break;
14640 case MOVZ_FMT: /* SELEQZ_FMT */
14641 if (ctx->insn_flags & ISA_MIPS32R6) {
14642 /* SELEQZ_FMT */
14643 switch ((ctx->opcode >> 9) & 0x3) {
14644 case FMT_SDPS_S:
14645 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
14646 break;
14647 case FMT_SDPS_D:
14648 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
14649 break;
14650 default:
14651 goto pool32f_invalid;
14653 } else {
14654 /* MOVZ_FMT */
14655 FINSN_3ARG_SDPS(MOVZ);
14657 break;
14658 case MOVZ_FMT_05:
14659 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14660 FINSN_3ARG_SDPS(MOVZ);
14661 break;
14662 case SEL_FMT:
14663 check_insn(ctx, ISA_MIPS32R6);
14664 switch ((ctx->opcode >> 9) & 0x3) {
14665 case FMT_SDPS_S:
14666 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
14667 break;
14668 case FMT_SDPS_D:
14669 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
14670 break;
14671 default:
14672 goto pool32f_invalid;
14674 break;
14675 case MADDF_FMT:
14676 check_insn(ctx, ISA_MIPS32R6);
14677 switch ((ctx->opcode >> 9) & 0x3) {
14678 case FMT_SDPS_S:
14679 mips32_op = OPC_MADDF_S;
14680 goto do_fpop;
14681 case FMT_SDPS_D:
14682 mips32_op = OPC_MADDF_D;
14683 goto do_fpop;
14684 default:
14685 goto pool32f_invalid;
14687 break;
14688 case MSUBF_FMT:
14689 check_insn(ctx, ISA_MIPS32R6);
14690 switch ((ctx->opcode >> 9) & 0x3) {
14691 case FMT_SDPS_S:
14692 mips32_op = OPC_MSUBF_S;
14693 goto do_fpop;
14694 case FMT_SDPS_D:
14695 mips32_op = OPC_MSUBF_D;
14696 goto do_fpop;
14697 default:
14698 goto pool32f_invalid;
14700 break;
14701 default:
14702 goto pool32f_invalid;
14704 break;
14705 do_fpop:
14706 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14707 break;
14708 default:
14709 pool32f_invalid:
14710 MIPS_INVAL("pool32f");
14711 generate_exception(ctx, EXCP_RI);
14712 break;
14714 } else {
14715 generate_exception_err(ctx, EXCP_CpU, 1);
14717 break;
14718 case POOL32I:
14719 minor = (ctx->opcode >> 21) & 0x1f;
14720 switch (minor) {
14721 case BLTZ:
14722 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14723 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
14724 break;
14725 case BLTZAL:
14726 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14727 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
14728 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14729 break;
14730 case BLTZALS:
14731 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14732 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
14733 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14734 break;
14735 case BGEZ:
14736 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14737 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
14738 break;
14739 case BGEZAL:
14740 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14741 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
14742 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14743 break;
14744 case BGEZALS:
14745 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14746 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
14747 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14748 break;
14749 case BLEZ:
14750 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14751 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
14752 break;
14753 case BGTZ:
14754 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14755 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
14756 break;
14758 /* Traps */
14759 case TLTI: /* BC1EQZC */
14760 if (ctx->insn_flags & ISA_MIPS32R6) {
14761 /* BC1EQZC */
14762 check_cp1_enabled(ctx);
14763 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
14764 } else {
14765 /* TLTI */
14766 mips32_op = OPC_TLTI;
14767 goto do_trapi;
14769 break;
14770 case TGEI: /* BC1NEZC */
14771 if (ctx->insn_flags & ISA_MIPS32R6) {
14772 /* BC1NEZC */
14773 check_cp1_enabled(ctx);
14774 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
14775 } else {
14776 /* TGEI */
14777 mips32_op = OPC_TGEI;
14778 goto do_trapi;
14780 break;
14781 case TLTIU:
14782 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14783 mips32_op = OPC_TLTIU;
14784 goto do_trapi;
14785 case TGEIU:
14786 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14787 mips32_op = OPC_TGEIU;
14788 goto do_trapi;
14789 case TNEI: /* SYNCI */
14790 if (ctx->insn_flags & ISA_MIPS32R6) {
14791 /* SYNCI */
14792 /* Break the TB to be able to sync copied instructions
14793 immediately */
14794 ctx->bstate = BS_STOP;
14795 } else {
14796 /* TNEI */
14797 mips32_op = OPC_TNEI;
14798 goto do_trapi;
14800 break;
14801 case TEQI:
14802 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14803 mips32_op = OPC_TEQI;
14804 do_trapi:
14805 gen_trap(ctx, mips32_op, rs, -1, imm);
14806 break;
14808 case BNEZC:
14809 case BEQZC:
14810 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14811 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
14812 4, rs, 0, imm << 1, 0);
14813 /* Compact branches don't have a delay slot, so just let
14814 the normal delay slot handling take us to the branch
14815 target. */
14816 break;
14817 case LUI:
14818 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14819 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
14820 break;
14821 case SYNCI:
14822 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14823 /* Break the TB to be able to sync copied instructions
14824 immediately */
14825 ctx->bstate = BS_STOP;
14826 break;
14827 case BC2F:
14828 case BC2T:
14829 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14830 /* COP2: Not implemented. */
14831 generate_exception_err(ctx, EXCP_CpU, 2);
14832 break;
14833 case BC1F:
14834 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14835 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
14836 goto do_cp1branch;
14837 case BC1T:
14838 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14839 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
14840 goto do_cp1branch;
14841 case BC1ANY4F:
14842 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14843 mips32_op = OPC_BC1FANY4;
14844 goto do_cp1mips3d;
14845 case BC1ANY4T:
14846 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14847 mips32_op = OPC_BC1TANY4;
14848 do_cp1mips3d:
14849 check_cop1x(ctx);
14850 check_insn(ctx, ASE_MIPS3D);
14851 /* Fall through */
14852 do_cp1branch:
14853 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
14854 check_cp1_enabled(ctx);
14855 gen_compute_branch1(ctx, mips32_op,
14856 (ctx->opcode >> 18) & 0x7, imm << 1);
14857 } else {
14858 generate_exception_err(ctx, EXCP_CpU, 1);
14860 break;
14861 case BPOSGE64:
14862 case BPOSGE32:
14863 /* MIPS DSP: not implemented */
14864 /* Fall through */
14865 default:
14866 MIPS_INVAL("pool32i");
14867 generate_exception(ctx, EXCP_RI);
14868 break;
14870 break;
14871 case POOL32C:
14872 minor = (ctx->opcode >> 12) & 0xf;
14873 offset = sextract32(ctx->opcode, 0,
14874 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
14875 switch (minor) {
14876 case LWL:
14877 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14878 mips32_op = OPC_LWL;
14879 goto do_ld_lr;
14880 case SWL:
14881 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14882 mips32_op = OPC_SWL;
14883 goto do_st_lr;
14884 case LWR:
14885 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14886 mips32_op = OPC_LWR;
14887 goto do_ld_lr;
14888 case SWR:
14889 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14890 mips32_op = OPC_SWR;
14891 goto do_st_lr;
14892 #if defined(TARGET_MIPS64)
14893 case LDL:
14894 check_insn(ctx, ISA_MIPS3);
14895 check_mips_64(ctx);
14896 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14897 mips32_op = OPC_LDL;
14898 goto do_ld_lr;
14899 case SDL:
14900 check_insn(ctx, ISA_MIPS3);
14901 check_mips_64(ctx);
14902 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14903 mips32_op = OPC_SDL;
14904 goto do_st_lr;
14905 case LDR:
14906 check_insn(ctx, ISA_MIPS3);
14907 check_mips_64(ctx);
14908 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14909 mips32_op = OPC_LDR;
14910 goto do_ld_lr;
14911 case SDR:
14912 check_insn(ctx, ISA_MIPS3);
14913 check_mips_64(ctx);
14914 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14915 mips32_op = OPC_SDR;
14916 goto do_st_lr;
14917 case LWU:
14918 check_insn(ctx, ISA_MIPS3);
14919 check_mips_64(ctx);
14920 mips32_op = OPC_LWU;
14921 goto do_ld_lr;
14922 case LLD:
14923 check_insn(ctx, ISA_MIPS3);
14924 check_mips_64(ctx);
14925 mips32_op = OPC_LLD;
14926 goto do_ld_lr;
14927 #endif
14928 case LL:
14929 mips32_op = OPC_LL;
14930 goto do_ld_lr;
14931 do_ld_lr:
14932 gen_ld(ctx, mips32_op, rt, rs, offset);
14933 break;
14934 do_st_lr:
14935 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
14936 break;
14937 case SC:
14938 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
14939 break;
14940 #if defined(TARGET_MIPS64)
14941 case SCD:
14942 check_insn(ctx, ISA_MIPS3);
14943 check_mips_64(ctx);
14944 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
14945 break;
14946 #endif
14947 case PREF:
14948 /* Treat as no-op */
14949 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
14950 /* hint codes 24-31 are reserved and signal RI */
14951 generate_exception(ctx, EXCP_RI);
14953 break;
14954 default:
14955 MIPS_INVAL("pool32c");
14956 generate_exception(ctx, EXCP_RI);
14957 break;
14959 break;
14960 case ADDI32: /* AUI, LUI */
14961 if (ctx->insn_flags & ISA_MIPS32R6) {
14962 /* AUI, LUI */
14963 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
14964 } else {
14965 /* ADDI32 */
14966 mips32_op = OPC_ADDI;
14967 goto do_addi;
14969 break;
14970 case ADDIU32:
14971 mips32_op = OPC_ADDIU;
14972 do_addi:
14973 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
14974 break;
14976 /* Logical operations */
14977 case ORI32:
14978 mips32_op = OPC_ORI;
14979 goto do_logici;
14980 case XORI32:
14981 mips32_op = OPC_XORI;
14982 goto do_logici;
14983 case ANDI32:
14984 mips32_op = OPC_ANDI;
14985 do_logici:
14986 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
14987 break;
14989 /* Set less than immediate */
14990 case SLTI32:
14991 mips32_op = OPC_SLTI;
14992 goto do_slti;
14993 case SLTIU32:
14994 mips32_op = OPC_SLTIU;
14995 do_slti:
14996 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
14997 break;
14998 case JALX32:
14999 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15000 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15001 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
15002 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15003 break;
15004 case JALS32: /* BOVC, BEQC, BEQZALC */
15005 if (ctx->insn_flags & ISA_MIPS32R6) {
15006 if (rs >= rt) {
15007 /* BOVC */
15008 mips32_op = OPC_BOVC;
15009 } else if (rs < rt && rs == 0) {
15010 /* BEQZALC */
15011 mips32_op = OPC_BEQZALC;
15012 } else {
15013 /* BEQC */
15014 mips32_op = OPC_BEQC;
15016 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15017 } else {
15018 /* JALS32 */
15019 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
15020 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
15021 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15023 break;
15024 case BEQ32: /* BC */
15025 if (ctx->insn_flags & ISA_MIPS32R6) {
15026 /* BC */
15027 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
15028 sextract32(ctx->opcode << 1, 0, 27));
15029 } else {
15030 /* BEQ32 */
15031 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
15033 break;
15034 case BNE32: /* BALC */
15035 if (ctx->insn_flags & ISA_MIPS32R6) {
15036 /* BALC */
15037 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
15038 sextract32(ctx->opcode << 1, 0, 27));
15039 } else {
15040 /* BNE32 */
15041 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
15043 break;
15044 case J32: /* BGTZC, BLTZC, BLTC */
15045 if (ctx->insn_flags & ISA_MIPS32R6) {
15046 if (rs == 0 && rt != 0) {
15047 /* BGTZC */
15048 mips32_op = OPC_BGTZC;
15049 } else if (rs != 0 && rt != 0 && rs == rt) {
15050 /* BLTZC */
15051 mips32_op = OPC_BLTZC;
15052 } else {
15053 /* BLTC */
15054 mips32_op = OPC_BLTC;
15056 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15057 } else {
15058 /* J32 */
15059 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
15060 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15062 break;
15063 case JAL32: /* BLEZC, BGEZC, BGEC */
15064 if (ctx->insn_flags & ISA_MIPS32R6) {
15065 if (rs == 0 && rt != 0) {
15066 /* BLEZC */
15067 mips32_op = OPC_BLEZC;
15068 } else if (rs != 0 && rt != 0 && rs == rt) {
15069 /* BGEZC */
15070 mips32_op = OPC_BGEZC;
15071 } else {
15072 /* BGEC */
15073 mips32_op = OPC_BGEC;
15075 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15076 } else {
15077 /* JAL32 */
15078 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
15079 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15080 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15082 break;
15083 /* Floating point (COP1) */
15084 case LWC132:
15085 mips32_op = OPC_LWC1;
15086 goto do_cop1;
15087 case LDC132:
15088 mips32_op = OPC_LDC1;
15089 goto do_cop1;
15090 case SWC132:
15091 mips32_op = OPC_SWC1;
15092 goto do_cop1;
15093 case SDC132:
15094 mips32_op = OPC_SDC1;
15095 do_cop1:
15096 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
15097 break;
15098 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15099 if (ctx->insn_flags & ISA_MIPS32R6) {
15100 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15101 switch ((ctx->opcode >> 16) & 0x1f) {
15102 case ADDIUPC_00 ... ADDIUPC_07:
15103 gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
15104 break;
15105 case AUIPC:
15106 gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
15107 break;
15108 case ALUIPC:
15109 gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt);
15110 break;
15111 case LWPC_08 ... LWPC_0F:
15112 gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt);
15113 break;
15114 default:
15115 generate_exception(ctx, EXCP_RI);
15116 break;
15118 } else {
15119 /* ADDIUPC */
15120 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
15121 int offset = SIMM(ctx->opcode, 0, 23) << 2;
15123 gen_addiupc(ctx, reg, offset, 0, 0);
15125 break;
15126 case BNVC: /* BNEC, BNEZALC */
15127 check_insn(ctx, ISA_MIPS32R6);
15128 if (rs >= rt) {
15129 /* BNVC */
15130 mips32_op = OPC_BNVC;
15131 } else if (rs < rt && rs == 0) {
15132 /* BNEZALC */
15133 mips32_op = OPC_BNEZALC;
15134 } else {
15135 /* BNEC */
15136 mips32_op = OPC_BNEC;
15138 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15139 break;
15140 case R6_BNEZC: /* JIALC */
15141 check_insn(ctx, ISA_MIPS32R6);
15142 if (rt != 0) {
15143 /* BNEZC */
15144 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
15145 sextract32(ctx->opcode << 1, 0, 22));
15146 } else {
15147 /* JIALC */
15148 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
15150 break;
15151 case R6_BEQZC: /* JIC */
15152 check_insn(ctx, ISA_MIPS32R6);
15153 if (rt != 0) {
15154 /* BEQZC */
15155 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
15156 sextract32(ctx->opcode << 1, 0, 22));
15157 } else {
15158 /* JIC */
15159 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
15161 break;
15162 case BLEZALC: /* BGEZALC, BGEUC */
15163 check_insn(ctx, ISA_MIPS32R6);
15164 if (rs == 0 && rt != 0) {
15165 /* BLEZALC */
15166 mips32_op = OPC_BLEZALC;
15167 } else if (rs != 0 && rt != 0 && rs == rt) {
15168 /* BGEZALC */
15169 mips32_op = OPC_BGEZALC;
15170 } else {
15171 /* BGEUC */
15172 mips32_op = OPC_BGEUC;
15174 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15175 break;
15176 case BGTZALC: /* BLTZALC, BLTUC */
15177 check_insn(ctx, ISA_MIPS32R6);
15178 if (rs == 0 && rt != 0) {
15179 /* BGTZALC */
15180 mips32_op = OPC_BGTZALC;
15181 } else if (rs != 0 && rt != 0 && rs == rt) {
15182 /* BLTZALC */
15183 mips32_op = OPC_BLTZALC;
15184 } else {
15185 /* BLTUC */
15186 mips32_op = OPC_BLTUC;
15188 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15189 break;
15190 /* Loads and stores */
15191 case LB32:
15192 mips32_op = OPC_LB;
15193 goto do_ld;
15194 case LBU32:
15195 mips32_op = OPC_LBU;
15196 goto do_ld;
15197 case LH32:
15198 mips32_op = OPC_LH;
15199 goto do_ld;
15200 case LHU32:
15201 mips32_op = OPC_LHU;
15202 goto do_ld;
15203 case LW32:
15204 mips32_op = OPC_LW;
15205 goto do_ld;
15206 #ifdef TARGET_MIPS64
15207 case LD32:
15208 check_insn(ctx, ISA_MIPS3);
15209 check_mips_64(ctx);
15210 mips32_op = OPC_LD;
15211 goto do_ld;
15212 case SD32:
15213 check_insn(ctx, ISA_MIPS3);
15214 check_mips_64(ctx);
15215 mips32_op = OPC_SD;
15216 goto do_st;
15217 #endif
15218 case SB32:
15219 mips32_op = OPC_SB;
15220 goto do_st;
15221 case SH32:
15222 mips32_op = OPC_SH;
15223 goto do_st;
15224 case SW32:
15225 mips32_op = OPC_SW;
15226 goto do_st;
15227 do_ld:
15228 gen_ld(ctx, mips32_op, rt, rs, imm);
15229 break;
15230 do_st:
15231 gen_st(ctx, mips32_op, rt, rs, imm);
15232 break;
15233 default:
15234 generate_exception(ctx, EXCP_RI);
15235 break;
15239 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
15241 uint32_t op;
15243 /* make sure instructions are on a halfword boundary */
15244 if (ctx->pc & 0x1) {
15245 env->CP0_BadVAddr = ctx->pc;
15246 generate_exception(ctx, EXCP_AdEL);
15247 ctx->bstate = BS_STOP;
15248 return 2;
15251 op = (ctx->opcode >> 10) & 0x3f;
15252 /* Enforce properly-sized instructions in a delay slot */
15253 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
15254 switch (op & 0x7) { /* MSB-3..MSB-5 */
15255 case 0:
15256 /* POOL32A, POOL32B, POOL32I, POOL32C */
15257 case 4:
15258 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
15259 case 5:
15260 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
15261 case 6:
15262 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
15263 case 7:
15264 /* LB32, LH32, LWC132, LDC132, LW32 */
15265 if (ctx->hflags & MIPS_HFLAG_BDS16) {
15266 generate_exception(ctx, EXCP_RI);
15267 /* Just stop translation; the user is confused. */
15268 ctx->bstate = BS_STOP;
15269 return 2;
15271 break;
15272 case 1:
15273 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
15274 case 2:
15275 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
15276 case 3:
15277 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
15278 if (ctx->hflags & MIPS_HFLAG_BDS32) {
15279 generate_exception(ctx, EXCP_RI);
15280 /* Just stop translation; the user is confused. */
15281 ctx->bstate = BS_STOP;
15282 return 2;
15284 break;
15288 switch (op) {
15289 case POOL16A:
15291 int rd = mmreg(uMIPS_RD(ctx->opcode));
15292 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
15293 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
15294 uint32_t opc = 0;
15296 switch (ctx->opcode & 0x1) {
15297 case ADDU16:
15298 opc = OPC_ADDU;
15299 break;
15300 case SUBU16:
15301 opc = OPC_SUBU;
15302 break;
15304 if (ctx->insn_flags & ISA_MIPS32R6) {
15305 /* In the Release 6 the register number location in
15306 * the instruction encoding has changed.
15308 gen_arith(ctx, opc, rs1, rd, rs2);
15309 } else {
15310 gen_arith(ctx, opc, rd, rs1, rs2);
15313 break;
15314 case POOL16B:
15316 int rd = mmreg(uMIPS_RD(ctx->opcode));
15317 int rs = mmreg(uMIPS_RS(ctx->opcode));
15318 int amount = (ctx->opcode >> 1) & 0x7;
15319 uint32_t opc = 0;
15320 amount = amount == 0 ? 8 : amount;
15322 switch (ctx->opcode & 0x1) {
15323 case SLL16:
15324 opc = OPC_SLL;
15325 break;
15326 case SRL16:
15327 opc = OPC_SRL;
15328 break;
15331 gen_shift_imm(ctx, opc, rd, rs, amount);
15333 break;
15334 case POOL16C:
15335 if (ctx->insn_flags & ISA_MIPS32R6) {
15336 gen_pool16c_r6_insn(ctx);
15337 } else {
15338 gen_pool16c_insn(ctx);
15340 break;
15341 case LWGP16:
15343 int rd = mmreg(uMIPS_RD(ctx->opcode));
15344 int rb = 28; /* GP */
15345 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
15347 gen_ld(ctx, OPC_LW, rd, rb, offset);
15349 break;
15350 case POOL16F:
15351 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15352 if (ctx->opcode & 1) {
15353 generate_exception(ctx, EXCP_RI);
15354 } else {
15355 /* MOVEP */
15356 int enc_dest = uMIPS_RD(ctx->opcode);
15357 int enc_rt = uMIPS_RS2(ctx->opcode);
15358 int enc_rs = uMIPS_RS1(ctx->opcode);
15359 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15361 break;
15362 case LBU16:
15364 int rd = mmreg(uMIPS_RD(ctx->opcode));
15365 int rb = mmreg(uMIPS_RS(ctx->opcode));
15366 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15367 offset = (offset == 0xf ? -1 : offset);
15369 gen_ld(ctx, OPC_LBU, rd, rb, offset);
15371 break;
15372 case LHU16:
15374 int rd = mmreg(uMIPS_RD(ctx->opcode));
15375 int rb = mmreg(uMIPS_RS(ctx->opcode));
15376 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15378 gen_ld(ctx, OPC_LHU, rd, rb, offset);
15380 break;
15381 case LWSP16:
15383 int rd = (ctx->opcode >> 5) & 0x1f;
15384 int rb = 29; /* SP */
15385 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15387 gen_ld(ctx, OPC_LW, rd, rb, offset);
15389 break;
15390 case LW16:
15392 int rd = mmreg(uMIPS_RD(ctx->opcode));
15393 int rb = mmreg(uMIPS_RS(ctx->opcode));
15394 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15396 gen_ld(ctx, OPC_LW, rd, rb, offset);
15398 break;
15399 case SB16:
15401 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15402 int rb = mmreg(uMIPS_RS(ctx->opcode));
15403 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15405 gen_st(ctx, OPC_SB, rd, rb, offset);
15407 break;
15408 case SH16:
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) << 1;
15414 gen_st(ctx, OPC_SH, rd, rb, offset);
15416 break;
15417 case SWSP16:
15419 int rd = (ctx->opcode >> 5) & 0x1f;
15420 int rb = 29; /* SP */
15421 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15423 gen_st(ctx, OPC_SW, rd, rb, offset);
15425 break;
15426 case SW16:
15428 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15429 int rb = mmreg(uMIPS_RS(ctx->opcode));
15430 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15432 gen_st(ctx, OPC_SW, rd, rb, offset);
15434 break;
15435 case MOVE16:
15437 int rd = uMIPS_RD5(ctx->opcode);
15438 int rs = uMIPS_RS5(ctx->opcode);
15440 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
15442 break;
15443 case ANDI16:
15444 gen_andi16(ctx);
15445 break;
15446 case POOL16D:
15447 switch (ctx->opcode & 0x1) {
15448 case ADDIUS5:
15449 gen_addius5(ctx);
15450 break;
15451 case ADDIUSP:
15452 gen_addiusp(ctx);
15453 break;
15455 break;
15456 case POOL16E:
15457 switch (ctx->opcode & 0x1) {
15458 case ADDIUR2:
15459 gen_addiur2(ctx);
15460 break;
15461 case ADDIUR1SP:
15462 gen_addiur1sp(ctx);
15463 break;
15465 break;
15466 case B16: /* BC16 */
15467 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
15468 sextract32(ctx->opcode, 0, 10) << 1,
15469 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15470 break;
15471 case BNEZ16: /* BNEZC16 */
15472 case BEQZ16: /* BEQZC16 */
15473 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
15474 mmreg(uMIPS_RD(ctx->opcode)),
15475 0, sextract32(ctx->opcode, 0, 7) << 1,
15476 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15478 break;
15479 case LI16:
15481 int reg = mmreg(uMIPS_RD(ctx->opcode));
15482 int imm = ZIMM(ctx->opcode, 0, 7);
15484 imm = (imm == 0x7f ? -1 : imm);
15485 tcg_gen_movi_tl(cpu_gpr[reg], imm);
15487 break;
15488 case RES_29:
15489 case RES_31:
15490 case RES_39:
15491 generate_exception(ctx, EXCP_RI);
15492 break;
15493 default:
15494 decode_micromips32_opc(env, ctx);
15495 return 4;
15498 return 2;
15501 /* SmartMIPS extension to MIPS32 */
15503 #if defined(TARGET_MIPS64)
15505 /* MDMX extension to MIPS64 */
15507 #endif
15509 /* MIPSDSP functions. */
15510 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
15511 int rd, int base, int offset)
15513 const char *opn = "ldx";
15514 TCGv t0;
15516 check_dsp(ctx);
15517 t0 = tcg_temp_new();
15519 if (base == 0) {
15520 gen_load_gpr(t0, offset);
15521 } else if (offset == 0) {
15522 gen_load_gpr(t0, base);
15523 } else {
15524 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
15527 switch (opc) {
15528 case OPC_LBUX:
15529 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
15530 gen_store_gpr(t0, rd);
15531 opn = "lbux";
15532 break;
15533 case OPC_LHX:
15534 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
15535 gen_store_gpr(t0, rd);
15536 opn = "lhx";
15537 break;
15538 case OPC_LWX:
15539 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
15540 gen_store_gpr(t0, rd);
15541 opn = "lwx";
15542 break;
15543 #if defined(TARGET_MIPS64)
15544 case OPC_LDX:
15545 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
15546 gen_store_gpr(t0, rd);
15547 opn = "ldx";
15548 break;
15549 #endif
15551 (void)opn; /* avoid a compiler warning */
15552 MIPS_DEBUG("%s %s, %s(%s)", opn,
15553 regnames[rd], regnames[offset], regnames[base]);
15554 tcg_temp_free(t0);
15557 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
15558 int ret, int v1, int v2)
15560 const char *opn = "mipsdsp arith";
15561 TCGv v1_t;
15562 TCGv v2_t;
15564 if (ret == 0) {
15565 /* Treat as NOP. */
15566 MIPS_DEBUG("NOP");
15567 return;
15570 v1_t = tcg_temp_new();
15571 v2_t = tcg_temp_new();
15573 gen_load_gpr(v1_t, v1);
15574 gen_load_gpr(v2_t, v2);
15576 switch (op1) {
15577 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
15578 case OPC_MULT_G_2E:
15579 check_dspr2(ctx);
15580 switch (op2) {
15581 case OPC_ADDUH_QB:
15582 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
15583 break;
15584 case OPC_ADDUH_R_QB:
15585 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15586 break;
15587 case OPC_ADDQH_PH:
15588 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
15589 break;
15590 case OPC_ADDQH_R_PH:
15591 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15592 break;
15593 case OPC_ADDQH_W:
15594 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
15595 break;
15596 case OPC_ADDQH_R_W:
15597 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15598 break;
15599 case OPC_SUBUH_QB:
15600 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
15601 break;
15602 case OPC_SUBUH_R_QB:
15603 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15604 break;
15605 case OPC_SUBQH_PH:
15606 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
15607 break;
15608 case OPC_SUBQH_R_PH:
15609 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15610 break;
15611 case OPC_SUBQH_W:
15612 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
15613 break;
15614 case OPC_SUBQH_R_W:
15615 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15616 break;
15618 break;
15619 case OPC_ABSQ_S_PH_DSP:
15620 switch (op2) {
15621 case OPC_ABSQ_S_QB:
15622 check_dspr2(ctx);
15623 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
15624 break;
15625 case OPC_ABSQ_S_PH:
15626 check_dsp(ctx);
15627 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
15628 break;
15629 case OPC_ABSQ_S_W:
15630 check_dsp(ctx);
15631 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
15632 break;
15633 case OPC_PRECEQ_W_PHL:
15634 check_dsp(ctx);
15635 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
15636 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15637 break;
15638 case OPC_PRECEQ_W_PHR:
15639 check_dsp(ctx);
15640 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
15641 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
15642 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15643 break;
15644 case OPC_PRECEQU_PH_QBL:
15645 check_dsp(ctx);
15646 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
15647 break;
15648 case OPC_PRECEQU_PH_QBR:
15649 check_dsp(ctx);
15650 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
15651 break;
15652 case OPC_PRECEQU_PH_QBLA:
15653 check_dsp(ctx);
15654 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
15655 break;
15656 case OPC_PRECEQU_PH_QBRA:
15657 check_dsp(ctx);
15658 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
15659 break;
15660 case OPC_PRECEU_PH_QBL:
15661 check_dsp(ctx);
15662 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
15663 break;
15664 case OPC_PRECEU_PH_QBR:
15665 check_dsp(ctx);
15666 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
15667 break;
15668 case OPC_PRECEU_PH_QBLA:
15669 check_dsp(ctx);
15670 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
15671 break;
15672 case OPC_PRECEU_PH_QBRA:
15673 check_dsp(ctx);
15674 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
15675 break;
15677 break;
15678 case OPC_ADDU_QB_DSP:
15679 switch (op2) {
15680 case OPC_ADDQ_PH:
15681 check_dsp(ctx);
15682 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15683 break;
15684 case OPC_ADDQ_S_PH:
15685 check_dsp(ctx);
15686 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15687 break;
15688 case OPC_ADDQ_S_W:
15689 check_dsp(ctx);
15690 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15691 break;
15692 case OPC_ADDU_QB:
15693 check_dsp(ctx);
15694 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15695 break;
15696 case OPC_ADDU_S_QB:
15697 check_dsp(ctx);
15698 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15699 break;
15700 case OPC_ADDU_PH:
15701 check_dspr2(ctx);
15702 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15703 break;
15704 case OPC_ADDU_S_PH:
15705 check_dspr2(ctx);
15706 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15707 break;
15708 case OPC_SUBQ_PH:
15709 check_dsp(ctx);
15710 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15711 break;
15712 case OPC_SUBQ_S_PH:
15713 check_dsp(ctx);
15714 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15715 break;
15716 case OPC_SUBQ_S_W:
15717 check_dsp(ctx);
15718 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15719 break;
15720 case OPC_SUBU_QB:
15721 check_dsp(ctx);
15722 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15723 break;
15724 case OPC_SUBU_S_QB:
15725 check_dsp(ctx);
15726 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15727 break;
15728 case OPC_SUBU_PH:
15729 check_dspr2(ctx);
15730 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15731 break;
15732 case OPC_SUBU_S_PH:
15733 check_dspr2(ctx);
15734 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15735 break;
15736 case OPC_ADDSC:
15737 check_dsp(ctx);
15738 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15739 break;
15740 case OPC_ADDWC:
15741 check_dsp(ctx);
15742 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15743 break;
15744 case OPC_MODSUB:
15745 check_dsp(ctx);
15746 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
15747 break;
15748 case OPC_RADDU_W_QB:
15749 check_dsp(ctx);
15750 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
15751 break;
15753 break;
15754 case OPC_CMPU_EQ_QB_DSP:
15755 switch (op2) {
15756 case OPC_PRECR_QB_PH:
15757 check_dspr2(ctx);
15758 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15759 break;
15760 case OPC_PRECRQ_QB_PH:
15761 check_dsp(ctx);
15762 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15763 break;
15764 case OPC_PRECR_SRA_PH_W:
15765 check_dspr2(ctx);
15767 TCGv_i32 sa_t = tcg_const_i32(v2);
15768 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
15769 cpu_gpr[ret]);
15770 tcg_temp_free_i32(sa_t);
15771 break;
15773 case OPC_PRECR_SRA_R_PH_W:
15774 check_dspr2(ctx);
15776 TCGv_i32 sa_t = tcg_const_i32(v2);
15777 gen_helper_precr_sra_r_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_PRECRQ_PH_W:
15783 check_dsp(ctx);
15784 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
15785 break;
15786 case OPC_PRECRQ_RS_PH_W:
15787 check_dsp(ctx);
15788 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15789 break;
15790 case OPC_PRECRQU_S_QB_PH:
15791 check_dsp(ctx);
15792 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15793 break;
15795 break;
15796 #ifdef TARGET_MIPS64
15797 case OPC_ABSQ_S_QH_DSP:
15798 switch (op2) {
15799 case OPC_PRECEQ_L_PWL:
15800 check_dsp(ctx);
15801 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
15802 break;
15803 case OPC_PRECEQ_L_PWR:
15804 check_dsp(ctx);
15805 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
15806 break;
15807 case OPC_PRECEQ_PW_QHL:
15808 check_dsp(ctx);
15809 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
15810 break;
15811 case OPC_PRECEQ_PW_QHR:
15812 check_dsp(ctx);
15813 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
15814 break;
15815 case OPC_PRECEQ_PW_QHLA:
15816 check_dsp(ctx);
15817 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
15818 break;
15819 case OPC_PRECEQ_PW_QHRA:
15820 check_dsp(ctx);
15821 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
15822 break;
15823 case OPC_PRECEQU_QH_OBL:
15824 check_dsp(ctx);
15825 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
15826 break;
15827 case OPC_PRECEQU_QH_OBR:
15828 check_dsp(ctx);
15829 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
15830 break;
15831 case OPC_PRECEQU_QH_OBLA:
15832 check_dsp(ctx);
15833 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
15834 break;
15835 case OPC_PRECEQU_QH_OBRA:
15836 check_dsp(ctx);
15837 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
15838 break;
15839 case OPC_PRECEU_QH_OBL:
15840 check_dsp(ctx);
15841 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
15842 break;
15843 case OPC_PRECEU_QH_OBR:
15844 check_dsp(ctx);
15845 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
15846 break;
15847 case OPC_PRECEU_QH_OBLA:
15848 check_dsp(ctx);
15849 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
15850 break;
15851 case OPC_PRECEU_QH_OBRA:
15852 check_dsp(ctx);
15853 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
15854 break;
15855 case OPC_ABSQ_S_OB:
15856 check_dspr2(ctx);
15857 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
15858 break;
15859 case OPC_ABSQ_S_PW:
15860 check_dsp(ctx);
15861 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
15862 break;
15863 case OPC_ABSQ_S_QH:
15864 check_dsp(ctx);
15865 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
15866 break;
15868 break;
15869 case OPC_ADDU_OB_DSP:
15870 switch (op2) {
15871 case OPC_RADDU_L_OB:
15872 check_dsp(ctx);
15873 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
15874 break;
15875 case OPC_SUBQ_PW:
15876 check_dsp(ctx);
15877 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15878 break;
15879 case OPC_SUBQ_S_PW:
15880 check_dsp(ctx);
15881 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15882 break;
15883 case OPC_SUBQ_QH:
15884 check_dsp(ctx);
15885 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15886 break;
15887 case OPC_SUBQ_S_QH:
15888 check_dsp(ctx);
15889 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15890 break;
15891 case OPC_SUBU_OB:
15892 check_dsp(ctx);
15893 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15894 break;
15895 case OPC_SUBU_S_OB:
15896 check_dsp(ctx);
15897 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15898 break;
15899 case OPC_SUBU_QH:
15900 check_dspr2(ctx);
15901 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15902 break;
15903 case OPC_SUBU_S_QH:
15904 check_dspr2(ctx);
15905 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15906 break;
15907 case OPC_SUBUH_OB:
15908 check_dspr2(ctx);
15909 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
15910 break;
15911 case OPC_SUBUH_R_OB:
15912 check_dspr2(ctx);
15913 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15914 break;
15915 case OPC_ADDQ_PW:
15916 check_dsp(ctx);
15917 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15918 break;
15919 case OPC_ADDQ_S_PW:
15920 check_dsp(ctx);
15921 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15922 break;
15923 case OPC_ADDQ_QH:
15924 check_dsp(ctx);
15925 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15926 break;
15927 case OPC_ADDQ_S_QH:
15928 check_dsp(ctx);
15929 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15930 break;
15931 case OPC_ADDU_OB:
15932 check_dsp(ctx);
15933 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15934 break;
15935 case OPC_ADDU_S_OB:
15936 check_dsp(ctx);
15937 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15938 break;
15939 case OPC_ADDU_QH:
15940 check_dspr2(ctx);
15941 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15942 break;
15943 case OPC_ADDU_S_QH:
15944 check_dspr2(ctx);
15945 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15946 break;
15947 case OPC_ADDUH_OB:
15948 check_dspr2(ctx);
15949 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
15950 break;
15951 case OPC_ADDUH_R_OB:
15952 check_dspr2(ctx);
15953 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15954 break;
15956 break;
15957 case OPC_CMPU_EQ_OB_DSP:
15958 switch (op2) {
15959 case OPC_PRECR_OB_QH:
15960 check_dspr2(ctx);
15961 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15962 break;
15963 case OPC_PRECR_SRA_QH_PW:
15964 check_dspr2(ctx);
15966 TCGv_i32 ret_t = tcg_const_i32(ret);
15967 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
15968 tcg_temp_free_i32(ret_t);
15969 break;
15971 case OPC_PRECR_SRA_R_QH_PW:
15972 check_dspr2(ctx);
15974 TCGv_i32 sa_v = tcg_const_i32(ret);
15975 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
15976 tcg_temp_free_i32(sa_v);
15977 break;
15979 case OPC_PRECRQ_OB_QH:
15980 check_dsp(ctx);
15981 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15982 break;
15983 case OPC_PRECRQ_PW_L:
15984 check_dsp(ctx);
15985 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
15986 break;
15987 case OPC_PRECRQ_QH_PW:
15988 check_dsp(ctx);
15989 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
15990 break;
15991 case OPC_PRECRQ_RS_QH_PW:
15992 check_dsp(ctx);
15993 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15994 break;
15995 case OPC_PRECRQU_S_OB_QH:
15996 check_dsp(ctx);
15997 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15998 break;
16000 break;
16001 #endif
16004 tcg_temp_free(v1_t);
16005 tcg_temp_free(v2_t);
16007 (void)opn; /* avoid a compiler warning */
16008 MIPS_DEBUG("%s", opn);
16011 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
16012 int ret, int v1, int v2)
16014 uint32_t op2;
16015 const char *opn = "mipsdsp shift";
16016 TCGv t0;
16017 TCGv v1_t;
16018 TCGv v2_t;
16020 if (ret == 0) {
16021 /* Treat as NOP. */
16022 MIPS_DEBUG("NOP");
16023 return;
16026 t0 = tcg_temp_new();
16027 v1_t = tcg_temp_new();
16028 v2_t = tcg_temp_new();
16030 tcg_gen_movi_tl(t0, v1);
16031 gen_load_gpr(v1_t, v1);
16032 gen_load_gpr(v2_t, v2);
16034 switch (opc) {
16035 case OPC_SHLL_QB_DSP:
16037 op2 = MASK_SHLL_QB(ctx->opcode);
16038 switch (op2) {
16039 case OPC_SHLL_QB:
16040 check_dsp(ctx);
16041 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
16042 break;
16043 case OPC_SHLLV_QB:
16044 check_dsp(ctx);
16045 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16046 break;
16047 case OPC_SHLL_PH:
16048 check_dsp(ctx);
16049 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
16050 break;
16051 case OPC_SHLLV_PH:
16052 check_dsp(ctx);
16053 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16054 break;
16055 case OPC_SHLL_S_PH:
16056 check_dsp(ctx);
16057 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
16058 break;
16059 case OPC_SHLLV_S_PH:
16060 check_dsp(ctx);
16061 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16062 break;
16063 case OPC_SHLL_S_W:
16064 check_dsp(ctx);
16065 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
16066 break;
16067 case OPC_SHLLV_S_W:
16068 check_dsp(ctx);
16069 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16070 break;
16071 case OPC_SHRL_QB:
16072 check_dsp(ctx);
16073 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
16074 break;
16075 case OPC_SHRLV_QB:
16076 check_dsp(ctx);
16077 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
16078 break;
16079 case OPC_SHRL_PH:
16080 check_dspr2(ctx);
16081 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
16082 break;
16083 case OPC_SHRLV_PH:
16084 check_dspr2(ctx);
16085 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
16086 break;
16087 case OPC_SHRA_QB:
16088 check_dspr2(ctx);
16089 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
16090 break;
16091 case OPC_SHRA_R_QB:
16092 check_dspr2(ctx);
16093 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
16094 break;
16095 case OPC_SHRAV_QB:
16096 check_dspr2(ctx);
16097 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
16098 break;
16099 case OPC_SHRAV_R_QB:
16100 check_dspr2(ctx);
16101 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
16102 break;
16103 case OPC_SHRA_PH:
16104 check_dsp(ctx);
16105 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
16106 break;
16107 case OPC_SHRA_R_PH:
16108 check_dsp(ctx);
16109 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
16110 break;
16111 case OPC_SHRAV_PH:
16112 check_dsp(ctx);
16113 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
16114 break;
16115 case OPC_SHRAV_R_PH:
16116 check_dsp(ctx);
16117 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
16118 break;
16119 case OPC_SHRA_R_W:
16120 check_dsp(ctx);
16121 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
16122 break;
16123 case OPC_SHRAV_R_W:
16124 check_dsp(ctx);
16125 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
16126 break;
16127 default: /* Invalid */
16128 MIPS_INVAL("MASK SHLL.QB");
16129 generate_exception(ctx, EXCP_RI);
16130 break;
16132 break;
16134 #ifdef TARGET_MIPS64
16135 case OPC_SHLL_OB_DSP:
16136 op2 = MASK_SHLL_OB(ctx->opcode);
16137 switch (op2) {
16138 case OPC_SHLL_PW:
16139 check_dsp(ctx);
16140 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
16141 break;
16142 case OPC_SHLLV_PW:
16143 check_dsp(ctx);
16144 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16145 break;
16146 case OPC_SHLL_S_PW:
16147 check_dsp(ctx);
16148 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
16149 break;
16150 case OPC_SHLLV_S_PW:
16151 check_dsp(ctx);
16152 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16153 break;
16154 case OPC_SHLL_OB:
16155 check_dsp(ctx);
16156 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
16157 break;
16158 case OPC_SHLLV_OB:
16159 check_dsp(ctx);
16160 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16161 break;
16162 case OPC_SHLL_QH:
16163 check_dsp(ctx);
16164 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
16165 break;
16166 case OPC_SHLLV_QH:
16167 check_dsp(ctx);
16168 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16169 break;
16170 case OPC_SHLL_S_QH:
16171 check_dsp(ctx);
16172 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
16173 break;
16174 case OPC_SHLLV_S_QH:
16175 check_dsp(ctx);
16176 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16177 break;
16178 case OPC_SHRA_OB:
16179 check_dspr2(ctx);
16180 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
16181 break;
16182 case OPC_SHRAV_OB:
16183 check_dspr2(ctx);
16184 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
16185 break;
16186 case OPC_SHRA_R_OB:
16187 check_dspr2(ctx);
16188 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
16189 break;
16190 case OPC_SHRAV_R_OB:
16191 check_dspr2(ctx);
16192 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
16193 break;
16194 case OPC_SHRA_PW:
16195 check_dsp(ctx);
16196 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
16197 break;
16198 case OPC_SHRAV_PW:
16199 check_dsp(ctx);
16200 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
16201 break;
16202 case OPC_SHRA_R_PW:
16203 check_dsp(ctx);
16204 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
16205 break;
16206 case OPC_SHRAV_R_PW:
16207 check_dsp(ctx);
16208 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
16209 break;
16210 case OPC_SHRA_QH:
16211 check_dsp(ctx);
16212 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
16213 break;
16214 case OPC_SHRAV_QH:
16215 check_dsp(ctx);
16216 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
16217 break;
16218 case OPC_SHRA_R_QH:
16219 check_dsp(ctx);
16220 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
16221 break;
16222 case OPC_SHRAV_R_QH:
16223 check_dsp(ctx);
16224 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
16225 break;
16226 case OPC_SHRL_OB:
16227 check_dsp(ctx);
16228 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
16229 break;
16230 case OPC_SHRLV_OB:
16231 check_dsp(ctx);
16232 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
16233 break;
16234 case OPC_SHRL_QH:
16235 check_dspr2(ctx);
16236 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
16237 break;
16238 case OPC_SHRLV_QH:
16239 check_dspr2(ctx);
16240 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
16241 break;
16242 default: /* Invalid */
16243 MIPS_INVAL("MASK SHLL.OB");
16244 generate_exception(ctx, EXCP_RI);
16245 break;
16247 break;
16248 #endif
16251 tcg_temp_free(t0);
16252 tcg_temp_free(v1_t);
16253 tcg_temp_free(v2_t);
16254 (void)opn; /* avoid a compiler warning */
16255 MIPS_DEBUG("%s", opn);
16258 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
16259 int ret, int v1, int v2, int check_ret)
16261 const char *opn = "mipsdsp multiply";
16262 TCGv_i32 t0;
16263 TCGv v1_t;
16264 TCGv v2_t;
16266 if ((ret == 0) && (check_ret == 1)) {
16267 /* Treat as NOP. */
16268 MIPS_DEBUG("NOP");
16269 return;
16272 t0 = tcg_temp_new_i32();
16273 v1_t = tcg_temp_new();
16274 v2_t = tcg_temp_new();
16276 tcg_gen_movi_i32(t0, ret);
16277 gen_load_gpr(v1_t, v1);
16278 gen_load_gpr(v2_t, v2);
16280 switch (op1) {
16281 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
16282 * the same mask and op1. */
16283 case OPC_MULT_G_2E:
16284 check_dspr2(ctx);
16285 switch (op2) {
16286 case OPC_MUL_PH:
16287 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16288 break;
16289 case OPC_MUL_S_PH:
16290 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16291 break;
16292 case OPC_MULQ_S_W:
16293 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16294 break;
16295 case OPC_MULQ_RS_W:
16296 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16297 break;
16299 break;
16300 case OPC_DPA_W_PH_DSP:
16301 switch (op2) {
16302 case OPC_DPAU_H_QBL:
16303 check_dsp(ctx);
16304 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
16305 break;
16306 case OPC_DPAU_H_QBR:
16307 check_dsp(ctx);
16308 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
16309 break;
16310 case OPC_DPSU_H_QBL:
16311 check_dsp(ctx);
16312 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
16313 break;
16314 case OPC_DPSU_H_QBR:
16315 check_dsp(ctx);
16316 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
16317 break;
16318 case OPC_DPA_W_PH:
16319 check_dspr2(ctx);
16320 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
16321 break;
16322 case OPC_DPAX_W_PH:
16323 check_dspr2(ctx);
16324 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
16325 break;
16326 case OPC_DPAQ_S_W_PH:
16327 check_dsp(ctx);
16328 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16329 break;
16330 case OPC_DPAQX_S_W_PH:
16331 check_dspr2(ctx);
16332 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16333 break;
16334 case OPC_DPAQX_SA_W_PH:
16335 check_dspr2(ctx);
16336 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16337 break;
16338 case OPC_DPS_W_PH:
16339 check_dspr2(ctx);
16340 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
16341 break;
16342 case OPC_DPSX_W_PH:
16343 check_dspr2(ctx);
16344 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
16345 break;
16346 case OPC_DPSQ_S_W_PH:
16347 check_dsp(ctx);
16348 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16349 break;
16350 case OPC_DPSQX_S_W_PH:
16351 check_dspr2(ctx);
16352 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16353 break;
16354 case OPC_DPSQX_SA_W_PH:
16355 check_dspr2(ctx);
16356 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16357 break;
16358 case OPC_MULSAQ_S_W_PH:
16359 check_dsp(ctx);
16360 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16361 break;
16362 case OPC_DPAQ_SA_L_W:
16363 check_dsp(ctx);
16364 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16365 break;
16366 case OPC_DPSQ_SA_L_W:
16367 check_dsp(ctx);
16368 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16369 break;
16370 case OPC_MAQ_S_W_PHL:
16371 check_dsp(ctx);
16372 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
16373 break;
16374 case OPC_MAQ_S_W_PHR:
16375 check_dsp(ctx);
16376 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
16377 break;
16378 case OPC_MAQ_SA_W_PHL:
16379 check_dsp(ctx);
16380 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
16381 break;
16382 case OPC_MAQ_SA_W_PHR:
16383 check_dsp(ctx);
16384 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
16385 break;
16386 case OPC_MULSA_W_PH:
16387 check_dspr2(ctx);
16388 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
16389 break;
16391 break;
16392 #ifdef TARGET_MIPS64
16393 case OPC_DPAQ_W_QH_DSP:
16395 int ac = ret & 0x03;
16396 tcg_gen_movi_i32(t0, ac);
16398 switch (op2) {
16399 case OPC_DMADD:
16400 check_dsp(ctx);
16401 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
16402 break;
16403 case OPC_DMADDU:
16404 check_dsp(ctx);
16405 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
16406 break;
16407 case OPC_DMSUB:
16408 check_dsp(ctx);
16409 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
16410 break;
16411 case OPC_DMSUBU:
16412 check_dsp(ctx);
16413 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
16414 break;
16415 case OPC_DPA_W_QH:
16416 check_dspr2(ctx);
16417 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
16418 break;
16419 case OPC_DPAQ_S_W_QH:
16420 check_dsp(ctx);
16421 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16422 break;
16423 case OPC_DPAQ_SA_L_PW:
16424 check_dsp(ctx);
16425 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16426 break;
16427 case OPC_DPAU_H_OBL:
16428 check_dsp(ctx);
16429 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
16430 break;
16431 case OPC_DPAU_H_OBR:
16432 check_dsp(ctx);
16433 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
16434 break;
16435 case OPC_DPS_W_QH:
16436 check_dspr2(ctx);
16437 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
16438 break;
16439 case OPC_DPSQ_S_W_QH:
16440 check_dsp(ctx);
16441 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16442 break;
16443 case OPC_DPSQ_SA_L_PW:
16444 check_dsp(ctx);
16445 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16446 break;
16447 case OPC_DPSU_H_OBL:
16448 check_dsp(ctx);
16449 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
16450 break;
16451 case OPC_DPSU_H_OBR:
16452 check_dsp(ctx);
16453 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
16454 break;
16455 case OPC_MAQ_S_L_PWL:
16456 check_dsp(ctx);
16457 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
16458 break;
16459 case OPC_MAQ_S_L_PWR:
16460 check_dsp(ctx);
16461 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
16462 break;
16463 case OPC_MAQ_S_W_QHLL:
16464 check_dsp(ctx);
16465 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
16466 break;
16467 case OPC_MAQ_SA_W_QHLL:
16468 check_dsp(ctx);
16469 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
16470 break;
16471 case OPC_MAQ_S_W_QHLR:
16472 check_dsp(ctx);
16473 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
16474 break;
16475 case OPC_MAQ_SA_W_QHLR:
16476 check_dsp(ctx);
16477 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
16478 break;
16479 case OPC_MAQ_S_W_QHRL:
16480 check_dsp(ctx);
16481 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
16482 break;
16483 case OPC_MAQ_SA_W_QHRL:
16484 check_dsp(ctx);
16485 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
16486 break;
16487 case OPC_MAQ_S_W_QHRR:
16488 check_dsp(ctx);
16489 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
16490 break;
16491 case OPC_MAQ_SA_W_QHRR:
16492 check_dsp(ctx);
16493 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
16494 break;
16495 case OPC_MULSAQ_S_L_PW:
16496 check_dsp(ctx);
16497 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
16498 break;
16499 case OPC_MULSAQ_S_W_QH:
16500 check_dsp(ctx);
16501 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16502 break;
16505 break;
16506 #endif
16507 case OPC_ADDU_QB_DSP:
16508 switch (op2) {
16509 case OPC_MULEU_S_PH_QBL:
16510 check_dsp(ctx);
16511 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16512 break;
16513 case OPC_MULEU_S_PH_QBR:
16514 check_dsp(ctx);
16515 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16516 break;
16517 case OPC_MULQ_RS_PH:
16518 check_dsp(ctx);
16519 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16520 break;
16521 case OPC_MULEQ_S_W_PHL:
16522 check_dsp(ctx);
16523 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16524 break;
16525 case OPC_MULEQ_S_W_PHR:
16526 check_dsp(ctx);
16527 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16528 break;
16529 case OPC_MULQ_S_PH:
16530 check_dspr2(ctx);
16531 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16532 break;
16534 break;
16535 #ifdef TARGET_MIPS64
16536 case OPC_ADDU_OB_DSP:
16537 switch (op2) {
16538 case OPC_MULEQ_S_PW_QHL:
16539 check_dsp(ctx);
16540 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16541 break;
16542 case OPC_MULEQ_S_PW_QHR:
16543 check_dsp(ctx);
16544 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16545 break;
16546 case OPC_MULEU_S_QH_OBL:
16547 check_dsp(ctx);
16548 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16549 break;
16550 case OPC_MULEU_S_QH_OBR:
16551 check_dsp(ctx);
16552 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16553 break;
16554 case OPC_MULQ_RS_QH:
16555 check_dsp(ctx);
16556 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16557 break;
16559 break;
16560 #endif
16563 tcg_temp_free_i32(t0);
16564 tcg_temp_free(v1_t);
16565 tcg_temp_free(v2_t);
16567 (void)opn; /* avoid a compiler warning */
16568 MIPS_DEBUG("%s", opn);
16572 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16573 int ret, int val)
16575 const char *opn = "mipsdsp Bit/ Manipulation";
16576 int16_t imm;
16577 TCGv t0;
16578 TCGv val_t;
16580 if (ret == 0) {
16581 /* Treat as NOP. */
16582 MIPS_DEBUG("NOP");
16583 return;
16586 t0 = tcg_temp_new();
16587 val_t = tcg_temp_new();
16588 gen_load_gpr(val_t, val);
16590 switch (op1) {
16591 case OPC_ABSQ_S_PH_DSP:
16592 switch (op2) {
16593 case OPC_BITREV:
16594 check_dsp(ctx);
16595 gen_helper_bitrev(cpu_gpr[ret], val_t);
16596 break;
16597 case OPC_REPL_QB:
16598 check_dsp(ctx);
16600 target_long result;
16601 imm = (ctx->opcode >> 16) & 0xFF;
16602 result = (uint32_t)imm << 24 |
16603 (uint32_t)imm << 16 |
16604 (uint32_t)imm << 8 |
16605 (uint32_t)imm;
16606 result = (int32_t)result;
16607 tcg_gen_movi_tl(cpu_gpr[ret], result);
16609 break;
16610 case OPC_REPLV_QB:
16611 check_dsp(ctx);
16612 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16613 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16614 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16615 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16616 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16617 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16618 break;
16619 case OPC_REPL_PH:
16620 check_dsp(ctx);
16622 imm = (ctx->opcode >> 16) & 0x03FF;
16623 imm = (int16_t)(imm << 6) >> 6;
16624 tcg_gen_movi_tl(cpu_gpr[ret], \
16625 (target_long)((int32_t)imm << 16 | \
16626 (uint16_t)imm));
16628 break;
16629 case OPC_REPLV_PH:
16630 check_dsp(ctx);
16631 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16632 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16633 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16634 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16635 break;
16637 break;
16638 #ifdef TARGET_MIPS64
16639 case OPC_ABSQ_S_QH_DSP:
16640 switch (op2) {
16641 case OPC_REPL_OB:
16642 check_dsp(ctx);
16644 target_long temp;
16646 imm = (ctx->opcode >> 16) & 0xFF;
16647 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
16648 temp = (temp << 16) | temp;
16649 temp = (temp << 32) | temp;
16650 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16651 break;
16653 case OPC_REPL_PW:
16654 check_dsp(ctx);
16656 target_long temp;
16658 imm = (ctx->opcode >> 16) & 0x03FF;
16659 imm = (int16_t)(imm << 6) >> 6;
16660 temp = ((target_long)imm << 32) \
16661 | ((target_long)imm & 0xFFFFFFFF);
16662 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16663 break;
16665 case OPC_REPL_QH:
16666 check_dsp(ctx);
16668 target_long temp;
16670 imm = (ctx->opcode >> 16) & 0x03FF;
16671 imm = (int16_t)(imm << 6) >> 6;
16673 temp = ((uint64_t)(uint16_t)imm << 48) |
16674 ((uint64_t)(uint16_t)imm << 32) |
16675 ((uint64_t)(uint16_t)imm << 16) |
16676 (uint64_t)(uint16_t)imm;
16677 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16678 break;
16680 case OPC_REPLV_OB:
16681 check_dsp(ctx);
16682 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16683 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16684 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16685 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16686 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16687 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16688 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16689 break;
16690 case OPC_REPLV_PW:
16691 check_dsp(ctx);
16692 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
16693 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16694 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16695 break;
16696 case OPC_REPLV_QH:
16697 check_dsp(ctx);
16698 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16699 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16700 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16701 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16702 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16703 break;
16705 break;
16706 #endif
16708 tcg_temp_free(t0);
16709 tcg_temp_free(val_t);
16711 (void)opn; /* avoid a compiler warning */
16712 MIPS_DEBUG("%s", opn);
16715 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
16716 uint32_t op1, uint32_t op2,
16717 int ret, int v1, int v2, int check_ret)
16719 const char *opn = "mipsdsp add compare pick";
16720 TCGv t1;
16721 TCGv v1_t;
16722 TCGv v2_t;
16724 if ((ret == 0) && (check_ret == 1)) {
16725 /* Treat as NOP. */
16726 MIPS_DEBUG("NOP");
16727 return;
16730 t1 = tcg_temp_new();
16731 v1_t = tcg_temp_new();
16732 v2_t = tcg_temp_new();
16734 gen_load_gpr(v1_t, v1);
16735 gen_load_gpr(v2_t, v2);
16737 switch (op1) {
16738 case OPC_CMPU_EQ_QB_DSP:
16739 switch (op2) {
16740 case OPC_CMPU_EQ_QB:
16741 check_dsp(ctx);
16742 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
16743 break;
16744 case OPC_CMPU_LT_QB:
16745 check_dsp(ctx);
16746 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
16747 break;
16748 case OPC_CMPU_LE_QB:
16749 check_dsp(ctx);
16750 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
16751 break;
16752 case OPC_CMPGU_EQ_QB:
16753 check_dsp(ctx);
16754 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
16755 break;
16756 case OPC_CMPGU_LT_QB:
16757 check_dsp(ctx);
16758 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
16759 break;
16760 case OPC_CMPGU_LE_QB:
16761 check_dsp(ctx);
16762 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
16763 break;
16764 case OPC_CMPGDU_EQ_QB:
16765 check_dspr2(ctx);
16766 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
16767 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16768 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16769 tcg_gen_shli_tl(t1, t1, 24);
16770 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16771 break;
16772 case OPC_CMPGDU_LT_QB:
16773 check_dspr2(ctx);
16774 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
16775 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16776 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16777 tcg_gen_shli_tl(t1, t1, 24);
16778 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16779 break;
16780 case OPC_CMPGDU_LE_QB:
16781 check_dspr2(ctx);
16782 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
16783 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16784 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16785 tcg_gen_shli_tl(t1, t1, 24);
16786 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16787 break;
16788 case OPC_CMP_EQ_PH:
16789 check_dsp(ctx);
16790 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
16791 break;
16792 case OPC_CMP_LT_PH:
16793 check_dsp(ctx);
16794 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
16795 break;
16796 case OPC_CMP_LE_PH:
16797 check_dsp(ctx);
16798 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
16799 break;
16800 case OPC_PICK_QB:
16801 check_dsp(ctx);
16802 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16803 break;
16804 case OPC_PICK_PH:
16805 check_dsp(ctx);
16806 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16807 break;
16808 case OPC_PACKRL_PH:
16809 check_dsp(ctx);
16810 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
16811 break;
16813 break;
16814 #ifdef TARGET_MIPS64
16815 case OPC_CMPU_EQ_OB_DSP:
16816 switch (op2) {
16817 case OPC_CMP_EQ_PW:
16818 check_dsp(ctx);
16819 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
16820 break;
16821 case OPC_CMP_LT_PW:
16822 check_dsp(ctx);
16823 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
16824 break;
16825 case OPC_CMP_LE_PW:
16826 check_dsp(ctx);
16827 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
16828 break;
16829 case OPC_CMP_EQ_QH:
16830 check_dsp(ctx);
16831 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
16832 break;
16833 case OPC_CMP_LT_QH:
16834 check_dsp(ctx);
16835 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
16836 break;
16837 case OPC_CMP_LE_QH:
16838 check_dsp(ctx);
16839 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
16840 break;
16841 case OPC_CMPGDU_EQ_OB:
16842 check_dspr2(ctx);
16843 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16844 break;
16845 case OPC_CMPGDU_LT_OB:
16846 check_dspr2(ctx);
16847 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16848 break;
16849 case OPC_CMPGDU_LE_OB:
16850 check_dspr2(ctx);
16851 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16852 break;
16853 case OPC_CMPGU_EQ_OB:
16854 check_dsp(ctx);
16855 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
16856 break;
16857 case OPC_CMPGU_LT_OB:
16858 check_dsp(ctx);
16859 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
16860 break;
16861 case OPC_CMPGU_LE_OB:
16862 check_dsp(ctx);
16863 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
16864 break;
16865 case OPC_CMPU_EQ_OB:
16866 check_dsp(ctx);
16867 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
16868 break;
16869 case OPC_CMPU_LT_OB:
16870 check_dsp(ctx);
16871 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
16872 break;
16873 case OPC_CMPU_LE_OB:
16874 check_dsp(ctx);
16875 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
16876 break;
16877 case OPC_PACKRL_PW:
16878 check_dsp(ctx);
16879 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
16880 break;
16881 case OPC_PICK_OB:
16882 check_dsp(ctx);
16883 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16884 break;
16885 case OPC_PICK_PW:
16886 check_dsp(ctx);
16887 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16888 break;
16889 case OPC_PICK_QH:
16890 check_dsp(ctx);
16891 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16892 break;
16894 break;
16895 #endif
16898 tcg_temp_free(t1);
16899 tcg_temp_free(v1_t);
16900 tcg_temp_free(v2_t);
16902 (void)opn; /* avoid a compiler warning */
16903 MIPS_DEBUG("%s", opn);
16906 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
16907 uint32_t op1, int rt, int rs, int sa)
16909 const char *opn = "mipsdsp append/dappend";
16910 TCGv t0;
16912 check_dspr2(ctx);
16914 if (rt == 0) {
16915 /* Treat as NOP. */
16916 MIPS_DEBUG("NOP");
16917 return;
16920 t0 = tcg_temp_new();
16921 gen_load_gpr(t0, rs);
16923 switch (op1) {
16924 case OPC_APPEND_DSP:
16925 switch (MASK_APPEND(ctx->opcode)) {
16926 case OPC_APPEND:
16927 if (sa != 0) {
16928 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
16930 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16931 break;
16932 case OPC_PREPEND:
16933 if (sa != 0) {
16934 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
16935 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16936 tcg_gen_shli_tl(t0, t0, 32 - sa);
16937 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16939 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16940 break;
16941 case OPC_BALIGN:
16942 sa &= 3;
16943 if (sa != 0 && sa != 2) {
16944 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16945 tcg_gen_ext32u_tl(t0, t0);
16946 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
16947 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16949 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16950 break;
16951 default: /* Invalid */
16952 MIPS_INVAL("MASK APPEND");
16953 generate_exception(ctx, EXCP_RI);
16954 break;
16956 break;
16957 #ifdef TARGET_MIPS64
16958 case OPC_DAPPEND_DSP:
16959 switch (MASK_DAPPEND(ctx->opcode)) {
16960 case OPC_DAPPEND:
16961 if (sa != 0) {
16962 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
16964 break;
16965 case OPC_PREPENDD:
16966 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
16967 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
16968 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
16969 break;
16970 case OPC_PREPENDW:
16971 if (sa != 0) {
16972 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16973 tcg_gen_shli_tl(t0, t0, 64 - sa);
16974 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16976 break;
16977 case OPC_DBALIGN:
16978 sa &= 7;
16979 if (sa != 0 && sa != 2 && sa != 4) {
16980 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16981 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
16982 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16984 break;
16985 default: /* Invalid */
16986 MIPS_INVAL("MASK DAPPEND");
16987 generate_exception(ctx, EXCP_RI);
16988 break;
16990 break;
16991 #endif
16993 tcg_temp_free(t0);
16994 (void)opn; /* avoid a compiler warning */
16995 MIPS_DEBUG("%s", opn);
16998 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16999 int ret, int v1, int v2, int check_ret)
17002 const char *opn = "mipsdsp accumulator";
17003 TCGv t0;
17004 TCGv t1;
17005 TCGv v1_t;
17006 TCGv v2_t;
17007 int16_t imm;
17009 if ((ret == 0) && (check_ret == 1)) {
17010 /* Treat as NOP. */
17011 MIPS_DEBUG("NOP");
17012 return;
17015 t0 = tcg_temp_new();
17016 t1 = tcg_temp_new();
17017 v1_t = tcg_temp_new();
17018 v2_t = tcg_temp_new();
17020 gen_load_gpr(v1_t, v1);
17021 gen_load_gpr(v2_t, v2);
17023 switch (op1) {
17024 case OPC_EXTR_W_DSP:
17025 check_dsp(ctx);
17026 switch (op2) {
17027 case OPC_EXTR_W:
17028 tcg_gen_movi_tl(t0, v2);
17029 tcg_gen_movi_tl(t1, v1);
17030 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
17031 break;
17032 case OPC_EXTR_R_W:
17033 tcg_gen_movi_tl(t0, v2);
17034 tcg_gen_movi_tl(t1, v1);
17035 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
17036 break;
17037 case OPC_EXTR_RS_W:
17038 tcg_gen_movi_tl(t0, v2);
17039 tcg_gen_movi_tl(t1, v1);
17040 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
17041 break;
17042 case OPC_EXTR_S_H:
17043 tcg_gen_movi_tl(t0, v2);
17044 tcg_gen_movi_tl(t1, v1);
17045 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17046 break;
17047 case OPC_EXTRV_S_H:
17048 tcg_gen_movi_tl(t0, v2);
17049 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
17050 break;
17051 case OPC_EXTRV_W:
17052 tcg_gen_movi_tl(t0, v2);
17053 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17054 break;
17055 case OPC_EXTRV_R_W:
17056 tcg_gen_movi_tl(t0, v2);
17057 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17058 break;
17059 case OPC_EXTRV_RS_W:
17060 tcg_gen_movi_tl(t0, v2);
17061 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17062 break;
17063 case OPC_EXTP:
17064 tcg_gen_movi_tl(t0, v2);
17065 tcg_gen_movi_tl(t1, v1);
17066 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
17067 break;
17068 case OPC_EXTPV:
17069 tcg_gen_movi_tl(t0, v2);
17070 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
17071 break;
17072 case OPC_EXTPDP:
17073 tcg_gen_movi_tl(t0, v2);
17074 tcg_gen_movi_tl(t1, v1);
17075 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
17076 break;
17077 case OPC_EXTPDPV:
17078 tcg_gen_movi_tl(t0, v2);
17079 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
17080 break;
17081 case OPC_SHILO:
17082 imm = (ctx->opcode >> 20) & 0x3F;
17083 tcg_gen_movi_tl(t0, ret);
17084 tcg_gen_movi_tl(t1, imm);
17085 gen_helper_shilo(t0, t1, cpu_env);
17086 break;
17087 case OPC_SHILOV:
17088 tcg_gen_movi_tl(t0, ret);
17089 gen_helper_shilo(t0, v1_t, cpu_env);
17090 break;
17091 case OPC_MTHLIP:
17092 tcg_gen_movi_tl(t0, ret);
17093 gen_helper_mthlip(t0, v1_t, cpu_env);
17094 break;
17095 case OPC_WRDSP:
17096 imm = (ctx->opcode >> 11) & 0x3FF;
17097 tcg_gen_movi_tl(t0, imm);
17098 gen_helper_wrdsp(v1_t, t0, cpu_env);
17099 break;
17100 case OPC_RDDSP:
17101 imm = (ctx->opcode >> 16) & 0x03FF;
17102 tcg_gen_movi_tl(t0, imm);
17103 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
17104 break;
17106 break;
17107 #ifdef TARGET_MIPS64
17108 case OPC_DEXTR_W_DSP:
17109 check_dsp(ctx);
17110 switch (op2) {
17111 case OPC_DMTHLIP:
17112 tcg_gen_movi_tl(t0, ret);
17113 gen_helper_dmthlip(v1_t, t0, cpu_env);
17114 break;
17115 case OPC_DSHILO:
17117 int shift = (ctx->opcode >> 19) & 0x7F;
17118 int ac = (ctx->opcode >> 11) & 0x03;
17119 tcg_gen_movi_tl(t0, shift);
17120 tcg_gen_movi_tl(t1, ac);
17121 gen_helper_dshilo(t0, t1, cpu_env);
17122 break;
17124 case OPC_DSHILOV:
17126 int ac = (ctx->opcode >> 11) & 0x03;
17127 tcg_gen_movi_tl(t0, ac);
17128 gen_helper_dshilo(v1_t, t0, cpu_env);
17129 break;
17131 case OPC_DEXTP:
17132 tcg_gen_movi_tl(t0, v2);
17133 tcg_gen_movi_tl(t1, v1);
17135 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
17136 break;
17137 case OPC_DEXTPV:
17138 tcg_gen_movi_tl(t0, v2);
17139 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
17140 break;
17141 case OPC_DEXTPDP:
17142 tcg_gen_movi_tl(t0, v2);
17143 tcg_gen_movi_tl(t1, v1);
17144 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
17145 break;
17146 case OPC_DEXTPDPV:
17147 tcg_gen_movi_tl(t0, v2);
17148 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
17149 break;
17150 case OPC_DEXTR_L:
17151 tcg_gen_movi_tl(t0, v2);
17152 tcg_gen_movi_tl(t1, v1);
17153 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
17154 break;
17155 case OPC_DEXTR_R_L:
17156 tcg_gen_movi_tl(t0, v2);
17157 tcg_gen_movi_tl(t1, v1);
17158 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
17159 break;
17160 case OPC_DEXTR_RS_L:
17161 tcg_gen_movi_tl(t0, v2);
17162 tcg_gen_movi_tl(t1, v1);
17163 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
17164 break;
17165 case OPC_DEXTR_W:
17166 tcg_gen_movi_tl(t0, v2);
17167 tcg_gen_movi_tl(t1, v1);
17168 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
17169 break;
17170 case OPC_DEXTR_R_W:
17171 tcg_gen_movi_tl(t0, v2);
17172 tcg_gen_movi_tl(t1, v1);
17173 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
17174 break;
17175 case OPC_DEXTR_RS_W:
17176 tcg_gen_movi_tl(t0, v2);
17177 tcg_gen_movi_tl(t1, v1);
17178 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
17179 break;
17180 case OPC_DEXTR_S_H:
17181 tcg_gen_movi_tl(t0, v2);
17182 tcg_gen_movi_tl(t1, v1);
17183 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17184 break;
17185 case OPC_DEXTRV_S_H:
17186 tcg_gen_movi_tl(t0, v2);
17187 tcg_gen_movi_tl(t1, v1);
17188 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17189 break;
17190 case OPC_DEXTRV_L:
17191 tcg_gen_movi_tl(t0, v2);
17192 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17193 break;
17194 case OPC_DEXTRV_R_L:
17195 tcg_gen_movi_tl(t0, v2);
17196 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17197 break;
17198 case OPC_DEXTRV_RS_L:
17199 tcg_gen_movi_tl(t0, v2);
17200 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17201 break;
17202 case OPC_DEXTRV_W:
17203 tcg_gen_movi_tl(t0, v2);
17204 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17205 break;
17206 case OPC_DEXTRV_R_W:
17207 tcg_gen_movi_tl(t0, v2);
17208 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17209 break;
17210 case OPC_DEXTRV_RS_W:
17211 tcg_gen_movi_tl(t0, v2);
17212 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17213 break;
17215 break;
17216 #endif
17219 tcg_temp_free(t0);
17220 tcg_temp_free(t1);
17221 tcg_temp_free(v1_t);
17222 tcg_temp_free(v2_t);
17224 (void)opn; /* avoid a compiler warning */
17225 MIPS_DEBUG("%s", opn);
17228 /* End MIPSDSP functions. */
17230 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
17232 int rs, rt, rd, sa;
17233 uint32_t op1, op2;
17235 rs = (ctx->opcode >> 21) & 0x1f;
17236 rt = (ctx->opcode >> 16) & 0x1f;
17237 rd = (ctx->opcode >> 11) & 0x1f;
17238 sa = (ctx->opcode >> 6) & 0x1f;
17240 op1 = MASK_SPECIAL(ctx->opcode);
17241 switch (op1) {
17242 case OPC_LSA:
17243 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
17244 break;
17245 case OPC_MULT ... OPC_DIVU:
17246 op2 = MASK_R6_MULDIV(ctx->opcode);
17247 switch (op2) {
17248 case R6_OPC_MUL:
17249 case R6_OPC_MUH:
17250 case R6_OPC_MULU:
17251 case R6_OPC_MUHU:
17252 case R6_OPC_DIV:
17253 case R6_OPC_MOD:
17254 case R6_OPC_DIVU:
17255 case R6_OPC_MODU:
17256 gen_r6_muldiv(ctx, op2, rd, rs, rt);
17257 break;
17258 default:
17259 MIPS_INVAL("special_r6 muldiv");
17260 generate_exception(ctx, EXCP_RI);
17261 break;
17263 break;
17264 case OPC_SELEQZ:
17265 case OPC_SELNEZ:
17266 gen_cond_move(ctx, op1, rd, rs, rt);
17267 break;
17268 case R6_OPC_CLO:
17269 case R6_OPC_CLZ:
17270 if (rt == 0 && sa == 1) {
17271 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
17272 We need additionally to check other fields */
17273 gen_cl(ctx, op1, rd, rs);
17274 } else {
17275 generate_exception(ctx, EXCP_RI);
17277 break;
17278 case R6_OPC_SDBBP:
17279 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17280 gen_helper_do_semihosting(cpu_env);
17281 } else {
17282 if (ctx->hflags & MIPS_HFLAG_SBRI) {
17283 generate_exception(ctx, EXCP_RI);
17284 } else {
17285 generate_exception(ctx, EXCP_DBp);
17288 break;
17289 #if defined(TARGET_MIPS64)
17290 case OPC_DLSA:
17291 check_mips_64(ctx);
17292 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
17293 break;
17294 case R6_OPC_DCLO:
17295 case R6_OPC_DCLZ:
17296 if (rt == 0 && sa == 1) {
17297 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
17298 We need additionally to check other fields */
17299 check_mips_64(ctx);
17300 gen_cl(ctx, op1, rd, rs);
17301 } else {
17302 generate_exception(ctx, EXCP_RI);
17304 break;
17305 case OPC_DMULT ... OPC_DDIVU:
17306 op2 = MASK_R6_MULDIV(ctx->opcode);
17307 switch (op2) {
17308 case R6_OPC_DMUL:
17309 case R6_OPC_DMUH:
17310 case R6_OPC_DMULU:
17311 case R6_OPC_DMUHU:
17312 case R6_OPC_DDIV:
17313 case R6_OPC_DMOD:
17314 case R6_OPC_DDIVU:
17315 case R6_OPC_DMODU:
17316 check_mips_64(ctx);
17317 gen_r6_muldiv(ctx, op2, rd, rs, rt);
17318 break;
17319 default:
17320 MIPS_INVAL("special_r6 muldiv");
17321 generate_exception(ctx, EXCP_RI);
17322 break;
17324 break;
17325 #endif
17326 default: /* Invalid */
17327 MIPS_INVAL("special_r6");
17328 generate_exception(ctx, EXCP_RI);
17329 break;
17333 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
17335 int rs, rt, rd, sa;
17336 uint32_t op1;
17338 rs = (ctx->opcode >> 21) & 0x1f;
17339 rt = (ctx->opcode >> 16) & 0x1f;
17340 rd = (ctx->opcode >> 11) & 0x1f;
17341 sa = (ctx->opcode >> 6) & 0x1f;
17343 op1 = MASK_SPECIAL(ctx->opcode);
17344 switch (op1) {
17345 case OPC_MOVN: /* Conditional move */
17346 case OPC_MOVZ:
17347 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
17348 INSN_LOONGSON2E | INSN_LOONGSON2F);
17349 gen_cond_move(ctx, op1, rd, rs, rt);
17350 break;
17351 case OPC_MFHI: /* Move from HI/LO */
17352 case OPC_MFLO:
17353 gen_HILO(ctx, op1, rs & 3, rd);
17354 break;
17355 case OPC_MTHI:
17356 case OPC_MTLO: /* Move to HI/LO */
17357 gen_HILO(ctx, op1, rd & 3, rs);
17358 break;
17359 case OPC_MOVCI:
17360 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
17361 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17362 check_cp1_enabled(ctx);
17363 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
17364 (ctx->opcode >> 16) & 1);
17365 } else {
17366 generate_exception_err(ctx, EXCP_CpU, 1);
17368 break;
17369 case OPC_MULT:
17370 case OPC_MULTU:
17371 if (sa) {
17372 check_insn(ctx, INSN_VR54XX);
17373 op1 = MASK_MUL_VR54XX(ctx->opcode);
17374 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
17375 } else {
17376 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17378 break;
17379 case OPC_DIV:
17380 case OPC_DIVU:
17381 gen_muldiv(ctx, op1, 0, rs, rt);
17382 break;
17383 #if defined(TARGET_MIPS64)
17384 case OPC_DMULT ... OPC_DDIVU:
17385 check_insn(ctx, ISA_MIPS3);
17386 check_mips_64(ctx);
17387 gen_muldiv(ctx, op1, 0, rs, rt);
17388 break;
17389 #endif
17390 case OPC_JR:
17391 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17392 break;
17393 case OPC_SPIM:
17394 #ifdef MIPS_STRICT_STANDARD
17395 MIPS_INVAL("SPIM");
17396 generate_exception(ctx, EXCP_RI);
17397 #else
17398 /* Implemented as RI exception for now. */
17399 MIPS_INVAL("spim (unofficial)");
17400 generate_exception(ctx, EXCP_RI);
17401 #endif
17402 break;
17403 default: /* Invalid */
17404 MIPS_INVAL("special_legacy");
17405 generate_exception(ctx, EXCP_RI);
17406 break;
17410 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
17412 int rs, rt, rd, sa;
17413 uint32_t op1;
17415 rs = (ctx->opcode >> 21) & 0x1f;
17416 rt = (ctx->opcode >> 16) & 0x1f;
17417 rd = (ctx->opcode >> 11) & 0x1f;
17418 sa = (ctx->opcode >> 6) & 0x1f;
17420 op1 = MASK_SPECIAL(ctx->opcode);
17421 switch (op1) {
17422 case OPC_SLL: /* Shift with immediate */
17423 if (sa == 5 && rd == 0 &&
17424 rs == 0 && rt == 0) { /* PAUSE */
17425 if ((ctx->insn_flags & ISA_MIPS32R6) &&
17426 (ctx->hflags & MIPS_HFLAG_BMASK)) {
17427 MIPS_DEBUG("CTI in delay / forbidden slot");
17428 generate_exception(ctx, EXCP_RI);
17429 break;
17432 /* Fallthrough */
17433 case OPC_SRA:
17434 gen_shift_imm(ctx, op1, rd, rt, sa);
17435 break;
17436 case OPC_SRL:
17437 switch ((ctx->opcode >> 21) & 0x1f) {
17438 case 1:
17439 /* rotr is decoded as srl on non-R2 CPUs */
17440 if (ctx->insn_flags & ISA_MIPS32R2) {
17441 op1 = OPC_ROTR;
17443 /* Fallthrough */
17444 case 0:
17445 gen_shift_imm(ctx, op1, rd, rt, sa);
17446 break;
17447 default:
17448 generate_exception(ctx, EXCP_RI);
17449 break;
17451 break;
17452 case OPC_ADD ... OPC_SUBU:
17453 gen_arith(ctx, op1, rd, rs, rt);
17454 break;
17455 case OPC_SLLV: /* Shifts */
17456 case OPC_SRAV:
17457 gen_shift(ctx, op1, rd, rs, rt);
17458 break;
17459 case OPC_SRLV:
17460 switch ((ctx->opcode >> 6) & 0x1f) {
17461 case 1:
17462 /* rotrv is decoded as srlv on non-R2 CPUs */
17463 if (ctx->insn_flags & ISA_MIPS32R2) {
17464 op1 = OPC_ROTRV;
17466 /* Fallthrough */
17467 case 0:
17468 gen_shift(ctx, op1, rd, rs, rt);
17469 break;
17470 default:
17471 generate_exception(ctx, EXCP_RI);
17472 break;
17474 break;
17475 case OPC_SLT: /* Set on less than */
17476 case OPC_SLTU:
17477 gen_slt(ctx, op1, rd, rs, rt);
17478 break;
17479 case OPC_AND: /* Logic*/
17480 case OPC_OR:
17481 case OPC_NOR:
17482 case OPC_XOR:
17483 gen_logic(ctx, op1, rd, rs, rt);
17484 break;
17485 case OPC_JALR:
17486 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17487 break;
17488 case OPC_TGE ... OPC_TEQ: /* Traps */
17489 case OPC_TNE:
17490 check_insn(ctx, ISA_MIPS2);
17491 gen_trap(ctx, op1, rs, rt, -1);
17492 break;
17493 case OPC_LSA: /* OPC_PMON */
17494 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17495 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17496 decode_opc_special_r6(env, ctx);
17497 } else {
17498 /* Pmon entry point, also R4010 selsl */
17499 #ifdef MIPS_STRICT_STANDARD
17500 MIPS_INVAL("PMON / selsl");
17501 generate_exception(ctx, EXCP_RI);
17502 #else
17503 gen_helper_0e0i(pmon, sa);
17504 #endif
17506 break;
17507 case OPC_SYSCALL:
17508 generate_exception(ctx, EXCP_SYSCALL);
17509 ctx->bstate = BS_STOP;
17510 break;
17511 case OPC_BREAK:
17512 generate_exception(ctx, EXCP_BREAK);
17513 break;
17514 case OPC_SYNC:
17515 check_insn(ctx, ISA_MIPS2);
17516 /* Treat as NOP. */
17517 break;
17519 #if defined(TARGET_MIPS64)
17520 /* MIPS64 specific opcodes */
17521 case OPC_DSLL:
17522 case OPC_DSRA:
17523 case OPC_DSLL32:
17524 case OPC_DSRA32:
17525 check_insn(ctx, ISA_MIPS3);
17526 check_mips_64(ctx);
17527 gen_shift_imm(ctx, op1, rd, rt, sa);
17528 break;
17529 case OPC_DSRL:
17530 switch ((ctx->opcode >> 21) & 0x1f) {
17531 case 1:
17532 /* drotr is decoded as dsrl on non-R2 CPUs */
17533 if (ctx->insn_flags & ISA_MIPS32R2) {
17534 op1 = OPC_DROTR;
17536 /* Fallthrough */
17537 case 0:
17538 check_insn(ctx, ISA_MIPS3);
17539 check_mips_64(ctx);
17540 gen_shift_imm(ctx, op1, rd, rt, sa);
17541 break;
17542 default:
17543 generate_exception(ctx, EXCP_RI);
17544 break;
17546 break;
17547 case OPC_DSRL32:
17548 switch ((ctx->opcode >> 21) & 0x1f) {
17549 case 1:
17550 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
17551 if (ctx->insn_flags & ISA_MIPS32R2) {
17552 op1 = OPC_DROTR32;
17554 /* Fallthrough */
17555 case 0:
17556 check_insn(ctx, ISA_MIPS3);
17557 check_mips_64(ctx);
17558 gen_shift_imm(ctx, op1, rd, rt, sa);
17559 break;
17560 default:
17561 generate_exception(ctx, EXCP_RI);
17562 break;
17564 break;
17565 case OPC_DADD ... OPC_DSUBU:
17566 check_insn(ctx, ISA_MIPS3);
17567 check_mips_64(ctx);
17568 gen_arith(ctx, op1, rd, rs, rt);
17569 break;
17570 case OPC_DSLLV:
17571 case OPC_DSRAV:
17572 check_insn(ctx, ISA_MIPS3);
17573 check_mips_64(ctx);
17574 gen_shift(ctx, op1, rd, rs, rt);
17575 break;
17576 case OPC_DSRLV:
17577 switch ((ctx->opcode >> 6) & 0x1f) {
17578 case 1:
17579 /* drotrv is decoded as dsrlv on non-R2 CPUs */
17580 if (ctx->insn_flags & ISA_MIPS32R2) {
17581 op1 = OPC_DROTRV;
17583 /* Fallthrough */
17584 case 0:
17585 check_insn(ctx, ISA_MIPS3);
17586 check_mips_64(ctx);
17587 gen_shift(ctx, op1, rd, rs, rt);
17588 break;
17589 default:
17590 generate_exception(ctx, EXCP_RI);
17591 break;
17593 break;
17594 case OPC_DLSA:
17595 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17596 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17597 decode_opc_special_r6(env, ctx);
17599 break;
17600 #endif
17601 default:
17602 if (ctx->insn_flags & ISA_MIPS32R6) {
17603 decode_opc_special_r6(env, ctx);
17604 } else {
17605 decode_opc_special_legacy(env, ctx);
17610 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
17612 int rs, rt, rd;
17613 uint32_t op1;
17615 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17617 rs = (ctx->opcode >> 21) & 0x1f;
17618 rt = (ctx->opcode >> 16) & 0x1f;
17619 rd = (ctx->opcode >> 11) & 0x1f;
17621 op1 = MASK_SPECIAL2(ctx->opcode);
17622 switch (op1) {
17623 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
17624 case OPC_MSUB ... OPC_MSUBU:
17625 check_insn(ctx, ISA_MIPS32);
17626 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17627 break;
17628 case OPC_MUL:
17629 gen_arith(ctx, op1, rd, rs, rt);
17630 break;
17631 case OPC_DIV_G_2F:
17632 case OPC_DIVU_G_2F:
17633 case OPC_MULT_G_2F:
17634 case OPC_MULTU_G_2F:
17635 case OPC_MOD_G_2F:
17636 case OPC_MODU_G_2F:
17637 check_insn(ctx, INSN_LOONGSON2F);
17638 gen_loongson_integer(ctx, op1, rd, rs, rt);
17639 break;
17640 case OPC_CLO:
17641 case OPC_CLZ:
17642 check_insn(ctx, ISA_MIPS32);
17643 gen_cl(ctx, op1, rd, rs);
17644 break;
17645 case OPC_SDBBP:
17646 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17647 gen_helper_do_semihosting(cpu_env);
17648 } else {
17649 /* XXX: not clear which exception should be raised
17650 * when in debug mode...
17652 check_insn(ctx, ISA_MIPS32);
17653 generate_exception(ctx, EXCP_DBp);
17655 break;
17656 #if defined(TARGET_MIPS64)
17657 case OPC_DCLO:
17658 case OPC_DCLZ:
17659 check_insn(ctx, ISA_MIPS64);
17660 check_mips_64(ctx);
17661 gen_cl(ctx, op1, rd, rs);
17662 break;
17663 case OPC_DMULT_G_2F:
17664 case OPC_DMULTU_G_2F:
17665 case OPC_DDIV_G_2F:
17666 case OPC_DDIVU_G_2F:
17667 case OPC_DMOD_G_2F:
17668 case OPC_DMODU_G_2F:
17669 check_insn(ctx, INSN_LOONGSON2F);
17670 gen_loongson_integer(ctx, op1, rd, rs, rt);
17671 break;
17672 #endif
17673 default: /* Invalid */
17674 MIPS_INVAL("special2_legacy");
17675 generate_exception(ctx, EXCP_RI);
17676 break;
17680 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
17682 int rs, rt, rd, sa;
17683 uint32_t op1, op2;
17684 int16_t imm;
17686 rs = (ctx->opcode >> 21) & 0x1f;
17687 rt = (ctx->opcode >> 16) & 0x1f;
17688 rd = (ctx->opcode >> 11) & 0x1f;
17689 sa = (ctx->opcode >> 6) & 0x1f;
17690 imm = (int16_t)ctx->opcode >> 7;
17692 op1 = MASK_SPECIAL3(ctx->opcode);
17693 switch (op1) {
17694 case R6_OPC_PREF:
17695 if (rt >= 24) {
17696 /* hint codes 24-31 are reserved and signal RI */
17697 generate_exception(ctx, EXCP_RI);
17699 /* Treat as NOP. */
17700 break;
17701 case R6_OPC_CACHE:
17702 /* Treat as NOP. */
17703 break;
17704 case R6_OPC_SC:
17705 gen_st_cond(ctx, op1, rt, rs, imm);
17706 break;
17707 case R6_OPC_LL:
17708 gen_ld(ctx, op1, rt, rs, imm);
17709 break;
17710 case OPC_BSHFL:
17712 if (rd == 0) {
17713 /* Treat as NOP. */
17714 break;
17716 op2 = MASK_BSHFL(ctx->opcode);
17717 switch (op2) {
17718 case OPC_ALIGN ... OPC_ALIGN_END:
17719 gen_align(ctx, OPC_ALIGN, rd, rs, rt, sa & 3);
17720 break;
17721 case OPC_BITSWAP:
17722 gen_bitswap(ctx, op2, rd, rt);
17723 break;
17726 break;
17727 #if defined(TARGET_MIPS64)
17728 case R6_OPC_SCD:
17729 gen_st_cond(ctx, op1, rt, rs, imm);
17730 break;
17731 case R6_OPC_LLD:
17732 gen_ld(ctx, op1, rt, rs, imm);
17733 break;
17734 case OPC_DBSHFL:
17735 check_mips_64(ctx);
17737 if (rd == 0) {
17738 /* Treat as NOP. */
17739 break;
17741 op2 = MASK_DBSHFL(ctx->opcode);
17742 switch (op2) {
17743 case OPC_DALIGN ... OPC_DALIGN_END:
17744 gen_align(ctx, OPC_DALIGN, rd, rs, rt, sa & 7);
17745 break;
17746 case OPC_DBITSWAP:
17747 gen_bitswap(ctx, op2, rd, rt);
17748 break;
17752 break;
17753 #endif
17754 default: /* Invalid */
17755 MIPS_INVAL("special3_r6");
17756 generate_exception(ctx, EXCP_RI);
17757 break;
17761 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
17763 int rs, rt, rd;
17764 uint32_t op1, op2;
17766 rs = (ctx->opcode >> 21) & 0x1f;
17767 rt = (ctx->opcode >> 16) & 0x1f;
17768 rd = (ctx->opcode >> 11) & 0x1f;
17770 op1 = MASK_SPECIAL3(ctx->opcode);
17771 switch (op1) {
17772 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
17773 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
17774 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
17775 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
17776 * the same mask and op1. */
17777 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
17778 op2 = MASK_ADDUH_QB(ctx->opcode);
17779 switch (op2) {
17780 case OPC_ADDUH_QB:
17781 case OPC_ADDUH_R_QB:
17782 case OPC_ADDQH_PH:
17783 case OPC_ADDQH_R_PH:
17784 case OPC_ADDQH_W:
17785 case OPC_ADDQH_R_W:
17786 case OPC_SUBUH_QB:
17787 case OPC_SUBUH_R_QB:
17788 case OPC_SUBQH_PH:
17789 case OPC_SUBQH_R_PH:
17790 case OPC_SUBQH_W:
17791 case OPC_SUBQH_R_W:
17792 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17793 break;
17794 case OPC_MUL_PH:
17795 case OPC_MUL_S_PH:
17796 case OPC_MULQ_S_W:
17797 case OPC_MULQ_RS_W:
17798 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17799 break;
17800 default:
17801 MIPS_INVAL("MASK ADDUH.QB");
17802 generate_exception(ctx, EXCP_RI);
17803 break;
17805 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
17806 gen_loongson_integer(ctx, op1, rd, rs, rt);
17807 } else {
17808 generate_exception(ctx, EXCP_RI);
17810 break;
17811 case OPC_LX_DSP:
17812 op2 = MASK_LX(ctx->opcode);
17813 switch (op2) {
17814 #if defined(TARGET_MIPS64)
17815 case OPC_LDX:
17816 #endif
17817 case OPC_LBUX:
17818 case OPC_LHX:
17819 case OPC_LWX:
17820 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
17821 break;
17822 default: /* Invalid */
17823 MIPS_INVAL("MASK LX");
17824 generate_exception(ctx, EXCP_RI);
17825 break;
17827 break;
17828 case OPC_ABSQ_S_PH_DSP:
17829 op2 = MASK_ABSQ_S_PH(ctx->opcode);
17830 switch (op2) {
17831 case OPC_ABSQ_S_QB:
17832 case OPC_ABSQ_S_PH:
17833 case OPC_ABSQ_S_W:
17834 case OPC_PRECEQ_W_PHL:
17835 case OPC_PRECEQ_W_PHR:
17836 case OPC_PRECEQU_PH_QBL:
17837 case OPC_PRECEQU_PH_QBR:
17838 case OPC_PRECEQU_PH_QBLA:
17839 case OPC_PRECEQU_PH_QBRA:
17840 case OPC_PRECEU_PH_QBL:
17841 case OPC_PRECEU_PH_QBR:
17842 case OPC_PRECEU_PH_QBLA:
17843 case OPC_PRECEU_PH_QBRA:
17844 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17845 break;
17846 case OPC_BITREV:
17847 case OPC_REPL_QB:
17848 case OPC_REPLV_QB:
17849 case OPC_REPL_PH:
17850 case OPC_REPLV_PH:
17851 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17852 break;
17853 default:
17854 MIPS_INVAL("MASK ABSQ_S.PH");
17855 generate_exception(ctx, EXCP_RI);
17856 break;
17858 break;
17859 case OPC_ADDU_QB_DSP:
17860 op2 = MASK_ADDU_QB(ctx->opcode);
17861 switch (op2) {
17862 case OPC_ADDQ_PH:
17863 case OPC_ADDQ_S_PH:
17864 case OPC_ADDQ_S_W:
17865 case OPC_ADDU_QB:
17866 case OPC_ADDU_S_QB:
17867 case OPC_ADDU_PH:
17868 case OPC_ADDU_S_PH:
17869 case OPC_SUBQ_PH:
17870 case OPC_SUBQ_S_PH:
17871 case OPC_SUBQ_S_W:
17872 case OPC_SUBU_QB:
17873 case OPC_SUBU_S_QB:
17874 case OPC_SUBU_PH:
17875 case OPC_SUBU_S_PH:
17876 case OPC_ADDSC:
17877 case OPC_ADDWC:
17878 case OPC_MODSUB:
17879 case OPC_RADDU_W_QB:
17880 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17881 break;
17882 case OPC_MULEU_S_PH_QBL:
17883 case OPC_MULEU_S_PH_QBR:
17884 case OPC_MULQ_RS_PH:
17885 case OPC_MULEQ_S_W_PHL:
17886 case OPC_MULEQ_S_W_PHR:
17887 case OPC_MULQ_S_PH:
17888 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17889 break;
17890 default: /* Invalid */
17891 MIPS_INVAL("MASK ADDU.QB");
17892 generate_exception(ctx, EXCP_RI);
17893 break;
17896 break;
17897 case OPC_CMPU_EQ_QB_DSP:
17898 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
17899 switch (op2) {
17900 case OPC_PRECR_SRA_PH_W:
17901 case OPC_PRECR_SRA_R_PH_W:
17902 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17903 break;
17904 case OPC_PRECR_QB_PH:
17905 case OPC_PRECRQ_QB_PH:
17906 case OPC_PRECRQ_PH_W:
17907 case OPC_PRECRQ_RS_PH_W:
17908 case OPC_PRECRQU_S_QB_PH:
17909 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17910 break;
17911 case OPC_CMPU_EQ_QB:
17912 case OPC_CMPU_LT_QB:
17913 case OPC_CMPU_LE_QB:
17914 case OPC_CMP_EQ_PH:
17915 case OPC_CMP_LT_PH:
17916 case OPC_CMP_LE_PH:
17917 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17918 break;
17919 case OPC_CMPGU_EQ_QB:
17920 case OPC_CMPGU_LT_QB:
17921 case OPC_CMPGU_LE_QB:
17922 case OPC_CMPGDU_EQ_QB:
17923 case OPC_CMPGDU_LT_QB:
17924 case OPC_CMPGDU_LE_QB:
17925 case OPC_PICK_QB:
17926 case OPC_PICK_PH:
17927 case OPC_PACKRL_PH:
17928 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17929 break;
17930 default: /* Invalid */
17931 MIPS_INVAL("MASK CMPU.EQ.QB");
17932 generate_exception(ctx, EXCP_RI);
17933 break;
17935 break;
17936 case OPC_SHLL_QB_DSP:
17937 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17938 break;
17939 case OPC_DPA_W_PH_DSP:
17940 op2 = MASK_DPA_W_PH(ctx->opcode);
17941 switch (op2) {
17942 case OPC_DPAU_H_QBL:
17943 case OPC_DPAU_H_QBR:
17944 case OPC_DPSU_H_QBL:
17945 case OPC_DPSU_H_QBR:
17946 case OPC_DPA_W_PH:
17947 case OPC_DPAX_W_PH:
17948 case OPC_DPAQ_S_W_PH:
17949 case OPC_DPAQX_S_W_PH:
17950 case OPC_DPAQX_SA_W_PH:
17951 case OPC_DPS_W_PH:
17952 case OPC_DPSX_W_PH:
17953 case OPC_DPSQ_S_W_PH:
17954 case OPC_DPSQX_S_W_PH:
17955 case OPC_DPSQX_SA_W_PH:
17956 case OPC_MULSAQ_S_W_PH:
17957 case OPC_DPAQ_SA_L_W:
17958 case OPC_DPSQ_SA_L_W:
17959 case OPC_MAQ_S_W_PHL:
17960 case OPC_MAQ_S_W_PHR:
17961 case OPC_MAQ_SA_W_PHL:
17962 case OPC_MAQ_SA_W_PHR:
17963 case OPC_MULSA_W_PH:
17964 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17965 break;
17966 default: /* Invalid */
17967 MIPS_INVAL("MASK DPAW.PH");
17968 generate_exception(ctx, EXCP_RI);
17969 break;
17971 break;
17972 case OPC_INSV_DSP:
17973 op2 = MASK_INSV(ctx->opcode);
17974 switch (op2) {
17975 case OPC_INSV:
17976 check_dsp(ctx);
17978 TCGv t0, t1;
17980 if (rt == 0) {
17981 MIPS_DEBUG("NOP");
17982 break;
17985 t0 = tcg_temp_new();
17986 t1 = tcg_temp_new();
17988 gen_load_gpr(t0, rt);
17989 gen_load_gpr(t1, rs);
17991 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
17993 tcg_temp_free(t0);
17994 tcg_temp_free(t1);
17995 break;
17997 default: /* Invalid */
17998 MIPS_INVAL("MASK INSV");
17999 generate_exception(ctx, EXCP_RI);
18000 break;
18002 break;
18003 case OPC_APPEND_DSP:
18004 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
18005 break;
18006 case OPC_EXTR_W_DSP:
18007 op2 = MASK_EXTR_W(ctx->opcode);
18008 switch (op2) {
18009 case OPC_EXTR_W:
18010 case OPC_EXTR_R_W:
18011 case OPC_EXTR_RS_W:
18012 case OPC_EXTR_S_H:
18013 case OPC_EXTRV_S_H:
18014 case OPC_EXTRV_W:
18015 case OPC_EXTRV_R_W:
18016 case OPC_EXTRV_RS_W:
18017 case OPC_EXTP:
18018 case OPC_EXTPV:
18019 case OPC_EXTPDP:
18020 case OPC_EXTPDPV:
18021 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
18022 break;
18023 case OPC_RDDSP:
18024 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
18025 break;
18026 case OPC_SHILO:
18027 case OPC_SHILOV:
18028 case OPC_MTHLIP:
18029 case OPC_WRDSP:
18030 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
18031 break;
18032 default: /* Invalid */
18033 MIPS_INVAL("MASK EXTR.W");
18034 generate_exception(ctx, EXCP_RI);
18035 break;
18037 break;
18038 #if defined(TARGET_MIPS64)
18039 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
18040 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
18041 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
18042 check_insn(ctx, INSN_LOONGSON2E);
18043 gen_loongson_integer(ctx, op1, rd, rs, rt);
18044 break;
18045 case OPC_ABSQ_S_QH_DSP:
18046 op2 = MASK_ABSQ_S_QH(ctx->opcode);
18047 switch (op2) {
18048 case OPC_PRECEQ_L_PWL:
18049 case OPC_PRECEQ_L_PWR:
18050 case OPC_PRECEQ_PW_QHL:
18051 case OPC_PRECEQ_PW_QHR:
18052 case OPC_PRECEQ_PW_QHLA:
18053 case OPC_PRECEQ_PW_QHRA:
18054 case OPC_PRECEQU_QH_OBL:
18055 case OPC_PRECEQU_QH_OBR:
18056 case OPC_PRECEQU_QH_OBLA:
18057 case OPC_PRECEQU_QH_OBRA:
18058 case OPC_PRECEU_QH_OBL:
18059 case OPC_PRECEU_QH_OBR:
18060 case OPC_PRECEU_QH_OBLA:
18061 case OPC_PRECEU_QH_OBRA:
18062 case OPC_ABSQ_S_OB:
18063 case OPC_ABSQ_S_PW:
18064 case OPC_ABSQ_S_QH:
18065 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18066 break;
18067 case OPC_REPL_OB:
18068 case OPC_REPL_PW:
18069 case OPC_REPL_QH:
18070 case OPC_REPLV_OB:
18071 case OPC_REPLV_PW:
18072 case OPC_REPLV_QH:
18073 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
18074 break;
18075 default: /* Invalid */
18076 MIPS_INVAL("MASK ABSQ_S.QH");
18077 generate_exception(ctx, EXCP_RI);
18078 break;
18080 break;
18081 case OPC_ADDU_OB_DSP:
18082 op2 = MASK_ADDU_OB(ctx->opcode);
18083 switch (op2) {
18084 case OPC_RADDU_L_OB:
18085 case OPC_SUBQ_PW:
18086 case OPC_SUBQ_S_PW:
18087 case OPC_SUBQ_QH:
18088 case OPC_SUBQ_S_QH:
18089 case OPC_SUBU_OB:
18090 case OPC_SUBU_S_OB:
18091 case OPC_SUBU_QH:
18092 case OPC_SUBU_S_QH:
18093 case OPC_SUBUH_OB:
18094 case OPC_SUBUH_R_OB:
18095 case OPC_ADDQ_PW:
18096 case OPC_ADDQ_S_PW:
18097 case OPC_ADDQ_QH:
18098 case OPC_ADDQ_S_QH:
18099 case OPC_ADDU_OB:
18100 case OPC_ADDU_S_OB:
18101 case OPC_ADDU_QH:
18102 case OPC_ADDU_S_QH:
18103 case OPC_ADDUH_OB:
18104 case OPC_ADDUH_R_OB:
18105 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18106 break;
18107 case OPC_MULEQ_S_PW_QHL:
18108 case OPC_MULEQ_S_PW_QHR:
18109 case OPC_MULEU_S_QH_OBL:
18110 case OPC_MULEU_S_QH_OBR:
18111 case OPC_MULQ_RS_QH:
18112 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
18113 break;
18114 default: /* Invalid */
18115 MIPS_INVAL("MASK ADDU.OB");
18116 generate_exception(ctx, EXCP_RI);
18117 break;
18119 break;
18120 case OPC_CMPU_EQ_OB_DSP:
18121 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
18122 switch (op2) {
18123 case OPC_PRECR_SRA_QH_PW:
18124 case OPC_PRECR_SRA_R_QH_PW:
18125 /* Return value is rt. */
18126 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
18127 break;
18128 case OPC_PRECR_OB_QH:
18129 case OPC_PRECRQ_OB_QH:
18130 case OPC_PRECRQ_PW_L:
18131 case OPC_PRECRQ_QH_PW:
18132 case OPC_PRECRQ_RS_QH_PW:
18133 case OPC_PRECRQU_S_OB_QH:
18134 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18135 break;
18136 case OPC_CMPU_EQ_OB:
18137 case OPC_CMPU_LT_OB:
18138 case OPC_CMPU_LE_OB:
18139 case OPC_CMP_EQ_QH:
18140 case OPC_CMP_LT_QH:
18141 case OPC_CMP_LE_QH:
18142 case OPC_CMP_EQ_PW:
18143 case OPC_CMP_LT_PW:
18144 case OPC_CMP_LE_PW:
18145 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
18146 break;
18147 case OPC_CMPGDU_EQ_OB:
18148 case OPC_CMPGDU_LT_OB:
18149 case OPC_CMPGDU_LE_OB:
18150 case OPC_CMPGU_EQ_OB:
18151 case OPC_CMPGU_LT_OB:
18152 case OPC_CMPGU_LE_OB:
18153 case OPC_PACKRL_PW:
18154 case OPC_PICK_OB:
18155 case OPC_PICK_PW:
18156 case OPC_PICK_QH:
18157 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
18158 break;
18159 default: /* Invalid */
18160 MIPS_INVAL("MASK CMPU_EQ.OB");
18161 generate_exception(ctx, EXCP_RI);
18162 break;
18164 break;
18165 case OPC_DAPPEND_DSP:
18166 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
18167 break;
18168 case OPC_DEXTR_W_DSP:
18169 op2 = MASK_DEXTR_W(ctx->opcode);
18170 switch (op2) {
18171 case OPC_DEXTP:
18172 case OPC_DEXTPDP:
18173 case OPC_DEXTPDPV:
18174 case OPC_DEXTPV:
18175 case OPC_DEXTR_L:
18176 case OPC_DEXTR_R_L:
18177 case OPC_DEXTR_RS_L:
18178 case OPC_DEXTR_W:
18179 case OPC_DEXTR_R_W:
18180 case OPC_DEXTR_RS_W:
18181 case OPC_DEXTR_S_H:
18182 case OPC_DEXTRV_L:
18183 case OPC_DEXTRV_R_L:
18184 case OPC_DEXTRV_RS_L:
18185 case OPC_DEXTRV_S_H:
18186 case OPC_DEXTRV_W:
18187 case OPC_DEXTRV_R_W:
18188 case OPC_DEXTRV_RS_W:
18189 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
18190 break;
18191 case OPC_DMTHLIP:
18192 case OPC_DSHILO:
18193 case OPC_DSHILOV:
18194 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
18195 break;
18196 default: /* Invalid */
18197 MIPS_INVAL("MASK EXTR.W");
18198 generate_exception(ctx, EXCP_RI);
18199 break;
18201 break;
18202 case OPC_DPAQ_W_QH_DSP:
18203 op2 = MASK_DPAQ_W_QH(ctx->opcode);
18204 switch (op2) {
18205 case OPC_DPAU_H_OBL:
18206 case OPC_DPAU_H_OBR:
18207 case OPC_DPSU_H_OBL:
18208 case OPC_DPSU_H_OBR:
18209 case OPC_DPA_W_QH:
18210 case OPC_DPAQ_S_W_QH:
18211 case OPC_DPS_W_QH:
18212 case OPC_DPSQ_S_W_QH:
18213 case OPC_MULSAQ_S_W_QH:
18214 case OPC_DPAQ_SA_L_PW:
18215 case OPC_DPSQ_SA_L_PW:
18216 case OPC_MULSAQ_S_L_PW:
18217 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
18218 break;
18219 case OPC_MAQ_S_W_QHLL:
18220 case OPC_MAQ_S_W_QHLR:
18221 case OPC_MAQ_S_W_QHRL:
18222 case OPC_MAQ_S_W_QHRR:
18223 case OPC_MAQ_SA_W_QHLL:
18224 case OPC_MAQ_SA_W_QHLR:
18225 case OPC_MAQ_SA_W_QHRL:
18226 case OPC_MAQ_SA_W_QHRR:
18227 case OPC_MAQ_S_L_PWL:
18228 case OPC_MAQ_S_L_PWR:
18229 case OPC_DMADD:
18230 case OPC_DMADDU:
18231 case OPC_DMSUB:
18232 case OPC_DMSUBU:
18233 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
18234 break;
18235 default: /* Invalid */
18236 MIPS_INVAL("MASK DPAQ.W.QH");
18237 generate_exception(ctx, EXCP_RI);
18238 break;
18240 break;
18241 case OPC_DINSV_DSP:
18242 op2 = MASK_INSV(ctx->opcode);
18243 switch (op2) {
18244 case OPC_DINSV:
18246 TCGv t0, t1;
18248 if (rt == 0) {
18249 MIPS_DEBUG("NOP");
18250 break;
18252 check_dsp(ctx);
18254 t0 = tcg_temp_new();
18255 t1 = tcg_temp_new();
18257 gen_load_gpr(t0, rt);
18258 gen_load_gpr(t1, rs);
18260 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
18262 tcg_temp_free(t0);
18263 tcg_temp_free(t1);
18264 break;
18266 default: /* Invalid */
18267 MIPS_INVAL("MASK DINSV");
18268 generate_exception(ctx, EXCP_RI);
18269 break;
18271 break;
18272 case OPC_SHLL_OB_DSP:
18273 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
18274 break;
18275 #endif
18276 default: /* Invalid */
18277 MIPS_INVAL("special3_legacy");
18278 generate_exception(ctx, EXCP_RI);
18279 break;
18283 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
18285 int rs, rt, rd, sa;
18286 uint32_t op1, op2;
18288 rs = (ctx->opcode >> 21) & 0x1f;
18289 rt = (ctx->opcode >> 16) & 0x1f;
18290 rd = (ctx->opcode >> 11) & 0x1f;
18291 sa = (ctx->opcode >> 6) & 0x1f;
18293 op1 = MASK_SPECIAL3(ctx->opcode);
18294 switch (op1) {
18295 case OPC_EXT:
18296 case OPC_INS:
18297 check_insn(ctx, ISA_MIPS32R2);
18298 gen_bitops(ctx, op1, rt, rs, sa, rd);
18299 break;
18300 case OPC_BSHFL:
18301 op2 = MASK_BSHFL(ctx->opcode);
18302 switch (op2) {
18303 case OPC_ALIGN ... OPC_ALIGN_END:
18304 case OPC_BITSWAP:
18305 check_insn(ctx, ISA_MIPS32R6);
18306 decode_opc_special3_r6(env, ctx);
18307 break;
18308 default:
18309 check_insn(ctx, ISA_MIPS32R2);
18310 gen_bshfl(ctx, op2, rt, rd);
18311 break;
18313 break;
18314 #if defined(TARGET_MIPS64)
18315 case OPC_DEXTM ... OPC_DEXT:
18316 case OPC_DINSM ... OPC_DINS:
18317 check_insn(ctx, ISA_MIPS64R2);
18318 check_mips_64(ctx);
18319 gen_bitops(ctx, op1, rt, rs, sa, rd);
18320 break;
18321 case OPC_DBSHFL:
18322 op2 = MASK_DBSHFL(ctx->opcode);
18323 switch (op2) {
18324 case OPC_DALIGN ... OPC_DALIGN_END:
18325 case OPC_DBITSWAP:
18326 check_insn(ctx, ISA_MIPS32R6);
18327 decode_opc_special3_r6(env, ctx);
18328 break;
18329 default:
18330 check_insn(ctx, ISA_MIPS64R2);
18331 check_mips_64(ctx);
18332 op2 = MASK_DBSHFL(ctx->opcode);
18333 gen_bshfl(ctx, op2, rt, rd);
18334 break;
18336 break;
18337 #endif
18338 case OPC_RDHWR:
18339 gen_rdhwr(ctx, rt, rd);
18340 break;
18341 case OPC_FORK:
18342 check_insn(ctx, ASE_MT);
18344 TCGv t0 = tcg_temp_new();
18345 TCGv t1 = tcg_temp_new();
18347 gen_load_gpr(t0, rt);
18348 gen_load_gpr(t1, rs);
18349 gen_helper_fork(t0, t1);
18350 tcg_temp_free(t0);
18351 tcg_temp_free(t1);
18353 break;
18354 case OPC_YIELD:
18355 check_insn(ctx, ASE_MT);
18357 TCGv t0 = tcg_temp_new();
18359 save_cpu_state(ctx, 1);
18360 gen_load_gpr(t0, rs);
18361 gen_helper_yield(t0, cpu_env, t0);
18362 gen_store_gpr(t0, rd);
18363 tcg_temp_free(t0);
18365 break;
18366 default:
18367 if (ctx->insn_flags & ISA_MIPS32R6) {
18368 decode_opc_special3_r6(env, ctx);
18369 } else {
18370 decode_opc_special3_legacy(env, ctx);
18375 /* MIPS SIMD Architecture (MSA) */
18376 static inline int check_msa_access(DisasContext *ctx)
18378 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
18379 !(ctx->hflags & MIPS_HFLAG_F64))) {
18380 generate_exception(ctx, EXCP_RI);
18381 return 0;
18384 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
18385 if (ctx->insn_flags & ASE_MSA) {
18386 generate_exception(ctx, EXCP_MSADIS);
18387 return 0;
18388 } else {
18389 generate_exception(ctx, EXCP_RI);
18390 return 0;
18393 return 1;
18396 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
18398 /* generates tcg ops to check if any element is 0 */
18399 /* Note this function only works with MSA_WRLEN = 128 */
18400 uint64_t eval_zero_or_big = 0;
18401 uint64_t eval_big = 0;
18402 TCGv_i64 t0 = tcg_temp_new_i64();
18403 TCGv_i64 t1 = tcg_temp_new_i64();
18404 switch (df) {
18405 case DF_BYTE:
18406 eval_zero_or_big = 0x0101010101010101ULL;
18407 eval_big = 0x8080808080808080ULL;
18408 break;
18409 case DF_HALF:
18410 eval_zero_or_big = 0x0001000100010001ULL;
18411 eval_big = 0x8000800080008000ULL;
18412 break;
18413 case DF_WORD:
18414 eval_zero_or_big = 0x0000000100000001ULL;
18415 eval_big = 0x8000000080000000ULL;
18416 break;
18417 case DF_DOUBLE:
18418 eval_zero_or_big = 0x0000000000000001ULL;
18419 eval_big = 0x8000000000000000ULL;
18420 break;
18422 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
18423 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
18424 tcg_gen_andi_i64(t0, t0, eval_big);
18425 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
18426 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
18427 tcg_gen_andi_i64(t1, t1, eval_big);
18428 tcg_gen_or_i64(t0, t0, t1);
18429 /* if all bits are zero then all elements are not zero */
18430 /* if some bit is non-zero then some element is zero */
18431 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
18432 tcg_gen_trunc_i64_tl(tresult, t0);
18433 tcg_temp_free_i64(t0);
18434 tcg_temp_free_i64(t1);
18437 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
18439 uint8_t df = (ctx->opcode >> 21) & 0x3;
18440 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18441 int64_t s16 = (int16_t)ctx->opcode;
18443 check_msa_access(ctx);
18445 if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
18446 MIPS_DEBUG("CTI in delay / forbidden slot");
18447 generate_exception(ctx, EXCP_RI);
18448 return;
18450 switch (op1) {
18451 case OPC_BZ_V:
18452 case OPC_BNZ_V:
18454 TCGv_i64 t0 = tcg_temp_new_i64();
18455 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
18456 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
18457 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
18458 tcg_gen_trunc_i64_tl(bcond, t0);
18459 tcg_temp_free_i64(t0);
18461 break;
18462 case OPC_BZ_B:
18463 case OPC_BZ_H:
18464 case OPC_BZ_W:
18465 case OPC_BZ_D:
18466 gen_check_zero_element(bcond, df, wt);
18467 break;
18468 case OPC_BNZ_B:
18469 case OPC_BNZ_H:
18470 case OPC_BNZ_W:
18471 case OPC_BNZ_D:
18472 gen_check_zero_element(bcond, df, wt);
18473 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
18474 break;
18477 ctx->btarget = ctx->pc + (s16 << 2) + 4;
18479 ctx->hflags |= MIPS_HFLAG_BC;
18480 ctx->hflags |= MIPS_HFLAG_BDS32;
18483 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
18485 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
18486 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
18487 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18488 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18490 TCGv_i32 twd = tcg_const_i32(wd);
18491 TCGv_i32 tws = tcg_const_i32(ws);
18492 TCGv_i32 ti8 = tcg_const_i32(i8);
18494 switch (MASK_MSA_I8(ctx->opcode)) {
18495 case OPC_ANDI_B:
18496 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
18497 break;
18498 case OPC_ORI_B:
18499 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
18500 break;
18501 case OPC_NORI_B:
18502 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
18503 break;
18504 case OPC_XORI_B:
18505 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
18506 break;
18507 case OPC_BMNZI_B:
18508 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
18509 break;
18510 case OPC_BMZI_B:
18511 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
18512 break;
18513 case OPC_BSELI_B:
18514 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
18515 break;
18516 case OPC_SHF_B:
18517 case OPC_SHF_H:
18518 case OPC_SHF_W:
18520 uint8_t df = (ctx->opcode >> 24) & 0x3;
18521 if (df == DF_DOUBLE) {
18522 generate_exception(ctx, EXCP_RI);
18523 } else {
18524 TCGv_i32 tdf = tcg_const_i32(df);
18525 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
18526 tcg_temp_free_i32(tdf);
18529 break;
18530 default:
18531 MIPS_INVAL("MSA instruction");
18532 generate_exception(ctx, EXCP_RI);
18533 break;
18536 tcg_temp_free_i32(twd);
18537 tcg_temp_free_i32(tws);
18538 tcg_temp_free_i32(ti8);
18541 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
18543 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18544 uint8_t df = (ctx->opcode >> 21) & 0x3;
18545 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
18546 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
18547 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18548 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18550 TCGv_i32 tdf = tcg_const_i32(df);
18551 TCGv_i32 twd = tcg_const_i32(wd);
18552 TCGv_i32 tws = tcg_const_i32(ws);
18553 TCGv_i32 timm = tcg_temp_new_i32();
18554 tcg_gen_movi_i32(timm, u5);
18556 switch (MASK_MSA_I5(ctx->opcode)) {
18557 case OPC_ADDVI_df:
18558 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
18559 break;
18560 case OPC_SUBVI_df:
18561 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
18562 break;
18563 case OPC_MAXI_S_df:
18564 tcg_gen_movi_i32(timm, s5);
18565 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
18566 break;
18567 case OPC_MAXI_U_df:
18568 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
18569 break;
18570 case OPC_MINI_S_df:
18571 tcg_gen_movi_i32(timm, s5);
18572 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
18573 break;
18574 case OPC_MINI_U_df:
18575 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
18576 break;
18577 case OPC_CEQI_df:
18578 tcg_gen_movi_i32(timm, s5);
18579 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
18580 break;
18581 case OPC_CLTI_S_df:
18582 tcg_gen_movi_i32(timm, s5);
18583 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
18584 break;
18585 case OPC_CLTI_U_df:
18586 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
18587 break;
18588 case OPC_CLEI_S_df:
18589 tcg_gen_movi_i32(timm, s5);
18590 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
18591 break;
18592 case OPC_CLEI_U_df:
18593 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
18594 break;
18595 case OPC_LDI_df:
18597 int32_t s10 = sextract32(ctx->opcode, 11, 10);
18598 tcg_gen_movi_i32(timm, s10);
18599 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
18601 break;
18602 default:
18603 MIPS_INVAL("MSA instruction");
18604 generate_exception(ctx, EXCP_RI);
18605 break;
18608 tcg_temp_free_i32(tdf);
18609 tcg_temp_free_i32(twd);
18610 tcg_temp_free_i32(tws);
18611 tcg_temp_free_i32(timm);
18614 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
18616 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18617 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
18618 uint32_t df = 0, m = 0;
18619 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18620 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18622 TCGv_i32 tdf;
18623 TCGv_i32 tm;
18624 TCGv_i32 twd;
18625 TCGv_i32 tws;
18627 if ((dfm & 0x40) == 0x00) {
18628 m = dfm & 0x3f;
18629 df = DF_DOUBLE;
18630 } else if ((dfm & 0x60) == 0x40) {
18631 m = dfm & 0x1f;
18632 df = DF_WORD;
18633 } else if ((dfm & 0x70) == 0x60) {
18634 m = dfm & 0x0f;
18635 df = DF_HALF;
18636 } else if ((dfm & 0x78) == 0x70) {
18637 m = dfm & 0x7;
18638 df = DF_BYTE;
18639 } else {
18640 generate_exception(ctx, EXCP_RI);
18641 return;
18644 tdf = tcg_const_i32(df);
18645 tm = tcg_const_i32(m);
18646 twd = tcg_const_i32(wd);
18647 tws = tcg_const_i32(ws);
18649 switch (MASK_MSA_BIT(ctx->opcode)) {
18650 case OPC_SLLI_df:
18651 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
18652 break;
18653 case OPC_SRAI_df:
18654 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
18655 break;
18656 case OPC_SRLI_df:
18657 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
18658 break;
18659 case OPC_BCLRI_df:
18660 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
18661 break;
18662 case OPC_BSETI_df:
18663 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
18664 break;
18665 case OPC_BNEGI_df:
18666 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
18667 break;
18668 case OPC_BINSLI_df:
18669 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
18670 break;
18671 case OPC_BINSRI_df:
18672 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
18673 break;
18674 case OPC_SAT_S_df:
18675 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
18676 break;
18677 case OPC_SAT_U_df:
18678 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
18679 break;
18680 case OPC_SRARI_df:
18681 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
18682 break;
18683 case OPC_SRLRI_df:
18684 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
18685 break;
18686 default:
18687 MIPS_INVAL("MSA instruction");
18688 generate_exception(ctx, EXCP_RI);
18689 break;
18692 tcg_temp_free_i32(tdf);
18693 tcg_temp_free_i32(tm);
18694 tcg_temp_free_i32(twd);
18695 tcg_temp_free_i32(tws);
18698 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
18700 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18701 uint8_t df = (ctx->opcode >> 21) & 0x3;
18702 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18703 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18704 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18706 TCGv_i32 tdf = tcg_const_i32(df);
18707 TCGv_i32 twd = tcg_const_i32(wd);
18708 TCGv_i32 tws = tcg_const_i32(ws);
18709 TCGv_i32 twt = tcg_const_i32(wt);
18711 switch (MASK_MSA_3R(ctx->opcode)) {
18712 case OPC_SLL_df:
18713 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
18714 break;
18715 case OPC_ADDV_df:
18716 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
18717 break;
18718 case OPC_CEQ_df:
18719 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
18720 break;
18721 case OPC_ADD_A_df:
18722 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
18723 break;
18724 case OPC_SUBS_S_df:
18725 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
18726 break;
18727 case OPC_MULV_df:
18728 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
18729 break;
18730 case OPC_SLD_df:
18731 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
18732 break;
18733 case OPC_VSHF_df:
18734 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
18735 break;
18736 case OPC_SRA_df:
18737 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
18738 break;
18739 case OPC_SUBV_df:
18740 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
18741 break;
18742 case OPC_ADDS_A_df:
18743 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
18744 break;
18745 case OPC_SUBS_U_df:
18746 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
18747 break;
18748 case OPC_MADDV_df:
18749 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
18750 break;
18751 case OPC_SPLAT_df:
18752 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
18753 break;
18754 case OPC_SRAR_df:
18755 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
18756 break;
18757 case OPC_SRL_df:
18758 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
18759 break;
18760 case OPC_MAX_S_df:
18761 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
18762 break;
18763 case OPC_CLT_S_df:
18764 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
18765 break;
18766 case OPC_ADDS_S_df:
18767 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
18768 break;
18769 case OPC_SUBSUS_U_df:
18770 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
18771 break;
18772 case OPC_MSUBV_df:
18773 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
18774 break;
18775 case OPC_PCKEV_df:
18776 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
18777 break;
18778 case OPC_SRLR_df:
18779 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
18780 break;
18781 case OPC_BCLR_df:
18782 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
18783 break;
18784 case OPC_MAX_U_df:
18785 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
18786 break;
18787 case OPC_CLT_U_df:
18788 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
18789 break;
18790 case OPC_ADDS_U_df:
18791 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
18792 break;
18793 case OPC_SUBSUU_S_df:
18794 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
18795 break;
18796 case OPC_PCKOD_df:
18797 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
18798 break;
18799 case OPC_BSET_df:
18800 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
18801 break;
18802 case OPC_MIN_S_df:
18803 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
18804 break;
18805 case OPC_CLE_S_df:
18806 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
18807 break;
18808 case OPC_AVE_S_df:
18809 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
18810 break;
18811 case OPC_ASUB_S_df:
18812 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
18813 break;
18814 case OPC_DIV_S_df:
18815 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
18816 break;
18817 case OPC_ILVL_df:
18818 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
18819 break;
18820 case OPC_BNEG_df:
18821 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
18822 break;
18823 case OPC_MIN_U_df:
18824 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
18825 break;
18826 case OPC_CLE_U_df:
18827 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
18828 break;
18829 case OPC_AVE_U_df:
18830 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
18831 break;
18832 case OPC_ASUB_U_df:
18833 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
18834 break;
18835 case OPC_DIV_U_df:
18836 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
18837 break;
18838 case OPC_ILVR_df:
18839 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
18840 break;
18841 case OPC_BINSL_df:
18842 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
18843 break;
18844 case OPC_MAX_A_df:
18845 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
18846 break;
18847 case OPC_AVER_S_df:
18848 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
18849 break;
18850 case OPC_MOD_S_df:
18851 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
18852 break;
18853 case OPC_ILVEV_df:
18854 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
18855 break;
18856 case OPC_BINSR_df:
18857 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
18858 break;
18859 case OPC_MIN_A_df:
18860 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
18861 break;
18862 case OPC_AVER_U_df:
18863 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
18864 break;
18865 case OPC_MOD_U_df:
18866 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
18867 break;
18868 case OPC_ILVOD_df:
18869 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
18870 break;
18872 case OPC_DOTP_S_df:
18873 case OPC_DOTP_U_df:
18874 case OPC_DPADD_S_df:
18875 case OPC_DPADD_U_df:
18876 case OPC_DPSUB_S_df:
18877 case OPC_HADD_S_df:
18878 case OPC_DPSUB_U_df:
18879 case OPC_HADD_U_df:
18880 case OPC_HSUB_S_df:
18881 case OPC_HSUB_U_df:
18882 if (df == DF_BYTE) {
18883 generate_exception(ctx, EXCP_RI);
18885 switch (MASK_MSA_3R(ctx->opcode)) {
18886 case OPC_DOTP_S_df:
18887 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
18888 break;
18889 case OPC_DOTP_U_df:
18890 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
18891 break;
18892 case OPC_DPADD_S_df:
18893 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
18894 break;
18895 case OPC_DPADD_U_df:
18896 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
18897 break;
18898 case OPC_DPSUB_S_df:
18899 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
18900 break;
18901 case OPC_HADD_S_df:
18902 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
18903 break;
18904 case OPC_DPSUB_U_df:
18905 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
18906 break;
18907 case OPC_HADD_U_df:
18908 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
18909 break;
18910 case OPC_HSUB_S_df:
18911 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
18912 break;
18913 case OPC_HSUB_U_df:
18914 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
18915 break;
18917 break;
18918 default:
18919 MIPS_INVAL("MSA instruction");
18920 generate_exception(ctx, EXCP_RI);
18921 break;
18923 tcg_temp_free_i32(twd);
18924 tcg_temp_free_i32(tws);
18925 tcg_temp_free_i32(twt);
18926 tcg_temp_free_i32(tdf);
18929 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
18931 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
18932 uint8_t source = (ctx->opcode >> 11) & 0x1f;
18933 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
18934 TCGv telm = tcg_temp_new();
18935 TCGv_i32 tsr = tcg_const_i32(source);
18936 TCGv_i32 tdt = tcg_const_i32(dest);
18938 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
18939 case OPC_CTCMSA:
18940 gen_load_gpr(telm, source);
18941 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
18942 break;
18943 case OPC_CFCMSA:
18944 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
18945 gen_store_gpr(telm, dest);
18946 break;
18947 case OPC_MOVE_V:
18948 gen_helper_msa_move_v(cpu_env, tdt, tsr);
18949 break;
18950 default:
18951 MIPS_INVAL("MSA instruction");
18952 generate_exception(ctx, EXCP_RI);
18953 break;
18956 tcg_temp_free(telm);
18957 tcg_temp_free_i32(tdt);
18958 tcg_temp_free_i32(tsr);
18961 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
18962 uint32_t n)
18964 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18965 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18966 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18968 TCGv_i32 tws = tcg_const_i32(ws);
18969 TCGv_i32 twd = tcg_const_i32(wd);
18970 TCGv_i32 tn = tcg_const_i32(n);
18971 TCGv_i32 tdf = tcg_const_i32(df);
18973 switch (MASK_MSA_ELM(ctx->opcode)) {
18974 case OPC_SLDI_df:
18975 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
18976 break;
18977 case OPC_SPLATI_df:
18978 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
18979 break;
18980 case OPC_INSVE_df:
18981 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
18982 break;
18983 case OPC_COPY_S_df:
18984 case OPC_COPY_U_df:
18985 case OPC_INSERT_df:
18986 #if !defined(TARGET_MIPS64)
18987 /* Double format valid only for MIPS64 */
18988 if (df == DF_DOUBLE) {
18989 generate_exception(ctx, EXCP_RI);
18990 break;
18992 #endif
18993 switch (MASK_MSA_ELM(ctx->opcode)) {
18994 case OPC_COPY_S_df:
18995 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
18996 break;
18997 case OPC_COPY_U_df:
18998 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
18999 break;
19000 case OPC_INSERT_df:
19001 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
19002 break;
19004 break;
19005 default:
19006 MIPS_INVAL("MSA instruction");
19007 generate_exception(ctx, EXCP_RI);
19009 tcg_temp_free_i32(twd);
19010 tcg_temp_free_i32(tws);
19011 tcg_temp_free_i32(tn);
19012 tcg_temp_free_i32(tdf);
19015 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
19017 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
19018 uint32_t df = 0, n = 0;
19020 if ((dfn & 0x30) == 0x00) {
19021 n = dfn & 0x0f;
19022 df = DF_BYTE;
19023 } else if ((dfn & 0x38) == 0x20) {
19024 n = dfn & 0x07;
19025 df = DF_HALF;
19026 } else if ((dfn & 0x3c) == 0x30) {
19027 n = dfn & 0x03;
19028 df = DF_WORD;
19029 } else if ((dfn & 0x3e) == 0x38) {
19030 n = dfn & 0x01;
19031 df = DF_DOUBLE;
19032 } else if (dfn == 0x3E) {
19033 /* CTCMSA, CFCMSA, MOVE.V */
19034 gen_msa_elm_3e(env, ctx);
19035 return;
19036 } else {
19037 generate_exception(ctx, EXCP_RI);
19038 return;
19041 gen_msa_elm_df(env, ctx, df, n);
19044 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
19046 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
19047 uint8_t df = (ctx->opcode >> 21) & 0x1;
19048 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19049 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19050 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19052 TCGv_i32 twd = tcg_const_i32(wd);
19053 TCGv_i32 tws = tcg_const_i32(ws);
19054 TCGv_i32 twt = tcg_const_i32(wt);
19055 TCGv_i32 tdf = tcg_temp_new_i32();
19057 /* adjust df value for floating-point instruction */
19058 tcg_gen_movi_i32(tdf, df + 2);
19060 switch (MASK_MSA_3RF(ctx->opcode)) {
19061 case OPC_FCAF_df:
19062 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
19063 break;
19064 case OPC_FADD_df:
19065 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
19066 break;
19067 case OPC_FCUN_df:
19068 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
19069 break;
19070 case OPC_FSUB_df:
19071 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
19072 break;
19073 case OPC_FCOR_df:
19074 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
19075 break;
19076 case OPC_FCEQ_df:
19077 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
19078 break;
19079 case OPC_FMUL_df:
19080 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
19081 break;
19082 case OPC_FCUNE_df:
19083 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
19084 break;
19085 case OPC_FCUEQ_df:
19086 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
19087 break;
19088 case OPC_FDIV_df:
19089 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
19090 break;
19091 case OPC_FCNE_df:
19092 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
19093 break;
19094 case OPC_FCLT_df:
19095 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
19096 break;
19097 case OPC_FMADD_df:
19098 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
19099 break;
19100 case OPC_MUL_Q_df:
19101 tcg_gen_movi_i32(tdf, df + 1);
19102 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
19103 break;
19104 case OPC_FCULT_df:
19105 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
19106 break;
19107 case OPC_FMSUB_df:
19108 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
19109 break;
19110 case OPC_MADD_Q_df:
19111 tcg_gen_movi_i32(tdf, df + 1);
19112 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
19113 break;
19114 case OPC_FCLE_df:
19115 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
19116 break;
19117 case OPC_MSUB_Q_df:
19118 tcg_gen_movi_i32(tdf, df + 1);
19119 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
19120 break;
19121 case OPC_FCULE_df:
19122 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
19123 break;
19124 case OPC_FEXP2_df:
19125 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
19126 break;
19127 case OPC_FSAF_df:
19128 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
19129 break;
19130 case OPC_FEXDO_df:
19131 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
19132 break;
19133 case OPC_FSUN_df:
19134 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
19135 break;
19136 case OPC_FSOR_df:
19137 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
19138 break;
19139 case OPC_FSEQ_df:
19140 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
19141 break;
19142 case OPC_FTQ_df:
19143 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
19144 break;
19145 case OPC_FSUNE_df:
19146 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
19147 break;
19148 case OPC_FSUEQ_df:
19149 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
19150 break;
19151 case OPC_FSNE_df:
19152 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
19153 break;
19154 case OPC_FSLT_df:
19155 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
19156 break;
19157 case OPC_FMIN_df:
19158 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
19159 break;
19160 case OPC_MULR_Q_df:
19161 tcg_gen_movi_i32(tdf, df + 1);
19162 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
19163 break;
19164 case OPC_FSULT_df:
19165 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
19166 break;
19167 case OPC_FMIN_A_df:
19168 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
19169 break;
19170 case OPC_MADDR_Q_df:
19171 tcg_gen_movi_i32(tdf, df + 1);
19172 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
19173 break;
19174 case OPC_FSLE_df:
19175 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
19176 break;
19177 case OPC_FMAX_df:
19178 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
19179 break;
19180 case OPC_MSUBR_Q_df:
19181 tcg_gen_movi_i32(tdf, df + 1);
19182 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
19183 break;
19184 case OPC_FSULE_df:
19185 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
19186 break;
19187 case OPC_FMAX_A_df:
19188 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
19189 break;
19190 default:
19191 MIPS_INVAL("MSA instruction");
19192 generate_exception(ctx, EXCP_RI);
19193 break;
19196 tcg_temp_free_i32(twd);
19197 tcg_temp_free_i32(tws);
19198 tcg_temp_free_i32(twt);
19199 tcg_temp_free_i32(tdf);
19202 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
19204 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
19205 (op & (0x7 << 18)))
19206 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19207 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19208 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19209 uint8_t df = (ctx->opcode >> 16) & 0x3;
19210 TCGv_i32 twd = tcg_const_i32(wd);
19211 TCGv_i32 tws = tcg_const_i32(ws);
19212 TCGv_i32 twt = tcg_const_i32(wt);
19213 TCGv_i32 tdf = tcg_const_i32(df);
19215 switch (MASK_MSA_2R(ctx->opcode)) {
19216 case OPC_FILL_df:
19217 #if !defined(TARGET_MIPS64)
19218 /* Double format valid only for MIPS64 */
19219 if (df == DF_DOUBLE) {
19220 generate_exception(ctx, EXCP_RI);
19221 break;
19223 #endif
19224 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
19225 break;
19226 case OPC_PCNT_df:
19227 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
19228 break;
19229 case OPC_NLOC_df:
19230 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
19231 break;
19232 case OPC_NLZC_df:
19233 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
19234 break;
19235 default:
19236 MIPS_INVAL("MSA instruction");
19237 generate_exception(ctx, EXCP_RI);
19238 break;
19241 tcg_temp_free_i32(twd);
19242 tcg_temp_free_i32(tws);
19243 tcg_temp_free_i32(twt);
19244 tcg_temp_free_i32(tdf);
19247 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
19249 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
19250 (op & (0xf << 17)))
19251 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19252 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19253 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19254 uint8_t df = (ctx->opcode >> 16) & 0x1;
19255 TCGv_i32 twd = tcg_const_i32(wd);
19256 TCGv_i32 tws = tcg_const_i32(ws);
19257 TCGv_i32 twt = tcg_const_i32(wt);
19258 /* adjust df value for floating-point instruction */
19259 TCGv_i32 tdf = tcg_const_i32(df + 2);
19261 switch (MASK_MSA_2RF(ctx->opcode)) {
19262 case OPC_FCLASS_df:
19263 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
19264 break;
19265 case OPC_FTRUNC_S_df:
19266 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
19267 break;
19268 case OPC_FTRUNC_U_df:
19269 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
19270 break;
19271 case OPC_FSQRT_df:
19272 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
19273 break;
19274 case OPC_FRSQRT_df:
19275 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
19276 break;
19277 case OPC_FRCP_df:
19278 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
19279 break;
19280 case OPC_FRINT_df:
19281 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
19282 break;
19283 case OPC_FLOG2_df:
19284 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
19285 break;
19286 case OPC_FEXUPL_df:
19287 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
19288 break;
19289 case OPC_FEXUPR_df:
19290 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
19291 break;
19292 case OPC_FFQL_df:
19293 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
19294 break;
19295 case OPC_FFQR_df:
19296 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
19297 break;
19298 case OPC_FTINT_S_df:
19299 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
19300 break;
19301 case OPC_FTINT_U_df:
19302 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
19303 break;
19304 case OPC_FFINT_S_df:
19305 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
19306 break;
19307 case OPC_FFINT_U_df:
19308 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
19309 break;
19312 tcg_temp_free_i32(twd);
19313 tcg_temp_free_i32(tws);
19314 tcg_temp_free_i32(twt);
19315 tcg_temp_free_i32(tdf);
19318 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
19320 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
19321 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19322 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19323 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19324 TCGv_i32 twd = tcg_const_i32(wd);
19325 TCGv_i32 tws = tcg_const_i32(ws);
19326 TCGv_i32 twt = tcg_const_i32(wt);
19328 switch (MASK_MSA_VEC(ctx->opcode)) {
19329 case OPC_AND_V:
19330 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
19331 break;
19332 case OPC_OR_V:
19333 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
19334 break;
19335 case OPC_NOR_V:
19336 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
19337 break;
19338 case OPC_XOR_V:
19339 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
19340 break;
19341 case OPC_BMNZ_V:
19342 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
19343 break;
19344 case OPC_BMZ_V:
19345 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
19346 break;
19347 case OPC_BSEL_V:
19348 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
19349 break;
19350 default:
19351 MIPS_INVAL("MSA instruction");
19352 generate_exception(ctx, EXCP_RI);
19353 break;
19356 tcg_temp_free_i32(twd);
19357 tcg_temp_free_i32(tws);
19358 tcg_temp_free_i32(twt);
19361 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
19363 switch (MASK_MSA_VEC(ctx->opcode)) {
19364 case OPC_AND_V:
19365 case OPC_OR_V:
19366 case OPC_NOR_V:
19367 case OPC_XOR_V:
19368 case OPC_BMNZ_V:
19369 case OPC_BMZ_V:
19370 case OPC_BSEL_V:
19371 gen_msa_vec_v(env, ctx);
19372 break;
19373 case OPC_MSA_2R:
19374 gen_msa_2r(env, ctx);
19375 break;
19376 case OPC_MSA_2RF:
19377 gen_msa_2rf(env, ctx);
19378 break;
19379 default:
19380 MIPS_INVAL("MSA instruction");
19381 generate_exception(ctx, EXCP_RI);
19382 break;
19386 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
19388 uint32_t opcode = ctx->opcode;
19389 check_insn(ctx, ASE_MSA);
19390 check_msa_access(ctx);
19392 switch (MASK_MSA_MINOR(opcode)) {
19393 case OPC_MSA_I8_00:
19394 case OPC_MSA_I8_01:
19395 case OPC_MSA_I8_02:
19396 gen_msa_i8(env, ctx);
19397 break;
19398 case OPC_MSA_I5_06:
19399 case OPC_MSA_I5_07:
19400 gen_msa_i5(env, ctx);
19401 break;
19402 case OPC_MSA_BIT_09:
19403 case OPC_MSA_BIT_0A:
19404 gen_msa_bit(env, ctx);
19405 break;
19406 case OPC_MSA_3R_0D:
19407 case OPC_MSA_3R_0E:
19408 case OPC_MSA_3R_0F:
19409 case OPC_MSA_3R_10:
19410 case OPC_MSA_3R_11:
19411 case OPC_MSA_3R_12:
19412 case OPC_MSA_3R_13:
19413 case OPC_MSA_3R_14:
19414 case OPC_MSA_3R_15:
19415 gen_msa_3r(env, ctx);
19416 break;
19417 case OPC_MSA_ELM:
19418 gen_msa_elm(env, ctx);
19419 break;
19420 case OPC_MSA_3RF_1A:
19421 case OPC_MSA_3RF_1B:
19422 case OPC_MSA_3RF_1C:
19423 gen_msa_3rf(env, ctx);
19424 break;
19425 case OPC_MSA_VEC:
19426 gen_msa_vec(env, ctx);
19427 break;
19428 case OPC_LD_B:
19429 case OPC_LD_H:
19430 case OPC_LD_W:
19431 case OPC_LD_D:
19432 case OPC_ST_B:
19433 case OPC_ST_H:
19434 case OPC_ST_W:
19435 case OPC_ST_D:
19437 int32_t s10 = sextract32(ctx->opcode, 16, 10);
19438 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
19439 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19440 uint8_t df = (ctx->opcode >> 0) & 0x3;
19442 TCGv_i32 twd = tcg_const_i32(wd);
19443 TCGv taddr = tcg_temp_new();
19444 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
19446 switch (MASK_MSA_MINOR(opcode)) {
19447 case OPC_LD_B:
19448 gen_helper_msa_ld_b(cpu_env, twd, taddr);
19449 break;
19450 case OPC_LD_H:
19451 gen_helper_msa_ld_h(cpu_env, twd, taddr);
19452 break;
19453 case OPC_LD_W:
19454 gen_helper_msa_ld_w(cpu_env, twd, taddr);
19455 break;
19456 case OPC_LD_D:
19457 gen_helper_msa_ld_d(cpu_env, twd, taddr);
19458 break;
19459 case OPC_ST_B:
19460 gen_helper_msa_st_b(cpu_env, twd, taddr);
19461 break;
19462 case OPC_ST_H:
19463 gen_helper_msa_st_h(cpu_env, twd, taddr);
19464 break;
19465 case OPC_ST_W:
19466 gen_helper_msa_st_w(cpu_env, twd, taddr);
19467 break;
19468 case OPC_ST_D:
19469 gen_helper_msa_st_d(cpu_env, twd, taddr);
19470 break;
19473 tcg_temp_free_i32(twd);
19474 tcg_temp_free(taddr);
19476 break;
19477 default:
19478 MIPS_INVAL("MSA instruction");
19479 generate_exception(ctx, EXCP_RI);
19480 break;
19485 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
19487 int32_t offset;
19488 int rs, rt, rd, sa;
19489 uint32_t op, op1;
19490 int16_t imm;
19492 /* make sure instructions are on a word boundary */
19493 if (ctx->pc & 0x3) {
19494 env->CP0_BadVAddr = ctx->pc;
19495 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
19496 ctx->bstate = BS_STOP;
19497 return;
19500 /* Handle blikely not taken case */
19501 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
19502 TCGLabel *l1 = gen_new_label();
19504 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
19505 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
19506 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
19507 gen_goto_tb(ctx, 1, ctx->pc + 4);
19508 gen_set_label(l1);
19511 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
19512 tcg_gen_debug_insn_start(ctx->pc);
19515 op = MASK_OP_MAJOR(ctx->opcode);
19516 rs = (ctx->opcode >> 21) & 0x1f;
19517 rt = (ctx->opcode >> 16) & 0x1f;
19518 rd = (ctx->opcode >> 11) & 0x1f;
19519 sa = (ctx->opcode >> 6) & 0x1f;
19520 imm = (int16_t)ctx->opcode;
19521 switch (op) {
19522 case OPC_SPECIAL:
19523 decode_opc_special(env, ctx);
19524 break;
19525 case OPC_SPECIAL2:
19526 decode_opc_special2_legacy(env, ctx);
19527 break;
19528 case OPC_SPECIAL3:
19529 decode_opc_special3(env, ctx);
19530 break;
19531 case OPC_REGIMM:
19532 op1 = MASK_REGIMM(ctx->opcode);
19533 switch (op1) {
19534 case OPC_BLTZL: /* REGIMM branches */
19535 case OPC_BGEZL:
19536 case OPC_BLTZALL:
19537 case OPC_BGEZALL:
19538 check_insn(ctx, ISA_MIPS2);
19539 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19540 /* Fallthrough */
19541 case OPC_BLTZ:
19542 case OPC_BGEZ:
19543 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19544 break;
19545 case OPC_BLTZAL:
19546 case OPC_BGEZAL:
19547 if (ctx->insn_flags & ISA_MIPS32R6) {
19548 if (rs == 0) {
19549 /* OPC_NAL, OPC_BAL */
19550 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
19551 } else {
19552 generate_exception(ctx, EXCP_RI);
19554 } else {
19555 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19557 break;
19558 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
19559 case OPC_TNEI:
19560 check_insn(ctx, ISA_MIPS2);
19561 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19562 gen_trap(ctx, op1, rs, -1, imm);
19563 break;
19564 case OPC_SYNCI:
19565 check_insn(ctx, ISA_MIPS32R2);
19566 /* Break the TB to be able to sync copied instructions
19567 immediately */
19568 ctx->bstate = BS_STOP;
19569 break;
19570 case OPC_BPOSGE32: /* MIPS DSP branch */
19571 #if defined(TARGET_MIPS64)
19572 case OPC_BPOSGE64:
19573 #endif
19574 check_dsp(ctx);
19575 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
19576 break;
19577 #if defined(TARGET_MIPS64)
19578 case OPC_DAHI:
19579 check_insn(ctx, ISA_MIPS32R6);
19580 check_mips_64(ctx);
19581 if (rs != 0) {
19582 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
19584 MIPS_DEBUG("dahi %s, %04x", regnames[rs], imm);
19585 break;
19586 case OPC_DATI:
19587 check_insn(ctx, ISA_MIPS32R6);
19588 check_mips_64(ctx);
19589 if (rs != 0) {
19590 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
19592 MIPS_DEBUG("dati %s, %04x", regnames[rs], imm);
19593 break;
19594 #endif
19595 default: /* Invalid */
19596 MIPS_INVAL("regimm");
19597 generate_exception(ctx, EXCP_RI);
19598 break;
19600 break;
19601 case OPC_CP0:
19602 check_cp0_enabled(ctx);
19603 op1 = MASK_CP0(ctx->opcode);
19604 switch (op1) {
19605 case OPC_MFC0:
19606 case OPC_MTC0:
19607 case OPC_MFTR:
19608 case OPC_MTTR:
19609 case OPC_MFHC0:
19610 case OPC_MTHC0:
19611 #if defined(TARGET_MIPS64)
19612 case OPC_DMFC0:
19613 case OPC_DMTC0:
19614 #endif
19615 #ifndef CONFIG_USER_ONLY
19616 gen_cp0(env, ctx, op1, rt, rd);
19617 #endif /* !CONFIG_USER_ONLY */
19618 break;
19619 case OPC_C0_FIRST ... OPC_C0_LAST:
19620 #ifndef CONFIG_USER_ONLY
19621 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
19622 #endif /* !CONFIG_USER_ONLY */
19623 break;
19624 case OPC_MFMC0:
19625 #ifndef CONFIG_USER_ONLY
19627 uint32_t op2;
19628 TCGv t0 = tcg_temp_new();
19630 op2 = MASK_MFMC0(ctx->opcode);
19631 switch (op2) {
19632 case OPC_DMT:
19633 check_insn(ctx, ASE_MT);
19634 gen_helper_dmt(t0);
19635 gen_store_gpr(t0, rt);
19636 break;
19637 case OPC_EMT:
19638 check_insn(ctx, ASE_MT);
19639 gen_helper_emt(t0);
19640 gen_store_gpr(t0, rt);
19641 break;
19642 case OPC_DVPE:
19643 check_insn(ctx, ASE_MT);
19644 gen_helper_dvpe(t0, cpu_env);
19645 gen_store_gpr(t0, rt);
19646 break;
19647 case OPC_EVPE:
19648 check_insn(ctx, ASE_MT);
19649 gen_helper_evpe(t0, cpu_env);
19650 gen_store_gpr(t0, rt);
19651 break;
19652 case OPC_DI:
19653 check_insn(ctx, ISA_MIPS32R2);
19654 save_cpu_state(ctx, 1);
19655 gen_helper_di(t0, cpu_env);
19656 gen_store_gpr(t0, rt);
19657 /* Stop translation as we may have switched
19658 the execution mode. */
19659 ctx->bstate = BS_STOP;
19660 break;
19661 case OPC_EI:
19662 check_insn(ctx, ISA_MIPS32R2);
19663 save_cpu_state(ctx, 1);
19664 gen_helper_ei(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 default: /* Invalid */
19671 MIPS_INVAL("mfmc0");
19672 generate_exception(ctx, EXCP_RI);
19673 break;
19675 tcg_temp_free(t0);
19677 #endif /* !CONFIG_USER_ONLY */
19678 break;
19679 case OPC_RDPGPR:
19680 check_insn(ctx, ISA_MIPS32R2);
19681 gen_load_srsgpr(rt, rd);
19682 break;
19683 case OPC_WRPGPR:
19684 check_insn(ctx, ISA_MIPS32R2);
19685 gen_store_srsgpr(rt, rd);
19686 break;
19687 default:
19688 MIPS_INVAL("cp0");
19689 generate_exception(ctx, EXCP_RI);
19690 break;
19692 break;
19693 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
19694 if (ctx->insn_flags & ISA_MIPS32R6) {
19695 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
19696 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19697 } else {
19698 /* OPC_ADDI */
19699 /* Arithmetic with immediate opcode */
19700 gen_arith_imm(ctx, op, rt, rs, imm);
19702 break;
19703 case OPC_ADDIU:
19704 gen_arith_imm(ctx, op, rt, rs, imm);
19705 break;
19706 case OPC_SLTI: /* Set on less than with immediate opcode */
19707 case OPC_SLTIU:
19708 gen_slt_imm(ctx, op, rt, rs, imm);
19709 break;
19710 case OPC_ANDI: /* Arithmetic with immediate opcode */
19711 case OPC_LUI: /* OPC_AUI */
19712 case OPC_ORI:
19713 case OPC_XORI:
19714 gen_logic_imm(ctx, op, rt, rs, imm);
19715 break;
19716 case OPC_J ... OPC_JAL: /* Jump */
19717 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19718 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19719 break;
19720 /* Branch */
19721 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
19722 if (ctx->insn_flags & ISA_MIPS32R6) {
19723 if (rt == 0) {
19724 generate_exception(ctx, EXCP_RI);
19725 break;
19727 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
19728 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19729 } else {
19730 /* OPC_BLEZL */
19731 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19733 break;
19734 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
19735 if (ctx->insn_flags & ISA_MIPS32R6) {
19736 if (rt == 0) {
19737 generate_exception(ctx, EXCP_RI);
19738 break;
19740 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
19741 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19742 } else {
19743 /* OPC_BGTZL */
19744 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19746 break;
19747 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
19748 if (rt == 0) {
19749 /* OPC_BLEZ */
19750 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19751 } else {
19752 check_insn(ctx, ISA_MIPS32R6);
19753 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
19754 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19756 break;
19757 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
19758 if (rt == 0) {
19759 /* OPC_BGTZ */
19760 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19761 } else {
19762 check_insn(ctx, ISA_MIPS32R6);
19763 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
19764 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19766 break;
19767 case OPC_BEQL:
19768 case OPC_BNEL:
19769 check_insn(ctx, ISA_MIPS2);
19770 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19771 /* Fallthrough */
19772 case OPC_BEQ:
19773 case OPC_BNE:
19774 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19775 break;
19776 case OPC_LL: /* Load and stores */
19777 check_insn(ctx, ISA_MIPS2);
19778 /* Fallthrough */
19779 case OPC_LWL:
19780 case OPC_LWR:
19781 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19782 /* Fallthrough */
19783 case OPC_LB ... OPC_LH:
19784 case OPC_LW ... OPC_LHU:
19785 gen_ld(ctx, op, rt, rs, imm);
19786 break;
19787 case OPC_SWL:
19788 case OPC_SWR:
19789 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19790 /* fall through */
19791 case OPC_SB ... OPC_SH:
19792 case OPC_SW:
19793 gen_st(ctx, op, rt, rs, imm);
19794 break;
19795 case OPC_SC:
19796 check_insn(ctx, ISA_MIPS2);
19797 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19798 gen_st_cond(ctx, op, rt, rs, imm);
19799 break;
19800 case OPC_CACHE:
19801 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19802 check_cp0_enabled(ctx);
19803 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
19804 /* Treat as NOP. */
19805 break;
19806 case OPC_PREF:
19807 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19808 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
19809 /* Treat as NOP. */
19810 break;
19812 /* Floating point (COP1). */
19813 case OPC_LWC1:
19814 case OPC_LDC1:
19815 case OPC_SWC1:
19816 case OPC_SDC1:
19817 gen_cop1_ldst(ctx, op, rt, rs, imm);
19818 break;
19820 case OPC_CP1:
19821 op1 = MASK_CP1(ctx->opcode);
19823 switch (op1) {
19824 case OPC_MFHC1:
19825 case OPC_MTHC1:
19826 check_cp1_enabled(ctx);
19827 check_insn(ctx, ISA_MIPS32R2);
19828 case OPC_MFC1:
19829 case OPC_CFC1:
19830 case OPC_MTC1:
19831 case OPC_CTC1:
19832 check_cp1_enabled(ctx);
19833 gen_cp1(ctx, op1, rt, rd);
19834 break;
19835 #if defined(TARGET_MIPS64)
19836 case OPC_DMFC1:
19837 case OPC_DMTC1:
19838 check_cp1_enabled(ctx);
19839 check_insn(ctx, ISA_MIPS3);
19840 check_mips_64(ctx);
19841 gen_cp1(ctx, op1, rt, rd);
19842 break;
19843 #endif
19844 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
19845 check_cp1_enabled(ctx);
19846 if (ctx->insn_flags & ISA_MIPS32R6) {
19847 /* OPC_BC1EQZ */
19848 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19849 rt, imm << 2, 4);
19850 } else {
19851 /* OPC_BC1ANY2 */
19852 check_cop1x(ctx);
19853 check_insn(ctx, ASE_MIPS3D);
19854 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19855 (rt >> 2) & 0x7, imm << 2);
19857 break;
19858 case OPC_BC1NEZ:
19859 check_cp1_enabled(ctx);
19860 check_insn(ctx, ISA_MIPS32R6);
19861 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19862 rt, imm << 2, 4);
19863 break;
19864 case OPC_BC1ANY4:
19865 check_cp1_enabled(ctx);
19866 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19867 check_cop1x(ctx);
19868 check_insn(ctx, ASE_MIPS3D);
19869 /* fall through */
19870 case OPC_BC1:
19871 check_cp1_enabled(ctx);
19872 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19873 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19874 (rt >> 2) & 0x7, imm << 2);
19875 break;
19876 case OPC_PS_FMT:
19877 check_ps(ctx);
19878 /* fall through */
19879 case OPC_S_FMT:
19880 case OPC_D_FMT:
19881 check_cp1_enabled(ctx);
19882 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19883 (imm >> 8) & 0x7);
19884 break;
19885 case OPC_W_FMT:
19886 case OPC_L_FMT:
19888 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
19889 check_cp1_enabled(ctx);
19890 if (ctx->insn_flags & ISA_MIPS32R6) {
19891 switch (r6_op) {
19892 case R6_OPC_CMP_AF_S:
19893 case R6_OPC_CMP_UN_S:
19894 case R6_OPC_CMP_EQ_S:
19895 case R6_OPC_CMP_UEQ_S:
19896 case R6_OPC_CMP_LT_S:
19897 case R6_OPC_CMP_ULT_S:
19898 case R6_OPC_CMP_LE_S:
19899 case R6_OPC_CMP_ULE_S:
19900 case R6_OPC_CMP_SAF_S:
19901 case R6_OPC_CMP_SUN_S:
19902 case R6_OPC_CMP_SEQ_S:
19903 case R6_OPC_CMP_SEUQ_S:
19904 case R6_OPC_CMP_SLT_S:
19905 case R6_OPC_CMP_SULT_S:
19906 case R6_OPC_CMP_SLE_S:
19907 case R6_OPC_CMP_SULE_S:
19908 case R6_OPC_CMP_OR_S:
19909 case R6_OPC_CMP_UNE_S:
19910 case R6_OPC_CMP_NE_S:
19911 case R6_OPC_CMP_SOR_S:
19912 case R6_OPC_CMP_SUNE_S:
19913 case R6_OPC_CMP_SNE_S:
19914 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19915 break;
19916 case R6_OPC_CMP_AF_D:
19917 case R6_OPC_CMP_UN_D:
19918 case R6_OPC_CMP_EQ_D:
19919 case R6_OPC_CMP_UEQ_D:
19920 case R6_OPC_CMP_LT_D:
19921 case R6_OPC_CMP_ULT_D:
19922 case R6_OPC_CMP_LE_D:
19923 case R6_OPC_CMP_ULE_D:
19924 case R6_OPC_CMP_SAF_D:
19925 case R6_OPC_CMP_SUN_D:
19926 case R6_OPC_CMP_SEQ_D:
19927 case R6_OPC_CMP_SEUQ_D:
19928 case R6_OPC_CMP_SLT_D:
19929 case R6_OPC_CMP_SULT_D:
19930 case R6_OPC_CMP_SLE_D:
19931 case R6_OPC_CMP_SULE_D:
19932 case R6_OPC_CMP_OR_D:
19933 case R6_OPC_CMP_UNE_D:
19934 case R6_OPC_CMP_NE_D:
19935 case R6_OPC_CMP_SOR_D:
19936 case R6_OPC_CMP_SUNE_D:
19937 case R6_OPC_CMP_SNE_D:
19938 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19939 break;
19940 default:
19941 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
19942 rt, rd, sa, (imm >> 8) & 0x7);
19944 break;
19946 } else {
19947 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19948 (imm >> 8) & 0x7);
19950 break;
19952 case OPC_BZ_V:
19953 case OPC_BNZ_V:
19954 case OPC_BZ_B:
19955 case OPC_BZ_H:
19956 case OPC_BZ_W:
19957 case OPC_BZ_D:
19958 case OPC_BNZ_B:
19959 case OPC_BNZ_H:
19960 case OPC_BNZ_W:
19961 case OPC_BNZ_D:
19962 check_insn(ctx, ASE_MSA);
19963 gen_msa_branch(env, ctx, op1);
19964 break;
19965 default:
19966 MIPS_INVAL("cp1");
19967 generate_exception(ctx, EXCP_RI);
19968 break;
19970 break;
19972 /* Compact branches [R6] and COP2 [non-R6] */
19973 case OPC_BC: /* OPC_LWC2 */
19974 case OPC_BALC: /* OPC_SWC2 */
19975 if (ctx->insn_flags & ISA_MIPS32R6) {
19976 /* OPC_BC, OPC_BALC */
19977 gen_compute_compact_branch(ctx, op, 0, 0,
19978 sextract32(ctx->opcode << 2, 0, 28));
19979 } else {
19980 /* OPC_LWC2, OPC_SWC2 */
19981 /* COP2: Not implemented. */
19982 generate_exception_err(ctx, EXCP_CpU, 2);
19984 break;
19985 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
19986 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
19987 if (ctx->insn_flags & ISA_MIPS32R6) {
19988 if (rs != 0) {
19989 /* OPC_BEQZC, OPC_BNEZC */
19990 gen_compute_compact_branch(ctx, op, rs, 0,
19991 sextract32(ctx->opcode << 2, 0, 23));
19992 } else {
19993 /* OPC_JIC, OPC_JIALC */
19994 gen_compute_compact_branch(ctx, op, 0, rt, imm);
19996 } else {
19997 /* OPC_LWC2, OPC_SWC2 */
19998 /* COP2: Not implemented. */
19999 generate_exception_err(ctx, EXCP_CpU, 2);
20001 break;
20002 case OPC_CP2:
20003 check_insn(ctx, INSN_LOONGSON2F);
20004 /* Note that these instructions use different fields. */
20005 gen_loongson_multimedia(ctx, sa, rd, rt);
20006 break;
20008 case OPC_CP3:
20009 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20010 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20011 check_cp1_enabled(ctx);
20012 op1 = MASK_CP3(ctx->opcode);
20013 switch (op1) {
20014 case OPC_LUXC1:
20015 case OPC_SUXC1:
20016 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
20017 /* Fallthrough */
20018 case OPC_LWXC1:
20019 case OPC_LDXC1:
20020 case OPC_SWXC1:
20021 case OPC_SDXC1:
20022 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20023 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
20024 break;
20025 case OPC_PREFX:
20026 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20027 /* Treat as NOP. */
20028 break;
20029 case OPC_ALNV_PS:
20030 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
20031 /* Fallthrough */
20032 case OPC_MADD_S:
20033 case OPC_MADD_D:
20034 case OPC_MADD_PS:
20035 case OPC_MSUB_S:
20036 case OPC_MSUB_D:
20037 case OPC_MSUB_PS:
20038 case OPC_NMADD_S:
20039 case OPC_NMADD_D:
20040 case OPC_NMADD_PS:
20041 case OPC_NMSUB_S:
20042 case OPC_NMSUB_D:
20043 case OPC_NMSUB_PS:
20044 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20045 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
20046 break;
20047 default:
20048 MIPS_INVAL("cp3");
20049 generate_exception (ctx, EXCP_RI);
20050 break;
20052 } else {
20053 generate_exception_err(ctx, EXCP_CpU, 1);
20055 break;
20057 #if defined(TARGET_MIPS64)
20058 /* MIPS64 opcodes */
20059 case OPC_LDL ... OPC_LDR:
20060 case OPC_LLD:
20061 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20062 /* fall through */
20063 case OPC_LWU:
20064 case OPC_LD:
20065 check_insn(ctx, ISA_MIPS3);
20066 check_mips_64(ctx);
20067 gen_ld(ctx, op, rt, rs, imm);
20068 break;
20069 case OPC_SDL ... OPC_SDR:
20070 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20071 /* fall through */
20072 case OPC_SD:
20073 check_insn(ctx, ISA_MIPS3);
20074 check_mips_64(ctx);
20075 gen_st(ctx, op, rt, rs, imm);
20076 break;
20077 case OPC_SCD:
20078 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20079 check_insn(ctx, ISA_MIPS3);
20080 check_mips_64(ctx);
20081 gen_st_cond(ctx, op, rt, rs, imm);
20082 break;
20083 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
20084 if (ctx->insn_flags & ISA_MIPS32R6) {
20085 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
20086 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
20087 } else {
20088 /* OPC_DADDI */
20089 check_insn(ctx, ISA_MIPS3);
20090 check_mips_64(ctx);
20091 gen_arith_imm(ctx, op, rt, rs, imm);
20093 break;
20094 case OPC_DADDIU:
20095 check_insn(ctx, ISA_MIPS3);
20096 check_mips_64(ctx);
20097 gen_arith_imm(ctx, op, rt, rs, imm);
20098 break;
20099 #else
20100 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
20101 if (ctx->insn_flags & ISA_MIPS32R6) {
20102 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
20103 } else {
20104 MIPS_INVAL("major opcode");
20105 generate_exception(ctx, EXCP_RI);
20107 break;
20108 #endif
20109 case OPC_DAUI: /* OPC_JALX */
20110 if (ctx->insn_flags & ISA_MIPS32R6) {
20111 #if defined(TARGET_MIPS64)
20112 /* OPC_DAUI */
20113 check_mips_64(ctx);
20114 if (rt != 0) {
20115 TCGv t0 = tcg_temp_new();
20116 gen_load_gpr(t0, rs);
20117 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
20118 tcg_temp_free(t0);
20120 MIPS_DEBUG("daui %s, %s, %04x", regnames[rt], regnames[rs], imm);
20121 #else
20122 generate_exception(ctx, EXCP_RI);
20123 MIPS_INVAL("major opcode");
20124 #endif
20125 } else {
20126 /* OPC_JALX */
20127 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
20128 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
20129 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
20131 break;
20132 case OPC_MSA: /* OPC_MDMX */
20133 /* MDMX: Not implemented. */
20134 gen_msa(env, ctx);
20135 break;
20136 case OPC_PCREL:
20137 check_insn(ctx, ISA_MIPS32R6);
20138 gen_pcrel(ctx, ctx->opcode, ctx->pc, rs);
20139 break;
20140 default: /* Invalid */
20141 MIPS_INVAL("major opcode");
20142 generate_exception(ctx, EXCP_RI);
20143 break;
20147 static inline void
20148 gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
20149 bool search_pc)
20151 CPUState *cs = CPU(cpu);
20152 CPUMIPSState *env = &cpu->env;
20153 DisasContext ctx;
20154 target_ulong pc_start;
20155 target_ulong next_page_start;
20156 CPUBreakpoint *bp;
20157 int j, lj = -1;
20158 int num_insns;
20159 int max_insns;
20160 int insn_bytes;
20161 int is_slot;
20163 if (search_pc)
20164 qemu_log("search pc %d\n", search_pc);
20166 pc_start = tb->pc;
20167 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
20168 ctx.pc = pc_start;
20169 ctx.saved_pc = -1;
20170 ctx.singlestep_enabled = cs->singlestep_enabled;
20171 ctx.insn_flags = env->insn_flags;
20172 ctx.CP0_Config1 = env->CP0_Config1;
20173 ctx.tb = tb;
20174 ctx.bstate = BS_NONE;
20175 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
20176 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
20177 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
20178 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
20179 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
20180 ctx.PAMask = env->PAMask;
20181 ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
20182 ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
20183 /* Restore delay slot state from the tb context. */
20184 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
20185 ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
20186 ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
20187 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
20188 restore_cpu_state(env, &ctx);
20189 #ifdef CONFIG_USER_ONLY
20190 ctx.mem_idx = MIPS_HFLAG_UM;
20191 #else
20192 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
20193 #endif
20194 ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ?
20195 MO_UNALN : MO_ALIGN;
20196 num_insns = 0;
20197 max_insns = tb->cflags & CF_COUNT_MASK;
20198 if (max_insns == 0)
20199 max_insns = CF_COUNT_MASK;
20200 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
20201 gen_tb_start(tb);
20202 while (ctx.bstate == BS_NONE) {
20203 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
20204 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
20205 if (bp->pc == ctx.pc) {
20206 save_cpu_state(&ctx, 1);
20207 ctx.bstate = BS_BRANCH;
20208 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
20209 /* Include the breakpoint location or the tb won't
20210 * be flushed when it must be. */
20211 ctx.pc += 4;
20212 goto done_generating;
20217 if (search_pc) {
20218 j = tcg_op_buf_count();
20219 if (lj < j) {
20220 lj++;
20221 while (lj < j)
20222 tcg_ctx.gen_opc_instr_start[lj++] = 0;
20224 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
20225 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
20226 gen_opc_btarget[lj] = ctx.btarget;
20227 tcg_ctx.gen_opc_instr_start[lj] = 1;
20228 tcg_ctx.gen_opc_icount[lj] = num_insns;
20230 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
20231 gen_io_start();
20233 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
20234 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
20235 ctx.opcode = cpu_ldl_code(env, ctx.pc);
20236 insn_bytes = 4;
20237 decode_opc(env, &ctx);
20238 } else if (ctx.insn_flags & ASE_MICROMIPS) {
20239 ctx.opcode = cpu_lduw_code(env, ctx.pc);
20240 insn_bytes = decode_micromips_opc(env, &ctx);
20241 } else if (ctx.insn_flags & ASE_MIPS16) {
20242 ctx.opcode = cpu_lduw_code(env, ctx.pc);
20243 insn_bytes = decode_mips16_opc(env, &ctx);
20244 } else {
20245 generate_exception(&ctx, EXCP_RI);
20246 ctx.bstate = BS_STOP;
20247 break;
20250 if (ctx.hflags & MIPS_HFLAG_BMASK) {
20251 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
20252 MIPS_HFLAG_FBNSLOT))) {
20253 /* force to generate branch as there is neither delay nor
20254 forbidden slot */
20255 is_slot = 1;
20257 if ((ctx.hflags & MIPS_HFLAG_M16) &&
20258 (ctx.hflags & MIPS_HFLAG_FBNSLOT)) {
20259 /* Force to generate branch as microMIPS R6 doesn't restrict
20260 branches in the forbidden slot. */
20261 is_slot = 1;
20264 if (is_slot) {
20265 gen_branch(&ctx, insn_bytes);
20267 ctx.pc += insn_bytes;
20269 num_insns++;
20271 /* Execute a branch and its delay slot as a single instruction.
20272 This is what GDB expects and is consistent with what the
20273 hardware does (e.g. if a delay slot instruction faults, the
20274 reported PC is the PC of the branch). */
20275 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
20276 break;
20279 if (ctx.pc >= next_page_start) {
20280 break;
20283 if (tcg_op_buf_full()) {
20284 break;
20287 if (num_insns >= max_insns)
20288 break;
20290 if (singlestep)
20291 break;
20293 if (tb->cflags & CF_LAST_IO) {
20294 gen_io_end();
20296 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
20297 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
20298 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
20299 } else {
20300 switch (ctx.bstate) {
20301 case BS_STOP:
20302 gen_goto_tb(&ctx, 0, ctx.pc);
20303 break;
20304 case BS_NONE:
20305 save_cpu_state(&ctx, 0);
20306 gen_goto_tb(&ctx, 0, ctx.pc);
20307 break;
20308 case BS_EXCP:
20309 tcg_gen_exit_tb(0);
20310 break;
20311 case BS_BRANCH:
20312 default:
20313 break;
20316 done_generating:
20317 gen_tb_end(tb, num_insns);
20319 if (search_pc) {
20320 j = tcg_op_buf_count();
20321 lj++;
20322 while (lj <= j)
20323 tcg_ctx.gen_opc_instr_start[lj++] = 0;
20324 } else {
20325 tb->size = ctx.pc - pc_start;
20326 tb->icount = num_insns;
20328 #ifdef DEBUG_DISAS
20329 LOG_DISAS("\n");
20330 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
20331 qemu_log("IN: %s\n", lookup_symbol(pc_start));
20332 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
20333 qemu_log("\n");
20335 #endif
20338 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
20340 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
20343 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
20345 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
20348 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
20349 int flags)
20351 int i;
20352 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
20354 #define printfpr(fp) \
20355 do { \
20356 if (is_fpu64) \
20357 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20358 " fd:%13g fs:%13g psu: %13g\n", \
20359 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
20360 (double)(fp)->fd, \
20361 (double)(fp)->fs[FP_ENDIAN_IDX], \
20362 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
20363 else { \
20364 fpr_t tmp; \
20365 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
20366 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
20367 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20368 " fd:%13g fs:%13g psu:%13g\n", \
20369 tmp.w[FP_ENDIAN_IDX], tmp.d, \
20370 (double)tmp.fd, \
20371 (double)tmp.fs[FP_ENDIAN_IDX], \
20372 (double)tmp.fs[!FP_ENDIAN_IDX]); \
20374 } while(0)
20377 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
20378 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
20379 get_float_exception_flags(&env->active_fpu.fp_status));
20380 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
20381 fpu_fprintf(f, "%3s: ", fregnames[i]);
20382 printfpr(&env->active_fpu.fpr[i]);
20385 #undef printfpr
20388 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
20389 /* Debug help: The architecture requires 32bit code to maintain proper
20390 sign-extended values on 64bit machines. */
20392 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
20394 static void
20395 cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
20396 fprintf_function cpu_fprintf,
20397 int flags)
20399 int i;
20401 if (!SIGN_EXT_P(env->active_tc.PC))
20402 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
20403 if (!SIGN_EXT_P(env->active_tc.HI[0]))
20404 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
20405 if (!SIGN_EXT_P(env->active_tc.LO[0]))
20406 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
20407 if (!SIGN_EXT_P(env->btarget))
20408 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
20410 for (i = 0; i < 32; i++) {
20411 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
20412 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
20415 if (!SIGN_EXT_P(env->CP0_EPC))
20416 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
20417 if (!SIGN_EXT_P(env->lladdr))
20418 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
20420 #endif
20422 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
20423 int flags)
20425 MIPSCPU *cpu = MIPS_CPU(cs);
20426 CPUMIPSState *env = &cpu->env;
20427 int i;
20429 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
20430 " LO=0x" TARGET_FMT_lx " ds %04x "
20431 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
20432 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
20433 env->hflags, env->btarget, env->bcond);
20434 for (i = 0; i < 32; i++) {
20435 if ((i & 3) == 0)
20436 cpu_fprintf(f, "GPR%02d:", i);
20437 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
20438 if ((i & 3) == 3)
20439 cpu_fprintf(f, "\n");
20442 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
20443 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
20444 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
20445 PRIx64 "\n",
20446 env->CP0_Config0, env->CP0_Config1, env->lladdr);
20447 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
20448 env->CP0_Config2, env->CP0_Config3);
20449 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
20450 env->CP0_Config4, env->CP0_Config5);
20451 if (env->hflags & MIPS_HFLAG_FPU)
20452 fpu_dump_state(env, f, cpu_fprintf, flags);
20453 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
20454 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
20455 #endif
20458 void mips_tcg_init(void)
20460 int i;
20461 static int inited;
20463 /* Initialize various static tables. */
20464 if (inited)
20465 return;
20467 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
20468 TCGV_UNUSED(cpu_gpr[0]);
20469 for (i = 1; i < 32; i++)
20470 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
20471 offsetof(CPUMIPSState, active_tc.gpr[i]),
20472 regnames[i]);
20474 for (i = 0; i < 32; i++) {
20475 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
20476 msa_wr_d[i * 2] =
20477 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2]);
20478 /* The scalar floating-point unit (FPU) registers are mapped on
20479 * the MSA vector registers. */
20480 fpu_f64[i] = msa_wr_d[i * 2];
20481 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
20482 msa_wr_d[i * 2 + 1] =
20483 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2 + 1]);
20486 cpu_PC = tcg_global_mem_new(TCG_AREG0,
20487 offsetof(CPUMIPSState, active_tc.PC), "PC");
20488 for (i = 0; i < MIPS_DSP_ACC; i++) {
20489 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
20490 offsetof(CPUMIPSState, active_tc.HI[i]),
20491 regnames_HI[i]);
20492 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
20493 offsetof(CPUMIPSState, active_tc.LO[i]),
20494 regnames_LO[i]);
20496 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
20497 offsetof(CPUMIPSState, active_tc.DSPControl),
20498 "DSPControl");
20499 bcond = tcg_global_mem_new(TCG_AREG0,
20500 offsetof(CPUMIPSState, bcond), "bcond");
20501 btarget = tcg_global_mem_new(TCG_AREG0,
20502 offsetof(CPUMIPSState, btarget), "btarget");
20503 hflags = tcg_global_mem_new_i32(TCG_AREG0,
20504 offsetof(CPUMIPSState, hflags), "hflags");
20506 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
20507 offsetof(CPUMIPSState, active_fpu.fcr0),
20508 "fcr0");
20509 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
20510 offsetof(CPUMIPSState, active_fpu.fcr31),
20511 "fcr31");
20513 inited = 1;
20516 #include "translate_init.c"
20518 MIPSCPU *cpu_mips_init(const char *cpu_model)
20520 MIPSCPU *cpu;
20521 CPUMIPSState *env;
20522 const mips_def_t *def;
20524 def = cpu_mips_find_by_name(cpu_model);
20525 if (!def)
20526 return NULL;
20527 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
20528 env = &cpu->env;
20529 env->cpu_model = def;
20531 #ifndef CONFIG_USER_ONLY
20532 mmu_init(env, def);
20533 #endif
20534 fpu_init(env, def);
20535 mvp_init(env, def);
20537 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
20539 return cpu;
20542 void cpu_state_reset(CPUMIPSState *env)
20544 MIPSCPU *cpu = mips_env_get_cpu(env);
20545 CPUState *cs = CPU(cpu);
20547 /* Reset registers to their default values */
20548 env->CP0_PRid = env->cpu_model->CP0_PRid;
20549 env->CP0_Config0 = env->cpu_model->CP0_Config0;
20550 #ifdef TARGET_WORDS_BIGENDIAN
20551 env->CP0_Config0 |= (1 << CP0C0_BE);
20552 #endif
20553 env->CP0_Config1 = env->cpu_model->CP0_Config1;
20554 env->CP0_Config2 = env->cpu_model->CP0_Config2;
20555 env->CP0_Config3 = env->cpu_model->CP0_Config3;
20556 env->CP0_Config4 = env->cpu_model->CP0_Config4;
20557 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
20558 env->CP0_Config5 = env->cpu_model->CP0_Config5;
20559 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
20560 env->CP0_Config6 = env->cpu_model->CP0_Config6;
20561 env->CP0_Config7 = env->cpu_model->CP0_Config7;
20562 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
20563 << env->cpu_model->CP0_LLAddr_shift;
20564 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
20565 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
20566 env->CCRes = env->cpu_model->CCRes;
20567 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
20568 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
20569 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
20570 env->current_tc = 0;
20571 env->SEGBITS = env->cpu_model->SEGBITS;
20572 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
20573 #if defined(TARGET_MIPS64)
20574 if (env->cpu_model->insn_flags & ISA_MIPS3) {
20575 env->SEGMask |= 3ULL << 62;
20577 #endif
20578 env->PABITS = env->cpu_model->PABITS;
20579 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
20580 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
20581 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
20582 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
20583 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
20584 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
20585 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
20586 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
20587 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
20588 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
20589 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
20590 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
20591 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
20592 env->msair = env->cpu_model->MSAIR;
20593 env->insn_flags = env->cpu_model->insn_flags;
20595 #if defined(CONFIG_USER_ONLY)
20596 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
20597 # ifdef TARGET_MIPS64
20598 /* Enable 64-bit register mode. */
20599 env->CP0_Status |= (1 << CP0St_PX);
20600 # endif
20601 # ifdef TARGET_ABI_MIPSN64
20602 /* Enable 64-bit address mode. */
20603 env->CP0_Status |= (1 << CP0St_UX);
20604 # endif
20605 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
20606 hardware registers. */
20607 env->CP0_HWREna |= 0x0000000F;
20608 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
20609 env->CP0_Status |= (1 << CP0St_CU1);
20611 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
20612 env->CP0_Status |= (1 << CP0St_MX);
20614 # if defined(TARGET_MIPS64)
20615 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
20616 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
20617 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
20618 env->CP0_Status |= (1 << CP0St_FR);
20620 # endif
20621 #else
20622 if (env->hflags & MIPS_HFLAG_BMASK) {
20623 /* If the exception was raised from a delay slot,
20624 come back to the jump. */
20625 env->CP0_ErrorEPC = (env->active_tc.PC
20626 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
20627 } else {
20628 env->CP0_ErrorEPC = env->active_tc.PC;
20630 env->active_tc.PC = (int32_t)0xBFC00000;
20631 env->CP0_Random = env->tlb->nb_tlb - 1;
20632 env->tlb->tlb_in_use = env->tlb->nb_tlb;
20633 env->CP0_Wired = 0;
20634 env->CP0_EBase = (cs->cpu_index & 0x3FF);
20635 if (kvm_enabled()) {
20636 env->CP0_EBase |= 0x40000000;
20637 } else {
20638 env->CP0_EBase |= 0x80000000;
20640 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
20641 /* vectored interrupts not implemented, timer on int 7,
20642 no performance counters. */
20643 env->CP0_IntCtl = 0xe0000000;
20645 int i;
20647 for (i = 0; i < 7; i++) {
20648 env->CP0_WatchLo[i] = 0;
20649 env->CP0_WatchHi[i] = 0x80000000;
20651 env->CP0_WatchLo[7] = 0;
20652 env->CP0_WatchHi[7] = 0;
20654 /* Count register increments in debug mode, EJTAG version 1 */
20655 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
20657 cpu_mips_store_count(env, 1);
20659 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
20660 int i;
20662 /* Only TC0 on VPE 0 starts as active. */
20663 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
20664 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
20665 env->tcs[i].CP0_TCHalt = 1;
20667 env->active_tc.CP0_TCHalt = 1;
20668 cs->halted = 1;
20670 if (cs->cpu_index == 0) {
20671 /* VPE0 starts up enabled. */
20672 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
20673 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
20675 /* TC0 starts up unhalted. */
20676 cs->halted = 0;
20677 env->active_tc.CP0_TCHalt = 0;
20678 env->tcs[0].CP0_TCHalt = 0;
20679 /* With thread 0 active. */
20680 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
20681 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
20684 #endif
20685 if ((env->insn_flags & ISA_MIPS32R6) &&
20686 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
20687 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
20688 env->CP0_Status |= (1 << CP0St_FR);
20691 /* MSA */
20692 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
20693 msa_reset(env);
20696 compute_hflags(env);
20697 restore_rounding_mode(env);
20698 restore_flush_mode(env);
20699 restore_pamask(env);
20700 cs->exception_index = EXCP_NONE;
20702 if (semihosting_get_argc()) {
20703 /* UHI interface can be used to obtain argc and argv */
20704 env->active_tc.gpr[4] = -1;
20708 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
20710 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
20711 env->hflags &= ~MIPS_HFLAG_BMASK;
20712 env->hflags |= gen_opc_hflags[pc_pos];
20713 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
20714 case MIPS_HFLAG_BR:
20715 break;
20716 case MIPS_HFLAG_BC:
20717 case MIPS_HFLAG_BL:
20718 case MIPS_HFLAG_B:
20719 env->btarget = gen_opc_btarget[pc_pos];
20720 break;