pc: Eliminate PcGuestInfo struct
[qemu/cris-port.git] / target-mips / translate.c
blob791866bf2d76a06bb157bda8ba86370cfeb63072
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 "qemu/osdep.h"
25 #include "cpu.h"
26 #include "disas/disas.h"
27 #include "tcg-op.h"
28 #include "exec/cpu_ldst.h"
30 #include "exec/helper-proto.h"
31 #include "exec/helper-gen.h"
32 #include "sysemu/kvm.h"
33 #include "exec/semihost.h"
35 #include "trace-tcg.h"
36 #include "exec/log.h"
38 #define MIPS_DEBUG_DISAS 0
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_SIGRIE = (0x17 << 16) | OPC_REGIMM,
329 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
331 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
332 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
335 /* Special2 opcodes */
336 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
338 enum {
339 /* Multiply & xxx operations */
340 OPC_MADD = 0x00 | OPC_SPECIAL2,
341 OPC_MADDU = 0x01 | OPC_SPECIAL2,
342 OPC_MUL = 0x02 | OPC_SPECIAL2,
343 OPC_MSUB = 0x04 | OPC_SPECIAL2,
344 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
345 /* Loongson 2F */
346 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
347 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
348 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
349 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
350 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
351 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
352 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
353 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
354 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
355 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
356 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
357 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
358 /* Misc */
359 OPC_CLZ = 0x20 | OPC_SPECIAL2,
360 OPC_CLO = 0x21 | OPC_SPECIAL2,
361 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
362 OPC_DCLO = 0x25 | OPC_SPECIAL2,
363 /* Special */
364 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
367 /* Special3 opcodes */
368 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
370 enum {
371 OPC_EXT = 0x00 | OPC_SPECIAL3,
372 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
373 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
374 OPC_DEXT = 0x03 | OPC_SPECIAL3,
375 OPC_INS = 0x04 | OPC_SPECIAL3,
376 OPC_DINSM = 0x05 | OPC_SPECIAL3,
377 OPC_DINSU = 0x06 | OPC_SPECIAL3,
378 OPC_DINS = 0x07 | OPC_SPECIAL3,
379 OPC_FORK = 0x08 | OPC_SPECIAL3,
380 OPC_YIELD = 0x09 | OPC_SPECIAL3,
381 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
382 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
383 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
385 /* Loongson 2E */
386 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
387 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
388 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
389 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
390 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
391 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
392 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
393 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
394 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
395 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
396 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
397 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
399 /* MIPS DSP Load */
400 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
401 /* MIPS DSP Arithmetic */
402 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
403 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
404 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
405 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
406 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
407 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
408 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
409 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
410 /* MIPS DSP GPR-Based Shift Sub-class */
411 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
412 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
413 /* MIPS DSP Multiply Sub-class insns */
414 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
415 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
416 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
417 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
418 /* DSP Bit/Manipulation Sub-class */
419 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
420 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
421 /* MIPS DSP Append Sub-class */
422 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
423 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
424 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
425 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
426 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
428 /* R6 */
429 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
430 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
431 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
432 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
433 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
434 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
437 /* BSHFL opcodes */
438 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
440 enum {
441 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
442 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
443 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
444 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
445 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
446 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
449 /* DBSHFL opcodes */
450 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
452 enum {
453 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
454 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
455 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
456 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
457 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
460 /* MIPS DSP REGIMM opcodes */
461 enum {
462 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
463 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
466 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
467 /* MIPS DSP Load */
468 enum {
469 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
470 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
471 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
472 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
475 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
476 enum {
477 /* MIPS DSP Arithmetic Sub-class */
478 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
479 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
480 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
481 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
482 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
483 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
484 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
485 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
486 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
487 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
488 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
489 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
490 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
491 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
492 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
493 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
494 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
495 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
496 /* MIPS DSP Multiply Sub-class insns */
497 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
498 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
499 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
500 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
501 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
502 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
505 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
506 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
507 enum {
508 /* MIPS DSP Arithmetic Sub-class */
509 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
510 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
511 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
512 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
513 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
514 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
515 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
516 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
517 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
518 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
519 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
520 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
521 /* MIPS DSP Multiply Sub-class insns */
522 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
523 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
524 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
525 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
528 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
529 enum {
530 /* MIPS DSP Arithmetic Sub-class */
531 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
532 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
533 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
534 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
535 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
536 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
537 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
538 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
539 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
540 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
541 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
542 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
543 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
544 /* DSP Bit/Manipulation Sub-class */
545 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
546 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
547 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
548 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
549 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
552 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
553 enum {
554 /* MIPS DSP Arithmetic Sub-class */
555 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
556 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
557 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
558 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
559 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
560 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
561 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
562 /* DSP Compare-Pick Sub-class */
563 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
564 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
565 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
566 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
567 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
568 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
569 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
570 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
571 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
572 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
573 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
574 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
575 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
576 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
577 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
580 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
581 enum {
582 /* MIPS DSP GPR-Based Shift Sub-class */
583 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
584 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
585 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
586 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
587 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
588 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
589 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
590 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
591 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
592 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
593 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
594 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
595 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
596 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
597 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
598 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
599 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
600 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
601 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
602 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
603 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
604 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
607 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
608 enum {
609 /* MIPS DSP Multiply Sub-class insns */
610 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
611 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
612 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
613 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
614 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
615 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
616 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
617 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
618 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
619 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
620 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
621 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
622 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
623 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
624 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
625 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
626 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
627 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
628 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
629 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
630 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
631 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
634 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
635 enum {
636 /* DSP Bit/Manipulation Sub-class */
637 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
640 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
641 enum {
642 /* MIPS DSP Append Sub-class */
643 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
644 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
645 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
648 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
649 enum {
650 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
651 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
652 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
653 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
654 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
655 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
656 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
657 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
658 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
659 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
660 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
661 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
662 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
663 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
664 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
665 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
666 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
667 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
670 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671 enum {
672 /* MIPS DSP Arithmetic Sub-class */
673 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
674 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
675 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
676 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
677 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
678 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
679 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
680 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
681 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
682 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
683 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
684 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
685 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
686 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
687 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
688 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
689 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
690 /* DSP Bit/Manipulation Sub-class */
691 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
692 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
693 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
694 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
695 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
699 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
700 enum {
701 /* MIPS DSP Multiply Sub-class insns */
702 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
703 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
704 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
705 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
706 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
707 /* MIPS DSP Arithmetic Sub-class */
708 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
709 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
710 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
711 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
712 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
713 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
714 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
715 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
716 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
717 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
718 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
719 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
720 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
721 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
722 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
723 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
724 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
725 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
726 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
727 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
728 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
731 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
732 enum {
733 /* DSP Compare-Pick Sub-class */
734 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
735 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
736 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
737 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
738 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
739 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
740 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
741 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
742 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
743 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
744 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
745 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
746 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
747 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
748 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
749 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
750 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
751 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
752 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
753 /* MIPS DSP Arithmetic Sub-class */
754 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
755 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
756 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
764 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
765 enum {
766 /* DSP Append Sub-class */
767 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
768 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
769 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
770 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
773 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
774 enum {
775 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
776 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
777 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
778 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
779 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
780 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
781 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
782 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
783 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
784 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
785 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
786 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
787 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
788 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
789 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
790 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
791 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
792 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
793 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
794 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
795 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
796 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
799 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
800 enum {
801 /* DSP Bit/Manipulation Sub-class */
802 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
805 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
806 enum {
807 /* MIPS DSP Multiply Sub-class insns */
808 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
809 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
810 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
811 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
812 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
813 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
814 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
815 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
816 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
817 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
818 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
819 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
820 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
821 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
822 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
823 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
824 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
825 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
826 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
827 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
828 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
829 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
830 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
836 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
837 enum {
838 /* MIPS DSP GPR-Based Shift Sub-class */
839 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
840 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
841 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
842 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
843 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
844 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
845 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
846 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
847 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
848 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
849 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
850 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
851 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
852 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
853 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
854 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
855 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
856 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
857 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
858 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
859 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
860 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
861 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
867 /* Coprocessor 0 (rs field) */
868 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
870 enum {
871 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
872 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
873 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
874 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
875 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
876 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
877 OPC_MFTR = (0x08 << 21) | OPC_CP0,
878 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
879 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
880 OPC_MTTR = (0x0C << 21) | OPC_CP0,
881 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
882 OPC_C0 = (0x10 << 21) | OPC_CP0,
883 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
884 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
887 /* MFMC0 opcodes */
888 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
890 enum {
891 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
892 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
893 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
894 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
895 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
896 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
899 /* Coprocessor 0 (with rs == C0) */
900 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
902 enum {
903 OPC_TLBR = 0x01 | OPC_C0,
904 OPC_TLBWI = 0x02 | OPC_C0,
905 OPC_TLBINV = 0x03 | OPC_C0,
906 OPC_TLBINVF = 0x04 | OPC_C0,
907 OPC_TLBWR = 0x06 | OPC_C0,
908 OPC_TLBP = 0x08 | OPC_C0,
909 OPC_RFE = 0x10 | OPC_C0,
910 OPC_ERET = 0x18 | OPC_C0,
911 OPC_DERET = 0x1F | OPC_C0,
912 OPC_WAIT = 0x20 | OPC_C0,
915 /* Coprocessor 1 (rs field) */
916 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
918 /* Values for the fmt field in FP instructions */
919 enum {
920 /* 0 - 15 are reserved */
921 FMT_S = 16, /* single fp */
922 FMT_D = 17, /* double fp */
923 FMT_E = 18, /* extended fp */
924 FMT_Q = 19, /* quad fp */
925 FMT_W = 20, /* 32-bit fixed */
926 FMT_L = 21, /* 64-bit fixed */
927 FMT_PS = 22, /* paired single fp */
928 /* 23 - 31 are reserved */
931 enum {
932 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
933 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
934 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
935 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
936 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
937 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
938 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
939 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
940 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
941 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
942 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
943 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
944 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
945 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
946 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
947 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
948 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
949 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
950 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
951 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
952 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
953 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
954 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
955 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
956 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
957 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
958 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
959 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
960 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
961 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
964 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
965 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
967 enum {
968 OPC_BC1F = (0x00 << 16) | OPC_BC1,
969 OPC_BC1T = (0x01 << 16) | OPC_BC1,
970 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
971 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
974 enum {
975 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
976 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
979 enum {
980 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
981 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
984 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
986 enum {
987 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
988 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
989 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
990 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
991 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
992 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
993 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
994 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
995 OPC_BC2 = (0x08 << 21) | OPC_CP2,
996 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
997 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1000 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1002 enum {
1003 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1004 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1005 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1006 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1007 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1008 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1009 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1010 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1012 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1013 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1014 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1015 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1016 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1017 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1018 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1019 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1021 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1022 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1023 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1024 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1025 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1026 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1027 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1028 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1030 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1031 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1032 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1033 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1034 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1035 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1036 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1037 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1039 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1040 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1041 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1042 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1043 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1044 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1046 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1047 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1048 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1049 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1050 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1051 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1053 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1054 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1055 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1056 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1057 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1058 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1060 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1061 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1062 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1063 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1064 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1065 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1067 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1068 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1069 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1070 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1071 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1072 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1074 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1075 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1076 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1077 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1078 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1079 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1081 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1082 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1083 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1084 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1085 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1086 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1088 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1089 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1090 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1091 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1092 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1093 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1097 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1099 enum {
1100 OPC_LWXC1 = 0x00 | OPC_CP3,
1101 OPC_LDXC1 = 0x01 | OPC_CP3,
1102 OPC_LUXC1 = 0x05 | OPC_CP3,
1103 OPC_SWXC1 = 0x08 | OPC_CP3,
1104 OPC_SDXC1 = 0x09 | OPC_CP3,
1105 OPC_SUXC1 = 0x0D | OPC_CP3,
1106 OPC_PREFX = 0x0F | OPC_CP3,
1107 OPC_ALNV_PS = 0x1E | OPC_CP3,
1108 OPC_MADD_S = 0x20 | OPC_CP3,
1109 OPC_MADD_D = 0x21 | OPC_CP3,
1110 OPC_MADD_PS = 0x26 | OPC_CP3,
1111 OPC_MSUB_S = 0x28 | OPC_CP3,
1112 OPC_MSUB_D = 0x29 | OPC_CP3,
1113 OPC_MSUB_PS = 0x2E | OPC_CP3,
1114 OPC_NMADD_S = 0x30 | OPC_CP3,
1115 OPC_NMADD_D = 0x31 | OPC_CP3,
1116 OPC_NMADD_PS= 0x36 | OPC_CP3,
1117 OPC_NMSUB_S = 0x38 | OPC_CP3,
1118 OPC_NMSUB_D = 0x39 | OPC_CP3,
1119 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1122 /* MSA Opcodes */
1123 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1124 enum {
1125 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1126 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1127 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1128 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1129 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1130 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1131 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1132 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1133 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1134 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1135 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1136 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1137 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1138 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1139 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1140 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1141 OPC_MSA_ELM = 0x19 | OPC_MSA,
1142 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1143 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1144 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1145 OPC_MSA_VEC = 0x1E | OPC_MSA,
1147 /* MI10 instruction */
1148 OPC_LD_B = (0x20) | OPC_MSA,
1149 OPC_LD_H = (0x21) | OPC_MSA,
1150 OPC_LD_W = (0x22) | OPC_MSA,
1151 OPC_LD_D = (0x23) | OPC_MSA,
1152 OPC_ST_B = (0x24) | OPC_MSA,
1153 OPC_ST_H = (0x25) | OPC_MSA,
1154 OPC_ST_W = (0x26) | OPC_MSA,
1155 OPC_ST_D = (0x27) | OPC_MSA,
1158 enum {
1159 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1160 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1161 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1162 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1163 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1164 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1165 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1166 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1167 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1168 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1169 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1170 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1171 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1173 /* I8 instruction */
1174 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1175 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1176 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1177 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1178 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1179 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1180 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1181 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1182 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1183 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1185 /* VEC/2R/2RF instruction */
1186 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1187 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1188 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1189 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1190 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1191 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1192 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1194 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1195 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1197 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1198 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1199 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1200 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1201 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1203 /* 2RF instruction df(bit 16) = _w, _d */
1204 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1205 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1206 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1207 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1208 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1209 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1210 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1211 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1212 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1213 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1214 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1215 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1216 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1217 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1218 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1219 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1221 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1222 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1223 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1224 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1225 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1226 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1227 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1228 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1229 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1230 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1231 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1232 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1233 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1234 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1235 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1236 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1237 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1238 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1239 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1240 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1241 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1242 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1243 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1244 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1245 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1246 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1247 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1248 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1249 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1250 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1251 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1252 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1253 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1254 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1255 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1256 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1257 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1258 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1259 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1260 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1261 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1262 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1263 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1264 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1265 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1266 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1267 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1268 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1269 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1270 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1271 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1272 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1273 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1274 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1275 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1276 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1277 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1278 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1279 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1280 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1281 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1282 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1283 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1284 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1286 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1287 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1288 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1289 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1290 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1291 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1292 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1293 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1294 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1295 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1297 /* 3RF instruction _df(bit 21) = _w, _d */
1298 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1299 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1300 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1301 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1302 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1303 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1304 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1305 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1306 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1307 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1308 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1309 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1310 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1311 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1312 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1313 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1314 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1315 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1316 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1317 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1318 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1319 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1320 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1321 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1322 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1323 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1324 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1325 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1326 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1327 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1328 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1329 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1330 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1331 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1332 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1333 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1334 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1335 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1336 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1337 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1338 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1340 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1341 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1342 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1343 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1344 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1345 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1346 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1347 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1348 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1349 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1350 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1351 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1352 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1355 /* global register indices */
1356 static TCGv_ptr cpu_env;
1357 static TCGv cpu_gpr[32], cpu_PC;
1358 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1359 static TCGv cpu_dspctrl, btarget, bcond;
1360 static TCGv_i32 hflags;
1361 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1362 static TCGv_i64 fpu_f64[32];
1363 static TCGv_i64 msa_wr_d[64];
1365 #include "exec/gen-icount.h"
1367 #define gen_helper_0e0i(name, arg) do { \
1368 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1369 gen_helper_##name(cpu_env, helper_tmp); \
1370 tcg_temp_free_i32(helper_tmp); \
1371 } while(0)
1373 #define gen_helper_0e1i(name, arg1, arg2) do { \
1374 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1375 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1376 tcg_temp_free_i32(helper_tmp); \
1377 } while(0)
1379 #define gen_helper_1e0i(name, ret, arg1) do { \
1380 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1381 gen_helper_##name(ret, cpu_env, helper_tmp); \
1382 tcg_temp_free_i32(helper_tmp); \
1383 } while(0)
1385 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1386 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1387 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1388 tcg_temp_free_i32(helper_tmp); \
1389 } while(0)
1391 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1392 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1393 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1394 tcg_temp_free_i32(helper_tmp); \
1395 } while(0)
1397 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1398 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1399 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1400 tcg_temp_free_i32(helper_tmp); \
1401 } while(0)
1403 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1404 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1405 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1406 tcg_temp_free_i32(helper_tmp); \
1407 } while(0)
1409 typedef struct DisasContext {
1410 struct TranslationBlock *tb;
1411 target_ulong pc, saved_pc;
1412 uint32_t opcode;
1413 int singlestep_enabled;
1414 int insn_flags;
1415 int32_t CP0_Config1;
1416 /* Routine used to access memory */
1417 int mem_idx;
1418 TCGMemOp default_tcg_memop_mask;
1419 uint32_t hflags, saved_hflags;
1420 int bstate;
1421 target_ulong btarget;
1422 bool ulri;
1423 int kscrexist;
1424 bool rxi;
1425 int ie;
1426 bool bi;
1427 bool bp;
1428 uint64_t PAMask;
1429 bool mvh;
1430 int CP0_LLAddr_shift;
1431 bool ps;
1432 } DisasContext;
1434 enum {
1435 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1436 * exception condition */
1437 BS_STOP = 1, /* We want to stop translation for any reason */
1438 BS_BRANCH = 2, /* We reached a branch condition */
1439 BS_EXCP = 3, /* We reached an exception condition */
1442 static const char * const regnames[] = {
1443 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1444 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1445 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1446 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1449 static const char * const regnames_HI[] = {
1450 "HI0", "HI1", "HI2", "HI3",
1453 static const char * const regnames_LO[] = {
1454 "LO0", "LO1", "LO2", "LO3",
1457 static const char * const fregnames[] = {
1458 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1459 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1460 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1461 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1464 static const char * const msaregnames[] = {
1465 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1466 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1467 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1468 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1469 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1470 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1471 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1472 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1473 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1474 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1475 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1476 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1477 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1478 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1479 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1480 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1483 #define LOG_DISAS(...) \
1484 do { \
1485 if (MIPS_DEBUG_DISAS) { \
1486 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1488 } while (0)
1490 #define MIPS_INVAL(op) \
1491 do { \
1492 if (MIPS_DEBUG_DISAS) { \
1493 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1494 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
1495 ctx->pc, ctx->opcode, op, ctx->opcode >> 26, \
1496 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
1498 } while (0)
1500 /* General purpose registers moves. */
1501 static inline void gen_load_gpr (TCGv t, int reg)
1503 if (reg == 0)
1504 tcg_gen_movi_tl(t, 0);
1505 else
1506 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1509 static inline void gen_store_gpr (TCGv t, int reg)
1511 if (reg != 0)
1512 tcg_gen_mov_tl(cpu_gpr[reg], t);
1515 /* Moves to/from shadow registers. */
1516 static inline void gen_load_srsgpr (int from, int to)
1518 TCGv t0 = tcg_temp_new();
1520 if (from == 0)
1521 tcg_gen_movi_tl(t0, 0);
1522 else {
1523 TCGv_i32 t2 = tcg_temp_new_i32();
1524 TCGv_ptr addr = tcg_temp_new_ptr();
1526 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1527 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1528 tcg_gen_andi_i32(t2, t2, 0xf);
1529 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1530 tcg_gen_ext_i32_ptr(addr, t2);
1531 tcg_gen_add_ptr(addr, cpu_env, addr);
1533 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1534 tcg_temp_free_ptr(addr);
1535 tcg_temp_free_i32(t2);
1537 gen_store_gpr(t0, to);
1538 tcg_temp_free(t0);
1541 static inline void gen_store_srsgpr (int from, int to)
1543 if (to != 0) {
1544 TCGv t0 = tcg_temp_new();
1545 TCGv_i32 t2 = tcg_temp_new_i32();
1546 TCGv_ptr addr = tcg_temp_new_ptr();
1548 gen_load_gpr(t0, from);
1549 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1550 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1551 tcg_gen_andi_i32(t2, t2, 0xf);
1552 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1553 tcg_gen_ext_i32_ptr(addr, t2);
1554 tcg_gen_add_ptr(addr, cpu_env, addr);
1556 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1557 tcg_temp_free_ptr(addr);
1558 tcg_temp_free_i32(t2);
1559 tcg_temp_free(t0);
1563 /* Tests */
1564 static inline void gen_save_pc(target_ulong pc)
1566 tcg_gen_movi_tl(cpu_PC, pc);
1569 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1571 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1572 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1573 gen_save_pc(ctx->pc);
1574 ctx->saved_pc = ctx->pc;
1576 if (ctx->hflags != ctx->saved_hflags) {
1577 tcg_gen_movi_i32(hflags, ctx->hflags);
1578 ctx->saved_hflags = ctx->hflags;
1579 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1580 case MIPS_HFLAG_BR:
1581 break;
1582 case MIPS_HFLAG_BC:
1583 case MIPS_HFLAG_BL:
1584 case MIPS_HFLAG_B:
1585 tcg_gen_movi_tl(btarget, ctx->btarget);
1586 break;
1591 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1593 ctx->saved_hflags = ctx->hflags;
1594 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1595 case MIPS_HFLAG_BR:
1596 break;
1597 case MIPS_HFLAG_BC:
1598 case MIPS_HFLAG_BL:
1599 case MIPS_HFLAG_B:
1600 ctx->btarget = env->btarget;
1601 break;
1605 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1607 TCGv_i32 texcp = tcg_const_i32(excp);
1608 TCGv_i32 terr = tcg_const_i32(err);
1609 save_cpu_state(ctx, 1);
1610 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1611 tcg_temp_free_i32(terr);
1612 tcg_temp_free_i32(texcp);
1613 ctx->bstate = BS_EXCP;
1616 static inline void generate_exception(DisasContext *ctx, int excp)
1618 gen_helper_0e0i(raise_exception, excp);
1621 static inline void generate_exception_end(DisasContext *ctx, int excp)
1623 generate_exception_err(ctx, excp, 0);
1626 /* Floating point register moves. */
1627 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1629 if (ctx->hflags & MIPS_HFLAG_FRE) {
1630 generate_exception(ctx, EXCP_RI);
1632 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1635 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1637 TCGv_i64 t64;
1638 if (ctx->hflags & MIPS_HFLAG_FRE) {
1639 generate_exception(ctx, EXCP_RI);
1641 t64 = tcg_temp_new_i64();
1642 tcg_gen_extu_i32_i64(t64, t);
1643 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1644 tcg_temp_free_i64(t64);
1647 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1649 if (ctx->hflags & MIPS_HFLAG_F64) {
1650 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1651 } else {
1652 gen_load_fpr32(ctx, t, reg | 1);
1656 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1658 if (ctx->hflags & MIPS_HFLAG_F64) {
1659 TCGv_i64 t64 = tcg_temp_new_i64();
1660 tcg_gen_extu_i32_i64(t64, t);
1661 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1662 tcg_temp_free_i64(t64);
1663 } else {
1664 gen_store_fpr32(ctx, t, reg | 1);
1668 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1670 if (ctx->hflags & MIPS_HFLAG_F64) {
1671 tcg_gen_mov_i64(t, fpu_f64[reg]);
1672 } else {
1673 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1677 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1679 if (ctx->hflags & MIPS_HFLAG_F64) {
1680 tcg_gen_mov_i64(fpu_f64[reg], t);
1681 } else {
1682 TCGv_i64 t0;
1683 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1684 t0 = tcg_temp_new_i64();
1685 tcg_gen_shri_i64(t0, t, 32);
1686 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1687 tcg_temp_free_i64(t0);
1691 static inline int get_fp_bit (int cc)
1693 if (cc)
1694 return 24 + cc;
1695 else
1696 return 23;
1699 /* Addresses computation */
1700 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1702 tcg_gen_add_tl(ret, arg0, arg1);
1704 #if defined(TARGET_MIPS64)
1705 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1706 tcg_gen_ext32s_i64(ret, ret);
1708 #endif
1711 /* Addresses computation (translation time) */
1712 static target_long addr_add(DisasContext *ctx, target_long base,
1713 target_long offset)
1715 target_long sum = base + offset;
1717 #if defined(TARGET_MIPS64)
1718 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1719 sum = (int32_t)sum;
1721 #endif
1722 return sum;
1725 /* Sign-extract the low 32-bits to a target_long. */
1726 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
1728 #if defined(TARGET_MIPS64)
1729 tcg_gen_ext32s_i64(ret, arg);
1730 #else
1731 tcg_gen_extrl_i64_i32(ret, arg);
1732 #endif
1735 /* Sign-extract the high 32-bits to a target_long. */
1736 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
1738 #if defined(TARGET_MIPS64)
1739 tcg_gen_sari_i64(ret, arg, 32);
1740 #else
1741 tcg_gen_extrh_i64_i32(ret, arg);
1742 #endif
1745 static inline void check_cp0_enabled(DisasContext *ctx)
1747 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1748 generate_exception_err(ctx, EXCP_CpU, 0);
1751 static inline void check_cp1_enabled(DisasContext *ctx)
1753 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1754 generate_exception_err(ctx, EXCP_CpU, 1);
1757 /* Verify that the processor is running with COP1X instructions enabled.
1758 This is associated with the nabla symbol in the MIPS32 and MIPS64
1759 opcode tables. */
1761 static inline void check_cop1x(DisasContext *ctx)
1763 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1764 generate_exception_end(ctx, EXCP_RI);
1767 /* Verify that the processor is running with 64-bit floating-point
1768 operations enabled. */
1770 static inline void check_cp1_64bitmode(DisasContext *ctx)
1772 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1773 generate_exception_end(ctx, EXCP_RI);
1777 * Verify if floating point register is valid; an operation is not defined
1778 * if bit 0 of any register specification is set and the FR bit in the
1779 * Status register equals zero, since the register numbers specify an
1780 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1781 * in the Status register equals one, both even and odd register numbers
1782 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1784 * Multiple 64 bit wide registers can be checked by calling
1785 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1787 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1789 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1790 generate_exception_end(ctx, EXCP_RI);
1793 /* Verify that the processor is running with DSP instructions enabled.
1794 This is enabled by CP0 Status register MX(24) bit.
1797 static inline void check_dsp(DisasContext *ctx)
1799 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1800 if (ctx->insn_flags & ASE_DSP) {
1801 generate_exception_end(ctx, EXCP_DSPDIS);
1802 } else {
1803 generate_exception_end(ctx, EXCP_RI);
1808 static inline void check_dspr2(DisasContext *ctx)
1810 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1811 if (ctx->insn_flags & ASE_DSP) {
1812 generate_exception_end(ctx, EXCP_DSPDIS);
1813 } else {
1814 generate_exception_end(ctx, EXCP_RI);
1819 /* This code generates a "reserved instruction" exception if the
1820 CPU does not support the instruction set corresponding to flags. */
1821 static inline void check_insn(DisasContext *ctx, int flags)
1823 if (unlikely(!(ctx->insn_flags & flags))) {
1824 generate_exception_end(ctx, EXCP_RI);
1828 /* This code generates a "reserved instruction" exception if the
1829 CPU has corresponding flag set which indicates that the instruction
1830 has been removed. */
1831 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1833 if (unlikely(ctx->insn_flags & flags)) {
1834 generate_exception_end(ctx, EXCP_RI);
1838 /* This code generates a "reserved instruction" exception if the
1839 CPU does not support 64-bit paired-single (PS) floating point data type */
1840 static inline void check_ps(DisasContext *ctx)
1842 if (unlikely(!ctx->ps)) {
1843 generate_exception(ctx, EXCP_RI);
1845 check_cp1_64bitmode(ctx);
1848 #ifdef TARGET_MIPS64
1849 /* This code generates a "reserved instruction" exception if 64-bit
1850 instructions are not enabled. */
1851 static inline void check_mips_64(DisasContext *ctx)
1853 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1854 generate_exception_end(ctx, EXCP_RI);
1856 #endif
1858 #ifndef CONFIG_USER_ONLY
1859 static inline void check_mvh(DisasContext *ctx)
1861 if (unlikely(!ctx->mvh)) {
1862 generate_exception(ctx, EXCP_RI);
1865 #endif
1867 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1868 calling interface for 32 and 64-bit FPRs. No sense in changing
1869 all callers for gen_load_fpr32 when we need the CTX parameter for
1870 this one use. */
1871 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1872 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1873 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1874 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1875 int ft, int fs, int cc) \
1877 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1878 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1879 switch (ifmt) { \
1880 case FMT_PS: \
1881 check_ps(ctx); \
1882 break; \
1883 case FMT_D: \
1884 if (abs) { \
1885 check_cop1x(ctx); \
1887 check_cp1_registers(ctx, fs | ft); \
1888 break; \
1889 case FMT_S: \
1890 if (abs) { \
1891 check_cop1x(ctx); \
1893 break; \
1895 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1896 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1897 switch (n) { \
1898 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1899 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1900 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1901 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1902 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1903 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1904 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1905 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1906 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1907 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1908 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1909 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1910 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1911 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1912 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1913 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1914 default: abort(); \
1916 tcg_temp_free_i##bits (fp0); \
1917 tcg_temp_free_i##bits (fp1); \
1920 FOP_CONDS(, 0, d, FMT_D, 64)
1921 FOP_CONDS(abs, 1, d, FMT_D, 64)
1922 FOP_CONDS(, 0, s, FMT_S, 32)
1923 FOP_CONDS(abs, 1, s, FMT_S, 32)
1924 FOP_CONDS(, 0, ps, FMT_PS, 64)
1925 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1926 #undef FOP_CONDS
1928 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1929 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1930 int ft, int fs, int fd) \
1932 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1933 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1934 if (ifmt == FMT_D) { \
1935 check_cp1_registers(ctx, fs | ft | fd); \
1937 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1938 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1939 switch (n) { \
1940 case 0: \
1941 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1942 break; \
1943 case 1: \
1944 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1945 break; \
1946 case 2: \
1947 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1948 break; \
1949 case 3: \
1950 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1951 break; \
1952 case 4: \
1953 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1954 break; \
1955 case 5: \
1956 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1957 break; \
1958 case 6: \
1959 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1960 break; \
1961 case 7: \
1962 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1963 break; \
1964 case 8: \
1965 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1966 break; \
1967 case 9: \
1968 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1969 break; \
1970 case 10: \
1971 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1972 break; \
1973 case 11: \
1974 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1975 break; \
1976 case 12: \
1977 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1978 break; \
1979 case 13: \
1980 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1981 break; \
1982 case 14: \
1983 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1984 break; \
1985 case 15: \
1986 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1987 break; \
1988 case 17: \
1989 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1990 break; \
1991 case 18: \
1992 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1993 break; \
1994 case 19: \
1995 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1996 break; \
1997 case 25: \
1998 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1999 break; \
2000 case 26: \
2001 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2002 break; \
2003 case 27: \
2004 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2005 break; \
2006 default: \
2007 abort(); \
2009 STORE; \
2010 tcg_temp_free_i ## bits (fp0); \
2011 tcg_temp_free_i ## bits (fp1); \
2014 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2015 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2016 #undef FOP_CONDNS
2017 #undef gen_ldcmp_fpr32
2018 #undef gen_ldcmp_fpr64
2020 /* load/store instructions. */
2021 #ifdef CONFIG_USER_ONLY
2022 #define OP_LD_ATOMIC(insn,fname) \
2023 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2025 TCGv t0 = tcg_temp_new(); \
2026 tcg_gen_mov_tl(t0, arg1); \
2027 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2028 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2029 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2030 tcg_temp_free(t0); \
2032 #else
2033 #define OP_LD_ATOMIC(insn,fname) \
2034 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2036 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
2038 #endif
2039 OP_LD_ATOMIC(ll,ld32s);
2040 #if defined(TARGET_MIPS64)
2041 OP_LD_ATOMIC(lld,ld64);
2042 #endif
2043 #undef OP_LD_ATOMIC
2045 #ifdef CONFIG_USER_ONLY
2046 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2047 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2049 TCGv t0 = tcg_temp_new(); \
2050 TCGLabel *l1 = gen_new_label(); \
2051 TCGLabel *l2 = gen_new_label(); \
2053 tcg_gen_andi_tl(t0, arg2, almask); \
2054 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2055 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2056 generate_exception(ctx, EXCP_AdES); \
2057 gen_set_label(l1); \
2058 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2059 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2060 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2061 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2062 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2063 generate_exception_end(ctx, EXCP_SC); \
2064 gen_set_label(l2); \
2065 tcg_gen_movi_tl(t0, 0); \
2066 gen_store_gpr(t0, rt); \
2067 tcg_temp_free(t0); \
2069 #else
2070 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2071 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2073 TCGv t0 = tcg_temp_new(); \
2074 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
2075 gen_store_gpr(t0, rt); \
2076 tcg_temp_free(t0); \
2078 #endif
2079 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2080 #if defined(TARGET_MIPS64)
2081 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2082 #endif
2083 #undef OP_ST_ATOMIC
2085 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2086 int base, int16_t offset)
2088 if (base == 0) {
2089 tcg_gen_movi_tl(addr, offset);
2090 } else if (offset == 0) {
2091 gen_load_gpr(addr, base);
2092 } else {
2093 tcg_gen_movi_tl(addr, offset);
2094 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2098 static target_ulong pc_relative_pc (DisasContext *ctx)
2100 target_ulong pc = ctx->pc;
2102 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2103 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2105 pc -= branch_bytes;
2108 pc &= ~(target_ulong)3;
2109 return pc;
2112 /* Load */
2113 static void gen_ld(DisasContext *ctx, uint32_t opc,
2114 int rt, int base, int16_t offset)
2116 TCGv t0, t1, t2;
2118 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2119 /* Loongson CPU uses a load to zero register for prefetch.
2120 We emulate it as a NOP. On other CPU we must perform the
2121 actual memory access. */
2122 return;
2125 t0 = tcg_temp_new();
2126 gen_base_offset_addr(ctx, t0, base, offset);
2128 switch (opc) {
2129 #if defined(TARGET_MIPS64)
2130 case OPC_LWU:
2131 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL |
2132 ctx->default_tcg_memop_mask);
2133 gen_store_gpr(t0, rt);
2134 break;
2135 case OPC_LD:
2136 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
2137 ctx->default_tcg_memop_mask);
2138 gen_store_gpr(t0, rt);
2139 break;
2140 case OPC_LLD:
2141 case R6_OPC_LLD:
2142 op_ld_lld(t0, t0, ctx);
2143 gen_store_gpr(t0, rt);
2144 break;
2145 case OPC_LDL:
2146 t1 = tcg_temp_new();
2147 /* Do a byte access to possibly trigger a page
2148 fault with the unaligned address. */
2149 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2150 tcg_gen_andi_tl(t1, t0, 7);
2151 #ifndef TARGET_WORDS_BIGENDIAN
2152 tcg_gen_xori_tl(t1, t1, 7);
2153 #endif
2154 tcg_gen_shli_tl(t1, t1, 3);
2155 tcg_gen_andi_tl(t0, t0, ~7);
2156 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2157 tcg_gen_shl_tl(t0, t0, t1);
2158 t2 = tcg_const_tl(-1);
2159 tcg_gen_shl_tl(t2, t2, t1);
2160 gen_load_gpr(t1, rt);
2161 tcg_gen_andc_tl(t1, t1, t2);
2162 tcg_temp_free(t2);
2163 tcg_gen_or_tl(t0, t0, t1);
2164 tcg_temp_free(t1);
2165 gen_store_gpr(t0, rt);
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 break;
2190 case OPC_LDPC:
2191 t1 = tcg_const_tl(pc_relative_pc(ctx));
2192 gen_op_addr_add(ctx, t0, t0, t1);
2193 tcg_temp_free(t1);
2194 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2195 gen_store_gpr(t0, rt);
2196 break;
2197 #endif
2198 case OPC_LWPC:
2199 t1 = tcg_const_tl(pc_relative_pc(ctx));
2200 gen_op_addr_add(ctx, t0, t0, t1);
2201 tcg_temp_free(t1);
2202 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2203 gen_store_gpr(t0, rt);
2204 break;
2205 case OPC_LW:
2206 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
2207 ctx->default_tcg_memop_mask);
2208 gen_store_gpr(t0, rt);
2209 break;
2210 case OPC_LH:
2211 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
2212 ctx->default_tcg_memop_mask);
2213 gen_store_gpr(t0, rt);
2214 break;
2215 case OPC_LHU:
2216 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW |
2217 ctx->default_tcg_memop_mask);
2218 gen_store_gpr(t0, rt);
2219 break;
2220 case OPC_LB:
2221 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
2222 gen_store_gpr(t0, rt);
2223 break;
2224 case OPC_LBU:
2225 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
2226 gen_store_gpr(t0, rt);
2227 break;
2228 case OPC_LWL:
2229 t1 = tcg_temp_new();
2230 /* Do a byte access to possibly trigger a page
2231 fault with the unaligned address. */
2232 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2233 tcg_gen_andi_tl(t1, t0, 3);
2234 #ifndef TARGET_WORDS_BIGENDIAN
2235 tcg_gen_xori_tl(t1, t1, 3);
2236 #endif
2237 tcg_gen_shli_tl(t1, t1, 3);
2238 tcg_gen_andi_tl(t0, t0, ~3);
2239 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2240 tcg_gen_shl_tl(t0, t0, t1);
2241 t2 = tcg_const_tl(-1);
2242 tcg_gen_shl_tl(t2, t2, t1);
2243 gen_load_gpr(t1, rt);
2244 tcg_gen_andc_tl(t1, t1, t2);
2245 tcg_temp_free(t2);
2246 tcg_gen_or_tl(t0, t0, t1);
2247 tcg_temp_free(t1);
2248 tcg_gen_ext32s_tl(t0, t0);
2249 gen_store_gpr(t0, rt);
2250 break;
2251 case OPC_LWR:
2252 t1 = tcg_temp_new();
2253 /* Do a byte access to possibly trigger a page
2254 fault with the unaligned address. */
2255 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2256 tcg_gen_andi_tl(t1, t0, 3);
2257 #ifdef TARGET_WORDS_BIGENDIAN
2258 tcg_gen_xori_tl(t1, t1, 3);
2259 #endif
2260 tcg_gen_shli_tl(t1, t1, 3);
2261 tcg_gen_andi_tl(t0, t0, ~3);
2262 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2263 tcg_gen_shr_tl(t0, t0, t1);
2264 tcg_gen_xori_tl(t1, t1, 31);
2265 t2 = tcg_const_tl(0xfffffffeull);
2266 tcg_gen_shl_tl(t2, t2, t1);
2267 gen_load_gpr(t1, rt);
2268 tcg_gen_and_tl(t1, t1, t2);
2269 tcg_temp_free(t2);
2270 tcg_gen_or_tl(t0, t0, t1);
2271 tcg_temp_free(t1);
2272 tcg_gen_ext32s_tl(t0, t0);
2273 gen_store_gpr(t0, rt);
2274 break;
2275 case OPC_LL:
2276 case R6_OPC_LL:
2277 op_ld_ll(t0, t0, ctx);
2278 gen_store_gpr(t0, rt);
2279 break;
2281 tcg_temp_free(t0);
2284 /* Store */
2285 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2286 int base, int16_t offset)
2288 TCGv t0 = tcg_temp_new();
2289 TCGv t1 = tcg_temp_new();
2291 gen_base_offset_addr(ctx, t0, base, offset);
2292 gen_load_gpr(t1, rt);
2293 switch (opc) {
2294 #if defined(TARGET_MIPS64)
2295 case OPC_SD:
2296 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
2297 ctx->default_tcg_memop_mask);
2298 break;
2299 case OPC_SDL:
2300 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
2301 break;
2302 case OPC_SDR:
2303 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
2304 break;
2305 #endif
2306 case OPC_SW:
2307 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
2308 ctx->default_tcg_memop_mask);
2309 break;
2310 case OPC_SH:
2311 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
2312 ctx->default_tcg_memop_mask);
2313 break;
2314 case OPC_SB:
2315 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2316 break;
2317 case OPC_SWL:
2318 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2319 break;
2320 case OPC_SWR:
2321 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2322 break;
2324 tcg_temp_free(t0);
2325 tcg_temp_free(t1);
2329 /* Store conditional */
2330 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2331 int base, int16_t offset)
2333 TCGv t0, t1;
2335 #ifdef CONFIG_USER_ONLY
2336 t0 = tcg_temp_local_new();
2337 t1 = tcg_temp_local_new();
2338 #else
2339 t0 = tcg_temp_new();
2340 t1 = tcg_temp_new();
2341 #endif
2342 gen_base_offset_addr(ctx, t0, base, offset);
2343 gen_load_gpr(t1, rt);
2344 switch (opc) {
2345 #if defined(TARGET_MIPS64)
2346 case OPC_SCD:
2347 case R6_OPC_SCD:
2348 op_st_scd(t1, t0, rt, ctx);
2349 break;
2350 #endif
2351 case OPC_SC:
2352 case R6_OPC_SC:
2353 op_st_sc(t1, t0, rt, ctx);
2354 break;
2356 tcg_temp_free(t1);
2357 tcg_temp_free(t0);
2360 /* Load and store */
2361 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2362 int base, int16_t offset)
2364 TCGv t0 = tcg_temp_new();
2366 gen_base_offset_addr(ctx, t0, base, offset);
2367 /* Don't do NOP if destination is zero: we must perform the actual
2368 memory access. */
2369 switch (opc) {
2370 case OPC_LWC1:
2372 TCGv_i32 fp0 = tcg_temp_new_i32();
2373 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2374 ctx->default_tcg_memop_mask);
2375 gen_store_fpr32(ctx, fp0, ft);
2376 tcg_temp_free_i32(fp0);
2378 break;
2379 case OPC_SWC1:
2381 TCGv_i32 fp0 = tcg_temp_new_i32();
2382 gen_load_fpr32(ctx, fp0, ft);
2383 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2384 ctx->default_tcg_memop_mask);
2385 tcg_temp_free_i32(fp0);
2387 break;
2388 case OPC_LDC1:
2390 TCGv_i64 fp0 = tcg_temp_new_i64();
2391 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2392 ctx->default_tcg_memop_mask);
2393 gen_store_fpr64(ctx, fp0, ft);
2394 tcg_temp_free_i64(fp0);
2396 break;
2397 case OPC_SDC1:
2399 TCGv_i64 fp0 = tcg_temp_new_i64();
2400 gen_load_fpr64(ctx, fp0, ft);
2401 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2402 ctx->default_tcg_memop_mask);
2403 tcg_temp_free_i64(fp0);
2405 break;
2406 default:
2407 MIPS_INVAL("flt_ldst");
2408 generate_exception_end(ctx, EXCP_RI);
2409 goto out;
2411 out:
2412 tcg_temp_free(t0);
2415 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2416 int rs, int16_t imm)
2418 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2419 check_cp1_enabled(ctx);
2420 switch (op) {
2421 case OPC_LDC1:
2422 case OPC_SDC1:
2423 check_insn(ctx, ISA_MIPS2);
2424 /* Fallthrough */
2425 default:
2426 gen_flt_ldst(ctx, op, rt, rs, imm);
2428 } else {
2429 generate_exception_err(ctx, EXCP_CpU, 1);
2433 /* Arithmetic with immediate operand */
2434 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2435 int rt, int rs, int16_t imm)
2437 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2439 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2440 /* If no destination, treat it as a NOP.
2441 For addi, we must generate the overflow exception when needed. */
2442 return;
2444 switch (opc) {
2445 case OPC_ADDI:
2447 TCGv t0 = tcg_temp_local_new();
2448 TCGv t1 = tcg_temp_new();
2449 TCGv t2 = tcg_temp_new();
2450 TCGLabel *l1 = gen_new_label();
2452 gen_load_gpr(t1, rs);
2453 tcg_gen_addi_tl(t0, t1, uimm);
2454 tcg_gen_ext32s_tl(t0, t0);
2456 tcg_gen_xori_tl(t1, t1, ~uimm);
2457 tcg_gen_xori_tl(t2, t0, uimm);
2458 tcg_gen_and_tl(t1, t1, t2);
2459 tcg_temp_free(t2);
2460 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2461 tcg_temp_free(t1);
2462 /* operands of same sign, result different sign */
2463 generate_exception(ctx, EXCP_OVERFLOW);
2464 gen_set_label(l1);
2465 tcg_gen_ext32s_tl(t0, t0);
2466 gen_store_gpr(t0, rt);
2467 tcg_temp_free(t0);
2469 break;
2470 case OPC_ADDIU:
2471 if (rs != 0) {
2472 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2473 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2474 } else {
2475 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2477 break;
2478 #if defined(TARGET_MIPS64)
2479 case OPC_DADDI:
2481 TCGv t0 = tcg_temp_local_new();
2482 TCGv t1 = tcg_temp_new();
2483 TCGv t2 = tcg_temp_new();
2484 TCGLabel *l1 = gen_new_label();
2486 gen_load_gpr(t1, rs);
2487 tcg_gen_addi_tl(t0, t1, uimm);
2489 tcg_gen_xori_tl(t1, t1, ~uimm);
2490 tcg_gen_xori_tl(t2, t0, uimm);
2491 tcg_gen_and_tl(t1, t1, t2);
2492 tcg_temp_free(t2);
2493 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2494 tcg_temp_free(t1);
2495 /* operands of same sign, result different sign */
2496 generate_exception(ctx, EXCP_OVERFLOW);
2497 gen_set_label(l1);
2498 gen_store_gpr(t0, rt);
2499 tcg_temp_free(t0);
2501 break;
2502 case OPC_DADDIU:
2503 if (rs != 0) {
2504 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2505 } else {
2506 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2508 break;
2509 #endif
2513 /* Logic with immediate operand */
2514 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2515 int rt, int rs, int16_t imm)
2517 target_ulong uimm;
2519 if (rt == 0) {
2520 /* If no destination, treat it as a NOP. */
2521 return;
2523 uimm = (uint16_t)imm;
2524 switch (opc) {
2525 case OPC_ANDI:
2526 if (likely(rs != 0))
2527 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2528 else
2529 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2530 break;
2531 case OPC_ORI:
2532 if (rs != 0)
2533 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2534 else
2535 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2536 break;
2537 case OPC_XORI:
2538 if (likely(rs != 0))
2539 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2540 else
2541 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2542 break;
2543 case OPC_LUI:
2544 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2545 /* OPC_AUI */
2546 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2547 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2548 } else {
2549 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2551 break;
2553 default:
2554 break;
2558 /* Set on less than with immediate operand */
2559 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2560 int rt, int rs, int16_t imm)
2562 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2563 TCGv t0;
2565 if (rt == 0) {
2566 /* If no destination, treat it as a NOP. */
2567 return;
2569 t0 = tcg_temp_new();
2570 gen_load_gpr(t0, rs);
2571 switch (opc) {
2572 case OPC_SLTI:
2573 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2574 break;
2575 case OPC_SLTIU:
2576 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2577 break;
2579 tcg_temp_free(t0);
2582 /* Shifts with immediate operand */
2583 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2584 int rt, int rs, int16_t imm)
2586 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2587 TCGv t0;
2589 if (rt == 0) {
2590 /* If no destination, treat it as a NOP. */
2591 return;
2594 t0 = tcg_temp_new();
2595 gen_load_gpr(t0, rs);
2596 switch (opc) {
2597 case OPC_SLL:
2598 tcg_gen_shli_tl(t0, t0, uimm);
2599 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2600 break;
2601 case OPC_SRA:
2602 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2603 break;
2604 case OPC_SRL:
2605 if (uimm != 0) {
2606 tcg_gen_ext32u_tl(t0, t0);
2607 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2608 } else {
2609 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2611 break;
2612 case OPC_ROTR:
2613 if (uimm != 0) {
2614 TCGv_i32 t1 = tcg_temp_new_i32();
2616 tcg_gen_trunc_tl_i32(t1, t0);
2617 tcg_gen_rotri_i32(t1, t1, uimm);
2618 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2619 tcg_temp_free_i32(t1);
2620 } else {
2621 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2623 break;
2624 #if defined(TARGET_MIPS64)
2625 case OPC_DSLL:
2626 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2627 break;
2628 case OPC_DSRA:
2629 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2630 break;
2631 case OPC_DSRL:
2632 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2633 break;
2634 case OPC_DROTR:
2635 if (uimm != 0) {
2636 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2637 } else {
2638 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2640 break;
2641 case OPC_DSLL32:
2642 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2643 break;
2644 case OPC_DSRA32:
2645 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2646 break;
2647 case OPC_DSRL32:
2648 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2649 break;
2650 case OPC_DROTR32:
2651 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2652 break;
2653 #endif
2655 tcg_temp_free(t0);
2658 /* Arithmetic */
2659 static void gen_arith(DisasContext *ctx, uint32_t opc,
2660 int rd, int rs, int rt)
2662 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2663 && opc != OPC_DADD && opc != OPC_DSUB) {
2664 /* If no destination, treat it as a NOP.
2665 For add & sub, we must generate the overflow exception when needed. */
2666 return;
2669 switch (opc) {
2670 case OPC_ADD:
2672 TCGv t0 = tcg_temp_local_new();
2673 TCGv t1 = tcg_temp_new();
2674 TCGv t2 = tcg_temp_new();
2675 TCGLabel *l1 = gen_new_label();
2677 gen_load_gpr(t1, rs);
2678 gen_load_gpr(t2, rt);
2679 tcg_gen_add_tl(t0, t1, t2);
2680 tcg_gen_ext32s_tl(t0, t0);
2681 tcg_gen_xor_tl(t1, t1, t2);
2682 tcg_gen_xor_tl(t2, t0, t2);
2683 tcg_gen_andc_tl(t1, t2, t1);
2684 tcg_temp_free(t2);
2685 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2686 tcg_temp_free(t1);
2687 /* operands of same sign, result different sign */
2688 generate_exception(ctx, EXCP_OVERFLOW);
2689 gen_set_label(l1);
2690 gen_store_gpr(t0, rd);
2691 tcg_temp_free(t0);
2693 break;
2694 case OPC_ADDU:
2695 if (rs != 0 && rt != 0) {
2696 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2697 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2698 } else if (rs == 0 && rt != 0) {
2699 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2700 } else if (rs != 0 && rt == 0) {
2701 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2702 } else {
2703 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2705 break;
2706 case OPC_SUB:
2708 TCGv t0 = tcg_temp_local_new();
2709 TCGv t1 = tcg_temp_new();
2710 TCGv t2 = tcg_temp_new();
2711 TCGLabel *l1 = gen_new_label();
2713 gen_load_gpr(t1, rs);
2714 gen_load_gpr(t2, rt);
2715 tcg_gen_sub_tl(t0, t1, t2);
2716 tcg_gen_ext32s_tl(t0, t0);
2717 tcg_gen_xor_tl(t2, t1, t2);
2718 tcg_gen_xor_tl(t1, t0, t1);
2719 tcg_gen_and_tl(t1, t1, t2);
2720 tcg_temp_free(t2);
2721 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2722 tcg_temp_free(t1);
2723 /* operands of different sign, first operand and result different sign */
2724 generate_exception(ctx, EXCP_OVERFLOW);
2725 gen_set_label(l1);
2726 gen_store_gpr(t0, rd);
2727 tcg_temp_free(t0);
2729 break;
2730 case OPC_SUBU:
2731 if (rs != 0 && rt != 0) {
2732 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2733 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2734 } else if (rs == 0 && rt != 0) {
2735 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2736 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2737 } else if (rs != 0 && rt == 0) {
2738 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2739 } else {
2740 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2742 break;
2743 #if defined(TARGET_MIPS64)
2744 case OPC_DADD:
2746 TCGv t0 = tcg_temp_local_new();
2747 TCGv t1 = tcg_temp_new();
2748 TCGv t2 = tcg_temp_new();
2749 TCGLabel *l1 = gen_new_label();
2751 gen_load_gpr(t1, rs);
2752 gen_load_gpr(t2, rt);
2753 tcg_gen_add_tl(t0, t1, t2);
2754 tcg_gen_xor_tl(t1, t1, t2);
2755 tcg_gen_xor_tl(t2, t0, t2);
2756 tcg_gen_andc_tl(t1, t2, t1);
2757 tcg_temp_free(t2);
2758 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2759 tcg_temp_free(t1);
2760 /* operands of same sign, result different sign */
2761 generate_exception(ctx, EXCP_OVERFLOW);
2762 gen_set_label(l1);
2763 gen_store_gpr(t0, rd);
2764 tcg_temp_free(t0);
2766 break;
2767 case OPC_DADDU:
2768 if (rs != 0 && rt != 0) {
2769 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2770 } else if (rs == 0 && rt != 0) {
2771 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2772 } else if (rs != 0 && rt == 0) {
2773 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2774 } else {
2775 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2777 break;
2778 case OPC_DSUB:
2780 TCGv t0 = tcg_temp_local_new();
2781 TCGv t1 = tcg_temp_new();
2782 TCGv t2 = tcg_temp_new();
2783 TCGLabel *l1 = gen_new_label();
2785 gen_load_gpr(t1, rs);
2786 gen_load_gpr(t2, rt);
2787 tcg_gen_sub_tl(t0, t1, t2);
2788 tcg_gen_xor_tl(t2, t1, t2);
2789 tcg_gen_xor_tl(t1, t0, t1);
2790 tcg_gen_and_tl(t1, t1, t2);
2791 tcg_temp_free(t2);
2792 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2793 tcg_temp_free(t1);
2794 /* operands of different sign, first operand and result different sign */
2795 generate_exception(ctx, EXCP_OVERFLOW);
2796 gen_set_label(l1);
2797 gen_store_gpr(t0, rd);
2798 tcg_temp_free(t0);
2800 break;
2801 case OPC_DSUBU:
2802 if (rs != 0 && rt != 0) {
2803 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2804 } else if (rs == 0 && rt != 0) {
2805 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2806 } else if (rs != 0 && rt == 0) {
2807 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2808 } else {
2809 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2811 break;
2812 #endif
2813 case OPC_MUL:
2814 if (likely(rs != 0 && rt != 0)) {
2815 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2816 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2817 } else {
2818 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2820 break;
2824 /* Conditional move */
2825 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2826 int rd, int rs, int rt)
2828 TCGv t0, t1, t2;
2830 if (rd == 0) {
2831 /* If no destination, treat it as a NOP. */
2832 return;
2835 t0 = tcg_temp_new();
2836 gen_load_gpr(t0, rt);
2837 t1 = tcg_const_tl(0);
2838 t2 = tcg_temp_new();
2839 gen_load_gpr(t2, rs);
2840 switch (opc) {
2841 case OPC_MOVN:
2842 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2843 break;
2844 case OPC_MOVZ:
2845 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2846 break;
2847 case OPC_SELNEZ:
2848 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2849 break;
2850 case OPC_SELEQZ:
2851 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2852 break;
2854 tcg_temp_free(t2);
2855 tcg_temp_free(t1);
2856 tcg_temp_free(t0);
2859 /* Logic */
2860 static void gen_logic(DisasContext *ctx, uint32_t opc,
2861 int rd, int rs, int rt)
2863 if (rd == 0) {
2864 /* If no destination, treat it as a NOP. */
2865 return;
2868 switch (opc) {
2869 case OPC_AND:
2870 if (likely(rs != 0 && rt != 0)) {
2871 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2872 } else {
2873 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2875 break;
2876 case OPC_NOR:
2877 if (rs != 0 && rt != 0) {
2878 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2879 } else if (rs == 0 && rt != 0) {
2880 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2881 } else if (rs != 0 && rt == 0) {
2882 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2883 } else {
2884 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2886 break;
2887 case OPC_OR:
2888 if (likely(rs != 0 && rt != 0)) {
2889 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2890 } else if (rs == 0 && rt != 0) {
2891 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2892 } else if (rs != 0 && rt == 0) {
2893 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2894 } else {
2895 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2897 break;
2898 case OPC_XOR:
2899 if (likely(rs != 0 && rt != 0)) {
2900 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2901 } else if (rs == 0 && rt != 0) {
2902 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2903 } else if (rs != 0 && rt == 0) {
2904 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2905 } else {
2906 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2908 break;
2912 /* Set on lower than */
2913 static void gen_slt(DisasContext *ctx, uint32_t opc,
2914 int rd, int rs, int rt)
2916 TCGv t0, t1;
2918 if (rd == 0) {
2919 /* If no destination, treat it as a NOP. */
2920 return;
2923 t0 = tcg_temp_new();
2924 t1 = tcg_temp_new();
2925 gen_load_gpr(t0, rs);
2926 gen_load_gpr(t1, rt);
2927 switch (opc) {
2928 case OPC_SLT:
2929 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2930 break;
2931 case OPC_SLTU:
2932 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2933 break;
2935 tcg_temp_free(t0);
2936 tcg_temp_free(t1);
2939 /* Shifts */
2940 static void gen_shift(DisasContext *ctx, uint32_t opc,
2941 int rd, int rs, int rt)
2943 TCGv t0, t1;
2945 if (rd == 0) {
2946 /* If no destination, treat it as a NOP.
2947 For add & sub, we must generate the overflow exception when needed. */
2948 return;
2951 t0 = tcg_temp_new();
2952 t1 = tcg_temp_new();
2953 gen_load_gpr(t0, rs);
2954 gen_load_gpr(t1, rt);
2955 switch (opc) {
2956 case OPC_SLLV:
2957 tcg_gen_andi_tl(t0, t0, 0x1f);
2958 tcg_gen_shl_tl(t0, t1, t0);
2959 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2960 break;
2961 case OPC_SRAV:
2962 tcg_gen_andi_tl(t0, t0, 0x1f);
2963 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2964 break;
2965 case OPC_SRLV:
2966 tcg_gen_ext32u_tl(t1, t1);
2967 tcg_gen_andi_tl(t0, t0, 0x1f);
2968 tcg_gen_shr_tl(t0, t1, t0);
2969 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2970 break;
2971 case OPC_ROTRV:
2973 TCGv_i32 t2 = tcg_temp_new_i32();
2974 TCGv_i32 t3 = tcg_temp_new_i32();
2976 tcg_gen_trunc_tl_i32(t2, t0);
2977 tcg_gen_trunc_tl_i32(t3, t1);
2978 tcg_gen_andi_i32(t2, t2, 0x1f);
2979 tcg_gen_rotr_i32(t2, t3, t2);
2980 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2981 tcg_temp_free_i32(t2);
2982 tcg_temp_free_i32(t3);
2984 break;
2985 #if defined(TARGET_MIPS64)
2986 case OPC_DSLLV:
2987 tcg_gen_andi_tl(t0, t0, 0x3f);
2988 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2989 break;
2990 case OPC_DSRAV:
2991 tcg_gen_andi_tl(t0, t0, 0x3f);
2992 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2993 break;
2994 case OPC_DSRLV:
2995 tcg_gen_andi_tl(t0, t0, 0x3f);
2996 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2997 break;
2998 case OPC_DROTRV:
2999 tcg_gen_andi_tl(t0, t0, 0x3f);
3000 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3001 break;
3002 #endif
3004 tcg_temp_free(t0);
3005 tcg_temp_free(t1);
3008 /* Arithmetic on HI/LO registers */
3009 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3011 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3012 /* Treat as NOP. */
3013 return;
3016 if (acc != 0) {
3017 check_dsp(ctx);
3020 switch (opc) {
3021 case OPC_MFHI:
3022 #if defined(TARGET_MIPS64)
3023 if (acc != 0) {
3024 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3025 } else
3026 #endif
3028 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3030 break;
3031 case OPC_MFLO:
3032 #if defined(TARGET_MIPS64)
3033 if (acc != 0) {
3034 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3035 } else
3036 #endif
3038 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3040 break;
3041 case OPC_MTHI:
3042 if (reg != 0) {
3043 #if defined(TARGET_MIPS64)
3044 if (acc != 0) {
3045 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3046 } else
3047 #endif
3049 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3051 } else {
3052 tcg_gen_movi_tl(cpu_HI[acc], 0);
3054 break;
3055 case OPC_MTLO:
3056 if (reg != 0) {
3057 #if defined(TARGET_MIPS64)
3058 if (acc != 0) {
3059 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3060 } else
3061 #endif
3063 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3065 } else {
3066 tcg_gen_movi_tl(cpu_LO[acc], 0);
3068 break;
3072 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3073 TCGMemOp memop)
3075 TCGv t0 = tcg_const_tl(addr);
3076 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3077 gen_store_gpr(t0, reg);
3078 tcg_temp_free(t0);
3081 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3082 int rs)
3084 target_long offset;
3085 target_long addr;
3087 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3088 case OPC_ADDIUPC:
3089 if (rs != 0) {
3090 offset = sextract32(ctx->opcode << 2, 0, 21);
3091 addr = addr_add(ctx, pc, offset);
3092 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3094 break;
3095 case R6_OPC_LWPC:
3096 offset = sextract32(ctx->opcode << 2, 0, 21);
3097 addr = addr_add(ctx, pc, offset);
3098 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3099 break;
3100 #if defined(TARGET_MIPS64)
3101 case OPC_LWUPC:
3102 check_mips_64(ctx);
3103 offset = sextract32(ctx->opcode << 2, 0, 21);
3104 addr = addr_add(ctx, pc, offset);
3105 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3106 break;
3107 #endif
3108 default:
3109 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3110 case OPC_AUIPC:
3111 if (rs != 0) {
3112 offset = sextract32(ctx->opcode, 0, 16) << 16;
3113 addr = addr_add(ctx, pc, offset);
3114 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3116 break;
3117 case OPC_ALUIPC:
3118 if (rs != 0) {
3119 offset = sextract32(ctx->opcode, 0, 16) << 16;
3120 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3121 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3123 break;
3124 #if defined(TARGET_MIPS64)
3125 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3126 case R6_OPC_LDPC + (1 << 16):
3127 case R6_OPC_LDPC + (2 << 16):
3128 case R6_OPC_LDPC + (3 << 16):
3129 check_mips_64(ctx);
3130 offset = sextract32(ctx->opcode << 3, 0, 21);
3131 addr = addr_add(ctx, (pc & ~0x7), offset);
3132 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3133 break;
3134 #endif
3135 default:
3136 MIPS_INVAL("OPC_PCREL");
3137 generate_exception_end(ctx, EXCP_RI);
3138 break;
3140 break;
3144 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3146 TCGv t0, t1;
3148 if (rd == 0) {
3149 /* Treat as NOP. */
3150 return;
3153 t0 = tcg_temp_new();
3154 t1 = tcg_temp_new();
3156 gen_load_gpr(t0, rs);
3157 gen_load_gpr(t1, rt);
3159 switch (opc) {
3160 case R6_OPC_DIV:
3162 TCGv t2 = tcg_temp_new();
3163 TCGv t3 = tcg_temp_new();
3164 tcg_gen_ext32s_tl(t0, t0);
3165 tcg_gen_ext32s_tl(t1, t1);
3166 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3167 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3168 tcg_gen_and_tl(t2, t2, t3);
3169 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3170 tcg_gen_or_tl(t2, t2, t3);
3171 tcg_gen_movi_tl(t3, 0);
3172 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3173 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3174 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3175 tcg_temp_free(t3);
3176 tcg_temp_free(t2);
3178 break;
3179 case R6_OPC_MOD:
3181 TCGv t2 = tcg_temp_new();
3182 TCGv t3 = tcg_temp_new();
3183 tcg_gen_ext32s_tl(t0, t0);
3184 tcg_gen_ext32s_tl(t1, t1);
3185 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3186 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3187 tcg_gen_and_tl(t2, t2, t3);
3188 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3189 tcg_gen_or_tl(t2, t2, t3);
3190 tcg_gen_movi_tl(t3, 0);
3191 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3192 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3193 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3194 tcg_temp_free(t3);
3195 tcg_temp_free(t2);
3197 break;
3198 case R6_OPC_DIVU:
3200 TCGv t2 = tcg_const_tl(0);
3201 TCGv t3 = tcg_const_tl(1);
3202 tcg_gen_ext32u_tl(t0, t0);
3203 tcg_gen_ext32u_tl(t1, t1);
3204 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3205 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3206 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3207 tcg_temp_free(t3);
3208 tcg_temp_free(t2);
3210 break;
3211 case R6_OPC_MODU:
3213 TCGv t2 = tcg_const_tl(0);
3214 TCGv t3 = tcg_const_tl(1);
3215 tcg_gen_ext32u_tl(t0, t0);
3216 tcg_gen_ext32u_tl(t1, t1);
3217 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3218 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3219 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3220 tcg_temp_free(t3);
3221 tcg_temp_free(t2);
3223 break;
3224 case R6_OPC_MUL:
3226 TCGv_i32 t2 = tcg_temp_new_i32();
3227 TCGv_i32 t3 = tcg_temp_new_i32();
3228 tcg_gen_trunc_tl_i32(t2, t0);
3229 tcg_gen_trunc_tl_i32(t3, t1);
3230 tcg_gen_mul_i32(t2, t2, t3);
3231 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3232 tcg_temp_free_i32(t2);
3233 tcg_temp_free_i32(t3);
3235 break;
3236 case R6_OPC_MUH:
3238 TCGv_i32 t2 = tcg_temp_new_i32();
3239 TCGv_i32 t3 = tcg_temp_new_i32();
3240 tcg_gen_trunc_tl_i32(t2, t0);
3241 tcg_gen_trunc_tl_i32(t3, t1);
3242 tcg_gen_muls2_i32(t2, t3, t2, t3);
3243 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3244 tcg_temp_free_i32(t2);
3245 tcg_temp_free_i32(t3);
3247 break;
3248 case R6_OPC_MULU:
3250 TCGv_i32 t2 = tcg_temp_new_i32();
3251 TCGv_i32 t3 = tcg_temp_new_i32();
3252 tcg_gen_trunc_tl_i32(t2, t0);
3253 tcg_gen_trunc_tl_i32(t3, t1);
3254 tcg_gen_mul_i32(t2, t2, t3);
3255 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3256 tcg_temp_free_i32(t2);
3257 tcg_temp_free_i32(t3);
3259 break;
3260 case R6_OPC_MUHU:
3262 TCGv_i32 t2 = tcg_temp_new_i32();
3263 TCGv_i32 t3 = tcg_temp_new_i32();
3264 tcg_gen_trunc_tl_i32(t2, t0);
3265 tcg_gen_trunc_tl_i32(t3, t1);
3266 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3267 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3268 tcg_temp_free_i32(t2);
3269 tcg_temp_free_i32(t3);
3271 break;
3272 #if defined(TARGET_MIPS64)
3273 case R6_OPC_DDIV:
3275 TCGv t2 = tcg_temp_new();
3276 TCGv t3 = tcg_temp_new();
3277 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3278 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3279 tcg_gen_and_tl(t2, t2, t3);
3280 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3281 tcg_gen_or_tl(t2, t2, t3);
3282 tcg_gen_movi_tl(t3, 0);
3283 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3284 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3285 tcg_temp_free(t3);
3286 tcg_temp_free(t2);
3288 break;
3289 case R6_OPC_DMOD:
3291 TCGv t2 = tcg_temp_new();
3292 TCGv t3 = tcg_temp_new();
3293 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3294 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3295 tcg_gen_and_tl(t2, t2, t3);
3296 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3297 tcg_gen_or_tl(t2, t2, t3);
3298 tcg_gen_movi_tl(t3, 0);
3299 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3300 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3301 tcg_temp_free(t3);
3302 tcg_temp_free(t2);
3304 break;
3305 case R6_OPC_DDIVU:
3307 TCGv t2 = tcg_const_tl(0);
3308 TCGv t3 = tcg_const_tl(1);
3309 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3310 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3311 tcg_temp_free(t3);
3312 tcg_temp_free(t2);
3314 break;
3315 case R6_OPC_DMODU:
3317 TCGv t2 = tcg_const_tl(0);
3318 TCGv t3 = tcg_const_tl(1);
3319 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3320 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3321 tcg_temp_free(t3);
3322 tcg_temp_free(t2);
3324 break;
3325 case R6_OPC_DMUL:
3326 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3327 break;
3328 case R6_OPC_DMUH:
3330 TCGv t2 = tcg_temp_new();
3331 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3332 tcg_temp_free(t2);
3334 break;
3335 case R6_OPC_DMULU:
3336 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3337 break;
3338 case R6_OPC_DMUHU:
3340 TCGv t2 = tcg_temp_new();
3341 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3342 tcg_temp_free(t2);
3344 break;
3345 #endif
3346 default:
3347 MIPS_INVAL("r6 mul/div");
3348 generate_exception_end(ctx, EXCP_RI);
3349 goto out;
3351 out:
3352 tcg_temp_free(t0);
3353 tcg_temp_free(t1);
3356 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3357 int acc, int rs, int rt)
3359 TCGv t0, t1;
3361 t0 = tcg_temp_new();
3362 t1 = tcg_temp_new();
3364 gen_load_gpr(t0, rs);
3365 gen_load_gpr(t1, rt);
3367 if (acc != 0) {
3368 check_dsp(ctx);
3371 switch (opc) {
3372 case OPC_DIV:
3374 TCGv t2 = tcg_temp_new();
3375 TCGv t3 = tcg_temp_new();
3376 tcg_gen_ext32s_tl(t0, t0);
3377 tcg_gen_ext32s_tl(t1, t1);
3378 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3379 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3380 tcg_gen_and_tl(t2, t2, t3);
3381 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3382 tcg_gen_or_tl(t2, t2, t3);
3383 tcg_gen_movi_tl(t3, 0);
3384 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3385 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3386 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3387 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3388 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3389 tcg_temp_free(t3);
3390 tcg_temp_free(t2);
3392 break;
3393 case OPC_DIVU:
3395 TCGv t2 = tcg_const_tl(0);
3396 TCGv t3 = tcg_const_tl(1);
3397 tcg_gen_ext32u_tl(t0, t0);
3398 tcg_gen_ext32u_tl(t1, t1);
3399 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3400 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3401 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3402 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3403 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3404 tcg_temp_free(t3);
3405 tcg_temp_free(t2);
3407 break;
3408 case OPC_MULT:
3410 TCGv_i32 t2 = tcg_temp_new_i32();
3411 TCGv_i32 t3 = tcg_temp_new_i32();
3412 tcg_gen_trunc_tl_i32(t2, t0);
3413 tcg_gen_trunc_tl_i32(t3, t1);
3414 tcg_gen_muls2_i32(t2, t3, t2, t3);
3415 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3416 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3417 tcg_temp_free_i32(t2);
3418 tcg_temp_free_i32(t3);
3420 break;
3421 case OPC_MULTU:
3423 TCGv_i32 t2 = tcg_temp_new_i32();
3424 TCGv_i32 t3 = tcg_temp_new_i32();
3425 tcg_gen_trunc_tl_i32(t2, t0);
3426 tcg_gen_trunc_tl_i32(t3, t1);
3427 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3428 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3429 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3430 tcg_temp_free_i32(t2);
3431 tcg_temp_free_i32(t3);
3433 break;
3434 #if defined(TARGET_MIPS64)
3435 case OPC_DDIV:
3437 TCGv t2 = tcg_temp_new();
3438 TCGv t3 = tcg_temp_new();
3439 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3440 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3441 tcg_gen_and_tl(t2, t2, t3);
3442 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3443 tcg_gen_or_tl(t2, t2, t3);
3444 tcg_gen_movi_tl(t3, 0);
3445 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3446 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3447 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3448 tcg_temp_free(t3);
3449 tcg_temp_free(t2);
3451 break;
3452 case OPC_DDIVU:
3454 TCGv t2 = tcg_const_tl(0);
3455 TCGv t3 = tcg_const_tl(1);
3456 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3457 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3458 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3459 tcg_temp_free(t3);
3460 tcg_temp_free(t2);
3462 break;
3463 case OPC_DMULT:
3464 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3465 break;
3466 case OPC_DMULTU:
3467 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3468 break;
3469 #endif
3470 case OPC_MADD:
3472 TCGv_i64 t2 = tcg_temp_new_i64();
3473 TCGv_i64 t3 = tcg_temp_new_i64();
3475 tcg_gen_ext_tl_i64(t2, t0);
3476 tcg_gen_ext_tl_i64(t3, t1);
3477 tcg_gen_mul_i64(t2, t2, t3);
3478 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3479 tcg_gen_add_i64(t2, t2, t3);
3480 tcg_temp_free_i64(t3);
3481 gen_move_low32(cpu_LO[acc], t2);
3482 gen_move_high32(cpu_HI[acc], t2);
3483 tcg_temp_free_i64(t2);
3485 break;
3486 case OPC_MADDU:
3488 TCGv_i64 t2 = tcg_temp_new_i64();
3489 TCGv_i64 t3 = tcg_temp_new_i64();
3491 tcg_gen_ext32u_tl(t0, t0);
3492 tcg_gen_ext32u_tl(t1, t1);
3493 tcg_gen_extu_tl_i64(t2, t0);
3494 tcg_gen_extu_tl_i64(t3, t1);
3495 tcg_gen_mul_i64(t2, t2, t3);
3496 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3497 tcg_gen_add_i64(t2, t2, t3);
3498 tcg_temp_free_i64(t3);
3499 gen_move_low32(cpu_LO[acc], t2);
3500 gen_move_high32(cpu_HI[acc], t2);
3501 tcg_temp_free_i64(t2);
3503 break;
3504 case OPC_MSUB:
3506 TCGv_i64 t2 = tcg_temp_new_i64();
3507 TCGv_i64 t3 = tcg_temp_new_i64();
3509 tcg_gen_ext_tl_i64(t2, t0);
3510 tcg_gen_ext_tl_i64(t3, t1);
3511 tcg_gen_mul_i64(t2, t2, t3);
3512 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3513 tcg_gen_sub_i64(t2, t3, t2);
3514 tcg_temp_free_i64(t3);
3515 gen_move_low32(cpu_LO[acc], t2);
3516 gen_move_high32(cpu_HI[acc], t2);
3517 tcg_temp_free_i64(t2);
3519 break;
3520 case OPC_MSUBU:
3522 TCGv_i64 t2 = tcg_temp_new_i64();
3523 TCGv_i64 t3 = tcg_temp_new_i64();
3525 tcg_gen_ext32u_tl(t0, t0);
3526 tcg_gen_ext32u_tl(t1, t1);
3527 tcg_gen_extu_tl_i64(t2, t0);
3528 tcg_gen_extu_tl_i64(t3, t1);
3529 tcg_gen_mul_i64(t2, t2, t3);
3530 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3531 tcg_gen_sub_i64(t2, t3, t2);
3532 tcg_temp_free_i64(t3);
3533 gen_move_low32(cpu_LO[acc], t2);
3534 gen_move_high32(cpu_HI[acc], t2);
3535 tcg_temp_free_i64(t2);
3537 break;
3538 default:
3539 MIPS_INVAL("mul/div");
3540 generate_exception_end(ctx, EXCP_RI);
3541 goto out;
3543 out:
3544 tcg_temp_free(t0);
3545 tcg_temp_free(t1);
3548 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3549 int rd, int rs, int rt)
3551 TCGv t0 = tcg_temp_new();
3552 TCGv t1 = tcg_temp_new();
3554 gen_load_gpr(t0, rs);
3555 gen_load_gpr(t1, rt);
3557 switch (opc) {
3558 case OPC_VR54XX_MULS:
3559 gen_helper_muls(t0, cpu_env, t0, t1);
3560 break;
3561 case OPC_VR54XX_MULSU:
3562 gen_helper_mulsu(t0, cpu_env, t0, t1);
3563 break;
3564 case OPC_VR54XX_MACC:
3565 gen_helper_macc(t0, cpu_env, t0, t1);
3566 break;
3567 case OPC_VR54XX_MACCU:
3568 gen_helper_maccu(t0, cpu_env, t0, t1);
3569 break;
3570 case OPC_VR54XX_MSAC:
3571 gen_helper_msac(t0, cpu_env, t0, t1);
3572 break;
3573 case OPC_VR54XX_MSACU:
3574 gen_helper_msacu(t0, cpu_env, t0, t1);
3575 break;
3576 case OPC_VR54XX_MULHI:
3577 gen_helper_mulhi(t0, cpu_env, t0, t1);
3578 break;
3579 case OPC_VR54XX_MULHIU:
3580 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3581 break;
3582 case OPC_VR54XX_MULSHI:
3583 gen_helper_mulshi(t0, cpu_env, t0, t1);
3584 break;
3585 case OPC_VR54XX_MULSHIU:
3586 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3587 break;
3588 case OPC_VR54XX_MACCHI:
3589 gen_helper_macchi(t0, cpu_env, t0, t1);
3590 break;
3591 case OPC_VR54XX_MACCHIU:
3592 gen_helper_macchiu(t0, cpu_env, t0, t1);
3593 break;
3594 case OPC_VR54XX_MSACHI:
3595 gen_helper_msachi(t0, cpu_env, t0, t1);
3596 break;
3597 case OPC_VR54XX_MSACHIU:
3598 gen_helper_msachiu(t0, cpu_env, t0, t1);
3599 break;
3600 default:
3601 MIPS_INVAL("mul vr54xx");
3602 generate_exception_end(ctx, EXCP_RI);
3603 goto out;
3605 gen_store_gpr(t0, rd);
3607 out:
3608 tcg_temp_free(t0);
3609 tcg_temp_free(t1);
3612 static void gen_cl (DisasContext *ctx, uint32_t opc,
3613 int rd, int rs)
3615 TCGv t0;
3617 if (rd == 0) {
3618 /* Treat as NOP. */
3619 return;
3621 t0 = tcg_temp_new();
3622 gen_load_gpr(t0, rs);
3623 switch (opc) {
3624 case OPC_CLO:
3625 case R6_OPC_CLO:
3626 gen_helper_clo(cpu_gpr[rd], t0);
3627 break;
3628 case OPC_CLZ:
3629 case R6_OPC_CLZ:
3630 gen_helper_clz(cpu_gpr[rd], t0);
3631 break;
3632 #if defined(TARGET_MIPS64)
3633 case OPC_DCLO:
3634 case R6_OPC_DCLO:
3635 gen_helper_dclo(cpu_gpr[rd], t0);
3636 break;
3637 case OPC_DCLZ:
3638 case R6_OPC_DCLZ:
3639 gen_helper_dclz(cpu_gpr[rd], t0);
3640 break;
3641 #endif
3643 tcg_temp_free(t0);
3646 /* Godson integer instructions */
3647 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3648 int rd, int rs, int rt)
3650 TCGv t0, t1;
3652 if (rd == 0) {
3653 /* Treat as NOP. */
3654 return;
3657 switch (opc) {
3658 case OPC_MULT_G_2E:
3659 case OPC_MULT_G_2F:
3660 case OPC_MULTU_G_2E:
3661 case OPC_MULTU_G_2F:
3662 #if defined(TARGET_MIPS64)
3663 case OPC_DMULT_G_2E:
3664 case OPC_DMULT_G_2F:
3665 case OPC_DMULTU_G_2E:
3666 case OPC_DMULTU_G_2F:
3667 #endif
3668 t0 = tcg_temp_new();
3669 t1 = tcg_temp_new();
3670 break;
3671 default:
3672 t0 = tcg_temp_local_new();
3673 t1 = tcg_temp_local_new();
3674 break;
3677 gen_load_gpr(t0, rs);
3678 gen_load_gpr(t1, rt);
3680 switch (opc) {
3681 case OPC_MULT_G_2E:
3682 case OPC_MULT_G_2F:
3683 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3684 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3685 break;
3686 case OPC_MULTU_G_2E:
3687 case OPC_MULTU_G_2F:
3688 tcg_gen_ext32u_tl(t0, t0);
3689 tcg_gen_ext32u_tl(t1, t1);
3690 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3691 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3692 break;
3693 case OPC_DIV_G_2E:
3694 case OPC_DIV_G_2F:
3696 TCGLabel *l1 = gen_new_label();
3697 TCGLabel *l2 = gen_new_label();
3698 TCGLabel *l3 = gen_new_label();
3699 tcg_gen_ext32s_tl(t0, t0);
3700 tcg_gen_ext32s_tl(t1, t1);
3701 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3702 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3703 tcg_gen_br(l3);
3704 gen_set_label(l1);
3705 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3706 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3707 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3708 tcg_gen_br(l3);
3709 gen_set_label(l2);
3710 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3711 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3712 gen_set_label(l3);
3714 break;
3715 case OPC_DIVU_G_2E:
3716 case OPC_DIVU_G_2F:
3718 TCGLabel *l1 = gen_new_label();
3719 TCGLabel *l2 = gen_new_label();
3720 tcg_gen_ext32u_tl(t0, t0);
3721 tcg_gen_ext32u_tl(t1, t1);
3722 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3723 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3724 tcg_gen_br(l2);
3725 gen_set_label(l1);
3726 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3727 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3728 gen_set_label(l2);
3730 break;
3731 case OPC_MOD_G_2E:
3732 case OPC_MOD_G_2F:
3734 TCGLabel *l1 = gen_new_label();
3735 TCGLabel *l2 = gen_new_label();
3736 TCGLabel *l3 = gen_new_label();
3737 tcg_gen_ext32u_tl(t0, t0);
3738 tcg_gen_ext32u_tl(t1, t1);
3739 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3740 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3741 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3742 gen_set_label(l1);
3743 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3744 tcg_gen_br(l3);
3745 gen_set_label(l2);
3746 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3747 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3748 gen_set_label(l3);
3750 break;
3751 case OPC_MODU_G_2E:
3752 case OPC_MODU_G_2F:
3754 TCGLabel *l1 = gen_new_label();
3755 TCGLabel *l2 = gen_new_label();
3756 tcg_gen_ext32u_tl(t0, t0);
3757 tcg_gen_ext32u_tl(t1, t1);
3758 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3759 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3760 tcg_gen_br(l2);
3761 gen_set_label(l1);
3762 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3763 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3764 gen_set_label(l2);
3766 break;
3767 #if defined(TARGET_MIPS64)
3768 case OPC_DMULT_G_2E:
3769 case OPC_DMULT_G_2F:
3770 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3771 break;
3772 case OPC_DMULTU_G_2E:
3773 case OPC_DMULTU_G_2F:
3774 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3775 break;
3776 case OPC_DDIV_G_2E:
3777 case OPC_DDIV_G_2F:
3779 TCGLabel *l1 = gen_new_label();
3780 TCGLabel *l2 = gen_new_label();
3781 TCGLabel *l3 = gen_new_label();
3782 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3783 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3784 tcg_gen_br(l3);
3785 gen_set_label(l1);
3786 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3787 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3788 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3789 tcg_gen_br(l3);
3790 gen_set_label(l2);
3791 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3792 gen_set_label(l3);
3794 break;
3795 case OPC_DDIVU_G_2E:
3796 case OPC_DDIVU_G_2F:
3798 TCGLabel *l1 = gen_new_label();
3799 TCGLabel *l2 = gen_new_label();
3800 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3801 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3802 tcg_gen_br(l2);
3803 gen_set_label(l1);
3804 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3805 gen_set_label(l2);
3807 break;
3808 case OPC_DMOD_G_2E:
3809 case OPC_DMOD_G_2F:
3811 TCGLabel *l1 = gen_new_label();
3812 TCGLabel *l2 = gen_new_label();
3813 TCGLabel *l3 = gen_new_label();
3814 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3815 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3816 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3817 gen_set_label(l1);
3818 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3819 tcg_gen_br(l3);
3820 gen_set_label(l2);
3821 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3822 gen_set_label(l3);
3824 break;
3825 case OPC_DMODU_G_2E:
3826 case OPC_DMODU_G_2F:
3828 TCGLabel *l1 = gen_new_label();
3829 TCGLabel *l2 = gen_new_label();
3830 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3831 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3832 tcg_gen_br(l2);
3833 gen_set_label(l1);
3834 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3835 gen_set_label(l2);
3837 break;
3838 #endif
3841 tcg_temp_free(t0);
3842 tcg_temp_free(t1);
3845 /* Loongson multimedia instructions */
3846 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3848 uint32_t opc, shift_max;
3849 TCGv_i64 t0, t1;
3851 opc = MASK_LMI(ctx->opcode);
3852 switch (opc) {
3853 case OPC_ADD_CP2:
3854 case OPC_SUB_CP2:
3855 case OPC_DADD_CP2:
3856 case OPC_DSUB_CP2:
3857 t0 = tcg_temp_local_new_i64();
3858 t1 = tcg_temp_local_new_i64();
3859 break;
3860 default:
3861 t0 = tcg_temp_new_i64();
3862 t1 = tcg_temp_new_i64();
3863 break;
3866 gen_load_fpr64(ctx, t0, rs);
3867 gen_load_fpr64(ctx, t1, rt);
3869 #define LMI_HELPER(UP, LO) \
3870 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
3871 #define LMI_HELPER_1(UP, LO) \
3872 case OPC_##UP: gen_helper_##LO(t0, t0); break
3873 #define LMI_DIRECT(UP, LO, OP) \
3874 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
3876 switch (opc) {
3877 LMI_HELPER(PADDSH, paddsh);
3878 LMI_HELPER(PADDUSH, paddush);
3879 LMI_HELPER(PADDH, paddh);
3880 LMI_HELPER(PADDW, paddw);
3881 LMI_HELPER(PADDSB, paddsb);
3882 LMI_HELPER(PADDUSB, paddusb);
3883 LMI_HELPER(PADDB, paddb);
3885 LMI_HELPER(PSUBSH, psubsh);
3886 LMI_HELPER(PSUBUSH, psubush);
3887 LMI_HELPER(PSUBH, psubh);
3888 LMI_HELPER(PSUBW, psubw);
3889 LMI_HELPER(PSUBSB, psubsb);
3890 LMI_HELPER(PSUBUSB, psubusb);
3891 LMI_HELPER(PSUBB, psubb);
3893 LMI_HELPER(PSHUFH, pshufh);
3894 LMI_HELPER(PACKSSWH, packsswh);
3895 LMI_HELPER(PACKSSHB, packsshb);
3896 LMI_HELPER(PACKUSHB, packushb);
3898 LMI_HELPER(PUNPCKLHW, punpcklhw);
3899 LMI_HELPER(PUNPCKHHW, punpckhhw);
3900 LMI_HELPER(PUNPCKLBH, punpcklbh);
3901 LMI_HELPER(PUNPCKHBH, punpckhbh);
3902 LMI_HELPER(PUNPCKLWD, punpcklwd);
3903 LMI_HELPER(PUNPCKHWD, punpckhwd);
3905 LMI_HELPER(PAVGH, pavgh);
3906 LMI_HELPER(PAVGB, pavgb);
3907 LMI_HELPER(PMAXSH, pmaxsh);
3908 LMI_HELPER(PMINSH, pminsh);
3909 LMI_HELPER(PMAXUB, pmaxub);
3910 LMI_HELPER(PMINUB, pminub);
3912 LMI_HELPER(PCMPEQW, pcmpeqw);
3913 LMI_HELPER(PCMPGTW, pcmpgtw);
3914 LMI_HELPER(PCMPEQH, pcmpeqh);
3915 LMI_HELPER(PCMPGTH, pcmpgth);
3916 LMI_HELPER(PCMPEQB, pcmpeqb);
3917 LMI_HELPER(PCMPGTB, pcmpgtb);
3919 LMI_HELPER(PSLLW, psllw);
3920 LMI_HELPER(PSLLH, psllh);
3921 LMI_HELPER(PSRLW, psrlw);
3922 LMI_HELPER(PSRLH, psrlh);
3923 LMI_HELPER(PSRAW, psraw);
3924 LMI_HELPER(PSRAH, psrah);
3926 LMI_HELPER(PMULLH, pmullh);
3927 LMI_HELPER(PMULHH, pmulhh);
3928 LMI_HELPER(PMULHUH, pmulhuh);
3929 LMI_HELPER(PMADDHW, pmaddhw);
3931 LMI_HELPER(PASUBUB, pasubub);
3932 LMI_HELPER_1(BIADD, biadd);
3933 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3935 LMI_DIRECT(PADDD, paddd, add);
3936 LMI_DIRECT(PSUBD, psubd, sub);
3937 LMI_DIRECT(XOR_CP2, xor, xor);
3938 LMI_DIRECT(NOR_CP2, nor, nor);
3939 LMI_DIRECT(AND_CP2, and, and);
3940 LMI_DIRECT(PANDN, pandn, andc);
3941 LMI_DIRECT(OR, or, or);
3943 case OPC_PINSRH_0:
3944 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3945 break;
3946 case OPC_PINSRH_1:
3947 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3948 break;
3949 case OPC_PINSRH_2:
3950 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3951 break;
3952 case OPC_PINSRH_3:
3953 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3954 break;
3956 case OPC_PEXTRH:
3957 tcg_gen_andi_i64(t1, t1, 3);
3958 tcg_gen_shli_i64(t1, t1, 4);
3959 tcg_gen_shr_i64(t0, t0, t1);
3960 tcg_gen_ext16u_i64(t0, t0);
3961 break;
3963 case OPC_ADDU_CP2:
3964 tcg_gen_add_i64(t0, t0, t1);
3965 tcg_gen_ext32s_i64(t0, t0);
3966 break;
3967 case OPC_SUBU_CP2:
3968 tcg_gen_sub_i64(t0, t0, t1);
3969 tcg_gen_ext32s_i64(t0, t0);
3970 break;
3972 case OPC_SLL_CP2:
3973 shift_max = 32;
3974 goto do_shift;
3975 case OPC_SRL_CP2:
3976 shift_max = 32;
3977 goto do_shift;
3978 case OPC_SRA_CP2:
3979 shift_max = 32;
3980 goto do_shift;
3981 case OPC_DSLL_CP2:
3982 shift_max = 64;
3983 goto do_shift;
3984 case OPC_DSRL_CP2:
3985 shift_max = 64;
3986 goto do_shift;
3987 case OPC_DSRA_CP2:
3988 shift_max = 64;
3989 goto do_shift;
3990 do_shift:
3991 /* Make sure shift count isn't TCG undefined behaviour. */
3992 tcg_gen_andi_i64(t1, t1, shift_max - 1);
3994 switch (opc) {
3995 case OPC_SLL_CP2:
3996 case OPC_DSLL_CP2:
3997 tcg_gen_shl_i64(t0, t0, t1);
3998 break;
3999 case OPC_SRA_CP2:
4000 case OPC_DSRA_CP2:
4001 /* Since SRA is UndefinedResult without sign-extended inputs,
4002 we can treat SRA and DSRA the same. */
4003 tcg_gen_sar_i64(t0, t0, t1);
4004 break;
4005 case OPC_SRL_CP2:
4006 /* We want to shift in zeros for SRL; zero-extend first. */
4007 tcg_gen_ext32u_i64(t0, t0);
4008 /* FALLTHRU */
4009 case OPC_DSRL_CP2:
4010 tcg_gen_shr_i64(t0, t0, t1);
4011 break;
4014 if (shift_max == 32) {
4015 tcg_gen_ext32s_i64(t0, t0);
4018 /* Shifts larger than MAX produce zero. */
4019 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4020 tcg_gen_neg_i64(t1, t1);
4021 tcg_gen_and_i64(t0, t0, t1);
4022 break;
4024 case OPC_ADD_CP2:
4025 case OPC_DADD_CP2:
4027 TCGv_i64 t2 = tcg_temp_new_i64();
4028 TCGLabel *lab = gen_new_label();
4030 tcg_gen_mov_i64(t2, t0);
4031 tcg_gen_add_i64(t0, t1, t2);
4032 if (opc == OPC_ADD_CP2) {
4033 tcg_gen_ext32s_i64(t0, t0);
4035 tcg_gen_xor_i64(t1, t1, t2);
4036 tcg_gen_xor_i64(t2, t2, t0);
4037 tcg_gen_andc_i64(t1, t2, t1);
4038 tcg_temp_free_i64(t2);
4039 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4040 generate_exception(ctx, EXCP_OVERFLOW);
4041 gen_set_label(lab);
4042 break;
4045 case OPC_SUB_CP2:
4046 case OPC_DSUB_CP2:
4048 TCGv_i64 t2 = tcg_temp_new_i64();
4049 TCGLabel *lab = gen_new_label();
4051 tcg_gen_mov_i64(t2, t0);
4052 tcg_gen_sub_i64(t0, t1, t2);
4053 if (opc == OPC_SUB_CP2) {
4054 tcg_gen_ext32s_i64(t0, t0);
4056 tcg_gen_xor_i64(t1, t1, t2);
4057 tcg_gen_xor_i64(t2, t2, t0);
4058 tcg_gen_and_i64(t1, t1, t2);
4059 tcg_temp_free_i64(t2);
4060 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4061 generate_exception(ctx, EXCP_OVERFLOW);
4062 gen_set_label(lab);
4063 break;
4066 case OPC_PMULUW:
4067 tcg_gen_ext32u_i64(t0, t0);
4068 tcg_gen_ext32u_i64(t1, t1);
4069 tcg_gen_mul_i64(t0, t0, t1);
4070 break;
4072 case OPC_SEQU_CP2:
4073 case OPC_SEQ_CP2:
4074 case OPC_SLTU_CP2:
4075 case OPC_SLT_CP2:
4076 case OPC_SLEU_CP2:
4077 case OPC_SLE_CP2:
4078 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4079 FD field is the CC field? */
4080 default:
4081 MIPS_INVAL("loongson_cp2");
4082 generate_exception_end(ctx, EXCP_RI);
4083 return;
4086 #undef LMI_HELPER
4087 #undef LMI_DIRECT
4089 gen_store_fpr64(ctx, t0, rd);
4091 tcg_temp_free_i64(t0);
4092 tcg_temp_free_i64(t1);
4095 /* Traps */
4096 static void gen_trap (DisasContext *ctx, uint32_t opc,
4097 int rs, int rt, int16_t imm)
4099 int cond;
4100 TCGv t0 = tcg_temp_new();
4101 TCGv t1 = tcg_temp_new();
4103 cond = 0;
4104 /* Load needed operands */
4105 switch (opc) {
4106 case OPC_TEQ:
4107 case OPC_TGE:
4108 case OPC_TGEU:
4109 case OPC_TLT:
4110 case OPC_TLTU:
4111 case OPC_TNE:
4112 /* Compare two registers */
4113 if (rs != rt) {
4114 gen_load_gpr(t0, rs);
4115 gen_load_gpr(t1, rt);
4116 cond = 1;
4118 break;
4119 case OPC_TEQI:
4120 case OPC_TGEI:
4121 case OPC_TGEIU:
4122 case OPC_TLTI:
4123 case OPC_TLTIU:
4124 case OPC_TNEI:
4125 /* Compare register to immediate */
4126 if (rs != 0 || imm != 0) {
4127 gen_load_gpr(t0, rs);
4128 tcg_gen_movi_tl(t1, (int32_t)imm);
4129 cond = 1;
4131 break;
4133 if (cond == 0) {
4134 switch (opc) {
4135 case OPC_TEQ: /* rs == rs */
4136 case OPC_TEQI: /* r0 == 0 */
4137 case OPC_TGE: /* rs >= rs */
4138 case OPC_TGEI: /* r0 >= 0 */
4139 case OPC_TGEU: /* rs >= rs unsigned */
4140 case OPC_TGEIU: /* r0 >= 0 unsigned */
4141 /* Always trap */
4142 generate_exception_end(ctx, EXCP_TRAP);
4143 break;
4144 case OPC_TLT: /* rs < rs */
4145 case OPC_TLTI: /* r0 < 0 */
4146 case OPC_TLTU: /* rs < rs unsigned */
4147 case OPC_TLTIU: /* r0 < 0 unsigned */
4148 case OPC_TNE: /* rs != rs */
4149 case OPC_TNEI: /* r0 != 0 */
4150 /* Never trap: treat as NOP. */
4151 break;
4153 } else {
4154 TCGLabel *l1 = gen_new_label();
4156 switch (opc) {
4157 case OPC_TEQ:
4158 case OPC_TEQI:
4159 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4160 break;
4161 case OPC_TGE:
4162 case OPC_TGEI:
4163 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4164 break;
4165 case OPC_TGEU:
4166 case OPC_TGEIU:
4167 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4168 break;
4169 case OPC_TLT:
4170 case OPC_TLTI:
4171 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4172 break;
4173 case OPC_TLTU:
4174 case OPC_TLTIU:
4175 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4176 break;
4177 case OPC_TNE:
4178 case OPC_TNEI:
4179 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4180 break;
4182 generate_exception(ctx, EXCP_TRAP);
4183 gen_set_label(l1);
4185 tcg_temp_free(t0);
4186 tcg_temp_free(t1);
4189 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4191 TranslationBlock *tb;
4192 tb = ctx->tb;
4193 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
4194 likely(!ctx->singlestep_enabled)) {
4195 tcg_gen_goto_tb(n);
4196 gen_save_pc(dest);
4197 tcg_gen_exit_tb((uintptr_t)tb + n);
4198 } else {
4199 gen_save_pc(dest);
4200 if (ctx->singlestep_enabled) {
4201 save_cpu_state(ctx, 0);
4202 gen_helper_raise_exception_debug(cpu_env);
4204 tcg_gen_exit_tb(0);
4208 /* Branches (before delay slot) */
4209 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4210 int insn_bytes,
4211 int rs, int rt, int32_t offset,
4212 int delayslot_size)
4214 target_ulong btgt = -1;
4215 int blink = 0;
4216 int bcond_compute = 0;
4217 TCGv t0 = tcg_temp_new();
4218 TCGv t1 = tcg_temp_new();
4220 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4221 #ifdef MIPS_DEBUG_DISAS
4222 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4223 TARGET_FMT_lx "\n", ctx->pc);
4224 #endif
4225 generate_exception_end(ctx, EXCP_RI);
4226 goto out;
4229 /* Load needed operands */
4230 switch (opc) {
4231 case OPC_BEQ:
4232 case OPC_BEQL:
4233 case OPC_BNE:
4234 case OPC_BNEL:
4235 /* Compare two registers */
4236 if (rs != rt) {
4237 gen_load_gpr(t0, rs);
4238 gen_load_gpr(t1, rt);
4239 bcond_compute = 1;
4241 btgt = ctx->pc + insn_bytes + offset;
4242 break;
4243 case OPC_BGEZ:
4244 case OPC_BGEZAL:
4245 case OPC_BGEZALL:
4246 case OPC_BGEZL:
4247 case OPC_BGTZ:
4248 case OPC_BGTZL:
4249 case OPC_BLEZ:
4250 case OPC_BLEZL:
4251 case OPC_BLTZ:
4252 case OPC_BLTZAL:
4253 case OPC_BLTZALL:
4254 case OPC_BLTZL:
4255 /* Compare to zero */
4256 if (rs != 0) {
4257 gen_load_gpr(t0, rs);
4258 bcond_compute = 1;
4260 btgt = ctx->pc + insn_bytes + offset;
4261 break;
4262 case OPC_BPOSGE32:
4263 #if defined(TARGET_MIPS64)
4264 case OPC_BPOSGE64:
4265 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4266 #else
4267 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4268 #endif
4269 bcond_compute = 1;
4270 btgt = ctx->pc + insn_bytes + offset;
4271 break;
4272 case OPC_J:
4273 case OPC_JAL:
4274 case OPC_JALX:
4275 /* Jump to immediate */
4276 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4277 break;
4278 case OPC_JR:
4279 case OPC_JALR:
4280 /* Jump to register */
4281 if (offset != 0 && offset != 16) {
4282 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4283 others are reserved. */
4284 MIPS_INVAL("jump hint");
4285 generate_exception_end(ctx, EXCP_RI);
4286 goto out;
4288 gen_load_gpr(btarget, rs);
4289 break;
4290 default:
4291 MIPS_INVAL("branch/jump");
4292 generate_exception_end(ctx, EXCP_RI);
4293 goto out;
4295 if (bcond_compute == 0) {
4296 /* No condition to be computed */
4297 switch (opc) {
4298 case OPC_BEQ: /* rx == rx */
4299 case OPC_BEQL: /* rx == rx likely */
4300 case OPC_BGEZ: /* 0 >= 0 */
4301 case OPC_BGEZL: /* 0 >= 0 likely */
4302 case OPC_BLEZ: /* 0 <= 0 */
4303 case OPC_BLEZL: /* 0 <= 0 likely */
4304 /* Always take */
4305 ctx->hflags |= MIPS_HFLAG_B;
4306 break;
4307 case OPC_BGEZAL: /* 0 >= 0 */
4308 case OPC_BGEZALL: /* 0 >= 0 likely */
4309 /* Always take and link */
4310 blink = 31;
4311 ctx->hflags |= MIPS_HFLAG_B;
4312 break;
4313 case OPC_BNE: /* rx != rx */
4314 case OPC_BGTZ: /* 0 > 0 */
4315 case OPC_BLTZ: /* 0 < 0 */
4316 /* Treat as NOP. */
4317 goto out;
4318 case OPC_BLTZAL: /* 0 < 0 */
4319 /* Handle as an unconditional branch to get correct delay
4320 slot checking. */
4321 blink = 31;
4322 btgt = ctx->pc + insn_bytes + delayslot_size;
4323 ctx->hflags |= MIPS_HFLAG_B;
4324 break;
4325 case OPC_BLTZALL: /* 0 < 0 likely */
4326 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4327 /* Skip the instruction in the delay slot */
4328 ctx->pc += 4;
4329 goto out;
4330 case OPC_BNEL: /* rx != rx likely */
4331 case OPC_BGTZL: /* 0 > 0 likely */
4332 case OPC_BLTZL: /* 0 < 0 likely */
4333 /* Skip the instruction in the delay slot */
4334 ctx->pc += 4;
4335 goto out;
4336 case OPC_J:
4337 ctx->hflags |= MIPS_HFLAG_B;
4338 break;
4339 case OPC_JALX:
4340 ctx->hflags |= MIPS_HFLAG_BX;
4341 /* Fallthrough */
4342 case OPC_JAL:
4343 blink = 31;
4344 ctx->hflags |= MIPS_HFLAG_B;
4345 break;
4346 case OPC_JR:
4347 ctx->hflags |= MIPS_HFLAG_BR;
4348 break;
4349 case OPC_JALR:
4350 blink = rt;
4351 ctx->hflags |= MIPS_HFLAG_BR;
4352 break;
4353 default:
4354 MIPS_INVAL("branch/jump");
4355 generate_exception_end(ctx, EXCP_RI);
4356 goto out;
4358 } else {
4359 switch (opc) {
4360 case OPC_BEQ:
4361 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4362 goto not_likely;
4363 case OPC_BEQL:
4364 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4365 goto likely;
4366 case OPC_BNE:
4367 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4368 goto not_likely;
4369 case OPC_BNEL:
4370 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4371 goto likely;
4372 case OPC_BGEZ:
4373 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4374 goto not_likely;
4375 case OPC_BGEZL:
4376 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4377 goto likely;
4378 case OPC_BGEZAL:
4379 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4380 blink = 31;
4381 goto not_likely;
4382 case OPC_BGEZALL:
4383 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4384 blink = 31;
4385 goto likely;
4386 case OPC_BGTZ:
4387 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4388 goto not_likely;
4389 case OPC_BGTZL:
4390 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4391 goto likely;
4392 case OPC_BLEZ:
4393 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4394 goto not_likely;
4395 case OPC_BLEZL:
4396 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4397 goto likely;
4398 case OPC_BLTZ:
4399 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4400 goto not_likely;
4401 case OPC_BLTZL:
4402 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4403 goto likely;
4404 case OPC_BPOSGE32:
4405 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4406 goto not_likely;
4407 #if defined(TARGET_MIPS64)
4408 case OPC_BPOSGE64:
4409 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4410 goto not_likely;
4411 #endif
4412 case OPC_BLTZAL:
4413 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4414 blink = 31;
4415 not_likely:
4416 ctx->hflags |= MIPS_HFLAG_BC;
4417 break;
4418 case OPC_BLTZALL:
4419 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4420 blink = 31;
4421 likely:
4422 ctx->hflags |= MIPS_HFLAG_BL;
4423 break;
4424 default:
4425 MIPS_INVAL("conditional branch/jump");
4426 generate_exception_end(ctx, EXCP_RI);
4427 goto out;
4431 ctx->btarget = btgt;
4433 switch (delayslot_size) {
4434 case 2:
4435 ctx->hflags |= MIPS_HFLAG_BDS16;
4436 break;
4437 case 4:
4438 ctx->hflags |= MIPS_HFLAG_BDS32;
4439 break;
4442 if (blink > 0) {
4443 int post_delay = insn_bytes + delayslot_size;
4444 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4446 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4449 out:
4450 if (insn_bytes == 2)
4451 ctx->hflags |= MIPS_HFLAG_B16;
4452 tcg_temp_free(t0);
4453 tcg_temp_free(t1);
4456 /* special3 bitfield operations */
4457 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4458 int rs, int lsb, int msb)
4460 TCGv t0 = tcg_temp_new();
4461 TCGv t1 = tcg_temp_new();
4463 gen_load_gpr(t1, rs);
4464 switch (opc) {
4465 case OPC_EXT:
4466 if (lsb + msb > 31) {
4467 goto fail;
4469 tcg_gen_shri_tl(t0, t1, lsb);
4470 if (msb != 31) {
4471 tcg_gen_andi_tl(t0, t0, (1U << (msb + 1)) - 1);
4472 } else {
4473 tcg_gen_ext32s_tl(t0, t0);
4475 break;
4476 #if defined(TARGET_MIPS64)
4477 case OPC_DEXTU:
4478 lsb += 32;
4479 goto do_dext;
4480 case OPC_DEXTM:
4481 msb += 32;
4482 goto do_dext;
4483 case OPC_DEXT:
4484 do_dext:
4485 if (lsb + msb > 63) {
4486 goto fail;
4488 tcg_gen_shri_tl(t0, t1, lsb);
4489 if (msb != 63) {
4490 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4492 break;
4493 #endif
4494 case OPC_INS:
4495 if (lsb > msb) {
4496 goto fail;
4498 gen_load_gpr(t0, rt);
4499 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4500 tcg_gen_ext32s_tl(t0, t0);
4501 break;
4502 #if defined(TARGET_MIPS64)
4503 case OPC_DINSU:
4504 lsb += 32;
4505 /* FALLTHRU */
4506 case OPC_DINSM:
4507 msb += 32;
4508 /* FALLTHRU */
4509 case OPC_DINS:
4510 if (lsb > msb) {
4511 goto fail;
4513 gen_load_gpr(t0, rt);
4514 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4515 break;
4516 #endif
4517 default:
4518 fail:
4519 MIPS_INVAL("bitops");
4520 generate_exception_end(ctx, EXCP_RI);
4521 tcg_temp_free(t0);
4522 tcg_temp_free(t1);
4523 return;
4525 gen_store_gpr(t0, rt);
4526 tcg_temp_free(t0);
4527 tcg_temp_free(t1);
4530 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4532 TCGv t0;
4534 if (rd == 0) {
4535 /* If no destination, treat it as a NOP. */
4536 return;
4539 t0 = tcg_temp_new();
4540 gen_load_gpr(t0, rt);
4541 switch (op2) {
4542 case OPC_WSBH:
4544 TCGv t1 = tcg_temp_new();
4546 tcg_gen_shri_tl(t1, t0, 8);
4547 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4548 tcg_gen_shli_tl(t0, t0, 8);
4549 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4550 tcg_gen_or_tl(t0, t0, t1);
4551 tcg_temp_free(t1);
4552 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4554 break;
4555 case OPC_SEB:
4556 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4557 break;
4558 case OPC_SEH:
4559 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4560 break;
4561 #if defined(TARGET_MIPS64)
4562 case OPC_DSBH:
4564 TCGv t1 = tcg_temp_new();
4566 tcg_gen_shri_tl(t1, t0, 8);
4567 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4568 tcg_gen_shli_tl(t0, t0, 8);
4569 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4570 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4571 tcg_temp_free(t1);
4573 break;
4574 case OPC_DSHD:
4576 TCGv t1 = tcg_temp_new();
4578 tcg_gen_shri_tl(t1, t0, 16);
4579 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4580 tcg_gen_shli_tl(t0, t0, 16);
4581 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4582 tcg_gen_or_tl(t0, t0, t1);
4583 tcg_gen_shri_tl(t1, t0, 32);
4584 tcg_gen_shli_tl(t0, t0, 32);
4585 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4586 tcg_temp_free(t1);
4588 break;
4589 #endif
4590 default:
4591 MIPS_INVAL("bsfhl");
4592 generate_exception_end(ctx, EXCP_RI);
4593 tcg_temp_free(t0);
4594 return;
4596 tcg_temp_free(t0);
4599 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4600 int imm2)
4602 TCGv t0;
4603 TCGv t1;
4604 if (rd == 0) {
4605 /* Treat as NOP. */
4606 return;
4608 t0 = tcg_temp_new();
4609 t1 = tcg_temp_new();
4610 gen_load_gpr(t0, rs);
4611 gen_load_gpr(t1, rt);
4612 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4613 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4614 if (opc == OPC_LSA) {
4615 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4618 tcg_temp_free(t1);
4619 tcg_temp_free(t0);
4621 return;
4624 static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt,
4625 int bp)
4627 TCGv t0;
4628 if (rd == 0) {
4629 /* Treat as NOP. */
4630 return;
4632 t0 = tcg_temp_new();
4633 gen_load_gpr(t0, rt);
4634 if (bp == 0) {
4635 switch (opc) {
4636 case OPC_ALIGN:
4637 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4638 break;
4639 #if defined(TARGET_MIPS64)
4640 case OPC_DALIGN:
4641 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4642 break;
4643 #endif
4645 } else {
4646 TCGv t1 = tcg_temp_new();
4647 gen_load_gpr(t1, rs);
4648 switch (opc) {
4649 case OPC_ALIGN:
4651 TCGv_i64 t2 = tcg_temp_new_i64();
4652 tcg_gen_concat_tl_i64(t2, t1, t0);
4653 tcg_gen_shri_i64(t2, t2, 8 * (4 - bp));
4654 gen_move_low32(cpu_gpr[rd], t2);
4655 tcg_temp_free_i64(t2);
4657 break;
4658 #if defined(TARGET_MIPS64)
4659 case OPC_DALIGN:
4660 tcg_gen_shli_tl(t0, t0, 8 * bp);
4661 tcg_gen_shri_tl(t1, t1, 8 * (8 - bp));
4662 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
4663 break;
4664 #endif
4666 tcg_temp_free(t1);
4669 tcg_temp_free(t0);
4672 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
4674 TCGv t0;
4675 if (rd == 0) {
4676 /* Treat as NOP. */
4677 return;
4679 t0 = tcg_temp_new();
4680 gen_load_gpr(t0, rt);
4681 switch (opc) {
4682 case OPC_BITSWAP:
4683 gen_helper_bitswap(cpu_gpr[rd], t0);
4684 break;
4685 #if defined(TARGET_MIPS64)
4686 case OPC_DBITSWAP:
4687 gen_helper_dbitswap(cpu_gpr[rd], t0);
4688 break;
4689 #endif
4691 tcg_temp_free(t0);
4694 #ifndef CONFIG_USER_ONLY
4695 /* CP0 (MMU and control) */
4696 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4698 TCGv_i64 t0 = tcg_temp_new_i64();
4699 TCGv_i64 t1 = tcg_temp_new_i64();
4701 tcg_gen_ext_tl_i64(t0, arg);
4702 tcg_gen_ld_i64(t1, cpu_env, off);
4703 #if defined(TARGET_MIPS64)
4704 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4705 #else
4706 tcg_gen_concat32_i64(t1, t1, t0);
4707 #endif
4708 tcg_gen_st_i64(t1, cpu_env, off);
4709 tcg_temp_free_i64(t1);
4710 tcg_temp_free_i64(t0);
4713 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4715 TCGv_i64 t0 = tcg_temp_new_i64();
4716 TCGv_i64 t1 = tcg_temp_new_i64();
4718 tcg_gen_ext_tl_i64(t0, arg);
4719 tcg_gen_ld_i64(t1, cpu_env, off);
4720 tcg_gen_concat32_i64(t1, t1, t0);
4721 tcg_gen_st_i64(t1, cpu_env, off);
4722 tcg_temp_free_i64(t1);
4723 tcg_temp_free_i64(t0);
4726 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
4728 TCGv_i64 t0 = tcg_temp_new_i64();
4730 tcg_gen_ld_i64(t0, cpu_env, off);
4731 #if defined(TARGET_MIPS64)
4732 tcg_gen_shri_i64(t0, t0, 30);
4733 #else
4734 tcg_gen_shri_i64(t0, t0, 32);
4735 #endif
4736 gen_move_low32(arg, t0);
4737 tcg_temp_free_i64(t0);
4740 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
4742 TCGv_i64 t0 = tcg_temp_new_i64();
4744 tcg_gen_ld_i64(t0, cpu_env, off);
4745 tcg_gen_shri_i64(t0, t0, 32 + shift);
4746 gen_move_low32(arg, t0);
4747 tcg_temp_free_i64(t0);
4750 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4752 TCGv_i32 t0 = tcg_temp_new_i32();
4754 tcg_gen_ld_i32(t0, cpu_env, off);
4755 tcg_gen_ext_i32_tl(arg, t0);
4756 tcg_temp_free_i32(t0);
4759 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4761 tcg_gen_ld_tl(arg, cpu_env, off);
4762 tcg_gen_ext32s_tl(arg, arg);
4765 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4767 TCGv_i32 t0 = tcg_temp_new_i32();
4769 tcg_gen_trunc_tl_i32(t0, arg);
4770 tcg_gen_st_i32(t0, cpu_env, off);
4771 tcg_temp_free_i32(t0);
4774 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4776 const char *rn = "invalid";
4778 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
4779 goto mfhc0_read_zero;
4782 switch (reg) {
4783 case 2:
4784 switch (sel) {
4785 case 0:
4786 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4787 rn = "EntryLo0";
4788 break;
4789 default:
4790 goto mfhc0_read_zero;
4792 break;
4793 case 3:
4794 switch (sel) {
4795 case 0:
4796 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4797 rn = "EntryLo1";
4798 break;
4799 default:
4800 goto mfhc0_read_zero;
4802 break;
4803 case 17:
4804 switch (sel) {
4805 case 0:
4806 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
4807 ctx->CP0_LLAddr_shift);
4808 rn = "LLAddr";
4809 break;
4810 default:
4811 goto mfhc0_read_zero;
4813 break;
4814 case 28:
4815 switch (sel) {
4816 case 0:
4817 case 2:
4818 case 4:
4819 case 6:
4820 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
4821 rn = "TagLo";
4822 break;
4823 default:
4824 goto mfhc0_read_zero;
4826 break;
4827 default:
4828 goto mfhc0_read_zero;
4831 (void)rn; /* avoid a compiler warning */
4832 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
4833 return;
4835 mfhc0_read_zero:
4836 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
4837 tcg_gen_movi_tl(arg, 0);
4840 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4842 const char *rn = "invalid";
4843 uint64_t mask = ctx->PAMask >> 36;
4845 if (!(ctx->hflags & MIPS_HFLAG_ELPA)) {
4846 goto mthc0_nop;
4849 switch (reg) {
4850 case 2:
4851 switch (sel) {
4852 case 0:
4853 tcg_gen_andi_tl(arg, arg, mask);
4854 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4855 rn = "EntryLo0";
4856 break;
4857 default:
4858 goto mthc0_nop;
4860 break;
4861 case 3:
4862 switch (sel) {
4863 case 0:
4864 tcg_gen_andi_tl(arg, arg, mask);
4865 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4866 rn = "EntryLo1";
4867 break;
4868 default:
4869 goto mthc0_nop;
4871 break;
4872 case 17:
4873 switch (sel) {
4874 case 0:
4875 /* LLAddr is read-only (the only exception is bit 0 if LLB is
4876 supported); the CP0_LLAddr_rw_bitmask does not seem to be
4877 relevant for modern MIPS cores supporting MTHC0, therefore
4878 treating MTHC0 to LLAddr as NOP. */
4879 rn = "LLAddr";
4880 break;
4881 default:
4882 goto mthc0_nop;
4884 break;
4885 case 28:
4886 switch (sel) {
4887 case 0:
4888 case 2:
4889 case 4:
4890 case 6:
4891 tcg_gen_andi_tl(arg, arg, mask);
4892 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
4893 rn = "TagLo";
4894 break;
4895 default:
4896 goto mthc0_nop;
4898 break;
4899 default:
4900 goto mthc0_nop;
4903 (void)rn; /* avoid a compiler warning */
4904 mthc0_nop:
4905 LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
4908 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
4910 if (ctx->insn_flags & ISA_MIPS32R6) {
4911 tcg_gen_movi_tl(arg, 0);
4912 } else {
4913 tcg_gen_movi_tl(arg, ~0);
4917 #define CP0_CHECK(c) \
4918 do { \
4919 if (!(c)) { \
4920 goto cp0_unimplemented; \
4922 } while (0)
4924 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4926 const char *rn = "invalid";
4928 if (sel != 0)
4929 check_insn(ctx, ISA_MIPS32);
4931 switch (reg) {
4932 case 0:
4933 switch (sel) {
4934 case 0:
4935 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4936 rn = "Index";
4937 break;
4938 case 1:
4939 CP0_CHECK(ctx->insn_flags & ASE_MT);
4940 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4941 rn = "MVPControl";
4942 break;
4943 case 2:
4944 CP0_CHECK(ctx->insn_flags & ASE_MT);
4945 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4946 rn = "MVPConf0";
4947 break;
4948 case 3:
4949 CP0_CHECK(ctx->insn_flags & ASE_MT);
4950 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4951 rn = "MVPConf1";
4952 break;
4953 default:
4954 goto cp0_unimplemented;
4956 break;
4957 case 1:
4958 switch (sel) {
4959 case 0:
4960 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
4961 gen_helper_mfc0_random(arg, cpu_env);
4962 rn = "Random";
4963 break;
4964 case 1:
4965 CP0_CHECK(ctx->insn_flags & ASE_MT);
4966 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
4967 rn = "VPEControl";
4968 break;
4969 case 2:
4970 CP0_CHECK(ctx->insn_flags & ASE_MT);
4971 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
4972 rn = "VPEConf0";
4973 break;
4974 case 3:
4975 CP0_CHECK(ctx->insn_flags & ASE_MT);
4976 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
4977 rn = "VPEConf1";
4978 break;
4979 case 4:
4980 CP0_CHECK(ctx->insn_flags & ASE_MT);
4981 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
4982 rn = "YQMask";
4983 break;
4984 case 5:
4985 CP0_CHECK(ctx->insn_flags & ASE_MT);
4986 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
4987 rn = "VPESchedule";
4988 break;
4989 case 6:
4990 CP0_CHECK(ctx->insn_flags & ASE_MT);
4991 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
4992 rn = "VPEScheFBack";
4993 break;
4994 case 7:
4995 CP0_CHECK(ctx->insn_flags & ASE_MT);
4996 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
4997 rn = "VPEOpt";
4998 break;
4999 default:
5000 goto cp0_unimplemented;
5002 break;
5003 case 2:
5004 switch (sel) {
5005 case 0:
5007 TCGv_i64 tmp = tcg_temp_new_i64();
5008 tcg_gen_ld_i64(tmp, cpu_env,
5009 offsetof(CPUMIPSState, CP0_EntryLo0));
5010 #if defined(TARGET_MIPS64)
5011 if (ctx->rxi) {
5012 /* Move RI/XI fields to bits 31:30 */
5013 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5014 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5016 #endif
5017 gen_move_low32(arg, tmp);
5018 tcg_temp_free_i64(tmp);
5020 rn = "EntryLo0";
5021 break;
5022 case 1:
5023 CP0_CHECK(ctx->insn_flags & ASE_MT);
5024 gen_helper_mfc0_tcstatus(arg, cpu_env);
5025 rn = "TCStatus";
5026 break;
5027 case 2:
5028 CP0_CHECK(ctx->insn_flags & ASE_MT);
5029 gen_helper_mfc0_tcbind(arg, cpu_env);
5030 rn = "TCBind";
5031 break;
5032 case 3:
5033 CP0_CHECK(ctx->insn_flags & ASE_MT);
5034 gen_helper_mfc0_tcrestart(arg, cpu_env);
5035 rn = "TCRestart";
5036 break;
5037 case 4:
5038 CP0_CHECK(ctx->insn_flags & ASE_MT);
5039 gen_helper_mfc0_tchalt(arg, cpu_env);
5040 rn = "TCHalt";
5041 break;
5042 case 5:
5043 CP0_CHECK(ctx->insn_flags & ASE_MT);
5044 gen_helper_mfc0_tccontext(arg, cpu_env);
5045 rn = "TCContext";
5046 break;
5047 case 6:
5048 CP0_CHECK(ctx->insn_flags & ASE_MT);
5049 gen_helper_mfc0_tcschedule(arg, cpu_env);
5050 rn = "TCSchedule";
5051 break;
5052 case 7:
5053 CP0_CHECK(ctx->insn_flags & ASE_MT);
5054 gen_helper_mfc0_tcschefback(arg, cpu_env);
5055 rn = "TCScheFBack";
5056 break;
5057 default:
5058 goto cp0_unimplemented;
5060 break;
5061 case 3:
5062 switch (sel) {
5063 case 0:
5065 TCGv_i64 tmp = tcg_temp_new_i64();
5066 tcg_gen_ld_i64(tmp, cpu_env,
5067 offsetof(CPUMIPSState, CP0_EntryLo1));
5068 #if defined(TARGET_MIPS64)
5069 if (ctx->rxi) {
5070 /* Move RI/XI fields to bits 31:30 */
5071 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5072 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5074 #endif
5075 gen_move_low32(arg, tmp);
5076 tcg_temp_free_i64(tmp);
5078 rn = "EntryLo1";
5079 break;
5080 default:
5081 goto cp0_unimplemented;
5083 break;
5084 case 4:
5085 switch (sel) {
5086 case 0:
5087 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5088 tcg_gen_ext32s_tl(arg, arg);
5089 rn = "Context";
5090 break;
5091 case 1:
5092 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5093 rn = "ContextConfig";
5094 goto cp0_unimplemented;
5095 // break;
5096 case 2:
5097 CP0_CHECK(ctx->ulri);
5098 tcg_gen_ld32s_tl(arg, cpu_env,
5099 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5100 rn = "UserLocal";
5101 break;
5102 default:
5103 goto cp0_unimplemented;
5105 break;
5106 case 5:
5107 switch (sel) {
5108 case 0:
5109 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5110 rn = "PageMask";
5111 break;
5112 case 1:
5113 check_insn(ctx, ISA_MIPS32R2);
5114 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5115 rn = "PageGrain";
5116 break;
5117 default:
5118 goto cp0_unimplemented;
5120 break;
5121 case 6:
5122 switch (sel) {
5123 case 0:
5124 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5125 rn = "Wired";
5126 break;
5127 case 1:
5128 check_insn(ctx, ISA_MIPS32R2);
5129 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5130 rn = "SRSConf0";
5131 break;
5132 case 2:
5133 check_insn(ctx, ISA_MIPS32R2);
5134 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5135 rn = "SRSConf1";
5136 break;
5137 case 3:
5138 check_insn(ctx, ISA_MIPS32R2);
5139 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5140 rn = "SRSConf2";
5141 break;
5142 case 4:
5143 check_insn(ctx, ISA_MIPS32R2);
5144 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5145 rn = "SRSConf3";
5146 break;
5147 case 5:
5148 check_insn(ctx, ISA_MIPS32R2);
5149 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5150 rn = "SRSConf4";
5151 break;
5152 default:
5153 goto cp0_unimplemented;
5155 break;
5156 case 7:
5157 switch (sel) {
5158 case 0:
5159 check_insn(ctx, ISA_MIPS32R2);
5160 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5161 rn = "HWREna";
5162 break;
5163 default:
5164 goto cp0_unimplemented;
5166 break;
5167 case 8:
5168 switch (sel) {
5169 case 0:
5170 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5171 tcg_gen_ext32s_tl(arg, arg);
5172 rn = "BadVAddr";
5173 break;
5174 case 1:
5175 CP0_CHECK(ctx->bi);
5176 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5177 rn = "BadInstr";
5178 break;
5179 case 2:
5180 CP0_CHECK(ctx->bp);
5181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5182 rn = "BadInstrP";
5183 break;
5184 default:
5185 goto cp0_unimplemented;
5187 break;
5188 case 9:
5189 switch (sel) {
5190 case 0:
5191 /* Mark as an IO operation because we read the time. */
5192 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5193 gen_io_start();
5195 gen_helper_mfc0_count(arg, cpu_env);
5196 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5197 gen_io_end();
5199 /* Break the TB to be able to take timer interrupts immediately
5200 after reading count. */
5201 ctx->bstate = BS_STOP;
5202 rn = "Count";
5203 break;
5204 /* 6,7 are implementation dependent */
5205 default:
5206 goto cp0_unimplemented;
5208 break;
5209 case 10:
5210 switch (sel) {
5211 case 0:
5212 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5213 tcg_gen_ext32s_tl(arg, arg);
5214 rn = "EntryHi";
5215 break;
5216 default:
5217 goto cp0_unimplemented;
5219 break;
5220 case 11:
5221 switch (sel) {
5222 case 0:
5223 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5224 rn = "Compare";
5225 break;
5226 /* 6,7 are implementation dependent */
5227 default:
5228 goto cp0_unimplemented;
5230 break;
5231 case 12:
5232 switch (sel) {
5233 case 0:
5234 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5235 rn = "Status";
5236 break;
5237 case 1:
5238 check_insn(ctx, ISA_MIPS32R2);
5239 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5240 rn = "IntCtl";
5241 break;
5242 case 2:
5243 check_insn(ctx, ISA_MIPS32R2);
5244 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5245 rn = "SRSCtl";
5246 break;
5247 case 3:
5248 check_insn(ctx, ISA_MIPS32R2);
5249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5250 rn = "SRSMap";
5251 break;
5252 default:
5253 goto cp0_unimplemented;
5255 break;
5256 case 13:
5257 switch (sel) {
5258 case 0:
5259 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5260 rn = "Cause";
5261 break;
5262 default:
5263 goto cp0_unimplemented;
5265 break;
5266 case 14:
5267 switch (sel) {
5268 case 0:
5269 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5270 tcg_gen_ext32s_tl(arg, arg);
5271 rn = "EPC";
5272 break;
5273 default:
5274 goto cp0_unimplemented;
5276 break;
5277 case 15:
5278 switch (sel) {
5279 case 0:
5280 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5281 rn = "PRid";
5282 break;
5283 case 1:
5284 check_insn(ctx, ISA_MIPS32R2);
5285 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5286 rn = "EBase";
5287 break;
5288 default:
5289 goto cp0_unimplemented;
5291 break;
5292 case 16:
5293 switch (sel) {
5294 case 0:
5295 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5296 rn = "Config";
5297 break;
5298 case 1:
5299 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5300 rn = "Config1";
5301 break;
5302 case 2:
5303 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5304 rn = "Config2";
5305 break;
5306 case 3:
5307 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5308 rn = "Config3";
5309 break;
5310 case 4:
5311 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5312 rn = "Config4";
5313 break;
5314 case 5:
5315 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5316 rn = "Config5";
5317 break;
5318 /* 6,7 are implementation dependent */
5319 case 6:
5320 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5321 rn = "Config6";
5322 break;
5323 case 7:
5324 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5325 rn = "Config7";
5326 break;
5327 default:
5328 goto cp0_unimplemented;
5330 break;
5331 case 17:
5332 switch (sel) {
5333 case 0:
5334 gen_helper_mfc0_lladdr(arg, cpu_env);
5335 rn = "LLAddr";
5336 break;
5337 default:
5338 goto cp0_unimplemented;
5340 break;
5341 case 18:
5342 switch (sel) {
5343 case 0 ... 7:
5344 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5345 rn = "WatchLo";
5346 break;
5347 default:
5348 goto cp0_unimplemented;
5350 break;
5351 case 19:
5352 switch (sel) {
5353 case 0 ...7:
5354 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5355 rn = "WatchHi";
5356 break;
5357 default:
5358 goto cp0_unimplemented;
5360 break;
5361 case 20:
5362 switch (sel) {
5363 case 0:
5364 #if defined(TARGET_MIPS64)
5365 check_insn(ctx, ISA_MIPS3);
5366 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5367 tcg_gen_ext32s_tl(arg, arg);
5368 rn = "XContext";
5369 break;
5370 #endif
5371 default:
5372 goto cp0_unimplemented;
5374 break;
5375 case 21:
5376 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5377 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5378 switch (sel) {
5379 case 0:
5380 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5381 rn = "Framemask";
5382 break;
5383 default:
5384 goto cp0_unimplemented;
5386 break;
5387 case 22:
5388 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5389 rn = "'Diagnostic"; /* implementation dependent */
5390 break;
5391 case 23:
5392 switch (sel) {
5393 case 0:
5394 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5395 rn = "Debug";
5396 break;
5397 case 1:
5398 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5399 rn = "TraceControl";
5400 // break;
5401 case 2:
5402 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5403 rn = "TraceControl2";
5404 // break;
5405 case 3:
5406 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5407 rn = "UserTraceData";
5408 // break;
5409 case 4:
5410 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5411 rn = "TraceBPC";
5412 // break;
5413 default:
5414 goto cp0_unimplemented;
5416 break;
5417 case 24:
5418 switch (sel) {
5419 case 0:
5420 /* EJTAG support */
5421 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5422 tcg_gen_ext32s_tl(arg, arg);
5423 rn = "DEPC";
5424 break;
5425 default:
5426 goto cp0_unimplemented;
5428 break;
5429 case 25:
5430 switch (sel) {
5431 case 0:
5432 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5433 rn = "Performance0";
5434 break;
5435 case 1:
5436 // gen_helper_mfc0_performance1(arg);
5437 rn = "Performance1";
5438 // break;
5439 case 2:
5440 // gen_helper_mfc0_performance2(arg);
5441 rn = "Performance2";
5442 // break;
5443 case 3:
5444 // gen_helper_mfc0_performance3(arg);
5445 rn = "Performance3";
5446 // break;
5447 case 4:
5448 // gen_helper_mfc0_performance4(arg);
5449 rn = "Performance4";
5450 // break;
5451 case 5:
5452 // gen_helper_mfc0_performance5(arg);
5453 rn = "Performance5";
5454 // break;
5455 case 6:
5456 // gen_helper_mfc0_performance6(arg);
5457 rn = "Performance6";
5458 // break;
5459 case 7:
5460 // gen_helper_mfc0_performance7(arg);
5461 rn = "Performance7";
5462 // break;
5463 default:
5464 goto cp0_unimplemented;
5466 break;
5467 case 26:
5468 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5469 rn = "ECC";
5470 break;
5471 case 27:
5472 switch (sel) {
5473 case 0 ... 3:
5474 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5475 rn = "CacheErr";
5476 break;
5477 default:
5478 goto cp0_unimplemented;
5480 break;
5481 case 28:
5482 switch (sel) {
5483 case 0:
5484 case 2:
5485 case 4:
5486 case 6:
5488 TCGv_i64 tmp = tcg_temp_new_i64();
5489 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5490 gen_move_low32(arg, tmp);
5491 tcg_temp_free_i64(tmp);
5493 rn = "TagLo";
5494 break;
5495 case 1:
5496 case 3:
5497 case 5:
5498 case 7:
5499 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5500 rn = "DataLo";
5501 break;
5502 default:
5503 goto cp0_unimplemented;
5505 break;
5506 case 29:
5507 switch (sel) {
5508 case 0:
5509 case 2:
5510 case 4:
5511 case 6:
5512 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5513 rn = "TagHi";
5514 break;
5515 case 1:
5516 case 3:
5517 case 5:
5518 case 7:
5519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5520 rn = "DataHi";
5521 break;
5522 default:
5523 goto cp0_unimplemented;
5525 break;
5526 case 30:
5527 switch (sel) {
5528 case 0:
5529 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5530 tcg_gen_ext32s_tl(arg, arg);
5531 rn = "ErrorEPC";
5532 break;
5533 default:
5534 goto cp0_unimplemented;
5536 break;
5537 case 31:
5538 switch (sel) {
5539 case 0:
5540 /* EJTAG support */
5541 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5542 rn = "DESAVE";
5543 break;
5544 case 2 ... 7:
5545 CP0_CHECK(ctx->kscrexist & (1 << sel));
5546 tcg_gen_ld_tl(arg, cpu_env,
5547 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5548 tcg_gen_ext32s_tl(arg, arg);
5549 rn = "KScratch";
5550 break;
5551 default:
5552 goto cp0_unimplemented;
5554 break;
5555 default:
5556 goto cp0_unimplemented;
5558 (void)rn; /* avoid a compiler warning */
5559 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5560 return;
5562 cp0_unimplemented:
5563 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5564 gen_mfc0_unimplemented(ctx, arg);
5567 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5569 const char *rn = "invalid";
5571 if (sel != 0)
5572 check_insn(ctx, ISA_MIPS32);
5574 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5575 gen_io_start();
5578 switch (reg) {
5579 case 0:
5580 switch (sel) {
5581 case 0:
5582 gen_helper_mtc0_index(cpu_env, arg);
5583 rn = "Index";
5584 break;
5585 case 1:
5586 CP0_CHECK(ctx->insn_flags & ASE_MT);
5587 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5588 rn = "MVPControl";
5589 break;
5590 case 2:
5591 CP0_CHECK(ctx->insn_flags & ASE_MT);
5592 /* ignored */
5593 rn = "MVPConf0";
5594 break;
5595 case 3:
5596 CP0_CHECK(ctx->insn_flags & ASE_MT);
5597 /* ignored */
5598 rn = "MVPConf1";
5599 break;
5600 default:
5601 goto cp0_unimplemented;
5603 break;
5604 case 1:
5605 switch (sel) {
5606 case 0:
5607 /* ignored */
5608 rn = "Random";
5609 break;
5610 case 1:
5611 CP0_CHECK(ctx->insn_flags & ASE_MT);
5612 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5613 rn = "VPEControl";
5614 break;
5615 case 2:
5616 CP0_CHECK(ctx->insn_flags & ASE_MT);
5617 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5618 rn = "VPEConf0";
5619 break;
5620 case 3:
5621 CP0_CHECK(ctx->insn_flags & ASE_MT);
5622 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5623 rn = "VPEConf1";
5624 break;
5625 case 4:
5626 CP0_CHECK(ctx->insn_flags & ASE_MT);
5627 gen_helper_mtc0_yqmask(cpu_env, arg);
5628 rn = "YQMask";
5629 break;
5630 case 5:
5631 CP0_CHECK(ctx->insn_flags & ASE_MT);
5632 tcg_gen_st_tl(arg, cpu_env,
5633 offsetof(CPUMIPSState, CP0_VPESchedule));
5634 rn = "VPESchedule";
5635 break;
5636 case 6:
5637 CP0_CHECK(ctx->insn_flags & ASE_MT);
5638 tcg_gen_st_tl(arg, cpu_env,
5639 offsetof(CPUMIPSState, CP0_VPEScheFBack));
5640 rn = "VPEScheFBack";
5641 break;
5642 case 7:
5643 CP0_CHECK(ctx->insn_flags & ASE_MT);
5644 gen_helper_mtc0_vpeopt(cpu_env, arg);
5645 rn = "VPEOpt";
5646 break;
5647 default:
5648 goto cp0_unimplemented;
5650 break;
5651 case 2:
5652 switch (sel) {
5653 case 0:
5654 gen_helper_mtc0_entrylo0(cpu_env, arg);
5655 rn = "EntryLo0";
5656 break;
5657 case 1:
5658 CP0_CHECK(ctx->insn_flags & ASE_MT);
5659 gen_helper_mtc0_tcstatus(cpu_env, arg);
5660 rn = "TCStatus";
5661 break;
5662 case 2:
5663 CP0_CHECK(ctx->insn_flags & ASE_MT);
5664 gen_helper_mtc0_tcbind(cpu_env, arg);
5665 rn = "TCBind";
5666 break;
5667 case 3:
5668 CP0_CHECK(ctx->insn_flags & ASE_MT);
5669 gen_helper_mtc0_tcrestart(cpu_env, arg);
5670 rn = "TCRestart";
5671 break;
5672 case 4:
5673 CP0_CHECK(ctx->insn_flags & ASE_MT);
5674 gen_helper_mtc0_tchalt(cpu_env, arg);
5675 rn = "TCHalt";
5676 break;
5677 case 5:
5678 CP0_CHECK(ctx->insn_flags & ASE_MT);
5679 gen_helper_mtc0_tccontext(cpu_env, arg);
5680 rn = "TCContext";
5681 break;
5682 case 6:
5683 CP0_CHECK(ctx->insn_flags & ASE_MT);
5684 gen_helper_mtc0_tcschedule(cpu_env, arg);
5685 rn = "TCSchedule";
5686 break;
5687 case 7:
5688 CP0_CHECK(ctx->insn_flags & ASE_MT);
5689 gen_helper_mtc0_tcschefback(cpu_env, arg);
5690 rn = "TCScheFBack";
5691 break;
5692 default:
5693 goto cp0_unimplemented;
5695 break;
5696 case 3:
5697 switch (sel) {
5698 case 0:
5699 gen_helper_mtc0_entrylo1(cpu_env, arg);
5700 rn = "EntryLo1";
5701 break;
5702 default:
5703 goto cp0_unimplemented;
5705 break;
5706 case 4:
5707 switch (sel) {
5708 case 0:
5709 gen_helper_mtc0_context(cpu_env, arg);
5710 rn = "Context";
5711 break;
5712 case 1:
5713 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5714 rn = "ContextConfig";
5715 goto cp0_unimplemented;
5716 // break;
5717 case 2:
5718 CP0_CHECK(ctx->ulri);
5719 tcg_gen_st_tl(arg, cpu_env,
5720 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5721 rn = "UserLocal";
5722 break;
5723 default:
5724 goto cp0_unimplemented;
5726 break;
5727 case 5:
5728 switch (sel) {
5729 case 0:
5730 gen_helper_mtc0_pagemask(cpu_env, arg);
5731 rn = "PageMask";
5732 break;
5733 case 1:
5734 check_insn(ctx, ISA_MIPS32R2);
5735 gen_helper_mtc0_pagegrain(cpu_env, arg);
5736 rn = "PageGrain";
5737 ctx->bstate = BS_STOP;
5738 break;
5739 default:
5740 goto cp0_unimplemented;
5742 break;
5743 case 6:
5744 switch (sel) {
5745 case 0:
5746 gen_helper_mtc0_wired(cpu_env, arg);
5747 rn = "Wired";
5748 break;
5749 case 1:
5750 check_insn(ctx, ISA_MIPS32R2);
5751 gen_helper_mtc0_srsconf0(cpu_env, arg);
5752 rn = "SRSConf0";
5753 break;
5754 case 2:
5755 check_insn(ctx, ISA_MIPS32R2);
5756 gen_helper_mtc0_srsconf1(cpu_env, arg);
5757 rn = "SRSConf1";
5758 break;
5759 case 3:
5760 check_insn(ctx, ISA_MIPS32R2);
5761 gen_helper_mtc0_srsconf2(cpu_env, arg);
5762 rn = "SRSConf2";
5763 break;
5764 case 4:
5765 check_insn(ctx, ISA_MIPS32R2);
5766 gen_helper_mtc0_srsconf3(cpu_env, arg);
5767 rn = "SRSConf3";
5768 break;
5769 case 5:
5770 check_insn(ctx, ISA_MIPS32R2);
5771 gen_helper_mtc0_srsconf4(cpu_env, arg);
5772 rn = "SRSConf4";
5773 break;
5774 default:
5775 goto cp0_unimplemented;
5777 break;
5778 case 7:
5779 switch (sel) {
5780 case 0:
5781 check_insn(ctx, ISA_MIPS32R2);
5782 gen_helper_mtc0_hwrena(cpu_env, arg);
5783 ctx->bstate = BS_STOP;
5784 rn = "HWREna";
5785 break;
5786 default:
5787 goto cp0_unimplemented;
5789 break;
5790 case 8:
5791 switch (sel) {
5792 case 0:
5793 /* ignored */
5794 rn = "BadVAddr";
5795 break;
5796 case 1:
5797 /* ignored */
5798 rn = "BadInstr";
5799 break;
5800 case 2:
5801 /* ignored */
5802 rn = "BadInstrP";
5803 break;
5804 default:
5805 goto cp0_unimplemented;
5807 break;
5808 case 9:
5809 switch (sel) {
5810 case 0:
5811 gen_helper_mtc0_count(cpu_env, arg);
5812 rn = "Count";
5813 break;
5814 /* 6,7 are implementation dependent */
5815 default:
5816 goto cp0_unimplemented;
5818 break;
5819 case 10:
5820 switch (sel) {
5821 case 0:
5822 gen_helper_mtc0_entryhi(cpu_env, arg);
5823 rn = "EntryHi";
5824 break;
5825 default:
5826 goto cp0_unimplemented;
5828 break;
5829 case 11:
5830 switch (sel) {
5831 case 0:
5832 gen_helper_mtc0_compare(cpu_env, arg);
5833 rn = "Compare";
5834 break;
5835 /* 6,7 are implementation dependent */
5836 default:
5837 goto cp0_unimplemented;
5839 break;
5840 case 12:
5841 switch (sel) {
5842 case 0:
5843 save_cpu_state(ctx, 1);
5844 gen_helper_mtc0_status(cpu_env, arg);
5845 /* BS_STOP isn't good enough here, hflags may have changed. */
5846 gen_save_pc(ctx->pc + 4);
5847 ctx->bstate = BS_EXCP;
5848 rn = "Status";
5849 break;
5850 case 1:
5851 check_insn(ctx, ISA_MIPS32R2);
5852 gen_helper_mtc0_intctl(cpu_env, arg);
5853 /* Stop translation as we may have switched the execution mode */
5854 ctx->bstate = BS_STOP;
5855 rn = "IntCtl";
5856 break;
5857 case 2:
5858 check_insn(ctx, ISA_MIPS32R2);
5859 gen_helper_mtc0_srsctl(cpu_env, arg);
5860 /* Stop translation as we may have switched the execution mode */
5861 ctx->bstate = BS_STOP;
5862 rn = "SRSCtl";
5863 break;
5864 case 3:
5865 check_insn(ctx, ISA_MIPS32R2);
5866 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5867 /* Stop translation as we may have switched the execution mode */
5868 ctx->bstate = BS_STOP;
5869 rn = "SRSMap";
5870 break;
5871 default:
5872 goto cp0_unimplemented;
5874 break;
5875 case 13:
5876 switch (sel) {
5877 case 0:
5878 save_cpu_state(ctx, 1);
5879 gen_helper_mtc0_cause(cpu_env, arg);
5880 rn = "Cause";
5881 break;
5882 default:
5883 goto cp0_unimplemented;
5885 break;
5886 case 14:
5887 switch (sel) {
5888 case 0:
5889 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5890 rn = "EPC";
5891 break;
5892 default:
5893 goto cp0_unimplemented;
5895 break;
5896 case 15:
5897 switch (sel) {
5898 case 0:
5899 /* ignored */
5900 rn = "PRid";
5901 break;
5902 case 1:
5903 check_insn(ctx, ISA_MIPS32R2);
5904 gen_helper_mtc0_ebase(cpu_env, arg);
5905 rn = "EBase";
5906 break;
5907 default:
5908 goto cp0_unimplemented;
5910 break;
5911 case 16:
5912 switch (sel) {
5913 case 0:
5914 gen_helper_mtc0_config0(cpu_env, arg);
5915 rn = "Config";
5916 /* Stop translation as we may have switched the execution mode */
5917 ctx->bstate = BS_STOP;
5918 break;
5919 case 1:
5920 /* ignored, read only */
5921 rn = "Config1";
5922 break;
5923 case 2:
5924 gen_helper_mtc0_config2(cpu_env, arg);
5925 rn = "Config2";
5926 /* Stop translation as we may have switched the execution mode */
5927 ctx->bstate = BS_STOP;
5928 break;
5929 case 3:
5930 gen_helper_mtc0_config3(cpu_env, arg);
5931 rn = "Config3";
5932 /* Stop translation as we may have switched the execution mode */
5933 ctx->bstate = BS_STOP;
5934 break;
5935 case 4:
5936 gen_helper_mtc0_config4(cpu_env, arg);
5937 rn = "Config4";
5938 ctx->bstate = BS_STOP;
5939 break;
5940 case 5:
5941 gen_helper_mtc0_config5(cpu_env, arg);
5942 rn = "Config5";
5943 /* Stop translation as we may have switched the execution mode */
5944 ctx->bstate = BS_STOP;
5945 break;
5946 /* 6,7 are implementation dependent */
5947 case 6:
5948 /* ignored */
5949 rn = "Config6";
5950 break;
5951 case 7:
5952 /* ignored */
5953 rn = "Config7";
5954 break;
5955 default:
5956 rn = "Invalid config selector";
5957 goto cp0_unimplemented;
5959 break;
5960 case 17:
5961 switch (sel) {
5962 case 0:
5963 gen_helper_mtc0_lladdr(cpu_env, arg);
5964 rn = "LLAddr";
5965 break;
5966 default:
5967 goto cp0_unimplemented;
5969 break;
5970 case 18:
5971 switch (sel) {
5972 case 0 ... 7:
5973 gen_helper_0e1i(mtc0_watchlo, arg, sel);
5974 rn = "WatchLo";
5975 break;
5976 default:
5977 goto cp0_unimplemented;
5979 break;
5980 case 19:
5981 switch (sel) {
5982 case 0 ... 7:
5983 gen_helper_0e1i(mtc0_watchhi, arg, sel);
5984 rn = "WatchHi";
5985 break;
5986 default:
5987 goto cp0_unimplemented;
5989 break;
5990 case 20:
5991 switch (sel) {
5992 case 0:
5993 #if defined(TARGET_MIPS64)
5994 check_insn(ctx, ISA_MIPS3);
5995 gen_helper_mtc0_xcontext(cpu_env, arg);
5996 rn = "XContext";
5997 break;
5998 #endif
5999 default:
6000 goto cp0_unimplemented;
6002 break;
6003 case 21:
6004 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6005 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6006 switch (sel) {
6007 case 0:
6008 gen_helper_mtc0_framemask(cpu_env, arg);
6009 rn = "Framemask";
6010 break;
6011 default:
6012 goto cp0_unimplemented;
6014 break;
6015 case 22:
6016 /* ignored */
6017 rn = "Diagnostic"; /* implementation dependent */
6018 break;
6019 case 23:
6020 switch (sel) {
6021 case 0:
6022 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6023 /* BS_STOP isn't good enough here, hflags may have changed. */
6024 gen_save_pc(ctx->pc + 4);
6025 ctx->bstate = BS_EXCP;
6026 rn = "Debug";
6027 break;
6028 case 1:
6029 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6030 rn = "TraceControl";
6031 /* Stop translation as we may have switched the execution mode */
6032 ctx->bstate = BS_STOP;
6033 // break;
6034 case 2:
6035 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6036 rn = "TraceControl2";
6037 /* Stop translation as we may have switched the execution mode */
6038 ctx->bstate = BS_STOP;
6039 // break;
6040 case 3:
6041 /* Stop translation as we may have switched the execution mode */
6042 ctx->bstate = BS_STOP;
6043 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6044 rn = "UserTraceData";
6045 /* Stop translation as we may have switched the execution mode */
6046 ctx->bstate = BS_STOP;
6047 // break;
6048 case 4:
6049 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6050 /* Stop translation as we may have switched the execution mode */
6051 ctx->bstate = BS_STOP;
6052 rn = "TraceBPC";
6053 // break;
6054 default:
6055 goto cp0_unimplemented;
6057 break;
6058 case 24:
6059 switch (sel) {
6060 case 0:
6061 /* EJTAG support */
6062 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6063 rn = "DEPC";
6064 break;
6065 default:
6066 goto cp0_unimplemented;
6068 break;
6069 case 25:
6070 switch (sel) {
6071 case 0:
6072 gen_helper_mtc0_performance0(cpu_env, arg);
6073 rn = "Performance0";
6074 break;
6075 case 1:
6076 // gen_helper_mtc0_performance1(arg);
6077 rn = "Performance1";
6078 // break;
6079 case 2:
6080 // gen_helper_mtc0_performance2(arg);
6081 rn = "Performance2";
6082 // break;
6083 case 3:
6084 // gen_helper_mtc0_performance3(arg);
6085 rn = "Performance3";
6086 // break;
6087 case 4:
6088 // gen_helper_mtc0_performance4(arg);
6089 rn = "Performance4";
6090 // break;
6091 case 5:
6092 // gen_helper_mtc0_performance5(arg);
6093 rn = "Performance5";
6094 // break;
6095 case 6:
6096 // gen_helper_mtc0_performance6(arg);
6097 rn = "Performance6";
6098 // break;
6099 case 7:
6100 // gen_helper_mtc0_performance7(arg);
6101 rn = "Performance7";
6102 // break;
6103 default:
6104 goto cp0_unimplemented;
6106 break;
6107 case 26:
6108 /* ignored */
6109 rn = "ECC";
6110 break;
6111 case 27:
6112 switch (sel) {
6113 case 0 ... 3:
6114 /* ignored */
6115 rn = "CacheErr";
6116 break;
6117 default:
6118 goto cp0_unimplemented;
6120 break;
6121 case 28:
6122 switch (sel) {
6123 case 0:
6124 case 2:
6125 case 4:
6126 case 6:
6127 gen_helper_mtc0_taglo(cpu_env, arg);
6128 rn = "TagLo";
6129 break;
6130 case 1:
6131 case 3:
6132 case 5:
6133 case 7:
6134 gen_helper_mtc0_datalo(cpu_env, arg);
6135 rn = "DataLo";
6136 break;
6137 default:
6138 goto cp0_unimplemented;
6140 break;
6141 case 29:
6142 switch (sel) {
6143 case 0:
6144 case 2:
6145 case 4:
6146 case 6:
6147 gen_helper_mtc0_taghi(cpu_env, arg);
6148 rn = "TagHi";
6149 break;
6150 case 1:
6151 case 3:
6152 case 5:
6153 case 7:
6154 gen_helper_mtc0_datahi(cpu_env, arg);
6155 rn = "DataHi";
6156 break;
6157 default:
6158 rn = "invalid sel";
6159 goto cp0_unimplemented;
6161 break;
6162 case 30:
6163 switch (sel) {
6164 case 0:
6165 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6166 rn = "ErrorEPC";
6167 break;
6168 default:
6169 goto cp0_unimplemented;
6171 break;
6172 case 31:
6173 switch (sel) {
6174 case 0:
6175 /* EJTAG support */
6176 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6177 rn = "DESAVE";
6178 break;
6179 case 2 ... 7:
6180 CP0_CHECK(ctx->kscrexist & (1 << sel));
6181 tcg_gen_st_tl(arg, cpu_env,
6182 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6183 rn = "KScratch";
6184 break;
6185 default:
6186 goto cp0_unimplemented;
6188 /* Stop translation as we may have switched the execution mode */
6189 ctx->bstate = BS_STOP;
6190 break;
6191 default:
6192 goto cp0_unimplemented;
6194 (void)rn; /* avoid a compiler warning */
6195 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6196 /* For simplicity assume that all writes can cause interrupts. */
6197 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6198 gen_io_end();
6199 ctx->bstate = BS_STOP;
6201 return;
6203 cp0_unimplemented:
6204 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6207 #if defined(TARGET_MIPS64)
6208 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6210 const char *rn = "invalid";
6212 if (sel != 0)
6213 check_insn(ctx, ISA_MIPS64);
6215 switch (reg) {
6216 case 0:
6217 switch (sel) {
6218 case 0:
6219 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6220 rn = "Index";
6221 break;
6222 case 1:
6223 CP0_CHECK(ctx->insn_flags & ASE_MT);
6224 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6225 rn = "MVPControl";
6226 break;
6227 case 2:
6228 CP0_CHECK(ctx->insn_flags & ASE_MT);
6229 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6230 rn = "MVPConf0";
6231 break;
6232 case 3:
6233 CP0_CHECK(ctx->insn_flags & ASE_MT);
6234 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6235 rn = "MVPConf1";
6236 break;
6237 default:
6238 goto cp0_unimplemented;
6240 break;
6241 case 1:
6242 switch (sel) {
6243 case 0:
6244 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6245 gen_helper_mfc0_random(arg, cpu_env);
6246 rn = "Random";
6247 break;
6248 case 1:
6249 CP0_CHECK(ctx->insn_flags & ASE_MT);
6250 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6251 rn = "VPEControl";
6252 break;
6253 case 2:
6254 CP0_CHECK(ctx->insn_flags & ASE_MT);
6255 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6256 rn = "VPEConf0";
6257 break;
6258 case 3:
6259 CP0_CHECK(ctx->insn_flags & ASE_MT);
6260 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6261 rn = "VPEConf1";
6262 break;
6263 case 4:
6264 CP0_CHECK(ctx->insn_flags & ASE_MT);
6265 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6266 rn = "YQMask";
6267 break;
6268 case 5:
6269 CP0_CHECK(ctx->insn_flags & ASE_MT);
6270 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6271 rn = "VPESchedule";
6272 break;
6273 case 6:
6274 CP0_CHECK(ctx->insn_flags & ASE_MT);
6275 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6276 rn = "VPEScheFBack";
6277 break;
6278 case 7:
6279 CP0_CHECK(ctx->insn_flags & ASE_MT);
6280 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6281 rn = "VPEOpt";
6282 break;
6283 default:
6284 goto cp0_unimplemented;
6286 break;
6287 case 2:
6288 switch (sel) {
6289 case 0:
6290 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6291 rn = "EntryLo0";
6292 break;
6293 case 1:
6294 CP0_CHECK(ctx->insn_flags & ASE_MT);
6295 gen_helper_mfc0_tcstatus(arg, cpu_env);
6296 rn = "TCStatus";
6297 break;
6298 case 2:
6299 CP0_CHECK(ctx->insn_flags & ASE_MT);
6300 gen_helper_mfc0_tcbind(arg, cpu_env);
6301 rn = "TCBind";
6302 break;
6303 case 3:
6304 CP0_CHECK(ctx->insn_flags & ASE_MT);
6305 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6306 rn = "TCRestart";
6307 break;
6308 case 4:
6309 CP0_CHECK(ctx->insn_flags & ASE_MT);
6310 gen_helper_dmfc0_tchalt(arg, cpu_env);
6311 rn = "TCHalt";
6312 break;
6313 case 5:
6314 CP0_CHECK(ctx->insn_flags & ASE_MT);
6315 gen_helper_dmfc0_tccontext(arg, cpu_env);
6316 rn = "TCContext";
6317 break;
6318 case 6:
6319 CP0_CHECK(ctx->insn_flags & ASE_MT);
6320 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6321 rn = "TCSchedule";
6322 break;
6323 case 7:
6324 CP0_CHECK(ctx->insn_flags & ASE_MT);
6325 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6326 rn = "TCScheFBack";
6327 break;
6328 default:
6329 goto cp0_unimplemented;
6331 break;
6332 case 3:
6333 switch (sel) {
6334 case 0:
6335 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6336 rn = "EntryLo1";
6337 break;
6338 default:
6339 goto cp0_unimplemented;
6341 break;
6342 case 4:
6343 switch (sel) {
6344 case 0:
6345 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6346 rn = "Context";
6347 break;
6348 case 1:
6349 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6350 rn = "ContextConfig";
6351 goto cp0_unimplemented;
6352 // break;
6353 case 2:
6354 CP0_CHECK(ctx->ulri);
6355 tcg_gen_ld_tl(arg, cpu_env,
6356 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6357 rn = "UserLocal";
6358 break;
6359 default:
6360 goto cp0_unimplemented;
6362 break;
6363 case 5:
6364 switch (sel) {
6365 case 0:
6366 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6367 rn = "PageMask";
6368 break;
6369 case 1:
6370 check_insn(ctx, ISA_MIPS32R2);
6371 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6372 rn = "PageGrain";
6373 break;
6374 default:
6375 goto cp0_unimplemented;
6377 break;
6378 case 6:
6379 switch (sel) {
6380 case 0:
6381 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6382 rn = "Wired";
6383 break;
6384 case 1:
6385 check_insn(ctx, ISA_MIPS32R2);
6386 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6387 rn = "SRSConf0";
6388 break;
6389 case 2:
6390 check_insn(ctx, ISA_MIPS32R2);
6391 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6392 rn = "SRSConf1";
6393 break;
6394 case 3:
6395 check_insn(ctx, ISA_MIPS32R2);
6396 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6397 rn = "SRSConf2";
6398 break;
6399 case 4:
6400 check_insn(ctx, ISA_MIPS32R2);
6401 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6402 rn = "SRSConf3";
6403 break;
6404 case 5:
6405 check_insn(ctx, ISA_MIPS32R2);
6406 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6407 rn = "SRSConf4";
6408 break;
6409 default:
6410 goto cp0_unimplemented;
6412 break;
6413 case 7:
6414 switch (sel) {
6415 case 0:
6416 check_insn(ctx, ISA_MIPS32R2);
6417 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6418 rn = "HWREna";
6419 break;
6420 default:
6421 goto cp0_unimplemented;
6423 break;
6424 case 8:
6425 switch (sel) {
6426 case 0:
6427 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6428 rn = "BadVAddr";
6429 break;
6430 case 1:
6431 CP0_CHECK(ctx->bi);
6432 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6433 rn = "BadInstr";
6434 break;
6435 case 2:
6436 CP0_CHECK(ctx->bp);
6437 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6438 rn = "BadInstrP";
6439 break;
6440 default:
6441 goto cp0_unimplemented;
6443 break;
6444 case 9:
6445 switch (sel) {
6446 case 0:
6447 /* Mark as an IO operation because we read the time. */
6448 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6449 gen_io_start();
6451 gen_helper_mfc0_count(arg, cpu_env);
6452 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6453 gen_io_end();
6455 /* Break the TB to be able to take timer interrupts immediately
6456 after reading count. */
6457 ctx->bstate = BS_STOP;
6458 rn = "Count";
6459 break;
6460 /* 6,7 are implementation dependent */
6461 default:
6462 goto cp0_unimplemented;
6464 break;
6465 case 10:
6466 switch (sel) {
6467 case 0:
6468 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6469 rn = "EntryHi";
6470 break;
6471 default:
6472 goto cp0_unimplemented;
6474 break;
6475 case 11:
6476 switch (sel) {
6477 case 0:
6478 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6479 rn = "Compare";
6480 break;
6481 /* 6,7 are implementation dependent */
6482 default:
6483 goto cp0_unimplemented;
6485 break;
6486 case 12:
6487 switch (sel) {
6488 case 0:
6489 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6490 rn = "Status";
6491 break;
6492 case 1:
6493 check_insn(ctx, ISA_MIPS32R2);
6494 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6495 rn = "IntCtl";
6496 break;
6497 case 2:
6498 check_insn(ctx, ISA_MIPS32R2);
6499 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6500 rn = "SRSCtl";
6501 break;
6502 case 3:
6503 check_insn(ctx, ISA_MIPS32R2);
6504 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6505 rn = "SRSMap";
6506 break;
6507 default:
6508 goto cp0_unimplemented;
6510 break;
6511 case 13:
6512 switch (sel) {
6513 case 0:
6514 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6515 rn = "Cause";
6516 break;
6517 default:
6518 goto cp0_unimplemented;
6520 break;
6521 case 14:
6522 switch (sel) {
6523 case 0:
6524 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6525 rn = "EPC";
6526 break;
6527 default:
6528 goto cp0_unimplemented;
6530 break;
6531 case 15:
6532 switch (sel) {
6533 case 0:
6534 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6535 rn = "PRid";
6536 break;
6537 case 1:
6538 check_insn(ctx, ISA_MIPS32R2);
6539 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6540 rn = "EBase";
6541 break;
6542 default:
6543 goto cp0_unimplemented;
6545 break;
6546 case 16:
6547 switch (sel) {
6548 case 0:
6549 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6550 rn = "Config";
6551 break;
6552 case 1:
6553 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6554 rn = "Config1";
6555 break;
6556 case 2:
6557 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6558 rn = "Config2";
6559 break;
6560 case 3:
6561 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6562 rn = "Config3";
6563 break;
6564 case 4:
6565 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6566 rn = "Config4";
6567 break;
6568 case 5:
6569 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6570 rn = "Config5";
6571 break;
6572 /* 6,7 are implementation dependent */
6573 case 6:
6574 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6575 rn = "Config6";
6576 break;
6577 case 7:
6578 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6579 rn = "Config7";
6580 break;
6581 default:
6582 goto cp0_unimplemented;
6584 break;
6585 case 17:
6586 switch (sel) {
6587 case 0:
6588 gen_helper_dmfc0_lladdr(arg, cpu_env);
6589 rn = "LLAddr";
6590 break;
6591 default:
6592 goto cp0_unimplemented;
6594 break;
6595 case 18:
6596 switch (sel) {
6597 case 0 ... 7:
6598 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6599 rn = "WatchLo";
6600 break;
6601 default:
6602 goto cp0_unimplemented;
6604 break;
6605 case 19:
6606 switch (sel) {
6607 case 0 ... 7:
6608 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6609 rn = "WatchHi";
6610 break;
6611 default:
6612 goto cp0_unimplemented;
6614 break;
6615 case 20:
6616 switch (sel) {
6617 case 0:
6618 check_insn(ctx, ISA_MIPS3);
6619 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6620 rn = "XContext";
6621 break;
6622 default:
6623 goto cp0_unimplemented;
6625 break;
6626 case 21:
6627 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6628 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6629 switch (sel) {
6630 case 0:
6631 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6632 rn = "Framemask";
6633 break;
6634 default:
6635 goto cp0_unimplemented;
6637 break;
6638 case 22:
6639 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6640 rn = "'Diagnostic"; /* implementation dependent */
6641 break;
6642 case 23:
6643 switch (sel) {
6644 case 0:
6645 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6646 rn = "Debug";
6647 break;
6648 case 1:
6649 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6650 rn = "TraceControl";
6651 // break;
6652 case 2:
6653 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6654 rn = "TraceControl2";
6655 // break;
6656 case 3:
6657 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6658 rn = "UserTraceData";
6659 // break;
6660 case 4:
6661 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6662 rn = "TraceBPC";
6663 // break;
6664 default:
6665 goto cp0_unimplemented;
6667 break;
6668 case 24:
6669 switch (sel) {
6670 case 0:
6671 /* EJTAG support */
6672 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6673 rn = "DEPC";
6674 break;
6675 default:
6676 goto cp0_unimplemented;
6678 break;
6679 case 25:
6680 switch (sel) {
6681 case 0:
6682 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6683 rn = "Performance0";
6684 break;
6685 case 1:
6686 // gen_helper_dmfc0_performance1(arg);
6687 rn = "Performance1";
6688 // break;
6689 case 2:
6690 // gen_helper_dmfc0_performance2(arg);
6691 rn = "Performance2";
6692 // break;
6693 case 3:
6694 // gen_helper_dmfc0_performance3(arg);
6695 rn = "Performance3";
6696 // break;
6697 case 4:
6698 // gen_helper_dmfc0_performance4(arg);
6699 rn = "Performance4";
6700 // break;
6701 case 5:
6702 // gen_helper_dmfc0_performance5(arg);
6703 rn = "Performance5";
6704 // break;
6705 case 6:
6706 // gen_helper_dmfc0_performance6(arg);
6707 rn = "Performance6";
6708 // break;
6709 case 7:
6710 // gen_helper_dmfc0_performance7(arg);
6711 rn = "Performance7";
6712 // break;
6713 default:
6714 goto cp0_unimplemented;
6716 break;
6717 case 26:
6718 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6719 rn = "ECC";
6720 break;
6721 case 27:
6722 switch (sel) {
6723 /* ignored */
6724 case 0 ... 3:
6725 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6726 rn = "CacheErr";
6727 break;
6728 default:
6729 goto cp0_unimplemented;
6731 break;
6732 case 28:
6733 switch (sel) {
6734 case 0:
6735 case 2:
6736 case 4:
6737 case 6:
6738 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
6739 rn = "TagLo";
6740 break;
6741 case 1:
6742 case 3:
6743 case 5:
6744 case 7:
6745 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6746 rn = "DataLo";
6747 break;
6748 default:
6749 goto cp0_unimplemented;
6751 break;
6752 case 29:
6753 switch (sel) {
6754 case 0:
6755 case 2:
6756 case 4:
6757 case 6:
6758 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6759 rn = "TagHi";
6760 break;
6761 case 1:
6762 case 3:
6763 case 5:
6764 case 7:
6765 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6766 rn = "DataHi";
6767 break;
6768 default:
6769 goto cp0_unimplemented;
6771 break;
6772 case 30:
6773 switch (sel) {
6774 case 0:
6775 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6776 rn = "ErrorEPC";
6777 break;
6778 default:
6779 goto cp0_unimplemented;
6781 break;
6782 case 31:
6783 switch (sel) {
6784 case 0:
6785 /* EJTAG support */
6786 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6787 rn = "DESAVE";
6788 break;
6789 case 2 ... 7:
6790 CP0_CHECK(ctx->kscrexist & (1 << sel));
6791 tcg_gen_ld_tl(arg, cpu_env,
6792 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6793 rn = "KScratch";
6794 break;
6795 default:
6796 goto cp0_unimplemented;
6798 break;
6799 default:
6800 goto cp0_unimplemented;
6802 (void)rn; /* avoid a compiler warning */
6803 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6804 return;
6806 cp0_unimplemented:
6807 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6808 gen_mfc0_unimplemented(ctx, arg);
6811 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6813 const char *rn = "invalid";
6815 if (sel != 0)
6816 check_insn(ctx, ISA_MIPS64);
6818 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6819 gen_io_start();
6822 switch (reg) {
6823 case 0:
6824 switch (sel) {
6825 case 0:
6826 gen_helper_mtc0_index(cpu_env, arg);
6827 rn = "Index";
6828 break;
6829 case 1:
6830 CP0_CHECK(ctx->insn_flags & ASE_MT);
6831 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6832 rn = "MVPControl";
6833 break;
6834 case 2:
6835 CP0_CHECK(ctx->insn_flags & ASE_MT);
6836 /* ignored */
6837 rn = "MVPConf0";
6838 break;
6839 case 3:
6840 CP0_CHECK(ctx->insn_flags & ASE_MT);
6841 /* ignored */
6842 rn = "MVPConf1";
6843 break;
6844 default:
6845 goto cp0_unimplemented;
6847 break;
6848 case 1:
6849 switch (sel) {
6850 case 0:
6851 /* ignored */
6852 rn = "Random";
6853 break;
6854 case 1:
6855 CP0_CHECK(ctx->insn_flags & ASE_MT);
6856 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6857 rn = "VPEControl";
6858 break;
6859 case 2:
6860 CP0_CHECK(ctx->insn_flags & ASE_MT);
6861 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6862 rn = "VPEConf0";
6863 break;
6864 case 3:
6865 CP0_CHECK(ctx->insn_flags & ASE_MT);
6866 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6867 rn = "VPEConf1";
6868 break;
6869 case 4:
6870 CP0_CHECK(ctx->insn_flags & ASE_MT);
6871 gen_helper_mtc0_yqmask(cpu_env, arg);
6872 rn = "YQMask";
6873 break;
6874 case 5:
6875 CP0_CHECK(ctx->insn_flags & ASE_MT);
6876 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6877 rn = "VPESchedule";
6878 break;
6879 case 6:
6880 CP0_CHECK(ctx->insn_flags & ASE_MT);
6881 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6882 rn = "VPEScheFBack";
6883 break;
6884 case 7:
6885 CP0_CHECK(ctx->insn_flags & ASE_MT);
6886 gen_helper_mtc0_vpeopt(cpu_env, arg);
6887 rn = "VPEOpt";
6888 break;
6889 default:
6890 goto cp0_unimplemented;
6892 break;
6893 case 2:
6894 switch (sel) {
6895 case 0:
6896 gen_helper_dmtc0_entrylo0(cpu_env, arg);
6897 rn = "EntryLo0";
6898 break;
6899 case 1:
6900 CP0_CHECK(ctx->insn_flags & ASE_MT);
6901 gen_helper_mtc0_tcstatus(cpu_env, arg);
6902 rn = "TCStatus";
6903 break;
6904 case 2:
6905 CP0_CHECK(ctx->insn_flags & ASE_MT);
6906 gen_helper_mtc0_tcbind(cpu_env, arg);
6907 rn = "TCBind";
6908 break;
6909 case 3:
6910 CP0_CHECK(ctx->insn_flags & ASE_MT);
6911 gen_helper_mtc0_tcrestart(cpu_env, arg);
6912 rn = "TCRestart";
6913 break;
6914 case 4:
6915 CP0_CHECK(ctx->insn_flags & ASE_MT);
6916 gen_helper_mtc0_tchalt(cpu_env, arg);
6917 rn = "TCHalt";
6918 break;
6919 case 5:
6920 CP0_CHECK(ctx->insn_flags & ASE_MT);
6921 gen_helper_mtc0_tccontext(cpu_env, arg);
6922 rn = "TCContext";
6923 break;
6924 case 6:
6925 CP0_CHECK(ctx->insn_flags & ASE_MT);
6926 gen_helper_mtc0_tcschedule(cpu_env, arg);
6927 rn = "TCSchedule";
6928 break;
6929 case 7:
6930 CP0_CHECK(ctx->insn_flags & ASE_MT);
6931 gen_helper_mtc0_tcschefback(cpu_env, arg);
6932 rn = "TCScheFBack";
6933 break;
6934 default:
6935 goto cp0_unimplemented;
6937 break;
6938 case 3:
6939 switch (sel) {
6940 case 0:
6941 gen_helper_dmtc0_entrylo1(cpu_env, arg);
6942 rn = "EntryLo1";
6943 break;
6944 default:
6945 goto cp0_unimplemented;
6947 break;
6948 case 4:
6949 switch (sel) {
6950 case 0:
6951 gen_helper_mtc0_context(cpu_env, arg);
6952 rn = "Context";
6953 break;
6954 case 1:
6955 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
6956 rn = "ContextConfig";
6957 goto cp0_unimplemented;
6958 // break;
6959 case 2:
6960 CP0_CHECK(ctx->ulri);
6961 tcg_gen_st_tl(arg, cpu_env,
6962 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6963 rn = "UserLocal";
6964 break;
6965 default:
6966 goto cp0_unimplemented;
6968 break;
6969 case 5:
6970 switch (sel) {
6971 case 0:
6972 gen_helper_mtc0_pagemask(cpu_env, arg);
6973 rn = "PageMask";
6974 break;
6975 case 1:
6976 check_insn(ctx, ISA_MIPS32R2);
6977 gen_helper_mtc0_pagegrain(cpu_env, arg);
6978 rn = "PageGrain";
6979 break;
6980 default:
6981 goto cp0_unimplemented;
6983 break;
6984 case 6:
6985 switch (sel) {
6986 case 0:
6987 gen_helper_mtc0_wired(cpu_env, arg);
6988 rn = "Wired";
6989 break;
6990 case 1:
6991 check_insn(ctx, ISA_MIPS32R2);
6992 gen_helper_mtc0_srsconf0(cpu_env, arg);
6993 rn = "SRSConf0";
6994 break;
6995 case 2:
6996 check_insn(ctx, ISA_MIPS32R2);
6997 gen_helper_mtc0_srsconf1(cpu_env, arg);
6998 rn = "SRSConf1";
6999 break;
7000 case 3:
7001 check_insn(ctx, ISA_MIPS32R2);
7002 gen_helper_mtc0_srsconf2(cpu_env, arg);
7003 rn = "SRSConf2";
7004 break;
7005 case 4:
7006 check_insn(ctx, ISA_MIPS32R2);
7007 gen_helper_mtc0_srsconf3(cpu_env, arg);
7008 rn = "SRSConf3";
7009 break;
7010 case 5:
7011 check_insn(ctx, ISA_MIPS32R2);
7012 gen_helper_mtc0_srsconf4(cpu_env, arg);
7013 rn = "SRSConf4";
7014 break;
7015 default:
7016 goto cp0_unimplemented;
7018 break;
7019 case 7:
7020 switch (sel) {
7021 case 0:
7022 check_insn(ctx, ISA_MIPS32R2);
7023 gen_helper_mtc0_hwrena(cpu_env, arg);
7024 ctx->bstate = BS_STOP;
7025 rn = "HWREna";
7026 break;
7027 default:
7028 goto cp0_unimplemented;
7030 break;
7031 case 8:
7032 switch (sel) {
7033 case 0:
7034 /* ignored */
7035 rn = "BadVAddr";
7036 break;
7037 case 1:
7038 /* ignored */
7039 rn = "BadInstr";
7040 break;
7041 case 2:
7042 /* ignored */
7043 rn = "BadInstrP";
7044 break;
7045 default:
7046 goto cp0_unimplemented;
7048 break;
7049 case 9:
7050 switch (sel) {
7051 case 0:
7052 gen_helper_mtc0_count(cpu_env, arg);
7053 rn = "Count";
7054 break;
7055 /* 6,7 are implementation dependent */
7056 default:
7057 goto cp0_unimplemented;
7059 /* Stop translation as we may have switched the execution mode */
7060 ctx->bstate = BS_STOP;
7061 break;
7062 case 10:
7063 switch (sel) {
7064 case 0:
7065 gen_helper_mtc0_entryhi(cpu_env, arg);
7066 rn = "EntryHi";
7067 break;
7068 default:
7069 goto cp0_unimplemented;
7071 break;
7072 case 11:
7073 switch (sel) {
7074 case 0:
7075 gen_helper_mtc0_compare(cpu_env, arg);
7076 rn = "Compare";
7077 break;
7078 /* 6,7 are implementation dependent */
7079 default:
7080 goto cp0_unimplemented;
7082 /* Stop translation as we may have switched the execution mode */
7083 ctx->bstate = BS_STOP;
7084 break;
7085 case 12:
7086 switch (sel) {
7087 case 0:
7088 save_cpu_state(ctx, 1);
7089 gen_helper_mtc0_status(cpu_env, arg);
7090 /* BS_STOP isn't good enough here, hflags may have changed. */
7091 gen_save_pc(ctx->pc + 4);
7092 ctx->bstate = BS_EXCP;
7093 rn = "Status";
7094 break;
7095 case 1:
7096 check_insn(ctx, ISA_MIPS32R2);
7097 gen_helper_mtc0_intctl(cpu_env, arg);
7098 /* Stop translation as we may have switched the execution mode */
7099 ctx->bstate = BS_STOP;
7100 rn = "IntCtl";
7101 break;
7102 case 2:
7103 check_insn(ctx, ISA_MIPS32R2);
7104 gen_helper_mtc0_srsctl(cpu_env, arg);
7105 /* Stop translation as we may have switched the execution mode */
7106 ctx->bstate = BS_STOP;
7107 rn = "SRSCtl";
7108 break;
7109 case 3:
7110 check_insn(ctx, ISA_MIPS32R2);
7111 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7112 /* Stop translation as we may have switched the execution mode */
7113 ctx->bstate = BS_STOP;
7114 rn = "SRSMap";
7115 break;
7116 default:
7117 goto cp0_unimplemented;
7119 break;
7120 case 13:
7121 switch (sel) {
7122 case 0:
7123 save_cpu_state(ctx, 1);
7124 /* Mark as an IO operation because we may trigger a software
7125 interrupt. */
7126 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7127 gen_io_start();
7129 gen_helper_mtc0_cause(cpu_env, arg);
7130 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7131 gen_io_end();
7133 /* Stop translation as we may have triggered an intetrupt */
7134 ctx->bstate = BS_STOP;
7135 rn = "Cause";
7136 break;
7137 default:
7138 goto cp0_unimplemented;
7140 break;
7141 case 14:
7142 switch (sel) {
7143 case 0:
7144 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7145 rn = "EPC";
7146 break;
7147 default:
7148 goto cp0_unimplemented;
7150 break;
7151 case 15:
7152 switch (sel) {
7153 case 0:
7154 /* ignored */
7155 rn = "PRid";
7156 break;
7157 case 1:
7158 check_insn(ctx, ISA_MIPS32R2);
7159 gen_helper_mtc0_ebase(cpu_env, arg);
7160 rn = "EBase";
7161 break;
7162 default:
7163 goto cp0_unimplemented;
7165 break;
7166 case 16:
7167 switch (sel) {
7168 case 0:
7169 gen_helper_mtc0_config0(cpu_env, arg);
7170 rn = "Config";
7171 /* Stop translation as we may have switched the execution mode */
7172 ctx->bstate = BS_STOP;
7173 break;
7174 case 1:
7175 /* ignored, read only */
7176 rn = "Config1";
7177 break;
7178 case 2:
7179 gen_helper_mtc0_config2(cpu_env, arg);
7180 rn = "Config2";
7181 /* Stop translation as we may have switched the execution mode */
7182 ctx->bstate = BS_STOP;
7183 break;
7184 case 3:
7185 gen_helper_mtc0_config3(cpu_env, arg);
7186 rn = "Config3";
7187 /* Stop translation as we may have switched the execution mode */
7188 ctx->bstate = BS_STOP;
7189 break;
7190 case 4:
7191 /* currently ignored */
7192 rn = "Config4";
7193 break;
7194 case 5:
7195 gen_helper_mtc0_config5(cpu_env, arg);
7196 rn = "Config5";
7197 /* Stop translation as we may have switched the execution mode */
7198 ctx->bstate = BS_STOP;
7199 break;
7200 /* 6,7 are implementation dependent */
7201 default:
7202 rn = "Invalid config selector";
7203 goto cp0_unimplemented;
7205 break;
7206 case 17:
7207 switch (sel) {
7208 case 0:
7209 gen_helper_mtc0_lladdr(cpu_env, arg);
7210 rn = "LLAddr";
7211 break;
7212 default:
7213 goto cp0_unimplemented;
7215 break;
7216 case 18:
7217 switch (sel) {
7218 case 0 ... 7:
7219 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7220 rn = "WatchLo";
7221 break;
7222 default:
7223 goto cp0_unimplemented;
7225 break;
7226 case 19:
7227 switch (sel) {
7228 case 0 ... 7:
7229 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7230 rn = "WatchHi";
7231 break;
7232 default:
7233 goto cp0_unimplemented;
7235 break;
7236 case 20:
7237 switch (sel) {
7238 case 0:
7239 check_insn(ctx, ISA_MIPS3);
7240 gen_helper_mtc0_xcontext(cpu_env, arg);
7241 rn = "XContext";
7242 break;
7243 default:
7244 goto cp0_unimplemented;
7246 break;
7247 case 21:
7248 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7249 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7250 switch (sel) {
7251 case 0:
7252 gen_helper_mtc0_framemask(cpu_env, arg);
7253 rn = "Framemask";
7254 break;
7255 default:
7256 goto cp0_unimplemented;
7258 break;
7259 case 22:
7260 /* ignored */
7261 rn = "Diagnostic"; /* implementation dependent */
7262 break;
7263 case 23:
7264 switch (sel) {
7265 case 0:
7266 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7267 /* BS_STOP isn't good enough here, hflags may have changed. */
7268 gen_save_pc(ctx->pc + 4);
7269 ctx->bstate = BS_EXCP;
7270 rn = "Debug";
7271 break;
7272 case 1:
7273 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7274 /* Stop translation as we may have switched the execution mode */
7275 ctx->bstate = BS_STOP;
7276 rn = "TraceControl";
7277 // break;
7278 case 2:
7279 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7280 /* Stop translation as we may have switched the execution mode */
7281 ctx->bstate = BS_STOP;
7282 rn = "TraceControl2";
7283 // break;
7284 case 3:
7285 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7286 /* Stop translation as we may have switched the execution mode */
7287 ctx->bstate = BS_STOP;
7288 rn = "UserTraceData";
7289 // break;
7290 case 4:
7291 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7292 /* Stop translation as we may have switched the execution mode */
7293 ctx->bstate = BS_STOP;
7294 rn = "TraceBPC";
7295 // break;
7296 default:
7297 goto cp0_unimplemented;
7299 break;
7300 case 24:
7301 switch (sel) {
7302 case 0:
7303 /* EJTAG support */
7304 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7305 rn = "DEPC";
7306 break;
7307 default:
7308 goto cp0_unimplemented;
7310 break;
7311 case 25:
7312 switch (sel) {
7313 case 0:
7314 gen_helper_mtc0_performance0(cpu_env, arg);
7315 rn = "Performance0";
7316 break;
7317 case 1:
7318 // gen_helper_mtc0_performance1(cpu_env, arg);
7319 rn = "Performance1";
7320 // break;
7321 case 2:
7322 // gen_helper_mtc0_performance2(cpu_env, arg);
7323 rn = "Performance2";
7324 // break;
7325 case 3:
7326 // gen_helper_mtc0_performance3(cpu_env, arg);
7327 rn = "Performance3";
7328 // break;
7329 case 4:
7330 // gen_helper_mtc0_performance4(cpu_env, arg);
7331 rn = "Performance4";
7332 // break;
7333 case 5:
7334 // gen_helper_mtc0_performance5(cpu_env, arg);
7335 rn = "Performance5";
7336 // break;
7337 case 6:
7338 // gen_helper_mtc0_performance6(cpu_env, arg);
7339 rn = "Performance6";
7340 // break;
7341 case 7:
7342 // gen_helper_mtc0_performance7(cpu_env, arg);
7343 rn = "Performance7";
7344 // break;
7345 default:
7346 goto cp0_unimplemented;
7348 break;
7349 case 26:
7350 /* ignored */
7351 rn = "ECC";
7352 break;
7353 case 27:
7354 switch (sel) {
7355 case 0 ... 3:
7356 /* ignored */
7357 rn = "CacheErr";
7358 break;
7359 default:
7360 goto cp0_unimplemented;
7362 break;
7363 case 28:
7364 switch (sel) {
7365 case 0:
7366 case 2:
7367 case 4:
7368 case 6:
7369 gen_helper_mtc0_taglo(cpu_env, arg);
7370 rn = "TagLo";
7371 break;
7372 case 1:
7373 case 3:
7374 case 5:
7375 case 7:
7376 gen_helper_mtc0_datalo(cpu_env, arg);
7377 rn = "DataLo";
7378 break;
7379 default:
7380 goto cp0_unimplemented;
7382 break;
7383 case 29:
7384 switch (sel) {
7385 case 0:
7386 case 2:
7387 case 4:
7388 case 6:
7389 gen_helper_mtc0_taghi(cpu_env, arg);
7390 rn = "TagHi";
7391 break;
7392 case 1:
7393 case 3:
7394 case 5:
7395 case 7:
7396 gen_helper_mtc0_datahi(cpu_env, arg);
7397 rn = "DataHi";
7398 break;
7399 default:
7400 rn = "invalid sel";
7401 goto cp0_unimplemented;
7403 break;
7404 case 30:
7405 switch (sel) {
7406 case 0:
7407 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7408 rn = "ErrorEPC";
7409 break;
7410 default:
7411 goto cp0_unimplemented;
7413 break;
7414 case 31:
7415 switch (sel) {
7416 case 0:
7417 /* EJTAG support */
7418 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7419 rn = "DESAVE";
7420 break;
7421 case 2 ... 7:
7422 CP0_CHECK(ctx->kscrexist & (1 << sel));
7423 tcg_gen_st_tl(arg, cpu_env,
7424 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7425 rn = "KScratch";
7426 break;
7427 default:
7428 goto cp0_unimplemented;
7430 /* Stop translation as we may have switched the execution mode */
7431 ctx->bstate = BS_STOP;
7432 break;
7433 default:
7434 goto cp0_unimplemented;
7436 (void)rn; /* avoid a compiler warning */
7437 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7438 /* For simplicity assume that all writes can cause interrupts. */
7439 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7440 gen_io_end();
7441 ctx->bstate = BS_STOP;
7443 return;
7445 cp0_unimplemented:
7446 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7448 #endif /* TARGET_MIPS64 */
7450 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7451 int u, int sel, int h)
7453 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7454 TCGv t0 = tcg_temp_local_new();
7456 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7457 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7458 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7459 tcg_gen_movi_tl(t0, -1);
7460 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7461 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7462 tcg_gen_movi_tl(t0, -1);
7463 else if (u == 0) {
7464 switch (rt) {
7465 case 1:
7466 switch (sel) {
7467 case 1:
7468 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7469 break;
7470 case 2:
7471 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7472 break;
7473 default:
7474 goto die;
7475 break;
7477 break;
7478 case 2:
7479 switch (sel) {
7480 case 1:
7481 gen_helper_mftc0_tcstatus(t0, cpu_env);
7482 break;
7483 case 2:
7484 gen_helper_mftc0_tcbind(t0, cpu_env);
7485 break;
7486 case 3:
7487 gen_helper_mftc0_tcrestart(t0, cpu_env);
7488 break;
7489 case 4:
7490 gen_helper_mftc0_tchalt(t0, cpu_env);
7491 break;
7492 case 5:
7493 gen_helper_mftc0_tccontext(t0, cpu_env);
7494 break;
7495 case 6:
7496 gen_helper_mftc0_tcschedule(t0, cpu_env);
7497 break;
7498 case 7:
7499 gen_helper_mftc0_tcschefback(t0, cpu_env);
7500 break;
7501 default:
7502 gen_mfc0(ctx, t0, rt, sel);
7503 break;
7505 break;
7506 case 10:
7507 switch (sel) {
7508 case 0:
7509 gen_helper_mftc0_entryhi(t0, cpu_env);
7510 break;
7511 default:
7512 gen_mfc0(ctx, t0, rt, sel);
7513 break;
7515 case 12:
7516 switch (sel) {
7517 case 0:
7518 gen_helper_mftc0_status(t0, cpu_env);
7519 break;
7520 default:
7521 gen_mfc0(ctx, t0, rt, sel);
7522 break;
7524 case 13:
7525 switch (sel) {
7526 case 0:
7527 gen_helper_mftc0_cause(t0, cpu_env);
7528 break;
7529 default:
7530 goto die;
7531 break;
7533 break;
7534 case 14:
7535 switch (sel) {
7536 case 0:
7537 gen_helper_mftc0_epc(t0, cpu_env);
7538 break;
7539 default:
7540 goto die;
7541 break;
7543 break;
7544 case 15:
7545 switch (sel) {
7546 case 1:
7547 gen_helper_mftc0_ebase(t0, cpu_env);
7548 break;
7549 default:
7550 goto die;
7551 break;
7553 break;
7554 case 16:
7555 switch (sel) {
7556 case 0 ... 7:
7557 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7558 break;
7559 default:
7560 goto die;
7561 break;
7563 break;
7564 case 23:
7565 switch (sel) {
7566 case 0:
7567 gen_helper_mftc0_debug(t0, cpu_env);
7568 break;
7569 default:
7570 gen_mfc0(ctx, t0, rt, sel);
7571 break;
7573 break;
7574 default:
7575 gen_mfc0(ctx, t0, rt, sel);
7577 } else switch (sel) {
7578 /* GPR registers. */
7579 case 0:
7580 gen_helper_1e0i(mftgpr, t0, rt);
7581 break;
7582 /* Auxiliary CPU registers */
7583 case 1:
7584 switch (rt) {
7585 case 0:
7586 gen_helper_1e0i(mftlo, t0, 0);
7587 break;
7588 case 1:
7589 gen_helper_1e0i(mfthi, t0, 0);
7590 break;
7591 case 2:
7592 gen_helper_1e0i(mftacx, t0, 0);
7593 break;
7594 case 4:
7595 gen_helper_1e0i(mftlo, t0, 1);
7596 break;
7597 case 5:
7598 gen_helper_1e0i(mfthi, t0, 1);
7599 break;
7600 case 6:
7601 gen_helper_1e0i(mftacx, t0, 1);
7602 break;
7603 case 8:
7604 gen_helper_1e0i(mftlo, t0, 2);
7605 break;
7606 case 9:
7607 gen_helper_1e0i(mfthi, t0, 2);
7608 break;
7609 case 10:
7610 gen_helper_1e0i(mftacx, t0, 2);
7611 break;
7612 case 12:
7613 gen_helper_1e0i(mftlo, t0, 3);
7614 break;
7615 case 13:
7616 gen_helper_1e0i(mfthi, t0, 3);
7617 break;
7618 case 14:
7619 gen_helper_1e0i(mftacx, t0, 3);
7620 break;
7621 case 16:
7622 gen_helper_mftdsp(t0, cpu_env);
7623 break;
7624 default:
7625 goto die;
7627 break;
7628 /* Floating point (COP1). */
7629 case 2:
7630 /* XXX: For now we support only a single FPU context. */
7631 if (h == 0) {
7632 TCGv_i32 fp0 = tcg_temp_new_i32();
7634 gen_load_fpr32(ctx, fp0, rt);
7635 tcg_gen_ext_i32_tl(t0, fp0);
7636 tcg_temp_free_i32(fp0);
7637 } else {
7638 TCGv_i32 fp0 = tcg_temp_new_i32();
7640 gen_load_fpr32h(ctx, fp0, rt);
7641 tcg_gen_ext_i32_tl(t0, fp0);
7642 tcg_temp_free_i32(fp0);
7644 break;
7645 case 3:
7646 /* XXX: For now we support only a single FPU context. */
7647 gen_helper_1e0i(cfc1, t0, rt);
7648 break;
7649 /* COP2: Not implemented. */
7650 case 4:
7651 case 5:
7652 /* fall through */
7653 default:
7654 goto die;
7656 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7657 gen_store_gpr(t0, rd);
7658 tcg_temp_free(t0);
7659 return;
7661 die:
7662 tcg_temp_free(t0);
7663 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7664 generate_exception_end(ctx, EXCP_RI);
7667 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7668 int u, int sel, int h)
7670 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7671 TCGv t0 = tcg_temp_local_new();
7673 gen_load_gpr(t0, rt);
7674 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7675 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7676 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7677 /* NOP */ ;
7678 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7679 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7680 /* NOP */ ;
7681 else if (u == 0) {
7682 switch (rd) {
7683 case 1:
7684 switch (sel) {
7685 case 1:
7686 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7687 break;
7688 case 2:
7689 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7690 break;
7691 default:
7692 goto die;
7693 break;
7695 break;
7696 case 2:
7697 switch (sel) {
7698 case 1:
7699 gen_helper_mttc0_tcstatus(cpu_env, t0);
7700 break;
7701 case 2:
7702 gen_helper_mttc0_tcbind(cpu_env, t0);
7703 break;
7704 case 3:
7705 gen_helper_mttc0_tcrestart(cpu_env, t0);
7706 break;
7707 case 4:
7708 gen_helper_mttc0_tchalt(cpu_env, t0);
7709 break;
7710 case 5:
7711 gen_helper_mttc0_tccontext(cpu_env, t0);
7712 break;
7713 case 6:
7714 gen_helper_mttc0_tcschedule(cpu_env, t0);
7715 break;
7716 case 7:
7717 gen_helper_mttc0_tcschefback(cpu_env, t0);
7718 break;
7719 default:
7720 gen_mtc0(ctx, t0, rd, sel);
7721 break;
7723 break;
7724 case 10:
7725 switch (sel) {
7726 case 0:
7727 gen_helper_mttc0_entryhi(cpu_env, t0);
7728 break;
7729 default:
7730 gen_mtc0(ctx, t0, rd, sel);
7731 break;
7733 case 12:
7734 switch (sel) {
7735 case 0:
7736 gen_helper_mttc0_status(cpu_env, t0);
7737 break;
7738 default:
7739 gen_mtc0(ctx, t0, rd, sel);
7740 break;
7742 case 13:
7743 switch (sel) {
7744 case 0:
7745 gen_helper_mttc0_cause(cpu_env, t0);
7746 break;
7747 default:
7748 goto die;
7749 break;
7751 break;
7752 case 15:
7753 switch (sel) {
7754 case 1:
7755 gen_helper_mttc0_ebase(cpu_env, t0);
7756 break;
7757 default:
7758 goto die;
7759 break;
7761 break;
7762 case 23:
7763 switch (sel) {
7764 case 0:
7765 gen_helper_mttc0_debug(cpu_env, t0);
7766 break;
7767 default:
7768 gen_mtc0(ctx, t0, rd, sel);
7769 break;
7771 break;
7772 default:
7773 gen_mtc0(ctx, t0, rd, sel);
7775 } else switch (sel) {
7776 /* GPR registers. */
7777 case 0:
7778 gen_helper_0e1i(mttgpr, t0, rd);
7779 break;
7780 /* Auxiliary CPU registers */
7781 case 1:
7782 switch (rd) {
7783 case 0:
7784 gen_helper_0e1i(mttlo, t0, 0);
7785 break;
7786 case 1:
7787 gen_helper_0e1i(mtthi, t0, 0);
7788 break;
7789 case 2:
7790 gen_helper_0e1i(mttacx, t0, 0);
7791 break;
7792 case 4:
7793 gen_helper_0e1i(mttlo, t0, 1);
7794 break;
7795 case 5:
7796 gen_helper_0e1i(mtthi, t0, 1);
7797 break;
7798 case 6:
7799 gen_helper_0e1i(mttacx, t0, 1);
7800 break;
7801 case 8:
7802 gen_helper_0e1i(mttlo, t0, 2);
7803 break;
7804 case 9:
7805 gen_helper_0e1i(mtthi, t0, 2);
7806 break;
7807 case 10:
7808 gen_helper_0e1i(mttacx, t0, 2);
7809 break;
7810 case 12:
7811 gen_helper_0e1i(mttlo, t0, 3);
7812 break;
7813 case 13:
7814 gen_helper_0e1i(mtthi, t0, 3);
7815 break;
7816 case 14:
7817 gen_helper_0e1i(mttacx, t0, 3);
7818 break;
7819 case 16:
7820 gen_helper_mttdsp(cpu_env, t0);
7821 break;
7822 default:
7823 goto die;
7825 break;
7826 /* Floating point (COP1). */
7827 case 2:
7828 /* XXX: For now we support only a single FPU context. */
7829 if (h == 0) {
7830 TCGv_i32 fp0 = tcg_temp_new_i32();
7832 tcg_gen_trunc_tl_i32(fp0, t0);
7833 gen_store_fpr32(ctx, fp0, rd);
7834 tcg_temp_free_i32(fp0);
7835 } else {
7836 TCGv_i32 fp0 = tcg_temp_new_i32();
7838 tcg_gen_trunc_tl_i32(fp0, t0);
7839 gen_store_fpr32h(ctx, fp0, rd);
7840 tcg_temp_free_i32(fp0);
7842 break;
7843 case 3:
7844 /* XXX: For now we support only a single FPU context. */
7846 TCGv_i32 fs_tmp = tcg_const_i32(rd);
7848 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
7849 tcg_temp_free_i32(fs_tmp);
7851 /* Stop translation as we may have changed hflags */
7852 ctx->bstate = BS_STOP;
7853 break;
7854 /* COP2: Not implemented. */
7855 case 4:
7856 case 5:
7857 /* fall through */
7858 default:
7859 goto die;
7861 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
7862 tcg_temp_free(t0);
7863 return;
7865 die:
7866 tcg_temp_free(t0);
7867 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
7868 generate_exception_end(ctx, EXCP_RI);
7871 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
7873 const char *opn = "ldst";
7875 check_cp0_enabled(ctx);
7876 switch (opc) {
7877 case OPC_MFC0:
7878 if (rt == 0) {
7879 /* Treat as NOP. */
7880 return;
7882 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7883 opn = "mfc0";
7884 break;
7885 case OPC_MTC0:
7887 TCGv t0 = tcg_temp_new();
7889 gen_load_gpr(t0, rt);
7890 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
7891 tcg_temp_free(t0);
7893 opn = "mtc0";
7894 break;
7895 #if defined(TARGET_MIPS64)
7896 case OPC_DMFC0:
7897 check_insn(ctx, ISA_MIPS3);
7898 if (rt == 0) {
7899 /* Treat as NOP. */
7900 return;
7902 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7903 opn = "dmfc0";
7904 break;
7905 case OPC_DMTC0:
7906 check_insn(ctx, ISA_MIPS3);
7908 TCGv t0 = tcg_temp_new();
7910 gen_load_gpr(t0, rt);
7911 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
7912 tcg_temp_free(t0);
7914 opn = "dmtc0";
7915 break;
7916 #endif
7917 case OPC_MFHC0:
7918 check_mvh(ctx);
7919 if (rt == 0) {
7920 /* Treat as NOP. */
7921 return;
7923 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7924 opn = "mfhc0";
7925 break;
7926 case OPC_MTHC0:
7927 check_mvh(ctx);
7929 TCGv t0 = tcg_temp_new();
7930 gen_load_gpr(t0, rt);
7931 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
7932 tcg_temp_free(t0);
7934 opn = "mthc0";
7935 break;
7936 case OPC_MFTR:
7937 check_insn(ctx, ASE_MT);
7938 if (rd == 0) {
7939 /* Treat as NOP. */
7940 return;
7942 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
7943 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
7944 opn = "mftr";
7945 break;
7946 case OPC_MTTR:
7947 check_insn(ctx, ASE_MT);
7948 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
7949 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
7950 opn = "mttr";
7951 break;
7952 case OPC_TLBWI:
7953 opn = "tlbwi";
7954 if (!env->tlb->helper_tlbwi)
7955 goto die;
7956 gen_helper_tlbwi(cpu_env);
7957 break;
7958 case OPC_TLBINV:
7959 opn = "tlbinv";
7960 if (ctx->ie >= 2) {
7961 if (!env->tlb->helper_tlbinv) {
7962 goto die;
7964 gen_helper_tlbinv(cpu_env);
7965 } /* treat as nop if TLBINV not supported */
7966 break;
7967 case OPC_TLBINVF:
7968 opn = "tlbinvf";
7969 if (ctx->ie >= 2) {
7970 if (!env->tlb->helper_tlbinvf) {
7971 goto die;
7973 gen_helper_tlbinvf(cpu_env);
7974 } /* treat as nop if TLBINV not supported */
7975 break;
7976 case OPC_TLBWR:
7977 opn = "tlbwr";
7978 if (!env->tlb->helper_tlbwr)
7979 goto die;
7980 gen_helper_tlbwr(cpu_env);
7981 break;
7982 case OPC_TLBP:
7983 opn = "tlbp";
7984 if (!env->tlb->helper_tlbp)
7985 goto die;
7986 gen_helper_tlbp(cpu_env);
7987 break;
7988 case OPC_TLBR:
7989 opn = "tlbr";
7990 if (!env->tlb->helper_tlbr)
7991 goto die;
7992 gen_helper_tlbr(cpu_env);
7993 break;
7994 case OPC_ERET: /* OPC_ERETNC */
7995 if ((ctx->insn_flags & ISA_MIPS32R6) &&
7996 (ctx->hflags & MIPS_HFLAG_BMASK)) {
7997 goto die;
7998 } else {
7999 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8000 if (ctx->opcode & (1 << bit_shift)) {
8001 /* OPC_ERETNC */
8002 opn = "eretnc";
8003 check_insn(ctx, ISA_MIPS32R5);
8004 gen_helper_eretnc(cpu_env);
8005 } else {
8006 /* OPC_ERET */
8007 opn = "eret";
8008 check_insn(ctx, ISA_MIPS2);
8009 gen_helper_eret(cpu_env);
8011 ctx->bstate = BS_EXCP;
8013 break;
8014 case OPC_DERET:
8015 opn = "deret";
8016 check_insn(ctx, ISA_MIPS32);
8017 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8018 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8019 goto die;
8021 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8022 MIPS_INVAL(opn);
8023 generate_exception_end(ctx, EXCP_RI);
8024 } else {
8025 gen_helper_deret(cpu_env);
8026 ctx->bstate = BS_EXCP;
8028 break;
8029 case OPC_WAIT:
8030 opn = "wait";
8031 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8032 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8033 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8034 goto die;
8036 /* If we get an exception, we want to restart at next instruction */
8037 ctx->pc += 4;
8038 save_cpu_state(ctx, 1);
8039 ctx->pc -= 4;
8040 gen_helper_wait(cpu_env);
8041 ctx->bstate = BS_EXCP;
8042 break;
8043 default:
8044 die:
8045 MIPS_INVAL(opn);
8046 generate_exception_end(ctx, EXCP_RI);
8047 return;
8049 (void)opn; /* avoid a compiler warning */
8051 #endif /* !CONFIG_USER_ONLY */
8053 /* CP1 Branches (before delay slot) */
8054 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8055 int32_t cc, int32_t offset)
8057 target_ulong btarget;
8058 TCGv_i32 t0 = tcg_temp_new_i32();
8060 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8061 generate_exception_end(ctx, EXCP_RI);
8062 goto out;
8065 if (cc != 0)
8066 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8068 btarget = ctx->pc + 4 + offset;
8070 switch (op) {
8071 case OPC_BC1F:
8072 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8073 tcg_gen_not_i32(t0, t0);
8074 tcg_gen_andi_i32(t0, t0, 1);
8075 tcg_gen_extu_i32_tl(bcond, t0);
8076 goto not_likely;
8077 case OPC_BC1FL:
8078 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8079 tcg_gen_not_i32(t0, t0);
8080 tcg_gen_andi_i32(t0, t0, 1);
8081 tcg_gen_extu_i32_tl(bcond, t0);
8082 goto likely;
8083 case OPC_BC1T:
8084 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8085 tcg_gen_andi_i32(t0, t0, 1);
8086 tcg_gen_extu_i32_tl(bcond, t0);
8087 goto not_likely;
8088 case OPC_BC1TL:
8089 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8090 tcg_gen_andi_i32(t0, t0, 1);
8091 tcg_gen_extu_i32_tl(bcond, t0);
8092 likely:
8093 ctx->hflags |= MIPS_HFLAG_BL;
8094 break;
8095 case OPC_BC1FANY2:
8097 TCGv_i32 t1 = tcg_temp_new_i32();
8098 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8099 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8100 tcg_gen_nand_i32(t0, t0, t1);
8101 tcg_temp_free_i32(t1);
8102 tcg_gen_andi_i32(t0, t0, 1);
8103 tcg_gen_extu_i32_tl(bcond, t0);
8105 goto not_likely;
8106 case OPC_BC1TANY2:
8108 TCGv_i32 t1 = tcg_temp_new_i32();
8109 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8110 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8111 tcg_gen_or_i32(t0, t0, t1);
8112 tcg_temp_free_i32(t1);
8113 tcg_gen_andi_i32(t0, t0, 1);
8114 tcg_gen_extu_i32_tl(bcond, t0);
8116 goto not_likely;
8117 case OPC_BC1FANY4:
8119 TCGv_i32 t1 = tcg_temp_new_i32();
8120 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8121 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8122 tcg_gen_and_i32(t0, t0, t1);
8123 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8124 tcg_gen_and_i32(t0, t0, t1);
8125 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8126 tcg_gen_nand_i32(t0, t0, t1);
8127 tcg_temp_free_i32(t1);
8128 tcg_gen_andi_i32(t0, t0, 1);
8129 tcg_gen_extu_i32_tl(bcond, t0);
8131 goto not_likely;
8132 case OPC_BC1TANY4:
8134 TCGv_i32 t1 = tcg_temp_new_i32();
8135 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8136 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8137 tcg_gen_or_i32(t0, t0, t1);
8138 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8139 tcg_gen_or_i32(t0, t0, t1);
8140 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8141 tcg_gen_or_i32(t0, t0, t1);
8142 tcg_temp_free_i32(t1);
8143 tcg_gen_andi_i32(t0, t0, 1);
8144 tcg_gen_extu_i32_tl(bcond, t0);
8146 not_likely:
8147 ctx->hflags |= MIPS_HFLAG_BC;
8148 break;
8149 default:
8150 MIPS_INVAL("cp1 cond branch");
8151 generate_exception_end(ctx, EXCP_RI);
8152 goto out;
8154 ctx->btarget = btarget;
8155 ctx->hflags |= MIPS_HFLAG_BDS32;
8156 out:
8157 tcg_temp_free_i32(t0);
8160 /* R6 CP1 Branches */
8161 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8162 int32_t ft, int32_t offset,
8163 int delayslot_size)
8165 target_ulong btarget;
8166 TCGv_i64 t0 = tcg_temp_new_i64();
8168 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8169 #ifdef MIPS_DEBUG_DISAS
8170 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8171 "\n", ctx->pc);
8172 #endif
8173 generate_exception_end(ctx, EXCP_RI);
8174 goto out;
8177 gen_load_fpr64(ctx, t0, ft);
8178 tcg_gen_andi_i64(t0, t0, 1);
8180 btarget = addr_add(ctx, ctx->pc + 4, offset);
8182 switch (op) {
8183 case OPC_BC1EQZ:
8184 tcg_gen_xori_i64(t0, t0, 1);
8185 ctx->hflags |= MIPS_HFLAG_BC;
8186 break;
8187 case OPC_BC1NEZ:
8188 /* t0 already set */
8189 ctx->hflags |= MIPS_HFLAG_BC;
8190 break;
8191 default:
8192 MIPS_INVAL("cp1 cond branch");
8193 generate_exception_end(ctx, EXCP_RI);
8194 goto out;
8197 tcg_gen_trunc_i64_tl(bcond, t0);
8199 ctx->btarget = btarget;
8201 switch (delayslot_size) {
8202 case 2:
8203 ctx->hflags |= MIPS_HFLAG_BDS16;
8204 break;
8205 case 4:
8206 ctx->hflags |= MIPS_HFLAG_BDS32;
8207 break;
8210 out:
8211 tcg_temp_free_i64(t0);
8214 /* Coprocessor 1 (FPU) */
8216 #define FOP(func, fmt) (((fmt) << 21) | (func))
8218 enum fopcode {
8219 OPC_ADD_S = FOP(0, FMT_S),
8220 OPC_SUB_S = FOP(1, FMT_S),
8221 OPC_MUL_S = FOP(2, FMT_S),
8222 OPC_DIV_S = FOP(3, FMT_S),
8223 OPC_SQRT_S = FOP(4, FMT_S),
8224 OPC_ABS_S = FOP(5, FMT_S),
8225 OPC_MOV_S = FOP(6, FMT_S),
8226 OPC_NEG_S = FOP(7, FMT_S),
8227 OPC_ROUND_L_S = FOP(8, FMT_S),
8228 OPC_TRUNC_L_S = FOP(9, FMT_S),
8229 OPC_CEIL_L_S = FOP(10, FMT_S),
8230 OPC_FLOOR_L_S = FOP(11, FMT_S),
8231 OPC_ROUND_W_S = FOP(12, FMT_S),
8232 OPC_TRUNC_W_S = FOP(13, FMT_S),
8233 OPC_CEIL_W_S = FOP(14, FMT_S),
8234 OPC_FLOOR_W_S = FOP(15, FMT_S),
8235 OPC_SEL_S = FOP(16, FMT_S),
8236 OPC_MOVCF_S = FOP(17, FMT_S),
8237 OPC_MOVZ_S = FOP(18, FMT_S),
8238 OPC_MOVN_S = FOP(19, FMT_S),
8239 OPC_SELEQZ_S = FOP(20, FMT_S),
8240 OPC_RECIP_S = FOP(21, FMT_S),
8241 OPC_RSQRT_S = FOP(22, FMT_S),
8242 OPC_SELNEZ_S = FOP(23, FMT_S),
8243 OPC_MADDF_S = FOP(24, FMT_S),
8244 OPC_MSUBF_S = FOP(25, FMT_S),
8245 OPC_RINT_S = FOP(26, FMT_S),
8246 OPC_CLASS_S = FOP(27, FMT_S),
8247 OPC_MIN_S = FOP(28, FMT_S),
8248 OPC_RECIP2_S = FOP(28, FMT_S),
8249 OPC_MINA_S = FOP(29, FMT_S),
8250 OPC_RECIP1_S = FOP(29, FMT_S),
8251 OPC_MAX_S = FOP(30, FMT_S),
8252 OPC_RSQRT1_S = FOP(30, FMT_S),
8253 OPC_MAXA_S = FOP(31, FMT_S),
8254 OPC_RSQRT2_S = FOP(31, FMT_S),
8255 OPC_CVT_D_S = FOP(33, FMT_S),
8256 OPC_CVT_W_S = FOP(36, FMT_S),
8257 OPC_CVT_L_S = FOP(37, FMT_S),
8258 OPC_CVT_PS_S = FOP(38, FMT_S),
8259 OPC_CMP_F_S = FOP (48, FMT_S),
8260 OPC_CMP_UN_S = FOP (49, FMT_S),
8261 OPC_CMP_EQ_S = FOP (50, FMT_S),
8262 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8263 OPC_CMP_OLT_S = FOP (52, FMT_S),
8264 OPC_CMP_ULT_S = FOP (53, FMT_S),
8265 OPC_CMP_OLE_S = FOP (54, FMT_S),
8266 OPC_CMP_ULE_S = FOP (55, FMT_S),
8267 OPC_CMP_SF_S = FOP (56, FMT_S),
8268 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8269 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8270 OPC_CMP_NGL_S = FOP (59, FMT_S),
8271 OPC_CMP_LT_S = FOP (60, FMT_S),
8272 OPC_CMP_NGE_S = FOP (61, FMT_S),
8273 OPC_CMP_LE_S = FOP (62, FMT_S),
8274 OPC_CMP_NGT_S = FOP (63, FMT_S),
8276 OPC_ADD_D = FOP(0, FMT_D),
8277 OPC_SUB_D = FOP(1, FMT_D),
8278 OPC_MUL_D = FOP(2, FMT_D),
8279 OPC_DIV_D = FOP(3, FMT_D),
8280 OPC_SQRT_D = FOP(4, FMT_D),
8281 OPC_ABS_D = FOP(5, FMT_D),
8282 OPC_MOV_D = FOP(6, FMT_D),
8283 OPC_NEG_D = FOP(7, FMT_D),
8284 OPC_ROUND_L_D = FOP(8, FMT_D),
8285 OPC_TRUNC_L_D = FOP(9, FMT_D),
8286 OPC_CEIL_L_D = FOP(10, FMT_D),
8287 OPC_FLOOR_L_D = FOP(11, FMT_D),
8288 OPC_ROUND_W_D = FOP(12, FMT_D),
8289 OPC_TRUNC_W_D = FOP(13, FMT_D),
8290 OPC_CEIL_W_D = FOP(14, FMT_D),
8291 OPC_FLOOR_W_D = FOP(15, FMT_D),
8292 OPC_SEL_D = FOP(16, FMT_D),
8293 OPC_MOVCF_D = FOP(17, FMT_D),
8294 OPC_MOVZ_D = FOP(18, FMT_D),
8295 OPC_MOVN_D = FOP(19, FMT_D),
8296 OPC_SELEQZ_D = FOP(20, FMT_D),
8297 OPC_RECIP_D = FOP(21, FMT_D),
8298 OPC_RSQRT_D = FOP(22, FMT_D),
8299 OPC_SELNEZ_D = FOP(23, FMT_D),
8300 OPC_MADDF_D = FOP(24, FMT_D),
8301 OPC_MSUBF_D = FOP(25, FMT_D),
8302 OPC_RINT_D = FOP(26, FMT_D),
8303 OPC_CLASS_D = FOP(27, FMT_D),
8304 OPC_MIN_D = FOP(28, FMT_D),
8305 OPC_RECIP2_D = FOP(28, FMT_D),
8306 OPC_MINA_D = FOP(29, FMT_D),
8307 OPC_RECIP1_D = FOP(29, FMT_D),
8308 OPC_MAX_D = FOP(30, FMT_D),
8309 OPC_RSQRT1_D = FOP(30, FMT_D),
8310 OPC_MAXA_D = FOP(31, FMT_D),
8311 OPC_RSQRT2_D = FOP(31, FMT_D),
8312 OPC_CVT_S_D = FOP(32, FMT_D),
8313 OPC_CVT_W_D = FOP(36, FMT_D),
8314 OPC_CVT_L_D = FOP(37, FMT_D),
8315 OPC_CMP_F_D = FOP (48, FMT_D),
8316 OPC_CMP_UN_D = FOP (49, FMT_D),
8317 OPC_CMP_EQ_D = FOP (50, FMT_D),
8318 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8319 OPC_CMP_OLT_D = FOP (52, FMT_D),
8320 OPC_CMP_ULT_D = FOP (53, FMT_D),
8321 OPC_CMP_OLE_D = FOP (54, FMT_D),
8322 OPC_CMP_ULE_D = FOP (55, FMT_D),
8323 OPC_CMP_SF_D = FOP (56, FMT_D),
8324 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8325 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8326 OPC_CMP_NGL_D = FOP (59, FMT_D),
8327 OPC_CMP_LT_D = FOP (60, FMT_D),
8328 OPC_CMP_NGE_D = FOP (61, FMT_D),
8329 OPC_CMP_LE_D = FOP (62, FMT_D),
8330 OPC_CMP_NGT_D = FOP (63, FMT_D),
8332 OPC_CVT_S_W = FOP(32, FMT_W),
8333 OPC_CVT_D_W = FOP(33, FMT_W),
8334 OPC_CVT_S_L = FOP(32, FMT_L),
8335 OPC_CVT_D_L = FOP(33, FMT_L),
8336 OPC_CVT_PS_PW = FOP(38, FMT_W),
8338 OPC_ADD_PS = FOP(0, FMT_PS),
8339 OPC_SUB_PS = FOP(1, FMT_PS),
8340 OPC_MUL_PS = FOP(2, FMT_PS),
8341 OPC_DIV_PS = FOP(3, FMT_PS),
8342 OPC_ABS_PS = FOP(5, FMT_PS),
8343 OPC_MOV_PS = FOP(6, FMT_PS),
8344 OPC_NEG_PS = FOP(7, FMT_PS),
8345 OPC_MOVCF_PS = FOP(17, FMT_PS),
8346 OPC_MOVZ_PS = FOP(18, FMT_PS),
8347 OPC_MOVN_PS = FOP(19, FMT_PS),
8348 OPC_ADDR_PS = FOP(24, FMT_PS),
8349 OPC_MULR_PS = FOP(26, FMT_PS),
8350 OPC_RECIP2_PS = FOP(28, FMT_PS),
8351 OPC_RECIP1_PS = FOP(29, FMT_PS),
8352 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8353 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8355 OPC_CVT_S_PU = FOP(32, FMT_PS),
8356 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8357 OPC_CVT_S_PL = FOP(40, FMT_PS),
8358 OPC_PLL_PS = FOP(44, FMT_PS),
8359 OPC_PLU_PS = FOP(45, FMT_PS),
8360 OPC_PUL_PS = FOP(46, FMT_PS),
8361 OPC_PUU_PS = FOP(47, FMT_PS),
8362 OPC_CMP_F_PS = FOP (48, FMT_PS),
8363 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8364 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8365 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8366 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8367 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8368 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8369 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8370 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8371 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8372 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8373 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8374 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8375 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8376 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8377 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8380 enum r6_f_cmp_op {
8381 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8382 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8383 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8384 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8385 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8386 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8387 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8388 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8389 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8390 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8391 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8392 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8393 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8394 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8395 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8396 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8397 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8398 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8399 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8400 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8401 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8402 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8404 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8405 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8406 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8407 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8408 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8409 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8410 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8411 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8412 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8413 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8414 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8415 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8416 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8417 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8418 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8419 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8420 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8421 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8422 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8423 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8424 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8425 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8427 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8429 TCGv t0 = tcg_temp_new();
8431 switch (opc) {
8432 case OPC_MFC1:
8434 TCGv_i32 fp0 = tcg_temp_new_i32();
8436 gen_load_fpr32(ctx, fp0, fs);
8437 tcg_gen_ext_i32_tl(t0, fp0);
8438 tcg_temp_free_i32(fp0);
8440 gen_store_gpr(t0, rt);
8441 break;
8442 case OPC_MTC1:
8443 gen_load_gpr(t0, rt);
8445 TCGv_i32 fp0 = tcg_temp_new_i32();
8447 tcg_gen_trunc_tl_i32(fp0, t0);
8448 gen_store_fpr32(ctx, fp0, fs);
8449 tcg_temp_free_i32(fp0);
8451 break;
8452 case OPC_CFC1:
8453 gen_helper_1e0i(cfc1, t0, fs);
8454 gen_store_gpr(t0, rt);
8455 break;
8456 case OPC_CTC1:
8457 gen_load_gpr(t0, rt);
8458 save_cpu_state(ctx, 0);
8460 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8462 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8463 tcg_temp_free_i32(fs_tmp);
8465 /* Stop translation as we may have changed hflags */
8466 ctx->bstate = BS_STOP;
8467 break;
8468 #if defined(TARGET_MIPS64)
8469 case OPC_DMFC1:
8470 gen_load_fpr64(ctx, t0, fs);
8471 gen_store_gpr(t0, rt);
8472 break;
8473 case OPC_DMTC1:
8474 gen_load_gpr(t0, rt);
8475 gen_store_fpr64(ctx, t0, fs);
8476 break;
8477 #endif
8478 case OPC_MFHC1:
8480 TCGv_i32 fp0 = tcg_temp_new_i32();
8482 gen_load_fpr32h(ctx, fp0, fs);
8483 tcg_gen_ext_i32_tl(t0, fp0);
8484 tcg_temp_free_i32(fp0);
8486 gen_store_gpr(t0, rt);
8487 break;
8488 case OPC_MTHC1:
8489 gen_load_gpr(t0, rt);
8491 TCGv_i32 fp0 = tcg_temp_new_i32();
8493 tcg_gen_trunc_tl_i32(fp0, t0);
8494 gen_store_fpr32h(ctx, fp0, fs);
8495 tcg_temp_free_i32(fp0);
8497 break;
8498 default:
8499 MIPS_INVAL("cp1 move");
8500 generate_exception_end(ctx, EXCP_RI);
8501 goto out;
8504 out:
8505 tcg_temp_free(t0);
8508 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8510 TCGLabel *l1;
8511 TCGCond cond;
8512 TCGv_i32 t0;
8514 if (rd == 0) {
8515 /* Treat as NOP. */
8516 return;
8519 if (tf)
8520 cond = TCG_COND_EQ;
8521 else
8522 cond = TCG_COND_NE;
8524 l1 = gen_new_label();
8525 t0 = tcg_temp_new_i32();
8526 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8527 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8528 tcg_temp_free_i32(t0);
8529 if (rs == 0) {
8530 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8531 } else {
8532 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8534 gen_set_label(l1);
8537 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
8538 int tf)
8540 int cond;
8541 TCGv_i32 t0 = tcg_temp_new_i32();
8542 TCGLabel *l1 = gen_new_label();
8544 if (tf)
8545 cond = TCG_COND_EQ;
8546 else
8547 cond = TCG_COND_NE;
8549 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8550 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8551 gen_load_fpr32(ctx, t0, fs);
8552 gen_store_fpr32(ctx, t0, fd);
8553 gen_set_label(l1);
8554 tcg_temp_free_i32(t0);
8557 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8559 int cond;
8560 TCGv_i32 t0 = tcg_temp_new_i32();
8561 TCGv_i64 fp0;
8562 TCGLabel *l1 = gen_new_label();
8564 if (tf)
8565 cond = TCG_COND_EQ;
8566 else
8567 cond = TCG_COND_NE;
8569 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8570 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8571 tcg_temp_free_i32(t0);
8572 fp0 = tcg_temp_new_i64();
8573 gen_load_fpr64(ctx, fp0, fs);
8574 gen_store_fpr64(ctx, fp0, fd);
8575 tcg_temp_free_i64(fp0);
8576 gen_set_label(l1);
8579 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8580 int cc, int tf)
8582 int cond;
8583 TCGv_i32 t0 = tcg_temp_new_i32();
8584 TCGLabel *l1 = gen_new_label();
8585 TCGLabel *l2 = gen_new_label();
8587 if (tf)
8588 cond = TCG_COND_EQ;
8589 else
8590 cond = TCG_COND_NE;
8592 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8593 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8594 gen_load_fpr32(ctx, t0, fs);
8595 gen_store_fpr32(ctx, t0, fd);
8596 gen_set_label(l1);
8598 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8599 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8600 gen_load_fpr32h(ctx, t0, fs);
8601 gen_store_fpr32h(ctx, t0, fd);
8602 tcg_temp_free_i32(t0);
8603 gen_set_label(l2);
8606 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8607 int fs)
8609 TCGv_i32 t1 = tcg_const_i32(0);
8610 TCGv_i32 fp0 = tcg_temp_new_i32();
8611 TCGv_i32 fp1 = tcg_temp_new_i32();
8612 TCGv_i32 fp2 = tcg_temp_new_i32();
8613 gen_load_fpr32(ctx, fp0, fd);
8614 gen_load_fpr32(ctx, fp1, ft);
8615 gen_load_fpr32(ctx, fp2, fs);
8617 switch (op1) {
8618 case OPC_SEL_S:
8619 tcg_gen_andi_i32(fp0, fp0, 1);
8620 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8621 break;
8622 case OPC_SELEQZ_S:
8623 tcg_gen_andi_i32(fp1, fp1, 1);
8624 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8625 break;
8626 case OPC_SELNEZ_S:
8627 tcg_gen_andi_i32(fp1, fp1, 1);
8628 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8629 break;
8630 default:
8631 MIPS_INVAL("gen_sel_s");
8632 generate_exception_end(ctx, EXCP_RI);
8633 break;
8636 gen_store_fpr32(ctx, fp0, fd);
8637 tcg_temp_free_i32(fp2);
8638 tcg_temp_free_i32(fp1);
8639 tcg_temp_free_i32(fp0);
8640 tcg_temp_free_i32(t1);
8643 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8644 int fs)
8646 TCGv_i64 t1 = tcg_const_i64(0);
8647 TCGv_i64 fp0 = tcg_temp_new_i64();
8648 TCGv_i64 fp1 = tcg_temp_new_i64();
8649 TCGv_i64 fp2 = tcg_temp_new_i64();
8650 gen_load_fpr64(ctx, fp0, fd);
8651 gen_load_fpr64(ctx, fp1, ft);
8652 gen_load_fpr64(ctx, fp2, fs);
8654 switch (op1) {
8655 case OPC_SEL_D:
8656 tcg_gen_andi_i64(fp0, fp0, 1);
8657 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8658 break;
8659 case OPC_SELEQZ_D:
8660 tcg_gen_andi_i64(fp1, fp1, 1);
8661 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8662 break;
8663 case OPC_SELNEZ_D:
8664 tcg_gen_andi_i64(fp1, fp1, 1);
8665 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8666 break;
8667 default:
8668 MIPS_INVAL("gen_sel_d");
8669 generate_exception_end(ctx, EXCP_RI);
8670 break;
8673 gen_store_fpr64(ctx, fp0, fd);
8674 tcg_temp_free_i64(fp2);
8675 tcg_temp_free_i64(fp1);
8676 tcg_temp_free_i64(fp0);
8677 tcg_temp_free_i64(t1);
8680 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8681 int ft, int fs, int fd, int cc)
8683 uint32_t func = ctx->opcode & 0x3f;
8684 switch (op1) {
8685 case OPC_ADD_S:
8687 TCGv_i32 fp0 = tcg_temp_new_i32();
8688 TCGv_i32 fp1 = tcg_temp_new_i32();
8690 gen_load_fpr32(ctx, fp0, fs);
8691 gen_load_fpr32(ctx, fp1, ft);
8692 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
8693 tcg_temp_free_i32(fp1);
8694 gen_store_fpr32(ctx, fp0, fd);
8695 tcg_temp_free_i32(fp0);
8697 break;
8698 case OPC_SUB_S:
8700 TCGv_i32 fp0 = tcg_temp_new_i32();
8701 TCGv_i32 fp1 = tcg_temp_new_i32();
8703 gen_load_fpr32(ctx, fp0, fs);
8704 gen_load_fpr32(ctx, fp1, ft);
8705 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
8706 tcg_temp_free_i32(fp1);
8707 gen_store_fpr32(ctx, fp0, fd);
8708 tcg_temp_free_i32(fp0);
8710 break;
8711 case OPC_MUL_S:
8713 TCGv_i32 fp0 = tcg_temp_new_i32();
8714 TCGv_i32 fp1 = tcg_temp_new_i32();
8716 gen_load_fpr32(ctx, fp0, fs);
8717 gen_load_fpr32(ctx, fp1, ft);
8718 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
8719 tcg_temp_free_i32(fp1);
8720 gen_store_fpr32(ctx, fp0, fd);
8721 tcg_temp_free_i32(fp0);
8723 break;
8724 case OPC_DIV_S:
8726 TCGv_i32 fp0 = tcg_temp_new_i32();
8727 TCGv_i32 fp1 = tcg_temp_new_i32();
8729 gen_load_fpr32(ctx, fp0, fs);
8730 gen_load_fpr32(ctx, fp1, ft);
8731 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
8732 tcg_temp_free_i32(fp1);
8733 gen_store_fpr32(ctx, fp0, fd);
8734 tcg_temp_free_i32(fp0);
8736 break;
8737 case OPC_SQRT_S:
8739 TCGv_i32 fp0 = tcg_temp_new_i32();
8741 gen_load_fpr32(ctx, fp0, fs);
8742 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
8743 gen_store_fpr32(ctx, fp0, fd);
8744 tcg_temp_free_i32(fp0);
8746 break;
8747 case OPC_ABS_S:
8749 TCGv_i32 fp0 = tcg_temp_new_i32();
8751 gen_load_fpr32(ctx, fp0, fs);
8752 gen_helper_float_abs_s(fp0, fp0);
8753 gen_store_fpr32(ctx, fp0, fd);
8754 tcg_temp_free_i32(fp0);
8756 break;
8757 case OPC_MOV_S:
8759 TCGv_i32 fp0 = tcg_temp_new_i32();
8761 gen_load_fpr32(ctx, fp0, fs);
8762 gen_store_fpr32(ctx, fp0, fd);
8763 tcg_temp_free_i32(fp0);
8765 break;
8766 case OPC_NEG_S:
8768 TCGv_i32 fp0 = tcg_temp_new_i32();
8770 gen_load_fpr32(ctx, fp0, fs);
8771 gen_helper_float_chs_s(fp0, fp0);
8772 gen_store_fpr32(ctx, fp0, fd);
8773 tcg_temp_free_i32(fp0);
8775 break;
8776 case OPC_ROUND_L_S:
8777 check_cp1_64bitmode(ctx);
8779 TCGv_i32 fp32 = tcg_temp_new_i32();
8780 TCGv_i64 fp64 = tcg_temp_new_i64();
8782 gen_load_fpr32(ctx, fp32, fs);
8783 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
8784 tcg_temp_free_i32(fp32);
8785 gen_store_fpr64(ctx, fp64, fd);
8786 tcg_temp_free_i64(fp64);
8788 break;
8789 case OPC_TRUNC_L_S:
8790 check_cp1_64bitmode(ctx);
8792 TCGv_i32 fp32 = tcg_temp_new_i32();
8793 TCGv_i64 fp64 = tcg_temp_new_i64();
8795 gen_load_fpr32(ctx, fp32, fs);
8796 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
8797 tcg_temp_free_i32(fp32);
8798 gen_store_fpr64(ctx, fp64, fd);
8799 tcg_temp_free_i64(fp64);
8801 break;
8802 case OPC_CEIL_L_S:
8803 check_cp1_64bitmode(ctx);
8805 TCGv_i32 fp32 = tcg_temp_new_i32();
8806 TCGv_i64 fp64 = tcg_temp_new_i64();
8808 gen_load_fpr32(ctx, fp32, fs);
8809 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
8810 tcg_temp_free_i32(fp32);
8811 gen_store_fpr64(ctx, fp64, fd);
8812 tcg_temp_free_i64(fp64);
8814 break;
8815 case OPC_FLOOR_L_S:
8816 check_cp1_64bitmode(ctx);
8818 TCGv_i32 fp32 = tcg_temp_new_i32();
8819 TCGv_i64 fp64 = tcg_temp_new_i64();
8821 gen_load_fpr32(ctx, fp32, fs);
8822 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
8823 tcg_temp_free_i32(fp32);
8824 gen_store_fpr64(ctx, fp64, fd);
8825 tcg_temp_free_i64(fp64);
8827 break;
8828 case OPC_ROUND_W_S:
8830 TCGv_i32 fp0 = tcg_temp_new_i32();
8832 gen_load_fpr32(ctx, fp0, fs);
8833 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
8834 gen_store_fpr32(ctx, fp0, fd);
8835 tcg_temp_free_i32(fp0);
8837 break;
8838 case OPC_TRUNC_W_S:
8840 TCGv_i32 fp0 = tcg_temp_new_i32();
8842 gen_load_fpr32(ctx, fp0, fs);
8843 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
8844 gen_store_fpr32(ctx, fp0, fd);
8845 tcg_temp_free_i32(fp0);
8847 break;
8848 case OPC_CEIL_W_S:
8850 TCGv_i32 fp0 = tcg_temp_new_i32();
8852 gen_load_fpr32(ctx, fp0, fs);
8853 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
8854 gen_store_fpr32(ctx, fp0, fd);
8855 tcg_temp_free_i32(fp0);
8857 break;
8858 case OPC_FLOOR_W_S:
8860 TCGv_i32 fp0 = tcg_temp_new_i32();
8862 gen_load_fpr32(ctx, fp0, fs);
8863 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
8864 gen_store_fpr32(ctx, fp0, fd);
8865 tcg_temp_free_i32(fp0);
8867 break;
8868 case OPC_SEL_S:
8869 check_insn(ctx, ISA_MIPS32R6);
8870 gen_sel_s(ctx, op1, fd, ft, fs);
8871 break;
8872 case OPC_SELEQZ_S:
8873 check_insn(ctx, ISA_MIPS32R6);
8874 gen_sel_s(ctx, op1, fd, ft, fs);
8875 break;
8876 case OPC_SELNEZ_S:
8877 check_insn(ctx, ISA_MIPS32R6);
8878 gen_sel_s(ctx, op1, fd, ft, fs);
8879 break;
8880 case OPC_MOVCF_S:
8881 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8882 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
8883 break;
8884 case OPC_MOVZ_S:
8885 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8887 TCGLabel *l1 = gen_new_label();
8888 TCGv_i32 fp0;
8890 if (ft != 0) {
8891 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8893 fp0 = tcg_temp_new_i32();
8894 gen_load_fpr32(ctx, fp0, fs);
8895 gen_store_fpr32(ctx, fp0, fd);
8896 tcg_temp_free_i32(fp0);
8897 gen_set_label(l1);
8899 break;
8900 case OPC_MOVN_S:
8901 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8903 TCGLabel *l1 = gen_new_label();
8904 TCGv_i32 fp0;
8906 if (ft != 0) {
8907 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8908 fp0 = tcg_temp_new_i32();
8909 gen_load_fpr32(ctx, fp0, fs);
8910 gen_store_fpr32(ctx, fp0, fd);
8911 tcg_temp_free_i32(fp0);
8912 gen_set_label(l1);
8915 break;
8916 case OPC_RECIP_S:
8918 TCGv_i32 fp0 = tcg_temp_new_i32();
8920 gen_load_fpr32(ctx, fp0, fs);
8921 gen_helper_float_recip_s(fp0, cpu_env, fp0);
8922 gen_store_fpr32(ctx, fp0, fd);
8923 tcg_temp_free_i32(fp0);
8925 break;
8926 case OPC_RSQRT_S:
8928 TCGv_i32 fp0 = tcg_temp_new_i32();
8930 gen_load_fpr32(ctx, fp0, fs);
8931 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
8932 gen_store_fpr32(ctx, fp0, fd);
8933 tcg_temp_free_i32(fp0);
8935 break;
8936 case OPC_MADDF_S:
8937 check_insn(ctx, ISA_MIPS32R6);
8939 TCGv_i32 fp0 = tcg_temp_new_i32();
8940 TCGv_i32 fp1 = tcg_temp_new_i32();
8941 TCGv_i32 fp2 = tcg_temp_new_i32();
8942 gen_load_fpr32(ctx, fp0, fs);
8943 gen_load_fpr32(ctx, fp1, ft);
8944 gen_load_fpr32(ctx, fp2, fd);
8945 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
8946 gen_store_fpr32(ctx, fp2, fd);
8947 tcg_temp_free_i32(fp2);
8948 tcg_temp_free_i32(fp1);
8949 tcg_temp_free_i32(fp0);
8951 break;
8952 case OPC_MSUBF_S:
8953 check_insn(ctx, ISA_MIPS32R6);
8955 TCGv_i32 fp0 = tcg_temp_new_i32();
8956 TCGv_i32 fp1 = tcg_temp_new_i32();
8957 TCGv_i32 fp2 = tcg_temp_new_i32();
8958 gen_load_fpr32(ctx, fp0, fs);
8959 gen_load_fpr32(ctx, fp1, ft);
8960 gen_load_fpr32(ctx, fp2, fd);
8961 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
8962 gen_store_fpr32(ctx, fp2, fd);
8963 tcg_temp_free_i32(fp2);
8964 tcg_temp_free_i32(fp1);
8965 tcg_temp_free_i32(fp0);
8967 break;
8968 case OPC_RINT_S:
8969 check_insn(ctx, ISA_MIPS32R6);
8971 TCGv_i32 fp0 = tcg_temp_new_i32();
8972 gen_load_fpr32(ctx, fp0, fs);
8973 gen_helper_float_rint_s(fp0, cpu_env, fp0);
8974 gen_store_fpr32(ctx, fp0, fd);
8975 tcg_temp_free_i32(fp0);
8977 break;
8978 case OPC_CLASS_S:
8979 check_insn(ctx, ISA_MIPS32R6);
8981 TCGv_i32 fp0 = tcg_temp_new_i32();
8982 gen_load_fpr32(ctx, fp0, fs);
8983 gen_helper_float_class_s(fp0, fp0);
8984 gen_store_fpr32(ctx, fp0, fd);
8985 tcg_temp_free_i32(fp0);
8987 break;
8988 case OPC_MIN_S: /* OPC_RECIP2_S */
8989 if (ctx->insn_flags & ISA_MIPS32R6) {
8990 /* OPC_MIN_S */
8991 TCGv_i32 fp0 = tcg_temp_new_i32();
8992 TCGv_i32 fp1 = tcg_temp_new_i32();
8993 TCGv_i32 fp2 = tcg_temp_new_i32();
8994 gen_load_fpr32(ctx, fp0, fs);
8995 gen_load_fpr32(ctx, fp1, ft);
8996 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
8997 gen_store_fpr32(ctx, fp2, fd);
8998 tcg_temp_free_i32(fp2);
8999 tcg_temp_free_i32(fp1);
9000 tcg_temp_free_i32(fp0);
9001 } else {
9002 /* OPC_RECIP2_S */
9003 check_cp1_64bitmode(ctx);
9005 TCGv_i32 fp0 = tcg_temp_new_i32();
9006 TCGv_i32 fp1 = tcg_temp_new_i32();
9008 gen_load_fpr32(ctx, fp0, fs);
9009 gen_load_fpr32(ctx, fp1, ft);
9010 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9011 tcg_temp_free_i32(fp1);
9012 gen_store_fpr32(ctx, fp0, fd);
9013 tcg_temp_free_i32(fp0);
9016 break;
9017 case OPC_MINA_S: /* OPC_RECIP1_S */
9018 if (ctx->insn_flags & ISA_MIPS32R6) {
9019 /* OPC_MINA_S */
9020 TCGv_i32 fp0 = tcg_temp_new_i32();
9021 TCGv_i32 fp1 = tcg_temp_new_i32();
9022 TCGv_i32 fp2 = tcg_temp_new_i32();
9023 gen_load_fpr32(ctx, fp0, fs);
9024 gen_load_fpr32(ctx, fp1, ft);
9025 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9026 gen_store_fpr32(ctx, fp2, fd);
9027 tcg_temp_free_i32(fp2);
9028 tcg_temp_free_i32(fp1);
9029 tcg_temp_free_i32(fp0);
9030 } else {
9031 /* OPC_RECIP1_S */
9032 check_cp1_64bitmode(ctx);
9034 TCGv_i32 fp0 = tcg_temp_new_i32();
9036 gen_load_fpr32(ctx, fp0, fs);
9037 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9038 gen_store_fpr32(ctx, fp0, fd);
9039 tcg_temp_free_i32(fp0);
9042 break;
9043 case OPC_MAX_S: /* OPC_RSQRT1_S */
9044 if (ctx->insn_flags & ISA_MIPS32R6) {
9045 /* OPC_MAX_S */
9046 TCGv_i32 fp0 = tcg_temp_new_i32();
9047 TCGv_i32 fp1 = tcg_temp_new_i32();
9048 gen_load_fpr32(ctx, fp0, fs);
9049 gen_load_fpr32(ctx, fp1, ft);
9050 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9051 gen_store_fpr32(ctx, fp1, fd);
9052 tcg_temp_free_i32(fp1);
9053 tcg_temp_free_i32(fp0);
9054 } else {
9055 /* OPC_RSQRT1_S */
9056 check_cp1_64bitmode(ctx);
9058 TCGv_i32 fp0 = tcg_temp_new_i32();
9060 gen_load_fpr32(ctx, fp0, fs);
9061 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9062 gen_store_fpr32(ctx, fp0, fd);
9063 tcg_temp_free_i32(fp0);
9066 break;
9067 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9068 if (ctx->insn_flags & ISA_MIPS32R6) {
9069 /* OPC_MAXA_S */
9070 TCGv_i32 fp0 = tcg_temp_new_i32();
9071 TCGv_i32 fp1 = tcg_temp_new_i32();
9072 gen_load_fpr32(ctx, fp0, fs);
9073 gen_load_fpr32(ctx, fp1, ft);
9074 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9075 gen_store_fpr32(ctx, fp1, fd);
9076 tcg_temp_free_i32(fp1);
9077 tcg_temp_free_i32(fp0);
9078 } else {
9079 /* OPC_RSQRT2_S */
9080 check_cp1_64bitmode(ctx);
9082 TCGv_i32 fp0 = tcg_temp_new_i32();
9083 TCGv_i32 fp1 = tcg_temp_new_i32();
9085 gen_load_fpr32(ctx, fp0, fs);
9086 gen_load_fpr32(ctx, fp1, ft);
9087 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9088 tcg_temp_free_i32(fp1);
9089 gen_store_fpr32(ctx, fp0, fd);
9090 tcg_temp_free_i32(fp0);
9093 break;
9094 case OPC_CVT_D_S:
9095 check_cp1_registers(ctx, fd);
9097 TCGv_i32 fp32 = tcg_temp_new_i32();
9098 TCGv_i64 fp64 = tcg_temp_new_i64();
9100 gen_load_fpr32(ctx, fp32, fs);
9101 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9102 tcg_temp_free_i32(fp32);
9103 gen_store_fpr64(ctx, fp64, fd);
9104 tcg_temp_free_i64(fp64);
9106 break;
9107 case OPC_CVT_W_S:
9109 TCGv_i32 fp0 = tcg_temp_new_i32();
9111 gen_load_fpr32(ctx, fp0, fs);
9112 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
9113 gen_store_fpr32(ctx, fp0, fd);
9114 tcg_temp_free_i32(fp0);
9116 break;
9117 case OPC_CVT_L_S:
9118 check_cp1_64bitmode(ctx);
9120 TCGv_i32 fp32 = tcg_temp_new_i32();
9121 TCGv_i64 fp64 = tcg_temp_new_i64();
9123 gen_load_fpr32(ctx, fp32, fs);
9124 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
9125 tcg_temp_free_i32(fp32);
9126 gen_store_fpr64(ctx, fp64, fd);
9127 tcg_temp_free_i64(fp64);
9129 break;
9130 case OPC_CVT_PS_S:
9131 check_ps(ctx);
9133 TCGv_i64 fp64 = tcg_temp_new_i64();
9134 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9135 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9137 gen_load_fpr32(ctx, fp32_0, fs);
9138 gen_load_fpr32(ctx, fp32_1, ft);
9139 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9140 tcg_temp_free_i32(fp32_1);
9141 tcg_temp_free_i32(fp32_0);
9142 gen_store_fpr64(ctx, fp64, fd);
9143 tcg_temp_free_i64(fp64);
9145 break;
9146 case OPC_CMP_F_S:
9147 case OPC_CMP_UN_S:
9148 case OPC_CMP_EQ_S:
9149 case OPC_CMP_UEQ_S:
9150 case OPC_CMP_OLT_S:
9151 case OPC_CMP_ULT_S:
9152 case OPC_CMP_OLE_S:
9153 case OPC_CMP_ULE_S:
9154 case OPC_CMP_SF_S:
9155 case OPC_CMP_NGLE_S:
9156 case OPC_CMP_SEQ_S:
9157 case OPC_CMP_NGL_S:
9158 case OPC_CMP_LT_S:
9159 case OPC_CMP_NGE_S:
9160 case OPC_CMP_LE_S:
9161 case OPC_CMP_NGT_S:
9162 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9163 if (ctx->opcode & (1 << 6)) {
9164 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9165 } else {
9166 gen_cmp_s(ctx, func-48, ft, fs, cc);
9168 break;
9169 case OPC_ADD_D:
9170 check_cp1_registers(ctx, fs | ft | fd);
9172 TCGv_i64 fp0 = tcg_temp_new_i64();
9173 TCGv_i64 fp1 = tcg_temp_new_i64();
9175 gen_load_fpr64(ctx, fp0, fs);
9176 gen_load_fpr64(ctx, fp1, ft);
9177 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9178 tcg_temp_free_i64(fp1);
9179 gen_store_fpr64(ctx, fp0, fd);
9180 tcg_temp_free_i64(fp0);
9182 break;
9183 case OPC_SUB_D:
9184 check_cp1_registers(ctx, fs | ft | fd);
9186 TCGv_i64 fp0 = tcg_temp_new_i64();
9187 TCGv_i64 fp1 = tcg_temp_new_i64();
9189 gen_load_fpr64(ctx, fp0, fs);
9190 gen_load_fpr64(ctx, fp1, ft);
9191 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9192 tcg_temp_free_i64(fp1);
9193 gen_store_fpr64(ctx, fp0, fd);
9194 tcg_temp_free_i64(fp0);
9196 break;
9197 case OPC_MUL_D:
9198 check_cp1_registers(ctx, fs | ft | fd);
9200 TCGv_i64 fp0 = tcg_temp_new_i64();
9201 TCGv_i64 fp1 = tcg_temp_new_i64();
9203 gen_load_fpr64(ctx, fp0, fs);
9204 gen_load_fpr64(ctx, fp1, ft);
9205 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9206 tcg_temp_free_i64(fp1);
9207 gen_store_fpr64(ctx, fp0, fd);
9208 tcg_temp_free_i64(fp0);
9210 break;
9211 case OPC_DIV_D:
9212 check_cp1_registers(ctx, fs | ft | fd);
9214 TCGv_i64 fp0 = tcg_temp_new_i64();
9215 TCGv_i64 fp1 = tcg_temp_new_i64();
9217 gen_load_fpr64(ctx, fp0, fs);
9218 gen_load_fpr64(ctx, fp1, ft);
9219 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9220 tcg_temp_free_i64(fp1);
9221 gen_store_fpr64(ctx, fp0, fd);
9222 tcg_temp_free_i64(fp0);
9224 break;
9225 case OPC_SQRT_D:
9226 check_cp1_registers(ctx, fs | fd);
9228 TCGv_i64 fp0 = tcg_temp_new_i64();
9230 gen_load_fpr64(ctx, fp0, fs);
9231 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9232 gen_store_fpr64(ctx, fp0, fd);
9233 tcg_temp_free_i64(fp0);
9235 break;
9236 case OPC_ABS_D:
9237 check_cp1_registers(ctx, fs | fd);
9239 TCGv_i64 fp0 = tcg_temp_new_i64();
9241 gen_load_fpr64(ctx, fp0, fs);
9242 gen_helper_float_abs_d(fp0, fp0);
9243 gen_store_fpr64(ctx, fp0, fd);
9244 tcg_temp_free_i64(fp0);
9246 break;
9247 case OPC_MOV_D:
9248 check_cp1_registers(ctx, fs | fd);
9250 TCGv_i64 fp0 = tcg_temp_new_i64();
9252 gen_load_fpr64(ctx, fp0, fs);
9253 gen_store_fpr64(ctx, fp0, fd);
9254 tcg_temp_free_i64(fp0);
9256 break;
9257 case OPC_NEG_D:
9258 check_cp1_registers(ctx, fs | fd);
9260 TCGv_i64 fp0 = tcg_temp_new_i64();
9262 gen_load_fpr64(ctx, fp0, fs);
9263 gen_helper_float_chs_d(fp0, fp0);
9264 gen_store_fpr64(ctx, fp0, fd);
9265 tcg_temp_free_i64(fp0);
9267 break;
9268 case OPC_ROUND_L_D:
9269 check_cp1_64bitmode(ctx);
9271 TCGv_i64 fp0 = tcg_temp_new_i64();
9273 gen_load_fpr64(ctx, fp0, fs);
9274 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
9275 gen_store_fpr64(ctx, fp0, fd);
9276 tcg_temp_free_i64(fp0);
9278 break;
9279 case OPC_TRUNC_L_D:
9280 check_cp1_64bitmode(ctx);
9282 TCGv_i64 fp0 = tcg_temp_new_i64();
9284 gen_load_fpr64(ctx, fp0, fs);
9285 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
9286 gen_store_fpr64(ctx, fp0, fd);
9287 tcg_temp_free_i64(fp0);
9289 break;
9290 case OPC_CEIL_L_D:
9291 check_cp1_64bitmode(ctx);
9293 TCGv_i64 fp0 = tcg_temp_new_i64();
9295 gen_load_fpr64(ctx, fp0, fs);
9296 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
9297 gen_store_fpr64(ctx, fp0, fd);
9298 tcg_temp_free_i64(fp0);
9300 break;
9301 case OPC_FLOOR_L_D:
9302 check_cp1_64bitmode(ctx);
9304 TCGv_i64 fp0 = tcg_temp_new_i64();
9306 gen_load_fpr64(ctx, fp0, fs);
9307 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
9308 gen_store_fpr64(ctx, fp0, fd);
9309 tcg_temp_free_i64(fp0);
9311 break;
9312 case OPC_ROUND_W_D:
9313 check_cp1_registers(ctx, fs);
9315 TCGv_i32 fp32 = tcg_temp_new_i32();
9316 TCGv_i64 fp64 = tcg_temp_new_i64();
9318 gen_load_fpr64(ctx, fp64, fs);
9319 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
9320 tcg_temp_free_i64(fp64);
9321 gen_store_fpr32(ctx, fp32, fd);
9322 tcg_temp_free_i32(fp32);
9324 break;
9325 case OPC_TRUNC_W_D:
9326 check_cp1_registers(ctx, fs);
9328 TCGv_i32 fp32 = tcg_temp_new_i32();
9329 TCGv_i64 fp64 = tcg_temp_new_i64();
9331 gen_load_fpr64(ctx, fp64, fs);
9332 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
9333 tcg_temp_free_i64(fp64);
9334 gen_store_fpr32(ctx, fp32, fd);
9335 tcg_temp_free_i32(fp32);
9337 break;
9338 case OPC_CEIL_W_D:
9339 check_cp1_registers(ctx, fs);
9341 TCGv_i32 fp32 = tcg_temp_new_i32();
9342 TCGv_i64 fp64 = tcg_temp_new_i64();
9344 gen_load_fpr64(ctx, fp64, fs);
9345 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
9346 tcg_temp_free_i64(fp64);
9347 gen_store_fpr32(ctx, fp32, fd);
9348 tcg_temp_free_i32(fp32);
9350 break;
9351 case OPC_FLOOR_W_D:
9352 check_cp1_registers(ctx, fs);
9354 TCGv_i32 fp32 = tcg_temp_new_i32();
9355 TCGv_i64 fp64 = tcg_temp_new_i64();
9357 gen_load_fpr64(ctx, fp64, fs);
9358 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
9359 tcg_temp_free_i64(fp64);
9360 gen_store_fpr32(ctx, fp32, fd);
9361 tcg_temp_free_i32(fp32);
9363 break;
9364 case OPC_SEL_D:
9365 check_insn(ctx, ISA_MIPS32R6);
9366 gen_sel_d(ctx, op1, fd, ft, fs);
9367 break;
9368 case OPC_SELEQZ_D:
9369 check_insn(ctx, ISA_MIPS32R6);
9370 gen_sel_d(ctx, op1, fd, ft, fs);
9371 break;
9372 case OPC_SELNEZ_D:
9373 check_insn(ctx, ISA_MIPS32R6);
9374 gen_sel_d(ctx, op1, fd, ft, fs);
9375 break;
9376 case OPC_MOVCF_D:
9377 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9378 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9379 break;
9380 case OPC_MOVZ_D:
9381 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9383 TCGLabel *l1 = gen_new_label();
9384 TCGv_i64 fp0;
9386 if (ft != 0) {
9387 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9389 fp0 = tcg_temp_new_i64();
9390 gen_load_fpr64(ctx, fp0, fs);
9391 gen_store_fpr64(ctx, fp0, fd);
9392 tcg_temp_free_i64(fp0);
9393 gen_set_label(l1);
9395 break;
9396 case OPC_MOVN_D:
9397 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9399 TCGLabel *l1 = gen_new_label();
9400 TCGv_i64 fp0;
9402 if (ft != 0) {
9403 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9404 fp0 = tcg_temp_new_i64();
9405 gen_load_fpr64(ctx, fp0, fs);
9406 gen_store_fpr64(ctx, fp0, fd);
9407 tcg_temp_free_i64(fp0);
9408 gen_set_label(l1);
9411 break;
9412 case OPC_RECIP_D:
9413 check_cp1_registers(ctx, fs | fd);
9415 TCGv_i64 fp0 = tcg_temp_new_i64();
9417 gen_load_fpr64(ctx, fp0, fs);
9418 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9419 gen_store_fpr64(ctx, fp0, fd);
9420 tcg_temp_free_i64(fp0);
9422 break;
9423 case OPC_RSQRT_D:
9424 check_cp1_registers(ctx, fs | fd);
9426 TCGv_i64 fp0 = tcg_temp_new_i64();
9428 gen_load_fpr64(ctx, fp0, fs);
9429 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9430 gen_store_fpr64(ctx, fp0, fd);
9431 tcg_temp_free_i64(fp0);
9433 break;
9434 case OPC_MADDF_D:
9435 check_insn(ctx, ISA_MIPS32R6);
9437 TCGv_i64 fp0 = tcg_temp_new_i64();
9438 TCGv_i64 fp1 = tcg_temp_new_i64();
9439 TCGv_i64 fp2 = tcg_temp_new_i64();
9440 gen_load_fpr64(ctx, fp0, fs);
9441 gen_load_fpr64(ctx, fp1, ft);
9442 gen_load_fpr64(ctx, fp2, fd);
9443 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9444 gen_store_fpr64(ctx, fp2, fd);
9445 tcg_temp_free_i64(fp2);
9446 tcg_temp_free_i64(fp1);
9447 tcg_temp_free_i64(fp0);
9449 break;
9450 case OPC_MSUBF_D:
9451 check_insn(ctx, ISA_MIPS32R6);
9453 TCGv_i64 fp0 = tcg_temp_new_i64();
9454 TCGv_i64 fp1 = tcg_temp_new_i64();
9455 TCGv_i64 fp2 = tcg_temp_new_i64();
9456 gen_load_fpr64(ctx, fp0, fs);
9457 gen_load_fpr64(ctx, fp1, ft);
9458 gen_load_fpr64(ctx, fp2, fd);
9459 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9460 gen_store_fpr64(ctx, fp2, fd);
9461 tcg_temp_free_i64(fp2);
9462 tcg_temp_free_i64(fp1);
9463 tcg_temp_free_i64(fp0);
9465 break;
9466 case OPC_RINT_D:
9467 check_insn(ctx, ISA_MIPS32R6);
9469 TCGv_i64 fp0 = tcg_temp_new_i64();
9470 gen_load_fpr64(ctx, fp0, fs);
9471 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9472 gen_store_fpr64(ctx, fp0, fd);
9473 tcg_temp_free_i64(fp0);
9475 break;
9476 case OPC_CLASS_D:
9477 check_insn(ctx, ISA_MIPS32R6);
9479 TCGv_i64 fp0 = tcg_temp_new_i64();
9480 gen_load_fpr64(ctx, fp0, fs);
9481 gen_helper_float_class_d(fp0, fp0);
9482 gen_store_fpr64(ctx, fp0, fd);
9483 tcg_temp_free_i64(fp0);
9485 break;
9486 case OPC_MIN_D: /* OPC_RECIP2_D */
9487 if (ctx->insn_flags & ISA_MIPS32R6) {
9488 /* OPC_MIN_D */
9489 TCGv_i64 fp0 = tcg_temp_new_i64();
9490 TCGv_i64 fp1 = tcg_temp_new_i64();
9491 gen_load_fpr64(ctx, fp0, fs);
9492 gen_load_fpr64(ctx, fp1, ft);
9493 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9494 gen_store_fpr64(ctx, fp1, fd);
9495 tcg_temp_free_i64(fp1);
9496 tcg_temp_free_i64(fp0);
9497 } else {
9498 /* OPC_RECIP2_D */
9499 check_cp1_64bitmode(ctx);
9501 TCGv_i64 fp0 = tcg_temp_new_i64();
9502 TCGv_i64 fp1 = tcg_temp_new_i64();
9504 gen_load_fpr64(ctx, fp0, fs);
9505 gen_load_fpr64(ctx, fp1, ft);
9506 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9507 tcg_temp_free_i64(fp1);
9508 gen_store_fpr64(ctx, fp0, fd);
9509 tcg_temp_free_i64(fp0);
9512 break;
9513 case OPC_MINA_D: /* OPC_RECIP1_D */
9514 if (ctx->insn_flags & ISA_MIPS32R6) {
9515 /* OPC_MINA_D */
9516 TCGv_i64 fp0 = tcg_temp_new_i64();
9517 TCGv_i64 fp1 = tcg_temp_new_i64();
9518 gen_load_fpr64(ctx, fp0, fs);
9519 gen_load_fpr64(ctx, fp1, ft);
9520 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9521 gen_store_fpr64(ctx, fp1, fd);
9522 tcg_temp_free_i64(fp1);
9523 tcg_temp_free_i64(fp0);
9524 } else {
9525 /* OPC_RECIP1_D */
9526 check_cp1_64bitmode(ctx);
9528 TCGv_i64 fp0 = tcg_temp_new_i64();
9530 gen_load_fpr64(ctx, fp0, fs);
9531 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9532 gen_store_fpr64(ctx, fp0, fd);
9533 tcg_temp_free_i64(fp0);
9536 break;
9537 case OPC_MAX_D: /* OPC_RSQRT1_D */
9538 if (ctx->insn_flags & ISA_MIPS32R6) {
9539 /* OPC_MAX_D */
9540 TCGv_i64 fp0 = tcg_temp_new_i64();
9541 TCGv_i64 fp1 = tcg_temp_new_i64();
9542 gen_load_fpr64(ctx, fp0, fs);
9543 gen_load_fpr64(ctx, fp1, ft);
9544 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9545 gen_store_fpr64(ctx, fp1, fd);
9546 tcg_temp_free_i64(fp1);
9547 tcg_temp_free_i64(fp0);
9548 } else {
9549 /* OPC_RSQRT1_D */
9550 check_cp1_64bitmode(ctx);
9552 TCGv_i64 fp0 = tcg_temp_new_i64();
9554 gen_load_fpr64(ctx, fp0, fs);
9555 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9556 gen_store_fpr64(ctx, fp0, fd);
9557 tcg_temp_free_i64(fp0);
9560 break;
9561 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9562 if (ctx->insn_flags & ISA_MIPS32R6) {
9563 /* OPC_MAXA_D */
9564 TCGv_i64 fp0 = tcg_temp_new_i64();
9565 TCGv_i64 fp1 = tcg_temp_new_i64();
9566 gen_load_fpr64(ctx, fp0, fs);
9567 gen_load_fpr64(ctx, fp1, ft);
9568 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9569 gen_store_fpr64(ctx, fp1, fd);
9570 tcg_temp_free_i64(fp1);
9571 tcg_temp_free_i64(fp0);
9572 } else {
9573 /* OPC_RSQRT2_D */
9574 check_cp1_64bitmode(ctx);
9576 TCGv_i64 fp0 = tcg_temp_new_i64();
9577 TCGv_i64 fp1 = tcg_temp_new_i64();
9579 gen_load_fpr64(ctx, fp0, fs);
9580 gen_load_fpr64(ctx, fp1, ft);
9581 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
9582 tcg_temp_free_i64(fp1);
9583 gen_store_fpr64(ctx, fp0, fd);
9584 tcg_temp_free_i64(fp0);
9587 break;
9588 case OPC_CMP_F_D:
9589 case OPC_CMP_UN_D:
9590 case OPC_CMP_EQ_D:
9591 case OPC_CMP_UEQ_D:
9592 case OPC_CMP_OLT_D:
9593 case OPC_CMP_ULT_D:
9594 case OPC_CMP_OLE_D:
9595 case OPC_CMP_ULE_D:
9596 case OPC_CMP_SF_D:
9597 case OPC_CMP_NGLE_D:
9598 case OPC_CMP_SEQ_D:
9599 case OPC_CMP_NGL_D:
9600 case OPC_CMP_LT_D:
9601 case OPC_CMP_NGE_D:
9602 case OPC_CMP_LE_D:
9603 case OPC_CMP_NGT_D:
9604 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9605 if (ctx->opcode & (1 << 6)) {
9606 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
9607 } else {
9608 gen_cmp_d(ctx, func-48, ft, fs, cc);
9610 break;
9611 case OPC_CVT_S_D:
9612 check_cp1_registers(ctx, fs);
9614 TCGv_i32 fp32 = tcg_temp_new_i32();
9615 TCGv_i64 fp64 = tcg_temp_new_i64();
9617 gen_load_fpr64(ctx, fp64, fs);
9618 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
9619 tcg_temp_free_i64(fp64);
9620 gen_store_fpr32(ctx, fp32, fd);
9621 tcg_temp_free_i32(fp32);
9623 break;
9624 case OPC_CVT_W_D:
9625 check_cp1_registers(ctx, fs);
9627 TCGv_i32 fp32 = tcg_temp_new_i32();
9628 TCGv_i64 fp64 = tcg_temp_new_i64();
9630 gen_load_fpr64(ctx, fp64, fs);
9631 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
9632 tcg_temp_free_i64(fp64);
9633 gen_store_fpr32(ctx, fp32, fd);
9634 tcg_temp_free_i32(fp32);
9636 break;
9637 case OPC_CVT_L_D:
9638 check_cp1_64bitmode(ctx);
9640 TCGv_i64 fp0 = tcg_temp_new_i64();
9642 gen_load_fpr64(ctx, fp0, fs);
9643 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
9644 gen_store_fpr64(ctx, fp0, fd);
9645 tcg_temp_free_i64(fp0);
9647 break;
9648 case OPC_CVT_S_W:
9650 TCGv_i32 fp0 = tcg_temp_new_i32();
9652 gen_load_fpr32(ctx, fp0, fs);
9653 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
9654 gen_store_fpr32(ctx, fp0, fd);
9655 tcg_temp_free_i32(fp0);
9657 break;
9658 case OPC_CVT_D_W:
9659 check_cp1_registers(ctx, fd);
9661 TCGv_i32 fp32 = tcg_temp_new_i32();
9662 TCGv_i64 fp64 = tcg_temp_new_i64();
9664 gen_load_fpr32(ctx, fp32, fs);
9665 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
9666 tcg_temp_free_i32(fp32);
9667 gen_store_fpr64(ctx, fp64, fd);
9668 tcg_temp_free_i64(fp64);
9670 break;
9671 case OPC_CVT_S_L:
9672 check_cp1_64bitmode(ctx);
9674 TCGv_i32 fp32 = tcg_temp_new_i32();
9675 TCGv_i64 fp64 = tcg_temp_new_i64();
9677 gen_load_fpr64(ctx, fp64, fs);
9678 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
9679 tcg_temp_free_i64(fp64);
9680 gen_store_fpr32(ctx, fp32, fd);
9681 tcg_temp_free_i32(fp32);
9683 break;
9684 case OPC_CVT_D_L:
9685 check_cp1_64bitmode(ctx);
9687 TCGv_i64 fp0 = tcg_temp_new_i64();
9689 gen_load_fpr64(ctx, fp0, fs);
9690 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
9691 gen_store_fpr64(ctx, fp0, fd);
9692 tcg_temp_free_i64(fp0);
9694 break;
9695 case OPC_CVT_PS_PW:
9696 check_ps(ctx);
9698 TCGv_i64 fp0 = tcg_temp_new_i64();
9700 gen_load_fpr64(ctx, fp0, fs);
9701 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
9702 gen_store_fpr64(ctx, fp0, fd);
9703 tcg_temp_free_i64(fp0);
9705 break;
9706 case OPC_ADD_PS:
9707 check_ps(ctx);
9709 TCGv_i64 fp0 = tcg_temp_new_i64();
9710 TCGv_i64 fp1 = tcg_temp_new_i64();
9712 gen_load_fpr64(ctx, fp0, fs);
9713 gen_load_fpr64(ctx, fp1, ft);
9714 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
9715 tcg_temp_free_i64(fp1);
9716 gen_store_fpr64(ctx, fp0, fd);
9717 tcg_temp_free_i64(fp0);
9719 break;
9720 case OPC_SUB_PS:
9721 check_ps(ctx);
9723 TCGv_i64 fp0 = tcg_temp_new_i64();
9724 TCGv_i64 fp1 = tcg_temp_new_i64();
9726 gen_load_fpr64(ctx, fp0, fs);
9727 gen_load_fpr64(ctx, fp1, ft);
9728 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
9729 tcg_temp_free_i64(fp1);
9730 gen_store_fpr64(ctx, fp0, fd);
9731 tcg_temp_free_i64(fp0);
9733 break;
9734 case OPC_MUL_PS:
9735 check_ps(ctx);
9737 TCGv_i64 fp0 = tcg_temp_new_i64();
9738 TCGv_i64 fp1 = tcg_temp_new_i64();
9740 gen_load_fpr64(ctx, fp0, fs);
9741 gen_load_fpr64(ctx, fp1, ft);
9742 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
9743 tcg_temp_free_i64(fp1);
9744 gen_store_fpr64(ctx, fp0, fd);
9745 tcg_temp_free_i64(fp0);
9747 break;
9748 case OPC_ABS_PS:
9749 check_ps(ctx);
9751 TCGv_i64 fp0 = tcg_temp_new_i64();
9753 gen_load_fpr64(ctx, fp0, fs);
9754 gen_helper_float_abs_ps(fp0, fp0);
9755 gen_store_fpr64(ctx, fp0, fd);
9756 tcg_temp_free_i64(fp0);
9758 break;
9759 case OPC_MOV_PS:
9760 check_ps(ctx);
9762 TCGv_i64 fp0 = tcg_temp_new_i64();
9764 gen_load_fpr64(ctx, fp0, fs);
9765 gen_store_fpr64(ctx, fp0, fd);
9766 tcg_temp_free_i64(fp0);
9768 break;
9769 case OPC_NEG_PS:
9770 check_ps(ctx);
9772 TCGv_i64 fp0 = tcg_temp_new_i64();
9774 gen_load_fpr64(ctx, fp0, fs);
9775 gen_helper_float_chs_ps(fp0, fp0);
9776 gen_store_fpr64(ctx, fp0, fd);
9777 tcg_temp_free_i64(fp0);
9779 break;
9780 case OPC_MOVCF_PS:
9781 check_ps(ctx);
9782 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9783 break;
9784 case OPC_MOVZ_PS:
9785 check_ps(ctx);
9787 TCGLabel *l1 = gen_new_label();
9788 TCGv_i64 fp0;
9790 if (ft != 0)
9791 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9792 fp0 = tcg_temp_new_i64();
9793 gen_load_fpr64(ctx, fp0, fs);
9794 gen_store_fpr64(ctx, fp0, fd);
9795 tcg_temp_free_i64(fp0);
9796 gen_set_label(l1);
9798 break;
9799 case OPC_MOVN_PS:
9800 check_ps(ctx);
9802 TCGLabel *l1 = gen_new_label();
9803 TCGv_i64 fp0;
9805 if (ft != 0) {
9806 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9807 fp0 = tcg_temp_new_i64();
9808 gen_load_fpr64(ctx, fp0, fs);
9809 gen_store_fpr64(ctx, fp0, fd);
9810 tcg_temp_free_i64(fp0);
9811 gen_set_label(l1);
9814 break;
9815 case OPC_ADDR_PS:
9816 check_ps(ctx);
9818 TCGv_i64 fp0 = tcg_temp_new_i64();
9819 TCGv_i64 fp1 = tcg_temp_new_i64();
9821 gen_load_fpr64(ctx, fp0, ft);
9822 gen_load_fpr64(ctx, fp1, fs);
9823 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
9824 tcg_temp_free_i64(fp1);
9825 gen_store_fpr64(ctx, fp0, fd);
9826 tcg_temp_free_i64(fp0);
9828 break;
9829 case OPC_MULR_PS:
9830 check_ps(ctx);
9832 TCGv_i64 fp0 = tcg_temp_new_i64();
9833 TCGv_i64 fp1 = tcg_temp_new_i64();
9835 gen_load_fpr64(ctx, fp0, ft);
9836 gen_load_fpr64(ctx, fp1, fs);
9837 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
9838 tcg_temp_free_i64(fp1);
9839 gen_store_fpr64(ctx, fp0, fd);
9840 tcg_temp_free_i64(fp0);
9842 break;
9843 case OPC_RECIP2_PS:
9844 check_ps(ctx);
9846 TCGv_i64 fp0 = tcg_temp_new_i64();
9847 TCGv_i64 fp1 = tcg_temp_new_i64();
9849 gen_load_fpr64(ctx, fp0, fs);
9850 gen_load_fpr64(ctx, fp1, ft);
9851 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
9852 tcg_temp_free_i64(fp1);
9853 gen_store_fpr64(ctx, fp0, fd);
9854 tcg_temp_free_i64(fp0);
9856 break;
9857 case OPC_RECIP1_PS:
9858 check_ps(ctx);
9860 TCGv_i64 fp0 = tcg_temp_new_i64();
9862 gen_load_fpr64(ctx, fp0, fs);
9863 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
9864 gen_store_fpr64(ctx, fp0, fd);
9865 tcg_temp_free_i64(fp0);
9867 break;
9868 case OPC_RSQRT1_PS:
9869 check_ps(ctx);
9871 TCGv_i64 fp0 = tcg_temp_new_i64();
9873 gen_load_fpr64(ctx, fp0, fs);
9874 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
9875 gen_store_fpr64(ctx, fp0, fd);
9876 tcg_temp_free_i64(fp0);
9878 break;
9879 case OPC_RSQRT2_PS:
9880 check_ps(ctx);
9882 TCGv_i64 fp0 = tcg_temp_new_i64();
9883 TCGv_i64 fp1 = tcg_temp_new_i64();
9885 gen_load_fpr64(ctx, fp0, fs);
9886 gen_load_fpr64(ctx, fp1, ft);
9887 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
9888 tcg_temp_free_i64(fp1);
9889 gen_store_fpr64(ctx, fp0, fd);
9890 tcg_temp_free_i64(fp0);
9892 break;
9893 case OPC_CVT_S_PU:
9894 check_cp1_64bitmode(ctx);
9896 TCGv_i32 fp0 = tcg_temp_new_i32();
9898 gen_load_fpr32h(ctx, fp0, fs);
9899 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
9900 gen_store_fpr32(ctx, fp0, fd);
9901 tcg_temp_free_i32(fp0);
9903 break;
9904 case OPC_CVT_PW_PS:
9905 check_ps(ctx);
9907 TCGv_i64 fp0 = tcg_temp_new_i64();
9909 gen_load_fpr64(ctx, fp0, fs);
9910 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
9911 gen_store_fpr64(ctx, fp0, fd);
9912 tcg_temp_free_i64(fp0);
9914 break;
9915 case OPC_CVT_S_PL:
9916 check_cp1_64bitmode(ctx);
9918 TCGv_i32 fp0 = tcg_temp_new_i32();
9920 gen_load_fpr32(ctx, fp0, fs);
9921 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
9922 gen_store_fpr32(ctx, fp0, fd);
9923 tcg_temp_free_i32(fp0);
9925 break;
9926 case OPC_PLL_PS:
9927 check_ps(ctx);
9929 TCGv_i32 fp0 = tcg_temp_new_i32();
9930 TCGv_i32 fp1 = tcg_temp_new_i32();
9932 gen_load_fpr32(ctx, fp0, fs);
9933 gen_load_fpr32(ctx, fp1, ft);
9934 gen_store_fpr32h(ctx, fp0, fd);
9935 gen_store_fpr32(ctx, fp1, fd);
9936 tcg_temp_free_i32(fp0);
9937 tcg_temp_free_i32(fp1);
9939 break;
9940 case OPC_PLU_PS:
9941 check_ps(ctx);
9943 TCGv_i32 fp0 = tcg_temp_new_i32();
9944 TCGv_i32 fp1 = tcg_temp_new_i32();
9946 gen_load_fpr32(ctx, fp0, fs);
9947 gen_load_fpr32h(ctx, fp1, ft);
9948 gen_store_fpr32(ctx, fp1, fd);
9949 gen_store_fpr32h(ctx, fp0, fd);
9950 tcg_temp_free_i32(fp0);
9951 tcg_temp_free_i32(fp1);
9953 break;
9954 case OPC_PUL_PS:
9955 check_ps(ctx);
9957 TCGv_i32 fp0 = tcg_temp_new_i32();
9958 TCGv_i32 fp1 = tcg_temp_new_i32();
9960 gen_load_fpr32h(ctx, fp0, fs);
9961 gen_load_fpr32(ctx, fp1, ft);
9962 gen_store_fpr32(ctx, fp1, fd);
9963 gen_store_fpr32h(ctx, fp0, fd);
9964 tcg_temp_free_i32(fp0);
9965 tcg_temp_free_i32(fp1);
9967 break;
9968 case OPC_PUU_PS:
9969 check_ps(ctx);
9971 TCGv_i32 fp0 = tcg_temp_new_i32();
9972 TCGv_i32 fp1 = tcg_temp_new_i32();
9974 gen_load_fpr32h(ctx, fp0, fs);
9975 gen_load_fpr32h(ctx, fp1, ft);
9976 gen_store_fpr32(ctx, fp1, fd);
9977 gen_store_fpr32h(ctx, fp0, fd);
9978 tcg_temp_free_i32(fp0);
9979 tcg_temp_free_i32(fp1);
9981 break;
9982 case OPC_CMP_F_PS:
9983 case OPC_CMP_UN_PS:
9984 case OPC_CMP_EQ_PS:
9985 case OPC_CMP_UEQ_PS:
9986 case OPC_CMP_OLT_PS:
9987 case OPC_CMP_ULT_PS:
9988 case OPC_CMP_OLE_PS:
9989 case OPC_CMP_ULE_PS:
9990 case OPC_CMP_SF_PS:
9991 case OPC_CMP_NGLE_PS:
9992 case OPC_CMP_SEQ_PS:
9993 case OPC_CMP_NGL_PS:
9994 case OPC_CMP_LT_PS:
9995 case OPC_CMP_NGE_PS:
9996 case OPC_CMP_LE_PS:
9997 case OPC_CMP_NGT_PS:
9998 if (ctx->opcode & (1 << 6)) {
9999 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10000 } else {
10001 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10003 break;
10004 default:
10005 MIPS_INVAL("farith");
10006 generate_exception_end(ctx, EXCP_RI);
10007 return;
10011 /* Coprocessor 3 (FPU) */
10012 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10013 int fd, int fs, int base, int index)
10015 TCGv t0 = tcg_temp_new();
10017 if (base == 0) {
10018 gen_load_gpr(t0, index);
10019 } else if (index == 0) {
10020 gen_load_gpr(t0, base);
10021 } else {
10022 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10024 /* Don't do NOP if destination is zero: we must perform the actual
10025 memory access. */
10026 switch (opc) {
10027 case OPC_LWXC1:
10028 check_cop1x(ctx);
10030 TCGv_i32 fp0 = tcg_temp_new_i32();
10032 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10033 tcg_gen_trunc_tl_i32(fp0, t0);
10034 gen_store_fpr32(ctx, fp0, fd);
10035 tcg_temp_free_i32(fp0);
10037 break;
10038 case OPC_LDXC1:
10039 check_cop1x(ctx);
10040 check_cp1_registers(ctx, fd);
10042 TCGv_i64 fp0 = tcg_temp_new_i64();
10043 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10044 gen_store_fpr64(ctx, fp0, fd);
10045 tcg_temp_free_i64(fp0);
10047 break;
10048 case OPC_LUXC1:
10049 check_cp1_64bitmode(ctx);
10050 tcg_gen_andi_tl(t0, t0, ~0x7);
10052 TCGv_i64 fp0 = tcg_temp_new_i64();
10054 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10055 gen_store_fpr64(ctx, fp0, fd);
10056 tcg_temp_free_i64(fp0);
10058 break;
10059 case OPC_SWXC1:
10060 check_cop1x(ctx);
10062 TCGv_i32 fp0 = tcg_temp_new_i32();
10063 gen_load_fpr32(ctx, fp0, fs);
10064 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10065 tcg_temp_free_i32(fp0);
10067 break;
10068 case OPC_SDXC1:
10069 check_cop1x(ctx);
10070 check_cp1_registers(ctx, fs);
10072 TCGv_i64 fp0 = tcg_temp_new_i64();
10073 gen_load_fpr64(ctx, fp0, fs);
10074 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10075 tcg_temp_free_i64(fp0);
10077 break;
10078 case OPC_SUXC1:
10079 check_cp1_64bitmode(ctx);
10080 tcg_gen_andi_tl(t0, t0, ~0x7);
10082 TCGv_i64 fp0 = tcg_temp_new_i64();
10083 gen_load_fpr64(ctx, fp0, fs);
10084 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10085 tcg_temp_free_i64(fp0);
10087 break;
10089 tcg_temp_free(t0);
10092 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10093 int fd, int fr, int fs, int ft)
10095 switch (opc) {
10096 case OPC_ALNV_PS:
10097 check_ps(ctx);
10099 TCGv t0 = tcg_temp_local_new();
10100 TCGv_i32 fp = tcg_temp_new_i32();
10101 TCGv_i32 fph = tcg_temp_new_i32();
10102 TCGLabel *l1 = gen_new_label();
10103 TCGLabel *l2 = gen_new_label();
10105 gen_load_gpr(t0, fr);
10106 tcg_gen_andi_tl(t0, t0, 0x7);
10108 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10109 gen_load_fpr32(ctx, fp, fs);
10110 gen_load_fpr32h(ctx, fph, fs);
10111 gen_store_fpr32(ctx, fp, fd);
10112 gen_store_fpr32h(ctx, fph, fd);
10113 tcg_gen_br(l2);
10114 gen_set_label(l1);
10115 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10116 tcg_temp_free(t0);
10117 #ifdef TARGET_WORDS_BIGENDIAN
10118 gen_load_fpr32(ctx, fp, fs);
10119 gen_load_fpr32h(ctx, fph, ft);
10120 gen_store_fpr32h(ctx, fp, fd);
10121 gen_store_fpr32(ctx, fph, fd);
10122 #else
10123 gen_load_fpr32h(ctx, fph, fs);
10124 gen_load_fpr32(ctx, fp, ft);
10125 gen_store_fpr32(ctx, fph, fd);
10126 gen_store_fpr32h(ctx, fp, fd);
10127 #endif
10128 gen_set_label(l2);
10129 tcg_temp_free_i32(fp);
10130 tcg_temp_free_i32(fph);
10132 break;
10133 case OPC_MADD_S:
10134 check_cop1x(ctx);
10136 TCGv_i32 fp0 = tcg_temp_new_i32();
10137 TCGv_i32 fp1 = tcg_temp_new_i32();
10138 TCGv_i32 fp2 = tcg_temp_new_i32();
10140 gen_load_fpr32(ctx, fp0, fs);
10141 gen_load_fpr32(ctx, fp1, ft);
10142 gen_load_fpr32(ctx, fp2, fr);
10143 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10144 tcg_temp_free_i32(fp0);
10145 tcg_temp_free_i32(fp1);
10146 gen_store_fpr32(ctx, fp2, fd);
10147 tcg_temp_free_i32(fp2);
10149 break;
10150 case OPC_MADD_D:
10151 check_cop1x(ctx);
10152 check_cp1_registers(ctx, fd | fs | ft | fr);
10154 TCGv_i64 fp0 = tcg_temp_new_i64();
10155 TCGv_i64 fp1 = tcg_temp_new_i64();
10156 TCGv_i64 fp2 = tcg_temp_new_i64();
10158 gen_load_fpr64(ctx, fp0, fs);
10159 gen_load_fpr64(ctx, fp1, ft);
10160 gen_load_fpr64(ctx, fp2, fr);
10161 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10162 tcg_temp_free_i64(fp0);
10163 tcg_temp_free_i64(fp1);
10164 gen_store_fpr64(ctx, fp2, fd);
10165 tcg_temp_free_i64(fp2);
10167 break;
10168 case OPC_MADD_PS:
10169 check_ps(ctx);
10171 TCGv_i64 fp0 = tcg_temp_new_i64();
10172 TCGv_i64 fp1 = tcg_temp_new_i64();
10173 TCGv_i64 fp2 = tcg_temp_new_i64();
10175 gen_load_fpr64(ctx, fp0, fs);
10176 gen_load_fpr64(ctx, fp1, ft);
10177 gen_load_fpr64(ctx, fp2, fr);
10178 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10179 tcg_temp_free_i64(fp0);
10180 tcg_temp_free_i64(fp1);
10181 gen_store_fpr64(ctx, fp2, fd);
10182 tcg_temp_free_i64(fp2);
10184 break;
10185 case OPC_MSUB_S:
10186 check_cop1x(ctx);
10188 TCGv_i32 fp0 = tcg_temp_new_i32();
10189 TCGv_i32 fp1 = tcg_temp_new_i32();
10190 TCGv_i32 fp2 = tcg_temp_new_i32();
10192 gen_load_fpr32(ctx, fp0, fs);
10193 gen_load_fpr32(ctx, fp1, ft);
10194 gen_load_fpr32(ctx, fp2, fr);
10195 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10196 tcg_temp_free_i32(fp0);
10197 tcg_temp_free_i32(fp1);
10198 gen_store_fpr32(ctx, fp2, fd);
10199 tcg_temp_free_i32(fp2);
10201 break;
10202 case OPC_MSUB_D:
10203 check_cop1x(ctx);
10204 check_cp1_registers(ctx, fd | fs | ft | fr);
10206 TCGv_i64 fp0 = tcg_temp_new_i64();
10207 TCGv_i64 fp1 = tcg_temp_new_i64();
10208 TCGv_i64 fp2 = tcg_temp_new_i64();
10210 gen_load_fpr64(ctx, fp0, fs);
10211 gen_load_fpr64(ctx, fp1, ft);
10212 gen_load_fpr64(ctx, fp2, fr);
10213 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
10214 tcg_temp_free_i64(fp0);
10215 tcg_temp_free_i64(fp1);
10216 gen_store_fpr64(ctx, fp2, fd);
10217 tcg_temp_free_i64(fp2);
10219 break;
10220 case OPC_MSUB_PS:
10221 check_ps(ctx);
10223 TCGv_i64 fp0 = tcg_temp_new_i64();
10224 TCGv_i64 fp1 = tcg_temp_new_i64();
10225 TCGv_i64 fp2 = tcg_temp_new_i64();
10227 gen_load_fpr64(ctx, fp0, fs);
10228 gen_load_fpr64(ctx, fp1, ft);
10229 gen_load_fpr64(ctx, fp2, fr);
10230 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10231 tcg_temp_free_i64(fp0);
10232 tcg_temp_free_i64(fp1);
10233 gen_store_fpr64(ctx, fp2, fd);
10234 tcg_temp_free_i64(fp2);
10236 break;
10237 case OPC_NMADD_S:
10238 check_cop1x(ctx);
10240 TCGv_i32 fp0 = tcg_temp_new_i32();
10241 TCGv_i32 fp1 = tcg_temp_new_i32();
10242 TCGv_i32 fp2 = tcg_temp_new_i32();
10244 gen_load_fpr32(ctx, fp0, fs);
10245 gen_load_fpr32(ctx, fp1, ft);
10246 gen_load_fpr32(ctx, fp2, fr);
10247 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10248 tcg_temp_free_i32(fp0);
10249 tcg_temp_free_i32(fp1);
10250 gen_store_fpr32(ctx, fp2, fd);
10251 tcg_temp_free_i32(fp2);
10253 break;
10254 case OPC_NMADD_D:
10255 check_cop1x(ctx);
10256 check_cp1_registers(ctx, fd | fs | ft | fr);
10258 TCGv_i64 fp0 = tcg_temp_new_i64();
10259 TCGv_i64 fp1 = tcg_temp_new_i64();
10260 TCGv_i64 fp2 = tcg_temp_new_i64();
10262 gen_load_fpr64(ctx, fp0, fs);
10263 gen_load_fpr64(ctx, fp1, ft);
10264 gen_load_fpr64(ctx, fp2, fr);
10265 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10266 tcg_temp_free_i64(fp0);
10267 tcg_temp_free_i64(fp1);
10268 gen_store_fpr64(ctx, fp2, fd);
10269 tcg_temp_free_i64(fp2);
10271 break;
10272 case OPC_NMADD_PS:
10273 check_ps(ctx);
10275 TCGv_i64 fp0 = tcg_temp_new_i64();
10276 TCGv_i64 fp1 = tcg_temp_new_i64();
10277 TCGv_i64 fp2 = tcg_temp_new_i64();
10279 gen_load_fpr64(ctx, fp0, fs);
10280 gen_load_fpr64(ctx, fp1, ft);
10281 gen_load_fpr64(ctx, fp2, fr);
10282 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10283 tcg_temp_free_i64(fp0);
10284 tcg_temp_free_i64(fp1);
10285 gen_store_fpr64(ctx, fp2, fd);
10286 tcg_temp_free_i64(fp2);
10288 break;
10289 case OPC_NMSUB_S:
10290 check_cop1x(ctx);
10292 TCGv_i32 fp0 = tcg_temp_new_i32();
10293 TCGv_i32 fp1 = tcg_temp_new_i32();
10294 TCGv_i32 fp2 = tcg_temp_new_i32();
10296 gen_load_fpr32(ctx, fp0, fs);
10297 gen_load_fpr32(ctx, fp1, ft);
10298 gen_load_fpr32(ctx, fp2, fr);
10299 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10300 tcg_temp_free_i32(fp0);
10301 tcg_temp_free_i32(fp1);
10302 gen_store_fpr32(ctx, fp2, fd);
10303 tcg_temp_free_i32(fp2);
10305 break;
10306 case OPC_NMSUB_D:
10307 check_cop1x(ctx);
10308 check_cp1_registers(ctx, fd | fs | ft | fr);
10310 TCGv_i64 fp0 = tcg_temp_new_i64();
10311 TCGv_i64 fp1 = tcg_temp_new_i64();
10312 TCGv_i64 fp2 = tcg_temp_new_i64();
10314 gen_load_fpr64(ctx, fp0, fs);
10315 gen_load_fpr64(ctx, fp1, ft);
10316 gen_load_fpr64(ctx, fp2, fr);
10317 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10318 tcg_temp_free_i64(fp0);
10319 tcg_temp_free_i64(fp1);
10320 gen_store_fpr64(ctx, fp2, fd);
10321 tcg_temp_free_i64(fp2);
10323 break;
10324 case OPC_NMSUB_PS:
10325 check_ps(ctx);
10327 TCGv_i64 fp0 = tcg_temp_new_i64();
10328 TCGv_i64 fp1 = tcg_temp_new_i64();
10329 TCGv_i64 fp2 = tcg_temp_new_i64();
10331 gen_load_fpr64(ctx, fp0, fs);
10332 gen_load_fpr64(ctx, fp1, ft);
10333 gen_load_fpr64(ctx, fp2, fr);
10334 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10335 tcg_temp_free_i64(fp0);
10336 tcg_temp_free_i64(fp1);
10337 gen_store_fpr64(ctx, fp2, fd);
10338 tcg_temp_free_i64(fp2);
10340 break;
10341 default:
10342 MIPS_INVAL("flt3_arith");
10343 generate_exception_end(ctx, EXCP_RI);
10344 return;
10348 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
10350 TCGv t0;
10352 #if !defined(CONFIG_USER_ONLY)
10353 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10354 Therefore only check the ISA in system mode. */
10355 check_insn(ctx, ISA_MIPS32R2);
10356 #endif
10357 t0 = tcg_temp_new();
10359 switch (rd) {
10360 case 0:
10361 gen_helper_rdhwr_cpunum(t0, cpu_env);
10362 gen_store_gpr(t0, rt);
10363 break;
10364 case 1:
10365 gen_helper_rdhwr_synci_step(t0, cpu_env);
10366 gen_store_gpr(t0, rt);
10367 break;
10368 case 2:
10369 gen_helper_rdhwr_cc(t0, cpu_env);
10370 gen_store_gpr(t0, rt);
10371 break;
10372 case 3:
10373 gen_helper_rdhwr_ccres(t0, cpu_env);
10374 gen_store_gpr(t0, rt);
10375 break;
10376 case 4:
10377 check_insn(ctx, ISA_MIPS32R6);
10378 if (sel != 0) {
10379 /* Performance counter registers are not implemented other than
10380 * control register 0.
10382 generate_exception(ctx, EXCP_RI);
10384 gen_helper_rdhwr_performance(t0, cpu_env);
10385 gen_store_gpr(t0, rt);
10386 break;
10387 case 5:
10388 check_insn(ctx, ISA_MIPS32R6);
10389 gen_helper_rdhwr_xnp(t0, cpu_env);
10390 gen_store_gpr(t0, rt);
10391 break;
10392 case 29:
10393 #if defined(CONFIG_USER_ONLY)
10394 tcg_gen_ld_tl(t0, cpu_env,
10395 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10396 gen_store_gpr(t0, rt);
10397 break;
10398 #else
10399 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10400 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10401 tcg_gen_ld_tl(t0, cpu_env,
10402 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10403 gen_store_gpr(t0, rt);
10404 } else {
10405 generate_exception_end(ctx, EXCP_RI);
10407 break;
10408 #endif
10409 default: /* Invalid */
10410 MIPS_INVAL("rdhwr");
10411 generate_exception_end(ctx, EXCP_RI);
10412 break;
10414 tcg_temp_free(t0);
10417 static inline void clear_branch_hflags(DisasContext *ctx)
10419 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10420 if (ctx->bstate == BS_NONE) {
10421 save_cpu_state(ctx, 0);
10422 } else {
10423 /* it is not safe to save ctx->hflags as hflags may be changed
10424 in execution time by the instruction in delay / forbidden slot. */
10425 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10429 static void gen_branch(DisasContext *ctx, int insn_bytes)
10431 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10432 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10433 /* Branches completion */
10434 clear_branch_hflags(ctx);
10435 ctx->bstate = BS_BRANCH;
10436 /* FIXME: Need to clear can_do_io. */
10437 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10438 case MIPS_HFLAG_FBNSLOT:
10439 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10440 break;
10441 case MIPS_HFLAG_B:
10442 /* unconditional branch */
10443 if (proc_hflags & MIPS_HFLAG_BX) {
10444 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10446 gen_goto_tb(ctx, 0, ctx->btarget);
10447 break;
10448 case MIPS_HFLAG_BL:
10449 /* blikely taken case */
10450 gen_goto_tb(ctx, 0, ctx->btarget);
10451 break;
10452 case MIPS_HFLAG_BC:
10453 /* Conditional branch */
10455 TCGLabel *l1 = gen_new_label();
10457 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10458 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10459 gen_set_label(l1);
10460 gen_goto_tb(ctx, 0, ctx->btarget);
10462 break;
10463 case MIPS_HFLAG_BR:
10464 /* unconditional branch to register */
10465 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10466 TCGv t0 = tcg_temp_new();
10467 TCGv_i32 t1 = tcg_temp_new_i32();
10469 tcg_gen_andi_tl(t0, btarget, 0x1);
10470 tcg_gen_trunc_tl_i32(t1, t0);
10471 tcg_temp_free(t0);
10472 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10473 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10474 tcg_gen_or_i32(hflags, hflags, t1);
10475 tcg_temp_free_i32(t1);
10477 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10478 } else {
10479 tcg_gen_mov_tl(cpu_PC, btarget);
10481 if (ctx->singlestep_enabled) {
10482 save_cpu_state(ctx, 0);
10483 gen_helper_raise_exception_debug(cpu_env);
10485 tcg_gen_exit_tb(0);
10486 break;
10487 default:
10488 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
10489 abort();
10494 /* Compact Branches */
10495 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
10496 int rs, int rt, int32_t offset)
10498 int bcond_compute = 0;
10499 TCGv t0 = tcg_temp_new();
10500 TCGv t1 = tcg_temp_new();
10501 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
10503 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10504 #ifdef MIPS_DEBUG_DISAS
10505 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10506 "\n", ctx->pc);
10507 #endif
10508 generate_exception_end(ctx, EXCP_RI);
10509 goto out;
10512 /* Load needed operands and calculate btarget */
10513 switch (opc) {
10514 /* compact branch */
10515 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10516 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10517 gen_load_gpr(t0, rs);
10518 gen_load_gpr(t1, rt);
10519 bcond_compute = 1;
10520 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10521 if (rs <= rt && rs == 0) {
10522 /* OPC_BEQZALC, OPC_BNEZALC */
10523 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10525 break;
10526 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10527 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10528 gen_load_gpr(t0, rs);
10529 gen_load_gpr(t1, rt);
10530 bcond_compute = 1;
10531 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10532 break;
10533 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10534 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10535 if (rs == 0 || rs == rt) {
10536 /* OPC_BLEZALC, OPC_BGEZALC */
10537 /* OPC_BGTZALC, OPC_BLTZALC */
10538 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10540 gen_load_gpr(t0, rs);
10541 gen_load_gpr(t1, rt);
10542 bcond_compute = 1;
10543 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10544 break;
10545 case OPC_BC:
10546 case OPC_BALC:
10547 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10548 break;
10549 case OPC_BEQZC:
10550 case OPC_BNEZC:
10551 if (rs != 0) {
10552 /* OPC_BEQZC, OPC_BNEZC */
10553 gen_load_gpr(t0, rs);
10554 bcond_compute = 1;
10555 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10556 } else {
10557 /* OPC_JIC, OPC_JIALC */
10558 TCGv tbase = tcg_temp_new();
10559 TCGv toffset = tcg_temp_new();
10561 gen_load_gpr(tbase, rt);
10562 tcg_gen_movi_tl(toffset, offset);
10563 gen_op_addr_add(ctx, btarget, tbase, toffset);
10564 tcg_temp_free(tbase);
10565 tcg_temp_free(toffset);
10567 break;
10568 default:
10569 MIPS_INVAL("Compact branch/jump");
10570 generate_exception_end(ctx, EXCP_RI);
10571 goto out;
10574 if (bcond_compute == 0) {
10575 /* Uncoditional compact branch */
10576 switch (opc) {
10577 case OPC_JIALC:
10578 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10579 /* Fallthrough */
10580 case OPC_JIC:
10581 ctx->hflags |= MIPS_HFLAG_BR;
10582 break;
10583 case OPC_BALC:
10584 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10585 /* Fallthrough */
10586 case OPC_BC:
10587 ctx->hflags |= MIPS_HFLAG_B;
10588 break;
10589 default:
10590 MIPS_INVAL("Compact branch/jump");
10591 generate_exception_end(ctx, EXCP_RI);
10592 goto out;
10595 /* Generating branch here as compact branches don't have delay slot */
10596 gen_branch(ctx, 4);
10597 } else {
10598 /* Conditional compact branch */
10599 TCGLabel *fs = gen_new_label();
10600 save_cpu_state(ctx, 0);
10602 switch (opc) {
10603 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10604 if (rs == 0 && rt != 0) {
10605 /* OPC_BLEZALC */
10606 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
10607 } else if (rs != 0 && rt != 0 && rs == rt) {
10608 /* OPC_BGEZALC */
10609 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
10610 } else {
10611 /* OPC_BGEUC */
10612 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
10614 break;
10615 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10616 if (rs == 0 && rt != 0) {
10617 /* OPC_BGTZALC */
10618 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
10619 } else if (rs != 0 && rt != 0 && rs == rt) {
10620 /* OPC_BLTZALC */
10621 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
10622 } else {
10623 /* OPC_BLTUC */
10624 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
10626 break;
10627 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10628 if (rs == 0 && rt != 0) {
10629 /* OPC_BLEZC */
10630 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
10631 } else if (rs != 0 && rt != 0 && rs == rt) {
10632 /* OPC_BGEZC */
10633 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
10634 } else {
10635 /* OPC_BGEC */
10636 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
10638 break;
10639 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10640 if (rs == 0 && rt != 0) {
10641 /* OPC_BGTZC */
10642 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
10643 } else if (rs != 0 && rt != 0 && rs == rt) {
10644 /* OPC_BLTZC */
10645 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
10646 } else {
10647 /* OPC_BLTC */
10648 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
10650 break;
10651 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10652 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10653 if (rs >= rt) {
10654 /* OPC_BOVC, OPC_BNVC */
10655 TCGv t2 = tcg_temp_new();
10656 TCGv t3 = tcg_temp_new();
10657 TCGv t4 = tcg_temp_new();
10658 TCGv input_overflow = tcg_temp_new();
10660 gen_load_gpr(t0, rs);
10661 gen_load_gpr(t1, rt);
10662 tcg_gen_ext32s_tl(t2, t0);
10663 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
10664 tcg_gen_ext32s_tl(t3, t1);
10665 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
10666 tcg_gen_or_tl(input_overflow, input_overflow, t4);
10668 tcg_gen_add_tl(t4, t2, t3);
10669 tcg_gen_ext32s_tl(t4, t4);
10670 tcg_gen_xor_tl(t2, t2, t3);
10671 tcg_gen_xor_tl(t3, t4, t3);
10672 tcg_gen_andc_tl(t2, t3, t2);
10673 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
10674 tcg_gen_or_tl(t4, t4, input_overflow);
10675 if (opc == OPC_BOVC) {
10676 /* OPC_BOVC */
10677 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
10678 } else {
10679 /* OPC_BNVC */
10680 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
10682 tcg_temp_free(input_overflow);
10683 tcg_temp_free(t4);
10684 tcg_temp_free(t3);
10685 tcg_temp_free(t2);
10686 } else if (rs < rt && rs == 0) {
10687 /* OPC_BEQZALC, OPC_BNEZALC */
10688 if (opc == OPC_BEQZALC) {
10689 /* OPC_BEQZALC */
10690 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
10691 } else {
10692 /* OPC_BNEZALC */
10693 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
10695 } else {
10696 /* OPC_BEQC, OPC_BNEC */
10697 if (opc == OPC_BEQC) {
10698 /* OPC_BEQC */
10699 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
10700 } else {
10701 /* OPC_BNEC */
10702 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
10705 break;
10706 case OPC_BEQZC:
10707 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
10708 break;
10709 case OPC_BNEZC:
10710 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
10711 break;
10712 default:
10713 MIPS_INVAL("Compact conditional branch/jump");
10714 generate_exception_end(ctx, EXCP_RI);
10715 goto out;
10718 /* Generating branch here as compact branches don't have delay slot */
10719 gen_goto_tb(ctx, 1, ctx->btarget);
10720 gen_set_label(fs);
10722 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
10725 out:
10726 tcg_temp_free(t0);
10727 tcg_temp_free(t1);
10730 /* ISA extensions (ASEs) */
10731 /* MIPS16 extension to MIPS32 */
10733 /* MIPS16 major opcodes */
10734 enum {
10735 M16_OPC_ADDIUSP = 0x00,
10736 M16_OPC_ADDIUPC = 0x01,
10737 M16_OPC_B = 0x02,
10738 M16_OPC_JAL = 0x03,
10739 M16_OPC_BEQZ = 0x04,
10740 M16_OPC_BNEQZ = 0x05,
10741 M16_OPC_SHIFT = 0x06,
10742 M16_OPC_LD = 0x07,
10743 M16_OPC_RRIA = 0x08,
10744 M16_OPC_ADDIU8 = 0x09,
10745 M16_OPC_SLTI = 0x0a,
10746 M16_OPC_SLTIU = 0x0b,
10747 M16_OPC_I8 = 0x0c,
10748 M16_OPC_LI = 0x0d,
10749 M16_OPC_CMPI = 0x0e,
10750 M16_OPC_SD = 0x0f,
10751 M16_OPC_LB = 0x10,
10752 M16_OPC_LH = 0x11,
10753 M16_OPC_LWSP = 0x12,
10754 M16_OPC_LW = 0x13,
10755 M16_OPC_LBU = 0x14,
10756 M16_OPC_LHU = 0x15,
10757 M16_OPC_LWPC = 0x16,
10758 M16_OPC_LWU = 0x17,
10759 M16_OPC_SB = 0x18,
10760 M16_OPC_SH = 0x19,
10761 M16_OPC_SWSP = 0x1a,
10762 M16_OPC_SW = 0x1b,
10763 M16_OPC_RRR = 0x1c,
10764 M16_OPC_RR = 0x1d,
10765 M16_OPC_EXTEND = 0x1e,
10766 M16_OPC_I64 = 0x1f
10769 /* I8 funct field */
10770 enum {
10771 I8_BTEQZ = 0x0,
10772 I8_BTNEZ = 0x1,
10773 I8_SWRASP = 0x2,
10774 I8_ADJSP = 0x3,
10775 I8_SVRS = 0x4,
10776 I8_MOV32R = 0x5,
10777 I8_MOVR32 = 0x7
10780 /* RRR f field */
10781 enum {
10782 RRR_DADDU = 0x0,
10783 RRR_ADDU = 0x1,
10784 RRR_DSUBU = 0x2,
10785 RRR_SUBU = 0x3
10788 /* RR funct field */
10789 enum {
10790 RR_JR = 0x00,
10791 RR_SDBBP = 0x01,
10792 RR_SLT = 0x02,
10793 RR_SLTU = 0x03,
10794 RR_SLLV = 0x04,
10795 RR_BREAK = 0x05,
10796 RR_SRLV = 0x06,
10797 RR_SRAV = 0x07,
10798 RR_DSRL = 0x08,
10799 RR_CMP = 0x0a,
10800 RR_NEG = 0x0b,
10801 RR_AND = 0x0c,
10802 RR_OR = 0x0d,
10803 RR_XOR = 0x0e,
10804 RR_NOT = 0x0f,
10805 RR_MFHI = 0x10,
10806 RR_CNVT = 0x11,
10807 RR_MFLO = 0x12,
10808 RR_DSRA = 0x13,
10809 RR_DSLLV = 0x14,
10810 RR_DSRLV = 0x16,
10811 RR_DSRAV = 0x17,
10812 RR_MULT = 0x18,
10813 RR_MULTU = 0x19,
10814 RR_DIV = 0x1a,
10815 RR_DIVU = 0x1b,
10816 RR_DMULT = 0x1c,
10817 RR_DMULTU = 0x1d,
10818 RR_DDIV = 0x1e,
10819 RR_DDIVU = 0x1f
10822 /* I64 funct field */
10823 enum {
10824 I64_LDSP = 0x0,
10825 I64_SDSP = 0x1,
10826 I64_SDRASP = 0x2,
10827 I64_DADJSP = 0x3,
10828 I64_LDPC = 0x4,
10829 I64_DADDIU5 = 0x5,
10830 I64_DADDIUPC = 0x6,
10831 I64_DADDIUSP = 0x7
10834 /* RR ry field for CNVT */
10835 enum {
10836 RR_RY_CNVT_ZEB = 0x0,
10837 RR_RY_CNVT_ZEH = 0x1,
10838 RR_RY_CNVT_ZEW = 0x2,
10839 RR_RY_CNVT_SEB = 0x4,
10840 RR_RY_CNVT_SEH = 0x5,
10841 RR_RY_CNVT_SEW = 0x6,
10844 static int xlat (int r)
10846 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10848 return map[r];
10851 static void gen_mips16_save (DisasContext *ctx,
10852 int xsregs, int aregs,
10853 int do_ra, int do_s0, int do_s1,
10854 int framesize)
10856 TCGv t0 = tcg_temp_new();
10857 TCGv t1 = tcg_temp_new();
10858 TCGv t2 = tcg_temp_new();
10859 int args, astatic;
10861 switch (aregs) {
10862 case 0:
10863 case 1:
10864 case 2:
10865 case 3:
10866 case 11:
10867 args = 0;
10868 break;
10869 case 4:
10870 case 5:
10871 case 6:
10872 case 7:
10873 args = 1;
10874 break;
10875 case 8:
10876 case 9:
10877 case 10:
10878 args = 2;
10879 break;
10880 case 12:
10881 case 13:
10882 args = 3;
10883 break;
10884 case 14:
10885 args = 4;
10886 break;
10887 default:
10888 generate_exception_end(ctx, EXCP_RI);
10889 return;
10892 switch (args) {
10893 case 4:
10894 gen_base_offset_addr(ctx, t0, 29, 12);
10895 gen_load_gpr(t1, 7);
10896 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10897 /* Fall through */
10898 case 3:
10899 gen_base_offset_addr(ctx, t0, 29, 8);
10900 gen_load_gpr(t1, 6);
10901 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10902 /* Fall through */
10903 case 2:
10904 gen_base_offset_addr(ctx, t0, 29, 4);
10905 gen_load_gpr(t1, 5);
10906 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10907 /* Fall through */
10908 case 1:
10909 gen_base_offset_addr(ctx, t0, 29, 0);
10910 gen_load_gpr(t1, 4);
10911 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10914 gen_load_gpr(t0, 29);
10916 #define DECR_AND_STORE(reg) do { \
10917 tcg_gen_movi_tl(t2, -4); \
10918 gen_op_addr_add(ctx, t0, t0, t2); \
10919 gen_load_gpr(t1, reg); \
10920 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
10921 } while (0)
10923 if (do_ra) {
10924 DECR_AND_STORE(31);
10927 switch (xsregs) {
10928 case 7:
10929 DECR_AND_STORE(30);
10930 /* Fall through */
10931 case 6:
10932 DECR_AND_STORE(23);
10933 /* Fall through */
10934 case 5:
10935 DECR_AND_STORE(22);
10936 /* Fall through */
10937 case 4:
10938 DECR_AND_STORE(21);
10939 /* Fall through */
10940 case 3:
10941 DECR_AND_STORE(20);
10942 /* Fall through */
10943 case 2:
10944 DECR_AND_STORE(19);
10945 /* Fall through */
10946 case 1:
10947 DECR_AND_STORE(18);
10950 if (do_s1) {
10951 DECR_AND_STORE(17);
10953 if (do_s0) {
10954 DECR_AND_STORE(16);
10957 switch (aregs) {
10958 case 0:
10959 case 4:
10960 case 8:
10961 case 12:
10962 case 14:
10963 astatic = 0;
10964 break;
10965 case 1:
10966 case 5:
10967 case 9:
10968 case 13:
10969 astatic = 1;
10970 break;
10971 case 2:
10972 case 6:
10973 case 10:
10974 astatic = 2;
10975 break;
10976 case 3:
10977 case 7:
10978 astatic = 3;
10979 break;
10980 case 11:
10981 astatic = 4;
10982 break;
10983 default:
10984 generate_exception_end(ctx, EXCP_RI);
10985 return;
10988 if (astatic > 0) {
10989 DECR_AND_STORE(7);
10990 if (astatic > 1) {
10991 DECR_AND_STORE(6);
10992 if (astatic > 2) {
10993 DECR_AND_STORE(5);
10994 if (astatic > 3) {
10995 DECR_AND_STORE(4);
11000 #undef DECR_AND_STORE
11002 tcg_gen_movi_tl(t2, -framesize);
11003 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11004 tcg_temp_free(t0);
11005 tcg_temp_free(t1);
11006 tcg_temp_free(t2);
11009 static void gen_mips16_restore (DisasContext *ctx,
11010 int xsregs, int aregs,
11011 int do_ra, int do_s0, int do_s1,
11012 int framesize)
11014 int astatic;
11015 TCGv t0 = tcg_temp_new();
11016 TCGv t1 = tcg_temp_new();
11017 TCGv t2 = tcg_temp_new();
11019 tcg_gen_movi_tl(t2, framesize);
11020 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11022 #define DECR_AND_LOAD(reg) do { \
11023 tcg_gen_movi_tl(t2, -4); \
11024 gen_op_addr_add(ctx, t0, t0, t2); \
11025 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11026 gen_store_gpr(t1, reg); \
11027 } while (0)
11029 if (do_ra) {
11030 DECR_AND_LOAD(31);
11033 switch (xsregs) {
11034 case 7:
11035 DECR_AND_LOAD(30);
11036 /* Fall through */
11037 case 6:
11038 DECR_AND_LOAD(23);
11039 /* Fall through */
11040 case 5:
11041 DECR_AND_LOAD(22);
11042 /* Fall through */
11043 case 4:
11044 DECR_AND_LOAD(21);
11045 /* Fall through */
11046 case 3:
11047 DECR_AND_LOAD(20);
11048 /* Fall through */
11049 case 2:
11050 DECR_AND_LOAD(19);
11051 /* Fall through */
11052 case 1:
11053 DECR_AND_LOAD(18);
11056 if (do_s1) {
11057 DECR_AND_LOAD(17);
11059 if (do_s0) {
11060 DECR_AND_LOAD(16);
11063 switch (aregs) {
11064 case 0:
11065 case 4:
11066 case 8:
11067 case 12:
11068 case 14:
11069 astatic = 0;
11070 break;
11071 case 1:
11072 case 5:
11073 case 9:
11074 case 13:
11075 astatic = 1;
11076 break;
11077 case 2:
11078 case 6:
11079 case 10:
11080 astatic = 2;
11081 break;
11082 case 3:
11083 case 7:
11084 astatic = 3;
11085 break;
11086 case 11:
11087 astatic = 4;
11088 break;
11089 default:
11090 generate_exception_end(ctx, EXCP_RI);
11091 return;
11094 if (astatic > 0) {
11095 DECR_AND_LOAD(7);
11096 if (astatic > 1) {
11097 DECR_AND_LOAD(6);
11098 if (astatic > 2) {
11099 DECR_AND_LOAD(5);
11100 if (astatic > 3) {
11101 DECR_AND_LOAD(4);
11106 #undef DECR_AND_LOAD
11108 tcg_gen_movi_tl(t2, framesize);
11109 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11110 tcg_temp_free(t0);
11111 tcg_temp_free(t1);
11112 tcg_temp_free(t2);
11115 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11116 int is_64_bit, int extended)
11118 TCGv t0;
11120 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11121 generate_exception_end(ctx, EXCP_RI);
11122 return;
11125 t0 = tcg_temp_new();
11127 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11128 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11129 if (!is_64_bit) {
11130 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11133 tcg_temp_free(t0);
11136 #if defined(TARGET_MIPS64)
11137 static void decode_i64_mips16 (DisasContext *ctx,
11138 int ry, int funct, int16_t offset,
11139 int extended)
11141 switch (funct) {
11142 case I64_LDSP:
11143 check_insn(ctx, ISA_MIPS3);
11144 check_mips_64(ctx);
11145 offset = extended ? offset : offset << 3;
11146 gen_ld(ctx, OPC_LD, ry, 29, offset);
11147 break;
11148 case I64_SDSP:
11149 check_insn(ctx, ISA_MIPS3);
11150 check_mips_64(ctx);
11151 offset = extended ? offset : offset << 3;
11152 gen_st(ctx, OPC_SD, ry, 29, offset);
11153 break;
11154 case I64_SDRASP:
11155 check_insn(ctx, ISA_MIPS3);
11156 check_mips_64(ctx);
11157 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11158 gen_st(ctx, OPC_SD, 31, 29, offset);
11159 break;
11160 case I64_DADJSP:
11161 check_insn(ctx, ISA_MIPS3);
11162 check_mips_64(ctx);
11163 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11164 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11165 break;
11166 case I64_LDPC:
11167 check_insn(ctx, ISA_MIPS3);
11168 check_mips_64(ctx);
11169 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11170 generate_exception_end(ctx, EXCP_RI);
11171 } else {
11172 offset = extended ? offset : offset << 3;
11173 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11175 break;
11176 case I64_DADDIU5:
11177 check_insn(ctx, ISA_MIPS3);
11178 check_mips_64(ctx);
11179 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11180 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11181 break;
11182 case I64_DADDIUPC:
11183 check_insn(ctx, ISA_MIPS3);
11184 check_mips_64(ctx);
11185 offset = extended ? offset : offset << 2;
11186 gen_addiupc(ctx, ry, offset, 1, extended);
11187 break;
11188 case I64_DADDIUSP:
11189 check_insn(ctx, ISA_MIPS3);
11190 check_mips_64(ctx);
11191 offset = extended ? offset : offset << 2;
11192 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11193 break;
11196 #endif
11198 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11200 int extend = cpu_lduw_code(env, ctx->pc + 2);
11201 int op, rx, ry, funct, sa;
11202 int16_t imm, offset;
11204 ctx->opcode = (ctx->opcode << 16) | extend;
11205 op = (ctx->opcode >> 11) & 0x1f;
11206 sa = (ctx->opcode >> 22) & 0x1f;
11207 funct = (ctx->opcode >> 8) & 0x7;
11208 rx = xlat((ctx->opcode >> 8) & 0x7);
11209 ry = xlat((ctx->opcode >> 5) & 0x7);
11210 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11211 | ((ctx->opcode >> 21) & 0x3f) << 5
11212 | (ctx->opcode & 0x1f));
11214 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11215 counterparts. */
11216 switch (op) {
11217 case M16_OPC_ADDIUSP:
11218 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11219 break;
11220 case M16_OPC_ADDIUPC:
11221 gen_addiupc(ctx, rx, imm, 0, 1);
11222 break;
11223 case M16_OPC_B:
11224 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11225 /* No delay slot, so just process as a normal instruction */
11226 break;
11227 case M16_OPC_BEQZ:
11228 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11229 /* No delay slot, so just process as a normal instruction */
11230 break;
11231 case M16_OPC_BNEQZ:
11232 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11233 /* No delay slot, so just process as a normal instruction */
11234 break;
11235 case M16_OPC_SHIFT:
11236 switch (ctx->opcode & 0x3) {
11237 case 0x0:
11238 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11239 break;
11240 case 0x1:
11241 #if defined(TARGET_MIPS64)
11242 check_mips_64(ctx);
11243 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11244 #else
11245 generate_exception_end(ctx, EXCP_RI);
11246 #endif
11247 break;
11248 case 0x2:
11249 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11250 break;
11251 case 0x3:
11252 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11253 break;
11255 break;
11256 #if defined(TARGET_MIPS64)
11257 case M16_OPC_LD:
11258 check_insn(ctx, ISA_MIPS3);
11259 check_mips_64(ctx);
11260 gen_ld(ctx, OPC_LD, ry, rx, offset);
11261 break;
11262 #endif
11263 case M16_OPC_RRIA:
11264 imm = ctx->opcode & 0xf;
11265 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11266 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11267 imm = (int16_t) (imm << 1) >> 1;
11268 if ((ctx->opcode >> 4) & 0x1) {
11269 #if defined(TARGET_MIPS64)
11270 check_mips_64(ctx);
11271 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11272 #else
11273 generate_exception_end(ctx, EXCP_RI);
11274 #endif
11275 } else {
11276 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11278 break;
11279 case M16_OPC_ADDIU8:
11280 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11281 break;
11282 case M16_OPC_SLTI:
11283 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11284 break;
11285 case M16_OPC_SLTIU:
11286 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11287 break;
11288 case M16_OPC_I8:
11289 switch (funct) {
11290 case I8_BTEQZ:
11291 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11292 break;
11293 case I8_BTNEZ:
11294 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11295 break;
11296 case I8_SWRASP:
11297 gen_st(ctx, OPC_SW, 31, 29, imm);
11298 break;
11299 case I8_ADJSP:
11300 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11301 break;
11302 case I8_SVRS:
11303 check_insn(ctx, ISA_MIPS32);
11305 int xsregs = (ctx->opcode >> 24) & 0x7;
11306 int aregs = (ctx->opcode >> 16) & 0xf;
11307 int do_ra = (ctx->opcode >> 6) & 0x1;
11308 int do_s0 = (ctx->opcode >> 5) & 0x1;
11309 int do_s1 = (ctx->opcode >> 4) & 0x1;
11310 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11311 | (ctx->opcode & 0xf)) << 3;
11313 if (ctx->opcode & (1 << 7)) {
11314 gen_mips16_save(ctx, xsregs, aregs,
11315 do_ra, do_s0, do_s1,
11316 framesize);
11317 } else {
11318 gen_mips16_restore(ctx, xsregs, aregs,
11319 do_ra, do_s0, do_s1,
11320 framesize);
11323 break;
11324 default:
11325 generate_exception_end(ctx, EXCP_RI);
11326 break;
11328 break;
11329 case M16_OPC_LI:
11330 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11331 break;
11332 case M16_OPC_CMPI:
11333 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11334 break;
11335 #if defined(TARGET_MIPS64)
11336 case M16_OPC_SD:
11337 check_insn(ctx, ISA_MIPS3);
11338 check_mips_64(ctx);
11339 gen_st(ctx, OPC_SD, ry, rx, offset);
11340 break;
11341 #endif
11342 case M16_OPC_LB:
11343 gen_ld(ctx, OPC_LB, ry, rx, offset);
11344 break;
11345 case M16_OPC_LH:
11346 gen_ld(ctx, OPC_LH, ry, rx, offset);
11347 break;
11348 case M16_OPC_LWSP:
11349 gen_ld(ctx, OPC_LW, rx, 29, offset);
11350 break;
11351 case M16_OPC_LW:
11352 gen_ld(ctx, OPC_LW, ry, rx, offset);
11353 break;
11354 case M16_OPC_LBU:
11355 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11356 break;
11357 case M16_OPC_LHU:
11358 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11359 break;
11360 case M16_OPC_LWPC:
11361 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11362 break;
11363 #if defined(TARGET_MIPS64)
11364 case M16_OPC_LWU:
11365 check_insn(ctx, ISA_MIPS3);
11366 check_mips_64(ctx);
11367 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11368 break;
11369 #endif
11370 case M16_OPC_SB:
11371 gen_st(ctx, OPC_SB, ry, rx, offset);
11372 break;
11373 case M16_OPC_SH:
11374 gen_st(ctx, OPC_SH, ry, rx, offset);
11375 break;
11376 case M16_OPC_SWSP:
11377 gen_st(ctx, OPC_SW, rx, 29, offset);
11378 break;
11379 case M16_OPC_SW:
11380 gen_st(ctx, OPC_SW, ry, rx, offset);
11381 break;
11382 #if defined(TARGET_MIPS64)
11383 case M16_OPC_I64:
11384 decode_i64_mips16(ctx, ry, funct, offset, 1);
11385 break;
11386 #endif
11387 default:
11388 generate_exception_end(ctx, EXCP_RI);
11389 break;
11392 return 4;
11395 static inline bool is_uhi(int sdbbp_code)
11397 #ifdef CONFIG_USER_ONLY
11398 return false;
11399 #else
11400 return semihosting_enabled() && sdbbp_code == 1;
11401 #endif
11404 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11406 int rx, ry;
11407 int sa;
11408 int op, cnvt_op, op1, offset;
11409 int funct;
11410 int n_bytes;
11412 op = (ctx->opcode >> 11) & 0x1f;
11413 sa = (ctx->opcode >> 2) & 0x7;
11414 sa = sa == 0 ? 8 : sa;
11415 rx = xlat((ctx->opcode >> 8) & 0x7);
11416 cnvt_op = (ctx->opcode >> 5) & 0x7;
11417 ry = xlat((ctx->opcode >> 5) & 0x7);
11418 op1 = offset = ctx->opcode & 0x1f;
11420 n_bytes = 2;
11422 switch (op) {
11423 case M16_OPC_ADDIUSP:
11425 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11427 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11429 break;
11430 case M16_OPC_ADDIUPC:
11431 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11432 break;
11433 case M16_OPC_B:
11434 offset = (ctx->opcode & 0x7ff) << 1;
11435 offset = (int16_t)(offset << 4) >> 4;
11436 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11437 /* No delay slot, so just process as a normal instruction */
11438 break;
11439 case M16_OPC_JAL:
11440 offset = cpu_lduw_code(env, ctx->pc + 2);
11441 offset = (((ctx->opcode & 0x1f) << 21)
11442 | ((ctx->opcode >> 5) & 0x1f) << 16
11443 | offset) << 2;
11444 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11445 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11446 n_bytes = 4;
11447 break;
11448 case M16_OPC_BEQZ:
11449 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11450 ((int8_t)ctx->opcode) << 1, 0);
11451 /* No delay slot, so just process as a normal instruction */
11452 break;
11453 case M16_OPC_BNEQZ:
11454 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
11455 ((int8_t)ctx->opcode) << 1, 0);
11456 /* No delay slot, so just process as a normal instruction */
11457 break;
11458 case M16_OPC_SHIFT:
11459 switch (ctx->opcode & 0x3) {
11460 case 0x0:
11461 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11462 break;
11463 case 0x1:
11464 #if defined(TARGET_MIPS64)
11465 check_insn(ctx, ISA_MIPS3);
11466 check_mips_64(ctx);
11467 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11468 #else
11469 generate_exception_end(ctx, EXCP_RI);
11470 #endif
11471 break;
11472 case 0x2:
11473 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11474 break;
11475 case 0x3:
11476 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11477 break;
11479 break;
11480 #if defined(TARGET_MIPS64)
11481 case M16_OPC_LD:
11482 check_insn(ctx, ISA_MIPS3);
11483 check_mips_64(ctx);
11484 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
11485 break;
11486 #endif
11487 case M16_OPC_RRIA:
11489 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
11491 if ((ctx->opcode >> 4) & 1) {
11492 #if defined(TARGET_MIPS64)
11493 check_insn(ctx, ISA_MIPS3);
11494 check_mips_64(ctx);
11495 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11496 #else
11497 generate_exception_end(ctx, EXCP_RI);
11498 #endif
11499 } else {
11500 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11503 break;
11504 case M16_OPC_ADDIU8:
11506 int16_t imm = (int8_t) ctx->opcode;
11508 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11510 break;
11511 case M16_OPC_SLTI:
11513 int16_t imm = (uint8_t) ctx->opcode;
11514 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11516 break;
11517 case M16_OPC_SLTIU:
11519 int16_t imm = (uint8_t) ctx->opcode;
11520 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11522 break;
11523 case M16_OPC_I8:
11525 int reg32;
11527 funct = (ctx->opcode >> 8) & 0x7;
11528 switch (funct) {
11529 case I8_BTEQZ:
11530 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
11531 ((int8_t)ctx->opcode) << 1, 0);
11532 break;
11533 case I8_BTNEZ:
11534 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
11535 ((int8_t)ctx->opcode) << 1, 0);
11536 break;
11537 case I8_SWRASP:
11538 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
11539 break;
11540 case I8_ADJSP:
11541 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
11542 ((int8_t)ctx->opcode) << 3);
11543 break;
11544 case I8_SVRS:
11545 check_insn(ctx, ISA_MIPS32);
11547 int do_ra = ctx->opcode & (1 << 6);
11548 int do_s0 = ctx->opcode & (1 << 5);
11549 int do_s1 = ctx->opcode & (1 << 4);
11550 int framesize = ctx->opcode & 0xf;
11552 if (framesize == 0) {
11553 framesize = 128;
11554 } else {
11555 framesize = framesize << 3;
11558 if (ctx->opcode & (1 << 7)) {
11559 gen_mips16_save(ctx, 0, 0,
11560 do_ra, do_s0, do_s1, framesize);
11561 } else {
11562 gen_mips16_restore(ctx, 0, 0,
11563 do_ra, do_s0, do_s1, framesize);
11566 break;
11567 case I8_MOV32R:
11569 int rz = xlat(ctx->opcode & 0x7);
11571 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
11572 ((ctx->opcode >> 5) & 0x7);
11573 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
11575 break;
11576 case I8_MOVR32:
11577 reg32 = ctx->opcode & 0x1f;
11578 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
11579 break;
11580 default:
11581 generate_exception_end(ctx, EXCP_RI);
11582 break;
11585 break;
11586 case M16_OPC_LI:
11588 int16_t imm = (uint8_t) ctx->opcode;
11590 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
11592 break;
11593 case M16_OPC_CMPI:
11595 int16_t imm = (uint8_t) ctx->opcode;
11596 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
11598 break;
11599 #if defined(TARGET_MIPS64)
11600 case M16_OPC_SD:
11601 check_insn(ctx, ISA_MIPS3);
11602 check_mips_64(ctx);
11603 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
11604 break;
11605 #endif
11606 case M16_OPC_LB:
11607 gen_ld(ctx, OPC_LB, ry, rx, offset);
11608 break;
11609 case M16_OPC_LH:
11610 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
11611 break;
11612 case M16_OPC_LWSP:
11613 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11614 break;
11615 case M16_OPC_LW:
11616 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
11617 break;
11618 case M16_OPC_LBU:
11619 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11620 break;
11621 case M16_OPC_LHU:
11622 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
11623 break;
11624 case M16_OPC_LWPC:
11625 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
11626 break;
11627 #if defined (TARGET_MIPS64)
11628 case M16_OPC_LWU:
11629 check_insn(ctx, ISA_MIPS3);
11630 check_mips_64(ctx);
11631 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
11632 break;
11633 #endif
11634 case M16_OPC_SB:
11635 gen_st(ctx, OPC_SB, ry, rx, offset);
11636 break;
11637 case M16_OPC_SH:
11638 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
11639 break;
11640 case M16_OPC_SWSP:
11641 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11642 break;
11643 case M16_OPC_SW:
11644 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
11645 break;
11646 case M16_OPC_RRR:
11648 int rz = xlat((ctx->opcode >> 2) & 0x7);
11649 int mips32_op;
11651 switch (ctx->opcode & 0x3) {
11652 case RRR_ADDU:
11653 mips32_op = OPC_ADDU;
11654 break;
11655 case RRR_SUBU:
11656 mips32_op = OPC_SUBU;
11657 break;
11658 #if defined(TARGET_MIPS64)
11659 case RRR_DADDU:
11660 mips32_op = OPC_DADDU;
11661 check_insn(ctx, ISA_MIPS3);
11662 check_mips_64(ctx);
11663 break;
11664 case RRR_DSUBU:
11665 mips32_op = OPC_DSUBU;
11666 check_insn(ctx, ISA_MIPS3);
11667 check_mips_64(ctx);
11668 break;
11669 #endif
11670 default:
11671 generate_exception_end(ctx, EXCP_RI);
11672 goto done;
11675 gen_arith(ctx, mips32_op, rz, rx, ry);
11676 done:
11679 break;
11680 case M16_OPC_RR:
11681 switch (op1) {
11682 case RR_JR:
11684 int nd = (ctx->opcode >> 7) & 0x1;
11685 int link = (ctx->opcode >> 6) & 0x1;
11686 int ra = (ctx->opcode >> 5) & 0x1;
11688 if (nd) {
11689 check_insn(ctx, ISA_MIPS32);
11692 if (link) {
11693 op = OPC_JALR;
11694 } else {
11695 op = OPC_JR;
11698 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
11699 (nd ? 0 : 2));
11701 break;
11702 case RR_SDBBP:
11703 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
11704 gen_helper_do_semihosting(cpu_env);
11705 } else {
11706 /* XXX: not clear which exception should be raised
11707 * when in debug mode...
11709 check_insn(ctx, ISA_MIPS32);
11710 generate_exception_end(ctx, EXCP_DBp);
11712 break;
11713 case RR_SLT:
11714 gen_slt(ctx, OPC_SLT, 24, rx, ry);
11715 break;
11716 case RR_SLTU:
11717 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
11718 break;
11719 case RR_BREAK:
11720 generate_exception_end(ctx, EXCP_BREAK);
11721 break;
11722 case RR_SLLV:
11723 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
11724 break;
11725 case RR_SRLV:
11726 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
11727 break;
11728 case RR_SRAV:
11729 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
11730 break;
11731 #if defined (TARGET_MIPS64)
11732 case RR_DSRL:
11733 check_insn(ctx, ISA_MIPS3);
11734 check_mips_64(ctx);
11735 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
11736 break;
11737 #endif
11738 case RR_CMP:
11739 gen_logic(ctx, OPC_XOR, 24, rx, ry);
11740 break;
11741 case RR_NEG:
11742 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
11743 break;
11744 case RR_AND:
11745 gen_logic(ctx, OPC_AND, rx, rx, ry);
11746 break;
11747 case RR_OR:
11748 gen_logic(ctx, OPC_OR, rx, rx, ry);
11749 break;
11750 case RR_XOR:
11751 gen_logic(ctx, OPC_XOR, rx, rx, ry);
11752 break;
11753 case RR_NOT:
11754 gen_logic(ctx, OPC_NOR, rx, ry, 0);
11755 break;
11756 case RR_MFHI:
11757 gen_HILO(ctx, OPC_MFHI, 0, rx);
11758 break;
11759 case RR_CNVT:
11760 check_insn(ctx, ISA_MIPS32);
11761 switch (cnvt_op) {
11762 case RR_RY_CNVT_ZEB:
11763 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11764 break;
11765 case RR_RY_CNVT_ZEH:
11766 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11767 break;
11768 case RR_RY_CNVT_SEB:
11769 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11770 break;
11771 case RR_RY_CNVT_SEH:
11772 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11773 break;
11774 #if defined (TARGET_MIPS64)
11775 case RR_RY_CNVT_ZEW:
11776 check_insn(ctx, ISA_MIPS64);
11777 check_mips_64(ctx);
11778 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11779 break;
11780 case RR_RY_CNVT_SEW:
11781 check_insn(ctx, ISA_MIPS64);
11782 check_mips_64(ctx);
11783 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11784 break;
11785 #endif
11786 default:
11787 generate_exception_end(ctx, EXCP_RI);
11788 break;
11790 break;
11791 case RR_MFLO:
11792 gen_HILO(ctx, OPC_MFLO, 0, rx);
11793 break;
11794 #if defined (TARGET_MIPS64)
11795 case RR_DSRA:
11796 check_insn(ctx, ISA_MIPS3);
11797 check_mips_64(ctx);
11798 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
11799 break;
11800 case RR_DSLLV:
11801 check_insn(ctx, ISA_MIPS3);
11802 check_mips_64(ctx);
11803 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
11804 break;
11805 case RR_DSRLV:
11806 check_insn(ctx, ISA_MIPS3);
11807 check_mips_64(ctx);
11808 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
11809 break;
11810 case RR_DSRAV:
11811 check_insn(ctx, ISA_MIPS3);
11812 check_mips_64(ctx);
11813 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
11814 break;
11815 #endif
11816 case RR_MULT:
11817 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
11818 break;
11819 case RR_MULTU:
11820 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
11821 break;
11822 case RR_DIV:
11823 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
11824 break;
11825 case RR_DIVU:
11826 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
11827 break;
11828 #if defined (TARGET_MIPS64)
11829 case RR_DMULT:
11830 check_insn(ctx, ISA_MIPS3);
11831 check_mips_64(ctx);
11832 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
11833 break;
11834 case RR_DMULTU:
11835 check_insn(ctx, ISA_MIPS3);
11836 check_mips_64(ctx);
11837 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
11838 break;
11839 case RR_DDIV:
11840 check_insn(ctx, ISA_MIPS3);
11841 check_mips_64(ctx);
11842 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
11843 break;
11844 case RR_DDIVU:
11845 check_insn(ctx, ISA_MIPS3);
11846 check_mips_64(ctx);
11847 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
11848 break;
11849 #endif
11850 default:
11851 generate_exception_end(ctx, EXCP_RI);
11852 break;
11854 break;
11855 case M16_OPC_EXTEND:
11856 decode_extended_mips16_opc(env, ctx);
11857 n_bytes = 4;
11858 break;
11859 #if defined(TARGET_MIPS64)
11860 case M16_OPC_I64:
11861 funct = (ctx->opcode >> 8) & 0x7;
11862 decode_i64_mips16(ctx, ry, funct, offset, 0);
11863 break;
11864 #endif
11865 default:
11866 generate_exception_end(ctx, EXCP_RI);
11867 break;
11870 return n_bytes;
11873 /* microMIPS extension to MIPS32/MIPS64 */
11876 * microMIPS32/microMIPS64 major opcodes
11878 * 1. MIPS Architecture for Programmers Volume II-B:
11879 * The microMIPS32 Instruction Set (Revision 3.05)
11881 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
11883 * 2. MIPS Architecture For Programmers Volume II-A:
11884 * The MIPS64 Instruction Set (Revision 3.51)
11887 enum {
11888 POOL32A = 0x00,
11889 POOL16A = 0x01,
11890 LBU16 = 0x02,
11891 MOVE16 = 0x03,
11892 ADDI32 = 0x04,
11893 R6_LUI = 0x04,
11894 AUI = 0x04,
11895 LBU32 = 0x05,
11896 SB32 = 0x06,
11897 LB32 = 0x07,
11899 POOL32B = 0x08,
11900 POOL16B = 0x09,
11901 LHU16 = 0x0a,
11902 ANDI16 = 0x0b,
11903 ADDIU32 = 0x0c,
11904 LHU32 = 0x0d,
11905 SH32 = 0x0e,
11906 LH32 = 0x0f,
11908 POOL32I = 0x10,
11909 POOL16C = 0x11,
11910 LWSP16 = 0x12,
11911 POOL16D = 0x13,
11912 ORI32 = 0x14,
11913 POOL32F = 0x15,
11914 POOL32S = 0x16, /* MIPS64 */
11915 DADDIU32 = 0x17, /* MIPS64 */
11917 POOL32C = 0x18,
11918 LWGP16 = 0x19,
11919 LW16 = 0x1a,
11920 POOL16E = 0x1b,
11921 XORI32 = 0x1c,
11922 JALS32 = 0x1d,
11923 BOVC = 0x1d,
11924 BEQC = 0x1d,
11925 BEQZALC = 0x1d,
11926 ADDIUPC = 0x1e,
11927 PCREL = 0x1e,
11928 BNVC = 0x1f,
11929 BNEC = 0x1f,
11930 BNEZALC = 0x1f,
11932 R6_BEQZC = 0x20,
11933 JIC = 0x20,
11934 POOL16F = 0x21,
11935 SB16 = 0x22,
11936 BEQZ16 = 0x23,
11937 BEQZC16 = 0x23,
11938 SLTI32 = 0x24,
11939 BEQ32 = 0x25,
11940 BC = 0x25,
11941 SWC132 = 0x26,
11942 LWC132 = 0x27,
11944 /* 0x29 is reserved */
11945 RES_29 = 0x29,
11946 R6_BNEZC = 0x28,
11947 JIALC = 0x28,
11948 SH16 = 0x2a,
11949 BNEZ16 = 0x2b,
11950 BNEZC16 = 0x2b,
11951 SLTIU32 = 0x2c,
11952 BNE32 = 0x2d,
11953 BALC = 0x2d,
11954 SDC132 = 0x2e,
11955 LDC132 = 0x2f,
11957 /* 0x31 is reserved */
11958 RES_31 = 0x31,
11959 BLEZALC = 0x30,
11960 BGEZALC = 0x30,
11961 BGEUC = 0x30,
11962 SWSP16 = 0x32,
11963 B16 = 0x33,
11964 BC16 = 0x33,
11965 ANDI32 = 0x34,
11966 J32 = 0x35,
11967 BGTZC = 0x35,
11968 BLTZC = 0x35,
11969 BLTC = 0x35,
11970 SD32 = 0x36, /* MIPS64 */
11971 LD32 = 0x37, /* MIPS64 */
11973 /* 0x39 is reserved */
11974 RES_39 = 0x39,
11975 BGTZALC = 0x38,
11976 BLTZALC = 0x38,
11977 BLTUC = 0x38,
11978 SW16 = 0x3a,
11979 LI16 = 0x3b,
11980 JALX32 = 0x3c,
11981 JAL32 = 0x3d,
11982 BLEZC = 0x3d,
11983 BGEZC = 0x3d,
11984 BGEC = 0x3d,
11985 SW32 = 0x3e,
11986 LW32 = 0x3f
11989 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
11990 enum {
11991 ADDIUPC_00 = 0x00,
11992 ADDIUPC_07 = 0x07,
11993 AUIPC = 0x1e,
11994 ALUIPC = 0x1f,
11995 LWPC_08 = 0x08,
11996 LWPC_0F = 0x0F,
11999 /* POOL32A encoding of minor opcode field */
12001 enum {
12002 /* These opcodes are distinguished only by bits 9..6; those bits are
12003 * what are recorded below. */
12004 SLL32 = 0x0,
12005 SRL32 = 0x1,
12006 SRA = 0x2,
12007 ROTR = 0x3,
12008 SELEQZ = 0x5,
12009 SELNEZ = 0x6,
12010 R6_RDHWR = 0x7,
12012 SLLV = 0x0,
12013 SRLV = 0x1,
12014 SRAV = 0x2,
12015 ROTRV = 0x3,
12016 ADD = 0x4,
12017 ADDU32 = 0x5,
12018 SUB = 0x6,
12019 SUBU32 = 0x7,
12020 MUL = 0x8,
12021 AND = 0x9,
12022 OR32 = 0xa,
12023 NOR = 0xb,
12024 XOR32 = 0xc,
12025 SLT = 0xd,
12026 SLTU = 0xe,
12028 MOVN = 0x0,
12029 R6_MUL = 0x0,
12030 MOVZ = 0x1,
12031 MUH = 0x1,
12032 MULU = 0x2,
12033 MUHU = 0x3,
12034 LWXS = 0x4,
12035 R6_DIV = 0x4,
12036 MOD = 0x5,
12037 R6_DIVU = 0x6,
12038 MODU = 0x7,
12040 /* The following can be distinguished by their lower 6 bits. */
12041 BREAK32 = 0x07,
12042 INS = 0x0c,
12043 LSA = 0x0f,
12044 ALIGN = 0x1f,
12045 EXT = 0x2c,
12046 POOL32AXF = 0x3c,
12047 SIGRIE = 0x3f
12050 /* POOL32AXF encoding of minor opcode field extension */
12053 * 1. MIPS Architecture for Programmers Volume II-B:
12054 * The microMIPS32 Instruction Set (Revision 3.05)
12056 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12058 * 2. MIPS Architecture for Programmers VolumeIV-e:
12059 * The MIPS DSP Application-Specific Extension
12060 * to the microMIPS32 Architecture (Revision 2.34)
12062 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12065 enum {
12066 /* bits 11..6 */
12067 TEQ = 0x00,
12068 TGE = 0x08,
12069 TGEU = 0x10,
12070 TLT = 0x20,
12071 TLTU = 0x28,
12072 TNE = 0x30,
12074 MFC0 = 0x03,
12075 MTC0 = 0x0b,
12077 /* begin of microMIPS32 DSP */
12079 /* bits 13..12 for 0x01 */
12080 MFHI_ACC = 0x0,
12081 MFLO_ACC = 0x1,
12082 MTHI_ACC = 0x2,
12083 MTLO_ACC = 0x3,
12085 /* bits 13..12 for 0x2a */
12086 MADD_ACC = 0x0,
12087 MADDU_ACC = 0x1,
12088 MSUB_ACC = 0x2,
12089 MSUBU_ACC = 0x3,
12091 /* bits 13..12 for 0x32 */
12092 MULT_ACC = 0x0,
12093 MULTU_ACC = 0x1,
12095 /* end of microMIPS32 DSP */
12097 /* bits 15..12 for 0x2c */
12098 BITSWAP = 0x0,
12099 SEB = 0x2,
12100 SEH = 0x3,
12101 CLO = 0x4,
12102 CLZ = 0x5,
12103 RDHWR = 0x6,
12104 WSBH = 0x7,
12105 MULT = 0x8,
12106 MULTU = 0x9,
12107 DIV = 0xa,
12108 DIVU = 0xb,
12109 MADD = 0xc,
12110 MADDU = 0xd,
12111 MSUB = 0xe,
12112 MSUBU = 0xf,
12114 /* bits 15..12 for 0x34 */
12115 MFC2 = 0x4,
12116 MTC2 = 0x5,
12117 MFHC2 = 0x8,
12118 MTHC2 = 0x9,
12119 CFC2 = 0xc,
12120 CTC2 = 0xd,
12122 /* bits 15..12 for 0x3c */
12123 JALR = 0x0,
12124 JR = 0x0, /* alias */
12125 JALRC = 0x0,
12126 JRC = 0x0,
12127 JALR_HB = 0x1,
12128 JALRC_HB = 0x1,
12129 JALRS = 0x4,
12130 JALRS_HB = 0x5,
12132 /* bits 15..12 for 0x05 */
12133 RDPGPR = 0xe,
12134 WRPGPR = 0xf,
12136 /* bits 15..12 for 0x0d */
12137 TLBP = 0x0,
12138 TLBR = 0x1,
12139 TLBWI = 0x2,
12140 TLBWR = 0x3,
12141 TLBINV = 0x4,
12142 TLBINVF = 0x5,
12143 WAIT = 0x9,
12144 IRET = 0xd,
12145 DERET = 0xe,
12146 ERET = 0xf,
12148 /* bits 15..12 for 0x15 */
12149 DMT = 0x0,
12150 DVPE = 0x1,
12151 EMT = 0x2,
12152 EVPE = 0x3,
12154 /* bits 15..12 for 0x1d */
12155 DI = 0x4,
12156 EI = 0x5,
12158 /* bits 15..12 for 0x2d */
12159 SYNC = 0x6,
12160 SYSCALL = 0x8,
12161 SDBBP = 0xd,
12163 /* bits 15..12 for 0x35 */
12164 MFHI32 = 0x0,
12165 MFLO32 = 0x1,
12166 MTHI32 = 0x2,
12167 MTLO32 = 0x3,
12170 /* POOL32B encoding of minor opcode field (bits 15..12) */
12172 enum {
12173 LWC2 = 0x0,
12174 LWP = 0x1,
12175 LDP = 0x4,
12176 LWM32 = 0x5,
12177 CACHE = 0x6,
12178 LDM = 0x7,
12179 SWC2 = 0x8,
12180 SWP = 0x9,
12181 SDP = 0xc,
12182 SWM32 = 0xd,
12183 SDM = 0xf
12186 /* POOL32C encoding of minor opcode field (bits 15..12) */
12188 enum {
12189 LWL = 0x0,
12190 SWL = 0x8,
12191 LWR = 0x1,
12192 SWR = 0x9,
12193 PREF = 0x2,
12194 /* 0xa is reserved */
12195 LL = 0x3,
12196 SC = 0xb,
12197 LDL = 0x4,
12198 SDL = 0xc,
12199 LDR = 0x5,
12200 SDR = 0xd,
12201 /* 0x6 is reserved */
12202 LWU = 0xe,
12203 LLD = 0x7,
12204 SCD = 0xf
12207 /* POOL32F encoding of minor opcode field (bits 5..0) */
12209 enum {
12210 /* These are the bit 7..6 values */
12211 ADD_FMT = 0x0,
12213 SUB_FMT = 0x1,
12215 MUL_FMT = 0x2,
12217 DIV_FMT = 0x3,
12219 /* These are the bit 8..6 values */
12220 MOVN_FMT = 0x0,
12221 RSQRT2_FMT = 0x0,
12222 MOVF_FMT = 0x0,
12223 RINT_FMT = 0x0,
12224 SELNEZ_FMT = 0x0,
12226 MOVZ_FMT = 0x1,
12227 LWXC1 = 0x1,
12228 MOVT_FMT = 0x1,
12229 CLASS_FMT = 0x1,
12230 SELEQZ_FMT = 0x1,
12232 PLL_PS = 0x2,
12233 SWXC1 = 0x2,
12234 SEL_FMT = 0x2,
12236 PLU_PS = 0x3,
12237 LDXC1 = 0x3,
12239 MOVN_FMT_04 = 0x4,
12240 PUL_PS = 0x4,
12241 SDXC1 = 0x4,
12242 RECIP2_FMT = 0x4,
12244 MOVZ_FMT_05 = 0x05,
12245 PUU_PS = 0x5,
12246 LUXC1 = 0x5,
12248 CVT_PS_S = 0x6,
12249 SUXC1 = 0x6,
12250 ADDR_PS = 0x6,
12251 PREFX = 0x6,
12252 MADDF_FMT = 0x6,
12254 MULR_PS = 0x7,
12255 MSUBF_FMT = 0x7,
12257 MADD_S = 0x01,
12258 MADD_D = 0x09,
12259 MADD_PS = 0x11,
12260 ALNV_PS = 0x19,
12261 MSUB_S = 0x21,
12262 MSUB_D = 0x29,
12263 MSUB_PS = 0x31,
12265 NMADD_S = 0x02,
12266 NMADD_D = 0x0a,
12267 NMADD_PS = 0x12,
12268 NMSUB_S = 0x22,
12269 NMSUB_D = 0x2a,
12270 NMSUB_PS = 0x32,
12272 MIN_FMT = 0x3,
12273 MAX_FMT = 0xb,
12274 MINA_FMT = 0x23,
12275 MAXA_FMT = 0x2b,
12276 POOL32FXF = 0x3b,
12278 CABS_COND_FMT = 0x1c, /* MIPS3D */
12279 C_COND_FMT = 0x3c,
12281 CMP_CONDN_S = 0x5,
12282 CMP_CONDN_D = 0x15
12285 /* POOL32Fxf encoding of minor opcode extension field */
12287 enum {
12288 CVT_L = 0x04,
12289 RSQRT_FMT = 0x08,
12290 FLOOR_L = 0x0c,
12291 CVT_PW_PS = 0x1c,
12292 CVT_W = 0x24,
12293 SQRT_FMT = 0x28,
12294 FLOOR_W = 0x2c,
12295 CVT_PS_PW = 0x3c,
12296 CFC1 = 0x40,
12297 RECIP_FMT = 0x48,
12298 CEIL_L = 0x4c,
12299 CTC1 = 0x60,
12300 CEIL_W = 0x6c,
12301 MFC1 = 0x80,
12302 CVT_S_PL = 0x84,
12303 TRUNC_L = 0x8c,
12304 MTC1 = 0xa0,
12305 CVT_S_PU = 0xa4,
12306 TRUNC_W = 0xac,
12307 MFHC1 = 0xc0,
12308 ROUND_L = 0xcc,
12309 MTHC1 = 0xe0,
12310 ROUND_W = 0xec,
12312 MOV_FMT = 0x01,
12313 MOVF = 0x05,
12314 ABS_FMT = 0x0d,
12315 RSQRT1_FMT = 0x1d,
12316 MOVT = 0x25,
12317 NEG_FMT = 0x2d,
12318 CVT_D = 0x4d,
12319 RECIP1_FMT = 0x5d,
12320 CVT_S = 0x6d
12323 /* POOL32I encoding of minor opcode field (bits 25..21) */
12325 enum {
12326 BLTZ = 0x00,
12327 BLTZAL = 0x01,
12328 BGEZ = 0x02,
12329 BGEZAL = 0x03,
12330 BLEZ = 0x04,
12331 BNEZC = 0x05,
12332 BGTZ = 0x06,
12333 BEQZC = 0x07,
12334 TLTI = 0x08,
12335 BC1EQZC = 0x08,
12336 TGEI = 0x09,
12337 BC1NEZC = 0x09,
12338 TLTIU = 0x0a,
12339 BC2EQZC = 0x0a,
12340 TGEIU = 0x0b,
12341 BC2NEZC = 0x0a,
12342 TNEI = 0x0c,
12343 R6_SYNCI = 0x0c,
12344 LUI = 0x0d,
12345 TEQI = 0x0e,
12346 SYNCI = 0x10,
12347 BLTZALS = 0x11,
12348 BGEZALS = 0x13,
12349 BC2F = 0x14,
12350 BC2T = 0x15,
12351 BPOSGE64 = 0x1a,
12352 BPOSGE32 = 0x1b,
12353 /* These overlap and are distinguished by bit16 of the instruction */
12354 BC1F = 0x1c,
12355 BC1T = 0x1d,
12356 BC1ANY2F = 0x1c,
12357 BC1ANY2T = 0x1d,
12358 BC1ANY4F = 0x1e,
12359 BC1ANY4T = 0x1f
12362 /* POOL16A encoding of minor opcode field */
12364 enum {
12365 ADDU16 = 0x0,
12366 SUBU16 = 0x1
12369 /* POOL16B encoding of minor opcode field */
12371 enum {
12372 SLL16 = 0x0,
12373 SRL16 = 0x1
12376 /* POOL16C encoding of minor opcode field */
12378 enum {
12379 NOT16 = 0x00,
12380 XOR16 = 0x04,
12381 AND16 = 0x08,
12382 OR16 = 0x0c,
12383 LWM16 = 0x10,
12384 SWM16 = 0x14,
12385 JR16 = 0x18,
12386 JRC16 = 0x1a,
12387 JALR16 = 0x1c,
12388 JALR16S = 0x1e,
12389 MFHI16 = 0x20,
12390 MFLO16 = 0x24,
12391 BREAK16 = 0x28,
12392 SDBBP16 = 0x2c,
12393 JRADDIUSP = 0x30
12396 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
12398 enum {
12399 R6_NOT16 = 0x00,
12400 R6_AND16 = 0x01,
12401 R6_LWM16 = 0x02,
12402 R6_JRC16 = 0x03,
12403 MOVEP = 0x04,
12404 MOVEP_07 = 0x07,
12405 R6_XOR16 = 0x08,
12406 R6_OR16 = 0x09,
12407 R6_SWM16 = 0x0a,
12408 JALRC16 = 0x0b,
12409 MOVEP_0C = 0x0c,
12410 MOVEP_0F = 0x0f,
12411 JRCADDIUSP = 0x13,
12412 R6_BREAK16 = 0x1b,
12413 R6_SDBBP16 = 0x3b
12416 /* POOL16D encoding of minor opcode field */
12418 enum {
12419 ADDIUS5 = 0x0,
12420 ADDIUSP = 0x1
12423 /* POOL16E encoding of minor opcode field */
12425 enum {
12426 ADDIUR2 = 0x0,
12427 ADDIUR1SP = 0x1
12430 static int mmreg (int r)
12432 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12434 return map[r];
12437 /* Used for 16-bit store instructions. */
12438 static int mmreg2 (int r)
12440 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12442 return map[r];
12445 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12446 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12447 #define uMIPS_RS2(op) uMIPS_RS(op)
12448 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12449 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12450 #define uMIPS_RS5(op) (op & 0x1f)
12452 /* Signed immediate */
12453 #define SIMM(op, start, width) \
12454 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12455 << (32-width)) \
12456 >> (32-width))
12457 /* Zero-extended immediate */
12458 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12460 static void gen_addiur1sp(DisasContext *ctx)
12462 int rd = mmreg(uMIPS_RD(ctx->opcode));
12464 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12467 static void gen_addiur2(DisasContext *ctx)
12469 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12470 int rd = mmreg(uMIPS_RD(ctx->opcode));
12471 int rs = mmreg(uMIPS_RS(ctx->opcode));
12473 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12476 static void gen_addiusp(DisasContext *ctx)
12478 int encoded = ZIMM(ctx->opcode, 1, 9);
12479 int decoded;
12481 if (encoded <= 1) {
12482 decoded = 256 + encoded;
12483 } else if (encoded <= 255) {
12484 decoded = encoded;
12485 } else if (encoded <= 509) {
12486 decoded = encoded - 512;
12487 } else {
12488 decoded = encoded - 768;
12491 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
12494 static void gen_addius5(DisasContext *ctx)
12496 int imm = SIMM(ctx->opcode, 1, 4);
12497 int rd = (ctx->opcode >> 5) & 0x1f;
12499 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
12502 static void gen_andi16(DisasContext *ctx)
12504 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
12505 31, 32, 63, 64, 255, 32768, 65535 };
12506 int rd = mmreg(uMIPS_RD(ctx->opcode));
12507 int rs = mmreg(uMIPS_RS(ctx->opcode));
12508 int encoded = ZIMM(ctx->opcode, 0, 4);
12510 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
12513 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
12514 int base, int16_t offset)
12516 TCGv t0, t1;
12517 TCGv_i32 t2;
12519 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12520 generate_exception_end(ctx, EXCP_RI);
12521 return;
12524 t0 = tcg_temp_new();
12526 gen_base_offset_addr(ctx, t0, base, offset);
12528 t1 = tcg_const_tl(reglist);
12529 t2 = tcg_const_i32(ctx->mem_idx);
12531 save_cpu_state(ctx, 1);
12532 switch (opc) {
12533 case LWM32:
12534 gen_helper_lwm(cpu_env, t0, t1, t2);
12535 break;
12536 case SWM32:
12537 gen_helper_swm(cpu_env, t0, t1, t2);
12538 break;
12539 #ifdef TARGET_MIPS64
12540 case LDM:
12541 gen_helper_ldm(cpu_env, t0, t1, t2);
12542 break;
12543 case SDM:
12544 gen_helper_sdm(cpu_env, t0, t1, t2);
12545 break;
12546 #endif
12548 tcg_temp_free(t0);
12549 tcg_temp_free(t1);
12550 tcg_temp_free_i32(t2);
12554 static void gen_pool16c_insn(DisasContext *ctx)
12556 int rd = mmreg((ctx->opcode >> 3) & 0x7);
12557 int rs = mmreg(ctx->opcode & 0x7);
12559 switch (((ctx->opcode) >> 4) & 0x3f) {
12560 case NOT16 + 0:
12561 case NOT16 + 1:
12562 case NOT16 + 2:
12563 case NOT16 + 3:
12564 gen_logic(ctx, OPC_NOR, rd, rs, 0);
12565 break;
12566 case XOR16 + 0:
12567 case XOR16 + 1:
12568 case XOR16 + 2:
12569 case XOR16 + 3:
12570 gen_logic(ctx, OPC_XOR, rd, rd, rs);
12571 break;
12572 case AND16 + 0:
12573 case AND16 + 1:
12574 case AND16 + 2:
12575 case AND16 + 3:
12576 gen_logic(ctx, OPC_AND, rd, rd, rs);
12577 break;
12578 case OR16 + 0:
12579 case OR16 + 1:
12580 case OR16 + 2:
12581 case OR16 + 3:
12582 gen_logic(ctx, OPC_OR, rd, rd, rs);
12583 break;
12584 case LWM16 + 0:
12585 case LWM16 + 1:
12586 case LWM16 + 2:
12587 case LWM16 + 3:
12589 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12590 int offset = ZIMM(ctx->opcode, 0, 4);
12592 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
12593 29, offset << 2);
12595 break;
12596 case SWM16 + 0:
12597 case SWM16 + 1:
12598 case SWM16 + 2:
12599 case SWM16 + 3:
12601 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12602 int offset = ZIMM(ctx->opcode, 0, 4);
12604 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
12605 29, offset << 2);
12607 break;
12608 case JR16 + 0:
12609 case JR16 + 1:
12611 int reg = ctx->opcode & 0x1f;
12613 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
12615 break;
12616 case JRC16 + 0:
12617 case JRC16 + 1:
12619 int reg = ctx->opcode & 0x1f;
12620 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
12621 /* Let normal delay slot handling in our caller take us
12622 to the branch target. */
12624 break;
12625 case JALR16 + 0:
12626 case JALR16 + 1:
12627 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
12628 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12629 break;
12630 case JALR16S + 0:
12631 case JALR16S + 1:
12632 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
12633 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12634 break;
12635 case MFHI16 + 0:
12636 case MFHI16 + 1:
12637 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
12638 break;
12639 case MFLO16 + 0:
12640 case MFLO16 + 1:
12641 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
12642 break;
12643 case BREAK16:
12644 generate_exception_end(ctx, EXCP_BREAK);
12645 break;
12646 case SDBBP16:
12647 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
12648 gen_helper_do_semihosting(cpu_env);
12649 } else {
12650 /* XXX: not clear which exception should be raised
12651 * when in debug mode...
12653 check_insn(ctx, ISA_MIPS32);
12654 generate_exception_end(ctx, EXCP_DBp);
12656 break;
12657 case JRADDIUSP + 0:
12658 case JRADDIUSP + 1:
12660 int imm = ZIMM(ctx->opcode, 0, 5);
12661 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12662 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12663 /* Let normal delay slot handling in our caller take us
12664 to the branch target. */
12666 break;
12667 default:
12668 generate_exception_end(ctx, EXCP_RI);
12669 break;
12673 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
12674 int enc_rs)
12676 int rd, rs, re, rt;
12677 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
12678 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
12679 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
12680 rd = rd_enc[enc_dest];
12681 re = re_enc[enc_dest];
12682 rs = rs_rt_enc[enc_rs];
12683 rt = rs_rt_enc[enc_rt];
12684 if (rs) {
12685 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
12686 } else {
12687 tcg_gen_movi_tl(cpu_gpr[rd], 0);
12689 if (rt) {
12690 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
12691 } else {
12692 tcg_gen_movi_tl(cpu_gpr[re], 0);
12696 static void gen_pool16c_r6_insn(DisasContext *ctx)
12698 int rt = mmreg((ctx->opcode >> 7) & 0x7);
12699 int rs = mmreg((ctx->opcode >> 4) & 0x7);
12701 switch (ctx->opcode & 0xf) {
12702 case R6_NOT16:
12703 gen_logic(ctx, OPC_NOR, rt, rs, 0);
12704 break;
12705 case R6_AND16:
12706 gen_logic(ctx, OPC_AND, rt, rt, rs);
12707 break;
12708 case R6_LWM16:
12710 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
12711 int offset = extract32(ctx->opcode, 4, 4);
12712 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
12714 break;
12715 case R6_JRC16: /* JRCADDIUSP */
12716 if ((ctx->opcode >> 4) & 1) {
12717 /* JRCADDIUSP */
12718 int imm = extract32(ctx->opcode, 5, 5);
12719 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12720 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12721 } else {
12722 /* JRC16 */
12723 int rs = extract32(ctx->opcode, 5, 5);
12724 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
12726 break;
12727 case MOVEP ... MOVEP_07:
12728 case MOVEP_0C ... MOVEP_0F:
12730 int enc_dest = uMIPS_RD(ctx->opcode);
12731 int enc_rt = uMIPS_RS2(ctx->opcode);
12732 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
12733 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
12735 break;
12736 case R6_XOR16:
12737 gen_logic(ctx, OPC_XOR, rt, rt, rs);
12738 break;
12739 case R6_OR16:
12740 gen_logic(ctx, OPC_OR, rt, rt, rs);
12741 break;
12742 case R6_SWM16:
12744 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
12745 int offset = extract32(ctx->opcode, 4, 4);
12746 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
12748 break;
12749 case JALRC16: /* BREAK16, SDBBP16 */
12750 switch (ctx->opcode & 0x3f) {
12751 case JALRC16:
12752 case JALRC16 + 0x20:
12753 /* JALRC16 */
12754 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
12755 31, 0, 0);
12756 break;
12757 case R6_BREAK16:
12758 /* BREAK16 */
12759 generate_exception(ctx, EXCP_BREAK);
12760 break;
12761 case R6_SDBBP16:
12762 /* SDBBP16 */
12763 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
12764 gen_helper_do_semihosting(cpu_env);
12765 } else {
12766 if (ctx->hflags & MIPS_HFLAG_SBRI) {
12767 generate_exception(ctx, EXCP_RI);
12768 } else {
12769 generate_exception(ctx, EXCP_DBp);
12772 break;
12774 break;
12775 default:
12776 generate_exception(ctx, EXCP_RI);
12777 break;
12781 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
12783 TCGv t0 = tcg_temp_new();
12784 TCGv t1 = tcg_temp_new();
12786 gen_load_gpr(t0, base);
12788 if (index != 0) {
12789 gen_load_gpr(t1, index);
12790 tcg_gen_shli_tl(t1, t1, 2);
12791 gen_op_addr_add(ctx, t0, t1, t0);
12794 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12795 gen_store_gpr(t1, rd);
12797 tcg_temp_free(t0);
12798 tcg_temp_free(t1);
12801 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
12802 int base, int16_t offset)
12804 TCGv t0, t1;
12806 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
12807 generate_exception_end(ctx, EXCP_RI);
12808 return;
12811 t0 = tcg_temp_new();
12812 t1 = tcg_temp_new();
12814 gen_base_offset_addr(ctx, t0, base, offset);
12816 switch (opc) {
12817 case LWP:
12818 if (rd == base) {
12819 generate_exception_end(ctx, EXCP_RI);
12820 return;
12822 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12823 gen_store_gpr(t1, rd);
12824 tcg_gen_movi_tl(t1, 4);
12825 gen_op_addr_add(ctx, t0, t0, t1);
12826 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12827 gen_store_gpr(t1, rd+1);
12828 break;
12829 case SWP:
12830 gen_load_gpr(t1, rd);
12831 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12832 tcg_gen_movi_tl(t1, 4);
12833 gen_op_addr_add(ctx, t0, t0, t1);
12834 gen_load_gpr(t1, rd+1);
12835 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12836 break;
12837 #ifdef TARGET_MIPS64
12838 case LDP:
12839 if (rd == base) {
12840 generate_exception_end(ctx, EXCP_RI);
12841 return;
12843 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12844 gen_store_gpr(t1, rd);
12845 tcg_gen_movi_tl(t1, 8);
12846 gen_op_addr_add(ctx, t0, t0, t1);
12847 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12848 gen_store_gpr(t1, rd+1);
12849 break;
12850 case SDP:
12851 gen_load_gpr(t1, rd);
12852 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12853 tcg_gen_movi_tl(t1, 8);
12854 gen_op_addr_add(ctx, t0, t0, t1);
12855 gen_load_gpr(t1, rd+1);
12856 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12857 break;
12858 #endif
12860 tcg_temp_free(t0);
12861 tcg_temp_free(t1);
12864 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
12866 int extension = (ctx->opcode >> 6) & 0x3f;
12867 int minor = (ctx->opcode >> 12) & 0xf;
12868 uint32_t mips32_op;
12870 switch (extension) {
12871 case TEQ:
12872 mips32_op = OPC_TEQ;
12873 goto do_trap;
12874 case TGE:
12875 mips32_op = OPC_TGE;
12876 goto do_trap;
12877 case TGEU:
12878 mips32_op = OPC_TGEU;
12879 goto do_trap;
12880 case TLT:
12881 mips32_op = OPC_TLT;
12882 goto do_trap;
12883 case TLTU:
12884 mips32_op = OPC_TLTU;
12885 goto do_trap;
12886 case TNE:
12887 mips32_op = OPC_TNE;
12888 do_trap:
12889 gen_trap(ctx, mips32_op, rs, rt, -1);
12890 break;
12891 #ifndef CONFIG_USER_ONLY
12892 case MFC0:
12893 case MFC0 + 32:
12894 check_cp0_enabled(ctx);
12895 if (rt == 0) {
12896 /* Treat as NOP. */
12897 break;
12899 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
12900 break;
12901 case MTC0:
12902 case MTC0 + 32:
12903 check_cp0_enabled(ctx);
12905 TCGv t0 = tcg_temp_new();
12907 gen_load_gpr(t0, rt);
12908 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
12909 tcg_temp_free(t0);
12911 break;
12912 #endif
12913 case 0x2a:
12914 switch (minor & 3) {
12915 case MADD_ACC:
12916 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
12917 break;
12918 case MADDU_ACC:
12919 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
12920 break;
12921 case MSUB_ACC:
12922 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
12923 break;
12924 case MSUBU_ACC:
12925 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
12926 break;
12927 default:
12928 goto pool32axf_invalid;
12930 break;
12931 case 0x32:
12932 switch (minor & 3) {
12933 case MULT_ACC:
12934 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
12935 break;
12936 case MULTU_ACC:
12937 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
12938 break;
12939 default:
12940 goto pool32axf_invalid;
12942 break;
12943 case 0x2c:
12944 switch (minor) {
12945 case BITSWAP:
12946 check_insn(ctx, ISA_MIPS32R6);
12947 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
12948 break;
12949 case SEB:
12950 gen_bshfl(ctx, OPC_SEB, rs, rt);
12951 break;
12952 case SEH:
12953 gen_bshfl(ctx, OPC_SEH, rs, rt);
12954 break;
12955 case CLO:
12956 mips32_op = OPC_CLO;
12957 goto do_cl;
12958 case CLZ:
12959 mips32_op = OPC_CLZ;
12960 do_cl:
12961 check_insn(ctx, ISA_MIPS32);
12962 gen_cl(ctx, mips32_op, rt, rs);
12963 break;
12964 case RDHWR:
12965 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12966 gen_rdhwr(ctx, rt, rs, 0);
12967 break;
12968 case WSBH:
12969 gen_bshfl(ctx, OPC_WSBH, rs, rt);
12970 break;
12971 case MULT:
12972 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12973 mips32_op = OPC_MULT;
12974 goto do_mul;
12975 case MULTU:
12976 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12977 mips32_op = OPC_MULTU;
12978 goto do_mul;
12979 case DIV:
12980 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12981 mips32_op = OPC_DIV;
12982 goto do_div;
12983 case DIVU:
12984 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12985 mips32_op = OPC_DIVU;
12986 goto do_div;
12987 do_div:
12988 check_insn(ctx, ISA_MIPS32);
12989 gen_muldiv(ctx, mips32_op, 0, rs, rt);
12990 break;
12991 case MADD:
12992 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12993 mips32_op = OPC_MADD;
12994 goto do_mul;
12995 case MADDU:
12996 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12997 mips32_op = OPC_MADDU;
12998 goto do_mul;
12999 case MSUB:
13000 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13001 mips32_op = OPC_MSUB;
13002 goto do_mul;
13003 case MSUBU:
13004 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13005 mips32_op = OPC_MSUBU;
13006 do_mul:
13007 check_insn(ctx, ISA_MIPS32);
13008 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13009 break;
13010 default:
13011 goto pool32axf_invalid;
13013 break;
13014 case 0x34:
13015 switch (minor) {
13016 case MFC2:
13017 case MTC2:
13018 case MFHC2:
13019 case MTHC2:
13020 case CFC2:
13021 case CTC2:
13022 generate_exception_err(ctx, EXCP_CpU, 2);
13023 break;
13024 default:
13025 goto pool32axf_invalid;
13027 break;
13028 case 0x3c:
13029 switch (minor) {
13030 case JALR: /* JALRC */
13031 case JALR_HB: /* JALRC_HB */
13032 if (ctx->insn_flags & ISA_MIPS32R6) {
13033 /* JALRC, JALRC_HB */
13034 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13035 } else {
13036 /* JALR, JALR_HB */
13037 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13038 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13040 break;
13041 case JALRS:
13042 case JALRS_HB:
13043 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13044 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13045 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13046 break;
13047 default:
13048 goto pool32axf_invalid;
13050 break;
13051 case 0x05:
13052 switch (minor) {
13053 case RDPGPR:
13054 check_cp0_enabled(ctx);
13055 check_insn(ctx, ISA_MIPS32R2);
13056 gen_load_srsgpr(rs, rt);
13057 break;
13058 case WRPGPR:
13059 check_cp0_enabled(ctx);
13060 check_insn(ctx, ISA_MIPS32R2);
13061 gen_store_srsgpr(rs, rt);
13062 break;
13063 default:
13064 goto pool32axf_invalid;
13066 break;
13067 #ifndef CONFIG_USER_ONLY
13068 case 0x0d:
13069 switch (minor) {
13070 case TLBP:
13071 mips32_op = OPC_TLBP;
13072 goto do_cp0;
13073 case TLBR:
13074 mips32_op = OPC_TLBR;
13075 goto do_cp0;
13076 case TLBWI:
13077 mips32_op = OPC_TLBWI;
13078 goto do_cp0;
13079 case TLBWR:
13080 mips32_op = OPC_TLBWR;
13081 goto do_cp0;
13082 case TLBINV:
13083 mips32_op = OPC_TLBINV;
13084 goto do_cp0;
13085 case TLBINVF:
13086 mips32_op = OPC_TLBINVF;
13087 goto do_cp0;
13088 case WAIT:
13089 mips32_op = OPC_WAIT;
13090 goto do_cp0;
13091 case DERET:
13092 mips32_op = OPC_DERET;
13093 goto do_cp0;
13094 case ERET:
13095 mips32_op = OPC_ERET;
13096 do_cp0:
13097 gen_cp0(env, ctx, mips32_op, rt, rs);
13098 break;
13099 default:
13100 goto pool32axf_invalid;
13102 break;
13103 case 0x1d:
13104 switch (minor) {
13105 case DI:
13106 check_cp0_enabled(ctx);
13108 TCGv t0 = tcg_temp_new();
13110 save_cpu_state(ctx, 1);
13111 gen_helper_di(t0, cpu_env);
13112 gen_store_gpr(t0, rs);
13113 /* Stop translation as we may have switched the execution mode */
13114 ctx->bstate = BS_STOP;
13115 tcg_temp_free(t0);
13117 break;
13118 case EI:
13119 check_cp0_enabled(ctx);
13121 TCGv t0 = tcg_temp_new();
13123 save_cpu_state(ctx, 1);
13124 gen_helper_ei(t0, cpu_env);
13125 gen_store_gpr(t0, rs);
13126 /* Stop translation as we may have switched the execution mode */
13127 ctx->bstate = BS_STOP;
13128 tcg_temp_free(t0);
13130 break;
13131 default:
13132 goto pool32axf_invalid;
13134 break;
13135 #endif
13136 case 0x2d:
13137 switch (minor) {
13138 case SYNC:
13139 /* NOP */
13140 break;
13141 case SYSCALL:
13142 generate_exception_end(ctx, EXCP_SYSCALL);
13143 break;
13144 case SDBBP:
13145 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
13146 gen_helper_do_semihosting(cpu_env);
13147 } else {
13148 check_insn(ctx, ISA_MIPS32);
13149 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13150 generate_exception_end(ctx, EXCP_RI);
13151 } else {
13152 generate_exception_end(ctx, EXCP_DBp);
13155 break;
13156 default:
13157 goto pool32axf_invalid;
13159 break;
13160 case 0x01:
13161 switch (minor & 3) {
13162 case MFHI_ACC:
13163 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
13164 break;
13165 case MFLO_ACC:
13166 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
13167 break;
13168 case MTHI_ACC:
13169 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
13170 break;
13171 case MTLO_ACC:
13172 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
13173 break;
13174 default:
13175 goto pool32axf_invalid;
13177 break;
13178 case 0x35:
13179 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13180 switch (minor) {
13181 case MFHI32:
13182 gen_HILO(ctx, OPC_MFHI, 0, rs);
13183 break;
13184 case MFLO32:
13185 gen_HILO(ctx, OPC_MFLO, 0, rs);
13186 break;
13187 case MTHI32:
13188 gen_HILO(ctx, OPC_MTHI, 0, rs);
13189 break;
13190 case MTLO32:
13191 gen_HILO(ctx, OPC_MTLO, 0, rs);
13192 break;
13193 default:
13194 goto pool32axf_invalid;
13196 break;
13197 default:
13198 pool32axf_invalid:
13199 MIPS_INVAL("pool32axf");
13200 generate_exception_end(ctx, EXCP_RI);
13201 break;
13205 /* Values for microMIPS fmt field. Variable-width, depending on which
13206 formats the instruction supports. */
13208 enum {
13209 FMT_SD_S = 0,
13210 FMT_SD_D = 1,
13212 FMT_SDPS_S = 0,
13213 FMT_SDPS_D = 1,
13214 FMT_SDPS_PS = 2,
13216 FMT_SWL_S = 0,
13217 FMT_SWL_W = 1,
13218 FMT_SWL_L = 2,
13220 FMT_DWL_D = 0,
13221 FMT_DWL_W = 1,
13222 FMT_DWL_L = 2
13225 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
13227 int extension = (ctx->opcode >> 6) & 0x3ff;
13228 uint32_t mips32_op;
13230 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
13231 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
13232 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
13234 switch (extension) {
13235 case FLOAT_1BIT_FMT(CFC1, 0):
13236 mips32_op = OPC_CFC1;
13237 goto do_cp1;
13238 case FLOAT_1BIT_FMT(CTC1, 0):
13239 mips32_op = OPC_CTC1;
13240 goto do_cp1;
13241 case FLOAT_1BIT_FMT(MFC1, 0):
13242 mips32_op = OPC_MFC1;
13243 goto do_cp1;
13244 case FLOAT_1BIT_FMT(MTC1, 0):
13245 mips32_op = OPC_MTC1;
13246 goto do_cp1;
13247 case FLOAT_1BIT_FMT(MFHC1, 0):
13248 mips32_op = OPC_MFHC1;
13249 goto do_cp1;
13250 case FLOAT_1BIT_FMT(MTHC1, 0):
13251 mips32_op = OPC_MTHC1;
13252 do_cp1:
13253 gen_cp1(ctx, mips32_op, rt, rs);
13254 break;
13256 /* Reciprocal square root */
13257 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
13258 mips32_op = OPC_RSQRT_S;
13259 goto do_unaryfp;
13260 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
13261 mips32_op = OPC_RSQRT_D;
13262 goto do_unaryfp;
13264 /* Square root */
13265 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
13266 mips32_op = OPC_SQRT_S;
13267 goto do_unaryfp;
13268 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
13269 mips32_op = OPC_SQRT_D;
13270 goto do_unaryfp;
13272 /* Reciprocal */
13273 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
13274 mips32_op = OPC_RECIP_S;
13275 goto do_unaryfp;
13276 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
13277 mips32_op = OPC_RECIP_D;
13278 goto do_unaryfp;
13280 /* Floor */
13281 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
13282 mips32_op = OPC_FLOOR_L_S;
13283 goto do_unaryfp;
13284 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
13285 mips32_op = OPC_FLOOR_L_D;
13286 goto do_unaryfp;
13287 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
13288 mips32_op = OPC_FLOOR_W_S;
13289 goto do_unaryfp;
13290 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
13291 mips32_op = OPC_FLOOR_W_D;
13292 goto do_unaryfp;
13294 /* Ceiling */
13295 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
13296 mips32_op = OPC_CEIL_L_S;
13297 goto do_unaryfp;
13298 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
13299 mips32_op = OPC_CEIL_L_D;
13300 goto do_unaryfp;
13301 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
13302 mips32_op = OPC_CEIL_W_S;
13303 goto do_unaryfp;
13304 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
13305 mips32_op = OPC_CEIL_W_D;
13306 goto do_unaryfp;
13308 /* Truncation */
13309 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
13310 mips32_op = OPC_TRUNC_L_S;
13311 goto do_unaryfp;
13312 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
13313 mips32_op = OPC_TRUNC_L_D;
13314 goto do_unaryfp;
13315 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
13316 mips32_op = OPC_TRUNC_W_S;
13317 goto do_unaryfp;
13318 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
13319 mips32_op = OPC_TRUNC_W_D;
13320 goto do_unaryfp;
13322 /* Round */
13323 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
13324 mips32_op = OPC_ROUND_L_S;
13325 goto do_unaryfp;
13326 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
13327 mips32_op = OPC_ROUND_L_D;
13328 goto do_unaryfp;
13329 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
13330 mips32_op = OPC_ROUND_W_S;
13331 goto do_unaryfp;
13332 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
13333 mips32_op = OPC_ROUND_W_D;
13334 goto do_unaryfp;
13336 /* Integer to floating-point conversion */
13337 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
13338 mips32_op = OPC_CVT_L_S;
13339 goto do_unaryfp;
13340 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
13341 mips32_op = OPC_CVT_L_D;
13342 goto do_unaryfp;
13343 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
13344 mips32_op = OPC_CVT_W_S;
13345 goto do_unaryfp;
13346 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
13347 mips32_op = OPC_CVT_W_D;
13348 goto do_unaryfp;
13350 /* Paired-foo conversions */
13351 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
13352 mips32_op = OPC_CVT_S_PL;
13353 goto do_unaryfp;
13354 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
13355 mips32_op = OPC_CVT_S_PU;
13356 goto do_unaryfp;
13357 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
13358 mips32_op = OPC_CVT_PW_PS;
13359 goto do_unaryfp;
13360 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
13361 mips32_op = OPC_CVT_PS_PW;
13362 goto do_unaryfp;
13364 /* Floating-point moves */
13365 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
13366 mips32_op = OPC_MOV_S;
13367 goto do_unaryfp;
13368 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
13369 mips32_op = OPC_MOV_D;
13370 goto do_unaryfp;
13371 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
13372 mips32_op = OPC_MOV_PS;
13373 goto do_unaryfp;
13375 /* Absolute value */
13376 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
13377 mips32_op = OPC_ABS_S;
13378 goto do_unaryfp;
13379 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
13380 mips32_op = OPC_ABS_D;
13381 goto do_unaryfp;
13382 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
13383 mips32_op = OPC_ABS_PS;
13384 goto do_unaryfp;
13386 /* Negation */
13387 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
13388 mips32_op = OPC_NEG_S;
13389 goto do_unaryfp;
13390 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
13391 mips32_op = OPC_NEG_D;
13392 goto do_unaryfp;
13393 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
13394 mips32_op = OPC_NEG_PS;
13395 goto do_unaryfp;
13397 /* Reciprocal square root step */
13398 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
13399 mips32_op = OPC_RSQRT1_S;
13400 goto do_unaryfp;
13401 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
13402 mips32_op = OPC_RSQRT1_D;
13403 goto do_unaryfp;
13404 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
13405 mips32_op = OPC_RSQRT1_PS;
13406 goto do_unaryfp;
13408 /* Reciprocal step */
13409 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
13410 mips32_op = OPC_RECIP1_S;
13411 goto do_unaryfp;
13412 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
13413 mips32_op = OPC_RECIP1_S;
13414 goto do_unaryfp;
13415 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13416 mips32_op = OPC_RECIP1_PS;
13417 goto do_unaryfp;
13419 /* Conversions from double */
13420 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13421 mips32_op = OPC_CVT_D_S;
13422 goto do_unaryfp;
13423 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13424 mips32_op = OPC_CVT_D_W;
13425 goto do_unaryfp;
13426 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13427 mips32_op = OPC_CVT_D_L;
13428 goto do_unaryfp;
13430 /* Conversions from single */
13431 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13432 mips32_op = OPC_CVT_S_D;
13433 goto do_unaryfp;
13434 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13435 mips32_op = OPC_CVT_S_W;
13436 goto do_unaryfp;
13437 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13438 mips32_op = OPC_CVT_S_L;
13439 do_unaryfp:
13440 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13441 break;
13443 /* Conditional moves on floating-point codes */
13444 case COND_FLOAT_MOV(MOVT, 0):
13445 case COND_FLOAT_MOV(MOVT, 1):
13446 case COND_FLOAT_MOV(MOVT, 2):
13447 case COND_FLOAT_MOV(MOVT, 3):
13448 case COND_FLOAT_MOV(MOVT, 4):
13449 case COND_FLOAT_MOV(MOVT, 5):
13450 case COND_FLOAT_MOV(MOVT, 6):
13451 case COND_FLOAT_MOV(MOVT, 7):
13452 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13453 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13454 break;
13455 case COND_FLOAT_MOV(MOVF, 0):
13456 case COND_FLOAT_MOV(MOVF, 1):
13457 case COND_FLOAT_MOV(MOVF, 2):
13458 case COND_FLOAT_MOV(MOVF, 3):
13459 case COND_FLOAT_MOV(MOVF, 4):
13460 case COND_FLOAT_MOV(MOVF, 5):
13461 case COND_FLOAT_MOV(MOVF, 6):
13462 case COND_FLOAT_MOV(MOVF, 7):
13463 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13464 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13465 break;
13466 default:
13467 MIPS_INVAL("pool32fxf");
13468 generate_exception_end(ctx, EXCP_RI);
13469 break;
13473 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
13475 int32_t offset;
13476 uint16_t insn;
13477 int rt, rs, rd, rr;
13478 int16_t imm;
13479 uint32_t op, minor, mips32_op;
13480 uint32_t cond, fmt, cc;
13482 insn = cpu_lduw_code(env, ctx->pc + 2);
13483 ctx->opcode = (ctx->opcode << 16) | insn;
13485 rt = (ctx->opcode >> 21) & 0x1f;
13486 rs = (ctx->opcode >> 16) & 0x1f;
13487 rd = (ctx->opcode >> 11) & 0x1f;
13488 rr = (ctx->opcode >> 6) & 0x1f;
13489 imm = (int16_t) ctx->opcode;
13491 op = (ctx->opcode >> 26) & 0x3f;
13492 switch (op) {
13493 case POOL32A:
13494 minor = ctx->opcode & 0x3f;
13495 switch (minor) {
13496 case 0x00:
13497 minor = (ctx->opcode >> 6) & 0xf;
13498 switch (minor) {
13499 case SLL32:
13500 mips32_op = OPC_SLL;
13501 goto do_shifti;
13502 case SRA:
13503 mips32_op = OPC_SRA;
13504 goto do_shifti;
13505 case SRL32:
13506 mips32_op = OPC_SRL;
13507 goto do_shifti;
13508 case ROTR:
13509 mips32_op = OPC_ROTR;
13510 do_shifti:
13511 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
13512 break;
13513 case SELEQZ:
13514 check_insn(ctx, ISA_MIPS32R6);
13515 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
13516 break;
13517 case SELNEZ:
13518 check_insn(ctx, ISA_MIPS32R6);
13519 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
13520 break;
13521 case R6_RDHWR:
13522 check_insn(ctx, ISA_MIPS32R6);
13523 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
13524 break;
13525 default:
13526 goto pool32a_invalid;
13528 break;
13529 case 0x10:
13530 minor = (ctx->opcode >> 6) & 0xf;
13531 switch (minor) {
13532 /* Arithmetic */
13533 case ADD:
13534 mips32_op = OPC_ADD;
13535 goto do_arith;
13536 case ADDU32:
13537 mips32_op = OPC_ADDU;
13538 goto do_arith;
13539 case SUB:
13540 mips32_op = OPC_SUB;
13541 goto do_arith;
13542 case SUBU32:
13543 mips32_op = OPC_SUBU;
13544 goto do_arith;
13545 case MUL:
13546 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13547 mips32_op = OPC_MUL;
13548 do_arith:
13549 gen_arith(ctx, mips32_op, rd, rs, rt);
13550 break;
13551 /* Shifts */
13552 case SLLV:
13553 mips32_op = OPC_SLLV;
13554 goto do_shift;
13555 case SRLV:
13556 mips32_op = OPC_SRLV;
13557 goto do_shift;
13558 case SRAV:
13559 mips32_op = OPC_SRAV;
13560 goto do_shift;
13561 case ROTRV:
13562 mips32_op = OPC_ROTRV;
13563 do_shift:
13564 gen_shift(ctx, mips32_op, rd, rs, rt);
13565 break;
13566 /* Logical operations */
13567 case AND:
13568 mips32_op = OPC_AND;
13569 goto do_logic;
13570 case OR32:
13571 mips32_op = OPC_OR;
13572 goto do_logic;
13573 case NOR:
13574 mips32_op = OPC_NOR;
13575 goto do_logic;
13576 case XOR32:
13577 mips32_op = OPC_XOR;
13578 do_logic:
13579 gen_logic(ctx, mips32_op, rd, rs, rt);
13580 break;
13581 /* Set less than */
13582 case SLT:
13583 mips32_op = OPC_SLT;
13584 goto do_slt;
13585 case SLTU:
13586 mips32_op = OPC_SLTU;
13587 do_slt:
13588 gen_slt(ctx, mips32_op, rd, rs, rt);
13589 break;
13590 default:
13591 goto pool32a_invalid;
13593 break;
13594 case 0x18:
13595 minor = (ctx->opcode >> 6) & 0xf;
13596 switch (minor) {
13597 /* Conditional moves */
13598 case MOVN: /* MUL */
13599 if (ctx->insn_flags & ISA_MIPS32R6) {
13600 /* MUL */
13601 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
13602 } else {
13603 /* MOVN */
13604 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
13606 break;
13607 case MOVZ: /* MUH */
13608 if (ctx->insn_flags & ISA_MIPS32R6) {
13609 /* MUH */
13610 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
13611 } else {
13612 /* MOVZ */
13613 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
13615 break;
13616 case MULU:
13617 check_insn(ctx, ISA_MIPS32R6);
13618 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
13619 break;
13620 case MUHU:
13621 check_insn(ctx, ISA_MIPS32R6);
13622 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
13623 break;
13624 case LWXS: /* DIV */
13625 if (ctx->insn_flags & ISA_MIPS32R6) {
13626 /* DIV */
13627 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
13628 } else {
13629 /* LWXS */
13630 gen_ldxs(ctx, rs, rt, rd);
13632 break;
13633 case MOD:
13634 check_insn(ctx, ISA_MIPS32R6);
13635 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
13636 break;
13637 case R6_DIVU:
13638 check_insn(ctx, ISA_MIPS32R6);
13639 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
13640 break;
13641 case MODU:
13642 check_insn(ctx, ISA_MIPS32R6);
13643 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
13644 break;
13645 default:
13646 goto pool32a_invalid;
13648 break;
13649 case INS:
13650 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
13651 return;
13652 case LSA:
13653 check_insn(ctx, ISA_MIPS32R6);
13654 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
13655 extract32(ctx->opcode, 9, 2));
13656 break;
13657 case ALIGN:
13658 check_insn(ctx, ISA_MIPS32R6);
13659 gen_align(ctx, OPC_ALIGN, rd, rs, rt,
13660 extract32(ctx->opcode, 9, 2));
13661 break;
13662 case EXT:
13663 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
13664 return;
13665 case POOL32AXF:
13666 gen_pool32axf(env, ctx, rt, rs);
13667 break;
13668 case BREAK32:
13669 generate_exception_end(ctx, EXCP_BREAK);
13670 break;
13671 case SIGRIE:
13672 check_insn(ctx, ISA_MIPS32R6);
13673 generate_exception_end(ctx, EXCP_RI);
13674 break;
13675 default:
13676 pool32a_invalid:
13677 MIPS_INVAL("pool32a");
13678 generate_exception_end(ctx, EXCP_RI);
13679 break;
13681 break;
13682 case POOL32B:
13683 minor = (ctx->opcode >> 12) & 0xf;
13684 switch (minor) {
13685 case CACHE:
13686 check_cp0_enabled(ctx);
13687 /* Treat as no-op. */
13688 break;
13689 case LWC2:
13690 case SWC2:
13691 /* COP2: Not implemented. */
13692 generate_exception_err(ctx, EXCP_CpU, 2);
13693 break;
13694 #ifdef TARGET_MIPS64
13695 case LDP:
13696 case SDP:
13697 check_insn(ctx, ISA_MIPS3);
13698 check_mips_64(ctx);
13699 /* Fallthrough */
13700 #endif
13701 case LWP:
13702 case SWP:
13703 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13704 break;
13705 #ifdef TARGET_MIPS64
13706 case LDM:
13707 case SDM:
13708 check_insn(ctx, ISA_MIPS3);
13709 check_mips_64(ctx);
13710 /* Fallthrough */
13711 #endif
13712 case LWM32:
13713 case SWM32:
13714 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13715 break;
13716 default:
13717 MIPS_INVAL("pool32b");
13718 generate_exception_end(ctx, EXCP_RI);
13719 break;
13721 break;
13722 case POOL32F:
13723 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
13724 minor = ctx->opcode & 0x3f;
13725 check_cp1_enabled(ctx);
13726 switch (minor) {
13727 case ALNV_PS:
13728 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13729 mips32_op = OPC_ALNV_PS;
13730 goto do_madd;
13731 case MADD_S:
13732 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13733 mips32_op = OPC_MADD_S;
13734 goto do_madd;
13735 case MADD_D:
13736 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13737 mips32_op = OPC_MADD_D;
13738 goto do_madd;
13739 case MADD_PS:
13740 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13741 mips32_op = OPC_MADD_PS;
13742 goto do_madd;
13743 case MSUB_S:
13744 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13745 mips32_op = OPC_MSUB_S;
13746 goto do_madd;
13747 case MSUB_D:
13748 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13749 mips32_op = OPC_MSUB_D;
13750 goto do_madd;
13751 case MSUB_PS:
13752 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13753 mips32_op = OPC_MSUB_PS;
13754 goto do_madd;
13755 case NMADD_S:
13756 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13757 mips32_op = OPC_NMADD_S;
13758 goto do_madd;
13759 case NMADD_D:
13760 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13761 mips32_op = OPC_NMADD_D;
13762 goto do_madd;
13763 case NMADD_PS:
13764 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13765 mips32_op = OPC_NMADD_PS;
13766 goto do_madd;
13767 case NMSUB_S:
13768 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13769 mips32_op = OPC_NMSUB_S;
13770 goto do_madd;
13771 case NMSUB_D:
13772 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13773 mips32_op = OPC_NMSUB_D;
13774 goto do_madd;
13775 case NMSUB_PS:
13776 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13777 mips32_op = OPC_NMSUB_PS;
13778 do_madd:
13779 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
13780 break;
13781 case CABS_COND_FMT:
13782 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13783 cond = (ctx->opcode >> 6) & 0xf;
13784 cc = (ctx->opcode >> 13) & 0x7;
13785 fmt = (ctx->opcode >> 10) & 0x3;
13786 switch (fmt) {
13787 case 0x0:
13788 gen_cmpabs_s(ctx, cond, rt, rs, cc);
13789 break;
13790 case 0x1:
13791 gen_cmpabs_d(ctx, cond, rt, rs, cc);
13792 break;
13793 case 0x2:
13794 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
13795 break;
13796 default:
13797 goto pool32f_invalid;
13799 break;
13800 case C_COND_FMT:
13801 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13802 cond = (ctx->opcode >> 6) & 0xf;
13803 cc = (ctx->opcode >> 13) & 0x7;
13804 fmt = (ctx->opcode >> 10) & 0x3;
13805 switch (fmt) {
13806 case 0x0:
13807 gen_cmp_s(ctx, cond, rt, rs, cc);
13808 break;
13809 case 0x1:
13810 gen_cmp_d(ctx, cond, rt, rs, cc);
13811 break;
13812 case 0x2:
13813 gen_cmp_ps(ctx, cond, rt, rs, cc);
13814 break;
13815 default:
13816 goto pool32f_invalid;
13818 break;
13819 case CMP_CONDN_S:
13820 check_insn(ctx, ISA_MIPS32R6);
13821 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
13822 break;
13823 case CMP_CONDN_D:
13824 check_insn(ctx, ISA_MIPS32R6);
13825 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
13826 break;
13827 case POOL32FXF:
13828 gen_pool32fxf(ctx, rt, rs);
13829 break;
13830 case 0x00:
13831 /* PLL foo */
13832 switch ((ctx->opcode >> 6) & 0x7) {
13833 case PLL_PS:
13834 mips32_op = OPC_PLL_PS;
13835 goto do_ps;
13836 case PLU_PS:
13837 mips32_op = OPC_PLU_PS;
13838 goto do_ps;
13839 case PUL_PS:
13840 mips32_op = OPC_PUL_PS;
13841 goto do_ps;
13842 case PUU_PS:
13843 mips32_op = OPC_PUU_PS;
13844 goto do_ps;
13845 case CVT_PS_S:
13846 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13847 mips32_op = OPC_CVT_PS_S;
13848 do_ps:
13849 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13850 break;
13851 default:
13852 goto pool32f_invalid;
13854 break;
13855 case MIN_FMT:
13856 check_insn(ctx, ISA_MIPS32R6);
13857 switch ((ctx->opcode >> 9) & 0x3) {
13858 case FMT_SDPS_S:
13859 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
13860 break;
13861 case FMT_SDPS_D:
13862 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
13863 break;
13864 default:
13865 goto pool32f_invalid;
13867 break;
13868 case 0x08:
13869 /* [LS][WDU]XC1 */
13870 switch ((ctx->opcode >> 6) & 0x7) {
13871 case LWXC1:
13872 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13873 mips32_op = OPC_LWXC1;
13874 goto do_ldst_cp1;
13875 case SWXC1:
13876 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13877 mips32_op = OPC_SWXC1;
13878 goto do_ldst_cp1;
13879 case LDXC1:
13880 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13881 mips32_op = OPC_LDXC1;
13882 goto do_ldst_cp1;
13883 case SDXC1:
13884 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13885 mips32_op = OPC_SDXC1;
13886 goto do_ldst_cp1;
13887 case LUXC1:
13888 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13889 mips32_op = OPC_LUXC1;
13890 goto do_ldst_cp1;
13891 case SUXC1:
13892 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13893 mips32_op = OPC_SUXC1;
13894 do_ldst_cp1:
13895 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
13896 break;
13897 default:
13898 goto pool32f_invalid;
13900 break;
13901 case MAX_FMT:
13902 check_insn(ctx, ISA_MIPS32R6);
13903 switch ((ctx->opcode >> 9) & 0x3) {
13904 case FMT_SDPS_S:
13905 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
13906 break;
13907 case FMT_SDPS_D:
13908 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
13909 break;
13910 default:
13911 goto pool32f_invalid;
13913 break;
13914 case 0x18:
13915 /* 3D insns */
13916 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13917 fmt = (ctx->opcode >> 9) & 0x3;
13918 switch ((ctx->opcode >> 6) & 0x7) {
13919 case RSQRT2_FMT:
13920 switch (fmt) {
13921 case FMT_SDPS_S:
13922 mips32_op = OPC_RSQRT2_S;
13923 goto do_3d;
13924 case FMT_SDPS_D:
13925 mips32_op = OPC_RSQRT2_D;
13926 goto do_3d;
13927 case FMT_SDPS_PS:
13928 mips32_op = OPC_RSQRT2_PS;
13929 goto do_3d;
13930 default:
13931 goto pool32f_invalid;
13933 break;
13934 case RECIP2_FMT:
13935 switch (fmt) {
13936 case FMT_SDPS_S:
13937 mips32_op = OPC_RECIP2_S;
13938 goto do_3d;
13939 case FMT_SDPS_D:
13940 mips32_op = OPC_RECIP2_D;
13941 goto do_3d;
13942 case FMT_SDPS_PS:
13943 mips32_op = OPC_RECIP2_PS;
13944 goto do_3d;
13945 default:
13946 goto pool32f_invalid;
13948 break;
13949 case ADDR_PS:
13950 mips32_op = OPC_ADDR_PS;
13951 goto do_3d;
13952 case MULR_PS:
13953 mips32_op = OPC_MULR_PS;
13954 do_3d:
13955 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13956 break;
13957 default:
13958 goto pool32f_invalid;
13960 break;
13961 case 0x20:
13962 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
13963 cc = (ctx->opcode >> 13) & 0x7;
13964 fmt = (ctx->opcode >> 9) & 0x3;
13965 switch ((ctx->opcode >> 6) & 0x7) {
13966 case MOVF_FMT: /* RINT_FMT */
13967 if (ctx->insn_flags & ISA_MIPS32R6) {
13968 /* RINT_FMT */
13969 switch (fmt) {
13970 case FMT_SDPS_S:
13971 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
13972 break;
13973 case FMT_SDPS_D:
13974 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
13975 break;
13976 default:
13977 goto pool32f_invalid;
13979 } else {
13980 /* MOVF_FMT */
13981 switch (fmt) {
13982 case FMT_SDPS_S:
13983 gen_movcf_s(ctx, rs, rt, cc, 0);
13984 break;
13985 case FMT_SDPS_D:
13986 gen_movcf_d(ctx, rs, rt, cc, 0);
13987 break;
13988 case FMT_SDPS_PS:
13989 check_ps(ctx);
13990 gen_movcf_ps(ctx, rs, rt, cc, 0);
13991 break;
13992 default:
13993 goto pool32f_invalid;
13996 break;
13997 case MOVT_FMT: /* CLASS_FMT */
13998 if (ctx->insn_flags & ISA_MIPS32R6) {
13999 /* CLASS_FMT */
14000 switch (fmt) {
14001 case FMT_SDPS_S:
14002 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14003 break;
14004 case FMT_SDPS_D:
14005 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14006 break;
14007 default:
14008 goto pool32f_invalid;
14010 } else {
14011 /* MOVT_FMT */
14012 switch (fmt) {
14013 case FMT_SDPS_S:
14014 gen_movcf_s(ctx, rs, rt, cc, 1);
14015 break;
14016 case FMT_SDPS_D:
14017 gen_movcf_d(ctx, rs, rt, cc, 1);
14018 break;
14019 case FMT_SDPS_PS:
14020 check_ps(ctx);
14021 gen_movcf_ps(ctx, rs, rt, cc, 1);
14022 break;
14023 default:
14024 goto pool32f_invalid;
14027 break;
14028 case PREFX:
14029 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14030 break;
14031 default:
14032 goto pool32f_invalid;
14034 break;
14035 #define FINSN_3ARG_SDPS(prfx) \
14036 switch ((ctx->opcode >> 8) & 0x3) { \
14037 case FMT_SDPS_S: \
14038 mips32_op = OPC_##prfx##_S; \
14039 goto do_fpop; \
14040 case FMT_SDPS_D: \
14041 mips32_op = OPC_##prfx##_D; \
14042 goto do_fpop; \
14043 case FMT_SDPS_PS: \
14044 check_ps(ctx); \
14045 mips32_op = OPC_##prfx##_PS; \
14046 goto do_fpop; \
14047 default: \
14048 goto pool32f_invalid; \
14050 case MINA_FMT:
14051 check_insn(ctx, ISA_MIPS32R6);
14052 switch ((ctx->opcode >> 9) & 0x3) {
14053 case FMT_SDPS_S:
14054 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14055 break;
14056 case FMT_SDPS_D:
14057 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14058 break;
14059 default:
14060 goto pool32f_invalid;
14062 break;
14063 case MAXA_FMT:
14064 check_insn(ctx, ISA_MIPS32R6);
14065 switch ((ctx->opcode >> 9) & 0x3) {
14066 case FMT_SDPS_S:
14067 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14068 break;
14069 case FMT_SDPS_D:
14070 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14071 break;
14072 default:
14073 goto pool32f_invalid;
14075 break;
14076 case 0x30:
14077 /* regular FP ops */
14078 switch ((ctx->opcode >> 6) & 0x3) {
14079 case ADD_FMT:
14080 FINSN_3ARG_SDPS(ADD);
14081 break;
14082 case SUB_FMT:
14083 FINSN_3ARG_SDPS(SUB);
14084 break;
14085 case MUL_FMT:
14086 FINSN_3ARG_SDPS(MUL);
14087 break;
14088 case DIV_FMT:
14089 fmt = (ctx->opcode >> 8) & 0x3;
14090 if (fmt == 1) {
14091 mips32_op = OPC_DIV_D;
14092 } else if (fmt == 0) {
14093 mips32_op = OPC_DIV_S;
14094 } else {
14095 goto pool32f_invalid;
14097 goto do_fpop;
14098 default:
14099 goto pool32f_invalid;
14101 break;
14102 case 0x38:
14103 /* cmovs */
14104 switch ((ctx->opcode >> 6) & 0x7) {
14105 case MOVN_FMT: /* SELNEZ_FMT */
14106 if (ctx->insn_flags & ISA_MIPS32R6) {
14107 /* SELNEZ_FMT */
14108 switch ((ctx->opcode >> 9) & 0x3) {
14109 case FMT_SDPS_S:
14110 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
14111 break;
14112 case FMT_SDPS_D:
14113 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
14114 break;
14115 default:
14116 goto pool32f_invalid;
14118 } else {
14119 /* MOVN_FMT */
14120 FINSN_3ARG_SDPS(MOVN);
14122 break;
14123 case MOVN_FMT_04:
14124 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14125 FINSN_3ARG_SDPS(MOVN);
14126 break;
14127 case MOVZ_FMT: /* SELEQZ_FMT */
14128 if (ctx->insn_flags & ISA_MIPS32R6) {
14129 /* SELEQZ_FMT */
14130 switch ((ctx->opcode >> 9) & 0x3) {
14131 case FMT_SDPS_S:
14132 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
14133 break;
14134 case FMT_SDPS_D:
14135 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
14136 break;
14137 default:
14138 goto pool32f_invalid;
14140 } else {
14141 /* MOVZ_FMT */
14142 FINSN_3ARG_SDPS(MOVZ);
14144 break;
14145 case MOVZ_FMT_05:
14146 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14147 FINSN_3ARG_SDPS(MOVZ);
14148 break;
14149 case SEL_FMT:
14150 check_insn(ctx, ISA_MIPS32R6);
14151 switch ((ctx->opcode >> 9) & 0x3) {
14152 case FMT_SDPS_S:
14153 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
14154 break;
14155 case FMT_SDPS_D:
14156 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
14157 break;
14158 default:
14159 goto pool32f_invalid;
14161 break;
14162 case MADDF_FMT:
14163 check_insn(ctx, ISA_MIPS32R6);
14164 switch ((ctx->opcode >> 9) & 0x3) {
14165 case FMT_SDPS_S:
14166 mips32_op = OPC_MADDF_S;
14167 goto do_fpop;
14168 case FMT_SDPS_D:
14169 mips32_op = OPC_MADDF_D;
14170 goto do_fpop;
14171 default:
14172 goto pool32f_invalid;
14174 break;
14175 case MSUBF_FMT:
14176 check_insn(ctx, ISA_MIPS32R6);
14177 switch ((ctx->opcode >> 9) & 0x3) {
14178 case FMT_SDPS_S:
14179 mips32_op = OPC_MSUBF_S;
14180 goto do_fpop;
14181 case FMT_SDPS_D:
14182 mips32_op = OPC_MSUBF_D;
14183 goto do_fpop;
14184 default:
14185 goto pool32f_invalid;
14187 break;
14188 default:
14189 goto pool32f_invalid;
14191 break;
14192 do_fpop:
14193 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14194 break;
14195 default:
14196 pool32f_invalid:
14197 MIPS_INVAL("pool32f");
14198 generate_exception_end(ctx, EXCP_RI);
14199 break;
14201 } else {
14202 generate_exception_err(ctx, EXCP_CpU, 1);
14204 break;
14205 case POOL32I:
14206 minor = (ctx->opcode >> 21) & 0x1f;
14207 switch (minor) {
14208 case BLTZ:
14209 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14210 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
14211 break;
14212 case BLTZAL:
14213 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14214 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
14215 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14216 break;
14217 case BLTZALS:
14218 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14219 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
14220 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14221 break;
14222 case BGEZ:
14223 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14224 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
14225 break;
14226 case BGEZAL:
14227 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14228 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
14229 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14230 break;
14231 case BGEZALS:
14232 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14233 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
14234 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14235 break;
14236 case BLEZ:
14237 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14238 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
14239 break;
14240 case BGTZ:
14241 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14242 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
14243 break;
14245 /* Traps */
14246 case TLTI: /* BC1EQZC */
14247 if (ctx->insn_flags & ISA_MIPS32R6) {
14248 /* BC1EQZC */
14249 check_cp1_enabled(ctx);
14250 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
14251 } else {
14252 /* TLTI */
14253 mips32_op = OPC_TLTI;
14254 goto do_trapi;
14256 break;
14257 case TGEI: /* BC1NEZC */
14258 if (ctx->insn_flags & ISA_MIPS32R6) {
14259 /* BC1NEZC */
14260 check_cp1_enabled(ctx);
14261 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
14262 } else {
14263 /* TGEI */
14264 mips32_op = OPC_TGEI;
14265 goto do_trapi;
14267 break;
14268 case TLTIU:
14269 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14270 mips32_op = OPC_TLTIU;
14271 goto do_trapi;
14272 case TGEIU:
14273 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14274 mips32_op = OPC_TGEIU;
14275 goto do_trapi;
14276 case TNEI: /* SYNCI */
14277 if (ctx->insn_flags & ISA_MIPS32R6) {
14278 /* SYNCI */
14279 /* Break the TB to be able to sync copied instructions
14280 immediately */
14281 ctx->bstate = BS_STOP;
14282 } else {
14283 /* TNEI */
14284 mips32_op = OPC_TNEI;
14285 goto do_trapi;
14287 break;
14288 case TEQI:
14289 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14290 mips32_op = OPC_TEQI;
14291 do_trapi:
14292 gen_trap(ctx, mips32_op, rs, -1, imm);
14293 break;
14295 case BNEZC:
14296 case BEQZC:
14297 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14298 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
14299 4, rs, 0, imm << 1, 0);
14300 /* Compact branches don't have a delay slot, so just let
14301 the normal delay slot handling take us to the branch
14302 target. */
14303 break;
14304 case LUI:
14305 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14306 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
14307 break;
14308 case SYNCI:
14309 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14310 /* Break the TB to be able to sync copied instructions
14311 immediately */
14312 ctx->bstate = BS_STOP;
14313 break;
14314 case BC2F:
14315 case BC2T:
14316 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14317 /* COP2: Not implemented. */
14318 generate_exception_err(ctx, EXCP_CpU, 2);
14319 break;
14320 case BC1F:
14321 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14322 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
14323 goto do_cp1branch;
14324 case BC1T:
14325 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14326 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
14327 goto do_cp1branch;
14328 case BC1ANY4F:
14329 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14330 mips32_op = OPC_BC1FANY4;
14331 goto do_cp1mips3d;
14332 case BC1ANY4T:
14333 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14334 mips32_op = OPC_BC1TANY4;
14335 do_cp1mips3d:
14336 check_cop1x(ctx);
14337 check_insn(ctx, ASE_MIPS3D);
14338 /* Fall through */
14339 do_cp1branch:
14340 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
14341 check_cp1_enabled(ctx);
14342 gen_compute_branch1(ctx, mips32_op,
14343 (ctx->opcode >> 18) & 0x7, imm << 1);
14344 } else {
14345 generate_exception_err(ctx, EXCP_CpU, 1);
14347 break;
14348 case BPOSGE64:
14349 case BPOSGE32:
14350 /* MIPS DSP: not implemented */
14351 /* Fall through */
14352 default:
14353 MIPS_INVAL("pool32i");
14354 generate_exception_end(ctx, EXCP_RI);
14355 break;
14357 break;
14358 case POOL32C:
14359 minor = (ctx->opcode >> 12) & 0xf;
14360 offset = sextract32(ctx->opcode, 0,
14361 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
14362 switch (minor) {
14363 case LWL:
14364 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14365 mips32_op = OPC_LWL;
14366 goto do_ld_lr;
14367 case SWL:
14368 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14369 mips32_op = OPC_SWL;
14370 goto do_st_lr;
14371 case LWR:
14372 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14373 mips32_op = OPC_LWR;
14374 goto do_ld_lr;
14375 case SWR:
14376 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14377 mips32_op = OPC_SWR;
14378 goto do_st_lr;
14379 #if defined(TARGET_MIPS64)
14380 case LDL:
14381 check_insn(ctx, ISA_MIPS3);
14382 check_mips_64(ctx);
14383 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14384 mips32_op = OPC_LDL;
14385 goto do_ld_lr;
14386 case SDL:
14387 check_insn(ctx, ISA_MIPS3);
14388 check_mips_64(ctx);
14389 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14390 mips32_op = OPC_SDL;
14391 goto do_st_lr;
14392 case LDR:
14393 check_insn(ctx, ISA_MIPS3);
14394 check_mips_64(ctx);
14395 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14396 mips32_op = OPC_LDR;
14397 goto do_ld_lr;
14398 case SDR:
14399 check_insn(ctx, ISA_MIPS3);
14400 check_mips_64(ctx);
14401 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14402 mips32_op = OPC_SDR;
14403 goto do_st_lr;
14404 case LWU:
14405 check_insn(ctx, ISA_MIPS3);
14406 check_mips_64(ctx);
14407 mips32_op = OPC_LWU;
14408 goto do_ld_lr;
14409 case LLD:
14410 check_insn(ctx, ISA_MIPS3);
14411 check_mips_64(ctx);
14412 mips32_op = OPC_LLD;
14413 goto do_ld_lr;
14414 #endif
14415 case LL:
14416 mips32_op = OPC_LL;
14417 goto do_ld_lr;
14418 do_ld_lr:
14419 gen_ld(ctx, mips32_op, rt, rs, offset);
14420 break;
14421 do_st_lr:
14422 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
14423 break;
14424 case SC:
14425 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
14426 break;
14427 #if defined(TARGET_MIPS64)
14428 case SCD:
14429 check_insn(ctx, ISA_MIPS3);
14430 check_mips_64(ctx);
14431 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
14432 break;
14433 #endif
14434 case PREF:
14435 /* Treat as no-op */
14436 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
14437 /* hint codes 24-31 are reserved and signal RI */
14438 generate_exception(ctx, EXCP_RI);
14440 break;
14441 default:
14442 MIPS_INVAL("pool32c");
14443 generate_exception_end(ctx, EXCP_RI);
14444 break;
14446 break;
14447 case ADDI32: /* AUI, LUI */
14448 if (ctx->insn_flags & ISA_MIPS32R6) {
14449 /* AUI, LUI */
14450 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
14451 } else {
14452 /* ADDI32 */
14453 mips32_op = OPC_ADDI;
14454 goto do_addi;
14456 break;
14457 case ADDIU32:
14458 mips32_op = OPC_ADDIU;
14459 do_addi:
14460 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
14461 break;
14463 /* Logical operations */
14464 case ORI32:
14465 mips32_op = OPC_ORI;
14466 goto do_logici;
14467 case XORI32:
14468 mips32_op = OPC_XORI;
14469 goto do_logici;
14470 case ANDI32:
14471 mips32_op = OPC_ANDI;
14472 do_logici:
14473 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
14474 break;
14476 /* Set less than immediate */
14477 case SLTI32:
14478 mips32_op = OPC_SLTI;
14479 goto do_slti;
14480 case SLTIU32:
14481 mips32_op = OPC_SLTIU;
14482 do_slti:
14483 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
14484 break;
14485 case JALX32:
14486 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14487 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
14488 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
14489 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14490 break;
14491 case JALS32: /* BOVC, BEQC, BEQZALC */
14492 if (ctx->insn_flags & ISA_MIPS32R6) {
14493 if (rs >= rt) {
14494 /* BOVC */
14495 mips32_op = OPC_BOVC;
14496 } else if (rs < rt && rs == 0) {
14497 /* BEQZALC */
14498 mips32_op = OPC_BEQZALC;
14499 } else {
14500 /* BEQC */
14501 mips32_op = OPC_BEQC;
14503 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14504 } else {
14505 /* JALS32 */
14506 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
14507 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
14508 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14510 break;
14511 case BEQ32: /* BC */
14512 if (ctx->insn_flags & ISA_MIPS32R6) {
14513 /* BC */
14514 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
14515 sextract32(ctx->opcode << 1, 0, 27));
14516 } else {
14517 /* BEQ32 */
14518 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
14520 break;
14521 case BNE32: /* BALC */
14522 if (ctx->insn_flags & ISA_MIPS32R6) {
14523 /* BALC */
14524 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
14525 sextract32(ctx->opcode << 1, 0, 27));
14526 } else {
14527 /* BNE32 */
14528 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
14530 break;
14531 case J32: /* BGTZC, BLTZC, BLTC */
14532 if (ctx->insn_flags & ISA_MIPS32R6) {
14533 if (rs == 0 && rt != 0) {
14534 /* BGTZC */
14535 mips32_op = OPC_BGTZC;
14536 } else if (rs != 0 && rt != 0 && rs == rt) {
14537 /* BLTZC */
14538 mips32_op = OPC_BLTZC;
14539 } else {
14540 /* BLTC */
14541 mips32_op = OPC_BLTC;
14543 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14544 } else {
14545 /* J32 */
14546 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
14547 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14549 break;
14550 case JAL32: /* BLEZC, BGEZC, BGEC */
14551 if (ctx->insn_flags & ISA_MIPS32R6) {
14552 if (rs == 0 && rt != 0) {
14553 /* BLEZC */
14554 mips32_op = OPC_BLEZC;
14555 } else if (rs != 0 && rt != 0 && rs == rt) {
14556 /* BGEZC */
14557 mips32_op = OPC_BGEZC;
14558 } else {
14559 /* BGEC */
14560 mips32_op = OPC_BGEC;
14562 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14563 } else {
14564 /* JAL32 */
14565 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
14566 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14567 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14569 break;
14570 /* Floating point (COP1) */
14571 case LWC132:
14572 mips32_op = OPC_LWC1;
14573 goto do_cop1;
14574 case LDC132:
14575 mips32_op = OPC_LDC1;
14576 goto do_cop1;
14577 case SWC132:
14578 mips32_op = OPC_SWC1;
14579 goto do_cop1;
14580 case SDC132:
14581 mips32_op = OPC_SDC1;
14582 do_cop1:
14583 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
14584 break;
14585 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
14586 if (ctx->insn_flags & ISA_MIPS32R6) {
14587 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
14588 switch ((ctx->opcode >> 16) & 0x1f) {
14589 case ADDIUPC_00 ... ADDIUPC_07:
14590 gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
14591 break;
14592 case AUIPC:
14593 gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
14594 break;
14595 case ALUIPC:
14596 gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt);
14597 break;
14598 case LWPC_08 ... LWPC_0F:
14599 gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt);
14600 break;
14601 default:
14602 generate_exception(ctx, EXCP_RI);
14603 break;
14605 } else {
14606 /* ADDIUPC */
14607 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
14608 int offset = SIMM(ctx->opcode, 0, 23) << 2;
14610 gen_addiupc(ctx, reg, offset, 0, 0);
14612 break;
14613 case BNVC: /* BNEC, BNEZALC */
14614 check_insn(ctx, ISA_MIPS32R6);
14615 if (rs >= rt) {
14616 /* BNVC */
14617 mips32_op = OPC_BNVC;
14618 } else if (rs < rt && rs == 0) {
14619 /* BNEZALC */
14620 mips32_op = OPC_BNEZALC;
14621 } else {
14622 /* BNEC */
14623 mips32_op = OPC_BNEC;
14625 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14626 break;
14627 case R6_BNEZC: /* JIALC */
14628 check_insn(ctx, ISA_MIPS32R6);
14629 if (rt != 0) {
14630 /* BNEZC */
14631 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
14632 sextract32(ctx->opcode << 1, 0, 22));
14633 } else {
14634 /* JIALC */
14635 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
14637 break;
14638 case R6_BEQZC: /* JIC */
14639 check_insn(ctx, ISA_MIPS32R6);
14640 if (rt != 0) {
14641 /* BEQZC */
14642 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
14643 sextract32(ctx->opcode << 1, 0, 22));
14644 } else {
14645 /* JIC */
14646 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
14648 break;
14649 case BLEZALC: /* BGEZALC, BGEUC */
14650 check_insn(ctx, ISA_MIPS32R6);
14651 if (rs == 0 && rt != 0) {
14652 /* BLEZALC */
14653 mips32_op = OPC_BLEZALC;
14654 } else if (rs != 0 && rt != 0 && rs == rt) {
14655 /* BGEZALC */
14656 mips32_op = OPC_BGEZALC;
14657 } else {
14658 /* BGEUC */
14659 mips32_op = OPC_BGEUC;
14661 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14662 break;
14663 case BGTZALC: /* BLTZALC, BLTUC */
14664 check_insn(ctx, ISA_MIPS32R6);
14665 if (rs == 0 && rt != 0) {
14666 /* BGTZALC */
14667 mips32_op = OPC_BGTZALC;
14668 } else if (rs != 0 && rt != 0 && rs == rt) {
14669 /* BLTZALC */
14670 mips32_op = OPC_BLTZALC;
14671 } else {
14672 /* BLTUC */
14673 mips32_op = OPC_BLTUC;
14675 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14676 break;
14677 /* Loads and stores */
14678 case LB32:
14679 mips32_op = OPC_LB;
14680 goto do_ld;
14681 case LBU32:
14682 mips32_op = OPC_LBU;
14683 goto do_ld;
14684 case LH32:
14685 mips32_op = OPC_LH;
14686 goto do_ld;
14687 case LHU32:
14688 mips32_op = OPC_LHU;
14689 goto do_ld;
14690 case LW32:
14691 mips32_op = OPC_LW;
14692 goto do_ld;
14693 #ifdef TARGET_MIPS64
14694 case LD32:
14695 check_insn(ctx, ISA_MIPS3);
14696 check_mips_64(ctx);
14697 mips32_op = OPC_LD;
14698 goto do_ld;
14699 case SD32:
14700 check_insn(ctx, ISA_MIPS3);
14701 check_mips_64(ctx);
14702 mips32_op = OPC_SD;
14703 goto do_st;
14704 #endif
14705 case SB32:
14706 mips32_op = OPC_SB;
14707 goto do_st;
14708 case SH32:
14709 mips32_op = OPC_SH;
14710 goto do_st;
14711 case SW32:
14712 mips32_op = OPC_SW;
14713 goto do_st;
14714 do_ld:
14715 gen_ld(ctx, mips32_op, rt, rs, imm);
14716 break;
14717 do_st:
14718 gen_st(ctx, mips32_op, rt, rs, imm);
14719 break;
14720 default:
14721 generate_exception_end(ctx, EXCP_RI);
14722 break;
14726 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
14728 uint32_t op;
14730 /* make sure instructions are on a halfword boundary */
14731 if (ctx->pc & 0x1) {
14732 env->CP0_BadVAddr = ctx->pc;
14733 generate_exception_end(ctx, EXCP_AdEL);
14734 return 2;
14737 op = (ctx->opcode >> 10) & 0x3f;
14738 /* Enforce properly-sized instructions in a delay slot */
14739 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
14740 switch (op & 0x7) { /* MSB-3..MSB-5 */
14741 case 0:
14742 /* POOL32A, POOL32B, POOL32I, POOL32C */
14743 case 4:
14744 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
14745 case 5:
14746 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
14747 case 6:
14748 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
14749 case 7:
14750 /* LB32, LH32, LWC132, LDC132, LW32 */
14751 if (ctx->hflags & MIPS_HFLAG_BDS16) {
14752 generate_exception_end(ctx, EXCP_RI);
14753 return 2;
14755 break;
14756 case 1:
14757 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
14758 case 2:
14759 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
14760 case 3:
14761 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
14762 if (ctx->hflags & MIPS_HFLAG_BDS32) {
14763 generate_exception_end(ctx, EXCP_RI);
14764 return 2;
14766 break;
14770 switch (op) {
14771 case POOL16A:
14773 int rd = mmreg(uMIPS_RD(ctx->opcode));
14774 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
14775 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
14776 uint32_t opc = 0;
14778 switch (ctx->opcode & 0x1) {
14779 case ADDU16:
14780 opc = OPC_ADDU;
14781 break;
14782 case SUBU16:
14783 opc = OPC_SUBU;
14784 break;
14786 if (ctx->insn_flags & ISA_MIPS32R6) {
14787 /* In the Release 6 the register number location in
14788 * the instruction encoding has changed.
14790 gen_arith(ctx, opc, rs1, rd, rs2);
14791 } else {
14792 gen_arith(ctx, opc, rd, rs1, rs2);
14795 break;
14796 case POOL16B:
14798 int rd = mmreg(uMIPS_RD(ctx->opcode));
14799 int rs = mmreg(uMIPS_RS(ctx->opcode));
14800 int amount = (ctx->opcode >> 1) & 0x7;
14801 uint32_t opc = 0;
14802 amount = amount == 0 ? 8 : amount;
14804 switch (ctx->opcode & 0x1) {
14805 case SLL16:
14806 opc = OPC_SLL;
14807 break;
14808 case SRL16:
14809 opc = OPC_SRL;
14810 break;
14813 gen_shift_imm(ctx, opc, rd, rs, amount);
14815 break;
14816 case POOL16C:
14817 if (ctx->insn_flags & ISA_MIPS32R6) {
14818 gen_pool16c_r6_insn(ctx);
14819 } else {
14820 gen_pool16c_insn(ctx);
14822 break;
14823 case LWGP16:
14825 int rd = mmreg(uMIPS_RD(ctx->opcode));
14826 int rb = 28; /* GP */
14827 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
14829 gen_ld(ctx, OPC_LW, rd, rb, offset);
14831 break;
14832 case POOL16F:
14833 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14834 if (ctx->opcode & 1) {
14835 generate_exception_end(ctx, EXCP_RI);
14836 } else {
14837 /* MOVEP */
14838 int enc_dest = uMIPS_RD(ctx->opcode);
14839 int enc_rt = uMIPS_RS2(ctx->opcode);
14840 int enc_rs = uMIPS_RS1(ctx->opcode);
14841 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14843 break;
14844 case LBU16:
14846 int rd = mmreg(uMIPS_RD(ctx->opcode));
14847 int rb = mmreg(uMIPS_RS(ctx->opcode));
14848 int16_t offset = ZIMM(ctx->opcode, 0, 4);
14849 offset = (offset == 0xf ? -1 : offset);
14851 gen_ld(ctx, OPC_LBU, rd, rb, offset);
14853 break;
14854 case LHU16:
14856 int rd = mmreg(uMIPS_RD(ctx->opcode));
14857 int rb = mmreg(uMIPS_RS(ctx->opcode));
14858 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
14860 gen_ld(ctx, OPC_LHU, rd, rb, offset);
14862 break;
14863 case LWSP16:
14865 int rd = (ctx->opcode >> 5) & 0x1f;
14866 int rb = 29; /* SP */
14867 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
14869 gen_ld(ctx, OPC_LW, rd, rb, offset);
14871 break;
14872 case LW16:
14874 int rd = mmreg(uMIPS_RD(ctx->opcode));
14875 int rb = mmreg(uMIPS_RS(ctx->opcode));
14876 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
14878 gen_ld(ctx, OPC_LW, rd, rb, offset);
14880 break;
14881 case SB16:
14883 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14884 int rb = mmreg(uMIPS_RS(ctx->opcode));
14885 int16_t offset = ZIMM(ctx->opcode, 0, 4);
14887 gen_st(ctx, OPC_SB, rd, rb, offset);
14889 break;
14890 case SH16:
14892 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14893 int rb = mmreg(uMIPS_RS(ctx->opcode));
14894 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
14896 gen_st(ctx, OPC_SH, rd, rb, offset);
14898 break;
14899 case SWSP16:
14901 int rd = (ctx->opcode >> 5) & 0x1f;
14902 int rb = 29; /* SP */
14903 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
14905 gen_st(ctx, OPC_SW, rd, rb, offset);
14907 break;
14908 case SW16:
14910 int rd = mmreg2(uMIPS_RD(ctx->opcode));
14911 int rb = mmreg(uMIPS_RS(ctx->opcode));
14912 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
14914 gen_st(ctx, OPC_SW, rd, rb, offset);
14916 break;
14917 case MOVE16:
14919 int rd = uMIPS_RD5(ctx->opcode);
14920 int rs = uMIPS_RS5(ctx->opcode);
14922 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
14924 break;
14925 case ANDI16:
14926 gen_andi16(ctx);
14927 break;
14928 case POOL16D:
14929 switch (ctx->opcode & 0x1) {
14930 case ADDIUS5:
14931 gen_addius5(ctx);
14932 break;
14933 case ADDIUSP:
14934 gen_addiusp(ctx);
14935 break;
14937 break;
14938 case POOL16E:
14939 switch (ctx->opcode & 0x1) {
14940 case ADDIUR2:
14941 gen_addiur2(ctx);
14942 break;
14943 case ADDIUR1SP:
14944 gen_addiur1sp(ctx);
14945 break;
14947 break;
14948 case B16: /* BC16 */
14949 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
14950 sextract32(ctx->opcode, 0, 10) << 1,
14951 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
14952 break;
14953 case BNEZ16: /* BNEZC16 */
14954 case BEQZ16: /* BEQZC16 */
14955 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
14956 mmreg(uMIPS_RD(ctx->opcode)),
14957 0, sextract32(ctx->opcode, 0, 7) << 1,
14958 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
14960 break;
14961 case LI16:
14963 int reg = mmreg(uMIPS_RD(ctx->opcode));
14964 int imm = ZIMM(ctx->opcode, 0, 7);
14966 imm = (imm == 0x7f ? -1 : imm);
14967 tcg_gen_movi_tl(cpu_gpr[reg], imm);
14969 break;
14970 case RES_29:
14971 case RES_31:
14972 case RES_39:
14973 generate_exception_end(ctx, EXCP_RI);
14974 break;
14975 default:
14976 decode_micromips32_opc(env, ctx);
14977 return 4;
14980 return 2;
14983 /* SmartMIPS extension to MIPS32 */
14985 #if defined(TARGET_MIPS64)
14987 /* MDMX extension to MIPS64 */
14989 #endif
14991 /* MIPSDSP functions. */
14992 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
14993 int rd, int base, int offset)
14995 TCGv t0;
14997 check_dsp(ctx);
14998 t0 = tcg_temp_new();
15000 if (base == 0) {
15001 gen_load_gpr(t0, offset);
15002 } else if (offset == 0) {
15003 gen_load_gpr(t0, base);
15004 } else {
15005 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
15008 switch (opc) {
15009 case OPC_LBUX:
15010 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
15011 gen_store_gpr(t0, rd);
15012 break;
15013 case OPC_LHX:
15014 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
15015 gen_store_gpr(t0, rd);
15016 break;
15017 case OPC_LWX:
15018 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
15019 gen_store_gpr(t0, rd);
15020 break;
15021 #if defined(TARGET_MIPS64)
15022 case OPC_LDX:
15023 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
15024 gen_store_gpr(t0, rd);
15025 break;
15026 #endif
15028 tcg_temp_free(t0);
15031 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
15032 int ret, int v1, int v2)
15034 TCGv v1_t;
15035 TCGv v2_t;
15037 if (ret == 0) {
15038 /* Treat as NOP. */
15039 return;
15042 v1_t = tcg_temp_new();
15043 v2_t = tcg_temp_new();
15045 gen_load_gpr(v1_t, v1);
15046 gen_load_gpr(v2_t, v2);
15048 switch (op1) {
15049 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
15050 case OPC_MULT_G_2E:
15051 check_dspr2(ctx);
15052 switch (op2) {
15053 case OPC_ADDUH_QB:
15054 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
15055 break;
15056 case OPC_ADDUH_R_QB:
15057 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15058 break;
15059 case OPC_ADDQH_PH:
15060 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
15061 break;
15062 case OPC_ADDQH_R_PH:
15063 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15064 break;
15065 case OPC_ADDQH_W:
15066 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
15067 break;
15068 case OPC_ADDQH_R_W:
15069 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15070 break;
15071 case OPC_SUBUH_QB:
15072 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
15073 break;
15074 case OPC_SUBUH_R_QB:
15075 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15076 break;
15077 case OPC_SUBQH_PH:
15078 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
15079 break;
15080 case OPC_SUBQH_R_PH:
15081 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15082 break;
15083 case OPC_SUBQH_W:
15084 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
15085 break;
15086 case OPC_SUBQH_R_W:
15087 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15088 break;
15090 break;
15091 case OPC_ABSQ_S_PH_DSP:
15092 switch (op2) {
15093 case OPC_ABSQ_S_QB:
15094 check_dspr2(ctx);
15095 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
15096 break;
15097 case OPC_ABSQ_S_PH:
15098 check_dsp(ctx);
15099 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
15100 break;
15101 case OPC_ABSQ_S_W:
15102 check_dsp(ctx);
15103 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
15104 break;
15105 case OPC_PRECEQ_W_PHL:
15106 check_dsp(ctx);
15107 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
15108 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15109 break;
15110 case OPC_PRECEQ_W_PHR:
15111 check_dsp(ctx);
15112 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
15113 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
15114 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15115 break;
15116 case OPC_PRECEQU_PH_QBL:
15117 check_dsp(ctx);
15118 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
15119 break;
15120 case OPC_PRECEQU_PH_QBR:
15121 check_dsp(ctx);
15122 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
15123 break;
15124 case OPC_PRECEQU_PH_QBLA:
15125 check_dsp(ctx);
15126 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
15127 break;
15128 case OPC_PRECEQU_PH_QBRA:
15129 check_dsp(ctx);
15130 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
15131 break;
15132 case OPC_PRECEU_PH_QBL:
15133 check_dsp(ctx);
15134 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
15135 break;
15136 case OPC_PRECEU_PH_QBR:
15137 check_dsp(ctx);
15138 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
15139 break;
15140 case OPC_PRECEU_PH_QBLA:
15141 check_dsp(ctx);
15142 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
15143 break;
15144 case OPC_PRECEU_PH_QBRA:
15145 check_dsp(ctx);
15146 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
15147 break;
15149 break;
15150 case OPC_ADDU_QB_DSP:
15151 switch (op2) {
15152 case OPC_ADDQ_PH:
15153 check_dsp(ctx);
15154 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15155 break;
15156 case OPC_ADDQ_S_PH:
15157 check_dsp(ctx);
15158 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15159 break;
15160 case OPC_ADDQ_S_W:
15161 check_dsp(ctx);
15162 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15163 break;
15164 case OPC_ADDU_QB:
15165 check_dsp(ctx);
15166 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15167 break;
15168 case OPC_ADDU_S_QB:
15169 check_dsp(ctx);
15170 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15171 break;
15172 case OPC_ADDU_PH:
15173 check_dspr2(ctx);
15174 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15175 break;
15176 case OPC_ADDU_S_PH:
15177 check_dspr2(ctx);
15178 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15179 break;
15180 case OPC_SUBQ_PH:
15181 check_dsp(ctx);
15182 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15183 break;
15184 case OPC_SUBQ_S_PH:
15185 check_dsp(ctx);
15186 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15187 break;
15188 case OPC_SUBQ_S_W:
15189 check_dsp(ctx);
15190 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15191 break;
15192 case OPC_SUBU_QB:
15193 check_dsp(ctx);
15194 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15195 break;
15196 case OPC_SUBU_S_QB:
15197 check_dsp(ctx);
15198 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15199 break;
15200 case OPC_SUBU_PH:
15201 check_dspr2(ctx);
15202 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15203 break;
15204 case OPC_SUBU_S_PH:
15205 check_dspr2(ctx);
15206 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15207 break;
15208 case OPC_ADDSC:
15209 check_dsp(ctx);
15210 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15211 break;
15212 case OPC_ADDWC:
15213 check_dsp(ctx);
15214 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15215 break;
15216 case OPC_MODSUB:
15217 check_dsp(ctx);
15218 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
15219 break;
15220 case OPC_RADDU_W_QB:
15221 check_dsp(ctx);
15222 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
15223 break;
15225 break;
15226 case OPC_CMPU_EQ_QB_DSP:
15227 switch (op2) {
15228 case OPC_PRECR_QB_PH:
15229 check_dspr2(ctx);
15230 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15231 break;
15232 case OPC_PRECRQ_QB_PH:
15233 check_dsp(ctx);
15234 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15235 break;
15236 case OPC_PRECR_SRA_PH_W:
15237 check_dspr2(ctx);
15239 TCGv_i32 sa_t = tcg_const_i32(v2);
15240 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
15241 cpu_gpr[ret]);
15242 tcg_temp_free_i32(sa_t);
15243 break;
15245 case OPC_PRECR_SRA_R_PH_W:
15246 check_dspr2(ctx);
15248 TCGv_i32 sa_t = tcg_const_i32(v2);
15249 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
15250 cpu_gpr[ret]);
15251 tcg_temp_free_i32(sa_t);
15252 break;
15254 case OPC_PRECRQ_PH_W:
15255 check_dsp(ctx);
15256 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
15257 break;
15258 case OPC_PRECRQ_RS_PH_W:
15259 check_dsp(ctx);
15260 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15261 break;
15262 case OPC_PRECRQU_S_QB_PH:
15263 check_dsp(ctx);
15264 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15265 break;
15267 break;
15268 #ifdef TARGET_MIPS64
15269 case OPC_ABSQ_S_QH_DSP:
15270 switch (op2) {
15271 case OPC_PRECEQ_L_PWL:
15272 check_dsp(ctx);
15273 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
15274 break;
15275 case OPC_PRECEQ_L_PWR:
15276 check_dsp(ctx);
15277 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
15278 break;
15279 case OPC_PRECEQ_PW_QHL:
15280 check_dsp(ctx);
15281 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
15282 break;
15283 case OPC_PRECEQ_PW_QHR:
15284 check_dsp(ctx);
15285 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
15286 break;
15287 case OPC_PRECEQ_PW_QHLA:
15288 check_dsp(ctx);
15289 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
15290 break;
15291 case OPC_PRECEQ_PW_QHRA:
15292 check_dsp(ctx);
15293 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
15294 break;
15295 case OPC_PRECEQU_QH_OBL:
15296 check_dsp(ctx);
15297 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
15298 break;
15299 case OPC_PRECEQU_QH_OBR:
15300 check_dsp(ctx);
15301 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
15302 break;
15303 case OPC_PRECEQU_QH_OBLA:
15304 check_dsp(ctx);
15305 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
15306 break;
15307 case OPC_PRECEQU_QH_OBRA:
15308 check_dsp(ctx);
15309 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
15310 break;
15311 case OPC_PRECEU_QH_OBL:
15312 check_dsp(ctx);
15313 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
15314 break;
15315 case OPC_PRECEU_QH_OBR:
15316 check_dsp(ctx);
15317 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
15318 break;
15319 case OPC_PRECEU_QH_OBLA:
15320 check_dsp(ctx);
15321 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
15322 break;
15323 case OPC_PRECEU_QH_OBRA:
15324 check_dsp(ctx);
15325 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
15326 break;
15327 case OPC_ABSQ_S_OB:
15328 check_dspr2(ctx);
15329 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
15330 break;
15331 case OPC_ABSQ_S_PW:
15332 check_dsp(ctx);
15333 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
15334 break;
15335 case OPC_ABSQ_S_QH:
15336 check_dsp(ctx);
15337 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
15338 break;
15340 break;
15341 case OPC_ADDU_OB_DSP:
15342 switch (op2) {
15343 case OPC_RADDU_L_OB:
15344 check_dsp(ctx);
15345 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
15346 break;
15347 case OPC_SUBQ_PW:
15348 check_dsp(ctx);
15349 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15350 break;
15351 case OPC_SUBQ_S_PW:
15352 check_dsp(ctx);
15353 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15354 break;
15355 case OPC_SUBQ_QH:
15356 check_dsp(ctx);
15357 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15358 break;
15359 case OPC_SUBQ_S_QH:
15360 check_dsp(ctx);
15361 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15362 break;
15363 case OPC_SUBU_OB:
15364 check_dsp(ctx);
15365 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15366 break;
15367 case OPC_SUBU_S_OB:
15368 check_dsp(ctx);
15369 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15370 break;
15371 case OPC_SUBU_QH:
15372 check_dspr2(ctx);
15373 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15374 break;
15375 case OPC_SUBU_S_QH:
15376 check_dspr2(ctx);
15377 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15378 break;
15379 case OPC_SUBUH_OB:
15380 check_dspr2(ctx);
15381 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
15382 break;
15383 case OPC_SUBUH_R_OB:
15384 check_dspr2(ctx);
15385 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15386 break;
15387 case OPC_ADDQ_PW:
15388 check_dsp(ctx);
15389 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15390 break;
15391 case OPC_ADDQ_S_PW:
15392 check_dsp(ctx);
15393 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15394 break;
15395 case OPC_ADDQ_QH:
15396 check_dsp(ctx);
15397 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15398 break;
15399 case OPC_ADDQ_S_QH:
15400 check_dsp(ctx);
15401 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15402 break;
15403 case OPC_ADDU_OB:
15404 check_dsp(ctx);
15405 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15406 break;
15407 case OPC_ADDU_S_OB:
15408 check_dsp(ctx);
15409 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15410 break;
15411 case OPC_ADDU_QH:
15412 check_dspr2(ctx);
15413 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15414 break;
15415 case OPC_ADDU_S_QH:
15416 check_dspr2(ctx);
15417 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15418 break;
15419 case OPC_ADDUH_OB:
15420 check_dspr2(ctx);
15421 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
15422 break;
15423 case OPC_ADDUH_R_OB:
15424 check_dspr2(ctx);
15425 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15426 break;
15428 break;
15429 case OPC_CMPU_EQ_OB_DSP:
15430 switch (op2) {
15431 case OPC_PRECR_OB_QH:
15432 check_dspr2(ctx);
15433 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15434 break;
15435 case OPC_PRECR_SRA_QH_PW:
15436 check_dspr2(ctx);
15438 TCGv_i32 ret_t = tcg_const_i32(ret);
15439 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
15440 tcg_temp_free_i32(ret_t);
15441 break;
15443 case OPC_PRECR_SRA_R_QH_PW:
15444 check_dspr2(ctx);
15446 TCGv_i32 sa_v = tcg_const_i32(ret);
15447 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
15448 tcg_temp_free_i32(sa_v);
15449 break;
15451 case OPC_PRECRQ_OB_QH:
15452 check_dsp(ctx);
15453 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15454 break;
15455 case OPC_PRECRQ_PW_L:
15456 check_dsp(ctx);
15457 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
15458 break;
15459 case OPC_PRECRQ_QH_PW:
15460 check_dsp(ctx);
15461 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
15462 break;
15463 case OPC_PRECRQ_RS_QH_PW:
15464 check_dsp(ctx);
15465 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15466 break;
15467 case OPC_PRECRQU_S_OB_QH:
15468 check_dsp(ctx);
15469 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15470 break;
15472 break;
15473 #endif
15476 tcg_temp_free(v1_t);
15477 tcg_temp_free(v2_t);
15480 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
15481 int ret, int v1, int v2)
15483 uint32_t op2;
15484 TCGv t0;
15485 TCGv v1_t;
15486 TCGv v2_t;
15488 if (ret == 0) {
15489 /* Treat as NOP. */
15490 return;
15493 t0 = tcg_temp_new();
15494 v1_t = tcg_temp_new();
15495 v2_t = tcg_temp_new();
15497 tcg_gen_movi_tl(t0, v1);
15498 gen_load_gpr(v1_t, v1);
15499 gen_load_gpr(v2_t, v2);
15501 switch (opc) {
15502 case OPC_SHLL_QB_DSP:
15504 op2 = MASK_SHLL_QB(ctx->opcode);
15505 switch (op2) {
15506 case OPC_SHLL_QB:
15507 check_dsp(ctx);
15508 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
15509 break;
15510 case OPC_SHLLV_QB:
15511 check_dsp(ctx);
15512 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15513 break;
15514 case OPC_SHLL_PH:
15515 check_dsp(ctx);
15516 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15517 break;
15518 case OPC_SHLLV_PH:
15519 check_dsp(ctx);
15520 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15521 break;
15522 case OPC_SHLL_S_PH:
15523 check_dsp(ctx);
15524 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15525 break;
15526 case OPC_SHLLV_S_PH:
15527 check_dsp(ctx);
15528 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15529 break;
15530 case OPC_SHLL_S_W:
15531 check_dsp(ctx);
15532 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
15533 break;
15534 case OPC_SHLLV_S_W:
15535 check_dsp(ctx);
15536 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15537 break;
15538 case OPC_SHRL_QB:
15539 check_dsp(ctx);
15540 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
15541 break;
15542 case OPC_SHRLV_QB:
15543 check_dsp(ctx);
15544 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
15545 break;
15546 case OPC_SHRL_PH:
15547 check_dspr2(ctx);
15548 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
15549 break;
15550 case OPC_SHRLV_PH:
15551 check_dspr2(ctx);
15552 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
15553 break;
15554 case OPC_SHRA_QB:
15555 check_dspr2(ctx);
15556 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
15557 break;
15558 case OPC_SHRA_R_QB:
15559 check_dspr2(ctx);
15560 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
15561 break;
15562 case OPC_SHRAV_QB:
15563 check_dspr2(ctx);
15564 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
15565 break;
15566 case OPC_SHRAV_R_QB:
15567 check_dspr2(ctx);
15568 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
15569 break;
15570 case OPC_SHRA_PH:
15571 check_dsp(ctx);
15572 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
15573 break;
15574 case OPC_SHRA_R_PH:
15575 check_dsp(ctx);
15576 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
15577 break;
15578 case OPC_SHRAV_PH:
15579 check_dsp(ctx);
15580 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
15581 break;
15582 case OPC_SHRAV_R_PH:
15583 check_dsp(ctx);
15584 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
15585 break;
15586 case OPC_SHRA_R_W:
15587 check_dsp(ctx);
15588 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
15589 break;
15590 case OPC_SHRAV_R_W:
15591 check_dsp(ctx);
15592 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
15593 break;
15594 default: /* Invalid */
15595 MIPS_INVAL("MASK SHLL.QB");
15596 generate_exception_end(ctx, EXCP_RI);
15597 break;
15599 break;
15601 #ifdef TARGET_MIPS64
15602 case OPC_SHLL_OB_DSP:
15603 op2 = MASK_SHLL_OB(ctx->opcode);
15604 switch (op2) {
15605 case OPC_SHLL_PW:
15606 check_dsp(ctx);
15607 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15608 break;
15609 case OPC_SHLLV_PW:
15610 check_dsp(ctx);
15611 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15612 break;
15613 case OPC_SHLL_S_PW:
15614 check_dsp(ctx);
15615 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15616 break;
15617 case OPC_SHLLV_S_PW:
15618 check_dsp(ctx);
15619 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15620 break;
15621 case OPC_SHLL_OB:
15622 check_dsp(ctx);
15623 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
15624 break;
15625 case OPC_SHLLV_OB:
15626 check_dsp(ctx);
15627 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15628 break;
15629 case OPC_SHLL_QH:
15630 check_dsp(ctx);
15631 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15632 break;
15633 case OPC_SHLLV_QH:
15634 check_dsp(ctx);
15635 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15636 break;
15637 case OPC_SHLL_S_QH:
15638 check_dsp(ctx);
15639 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15640 break;
15641 case OPC_SHLLV_S_QH:
15642 check_dsp(ctx);
15643 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15644 break;
15645 case OPC_SHRA_OB:
15646 check_dspr2(ctx);
15647 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
15648 break;
15649 case OPC_SHRAV_OB:
15650 check_dspr2(ctx);
15651 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
15652 break;
15653 case OPC_SHRA_R_OB:
15654 check_dspr2(ctx);
15655 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
15656 break;
15657 case OPC_SHRAV_R_OB:
15658 check_dspr2(ctx);
15659 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
15660 break;
15661 case OPC_SHRA_PW:
15662 check_dsp(ctx);
15663 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
15664 break;
15665 case OPC_SHRAV_PW:
15666 check_dsp(ctx);
15667 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
15668 break;
15669 case OPC_SHRA_R_PW:
15670 check_dsp(ctx);
15671 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
15672 break;
15673 case OPC_SHRAV_R_PW:
15674 check_dsp(ctx);
15675 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
15676 break;
15677 case OPC_SHRA_QH:
15678 check_dsp(ctx);
15679 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
15680 break;
15681 case OPC_SHRAV_QH:
15682 check_dsp(ctx);
15683 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
15684 break;
15685 case OPC_SHRA_R_QH:
15686 check_dsp(ctx);
15687 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
15688 break;
15689 case OPC_SHRAV_R_QH:
15690 check_dsp(ctx);
15691 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
15692 break;
15693 case OPC_SHRL_OB:
15694 check_dsp(ctx);
15695 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
15696 break;
15697 case OPC_SHRLV_OB:
15698 check_dsp(ctx);
15699 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
15700 break;
15701 case OPC_SHRL_QH:
15702 check_dspr2(ctx);
15703 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
15704 break;
15705 case OPC_SHRLV_QH:
15706 check_dspr2(ctx);
15707 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
15708 break;
15709 default: /* Invalid */
15710 MIPS_INVAL("MASK SHLL.OB");
15711 generate_exception_end(ctx, EXCP_RI);
15712 break;
15714 break;
15715 #endif
15718 tcg_temp_free(t0);
15719 tcg_temp_free(v1_t);
15720 tcg_temp_free(v2_t);
15723 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
15724 int ret, int v1, int v2, int check_ret)
15726 TCGv_i32 t0;
15727 TCGv v1_t;
15728 TCGv v2_t;
15730 if ((ret == 0) && (check_ret == 1)) {
15731 /* Treat as NOP. */
15732 return;
15735 t0 = tcg_temp_new_i32();
15736 v1_t = tcg_temp_new();
15737 v2_t = tcg_temp_new();
15739 tcg_gen_movi_i32(t0, ret);
15740 gen_load_gpr(v1_t, v1);
15741 gen_load_gpr(v2_t, v2);
15743 switch (op1) {
15744 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
15745 * the same mask and op1. */
15746 case OPC_MULT_G_2E:
15747 check_dspr2(ctx);
15748 switch (op2) {
15749 case OPC_MUL_PH:
15750 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15751 break;
15752 case OPC_MUL_S_PH:
15753 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15754 break;
15755 case OPC_MULQ_S_W:
15756 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15757 break;
15758 case OPC_MULQ_RS_W:
15759 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15760 break;
15762 break;
15763 case OPC_DPA_W_PH_DSP:
15764 switch (op2) {
15765 case OPC_DPAU_H_QBL:
15766 check_dsp(ctx);
15767 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
15768 break;
15769 case OPC_DPAU_H_QBR:
15770 check_dsp(ctx);
15771 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
15772 break;
15773 case OPC_DPSU_H_QBL:
15774 check_dsp(ctx);
15775 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
15776 break;
15777 case OPC_DPSU_H_QBR:
15778 check_dsp(ctx);
15779 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
15780 break;
15781 case OPC_DPA_W_PH:
15782 check_dspr2(ctx);
15783 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
15784 break;
15785 case OPC_DPAX_W_PH:
15786 check_dspr2(ctx);
15787 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
15788 break;
15789 case OPC_DPAQ_S_W_PH:
15790 check_dsp(ctx);
15791 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15792 break;
15793 case OPC_DPAQX_S_W_PH:
15794 check_dspr2(ctx);
15795 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
15796 break;
15797 case OPC_DPAQX_SA_W_PH:
15798 check_dspr2(ctx);
15799 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
15800 break;
15801 case OPC_DPS_W_PH:
15802 check_dspr2(ctx);
15803 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
15804 break;
15805 case OPC_DPSX_W_PH:
15806 check_dspr2(ctx);
15807 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
15808 break;
15809 case OPC_DPSQ_S_W_PH:
15810 check_dsp(ctx);
15811 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15812 break;
15813 case OPC_DPSQX_S_W_PH:
15814 check_dspr2(ctx);
15815 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
15816 break;
15817 case OPC_DPSQX_SA_W_PH:
15818 check_dspr2(ctx);
15819 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
15820 break;
15821 case OPC_MULSAQ_S_W_PH:
15822 check_dsp(ctx);
15823 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
15824 break;
15825 case OPC_DPAQ_SA_L_W:
15826 check_dsp(ctx);
15827 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
15828 break;
15829 case OPC_DPSQ_SA_L_W:
15830 check_dsp(ctx);
15831 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
15832 break;
15833 case OPC_MAQ_S_W_PHL:
15834 check_dsp(ctx);
15835 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
15836 break;
15837 case OPC_MAQ_S_W_PHR:
15838 check_dsp(ctx);
15839 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
15840 break;
15841 case OPC_MAQ_SA_W_PHL:
15842 check_dsp(ctx);
15843 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
15844 break;
15845 case OPC_MAQ_SA_W_PHR:
15846 check_dsp(ctx);
15847 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
15848 break;
15849 case OPC_MULSA_W_PH:
15850 check_dspr2(ctx);
15851 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
15852 break;
15854 break;
15855 #ifdef TARGET_MIPS64
15856 case OPC_DPAQ_W_QH_DSP:
15858 int ac = ret & 0x03;
15859 tcg_gen_movi_i32(t0, ac);
15861 switch (op2) {
15862 case OPC_DMADD:
15863 check_dsp(ctx);
15864 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
15865 break;
15866 case OPC_DMADDU:
15867 check_dsp(ctx);
15868 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
15869 break;
15870 case OPC_DMSUB:
15871 check_dsp(ctx);
15872 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
15873 break;
15874 case OPC_DMSUBU:
15875 check_dsp(ctx);
15876 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
15877 break;
15878 case OPC_DPA_W_QH:
15879 check_dspr2(ctx);
15880 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
15881 break;
15882 case OPC_DPAQ_S_W_QH:
15883 check_dsp(ctx);
15884 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15885 break;
15886 case OPC_DPAQ_SA_L_PW:
15887 check_dsp(ctx);
15888 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
15889 break;
15890 case OPC_DPAU_H_OBL:
15891 check_dsp(ctx);
15892 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
15893 break;
15894 case OPC_DPAU_H_OBR:
15895 check_dsp(ctx);
15896 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
15897 break;
15898 case OPC_DPS_W_QH:
15899 check_dspr2(ctx);
15900 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
15901 break;
15902 case OPC_DPSQ_S_W_QH:
15903 check_dsp(ctx);
15904 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15905 break;
15906 case OPC_DPSQ_SA_L_PW:
15907 check_dsp(ctx);
15908 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
15909 break;
15910 case OPC_DPSU_H_OBL:
15911 check_dsp(ctx);
15912 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
15913 break;
15914 case OPC_DPSU_H_OBR:
15915 check_dsp(ctx);
15916 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
15917 break;
15918 case OPC_MAQ_S_L_PWL:
15919 check_dsp(ctx);
15920 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
15921 break;
15922 case OPC_MAQ_S_L_PWR:
15923 check_dsp(ctx);
15924 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
15925 break;
15926 case OPC_MAQ_S_W_QHLL:
15927 check_dsp(ctx);
15928 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
15929 break;
15930 case OPC_MAQ_SA_W_QHLL:
15931 check_dsp(ctx);
15932 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
15933 break;
15934 case OPC_MAQ_S_W_QHLR:
15935 check_dsp(ctx);
15936 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
15937 break;
15938 case OPC_MAQ_SA_W_QHLR:
15939 check_dsp(ctx);
15940 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
15941 break;
15942 case OPC_MAQ_S_W_QHRL:
15943 check_dsp(ctx);
15944 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
15945 break;
15946 case OPC_MAQ_SA_W_QHRL:
15947 check_dsp(ctx);
15948 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
15949 break;
15950 case OPC_MAQ_S_W_QHRR:
15951 check_dsp(ctx);
15952 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
15953 break;
15954 case OPC_MAQ_SA_W_QHRR:
15955 check_dsp(ctx);
15956 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
15957 break;
15958 case OPC_MULSAQ_S_L_PW:
15959 check_dsp(ctx);
15960 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
15961 break;
15962 case OPC_MULSAQ_S_W_QH:
15963 check_dsp(ctx);
15964 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
15965 break;
15968 break;
15969 #endif
15970 case OPC_ADDU_QB_DSP:
15971 switch (op2) {
15972 case OPC_MULEU_S_PH_QBL:
15973 check_dsp(ctx);
15974 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15975 break;
15976 case OPC_MULEU_S_PH_QBR:
15977 check_dsp(ctx);
15978 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15979 break;
15980 case OPC_MULQ_RS_PH:
15981 check_dsp(ctx);
15982 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15983 break;
15984 case OPC_MULEQ_S_W_PHL:
15985 check_dsp(ctx);
15986 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15987 break;
15988 case OPC_MULEQ_S_W_PHR:
15989 check_dsp(ctx);
15990 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15991 break;
15992 case OPC_MULQ_S_PH:
15993 check_dspr2(ctx);
15994 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15995 break;
15997 break;
15998 #ifdef TARGET_MIPS64
15999 case OPC_ADDU_OB_DSP:
16000 switch (op2) {
16001 case OPC_MULEQ_S_PW_QHL:
16002 check_dsp(ctx);
16003 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16004 break;
16005 case OPC_MULEQ_S_PW_QHR:
16006 check_dsp(ctx);
16007 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16008 break;
16009 case OPC_MULEU_S_QH_OBL:
16010 check_dsp(ctx);
16011 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16012 break;
16013 case OPC_MULEU_S_QH_OBR:
16014 check_dsp(ctx);
16015 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16016 break;
16017 case OPC_MULQ_RS_QH:
16018 check_dsp(ctx);
16019 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16020 break;
16022 break;
16023 #endif
16026 tcg_temp_free_i32(t0);
16027 tcg_temp_free(v1_t);
16028 tcg_temp_free(v2_t);
16031 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16032 int ret, int val)
16034 int16_t imm;
16035 TCGv t0;
16036 TCGv val_t;
16038 if (ret == 0) {
16039 /* Treat as NOP. */
16040 return;
16043 t0 = tcg_temp_new();
16044 val_t = tcg_temp_new();
16045 gen_load_gpr(val_t, val);
16047 switch (op1) {
16048 case OPC_ABSQ_S_PH_DSP:
16049 switch (op2) {
16050 case OPC_BITREV:
16051 check_dsp(ctx);
16052 gen_helper_bitrev(cpu_gpr[ret], val_t);
16053 break;
16054 case OPC_REPL_QB:
16055 check_dsp(ctx);
16057 target_long result;
16058 imm = (ctx->opcode >> 16) & 0xFF;
16059 result = (uint32_t)imm << 24 |
16060 (uint32_t)imm << 16 |
16061 (uint32_t)imm << 8 |
16062 (uint32_t)imm;
16063 result = (int32_t)result;
16064 tcg_gen_movi_tl(cpu_gpr[ret], result);
16066 break;
16067 case OPC_REPLV_QB:
16068 check_dsp(ctx);
16069 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16070 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16071 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16072 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16073 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16074 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16075 break;
16076 case OPC_REPL_PH:
16077 check_dsp(ctx);
16079 imm = (ctx->opcode >> 16) & 0x03FF;
16080 imm = (int16_t)(imm << 6) >> 6;
16081 tcg_gen_movi_tl(cpu_gpr[ret], \
16082 (target_long)((int32_t)imm << 16 | \
16083 (uint16_t)imm));
16085 break;
16086 case OPC_REPLV_PH:
16087 check_dsp(ctx);
16088 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16089 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16090 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16091 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16092 break;
16094 break;
16095 #ifdef TARGET_MIPS64
16096 case OPC_ABSQ_S_QH_DSP:
16097 switch (op2) {
16098 case OPC_REPL_OB:
16099 check_dsp(ctx);
16101 target_long temp;
16103 imm = (ctx->opcode >> 16) & 0xFF;
16104 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
16105 temp = (temp << 16) | temp;
16106 temp = (temp << 32) | temp;
16107 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16108 break;
16110 case OPC_REPL_PW:
16111 check_dsp(ctx);
16113 target_long temp;
16115 imm = (ctx->opcode >> 16) & 0x03FF;
16116 imm = (int16_t)(imm << 6) >> 6;
16117 temp = ((target_long)imm << 32) \
16118 | ((target_long)imm & 0xFFFFFFFF);
16119 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16120 break;
16122 case OPC_REPL_QH:
16123 check_dsp(ctx);
16125 target_long temp;
16127 imm = (ctx->opcode >> 16) & 0x03FF;
16128 imm = (int16_t)(imm << 6) >> 6;
16130 temp = ((uint64_t)(uint16_t)imm << 48) |
16131 ((uint64_t)(uint16_t)imm << 32) |
16132 ((uint64_t)(uint16_t)imm << 16) |
16133 (uint64_t)(uint16_t)imm;
16134 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16135 break;
16137 case OPC_REPLV_OB:
16138 check_dsp(ctx);
16139 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16140 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16141 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16142 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16143 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16144 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16145 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16146 break;
16147 case OPC_REPLV_PW:
16148 check_dsp(ctx);
16149 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
16150 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16151 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16152 break;
16153 case OPC_REPLV_QH:
16154 check_dsp(ctx);
16155 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16156 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16157 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16158 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16159 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16160 break;
16162 break;
16163 #endif
16165 tcg_temp_free(t0);
16166 tcg_temp_free(val_t);
16169 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
16170 uint32_t op1, uint32_t op2,
16171 int ret, int v1, int v2, int check_ret)
16173 TCGv t1;
16174 TCGv v1_t;
16175 TCGv v2_t;
16177 if ((ret == 0) && (check_ret == 1)) {
16178 /* Treat as NOP. */
16179 return;
16182 t1 = tcg_temp_new();
16183 v1_t = tcg_temp_new();
16184 v2_t = tcg_temp_new();
16186 gen_load_gpr(v1_t, v1);
16187 gen_load_gpr(v2_t, v2);
16189 switch (op1) {
16190 case OPC_CMPU_EQ_QB_DSP:
16191 switch (op2) {
16192 case OPC_CMPU_EQ_QB:
16193 check_dsp(ctx);
16194 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
16195 break;
16196 case OPC_CMPU_LT_QB:
16197 check_dsp(ctx);
16198 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
16199 break;
16200 case OPC_CMPU_LE_QB:
16201 check_dsp(ctx);
16202 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
16203 break;
16204 case OPC_CMPGU_EQ_QB:
16205 check_dsp(ctx);
16206 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
16207 break;
16208 case OPC_CMPGU_LT_QB:
16209 check_dsp(ctx);
16210 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
16211 break;
16212 case OPC_CMPGU_LE_QB:
16213 check_dsp(ctx);
16214 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
16215 break;
16216 case OPC_CMPGDU_EQ_QB:
16217 check_dspr2(ctx);
16218 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
16219 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16220 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16221 tcg_gen_shli_tl(t1, t1, 24);
16222 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16223 break;
16224 case OPC_CMPGDU_LT_QB:
16225 check_dspr2(ctx);
16226 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
16227 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16228 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16229 tcg_gen_shli_tl(t1, t1, 24);
16230 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16231 break;
16232 case OPC_CMPGDU_LE_QB:
16233 check_dspr2(ctx);
16234 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
16235 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16236 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16237 tcg_gen_shli_tl(t1, t1, 24);
16238 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16239 break;
16240 case OPC_CMP_EQ_PH:
16241 check_dsp(ctx);
16242 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
16243 break;
16244 case OPC_CMP_LT_PH:
16245 check_dsp(ctx);
16246 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
16247 break;
16248 case OPC_CMP_LE_PH:
16249 check_dsp(ctx);
16250 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
16251 break;
16252 case OPC_PICK_QB:
16253 check_dsp(ctx);
16254 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16255 break;
16256 case OPC_PICK_PH:
16257 check_dsp(ctx);
16258 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16259 break;
16260 case OPC_PACKRL_PH:
16261 check_dsp(ctx);
16262 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
16263 break;
16265 break;
16266 #ifdef TARGET_MIPS64
16267 case OPC_CMPU_EQ_OB_DSP:
16268 switch (op2) {
16269 case OPC_CMP_EQ_PW:
16270 check_dsp(ctx);
16271 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
16272 break;
16273 case OPC_CMP_LT_PW:
16274 check_dsp(ctx);
16275 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
16276 break;
16277 case OPC_CMP_LE_PW:
16278 check_dsp(ctx);
16279 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
16280 break;
16281 case OPC_CMP_EQ_QH:
16282 check_dsp(ctx);
16283 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
16284 break;
16285 case OPC_CMP_LT_QH:
16286 check_dsp(ctx);
16287 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
16288 break;
16289 case OPC_CMP_LE_QH:
16290 check_dsp(ctx);
16291 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
16292 break;
16293 case OPC_CMPGDU_EQ_OB:
16294 check_dspr2(ctx);
16295 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16296 break;
16297 case OPC_CMPGDU_LT_OB:
16298 check_dspr2(ctx);
16299 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16300 break;
16301 case OPC_CMPGDU_LE_OB:
16302 check_dspr2(ctx);
16303 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16304 break;
16305 case OPC_CMPGU_EQ_OB:
16306 check_dsp(ctx);
16307 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
16308 break;
16309 case OPC_CMPGU_LT_OB:
16310 check_dsp(ctx);
16311 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
16312 break;
16313 case OPC_CMPGU_LE_OB:
16314 check_dsp(ctx);
16315 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
16316 break;
16317 case OPC_CMPU_EQ_OB:
16318 check_dsp(ctx);
16319 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
16320 break;
16321 case OPC_CMPU_LT_OB:
16322 check_dsp(ctx);
16323 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
16324 break;
16325 case OPC_CMPU_LE_OB:
16326 check_dsp(ctx);
16327 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
16328 break;
16329 case OPC_PACKRL_PW:
16330 check_dsp(ctx);
16331 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
16332 break;
16333 case OPC_PICK_OB:
16334 check_dsp(ctx);
16335 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16336 break;
16337 case OPC_PICK_PW:
16338 check_dsp(ctx);
16339 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16340 break;
16341 case OPC_PICK_QH:
16342 check_dsp(ctx);
16343 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16344 break;
16346 break;
16347 #endif
16350 tcg_temp_free(t1);
16351 tcg_temp_free(v1_t);
16352 tcg_temp_free(v2_t);
16355 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
16356 uint32_t op1, int rt, int rs, int sa)
16358 TCGv t0;
16360 check_dspr2(ctx);
16362 if (rt == 0) {
16363 /* Treat as NOP. */
16364 return;
16367 t0 = tcg_temp_new();
16368 gen_load_gpr(t0, rs);
16370 switch (op1) {
16371 case OPC_APPEND_DSP:
16372 switch (MASK_APPEND(ctx->opcode)) {
16373 case OPC_APPEND:
16374 if (sa != 0) {
16375 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
16377 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16378 break;
16379 case OPC_PREPEND:
16380 if (sa != 0) {
16381 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
16382 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16383 tcg_gen_shli_tl(t0, t0, 32 - sa);
16384 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16386 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16387 break;
16388 case OPC_BALIGN:
16389 sa &= 3;
16390 if (sa != 0 && sa != 2) {
16391 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16392 tcg_gen_ext32u_tl(t0, t0);
16393 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
16394 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16396 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16397 break;
16398 default: /* Invalid */
16399 MIPS_INVAL("MASK APPEND");
16400 generate_exception_end(ctx, EXCP_RI);
16401 break;
16403 break;
16404 #ifdef TARGET_MIPS64
16405 case OPC_DAPPEND_DSP:
16406 switch (MASK_DAPPEND(ctx->opcode)) {
16407 case OPC_DAPPEND:
16408 if (sa != 0) {
16409 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
16411 break;
16412 case OPC_PREPENDD:
16413 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
16414 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
16415 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
16416 break;
16417 case OPC_PREPENDW:
16418 if (sa != 0) {
16419 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16420 tcg_gen_shli_tl(t0, t0, 64 - sa);
16421 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16423 break;
16424 case OPC_DBALIGN:
16425 sa &= 7;
16426 if (sa != 0 && sa != 2 && sa != 4) {
16427 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16428 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
16429 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16431 break;
16432 default: /* Invalid */
16433 MIPS_INVAL("MASK DAPPEND");
16434 generate_exception_end(ctx, EXCP_RI);
16435 break;
16437 break;
16438 #endif
16440 tcg_temp_free(t0);
16443 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16444 int ret, int v1, int v2, int check_ret)
16447 TCGv t0;
16448 TCGv t1;
16449 TCGv v1_t;
16450 TCGv v2_t;
16451 int16_t imm;
16453 if ((ret == 0) && (check_ret == 1)) {
16454 /* Treat as NOP. */
16455 return;
16458 t0 = tcg_temp_new();
16459 t1 = tcg_temp_new();
16460 v1_t = tcg_temp_new();
16461 v2_t = tcg_temp_new();
16463 gen_load_gpr(v1_t, v1);
16464 gen_load_gpr(v2_t, v2);
16466 switch (op1) {
16467 case OPC_EXTR_W_DSP:
16468 check_dsp(ctx);
16469 switch (op2) {
16470 case OPC_EXTR_W:
16471 tcg_gen_movi_tl(t0, v2);
16472 tcg_gen_movi_tl(t1, v1);
16473 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
16474 break;
16475 case OPC_EXTR_R_W:
16476 tcg_gen_movi_tl(t0, v2);
16477 tcg_gen_movi_tl(t1, v1);
16478 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16479 break;
16480 case OPC_EXTR_RS_W:
16481 tcg_gen_movi_tl(t0, v2);
16482 tcg_gen_movi_tl(t1, v1);
16483 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16484 break;
16485 case OPC_EXTR_S_H:
16486 tcg_gen_movi_tl(t0, v2);
16487 tcg_gen_movi_tl(t1, v1);
16488 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16489 break;
16490 case OPC_EXTRV_S_H:
16491 tcg_gen_movi_tl(t0, v2);
16492 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
16493 break;
16494 case OPC_EXTRV_W:
16495 tcg_gen_movi_tl(t0, v2);
16496 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16497 break;
16498 case OPC_EXTRV_R_W:
16499 tcg_gen_movi_tl(t0, v2);
16500 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16501 break;
16502 case OPC_EXTRV_RS_W:
16503 tcg_gen_movi_tl(t0, v2);
16504 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16505 break;
16506 case OPC_EXTP:
16507 tcg_gen_movi_tl(t0, v2);
16508 tcg_gen_movi_tl(t1, v1);
16509 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
16510 break;
16511 case OPC_EXTPV:
16512 tcg_gen_movi_tl(t0, v2);
16513 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
16514 break;
16515 case OPC_EXTPDP:
16516 tcg_gen_movi_tl(t0, v2);
16517 tcg_gen_movi_tl(t1, v1);
16518 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
16519 break;
16520 case OPC_EXTPDPV:
16521 tcg_gen_movi_tl(t0, v2);
16522 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16523 break;
16524 case OPC_SHILO:
16525 imm = (ctx->opcode >> 20) & 0x3F;
16526 tcg_gen_movi_tl(t0, ret);
16527 tcg_gen_movi_tl(t1, imm);
16528 gen_helper_shilo(t0, t1, cpu_env);
16529 break;
16530 case OPC_SHILOV:
16531 tcg_gen_movi_tl(t0, ret);
16532 gen_helper_shilo(t0, v1_t, cpu_env);
16533 break;
16534 case OPC_MTHLIP:
16535 tcg_gen_movi_tl(t0, ret);
16536 gen_helper_mthlip(t0, v1_t, cpu_env);
16537 break;
16538 case OPC_WRDSP:
16539 imm = (ctx->opcode >> 11) & 0x3FF;
16540 tcg_gen_movi_tl(t0, imm);
16541 gen_helper_wrdsp(v1_t, t0, cpu_env);
16542 break;
16543 case OPC_RDDSP:
16544 imm = (ctx->opcode >> 16) & 0x03FF;
16545 tcg_gen_movi_tl(t0, imm);
16546 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
16547 break;
16549 break;
16550 #ifdef TARGET_MIPS64
16551 case OPC_DEXTR_W_DSP:
16552 check_dsp(ctx);
16553 switch (op2) {
16554 case OPC_DMTHLIP:
16555 tcg_gen_movi_tl(t0, ret);
16556 gen_helper_dmthlip(v1_t, t0, cpu_env);
16557 break;
16558 case OPC_DSHILO:
16560 int shift = (ctx->opcode >> 19) & 0x7F;
16561 int ac = (ctx->opcode >> 11) & 0x03;
16562 tcg_gen_movi_tl(t0, shift);
16563 tcg_gen_movi_tl(t1, ac);
16564 gen_helper_dshilo(t0, t1, cpu_env);
16565 break;
16567 case OPC_DSHILOV:
16569 int ac = (ctx->opcode >> 11) & 0x03;
16570 tcg_gen_movi_tl(t0, ac);
16571 gen_helper_dshilo(v1_t, t0, cpu_env);
16572 break;
16574 case OPC_DEXTP:
16575 tcg_gen_movi_tl(t0, v2);
16576 tcg_gen_movi_tl(t1, v1);
16578 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
16579 break;
16580 case OPC_DEXTPV:
16581 tcg_gen_movi_tl(t0, v2);
16582 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
16583 break;
16584 case OPC_DEXTPDP:
16585 tcg_gen_movi_tl(t0, v2);
16586 tcg_gen_movi_tl(t1, v1);
16587 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
16588 break;
16589 case OPC_DEXTPDPV:
16590 tcg_gen_movi_tl(t0, v2);
16591 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16592 break;
16593 case OPC_DEXTR_L:
16594 tcg_gen_movi_tl(t0, v2);
16595 tcg_gen_movi_tl(t1, v1);
16596 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
16597 break;
16598 case OPC_DEXTR_R_L:
16599 tcg_gen_movi_tl(t0, v2);
16600 tcg_gen_movi_tl(t1, v1);
16601 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
16602 break;
16603 case OPC_DEXTR_RS_L:
16604 tcg_gen_movi_tl(t0, v2);
16605 tcg_gen_movi_tl(t1, v1);
16606 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
16607 break;
16608 case OPC_DEXTR_W:
16609 tcg_gen_movi_tl(t0, v2);
16610 tcg_gen_movi_tl(t1, v1);
16611 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
16612 break;
16613 case OPC_DEXTR_R_W:
16614 tcg_gen_movi_tl(t0, v2);
16615 tcg_gen_movi_tl(t1, v1);
16616 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16617 break;
16618 case OPC_DEXTR_RS_W:
16619 tcg_gen_movi_tl(t0, v2);
16620 tcg_gen_movi_tl(t1, v1);
16621 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16622 break;
16623 case OPC_DEXTR_S_H:
16624 tcg_gen_movi_tl(t0, v2);
16625 tcg_gen_movi_tl(t1, v1);
16626 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16627 break;
16628 case OPC_DEXTRV_S_H:
16629 tcg_gen_movi_tl(t0, v2);
16630 tcg_gen_movi_tl(t1, v1);
16631 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16632 break;
16633 case OPC_DEXTRV_L:
16634 tcg_gen_movi_tl(t0, v2);
16635 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16636 break;
16637 case OPC_DEXTRV_R_L:
16638 tcg_gen_movi_tl(t0, v2);
16639 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16640 break;
16641 case OPC_DEXTRV_RS_L:
16642 tcg_gen_movi_tl(t0, v2);
16643 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16644 break;
16645 case OPC_DEXTRV_W:
16646 tcg_gen_movi_tl(t0, v2);
16647 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16648 break;
16649 case OPC_DEXTRV_R_W:
16650 tcg_gen_movi_tl(t0, v2);
16651 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16652 break;
16653 case OPC_DEXTRV_RS_W:
16654 tcg_gen_movi_tl(t0, v2);
16655 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16656 break;
16658 break;
16659 #endif
16662 tcg_temp_free(t0);
16663 tcg_temp_free(t1);
16664 tcg_temp_free(v1_t);
16665 tcg_temp_free(v2_t);
16668 /* End MIPSDSP functions. */
16670 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
16672 int rs, rt, rd, sa;
16673 uint32_t op1, op2;
16675 rs = (ctx->opcode >> 21) & 0x1f;
16676 rt = (ctx->opcode >> 16) & 0x1f;
16677 rd = (ctx->opcode >> 11) & 0x1f;
16678 sa = (ctx->opcode >> 6) & 0x1f;
16680 op1 = MASK_SPECIAL(ctx->opcode);
16681 switch (op1) {
16682 case OPC_LSA:
16683 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
16684 break;
16685 case OPC_MULT ... OPC_DIVU:
16686 op2 = MASK_R6_MULDIV(ctx->opcode);
16687 switch (op2) {
16688 case R6_OPC_MUL:
16689 case R6_OPC_MUH:
16690 case R6_OPC_MULU:
16691 case R6_OPC_MUHU:
16692 case R6_OPC_DIV:
16693 case R6_OPC_MOD:
16694 case R6_OPC_DIVU:
16695 case R6_OPC_MODU:
16696 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16697 break;
16698 default:
16699 MIPS_INVAL("special_r6 muldiv");
16700 generate_exception_end(ctx, EXCP_RI);
16701 break;
16703 break;
16704 case OPC_SELEQZ:
16705 case OPC_SELNEZ:
16706 gen_cond_move(ctx, op1, rd, rs, rt);
16707 break;
16708 case R6_OPC_CLO:
16709 case R6_OPC_CLZ:
16710 if (rt == 0 && sa == 1) {
16711 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16712 We need additionally to check other fields */
16713 gen_cl(ctx, op1, rd, rs);
16714 } else {
16715 generate_exception_end(ctx, EXCP_RI);
16717 break;
16718 case R6_OPC_SDBBP:
16719 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
16720 gen_helper_do_semihosting(cpu_env);
16721 } else {
16722 if (ctx->hflags & MIPS_HFLAG_SBRI) {
16723 generate_exception_end(ctx, EXCP_RI);
16724 } else {
16725 generate_exception_end(ctx, EXCP_DBp);
16728 break;
16729 #if defined(TARGET_MIPS64)
16730 case OPC_DLSA:
16731 check_mips_64(ctx);
16732 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
16733 break;
16734 case R6_OPC_DCLO:
16735 case R6_OPC_DCLZ:
16736 if (rt == 0 && sa == 1) {
16737 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
16738 We need additionally to check other fields */
16739 check_mips_64(ctx);
16740 gen_cl(ctx, op1, rd, rs);
16741 } else {
16742 generate_exception_end(ctx, EXCP_RI);
16744 break;
16745 case OPC_DMULT ... OPC_DDIVU:
16746 op2 = MASK_R6_MULDIV(ctx->opcode);
16747 switch (op2) {
16748 case R6_OPC_DMUL:
16749 case R6_OPC_DMUH:
16750 case R6_OPC_DMULU:
16751 case R6_OPC_DMUHU:
16752 case R6_OPC_DDIV:
16753 case R6_OPC_DMOD:
16754 case R6_OPC_DDIVU:
16755 case R6_OPC_DMODU:
16756 check_mips_64(ctx);
16757 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16758 break;
16759 default:
16760 MIPS_INVAL("special_r6 muldiv");
16761 generate_exception_end(ctx, EXCP_RI);
16762 break;
16764 break;
16765 #endif
16766 default: /* Invalid */
16767 MIPS_INVAL("special_r6");
16768 generate_exception_end(ctx, EXCP_RI);
16769 break;
16773 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
16775 int rs, rt, rd, sa;
16776 uint32_t op1;
16778 rs = (ctx->opcode >> 21) & 0x1f;
16779 rt = (ctx->opcode >> 16) & 0x1f;
16780 rd = (ctx->opcode >> 11) & 0x1f;
16781 sa = (ctx->opcode >> 6) & 0x1f;
16783 op1 = MASK_SPECIAL(ctx->opcode);
16784 switch (op1) {
16785 case OPC_MOVN: /* Conditional move */
16786 case OPC_MOVZ:
16787 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
16788 INSN_LOONGSON2E | INSN_LOONGSON2F);
16789 gen_cond_move(ctx, op1, rd, rs, rt);
16790 break;
16791 case OPC_MFHI: /* Move from HI/LO */
16792 case OPC_MFLO:
16793 gen_HILO(ctx, op1, rs & 3, rd);
16794 break;
16795 case OPC_MTHI:
16796 case OPC_MTLO: /* Move to HI/LO */
16797 gen_HILO(ctx, op1, rd & 3, rs);
16798 break;
16799 case OPC_MOVCI:
16800 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
16801 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16802 check_cp1_enabled(ctx);
16803 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
16804 (ctx->opcode >> 16) & 1);
16805 } else {
16806 generate_exception_err(ctx, EXCP_CpU, 1);
16808 break;
16809 case OPC_MULT:
16810 case OPC_MULTU:
16811 if (sa) {
16812 check_insn(ctx, INSN_VR54XX);
16813 op1 = MASK_MUL_VR54XX(ctx->opcode);
16814 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
16815 } else {
16816 gen_muldiv(ctx, op1, rd & 3, rs, rt);
16818 break;
16819 case OPC_DIV:
16820 case OPC_DIVU:
16821 gen_muldiv(ctx, op1, 0, rs, rt);
16822 break;
16823 #if defined(TARGET_MIPS64)
16824 case OPC_DMULT ... OPC_DDIVU:
16825 check_insn(ctx, ISA_MIPS3);
16826 check_mips_64(ctx);
16827 gen_muldiv(ctx, op1, 0, rs, rt);
16828 break;
16829 #endif
16830 case OPC_JR:
16831 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
16832 break;
16833 case OPC_SPIM:
16834 #ifdef MIPS_STRICT_STANDARD
16835 MIPS_INVAL("SPIM");
16836 generate_exception_end(ctx, EXCP_RI);
16837 #else
16838 /* Implemented as RI exception for now. */
16839 MIPS_INVAL("spim (unofficial)");
16840 generate_exception_end(ctx, EXCP_RI);
16841 #endif
16842 break;
16843 default: /* Invalid */
16844 MIPS_INVAL("special_legacy");
16845 generate_exception_end(ctx, EXCP_RI);
16846 break;
16850 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
16852 int rs, rt, rd, sa;
16853 uint32_t op1;
16855 rs = (ctx->opcode >> 21) & 0x1f;
16856 rt = (ctx->opcode >> 16) & 0x1f;
16857 rd = (ctx->opcode >> 11) & 0x1f;
16858 sa = (ctx->opcode >> 6) & 0x1f;
16860 op1 = MASK_SPECIAL(ctx->opcode);
16861 switch (op1) {
16862 case OPC_SLL: /* Shift with immediate */
16863 if (sa == 5 && rd == 0 &&
16864 rs == 0 && rt == 0) { /* PAUSE */
16865 if ((ctx->insn_flags & ISA_MIPS32R6) &&
16866 (ctx->hflags & MIPS_HFLAG_BMASK)) {
16867 generate_exception_end(ctx, EXCP_RI);
16868 break;
16871 /* Fallthrough */
16872 case OPC_SRA:
16873 gen_shift_imm(ctx, op1, rd, rt, sa);
16874 break;
16875 case OPC_SRL:
16876 switch ((ctx->opcode >> 21) & 0x1f) {
16877 case 1:
16878 /* rotr is decoded as srl on non-R2 CPUs */
16879 if (ctx->insn_flags & ISA_MIPS32R2) {
16880 op1 = OPC_ROTR;
16882 /* Fallthrough */
16883 case 0:
16884 gen_shift_imm(ctx, op1, rd, rt, sa);
16885 break;
16886 default:
16887 generate_exception_end(ctx, EXCP_RI);
16888 break;
16890 break;
16891 case OPC_ADD ... OPC_SUBU:
16892 gen_arith(ctx, op1, rd, rs, rt);
16893 break;
16894 case OPC_SLLV: /* Shifts */
16895 case OPC_SRAV:
16896 gen_shift(ctx, op1, rd, rs, rt);
16897 break;
16898 case OPC_SRLV:
16899 switch ((ctx->opcode >> 6) & 0x1f) {
16900 case 1:
16901 /* rotrv is decoded as srlv on non-R2 CPUs */
16902 if (ctx->insn_flags & ISA_MIPS32R2) {
16903 op1 = OPC_ROTRV;
16905 /* Fallthrough */
16906 case 0:
16907 gen_shift(ctx, op1, rd, rs, rt);
16908 break;
16909 default:
16910 generate_exception_end(ctx, EXCP_RI);
16911 break;
16913 break;
16914 case OPC_SLT: /* Set on less than */
16915 case OPC_SLTU:
16916 gen_slt(ctx, op1, rd, rs, rt);
16917 break;
16918 case OPC_AND: /* Logic*/
16919 case OPC_OR:
16920 case OPC_NOR:
16921 case OPC_XOR:
16922 gen_logic(ctx, op1, rd, rs, rt);
16923 break;
16924 case OPC_JALR:
16925 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
16926 break;
16927 case OPC_TGE ... OPC_TEQ: /* Traps */
16928 case OPC_TNE:
16929 check_insn(ctx, ISA_MIPS2);
16930 gen_trap(ctx, op1, rs, rt, -1);
16931 break;
16932 case OPC_LSA: /* OPC_PMON */
16933 if ((ctx->insn_flags & ISA_MIPS32R6) ||
16934 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
16935 decode_opc_special_r6(env, ctx);
16936 } else {
16937 /* Pmon entry point, also R4010 selsl */
16938 #ifdef MIPS_STRICT_STANDARD
16939 MIPS_INVAL("PMON / selsl");
16940 generate_exception_end(ctx, EXCP_RI);
16941 #else
16942 gen_helper_0e0i(pmon, sa);
16943 #endif
16945 break;
16946 case OPC_SYSCALL:
16947 generate_exception_end(ctx, EXCP_SYSCALL);
16948 break;
16949 case OPC_BREAK:
16950 generate_exception_end(ctx, EXCP_BREAK);
16951 break;
16952 case OPC_SYNC:
16953 check_insn(ctx, ISA_MIPS2);
16954 /* Treat as NOP. */
16955 break;
16957 #if defined(TARGET_MIPS64)
16958 /* MIPS64 specific opcodes */
16959 case OPC_DSLL:
16960 case OPC_DSRA:
16961 case OPC_DSLL32:
16962 case OPC_DSRA32:
16963 check_insn(ctx, ISA_MIPS3);
16964 check_mips_64(ctx);
16965 gen_shift_imm(ctx, op1, rd, rt, sa);
16966 break;
16967 case OPC_DSRL:
16968 switch ((ctx->opcode >> 21) & 0x1f) {
16969 case 1:
16970 /* drotr is decoded as dsrl on non-R2 CPUs */
16971 if (ctx->insn_flags & ISA_MIPS32R2) {
16972 op1 = OPC_DROTR;
16974 /* Fallthrough */
16975 case 0:
16976 check_insn(ctx, ISA_MIPS3);
16977 check_mips_64(ctx);
16978 gen_shift_imm(ctx, op1, rd, rt, sa);
16979 break;
16980 default:
16981 generate_exception_end(ctx, EXCP_RI);
16982 break;
16984 break;
16985 case OPC_DSRL32:
16986 switch ((ctx->opcode >> 21) & 0x1f) {
16987 case 1:
16988 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
16989 if (ctx->insn_flags & ISA_MIPS32R2) {
16990 op1 = OPC_DROTR32;
16992 /* Fallthrough */
16993 case 0:
16994 check_insn(ctx, ISA_MIPS3);
16995 check_mips_64(ctx);
16996 gen_shift_imm(ctx, op1, rd, rt, sa);
16997 break;
16998 default:
16999 generate_exception_end(ctx, EXCP_RI);
17000 break;
17002 break;
17003 case OPC_DADD ... OPC_DSUBU:
17004 check_insn(ctx, ISA_MIPS3);
17005 check_mips_64(ctx);
17006 gen_arith(ctx, op1, rd, rs, rt);
17007 break;
17008 case OPC_DSLLV:
17009 case OPC_DSRAV:
17010 check_insn(ctx, ISA_MIPS3);
17011 check_mips_64(ctx);
17012 gen_shift(ctx, op1, rd, rs, rt);
17013 break;
17014 case OPC_DSRLV:
17015 switch ((ctx->opcode >> 6) & 0x1f) {
17016 case 1:
17017 /* drotrv is decoded as dsrlv on non-R2 CPUs */
17018 if (ctx->insn_flags & ISA_MIPS32R2) {
17019 op1 = OPC_DROTRV;
17021 /* Fallthrough */
17022 case 0:
17023 check_insn(ctx, ISA_MIPS3);
17024 check_mips_64(ctx);
17025 gen_shift(ctx, op1, rd, rs, rt);
17026 break;
17027 default:
17028 generate_exception_end(ctx, EXCP_RI);
17029 break;
17031 break;
17032 case OPC_DLSA:
17033 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17034 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17035 decode_opc_special_r6(env, ctx);
17037 break;
17038 #endif
17039 default:
17040 if (ctx->insn_flags & ISA_MIPS32R6) {
17041 decode_opc_special_r6(env, ctx);
17042 } else {
17043 decode_opc_special_legacy(env, ctx);
17048 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
17050 int rs, rt, rd;
17051 uint32_t op1;
17053 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17055 rs = (ctx->opcode >> 21) & 0x1f;
17056 rt = (ctx->opcode >> 16) & 0x1f;
17057 rd = (ctx->opcode >> 11) & 0x1f;
17059 op1 = MASK_SPECIAL2(ctx->opcode);
17060 switch (op1) {
17061 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
17062 case OPC_MSUB ... OPC_MSUBU:
17063 check_insn(ctx, ISA_MIPS32);
17064 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17065 break;
17066 case OPC_MUL:
17067 gen_arith(ctx, op1, rd, rs, rt);
17068 break;
17069 case OPC_DIV_G_2F:
17070 case OPC_DIVU_G_2F:
17071 case OPC_MULT_G_2F:
17072 case OPC_MULTU_G_2F:
17073 case OPC_MOD_G_2F:
17074 case OPC_MODU_G_2F:
17075 check_insn(ctx, INSN_LOONGSON2F);
17076 gen_loongson_integer(ctx, op1, rd, rs, rt);
17077 break;
17078 case OPC_CLO:
17079 case OPC_CLZ:
17080 check_insn(ctx, ISA_MIPS32);
17081 gen_cl(ctx, op1, rd, rs);
17082 break;
17083 case OPC_SDBBP:
17084 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17085 gen_helper_do_semihosting(cpu_env);
17086 } else {
17087 /* XXX: not clear which exception should be raised
17088 * when in debug mode...
17090 check_insn(ctx, ISA_MIPS32);
17091 generate_exception_end(ctx, EXCP_DBp);
17093 break;
17094 #if defined(TARGET_MIPS64)
17095 case OPC_DCLO:
17096 case OPC_DCLZ:
17097 check_insn(ctx, ISA_MIPS64);
17098 check_mips_64(ctx);
17099 gen_cl(ctx, op1, rd, rs);
17100 break;
17101 case OPC_DMULT_G_2F:
17102 case OPC_DMULTU_G_2F:
17103 case OPC_DDIV_G_2F:
17104 case OPC_DDIVU_G_2F:
17105 case OPC_DMOD_G_2F:
17106 case OPC_DMODU_G_2F:
17107 check_insn(ctx, INSN_LOONGSON2F);
17108 gen_loongson_integer(ctx, op1, rd, rs, rt);
17109 break;
17110 #endif
17111 default: /* Invalid */
17112 MIPS_INVAL("special2_legacy");
17113 generate_exception_end(ctx, EXCP_RI);
17114 break;
17118 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
17120 int rs, rt, rd, sa;
17121 uint32_t op1, op2;
17122 int16_t imm;
17124 rs = (ctx->opcode >> 21) & 0x1f;
17125 rt = (ctx->opcode >> 16) & 0x1f;
17126 rd = (ctx->opcode >> 11) & 0x1f;
17127 sa = (ctx->opcode >> 6) & 0x1f;
17128 imm = (int16_t)ctx->opcode >> 7;
17130 op1 = MASK_SPECIAL3(ctx->opcode);
17131 switch (op1) {
17132 case R6_OPC_PREF:
17133 if (rt >= 24) {
17134 /* hint codes 24-31 are reserved and signal RI */
17135 generate_exception_end(ctx, EXCP_RI);
17137 /* Treat as NOP. */
17138 break;
17139 case R6_OPC_CACHE:
17140 /* Treat as NOP. */
17141 break;
17142 case R6_OPC_SC:
17143 gen_st_cond(ctx, op1, rt, rs, imm);
17144 break;
17145 case R6_OPC_LL:
17146 gen_ld(ctx, op1, rt, rs, imm);
17147 break;
17148 case OPC_BSHFL:
17150 if (rd == 0) {
17151 /* Treat as NOP. */
17152 break;
17154 op2 = MASK_BSHFL(ctx->opcode);
17155 switch (op2) {
17156 case OPC_ALIGN ... OPC_ALIGN_END:
17157 gen_align(ctx, OPC_ALIGN, rd, rs, rt, sa & 3);
17158 break;
17159 case OPC_BITSWAP:
17160 gen_bitswap(ctx, op2, rd, rt);
17161 break;
17164 break;
17165 #if defined(TARGET_MIPS64)
17166 case R6_OPC_SCD:
17167 gen_st_cond(ctx, op1, rt, rs, imm);
17168 break;
17169 case R6_OPC_LLD:
17170 gen_ld(ctx, op1, rt, rs, imm);
17171 break;
17172 case OPC_DBSHFL:
17173 check_mips_64(ctx);
17175 if (rd == 0) {
17176 /* Treat as NOP. */
17177 break;
17179 op2 = MASK_DBSHFL(ctx->opcode);
17180 switch (op2) {
17181 case OPC_DALIGN ... OPC_DALIGN_END:
17182 gen_align(ctx, OPC_DALIGN, rd, rs, rt, sa & 7);
17183 break;
17184 case OPC_DBITSWAP:
17185 gen_bitswap(ctx, op2, rd, rt);
17186 break;
17190 break;
17191 #endif
17192 default: /* Invalid */
17193 MIPS_INVAL("special3_r6");
17194 generate_exception_end(ctx, EXCP_RI);
17195 break;
17199 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
17201 int rs, rt, rd;
17202 uint32_t op1, op2;
17204 rs = (ctx->opcode >> 21) & 0x1f;
17205 rt = (ctx->opcode >> 16) & 0x1f;
17206 rd = (ctx->opcode >> 11) & 0x1f;
17208 op1 = MASK_SPECIAL3(ctx->opcode);
17209 switch (op1) {
17210 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
17211 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
17212 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
17213 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
17214 * the same mask and op1. */
17215 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
17216 op2 = MASK_ADDUH_QB(ctx->opcode);
17217 switch (op2) {
17218 case OPC_ADDUH_QB:
17219 case OPC_ADDUH_R_QB:
17220 case OPC_ADDQH_PH:
17221 case OPC_ADDQH_R_PH:
17222 case OPC_ADDQH_W:
17223 case OPC_ADDQH_R_W:
17224 case OPC_SUBUH_QB:
17225 case OPC_SUBUH_R_QB:
17226 case OPC_SUBQH_PH:
17227 case OPC_SUBQH_R_PH:
17228 case OPC_SUBQH_W:
17229 case OPC_SUBQH_R_W:
17230 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17231 break;
17232 case OPC_MUL_PH:
17233 case OPC_MUL_S_PH:
17234 case OPC_MULQ_S_W:
17235 case OPC_MULQ_RS_W:
17236 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17237 break;
17238 default:
17239 MIPS_INVAL("MASK ADDUH.QB");
17240 generate_exception_end(ctx, EXCP_RI);
17241 break;
17243 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
17244 gen_loongson_integer(ctx, op1, rd, rs, rt);
17245 } else {
17246 generate_exception_end(ctx, EXCP_RI);
17248 break;
17249 case OPC_LX_DSP:
17250 op2 = MASK_LX(ctx->opcode);
17251 switch (op2) {
17252 #if defined(TARGET_MIPS64)
17253 case OPC_LDX:
17254 #endif
17255 case OPC_LBUX:
17256 case OPC_LHX:
17257 case OPC_LWX:
17258 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
17259 break;
17260 default: /* Invalid */
17261 MIPS_INVAL("MASK LX");
17262 generate_exception_end(ctx, EXCP_RI);
17263 break;
17265 break;
17266 case OPC_ABSQ_S_PH_DSP:
17267 op2 = MASK_ABSQ_S_PH(ctx->opcode);
17268 switch (op2) {
17269 case OPC_ABSQ_S_QB:
17270 case OPC_ABSQ_S_PH:
17271 case OPC_ABSQ_S_W:
17272 case OPC_PRECEQ_W_PHL:
17273 case OPC_PRECEQ_W_PHR:
17274 case OPC_PRECEQU_PH_QBL:
17275 case OPC_PRECEQU_PH_QBR:
17276 case OPC_PRECEQU_PH_QBLA:
17277 case OPC_PRECEQU_PH_QBRA:
17278 case OPC_PRECEU_PH_QBL:
17279 case OPC_PRECEU_PH_QBR:
17280 case OPC_PRECEU_PH_QBLA:
17281 case OPC_PRECEU_PH_QBRA:
17282 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17283 break;
17284 case OPC_BITREV:
17285 case OPC_REPL_QB:
17286 case OPC_REPLV_QB:
17287 case OPC_REPL_PH:
17288 case OPC_REPLV_PH:
17289 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17290 break;
17291 default:
17292 MIPS_INVAL("MASK ABSQ_S.PH");
17293 generate_exception_end(ctx, EXCP_RI);
17294 break;
17296 break;
17297 case OPC_ADDU_QB_DSP:
17298 op2 = MASK_ADDU_QB(ctx->opcode);
17299 switch (op2) {
17300 case OPC_ADDQ_PH:
17301 case OPC_ADDQ_S_PH:
17302 case OPC_ADDQ_S_W:
17303 case OPC_ADDU_QB:
17304 case OPC_ADDU_S_QB:
17305 case OPC_ADDU_PH:
17306 case OPC_ADDU_S_PH:
17307 case OPC_SUBQ_PH:
17308 case OPC_SUBQ_S_PH:
17309 case OPC_SUBQ_S_W:
17310 case OPC_SUBU_QB:
17311 case OPC_SUBU_S_QB:
17312 case OPC_SUBU_PH:
17313 case OPC_SUBU_S_PH:
17314 case OPC_ADDSC:
17315 case OPC_ADDWC:
17316 case OPC_MODSUB:
17317 case OPC_RADDU_W_QB:
17318 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17319 break;
17320 case OPC_MULEU_S_PH_QBL:
17321 case OPC_MULEU_S_PH_QBR:
17322 case OPC_MULQ_RS_PH:
17323 case OPC_MULEQ_S_W_PHL:
17324 case OPC_MULEQ_S_W_PHR:
17325 case OPC_MULQ_S_PH:
17326 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17327 break;
17328 default: /* Invalid */
17329 MIPS_INVAL("MASK ADDU.QB");
17330 generate_exception_end(ctx, EXCP_RI);
17331 break;
17334 break;
17335 case OPC_CMPU_EQ_QB_DSP:
17336 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
17337 switch (op2) {
17338 case OPC_PRECR_SRA_PH_W:
17339 case OPC_PRECR_SRA_R_PH_W:
17340 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17341 break;
17342 case OPC_PRECR_QB_PH:
17343 case OPC_PRECRQ_QB_PH:
17344 case OPC_PRECRQ_PH_W:
17345 case OPC_PRECRQ_RS_PH_W:
17346 case OPC_PRECRQU_S_QB_PH:
17347 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17348 break;
17349 case OPC_CMPU_EQ_QB:
17350 case OPC_CMPU_LT_QB:
17351 case OPC_CMPU_LE_QB:
17352 case OPC_CMP_EQ_PH:
17353 case OPC_CMP_LT_PH:
17354 case OPC_CMP_LE_PH:
17355 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17356 break;
17357 case OPC_CMPGU_EQ_QB:
17358 case OPC_CMPGU_LT_QB:
17359 case OPC_CMPGU_LE_QB:
17360 case OPC_CMPGDU_EQ_QB:
17361 case OPC_CMPGDU_LT_QB:
17362 case OPC_CMPGDU_LE_QB:
17363 case OPC_PICK_QB:
17364 case OPC_PICK_PH:
17365 case OPC_PACKRL_PH:
17366 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17367 break;
17368 default: /* Invalid */
17369 MIPS_INVAL("MASK CMPU.EQ.QB");
17370 generate_exception_end(ctx, EXCP_RI);
17371 break;
17373 break;
17374 case OPC_SHLL_QB_DSP:
17375 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17376 break;
17377 case OPC_DPA_W_PH_DSP:
17378 op2 = MASK_DPA_W_PH(ctx->opcode);
17379 switch (op2) {
17380 case OPC_DPAU_H_QBL:
17381 case OPC_DPAU_H_QBR:
17382 case OPC_DPSU_H_QBL:
17383 case OPC_DPSU_H_QBR:
17384 case OPC_DPA_W_PH:
17385 case OPC_DPAX_W_PH:
17386 case OPC_DPAQ_S_W_PH:
17387 case OPC_DPAQX_S_W_PH:
17388 case OPC_DPAQX_SA_W_PH:
17389 case OPC_DPS_W_PH:
17390 case OPC_DPSX_W_PH:
17391 case OPC_DPSQ_S_W_PH:
17392 case OPC_DPSQX_S_W_PH:
17393 case OPC_DPSQX_SA_W_PH:
17394 case OPC_MULSAQ_S_W_PH:
17395 case OPC_DPAQ_SA_L_W:
17396 case OPC_DPSQ_SA_L_W:
17397 case OPC_MAQ_S_W_PHL:
17398 case OPC_MAQ_S_W_PHR:
17399 case OPC_MAQ_SA_W_PHL:
17400 case OPC_MAQ_SA_W_PHR:
17401 case OPC_MULSA_W_PH:
17402 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17403 break;
17404 default: /* Invalid */
17405 MIPS_INVAL("MASK DPAW.PH");
17406 generate_exception_end(ctx, EXCP_RI);
17407 break;
17409 break;
17410 case OPC_INSV_DSP:
17411 op2 = MASK_INSV(ctx->opcode);
17412 switch (op2) {
17413 case OPC_INSV:
17414 check_dsp(ctx);
17416 TCGv t0, t1;
17418 if (rt == 0) {
17419 break;
17422 t0 = tcg_temp_new();
17423 t1 = tcg_temp_new();
17425 gen_load_gpr(t0, rt);
17426 gen_load_gpr(t1, rs);
17428 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
17430 tcg_temp_free(t0);
17431 tcg_temp_free(t1);
17432 break;
17434 default: /* Invalid */
17435 MIPS_INVAL("MASK INSV");
17436 generate_exception_end(ctx, EXCP_RI);
17437 break;
17439 break;
17440 case OPC_APPEND_DSP:
17441 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17442 break;
17443 case OPC_EXTR_W_DSP:
17444 op2 = MASK_EXTR_W(ctx->opcode);
17445 switch (op2) {
17446 case OPC_EXTR_W:
17447 case OPC_EXTR_R_W:
17448 case OPC_EXTR_RS_W:
17449 case OPC_EXTR_S_H:
17450 case OPC_EXTRV_S_H:
17451 case OPC_EXTRV_W:
17452 case OPC_EXTRV_R_W:
17453 case OPC_EXTRV_RS_W:
17454 case OPC_EXTP:
17455 case OPC_EXTPV:
17456 case OPC_EXTPDP:
17457 case OPC_EXTPDPV:
17458 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17459 break;
17460 case OPC_RDDSP:
17461 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
17462 break;
17463 case OPC_SHILO:
17464 case OPC_SHILOV:
17465 case OPC_MTHLIP:
17466 case OPC_WRDSP:
17467 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17468 break;
17469 default: /* Invalid */
17470 MIPS_INVAL("MASK EXTR.W");
17471 generate_exception_end(ctx, EXCP_RI);
17472 break;
17474 break;
17475 #if defined(TARGET_MIPS64)
17476 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
17477 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
17478 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
17479 check_insn(ctx, INSN_LOONGSON2E);
17480 gen_loongson_integer(ctx, op1, rd, rs, rt);
17481 break;
17482 case OPC_ABSQ_S_QH_DSP:
17483 op2 = MASK_ABSQ_S_QH(ctx->opcode);
17484 switch (op2) {
17485 case OPC_PRECEQ_L_PWL:
17486 case OPC_PRECEQ_L_PWR:
17487 case OPC_PRECEQ_PW_QHL:
17488 case OPC_PRECEQ_PW_QHR:
17489 case OPC_PRECEQ_PW_QHLA:
17490 case OPC_PRECEQ_PW_QHRA:
17491 case OPC_PRECEQU_QH_OBL:
17492 case OPC_PRECEQU_QH_OBR:
17493 case OPC_PRECEQU_QH_OBLA:
17494 case OPC_PRECEQU_QH_OBRA:
17495 case OPC_PRECEU_QH_OBL:
17496 case OPC_PRECEU_QH_OBR:
17497 case OPC_PRECEU_QH_OBLA:
17498 case OPC_PRECEU_QH_OBRA:
17499 case OPC_ABSQ_S_OB:
17500 case OPC_ABSQ_S_PW:
17501 case OPC_ABSQ_S_QH:
17502 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17503 break;
17504 case OPC_REPL_OB:
17505 case OPC_REPL_PW:
17506 case OPC_REPL_QH:
17507 case OPC_REPLV_OB:
17508 case OPC_REPLV_PW:
17509 case OPC_REPLV_QH:
17510 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17511 break;
17512 default: /* Invalid */
17513 MIPS_INVAL("MASK ABSQ_S.QH");
17514 generate_exception_end(ctx, EXCP_RI);
17515 break;
17517 break;
17518 case OPC_ADDU_OB_DSP:
17519 op2 = MASK_ADDU_OB(ctx->opcode);
17520 switch (op2) {
17521 case OPC_RADDU_L_OB:
17522 case OPC_SUBQ_PW:
17523 case OPC_SUBQ_S_PW:
17524 case OPC_SUBQ_QH:
17525 case OPC_SUBQ_S_QH:
17526 case OPC_SUBU_OB:
17527 case OPC_SUBU_S_OB:
17528 case OPC_SUBU_QH:
17529 case OPC_SUBU_S_QH:
17530 case OPC_SUBUH_OB:
17531 case OPC_SUBUH_R_OB:
17532 case OPC_ADDQ_PW:
17533 case OPC_ADDQ_S_PW:
17534 case OPC_ADDQ_QH:
17535 case OPC_ADDQ_S_QH:
17536 case OPC_ADDU_OB:
17537 case OPC_ADDU_S_OB:
17538 case OPC_ADDU_QH:
17539 case OPC_ADDU_S_QH:
17540 case OPC_ADDUH_OB:
17541 case OPC_ADDUH_R_OB:
17542 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17543 break;
17544 case OPC_MULEQ_S_PW_QHL:
17545 case OPC_MULEQ_S_PW_QHR:
17546 case OPC_MULEU_S_QH_OBL:
17547 case OPC_MULEU_S_QH_OBR:
17548 case OPC_MULQ_RS_QH:
17549 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17550 break;
17551 default: /* Invalid */
17552 MIPS_INVAL("MASK ADDU.OB");
17553 generate_exception_end(ctx, EXCP_RI);
17554 break;
17556 break;
17557 case OPC_CMPU_EQ_OB_DSP:
17558 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
17559 switch (op2) {
17560 case OPC_PRECR_SRA_QH_PW:
17561 case OPC_PRECR_SRA_R_QH_PW:
17562 /* Return value is rt. */
17563 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17564 break;
17565 case OPC_PRECR_OB_QH:
17566 case OPC_PRECRQ_OB_QH:
17567 case OPC_PRECRQ_PW_L:
17568 case OPC_PRECRQ_QH_PW:
17569 case OPC_PRECRQ_RS_QH_PW:
17570 case OPC_PRECRQU_S_OB_QH:
17571 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17572 break;
17573 case OPC_CMPU_EQ_OB:
17574 case OPC_CMPU_LT_OB:
17575 case OPC_CMPU_LE_OB:
17576 case OPC_CMP_EQ_QH:
17577 case OPC_CMP_LT_QH:
17578 case OPC_CMP_LE_QH:
17579 case OPC_CMP_EQ_PW:
17580 case OPC_CMP_LT_PW:
17581 case OPC_CMP_LE_PW:
17582 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17583 break;
17584 case OPC_CMPGDU_EQ_OB:
17585 case OPC_CMPGDU_LT_OB:
17586 case OPC_CMPGDU_LE_OB:
17587 case OPC_CMPGU_EQ_OB:
17588 case OPC_CMPGU_LT_OB:
17589 case OPC_CMPGU_LE_OB:
17590 case OPC_PACKRL_PW:
17591 case OPC_PICK_OB:
17592 case OPC_PICK_PW:
17593 case OPC_PICK_QH:
17594 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17595 break;
17596 default: /* Invalid */
17597 MIPS_INVAL("MASK CMPU_EQ.OB");
17598 generate_exception_end(ctx, EXCP_RI);
17599 break;
17601 break;
17602 case OPC_DAPPEND_DSP:
17603 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17604 break;
17605 case OPC_DEXTR_W_DSP:
17606 op2 = MASK_DEXTR_W(ctx->opcode);
17607 switch (op2) {
17608 case OPC_DEXTP:
17609 case OPC_DEXTPDP:
17610 case OPC_DEXTPDPV:
17611 case OPC_DEXTPV:
17612 case OPC_DEXTR_L:
17613 case OPC_DEXTR_R_L:
17614 case OPC_DEXTR_RS_L:
17615 case OPC_DEXTR_W:
17616 case OPC_DEXTR_R_W:
17617 case OPC_DEXTR_RS_W:
17618 case OPC_DEXTR_S_H:
17619 case OPC_DEXTRV_L:
17620 case OPC_DEXTRV_R_L:
17621 case OPC_DEXTRV_RS_L:
17622 case OPC_DEXTRV_S_H:
17623 case OPC_DEXTRV_W:
17624 case OPC_DEXTRV_R_W:
17625 case OPC_DEXTRV_RS_W:
17626 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17627 break;
17628 case OPC_DMTHLIP:
17629 case OPC_DSHILO:
17630 case OPC_DSHILOV:
17631 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17632 break;
17633 default: /* Invalid */
17634 MIPS_INVAL("MASK EXTR.W");
17635 generate_exception_end(ctx, EXCP_RI);
17636 break;
17638 break;
17639 case OPC_DPAQ_W_QH_DSP:
17640 op2 = MASK_DPAQ_W_QH(ctx->opcode);
17641 switch (op2) {
17642 case OPC_DPAU_H_OBL:
17643 case OPC_DPAU_H_OBR:
17644 case OPC_DPSU_H_OBL:
17645 case OPC_DPSU_H_OBR:
17646 case OPC_DPA_W_QH:
17647 case OPC_DPAQ_S_W_QH:
17648 case OPC_DPS_W_QH:
17649 case OPC_DPSQ_S_W_QH:
17650 case OPC_MULSAQ_S_W_QH:
17651 case OPC_DPAQ_SA_L_PW:
17652 case OPC_DPSQ_SA_L_PW:
17653 case OPC_MULSAQ_S_L_PW:
17654 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17655 break;
17656 case OPC_MAQ_S_W_QHLL:
17657 case OPC_MAQ_S_W_QHLR:
17658 case OPC_MAQ_S_W_QHRL:
17659 case OPC_MAQ_S_W_QHRR:
17660 case OPC_MAQ_SA_W_QHLL:
17661 case OPC_MAQ_SA_W_QHLR:
17662 case OPC_MAQ_SA_W_QHRL:
17663 case OPC_MAQ_SA_W_QHRR:
17664 case OPC_MAQ_S_L_PWL:
17665 case OPC_MAQ_S_L_PWR:
17666 case OPC_DMADD:
17667 case OPC_DMADDU:
17668 case OPC_DMSUB:
17669 case OPC_DMSUBU:
17670 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17671 break;
17672 default: /* Invalid */
17673 MIPS_INVAL("MASK DPAQ.W.QH");
17674 generate_exception_end(ctx, EXCP_RI);
17675 break;
17677 break;
17678 case OPC_DINSV_DSP:
17679 op2 = MASK_INSV(ctx->opcode);
17680 switch (op2) {
17681 case OPC_DINSV:
17683 TCGv t0, t1;
17685 if (rt == 0) {
17686 break;
17688 check_dsp(ctx);
17690 t0 = tcg_temp_new();
17691 t1 = tcg_temp_new();
17693 gen_load_gpr(t0, rt);
17694 gen_load_gpr(t1, rs);
17696 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
17698 tcg_temp_free(t0);
17699 tcg_temp_free(t1);
17700 break;
17702 default: /* Invalid */
17703 MIPS_INVAL("MASK DINSV");
17704 generate_exception_end(ctx, EXCP_RI);
17705 break;
17707 break;
17708 case OPC_SHLL_OB_DSP:
17709 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17710 break;
17711 #endif
17712 default: /* Invalid */
17713 MIPS_INVAL("special3_legacy");
17714 generate_exception_end(ctx, EXCP_RI);
17715 break;
17719 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
17721 int rs, rt, rd, sa;
17722 uint32_t op1, op2;
17724 rs = (ctx->opcode >> 21) & 0x1f;
17725 rt = (ctx->opcode >> 16) & 0x1f;
17726 rd = (ctx->opcode >> 11) & 0x1f;
17727 sa = (ctx->opcode >> 6) & 0x1f;
17729 op1 = MASK_SPECIAL3(ctx->opcode);
17730 switch (op1) {
17731 case OPC_EXT:
17732 case OPC_INS:
17733 check_insn(ctx, ISA_MIPS32R2);
17734 gen_bitops(ctx, op1, rt, rs, sa, rd);
17735 break;
17736 case OPC_BSHFL:
17737 op2 = MASK_BSHFL(ctx->opcode);
17738 switch (op2) {
17739 case OPC_ALIGN ... OPC_ALIGN_END:
17740 case OPC_BITSWAP:
17741 check_insn(ctx, ISA_MIPS32R6);
17742 decode_opc_special3_r6(env, ctx);
17743 break;
17744 default:
17745 check_insn(ctx, ISA_MIPS32R2);
17746 gen_bshfl(ctx, op2, rt, rd);
17747 break;
17749 break;
17750 #if defined(TARGET_MIPS64)
17751 case OPC_DEXTM ... OPC_DEXT:
17752 case OPC_DINSM ... OPC_DINS:
17753 check_insn(ctx, ISA_MIPS64R2);
17754 check_mips_64(ctx);
17755 gen_bitops(ctx, op1, rt, rs, sa, rd);
17756 break;
17757 case OPC_DBSHFL:
17758 op2 = MASK_DBSHFL(ctx->opcode);
17759 switch (op2) {
17760 case OPC_DALIGN ... OPC_DALIGN_END:
17761 case OPC_DBITSWAP:
17762 check_insn(ctx, ISA_MIPS32R6);
17763 decode_opc_special3_r6(env, ctx);
17764 break;
17765 default:
17766 check_insn(ctx, ISA_MIPS64R2);
17767 check_mips_64(ctx);
17768 op2 = MASK_DBSHFL(ctx->opcode);
17769 gen_bshfl(ctx, op2, rt, rd);
17770 break;
17772 break;
17773 #endif
17774 case OPC_RDHWR:
17775 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
17776 break;
17777 case OPC_FORK:
17778 check_insn(ctx, ASE_MT);
17780 TCGv t0 = tcg_temp_new();
17781 TCGv t1 = tcg_temp_new();
17783 gen_load_gpr(t0, rt);
17784 gen_load_gpr(t1, rs);
17785 gen_helper_fork(t0, t1);
17786 tcg_temp_free(t0);
17787 tcg_temp_free(t1);
17789 break;
17790 case OPC_YIELD:
17791 check_insn(ctx, ASE_MT);
17793 TCGv t0 = tcg_temp_new();
17795 gen_load_gpr(t0, rs);
17796 gen_helper_yield(t0, cpu_env, t0);
17797 gen_store_gpr(t0, rd);
17798 tcg_temp_free(t0);
17800 break;
17801 default:
17802 if (ctx->insn_flags & ISA_MIPS32R6) {
17803 decode_opc_special3_r6(env, ctx);
17804 } else {
17805 decode_opc_special3_legacy(env, ctx);
17810 /* MIPS SIMD Architecture (MSA) */
17811 static inline int check_msa_access(DisasContext *ctx)
17813 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
17814 !(ctx->hflags & MIPS_HFLAG_F64))) {
17815 generate_exception_end(ctx, EXCP_RI);
17816 return 0;
17819 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
17820 if (ctx->insn_flags & ASE_MSA) {
17821 generate_exception_end(ctx, EXCP_MSADIS);
17822 return 0;
17823 } else {
17824 generate_exception_end(ctx, EXCP_RI);
17825 return 0;
17828 return 1;
17831 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
17833 /* generates tcg ops to check if any element is 0 */
17834 /* Note this function only works with MSA_WRLEN = 128 */
17835 uint64_t eval_zero_or_big = 0;
17836 uint64_t eval_big = 0;
17837 TCGv_i64 t0 = tcg_temp_new_i64();
17838 TCGv_i64 t1 = tcg_temp_new_i64();
17839 switch (df) {
17840 case DF_BYTE:
17841 eval_zero_or_big = 0x0101010101010101ULL;
17842 eval_big = 0x8080808080808080ULL;
17843 break;
17844 case DF_HALF:
17845 eval_zero_or_big = 0x0001000100010001ULL;
17846 eval_big = 0x8000800080008000ULL;
17847 break;
17848 case DF_WORD:
17849 eval_zero_or_big = 0x0000000100000001ULL;
17850 eval_big = 0x8000000080000000ULL;
17851 break;
17852 case DF_DOUBLE:
17853 eval_zero_or_big = 0x0000000000000001ULL;
17854 eval_big = 0x8000000000000000ULL;
17855 break;
17857 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
17858 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
17859 tcg_gen_andi_i64(t0, t0, eval_big);
17860 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
17861 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
17862 tcg_gen_andi_i64(t1, t1, eval_big);
17863 tcg_gen_or_i64(t0, t0, t1);
17864 /* if all bits are zero then all elements are not zero */
17865 /* if some bit is non-zero then some element is zero */
17866 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
17867 tcg_gen_trunc_i64_tl(tresult, t0);
17868 tcg_temp_free_i64(t0);
17869 tcg_temp_free_i64(t1);
17872 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
17874 uint8_t df = (ctx->opcode >> 21) & 0x3;
17875 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
17876 int64_t s16 = (int16_t)ctx->opcode;
17878 check_msa_access(ctx);
17880 if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
17881 generate_exception_end(ctx, EXCP_RI);
17882 return;
17884 switch (op1) {
17885 case OPC_BZ_V:
17886 case OPC_BNZ_V:
17888 TCGv_i64 t0 = tcg_temp_new_i64();
17889 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
17890 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
17891 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
17892 tcg_gen_trunc_i64_tl(bcond, t0);
17893 tcg_temp_free_i64(t0);
17895 break;
17896 case OPC_BZ_B:
17897 case OPC_BZ_H:
17898 case OPC_BZ_W:
17899 case OPC_BZ_D:
17900 gen_check_zero_element(bcond, df, wt);
17901 break;
17902 case OPC_BNZ_B:
17903 case OPC_BNZ_H:
17904 case OPC_BNZ_W:
17905 case OPC_BNZ_D:
17906 gen_check_zero_element(bcond, df, wt);
17907 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
17908 break;
17911 ctx->btarget = ctx->pc + (s16 << 2) + 4;
17913 ctx->hflags |= MIPS_HFLAG_BC;
17914 ctx->hflags |= MIPS_HFLAG_BDS32;
17917 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
17919 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
17920 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
17921 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17922 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17924 TCGv_i32 twd = tcg_const_i32(wd);
17925 TCGv_i32 tws = tcg_const_i32(ws);
17926 TCGv_i32 ti8 = tcg_const_i32(i8);
17928 switch (MASK_MSA_I8(ctx->opcode)) {
17929 case OPC_ANDI_B:
17930 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
17931 break;
17932 case OPC_ORI_B:
17933 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
17934 break;
17935 case OPC_NORI_B:
17936 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
17937 break;
17938 case OPC_XORI_B:
17939 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
17940 break;
17941 case OPC_BMNZI_B:
17942 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
17943 break;
17944 case OPC_BMZI_B:
17945 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
17946 break;
17947 case OPC_BSELI_B:
17948 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
17949 break;
17950 case OPC_SHF_B:
17951 case OPC_SHF_H:
17952 case OPC_SHF_W:
17954 uint8_t df = (ctx->opcode >> 24) & 0x3;
17955 if (df == DF_DOUBLE) {
17956 generate_exception_end(ctx, EXCP_RI);
17957 } else {
17958 TCGv_i32 tdf = tcg_const_i32(df);
17959 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
17960 tcg_temp_free_i32(tdf);
17963 break;
17964 default:
17965 MIPS_INVAL("MSA instruction");
17966 generate_exception_end(ctx, EXCP_RI);
17967 break;
17970 tcg_temp_free_i32(twd);
17971 tcg_temp_free_i32(tws);
17972 tcg_temp_free_i32(ti8);
17975 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
17977 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
17978 uint8_t df = (ctx->opcode >> 21) & 0x3;
17979 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
17980 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
17981 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
17982 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
17984 TCGv_i32 tdf = tcg_const_i32(df);
17985 TCGv_i32 twd = tcg_const_i32(wd);
17986 TCGv_i32 tws = tcg_const_i32(ws);
17987 TCGv_i32 timm = tcg_temp_new_i32();
17988 tcg_gen_movi_i32(timm, u5);
17990 switch (MASK_MSA_I5(ctx->opcode)) {
17991 case OPC_ADDVI_df:
17992 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
17993 break;
17994 case OPC_SUBVI_df:
17995 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
17996 break;
17997 case OPC_MAXI_S_df:
17998 tcg_gen_movi_i32(timm, s5);
17999 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
18000 break;
18001 case OPC_MAXI_U_df:
18002 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
18003 break;
18004 case OPC_MINI_S_df:
18005 tcg_gen_movi_i32(timm, s5);
18006 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
18007 break;
18008 case OPC_MINI_U_df:
18009 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
18010 break;
18011 case OPC_CEQI_df:
18012 tcg_gen_movi_i32(timm, s5);
18013 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
18014 break;
18015 case OPC_CLTI_S_df:
18016 tcg_gen_movi_i32(timm, s5);
18017 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
18018 break;
18019 case OPC_CLTI_U_df:
18020 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
18021 break;
18022 case OPC_CLEI_S_df:
18023 tcg_gen_movi_i32(timm, s5);
18024 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
18025 break;
18026 case OPC_CLEI_U_df:
18027 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
18028 break;
18029 case OPC_LDI_df:
18031 int32_t s10 = sextract32(ctx->opcode, 11, 10);
18032 tcg_gen_movi_i32(timm, s10);
18033 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
18035 break;
18036 default:
18037 MIPS_INVAL("MSA instruction");
18038 generate_exception_end(ctx, EXCP_RI);
18039 break;
18042 tcg_temp_free_i32(tdf);
18043 tcg_temp_free_i32(twd);
18044 tcg_temp_free_i32(tws);
18045 tcg_temp_free_i32(timm);
18048 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
18050 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18051 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
18052 uint32_t df = 0, m = 0;
18053 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18054 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18056 TCGv_i32 tdf;
18057 TCGv_i32 tm;
18058 TCGv_i32 twd;
18059 TCGv_i32 tws;
18061 if ((dfm & 0x40) == 0x00) {
18062 m = dfm & 0x3f;
18063 df = DF_DOUBLE;
18064 } else if ((dfm & 0x60) == 0x40) {
18065 m = dfm & 0x1f;
18066 df = DF_WORD;
18067 } else if ((dfm & 0x70) == 0x60) {
18068 m = dfm & 0x0f;
18069 df = DF_HALF;
18070 } else if ((dfm & 0x78) == 0x70) {
18071 m = dfm & 0x7;
18072 df = DF_BYTE;
18073 } else {
18074 generate_exception_end(ctx, EXCP_RI);
18075 return;
18078 tdf = tcg_const_i32(df);
18079 tm = tcg_const_i32(m);
18080 twd = tcg_const_i32(wd);
18081 tws = tcg_const_i32(ws);
18083 switch (MASK_MSA_BIT(ctx->opcode)) {
18084 case OPC_SLLI_df:
18085 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
18086 break;
18087 case OPC_SRAI_df:
18088 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
18089 break;
18090 case OPC_SRLI_df:
18091 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
18092 break;
18093 case OPC_BCLRI_df:
18094 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
18095 break;
18096 case OPC_BSETI_df:
18097 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
18098 break;
18099 case OPC_BNEGI_df:
18100 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
18101 break;
18102 case OPC_BINSLI_df:
18103 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
18104 break;
18105 case OPC_BINSRI_df:
18106 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
18107 break;
18108 case OPC_SAT_S_df:
18109 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
18110 break;
18111 case OPC_SAT_U_df:
18112 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
18113 break;
18114 case OPC_SRARI_df:
18115 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
18116 break;
18117 case OPC_SRLRI_df:
18118 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
18119 break;
18120 default:
18121 MIPS_INVAL("MSA instruction");
18122 generate_exception_end(ctx, EXCP_RI);
18123 break;
18126 tcg_temp_free_i32(tdf);
18127 tcg_temp_free_i32(tm);
18128 tcg_temp_free_i32(twd);
18129 tcg_temp_free_i32(tws);
18132 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
18134 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18135 uint8_t df = (ctx->opcode >> 21) & 0x3;
18136 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18137 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18138 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18140 TCGv_i32 tdf = tcg_const_i32(df);
18141 TCGv_i32 twd = tcg_const_i32(wd);
18142 TCGv_i32 tws = tcg_const_i32(ws);
18143 TCGv_i32 twt = tcg_const_i32(wt);
18145 switch (MASK_MSA_3R(ctx->opcode)) {
18146 case OPC_SLL_df:
18147 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
18148 break;
18149 case OPC_ADDV_df:
18150 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
18151 break;
18152 case OPC_CEQ_df:
18153 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
18154 break;
18155 case OPC_ADD_A_df:
18156 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
18157 break;
18158 case OPC_SUBS_S_df:
18159 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
18160 break;
18161 case OPC_MULV_df:
18162 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
18163 break;
18164 case OPC_SLD_df:
18165 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
18166 break;
18167 case OPC_VSHF_df:
18168 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
18169 break;
18170 case OPC_SRA_df:
18171 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
18172 break;
18173 case OPC_SUBV_df:
18174 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
18175 break;
18176 case OPC_ADDS_A_df:
18177 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
18178 break;
18179 case OPC_SUBS_U_df:
18180 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
18181 break;
18182 case OPC_MADDV_df:
18183 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
18184 break;
18185 case OPC_SPLAT_df:
18186 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
18187 break;
18188 case OPC_SRAR_df:
18189 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
18190 break;
18191 case OPC_SRL_df:
18192 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
18193 break;
18194 case OPC_MAX_S_df:
18195 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
18196 break;
18197 case OPC_CLT_S_df:
18198 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
18199 break;
18200 case OPC_ADDS_S_df:
18201 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
18202 break;
18203 case OPC_SUBSUS_U_df:
18204 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
18205 break;
18206 case OPC_MSUBV_df:
18207 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
18208 break;
18209 case OPC_PCKEV_df:
18210 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
18211 break;
18212 case OPC_SRLR_df:
18213 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
18214 break;
18215 case OPC_BCLR_df:
18216 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
18217 break;
18218 case OPC_MAX_U_df:
18219 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
18220 break;
18221 case OPC_CLT_U_df:
18222 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
18223 break;
18224 case OPC_ADDS_U_df:
18225 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
18226 break;
18227 case OPC_SUBSUU_S_df:
18228 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
18229 break;
18230 case OPC_PCKOD_df:
18231 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
18232 break;
18233 case OPC_BSET_df:
18234 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
18235 break;
18236 case OPC_MIN_S_df:
18237 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
18238 break;
18239 case OPC_CLE_S_df:
18240 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
18241 break;
18242 case OPC_AVE_S_df:
18243 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
18244 break;
18245 case OPC_ASUB_S_df:
18246 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
18247 break;
18248 case OPC_DIV_S_df:
18249 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
18250 break;
18251 case OPC_ILVL_df:
18252 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
18253 break;
18254 case OPC_BNEG_df:
18255 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
18256 break;
18257 case OPC_MIN_U_df:
18258 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
18259 break;
18260 case OPC_CLE_U_df:
18261 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
18262 break;
18263 case OPC_AVE_U_df:
18264 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
18265 break;
18266 case OPC_ASUB_U_df:
18267 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
18268 break;
18269 case OPC_DIV_U_df:
18270 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
18271 break;
18272 case OPC_ILVR_df:
18273 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
18274 break;
18275 case OPC_BINSL_df:
18276 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
18277 break;
18278 case OPC_MAX_A_df:
18279 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
18280 break;
18281 case OPC_AVER_S_df:
18282 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
18283 break;
18284 case OPC_MOD_S_df:
18285 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
18286 break;
18287 case OPC_ILVEV_df:
18288 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
18289 break;
18290 case OPC_BINSR_df:
18291 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
18292 break;
18293 case OPC_MIN_A_df:
18294 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
18295 break;
18296 case OPC_AVER_U_df:
18297 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
18298 break;
18299 case OPC_MOD_U_df:
18300 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
18301 break;
18302 case OPC_ILVOD_df:
18303 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
18304 break;
18306 case OPC_DOTP_S_df:
18307 case OPC_DOTP_U_df:
18308 case OPC_DPADD_S_df:
18309 case OPC_DPADD_U_df:
18310 case OPC_DPSUB_S_df:
18311 case OPC_HADD_S_df:
18312 case OPC_DPSUB_U_df:
18313 case OPC_HADD_U_df:
18314 case OPC_HSUB_S_df:
18315 case OPC_HSUB_U_df:
18316 if (df == DF_BYTE) {
18317 generate_exception_end(ctx, EXCP_RI);
18318 break;
18320 switch (MASK_MSA_3R(ctx->opcode)) {
18321 case OPC_DOTP_S_df:
18322 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
18323 break;
18324 case OPC_DOTP_U_df:
18325 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
18326 break;
18327 case OPC_DPADD_S_df:
18328 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
18329 break;
18330 case OPC_DPADD_U_df:
18331 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
18332 break;
18333 case OPC_DPSUB_S_df:
18334 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
18335 break;
18336 case OPC_HADD_S_df:
18337 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
18338 break;
18339 case OPC_DPSUB_U_df:
18340 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
18341 break;
18342 case OPC_HADD_U_df:
18343 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
18344 break;
18345 case OPC_HSUB_S_df:
18346 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
18347 break;
18348 case OPC_HSUB_U_df:
18349 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
18350 break;
18352 break;
18353 default:
18354 MIPS_INVAL("MSA instruction");
18355 generate_exception_end(ctx, EXCP_RI);
18356 break;
18358 tcg_temp_free_i32(twd);
18359 tcg_temp_free_i32(tws);
18360 tcg_temp_free_i32(twt);
18361 tcg_temp_free_i32(tdf);
18364 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
18366 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
18367 uint8_t source = (ctx->opcode >> 11) & 0x1f;
18368 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
18369 TCGv telm = tcg_temp_new();
18370 TCGv_i32 tsr = tcg_const_i32(source);
18371 TCGv_i32 tdt = tcg_const_i32(dest);
18373 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
18374 case OPC_CTCMSA:
18375 gen_load_gpr(telm, source);
18376 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
18377 break;
18378 case OPC_CFCMSA:
18379 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
18380 gen_store_gpr(telm, dest);
18381 break;
18382 case OPC_MOVE_V:
18383 gen_helper_msa_move_v(cpu_env, tdt, tsr);
18384 break;
18385 default:
18386 MIPS_INVAL("MSA instruction");
18387 generate_exception_end(ctx, EXCP_RI);
18388 break;
18391 tcg_temp_free(telm);
18392 tcg_temp_free_i32(tdt);
18393 tcg_temp_free_i32(tsr);
18396 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
18397 uint32_t n)
18399 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18400 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18401 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18403 TCGv_i32 tws = tcg_const_i32(ws);
18404 TCGv_i32 twd = tcg_const_i32(wd);
18405 TCGv_i32 tn = tcg_const_i32(n);
18406 TCGv_i32 tdf = tcg_const_i32(df);
18408 switch (MASK_MSA_ELM(ctx->opcode)) {
18409 case OPC_SLDI_df:
18410 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
18411 break;
18412 case OPC_SPLATI_df:
18413 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
18414 break;
18415 case OPC_INSVE_df:
18416 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
18417 break;
18418 case OPC_COPY_S_df:
18419 case OPC_COPY_U_df:
18420 case OPC_INSERT_df:
18421 #if !defined(TARGET_MIPS64)
18422 /* Double format valid only for MIPS64 */
18423 if (df == DF_DOUBLE) {
18424 generate_exception_end(ctx, EXCP_RI);
18425 break;
18427 #endif
18428 switch (MASK_MSA_ELM(ctx->opcode)) {
18429 case OPC_COPY_S_df:
18430 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
18431 break;
18432 case OPC_COPY_U_df:
18433 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
18434 break;
18435 case OPC_INSERT_df:
18436 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
18437 break;
18439 break;
18440 default:
18441 MIPS_INVAL("MSA instruction");
18442 generate_exception_end(ctx, EXCP_RI);
18444 tcg_temp_free_i32(twd);
18445 tcg_temp_free_i32(tws);
18446 tcg_temp_free_i32(tn);
18447 tcg_temp_free_i32(tdf);
18450 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
18452 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
18453 uint32_t df = 0, n = 0;
18455 if ((dfn & 0x30) == 0x00) {
18456 n = dfn & 0x0f;
18457 df = DF_BYTE;
18458 } else if ((dfn & 0x38) == 0x20) {
18459 n = dfn & 0x07;
18460 df = DF_HALF;
18461 } else if ((dfn & 0x3c) == 0x30) {
18462 n = dfn & 0x03;
18463 df = DF_WORD;
18464 } else if ((dfn & 0x3e) == 0x38) {
18465 n = dfn & 0x01;
18466 df = DF_DOUBLE;
18467 } else if (dfn == 0x3E) {
18468 /* CTCMSA, CFCMSA, MOVE.V */
18469 gen_msa_elm_3e(env, ctx);
18470 return;
18471 } else {
18472 generate_exception_end(ctx, EXCP_RI);
18473 return;
18476 gen_msa_elm_df(env, ctx, df, n);
18479 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
18481 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18482 uint8_t df = (ctx->opcode >> 21) & 0x1;
18483 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18484 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18485 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18487 TCGv_i32 twd = tcg_const_i32(wd);
18488 TCGv_i32 tws = tcg_const_i32(ws);
18489 TCGv_i32 twt = tcg_const_i32(wt);
18490 TCGv_i32 tdf = tcg_temp_new_i32();
18492 /* adjust df value for floating-point instruction */
18493 tcg_gen_movi_i32(tdf, df + 2);
18495 switch (MASK_MSA_3RF(ctx->opcode)) {
18496 case OPC_FCAF_df:
18497 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
18498 break;
18499 case OPC_FADD_df:
18500 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
18501 break;
18502 case OPC_FCUN_df:
18503 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
18504 break;
18505 case OPC_FSUB_df:
18506 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
18507 break;
18508 case OPC_FCOR_df:
18509 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
18510 break;
18511 case OPC_FCEQ_df:
18512 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
18513 break;
18514 case OPC_FMUL_df:
18515 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
18516 break;
18517 case OPC_FCUNE_df:
18518 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
18519 break;
18520 case OPC_FCUEQ_df:
18521 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
18522 break;
18523 case OPC_FDIV_df:
18524 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
18525 break;
18526 case OPC_FCNE_df:
18527 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
18528 break;
18529 case OPC_FCLT_df:
18530 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
18531 break;
18532 case OPC_FMADD_df:
18533 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
18534 break;
18535 case OPC_MUL_Q_df:
18536 tcg_gen_movi_i32(tdf, df + 1);
18537 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
18538 break;
18539 case OPC_FCULT_df:
18540 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
18541 break;
18542 case OPC_FMSUB_df:
18543 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
18544 break;
18545 case OPC_MADD_Q_df:
18546 tcg_gen_movi_i32(tdf, df + 1);
18547 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
18548 break;
18549 case OPC_FCLE_df:
18550 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
18551 break;
18552 case OPC_MSUB_Q_df:
18553 tcg_gen_movi_i32(tdf, df + 1);
18554 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
18555 break;
18556 case OPC_FCULE_df:
18557 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
18558 break;
18559 case OPC_FEXP2_df:
18560 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
18561 break;
18562 case OPC_FSAF_df:
18563 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
18564 break;
18565 case OPC_FEXDO_df:
18566 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
18567 break;
18568 case OPC_FSUN_df:
18569 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
18570 break;
18571 case OPC_FSOR_df:
18572 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
18573 break;
18574 case OPC_FSEQ_df:
18575 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
18576 break;
18577 case OPC_FTQ_df:
18578 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
18579 break;
18580 case OPC_FSUNE_df:
18581 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
18582 break;
18583 case OPC_FSUEQ_df:
18584 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
18585 break;
18586 case OPC_FSNE_df:
18587 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
18588 break;
18589 case OPC_FSLT_df:
18590 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
18591 break;
18592 case OPC_FMIN_df:
18593 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
18594 break;
18595 case OPC_MULR_Q_df:
18596 tcg_gen_movi_i32(tdf, df + 1);
18597 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
18598 break;
18599 case OPC_FSULT_df:
18600 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
18601 break;
18602 case OPC_FMIN_A_df:
18603 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
18604 break;
18605 case OPC_MADDR_Q_df:
18606 tcg_gen_movi_i32(tdf, df + 1);
18607 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
18608 break;
18609 case OPC_FSLE_df:
18610 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
18611 break;
18612 case OPC_FMAX_df:
18613 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
18614 break;
18615 case OPC_MSUBR_Q_df:
18616 tcg_gen_movi_i32(tdf, df + 1);
18617 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
18618 break;
18619 case OPC_FSULE_df:
18620 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
18621 break;
18622 case OPC_FMAX_A_df:
18623 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
18624 break;
18625 default:
18626 MIPS_INVAL("MSA instruction");
18627 generate_exception_end(ctx, EXCP_RI);
18628 break;
18631 tcg_temp_free_i32(twd);
18632 tcg_temp_free_i32(tws);
18633 tcg_temp_free_i32(twt);
18634 tcg_temp_free_i32(tdf);
18637 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
18639 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18640 (op & (0x7 << 18)))
18641 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18642 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18643 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18644 uint8_t df = (ctx->opcode >> 16) & 0x3;
18645 TCGv_i32 twd = tcg_const_i32(wd);
18646 TCGv_i32 tws = tcg_const_i32(ws);
18647 TCGv_i32 twt = tcg_const_i32(wt);
18648 TCGv_i32 tdf = tcg_const_i32(df);
18650 switch (MASK_MSA_2R(ctx->opcode)) {
18651 case OPC_FILL_df:
18652 #if !defined(TARGET_MIPS64)
18653 /* Double format valid only for MIPS64 */
18654 if (df == DF_DOUBLE) {
18655 generate_exception_end(ctx, EXCP_RI);
18656 break;
18658 #endif
18659 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
18660 break;
18661 case OPC_PCNT_df:
18662 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
18663 break;
18664 case OPC_NLOC_df:
18665 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
18666 break;
18667 case OPC_NLZC_df:
18668 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
18669 break;
18670 default:
18671 MIPS_INVAL("MSA instruction");
18672 generate_exception_end(ctx, EXCP_RI);
18673 break;
18676 tcg_temp_free_i32(twd);
18677 tcg_temp_free_i32(tws);
18678 tcg_temp_free_i32(twt);
18679 tcg_temp_free_i32(tdf);
18682 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
18684 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18685 (op & (0xf << 17)))
18686 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18687 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18688 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18689 uint8_t df = (ctx->opcode >> 16) & 0x1;
18690 TCGv_i32 twd = tcg_const_i32(wd);
18691 TCGv_i32 tws = tcg_const_i32(ws);
18692 TCGv_i32 twt = tcg_const_i32(wt);
18693 /* adjust df value for floating-point instruction */
18694 TCGv_i32 tdf = tcg_const_i32(df + 2);
18696 switch (MASK_MSA_2RF(ctx->opcode)) {
18697 case OPC_FCLASS_df:
18698 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
18699 break;
18700 case OPC_FTRUNC_S_df:
18701 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
18702 break;
18703 case OPC_FTRUNC_U_df:
18704 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
18705 break;
18706 case OPC_FSQRT_df:
18707 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
18708 break;
18709 case OPC_FRSQRT_df:
18710 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
18711 break;
18712 case OPC_FRCP_df:
18713 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
18714 break;
18715 case OPC_FRINT_df:
18716 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
18717 break;
18718 case OPC_FLOG2_df:
18719 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
18720 break;
18721 case OPC_FEXUPL_df:
18722 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
18723 break;
18724 case OPC_FEXUPR_df:
18725 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
18726 break;
18727 case OPC_FFQL_df:
18728 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
18729 break;
18730 case OPC_FFQR_df:
18731 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
18732 break;
18733 case OPC_FTINT_S_df:
18734 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
18735 break;
18736 case OPC_FTINT_U_df:
18737 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
18738 break;
18739 case OPC_FFINT_S_df:
18740 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
18741 break;
18742 case OPC_FFINT_U_df:
18743 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
18744 break;
18747 tcg_temp_free_i32(twd);
18748 tcg_temp_free_i32(tws);
18749 tcg_temp_free_i32(twt);
18750 tcg_temp_free_i32(tdf);
18753 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
18755 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
18756 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18757 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18758 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18759 TCGv_i32 twd = tcg_const_i32(wd);
18760 TCGv_i32 tws = tcg_const_i32(ws);
18761 TCGv_i32 twt = tcg_const_i32(wt);
18763 switch (MASK_MSA_VEC(ctx->opcode)) {
18764 case OPC_AND_V:
18765 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
18766 break;
18767 case OPC_OR_V:
18768 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
18769 break;
18770 case OPC_NOR_V:
18771 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
18772 break;
18773 case OPC_XOR_V:
18774 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
18775 break;
18776 case OPC_BMNZ_V:
18777 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
18778 break;
18779 case OPC_BMZ_V:
18780 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
18781 break;
18782 case OPC_BSEL_V:
18783 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
18784 break;
18785 default:
18786 MIPS_INVAL("MSA instruction");
18787 generate_exception_end(ctx, EXCP_RI);
18788 break;
18791 tcg_temp_free_i32(twd);
18792 tcg_temp_free_i32(tws);
18793 tcg_temp_free_i32(twt);
18796 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
18798 switch (MASK_MSA_VEC(ctx->opcode)) {
18799 case OPC_AND_V:
18800 case OPC_OR_V:
18801 case OPC_NOR_V:
18802 case OPC_XOR_V:
18803 case OPC_BMNZ_V:
18804 case OPC_BMZ_V:
18805 case OPC_BSEL_V:
18806 gen_msa_vec_v(env, ctx);
18807 break;
18808 case OPC_MSA_2R:
18809 gen_msa_2r(env, ctx);
18810 break;
18811 case OPC_MSA_2RF:
18812 gen_msa_2rf(env, ctx);
18813 break;
18814 default:
18815 MIPS_INVAL("MSA instruction");
18816 generate_exception_end(ctx, EXCP_RI);
18817 break;
18821 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
18823 uint32_t opcode = ctx->opcode;
18824 check_insn(ctx, ASE_MSA);
18825 check_msa_access(ctx);
18827 switch (MASK_MSA_MINOR(opcode)) {
18828 case OPC_MSA_I8_00:
18829 case OPC_MSA_I8_01:
18830 case OPC_MSA_I8_02:
18831 gen_msa_i8(env, ctx);
18832 break;
18833 case OPC_MSA_I5_06:
18834 case OPC_MSA_I5_07:
18835 gen_msa_i5(env, ctx);
18836 break;
18837 case OPC_MSA_BIT_09:
18838 case OPC_MSA_BIT_0A:
18839 gen_msa_bit(env, ctx);
18840 break;
18841 case OPC_MSA_3R_0D:
18842 case OPC_MSA_3R_0E:
18843 case OPC_MSA_3R_0F:
18844 case OPC_MSA_3R_10:
18845 case OPC_MSA_3R_11:
18846 case OPC_MSA_3R_12:
18847 case OPC_MSA_3R_13:
18848 case OPC_MSA_3R_14:
18849 case OPC_MSA_3R_15:
18850 gen_msa_3r(env, ctx);
18851 break;
18852 case OPC_MSA_ELM:
18853 gen_msa_elm(env, ctx);
18854 break;
18855 case OPC_MSA_3RF_1A:
18856 case OPC_MSA_3RF_1B:
18857 case OPC_MSA_3RF_1C:
18858 gen_msa_3rf(env, ctx);
18859 break;
18860 case OPC_MSA_VEC:
18861 gen_msa_vec(env, ctx);
18862 break;
18863 case OPC_LD_B:
18864 case OPC_LD_H:
18865 case OPC_LD_W:
18866 case OPC_LD_D:
18867 case OPC_ST_B:
18868 case OPC_ST_H:
18869 case OPC_ST_W:
18870 case OPC_ST_D:
18872 int32_t s10 = sextract32(ctx->opcode, 16, 10);
18873 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
18874 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18875 uint8_t df = (ctx->opcode >> 0) & 0x3;
18877 TCGv_i32 twd = tcg_const_i32(wd);
18878 TCGv taddr = tcg_temp_new();
18879 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
18881 switch (MASK_MSA_MINOR(opcode)) {
18882 case OPC_LD_B:
18883 gen_helper_msa_ld_b(cpu_env, twd, taddr);
18884 break;
18885 case OPC_LD_H:
18886 gen_helper_msa_ld_h(cpu_env, twd, taddr);
18887 break;
18888 case OPC_LD_W:
18889 gen_helper_msa_ld_w(cpu_env, twd, taddr);
18890 break;
18891 case OPC_LD_D:
18892 gen_helper_msa_ld_d(cpu_env, twd, taddr);
18893 break;
18894 case OPC_ST_B:
18895 gen_helper_msa_st_b(cpu_env, twd, taddr);
18896 break;
18897 case OPC_ST_H:
18898 gen_helper_msa_st_h(cpu_env, twd, taddr);
18899 break;
18900 case OPC_ST_W:
18901 gen_helper_msa_st_w(cpu_env, twd, taddr);
18902 break;
18903 case OPC_ST_D:
18904 gen_helper_msa_st_d(cpu_env, twd, taddr);
18905 break;
18908 tcg_temp_free_i32(twd);
18909 tcg_temp_free(taddr);
18911 break;
18912 default:
18913 MIPS_INVAL("MSA instruction");
18914 generate_exception_end(ctx, EXCP_RI);
18915 break;
18920 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
18922 int32_t offset;
18923 int rs, rt, rd, sa;
18924 uint32_t op, op1;
18925 int16_t imm;
18927 /* make sure instructions are on a word boundary */
18928 if (ctx->pc & 0x3) {
18929 env->CP0_BadVAddr = ctx->pc;
18930 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
18931 return;
18934 /* Handle blikely not taken case */
18935 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
18936 TCGLabel *l1 = gen_new_label();
18938 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
18939 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
18940 gen_goto_tb(ctx, 1, ctx->pc + 4);
18941 gen_set_label(l1);
18944 op = MASK_OP_MAJOR(ctx->opcode);
18945 rs = (ctx->opcode >> 21) & 0x1f;
18946 rt = (ctx->opcode >> 16) & 0x1f;
18947 rd = (ctx->opcode >> 11) & 0x1f;
18948 sa = (ctx->opcode >> 6) & 0x1f;
18949 imm = (int16_t)ctx->opcode;
18950 switch (op) {
18951 case OPC_SPECIAL:
18952 decode_opc_special(env, ctx);
18953 break;
18954 case OPC_SPECIAL2:
18955 decode_opc_special2_legacy(env, ctx);
18956 break;
18957 case OPC_SPECIAL3:
18958 decode_opc_special3(env, ctx);
18959 break;
18960 case OPC_REGIMM:
18961 op1 = MASK_REGIMM(ctx->opcode);
18962 switch (op1) {
18963 case OPC_BLTZL: /* REGIMM branches */
18964 case OPC_BGEZL:
18965 case OPC_BLTZALL:
18966 case OPC_BGEZALL:
18967 check_insn(ctx, ISA_MIPS2);
18968 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18969 /* Fallthrough */
18970 case OPC_BLTZ:
18971 case OPC_BGEZ:
18972 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
18973 break;
18974 case OPC_BLTZAL:
18975 case OPC_BGEZAL:
18976 if (ctx->insn_flags & ISA_MIPS32R6) {
18977 if (rs == 0) {
18978 /* OPC_NAL, OPC_BAL */
18979 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
18980 } else {
18981 generate_exception_end(ctx, EXCP_RI);
18983 } else {
18984 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
18986 break;
18987 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
18988 case OPC_TNEI:
18989 check_insn(ctx, ISA_MIPS2);
18990 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18991 gen_trap(ctx, op1, rs, -1, imm);
18992 break;
18993 case OPC_SIGRIE:
18994 check_insn(ctx, ISA_MIPS32R6);
18995 generate_exception_end(ctx, EXCP_RI);
18996 break;
18997 case OPC_SYNCI:
18998 check_insn(ctx, ISA_MIPS32R2);
18999 /* Break the TB to be able to sync copied instructions
19000 immediately */
19001 ctx->bstate = BS_STOP;
19002 break;
19003 case OPC_BPOSGE32: /* MIPS DSP branch */
19004 #if defined(TARGET_MIPS64)
19005 case OPC_BPOSGE64:
19006 #endif
19007 check_dsp(ctx);
19008 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
19009 break;
19010 #if defined(TARGET_MIPS64)
19011 case OPC_DAHI:
19012 check_insn(ctx, ISA_MIPS32R6);
19013 check_mips_64(ctx);
19014 if (rs != 0) {
19015 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
19017 break;
19018 case OPC_DATI:
19019 check_insn(ctx, ISA_MIPS32R6);
19020 check_mips_64(ctx);
19021 if (rs != 0) {
19022 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
19024 break;
19025 #endif
19026 default: /* Invalid */
19027 MIPS_INVAL("regimm");
19028 generate_exception_end(ctx, EXCP_RI);
19029 break;
19031 break;
19032 case OPC_CP0:
19033 check_cp0_enabled(ctx);
19034 op1 = MASK_CP0(ctx->opcode);
19035 switch (op1) {
19036 case OPC_MFC0:
19037 case OPC_MTC0:
19038 case OPC_MFTR:
19039 case OPC_MTTR:
19040 case OPC_MFHC0:
19041 case OPC_MTHC0:
19042 #if defined(TARGET_MIPS64)
19043 case OPC_DMFC0:
19044 case OPC_DMTC0:
19045 #endif
19046 #ifndef CONFIG_USER_ONLY
19047 gen_cp0(env, ctx, op1, rt, rd);
19048 #endif /* !CONFIG_USER_ONLY */
19049 break;
19050 case OPC_C0_FIRST ... OPC_C0_LAST:
19051 #ifndef CONFIG_USER_ONLY
19052 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
19053 #endif /* !CONFIG_USER_ONLY */
19054 break;
19055 case OPC_MFMC0:
19056 #ifndef CONFIG_USER_ONLY
19058 uint32_t op2;
19059 TCGv t0 = tcg_temp_new();
19061 op2 = MASK_MFMC0(ctx->opcode);
19062 switch (op2) {
19063 case OPC_DMT:
19064 check_insn(ctx, ASE_MT);
19065 gen_helper_dmt(t0);
19066 gen_store_gpr(t0, rt);
19067 break;
19068 case OPC_EMT:
19069 check_insn(ctx, ASE_MT);
19070 gen_helper_emt(t0);
19071 gen_store_gpr(t0, rt);
19072 break;
19073 case OPC_DVPE:
19074 check_insn(ctx, ASE_MT);
19075 gen_helper_dvpe(t0, cpu_env);
19076 gen_store_gpr(t0, rt);
19077 break;
19078 case OPC_EVPE:
19079 check_insn(ctx, ASE_MT);
19080 gen_helper_evpe(t0, cpu_env);
19081 gen_store_gpr(t0, rt);
19082 break;
19083 case OPC_DI:
19084 check_insn(ctx, ISA_MIPS32R2);
19085 save_cpu_state(ctx, 1);
19086 gen_helper_di(t0, cpu_env);
19087 gen_store_gpr(t0, rt);
19088 /* Stop translation as we may have switched
19089 the execution mode. */
19090 ctx->bstate = BS_STOP;
19091 break;
19092 case OPC_EI:
19093 check_insn(ctx, ISA_MIPS32R2);
19094 save_cpu_state(ctx, 1);
19095 gen_helper_ei(t0, cpu_env);
19096 gen_store_gpr(t0, rt);
19097 /* Stop translation as we may have switched
19098 the execution mode. */
19099 ctx->bstate = BS_STOP;
19100 break;
19101 default: /* Invalid */
19102 MIPS_INVAL("mfmc0");
19103 generate_exception_end(ctx, EXCP_RI);
19104 break;
19106 tcg_temp_free(t0);
19108 #endif /* !CONFIG_USER_ONLY */
19109 break;
19110 case OPC_RDPGPR:
19111 check_insn(ctx, ISA_MIPS32R2);
19112 gen_load_srsgpr(rt, rd);
19113 break;
19114 case OPC_WRPGPR:
19115 check_insn(ctx, ISA_MIPS32R2);
19116 gen_store_srsgpr(rt, rd);
19117 break;
19118 default:
19119 MIPS_INVAL("cp0");
19120 generate_exception_end(ctx, EXCP_RI);
19121 break;
19123 break;
19124 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
19125 if (ctx->insn_flags & ISA_MIPS32R6) {
19126 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
19127 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19128 } else {
19129 /* OPC_ADDI */
19130 /* Arithmetic with immediate opcode */
19131 gen_arith_imm(ctx, op, rt, rs, imm);
19133 break;
19134 case OPC_ADDIU:
19135 gen_arith_imm(ctx, op, rt, rs, imm);
19136 break;
19137 case OPC_SLTI: /* Set on less than with immediate opcode */
19138 case OPC_SLTIU:
19139 gen_slt_imm(ctx, op, rt, rs, imm);
19140 break;
19141 case OPC_ANDI: /* Arithmetic with immediate opcode */
19142 case OPC_LUI: /* OPC_AUI */
19143 case OPC_ORI:
19144 case OPC_XORI:
19145 gen_logic_imm(ctx, op, rt, rs, imm);
19146 break;
19147 case OPC_J ... OPC_JAL: /* Jump */
19148 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19149 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19150 break;
19151 /* Branch */
19152 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
19153 if (ctx->insn_flags & ISA_MIPS32R6) {
19154 if (rt == 0) {
19155 generate_exception_end(ctx, EXCP_RI);
19156 break;
19158 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
19159 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19160 } else {
19161 /* OPC_BLEZL */
19162 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19164 break;
19165 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
19166 if (ctx->insn_flags & ISA_MIPS32R6) {
19167 if (rt == 0) {
19168 generate_exception_end(ctx, EXCP_RI);
19169 break;
19171 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
19172 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19173 } else {
19174 /* OPC_BGTZL */
19175 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19177 break;
19178 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
19179 if (rt == 0) {
19180 /* OPC_BLEZ */
19181 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19182 } else {
19183 check_insn(ctx, ISA_MIPS32R6);
19184 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
19185 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19187 break;
19188 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
19189 if (rt == 0) {
19190 /* OPC_BGTZ */
19191 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19192 } else {
19193 check_insn(ctx, ISA_MIPS32R6);
19194 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
19195 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19197 break;
19198 case OPC_BEQL:
19199 case OPC_BNEL:
19200 check_insn(ctx, ISA_MIPS2);
19201 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19202 /* Fallthrough */
19203 case OPC_BEQ:
19204 case OPC_BNE:
19205 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19206 break;
19207 case OPC_LL: /* Load and stores */
19208 check_insn(ctx, ISA_MIPS2);
19209 /* Fallthrough */
19210 case OPC_LWL:
19211 case OPC_LWR:
19212 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19213 /* Fallthrough */
19214 case OPC_LB ... OPC_LH:
19215 case OPC_LW ... OPC_LHU:
19216 gen_ld(ctx, op, rt, rs, imm);
19217 break;
19218 case OPC_SWL:
19219 case OPC_SWR:
19220 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19221 /* fall through */
19222 case OPC_SB ... OPC_SH:
19223 case OPC_SW:
19224 gen_st(ctx, op, rt, rs, imm);
19225 break;
19226 case OPC_SC:
19227 check_insn(ctx, ISA_MIPS2);
19228 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19229 gen_st_cond(ctx, op, rt, rs, imm);
19230 break;
19231 case OPC_CACHE:
19232 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19233 check_cp0_enabled(ctx);
19234 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
19235 /* Treat as NOP. */
19236 break;
19237 case OPC_PREF:
19238 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19239 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
19240 /* Treat as NOP. */
19241 break;
19243 /* Floating point (COP1). */
19244 case OPC_LWC1:
19245 case OPC_LDC1:
19246 case OPC_SWC1:
19247 case OPC_SDC1:
19248 gen_cop1_ldst(ctx, op, rt, rs, imm);
19249 break;
19251 case OPC_CP1:
19252 op1 = MASK_CP1(ctx->opcode);
19254 switch (op1) {
19255 case OPC_MFHC1:
19256 case OPC_MTHC1:
19257 check_cp1_enabled(ctx);
19258 check_insn(ctx, ISA_MIPS32R2);
19259 case OPC_MFC1:
19260 case OPC_CFC1:
19261 case OPC_MTC1:
19262 case OPC_CTC1:
19263 check_cp1_enabled(ctx);
19264 gen_cp1(ctx, op1, rt, rd);
19265 break;
19266 #if defined(TARGET_MIPS64)
19267 case OPC_DMFC1:
19268 case OPC_DMTC1:
19269 check_cp1_enabled(ctx);
19270 check_insn(ctx, ISA_MIPS3);
19271 check_mips_64(ctx);
19272 gen_cp1(ctx, op1, rt, rd);
19273 break;
19274 #endif
19275 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
19276 check_cp1_enabled(ctx);
19277 if (ctx->insn_flags & ISA_MIPS32R6) {
19278 /* OPC_BC1EQZ */
19279 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19280 rt, imm << 2, 4);
19281 } else {
19282 /* OPC_BC1ANY2 */
19283 check_cop1x(ctx);
19284 check_insn(ctx, ASE_MIPS3D);
19285 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19286 (rt >> 2) & 0x7, imm << 2);
19288 break;
19289 case OPC_BC1NEZ:
19290 check_cp1_enabled(ctx);
19291 check_insn(ctx, ISA_MIPS32R6);
19292 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19293 rt, imm << 2, 4);
19294 break;
19295 case OPC_BC1ANY4:
19296 check_cp1_enabled(ctx);
19297 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19298 check_cop1x(ctx);
19299 check_insn(ctx, ASE_MIPS3D);
19300 /* fall through */
19301 case OPC_BC1:
19302 check_cp1_enabled(ctx);
19303 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19304 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19305 (rt >> 2) & 0x7, imm << 2);
19306 break;
19307 case OPC_PS_FMT:
19308 check_ps(ctx);
19309 /* fall through */
19310 case OPC_S_FMT:
19311 case OPC_D_FMT:
19312 check_cp1_enabled(ctx);
19313 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19314 (imm >> 8) & 0x7);
19315 break;
19316 case OPC_W_FMT:
19317 case OPC_L_FMT:
19319 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
19320 check_cp1_enabled(ctx);
19321 if (ctx->insn_flags & ISA_MIPS32R6) {
19322 switch (r6_op) {
19323 case R6_OPC_CMP_AF_S:
19324 case R6_OPC_CMP_UN_S:
19325 case R6_OPC_CMP_EQ_S:
19326 case R6_OPC_CMP_UEQ_S:
19327 case R6_OPC_CMP_LT_S:
19328 case R6_OPC_CMP_ULT_S:
19329 case R6_OPC_CMP_LE_S:
19330 case R6_OPC_CMP_ULE_S:
19331 case R6_OPC_CMP_SAF_S:
19332 case R6_OPC_CMP_SUN_S:
19333 case R6_OPC_CMP_SEQ_S:
19334 case R6_OPC_CMP_SEUQ_S:
19335 case R6_OPC_CMP_SLT_S:
19336 case R6_OPC_CMP_SULT_S:
19337 case R6_OPC_CMP_SLE_S:
19338 case R6_OPC_CMP_SULE_S:
19339 case R6_OPC_CMP_OR_S:
19340 case R6_OPC_CMP_UNE_S:
19341 case R6_OPC_CMP_NE_S:
19342 case R6_OPC_CMP_SOR_S:
19343 case R6_OPC_CMP_SUNE_S:
19344 case R6_OPC_CMP_SNE_S:
19345 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19346 break;
19347 case R6_OPC_CMP_AF_D:
19348 case R6_OPC_CMP_UN_D:
19349 case R6_OPC_CMP_EQ_D:
19350 case R6_OPC_CMP_UEQ_D:
19351 case R6_OPC_CMP_LT_D:
19352 case R6_OPC_CMP_ULT_D:
19353 case R6_OPC_CMP_LE_D:
19354 case R6_OPC_CMP_ULE_D:
19355 case R6_OPC_CMP_SAF_D:
19356 case R6_OPC_CMP_SUN_D:
19357 case R6_OPC_CMP_SEQ_D:
19358 case R6_OPC_CMP_SEUQ_D:
19359 case R6_OPC_CMP_SLT_D:
19360 case R6_OPC_CMP_SULT_D:
19361 case R6_OPC_CMP_SLE_D:
19362 case R6_OPC_CMP_SULE_D:
19363 case R6_OPC_CMP_OR_D:
19364 case R6_OPC_CMP_UNE_D:
19365 case R6_OPC_CMP_NE_D:
19366 case R6_OPC_CMP_SOR_D:
19367 case R6_OPC_CMP_SUNE_D:
19368 case R6_OPC_CMP_SNE_D:
19369 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19370 break;
19371 default:
19372 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
19373 rt, rd, sa, (imm >> 8) & 0x7);
19375 break;
19377 } else {
19378 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19379 (imm >> 8) & 0x7);
19381 break;
19383 case OPC_BZ_V:
19384 case OPC_BNZ_V:
19385 case OPC_BZ_B:
19386 case OPC_BZ_H:
19387 case OPC_BZ_W:
19388 case OPC_BZ_D:
19389 case OPC_BNZ_B:
19390 case OPC_BNZ_H:
19391 case OPC_BNZ_W:
19392 case OPC_BNZ_D:
19393 check_insn(ctx, ASE_MSA);
19394 gen_msa_branch(env, ctx, op1);
19395 break;
19396 default:
19397 MIPS_INVAL("cp1");
19398 generate_exception_end(ctx, EXCP_RI);
19399 break;
19401 break;
19403 /* Compact branches [R6] and COP2 [non-R6] */
19404 case OPC_BC: /* OPC_LWC2 */
19405 case OPC_BALC: /* OPC_SWC2 */
19406 if (ctx->insn_flags & ISA_MIPS32R6) {
19407 /* OPC_BC, OPC_BALC */
19408 gen_compute_compact_branch(ctx, op, 0, 0,
19409 sextract32(ctx->opcode << 2, 0, 28));
19410 } else {
19411 /* OPC_LWC2, OPC_SWC2 */
19412 /* COP2: Not implemented. */
19413 generate_exception_err(ctx, EXCP_CpU, 2);
19415 break;
19416 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
19417 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
19418 if (ctx->insn_flags & ISA_MIPS32R6) {
19419 if (rs != 0) {
19420 /* OPC_BEQZC, OPC_BNEZC */
19421 gen_compute_compact_branch(ctx, op, rs, 0,
19422 sextract32(ctx->opcode << 2, 0, 23));
19423 } else {
19424 /* OPC_JIC, OPC_JIALC */
19425 gen_compute_compact_branch(ctx, op, 0, rt, imm);
19427 } else {
19428 /* OPC_LWC2, OPC_SWC2 */
19429 /* COP2: Not implemented. */
19430 generate_exception_err(ctx, EXCP_CpU, 2);
19432 break;
19433 case OPC_CP2:
19434 check_insn(ctx, INSN_LOONGSON2F);
19435 /* Note that these instructions use different fields. */
19436 gen_loongson_multimedia(ctx, sa, rd, rt);
19437 break;
19439 case OPC_CP3:
19440 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19441 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19442 check_cp1_enabled(ctx);
19443 op1 = MASK_CP3(ctx->opcode);
19444 switch (op1) {
19445 case OPC_LUXC1:
19446 case OPC_SUXC1:
19447 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19448 /* Fallthrough */
19449 case OPC_LWXC1:
19450 case OPC_LDXC1:
19451 case OPC_SWXC1:
19452 case OPC_SDXC1:
19453 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19454 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
19455 break;
19456 case OPC_PREFX:
19457 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19458 /* Treat as NOP. */
19459 break;
19460 case OPC_ALNV_PS:
19461 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19462 /* Fallthrough */
19463 case OPC_MADD_S:
19464 case OPC_MADD_D:
19465 case OPC_MADD_PS:
19466 case OPC_MSUB_S:
19467 case OPC_MSUB_D:
19468 case OPC_MSUB_PS:
19469 case OPC_NMADD_S:
19470 case OPC_NMADD_D:
19471 case OPC_NMADD_PS:
19472 case OPC_NMSUB_S:
19473 case OPC_NMSUB_D:
19474 case OPC_NMSUB_PS:
19475 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19476 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
19477 break;
19478 default:
19479 MIPS_INVAL("cp3");
19480 generate_exception_end(ctx, EXCP_RI);
19481 break;
19483 } else {
19484 generate_exception_err(ctx, EXCP_CpU, 1);
19486 break;
19488 #if defined(TARGET_MIPS64)
19489 /* MIPS64 opcodes */
19490 case OPC_LDL ... OPC_LDR:
19491 case OPC_LLD:
19492 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19493 /* fall through */
19494 case OPC_LWU:
19495 case OPC_LD:
19496 check_insn(ctx, ISA_MIPS3);
19497 check_mips_64(ctx);
19498 gen_ld(ctx, op, rt, rs, imm);
19499 break;
19500 case OPC_SDL ... OPC_SDR:
19501 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19502 /* fall through */
19503 case OPC_SD:
19504 check_insn(ctx, ISA_MIPS3);
19505 check_mips_64(ctx);
19506 gen_st(ctx, op, rt, rs, imm);
19507 break;
19508 case OPC_SCD:
19509 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19510 check_insn(ctx, ISA_MIPS3);
19511 check_mips_64(ctx);
19512 gen_st_cond(ctx, op, rt, rs, imm);
19513 break;
19514 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
19515 if (ctx->insn_flags & ISA_MIPS32R6) {
19516 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
19517 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19518 } else {
19519 /* OPC_DADDI */
19520 check_insn(ctx, ISA_MIPS3);
19521 check_mips_64(ctx);
19522 gen_arith_imm(ctx, op, rt, rs, imm);
19524 break;
19525 case OPC_DADDIU:
19526 check_insn(ctx, ISA_MIPS3);
19527 check_mips_64(ctx);
19528 gen_arith_imm(ctx, op, rt, rs, imm);
19529 break;
19530 #else
19531 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
19532 if (ctx->insn_flags & ISA_MIPS32R6) {
19533 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19534 } else {
19535 MIPS_INVAL("major opcode");
19536 generate_exception_end(ctx, EXCP_RI);
19538 break;
19539 #endif
19540 case OPC_DAUI: /* OPC_JALX */
19541 if (ctx->insn_flags & ISA_MIPS32R6) {
19542 #if defined(TARGET_MIPS64)
19543 /* OPC_DAUI */
19544 check_mips_64(ctx);
19545 if (rs == 0) {
19546 generate_exception(ctx, EXCP_RI);
19547 } else if (rt != 0) {
19548 TCGv t0 = tcg_temp_new();
19549 gen_load_gpr(t0, rs);
19550 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
19551 tcg_temp_free(t0);
19553 #else
19554 generate_exception_end(ctx, EXCP_RI);
19555 MIPS_INVAL("major opcode");
19556 #endif
19557 } else {
19558 /* OPC_JALX */
19559 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
19560 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19561 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19563 break;
19564 case OPC_MSA: /* OPC_MDMX */
19565 /* MDMX: Not implemented. */
19566 gen_msa(env, ctx);
19567 break;
19568 case OPC_PCREL:
19569 check_insn(ctx, ISA_MIPS32R6);
19570 gen_pcrel(ctx, ctx->opcode, ctx->pc, rs);
19571 break;
19572 default: /* Invalid */
19573 MIPS_INVAL("major opcode");
19574 generate_exception_end(ctx, EXCP_RI);
19575 break;
19579 void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
19581 MIPSCPU *cpu = mips_env_get_cpu(env);
19582 CPUState *cs = CPU(cpu);
19583 DisasContext ctx;
19584 target_ulong pc_start;
19585 target_ulong next_page_start;
19586 int num_insns;
19587 int max_insns;
19588 int insn_bytes;
19589 int is_slot;
19591 pc_start = tb->pc;
19592 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
19593 ctx.pc = pc_start;
19594 ctx.saved_pc = -1;
19595 ctx.singlestep_enabled = cs->singlestep_enabled;
19596 ctx.insn_flags = env->insn_flags;
19597 ctx.CP0_Config1 = env->CP0_Config1;
19598 ctx.tb = tb;
19599 ctx.bstate = BS_NONE;
19600 ctx.btarget = 0;
19601 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
19602 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
19603 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
19604 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
19605 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
19606 ctx.PAMask = env->PAMask;
19607 ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
19608 ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
19609 /* Restore delay slot state from the tb context. */
19610 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
19611 ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
19612 ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
19613 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
19614 restore_cpu_state(env, &ctx);
19615 #ifdef CONFIG_USER_ONLY
19616 ctx.mem_idx = MIPS_HFLAG_UM;
19617 #else
19618 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
19619 #endif
19620 ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ?
19621 MO_UNALN : MO_ALIGN;
19622 num_insns = 0;
19623 max_insns = tb->cflags & CF_COUNT_MASK;
19624 if (max_insns == 0) {
19625 max_insns = CF_COUNT_MASK;
19627 if (max_insns > TCG_MAX_INSNS) {
19628 max_insns = TCG_MAX_INSNS;
19631 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
19632 gen_tb_start(tb);
19633 while (ctx.bstate == BS_NONE) {
19634 tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget);
19635 num_insns++;
19637 if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
19638 save_cpu_state(&ctx, 1);
19639 ctx.bstate = BS_BRANCH;
19640 gen_helper_raise_exception_debug(cpu_env);
19641 /* The address covered by the breakpoint must be included in
19642 [tb->pc, tb->pc + tb->size) in order to for it to be
19643 properly cleared -- thus we increment the PC here so that
19644 the logic setting tb->size below does the right thing. */
19645 ctx.pc += 4;
19646 goto done_generating;
19649 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
19650 gen_io_start();
19653 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
19654 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
19655 ctx.opcode = cpu_ldl_code(env, ctx.pc);
19656 insn_bytes = 4;
19657 decode_opc(env, &ctx);
19658 } else if (ctx.insn_flags & ASE_MICROMIPS) {
19659 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19660 insn_bytes = decode_micromips_opc(env, &ctx);
19661 } else if (ctx.insn_flags & ASE_MIPS16) {
19662 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19663 insn_bytes = decode_mips16_opc(env, &ctx);
19664 } else {
19665 generate_exception_end(&ctx, EXCP_RI);
19666 break;
19669 if (ctx.hflags & MIPS_HFLAG_BMASK) {
19670 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
19671 MIPS_HFLAG_FBNSLOT))) {
19672 /* force to generate branch as there is neither delay nor
19673 forbidden slot */
19674 is_slot = 1;
19676 if ((ctx.hflags & MIPS_HFLAG_M16) &&
19677 (ctx.hflags & MIPS_HFLAG_FBNSLOT)) {
19678 /* Force to generate branch as microMIPS R6 doesn't restrict
19679 branches in the forbidden slot. */
19680 is_slot = 1;
19683 if (is_slot) {
19684 gen_branch(&ctx, insn_bytes);
19686 ctx.pc += insn_bytes;
19688 /* Execute a branch and its delay slot as a single instruction.
19689 This is what GDB expects and is consistent with what the
19690 hardware does (e.g. if a delay slot instruction faults, the
19691 reported PC is the PC of the branch). */
19692 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
19693 break;
19696 if (ctx.pc >= next_page_start) {
19697 break;
19700 if (tcg_op_buf_full()) {
19701 break;
19704 if (num_insns >= max_insns)
19705 break;
19707 if (singlestep)
19708 break;
19710 if (tb->cflags & CF_LAST_IO) {
19711 gen_io_end();
19713 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
19714 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
19715 gen_helper_raise_exception_debug(cpu_env);
19716 } else {
19717 switch (ctx.bstate) {
19718 case BS_STOP:
19719 gen_goto_tb(&ctx, 0, ctx.pc);
19720 break;
19721 case BS_NONE:
19722 save_cpu_state(&ctx, 0);
19723 gen_goto_tb(&ctx, 0, ctx.pc);
19724 break;
19725 case BS_EXCP:
19726 tcg_gen_exit_tb(0);
19727 break;
19728 case BS_BRANCH:
19729 default:
19730 break;
19733 done_generating:
19734 gen_tb_end(tb, num_insns);
19736 tb->size = ctx.pc - pc_start;
19737 tb->icount = num_insns;
19739 #ifdef DEBUG_DISAS
19740 LOG_DISAS("\n");
19741 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
19742 qemu_log("IN: %s\n", lookup_symbol(pc_start));
19743 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
19744 qemu_log("\n");
19746 #endif
19749 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
19750 int flags)
19752 int i;
19753 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
19755 #define printfpr(fp) \
19756 do { \
19757 if (is_fpu64) \
19758 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
19759 " fd:%13g fs:%13g psu: %13g\n", \
19760 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
19761 (double)(fp)->fd, \
19762 (double)(fp)->fs[FP_ENDIAN_IDX], \
19763 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
19764 else { \
19765 fpr_t tmp; \
19766 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
19767 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
19768 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
19769 " fd:%13g fs:%13g psu:%13g\n", \
19770 tmp.w[FP_ENDIAN_IDX], tmp.d, \
19771 (double)tmp.fd, \
19772 (double)tmp.fs[FP_ENDIAN_IDX], \
19773 (double)tmp.fs[!FP_ENDIAN_IDX]); \
19775 } while(0)
19778 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
19779 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
19780 get_float_exception_flags(&env->active_fpu.fp_status));
19781 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
19782 fpu_fprintf(f, "%3s: ", fregnames[i]);
19783 printfpr(&env->active_fpu.fpr[i]);
19786 #undef printfpr
19789 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
19790 int flags)
19792 MIPSCPU *cpu = MIPS_CPU(cs);
19793 CPUMIPSState *env = &cpu->env;
19794 int i;
19796 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
19797 " LO=0x" TARGET_FMT_lx " ds %04x "
19798 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
19799 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
19800 env->hflags, env->btarget, env->bcond);
19801 for (i = 0; i < 32; i++) {
19802 if ((i & 3) == 0)
19803 cpu_fprintf(f, "GPR%02d:", i);
19804 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
19805 if ((i & 3) == 3)
19806 cpu_fprintf(f, "\n");
19809 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
19810 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
19811 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
19812 PRIx64 "\n",
19813 env->CP0_Config0, env->CP0_Config1, env->lladdr);
19814 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
19815 env->CP0_Config2, env->CP0_Config3);
19816 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
19817 env->CP0_Config4, env->CP0_Config5);
19818 if (env->hflags & MIPS_HFLAG_FPU)
19819 fpu_dump_state(env, f, cpu_fprintf, flags);
19822 void mips_tcg_init(void)
19824 int i;
19825 static int inited;
19827 /* Initialize various static tables. */
19828 if (inited)
19829 return;
19831 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
19832 TCGV_UNUSED(cpu_gpr[0]);
19833 for (i = 1; i < 32; i++)
19834 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
19835 offsetof(CPUMIPSState, active_tc.gpr[i]),
19836 regnames[i]);
19838 for (i = 0; i < 32; i++) {
19839 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
19840 msa_wr_d[i * 2] =
19841 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2]);
19842 /* The scalar floating-point unit (FPU) registers are mapped on
19843 * the MSA vector registers. */
19844 fpu_f64[i] = msa_wr_d[i * 2];
19845 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
19846 msa_wr_d[i * 2 + 1] =
19847 tcg_global_mem_new_i64(TCG_AREG0, off, msaregnames[i * 2 + 1]);
19850 cpu_PC = tcg_global_mem_new(TCG_AREG0,
19851 offsetof(CPUMIPSState, active_tc.PC), "PC");
19852 for (i = 0; i < MIPS_DSP_ACC; i++) {
19853 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
19854 offsetof(CPUMIPSState, active_tc.HI[i]),
19855 regnames_HI[i]);
19856 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
19857 offsetof(CPUMIPSState, active_tc.LO[i]),
19858 regnames_LO[i]);
19860 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
19861 offsetof(CPUMIPSState, active_tc.DSPControl),
19862 "DSPControl");
19863 bcond = tcg_global_mem_new(TCG_AREG0,
19864 offsetof(CPUMIPSState, bcond), "bcond");
19865 btarget = tcg_global_mem_new(TCG_AREG0,
19866 offsetof(CPUMIPSState, btarget), "btarget");
19867 hflags = tcg_global_mem_new_i32(TCG_AREG0,
19868 offsetof(CPUMIPSState, hflags), "hflags");
19870 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
19871 offsetof(CPUMIPSState, active_fpu.fcr0),
19872 "fcr0");
19873 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
19874 offsetof(CPUMIPSState, active_fpu.fcr31),
19875 "fcr31");
19877 inited = 1;
19880 #include "translate_init.c"
19882 MIPSCPU *cpu_mips_init(const char *cpu_model)
19884 MIPSCPU *cpu;
19885 CPUMIPSState *env;
19886 const mips_def_t *def;
19888 def = cpu_mips_find_by_name(cpu_model);
19889 if (!def)
19890 return NULL;
19891 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
19892 env = &cpu->env;
19893 env->cpu_model = def;
19895 #ifndef CONFIG_USER_ONLY
19896 mmu_init(env, def);
19897 #endif
19898 fpu_init(env, def);
19899 mvp_init(env, def);
19901 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
19903 return cpu;
19906 void cpu_state_reset(CPUMIPSState *env)
19908 MIPSCPU *cpu = mips_env_get_cpu(env);
19909 CPUState *cs = CPU(cpu);
19911 /* Reset registers to their default values */
19912 env->CP0_PRid = env->cpu_model->CP0_PRid;
19913 env->CP0_Config0 = env->cpu_model->CP0_Config0;
19914 #ifdef TARGET_WORDS_BIGENDIAN
19915 env->CP0_Config0 |= (1 << CP0C0_BE);
19916 #endif
19917 env->CP0_Config1 = env->cpu_model->CP0_Config1;
19918 env->CP0_Config2 = env->cpu_model->CP0_Config2;
19919 env->CP0_Config3 = env->cpu_model->CP0_Config3;
19920 env->CP0_Config4 = env->cpu_model->CP0_Config4;
19921 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
19922 env->CP0_Config5 = env->cpu_model->CP0_Config5;
19923 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
19924 env->CP0_Config6 = env->cpu_model->CP0_Config6;
19925 env->CP0_Config7 = env->cpu_model->CP0_Config7;
19926 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
19927 << env->cpu_model->CP0_LLAddr_shift;
19928 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
19929 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
19930 env->CCRes = env->cpu_model->CCRes;
19931 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
19932 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
19933 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
19934 env->current_tc = 0;
19935 env->SEGBITS = env->cpu_model->SEGBITS;
19936 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
19937 #if defined(TARGET_MIPS64)
19938 if (env->cpu_model->insn_flags & ISA_MIPS3) {
19939 env->SEGMask |= 3ULL << 62;
19941 #endif
19942 env->PABITS = env->cpu_model->PABITS;
19943 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
19944 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
19945 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
19946 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
19947 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
19948 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
19949 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
19950 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
19951 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
19952 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
19953 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
19954 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
19955 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
19956 env->msair = env->cpu_model->MSAIR;
19957 env->insn_flags = env->cpu_model->insn_flags;
19959 #if defined(CONFIG_USER_ONLY)
19960 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
19961 # ifdef TARGET_MIPS64
19962 /* Enable 64-bit register mode. */
19963 env->CP0_Status |= (1 << CP0St_PX);
19964 # endif
19965 # ifdef TARGET_ABI_MIPSN64
19966 /* Enable 64-bit address mode. */
19967 env->CP0_Status |= (1 << CP0St_UX);
19968 # endif
19969 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
19970 hardware registers. */
19971 env->CP0_HWREna |= 0x0000000F;
19972 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
19973 env->CP0_Status |= (1 << CP0St_CU1);
19975 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
19976 env->CP0_Status |= (1 << CP0St_MX);
19978 # if defined(TARGET_MIPS64)
19979 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
19980 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
19981 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
19982 env->CP0_Status |= (1 << CP0St_FR);
19984 # endif
19985 #else
19986 if (env->hflags & MIPS_HFLAG_BMASK) {
19987 /* If the exception was raised from a delay slot,
19988 come back to the jump. */
19989 env->CP0_ErrorEPC = (env->active_tc.PC
19990 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
19991 } else {
19992 env->CP0_ErrorEPC = env->active_tc.PC;
19994 env->active_tc.PC = (int32_t)0xBFC00000;
19995 env->CP0_Random = env->tlb->nb_tlb - 1;
19996 env->tlb->tlb_in_use = env->tlb->nb_tlb;
19997 env->CP0_Wired = 0;
19998 env->CP0_EBase = (cs->cpu_index & 0x3FF);
19999 if (kvm_enabled()) {
20000 env->CP0_EBase |= 0x40000000;
20001 } else {
20002 env->CP0_EBase |= 0x80000000;
20004 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
20005 /* vectored interrupts not implemented, timer on int 7,
20006 no performance counters. */
20007 env->CP0_IntCtl = 0xe0000000;
20009 int i;
20011 for (i = 0; i < 7; i++) {
20012 env->CP0_WatchLo[i] = 0;
20013 env->CP0_WatchHi[i] = 0x80000000;
20015 env->CP0_WatchLo[7] = 0;
20016 env->CP0_WatchHi[7] = 0;
20018 /* Count register increments in debug mode, EJTAG version 1 */
20019 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
20021 cpu_mips_store_count(env, 1);
20023 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
20024 int i;
20026 /* Only TC0 on VPE 0 starts as active. */
20027 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
20028 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
20029 env->tcs[i].CP0_TCHalt = 1;
20031 env->active_tc.CP0_TCHalt = 1;
20032 cs->halted = 1;
20034 if (cs->cpu_index == 0) {
20035 /* VPE0 starts up enabled. */
20036 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
20037 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
20039 /* TC0 starts up unhalted. */
20040 cs->halted = 0;
20041 env->active_tc.CP0_TCHalt = 0;
20042 env->tcs[0].CP0_TCHalt = 0;
20043 /* With thread 0 active. */
20044 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
20045 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
20048 #endif
20049 if ((env->insn_flags & ISA_MIPS32R6) &&
20050 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
20051 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
20052 env->CP0_Status |= (1 << CP0St_FR);
20055 /* MSA */
20056 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
20057 msa_reset(env);
20060 compute_hflags(env);
20061 restore_rounding_mode(env);
20062 restore_flush_mode(env);
20063 restore_pamask(env);
20064 cs->exception_index = EXCP_NONE;
20066 if (semihosting_get_argc()) {
20067 /* UHI interface can be used to obtain argc and argv */
20068 env->active_tc.gpr[4] = -1;
20072 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
20073 target_ulong *data)
20075 env->active_tc.PC = data[0];
20076 env->hflags &= ~MIPS_HFLAG_BMASK;
20077 env->hflags |= data[1];
20078 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
20079 case MIPS_HFLAG_BR:
20080 break;
20081 case MIPS_HFLAG_BC:
20082 case MIPS_HFLAG_BL:
20083 case MIPS_HFLAG_B:
20084 env->btarget = data[2];
20085 break;