target/mips: Fix TCG temporary leak in gen_cache_operation()
[qemu/ar7.git] / target / mips / translate.c
blob71fa5ec19739ed14554aa99b7cd0508cfd7523db
1 /*
2 * MIPS 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)
9 * Copyright (c) 2020 Philippe Mathieu-Daudé
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 #include "qemu/osdep.h"
26 #include "cpu.h"
27 #include "internal.h"
28 #include "tcg/tcg-op.h"
29 #include "exec/translator.h"
30 #include "exec/helper-proto.h"
31 #include "exec/helper-gen.h"
32 #include "semihosting/semihost.h"
34 #include "target/mips/trace.h"
35 #include "trace-tcg.h"
36 #include "exec/translator.h"
37 #include "exec/log.h"
38 #include "qemu/qemu-print.h"
39 #include "fpu_helper.h"
40 #include "translate.h"
42 enum {
43 /* indirect opcode tables */
44 OPC_SPECIAL = (0x00 << 26),
45 OPC_REGIMM = (0x01 << 26),
46 OPC_CP0 = (0x10 << 26),
47 OPC_CP2 = (0x12 << 26),
48 OPC_CP3 = (0x13 << 26),
49 OPC_SPECIAL2 = (0x1C << 26),
50 OPC_SPECIAL3 = (0x1F << 26),
51 /* arithmetic with immediate */
52 OPC_ADDI = (0x08 << 26),
53 OPC_ADDIU = (0x09 << 26),
54 OPC_SLTI = (0x0A << 26),
55 OPC_SLTIU = (0x0B << 26),
56 /* logic with immediate */
57 OPC_ANDI = (0x0C << 26),
58 OPC_ORI = (0x0D << 26),
59 OPC_XORI = (0x0E << 26),
60 OPC_LUI = (0x0F << 26),
61 /* arithmetic with immediate */
62 OPC_DADDI = (0x18 << 26),
63 OPC_DADDIU = (0x19 << 26),
64 /* Jump and branches */
65 OPC_J = (0x02 << 26),
66 OPC_JAL = (0x03 << 26),
67 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
68 OPC_BEQL = (0x14 << 26),
69 OPC_BNE = (0x05 << 26),
70 OPC_BNEL = (0x15 << 26),
71 OPC_BLEZ = (0x06 << 26),
72 OPC_BLEZL = (0x16 << 26),
73 OPC_BGTZ = (0x07 << 26),
74 OPC_BGTZL = (0x17 << 26),
75 OPC_JALX = (0x1D << 26),
76 OPC_DAUI = (0x1D << 26),
77 /* Load and stores */
78 OPC_LDL = (0x1A << 26),
79 OPC_LDR = (0x1B << 26),
80 OPC_LB = (0x20 << 26),
81 OPC_LH = (0x21 << 26),
82 OPC_LWL = (0x22 << 26),
83 OPC_LW = (0x23 << 26),
84 OPC_LWPC = OPC_LW | 0x5,
85 OPC_LBU = (0x24 << 26),
86 OPC_LHU = (0x25 << 26),
87 OPC_LWR = (0x26 << 26),
88 OPC_LWU = (0x27 << 26),
89 OPC_SB = (0x28 << 26),
90 OPC_SH = (0x29 << 26),
91 OPC_SWL = (0x2A << 26),
92 OPC_SW = (0x2B << 26),
93 OPC_SDL = (0x2C << 26),
94 OPC_SDR = (0x2D << 26),
95 OPC_SWR = (0x2E << 26),
96 OPC_LL = (0x30 << 26),
97 OPC_LLD = (0x34 << 26),
98 OPC_LD = (0x37 << 26),
99 OPC_LDPC = OPC_LD | 0x5,
100 OPC_SC = (0x38 << 26),
101 OPC_SCD = (0x3C << 26),
102 OPC_SD = (0x3F << 26),
103 /* Floating point load/store */
104 OPC_LWC1 = (0x31 << 26),
105 OPC_LWC2 = (0x32 << 26),
106 OPC_LDC1 = (0x35 << 26),
107 OPC_LDC2 = (0x36 << 26),
108 OPC_SWC1 = (0x39 << 26),
109 OPC_SWC2 = (0x3A << 26),
110 OPC_SDC1 = (0x3D << 26),
111 OPC_SDC2 = (0x3E << 26),
112 /* Compact Branches */
113 OPC_BLEZALC = (0x06 << 26),
114 OPC_BGEZALC = (0x06 << 26),
115 OPC_BGEUC = (0x06 << 26),
116 OPC_BGTZALC = (0x07 << 26),
117 OPC_BLTZALC = (0x07 << 26),
118 OPC_BLTUC = (0x07 << 26),
119 OPC_BOVC = (0x08 << 26),
120 OPC_BEQZALC = (0x08 << 26),
121 OPC_BEQC = (0x08 << 26),
122 OPC_BLEZC = (0x16 << 26),
123 OPC_BGEZC = (0x16 << 26),
124 OPC_BGEC = (0x16 << 26),
125 OPC_BGTZC = (0x17 << 26),
126 OPC_BLTZC = (0x17 << 26),
127 OPC_BLTC = (0x17 << 26),
128 OPC_BNVC = (0x18 << 26),
129 OPC_BNEZALC = (0x18 << 26),
130 OPC_BNEC = (0x18 << 26),
131 OPC_BC = (0x32 << 26),
132 OPC_BEQZC = (0x36 << 26),
133 OPC_JIC = (0x36 << 26),
134 OPC_BALC = (0x3A << 26),
135 OPC_BNEZC = (0x3E << 26),
136 OPC_JIALC = (0x3E << 26),
137 /* MDMX ASE specific */
138 OPC_MDMX = (0x1E << 26),
139 /* Cache and prefetch */
140 OPC_CACHE = (0x2F << 26),
141 OPC_PREF = (0x33 << 26),
142 /* PC-relative address computation / loads */
143 OPC_PCREL = (0x3B << 26),
146 /* PC-relative address computation / loads */
147 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
148 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
149 enum {
150 /* Instructions determined by bits 19 and 20 */
151 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
152 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
153 OPC_LWUPC = OPC_PCREL | (2 << 19),
155 /* Instructions determined by bits 16 ... 20 */
156 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
157 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
159 /* Other */
160 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
163 /* MIPS special opcodes */
164 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
166 enum {
167 /* Shifts */
168 OPC_SLL = 0x00 | OPC_SPECIAL,
169 /* NOP is SLL r0, r0, 0 */
170 /* SSNOP is SLL r0, r0, 1 */
171 /* EHB is SLL r0, r0, 3 */
172 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
173 OPC_ROTR = OPC_SRL | (1 << 21),
174 OPC_SRA = 0x03 | OPC_SPECIAL,
175 OPC_SLLV = 0x04 | OPC_SPECIAL,
176 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
177 OPC_ROTRV = OPC_SRLV | (1 << 6),
178 OPC_SRAV = 0x07 | OPC_SPECIAL,
179 OPC_DSLLV = 0x14 | OPC_SPECIAL,
180 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
181 OPC_DROTRV = OPC_DSRLV | (1 << 6),
182 OPC_DSRAV = 0x17 | OPC_SPECIAL,
183 OPC_DSLL = 0x38 | OPC_SPECIAL,
184 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
185 OPC_DROTR = OPC_DSRL | (1 << 21),
186 OPC_DSRA = 0x3B | OPC_SPECIAL,
187 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
188 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
189 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
190 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
191 /* Multiplication / division */
192 OPC_MULT = 0x18 | OPC_SPECIAL,
193 OPC_MULTU = 0x19 | OPC_SPECIAL,
194 OPC_DIV = 0x1A | OPC_SPECIAL,
195 OPC_DIVU = 0x1B | OPC_SPECIAL,
196 OPC_DMULT = 0x1C | OPC_SPECIAL,
197 OPC_DMULTU = 0x1D | OPC_SPECIAL,
198 OPC_DDIV = 0x1E | OPC_SPECIAL,
199 OPC_DDIVU = 0x1F | OPC_SPECIAL,
201 /* 2 registers arithmetic / logic */
202 OPC_ADD = 0x20 | OPC_SPECIAL,
203 OPC_ADDU = 0x21 | OPC_SPECIAL,
204 OPC_SUB = 0x22 | OPC_SPECIAL,
205 OPC_SUBU = 0x23 | OPC_SPECIAL,
206 OPC_AND = 0x24 | OPC_SPECIAL,
207 OPC_OR = 0x25 | OPC_SPECIAL,
208 OPC_XOR = 0x26 | OPC_SPECIAL,
209 OPC_NOR = 0x27 | OPC_SPECIAL,
210 OPC_SLT = 0x2A | OPC_SPECIAL,
211 OPC_SLTU = 0x2B | OPC_SPECIAL,
212 OPC_DADD = 0x2C | OPC_SPECIAL,
213 OPC_DADDU = 0x2D | OPC_SPECIAL,
214 OPC_DSUB = 0x2E | OPC_SPECIAL,
215 OPC_DSUBU = 0x2F | OPC_SPECIAL,
216 /* Jumps */
217 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
218 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
219 /* Traps */
220 OPC_TGE = 0x30 | OPC_SPECIAL,
221 OPC_TGEU = 0x31 | OPC_SPECIAL,
222 OPC_TLT = 0x32 | OPC_SPECIAL,
223 OPC_TLTU = 0x33 | OPC_SPECIAL,
224 OPC_TEQ = 0x34 | OPC_SPECIAL,
225 OPC_TNE = 0x36 | OPC_SPECIAL,
226 /* HI / LO registers load & stores */
227 OPC_MFHI = 0x10 | OPC_SPECIAL,
228 OPC_MTHI = 0x11 | OPC_SPECIAL,
229 OPC_MFLO = 0x12 | OPC_SPECIAL,
230 OPC_MTLO = 0x13 | OPC_SPECIAL,
231 /* Conditional moves */
232 OPC_MOVZ = 0x0A | OPC_SPECIAL,
233 OPC_MOVN = 0x0B | OPC_SPECIAL,
235 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
236 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
238 OPC_MOVCI = 0x01 | OPC_SPECIAL,
240 /* Special */
241 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
242 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
243 OPC_BREAK = 0x0D | OPC_SPECIAL,
244 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
245 OPC_SYNC = 0x0F | OPC_SPECIAL,
247 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
248 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
249 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
250 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
254 * R6 Multiply and Divide instructions have the same opcode
255 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
257 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
259 enum {
260 R6_OPC_MUL = OPC_MULT | (2 << 6),
261 R6_OPC_MUH = OPC_MULT | (3 << 6),
262 R6_OPC_MULU = OPC_MULTU | (2 << 6),
263 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
264 R6_OPC_DIV = OPC_DIV | (2 << 6),
265 R6_OPC_MOD = OPC_DIV | (3 << 6),
266 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
267 R6_OPC_MODU = OPC_DIVU | (3 << 6),
269 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
270 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
271 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
272 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
273 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
274 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
275 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
276 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
278 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
279 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
280 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
281 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
282 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
285 /* Multiplication variants of the vr54xx. */
286 #define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
288 enum {
289 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
290 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
291 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
292 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
293 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
294 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
295 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
296 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
297 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
298 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
299 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
300 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
301 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
302 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
305 /* REGIMM (rt field) opcodes */
306 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
308 enum {
309 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
310 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
311 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
312 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
313 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
314 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
315 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
316 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
317 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
318 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
319 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
320 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
321 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
322 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
323 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
324 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
326 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
327 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
330 /* Special2 opcodes */
331 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
333 enum {
334 /* Multiply & xxx operations */
335 OPC_MADD = 0x00 | OPC_SPECIAL2,
336 OPC_MADDU = 0x01 | OPC_SPECIAL2,
337 OPC_MUL = 0x02 | OPC_SPECIAL2,
338 OPC_MSUB = 0x04 | OPC_SPECIAL2,
339 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
340 /* Loongson 2F */
341 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
342 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
343 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
344 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
345 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
346 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
347 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
348 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
349 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
350 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
351 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
352 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
353 /* Misc */
354 OPC_CLZ = 0x20 | OPC_SPECIAL2,
355 OPC_CLO = 0x21 | OPC_SPECIAL2,
356 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
357 OPC_DCLO = 0x25 | OPC_SPECIAL2,
358 /* Special */
359 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
362 /* Special3 opcodes */
363 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
365 enum {
366 OPC_EXT = 0x00 | OPC_SPECIAL3,
367 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
368 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
369 OPC_DEXT = 0x03 | OPC_SPECIAL3,
370 OPC_INS = 0x04 | OPC_SPECIAL3,
371 OPC_DINSM = 0x05 | OPC_SPECIAL3,
372 OPC_DINSU = 0x06 | OPC_SPECIAL3,
373 OPC_DINS = 0x07 | OPC_SPECIAL3,
374 OPC_FORK = 0x08 | OPC_SPECIAL3,
375 OPC_YIELD = 0x09 | OPC_SPECIAL3,
376 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
377 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
378 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
379 OPC_GINV = 0x3D | OPC_SPECIAL3,
381 /* Loongson 2E */
382 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
383 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
384 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
385 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
386 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
387 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
388 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
389 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
390 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
391 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
392 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
393 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
395 /* MIPS DSP Load */
396 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
397 /* MIPS DSP Arithmetic */
398 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
399 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
400 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
401 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
402 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
403 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
404 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
405 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
406 /* MIPS DSP GPR-Based Shift Sub-class */
407 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
408 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
409 /* MIPS DSP Multiply Sub-class insns */
410 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
411 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
413 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
414 /* DSP Bit/Manipulation Sub-class */
415 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
416 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
417 /* MIPS DSP Append Sub-class */
418 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
419 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
420 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
421 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
422 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
424 /* EVA */
425 OPC_LWLE = 0x19 | OPC_SPECIAL3,
426 OPC_LWRE = 0x1A | OPC_SPECIAL3,
427 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
428 OPC_SBE = 0x1C | OPC_SPECIAL3,
429 OPC_SHE = 0x1D | OPC_SPECIAL3,
430 OPC_SCE = 0x1E | OPC_SPECIAL3,
431 OPC_SWE = 0x1F | OPC_SPECIAL3,
432 OPC_SWLE = 0x21 | OPC_SPECIAL3,
433 OPC_SWRE = 0x22 | OPC_SPECIAL3,
434 OPC_PREFE = 0x23 | OPC_SPECIAL3,
435 OPC_LBUE = 0x28 | OPC_SPECIAL3,
436 OPC_LHUE = 0x29 | OPC_SPECIAL3,
437 OPC_LBE = 0x2C | OPC_SPECIAL3,
438 OPC_LHE = 0x2D | OPC_SPECIAL3,
439 OPC_LLE = 0x2E | OPC_SPECIAL3,
440 OPC_LWE = 0x2F | OPC_SPECIAL3,
442 /* R6 */
443 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
444 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
445 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
446 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
447 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
448 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
451 /* Loongson EXT load/store quad word opcodes */
452 #define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
453 enum {
454 OPC_GSLQ = 0x0020 | OPC_LWC2,
455 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
456 OPC_GSSHFL = OPC_LWC2,
457 OPC_GSSQ = 0x0020 | OPC_SWC2,
458 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
459 OPC_GSSHFS = OPC_SWC2,
462 /* Loongson EXT shifted load/store opcodes */
463 #define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
464 enum {
465 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
466 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
467 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
468 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
469 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
470 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
471 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
472 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
475 /* Loongson EXT LDC2/SDC2 opcodes */
476 #define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
478 enum {
479 OPC_GSLBX = 0x0 | OPC_LDC2,
480 OPC_GSLHX = 0x1 | OPC_LDC2,
481 OPC_GSLWX = 0x2 | OPC_LDC2,
482 OPC_GSLDX = 0x3 | OPC_LDC2,
483 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
484 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
485 OPC_GSSBX = 0x0 | OPC_SDC2,
486 OPC_GSSHX = 0x1 | OPC_SDC2,
487 OPC_GSSWX = 0x2 | OPC_SDC2,
488 OPC_GSSDX = 0x3 | OPC_SDC2,
489 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
490 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
493 /* BSHFL opcodes */
494 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
496 enum {
497 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
498 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
499 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
500 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
501 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
502 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
503 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
504 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
507 /* DBSHFL opcodes */
508 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
510 enum {
511 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
512 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
513 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
514 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
515 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
516 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
517 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
518 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
519 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
520 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
521 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
524 /* MIPS DSP REGIMM opcodes */
525 enum {
526 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
527 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
530 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
531 /* MIPS DSP Load */
532 enum {
533 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
534 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
535 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
536 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
539 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
540 enum {
541 /* MIPS DSP Arithmetic Sub-class */
542 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
543 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
544 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
545 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
546 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
547 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
548 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
549 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
550 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
551 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
552 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
553 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
554 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
555 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
556 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
557 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
558 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
559 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
560 /* MIPS DSP Multiply Sub-class insns */
561 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
562 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
563 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
564 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
565 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
566 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
569 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
570 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
571 enum {
572 /* MIPS DSP Arithmetic Sub-class */
573 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
574 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
575 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
576 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
577 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
578 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
579 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
580 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
581 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
582 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
583 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
584 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
585 /* MIPS DSP Multiply Sub-class insns */
586 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
587 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
588 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
589 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
592 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
593 enum {
594 /* MIPS DSP Arithmetic Sub-class */
595 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
596 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
597 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
598 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
599 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
600 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
601 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
602 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
603 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
604 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
605 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
606 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
607 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
608 /* DSP Bit/Manipulation Sub-class */
609 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
610 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
611 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
612 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
613 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
616 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
617 enum {
618 /* MIPS DSP Arithmetic Sub-class */
619 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
620 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
621 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
622 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
623 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
624 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
625 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
626 /* DSP Compare-Pick Sub-class */
627 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
628 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
629 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
630 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
631 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
632 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
634 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
635 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
636 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
637 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
638 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
639 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
640 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
641 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
644 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
645 enum {
646 /* MIPS DSP GPR-Based Shift Sub-class */
647 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
648 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
649 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
650 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
651 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
652 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
653 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
654 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
655 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
656 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
657 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
658 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
659 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
660 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
661 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
662 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
663 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
664 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
665 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
666 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
667 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
668 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
671 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
672 enum {
673 /* MIPS DSP Multiply Sub-class insns */
674 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
675 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
676 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
677 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
678 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
679 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
680 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
681 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
682 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
683 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
684 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
685 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
686 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
687 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
688 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
689 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
690 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
691 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
692 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
693 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
694 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
695 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
698 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
699 enum {
700 /* DSP Bit/Manipulation Sub-class */
701 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
704 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
705 enum {
706 /* MIPS DSP Append Sub-class */
707 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
708 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
709 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
712 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
713 enum {
714 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
715 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
716 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
717 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
718 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
719 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
720 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
721 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
722 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
723 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
724 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
725 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
726 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
727 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
728 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
729 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
730 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
731 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
734 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
735 enum {
736 /* MIPS DSP Arithmetic Sub-class */
737 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
738 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
739 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
740 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
741 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
742 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
743 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
744 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
745 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
746 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
747 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
748 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
749 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
750 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
753 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
754 /* DSP Bit/Manipulation Sub-class */
755 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
756 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
757 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
758 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
759 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
760 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
763 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
764 enum {
765 /* MIPS DSP Multiply Sub-class insns */
766 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
767 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
768 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
769 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
770 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
771 /* MIPS DSP Arithmetic Sub-class */
772 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
773 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
774 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
775 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
776 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
777 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
778 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
779 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
780 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
781 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
782 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
783 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
784 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
785 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
786 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
787 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
788 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
789 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
790 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
791 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
792 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
795 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796 enum {
797 /* DSP Compare-Pick Sub-class */
798 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
799 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
800 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
801 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
802 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
803 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
804 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
805 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
806 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
807 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
808 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
809 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
810 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
811 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
817 /* MIPS DSP Arithmetic Sub-class */
818 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
819 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
820 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
821 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
822 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
823 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
824 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
825 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
828 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
829 enum {
830 /* DSP Append Sub-class */
831 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
832 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
833 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
834 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
837 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
838 enum {
839 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
840 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
841 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
842 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
843 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
844 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
845 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
846 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
847 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
848 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
849 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
850 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
851 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
852 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
853 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
854 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
855 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
856 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
857 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
858 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
859 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
860 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
863 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
864 enum {
865 /* DSP Bit/Manipulation Sub-class */
866 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
869 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
870 enum {
871 /* MIPS DSP Multiply Sub-class insns */
872 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
873 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
874 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
875 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
876 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
877 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
878 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
879 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
880 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
881 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
882 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
883 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
884 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
885 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
890 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
891 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
892 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
893 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
894 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
895 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
896 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
897 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
900 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
901 enum {
902 /* MIPS DSP GPR-Based Shift Sub-class */
903 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
904 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
905 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
906 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
907 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
908 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
909 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
910 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
911 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
912 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
913 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
914 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
915 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
916 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
921 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
922 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
923 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
924 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
925 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
926 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
927 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
928 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
931 /* Coprocessor 0 (rs field) */
932 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
934 enum {
935 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
936 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
937 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
938 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
939 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
940 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
941 OPC_MFTR = (0x08 << 21) | OPC_CP0,
942 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
943 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
944 OPC_MTTR = (0x0C << 21) | OPC_CP0,
945 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
946 OPC_C0 = (0x10 << 21) | OPC_CP0,
947 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
948 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
949 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
950 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
951 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
952 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
953 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
954 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
955 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
956 OPC_C0_A = (0x1A << 21) | OPC_CP0,
957 OPC_C0_B = (0x1B << 21) | OPC_CP0,
958 OPC_C0_C = (0x1C << 21) | OPC_CP0,
959 OPC_C0_D = (0x1D << 21) | OPC_CP0,
960 OPC_C0_E = (0x1E << 21) | OPC_CP0,
961 OPC_C0_F = (0x1F << 21) | OPC_CP0,
964 /* MFMC0 opcodes */
965 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
967 enum {
968 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
969 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
970 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
971 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
972 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
973 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
974 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
975 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
978 /* Coprocessor 0 (with rs == C0) */
979 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
981 enum {
982 OPC_TLBR = 0x01 | OPC_C0,
983 OPC_TLBWI = 0x02 | OPC_C0,
984 OPC_TLBINV = 0x03 | OPC_C0,
985 OPC_TLBINVF = 0x04 | OPC_C0,
986 OPC_TLBWR = 0x06 | OPC_C0,
987 OPC_TLBP = 0x08 | OPC_C0,
988 OPC_RFE = 0x10 | OPC_C0,
989 OPC_ERET = 0x18 | OPC_C0,
990 OPC_DERET = 0x1F | OPC_C0,
991 OPC_WAIT = 0x20 | OPC_C0,
994 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
996 enum {
997 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
998 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
999 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1000 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1001 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1002 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1003 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1004 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1005 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1006 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1007 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1010 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1012 enum {
1013 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1014 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1015 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1016 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1017 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1018 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1019 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1020 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1022 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1023 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1024 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1025 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1026 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1027 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1028 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1029 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1031 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1032 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1033 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1034 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1035 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1036 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1037 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1038 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1040 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1041 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1042 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1043 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1044 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1045 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1046 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1047 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1049 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1050 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1051 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1052 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1053 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1054 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1056 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1057 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1058 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1059 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1060 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1061 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1063 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1064 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1065 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1066 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1067 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1068 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1070 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1071 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1072 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1073 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1074 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1075 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1077 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1078 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1079 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1080 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1081 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1082 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1084 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1085 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1086 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1087 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1088 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1089 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1091 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1092 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1093 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1094 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1095 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1096 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1098 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1099 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1100 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1101 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1102 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1103 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1107 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1109 enum {
1110 OPC_LWXC1 = 0x00 | OPC_CP3,
1111 OPC_LDXC1 = 0x01 | OPC_CP3,
1112 OPC_LUXC1 = 0x05 | OPC_CP3,
1113 OPC_SWXC1 = 0x08 | OPC_CP3,
1114 OPC_SDXC1 = 0x09 | OPC_CP3,
1115 OPC_SUXC1 = 0x0D | OPC_CP3,
1116 OPC_PREFX = 0x0F | OPC_CP3,
1117 OPC_ALNV_PS = 0x1E | OPC_CP3,
1118 OPC_MADD_S = 0x20 | OPC_CP3,
1119 OPC_MADD_D = 0x21 | OPC_CP3,
1120 OPC_MADD_PS = 0x26 | OPC_CP3,
1121 OPC_MSUB_S = 0x28 | OPC_CP3,
1122 OPC_MSUB_D = 0x29 | OPC_CP3,
1123 OPC_MSUB_PS = 0x2E | OPC_CP3,
1124 OPC_NMADD_S = 0x30 | OPC_CP3,
1125 OPC_NMADD_D = 0x31 | OPC_CP3,
1126 OPC_NMADD_PS = 0x36 | OPC_CP3,
1127 OPC_NMSUB_S = 0x38 | OPC_CP3,
1128 OPC_NMSUB_D = 0x39 | OPC_CP3,
1129 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1133 * MMI (MultiMedia Instruction) encodings
1134 * ======================================
1136 * MMI instructions encoding table keys:
1138 * * This code is reserved for future use. An attempt to execute it
1139 * causes a Reserved Instruction exception.
1140 * % This code indicates an instruction class. The instruction word
1141 * must be further decoded by examining additional tables that show
1142 * the values for other instruction fields.
1143 * # This code is reserved for the unsupported instructions DMULT,
1144 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
1145 * to execute it causes a Reserved Instruction exception.
1147 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
1149 * 31 26 0
1150 * +--------+----------------------------------------+
1151 * | opcode | |
1152 * +--------+----------------------------------------+
1154 * opcode bits 28..26
1155 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1156 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1157 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1158 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
1159 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
1160 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
1161 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
1162 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
1163 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
1164 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
1165 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
1168 enum {
1169 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
1170 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
1171 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
1175 * MMI instructions with opcode field = MMI:
1177 * 31 26 5 0
1178 * +--------+-------------------------------+--------+
1179 * | MMI | |function|
1180 * +--------+-------------------------------+--------+
1182 * function bits 2..0
1183 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1184 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1185 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1186 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
1187 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
1188 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
1189 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
1190 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
1191 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
1192 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
1193 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
1196 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
1197 enum {
1198 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
1199 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
1200 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
1201 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
1202 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
1203 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
1204 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
1205 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
1208 /* global register indices */
1209 TCGv cpu_gpr[32], cpu_PC;
1211 * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[])
1212 * and the upper halves in cpu_gpr_hi[].
1214 TCGv_i64 cpu_gpr_hi[32];
1215 TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1216 static TCGv cpu_dspctrl, btarget;
1217 TCGv bcond;
1218 static TCGv cpu_lladdr, cpu_llval;
1219 static TCGv_i32 hflags;
1220 TCGv_i32 fpu_fcr0, fpu_fcr31;
1221 TCGv_i64 fpu_f64[32];
1223 #include "exec/gen-icount.h"
1225 #define gen_helper_0e0i(name, arg) do { \
1226 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1227 gen_helper_##name(cpu_env, helper_tmp); \
1228 tcg_temp_free_i32(helper_tmp); \
1229 } while (0)
1231 #define gen_helper_0e1i(name, arg1, arg2) do { \
1232 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1233 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1234 tcg_temp_free_i32(helper_tmp); \
1235 } while (0)
1237 #define gen_helper_1e0i(name, ret, arg1) do { \
1238 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1239 gen_helper_##name(ret, cpu_env, helper_tmp); \
1240 tcg_temp_free_i32(helper_tmp); \
1241 } while (0)
1243 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1244 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1245 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1246 tcg_temp_free_i32(helper_tmp); \
1247 } while (0)
1249 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1250 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1251 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1252 tcg_temp_free_i32(helper_tmp); \
1253 } while (0)
1255 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1256 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1257 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1258 tcg_temp_free_i32(helper_tmp); \
1259 } while (0)
1261 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1262 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1263 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1264 tcg_temp_free_i32(helper_tmp); \
1265 } while (0)
1267 #define DISAS_STOP DISAS_TARGET_0
1268 #define DISAS_EXIT DISAS_TARGET_1
1270 static const char * const regnames[] = {
1271 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1272 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1273 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1274 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1277 static const char * const regnames_HI[] = {
1278 "HI0", "HI1", "HI2", "HI3",
1281 static const char * const regnames_LO[] = {
1282 "LO0", "LO1", "LO2", "LO3",
1285 static const char * const fregnames[] = {
1286 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1287 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1288 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1289 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1292 /* General purpose registers moves. */
1293 void gen_load_gpr(TCGv t, int reg)
1295 if (reg == 0) {
1296 tcg_gen_movi_tl(t, 0);
1297 } else {
1298 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1302 void gen_store_gpr(TCGv t, int reg)
1304 if (reg != 0) {
1305 tcg_gen_mov_tl(cpu_gpr[reg], t);
1309 #if defined(TARGET_MIPS64)
1310 void gen_load_gpr_hi(TCGv_i64 t, int reg)
1312 if (reg == 0) {
1313 tcg_gen_movi_i64(t, 0);
1314 } else {
1315 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
1319 void gen_store_gpr_hi(TCGv_i64 t, int reg)
1321 if (reg != 0) {
1322 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
1325 #endif /* TARGET_MIPS64 */
1327 /* Moves to/from shadow registers. */
1328 static inline void gen_load_srsgpr(int from, int to)
1330 TCGv t0 = tcg_temp_new();
1332 if (from == 0) {
1333 tcg_gen_movi_tl(t0, 0);
1334 } else {
1335 TCGv_i32 t2 = tcg_temp_new_i32();
1336 TCGv_ptr addr = tcg_temp_new_ptr();
1338 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1339 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1340 tcg_gen_andi_i32(t2, t2, 0xf);
1341 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1342 tcg_gen_ext_i32_ptr(addr, t2);
1343 tcg_gen_add_ptr(addr, cpu_env, addr);
1345 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1346 tcg_temp_free_ptr(addr);
1347 tcg_temp_free_i32(t2);
1349 gen_store_gpr(t0, to);
1350 tcg_temp_free(t0);
1353 static inline void gen_store_srsgpr(int from, int to)
1355 if (to != 0) {
1356 TCGv t0 = tcg_temp_new();
1357 TCGv_i32 t2 = tcg_temp_new_i32();
1358 TCGv_ptr addr = tcg_temp_new_ptr();
1360 gen_load_gpr(t0, from);
1361 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1362 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1363 tcg_gen_andi_i32(t2, t2, 0xf);
1364 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1365 tcg_gen_ext_i32_ptr(addr, t2);
1366 tcg_gen_add_ptr(addr, cpu_env, addr);
1368 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1369 tcg_temp_free_ptr(addr);
1370 tcg_temp_free_i32(t2);
1371 tcg_temp_free(t0);
1375 /* Tests */
1376 static inline void gen_save_pc(target_ulong pc)
1378 tcg_gen_movi_tl(cpu_PC, pc);
1381 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1383 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1384 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1385 gen_save_pc(ctx->base.pc_next);
1386 ctx->saved_pc = ctx->base.pc_next;
1388 if (ctx->hflags != ctx->saved_hflags) {
1389 tcg_gen_movi_i32(hflags, ctx->hflags);
1390 ctx->saved_hflags = ctx->hflags;
1391 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1392 case MIPS_HFLAG_BR:
1393 break;
1394 case MIPS_HFLAG_BC:
1395 case MIPS_HFLAG_BL:
1396 case MIPS_HFLAG_B:
1397 tcg_gen_movi_tl(btarget, ctx->btarget);
1398 break;
1403 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1405 ctx->saved_hflags = ctx->hflags;
1406 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1407 case MIPS_HFLAG_BR:
1408 break;
1409 case MIPS_HFLAG_BC:
1410 case MIPS_HFLAG_BL:
1411 case MIPS_HFLAG_B:
1412 ctx->btarget = env->btarget;
1413 break;
1417 void generate_exception_err(DisasContext *ctx, int excp, int err)
1419 TCGv_i32 texcp = tcg_const_i32(excp);
1420 TCGv_i32 terr = tcg_const_i32(err);
1421 save_cpu_state(ctx, 1);
1422 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1423 tcg_temp_free_i32(terr);
1424 tcg_temp_free_i32(texcp);
1425 ctx->base.is_jmp = DISAS_NORETURN;
1428 void generate_exception(DisasContext *ctx, int excp)
1430 gen_helper_0e0i(raise_exception, excp);
1433 void generate_exception_end(DisasContext *ctx, int excp)
1435 generate_exception_err(ctx, excp, 0);
1438 void gen_reserved_instruction(DisasContext *ctx)
1440 generate_exception_end(ctx, EXCP_RI);
1443 /* Floating point register moves. */
1444 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1446 if (ctx->hflags & MIPS_HFLAG_FRE) {
1447 generate_exception(ctx, EXCP_RI);
1449 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1452 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1454 TCGv_i64 t64;
1455 if (ctx->hflags & MIPS_HFLAG_FRE) {
1456 generate_exception(ctx, EXCP_RI);
1458 t64 = tcg_temp_new_i64();
1459 tcg_gen_extu_i32_i64(t64, t);
1460 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1461 tcg_temp_free_i64(t64);
1464 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1466 if (ctx->hflags & MIPS_HFLAG_F64) {
1467 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1468 } else {
1469 gen_load_fpr32(ctx, t, reg | 1);
1473 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1475 if (ctx->hflags & MIPS_HFLAG_F64) {
1476 TCGv_i64 t64 = tcg_temp_new_i64();
1477 tcg_gen_extu_i32_i64(t64, t);
1478 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1479 tcg_temp_free_i64(t64);
1480 } else {
1481 gen_store_fpr32(ctx, t, reg | 1);
1485 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1487 if (ctx->hflags & MIPS_HFLAG_F64) {
1488 tcg_gen_mov_i64(t, fpu_f64[reg]);
1489 } else {
1490 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1494 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1496 if (ctx->hflags & MIPS_HFLAG_F64) {
1497 tcg_gen_mov_i64(fpu_f64[reg], t);
1498 } else {
1499 TCGv_i64 t0;
1500 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1501 t0 = tcg_temp_new_i64();
1502 tcg_gen_shri_i64(t0, t, 32);
1503 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1504 tcg_temp_free_i64(t0);
1508 int get_fp_bit(int cc)
1510 if (cc) {
1511 return 24 + cc;
1512 } else {
1513 return 23;
1517 /* Addresses computation */
1518 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1520 tcg_gen_add_tl(ret, arg0, arg1);
1522 #if defined(TARGET_MIPS64)
1523 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1524 tcg_gen_ext32s_i64(ret, ret);
1526 #endif
1529 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
1530 target_long ofs)
1532 tcg_gen_addi_tl(ret, base, ofs);
1534 #if defined(TARGET_MIPS64)
1535 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1536 tcg_gen_ext32s_i64(ret, ret);
1538 #endif
1541 /* Addresses computation (translation time) */
1542 static target_long addr_add(DisasContext *ctx, target_long base,
1543 target_long offset)
1545 target_long sum = base + offset;
1547 #if defined(TARGET_MIPS64)
1548 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1549 sum = (int32_t)sum;
1551 #endif
1552 return sum;
1555 /* Sign-extract the low 32-bits to a target_long. */
1556 void gen_move_low32(TCGv ret, TCGv_i64 arg)
1558 #if defined(TARGET_MIPS64)
1559 tcg_gen_ext32s_i64(ret, arg);
1560 #else
1561 tcg_gen_extrl_i64_i32(ret, arg);
1562 #endif
1565 /* Sign-extract the high 32-bits to a target_long. */
1566 void gen_move_high32(TCGv ret, TCGv_i64 arg)
1568 #if defined(TARGET_MIPS64)
1569 tcg_gen_sari_i64(ret, arg, 32);
1570 #else
1571 tcg_gen_extrh_i64_i32(ret, arg);
1572 #endif
1575 void check_cp0_enabled(DisasContext *ctx)
1577 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1578 generate_exception_end(ctx, EXCP_CpU);
1582 void check_cp1_enabled(DisasContext *ctx)
1584 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
1585 generate_exception_err(ctx, EXCP_CpU, 1);
1590 * Verify that the processor is running with COP1X instructions enabled.
1591 * This is associated with the nabla symbol in the MIPS32 and MIPS64
1592 * opcode tables.
1594 void check_cop1x(DisasContext *ctx)
1596 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
1597 gen_reserved_instruction(ctx);
1602 * Verify that the processor is running with 64-bit floating-point
1603 * operations enabled.
1605 void check_cp1_64bitmode(DisasContext *ctx)
1607 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
1608 gen_reserved_instruction(ctx);
1613 * Verify if floating point register is valid; an operation is not defined
1614 * if bit 0 of any register specification is set and the FR bit in the
1615 * Status register equals zero, since the register numbers specify an
1616 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1617 * in the Status register equals one, both even and odd register numbers
1618 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1620 * Multiple 64 bit wide registers can be checked by calling
1621 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1623 void check_cp1_registers(DisasContext *ctx, int regs)
1625 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
1626 gen_reserved_instruction(ctx);
1631 * Verify that the processor is running with DSP instructions enabled.
1632 * This is enabled by CP0 Status register MX(24) bit.
1634 static inline void check_dsp(DisasContext *ctx)
1636 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1637 if (ctx->insn_flags & ASE_DSP) {
1638 generate_exception_end(ctx, EXCP_DSPDIS);
1639 } else {
1640 gen_reserved_instruction(ctx);
1645 static inline void check_dsp_r2(DisasContext *ctx)
1647 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
1648 if (ctx->insn_flags & ASE_DSP) {
1649 generate_exception_end(ctx, EXCP_DSPDIS);
1650 } else {
1651 gen_reserved_instruction(ctx);
1656 static inline void check_dsp_r3(DisasContext *ctx)
1658 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
1659 if (ctx->insn_flags & ASE_DSP) {
1660 generate_exception_end(ctx, EXCP_DSPDIS);
1661 } else {
1662 gen_reserved_instruction(ctx);
1668 * This code generates a "reserved instruction" exception if the
1669 * CPU does not support the instruction set corresponding to flags.
1671 void check_insn(DisasContext *ctx, uint64_t flags)
1673 if (unlikely(!(ctx->insn_flags & flags))) {
1674 gen_reserved_instruction(ctx);
1679 * This code generates a "reserved instruction" exception if the
1680 * CPU has corresponding flag set which indicates that the instruction
1681 * has been removed.
1683 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
1685 if (unlikely(ctx->insn_flags & flags)) {
1686 gen_reserved_instruction(ctx);
1691 * The Linux kernel traps certain reserved instruction exceptions to
1692 * emulate the corresponding instructions. QEMU is the kernel in user
1693 * mode, so those traps are emulated by accepting the instructions.
1695 * A reserved instruction exception is generated for flagged CPUs if
1696 * QEMU runs in system mode.
1698 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
1700 #ifndef CONFIG_USER_ONLY
1701 check_insn_opc_removed(ctx, flags);
1702 #endif
1706 * This code generates a "reserved instruction" exception if the
1707 * CPU does not support 64-bit paired-single (PS) floating point data type.
1709 static inline void check_ps(DisasContext *ctx)
1711 if (unlikely(!ctx->ps)) {
1712 generate_exception(ctx, EXCP_RI);
1714 check_cp1_64bitmode(ctx);
1718 * This code generates a "reserved instruction" exception if cpu is not
1719 * 64-bit or 64-bit instructions are not enabled.
1721 void check_mips_64(DisasContext *ctx)
1723 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
1724 gen_reserved_instruction(ctx);
1728 #ifndef CONFIG_USER_ONLY
1729 static inline void check_mvh(DisasContext *ctx)
1731 if (unlikely(!ctx->mvh)) {
1732 generate_exception(ctx, EXCP_RI);
1735 #endif
1738 * This code generates a "reserved instruction" exception if the
1739 * Config5 XNP bit is set.
1741 static inline void check_xnp(DisasContext *ctx)
1743 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
1744 gen_reserved_instruction(ctx);
1748 #ifndef CONFIG_USER_ONLY
1750 * This code generates a "reserved instruction" exception if the
1751 * Config3 PW bit is NOT set.
1753 static inline void check_pw(DisasContext *ctx)
1755 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
1756 gen_reserved_instruction(ctx);
1759 #endif
1762 * This code generates a "reserved instruction" exception if the
1763 * Config3 MT bit is NOT set.
1765 static inline void check_mt(DisasContext *ctx)
1767 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1768 gen_reserved_instruction(ctx);
1772 #ifndef CONFIG_USER_ONLY
1774 * This code generates a "coprocessor unusable" exception if CP0 is not
1775 * available, and, if that is not the case, generates a "reserved instruction"
1776 * exception if the Config5 MT bit is NOT set. This is needed for availability
1777 * control of some of MT ASE instructions.
1779 static inline void check_cp0_mt(DisasContext *ctx)
1781 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1782 generate_exception_end(ctx, EXCP_CpU);
1783 } else {
1784 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1785 gen_reserved_instruction(ctx);
1789 #endif
1792 * This code generates a "reserved instruction" exception if the
1793 * Config5 NMS bit is set.
1795 static inline void check_nms(DisasContext *ctx)
1797 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
1798 gen_reserved_instruction(ctx);
1803 * This code generates a "reserved instruction" exception if the
1804 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
1805 * Config2 TL, and Config5 L2C are unset.
1807 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
1809 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
1810 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
1811 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
1812 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
1813 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
1814 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
1815 gen_reserved_instruction(ctx);
1820 * This code generates a "reserved instruction" exception if the
1821 * Config5 EVA bit is NOT set.
1823 static inline void check_eva(DisasContext *ctx)
1825 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
1826 gen_reserved_instruction(ctx);
1832 * Define small wrappers for gen_load_fpr* so that we have a uniform
1833 * calling interface for 32 and 64-bit FPRs. No sense in changing
1834 * all callers for gen_load_fpr32 when we need the CTX parameter for
1835 * this one use.
1837 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1838 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1839 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1840 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1841 int ft, int fs, int cc) \
1843 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
1844 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
1845 switch (ifmt) { \
1846 case FMT_PS: \
1847 check_ps(ctx); \
1848 break; \
1849 case FMT_D: \
1850 if (abs) { \
1851 check_cop1x(ctx); \
1853 check_cp1_registers(ctx, fs | ft); \
1854 break; \
1855 case FMT_S: \
1856 if (abs) { \
1857 check_cop1x(ctx); \
1859 break; \
1861 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
1862 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
1863 switch (n) { \
1864 case 0: \
1865 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
1866 break; \
1867 case 1: \
1868 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
1869 break; \
1870 case 2: \
1871 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
1872 break; \
1873 case 3: \
1874 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
1875 break; \
1876 case 4: \
1877 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
1878 break; \
1879 case 5: \
1880 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
1881 break; \
1882 case 6: \
1883 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
1884 break; \
1885 case 7: \
1886 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
1887 break; \
1888 case 8: \
1889 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
1890 break; \
1891 case 9: \
1892 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
1893 break; \
1894 case 10: \
1895 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
1896 break; \
1897 case 11: \
1898 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
1899 break; \
1900 case 12: \
1901 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
1902 break; \
1903 case 13: \
1904 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
1905 break; \
1906 case 14: \
1907 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
1908 break; \
1909 case 15: \
1910 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
1911 break; \
1912 default: \
1913 abort(); \
1915 tcg_temp_free_i##bits(fp0); \
1916 tcg_temp_free_i##bits(fp1); \
1919 FOP_CONDS(, 0, d, FMT_D, 64)
1920 FOP_CONDS(abs, 1, d, FMT_D, 64)
1921 FOP_CONDS(, 0, s, FMT_S, 32)
1922 FOP_CONDS(abs, 1, s, FMT_S, 32)
1923 FOP_CONDS(, 0, ps, FMT_PS, 64)
1924 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1925 #undef FOP_CONDS
1927 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1928 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
1929 int ft, int fs, int fd) \
1931 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1932 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1933 if (ifmt == FMT_D) { \
1934 check_cp1_registers(ctx, fs | ft | fd); \
1936 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1937 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1938 switch (n) { \
1939 case 0: \
1940 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1941 break; \
1942 case 1: \
1943 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1944 break; \
1945 case 2: \
1946 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1947 break; \
1948 case 3: \
1949 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1950 break; \
1951 case 4: \
1952 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1953 break; \
1954 case 5: \
1955 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1956 break; \
1957 case 6: \
1958 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1959 break; \
1960 case 7: \
1961 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1962 break; \
1963 case 8: \
1964 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1965 break; \
1966 case 9: \
1967 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1968 break; \
1969 case 10: \
1970 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1971 break; \
1972 case 11: \
1973 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1974 break; \
1975 case 12: \
1976 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1977 break; \
1978 case 13: \
1979 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1980 break; \
1981 case 14: \
1982 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1983 break; \
1984 case 15: \
1985 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1986 break; \
1987 case 17: \
1988 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1989 break; \
1990 case 18: \
1991 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1992 break; \
1993 case 19: \
1994 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1995 break; \
1996 case 25: \
1997 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1998 break; \
1999 case 26: \
2000 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2001 break; \
2002 case 27: \
2003 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2004 break; \
2005 default: \
2006 abort(); \
2008 STORE; \
2009 tcg_temp_free_i ## bits(fp0); \
2010 tcg_temp_free_i ## bits(fp1); \
2013 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2014 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2015 #undef FOP_CONDNS
2016 #undef gen_ldcmp_fpr32
2017 #undef gen_ldcmp_fpr64
2019 /* load/store instructions. */
2020 #ifdef CONFIG_USER_ONLY
2021 #define OP_LD_ATOMIC(insn, fname) \
2022 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2023 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, int mem_idx, \
2035 DisasContext *ctx) \
2037 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2039 #endif
2040 OP_LD_ATOMIC(ll, ld32s);
2041 #if defined(TARGET_MIPS64)
2042 OP_LD_ATOMIC(lld, ld64);
2043 #endif
2044 #undef OP_LD_ATOMIC
2046 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
2048 if (base == 0) {
2049 tcg_gen_movi_tl(addr, offset);
2050 } else if (offset == 0) {
2051 gen_load_gpr(addr, base);
2052 } else {
2053 tcg_gen_movi_tl(addr, offset);
2054 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2058 static target_ulong pc_relative_pc(DisasContext *ctx)
2060 target_ulong pc = ctx->base.pc_next;
2062 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2063 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2065 pc -= branch_bytes;
2068 pc &= ~(target_ulong)3;
2069 return pc;
2072 /* Load */
2073 static void gen_ld(DisasContext *ctx, uint32_t opc,
2074 int rt, int base, int offset)
2076 TCGv t0, t1, t2;
2077 int mem_idx = ctx->mem_idx;
2079 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
2080 INSN_LOONGSON3A)) {
2082 * Loongson CPU uses a load to zero register for prefetch.
2083 * We emulate it as a NOP. On other CPU we must perform the
2084 * actual memory access.
2086 return;
2089 t0 = tcg_temp_new();
2090 gen_base_offset_addr(ctx, t0, base, offset);
2092 switch (opc) {
2093 #if defined(TARGET_MIPS64)
2094 case OPC_LWU:
2095 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
2096 ctx->default_tcg_memop_mask);
2097 gen_store_gpr(t0, rt);
2098 break;
2099 case OPC_LD:
2100 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
2101 ctx->default_tcg_memop_mask);
2102 gen_store_gpr(t0, rt);
2103 break;
2104 case OPC_LLD:
2105 case R6_OPC_LLD:
2106 op_ld_lld(t0, t0, mem_idx, ctx);
2107 gen_store_gpr(t0, rt);
2108 break;
2109 case OPC_LDL:
2110 t1 = tcg_temp_new();
2112 * Do a byte access to possibly trigger a page
2113 * fault with the unaligned address.
2115 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2116 tcg_gen_andi_tl(t1, t0, 7);
2117 #ifndef TARGET_WORDS_BIGENDIAN
2118 tcg_gen_xori_tl(t1, t1, 7);
2119 #endif
2120 tcg_gen_shli_tl(t1, t1, 3);
2121 tcg_gen_andi_tl(t0, t0, ~7);
2122 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2123 tcg_gen_shl_tl(t0, t0, t1);
2124 t2 = tcg_const_tl(-1);
2125 tcg_gen_shl_tl(t2, t2, t1);
2126 gen_load_gpr(t1, rt);
2127 tcg_gen_andc_tl(t1, t1, t2);
2128 tcg_temp_free(t2);
2129 tcg_gen_or_tl(t0, t0, t1);
2130 tcg_temp_free(t1);
2131 gen_store_gpr(t0, rt);
2132 break;
2133 case OPC_LDR:
2134 t1 = tcg_temp_new();
2136 * Do a byte access to possibly trigger a page
2137 * fault with the unaligned address.
2139 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2140 tcg_gen_andi_tl(t1, t0, 7);
2141 #ifdef TARGET_WORDS_BIGENDIAN
2142 tcg_gen_xori_tl(t1, t1, 7);
2143 #endif
2144 tcg_gen_shli_tl(t1, t1, 3);
2145 tcg_gen_andi_tl(t0, t0, ~7);
2146 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2147 tcg_gen_shr_tl(t0, t0, t1);
2148 tcg_gen_xori_tl(t1, t1, 63);
2149 t2 = tcg_const_tl(0xfffffffffffffffeull);
2150 tcg_gen_shl_tl(t2, t2, t1);
2151 gen_load_gpr(t1, rt);
2152 tcg_gen_and_tl(t1, t1, t2);
2153 tcg_temp_free(t2);
2154 tcg_gen_or_tl(t0, t0, t1);
2155 tcg_temp_free(t1);
2156 gen_store_gpr(t0, rt);
2157 break;
2158 case OPC_LDPC:
2159 t1 = tcg_const_tl(pc_relative_pc(ctx));
2160 gen_op_addr_add(ctx, t0, t0, t1);
2161 tcg_temp_free(t1);
2162 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2163 gen_store_gpr(t0, rt);
2164 break;
2165 #endif
2166 case OPC_LWPC:
2167 t1 = tcg_const_tl(pc_relative_pc(ctx));
2168 gen_op_addr_add(ctx, t0, t0, t1);
2169 tcg_temp_free(t1);
2170 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
2171 gen_store_gpr(t0, rt);
2172 break;
2173 case OPC_LWE:
2174 mem_idx = MIPS_HFLAG_UM;
2175 /* fall through */
2176 case OPC_LW:
2177 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
2178 ctx->default_tcg_memop_mask);
2179 gen_store_gpr(t0, rt);
2180 break;
2181 case OPC_LHE:
2182 mem_idx = MIPS_HFLAG_UM;
2183 /* fall through */
2184 case OPC_LH:
2185 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
2186 ctx->default_tcg_memop_mask);
2187 gen_store_gpr(t0, rt);
2188 break;
2189 case OPC_LHUE:
2190 mem_idx = MIPS_HFLAG_UM;
2191 /* fall through */
2192 case OPC_LHU:
2193 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
2194 ctx->default_tcg_memop_mask);
2195 gen_store_gpr(t0, rt);
2196 break;
2197 case OPC_LBE:
2198 mem_idx = MIPS_HFLAG_UM;
2199 /* fall through */
2200 case OPC_LB:
2201 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2202 gen_store_gpr(t0, rt);
2203 break;
2204 case OPC_LBUE:
2205 mem_idx = MIPS_HFLAG_UM;
2206 /* fall through */
2207 case OPC_LBU:
2208 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2209 gen_store_gpr(t0, rt);
2210 break;
2211 case OPC_LWLE:
2212 mem_idx = MIPS_HFLAG_UM;
2213 /* fall through */
2214 case OPC_LWL:
2215 t1 = tcg_temp_new();
2217 * Do a byte access to possibly trigger a page
2218 * fault with the unaligned address.
2220 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2221 tcg_gen_andi_tl(t1, t0, 3);
2222 #ifndef TARGET_WORDS_BIGENDIAN
2223 tcg_gen_xori_tl(t1, t1, 3);
2224 #endif
2225 tcg_gen_shli_tl(t1, t1, 3);
2226 tcg_gen_andi_tl(t0, t0, ~3);
2227 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2228 tcg_gen_shl_tl(t0, t0, t1);
2229 t2 = tcg_const_tl(-1);
2230 tcg_gen_shl_tl(t2, t2, t1);
2231 gen_load_gpr(t1, rt);
2232 tcg_gen_andc_tl(t1, t1, t2);
2233 tcg_temp_free(t2);
2234 tcg_gen_or_tl(t0, t0, t1);
2235 tcg_temp_free(t1);
2236 tcg_gen_ext32s_tl(t0, t0);
2237 gen_store_gpr(t0, rt);
2238 break;
2239 case OPC_LWRE:
2240 mem_idx = MIPS_HFLAG_UM;
2241 /* fall through */
2242 case OPC_LWR:
2243 t1 = tcg_temp_new();
2245 * Do a byte access to possibly trigger a page
2246 * fault with the unaligned address.
2248 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2249 tcg_gen_andi_tl(t1, t0, 3);
2250 #ifdef TARGET_WORDS_BIGENDIAN
2251 tcg_gen_xori_tl(t1, t1, 3);
2252 #endif
2253 tcg_gen_shli_tl(t1, t1, 3);
2254 tcg_gen_andi_tl(t0, t0, ~3);
2255 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2256 tcg_gen_shr_tl(t0, t0, t1);
2257 tcg_gen_xori_tl(t1, t1, 31);
2258 t2 = tcg_const_tl(0xfffffffeull);
2259 tcg_gen_shl_tl(t2, t2, t1);
2260 gen_load_gpr(t1, rt);
2261 tcg_gen_and_tl(t1, t1, t2);
2262 tcg_temp_free(t2);
2263 tcg_gen_or_tl(t0, t0, t1);
2264 tcg_temp_free(t1);
2265 tcg_gen_ext32s_tl(t0, t0);
2266 gen_store_gpr(t0, rt);
2267 break;
2268 case OPC_LLE:
2269 mem_idx = MIPS_HFLAG_UM;
2270 /* fall through */
2271 case OPC_LL:
2272 case R6_OPC_LL:
2273 op_ld_ll(t0, t0, mem_idx, ctx);
2274 gen_store_gpr(t0, rt);
2275 break;
2277 tcg_temp_free(t0);
2280 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
2281 uint32_t reg1, uint32_t reg2)
2283 TCGv taddr = tcg_temp_new();
2284 TCGv_i64 tval = tcg_temp_new_i64();
2285 TCGv tmp1 = tcg_temp_new();
2286 TCGv tmp2 = tcg_temp_new();
2288 gen_base_offset_addr(ctx, taddr, base, offset);
2289 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
2290 #ifdef TARGET_WORDS_BIGENDIAN
2291 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
2292 #else
2293 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
2294 #endif
2295 gen_store_gpr(tmp1, reg1);
2296 tcg_temp_free(tmp1);
2297 gen_store_gpr(tmp2, reg2);
2298 tcg_temp_free(tmp2);
2299 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2300 tcg_temp_free_i64(tval);
2301 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
2302 tcg_temp_free(taddr);
2305 /* Store */
2306 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
2307 int base, int offset)
2309 TCGv t0 = tcg_temp_new();
2310 TCGv t1 = tcg_temp_new();
2311 int mem_idx = ctx->mem_idx;
2313 gen_base_offset_addr(ctx, t0, base, offset);
2314 gen_load_gpr(t1, rt);
2315 switch (opc) {
2316 #if defined(TARGET_MIPS64)
2317 case OPC_SD:
2318 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
2319 ctx->default_tcg_memop_mask);
2320 break;
2321 case OPC_SDL:
2322 gen_helper_0e2i(sdl, t1, t0, mem_idx);
2323 break;
2324 case OPC_SDR:
2325 gen_helper_0e2i(sdr, t1, t0, mem_idx);
2326 break;
2327 #endif
2328 case OPC_SWE:
2329 mem_idx = MIPS_HFLAG_UM;
2330 /* fall through */
2331 case OPC_SW:
2332 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
2333 ctx->default_tcg_memop_mask);
2334 break;
2335 case OPC_SHE:
2336 mem_idx = MIPS_HFLAG_UM;
2337 /* fall through */
2338 case OPC_SH:
2339 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
2340 ctx->default_tcg_memop_mask);
2341 break;
2342 case OPC_SBE:
2343 mem_idx = MIPS_HFLAG_UM;
2344 /* fall through */
2345 case OPC_SB:
2346 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
2347 break;
2348 case OPC_SWLE:
2349 mem_idx = MIPS_HFLAG_UM;
2350 /* fall through */
2351 case OPC_SWL:
2352 gen_helper_0e2i(swl, t1, t0, mem_idx);
2353 break;
2354 case OPC_SWRE:
2355 mem_idx = MIPS_HFLAG_UM;
2356 /* fall through */
2357 case OPC_SWR:
2358 gen_helper_0e2i(swr, t1, t0, mem_idx);
2359 break;
2361 tcg_temp_free(t0);
2362 tcg_temp_free(t1);
2366 /* Store conditional */
2367 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
2368 MemOp tcg_mo, bool eva)
2370 TCGv addr, t0, val;
2371 TCGLabel *l1 = gen_new_label();
2372 TCGLabel *done = gen_new_label();
2374 t0 = tcg_temp_new();
2375 addr = tcg_temp_new();
2376 /* compare the address against that of the preceding LL */
2377 gen_base_offset_addr(ctx, addr, base, offset);
2378 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
2379 tcg_temp_free(addr);
2380 tcg_gen_movi_tl(t0, 0);
2381 gen_store_gpr(t0, rt);
2382 tcg_gen_br(done);
2384 gen_set_label(l1);
2385 /* generate cmpxchg */
2386 val = tcg_temp_new();
2387 gen_load_gpr(val, rt);
2388 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
2389 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
2390 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
2391 gen_store_gpr(t0, rt);
2392 tcg_temp_free(val);
2394 gen_set_label(done);
2395 tcg_temp_free(t0);
2399 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
2400 uint32_t reg1, uint32_t reg2, bool eva)
2402 TCGv taddr = tcg_temp_local_new();
2403 TCGv lladdr = tcg_temp_local_new();
2404 TCGv_i64 tval = tcg_temp_new_i64();
2405 TCGv_i64 llval = tcg_temp_new_i64();
2406 TCGv_i64 val = tcg_temp_new_i64();
2407 TCGv tmp1 = tcg_temp_new();
2408 TCGv tmp2 = tcg_temp_new();
2409 TCGLabel *lab_fail = gen_new_label();
2410 TCGLabel *lab_done = gen_new_label();
2412 gen_base_offset_addr(ctx, taddr, base, offset);
2414 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2415 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
2417 gen_load_gpr(tmp1, reg1);
2418 gen_load_gpr(tmp2, reg2);
2420 #ifdef TARGET_WORDS_BIGENDIAN
2421 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
2422 #else
2423 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
2424 #endif
2426 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2427 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
2428 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
2429 if (reg1 != 0) {
2430 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
2432 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
2434 gen_set_label(lab_fail);
2436 if (reg1 != 0) {
2437 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
2439 gen_set_label(lab_done);
2440 tcg_gen_movi_tl(lladdr, -1);
2441 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2444 /* Load and store */
2445 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
2446 TCGv t0)
2449 * Don't do NOP if destination is zero: we must perform the actual
2450 * memory access.
2452 switch (opc) {
2453 case OPC_LWC1:
2455 TCGv_i32 fp0 = tcg_temp_new_i32();
2456 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2457 ctx->default_tcg_memop_mask);
2458 gen_store_fpr32(ctx, fp0, ft);
2459 tcg_temp_free_i32(fp0);
2461 break;
2462 case OPC_SWC1:
2464 TCGv_i32 fp0 = tcg_temp_new_i32();
2465 gen_load_fpr32(ctx, fp0, ft);
2466 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2467 ctx->default_tcg_memop_mask);
2468 tcg_temp_free_i32(fp0);
2470 break;
2471 case OPC_LDC1:
2473 TCGv_i64 fp0 = tcg_temp_new_i64();
2474 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2475 ctx->default_tcg_memop_mask);
2476 gen_store_fpr64(ctx, fp0, ft);
2477 tcg_temp_free_i64(fp0);
2479 break;
2480 case OPC_SDC1:
2482 TCGv_i64 fp0 = tcg_temp_new_i64();
2483 gen_load_fpr64(ctx, fp0, ft);
2484 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2485 ctx->default_tcg_memop_mask);
2486 tcg_temp_free_i64(fp0);
2488 break;
2489 default:
2490 MIPS_INVAL("flt_ldst");
2491 gen_reserved_instruction(ctx);
2492 break;
2496 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2497 int rs, int16_t imm)
2499 TCGv t0 = tcg_temp_new();
2501 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2502 check_cp1_enabled(ctx);
2503 switch (op) {
2504 case OPC_LDC1:
2505 case OPC_SDC1:
2506 check_insn(ctx, ISA_MIPS2);
2507 /* Fallthrough */
2508 default:
2509 gen_base_offset_addr(ctx, t0, rs, imm);
2510 gen_flt_ldst(ctx, op, rt, t0);
2512 } else {
2513 generate_exception_err(ctx, EXCP_CpU, 1);
2515 tcg_temp_free(t0);
2518 /* Arithmetic with immediate operand */
2519 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2520 int rt, int rs, int imm)
2522 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2524 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2526 * If no destination, treat it as a NOP.
2527 * For addi, we must generate the overflow exception when needed.
2529 return;
2531 switch (opc) {
2532 case OPC_ADDI:
2534 TCGv t0 = tcg_temp_local_new();
2535 TCGv t1 = tcg_temp_new();
2536 TCGv t2 = tcg_temp_new();
2537 TCGLabel *l1 = gen_new_label();
2539 gen_load_gpr(t1, rs);
2540 tcg_gen_addi_tl(t0, t1, uimm);
2541 tcg_gen_ext32s_tl(t0, t0);
2543 tcg_gen_xori_tl(t1, t1, ~uimm);
2544 tcg_gen_xori_tl(t2, t0, uimm);
2545 tcg_gen_and_tl(t1, t1, t2);
2546 tcg_temp_free(t2);
2547 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2548 tcg_temp_free(t1);
2549 /* operands of same sign, result different sign */
2550 generate_exception(ctx, EXCP_OVERFLOW);
2551 gen_set_label(l1);
2552 tcg_gen_ext32s_tl(t0, t0);
2553 gen_store_gpr(t0, rt);
2554 tcg_temp_free(t0);
2556 break;
2557 case OPC_ADDIU:
2558 if (rs != 0) {
2559 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2560 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2561 } else {
2562 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2564 break;
2565 #if defined(TARGET_MIPS64)
2566 case OPC_DADDI:
2568 TCGv t0 = tcg_temp_local_new();
2569 TCGv t1 = tcg_temp_new();
2570 TCGv t2 = tcg_temp_new();
2571 TCGLabel *l1 = gen_new_label();
2573 gen_load_gpr(t1, rs);
2574 tcg_gen_addi_tl(t0, t1, uimm);
2576 tcg_gen_xori_tl(t1, t1, ~uimm);
2577 tcg_gen_xori_tl(t2, t0, uimm);
2578 tcg_gen_and_tl(t1, t1, t2);
2579 tcg_temp_free(t2);
2580 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2581 tcg_temp_free(t1);
2582 /* operands of same sign, result different sign */
2583 generate_exception(ctx, EXCP_OVERFLOW);
2584 gen_set_label(l1);
2585 gen_store_gpr(t0, rt);
2586 tcg_temp_free(t0);
2588 break;
2589 case OPC_DADDIU:
2590 if (rs != 0) {
2591 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2592 } else {
2593 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2595 break;
2596 #endif
2600 /* Logic with immediate operand */
2601 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2602 int rt, int rs, int16_t imm)
2604 target_ulong uimm;
2606 if (rt == 0) {
2607 /* If no destination, treat it as a NOP. */
2608 return;
2610 uimm = (uint16_t)imm;
2611 switch (opc) {
2612 case OPC_ANDI:
2613 if (likely(rs != 0)) {
2614 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2615 } else {
2616 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2618 break;
2619 case OPC_ORI:
2620 if (rs != 0) {
2621 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2622 } else {
2623 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2625 break;
2626 case OPC_XORI:
2627 if (likely(rs != 0)) {
2628 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2629 } else {
2630 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2632 break;
2633 case OPC_LUI:
2634 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
2635 /* OPC_AUI */
2636 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2637 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2638 } else {
2639 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2641 break;
2643 default:
2644 break;
2648 /* Set on less than with immediate operand */
2649 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2650 int rt, int rs, int16_t imm)
2652 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2653 TCGv t0;
2655 if (rt == 0) {
2656 /* If no destination, treat it as a NOP. */
2657 return;
2659 t0 = tcg_temp_new();
2660 gen_load_gpr(t0, rs);
2661 switch (opc) {
2662 case OPC_SLTI:
2663 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2664 break;
2665 case OPC_SLTIU:
2666 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2667 break;
2669 tcg_temp_free(t0);
2672 /* Shifts with immediate operand */
2673 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2674 int rt, int rs, int16_t imm)
2676 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2677 TCGv t0;
2679 if (rt == 0) {
2680 /* If no destination, treat it as a NOP. */
2681 return;
2684 t0 = tcg_temp_new();
2685 gen_load_gpr(t0, rs);
2686 switch (opc) {
2687 case OPC_SLL:
2688 tcg_gen_shli_tl(t0, t0, uimm);
2689 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2690 break;
2691 case OPC_SRA:
2692 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2693 break;
2694 case OPC_SRL:
2695 if (uimm != 0) {
2696 tcg_gen_ext32u_tl(t0, t0);
2697 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2698 } else {
2699 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2701 break;
2702 case OPC_ROTR:
2703 if (uimm != 0) {
2704 TCGv_i32 t1 = tcg_temp_new_i32();
2706 tcg_gen_trunc_tl_i32(t1, t0);
2707 tcg_gen_rotri_i32(t1, t1, uimm);
2708 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2709 tcg_temp_free_i32(t1);
2710 } else {
2711 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2713 break;
2714 #if defined(TARGET_MIPS64)
2715 case OPC_DSLL:
2716 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2717 break;
2718 case OPC_DSRA:
2719 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2720 break;
2721 case OPC_DSRL:
2722 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2723 break;
2724 case OPC_DROTR:
2725 if (uimm != 0) {
2726 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2727 } else {
2728 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2730 break;
2731 case OPC_DSLL32:
2732 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2733 break;
2734 case OPC_DSRA32:
2735 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2736 break;
2737 case OPC_DSRL32:
2738 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2739 break;
2740 case OPC_DROTR32:
2741 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2742 break;
2743 #endif
2745 tcg_temp_free(t0);
2748 /* Arithmetic */
2749 static void gen_arith(DisasContext *ctx, uint32_t opc,
2750 int rd, int rs, int rt)
2752 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2753 && opc != OPC_DADD && opc != OPC_DSUB) {
2755 * If no destination, treat it as a NOP.
2756 * For add & sub, we must generate the overflow exception when needed.
2758 return;
2761 switch (opc) {
2762 case OPC_ADD:
2764 TCGv t0 = tcg_temp_local_new();
2765 TCGv t1 = tcg_temp_new();
2766 TCGv t2 = tcg_temp_new();
2767 TCGLabel *l1 = gen_new_label();
2769 gen_load_gpr(t1, rs);
2770 gen_load_gpr(t2, rt);
2771 tcg_gen_add_tl(t0, t1, t2);
2772 tcg_gen_ext32s_tl(t0, t0);
2773 tcg_gen_xor_tl(t1, t1, t2);
2774 tcg_gen_xor_tl(t2, t0, t2);
2775 tcg_gen_andc_tl(t1, t2, t1);
2776 tcg_temp_free(t2);
2777 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2778 tcg_temp_free(t1);
2779 /* operands of same sign, result different sign */
2780 generate_exception(ctx, EXCP_OVERFLOW);
2781 gen_set_label(l1);
2782 gen_store_gpr(t0, rd);
2783 tcg_temp_free(t0);
2785 break;
2786 case OPC_ADDU:
2787 if (rs != 0 && rt != 0) {
2788 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2789 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2790 } else if (rs == 0 && rt != 0) {
2791 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2792 } else if (rs != 0 && rt == 0) {
2793 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2794 } else {
2795 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2797 break;
2798 case OPC_SUB:
2800 TCGv t0 = tcg_temp_local_new();
2801 TCGv t1 = tcg_temp_new();
2802 TCGv t2 = tcg_temp_new();
2803 TCGLabel *l1 = gen_new_label();
2805 gen_load_gpr(t1, rs);
2806 gen_load_gpr(t2, rt);
2807 tcg_gen_sub_tl(t0, t1, t2);
2808 tcg_gen_ext32s_tl(t0, t0);
2809 tcg_gen_xor_tl(t2, t1, t2);
2810 tcg_gen_xor_tl(t1, t0, t1);
2811 tcg_gen_and_tl(t1, t1, t2);
2812 tcg_temp_free(t2);
2813 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2814 tcg_temp_free(t1);
2816 * operands of different sign, first operand and the result
2817 * of different sign
2819 generate_exception(ctx, EXCP_OVERFLOW);
2820 gen_set_label(l1);
2821 gen_store_gpr(t0, rd);
2822 tcg_temp_free(t0);
2824 break;
2825 case OPC_SUBU:
2826 if (rs != 0 && rt != 0) {
2827 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2828 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2829 } else if (rs == 0 && rt != 0) {
2830 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2831 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2832 } else if (rs != 0 && rt == 0) {
2833 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2834 } else {
2835 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2837 break;
2838 #if defined(TARGET_MIPS64)
2839 case OPC_DADD:
2841 TCGv t0 = tcg_temp_local_new();
2842 TCGv t1 = tcg_temp_new();
2843 TCGv t2 = tcg_temp_new();
2844 TCGLabel *l1 = gen_new_label();
2846 gen_load_gpr(t1, rs);
2847 gen_load_gpr(t2, rt);
2848 tcg_gen_add_tl(t0, t1, t2);
2849 tcg_gen_xor_tl(t1, t1, t2);
2850 tcg_gen_xor_tl(t2, t0, t2);
2851 tcg_gen_andc_tl(t1, t2, t1);
2852 tcg_temp_free(t2);
2853 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2854 tcg_temp_free(t1);
2855 /* operands of same sign, result different sign */
2856 generate_exception(ctx, EXCP_OVERFLOW);
2857 gen_set_label(l1);
2858 gen_store_gpr(t0, rd);
2859 tcg_temp_free(t0);
2861 break;
2862 case OPC_DADDU:
2863 if (rs != 0 && rt != 0) {
2864 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2865 } else if (rs == 0 && rt != 0) {
2866 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2867 } else if (rs != 0 && rt == 0) {
2868 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2869 } else {
2870 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2872 break;
2873 case OPC_DSUB:
2875 TCGv t0 = tcg_temp_local_new();
2876 TCGv t1 = tcg_temp_new();
2877 TCGv t2 = tcg_temp_new();
2878 TCGLabel *l1 = gen_new_label();
2880 gen_load_gpr(t1, rs);
2881 gen_load_gpr(t2, rt);
2882 tcg_gen_sub_tl(t0, t1, t2);
2883 tcg_gen_xor_tl(t2, t1, t2);
2884 tcg_gen_xor_tl(t1, t0, t1);
2885 tcg_gen_and_tl(t1, t1, t2);
2886 tcg_temp_free(t2);
2887 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2888 tcg_temp_free(t1);
2890 * Operands of different sign, first operand and result different
2891 * sign.
2893 generate_exception(ctx, EXCP_OVERFLOW);
2894 gen_set_label(l1);
2895 gen_store_gpr(t0, rd);
2896 tcg_temp_free(t0);
2898 break;
2899 case OPC_DSUBU:
2900 if (rs != 0 && rt != 0) {
2901 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2902 } else if (rs == 0 && rt != 0) {
2903 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2904 } else if (rs != 0 && rt == 0) {
2905 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2906 } else {
2907 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2909 break;
2910 #endif
2911 case OPC_MUL:
2912 if (likely(rs != 0 && rt != 0)) {
2913 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2914 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2915 } else {
2916 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2918 break;
2922 /* Conditional move */
2923 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2924 int rd, int rs, int rt)
2926 TCGv t0, t1, t2;
2928 if (rd == 0) {
2929 /* If no destination, treat it as a NOP. */
2930 return;
2933 t0 = tcg_temp_new();
2934 gen_load_gpr(t0, rt);
2935 t1 = tcg_const_tl(0);
2936 t2 = tcg_temp_new();
2937 gen_load_gpr(t2, rs);
2938 switch (opc) {
2939 case OPC_MOVN:
2940 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2941 break;
2942 case OPC_MOVZ:
2943 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2944 break;
2945 case OPC_SELNEZ:
2946 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2947 break;
2948 case OPC_SELEQZ:
2949 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2950 break;
2952 tcg_temp_free(t2);
2953 tcg_temp_free(t1);
2954 tcg_temp_free(t0);
2957 /* Logic */
2958 static void gen_logic(DisasContext *ctx, uint32_t opc,
2959 int rd, int rs, int rt)
2961 if (rd == 0) {
2962 /* If no destination, treat it as a NOP. */
2963 return;
2966 switch (opc) {
2967 case OPC_AND:
2968 if (likely(rs != 0 && rt != 0)) {
2969 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2970 } else {
2971 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2973 break;
2974 case OPC_NOR:
2975 if (rs != 0 && rt != 0) {
2976 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2977 } else if (rs == 0 && rt != 0) {
2978 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2979 } else if (rs != 0 && rt == 0) {
2980 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2981 } else {
2982 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2984 break;
2985 case OPC_OR:
2986 if (likely(rs != 0 && rt != 0)) {
2987 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2988 } else if (rs == 0 && rt != 0) {
2989 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2990 } else if (rs != 0 && rt == 0) {
2991 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2992 } else {
2993 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2995 break;
2996 case OPC_XOR:
2997 if (likely(rs != 0 && rt != 0)) {
2998 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2999 } else if (rs == 0 && rt != 0) {
3000 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3001 } else if (rs != 0 && rt == 0) {
3002 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3003 } else {
3004 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3006 break;
3010 /* Set on lower than */
3011 static void gen_slt(DisasContext *ctx, uint32_t opc,
3012 int rd, int rs, int rt)
3014 TCGv t0, t1;
3016 if (rd == 0) {
3017 /* If no destination, treat it as a NOP. */
3018 return;
3021 t0 = tcg_temp_new();
3022 t1 = tcg_temp_new();
3023 gen_load_gpr(t0, rs);
3024 gen_load_gpr(t1, rt);
3025 switch (opc) {
3026 case OPC_SLT:
3027 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3028 break;
3029 case OPC_SLTU:
3030 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3031 break;
3033 tcg_temp_free(t0);
3034 tcg_temp_free(t1);
3037 /* Shifts */
3038 static void gen_shift(DisasContext *ctx, uint32_t opc,
3039 int rd, int rs, int rt)
3041 TCGv t0, t1;
3043 if (rd == 0) {
3045 * If no destination, treat it as a NOP.
3046 * For add & sub, we must generate the overflow exception when needed.
3048 return;
3051 t0 = tcg_temp_new();
3052 t1 = tcg_temp_new();
3053 gen_load_gpr(t0, rs);
3054 gen_load_gpr(t1, rt);
3055 switch (opc) {
3056 case OPC_SLLV:
3057 tcg_gen_andi_tl(t0, t0, 0x1f);
3058 tcg_gen_shl_tl(t0, t1, t0);
3059 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3060 break;
3061 case OPC_SRAV:
3062 tcg_gen_andi_tl(t0, t0, 0x1f);
3063 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3064 break;
3065 case OPC_SRLV:
3066 tcg_gen_ext32u_tl(t1, t1);
3067 tcg_gen_andi_tl(t0, t0, 0x1f);
3068 tcg_gen_shr_tl(t0, t1, t0);
3069 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3070 break;
3071 case OPC_ROTRV:
3073 TCGv_i32 t2 = tcg_temp_new_i32();
3074 TCGv_i32 t3 = tcg_temp_new_i32();
3076 tcg_gen_trunc_tl_i32(t2, t0);
3077 tcg_gen_trunc_tl_i32(t3, t1);
3078 tcg_gen_andi_i32(t2, t2, 0x1f);
3079 tcg_gen_rotr_i32(t2, t3, t2);
3080 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3081 tcg_temp_free_i32(t2);
3082 tcg_temp_free_i32(t3);
3084 break;
3085 #if defined(TARGET_MIPS64)
3086 case OPC_DSLLV:
3087 tcg_gen_andi_tl(t0, t0, 0x3f);
3088 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3089 break;
3090 case OPC_DSRAV:
3091 tcg_gen_andi_tl(t0, t0, 0x3f);
3092 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3093 break;
3094 case OPC_DSRLV:
3095 tcg_gen_andi_tl(t0, t0, 0x3f);
3096 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3097 break;
3098 case OPC_DROTRV:
3099 tcg_gen_andi_tl(t0, t0, 0x3f);
3100 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3101 break;
3102 #endif
3104 tcg_temp_free(t0);
3105 tcg_temp_free(t1);
3108 /* Arithmetic on HI/LO registers */
3109 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3111 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3112 /* Treat as NOP. */
3113 return;
3116 if (acc != 0) {
3117 check_dsp(ctx);
3120 switch (opc) {
3121 case OPC_MFHI:
3122 #if defined(TARGET_MIPS64)
3123 if (acc != 0) {
3124 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3125 } else
3126 #endif
3128 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3130 break;
3131 case OPC_MFLO:
3132 #if defined(TARGET_MIPS64)
3133 if (acc != 0) {
3134 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3135 } else
3136 #endif
3138 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3140 break;
3141 case OPC_MTHI:
3142 if (reg != 0) {
3143 #if defined(TARGET_MIPS64)
3144 if (acc != 0) {
3145 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3146 } else
3147 #endif
3149 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3151 } else {
3152 tcg_gen_movi_tl(cpu_HI[acc], 0);
3154 break;
3155 case OPC_MTLO:
3156 if (reg != 0) {
3157 #if defined(TARGET_MIPS64)
3158 if (acc != 0) {
3159 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3160 } else
3161 #endif
3163 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3165 } else {
3166 tcg_gen_movi_tl(cpu_LO[acc], 0);
3168 break;
3172 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3173 MemOp memop)
3175 TCGv t0 = tcg_const_tl(addr);
3176 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3177 gen_store_gpr(t0, reg);
3178 tcg_temp_free(t0);
3181 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3182 int rs)
3184 target_long offset;
3185 target_long addr;
3187 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3188 case OPC_ADDIUPC:
3189 if (rs != 0) {
3190 offset = sextract32(ctx->opcode << 2, 0, 21);
3191 addr = addr_add(ctx, pc, offset);
3192 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3194 break;
3195 case R6_OPC_LWPC:
3196 offset = sextract32(ctx->opcode << 2, 0, 21);
3197 addr = addr_add(ctx, pc, offset);
3198 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3199 break;
3200 #if defined(TARGET_MIPS64)
3201 case OPC_LWUPC:
3202 check_mips_64(ctx);
3203 offset = sextract32(ctx->opcode << 2, 0, 21);
3204 addr = addr_add(ctx, pc, offset);
3205 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3206 break;
3207 #endif
3208 default:
3209 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3210 case OPC_AUIPC:
3211 if (rs != 0) {
3212 offset = sextract32(ctx->opcode, 0, 16) << 16;
3213 addr = addr_add(ctx, pc, offset);
3214 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3216 break;
3217 case OPC_ALUIPC:
3218 if (rs != 0) {
3219 offset = sextract32(ctx->opcode, 0, 16) << 16;
3220 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3221 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3223 break;
3224 #if defined(TARGET_MIPS64)
3225 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3226 case R6_OPC_LDPC + (1 << 16):
3227 case R6_OPC_LDPC + (2 << 16):
3228 case R6_OPC_LDPC + (3 << 16):
3229 check_mips_64(ctx);
3230 offset = sextract32(ctx->opcode << 3, 0, 21);
3231 addr = addr_add(ctx, (pc & ~0x7), offset);
3232 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3233 break;
3234 #endif
3235 default:
3236 MIPS_INVAL("OPC_PCREL");
3237 gen_reserved_instruction(ctx);
3238 break;
3240 break;
3244 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3246 TCGv t0, t1;
3248 if (rd == 0) {
3249 /* Treat as NOP. */
3250 return;
3253 t0 = tcg_temp_new();
3254 t1 = tcg_temp_new();
3256 gen_load_gpr(t0, rs);
3257 gen_load_gpr(t1, rt);
3259 switch (opc) {
3260 case R6_OPC_DIV:
3262 TCGv t2 = tcg_temp_new();
3263 TCGv t3 = tcg_temp_new();
3264 tcg_gen_ext32s_tl(t0, t0);
3265 tcg_gen_ext32s_tl(t1, t1);
3266 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3267 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3268 tcg_gen_and_tl(t2, t2, t3);
3269 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3270 tcg_gen_or_tl(t2, t2, t3);
3271 tcg_gen_movi_tl(t3, 0);
3272 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3273 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3274 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3275 tcg_temp_free(t3);
3276 tcg_temp_free(t2);
3278 break;
3279 case R6_OPC_MOD:
3281 TCGv t2 = tcg_temp_new();
3282 TCGv t3 = tcg_temp_new();
3283 tcg_gen_ext32s_tl(t0, t0);
3284 tcg_gen_ext32s_tl(t1, t1);
3285 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3286 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3287 tcg_gen_and_tl(t2, t2, t3);
3288 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3289 tcg_gen_or_tl(t2, t2, t3);
3290 tcg_gen_movi_tl(t3, 0);
3291 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3292 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3293 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3294 tcg_temp_free(t3);
3295 tcg_temp_free(t2);
3297 break;
3298 case R6_OPC_DIVU:
3300 TCGv t2 = tcg_const_tl(0);
3301 TCGv t3 = tcg_const_tl(1);
3302 tcg_gen_ext32u_tl(t0, t0);
3303 tcg_gen_ext32u_tl(t1, t1);
3304 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3305 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3306 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3307 tcg_temp_free(t3);
3308 tcg_temp_free(t2);
3310 break;
3311 case R6_OPC_MODU:
3313 TCGv t2 = tcg_const_tl(0);
3314 TCGv t3 = tcg_const_tl(1);
3315 tcg_gen_ext32u_tl(t0, t0);
3316 tcg_gen_ext32u_tl(t1, t1);
3317 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3318 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3319 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3320 tcg_temp_free(t3);
3321 tcg_temp_free(t2);
3323 break;
3324 case R6_OPC_MUL:
3326 TCGv_i32 t2 = tcg_temp_new_i32();
3327 TCGv_i32 t3 = tcg_temp_new_i32();
3328 tcg_gen_trunc_tl_i32(t2, t0);
3329 tcg_gen_trunc_tl_i32(t3, t1);
3330 tcg_gen_mul_i32(t2, t2, t3);
3331 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3332 tcg_temp_free_i32(t2);
3333 tcg_temp_free_i32(t3);
3335 break;
3336 case R6_OPC_MUH:
3338 TCGv_i32 t2 = tcg_temp_new_i32();
3339 TCGv_i32 t3 = tcg_temp_new_i32();
3340 tcg_gen_trunc_tl_i32(t2, t0);
3341 tcg_gen_trunc_tl_i32(t3, t1);
3342 tcg_gen_muls2_i32(t2, t3, t2, t3);
3343 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3344 tcg_temp_free_i32(t2);
3345 tcg_temp_free_i32(t3);
3347 break;
3348 case R6_OPC_MULU:
3350 TCGv_i32 t2 = tcg_temp_new_i32();
3351 TCGv_i32 t3 = tcg_temp_new_i32();
3352 tcg_gen_trunc_tl_i32(t2, t0);
3353 tcg_gen_trunc_tl_i32(t3, t1);
3354 tcg_gen_mul_i32(t2, t2, t3);
3355 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3356 tcg_temp_free_i32(t2);
3357 tcg_temp_free_i32(t3);
3359 break;
3360 case R6_OPC_MUHU:
3362 TCGv_i32 t2 = tcg_temp_new_i32();
3363 TCGv_i32 t3 = tcg_temp_new_i32();
3364 tcg_gen_trunc_tl_i32(t2, t0);
3365 tcg_gen_trunc_tl_i32(t3, t1);
3366 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3367 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3368 tcg_temp_free_i32(t2);
3369 tcg_temp_free_i32(t3);
3371 break;
3372 #if defined(TARGET_MIPS64)
3373 case R6_OPC_DDIV:
3375 TCGv t2 = tcg_temp_new();
3376 TCGv t3 = tcg_temp_new();
3377 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3378 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3379 tcg_gen_and_tl(t2, t2, t3);
3380 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3381 tcg_gen_or_tl(t2, t2, t3);
3382 tcg_gen_movi_tl(t3, 0);
3383 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3384 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3385 tcg_temp_free(t3);
3386 tcg_temp_free(t2);
3388 break;
3389 case R6_OPC_DMOD:
3391 TCGv t2 = tcg_temp_new();
3392 TCGv t3 = tcg_temp_new();
3393 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3394 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3395 tcg_gen_and_tl(t2, t2, t3);
3396 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3397 tcg_gen_or_tl(t2, t2, t3);
3398 tcg_gen_movi_tl(t3, 0);
3399 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3400 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3401 tcg_temp_free(t3);
3402 tcg_temp_free(t2);
3404 break;
3405 case R6_OPC_DDIVU:
3407 TCGv t2 = tcg_const_tl(0);
3408 TCGv t3 = tcg_const_tl(1);
3409 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3410 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3411 tcg_temp_free(t3);
3412 tcg_temp_free(t2);
3414 break;
3415 case R6_OPC_DMODU:
3417 TCGv t2 = tcg_const_tl(0);
3418 TCGv t3 = tcg_const_tl(1);
3419 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3420 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3421 tcg_temp_free(t3);
3422 tcg_temp_free(t2);
3424 break;
3425 case R6_OPC_DMUL:
3426 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3427 break;
3428 case R6_OPC_DMUH:
3430 TCGv t2 = tcg_temp_new();
3431 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3432 tcg_temp_free(t2);
3434 break;
3435 case R6_OPC_DMULU:
3436 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3437 break;
3438 case R6_OPC_DMUHU:
3440 TCGv t2 = tcg_temp_new();
3441 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3442 tcg_temp_free(t2);
3444 break;
3445 #endif
3446 default:
3447 MIPS_INVAL("r6 mul/div");
3448 gen_reserved_instruction(ctx);
3449 goto out;
3451 out:
3452 tcg_temp_free(t0);
3453 tcg_temp_free(t1);
3456 #if defined(TARGET_MIPS64)
3457 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
3459 TCGv t0, t1;
3461 t0 = tcg_temp_new();
3462 t1 = tcg_temp_new();
3464 gen_load_gpr(t0, rs);
3465 gen_load_gpr(t1, rt);
3467 switch (opc) {
3468 case MMI_OPC_DIV1:
3470 TCGv t2 = tcg_temp_new();
3471 TCGv t3 = tcg_temp_new();
3472 tcg_gen_ext32s_tl(t0, t0);
3473 tcg_gen_ext32s_tl(t1, t1);
3474 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3475 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3476 tcg_gen_and_tl(t2, t2, t3);
3477 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3478 tcg_gen_or_tl(t2, t2, t3);
3479 tcg_gen_movi_tl(t3, 0);
3480 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3481 tcg_gen_div_tl(cpu_LO[1], t0, t1);
3482 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
3483 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3484 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3485 tcg_temp_free(t3);
3486 tcg_temp_free(t2);
3488 break;
3489 case MMI_OPC_DIVU1:
3491 TCGv t2 = tcg_const_tl(0);
3492 TCGv t3 = tcg_const_tl(1);
3493 tcg_gen_ext32u_tl(t0, t0);
3494 tcg_gen_ext32u_tl(t1, t1);
3495 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3496 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
3497 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
3498 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3499 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3500 tcg_temp_free(t3);
3501 tcg_temp_free(t2);
3503 break;
3504 default:
3505 MIPS_INVAL("div1 TX79");
3506 gen_reserved_instruction(ctx);
3507 goto out;
3509 out:
3510 tcg_temp_free(t0);
3511 tcg_temp_free(t1);
3513 #endif
3515 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3516 int acc, int rs, int rt)
3518 TCGv t0, t1;
3520 t0 = tcg_temp_new();
3521 t1 = tcg_temp_new();
3523 gen_load_gpr(t0, rs);
3524 gen_load_gpr(t1, rt);
3526 if (acc != 0) {
3527 check_dsp(ctx);
3530 switch (opc) {
3531 case OPC_DIV:
3533 TCGv t2 = tcg_temp_new();
3534 TCGv t3 = tcg_temp_new();
3535 tcg_gen_ext32s_tl(t0, t0);
3536 tcg_gen_ext32s_tl(t1, t1);
3537 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3538 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3539 tcg_gen_and_tl(t2, t2, t3);
3540 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3541 tcg_gen_or_tl(t2, t2, t3);
3542 tcg_gen_movi_tl(t3, 0);
3543 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3544 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3545 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3546 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3547 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3548 tcg_temp_free(t3);
3549 tcg_temp_free(t2);
3551 break;
3552 case OPC_DIVU:
3554 TCGv t2 = tcg_const_tl(0);
3555 TCGv t3 = tcg_const_tl(1);
3556 tcg_gen_ext32u_tl(t0, t0);
3557 tcg_gen_ext32u_tl(t1, t1);
3558 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3559 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3560 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3561 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3562 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3563 tcg_temp_free(t3);
3564 tcg_temp_free(t2);
3566 break;
3567 case OPC_MULT:
3569 TCGv_i32 t2 = tcg_temp_new_i32();
3570 TCGv_i32 t3 = tcg_temp_new_i32();
3571 tcg_gen_trunc_tl_i32(t2, t0);
3572 tcg_gen_trunc_tl_i32(t3, t1);
3573 tcg_gen_muls2_i32(t2, t3, t2, t3);
3574 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3575 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3576 tcg_temp_free_i32(t2);
3577 tcg_temp_free_i32(t3);
3579 break;
3580 case OPC_MULTU:
3582 TCGv_i32 t2 = tcg_temp_new_i32();
3583 TCGv_i32 t3 = tcg_temp_new_i32();
3584 tcg_gen_trunc_tl_i32(t2, t0);
3585 tcg_gen_trunc_tl_i32(t3, t1);
3586 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3587 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3588 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3589 tcg_temp_free_i32(t2);
3590 tcg_temp_free_i32(t3);
3592 break;
3593 #if defined(TARGET_MIPS64)
3594 case OPC_DDIV:
3596 TCGv t2 = tcg_temp_new();
3597 TCGv t3 = tcg_temp_new();
3598 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3599 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3600 tcg_gen_and_tl(t2, t2, t3);
3601 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3602 tcg_gen_or_tl(t2, t2, t3);
3603 tcg_gen_movi_tl(t3, 0);
3604 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3605 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3606 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3607 tcg_temp_free(t3);
3608 tcg_temp_free(t2);
3610 break;
3611 case OPC_DDIVU:
3613 TCGv t2 = tcg_const_tl(0);
3614 TCGv t3 = tcg_const_tl(1);
3615 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3616 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3617 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3618 tcg_temp_free(t3);
3619 tcg_temp_free(t2);
3621 break;
3622 case OPC_DMULT:
3623 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3624 break;
3625 case OPC_DMULTU:
3626 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3627 break;
3628 #endif
3629 case OPC_MADD:
3631 TCGv_i64 t2 = tcg_temp_new_i64();
3632 TCGv_i64 t3 = tcg_temp_new_i64();
3634 tcg_gen_ext_tl_i64(t2, t0);
3635 tcg_gen_ext_tl_i64(t3, t1);
3636 tcg_gen_mul_i64(t2, t2, t3);
3637 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3638 tcg_gen_add_i64(t2, t2, t3);
3639 tcg_temp_free_i64(t3);
3640 gen_move_low32(cpu_LO[acc], t2);
3641 gen_move_high32(cpu_HI[acc], t2);
3642 tcg_temp_free_i64(t2);
3644 break;
3645 case OPC_MADDU:
3647 TCGv_i64 t2 = tcg_temp_new_i64();
3648 TCGv_i64 t3 = tcg_temp_new_i64();
3650 tcg_gen_ext32u_tl(t0, t0);
3651 tcg_gen_ext32u_tl(t1, t1);
3652 tcg_gen_extu_tl_i64(t2, t0);
3653 tcg_gen_extu_tl_i64(t3, t1);
3654 tcg_gen_mul_i64(t2, t2, t3);
3655 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3656 tcg_gen_add_i64(t2, t2, t3);
3657 tcg_temp_free_i64(t3);
3658 gen_move_low32(cpu_LO[acc], t2);
3659 gen_move_high32(cpu_HI[acc], t2);
3660 tcg_temp_free_i64(t2);
3662 break;
3663 case OPC_MSUB:
3665 TCGv_i64 t2 = tcg_temp_new_i64();
3666 TCGv_i64 t3 = tcg_temp_new_i64();
3668 tcg_gen_ext_tl_i64(t2, t0);
3669 tcg_gen_ext_tl_i64(t3, t1);
3670 tcg_gen_mul_i64(t2, t2, t3);
3671 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3672 tcg_gen_sub_i64(t2, t3, t2);
3673 tcg_temp_free_i64(t3);
3674 gen_move_low32(cpu_LO[acc], t2);
3675 gen_move_high32(cpu_HI[acc], t2);
3676 tcg_temp_free_i64(t2);
3678 break;
3679 case OPC_MSUBU:
3681 TCGv_i64 t2 = tcg_temp_new_i64();
3682 TCGv_i64 t3 = tcg_temp_new_i64();
3684 tcg_gen_ext32u_tl(t0, t0);
3685 tcg_gen_ext32u_tl(t1, t1);
3686 tcg_gen_extu_tl_i64(t2, t0);
3687 tcg_gen_extu_tl_i64(t3, t1);
3688 tcg_gen_mul_i64(t2, t2, t3);
3689 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3690 tcg_gen_sub_i64(t2, t3, t2);
3691 tcg_temp_free_i64(t3);
3692 gen_move_low32(cpu_LO[acc], t2);
3693 gen_move_high32(cpu_HI[acc], t2);
3694 tcg_temp_free_i64(t2);
3696 break;
3697 default:
3698 MIPS_INVAL("mul/div");
3699 gen_reserved_instruction(ctx);
3700 goto out;
3702 out:
3703 tcg_temp_free(t0);
3704 tcg_temp_free(t1);
3708 * These MULT[U] and MADD[U] instructions implemented in for example
3709 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
3710 * architectures are special three-operand variants with the syntax
3712 * MULT[U][1] rd, rs, rt
3714 * such that
3716 * (rd, LO, HI) <- rs * rt
3718 * and
3720 * MADD[U][1] rd, rs, rt
3722 * such that
3724 * (rd, LO, HI) <- (LO, HI) + rs * rt
3726 * where the low-order 32-bits of the result is placed into both the
3727 * GPR rd and the special register LO. The high-order 32-bits of the
3728 * result is placed into the special register HI.
3730 * If the GPR rd is omitted in assembly language, it is taken to be 0,
3731 * which is the zero register that always reads as 0.
3733 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
3734 int rd, int rs, int rt)
3736 TCGv t0 = tcg_temp_new();
3737 TCGv t1 = tcg_temp_new();
3738 int acc = 0;
3740 gen_load_gpr(t0, rs);
3741 gen_load_gpr(t1, rt);
3743 switch (opc) {
3744 case MMI_OPC_MULT1:
3745 acc = 1;
3746 /* Fall through */
3747 case OPC_MULT:
3749 TCGv_i32 t2 = tcg_temp_new_i32();
3750 TCGv_i32 t3 = tcg_temp_new_i32();
3751 tcg_gen_trunc_tl_i32(t2, t0);
3752 tcg_gen_trunc_tl_i32(t3, t1);
3753 tcg_gen_muls2_i32(t2, t3, t2, t3);
3754 if (rd) {
3755 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3757 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3758 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3759 tcg_temp_free_i32(t2);
3760 tcg_temp_free_i32(t3);
3762 break;
3763 case MMI_OPC_MULTU1:
3764 acc = 1;
3765 /* Fall through */
3766 case OPC_MULTU:
3768 TCGv_i32 t2 = tcg_temp_new_i32();
3769 TCGv_i32 t3 = tcg_temp_new_i32();
3770 tcg_gen_trunc_tl_i32(t2, t0);
3771 tcg_gen_trunc_tl_i32(t3, t1);
3772 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3773 if (rd) {
3774 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3776 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3777 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3778 tcg_temp_free_i32(t2);
3779 tcg_temp_free_i32(t3);
3781 break;
3782 case MMI_OPC_MADD1:
3783 acc = 1;
3784 /* Fall through */
3785 case MMI_OPC_MADD:
3787 TCGv_i64 t2 = tcg_temp_new_i64();
3788 TCGv_i64 t3 = tcg_temp_new_i64();
3790 tcg_gen_ext_tl_i64(t2, t0);
3791 tcg_gen_ext_tl_i64(t3, t1);
3792 tcg_gen_mul_i64(t2, t2, t3);
3793 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3794 tcg_gen_add_i64(t2, t2, t3);
3795 tcg_temp_free_i64(t3);
3796 gen_move_low32(cpu_LO[acc], t2);
3797 gen_move_high32(cpu_HI[acc], t2);
3798 if (rd) {
3799 gen_move_low32(cpu_gpr[rd], t2);
3801 tcg_temp_free_i64(t2);
3803 break;
3804 case MMI_OPC_MADDU1:
3805 acc = 1;
3806 /* Fall through */
3807 case MMI_OPC_MADDU:
3809 TCGv_i64 t2 = tcg_temp_new_i64();
3810 TCGv_i64 t3 = tcg_temp_new_i64();
3812 tcg_gen_ext32u_tl(t0, t0);
3813 tcg_gen_ext32u_tl(t1, t1);
3814 tcg_gen_extu_tl_i64(t2, t0);
3815 tcg_gen_extu_tl_i64(t3, t1);
3816 tcg_gen_mul_i64(t2, t2, t3);
3817 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3818 tcg_gen_add_i64(t2, t2, t3);
3819 tcg_temp_free_i64(t3);
3820 gen_move_low32(cpu_LO[acc], t2);
3821 gen_move_high32(cpu_HI[acc], t2);
3822 if (rd) {
3823 gen_move_low32(cpu_gpr[rd], t2);
3825 tcg_temp_free_i64(t2);
3827 break;
3828 default:
3829 MIPS_INVAL("mul/madd TXx9");
3830 gen_reserved_instruction(ctx);
3831 goto out;
3834 out:
3835 tcg_temp_free(t0);
3836 tcg_temp_free(t1);
3839 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
3840 int rd, int rs, int rt)
3842 TCGv t0 = tcg_temp_new();
3843 TCGv t1 = tcg_temp_new();
3845 gen_load_gpr(t0, rs);
3846 gen_load_gpr(t1, rt);
3848 switch (opc) {
3849 case OPC_VR54XX_MULS:
3850 gen_helper_muls(t0, cpu_env, t0, t1);
3851 break;
3852 case OPC_VR54XX_MULSU:
3853 gen_helper_mulsu(t0, cpu_env, t0, t1);
3854 break;
3855 case OPC_VR54XX_MACC:
3856 gen_helper_macc(t0, cpu_env, t0, t1);
3857 break;
3858 case OPC_VR54XX_MACCU:
3859 gen_helper_maccu(t0, cpu_env, t0, t1);
3860 break;
3861 case OPC_VR54XX_MSAC:
3862 gen_helper_msac(t0, cpu_env, t0, t1);
3863 break;
3864 case OPC_VR54XX_MSACU:
3865 gen_helper_msacu(t0, cpu_env, t0, t1);
3866 break;
3867 case OPC_VR54XX_MULHI:
3868 gen_helper_mulhi(t0, cpu_env, t0, t1);
3869 break;
3870 case OPC_VR54XX_MULHIU:
3871 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3872 break;
3873 case OPC_VR54XX_MULSHI:
3874 gen_helper_mulshi(t0, cpu_env, t0, t1);
3875 break;
3876 case OPC_VR54XX_MULSHIU:
3877 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3878 break;
3879 case OPC_VR54XX_MACCHI:
3880 gen_helper_macchi(t0, cpu_env, t0, t1);
3881 break;
3882 case OPC_VR54XX_MACCHIU:
3883 gen_helper_macchiu(t0, cpu_env, t0, t1);
3884 break;
3885 case OPC_VR54XX_MSACHI:
3886 gen_helper_msachi(t0, cpu_env, t0, t1);
3887 break;
3888 case OPC_VR54XX_MSACHIU:
3889 gen_helper_msachiu(t0, cpu_env, t0, t1);
3890 break;
3891 default:
3892 MIPS_INVAL("mul vr54xx");
3893 gen_reserved_instruction(ctx);
3894 goto out;
3896 gen_store_gpr(t0, rd);
3898 out:
3899 tcg_temp_free(t0);
3900 tcg_temp_free(t1);
3903 static void gen_cl(DisasContext *ctx, uint32_t opc,
3904 int rd, int rs)
3906 TCGv t0;
3908 if (rd == 0) {
3909 /* Treat as NOP. */
3910 return;
3912 t0 = cpu_gpr[rd];
3913 gen_load_gpr(t0, rs);
3915 switch (opc) {
3916 case OPC_CLO:
3917 case R6_OPC_CLO:
3918 #if defined(TARGET_MIPS64)
3919 case OPC_DCLO:
3920 case R6_OPC_DCLO:
3921 #endif
3922 tcg_gen_not_tl(t0, t0);
3923 break;
3926 switch (opc) {
3927 case OPC_CLO:
3928 case R6_OPC_CLO:
3929 case OPC_CLZ:
3930 case R6_OPC_CLZ:
3931 tcg_gen_ext32u_tl(t0, t0);
3932 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3933 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
3934 break;
3935 #if defined(TARGET_MIPS64)
3936 case OPC_DCLO:
3937 case R6_OPC_DCLO:
3938 case OPC_DCLZ:
3939 case R6_OPC_DCLZ:
3940 tcg_gen_clzi_i64(t0, t0, 64);
3941 break;
3942 #endif
3946 /* Godson integer instructions */
3947 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3948 int rd, int rs, int rt)
3950 TCGv t0, t1;
3952 if (rd == 0) {
3953 /* Treat as NOP. */
3954 return;
3957 switch (opc) {
3958 case OPC_MULT_G_2E:
3959 case OPC_MULT_G_2F:
3960 case OPC_MULTU_G_2E:
3961 case OPC_MULTU_G_2F:
3962 #if defined(TARGET_MIPS64)
3963 case OPC_DMULT_G_2E:
3964 case OPC_DMULT_G_2F:
3965 case OPC_DMULTU_G_2E:
3966 case OPC_DMULTU_G_2F:
3967 #endif
3968 t0 = tcg_temp_new();
3969 t1 = tcg_temp_new();
3970 break;
3971 default:
3972 t0 = tcg_temp_local_new();
3973 t1 = tcg_temp_local_new();
3974 break;
3977 gen_load_gpr(t0, rs);
3978 gen_load_gpr(t1, rt);
3980 switch (opc) {
3981 case OPC_MULT_G_2E:
3982 case OPC_MULT_G_2F:
3983 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3984 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3985 break;
3986 case OPC_MULTU_G_2E:
3987 case OPC_MULTU_G_2F:
3988 tcg_gen_ext32u_tl(t0, t0);
3989 tcg_gen_ext32u_tl(t1, t1);
3990 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3991 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3992 break;
3993 case OPC_DIV_G_2E:
3994 case OPC_DIV_G_2F:
3996 TCGLabel *l1 = gen_new_label();
3997 TCGLabel *l2 = gen_new_label();
3998 TCGLabel *l3 = gen_new_label();
3999 tcg_gen_ext32s_tl(t0, t0);
4000 tcg_gen_ext32s_tl(t1, t1);
4001 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4002 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4003 tcg_gen_br(l3);
4004 gen_set_label(l1);
4005 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4006 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4007 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4008 tcg_gen_br(l3);
4009 gen_set_label(l2);
4010 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4011 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4012 gen_set_label(l3);
4014 break;
4015 case OPC_DIVU_G_2E:
4016 case OPC_DIVU_G_2F:
4018 TCGLabel *l1 = gen_new_label();
4019 TCGLabel *l2 = gen_new_label();
4020 tcg_gen_ext32u_tl(t0, t0);
4021 tcg_gen_ext32u_tl(t1, t1);
4022 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4023 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4024 tcg_gen_br(l2);
4025 gen_set_label(l1);
4026 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4027 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4028 gen_set_label(l2);
4030 break;
4031 case OPC_MOD_G_2E:
4032 case OPC_MOD_G_2F:
4034 TCGLabel *l1 = gen_new_label();
4035 TCGLabel *l2 = gen_new_label();
4036 TCGLabel *l3 = gen_new_label();
4037 tcg_gen_ext32u_tl(t0, t0);
4038 tcg_gen_ext32u_tl(t1, t1);
4039 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4040 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4041 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4042 gen_set_label(l1);
4043 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4044 tcg_gen_br(l3);
4045 gen_set_label(l2);
4046 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4047 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4048 gen_set_label(l3);
4050 break;
4051 case OPC_MODU_G_2E:
4052 case OPC_MODU_G_2F:
4054 TCGLabel *l1 = gen_new_label();
4055 TCGLabel *l2 = gen_new_label();
4056 tcg_gen_ext32u_tl(t0, t0);
4057 tcg_gen_ext32u_tl(t1, t1);
4058 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4059 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4060 tcg_gen_br(l2);
4061 gen_set_label(l1);
4062 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4063 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4064 gen_set_label(l2);
4066 break;
4067 #if defined(TARGET_MIPS64)
4068 case OPC_DMULT_G_2E:
4069 case OPC_DMULT_G_2F:
4070 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4071 break;
4072 case OPC_DMULTU_G_2E:
4073 case OPC_DMULTU_G_2F:
4074 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4075 break;
4076 case OPC_DDIV_G_2E:
4077 case OPC_DDIV_G_2F:
4079 TCGLabel *l1 = gen_new_label();
4080 TCGLabel *l2 = gen_new_label();
4081 TCGLabel *l3 = gen_new_label();
4082 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4083 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4084 tcg_gen_br(l3);
4085 gen_set_label(l1);
4086 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4087 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4088 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4089 tcg_gen_br(l3);
4090 gen_set_label(l2);
4091 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4092 gen_set_label(l3);
4094 break;
4095 case OPC_DDIVU_G_2E:
4096 case OPC_DDIVU_G_2F:
4098 TCGLabel *l1 = gen_new_label();
4099 TCGLabel *l2 = gen_new_label();
4100 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4101 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4102 tcg_gen_br(l2);
4103 gen_set_label(l1);
4104 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4105 gen_set_label(l2);
4107 break;
4108 case OPC_DMOD_G_2E:
4109 case OPC_DMOD_G_2F:
4111 TCGLabel *l1 = gen_new_label();
4112 TCGLabel *l2 = gen_new_label();
4113 TCGLabel *l3 = gen_new_label();
4114 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4115 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4116 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4117 gen_set_label(l1);
4118 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4119 tcg_gen_br(l3);
4120 gen_set_label(l2);
4121 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4122 gen_set_label(l3);
4124 break;
4125 case OPC_DMODU_G_2E:
4126 case OPC_DMODU_G_2F:
4128 TCGLabel *l1 = gen_new_label();
4129 TCGLabel *l2 = gen_new_label();
4130 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4131 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4132 tcg_gen_br(l2);
4133 gen_set_label(l1);
4134 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4135 gen_set_label(l2);
4137 break;
4138 #endif
4141 tcg_temp_free(t0);
4142 tcg_temp_free(t1);
4145 /* Loongson multimedia instructions */
4146 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4148 uint32_t opc, shift_max;
4149 TCGv_i64 t0, t1;
4150 TCGCond cond;
4152 opc = MASK_LMMI(ctx->opcode);
4153 switch (opc) {
4154 case OPC_ADD_CP2:
4155 case OPC_SUB_CP2:
4156 case OPC_DADD_CP2:
4157 case OPC_DSUB_CP2:
4158 t0 = tcg_temp_local_new_i64();
4159 t1 = tcg_temp_local_new_i64();
4160 break;
4161 default:
4162 t0 = tcg_temp_new_i64();
4163 t1 = tcg_temp_new_i64();
4164 break;
4167 check_cp1_enabled(ctx);
4168 gen_load_fpr64(ctx, t0, rs);
4169 gen_load_fpr64(ctx, t1, rt);
4171 switch (opc) {
4172 case OPC_PADDSH:
4173 gen_helper_paddsh(t0, t0, t1);
4174 break;
4175 case OPC_PADDUSH:
4176 gen_helper_paddush(t0, t0, t1);
4177 break;
4178 case OPC_PADDH:
4179 gen_helper_paddh(t0, t0, t1);
4180 break;
4181 case OPC_PADDW:
4182 gen_helper_paddw(t0, t0, t1);
4183 break;
4184 case OPC_PADDSB:
4185 gen_helper_paddsb(t0, t0, t1);
4186 break;
4187 case OPC_PADDUSB:
4188 gen_helper_paddusb(t0, t0, t1);
4189 break;
4190 case OPC_PADDB:
4191 gen_helper_paddb(t0, t0, t1);
4192 break;
4194 case OPC_PSUBSH:
4195 gen_helper_psubsh(t0, t0, t1);
4196 break;
4197 case OPC_PSUBUSH:
4198 gen_helper_psubush(t0, t0, t1);
4199 break;
4200 case OPC_PSUBH:
4201 gen_helper_psubh(t0, t0, t1);
4202 break;
4203 case OPC_PSUBW:
4204 gen_helper_psubw(t0, t0, t1);
4205 break;
4206 case OPC_PSUBSB:
4207 gen_helper_psubsb(t0, t0, t1);
4208 break;
4209 case OPC_PSUBUSB:
4210 gen_helper_psubusb(t0, t0, t1);
4211 break;
4212 case OPC_PSUBB:
4213 gen_helper_psubb(t0, t0, t1);
4214 break;
4216 case OPC_PSHUFH:
4217 gen_helper_pshufh(t0, t0, t1);
4218 break;
4219 case OPC_PACKSSWH:
4220 gen_helper_packsswh(t0, t0, t1);
4221 break;
4222 case OPC_PACKSSHB:
4223 gen_helper_packsshb(t0, t0, t1);
4224 break;
4225 case OPC_PACKUSHB:
4226 gen_helper_packushb(t0, t0, t1);
4227 break;
4229 case OPC_PUNPCKLHW:
4230 gen_helper_punpcklhw(t0, t0, t1);
4231 break;
4232 case OPC_PUNPCKHHW:
4233 gen_helper_punpckhhw(t0, t0, t1);
4234 break;
4235 case OPC_PUNPCKLBH:
4236 gen_helper_punpcklbh(t0, t0, t1);
4237 break;
4238 case OPC_PUNPCKHBH:
4239 gen_helper_punpckhbh(t0, t0, t1);
4240 break;
4241 case OPC_PUNPCKLWD:
4242 gen_helper_punpcklwd(t0, t0, t1);
4243 break;
4244 case OPC_PUNPCKHWD:
4245 gen_helper_punpckhwd(t0, t0, t1);
4246 break;
4248 case OPC_PAVGH:
4249 gen_helper_pavgh(t0, t0, t1);
4250 break;
4251 case OPC_PAVGB:
4252 gen_helper_pavgb(t0, t0, t1);
4253 break;
4254 case OPC_PMAXSH:
4255 gen_helper_pmaxsh(t0, t0, t1);
4256 break;
4257 case OPC_PMINSH:
4258 gen_helper_pminsh(t0, t0, t1);
4259 break;
4260 case OPC_PMAXUB:
4261 gen_helper_pmaxub(t0, t0, t1);
4262 break;
4263 case OPC_PMINUB:
4264 gen_helper_pminub(t0, t0, t1);
4265 break;
4267 case OPC_PCMPEQW:
4268 gen_helper_pcmpeqw(t0, t0, t1);
4269 break;
4270 case OPC_PCMPGTW:
4271 gen_helper_pcmpgtw(t0, t0, t1);
4272 break;
4273 case OPC_PCMPEQH:
4274 gen_helper_pcmpeqh(t0, t0, t1);
4275 break;
4276 case OPC_PCMPGTH:
4277 gen_helper_pcmpgth(t0, t0, t1);
4278 break;
4279 case OPC_PCMPEQB:
4280 gen_helper_pcmpeqb(t0, t0, t1);
4281 break;
4282 case OPC_PCMPGTB:
4283 gen_helper_pcmpgtb(t0, t0, t1);
4284 break;
4286 case OPC_PSLLW:
4287 gen_helper_psllw(t0, t0, t1);
4288 break;
4289 case OPC_PSLLH:
4290 gen_helper_psllh(t0, t0, t1);
4291 break;
4292 case OPC_PSRLW:
4293 gen_helper_psrlw(t0, t0, t1);
4294 break;
4295 case OPC_PSRLH:
4296 gen_helper_psrlh(t0, t0, t1);
4297 break;
4298 case OPC_PSRAW:
4299 gen_helper_psraw(t0, t0, t1);
4300 break;
4301 case OPC_PSRAH:
4302 gen_helper_psrah(t0, t0, t1);
4303 break;
4305 case OPC_PMULLH:
4306 gen_helper_pmullh(t0, t0, t1);
4307 break;
4308 case OPC_PMULHH:
4309 gen_helper_pmulhh(t0, t0, t1);
4310 break;
4311 case OPC_PMULHUH:
4312 gen_helper_pmulhuh(t0, t0, t1);
4313 break;
4314 case OPC_PMADDHW:
4315 gen_helper_pmaddhw(t0, t0, t1);
4316 break;
4318 case OPC_PASUBUB:
4319 gen_helper_pasubub(t0, t0, t1);
4320 break;
4321 case OPC_BIADD:
4322 gen_helper_biadd(t0, t0);
4323 break;
4324 case OPC_PMOVMSKB:
4325 gen_helper_pmovmskb(t0, t0);
4326 break;
4328 case OPC_PADDD:
4329 tcg_gen_add_i64(t0, t0, t1);
4330 break;
4331 case OPC_PSUBD:
4332 tcg_gen_sub_i64(t0, t0, t1);
4333 break;
4334 case OPC_XOR_CP2:
4335 tcg_gen_xor_i64(t0, t0, t1);
4336 break;
4337 case OPC_NOR_CP2:
4338 tcg_gen_nor_i64(t0, t0, t1);
4339 break;
4340 case OPC_AND_CP2:
4341 tcg_gen_and_i64(t0, t0, t1);
4342 break;
4343 case OPC_OR_CP2:
4344 tcg_gen_or_i64(t0, t0, t1);
4345 break;
4347 case OPC_PANDN:
4348 tcg_gen_andc_i64(t0, t1, t0);
4349 break;
4351 case OPC_PINSRH_0:
4352 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4353 break;
4354 case OPC_PINSRH_1:
4355 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4356 break;
4357 case OPC_PINSRH_2:
4358 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4359 break;
4360 case OPC_PINSRH_3:
4361 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4362 break;
4364 case OPC_PEXTRH:
4365 tcg_gen_andi_i64(t1, t1, 3);
4366 tcg_gen_shli_i64(t1, t1, 4);
4367 tcg_gen_shr_i64(t0, t0, t1);
4368 tcg_gen_ext16u_i64(t0, t0);
4369 break;
4371 case OPC_ADDU_CP2:
4372 tcg_gen_add_i64(t0, t0, t1);
4373 tcg_gen_ext32s_i64(t0, t0);
4374 break;
4375 case OPC_SUBU_CP2:
4376 tcg_gen_sub_i64(t0, t0, t1);
4377 tcg_gen_ext32s_i64(t0, t0);
4378 break;
4380 case OPC_SLL_CP2:
4381 shift_max = 32;
4382 goto do_shift;
4383 case OPC_SRL_CP2:
4384 shift_max = 32;
4385 goto do_shift;
4386 case OPC_SRA_CP2:
4387 shift_max = 32;
4388 goto do_shift;
4389 case OPC_DSLL_CP2:
4390 shift_max = 64;
4391 goto do_shift;
4392 case OPC_DSRL_CP2:
4393 shift_max = 64;
4394 goto do_shift;
4395 case OPC_DSRA_CP2:
4396 shift_max = 64;
4397 goto do_shift;
4398 do_shift:
4399 /* Make sure shift count isn't TCG undefined behaviour. */
4400 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4402 switch (opc) {
4403 case OPC_SLL_CP2:
4404 case OPC_DSLL_CP2:
4405 tcg_gen_shl_i64(t0, t0, t1);
4406 break;
4407 case OPC_SRA_CP2:
4408 case OPC_DSRA_CP2:
4410 * Since SRA is UndefinedResult without sign-extended inputs,
4411 * we can treat SRA and DSRA the same.
4413 tcg_gen_sar_i64(t0, t0, t1);
4414 break;
4415 case OPC_SRL_CP2:
4416 /* We want to shift in zeros for SRL; zero-extend first. */
4417 tcg_gen_ext32u_i64(t0, t0);
4418 /* FALLTHRU */
4419 case OPC_DSRL_CP2:
4420 tcg_gen_shr_i64(t0, t0, t1);
4421 break;
4424 if (shift_max == 32) {
4425 tcg_gen_ext32s_i64(t0, t0);
4428 /* Shifts larger than MAX produce zero. */
4429 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4430 tcg_gen_neg_i64(t1, t1);
4431 tcg_gen_and_i64(t0, t0, t1);
4432 break;
4434 case OPC_ADD_CP2:
4435 case OPC_DADD_CP2:
4437 TCGv_i64 t2 = tcg_temp_new_i64();
4438 TCGLabel *lab = gen_new_label();
4440 tcg_gen_mov_i64(t2, t0);
4441 tcg_gen_add_i64(t0, t1, t2);
4442 if (opc == OPC_ADD_CP2) {
4443 tcg_gen_ext32s_i64(t0, t0);
4445 tcg_gen_xor_i64(t1, t1, t2);
4446 tcg_gen_xor_i64(t2, t2, t0);
4447 tcg_gen_andc_i64(t1, t2, t1);
4448 tcg_temp_free_i64(t2);
4449 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4450 generate_exception(ctx, EXCP_OVERFLOW);
4451 gen_set_label(lab);
4452 break;
4455 case OPC_SUB_CP2:
4456 case OPC_DSUB_CP2:
4458 TCGv_i64 t2 = tcg_temp_new_i64();
4459 TCGLabel *lab = gen_new_label();
4461 tcg_gen_mov_i64(t2, t0);
4462 tcg_gen_sub_i64(t0, t1, t2);
4463 if (opc == OPC_SUB_CP2) {
4464 tcg_gen_ext32s_i64(t0, t0);
4466 tcg_gen_xor_i64(t1, t1, t2);
4467 tcg_gen_xor_i64(t2, t2, t0);
4468 tcg_gen_and_i64(t1, t1, t2);
4469 tcg_temp_free_i64(t2);
4470 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4471 generate_exception(ctx, EXCP_OVERFLOW);
4472 gen_set_label(lab);
4473 break;
4476 case OPC_PMULUW:
4477 tcg_gen_ext32u_i64(t0, t0);
4478 tcg_gen_ext32u_i64(t1, t1);
4479 tcg_gen_mul_i64(t0, t0, t1);
4480 break;
4482 case OPC_SEQU_CP2:
4483 case OPC_SEQ_CP2:
4484 cond = TCG_COND_EQ;
4485 goto do_cc_cond;
4486 break;
4487 case OPC_SLTU_CP2:
4488 cond = TCG_COND_LTU;
4489 goto do_cc_cond;
4490 break;
4491 case OPC_SLT_CP2:
4492 cond = TCG_COND_LT;
4493 goto do_cc_cond;
4494 break;
4495 case OPC_SLEU_CP2:
4496 cond = TCG_COND_LEU;
4497 goto do_cc_cond;
4498 break;
4499 case OPC_SLE_CP2:
4500 cond = TCG_COND_LE;
4501 do_cc_cond:
4503 int cc = (ctx->opcode >> 8) & 0x7;
4504 TCGv_i64 t64 = tcg_temp_new_i64();
4505 TCGv_i32 t32 = tcg_temp_new_i32();
4507 tcg_gen_setcond_i64(cond, t64, t0, t1);
4508 tcg_gen_extrl_i64_i32(t32, t64);
4509 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
4510 get_fp_bit(cc), 1);
4512 tcg_temp_free_i32(t32);
4513 tcg_temp_free_i64(t64);
4515 goto no_rd;
4516 break;
4517 default:
4518 MIPS_INVAL("loongson_cp2");
4519 gen_reserved_instruction(ctx);
4520 return;
4523 gen_store_fpr64(ctx, t0, rd);
4525 no_rd:
4526 tcg_temp_free_i64(t0);
4527 tcg_temp_free_i64(t1);
4530 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
4531 int rs, int rd)
4533 TCGv t0, t1, t2;
4534 TCGv_i32 fp0;
4535 #if defined(TARGET_MIPS64)
4536 int lsq_rt1 = ctx->opcode & 0x1f;
4537 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
4538 #endif
4539 int shf_offset = sextract32(ctx->opcode, 6, 8);
4541 t0 = tcg_temp_new();
4543 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
4544 #if defined(TARGET_MIPS64)
4545 case OPC_GSLQ:
4546 t1 = tcg_temp_new();
4547 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4548 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4549 ctx->default_tcg_memop_mask);
4550 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4551 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4552 ctx->default_tcg_memop_mask);
4553 gen_store_gpr(t1, rt);
4554 gen_store_gpr(t0, lsq_rt1);
4555 tcg_temp_free(t1);
4556 break;
4557 case OPC_GSLQC1:
4558 check_cp1_enabled(ctx);
4559 t1 = tcg_temp_new();
4560 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4561 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4562 ctx->default_tcg_memop_mask);
4563 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4564 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4565 ctx->default_tcg_memop_mask);
4566 gen_store_fpr64(ctx, t1, rt);
4567 gen_store_fpr64(ctx, t0, lsq_rt1);
4568 tcg_temp_free(t1);
4569 break;
4570 case OPC_GSSQ:
4571 t1 = tcg_temp_new();
4572 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4573 gen_load_gpr(t1, rt);
4574 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4575 ctx->default_tcg_memop_mask);
4576 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4577 gen_load_gpr(t1, lsq_rt1);
4578 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4579 ctx->default_tcg_memop_mask);
4580 tcg_temp_free(t1);
4581 break;
4582 case OPC_GSSQC1:
4583 check_cp1_enabled(ctx);
4584 t1 = tcg_temp_new();
4585 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4586 gen_load_fpr64(ctx, t1, rt);
4587 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4588 ctx->default_tcg_memop_mask);
4589 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4590 gen_load_fpr64(ctx, t1, lsq_rt1);
4591 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4592 ctx->default_tcg_memop_mask);
4593 tcg_temp_free(t1);
4594 break;
4595 #endif
4596 case OPC_GSSHFL:
4597 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4598 case OPC_GSLWLC1:
4599 check_cp1_enabled(ctx);
4600 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4601 t1 = tcg_temp_new();
4602 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4603 tcg_gen_andi_tl(t1, t0, 3);
4604 #ifndef TARGET_WORDS_BIGENDIAN
4605 tcg_gen_xori_tl(t1, t1, 3);
4606 #endif
4607 tcg_gen_shli_tl(t1, t1, 3);
4608 tcg_gen_andi_tl(t0, t0, ~3);
4609 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4610 tcg_gen_shl_tl(t0, t0, t1);
4611 t2 = tcg_const_tl(-1);
4612 tcg_gen_shl_tl(t2, t2, t1);
4613 fp0 = tcg_temp_new_i32();
4614 gen_load_fpr32(ctx, fp0, rt);
4615 tcg_gen_ext_i32_tl(t1, fp0);
4616 tcg_gen_andc_tl(t1, t1, t2);
4617 tcg_temp_free(t2);
4618 tcg_gen_or_tl(t0, t0, t1);
4619 tcg_temp_free(t1);
4620 #if defined(TARGET_MIPS64)
4621 tcg_gen_extrl_i64_i32(fp0, t0);
4622 #else
4623 tcg_gen_ext32s_tl(fp0, t0);
4624 #endif
4625 gen_store_fpr32(ctx, fp0, rt);
4626 tcg_temp_free_i32(fp0);
4627 break;
4628 case OPC_GSLWRC1:
4629 check_cp1_enabled(ctx);
4630 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4631 t1 = tcg_temp_new();
4632 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4633 tcg_gen_andi_tl(t1, t0, 3);
4634 #ifdef TARGET_WORDS_BIGENDIAN
4635 tcg_gen_xori_tl(t1, t1, 3);
4636 #endif
4637 tcg_gen_shli_tl(t1, t1, 3);
4638 tcg_gen_andi_tl(t0, t0, ~3);
4639 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4640 tcg_gen_shr_tl(t0, t0, t1);
4641 tcg_gen_xori_tl(t1, t1, 31);
4642 t2 = tcg_const_tl(0xfffffffeull);
4643 tcg_gen_shl_tl(t2, t2, t1);
4644 fp0 = tcg_temp_new_i32();
4645 gen_load_fpr32(ctx, fp0, rt);
4646 tcg_gen_ext_i32_tl(t1, fp0);
4647 tcg_gen_and_tl(t1, t1, t2);
4648 tcg_temp_free(t2);
4649 tcg_gen_or_tl(t0, t0, t1);
4650 tcg_temp_free(t1);
4651 #if defined(TARGET_MIPS64)
4652 tcg_gen_extrl_i64_i32(fp0, t0);
4653 #else
4654 tcg_gen_ext32s_tl(fp0, t0);
4655 #endif
4656 gen_store_fpr32(ctx, fp0, rt);
4657 tcg_temp_free_i32(fp0);
4658 break;
4659 #if defined(TARGET_MIPS64)
4660 case OPC_GSLDLC1:
4661 check_cp1_enabled(ctx);
4662 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4663 t1 = tcg_temp_new();
4664 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4665 tcg_gen_andi_tl(t1, t0, 7);
4666 #ifndef TARGET_WORDS_BIGENDIAN
4667 tcg_gen_xori_tl(t1, t1, 7);
4668 #endif
4669 tcg_gen_shli_tl(t1, t1, 3);
4670 tcg_gen_andi_tl(t0, t0, ~7);
4671 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4672 tcg_gen_shl_tl(t0, t0, t1);
4673 t2 = tcg_const_tl(-1);
4674 tcg_gen_shl_tl(t2, t2, t1);
4675 gen_load_fpr64(ctx, t1, rt);
4676 tcg_gen_andc_tl(t1, t1, t2);
4677 tcg_temp_free(t2);
4678 tcg_gen_or_tl(t0, t0, t1);
4679 tcg_temp_free(t1);
4680 gen_store_fpr64(ctx, t0, rt);
4681 break;
4682 case OPC_GSLDRC1:
4683 check_cp1_enabled(ctx);
4684 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4685 t1 = tcg_temp_new();
4686 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4687 tcg_gen_andi_tl(t1, t0, 7);
4688 #ifdef TARGET_WORDS_BIGENDIAN
4689 tcg_gen_xori_tl(t1, t1, 7);
4690 #endif
4691 tcg_gen_shli_tl(t1, t1, 3);
4692 tcg_gen_andi_tl(t0, t0, ~7);
4693 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4694 tcg_gen_shr_tl(t0, t0, t1);
4695 tcg_gen_xori_tl(t1, t1, 63);
4696 t2 = tcg_const_tl(0xfffffffffffffffeull);
4697 tcg_gen_shl_tl(t2, t2, t1);
4698 gen_load_fpr64(ctx, t1, rt);
4699 tcg_gen_and_tl(t1, t1, t2);
4700 tcg_temp_free(t2);
4701 tcg_gen_or_tl(t0, t0, t1);
4702 tcg_temp_free(t1);
4703 gen_store_fpr64(ctx, t0, rt);
4704 break;
4705 #endif
4706 default:
4707 MIPS_INVAL("loongson_gsshfl");
4708 gen_reserved_instruction(ctx);
4709 break;
4711 break;
4712 case OPC_GSSHFS:
4713 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4714 case OPC_GSSWLC1:
4715 check_cp1_enabled(ctx);
4716 t1 = tcg_temp_new();
4717 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4718 fp0 = tcg_temp_new_i32();
4719 gen_load_fpr32(ctx, fp0, rt);
4720 tcg_gen_ext_i32_tl(t1, fp0);
4721 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
4722 tcg_temp_free_i32(fp0);
4723 tcg_temp_free(t1);
4724 break;
4725 case OPC_GSSWRC1:
4726 check_cp1_enabled(ctx);
4727 t1 = tcg_temp_new();
4728 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4729 fp0 = tcg_temp_new_i32();
4730 gen_load_fpr32(ctx, fp0, rt);
4731 tcg_gen_ext_i32_tl(t1, fp0);
4732 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
4733 tcg_temp_free_i32(fp0);
4734 tcg_temp_free(t1);
4735 break;
4736 #if defined(TARGET_MIPS64)
4737 case OPC_GSSDLC1:
4738 check_cp1_enabled(ctx);
4739 t1 = tcg_temp_new();
4740 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4741 gen_load_fpr64(ctx, t1, rt);
4742 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
4743 tcg_temp_free(t1);
4744 break;
4745 case OPC_GSSDRC1:
4746 check_cp1_enabled(ctx);
4747 t1 = tcg_temp_new();
4748 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4749 gen_load_fpr64(ctx, t1, rt);
4750 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
4751 tcg_temp_free(t1);
4752 break;
4753 #endif
4754 default:
4755 MIPS_INVAL("loongson_gsshfs");
4756 gen_reserved_instruction(ctx);
4757 break;
4759 break;
4760 default:
4761 MIPS_INVAL("loongson_gslsq");
4762 gen_reserved_instruction(ctx);
4763 break;
4765 tcg_temp_free(t0);
4768 /* Loongson EXT LDC2/SDC2 */
4769 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
4770 int rs, int rd)
4772 int offset = sextract32(ctx->opcode, 3, 8);
4773 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
4774 TCGv t0, t1;
4775 TCGv_i32 fp0;
4777 /* Pre-conditions */
4778 switch (opc) {
4779 case OPC_GSLBX:
4780 case OPC_GSLHX:
4781 case OPC_GSLWX:
4782 case OPC_GSLDX:
4783 /* prefetch, implement as NOP */
4784 if (rt == 0) {
4785 return;
4787 break;
4788 case OPC_GSSBX:
4789 case OPC_GSSHX:
4790 case OPC_GSSWX:
4791 case OPC_GSSDX:
4792 break;
4793 case OPC_GSLWXC1:
4794 #if defined(TARGET_MIPS64)
4795 case OPC_GSLDXC1:
4796 #endif
4797 check_cp1_enabled(ctx);
4798 /* prefetch, implement as NOP */
4799 if (rt == 0) {
4800 return;
4802 break;
4803 case OPC_GSSWXC1:
4804 #if defined(TARGET_MIPS64)
4805 case OPC_GSSDXC1:
4806 #endif
4807 check_cp1_enabled(ctx);
4808 break;
4809 default:
4810 MIPS_INVAL("loongson_lsdc2");
4811 gen_reserved_instruction(ctx);
4812 return;
4813 break;
4816 t0 = tcg_temp_new();
4818 gen_base_offset_addr(ctx, t0, rs, offset);
4819 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4821 switch (opc) {
4822 case OPC_GSLBX:
4823 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
4824 gen_store_gpr(t0, rt);
4825 break;
4826 case OPC_GSLHX:
4827 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
4828 ctx->default_tcg_memop_mask);
4829 gen_store_gpr(t0, rt);
4830 break;
4831 case OPC_GSLWX:
4832 gen_base_offset_addr(ctx, t0, rs, offset);
4833 if (rd) {
4834 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4836 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
4837 ctx->default_tcg_memop_mask);
4838 gen_store_gpr(t0, rt);
4839 break;
4840 #if defined(TARGET_MIPS64)
4841 case OPC_GSLDX:
4842 gen_base_offset_addr(ctx, t0, rs, offset);
4843 if (rd) {
4844 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4846 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4847 ctx->default_tcg_memop_mask);
4848 gen_store_gpr(t0, rt);
4849 break;
4850 #endif
4851 case OPC_GSLWXC1:
4852 check_cp1_enabled(ctx);
4853 gen_base_offset_addr(ctx, t0, rs, offset);
4854 if (rd) {
4855 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4857 fp0 = tcg_temp_new_i32();
4858 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
4859 ctx->default_tcg_memop_mask);
4860 gen_store_fpr32(ctx, fp0, rt);
4861 tcg_temp_free_i32(fp0);
4862 break;
4863 #if defined(TARGET_MIPS64)
4864 case OPC_GSLDXC1:
4865 check_cp1_enabled(ctx);
4866 gen_base_offset_addr(ctx, t0, rs, offset);
4867 if (rd) {
4868 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4870 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4871 ctx->default_tcg_memop_mask);
4872 gen_store_fpr64(ctx, t0, rt);
4873 break;
4874 #endif
4875 case OPC_GSSBX:
4876 t1 = tcg_temp_new();
4877 gen_load_gpr(t1, rt);
4878 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
4879 tcg_temp_free(t1);
4880 break;
4881 case OPC_GSSHX:
4882 t1 = tcg_temp_new();
4883 gen_load_gpr(t1, rt);
4884 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
4885 ctx->default_tcg_memop_mask);
4886 tcg_temp_free(t1);
4887 break;
4888 case OPC_GSSWX:
4889 t1 = tcg_temp_new();
4890 gen_load_gpr(t1, rt);
4891 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
4892 ctx->default_tcg_memop_mask);
4893 tcg_temp_free(t1);
4894 break;
4895 #if defined(TARGET_MIPS64)
4896 case OPC_GSSDX:
4897 t1 = tcg_temp_new();
4898 gen_load_gpr(t1, rt);
4899 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4900 ctx->default_tcg_memop_mask);
4901 tcg_temp_free(t1);
4902 break;
4903 #endif
4904 case OPC_GSSWXC1:
4905 fp0 = tcg_temp_new_i32();
4906 gen_load_fpr32(ctx, fp0, rt);
4907 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
4908 ctx->default_tcg_memop_mask);
4909 tcg_temp_free_i32(fp0);
4910 break;
4911 #if defined(TARGET_MIPS64)
4912 case OPC_GSSDXC1:
4913 t1 = tcg_temp_new();
4914 gen_load_fpr64(ctx, t1, rt);
4915 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
4916 ctx->default_tcg_memop_mask);
4917 tcg_temp_free(t1);
4918 break;
4919 #endif
4920 default:
4921 break;
4924 tcg_temp_free(t0);
4927 /* Traps */
4928 static void gen_trap(DisasContext *ctx, uint32_t opc,
4929 int rs, int rt, int16_t imm)
4931 int cond;
4932 TCGv t0 = tcg_temp_new();
4933 TCGv t1 = tcg_temp_new();
4935 cond = 0;
4936 /* Load needed operands */
4937 switch (opc) {
4938 case OPC_TEQ:
4939 case OPC_TGE:
4940 case OPC_TGEU:
4941 case OPC_TLT:
4942 case OPC_TLTU:
4943 case OPC_TNE:
4944 /* Compare two registers */
4945 if (rs != rt) {
4946 gen_load_gpr(t0, rs);
4947 gen_load_gpr(t1, rt);
4948 cond = 1;
4950 break;
4951 case OPC_TEQI:
4952 case OPC_TGEI:
4953 case OPC_TGEIU:
4954 case OPC_TLTI:
4955 case OPC_TLTIU:
4956 case OPC_TNEI:
4957 /* Compare register to immediate */
4958 if (rs != 0 || imm != 0) {
4959 gen_load_gpr(t0, rs);
4960 tcg_gen_movi_tl(t1, (int32_t)imm);
4961 cond = 1;
4963 break;
4965 if (cond == 0) {
4966 switch (opc) {
4967 case OPC_TEQ: /* rs == rs */
4968 case OPC_TEQI: /* r0 == 0 */
4969 case OPC_TGE: /* rs >= rs */
4970 case OPC_TGEI: /* r0 >= 0 */
4971 case OPC_TGEU: /* rs >= rs unsigned */
4972 case OPC_TGEIU: /* r0 >= 0 unsigned */
4973 /* Always trap */
4974 generate_exception_end(ctx, EXCP_TRAP);
4975 break;
4976 case OPC_TLT: /* rs < rs */
4977 case OPC_TLTI: /* r0 < 0 */
4978 case OPC_TLTU: /* rs < rs unsigned */
4979 case OPC_TLTIU: /* r0 < 0 unsigned */
4980 case OPC_TNE: /* rs != rs */
4981 case OPC_TNEI: /* r0 != 0 */
4982 /* Never trap: treat as NOP. */
4983 break;
4985 } else {
4986 TCGLabel *l1 = gen_new_label();
4988 switch (opc) {
4989 case OPC_TEQ:
4990 case OPC_TEQI:
4991 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4992 break;
4993 case OPC_TGE:
4994 case OPC_TGEI:
4995 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4996 break;
4997 case OPC_TGEU:
4998 case OPC_TGEIU:
4999 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5000 break;
5001 case OPC_TLT:
5002 case OPC_TLTI:
5003 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5004 break;
5005 case OPC_TLTU:
5006 case OPC_TLTIU:
5007 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5008 break;
5009 case OPC_TNE:
5010 case OPC_TNEI:
5011 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5012 break;
5014 generate_exception(ctx, EXCP_TRAP);
5015 gen_set_label(l1);
5017 tcg_temp_free(t0);
5018 tcg_temp_free(t1);
5021 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5023 if (unlikely(ctx->base.singlestep_enabled)) {
5024 return false;
5027 #ifndef CONFIG_USER_ONLY
5028 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5029 #else
5030 return true;
5031 #endif
5034 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5036 if (use_goto_tb(ctx, dest)) {
5037 tcg_gen_goto_tb(n);
5038 gen_save_pc(dest);
5039 tcg_gen_exit_tb(ctx->base.tb, n);
5040 } else {
5041 gen_save_pc(dest);
5042 if (ctx->base.singlestep_enabled) {
5043 save_cpu_state(ctx, 0);
5044 gen_helper_raise_exception_debug(cpu_env);
5046 tcg_gen_lookup_and_goto_ptr();
5050 /* Branches (before delay slot) */
5051 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
5052 int insn_bytes,
5053 int rs, int rt, int32_t offset,
5054 int delayslot_size)
5056 target_ulong btgt = -1;
5057 int blink = 0;
5058 int bcond_compute = 0;
5059 TCGv t0 = tcg_temp_new();
5060 TCGv t1 = tcg_temp_new();
5062 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5063 #ifdef MIPS_DEBUG_DISAS
5064 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5065 TARGET_FMT_lx "\n", ctx->base.pc_next);
5066 #endif
5067 gen_reserved_instruction(ctx);
5068 goto out;
5071 /* Load needed operands */
5072 switch (opc) {
5073 case OPC_BEQ:
5074 case OPC_BEQL:
5075 case OPC_BNE:
5076 case OPC_BNEL:
5077 /* Compare two registers */
5078 if (rs != rt) {
5079 gen_load_gpr(t0, rs);
5080 gen_load_gpr(t1, rt);
5081 bcond_compute = 1;
5083 btgt = ctx->base.pc_next + insn_bytes + offset;
5084 break;
5085 case OPC_BGEZ:
5086 case OPC_BGEZAL:
5087 case OPC_BGEZALL:
5088 case OPC_BGEZL:
5089 case OPC_BGTZ:
5090 case OPC_BGTZL:
5091 case OPC_BLEZ:
5092 case OPC_BLEZL:
5093 case OPC_BLTZ:
5094 case OPC_BLTZAL:
5095 case OPC_BLTZALL:
5096 case OPC_BLTZL:
5097 /* Compare to zero */
5098 if (rs != 0) {
5099 gen_load_gpr(t0, rs);
5100 bcond_compute = 1;
5102 btgt = ctx->base.pc_next + insn_bytes + offset;
5103 break;
5104 case OPC_BPOSGE32:
5105 #if defined(TARGET_MIPS64)
5106 case OPC_BPOSGE64:
5107 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5108 #else
5109 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5110 #endif
5111 bcond_compute = 1;
5112 btgt = ctx->base.pc_next + insn_bytes + offset;
5113 break;
5114 case OPC_J:
5115 case OPC_JAL:
5116 case OPC_JALX:
5117 /* Jump to immediate */
5118 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5119 (uint32_t)offset;
5120 break;
5121 case OPC_JR:
5122 case OPC_JALR:
5123 /* Jump to register */
5124 if (offset != 0 && offset != 16) {
5126 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5127 * others are reserved.
5129 MIPS_INVAL("jump hint");
5130 gen_reserved_instruction(ctx);
5131 goto out;
5133 gen_load_gpr(btarget, rs);
5134 break;
5135 default:
5136 MIPS_INVAL("branch/jump");
5137 gen_reserved_instruction(ctx);
5138 goto out;
5140 if (bcond_compute == 0) {
5141 /* No condition to be computed */
5142 switch (opc) {
5143 case OPC_BEQ: /* rx == rx */
5144 case OPC_BEQL: /* rx == rx likely */
5145 case OPC_BGEZ: /* 0 >= 0 */
5146 case OPC_BGEZL: /* 0 >= 0 likely */
5147 case OPC_BLEZ: /* 0 <= 0 */
5148 case OPC_BLEZL: /* 0 <= 0 likely */
5149 /* Always take */
5150 ctx->hflags |= MIPS_HFLAG_B;
5151 break;
5152 case OPC_BGEZAL: /* 0 >= 0 */
5153 case OPC_BGEZALL: /* 0 >= 0 likely */
5154 /* Always take and link */
5155 blink = 31;
5156 ctx->hflags |= MIPS_HFLAG_B;
5157 break;
5158 case OPC_BNE: /* rx != rx */
5159 case OPC_BGTZ: /* 0 > 0 */
5160 case OPC_BLTZ: /* 0 < 0 */
5161 /* Treat as NOP. */
5162 goto out;
5163 case OPC_BLTZAL: /* 0 < 0 */
5165 * Handle as an unconditional branch to get correct delay
5166 * slot checking.
5168 blink = 31;
5169 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5170 ctx->hflags |= MIPS_HFLAG_B;
5171 break;
5172 case OPC_BLTZALL: /* 0 < 0 likely */
5173 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5174 /* Skip the instruction in the delay slot */
5175 ctx->base.pc_next += 4;
5176 goto out;
5177 case OPC_BNEL: /* rx != rx likely */
5178 case OPC_BGTZL: /* 0 > 0 likely */
5179 case OPC_BLTZL: /* 0 < 0 likely */
5180 /* Skip the instruction in the delay slot */
5181 ctx->base.pc_next += 4;
5182 goto out;
5183 case OPC_J:
5184 ctx->hflags |= MIPS_HFLAG_B;
5185 break;
5186 case OPC_JALX:
5187 ctx->hflags |= MIPS_HFLAG_BX;
5188 /* Fallthrough */
5189 case OPC_JAL:
5190 blink = 31;
5191 ctx->hflags |= MIPS_HFLAG_B;
5192 break;
5193 case OPC_JR:
5194 ctx->hflags |= MIPS_HFLAG_BR;
5195 break;
5196 case OPC_JALR:
5197 blink = rt;
5198 ctx->hflags |= MIPS_HFLAG_BR;
5199 break;
5200 default:
5201 MIPS_INVAL("branch/jump");
5202 gen_reserved_instruction(ctx);
5203 goto out;
5205 } else {
5206 switch (opc) {
5207 case OPC_BEQ:
5208 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5209 goto not_likely;
5210 case OPC_BEQL:
5211 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5212 goto likely;
5213 case OPC_BNE:
5214 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5215 goto not_likely;
5216 case OPC_BNEL:
5217 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5218 goto likely;
5219 case OPC_BGEZ:
5220 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5221 goto not_likely;
5222 case OPC_BGEZL:
5223 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5224 goto likely;
5225 case OPC_BGEZAL:
5226 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5227 blink = 31;
5228 goto not_likely;
5229 case OPC_BGEZALL:
5230 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5231 blink = 31;
5232 goto likely;
5233 case OPC_BGTZ:
5234 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5235 goto not_likely;
5236 case OPC_BGTZL:
5237 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5238 goto likely;
5239 case OPC_BLEZ:
5240 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5241 goto not_likely;
5242 case OPC_BLEZL:
5243 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5244 goto likely;
5245 case OPC_BLTZ:
5246 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5247 goto not_likely;
5248 case OPC_BLTZL:
5249 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5250 goto likely;
5251 case OPC_BPOSGE32:
5252 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5253 goto not_likely;
5254 #if defined(TARGET_MIPS64)
5255 case OPC_BPOSGE64:
5256 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5257 goto not_likely;
5258 #endif
5259 case OPC_BLTZAL:
5260 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5261 blink = 31;
5262 not_likely:
5263 ctx->hflags |= MIPS_HFLAG_BC;
5264 break;
5265 case OPC_BLTZALL:
5266 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5267 blink = 31;
5268 likely:
5269 ctx->hflags |= MIPS_HFLAG_BL;
5270 break;
5271 default:
5272 MIPS_INVAL("conditional branch/jump");
5273 gen_reserved_instruction(ctx);
5274 goto out;
5278 ctx->btarget = btgt;
5280 switch (delayslot_size) {
5281 case 2:
5282 ctx->hflags |= MIPS_HFLAG_BDS16;
5283 break;
5284 case 4:
5285 ctx->hflags |= MIPS_HFLAG_BDS32;
5286 break;
5289 if (blink > 0) {
5290 int post_delay = insn_bytes + delayslot_size;
5291 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5293 tcg_gen_movi_tl(cpu_gpr[blink],
5294 ctx->base.pc_next + post_delay + lowbit);
5297 out:
5298 if (insn_bytes == 2) {
5299 ctx->hflags |= MIPS_HFLAG_B16;
5301 tcg_temp_free(t0);
5302 tcg_temp_free(t1);
5306 /* nanoMIPS Branches */
5307 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5308 int insn_bytes,
5309 int rs, int rt, int32_t offset)
5311 target_ulong btgt = -1;
5312 int bcond_compute = 0;
5313 TCGv t0 = tcg_temp_new();
5314 TCGv t1 = tcg_temp_new();
5316 /* Load needed operands */
5317 switch (opc) {
5318 case OPC_BEQ:
5319 case OPC_BNE:
5320 /* Compare two registers */
5321 if (rs != rt) {
5322 gen_load_gpr(t0, rs);
5323 gen_load_gpr(t1, rt);
5324 bcond_compute = 1;
5326 btgt = ctx->base.pc_next + insn_bytes + offset;
5327 break;
5328 case OPC_BGEZAL:
5329 /* Compare to zero */
5330 if (rs != 0) {
5331 gen_load_gpr(t0, rs);
5332 bcond_compute = 1;
5334 btgt = ctx->base.pc_next + insn_bytes + offset;
5335 break;
5336 case OPC_BPOSGE32:
5337 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5338 bcond_compute = 1;
5339 btgt = ctx->base.pc_next + insn_bytes + offset;
5340 break;
5341 case OPC_JR:
5342 case OPC_JALR:
5343 /* Jump to register */
5344 if (offset != 0 && offset != 16) {
5346 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5347 * others are reserved.
5349 MIPS_INVAL("jump hint");
5350 gen_reserved_instruction(ctx);
5351 goto out;
5353 gen_load_gpr(btarget, rs);
5354 break;
5355 default:
5356 MIPS_INVAL("branch/jump");
5357 gen_reserved_instruction(ctx);
5358 goto out;
5360 if (bcond_compute == 0) {
5361 /* No condition to be computed */
5362 switch (opc) {
5363 case OPC_BEQ: /* rx == rx */
5364 /* Always take */
5365 ctx->hflags |= MIPS_HFLAG_B;
5366 break;
5367 case OPC_BGEZAL: /* 0 >= 0 */
5368 /* Always take and link */
5369 tcg_gen_movi_tl(cpu_gpr[31],
5370 ctx->base.pc_next + insn_bytes);
5371 ctx->hflags |= MIPS_HFLAG_B;
5372 break;
5373 case OPC_BNE: /* rx != rx */
5374 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5375 /* Skip the instruction in the delay slot */
5376 ctx->base.pc_next += 4;
5377 goto out;
5378 case OPC_JR:
5379 ctx->hflags |= MIPS_HFLAG_BR;
5380 break;
5381 case OPC_JALR:
5382 if (rt > 0) {
5383 tcg_gen_movi_tl(cpu_gpr[rt],
5384 ctx->base.pc_next + insn_bytes);
5386 ctx->hflags |= MIPS_HFLAG_BR;
5387 break;
5388 default:
5389 MIPS_INVAL("branch/jump");
5390 gen_reserved_instruction(ctx);
5391 goto out;
5393 } else {
5394 switch (opc) {
5395 case OPC_BEQ:
5396 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5397 goto not_likely;
5398 case OPC_BNE:
5399 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5400 goto not_likely;
5401 case OPC_BGEZAL:
5402 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5403 tcg_gen_movi_tl(cpu_gpr[31],
5404 ctx->base.pc_next + insn_bytes);
5405 goto not_likely;
5406 case OPC_BPOSGE32:
5407 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5408 not_likely:
5409 ctx->hflags |= MIPS_HFLAG_BC;
5410 break;
5411 default:
5412 MIPS_INVAL("conditional branch/jump");
5413 gen_reserved_instruction(ctx);
5414 goto out;
5418 ctx->btarget = btgt;
5420 out:
5421 if (insn_bytes == 2) {
5422 ctx->hflags |= MIPS_HFLAG_B16;
5424 tcg_temp_free(t0);
5425 tcg_temp_free(t1);
5429 /* special3 bitfield operations */
5430 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
5431 int rs, int lsb, int msb)
5433 TCGv t0 = tcg_temp_new();
5434 TCGv t1 = tcg_temp_new();
5436 gen_load_gpr(t1, rs);
5437 switch (opc) {
5438 case OPC_EXT:
5439 if (lsb + msb > 31) {
5440 goto fail;
5442 if (msb != 31) {
5443 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5444 } else {
5446 * The two checks together imply that lsb == 0,
5447 * so this is a simple sign-extension.
5449 tcg_gen_ext32s_tl(t0, t1);
5451 break;
5452 #if defined(TARGET_MIPS64)
5453 case OPC_DEXTU:
5454 lsb += 32;
5455 goto do_dext;
5456 case OPC_DEXTM:
5457 msb += 32;
5458 goto do_dext;
5459 case OPC_DEXT:
5460 do_dext:
5461 if (lsb + msb > 63) {
5462 goto fail;
5464 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5465 break;
5466 #endif
5467 case OPC_INS:
5468 if (lsb > msb) {
5469 goto fail;
5471 gen_load_gpr(t0, rt);
5472 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5473 tcg_gen_ext32s_tl(t0, t0);
5474 break;
5475 #if defined(TARGET_MIPS64)
5476 case OPC_DINSU:
5477 lsb += 32;
5478 /* FALLTHRU */
5479 case OPC_DINSM:
5480 msb += 32;
5481 /* FALLTHRU */
5482 case OPC_DINS:
5483 if (lsb > msb) {
5484 goto fail;
5486 gen_load_gpr(t0, rt);
5487 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5488 break;
5489 #endif
5490 default:
5491 fail:
5492 MIPS_INVAL("bitops");
5493 gen_reserved_instruction(ctx);
5494 tcg_temp_free(t0);
5495 tcg_temp_free(t1);
5496 return;
5498 gen_store_gpr(t0, rt);
5499 tcg_temp_free(t0);
5500 tcg_temp_free(t1);
5503 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
5505 TCGv t0;
5507 if (rd == 0) {
5508 /* If no destination, treat it as a NOP. */
5509 return;
5512 t0 = tcg_temp_new();
5513 gen_load_gpr(t0, rt);
5514 switch (op2) {
5515 case OPC_WSBH:
5517 TCGv t1 = tcg_temp_new();
5518 TCGv t2 = tcg_const_tl(0x00FF00FF);
5520 tcg_gen_shri_tl(t1, t0, 8);
5521 tcg_gen_and_tl(t1, t1, t2);
5522 tcg_gen_and_tl(t0, t0, t2);
5523 tcg_gen_shli_tl(t0, t0, 8);
5524 tcg_gen_or_tl(t0, t0, t1);
5525 tcg_temp_free(t2);
5526 tcg_temp_free(t1);
5527 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5529 break;
5530 case OPC_SEB:
5531 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
5532 break;
5533 case OPC_SEH:
5534 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
5535 break;
5536 #if defined(TARGET_MIPS64)
5537 case OPC_DSBH:
5539 TCGv t1 = tcg_temp_new();
5540 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
5542 tcg_gen_shri_tl(t1, t0, 8);
5543 tcg_gen_and_tl(t1, t1, t2);
5544 tcg_gen_and_tl(t0, t0, t2);
5545 tcg_gen_shli_tl(t0, t0, 8);
5546 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5547 tcg_temp_free(t2);
5548 tcg_temp_free(t1);
5550 break;
5551 case OPC_DSHD:
5553 TCGv t1 = tcg_temp_new();
5554 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
5556 tcg_gen_shri_tl(t1, t0, 16);
5557 tcg_gen_and_tl(t1, t1, t2);
5558 tcg_gen_and_tl(t0, t0, t2);
5559 tcg_gen_shli_tl(t0, t0, 16);
5560 tcg_gen_or_tl(t0, t0, t1);
5561 tcg_gen_shri_tl(t1, t0, 32);
5562 tcg_gen_shli_tl(t0, t0, 32);
5563 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5564 tcg_temp_free(t2);
5565 tcg_temp_free(t1);
5567 break;
5568 #endif
5569 default:
5570 MIPS_INVAL("bsfhl");
5571 gen_reserved_instruction(ctx);
5572 tcg_temp_free(t0);
5573 return;
5575 tcg_temp_free(t0);
5578 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
5579 int rt, int bits)
5581 TCGv t0;
5582 if (rd == 0) {
5583 /* Treat as NOP. */
5584 return;
5586 t0 = tcg_temp_new();
5587 if (bits == 0 || bits == wordsz) {
5588 if (bits == 0) {
5589 gen_load_gpr(t0, rt);
5590 } else {
5591 gen_load_gpr(t0, rs);
5593 switch (wordsz) {
5594 case 32:
5595 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5596 break;
5597 #if defined(TARGET_MIPS64)
5598 case 64:
5599 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5600 break;
5601 #endif
5603 } else {
5604 TCGv t1 = tcg_temp_new();
5605 gen_load_gpr(t0, rt);
5606 gen_load_gpr(t1, rs);
5607 switch (wordsz) {
5608 case 32:
5610 TCGv_i64 t2 = tcg_temp_new_i64();
5611 tcg_gen_concat_tl_i64(t2, t1, t0);
5612 tcg_gen_shri_i64(t2, t2, 32 - bits);
5613 gen_move_low32(cpu_gpr[rd], t2);
5614 tcg_temp_free_i64(t2);
5616 break;
5617 #if defined(TARGET_MIPS64)
5618 case 64:
5619 tcg_gen_shli_tl(t0, t0, bits);
5620 tcg_gen_shri_tl(t1, t1, 64 - bits);
5621 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5622 break;
5623 #endif
5625 tcg_temp_free(t1);
5628 tcg_temp_free(t0);
5631 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5632 int bp)
5634 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5637 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5638 int shift)
5640 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5643 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5645 TCGv t0;
5646 if (rd == 0) {
5647 /* Treat as NOP. */
5648 return;
5650 t0 = tcg_temp_new();
5651 gen_load_gpr(t0, rt);
5652 switch (opc) {
5653 case OPC_BITSWAP:
5654 gen_helper_bitswap(cpu_gpr[rd], t0);
5655 break;
5656 #if defined(TARGET_MIPS64)
5657 case OPC_DBITSWAP:
5658 gen_helper_dbitswap(cpu_gpr[rd], t0);
5659 break;
5660 #endif
5662 tcg_temp_free(t0);
5665 #ifndef CONFIG_USER_ONLY
5666 /* CP0 (MMU and control) */
5667 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5669 TCGv_i64 t0 = tcg_temp_new_i64();
5670 TCGv_i64 t1 = tcg_temp_new_i64();
5672 tcg_gen_ext_tl_i64(t0, arg);
5673 tcg_gen_ld_i64(t1, cpu_env, off);
5674 #if defined(TARGET_MIPS64)
5675 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5676 #else
5677 tcg_gen_concat32_i64(t1, t1, t0);
5678 #endif
5679 tcg_gen_st_i64(t1, cpu_env, off);
5680 tcg_temp_free_i64(t1);
5681 tcg_temp_free_i64(t0);
5684 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5686 TCGv_i64 t0 = tcg_temp_new_i64();
5687 TCGv_i64 t1 = tcg_temp_new_i64();
5689 tcg_gen_ext_tl_i64(t0, arg);
5690 tcg_gen_ld_i64(t1, cpu_env, off);
5691 tcg_gen_concat32_i64(t1, t1, t0);
5692 tcg_gen_st_i64(t1, cpu_env, off);
5693 tcg_temp_free_i64(t1);
5694 tcg_temp_free_i64(t0);
5697 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5699 TCGv_i64 t0 = tcg_temp_new_i64();
5701 tcg_gen_ld_i64(t0, cpu_env, off);
5702 #if defined(TARGET_MIPS64)
5703 tcg_gen_shri_i64(t0, t0, 30);
5704 #else
5705 tcg_gen_shri_i64(t0, t0, 32);
5706 #endif
5707 gen_move_low32(arg, t0);
5708 tcg_temp_free_i64(t0);
5711 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5713 TCGv_i64 t0 = tcg_temp_new_i64();
5715 tcg_gen_ld_i64(t0, cpu_env, off);
5716 tcg_gen_shri_i64(t0, t0, 32 + shift);
5717 gen_move_low32(arg, t0);
5718 tcg_temp_free_i64(t0);
5721 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
5723 TCGv_i32 t0 = tcg_temp_new_i32();
5725 tcg_gen_ld_i32(t0, cpu_env, off);
5726 tcg_gen_ext_i32_tl(arg, t0);
5727 tcg_temp_free_i32(t0);
5730 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
5732 tcg_gen_ld_tl(arg, cpu_env, off);
5733 tcg_gen_ext32s_tl(arg, arg);
5736 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
5738 TCGv_i32 t0 = tcg_temp_new_i32();
5740 tcg_gen_trunc_tl_i32(t0, arg);
5741 tcg_gen_st_i32(t0, cpu_env, off);
5742 tcg_temp_free_i32(t0);
5745 #define CP0_CHECK(c) \
5746 do { \
5747 if (!(c)) { \
5748 goto cp0_unimplemented; \
5750 } while (0)
5752 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5754 const char *register_name = "invalid";
5756 switch (reg) {
5757 case CP0_REGISTER_02:
5758 switch (sel) {
5759 case 0:
5760 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5761 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5762 register_name = "EntryLo0";
5763 break;
5764 default:
5765 goto cp0_unimplemented;
5767 break;
5768 case CP0_REGISTER_03:
5769 switch (sel) {
5770 case CP0_REG03__ENTRYLO1:
5771 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5772 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5773 register_name = "EntryLo1";
5774 break;
5775 default:
5776 goto cp0_unimplemented;
5778 break;
5779 case CP0_REGISTER_09:
5780 switch (sel) {
5781 case CP0_REG09__SAAR:
5782 CP0_CHECK(ctx->saar);
5783 gen_helper_mfhc0_saar(arg, cpu_env);
5784 register_name = "SAAR";
5785 break;
5786 default:
5787 goto cp0_unimplemented;
5789 break;
5790 case CP0_REGISTER_17:
5791 switch (sel) {
5792 case CP0_REG17__LLADDR:
5793 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
5794 ctx->CP0_LLAddr_shift);
5795 register_name = "LLAddr";
5796 break;
5797 case CP0_REG17__MAAR:
5798 CP0_CHECK(ctx->mrp);
5799 gen_helper_mfhc0_maar(arg, cpu_env);
5800 register_name = "MAAR";
5801 break;
5802 default:
5803 goto cp0_unimplemented;
5805 break;
5806 case CP0_REGISTER_19:
5807 switch (sel) {
5808 case CP0_REG19__WATCHHI0:
5809 case CP0_REG19__WATCHHI1:
5810 case CP0_REG19__WATCHHI2:
5811 case CP0_REG19__WATCHHI3:
5812 case CP0_REG19__WATCHHI4:
5813 case CP0_REG19__WATCHHI5:
5814 case CP0_REG19__WATCHHI6:
5815 case CP0_REG19__WATCHHI7:
5816 /* upper 32 bits are only available when Config5MI != 0 */
5817 CP0_CHECK(ctx->mi);
5818 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
5819 register_name = "WatchHi";
5820 break;
5821 default:
5822 goto cp0_unimplemented;
5824 break;
5825 case CP0_REGISTER_28:
5826 switch (sel) {
5827 case 0:
5828 case 2:
5829 case 4:
5830 case 6:
5831 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5832 register_name = "TagLo";
5833 break;
5834 default:
5835 goto cp0_unimplemented;
5837 break;
5838 default:
5839 goto cp0_unimplemented;
5841 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
5842 return;
5844 cp0_unimplemented:
5845 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
5846 register_name, reg, sel);
5847 tcg_gen_movi_tl(arg, 0);
5850 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5852 const char *register_name = "invalid";
5853 uint64_t mask = ctx->PAMask >> 36;
5855 switch (reg) {
5856 case CP0_REGISTER_02:
5857 switch (sel) {
5858 case 0:
5859 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5860 tcg_gen_andi_tl(arg, arg, mask);
5861 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5862 register_name = "EntryLo0";
5863 break;
5864 default:
5865 goto cp0_unimplemented;
5867 break;
5868 case CP0_REGISTER_03:
5869 switch (sel) {
5870 case CP0_REG03__ENTRYLO1:
5871 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5872 tcg_gen_andi_tl(arg, arg, mask);
5873 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5874 register_name = "EntryLo1";
5875 break;
5876 default:
5877 goto cp0_unimplemented;
5879 break;
5880 case CP0_REGISTER_09:
5881 switch (sel) {
5882 case CP0_REG09__SAAR:
5883 CP0_CHECK(ctx->saar);
5884 gen_helper_mthc0_saar(cpu_env, arg);
5885 register_name = "SAAR";
5886 break;
5887 default:
5888 goto cp0_unimplemented;
5890 break;
5891 case CP0_REGISTER_17:
5892 switch (sel) {
5893 case CP0_REG17__LLADDR:
5895 * LLAddr is read-only (the only exception is bit 0 if LLB is
5896 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
5897 * relevant for modern MIPS cores supporting MTHC0, therefore
5898 * treating MTHC0 to LLAddr as NOP.
5900 register_name = "LLAddr";
5901 break;
5902 case CP0_REG17__MAAR:
5903 CP0_CHECK(ctx->mrp);
5904 gen_helper_mthc0_maar(cpu_env, arg);
5905 register_name = "MAAR";
5906 break;
5907 default:
5908 goto cp0_unimplemented;
5910 break;
5911 case CP0_REGISTER_19:
5912 switch (sel) {
5913 case CP0_REG19__WATCHHI0:
5914 case CP0_REG19__WATCHHI1:
5915 case CP0_REG19__WATCHHI2:
5916 case CP0_REG19__WATCHHI3:
5917 case CP0_REG19__WATCHHI4:
5918 case CP0_REG19__WATCHHI5:
5919 case CP0_REG19__WATCHHI6:
5920 case CP0_REG19__WATCHHI7:
5921 /* upper 32 bits are only available when Config5MI != 0 */
5922 CP0_CHECK(ctx->mi);
5923 gen_helper_0e1i(mthc0_watchhi, arg, sel);
5924 register_name = "WatchHi";
5925 break;
5926 default:
5927 goto cp0_unimplemented;
5929 break;
5930 case CP0_REGISTER_28:
5931 switch (sel) {
5932 case 0:
5933 case 2:
5934 case 4:
5935 case 6:
5936 tcg_gen_andi_tl(arg, arg, mask);
5937 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5938 register_name = "TagLo";
5939 break;
5940 default:
5941 goto cp0_unimplemented;
5943 break;
5944 default:
5945 goto cp0_unimplemented;
5947 trace_mips_translate_c0("mthc0", register_name, reg, sel);
5949 cp0_unimplemented:
5950 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
5951 register_name, reg, sel);
5954 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5956 if (ctx->insn_flags & ISA_MIPS_R6) {
5957 tcg_gen_movi_tl(arg, 0);
5958 } else {
5959 tcg_gen_movi_tl(arg, ~0);
5963 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5965 const char *register_name = "invalid";
5967 if (sel != 0) {
5968 check_insn(ctx, ISA_MIPS_R1);
5971 switch (reg) {
5972 case CP0_REGISTER_00:
5973 switch (sel) {
5974 case CP0_REG00__INDEX:
5975 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5976 register_name = "Index";
5977 break;
5978 case CP0_REG00__MVPCONTROL:
5979 CP0_CHECK(ctx->insn_flags & ASE_MT);
5980 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5981 register_name = "MVPControl";
5982 break;
5983 case CP0_REG00__MVPCONF0:
5984 CP0_CHECK(ctx->insn_flags & ASE_MT);
5985 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5986 register_name = "MVPConf0";
5987 break;
5988 case CP0_REG00__MVPCONF1:
5989 CP0_CHECK(ctx->insn_flags & ASE_MT);
5990 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5991 register_name = "MVPConf1";
5992 break;
5993 case CP0_REG00__VPCONTROL:
5994 CP0_CHECK(ctx->vp);
5995 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
5996 register_name = "VPControl";
5997 break;
5998 default:
5999 goto cp0_unimplemented;
6001 break;
6002 case CP0_REGISTER_01:
6003 switch (sel) {
6004 case CP0_REG01__RANDOM:
6005 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6006 gen_helper_mfc0_random(arg, cpu_env);
6007 register_name = "Random";
6008 break;
6009 case CP0_REG01__VPECONTROL:
6010 CP0_CHECK(ctx->insn_flags & ASE_MT);
6011 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6012 register_name = "VPEControl";
6013 break;
6014 case CP0_REG01__VPECONF0:
6015 CP0_CHECK(ctx->insn_flags & ASE_MT);
6016 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6017 register_name = "VPEConf0";
6018 break;
6019 case CP0_REG01__VPECONF1:
6020 CP0_CHECK(ctx->insn_flags & ASE_MT);
6021 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6022 register_name = "VPEConf1";
6023 break;
6024 case CP0_REG01__YQMASK:
6025 CP0_CHECK(ctx->insn_flags & ASE_MT);
6026 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6027 register_name = "YQMask";
6028 break;
6029 case CP0_REG01__VPESCHEDULE:
6030 CP0_CHECK(ctx->insn_flags & ASE_MT);
6031 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6032 register_name = "VPESchedule";
6033 break;
6034 case CP0_REG01__VPESCHEFBACK:
6035 CP0_CHECK(ctx->insn_flags & ASE_MT);
6036 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6037 register_name = "VPEScheFBack";
6038 break;
6039 case CP0_REG01__VPEOPT:
6040 CP0_CHECK(ctx->insn_flags & ASE_MT);
6041 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6042 register_name = "VPEOpt";
6043 break;
6044 default:
6045 goto cp0_unimplemented;
6047 break;
6048 case CP0_REGISTER_02:
6049 switch (sel) {
6050 case CP0_REG02__ENTRYLO0:
6052 TCGv_i64 tmp = tcg_temp_new_i64();
6053 tcg_gen_ld_i64(tmp, cpu_env,
6054 offsetof(CPUMIPSState, CP0_EntryLo0));
6055 #if defined(TARGET_MIPS64)
6056 if (ctx->rxi) {
6057 /* Move RI/XI fields to bits 31:30 */
6058 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6059 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6061 #endif
6062 gen_move_low32(arg, tmp);
6063 tcg_temp_free_i64(tmp);
6065 register_name = "EntryLo0";
6066 break;
6067 case CP0_REG02__TCSTATUS:
6068 CP0_CHECK(ctx->insn_flags & ASE_MT);
6069 gen_helper_mfc0_tcstatus(arg, cpu_env);
6070 register_name = "TCStatus";
6071 break;
6072 case CP0_REG02__TCBIND:
6073 CP0_CHECK(ctx->insn_flags & ASE_MT);
6074 gen_helper_mfc0_tcbind(arg, cpu_env);
6075 register_name = "TCBind";
6076 break;
6077 case CP0_REG02__TCRESTART:
6078 CP0_CHECK(ctx->insn_flags & ASE_MT);
6079 gen_helper_mfc0_tcrestart(arg, cpu_env);
6080 register_name = "TCRestart";
6081 break;
6082 case CP0_REG02__TCHALT:
6083 CP0_CHECK(ctx->insn_flags & ASE_MT);
6084 gen_helper_mfc0_tchalt(arg, cpu_env);
6085 register_name = "TCHalt";
6086 break;
6087 case CP0_REG02__TCCONTEXT:
6088 CP0_CHECK(ctx->insn_flags & ASE_MT);
6089 gen_helper_mfc0_tccontext(arg, cpu_env);
6090 register_name = "TCContext";
6091 break;
6092 case CP0_REG02__TCSCHEDULE:
6093 CP0_CHECK(ctx->insn_flags & ASE_MT);
6094 gen_helper_mfc0_tcschedule(arg, cpu_env);
6095 register_name = "TCSchedule";
6096 break;
6097 case CP0_REG02__TCSCHEFBACK:
6098 CP0_CHECK(ctx->insn_flags & ASE_MT);
6099 gen_helper_mfc0_tcschefback(arg, cpu_env);
6100 register_name = "TCScheFBack";
6101 break;
6102 default:
6103 goto cp0_unimplemented;
6105 break;
6106 case CP0_REGISTER_03:
6107 switch (sel) {
6108 case CP0_REG03__ENTRYLO1:
6110 TCGv_i64 tmp = tcg_temp_new_i64();
6111 tcg_gen_ld_i64(tmp, cpu_env,
6112 offsetof(CPUMIPSState, CP0_EntryLo1));
6113 #if defined(TARGET_MIPS64)
6114 if (ctx->rxi) {
6115 /* Move RI/XI fields to bits 31:30 */
6116 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6117 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6119 #endif
6120 gen_move_low32(arg, tmp);
6121 tcg_temp_free_i64(tmp);
6123 register_name = "EntryLo1";
6124 break;
6125 case CP0_REG03__GLOBALNUM:
6126 CP0_CHECK(ctx->vp);
6127 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6128 register_name = "GlobalNumber";
6129 break;
6130 default:
6131 goto cp0_unimplemented;
6133 break;
6134 case CP0_REGISTER_04:
6135 switch (sel) {
6136 case CP0_REG04__CONTEXT:
6137 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6138 tcg_gen_ext32s_tl(arg, arg);
6139 register_name = "Context";
6140 break;
6141 case CP0_REG04__CONTEXTCONFIG:
6142 /* SmartMIPS ASE */
6143 /* gen_helper_mfc0_contextconfig(arg); */
6144 register_name = "ContextConfig";
6145 goto cp0_unimplemented;
6146 case CP0_REG04__USERLOCAL:
6147 CP0_CHECK(ctx->ulri);
6148 tcg_gen_ld_tl(arg, cpu_env,
6149 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6150 tcg_gen_ext32s_tl(arg, arg);
6151 register_name = "UserLocal";
6152 break;
6153 case CP0_REG04__MMID:
6154 CP0_CHECK(ctx->mi);
6155 gen_helper_mtc0_memorymapid(cpu_env, arg);
6156 register_name = "MMID";
6157 break;
6158 default:
6159 goto cp0_unimplemented;
6161 break;
6162 case CP0_REGISTER_05:
6163 switch (sel) {
6164 case CP0_REG05__PAGEMASK:
6165 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6166 register_name = "PageMask";
6167 break;
6168 case CP0_REG05__PAGEGRAIN:
6169 check_insn(ctx, ISA_MIPS_R2);
6170 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6171 register_name = "PageGrain";
6172 break;
6173 case CP0_REG05__SEGCTL0:
6174 CP0_CHECK(ctx->sc);
6175 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6176 tcg_gen_ext32s_tl(arg, arg);
6177 register_name = "SegCtl0";
6178 break;
6179 case CP0_REG05__SEGCTL1:
6180 CP0_CHECK(ctx->sc);
6181 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6182 tcg_gen_ext32s_tl(arg, arg);
6183 register_name = "SegCtl1";
6184 break;
6185 case CP0_REG05__SEGCTL2:
6186 CP0_CHECK(ctx->sc);
6187 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6188 tcg_gen_ext32s_tl(arg, arg);
6189 register_name = "SegCtl2";
6190 break;
6191 case CP0_REG05__PWBASE:
6192 check_pw(ctx);
6193 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6194 register_name = "PWBase";
6195 break;
6196 case CP0_REG05__PWFIELD:
6197 check_pw(ctx);
6198 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6199 register_name = "PWField";
6200 break;
6201 case CP0_REG05__PWSIZE:
6202 check_pw(ctx);
6203 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6204 register_name = "PWSize";
6205 break;
6206 default:
6207 goto cp0_unimplemented;
6209 break;
6210 case CP0_REGISTER_06:
6211 switch (sel) {
6212 case CP0_REG06__WIRED:
6213 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6214 register_name = "Wired";
6215 break;
6216 case CP0_REG06__SRSCONF0:
6217 check_insn(ctx, ISA_MIPS_R2);
6218 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6219 register_name = "SRSConf0";
6220 break;
6221 case CP0_REG06__SRSCONF1:
6222 check_insn(ctx, ISA_MIPS_R2);
6223 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6224 register_name = "SRSConf1";
6225 break;
6226 case CP0_REG06__SRSCONF2:
6227 check_insn(ctx, ISA_MIPS_R2);
6228 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6229 register_name = "SRSConf2";
6230 break;
6231 case CP0_REG06__SRSCONF3:
6232 check_insn(ctx, ISA_MIPS_R2);
6233 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6234 register_name = "SRSConf3";
6235 break;
6236 case CP0_REG06__SRSCONF4:
6237 check_insn(ctx, ISA_MIPS_R2);
6238 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6239 register_name = "SRSConf4";
6240 break;
6241 case CP0_REG06__PWCTL:
6242 check_pw(ctx);
6243 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6244 register_name = "PWCtl";
6245 break;
6246 default:
6247 goto cp0_unimplemented;
6249 break;
6250 case CP0_REGISTER_07:
6251 switch (sel) {
6252 case CP0_REG07__HWRENA:
6253 check_insn(ctx, ISA_MIPS_R2);
6254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6255 register_name = "HWREna";
6256 break;
6257 default:
6258 goto cp0_unimplemented;
6260 break;
6261 case CP0_REGISTER_08:
6262 switch (sel) {
6263 case CP0_REG08__BADVADDR:
6264 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6265 tcg_gen_ext32s_tl(arg, arg);
6266 register_name = "BadVAddr";
6267 break;
6268 case CP0_REG08__BADINSTR:
6269 CP0_CHECK(ctx->bi);
6270 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6271 register_name = "BadInstr";
6272 break;
6273 case CP0_REG08__BADINSTRP:
6274 CP0_CHECK(ctx->bp);
6275 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6276 register_name = "BadInstrP";
6277 break;
6278 case CP0_REG08__BADINSTRX:
6279 CP0_CHECK(ctx->bi);
6280 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6281 tcg_gen_andi_tl(arg, arg, ~0xffff);
6282 register_name = "BadInstrX";
6283 break;
6284 default:
6285 goto cp0_unimplemented;
6287 break;
6288 case CP0_REGISTER_09:
6289 switch (sel) {
6290 case CP0_REG09__COUNT:
6291 /* Mark as an IO operation because we read the time. */
6292 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6293 gen_io_start();
6295 gen_helper_mfc0_count(arg, cpu_env);
6297 * Break the TB to be able to take timer interrupts immediately
6298 * after reading count. DISAS_STOP isn't sufficient, we need to
6299 * ensure we break completely out of translated code.
6301 gen_save_pc(ctx->base.pc_next + 4);
6302 ctx->base.is_jmp = DISAS_EXIT;
6303 register_name = "Count";
6304 break;
6305 case CP0_REG09__SAARI:
6306 CP0_CHECK(ctx->saar);
6307 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
6308 register_name = "SAARI";
6309 break;
6310 case CP0_REG09__SAAR:
6311 CP0_CHECK(ctx->saar);
6312 gen_helper_mfc0_saar(arg, cpu_env);
6313 register_name = "SAAR";
6314 break;
6315 default:
6316 goto cp0_unimplemented;
6318 break;
6319 case CP0_REGISTER_10:
6320 switch (sel) {
6321 case CP0_REG10__ENTRYHI:
6322 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6323 tcg_gen_ext32s_tl(arg, arg);
6324 register_name = "EntryHi";
6325 break;
6326 default:
6327 goto cp0_unimplemented;
6329 break;
6330 case CP0_REGISTER_11:
6331 switch (sel) {
6332 case CP0_REG11__COMPARE:
6333 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6334 register_name = "Compare";
6335 break;
6336 /* 6,7 are implementation dependent */
6337 default:
6338 goto cp0_unimplemented;
6340 break;
6341 case CP0_REGISTER_12:
6342 switch (sel) {
6343 case CP0_REG12__STATUS:
6344 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6345 register_name = "Status";
6346 break;
6347 case CP0_REG12__INTCTL:
6348 check_insn(ctx, ISA_MIPS_R2);
6349 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6350 register_name = "IntCtl";
6351 break;
6352 case CP0_REG12__SRSCTL:
6353 check_insn(ctx, ISA_MIPS_R2);
6354 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6355 register_name = "SRSCtl";
6356 break;
6357 case CP0_REG12__SRSMAP:
6358 check_insn(ctx, ISA_MIPS_R2);
6359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6360 register_name = "SRSMap";
6361 break;
6362 default:
6363 goto cp0_unimplemented;
6365 break;
6366 case CP0_REGISTER_13:
6367 switch (sel) {
6368 case CP0_REG13__CAUSE:
6369 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6370 register_name = "Cause";
6371 break;
6372 default:
6373 goto cp0_unimplemented;
6375 break;
6376 case CP0_REGISTER_14:
6377 switch (sel) {
6378 case CP0_REG14__EPC:
6379 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6380 tcg_gen_ext32s_tl(arg, arg);
6381 register_name = "EPC";
6382 break;
6383 default:
6384 goto cp0_unimplemented;
6386 break;
6387 case CP0_REGISTER_15:
6388 switch (sel) {
6389 case CP0_REG15__PRID:
6390 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6391 register_name = "PRid";
6392 break;
6393 case CP0_REG15__EBASE:
6394 check_insn(ctx, ISA_MIPS_R2);
6395 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6396 tcg_gen_ext32s_tl(arg, arg);
6397 register_name = "EBase";
6398 break;
6399 case CP0_REG15__CMGCRBASE:
6400 check_insn(ctx, ISA_MIPS_R2);
6401 CP0_CHECK(ctx->cmgcr);
6402 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6403 tcg_gen_ext32s_tl(arg, arg);
6404 register_name = "CMGCRBase";
6405 break;
6406 default:
6407 goto cp0_unimplemented;
6409 break;
6410 case CP0_REGISTER_16:
6411 switch (sel) {
6412 case CP0_REG16__CONFIG:
6413 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6414 register_name = "Config";
6415 break;
6416 case CP0_REG16__CONFIG1:
6417 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6418 register_name = "Config1";
6419 break;
6420 case CP0_REG16__CONFIG2:
6421 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6422 register_name = "Config2";
6423 break;
6424 case CP0_REG16__CONFIG3:
6425 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6426 register_name = "Config3";
6427 break;
6428 case CP0_REG16__CONFIG4:
6429 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6430 register_name = "Config4";
6431 break;
6432 case CP0_REG16__CONFIG5:
6433 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6434 register_name = "Config5";
6435 break;
6436 /* 6,7 are implementation dependent */
6437 case CP0_REG16__CONFIG6:
6438 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6439 register_name = "Config6";
6440 break;
6441 case CP0_REG16__CONFIG7:
6442 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6443 register_name = "Config7";
6444 break;
6445 default:
6446 goto cp0_unimplemented;
6448 break;
6449 case CP0_REGISTER_17:
6450 switch (sel) {
6451 case CP0_REG17__LLADDR:
6452 gen_helper_mfc0_lladdr(arg, cpu_env);
6453 register_name = "LLAddr";
6454 break;
6455 case CP0_REG17__MAAR:
6456 CP0_CHECK(ctx->mrp);
6457 gen_helper_mfc0_maar(arg, cpu_env);
6458 register_name = "MAAR";
6459 break;
6460 case CP0_REG17__MAARI:
6461 CP0_CHECK(ctx->mrp);
6462 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6463 register_name = "MAARI";
6464 break;
6465 default:
6466 goto cp0_unimplemented;
6468 break;
6469 case CP0_REGISTER_18:
6470 switch (sel) {
6471 case CP0_REG18__WATCHLO0:
6472 case CP0_REG18__WATCHLO1:
6473 case CP0_REG18__WATCHLO2:
6474 case CP0_REG18__WATCHLO3:
6475 case CP0_REG18__WATCHLO4:
6476 case CP0_REG18__WATCHLO5:
6477 case CP0_REG18__WATCHLO6:
6478 case CP0_REG18__WATCHLO7:
6479 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6480 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6481 register_name = "WatchLo";
6482 break;
6483 default:
6484 goto cp0_unimplemented;
6486 break;
6487 case CP0_REGISTER_19:
6488 switch (sel) {
6489 case CP0_REG19__WATCHHI0:
6490 case CP0_REG19__WATCHHI1:
6491 case CP0_REG19__WATCHHI2:
6492 case CP0_REG19__WATCHHI3:
6493 case CP0_REG19__WATCHHI4:
6494 case CP0_REG19__WATCHHI5:
6495 case CP0_REG19__WATCHHI6:
6496 case CP0_REG19__WATCHHI7:
6497 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6498 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6499 register_name = "WatchHi";
6500 break;
6501 default:
6502 goto cp0_unimplemented;
6504 break;
6505 case CP0_REGISTER_20:
6506 switch (sel) {
6507 case CP0_REG20__XCONTEXT:
6508 #if defined(TARGET_MIPS64)
6509 check_insn(ctx, ISA_MIPS3);
6510 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6511 tcg_gen_ext32s_tl(arg, arg);
6512 register_name = "XContext";
6513 break;
6514 #endif
6515 default:
6516 goto cp0_unimplemented;
6518 break;
6519 case CP0_REGISTER_21:
6520 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6521 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6522 switch (sel) {
6523 case 0:
6524 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6525 register_name = "Framemask";
6526 break;
6527 default:
6528 goto cp0_unimplemented;
6530 break;
6531 case CP0_REGISTER_22:
6532 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6533 register_name = "'Diagnostic"; /* implementation dependent */
6534 break;
6535 case CP0_REGISTER_23:
6536 switch (sel) {
6537 case CP0_REG23__DEBUG:
6538 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6539 register_name = "Debug";
6540 break;
6541 case CP0_REG23__TRACECONTROL:
6542 /* PDtrace support */
6543 /* gen_helper_mfc0_tracecontrol(arg); */
6544 register_name = "TraceControl";
6545 goto cp0_unimplemented;
6546 case CP0_REG23__TRACECONTROL2:
6547 /* PDtrace support */
6548 /* gen_helper_mfc0_tracecontrol2(arg); */
6549 register_name = "TraceControl2";
6550 goto cp0_unimplemented;
6551 case CP0_REG23__USERTRACEDATA1:
6552 /* PDtrace support */
6553 /* gen_helper_mfc0_usertracedata1(arg);*/
6554 register_name = "UserTraceData1";
6555 goto cp0_unimplemented;
6556 case CP0_REG23__TRACEIBPC:
6557 /* PDtrace support */
6558 /* gen_helper_mfc0_traceibpc(arg); */
6559 register_name = "TraceIBPC";
6560 goto cp0_unimplemented;
6561 case CP0_REG23__TRACEDBPC:
6562 /* PDtrace support */
6563 /* gen_helper_mfc0_tracedbpc(arg); */
6564 register_name = "TraceDBPC";
6565 goto cp0_unimplemented;
6566 default:
6567 goto cp0_unimplemented;
6569 break;
6570 case CP0_REGISTER_24:
6571 switch (sel) {
6572 case CP0_REG24__DEPC:
6573 /* EJTAG support */
6574 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6575 tcg_gen_ext32s_tl(arg, arg);
6576 register_name = "DEPC";
6577 break;
6578 default:
6579 goto cp0_unimplemented;
6581 break;
6582 case CP0_REGISTER_25:
6583 switch (sel) {
6584 case CP0_REG25__PERFCTL0:
6585 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6586 register_name = "Performance0";
6587 break;
6588 case CP0_REG25__PERFCNT0:
6589 /* gen_helper_mfc0_performance1(arg); */
6590 register_name = "Performance1";
6591 goto cp0_unimplemented;
6592 case CP0_REG25__PERFCTL1:
6593 /* gen_helper_mfc0_performance2(arg); */
6594 register_name = "Performance2";
6595 goto cp0_unimplemented;
6596 case CP0_REG25__PERFCNT1:
6597 /* gen_helper_mfc0_performance3(arg); */
6598 register_name = "Performance3";
6599 goto cp0_unimplemented;
6600 case CP0_REG25__PERFCTL2:
6601 /* gen_helper_mfc0_performance4(arg); */
6602 register_name = "Performance4";
6603 goto cp0_unimplemented;
6604 case CP0_REG25__PERFCNT2:
6605 /* gen_helper_mfc0_performance5(arg); */
6606 register_name = "Performance5";
6607 goto cp0_unimplemented;
6608 case CP0_REG25__PERFCTL3:
6609 /* gen_helper_mfc0_performance6(arg); */
6610 register_name = "Performance6";
6611 goto cp0_unimplemented;
6612 case CP0_REG25__PERFCNT3:
6613 /* gen_helper_mfc0_performance7(arg); */
6614 register_name = "Performance7";
6615 goto cp0_unimplemented;
6616 default:
6617 goto cp0_unimplemented;
6619 break;
6620 case CP0_REGISTER_26:
6621 switch (sel) {
6622 case CP0_REG26__ERRCTL:
6623 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6624 register_name = "ErrCtl";
6625 break;
6626 default:
6627 goto cp0_unimplemented;
6629 break;
6630 case CP0_REGISTER_27:
6631 switch (sel) {
6632 case CP0_REG27__CACHERR:
6633 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6634 register_name = "CacheErr";
6635 break;
6636 default:
6637 goto cp0_unimplemented;
6639 break;
6640 case CP0_REGISTER_28:
6641 switch (sel) {
6642 case CP0_REG28__TAGLO:
6643 case CP0_REG28__TAGLO1:
6644 case CP0_REG28__TAGLO2:
6645 case CP0_REG28__TAGLO3:
6647 TCGv_i64 tmp = tcg_temp_new_i64();
6648 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
6649 gen_move_low32(arg, tmp);
6650 tcg_temp_free_i64(tmp);
6652 register_name = "TagLo";
6653 break;
6654 case CP0_REG28__DATALO:
6655 case CP0_REG28__DATALO1:
6656 case CP0_REG28__DATALO2:
6657 case CP0_REG28__DATALO3:
6658 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6659 register_name = "DataLo";
6660 break;
6661 default:
6662 goto cp0_unimplemented;
6664 break;
6665 case CP0_REGISTER_29:
6666 switch (sel) {
6667 case CP0_REG29__TAGHI:
6668 case CP0_REG29__TAGHI1:
6669 case CP0_REG29__TAGHI2:
6670 case CP0_REG29__TAGHI3:
6671 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6672 register_name = "TagHi";
6673 break;
6674 case CP0_REG29__DATAHI:
6675 case CP0_REG29__DATAHI1:
6676 case CP0_REG29__DATAHI2:
6677 case CP0_REG29__DATAHI3:
6678 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6679 register_name = "DataHi";
6680 break;
6681 default:
6682 goto cp0_unimplemented;
6684 break;
6685 case CP0_REGISTER_30:
6686 switch (sel) {
6687 case CP0_REG30__ERROREPC:
6688 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6689 tcg_gen_ext32s_tl(arg, arg);
6690 register_name = "ErrorEPC";
6691 break;
6692 default:
6693 goto cp0_unimplemented;
6695 break;
6696 case CP0_REGISTER_31:
6697 switch (sel) {
6698 case CP0_REG31__DESAVE:
6699 /* EJTAG support */
6700 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6701 register_name = "DESAVE";
6702 break;
6703 case CP0_REG31__KSCRATCH1:
6704 case CP0_REG31__KSCRATCH2:
6705 case CP0_REG31__KSCRATCH3:
6706 case CP0_REG31__KSCRATCH4:
6707 case CP0_REG31__KSCRATCH5:
6708 case CP0_REG31__KSCRATCH6:
6709 CP0_CHECK(ctx->kscrexist & (1 << sel));
6710 tcg_gen_ld_tl(arg, cpu_env,
6711 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
6712 tcg_gen_ext32s_tl(arg, arg);
6713 register_name = "KScratch";
6714 break;
6715 default:
6716 goto cp0_unimplemented;
6718 break;
6719 default:
6720 goto cp0_unimplemented;
6722 trace_mips_translate_c0("mfc0", register_name, reg, sel);
6723 return;
6725 cp0_unimplemented:
6726 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
6727 register_name, reg, sel);
6728 gen_mfc0_unimplemented(ctx, arg);
6731 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6733 const char *register_name = "invalid";
6735 if (sel != 0) {
6736 check_insn(ctx, ISA_MIPS_R1);
6739 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6740 gen_io_start();
6743 switch (reg) {
6744 case CP0_REGISTER_00:
6745 switch (sel) {
6746 case CP0_REG00__INDEX:
6747 gen_helper_mtc0_index(cpu_env, arg);
6748 register_name = "Index";
6749 break;
6750 case CP0_REG00__MVPCONTROL:
6751 CP0_CHECK(ctx->insn_flags & ASE_MT);
6752 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6753 register_name = "MVPControl";
6754 break;
6755 case CP0_REG00__MVPCONF0:
6756 CP0_CHECK(ctx->insn_flags & ASE_MT);
6757 /* ignored */
6758 register_name = "MVPConf0";
6759 break;
6760 case CP0_REG00__MVPCONF1:
6761 CP0_CHECK(ctx->insn_flags & ASE_MT);
6762 /* ignored */
6763 register_name = "MVPConf1";
6764 break;
6765 case CP0_REG00__VPCONTROL:
6766 CP0_CHECK(ctx->vp);
6767 /* ignored */
6768 register_name = "VPControl";
6769 break;
6770 default:
6771 goto cp0_unimplemented;
6773 break;
6774 case CP0_REGISTER_01:
6775 switch (sel) {
6776 case CP0_REG01__RANDOM:
6777 /* ignored */
6778 register_name = "Random";
6779 break;
6780 case CP0_REG01__VPECONTROL:
6781 CP0_CHECK(ctx->insn_flags & ASE_MT);
6782 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6783 register_name = "VPEControl";
6784 break;
6785 case CP0_REG01__VPECONF0:
6786 CP0_CHECK(ctx->insn_flags & ASE_MT);
6787 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6788 register_name = "VPEConf0";
6789 break;
6790 case CP0_REG01__VPECONF1:
6791 CP0_CHECK(ctx->insn_flags & ASE_MT);
6792 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6793 register_name = "VPEConf1";
6794 break;
6795 case CP0_REG01__YQMASK:
6796 CP0_CHECK(ctx->insn_flags & ASE_MT);
6797 gen_helper_mtc0_yqmask(cpu_env, arg);
6798 register_name = "YQMask";
6799 break;
6800 case CP0_REG01__VPESCHEDULE:
6801 CP0_CHECK(ctx->insn_flags & ASE_MT);
6802 tcg_gen_st_tl(arg, cpu_env,
6803 offsetof(CPUMIPSState, CP0_VPESchedule));
6804 register_name = "VPESchedule";
6805 break;
6806 case CP0_REG01__VPESCHEFBACK:
6807 CP0_CHECK(ctx->insn_flags & ASE_MT);
6808 tcg_gen_st_tl(arg, cpu_env,
6809 offsetof(CPUMIPSState, CP0_VPEScheFBack));
6810 register_name = "VPEScheFBack";
6811 break;
6812 case CP0_REG01__VPEOPT:
6813 CP0_CHECK(ctx->insn_flags & ASE_MT);
6814 gen_helper_mtc0_vpeopt(cpu_env, arg);
6815 register_name = "VPEOpt";
6816 break;
6817 default:
6818 goto cp0_unimplemented;
6820 break;
6821 case CP0_REGISTER_02:
6822 switch (sel) {
6823 case CP0_REG02__ENTRYLO0:
6824 gen_helper_mtc0_entrylo0(cpu_env, arg);
6825 register_name = "EntryLo0";
6826 break;
6827 case CP0_REG02__TCSTATUS:
6828 CP0_CHECK(ctx->insn_flags & ASE_MT);
6829 gen_helper_mtc0_tcstatus(cpu_env, arg);
6830 register_name = "TCStatus";
6831 break;
6832 case CP0_REG02__TCBIND:
6833 CP0_CHECK(ctx->insn_flags & ASE_MT);
6834 gen_helper_mtc0_tcbind(cpu_env, arg);
6835 register_name = "TCBind";
6836 break;
6837 case CP0_REG02__TCRESTART:
6838 CP0_CHECK(ctx->insn_flags & ASE_MT);
6839 gen_helper_mtc0_tcrestart(cpu_env, arg);
6840 register_name = "TCRestart";
6841 break;
6842 case CP0_REG02__TCHALT:
6843 CP0_CHECK(ctx->insn_flags & ASE_MT);
6844 gen_helper_mtc0_tchalt(cpu_env, arg);
6845 register_name = "TCHalt";
6846 break;
6847 case CP0_REG02__TCCONTEXT:
6848 CP0_CHECK(ctx->insn_flags & ASE_MT);
6849 gen_helper_mtc0_tccontext(cpu_env, arg);
6850 register_name = "TCContext";
6851 break;
6852 case CP0_REG02__TCSCHEDULE:
6853 CP0_CHECK(ctx->insn_flags & ASE_MT);
6854 gen_helper_mtc0_tcschedule(cpu_env, arg);
6855 register_name = "TCSchedule";
6856 break;
6857 case CP0_REG02__TCSCHEFBACK:
6858 CP0_CHECK(ctx->insn_flags & ASE_MT);
6859 gen_helper_mtc0_tcschefback(cpu_env, arg);
6860 register_name = "TCScheFBack";
6861 break;
6862 default:
6863 goto cp0_unimplemented;
6865 break;
6866 case CP0_REGISTER_03:
6867 switch (sel) {
6868 case CP0_REG03__ENTRYLO1:
6869 gen_helper_mtc0_entrylo1(cpu_env, arg);
6870 register_name = "EntryLo1";
6871 break;
6872 case CP0_REG03__GLOBALNUM:
6873 CP0_CHECK(ctx->vp);
6874 /* ignored */
6875 register_name = "GlobalNumber";
6876 break;
6877 default:
6878 goto cp0_unimplemented;
6880 break;
6881 case CP0_REGISTER_04:
6882 switch (sel) {
6883 case CP0_REG04__CONTEXT:
6884 gen_helper_mtc0_context(cpu_env, arg);
6885 register_name = "Context";
6886 break;
6887 case CP0_REG04__CONTEXTCONFIG:
6888 /* SmartMIPS ASE */
6889 /* gen_helper_mtc0_contextconfig(arg); */
6890 register_name = "ContextConfig";
6891 goto cp0_unimplemented;
6892 case CP0_REG04__USERLOCAL:
6893 CP0_CHECK(ctx->ulri);
6894 tcg_gen_st_tl(arg, cpu_env,
6895 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6896 register_name = "UserLocal";
6897 break;
6898 case CP0_REG04__MMID:
6899 CP0_CHECK(ctx->mi);
6900 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
6901 register_name = "MMID";
6902 break;
6903 default:
6904 goto cp0_unimplemented;
6906 break;
6907 case CP0_REGISTER_05:
6908 switch (sel) {
6909 case CP0_REG05__PAGEMASK:
6910 gen_helper_mtc0_pagemask(cpu_env, arg);
6911 register_name = "PageMask";
6912 break;
6913 case CP0_REG05__PAGEGRAIN:
6914 check_insn(ctx, ISA_MIPS_R2);
6915 gen_helper_mtc0_pagegrain(cpu_env, arg);
6916 register_name = "PageGrain";
6917 ctx->base.is_jmp = DISAS_STOP;
6918 break;
6919 case CP0_REG05__SEGCTL0:
6920 CP0_CHECK(ctx->sc);
6921 gen_helper_mtc0_segctl0(cpu_env, arg);
6922 register_name = "SegCtl0";
6923 break;
6924 case CP0_REG05__SEGCTL1:
6925 CP0_CHECK(ctx->sc);
6926 gen_helper_mtc0_segctl1(cpu_env, arg);
6927 register_name = "SegCtl1";
6928 break;
6929 case CP0_REG05__SEGCTL2:
6930 CP0_CHECK(ctx->sc);
6931 gen_helper_mtc0_segctl2(cpu_env, arg);
6932 register_name = "SegCtl2";
6933 break;
6934 case CP0_REG05__PWBASE:
6935 check_pw(ctx);
6936 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6937 register_name = "PWBase";
6938 break;
6939 case CP0_REG05__PWFIELD:
6940 check_pw(ctx);
6941 gen_helper_mtc0_pwfield(cpu_env, arg);
6942 register_name = "PWField";
6943 break;
6944 case CP0_REG05__PWSIZE:
6945 check_pw(ctx);
6946 gen_helper_mtc0_pwsize(cpu_env, arg);
6947 register_name = "PWSize";
6948 break;
6949 default:
6950 goto cp0_unimplemented;
6952 break;
6953 case CP0_REGISTER_06:
6954 switch (sel) {
6955 case CP0_REG06__WIRED:
6956 gen_helper_mtc0_wired(cpu_env, arg);
6957 register_name = "Wired";
6958 break;
6959 case CP0_REG06__SRSCONF0:
6960 check_insn(ctx, ISA_MIPS_R2);
6961 gen_helper_mtc0_srsconf0(cpu_env, arg);
6962 register_name = "SRSConf0";
6963 break;
6964 case CP0_REG06__SRSCONF1:
6965 check_insn(ctx, ISA_MIPS_R2);
6966 gen_helper_mtc0_srsconf1(cpu_env, arg);
6967 register_name = "SRSConf1";
6968 break;
6969 case CP0_REG06__SRSCONF2:
6970 check_insn(ctx, ISA_MIPS_R2);
6971 gen_helper_mtc0_srsconf2(cpu_env, arg);
6972 register_name = "SRSConf2";
6973 break;
6974 case CP0_REG06__SRSCONF3:
6975 check_insn(ctx, ISA_MIPS_R2);
6976 gen_helper_mtc0_srsconf3(cpu_env, arg);
6977 register_name = "SRSConf3";
6978 break;
6979 case CP0_REG06__SRSCONF4:
6980 check_insn(ctx, ISA_MIPS_R2);
6981 gen_helper_mtc0_srsconf4(cpu_env, arg);
6982 register_name = "SRSConf4";
6983 break;
6984 case CP0_REG06__PWCTL:
6985 check_pw(ctx);
6986 gen_helper_mtc0_pwctl(cpu_env, arg);
6987 register_name = "PWCtl";
6988 break;
6989 default:
6990 goto cp0_unimplemented;
6992 break;
6993 case CP0_REGISTER_07:
6994 switch (sel) {
6995 case CP0_REG07__HWRENA:
6996 check_insn(ctx, ISA_MIPS_R2);
6997 gen_helper_mtc0_hwrena(cpu_env, arg);
6998 ctx->base.is_jmp = DISAS_STOP;
6999 register_name = "HWREna";
7000 break;
7001 default:
7002 goto cp0_unimplemented;
7004 break;
7005 case CP0_REGISTER_08:
7006 switch (sel) {
7007 case CP0_REG08__BADVADDR:
7008 /* ignored */
7009 register_name = "BadVAddr";
7010 break;
7011 case CP0_REG08__BADINSTR:
7012 /* ignored */
7013 register_name = "BadInstr";
7014 break;
7015 case CP0_REG08__BADINSTRP:
7016 /* ignored */
7017 register_name = "BadInstrP";
7018 break;
7019 case CP0_REG08__BADINSTRX:
7020 /* ignored */
7021 register_name = "BadInstrX";
7022 break;
7023 default:
7024 goto cp0_unimplemented;
7026 break;
7027 case CP0_REGISTER_09:
7028 switch (sel) {
7029 case CP0_REG09__COUNT:
7030 gen_helper_mtc0_count(cpu_env, arg);
7031 register_name = "Count";
7032 break;
7033 case CP0_REG09__SAARI:
7034 CP0_CHECK(ctx->saar);
7035 gen_helper_mtc0_saari(cpu_env, arg);
7036 register_name = "SAARI";
7037 break;
7038 case CP0_REG09__SAAR:
7039 CP0_CHECK(ctx->saar);
7040 gen_helper_mtc0_saar(cpu_env, arg);
7041 register_name = "SAAR";
7042 break;
7043 default:
7044 goto cp0_unimplemented;
7046 break;
7047 case CP0_REGISTER_10:
7048 switch (sel) {
7049 case CP0_REG10__ENTRYHI:
7050 gen_helper_mtc0_entryhi(cpu_env, arg);
7051 register_name = "EntryHi";
7052 break;
7053 default:
7054 goto cp0_unimplemented;
7056 break;
7057 case CP0_REGISTER_11:
7058 switch (sel) {
7059 case CP0_REG11__COMPARE:
7060 gen_helper_mtc0_compare(cpu_env, arg);
7061 register_name = "Compare";
7062 break;
7063 /* 6,7 are implementation dependent */
7064 default:
7065 goto cp0_unimplemented;
7067 break;
7068 case CP0_REGISTER_12:
7069 switch (sel) {
7070 case CP0_REG12__STATUS:
7071 save_cpu_state(ctx, 1);
7072 gen_helper_mtc0_status(cpu_env, arg);
7073 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7074 gen_save_pc(ctx->base.pc_next + 4);
7075 ctx->base.is_jmp = DISAS_EXIT;
7076 register_name = "Status";
7077 break;
7078 case CP0_REG12__INTCTL:
7079 check_insn(ctx, ISA_MIPS_R2);
7080 gen_helper_mtc0_intctl(cpu_env, arg);
7081 /* Stop translation as we may have switched the execution mode */
7082 ctx->base.is_jmp = DISAS_STOP;
7083 register_name = "IntCtl";
7084 break;
7085 case CP0_REG12__SRSCTL:
7086 check_insn(ctx, ISA_MIPS_R2);
7087 gen_helper_mtc0_srsctl(cpu_env, arg);
7088 /* Stop translation as we may have switched the execution mode */
7089 ctx->base.is_jmp = DISAS_STOP;
7090 register_name = "SRSCtl";
7091 break;
7092 case CP0_REG12__SRSMAP:
7093 check_insn(ctx, ISA_MIPS_R2);
7094 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7095 /* Stop translation as we may have switched the execution mode */
7096 ctx->base.is_jmp = DISAS_STOP;
7097 register_name = "SRSMap";
7098 break;
7099 default:
7100 goto cp0_unimplemented;
7102 break;
7103 case CP0_REGISTER_13:
7104 switch (sel) {
7105 case CP0_REG13__CAUSE:
7106 save_cpu_state(ctx, 1);
7107 gen_helper_mtc0_cause(cpu_env, arg);
7109 * Stop translation as we may have triggered an interrupt.
7110 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7111 * translated code to check for pending interrupts.
7113 gen_save_pc(ctx->base.pc_next + 4);
7114 ctx->base.is_jmp = DISAS_EXIT;
7115 register_name = "Cause";
7116 break;
7117 default:
7118 goto cp0_unimplemented;
7120 break;
7121 case CP0_REGISTER_14:
7122 switch (sel) {
7123 case CP0_REG14__EPC:
7124 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7125 register_name = "EPC";
7126 break;
7127 default:
7128 goto cp0_unimplemented;
7130 break;
7131 case CP0_REGISTER_15:
7132 switch (sel) {
7133 case CP0_REG15__PRID:
7134 /* ignored */
7135 register_name = "PRid";
7136 break;
7137 case CP0_REG15__EBASE:
7138 check_insn(ctx, ISA_MIPS_R2);
7139 gen_helper_mtc0_ebase(cpu_env, arg);
7140 register_name = "EBase";
7141 break;
7142 default:
7143 goto cp0_unimplemented;
7145 break;
7146 case CP0_REGISTER_16:
7147 switch (sel) {
7148 case CP0_REG16__CONFIG:
7149 gen_helper_mtc0_config0(cpu_env, arg);
7150 register_name = "Config";
7151 /* Stop translation as we may have switched the execution mode */
7152 ctx->base.is_jmp = DISAS_STOP;
7153 break;
7154 case CP0_REG16__CONFIG1:
7155 /* ignored, read only */
7156 register_name = "Config1";
7157 break;
7158 case CP0_REG16__CONFIG2:
7159 gen_helper_mtc0_config2(cpu_env, arg);
7160 register_name = "Config2";
7161 /* Stop translation as we may have switched the execution mode */
7162 ctx->base.is_jmp = DISAS_STOP;
7163 break;
7164 case CP0_REG16__CONFIG3:
7165 gen_helper_mtc0_config3(cpu_env, arg);
7166 register_name = "Config3";
7167 /* Stop translation as we may have switched the execution mode */
7168 ctx->base.is_jmp = DISAS_STOP;
7169 break;
7170 case CP0_REG16__CONFIG4:
7171 gen_helper_mtc0_config4(cpu_env, arg);
7172 register_name = "Config4";
7173 ctx->base.is_jmp = DISAS_STOP;
7174 break;
7175 case CP0_REG16__CONFIG5:
7176 gen_helper_mtc0_config5(cpu_env, arg);
7177 register_name = "Config5";
7178 /* Stop translation as we may have switched the execution mode */
7179 ctx->base.is_jmp = DISAS_STOP;
7180 break;
7181 /* 6,7 are implementation dependent */
7182 case CP0_REG16__CONFIG6:
7183 /* ignored */
7184 register_name = "Config6";
7185 break;
7186 case CP0_REG16__CONFIG7:
7187 /* ignored */
7188 register_name = "Config7";
7189 break;
7190 default:
7191 register_name = "Invalid config selector";
7192 goto cp0_unimplemented;
7194 break;
7195 case CP0_REGISTER_17:
7196 switch (sel) {
7197 case CP0_REG17__LLADDR:
7198 gen_helper_mtc0_lladdr(cpu_env, arg);
7199 register_name = "LLAddr";
7200 break;
7201 case CP0_REG17__MAAR:
7202 CP0_CHECK(ctx->mrp);
7203 gen_helper_mtc0_maar(cpu_env, arg);
7204 register_name = "MAAR";
7205 break;
7206 case CP0_REG17__MAARI:
7207 CP0_CHECK(ctx->mrp);
7208 gen_helper_mtc0_maari(cpu_env, arg);
7209 register_name = "MAARI";
7210 break;
7211 default:
7212 goto cp0_unimplemented;
7214 break;
7215 case CP0_REGISTER_18:
7216 switch (sel) {
7217 case CP0_REG18__WATCHLO0:
7218 case CP0_REG18__WATCHLO1:
7219 case CP0_REG18__WATCHLO2:
7220 case CP0_REG18__WATCHLO3:
7221 case CP0_REG18__WATCHLO4:
7222 case CP0_REG18__WATCHLO5:
7223 case CP0_REG18__WATCHLO6:
7224 case CP0_REG18__WATCHLO7:
7225 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7226 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7227 register_name = "WatchLo";
7228 break;
7229 default:
7230 goto cp0_unimplemented;
7232 break;
7233 case CP0_REGISTER_19:
7234 switch (sel) {
7235 case CP0_REG19__WATCHHI0:
7236 case CP0_REG19__WATCHHI1:
7237 case CP0_REG19__WATCHHI2:
7238 case CP0_REG19__WATCHHI3:
7239 case CP0_REG19__WATCHHI4:
7240 case CP0_REG19__WATCHHI5:
7241 case CP0_REG19__WATCHHI6:
7242 case CP0_REG19__WATCHHI7:
7243 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7244 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7245 register_name = "WatchHi";
7246 break;
7247 default:
7248 goto cp0_unimplemented;
7250 break;
7251 case CP0_REGISTER_20:
7252 switch (sel) {
7253 case CP0_REG20__XCONTEXT:
7254 #if defined(TARGET_MIPS64)
7255 check_insn(ctx, ISA_MIPS3);
7256 gen_helper_mtc0_xcontext(cpu_env, arg);
7257 register_name = "XContext";
7258 break;
7259 #endif
7260 default:
7261 goto cp0_unimplemented;
7263 break;
7264 case CP0_REGISTER_21:
7265 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7266 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7267 switch (sel) {
7268 case 0:
7269 gen_helper_mtc0_framemask(cpu_env, arg);
7270 register_name = "Framemask";
7271 break;
7272 default:
7273 goto cp0_unimplemented;
7275 break;
7276 case CP0_REGISTER_22:
7277 /* ignored */
7278 register_name = "Diagnostic"; /* implementation dependent */
7279 break;
7280 case CP0_REGISTER_23:
7281 switch (sel) {
7282 case CP0_REG23__DEBUG:
7283 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7284 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7285 gen_save_pc(ctx->base.pc_next + 4);
7286 ctx->base.is_jmp = DISAS_EXIT;
7287 register_name = "Debug";
7288 break;
7289 case CP0_REG23__TRACECONTROL:
7290 /* PDtrace support */
7291 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
7292 register_name = "TraceControl";
7293 /* Stop translation as we may have switched the execution mode */
7294 ctx->base.is_jmp = DISAS_STOP;
7295 goto cp0_unimplemented;
7296 case CP0_REG23__TRACECONTROL2:
7297 /* PDtrace support */
7298 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
7299 register_name = "TraceControl2";
7300 /* Stop translation as we may have switched the execution mode */
7301 ctx->base.is_jmp = DISAS_STOP;
7302 goto cp0_unimplemented;
7303 case CP0_REG23__USERTRACEDATA1:
7304 /* Stop translation as we may have switched the execution mode */
7305 ctx->base.is_jmp = DISAS_STOP;
7306 /* PDtrace support */
7307 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
7308 register_name = "UserTraceData";
7309 /* Stop translation as we may have switched the execution mode */
7310 ctx->base.is_jmp = DISAS_STOP;
7311 goto cp0_unimplemented;
7312 case CP0_REG23__TRACEIBPC:
7313 /* PDtrace support */
7314 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
7315 /* Stop translation as we may have switched the execution mode */
7316 ctx->base.is_jmp = DISAS_STOP;
7317 register_name = "TraceIBPC";
7318 goto cp0_unimplemented;
7319 case CP0_REG23__TRACEDBPC:
7320 /* PDtrace support */
7321 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
7322 /* Stop translation as we may have switched the execution mode */
7323 ctx->base.is_jmp = DISAS_STOP;
7324 register_name = "TraceDBPC";
7325 goto cp0_unimplemented;
7326 default:
7327 goto cp0_unimplemented;
7329 break;
7330 case CP0_REGISTER_24:
7331 switch (sel) {
7332 case CP0_REG24__DEPC:
7333 /* EJTAG support */
7334 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7335 register_name = "DEPC";
7336 break;
7337 default:
7338 goto cp0_unimplemented;
7340 break;
7341 case CP0_REGISTER_25:
7342 switch (sel) {
7343 case CP0_REG25__PERFCTL0:
7344 gen_helper_mtc0_performance0(cpu_env, arg);
7345 register_name = "Performance0";
7346 break;
7347 case CP0_REG25__PERFCNT0:
7348 /* gen_helper_mtc0_performance1(arg); */
7349 register_name = "Performance1";
7350 goto cp0_unimplemented;
7351 case CP0_REG25__PERFCTL1:
7352 /* gen_helper_mtc0_performance2(arg); */
7353 register_name = "Performance2";
7354 goto cp0_unimplemented;
7355 case CP0_REG25__PERFCNT1:
7356 /* gen_helper_mtc0_performance3(arg); */
7357 register_name = "Performance3";
7358 goto cp0_unimplemented;
7359 case CP0_REG25__PERFCTL2:
7360 /* gen_helper_mtc0_performance4(arg); */
7361 register_name = "Performance4";
7362 goto cp0_unimplemented;
7363 case CP0_REG25__PERFCNT2:
7364 /* gen_helper_mtc0_performance5(arg); */
7365 register_name = "Performance5";
7366 goto cp0_unimplemented;
7367 case CP0_REG25__PERFCTL3:
7368 /* gen_helper_mtc0_performance6(arg); */
7369 register_name = "Performance6";
7370 goto cp0_unimplemented;
7371 case CP0_REG25__PERFCNT3:
7372 /* gen_helper_mtc0_performance7(arg); */
7373 register_name = "Performance7";
7374 goto cp0_unimplemented;
7375 default:
7376 goto cp0_unimplemented;
7378 break;
7379 case CP0_REGISTER_26:
7380 switch (sel) {
7381 case CP0_REG26__ERRCTL:
7382 gen_helper_mtc0_errctl(cpu_env, arg);
7383 ctx->base.is_jmp = DISAS_STOP;
7384 register_name = "ErrCtl";
7385 break;
7386 default:
7387 goto cp0_unimplemented;
7389 break;
7390 case CP0_REGISTER_27:
7391 switch (sel) {
7392 case CP0_REG27__CACHERR:
7393 /* ignored */
7394 register_name = "CacheErr";
7395 break;
7396 default:
7397 goto cp0_unimplemented;
7399 break;
7400 case CP0_REGISTER_28:
7401 switch (sel) {
7402 case CP0_REG28__TAGLO:
7403 case CP0_REG28__TAGLO1:
7404 case CP0_REG28__TAGLO2:
7405 case CP0_REG28__TAGLO3:
7406 gen_helper_mtc0_taglo(cpu_env, arg);
7407 register_name = "TagLo";
7408 break;
7409 case CP0_REG28__DATALO:
7410 case CP0_REG28__DATALO1:
7411 case CP0_REG28__DATALO2:
7412 case CP0_REG28__DATALO3:
7413 gen_helper_mtc0_datalo(cpu_env, arg);
7414 register_name = "DataLo";
7415 break;
7416 default:
7417 goto cp0_unimplemented;
7419 break;
7420 case CP0_REGISTER_29:
7421 switch (sel) {
7422 case CP0_REG29__TAGHI:
7423 case CP0_REG29__TAGHI1:
7424 case CP0_REG29__TAGHI2:
7425 case CP0_REG29__TAGHI3:
7426 gen_helper_mtc0_taghi(cpu_env, arg);
7427 register_name = "TagHi";
7428 break;
7429 case CP0_REG29__DATAHI:
7430 case CP0_REG29__DATAHI1:
7431 case CP0_REG29__DATAHI2:
7432 case CP0_REG29__DATAHI3:
7433 gen_helper_mtc0_datahi(cpu_env, arg);
7434 register_name = "DataHi";
7435 break;
7436 default:
7437 register_name = "invalid sel";
7438 goto cp0_unimplemented;
7440 break;
7441 case CP0_REGISTER_30:
7442 switch (sel) {
7443 case CP0_REG30__ERROREPC:
7444 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7445 register_name = "ErrorEPC";
7446 break;
7447 default:
7448 goto cp0_unimplemented;
7450 break;
7451 case CP0_REGISTER_31:
7452 switch (sel) {
7453 case CP0_REG31__DESAVE:
7454 /* EJTAG support */
7455 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7456 register_name = "DESAVE";
7457 break;
7458 case CP0_REG31__KSCRATCH1:
7459 case CP0_REG31__KSCRATCH2:
7460 case CP0_REG31__KSCRATCH3:
7461 case CP0_REG31__KSCRATCH4:
7462 case CP0_REG31__KSCRATCH5:
7463 case CP0_REG31__KSCRATCH6:
7464 CP0_CHECK(ctx->kscrexist & (1 << sel));
7465 tcg_gen_st_tl(arg, cpu_env,
7466 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7467 register_name = "KScratch";
7468 break;
7469 default:
7470 goto cp0_unimplemented;
7472 break;
7473 default:
7474 goto cp0_unimplemented;
7476 trace_mips_translate_c0("mtc0", register_name, reg, sel);
7478 /* For simplicity assume that all writes can cause interrupts. */
7479 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7481 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7482 * translated code to check for pending interrupts.
7484 gen_save_pc(ctx->base.pc_next + 4);
7485 ctx->base.is_jmp = DISAS_EXIT;
7487 return;
7489 cp0_unimplemented:
7490 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
7491 register_name, reg, sel);
7494 #if defined(TARGET_MIPS64)
7495 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7497 const char *register_name = "invalid";
7499 if (sel != 0) {
7500 check_insn(ctx, ISA_MIPS_R1);
7503 switch (reg) {
7504 case CP0_REGISTER_00:
7505 switch (sel) {
7506 case CP0_REG00__INDEX:
7507 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7508 register_name = "Index";
7509 break;
7510 case CP0_REG00__MVPCONTROL:
7511 CP0_CHECK(ctx->insn_flags & ASE_MT);
7512 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7513 register_name = "MVPControl";
7514 break;
7515 case CP0_REG00__MVPCONF0:
7516 CP0_CHECK(ctx->insn_flags & ASE_MT);
7517 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7518 register_name = "MVPConf0";
7519 break;
7520 case CP0_REG00__MVPCONF1:
7521 CP0_CHECK(ctx->insn_flags & ASE_MT);
7522 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7523 register_name = "MVPConf1";
7524 break;
7525 case CP0_REG00__VPCONTROL:
7526 CP0_CHECK(ctx->vp);
7527 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7528 register_name = "VPControl";
7529 break;
7530 default:
7531 goto cp0_unimplemented;
7533 break;
7534 case CP0_REGISTER_01:
7535 switch (sel) {
7536 case CP0_REG01__RANDOM:
7537 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7538 gen_helper_mfc0_random(arg, cpu_env);
7539 register_name = "Random";
7540 break;
7541 case CP0_REG01__VPECONTROL:
7542 CP0_CHECK(ctx->insn_flags & ASE_MT);
7543 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7544 register_name = "VPEControl";
7545 break;
7546 case CP0_REG01__VPECONF0:
7547 CP0_CHECK(ctx->insn_flags & ASE_MT);
7548 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7549 register_name = "VPEConf0";
7550 break;
7551 case CP0_REG01__VPECONF1:
7552 CP0_CHECK(ctx->insn_flags & ASE_MT);
7553 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7554 register_name = "VPEConf1";
7555 break;
7556 case CP0_REG01__YQMASK:
7557 CP0_CHECK(ctx->insn_flags & ASE_MT);
7558 tcg_gen_ld_tl(arg, cpu_env,
7559 offsetof(CPUMIPSState, CP0_YQMask));
7560 register_name = "YQMask";
7561 break;
7562 case CP0_REG01__VPESCHEDULE:
7563 CP0_CHECK(ctx->insn_flags & ASE_MT);
7564 tcg_gen_ld_tl(arg, cpu_env,
7565 offsetof(CPUMIPSState, CP0_VPESchedule));
7566 register_name = "VPESchedule";
7567 break;
7568 case CP0_REG01__VPESCHEFBACK:
7569 CP0_CHECK(ctx->insn_flags & ASE_MT);
7570 tcg_gen_ld_tl(arg, cpu_env,
7571 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7572 register_name = "VPEScheFBack";
7573 break;
7574 case CP0_REG01__VPEOPT:
7575 CP0_CHECK(ctx->insn_flags & ASE_MT);
7576 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7577 register_name = "VPEOpt";
7578 break;
7579 default:
7580 goto cp0_unimplemented;
7582 break;
7583 case CP0_REGISTER_02:
7584 switch (sel) {
7585 case CP0_REG02__ENTRYLO0:
7586 tcg_gen_ld_tl(arg, cpu_env,
7587 offsetof(CPUMIPSState, CP0_EntryLo0));
7588 register_name = "EntryLo0";
7589 break;
7590 case CP0_REG02__TCSTATUS:
7591 CP0_CHECK(ctx->insn_flags & ASE_MT);
7592 gen_helper_mfc0_tcstatus(arg, cpu_env);
7593 register_name = "TCStatus";
7594 break;
7595 case CP0_REG02__TCBIND:
7596 CP0_CHECK(ctx->insn_flags & ASE_MT);
7597 gen_helper_mfc0_tcbind(arg, cpu_env);
7598 register_name = "TCBind";
7599 break;
7600 case CP0_REG02__TCRESTART:
7601 CP0_CHECK(ctx->insn_flags & ASE_MT);
7602 gen_helper_dmfc0_tcrestart(arg, cpu_env);
7603 register_name = "TCRestart";
7604 break;
7605 case CP0_REG02__TCHALT:
7606 CP0_CHECK(ctx->insn_flags & ASE_MT);
7607 gen_helper_dmfc0_tchalt(arg, cpu_env);
7608 register_name = "TCHalt";
7609 break;
7610 case CP0_REG02__TCCONTEXT:
7611 CP0_CHECK(ctx->insn_flags & ASE_MT);
7612 gen_helper_dmfc0_tccontext(arg, cpu_env);
7613 register_name = "TCContext";
7614 break;
7615 case CP0_REG02__TCSCHEDULE:
7616 CP0_CHECK(ctx->insn_flags & ASE_MT);
7617 gen_helper_dmfc0_tcschedule(arg, cpu_env);
7618 register_name = "TCSchedule";
7619 break;
7620 case CP0_REG02__TCSCHEFBACK:
7621 CP0_CHECK(ctx->insn_flags & ASE_MT);
7622 gen_helper_dmfc0_tcschefback(arg, cpu_env);
7623 register_name = "TCScheFBack";
7624 break;
7625 default:
7626 goto cp0_unimplemented;
7628 break;
7629 case CP0_REGISTER_03:
7630 switch (sel) {
7631 case CP0_REG03__ENTRYLO1:
7632 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
7633 register_name = "EntryLo1";
7634 break;
7635 case CP0_REG03__GLOBALNUM:
7636 CP0_CHECK(ctx->vp);
7637 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7638 register_name = "GlobalNumber";
7639 break;
7640 default:
7641 goto cp0_unimplemented;
7643 break;
7644 case CP0_REGISTER_04:
7645 switch (sel) {
7646 case CP0_REG04__CONTEXT:
7647 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7648 register_name = "Context";
7649 break;
7650 case CP0_REG04__CONTEXTCONFIG:
7651 /* SmartMIPS ASE */
7652 /* gen_helper_dmfc0_contextconfig(arg); */
7653 register_name = "ContextConfig";
7654 goto cp0_unimplemented;
7655 case CP0_REG04__USERLOCAL:
7656 CP0_CHECK(ctx->ulri);
7657 tcg_gen_ld_tl(arg, cpu_env,
7658 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7659 register_name = "UserLocal";
7660 break;
7661 case CP0_REG04__MMID:
7662 CP0_CHECK(ctx->mi);
7663 gen_helper_mtc0_memorymapid(cpu_env, arg);
7664 register_name = "MMID";
7665 break;
7666 default:
7667 goto cp0_unimplemented;
7669 break;
7670 case CP0_REGISTER_05:
7671 switch (sel) {
7672 case CP0_REG05__PAGEMASK:
7673 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7674 register_name = "PageMask";
7675 break;
7676 case CP0_REG05__PAGEGRAIN:
7677 check_insn(ctx, ISA_MIPS_R2);
7678 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7679 register_name = "PageGrain";
7680 break;
7681 case CP0_REG05__SEGCTL0:
7682 CP0_CHECK(ctx->sc);
7683 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7684 register_name = "SegCtl0";
7685 break;
7686 case CP0_REG05__SEGCTL1:
7687 CP0_CHECK(ctx->sc);
7688 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7689 register_name = "SegCtl1";
7690 break;
7691 case CP0_REG05__SEGCTL2:
7692 CP0_CHECK(ctx->sc);
7693 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7694 register_name = "SegCtl2";
7695 break;
7696 case CP0_REG05__PWBASE:
7697 check_pw(ctx);
7698 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
7699 register_name = "PWBase";
7700 break;
7701 case CP0_REG05__PWFIELD:
7702 check_pw(ctx);
7703 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
7704 register_name = "PWField";
7705 break;
7706 case CP0_REG05__PWSIZE:
7707 check_pw(ctx);
7708 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
7709 register_name = "PWSize";
7710 break;
7711 default:
7712 goto cp0_unimplemented;
7714 break;
7715 case CP0_REGISTER_06:
7716 switch (sel) {
7717 case CP0_REG06__WIRED:
7718 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7719 register_name = "Wired";
7720 break;
7721 case CP0_REG06__SRSCONF0:
7722 check_insn(ctx, ISA_MIPS_R2);
7723 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7724 register_name = "SRSConf0";
7725 break;
7726 case CP0_REG06__SRSCONF1:
7727 check_insn(ctx, ISA_MIPS_R2);
7728 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7729 register_name = "SRSConf1";
7730 break;
7731 case CP0_REG06__SRSCONF2:
7732 check_insn(ctx, ISA_MIPS_R2);
7733 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7734 register_name = "SRSConf2";
7735 break;
7736 case CP0_REG06__SRSCONF3:
7737 check_insn(ctx, ISA_MIPS_R2);
7738 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7739 register_name = "SRSConf3";
7740 break;
7741 case CP0_REG06__SRSCONF4:
7742 check_insn(ctx, ISA_MIPS_R2);
7743 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7744 register_name = "SRSConf4";
7745 break;
7746 case CP0_REG06__PWCTL:
7747 check_pw(ctx);
7748 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7749 register_name = "PWCtl";
7750 break;
7751 default:
7752 goto cp0_unimplemented;
7754 break;
7755 case CP0_REGISTER_07:
7756 switch (sel) {
7757 case CP0_REG07__HWRENA:
7758 check_insn(ctx, ISA_MIPS_R2);
7759 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7760 register_name = "HWREna";
7761 break;
7762 default:
7763 goto cp0_unimplemented;
7765 break;
7766 case CP0_REGISTER_08:
7767 switch (sel) {
7768 case CP0_REG08__BADVADDR:
7769 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7770 register_name = "BadVAddr";
7771 break;
7772 case CP0_REG08__BADINSTR:
7773 CP0_CHECK(ctx->bi);
7774 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7775 register_name = "BadInstr";
7776 break;
7777 case CP0_REG08__BADINSTRP:
7778 CP0_CHECK(ctx->bp);
7779 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7780 register_name = "BadInstrP";
7781 break;
7782 case CP0_REG08__BADINSTRX:
7783 CP0_CHECK(ctx->bi);
7784 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7785 tcg_gen_andi_tl(arg, arg, ~0xffff);
7786 register_name = "BadInstrX";
7787 break;
7788 default:
7789 goto cp0_unimplemented;
7791 break;
7792 case CP0_REGISTER_09:
7793 switch (sel) {
7794 case CP0_REG09__COUNT:
7795 /* Mark as an IO operation because we read the time. */
7796 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7797 gen_io_start();
7799 gen_helper_mfc0_count(arg, cpu_env);
7801 * Break the TB to be able to take timer interrupts immediately
7802 * after reading count. DISAS_STOP isn't sufficient, we need to
7803 * ensure we break completely out of translated code.
7805 gen_save_pc(ctx->base.pc_next + 4);
7806 ctx->base.is_jmp = DISAS_EXIT;
7807 register_name = "Count";
7808 break;
7809 case CP0_REG09__SAARI:
7810 CP0_CHECK(ctx->saar);
7811 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7812 register_name = "SAARI";
7813 break;
7814 case CP0_REG09__SAAR:
7815 CP0_CHECK(ctx->saar);
7816 gen_helper_dmfc0_saar(arg, cpu_env);
7817 register_name = "SAAR";
7818 break;
7819 default:
7820 goto cp0_unimplemented;
7822 break;
7823 case CP0_REGISTER_10:
7824 switch (sel) {
7825 case CP0_REG10__ENTRYHI:
7826 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7827 register_name = "EntryHi";
7828 break;
7829 default:
7830 goto cp0_unimplemented;
7832 break;
7833 case CP0_REGISTER_11:
7834 switch (sel) {
7835 case CP0_REG11__COMPARE:
7836 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7837 register_name = "Compare";
7838 break;
7839 /* 6,7 are implementation dependent */
7840 default:
7841 goto cp0_unimplemented;
7843 break;
7844 case CP0_REGISTER_12:
7845 switch (sel) {
7846 case CP0_REG12__STATUS:
7847 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7848 register_name = "Status";
7849 break;
7850 case CP0_REG12__INTCTL:
7851 check_insn(ctx, ISA_MIPS_R2);
7852 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7853 register_name = "IntCtl";
7854 break;
7855 case CP0_REG12__SRSCTL:
7856 check_insn(ctx, ISA_MIPS_R2);
7857 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7858 register_name = "SRSCtl";
7859 break;
7860 case CP0_REG12__SRSMAP:
7861 check_insn(ctx, ISA_MIPS_R2);
7862 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7863 register_name = "SRSMap";
7864 break;
7865 default:
7866 goto cp0_unimplemented;
7868 break;
7869 case CP0_REGISTER_13:
7870 switch (sel) {
7871 case CP0_REG13__CAUSE:
7872 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7873 register_name = "Cause";
7874 break;
7875 default:
7876 goto cp0_unimplemented;
7878 break;
7879 case CP0_REGISTER_14:
7880 switch (sel) {
7881 case CP0_REG14__EPC:
7882 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7883 register_name = "EPC";
7884 break;
7885 default:
7886 goto cp0_unimplemented;
7888 break;
7889 case CP0_REGISTER_15:
7890 switch (sel) {
7891 case CP0_REG15__PRID:
7892 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7893 register_name = "PRid";
7894 break;
7895 case CP0_REG15__EBASE:
7896 check_insn(ctx, ISA_MIPS_R2);
7897 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7898 register_name = "EBase";
7899 break;
7900 case CP0_REG15__CMGCRBASE:
7901 check_insn(ctx, ISA_MIPS_R2);
7902 CP0_CHECK(ctx->cmgcr);
7903 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7904 register_name = "CMGCRBase";
7905 break;
7906 default:
7907 goto cp0_unimplemented;
7909 break;
7910 case CP0_REGISTER_16:
7911 switch (sel) {
7912 case CP0_REG16__CONFIG:
7913 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7914 register_name = "Config";
7915 break;
7916 case CP0_REG16__CONFIG1:
7917 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7918 register_name = "Config1";
7919 break;
7920 case CP0_REG16__CONFIG2:
7921 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7922 register_name = "Config2";
7923 break;
7924 case CP0_REG16__CONFIG3:
7925 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7926 register_name = "Config3";
7927 break;
7928 case CP0_REG16__CONFIG4:
7929 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7930 register_name = "Config4";
7931 break;
7932 case CP0_REG16__CONFIG5:
7933 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7934 register_name = "Config5";
7935 break;
7936 /* 6,7 are implementation dependent */
7937 case CP0_REG16__CONFIG6:
7938 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7939 register_name = "Config6";
7940 break;
7941 case CP0_REG16__CONFIG7:
7942 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7943 register_name = "Config7";
7944 break;
7945 default:
7946 goto cp0_unimplemented;
7948 break;
7949 case CP0_REGISTER_17:
7950 switch (sel) {
7951 case CP0_REG17__LLADDR:
7952 gen_helper_dmfc0_lladdr(arg, cpu_env);
7953 register_name = "LLAddr";
7954 break;
7955 case CP0_REG17__MAAR:
7956 CP0_CHECK(ctx->mrp);
7957 gen_helper_dmfc0_maar(arg, cpu_env);
7958 register_name = "MAAR";
7959 break;
7960 case CP0_REG17__MAARI:
7961 CP0_CHECK(ctx->mrp);
7962 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7963 register_name = "MAARI";
7964 break;
7965 default:
7966 goto cp0_unimplemented;
7968 break;
7969 case CP0_REGISTER_18:
7970 switch (sel) {
7971 case CP0_REG18__WATCHLO0:
7972 case CP0_REG18__WATCHLO1:
7973 case CP0_REG18__WATCHLO2:
7974 case CP0_REG18__WATCHLO3:
7975 case CP0_REG18__WATCHLO4:
7976 case CP0_REG18__WATCHLO5:
7977 case CP0_REG18__WATCHLO6:
7978 case CP0_REG18__WATCHLO7:
7979 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7980 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
7981 register_name = "WatchLo";
7982 break;
7983 default:
7984 goto cp0_unimplemented;
7986 break;
7987 case CP0_REGISTER_19:
7988 switch (sel) {
7989 case CP0_REG19__WATCHHI0:
7990 case CP0_REG19__WATCHHI1:
7991 case CP0_REG19__WATCHHI2:
7992 case CP0_REG19__WATCHHI3:
7993 case CP0_REG19__WATCHHI4:
7994 case CP0_REG19__WATCHHI5:
7995 case CP0_REG19__WATCHHI6:
7996 case CP0_REG19__WATCHHI7:
7997 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7998 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
7999 register_name = "WatchHi";
8000 break;
8001 default:
8002 goto cp0_unimplemented;
8004 break;
8005 case CP0_REGISTER_20:
8006 switch (sel) {
8007 case CP0_REG20__XCONTEXT:
8008 check_insn(ctx, ISA_MIPS3);
8009 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8010 register_name = "XContext";
8011 break;
8012 default:
8013 goto cp0_unimplemented;
8015 break;
8016 case CP0_REGISTER_21:
8017 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8018 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8019 switch (sel) {
8020 case 0:
8021 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8022 register_name = "Framemask";
8023 break;
8024 default:
8025 goto cp0_unimplemented;
8027 break;
8028 case CP0_REGISTER_22:
8029 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8030 register_name = "'Diagnostic"; /* implementation dependent */
8031 break;
8032 case CP0_REGISTER_23:
8033 switch (sel) {
8034 case CP0_REG23__DEBUG:
8035 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8036 register_name = "Debug";
8037 break;
8038 case CP0_REG23__TRACECONTROL:
8039 /* PDtrace support */
8040 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
8041 register_name = "TraceControl";
8042 goto cp0_unimplemented;
8043 case CP0_REG23__TRACECONTROL2:
8044 /* PDtrace support */
8045 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
8046 register_name = "TraceControl2";
8047 goto cp0_unimplemented;
8048 case CP0_REG23__USERTRACEDATA1:
8049 /* PDtrace support */
8050 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
8051 register_name = "UserTraceData1";
8052 goto cp0_unimplemented;
8053 case CP0_REG23__TRACEIBPC:
8054 /* PDtrace support */
8055 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
8056 register_name = "TraceIBPC";
8057 goto cp0_unimplemented;
8058 case CP0_REG23__TRACEDBPC:
8059 /* PDtrace support */
8060 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
8061 register_name = "TraceDBPC";
8062 goto cp0_unimplemented;
8063 default:
8064 goto cp0_unimplemented;
8066 break;
8067 case CP0_REGISTER_24:
8068 switch (sel) {
8069 case CP0_REG24__DEPC:
8070 /* EJTAG support */
8071 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8072 register_name = "DEPC";
8073 break;
8074 default:
8075 goto cp0_unimplemented;
8077 break;
8078 case CP0_REGISTER_25:
8079 switch (sel) {
8080 case CP0_REG25__PERFCTL0:
8081 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8082 register_name = "Performance0";
8083 break;
8084 case CP0_REG25__PERFCNT0:
8085 /* gen_helper_dmfc0_performance1(arg); */
8086 register_name = "Performance1";
8087 goto cp0_unimplemented;
8088 case CP0_REG25__PERFCTL1:
8089 /* gen_helper_dmfc0_performance2(arg); */
8090 register_name = "Performance2";
8091 goto cp0_unimplemented;
8092 case CP0_REG25__PERFCNT1:
8093 /* gen_helper_dmfc0_performance3(arg); */
8094 register_name = "Performance3";
8095 goto cp0_unimplemented;
8096 case CP0_REG25__PERFCTL2:
8097 /* gen_helper_dmfc0_performance4(arg); */
8098 register_name = "Performance4";
8099 goto cp0_unimplemented;
8100 case CP0_REG25__PERFCNT2:
8101 /* gen_helper_dmfc0_performance5(arg); */
8102 register_name = "Performance5";
8103 goto cp0_unimplemented;
8104 case CP0_REG25__PERFCTL3:
8105 /* gen_helper_dmfc0_performance6(arg); */
8106 register_name = "Performance6";
8107 goto cp0_unimplemented;
8108 case CP0_REG25__PERFCNT3:
8109 /* gen_helper_dmfc0_performance7(arg); */
8110 register_name = "Performance7";
8111 goto cp0_unimplemented;
8112 default:
8113 goto cp0_unimplemented;
8115 break;
8116 case CP0_REGISTER_26:
8117 switch (sel) {
8118 case CP0_REG26__ERRCTL:
8119 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8120 register_name = "ErrCtl";
8121 break;
8122 default:
8123 goto cp0_unimplemented;
8125 break;
8126 case CP0_REGISTER_27:
8127 switch (sel) {
8128 /* ignored */
8129 case CP0_REG27__CACHERR:
8130 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8131 register_name = "CacheErr";
8132 break;
8133 default:
8134 goto cp0_unimplemented;
8136 break;
8137 case CP0_REGISTER_28:
8138 switch (sel) {
8139 case CP0_REG28__TAGLO:
8140 case CP0_REG28__TAGLO1:
8141 case CP0_REG28__TAGLO2:
8142 case CP0_REG28__TAGLO3:
8143 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8144 register_name = "TagLo";
8145 break;
8146 case CP0_REG28__DATALO:
8147 case CP0_REG28__DATALO1:
8148 case CP0_REG28__DATALO2:
8149 case CP0_REG28__DATALO3:
8150 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8151 register_name = "DataLo";
8152 break;
8153 default:
8154 goto cp0_unimplemented;
8156 break;
8157 case CP0_REGISTER_29:
8158 switch (sel) {
8159 case CP0_REG29__TAGHI:
8160 case CP0_REG29__TAGHI1:
8161 case CP0_REG29__TAGHI2:
8162 case CP0_REG29__TAGHI3:
8163 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8164 register_name = "TagHi";
8165 break;
8166 case CP0_REG29__DATAHI:
8167 case CP0_REG29__DATAHI1:
8168 case CP0_REG29__DATAHI2:
8169 case CP0_REG29__DATAHI3:
8170 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8171 register_name = "DataHi";
8172 break;
8173 default:
8174 goto cp0_unimplemented;
8176 break;
8177 case CP0_REGISTER_30:
8178 switch (sel) {
8179 case CP0_REG30__ERROREPC:
8180 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8181 register_name = "ErrorEPC";
8182 break;
8183 default:
8184 goto cp0_unimplemented;
8186 break;
8187 case CP0_REGISTER_31:
8188 switch (sel) {
8189 case CP0_REG31__DESAVE:
8190 /* EJTAG support */
8191 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8192 register_name = "DESAVE";
8193 break;
8194 case CP0_REG31__KSCRATCH1:
8195 case CP0_REG31__KSCRATCH2:
8196 case CP0_REG31__KSCRATCH3:
8197 case CP0_REG31__KSCRATCH4:
8198 case CP0_REG31__KSCRATCH5:
8199 case CP0_REG31__KSCRATCH6:
8200 CP0_CHECK(ctx->kscrexist & (1 << sel));
8201 tcg_gen_ld_tl(arg, cpu_env,
8202 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8203 register_name = "KScratch";
8204 break;
8205 default:
8206 goto cp0_unimplemented;
8208 break;
8209 default:
8210 goto cp0_unimplemented;
8212 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
8213 return;
8215 cp0_unimplemented:
8216 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
8217 register_name, reg, sel);
8218 gen_mfc0_unimplemented(ctx, arg);
8221 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8223 const char *register_name = "invalid";
8225 if (sel != 0) {
8226 check_insn(ctx, ISA_MIPS_R1);
8229 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8230 gen_io_start();
8233 switch (reg) {
8234 case CP0_REGISTER_00:
8235 switch (sel) {
8236 case CP0_REG00__INDEX:
8237 gen_helper_mtc0_index(cpu_env, arg);
8238 register_name = "Index";
8239 break;
8240 case CP0_REG00__MVPCONTROL:
8241 CP0_CHECK(ctx->insn_flags & ASE_MT);
8242 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8243 register_name = "MVPControl";
8244 break;
8245 case CP0_REG00__MVPCONF0:
8246 CP0_CHECK(ctx->insn_flags & ASE_MT);
8247 /* ignored */
8248 register_name = "MVPConf0";
8249 break;
8250 case CP0_REG00__MVPCONF1:
8251 CP0_CHECK(ctx->insn_flags & ASE_MT);
8252 /* ignored */
8253 register_name = "MVPConf1";
8254 break;
8255 case CP0_REG00__VPCONTROL:
8256 CP0_CHECK(ctx->vp);
8257 /* ignored */
8258 register_name = "VPControl";
8259 break;
8260 default:
8261 goto cp0_unimplemented;
8263 break;
8264 case CP0_REGISTER_01:
8265 switch (sel) {
8266 case CP0_REG01__RANDOM:
8267 /* ignored */
8268 register_name = "Random";
8269 break;
8270 case CP0_REG01__VPECONTROL:
8271 CP0_CHECK(ctx->insn_flags & ASE_MT);
8272 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8273 register_name = "VPEControl";
8274 break;
8275 case CP0_REG01__VPECONF0:
8276 CP0_CHECK(ctx->insn_flags & ASE_MT);
8277 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8278 register_name = "VPEConf0";
8279 break;
8280 case CP0_REG01__VPECONF1:
8281 CP0_CHECK(ctx->insn_flags & ASE_MT);
8282 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8283 register_name = "VPEConf1";
8284 break;
8285 case CP0_REG01__YQMASK:
8286 CP0_CHECK(ctx->insn_flags & ASE_MT);
8287 gen_helper_mtc0_yqmask(cpu_env, arg);
8288 register_name = "YQMask";
8289 break;
8290 case CP0_REG01__VPESCHEDULE:
8291 CP0_CHECK(ctx->insn_flags & ASE_MT);
8292 tcg_gen_st_tl(arg, cpu_env,
8293 offsetof(CPUMIPSState, CP0_VPESchedule));
8294 register_name = "VPESchedule";
8295 break;
8296 case CP0_REG01__VPESCHEFBACK:
8297 CP0_CHECK(ctx->insn_flags & ASE_MT);
8298 tcg_gen_st_tl(arg, cpu_env,
8299 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8300 register_name = "VPEScheFBack";
8301 break;
8302 case CP0_REG01__VPEOPT:
8303 CP0_CHECK(ctx->insn_flags & ASE_MT);
8304 gen_helper_mtc0_vpeopt(cpu_env, arg);
8305 register_name = "VPEOpt";
8306 break;
8307 default:
8308 goto cp0_unimplemented;
8310 break;
8311 case CP0_REGISTER_02:
8312 switch (sel) {
8313 case CP0_REG02__ENTRYLO0:
8314 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8315 register_name = "EntryLo0";
8316 break;
8317 case CP0_REG02__TCSTATUS:
8318 CP0_CHECK(ctx->insn_flags & ASE_MT);
8319 gen_helper_mtc0_tcstatus(cpu_env, arg);
8320 register_name = "TCStatus";
8321 break;
8322 case CP0_REG02__TCBIND:
8323 CP0_CHECK(ctx->insn_flags & ASE_MT);
8324 gen_helper_mtc0_tcbind(cpu_env, arg);
8325 register_name = "TCBind";
8326 break;
8327 case CP0_REG02__TCRESTART:
8328 CP0_CHECK(ctx->insn_flags & ASE_MT);
8329 gen_helper_mtc0_tcrestart(cpu_env, arg);
8330 register_name = "TCRestart";
8331 break;
8332 case CP0_REG02__TCHALT:
8333 CP0_CHECK(ctx->insn_flags & ASE_MT);
8334 gen_helper_mtc0_tchalt(cpu_env, arg);
8335 register_name = "TCHalt";
8336 break;
8337 case CP0_REG02__TCCONTEXT:
8338 CP0_CHECK(ctx->insn_flags & ASE_MT);
8339 gen_helper_mtc0_tccontext(cpu_env, arg);
8340 register_name = "TCContext";
8341 break;
8342 case CP0_REG02__TCSCHEDULE:
8343 CP0_CHECK(ctx->insn_flags & ASE_MT);
8344 gen_helper_mtc0_tcschedule(cpu_env, arg);
8345 register_name = "TCSchedule";
8346 break;
8347 case CP0_REG02__TCSCHEFBACK:
8348 CP0_CHECK(ctx->insn_flags & ASE_MT);
8349 gen_helper_mtc0_tcschefback(cpu_env, arg);
8350 register_name = "TCScheFBack";
8351 break;
8352 default:
8353 goto cp0_unimplemented;
8355 break;
8356 case CP0_REGISTER_03:
8357 switch (sel) {
8358 case CP0_REG03__ENTRYLO1:
8359 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8360 register_name = "EntryLo1";
8361 break;
8362 case CP0_REG03__GLOBALNUM:
8363 CP0_CHECK(ctx->vp);
8364 /* ignored */
8365 register_name = "GlobalNumber";
8366 break;
8367 default:
8368 goto cp0_unimplemented;
8370 break;
8371 case CP0_REGISTER_04:
8372 switch (sel) {
8373 case CP0_REG04__CONTEXT:
8374 gen_helper_mtc0_context(cpu_env, arg);
8375 register_name = "Context";
8376 break;
8377 case CP0_REG04__CONTEXTCONFIG:
8378 /* SmartMIPS ASE */
8379 /* gen_helper_dmtc0_contextconfig(arg); */
8380 register_name = "ContextConfig";
8381 goto cp0_unimplemented;
8382 case CP0_REG04__USERLOCAL:
8383 CP0_CHECK(ctx->ulri);
8384 tcg_gen_st_tl(arg, cpu_env,
8385 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8386 register_name = "UserLocal";
8387 break;
8388 case CP0_REG04__MMID:
8389 CP0_CHECK(ctx->mi);
8390 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8391 register_name = "MMID";
8392 break;
8393 default:
8394 goto cp0_unimplemented;
8396 break;
8397 case CP0_REGISTER_05:
8398 switch (sel) {
8399 case CP0_REG05__PAGEMASK:
8400 gen_helper_mtc0_pagemask(cpu_env, arg);
8401 register_name = "PageMask";
8402 break;
8403 case CP0_REG05__PAGEGRAIN:
8404 check_insn(ctx, ISA_MIPS_R2);
8405 gen_helper_mtc0_pagegrain(cpu_env, arg);
8406 register_name = "PageGrain";
8407 break;
8408 case CP0_REG05__SEGCTL0:
8409 CP0_CHECK(ctx->sc);
8410 gen_helper_mtc0_segctl0(cpu_env, arg);
8411 register_name = "SegCtl0";
8412 break;
8413 case CP0_REG05__SEGCTL1:
8414 CP0_CHECK(ctx->sc);
8415 gen_helper_mtc0_segctl1(cpu_env, arg);
8416 register_name = "SegCtl1";
8417 break;
8418 case CP0_REG05__SEGCTL2:
8419 CP0_CHECK(ctx->sc);
8420 gen_helper_mtc0_segctl2(cpu_env, arg);
8421 register_name = "SegCtl2";
8422 break;
8423 case CP0_REG05__PWBASE:
8424 check_pw(ctx);
8425 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8426 register_name = "PWBase";
8427 break;
8428 case CP0_REG05__PWFIELD:
8429 check_pw(ctx);
8430 gen_helper_mtc0_pwfield(cpu_env, arg);
8431 register_name = "PWField";
8432 break;
8433 case CP0_REG05__PWSIZE:
8434 check_pw(ctx);
8435 gen_helper_mtc0_pwsize(cpu_env, arg);
8436 register_name = "PWSize";
8437 break;
8438 default:
8439 goto cp0_unimplemented;
8441 break;
8442 case CP0_REGISTER_06:
8443 switch (sel) {
8444 case CP0_REG06__WIRED:
8445 gen_helper_mtc0_wired(cpu_env, arg);
8446 register_name = "Wired";
8447 break;
8448 case CP0_REG06__SRSCONF0:
8449 check_insn(ctx, ISA_MIPS_R2);
8450 gen_helper_mtc0_srsconf0(cpu_env, arg);
8451 register_name = "SRSConf0";
8452 break;
8453 case CP0_REG06__SRSCONF1:
8454 check_insn(ctx, ISA_MIPS_R2);
8455 gen_helper_mtc0_srsconf1(cpu_env, arg);
8456 register_name = "SRSConf1";
8457 break;
8458 case CP0_REG06__SRSCONF2:
8459 check_insn(ctx, ISA_MIPS_R2);
8460 gen_helper_mtc0_srsconf2(cpu_env, arg);
8461 register_name = "SRSConf2";
8462 break;
8463 case CP0_REG06__SRSCONF3:
8464 check_insn(ctx, ISA_MIPS_R2);
8465 gen_helper_mtc0_srsconf3(cpu_env, arg);
8466 register_name = "SRSConf3";
8467 break;
8468 case CP0_REG06__SRSCONF4:
8469 check_insn(ctx, ISA_MIPS_R2);
8470 gen_helper_mtc0_srsconf4(cpu_env, arg);
8471 register_name = "SRSConf4";
8472 break;
8473 case CP0_REG06__PWCTL:
8474 check_pw(ctx);
8475 gen_helper_mtc0_pwctl(cpu_env, arg);
8476 register_name = "PWCtl";
8477 break;
8478 default:
8479 goto cp0_unimplemented;
8481 break;
8482 case CP0_REGISTER_07:
8483 switch (sel) {
8484 case CP0_REG07__HWRENA:
8485 check_insn(ctx, ISA_MIPS_R2);
8486 gen_helper_mtc0_hwrena(cpu_env, arg);
8487 ctx->base.is_jmp = DISAS_STOP;
8488 register_name = "HWREna";
8489 break;
8490 default:
8491 goto cp0_unimplemented;
8493 break;
8494 case CP0_REGISTER_08:
8495 switch (sel) {
8496 case CP0_REG08__BADVADDR:
8497 /* ignored */
8498 register_name = "BadVAddr";
8499 break;
8500 case CP0_REG08__BADINSTR:
8501 /* ignored */
8502 register_name = "BadInstr";
8503 break;
8504 case CP0_REG08__BADINSTRP:
8505 /* ignored */
8506 register_name = "BadInstrP";
8507 break;
8508 case CP0_REG08__BADINSTRX:
8509 /* ignored */
8510 register_name = "BadInstrX";
8511 break;
8512 default:
8513 goto cp0_unimplemented;
8515 break;
8516 case CP0_REGISTER_09:
8517 switch (sel) {
8518 case CP0_REG09__COUNT:
8519 gen_helper_mtc0_count(cpu_env, arg);
8520 register_name = "Count";
8521 break;
8522 case CP0_REG09__SAARI:
8523 CP0_CHECK(ctx->saar);
8524 gen_helper_mtc0_saari(cpu_env, arg);
8525 register_name = "SAARI";
8526 break;
8527 case CP0_REG09__SAAR:
8528 CP0_CHECK(ctx->saar);
8529 gen_helper_mtc0_saar(cpu_env, arg);
8530 register_name = "SAAR";
8531 break;
8532 default:
8533 goto cp0_unimplemented;
8535 /* Stop translation as we may have switched the execution mode */
8536 ctx->base.is_jmp = DISAS_STOP;
8537 break;
8538 case CP0_REGISTER_10:
8539 switch (sel) {
8540 case CP0_REG10__ENTRYHI:
8541 gen_helper_mtc0_entryhi(cpu_env, arg);
8542 register_name = "EntryHi";
8543 break;
8544 default:
8545 goto cp0_unimplemented;
8547 break;
8548 case CP0_REGISTER_11:
8549 switch (sel) {
8550 case CP0_REG11__COMPARE:
8551 gen_helper_mtc0_compare(cpu_env, arg);
8552 register_name = "Compare";
8553 break;
8554 /* 6,7 are implementation dependent */
8555 default:
8556 goto cp0_unimplemented;
8558 /* Stop translation as we may have switched the execution mode */
8559 ctx->base.is_jmp = DISAS_STOP;
8560 break;
8561 case CP0_REGISTER_12:
8562 switch (sel) {
8563 case CP0_REG12__STATUS:
8564 save_cpu_state(ctx, 1);
8565 gen_helper_mtc0_status(cpu_env, arg);
8566 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8567 gen_save_pc(ctx->base.pc_next + 4);
8568 ctx->base.is_jmp = DISAS_EXIT;
8569 register_name = "Status";
8570 break;
8571 case CP0_REG12__INTCTL:
8572 check_insn(ctx, ISA_MIPS_R2);
8573 gen_helper_mtc0_intctl(cpu_env, arg);
8574 /* Stop translation as we may have switched the execution mode */
8575 ctx->base.is_jmp = DISAS_STOP;
8576 register_name = "IntCtl";
8577 break;
8578 case CP0_REG12__SRSCTL:
8579 check_insn(ctx, ISA_MIPS_R2);
8580 gen_helper_mtc0_srsctl(cpu_env, arg);
8581 /* Stop translation as we may have switched the execution mode */
8582 ctx->base.is_jmp = DISAS_STOP;
8583 register_name = "SRSCtl";
8584 break;
8585 case CP0_REG12__SRSMAP:
8586 check_insn(ctx, ISA_MIPS_R2);
8587 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8588 /* Stop translation as we may have switched the execution mode */
8589 ctx->base.is_jmp = DISAS_STOP;
8590 register_name = "SRSMap";
8591 break;
8592 default:
8593 goto cp0_unimplemented;
8595 break;
8596 case CP0_REGISTER_13:
8597 switch (sel) {
8598 case CP0_REG13__CAUSE:
8599 save_cpu_state(ctx, 1);
8600 gen_helper_mtc0_cause(cpu_env, arg);
8602 * Stop translation as we may have triggered an interrupt.
8603 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8604 * translated code to check for pending interrupts.
8606 gen_save_pc(ctx->base.pc_next + 4);
8607 ctx->base.is_jmp = DISAS_EXIT;
8608 register_name = "Cause";
8609 break;
8610 default:
8611 goto cp0_unimplemented;
8613 break;
8614 case CP0_REGISTER_14:
8615 switch (sel) {
8616 case CP0_REG14__EPC:
8617 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8618 register_name = "EPC";
8619 break;
8620 default:
8621 goto cp0_unimplemented;
8623 break;
8624 case CP0_REGISTER_15:
8625 switch (sel) {
8626 case CP0_REG15__PRID:
8627 /* ignored */
8628 register_name = "PRid";
8629 break;
8630 case CP0_REG15__EBASE:
8631 check_insn(ctx, ISA_MIPS_R2);
8632 gen_helper_mtc0_ebase(cpu_env, arg);
8633 register_name = "EBase";
8634 break;
8635 default:
8636 goto cp0_unimplemented;
8638 break;
8639 case CP0_REGISTER_16:
8640 switch (sel) {
8641 case CP0_REG16__CONFIG:
8642 gen_helper_mtc0_config0(cpu_env, arg);
8643 register_name = "Config";
8644 /* Stop translation as we may have switched the execution mode */
8645 ctx->base.is_jmp = DISAS_STOP;
8646 break;
8647 case CP0_REG16__CONFIG1:
8648 /* ignored, read only */
8649 register_name = "Config1";
8650 break;
8651 case CP0_REG16__CONFIG2:
8652 gen_helper_mtc0_config2(cpu_env, arg);
8653 register_name = "Config2";
8654 /* Stop translation as we may have switched the execution mode */
8655 ctx->base.is_jmp = DISAS_STOP;
8656 break;
8657 case CP0_REG16__CONFIG3:
8658 gen_helper_mtc0_config3(cpu_env, arg);
8659 register_name = "Config3";
8660 /* Stop translation as we may have switched the execution mode */
8661 ctx->base.is_jmp = DISAS_STOP;
8662 break;
8663 case CP0_REG16__CONFIG4:
8664 /* currently ignored */
8665 register_name = "Config4";
8666 break;
8667 case CP0_REG16__CONFIG5:
8668 gen_helper_mtc0_config5(cpu_env, arg);
8669 register_name = "Config5";
8670 /* Stop translation as we may have switched the execution mode */
8671 ctx->base.is_jmp = DISAS_STOP;
8672 break;
8673 /* 6,7 are implementation dependent */
8674 default:
8675 register_name = "Invalid config selector";
8676 goto cp0_unimplemented;
8678 break;
8679 case CP0_REGISTER_17:
8680 switch (sel) {
8681 case CP0_REG17__LLADDR:
8682 gen_helper_mtc0_lladdr(cpu_env, arg);
8683 register_name = "LLAddr";
8684 break;
8685 case CP0_REG17__MAAR:
8686 CP0_CHECK(ctx->mrp);
8687 gen_helper_mtc0_maar(cpu_env, arg);
8688 register_name = "MAAR";
8689 break;
8690 case CP0_REG17__MAARI:
8691 CP0_CHECK(ctx->mrp);
8692 gen_helper_mtc0_maari(cpu_env, arg);
8693 register_name = "MAARI";
8694 break;
8695 default:
8696 goto cp0_unimplemented;
8698 break;
8699 case CP0_REGISTER_18:
8700 switch (sel) {
8701 case CP0_REG18__WATCHLO0:
8702 case CP0_REG18__WATCHLO1:
8703 case CP0_REG18__WATCHLO2:
8704 case CP0_REG18__WATCHLO3:
8705 case CP0_REG18__WATCHLO4:
8706 case CP0_REG18__WATCHLO5:
8707 case CP0_REG18__WATCHLO6:
8708 case CP0_REG18__WATCHLO7:
8709 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8710 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8711 register_name = "WatchLo";
8712 break;
8713 default:
8714 goto cp0_unimplemented;
8716 break;
8717 case CP0_REGISTER_19:
8718 switch (sel) {
8719 case CP0_REG19__WATCHHI0:
8720 case CP0_REG19__WATCHHI1:
8721 case CP0_REG19__WATCHHI2:
8722 case CP0_REG19__WATCHHI3:
8723 case CP0_REG19__WATCHHI4:
8724 case CP0_REG19__WATCHHI5:
8725 case CP0_REG19__WATCHHI6:
8726 case CP0_REG19__WATCHHI7:
8727 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8728 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8729 register_name = "WatchHi";
8730 break;
8731 default:
8732 goto cp0_unimplemented;
8734 break;
8735 case CP0_REGISTER_20:
8736 switch (sel) {
8737 case CP0_REG20__XCONTEXT:
8738 check_insn(ctx, ISA_MIPS3);
8739 gen_helper_mtc0_xcontext(cpu_env, arg);
8740 register_name = "XContext";
8741 break;
8742 default:
8743 goto cp0_unimplemented;
8745 break;
8746 case CP0_REGISTER_21:
8747 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8748 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8749 switch (sel) {
8750 case 0:
8751 gen_helper_mtc0_framemask(cpu_env, arg);
8752 register_name = "Framemask";
8753 break;
8754 default:
8755 goto cp0_unimplemented;
8757 break;
8758 case CP0_REGISTER_22:
8759 /* ignored */
8760 register_name = "Diagnostic"; /* implementation dependent */
8761 break;
8762 case CP0_REGISTER_23:
8763 switch (sel) {
8764 case CP0_REG23__DEBUG:
8765 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8766 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8767 gen_save_pc(ctx->base.pc_next + 4);
8768 ctx->base.is_jmp = DISAS_EXIT;
8769 register_name = "Debug";
8770 break;
8771 case CP0_REG23__TRACECONTROL:
8772 /* PDtrace support */
8773 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8774 /* Stop translation as we may have switched the execution mode */
8775 ctx->base.is_jmp = DISAS_STOP;
8776 register_name = "TraceControl";
8777 goto cp0_unimplemented;
8778 case CP0_REG23__TRACECONTROL2:
8779 /* PDtrace support */
8780 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8781 /* Stop translation as we may have switched the execution mode */
8782 ctx->base.is_jmp = DISAS_STOP;
8783 register_name = "TraceControl2";
8784 goto cp0_unimplemented;
8785 case CP0_REG23__USERTRACEDATA1:
8786 /* PDtrace support */
8787 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8788 /* Stop translation as we may have switched the execution mode */
8789 ctx->base.is_jmp = DISAS_STOP;
8790 register_name = "UserTraceData1";
8791 goto cp0_unimplemented;
8792 case CP0_REG23__TRACEIBPC:
8793 /* PDtrace support */
8794 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8795 /* Stop translation as we may have switched the execution mode */
8796 ctx->base.is_jmp = DISAS_STOP;
8797 register_name = "TraceIBPC";
8798 goto cp0_unimplemented;
8799 case CP0_REG23__TRACEDBPC:
8800 /* PDtrace support */
8801 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8802 /* Stop translation as we may have switched the execution mode */
8803 ctx->base.is_jmp = DISAS_STOP;
8804 register_name = "TraceDBPC";
8805 goto cp0_unimplemented;
8806 default:
8807 goto cp0_unimplemented;
8809 break;
8810 case CP0_REGISTER_24:
8811 switch (sel) {
8812 case CP0_REG24__DEPC:
8813 /* EJTAG support */
8814 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8815 register_name = "DEPC";
8816 break;
8817 default:
8818 goto cp0_unimplemented;
8820 break;
8821 case CP0_REGISTER_25:
8822 switch (sel) {
8823 case CP0_REG25__PERFCTL0:
8824 gen_helper_mtc0_performance0(cpu_env, arg);
8825 register_name = "Performance0";
8826 break;
8827 case CP0_REG25__PERFCNT0:
8828 /* gen_helper_mtc0_performance1(cpu_env, arg); */
8829 register_name = "Performance1";
8830 goto cp0_unimplemented;
8831 case CP0_REG25__PERFCTL1:
8832 /* gen_helper_mtc0_performance2(cpu_env, arg); */
8833 register_name = "Performance2";
8834 goto cp0_unimplemented;
8835 case CP0_REG25__PERFCNT1:
8836 /* gen_helper_mtc0_performance3(cpu_env, arg); */
8837 register_name = "Performance3";
8838 goto cp0_unimplemented;
8839 case CP0_REG25__PERFCTL2:
8840 /* gen_helper_mtc0_performance4(cpu_env, arg); */
8841 register_name = "Performance4";
8842 goto cp0_unimplemented;
8843 case CP0_REG25__PERFCNT2:
8844 /* gen_helper_mtc0_performance5(cpu_env, arg); */
8845 register_name = "Performance5";
8846 goto cp0_unimplemented;
8847 case CP0_REG25__PERFCTL3:
8848 /* gen_helper_mtc0_performance6(cpu_env, arg); */
8849 register_name = "Performance6";
8850 goto cp0_unimplemented;
8851 case CP0_REG25__PERFCNT3:
8852 /* gen_helper_mtc0_performance7(cpu_env, arg); */
8853 register_name = "Performance7";
8854 goto cp0_unimplemented;
8855 default:
8856 goto cp0_unimplemented;
8858 break;
8859 case CP0_REGISTER_26:
8860 switch (sel) {
8861 case CP0_REG26__ERRCTL:
8862 gen_helper_mtc0_errctl(cpu_env, arg);
8863 ctx->base.is_jmp = DISAS_STOP;
8864 register_name = "ErrCtl";
8865 break;
8866 default:
8867 goto cp0_unimplemented;
8869 break;
8870 case CP0_REGISTER_27:
8871 switch (sel) {
8872 case CP0_REG27__CACHERR:
8873 /* ignored */
8874 register_name = "CacheErr";
8875 break;
8876 default:
8877 goto cp0_unimplemented;
8879 break;
8880 case CP0_REGISTER_28:
8881 switch (sel) {
8882 case CP0_REG28__TAGLO:
8883 case CP0_REG28__TAGLO1:
8884 case CP0_REG28__TAGLO2:
8885 case CP0_REG28__TAGLO3:
8886 gen_helper_mtc0_taglo(cpu_env, arg);
8887 register_name = "TagLo";
8888 break;
8889 case CP0_REG28__DATALO:
8890 case CP0_REG28__DATALO1:
8891 case CP0_REG28__DATALO2:
8892 case CP0_REG28__DATALO3:
8893 gen_helper_mtc0_datalo(cpu_env, arg);
8894 register_name = "DataLo";
8895 break;
8896 default:
8897 goto cp0_unimplemented;
8899 break;
8900 case CP0_REGISTER_29:
8901 switch (sel) {
8902 case CP0_REG29__TAGHI:
8903 case CP0_REG29__TAGHI1:
8904 case CP0_REG29__TAGHI2:
8905 case CP0_REG29__TAGHI3:
8906 gen_helper_mtc0_taghi(cpu_env, arg);
8907 register_name = "TagHi";
8908 break;
8909 case CP0_REG29__DATAHI:
8910 case CP0_REG29__DATAHI1:
8911 case CP0_REG29__DATAHI2:
8912 case CP0_REG29__DATAHI3:
8913 gen_helper_mtc0_datahi(cpu_env, arg);
8914 register_name = "DataHi";
8915 break;
8916 default:
8917 register_name = "invalid sel";
8918 goto cp0_unimplemented;
8920 break;
8921 case CP0_REGISTER_30:
8922 switch (sel) {
8923 case CP0_REG30__ERROREPC:
8924 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8925 register_name = "ErrorEPC";
8926 break;
8927 default:
8928 goto cp0_unimplemented;
8930 break;
8931 case CP0_REGISTER_31:
8932 switch (sel) {
8933 case CP0_REG31__DESAVE:
8934 /* EJTAG support */
8935 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8936 register_name = "DESAVE";
8937 break;
8938 case CP0_REG31__KSCRATCH1:
8939 case CP0_REG31__KSCRATCH2:
8940 case CP0_REG31__KSCRATCH3:
8941 case CP0_REG31__KSCRATCH4:
8942 case CP0_REG31__KSCRATCH5:
8943 case CP0_REG31__KSCRATCH6:
8944 CP0_CHECK(ctx->kscrexist & (1 << sel));
8945 tcg_gen_st_tl(arg, cpu_env,
8946 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8947 register_name = "KScratch";
8948 break;
8949 default:
8950 goto cp0_unimplemented;
8952 break;
8953 default:
8954 goto cp0_unimplemented;
8956 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
8958 /* For simplicity assume that all writes can cause interrupts. */
8959 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8961 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8962 * translated code to check for pending interrupts.
8964 gen_save_pc(ctx->base.pc_next + 4);
8965 ctx->base.is_jmp = DISAS_EXIT;
8967 return;
8969 cp0_unimplemented:
8970 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
8971 register_name, reg, sel);
8973 #endif /* TARGET_MIPS64 */
8975 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
8976 int u, int sel, int h)
8978 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8979 TCGv t0 = tcg_temp_local_new();
8981 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8982 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8983 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
8984 tcg_gen_movi_tl(t0, -1);
8985 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8986 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
8987 tcg_gen_movi_tl(t0, -1);
8988 } else if (u == 0) {
8989 switch (rt) {
8990 case 1:
8991 switch (sel) {
8992 case 1:
8993 gen_helper_mftc0_vpecontrol(t0, cpu_env);
8994 break;
8995 case 2:
8996 gen_helper_mftc0_vpeconf0(t0, cpu_env);
8997 break;
8998 default:
8999 goto die;
9000 break;
9002 break;
9003 case 2:
9004 switch (sel) {
9005 case 1:
9006 gen_helper_mftc0_tcstatus(t0, cpu_env);
9007 break;
9008 case 2:
9009 gen_helper_mftc0_tcbind(t0, cpu_env);
9010 break;
9011 case 3:
9012 gen_helper_mftc0_tcrestart(t0, cpu_env);
9013 break;
9014 case 4:
9015 gen_helper_mftc0_tchalt(t0, cpu_env);
9016 break;
9017 case 5:
9018 gen_helper_mftc0_tccontext(t0, cpu_env);
9019 break;
9020 case 6:
9021 gen_helper_mftc0_tcschedule(t0, cpu_env);
9022 break;
9023 case 7:
9024 gen_helper_mftc0_tcschefback(t0, cpu_env);
9025 break;
9026 default:
9027 gen_mfc0(ctx, t0, rt, sel);
9028 break;
9030 break;
9031 case 10:
9032 switch (sel) {
9033 case 0:
9034 gen_helper_mftc0_entryhi(t0, cpu_env);
9035 break;
9036 default:
9037 gen_mfc0(ctx, t0, rt, sel);
9038 break;
9040 break;
9041 case 12:
9042 switch (sel) {
9043 case 0:
9044 gen_helper_mftc0_status(t0, cpu_env);
9045 break;
9046 default:
9047 gen_mfc0(ctx, t0, rt, sel);
9048 break;
9050 break;
9051 case 13:
9052 switch (sel) {
9053 case 0:
9054 gen_helper_mftc0_cause(t0, cpu_env);
9055 break;
9056 default:
9057 goto die;
9058 break;
9060 break;
9061 case 14:
9062 switch (sel) {
9063 case 0:
9064 gen_helper_mftc0_epc(t0, cpu_env);
9065 break;
9066 default:
9067 goto die;
9068 break;
9070 break;
9071 case 15:
9072 switch (sel) {
9073 case 1:
9074 gen_helper_mftc0_ebase(t0, cpu_env);
9075 break;
9076 default:
9077 goto die;
9078 break;
9080 break;
9081 case 16:
9082 switch (sel) {
9083 case 0:
9084 case 1:
9085 case 2:
9086 case 3:
9087 case 4:
9088 case 5:
9089 case 6:
9090 case 7:
9091 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9092 break;
9093 default:
9094 goto die;
9095 break;
9097 break;
9098 case 23:
9099 switch (sel) {
9100 case 0:
9101 gen_helper_mftc0_debug(t0, cpu_env);
9102 break;
9103 default:
9104 gen_mfc0(ctx, t0, rt, sel);
9105 break;
9107 break;
9108 default:
9109 gen_mfc0(ctx, t0, rt, sel);
9111 } else {
9112 switch (sel) {
9113 /* GPR registers. */
9114 case 0:
9115 gen_helper_1e0i(mftgpr, t0, rt);
9116 break;
9117 /* Auxiliary CPU registers */
9118 case 1:
9119 switch (rt) {
9120 case 0:
9121 gen_helper_1e0i(mftlo, t0, 0);
9122 break;
9123 case 1:
9124 gen_helper_1e0i(mfthi, t0, 0);
9125 break;
9126 case 2:
9127 gen_helper_1e0i(mftacx, t0, 0);
9128 break;
9129 case 4:
9130 gen_helper_1e0i(mftlo, t0, 1);
9131 break;
9132 case 5:
9133 gen_helper_1e0i(mfthi, t0, 1);
9134 break;
9135 case 6:
9136 gen_helper_1e0i(mftacx, t0, 1);
9137 break;
9138 case 8:
9139 gen_helper_1e0i(mftlo, t0, 2);
9140 break;
9141 case 9:
9142 gen_helper_1e0i(mfthi, t0, 2);
9143 break;
9144 case 10:
9145 gen_helper_1e0i(mftacx, t0, 2);
9146 break;
9147 case 12:
9148 gen_helper_1e0i(mftlo, t0, 3);
9149 break;
9150 case 13:
9151 gen_helper_1e0i(mfthi, t0, 3);
9152 break;
9153 case 14:
9154 gen_helper_1e0i(mftacx, t0, 3);
9155 break;
9156 case 16:
9157 gen_helper_mftdsp(t0, cpu_env);
9158 break;
9159 default:
9160 goto die;
9162 break;
9163 /* Floating point (COP1). */
9164 case 2:
9165 /* XXX: For now we support only a single FPU context. */
9166 if (h == 0) {
9167 TCGv_i32 fp0 = tcg_temp_new_i32();
9169 gen_load_fpr32(ctx, fp0, rt);
9170 tcg_gen_ext_i32_tl(t0, fp0);
9171 tcg_temp_free_i32(fp0);
9172 } else {
9173 TCGv_i32 fp0 = tcg_temp_new_i32();
9175 gen_load_fpr32h(ctx, fp0, rt);
9176 tcg_gen_ext_i32_tl(t0, fp0);
9177 tcg_temp_free_i32(fp0);
9179 break;
9180 case 3:
9181 /* XXX: For now we support only a single FPU context. */
9182 gen_helper_1e0i(cfc1, t0, rt);
9183 break;
9184 /* COP2: Not implemented. */
9185 case 4:
9186 case 5:
9187 /* fall through */
9188 default:
9189 goto die;
9192 trace_mips_translate_tr("mftr", rt, u, sel, h);
9193 gen_store_gpr(t0, rd);
9194 tcg_temp_free(t0);
9195 return;
9197 die:
9198 tcg_temp_free(t0);
9199 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9200 gen_reserved_instruction(ctx);
9203 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9204 int u, int sel, int h)
9206 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9207 TCGv t0 = tcg_temp_local_new();
9209 gen_load_gpr(t0, rt);
9210 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9211 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9212 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9213 /* NOP */
9215 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9216 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9217 /* NOP */
9219 } else if (u == 0) {
9220 switch (rd) {
9221 case 1:
9222 switch (sel) {
9223 case 1:
9224 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9225 break;
9226 case 2:
9227 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9228 break;
9229 default:
9230 goto die;
9231 break;
9233 break;
9234 case 2:
9235 switch (sel) {
9236 case 1:
9237 gen_helper_mttc0_tcstatus(cpu_env, t0);
9238 break;
9239 case 2:
9240 gen_helper_mttc0_tcbind(cpu_env, t0);
9241 break;
9242 case 3:
9243 gen_helper_mttc0_tcrestart(cpu_env, t0);
9244 break;
9245 case 4:
9246 gen_helper_mttc0_tchalt(cpu_env, t0);
9247 break;
9248 case 5:
9249 gen_helper_mttc0_tccontext(cpu_env, t0);
9250 break;
9251 case 6:
9252 gen_helper_mttc0_tcschedule(cpu_env, t0);
9253 break;
9254 case 7:
9255 gen_helper_mttc0_tcschefback(cpu_env, t0);
9256 break;
9257 default:
9258 gen_mtc0(ctx, t0, rd, sel);
9259 break;
9261 break;
9262 case 10:
9263 switch (sel) {
9264 case 0:
9265 gen_helper_mttc0_entryhi(cpu_env, t0);
9266 break;
9267 default:
9268 gen_mtc0(ctx, t0, rd, sel);
9269 break;
9271 break;
9272 case 12:
9273 switch (sel) {
9274 case 0:
9275 gen_helper_mttc0_status(cpu_env, t0);
9276 break;
9277 default:
9278 gen_mtc0(ctx, t0, rd, sel);
9279 break;
9281 break;
9282 case 13:
9283 switch (sel) {
9284 case 0:
9285 gen_helper_mttc0_cause(cpu_env, t0);
9286 break;
9287 default:
9288 goto die;
9289 break;
9291 break;
9292 case 15:
9293 switch (sel) {
9294 case 1:
9295 gen_helper_mttc0_ebase(cpu_env, t0);
9296 break;
9297 default:
9298 goto die;
9299 break;
9301 break;
9302 case 23:
9303 switch (sel) {
9304 case 0:
9305 gen_helper_mttc0_debug(cpu_env, t0);
9306 break;
9307 default:
9308 gen_mtc0(ctx, t0, rd, sel);
9309 break;
9311 break;
9312 default:
9313 gen_mtc0(ctx, t0, rd, sel);
9315 } else {
9316 switch (sel) {
9317 /* GPR registers. */
9318 case 0:
9319 gen_helper_0e1i(mttgpr, t0, rd);
9320 break;
9321 /* Auxiliary CPU registers */
9322 case 1:
9323 switch (rd) {
9324 case 0:
9325 gen_helper_0e1i(mttlo, t0, 0);
9326 break;
9327 case 1:
9328 gen_helper_0e1i(mtthi, t0, 0);
9329 break;
9330 case 2:
9331 gen_helper_0e1i(mttacx, t0, 0);
9332 break;
9333 case 4:
9334 gen_helper_0e1i(mttlo, t0, 1);
9335 break;
9336 case 5:
9337 gen_helper_0e1i(mtthi, t0, 1);
9338 break;
9339 case 6:
9340 gen_helper_0e1i(mttacx, t0, 1);
9341 break;
9342 case 8:
9343 gen_helper_0e1i(mttlo, t0, 2);
9344 break;
9345 case 9:
9346 gen_helper_0e1i(mtthi, t0, 2);
9347 break;
9348 case 10:
9349 gen_helper_0e1i(mttacx, t0, 2);
9350 break;
9351 case 12:
9352 gen_helper_0e1i(mttlo, t0, 3);
9353 break;
9354 case 13:
9355 gen_helper_0e1i(mtthi, t0, 3);
9356 break;
9357 case 14:
9358 gen_helper_0e1i(mttacx, t0, 3);
9359 break;
9360 case 16:
9361 gen_helper_mttdsp(cpu_env, t0);
9362 break;
9363 default:
9364 goto die;
9366 break;
9367 /* Floating point (COP1). */
9368 case 2:
9369 /* XXX: For now we support only a single FPU context. */
9370 if (h == 0) {
9371 TCGv_i32 fp0 = tcg_temp_new_i32();
9373 tcg_gen_trunc_tl_i32(fp0, t0);
9374 gen_store_fpr32(ctx, fp0, rd);
9375 tcg_temp_free_i32(fp0);
9376 } else {
9377 TCGv_i32 fp0 = tcg_temp_new_i32();
9379 tcg_gen_trunc_tl_i32(fp0, t0);
9380 gen_store_fpr32h(ctx, fp0, rd);
9381 tcg_temp_free_i32(fp0);
9383 break;
9384 case 3:
9385 /* XXX: For now we support only a single FPU context. */
9387 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9389 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9390 tcg_temp_free_i32(fs_tmp);
9392 /* Stop translation as we may have changed hflags */
9393 ctx->base.is_jmp = DISAS_STOP;
9394 break;
9395 /* COP2: Not implemented. */
9396 case 4:
9397 case 5:
9398 /* fall through */
9399 default:
9400 goto die;
9403 trace_mips_translate_tr("mttr", rd, u, sel, h);
9404 tcg_temp_free(t0);
9405 return;
9407 die:
9408 tcg_temp_free(t0);
9409 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9410 gen_reserved_instruction(ctx);
9413 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
9414 int rt, int rd)
9416 const char *opn = "ldst";
9418 check_cp0_enabled(ctx);
9419 switch (opc) {
9420 case OPC_MFC0:
9421 if (rt == 0) {
9422 /* Treat as NOP. */
9423 return;
9425 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9426 opn = "mfc0";
9427 break;
9428 case OPC_MTC0:
9430 TCGv t0 = tcg_temp_new();
9432 gen_load_gpr(t0, rt);
9433 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9434 tcg_temp_free(t0);
9436 opn = "mtc0";
9437 break;
9438 #if defined(TARGET_MIPS64)
9439 case OPC_DMFC0:
9440 check_insn(ctx, ISA_MIPS3);
9441 if (rt == 0) {
9442 /* Treat as NOP. */
9443 return;
9445 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9446 opn = "dmfc0";
9447 break;
9448 case OPC_DMTC0:
9449 check_insn(ctx, ISA_MIPS3);
9451 TCGv t0 = tcg_temp_new();
9453 gen_load_gpr(t0, rt);
9454 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9455 tcg_temp_free(t0);
9457 opn = "dmtc0";
9458 break;
9459 #endif
9460 case OPC_MFHC0:
9461 check_mvh(ctx);
9462 if (rt == 0) {
9463 /* Treat as NOP. */
9464 return;
9466 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9467 opn = "mfhc0";
9468 break;
9469 case OPC_MTHC0:
9470 check_mvh(ctx);
9472 TCGv t0 = tcg_temp_new();
9473 gen_load_gpr(t0, rt);
9474 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9475 tcg_temp_free(t0);
9477 opn = "mthc0";
9478 break;
9479 case OPC_MFTR:
9480 check_cp0_enabled(ctx);
9481 if (rd == 0) {
9482 /* Treat as NOP. */
9483 return;
9485 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9486 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9487 opn = "mftr";
9488 break;
9489 case OPC_MTTR:
9490 check_cp0_enabled(ctx);
9491 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9492 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9493 opn = "mttr";
9494 break;
9495 case OPC_TLBWI:
9496 opn = "tlbwi";
9497 if (!env->tlb->helper_tlbwi) {
9498 goto die;
9500 gen_helper_tlbwi(cpu_env);
9501 break;
9502 case OPC_TLBINV:
9503 opn = "tlbinv";
9504 if (ctx->ie >= 2) {
9505 if (!env->tlb->helper_tlbinv) {
9506 goto die;
9508 gen_helper_tlbinv(cpu_env);
9509 } /* treat as nop if TLBINV not supported */
9510 break;
9511 case OPC_TLBINVF:
9512 opn = "tlbinvf";
9513 if (ctx->ie >= 2) {
9514 if (!env->tlb->helper_tlbinvf) {
9515 goto die;
9517 gen_helper_tlbinvf(cpu_env);
9518 } /* treat as nop if TLBINV not supported */
9519 break;
9520 case OPC_TLBWR:
9521 opn = "tlbwr";
9522 if (!env->tlb->helper_tlbwr) {
9523 goto die;
9525 gen_helper_tlbwr(cpu_env);
9526 break;
9527 case OPC_TLBP:
9528 opn = "tlbp";
9529 if (!env->tlb->helper_tlbp) {
9530 goto die;
9532 gen_helper_tlbp(cpu_env);
9533 break;
9534 case OPC_TLBR:
9535 opn = "tlbr";
9536 if (!env->tlb->helper_tlbr) {
9537 goto die;
9539 gen_helper_tlbr(cpu_env);
9540 break;
9541 case OPC_ERET: /* OPC_ERETNC */
9542 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9543 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9544 goto die;
9545 } else {
9546 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9547 if (ctx->opcode & (1 << bit_shift)) {
9548 /* OPC_ERETNC */
9549 opn = "eretnc";
9550 check_insn(ctx, ISA_MIPS_R5);
9551 gen_helper_eretnc(cpu_env);
9552 } else {
9553 /* OPC_ERET */
9554 opn = "eret";
9555 check_insn(ctx, ISA_MIPS2);
9556 gen_helper_eret(cpu_env);
9558 ctx->base.is_jmp = DISAS_EXIT;
9560 break;
9561 case OPC_DERET:
9562 opn = "deret";
9563 check_insn(ctx, ISA_MIPS_R1);
9564 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9565 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9566 goto die;
9568 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9569 MIPS_INVAL(opn);
9570 gen_reserved_instruction(ctx);
9571 } else {
9572 gen_helper_deret(cpu_env);
9573 ctx->base.is_jmp = DISAS_EXIT;
9575 break;
9576 case OPC_WAIT:
9577 opn = "wait";
9578 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
9579 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9580 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9581 goto die;
9583 /* If we get an exception, we want to restart at next instruction */
9584 ctx->base.pc_next += 4;
9585 save_cpu_state(ctx, 1);
9586 ctx->base.pc_next -= 4;
9587 gen_helper_wait(cpu_env);
9588 ctx->base.is_jmp = DISAS_NORETURN;
9589 break;
9590 default:
9591 die:
9592 MIPS_INVAL(opn);
9593 gen_reserved_instruction(ctx);
9594 return;
9596 (void)opn; /* avoid a compiler warning */
9598 #endif /* !CONFIG_USER_ONLY */
9600 /* CP1 Branches (before delay slot) */
9601 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9602 int32_t cc, int32_t offset)
9604 target_ulong btarget;
9605 TCGv_i32 t0 = tcg_temp_new_i32();
9607 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9608 gen_reserved_instruction(ctx);
9609 goto out;
9612 if (cc != 0) {
9613 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
9616 btarget = ctx->base.pc_next + 4 + offset;
9618 switch (op) {
9619 case OPC_BC1F:
9620 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9621 tcg_gen_not_i32(t0, t0);
9622 tcg_gen_andi_i32(t0, t0, 1);
9623 tcg_gen_extu_i32_tl(bcond, t0);
9624 goto not_likely;
9625 case OPC_BC1FL:
9626 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9627 tcg_gen_not_i32(t0, t0);
9628 tcg_gen_andi_i32(t0, t0, 1);
9629 tcg_gen_extu_i32_tl(bcond, t0);
9630 goto likely;
9631 case OPC_BC1T:
9632 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9633 tcg_gen_andi_i32(t0, t0, 1);
9634 tcg_gen_extu_i32_tl(bcond, t0);
9635 goto not_likely;
9636 case OPC_BC1TL:
9637 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9638 tcg_gen_andi_i32(t0, t0, 1);
9639 tcg_gen_extu_i32_tl(bcond, t0);
9640 likely:
9641 ctx->hflags |= MIPS_HFLAG_BL;
9642 break;
9643 case OPC_BC1FANY2:
9645 TCGv_i32 t1 = tcg_temp_new_i32();
9646 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9647 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9648 tcg_gen_nand_i32(t0, t0, t1);
9649 tcg_temp_free_i32(t1);
9650 tcg_gen_andi_i32(t0, t0, 1);
9651 tcg_gen_extu_i32_tl(bcond, t0);
9653 goto not_likely;
9654 case OPC_BC1TANY2:
9656 TCGv_i32 t1 = tcg_temp_new_i32();
9657 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9658 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9659 tcg_gen_or_i32(t0, t0, t1);
9660 tcg_temp_free_i32(t1);
9661 tcg_gen_andi_i32(t0, t0, 1);
9662 tcg_gen_extu_i32_tl(bcond, t0);
9664 goto not_likely;
9665 case OPC_BC1FANY4:
9667 TCGv_i32 t1 = tcg_temp_new_i32();
9668 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9669 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9670 tcg_gen_and_i32(t0, t0, t1);
9671 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
9672 tcg_gen_and_i32(t0, t0, t1);
9673 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
9674 tcg_gen_nand_i32(t0, t0, t1);
9675 tcg_temp_free_i32(t1);
9676 tcg_gen_andi_i32(t0, t0, 1);
9677 tcg_gen_extu_i32_tl(bcond, t0);
9679 goto not_likely;
9680 case OPC_BC1TANY4:
9682 TCGv_i32 t1 = tcg_temp_new_i32();
9683 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9684 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9685 tcg_gen_or_i32(t0, t0, t1);
9686 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
9687 tcg_gen_or_i32(t0, t0, t1);
9688 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
9689 tcg_gen_or_i32(t0, t0, t1);
9690 tcg_temp_free_i32(t1);
9691 tcg_gen_andi_i32(t0, t0, 1);
9692 tcg_gen_extu_i32_tl(bcond, t0);
9694 not_likely:
9695 ctx->hflags |= MIPS_HFLAG_BC;
9696 break;
9697 default:
9698 MIPS_INVAL("cp1 cond branch");
9699 gen_reserved_instruction(ctx);
9700 goto out;
9702 ctx->btarget = btarget;
9703 ctx->hflags |= MIPS_HFLAG_BDS32;
9704 out:
9705 tcg_temp_free_i32(t0);
9708 /* R6 CP1 Branches */
9709 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
9710 int32_t ft, int32_t offset,
9711 int delayslot_size)
9713 target_ulong btarget;
9714 TCGv_i64 t0 = tcg_temp_new_i64();
9716 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9717 #ifdef MIPS_DEBUG_DISAS
9718 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
9719 "\n", ctx->base.pc_next);
9720 #endif
9721 gen_reserved_instruction(ctx);
9722 goto out;
9725 gen_load_fpr64(ctx, t0, ft);
9726 tcg_gen_andi_i64(t0, t0, 1);
9728 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
9730 switch (op) {
9731 case OPC_BC1EQZ:
9732 tcg_gen_xori_i64(t0, t0, 1);
9733 ctx->hflags |= MIPS_HFLAG_BC;
9734 break;
9735 case OPC_BC1NEZ:
9736 /* t0 already set */
9737 ctx->hflags |= MIPS_HFLAG_BC;
9738 break;
9739 default:
9740 MIPS_INVAL("cp1 cond branch");
9741 gen_reserved_instruction(ctx);
9742 goto out;
9745 tcg_gen_trunc_i64_tl(bcond, t0);
9747 ctx->btarget = btarget;
9749 switch (delayslot_size) {
9750 case 2:
9751 ctx->hflags |= MIPS_HFLAG_BDS16;
9752 break;
9753 case 4:
9754 ctx->hflags |= MIPS_HFLAG_BDS32;
9755 break;
9758 out:
9759 tcg_temp_free_i64(t0);
9762 /* Coprocessor 1 (FPU) */
9764 #define FOP(func, fmt) (((fmt) << 21) | (func))
9766 enum fopcode {
9767 OPC_ADD_S = FOP(0, FMT_S),
9768 OPC_SUB_S = FOP(1, FMT_S),
9769 OPC_MUL_S = FOP(2, FMT_S),
9770 OPC_DIV_S = FOP(3, FMT_S),
9771 OPC_SQRT_S = FOP(4, FMT_S),
9772 OPC_ABS_S = FOP(5, FMT_S),
9773 OPC_MOV_S = FOP(6, FMT_S),
9774 OPC_NEG_S = FOP(7, FMT_S),
9775 OPC_ROUND_L_S = FOP(8, FMT_S),
9776 OPC_TRUNC_L_S = FOP(9, FMT_S),
9777 OPC_CEIL_L_S = FOP(10, FMT_S),
9778 OPC_FLOOR_L_S = FOP(11, FMT_S),
9779 OPC_ROUND_W_S = FOP(12, FMT_S),
9780 OPC_TRUNC_W_S = FOP(13, FMT_S),
9781 OPC_CEIL_W_S = FOP(14, FMT_S),
9782 OPC_FLOOR_W_S = FOP(15, FMT_S),
9783 OPC_SEL_S = FOP(16, FMT_S),
9784 OPC_MOVCF_S = FOP(17, FMT_S),
9785 OPC_MOVZ_S = FOP(18, FMT_S),
9786 OPC_MOVN_S = FOP(19, FMT_S),
9787 OPC_SELEQZ_S = FOP(20, FMT_S),
9788 OPC_RECIP_S = FOP(21, FMT_S),
9789 OPC_RSQRT_S = FOP(22, FMT_S),
9790 OPC_SELNEZ_S = FOP(23, FMT_S),
9791 OPC_MADDF_S = FOP(24, FMT_S),
9792 OPC_MSUBF_S = FOP(25, FMT_S),
9793 OPC_RINT_S = FOP(26, FMT_S),
9794 OPC_CLASS_S = FOP(27, FMT_S),
9795 OPC_MIN_S = FOP(28, FMT_S),
9796 OPC_RECIP2_S = FOP(28, FMT_S),
9797 OPC_MINA_S = FOP(29, FMT_S),
9798 OPC_RECIP1_S = FOP(29, FMT_S),
9799 OPC_MAX_S = FOP(30, FMT_S),
9800 OPC_RSQRT1_S = FOP(30, FMT_S),
9801 OPC_MAXA_S = FOP(31, FMT_S),
9802 OPC_RSQRT2_S = FOP(31, FMT_S),
9803 OPC_CVT_D_S = FOP(33, FMT_S),
9804 OPC_CVT_W_S = FOP(36, FMT_S),
9805 OPC_CVT_L_S = FOP(37, FMT_S),
9806 OPC_CVT_PS_S = FOP(38, FMT_S),
9807 OPC_CMP_F_S = FOP(48, FMT_S),
9808 OPC_CMP_UN_S = FOP(49, FMT_S),
9809 OPC_CMP_EQ_S = FOP(50, FMT_S),
9810 OPC_CMP_UEQ_S = FOP(51, FMT_S),
9811 OPC_CMP_OLT_S = FOP(52, FMT_S),
9812 OPC_CMP_ULT_S = FOP(53, FMT_S),
9813 OPC_CMP_OLE_S = FOP(54, FMT_S),
9814 OPC_CMP_ULE_S = FOP(55, FMT_S),
9815 OPC_CMP_SF_S = FOP(56, FMT_S),
9816 OPC_CMP_NGLE_S = FOP(57, FMT_S),
9817 OPC_CMP_SEQ_S = FOP(58, FMT_S),
9818 OPC_CMP_NGL_S = FOP(59, FMT_S),
9819 OPC_CMP_LT_S = FOP(60, FMT_S),
9820 OPC_CMP_NGE_S = FOP(61, FMT_S),
9821 OPC_CMP_LE_S = FOP(62, FMT_S),
9822 OPC_CMP_NGT_S = FOP(63, FMT_S),
9824 OPC_ADD_D = FOP(0, FMT_D),
9825 OPC_SUB_D = FOP(1, FMT_D),
9826 OPC_MUL_D = FOP(2, FMT_D),
9827 OPC_DIV_D = FOP(3, FMT_D),
9828 OPC_SQRT_D = FOP(4, FMT_D),
9829 OPC_ABS_D = FOP(5, FMT_D),
9830 OPC_MOV_D = FOP(6, FMT_D),
9831 OPC_NEG_D = FOP(7, FMT_D),
9832 OPC_ROUND_L_D = FOP(8, FMT_D),
9833 OPC_TRUNC_L_D = FOP(9, FMT_D),
9834 OPC_CEIL_L_D = FOP(10, FMT_D),
9835 OPC_FLOOR_L_D = FOP(11, FMT_D),
9836 OPC_ROUND_W_D = FOP(12, FMT_D),
9837 OPC_TRUNC_W_D = FOP(13, FMT_D),
9838 OPC_CEIL_W_D = FOP(14, FMT_D),
9839 OPC_FLOOR_W_D = FOP(15, FMT_D),
9840 OPC_SEL_D = FOP(16, FMT_D),
9841 OPC_MOVCF_D = FOP(17, FMT_D),
9842 OPC_MOVZ_D = FOP(18, FMT_D),
9843 OPC_MOVN_D = FOP(19, FMT_D),
9844 OPC_SELEQZ_D = FOP(20, FMT_D),
9845 OPC_RECIP_D = FOP(21, FMT_D),
9846 OPC_RSQRT_D = FOP(22, FMT_D),
9847 OPC_SELNEZ_D = FOP(23, FMT_D),
9848 OPC_MADDF_D = FOP(24, FMT_D),
9849 OPC_MSUBF_D = FOP(25, FMT_D),
9850 OPC_RINT_D = FOP(26, FMT_D),
9851 OPC_CLASS_D = FOP(27, FMT_D),
9852 OPC_MIN_D = FOP(28, FMT_D),
9853 OPC_RECIP2_D = FOP(28, FMT_D),
9854 OPC_MINA_D = FOP(29, FMT_D),
9855 OPC_RECIP1_D = FOP(29, FMT_D),
9856 OPC_MAX_D = FOP(30, FMT_D),
9857 OPC_RSQRT1_D = FOP(30, FMT_D),
9858 OPC_MAXA_D = FOP(31, FMT_D),
9859 OPC_RSQRT2_D = FOP(31, FMT_D),
9860 OPC_CVT_S_D = FOP(32, FMT_D),
9861 OPC_CVT_W_D = FOP(36, FMT_D),
9862 OPC_CVT_L_D = FOP(37, FMT_D),
9863 OPC_CMP_F_D = FOP(48, FMT_D),
9864 OPC_CMP_UN_D = FOP(49, FMT_D),
9865 OPC_CMP_EQ_D = FOP(50, FMT_D),
9866 OPC_CMP_UEQ_D = FOP(51, FMT_D),
9867 OPC_CMP_OLT_D = FOP(52, FMT_D),
9868 OPC_CMP_ULT_D = FOP(53, FMT_D),
9869 OPC_CMP_OLE_D = FOP(54, FMT_D),
9870 OPC_CMP_ULE_D = FOP(55, FMT_D),
9871 OPC_CMP_SF_D = FOP(56, FMT_D),
9872 OPC_CMP_NGLE_D = FOP(57, FMT_D),
9873 OPC_CMP_SEQ_D = FOP(58, FMT_D),
9874 OPC_CMP_NGL_D = FOP(59, FMT_D),
9875 OPC_CMP_LT_D = FOP(60, FMT_D),
9876 OPC_CMP_NGE_D = FOP(61, FMT_D),
9877 OPC_CMP_LE_D = FOP(62, FMT_D),
9878 OPC_CMP_NGT_D = FOP(63, FMT_D),
9880 OPC_CVT_S_W = FOP(32, FMT_W),
9881 OPC_CVT_D_W = FOP(33, FMT_W),
9882 OPC_CVT_S_L = FOP(32, FMT_L),
9883 OPC_CVT_D_L = FOP(33, FMT_L),
9884 OPC_CVT_PS_PW = FOP(38, FMT_W),
9886 OPC_ADD_PS = FOP(0, FMT_PS),
9887 OPC_SUB_PS = FOP(1, FMT_PS),
9888 OPC_MUL_PS = FOP(2, FMT_PS),
9889 OPC_DIV_PS = FOP(3, FMT_PS),
9890 OPC_ABS_PS = FOP(5, FMT_PS),
9891 OPC_MOV_PS = FOP(6, FMT_PS),
9892 OPC_NEG_PS = FOP(7, FMT_PS),
9893 OPC_MOVCF_PS = FOP(17, FMT_PS),
9894 OPC_MOVZ_PS = FOP(18, FMT_PS),
9895 OPC_MOVN_PS = FOP(19, FMT_PS),
9896 OPC_ADDR_PS = FOP(24, FMT_PS),
9897 OPC_MULR_PS = FOP(26, FMT_PS),
9898 OPC_RECIP2_PS = FOP(28, FMT_PS),
9899 OPC_RECIP1_PS = FOP(29, FMT_PS),
9900 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9901 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9903 OPC_CVT_S_PU = FOP(32, FMT_PS),
9904 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9905 OPC_CVT_S_PL = FOP(40, FMT_PS),
9906 OPC_PLL_PS = FOP(44, FMT_PS),
9907 OPC_PLU_PS = FOP(45, FMT_PS),
9908 OPC_PUL_PS = FOP(46, FMT_PS),
9909 OPC_PUU_PS = FOP(47, FMT_PS),
9910 OPC_CMP_F_PS = FOP(48, FMT_PS),
9911 OPC_CMP_UN_PS = FOP(49, FMT_PS),
9912 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
9913 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
9914 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
9915 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
9916 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
9917 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
9918 OPC_CMP_SF_PS = FOP(56, FMT_PS),
9919 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
9920 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
9921 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
9922 OPC_CMP_LT_PS = FOP(60, FMT_PS),
9923 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
9924 OPC_CMP_LE_PS = FOP(62, FMT_PS),
9925 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
9928 enum r6_f_cmp_op {
9929 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9930 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9931 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9932 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9933 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9934 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9935 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9936 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9937 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9938 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9939 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9940 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9941 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9942 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9943 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9944 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9945 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9946 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9947 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9948 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9949 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9950 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9952 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9953 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9954 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9955 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9956 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9957 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9958 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9959 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9960 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9961 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9962 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9963 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9964 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9965 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9966 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9967 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9968 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9969 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9970 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9971 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9972 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9973 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9976 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
9978 TCGv t0 = tcg_temp_new();
9980 switch (opc) {
9981 case OPC_MFC1:
9983 TCGv_i32 fp0 = tcg_temp_new_i32();
9985 gen_load_fpr32(ctx, fp0, fs);
9986 tcg_gen_ext_i32_tl(t0, fp0);
9987 tcg_temp_free_i32(fp0);
9989 gen_store_gpr(t0, rt);
9990 break;
9991 case OPC_MTC1:
9992 gen_load_gpr(t0, rt);
9994 TCGv_i32 fp0 = tcg_temp_new_i32();
9996 tcg_gen_trunc_tl_i32(fp0, t0);
9997 gen_store_fpr32(ctx, fp0, fs);
9998 tcg_temp_free_i32(fp0);
10000 break;
10001 case OPC_CFC1:
10002 gen_helper_1e0i(cfc1, t0, fs);
10003 gen_store_gpr(t0, rt);
10004 break;
10005 case OPC_CTC1:
10006 gen_load_gpr(t0, rt);
10007 save_cpu_state(ctx, 0);
10009 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10011 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10012 tcg_temp_free_i32(fs_tmp);
10014 /* Stop translation as we may have changed hflags */
10015 ctx->base.is_jmp = DISAS_STOP;
10016 break;
10017 #if defined(TARGET_MIPS64)
10018 case OPC_DMFC1:
10019 gen_load_fpr64(ctx, t0, fs);
10020 gen_store_gpr(t0, rt);
10021 break;
10022 case OPC_DMTC1:
10023 gen_load_gpr(t0, rt);
10024 gen_store_fpr64(ctx, t0, fs);
10025 break;
10026 #endif
10027 case OPC_MFHC1:
10029 TCGv_i32 fp0 = tcg_temp_new_i32();
10031 gen_load_fpr32h(ctx, fp0, fs);
10032 tcg_gen_ext_i32_tl(t0, fp0);
10033 tcg_temp_free_i32(fp0);
10035 gen_store_gpr(t0, rt);
10036 break;
10037 case OPC_MTHC1:
10038 gen_load_gpr(t0, rt);
10040 TCGv_i32 fp0 = tcg_temp_new_i32();
10042 tcg_gen_trunc_tl_i32(fp0, t0);
10043 gen_store_fpr32h(ctx, fp0, fs);
10044 tcg_temp_free_i32(fp0);
10046 break;
10047 default:
10048 MIPS_INVAL("cp1 move");
10049 gen_reserved_instruction(ctx);
10050 goto out;
10053 out:
10054 tcg_temp_free(t0);
10057 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
10059 TCGLabel *l1;
10060 TCGCond cond;
10061 TCGv_i32 t0;
10063 if (rd == 0) {
10064 /* Treat as NOP. */
10065 return;
10068 if (tf) {
10069 cond = TCG_COND_EQ;
10070 } else {
10071 cond = TCG_COND_NE;
10074 l1 = gen_new_label();
10075 t0 = tcg_temp_new_i32();
10076 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10077 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10078 tcg_temp_free_i32(t0);
10079 gen_load_gpr(cpu_gpr[rd], rs);
10080 gen_set_label(l1);
10083 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10084 int tf)
10086 int cond;
10087 TCGv_i32 t0 = tcg_temp_new_i32();
10088 TCGLabel *l1 = gen_new_label();
10090 if (tf) {
10091 cond = TCG_COND_EQ;
10092 } else {
10093 cond = TCG_COND_NE;
10096 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10097 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10098 gen_load_fpr32(ctx, t0, fs);
10099 gen_store_fpr32(ctx, t0, fd);
10100 gen_set_label(l1);
10101 tcg_temp_free_i32(t0);
10104 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
10105 int tf)
10107 int cond;
10108 TCGv_i32 t0 = tcg_temp_new_i32();
10109 TCGv_i64 fp0;
10110 TCGLabel *l1 = gen_new_label();
10112 if (tf) {
10113 cond = TCG_COND_EQ;
10114 } else {
10115 cond = TCG_COND_NE;
10118 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10119 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10120 tcg_temp_free_i32(t0);
10121 fp0 = tcg_temp_new_i64();
10122 gen_load_fpr64(ctx, fp0, fs);
10123 gen_store_fpr64(ctx, fp0, fd);
10124 tcg_temp_free_i64(fp0);
10125 gen_set_label(l1);
10128 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10129 int cc, int tf)
10131 int cond;
10132 TCGv_i32 t0 = tcg_temp_new_i32();
10133 TCGLabel *l1 = gen_new_label();
10134 TCGLabel *l2 = gen_new_label();
10136 if (tf) {
10137 cond = TCG_COND_EQ;
10138 } else {
10139 cond = TCG_COND_NE;
10142 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10143 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10144 gen_load_fpr32(ctx, t0, fs);
10145 gen_store_fpr32(ctx, t0, fd);
10146 gen_set_label(l1);
10148 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
10149 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10150 gen_load_fpr32h(ctx, t0, fs);
10151 gen_store_fpr32h(ctx, t0, fd);
10152 tcg_temp_free_i32(t0);
10153 gen_set_label(l2);
10156 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10157 int fs)
10159 TCGv_i32 t1 = tcg_const_i32(0);
10160 TCGv_i32 fp0 = tcg_temp_new_i32();
10161 TCGv_i32 fp1 = tcg_temp_new_i32();
10162 TCGv_i32 fp2 = tcg_temp_new_i32();
10163 gen_load_fpr32(ctx, fp0, fd);
10164 gen_load_fpr32(ctx, fp1, ft);
10165 gen_load_fpr32(ctx, fp2, fs);
10167 switch (op1) {
10168 case OPC_SEL_S:
10169 tcg_gen_andi_i32(fp0, fp0, 1);
10170 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10171 break;
10172 case OPC_SELEQZ_S:
10173 tcg_gen_andi_i32(fp1, fp1, 1);
10174 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10175 break;
10176 case OPC_SELNEZ_S:
10177 tcg_gen_andi_i32(fp1, fp1, 1);
10178 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10179 break;
10180 default:
10181 MIPS_INVAL("gen_sel_s");
10182 gen_reserved_instruction(ctx);
10183 break;
10186 gen_store_fpr32(ctx, fp0, fd);
10187 tcg_temp_free_i32(fp2);
10188 tcg_temp_free_i32(fp1);
10189 tcg_temp_free_i32(fp0);
10190 tcg_temp_free_i32(t1);
10193 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10194 int fs)
10196 TCGv_i64 t1 = tcg_const_i64(0);
10197 TCGv_i64 fp0 = tcg_temp_new_i64();
10198 TCGv_i64 fp1 = tcg_temp_new_i64();
10199 TCGv_i64 fp2 = tcg_temp_new_i64();
10200 gen_load_fpr64(ctx, fp0, fd);
10201 gen_load_fpr64(ctx, fp1, ft);
10202 gen_load_fpr64(ctx, fp2, fs);
10204 switch (op1) {
10205 case OPC_SEL_D:
10206 tcg_gen_andi_i64(fp0, fp0, 1);
10207 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10208 break;
10209 case OPC_SELEQZ_D:
10210 tcg_gen_andi_i64(fp1, fp1, 1);
10211 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10212 break;
10213 case OPC_SELNEZ_D:
10214 tcg_gen_andi_i64(fp1, fp1, 1);
10215 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10216 break;
10217 default:
10218 MIPS_INVAL("gen_sel_d");
10219 gen_reserved_instruction(ctx);
10220 break;
10223 gen_store_fpr64(ctx, fp0, fd);
10224 tcg_temp_free_i64(fp2);
10225 tcg_temp_free_i64(fp1);
10226 tcg_temp_free_i64(fp0);
10227 tcg_temp_free_i64(t1);
10230 static void gen_farith(DisasContext *ctx, enum fopcode op1,
10231 int ft, int fs, int fd, int cc)
10233 uint32_t func = ctx->opcode & 0x3f;
10234 switch (op1) {
10235 case OPC_ADD_S:
10237 TCGv_i32 fp0 = tcg_temp_new_i32();
10238 TCGv_i32 fp1 = tcg_temp_new_i32();
10240 gen_load_fpr32(ctx, fp0, fs);
10241 gen_load_fpr32(ctx, fp1, ft);
10242 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10243 tcg_temp_free_i32(fp1);
10244 gen_store_fpr32(ctx, fp0, fd);
10245 tcg_temp_free_i32(fp0);
10247 break;
10248 case OPC_SUB_S:
10250 TCGv_i32 fp0 = tcg_temp_new_i32();
10251 TCGv_i32 fp1 = tcg_temp_new_i32();
10253 gen_load_fpr32(ctx, fp0, fs);
10254 gen_load_fpr32(ctx, fp1, ft);
10255 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10256 tcg_temp_free_i32(fp1);
10257 gen_store_fpr32(ctx, fp0, fd);
10258 tcg_temp_free_i32(fp0);
10260 break;
10261 case OPC_MUL_S:
10263 TCGv_i32 fp0 = tcg_temp_new_i32();
10264 TCGv_i32 fp1 = tcg_temp_new_i32();
10266 gen_load_fpr32(ctx, fp0, fs);
10267 gen_load_fpr32(ctx, fp1, ft);
10268 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10269 tcg_temp_free_i32(fp1);
10270 gen_store_fpr32(ctx, fp0, fd);
10271 tcg_temp_free_i32(fp0);
10273 break;
10274 case OPC_DIV_S:
10276 TCGv_i32 fp0 = tcg_temp_new_i32();
10277 TCGv_i32 fp1 = tcg_temp_new_i32();
10279 gen_load_fpr32(ctx, fp0, fs);
10280 gen_load_fpr32(ctx, fp1, ft);
10281 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10282 tcg_temp_free_i32(fp1);
10283 gen_store_fpr32(ctx, fp0, fd);
10284 tcg_temp_free_i32(fp0);
10286 break;
10287 case OPC_SQRT_S:
10289 TCGv_i32 fp0 = tcg_temp_new_i32();
10291 gen_load_fpr32(ctx, fp0, fs);
10292 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10293 gen_store_fpr32(ctx, fp0, fd);
10294 tcg_temp_free_i32(fp0);
10296 break;
10297 case OPC_ABS_S:
10299 TCGv_i32 fp0 = tcg_temp_new_i32();
10301 gen_load_fpr32(ctx, fp0, fs);
10302 if (ctx->abs2008) {
10303 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10304 } else {
10305 gen_helper_float_abs_s(fp0, fp0);
10307 gen_store_fpr32(ctx, fp0, fd);
10308 tcg_temp_free_i32(fp0);
10310 break;
10311 case OPC_MOV_S:
10313 TCGv_i32 fp0 = tcg_temp_new_i32();
10315 gen_load_fpr32(ctx, fp0, fs);
10316 gen_store_fpr32(ctx, fp0, fd);
10317 tcg_temp_free_i32(fp0);
10319 break;
10320 case OPC_NEG_S:
10322 TCGv_i32 fp0 = tcg_temp_new_i32();
10324 gen_load_fpr32(ctx, fp0, fs);
10325 if (ctx->abs2008) {
10326 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10327 } else {
10328 gen_helper_float_chs_s(fp0, fp0);
10330 gen_store_fpr32(ctx, fp0, fd);
10331 tcg_temp_free_i32(fp0);
10333 break;
10334 case OPC_ROUND_L_S:
10335 check_cp1_64bitmode(ctx);
10337 TCGv_i32 fp32 = tcg_temp_new_i32();
10338 TCGv_i64 fp64 = tcg_temp_new_i64();
10340 gen_load_fpr32(ctx, fp32, fs);
10341 if (ctx->nan2008) {
10342 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10343 } else {
10344 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10346 tcg_temp_free_i32(fp32);
10347 gen_store_fpr64(ctx, fp64, fd);
10348 tcg_temp_free_i64(fp64);
10350 break;
10351 case OPC_TRUNC_L_S:
10352 check_cp1_64bitmode(ctx);
10354 TCGv_i32 fp32 = tcg_temp_new_i32();
10355 TCGv_i64 fp64 = tcg_temp_new_i64();
10357 gen_load_fpr32(ctx, fp32, fs);
10358 if (ctx->nan2008) {
10359 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10360 } else {
10361 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10363 tcg_temp_free_i32(fp32);
10364 gen_store_fpr64(ctx, fp64, fd);
10365 tcg_temp_free_i64(fp64);
10367 break;
10368 case OPC_CEIL_L_S:
10369 check_cp1_64bitmode(ctx);
10371 TCGv_i32 fp32 = tcg_temp_new_i32();
10372 TCGv_i64 fp64 = tcg_temp_new_i64();
10374 gen_load_fpr32(ctx, fp32, fs);
10375 if (ctx->nan2008) {
10376 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10377 } else {
10378 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10380 tcg_temp_free_i32(fp32);
10381 gen_store_fpr64(ctx, fp64, fd);
10382 tcg_temp_free_i64(fp64);
10384 break;
10385 case OPC_FLOOR_L_S:
10386 check_cp1_64bitmode(ctx);
10388 TCGv_i32 fp32 = tcg_temp_new_i32();
10389 TCGv_i64 fp64 = tcg_temp_new_i64();
10391 gen_load_fpr32(ctx, fp32, fs);
10392 if (ctx->nan2008) {
10393 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10394 } else {
10395 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10397 tcg_temp_free_i32(fp32);
10398 gen_store_fpr64(ctx, fp64, fd);
10399 tcg_temp_free_i64(fp64);
10401 break;
10402 case OPC_ROUND_W_S:
10404 TCGv_i32 fp0 = tcg_temp_new_i32();
10406 gen_load_fpr32(ctx, fp0, fs);
10407 if (ctx->nan2008) {
10408 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10409 } else {
10410 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10412 gen_store_fpr32(ctx, fp0, fd);
10413 tcg_temp_free_i32(fp0);
10415 break;
10416 case OPC_TRUNC_W_S:
10418 TCGv_i32 fp0 = tcg_temp_new_i32();
10420 gen_load_fpr32(ctx, fp0, fs);
10421 if (ctx->nan2008) {
10422 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10423 } else {
10424 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10426 gen_store_fpr32(ctx, fp0, fd);
10427 tcg_temp_free_i32(fp0);
10429 break;
10430 case OPC_CEIL_W_S:
10432 TCGv_i32 fp0 = tcg_temp_new_i32();
10434 gen_load_fpr32(ctx, fp0, fs);
10435 if (ctx->nan2008) {
10436 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10437 } else {
10438 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10440 gen_store_fpr32(ctx, fp0, fd);
10441 tcg_temp_free_i32(fp0);
10443 break;
10444 case OPC_FLOOR_W_S:
10446 TCGv_i32 fp0 = tcg_temp_new_i32();
10448 gen_load_fpr32(ctx, fp0, fs);
10449 if (ctx->nan2008) {
10450 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10451 } else {
10452 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10454 gen_store_fpr32(ctx, fp0, fd);
10455 tcg_temp_free_i32(fp0);
10457 break;
10458 case OPC_SEL_S:
10459 check_insn(ctx, ISA_MIPS_R6);
10460 gen_sel_s(ctx, op1, fd, ft, fs);
10461 break;
10462 case OPC_SELEQZ_S:
10463 check_insn(ctx, ISA_MIPS_R6);
10464 gen_sel_s(ctx, op1, fd, ft, fs);
10465 break;
10466 case OPC_SELNEZ_S:
10467 check_insn(ctx, ISA_MIPS_R6);
10468 gen_sel_s(ctx, op1, fd, ft, fs);
10469 break;
10470 case OPC_MOVCF_S:
10471 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10472 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10473 break;
10474 case OPC_MOVZ_S:
10475 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10477 TCGLabel *l1 = gen_new_label();
10478 TCGv_i32 fp0;
10480 if (ft != 0) {
10481 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10483 fp0 = tcg_temp_new_i32();
10484 gen_load_fpr32(ctx, fp0, fs);
10485 gen_store_fpr32(ctx, fp0, fd);
10486 tcg_temp_free_i32(fp0);
10487 gen_set_label(l1);
10489 break;
10490 case OPC_MOVN_S:
10491 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10493 TCGLabel *l1 = gen_new_label();
10494 TCGv_i32 fp0;
10496 if (ft != 0) {
10497 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10498 fp0 = tcg_temp_new_i32();
10499 gen_load_fpr32(ctx, fp0, fs);
10500 gen_store_fpr32(ctx, fp0, fd);
10501 tcg_temp_free_i32(fp0);
10502 gen_set_label(l1);
10505 break;
10506 case OPC_RECIP_S:
10508 TCGv_i32 fp0 = tcg_temp_new_i32();
10510 gen_load_fpr32(ctx, fp0, fs);
10511 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10512 gen_store_fpr32(ctx, fp0, fd);
10513 tcg_temp_free_i32(fp0);
10515 break;
10516 case OPC_RSQRT_S:
10518 TCGv_i32 fp0 = tcg_temp_new_i32();
10520 gen_load_fpr32(ctx, fp0, fs);
10521 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10522 gen_store_fpr32(ctx, fp0, fd);
10523 tcg_temp_free_i32(fp0);
10525 break;
10526 case OPC_MADDF_S:
10527 check_insn(ctx, ISA_MIPS_R6);
10529 TCGv_i32 fp0 = tcg_temp_new_i32();
10530 TCGv_i32 fp1 = tcg_temp_new_i32();
10531 TCGv_i32 fp2 = tcg_temp_new_i32();
10532 gen_load_fpr32(ctx, fp0, fs);
10533 gen_load_fpr32(ctx, fp1, ft);
10534 gen_load_fpr32(ctx, fp2, fd);
10535 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10536 gen_store_fpr32(ctx, fp2, fd);
10537 tcg_temp_free_i32(fp2);
10538 tcg_temp_free_i32(fp1);
10539 tcg_temp_free_i32(fp0);
10541 break;
10542 case OPC_MSUBF_S:
10543 check_insn(ctx, ISA_MIPS_R6);
10545 TCGv_i32 fp0 = tcg_temp_new_i32();
10546 TCGv_i32 fp1 = tcg_temp_new_i32();
10547 TCGv_i32 fp2 = tcg_temp_new_i32();
10548 gen_load_fpr32(ctx, fp0, fs);
10549 gen_load_fpr32(ctx, fp1, ft);
10550 gen_load_fpr32(ctx, fp2, fd);
10551 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10552 gen_store_fpr32(ctx, fp2, fd);
10553 tcg_temp_free_i32(fp2);
10554 tcg_temp_free_i32(fp1);
10555 tcg_temp_free_i32(fp0);
10557 break;
10558 case OPC_RINT_S:
10559 check_insn(ctx, ISA_MIPS_R6);
10561 TCGv_i32 fp0 = tcg_temp_new_i32();
10562 gen_load_fpr32(ctx, fp0, fs);
10563 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10564 gen_store_fpr32(ctx, fp0, fd);
10565 tcg_temp_free_i32(fp0);
10567 break;
10568 case OPC_CLASS_S:
10569 check_insn(ctx, ISA_MIPS_R6);
10571 TCGv_i32 fp0 = tcg_temp_new_i32();
10572 gen_load_fpr32(ctx, fp0, fs);
10573 gen_helper_float_class_s(fp0, cpu_env, fp0);
10574 gen_store_fpr32(ctx, fp0, fd);
10575 tcg_temp_free_i32(fp0);
10577 break;
10578 case OPC_MIN_S: /* OPC_RECIP2_S */
10579 if (ctx->insn_flags & ISA_MIPS_R6) {
10580 /* OPC_MIN_S */
10581 TCGv_i32 fp0 = tcg_temp_new_i32();
10582 TCGv_i32 fp1 = tcg_temp_new_i32();
10583 TCGv_i32 fp2 = tcg_temp_new_i32();
10584 gen_load_fpr32(ctx, fp0, fs);
10585 gen_load_fpr32(ctx, fp1, ft);
10586 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10587 gen_store_fpr32(ctx, fp2, fd);
10588 tcg_temp_free_i32(fp2);
10589 tcg_temp_free_i32(fp1);
10590 tcg_temp_free_i32(fp0);
10591 } else {
10592 /* OPC_RECIP2_S */
10593 check_cp1_64bitmode(ctx);
10595 TCGv_i32 fp0 = tcg_temp_new_i32();
10596 TCGv_i32 fp1 = tcg_temp_new_i32();
10598 gen_load_fpr32(ctx, fp0, fs);
10599 gen_load_fpr32(ctx, fp1, ft);
10600 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10601 tcg_temp_free_i32(fp1);
10602 gen_store_fpr32(ctx, fp0, fd);
10603 tcg_temp_free_i32(fp0);
10606 break;
10607 case OPC_MINA_S: /* OPC_RECIP1_S */
10608 if (ctx->insn_flags & ISA_MIPS_R6) {
10609 /* OPC_MINA_S */
10610 TCGv_i32 fp0 = tcg_temp_new_i32();
10611 TCGv_i32 fp1 = tcg_temp_new_i32();
10612 TCGv_i32 fp2 = tcg_temp_new_i32();
10613 gen_load_fpr32(ctx, fp0, fs);
10614 gen_load_fpr32(ctx, fp1, ft);
10615 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10616 gen_store_fpr32(ctx, fp2, fd);
10617 tcg_temp_free_i32(fp2);
10618 tcg_temp_free_i32(fp1);
10619 tcg_temp_free_i32(fp0);
10620 } else {
10621 /* OPC_RECIP1_S */
10622 check_cp1_64bitmode(ctx);
10624 TCGv_i32 fp0 = tcg_temp_new_i32();
10626 gen_load_fpr32(ctx, fp0, fs);
10627 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10628 gen_store_fpr32(ctx, fp0, fd);
10629 tcg_temp_free_i32(fp0);
10632 break;
10633 case OPC_MAX_S: /* OPC_RSQRT1_S */
10634 if (ctx->insn_flags & ISA_MIPS_R6) {
10635 /* OPC_MAX_S */
10636 TCGv_i32 fp0 = tcg_temp_new_i32();
10637 TCGv_i32 fp1 = tcg_temp_new_i32();
10638 gen_load_fpr32(ctx, fp0, fs);
10639 gen_load_fpr32(ctx, fp1, ft);
10640 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10641 gen_store_fpr32(ctx, fp1, fd);
10642 tcg_temp_free_i32(fp1);
10643 tcg_temp_free_i32(fp0);
10644 } else {
10645 /* OPC_RSQRT1_S */
10646 check_cp1_64bitmode(ctx);
10648 TCGv_i32 fp0 = tcg_temp_new_i32();
10650 gen_load_fpr32(ctx, fp0, fs);
10651 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
10652 gen_store_fpr32(ctx, fp0, fd);
10653 tcg_temp_free_i32(fp0);
10656 break;
10657 case OPC_MAXA_S: /* OPC_RSQRT2_S */
10658 if (ctx->insn_flags & ISA_MIPS_R6) {
10659 /* OPC_MAXA_S */
10660 TCGv_i32 fp0 = tcg_temp_new_i32();
10661 TCGv_i32 fp1 = tcg_temp_new_i32();
10662 gen_load_fpr32(ctx, fp0, fs);
10663 gen_load_fpr32(ctx, fp1, ft);
10664 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
10665 gen_store_fpr32(ctx, fp1, fd);
10666 tcg_temp_free_i32(fp1);
10667 tcg_temp_free_i32(fp0);
10668 } else {
10669 /* OPC_RSQRT2_S */
10670 check_cp1_64bitmode(ctx);
10672 TCGv_i32 fp0 = tcg_temp_new_i32();
10673 TCGv_i32 fp1 = tcg_temp_new_i32();
10675 gen_load_fpr32(ctx, fp0, fs);
10676 gen_load_fpr32(ctx, fp1, ft);
10677 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10678 tcg_temp_free_i32(fp1);
10679 gen_store_fpr32(ctx, fp0, fd);
10680 tcg_temp_free_i32(fp0);
10683 break;
10684 case OPC_CVT_D_S:
10685 check_cp1_registers(ctx, fd);
10687 TCGv_i32 fp32 = tcg_temp_new_i32();
10688 TCGv_i64 fp64 = tcg_temp_new_i64();
10690 gen_load_fpr32(ctx, fp32, fs);
10691 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
10692 tcg_temp_free_i32(fp32);
10693 gen_store_fpr64(ctx, fp64, fd);
10694 tcg_temp_free_i64(fp64);
10696 break;
10697 case OPC_CVT_W_S:
10699 TCGv_i32 fp0 = tcg_temp_new_i32();
10701 gen_load_fpr32(ctx, fp0, fs);
10702 if (ctx->nan2008) {
10703 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
10704 } else {
10705 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
10707 gen_store_fpr32(ctx, fp0, fd);
10708 tcg_temp_free_i32(fp0);
10710 break;
10711 case OPC_CVT_L_S:
10712 check_cp1_64bitmode(ctx);
10714 TCGv_i32 fp32 = tcg_temp_new_i32();
10715 TCGv_i64 fp64 = tcg_temp_new_i64();
10717 gen_load_fpr32(ctx, fp32, fs);
10718 if (ctx->nan2008) {
10719 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
10720 } else {
10721 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
10723 tcg_temp_free_i32(fp32);
10724 gen_store_fpr64(ctx, fp64, fd);
10725 tcg_temp_free_i64(fp64);
10727 break;
10728 case OPC_CVT_PS_S:
10729 check_ps(ctx);
10731 TCGv_i64 fp64 = tcg_temp_new_i64();
10732 TCGv_i32 fp32_0 = tcg_temp_new_i32();
10733 TCGv_i32 fp32_1 = tcg_temp_new_i32();
10735 gen_load_fpr32(ctx, fp32_0, fs);
10736 gen_load_fpr32(ctx, fp32_1, ft);
10737 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
10738 tcg_temp_free_i32(fp32_1);
10739 tcg_temp_free_i32(fp32_0);
10740 gen_store_fpr64(ctx, fp64, fd);
10741 tcg_temp_free_i64(fp64);
10743 break;
10744 case OPC_CMP_F_S:
10745 case OPC_CMP_UN_S:
10746 case OPC_CMP_EQ_S:
10747 case OPC_CMP_UEQ_S:
10748 case OPC_CMP_OLT_S:
10749 case OPC_CMP_ULT_S:
10750 case OPC_CMP_OLE_S:
10751 case OPC_CMP_ULE_S:
10752 case OPC_CMP_SF_S:
10753 case OPC_CMP_NGLE_S:
10754 case OPC_CMP_SEQ_S:
10755 case OPC_CMP_NGL_S:
10756 case OPC_CMP_LT_S:
10757 case OPC_CMP_NGE_S:
10758 case OPC_CMP_LE_S:
10759 case OPC_CMP_NGT_S:
10760 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10761 if (ctx->opcode & (1 << 6)) {
10762 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
10763 } else {
10764 gen_cmp_s(ctx, func - 48, ft, fs, cc);
10766 break;
10767 case OPC_ADD_D:
10768 check_cp1_registers(ctx, fs | ft | fd);
10770 TCGv_i64 fp0 = tcg_temp_new_i64();
10771 TCGv_i64 fp1 = tcg_temp_new_i64();
10773 gen_load_fpr64(ctx, fp0, fs);
10774 gen_load_fpr64(ctx, fp1, ft);
10775 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
10776 tcg_temp_free_i64(fp1);
10777 gen_store_fpr64(ctx, fp0, fd);
10778 tcg_temp_free_i64(fp0);
10780 break;
10781 case OPC_SUB_D:
10782 check_cp1_registers(ctx, fs | ft | fd);
10784 TCGv_i64 fp0 = tcg_temp_new_i64();
10785 TCGv_i64 fp1 = tcg_temp_new_i64();
10787 gen_load_fpr64(ctx, fp0, fs);
10788 gen_load_fpr64(ctx, fp1, ft);
10789 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
10790 tcg_temp_free_i64(fp1);
10791 gen_store_fpr64(ctx, fp0, fd);
10792 tcg_temp_free_i64(fp0);
10794 break;
10795 case OPC_MUL_D:
10796 check_cp1_registers(ctx, fs | ft | fd);
10798 TCGv_i64 fp0 = tcg_temp_new_i64();
10799 TCGv_i64 fp1 = tcg_temp_new_i64();
10801 gen_load_fpr64(ctx, fp0, fs);
10802 gen_load_fpr64(ctx, fp1, ft);
10803 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
10804 tcg_temp_free_i64(fp1);
10805 gen_store_fpr64(ctx, fp0, fd);
10806 tcg_temp_free_i64(fp0);
10808 break;
10809 case OPC_DIV_D:
10810 check_cp1_registers(ctx, fs | ft | fd);
10812 TCGv_i64 fp0 = tcg_temp_new_i64();
10813 TCGv_i64 fp1 = tcg_temp_new_i64();
10815 gen_load_fpr64(ctx, fp0, fs);
10816 gen_load_fpr64(ctx, fp1, ft);
10817 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
10818 tcg_temp_free_i64(fp1);
10819 gen_store_fpr64(ctx, fp0, fd);
10820 tcg_temp_free_i64(fp0);
10822 break;
10823 case OPC_SQRT_D:
10824 check_cp1_registers(ctx, fs | fd);
10826 TCGv_i64 fp0 = tcg_temp_new_i64();
10828 gen_load_fpr64(ctx, fp0, fs);
10829 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
10830 gen_store_fpr64(ctx, fp0, fd);
10831 tcg_temp_free_i64(fp0);
10833 break;
10834 case OPC_ABS_D:
10835 check_cp1_registers(ctx, fs | fd);
10837 TCGv_i64 fp0 = tcg_temp_new_i64();
10839 gen_load_fpr64(ctx, fp0, fs);
10840 if (ctx->abs2008) {
10841 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
10842 } else {
10843 gen_helper_float_abs_d(fp0, fp0);
10845 gen_store_fpr64(ctx, fp0, fd);
10846 tcg_temp_free_i64(fp0);
10848 break;
10849 case OPC_MOV_D:
10850 check_cp1_registers(ctx, fs | fd);
10852 TCGv_i64 fp0 = tcg_temp_new_i64();
10854 gen_load_fpr64(ctx, fp0, fs);
10855 gen_store_fpr64(ctx, fp0, fd);
10856 tcg_temp_free_i64(fp0);
10858 break;
10859 case OPC_NEG_D:
10860 check_cp1_registers(ctx, fs | fd);
10862 TCGv_i64 fp0 = tcg_temp_new_i64();
10864 gen_load_fpr64(ctx, fp0, fs);
10865 if (ctx->abs2008) {
10866 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10867 } else {
10868 gen_helper_float_chs_d(fp0, fp0);
10870 gen_store_fpr64(ctx, fp0, fd);
10871 tcg_temp_free_i64(fp0);
10873 break;
10874 case OPC_ROUND_L_D:
10875 check_cp1_64bitmode(ctx);
10877 TCGv_i64 fp0 = tcg_temp_new_i64();
10879 gen_load_fpr64(ctx, fp0, fs);
10880 if (ctx->nan2008) {
10881 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
10882 } else {
10883 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
10885 gen_store_fpr64(ctx, fp0, fd);
10886 tcg_temp_free_i64(fp0);
10888 break;
10889 case OPC_TRUNC_L_D:
10890 check_cp1_64bitmode(ctx);
10892 TCGv_i64 fp0 = tcg_temp_new_i64();
10894 gen_load_fpr64(ctx, fp0, fs);
10895 if (ctx->nan2008) {
10896 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10897 } else {
10898 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10900 gen_store_fpr64(ctx, fp0, fd);
10901 tcg_temp_free_i64(fp0);
10903 break;
10904 case OPC_CEIL_L_D:
10905 check_cp1_64bitmode(ctx);
10907 TCGv_i64 fp0 = tcg_temp_new_i64();
10909 gen_load_fpr64(ctx, fp0, fs);
10910 if (ctx->nan2008) {
10911 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10912 } else {
10913 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10915 gen_store_fpr64(ctx, fp0, fd);
10916 tcg_temp_free_i64(fp0);
10918 break;
10919 case OPC_FLOOR_L_D:
10920 check_cp1_64bitmode(ctx);
10922 TCGv_i64 fp0 = tcg_temp_new_i64();
10924 gen_load_fpr64(ctx, fp0, fs);
10925 if (ctx->nan2008) {
10926 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10927 } else {
10928 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10930 gen_store_fpr64(ctx, fp0, fd);
10931 tcg_temp_free_i64(fp0);
10933 break;
10934 case OPC_ROUND_W_D:
10935 check_cp1_registers(ctx, fs);
10937 TCGv_i32 fp32 = tcg_temp_new_i32();
10938 TCGv_i64 fp64 = tcg_temp_new_i64();
10940 gen_load_fpr64(ctx, fp64, fs);
10941 if (ctx->nan2008) {
10942 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10943 } else {
10944 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10946 tcg_temp_free_i64(fp64);
10947 gen_store_fpr32(ctx, fp32, fd);
10948 tcg_temp_free_i32(fp32);
10950 break;
10951 case OPC_TRUNC_W_D:
10952 check_cp1_registers(ctx, fs);
10954 TCGv_i32 fp32 = tcg_temp_new_i32();
10955 TCGv_i64 fp64 = tcg_temp_new_i64();
10957 gen_load_fpr64(ctx, fp64, fs);
10958 if (ctx->nan2008) {
10959 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
10960 } else {
10961 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
10963 tcg_temp_free_i64(fp64);
10964 gen_store_fpr32(ctx, fp32, fd);
10965 tcg_temp_free_i32(fp32);
10967 break;
10968 case OPC_CEIL_W_D:
10969 check_cp1_registers(ctx, fs);
10971 TCGv_i32 fp32 = tcg_temp_new_i32();
10972 TCGv_i64 fp64 = tcg_temp_new_i64();
10974 gen_load_fpr64(ctx, fp64, fs);
10975 if (ctx->nan2008) {
10976 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
10977 } else {
10978 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
10980 tcg_temp_free_i64(fp64);
10981 gen_store_fpr32(ctx, fp32, fd);
10982 tcg_temp_free_i32(fp32);
10984 break;
10985 case OPC_FLOOR_W_D:
10986 check_cp1_registers(ctx, fs);
10988 TCGv_i32 fp32 = tcg_temp_new_i32();
10989 TCGv_i64 fp64 = tcg_temp_new_i64();
10991 gen_load_fpr64(ctx, fp64, fs);
10992 if (ctx->nan2008) {
10993 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
10994 } else {
10995 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
10997 tcg_temp_free_i64(fp64);
10998 gen_store_fpr32(ctx, fp32, fd);
10999 tcg_temp_free_i32(fp32);
11001 break;
11002 case OPC_SEL_D:
11003 check_insn(ctx, ISA_MIPS_R6);
11004 gen_sel_d(ctx, op1, fd, ft, fs);
11005 break;
11006 case OPC_SELEQZ_D:
11007 check_insn(ctx, ISA_MIPS_R6);
11008 gen_sel_d(ctx, op1, fd, ft, fs);
11009 break;
11010 case OPC_SELNEZ_D:
11011 check_insn(ctx, ISA_MIPS_R6);
11012 gen_sel_d(ctx, op1, fd, ft, fs);
11013 break;
11014 case OPC_MOVCF_D:
11015 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11016 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11017 break;
11018 case OPC_MOVZ_D:
11019 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11021 TCGLabel *l1 = gen_new_label();
11022 TCGv_i64 fp0;
11024 if (ft != 0) {
11025 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11027 fp0 = tcg_temp_new_i64();
11028 gen_load_fpr64(ctx, fp0, fs);
11029 gen_store_fpr64(ctx, fp0, fd);
11030 tcg_temp_free_i64(fp0);
11031 gen_set_label(l1);
11033 break;
11034 case OPC_MOVN_D:
11035 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11037 TCGLabel *l1 = gen_new_label();
11038 TCGv_i64 fp0;
11040 if (ft != 0) {
11041 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11042 fp0 = tcg_temp_new_i64();
11043 gen_load_fpr64(ctx, fp0, fs);
11044 gen_store_fpr64(ctx, fp0, fd);
11045 tcg_temp_free_i64(fp0);
11046 gen_set_label(l1);
11049 break;
11050 case OPC_RECIP_D:
11051 check_cp1_registers(ctx, fs | fd);
11053 TCGv_i64 fp0 = tcg_temp_new_i64();
11055 gen_load_fpr64(ctx, fp0, fs);
11056 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11057 gen_store_fpr64(ctx, fp0, fd);
11058 tcg_temp_free_i64(fp0);
11060 break;
11061 case OPC_RSQRT_D:
11062 check_cp1_registers(ctx, fs | fd);
11064 TCGv_i64 fp0 = tcg_temp_new_i64();
11066 gen_load_fpr64(ctx, fp0, fs);
11067 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11068 gen_store_fpr64(ctx, fp0, fd);
11069 tcg_temp_free_i64(fp0);
11071 break;
11072 case OPC_MADDF_D:
11073 check_insn(ctx, ISA_MIPS_R6);
11075 TCGv_i64 fp0 = tcg_temp_new_i64();
11076 TCGv_i64 fp1 = tcg_temp_new_i64();
11077 TCGv_i64 fp2 = tcg_temp_new_i64();
11078 gen_load_fpr64(ctx, fp0, fs);
11079 gen_load_fpr64(ctx, fp1, ft);
11080 gen_load_fpr64(ctx, fp2, fd);
11081 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11082 gen_store_fpr64(ctx, fp2, fd);
11083 tcg_temp_free_i64(fp2);
11084 tcg_temp_free_i64(fp1);
11085 tcg_temp_free_i64(fp0);
11087 break;
11088 case OPC_MSUBF_D:
11089 check_insn(ctx, ISA_MIPS_R6);
11091 TCGv_i64 fp0 = tcg_temp_new_i64();
11092 TCGv_i64 fp1 = tcg_temp_new_i64();
11093 TCGv_i64 fp2 = tcg_temp_new_i64();
11094 gen_load_fpr64(ctx, fp0, fs);
11095 gen_load_fpr64(ctx, fp1, ft);
11096 gen_load_fpr64(ctx, fp2, fd);
11097 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11098 gen_store_fpr64(ctx, fp2, fd);
11099 tcg_temp_free_i64(fp2);
11100 tcg_temp_free_i64(fp1);
11101 tcg_temp_free_i64(fp0);
11103 break;
11104 case OPC_RINT_D:
11105 check_insn(ctx, ISA_MIPS_R6);
11107 TCGv_i64 fp0 = tcg_temp_new_i64();
11108 gen_load_fpr64(ctx, fp0, fs);
11109 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11110 gen_store_fpr64(ctx, fp0, fd);
11111 tcg_temp_free_i64(fp0);
11113 break;
11114 case OPC_CLASS_D:
11115 check_insn(ctx, ISA_MIPS_R6);
11117 TCGv_i64 fp0 = tcg_temp_new_i64();
11118 gen_load_fpr64(ctx, fp0, fs);
11119 gen_helper_float_class_d(fp0, cpu_env, fp0);
11120 gen_store_fpr64(ctx, fp0, fd);
11121 tcg_temp_free_i64(fp0);
11123 break;
11124 case OPC_MIN_D: /* OPC_RECIP2_D */
11125 if (ctx->insn_flags & ISA_MIPS_R6) {
11126 /* OPC_MIN_D */
11127 TCGv_i64 fp0 = tcg_temp_new_i64();
11128 TCGv_i64 fp1 = tcg_temp_new_i64();
11129 gen_load_fpr64(ctx, fp0, fs);
11130 gen_load_fpr64(ctx, fp1, ft);
11131 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11132 gen_store_fpr64(ctx, fp1, fd);
11133 tcg_temp_free_i64(fp1);
11134 tcg_temp_free_i64(fp0);
11135 } else {
11136 /* OPC_RECIP2_D */
11137 check_cp1_64bitmode(ctx);
11139 TCGv_i64 fp0 = tcg_temp_new_i64();
11140 TCGv_i64 fp1 = tcg_temp_new_i64();
11142 gen_load_fpr64(ctx, fp0, fs);
11143 gen_load_fpr64(ctx, fp1, ft);
11144 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11145 tcg_temp_free_i64(fp1);
11146 gen_store_fpr64(ctx, fp0, fd);
11147 tcg_temp_free_i64(fp0);
11150 break;
11151 case OPC_MINA_D: /* OPC_RECIP1_D */
11152 if (ctx->insn_flags & ISA_MIPS_R6) {
11153 /* OPC_MINA_D */
11154 TCGv_i64 fp0 = tcg_temp_new_i64();
11155 TCGv_i64 fp1 = tcg_temp_new_i64();
11156 gen_load_fpr64(ctx, fp0, fs);
11157 gen_load_fpr64(ctx, fp1, ft);
11158 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11159 gen_store_fpr64(ctx, fp1, fd);
11160 tcg_temp_free_i64(fp1);
11161 tcg_temp_free_i64(fp0);
11162 } else {
11163 /* OPC_RECIP1_D */
11164 check_cp1_64bitmode(ctx);
11166 TCGv_i64 fp0 = tcg_temp_new_i64();
11168 gen_load_fpr64(ctx, fp0, fs);
11169 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11170 gen_store_fpr64(ctx, fp0, fd);
11171 tcg_temp_free_i64(fp0);
11174 break;
11175 case OPC_MAX_D: /* OPC_RSQRT1_D */
11176 if (ctx->insn_flags & ISA_MIPS_R6) {
11177 /* OPC_MAX_D */
11178 TCGv_i64 fp0 = tcg_temp_new_i64();
11179 TCGv_i64 fp1 = tcg_temp_new_i64();
11180 gen_load_fpr64(ctx, fp0, fs);
11181 gen_load_fpr64(ctx, fp1, ft);
11182 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11183 gen_store_fpr64(ctx, fp1, fd);
11184 tcg_temp_free_i64(fp1);
11185 tcg_temp_free_i64(fp0);
11186 } else {
11187 /* OPC_RSQRT1_D */
11188 check_cp1_64bitmode(ctx);
11190 TCGv_i64 fp0 = tcg_temp_new_i64();
11192 gen_load_fpr64(ctx, fp0, fs);
11193 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11194 gen_store_fpr64(ctx, fp0, fd);
11195 tcg_temp_free_i64(fp0);
11198 break;
11199 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11200 if (ctx->insn_flags & ISA_MIPS_R6) {
11201 /* OPC_MAXA_D */
11202 TCGv_i64 fp0 = tcg_temp_new_i64();
11203 TCGv_i64 fp1 = tcg_temp_new_i64();
11204 gen_load_fpr64(ctx, fp0, fs);
11205 gen_load_fpr64(ctx, fp1, ft);
11206 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11207 gen_store_fpr64(ctx, fp1, fd);
11208 tcg_temp_free_i64(fp1);
11209 tcg_temp_free_i64(fp0);
11210 } else {
11211 /* OPC_RSQRT2_D */
11212 check_cp1_64bitmode(ctx);
11214 TCGv_i64 fp0 = tcg_temp_new_i64();
11215 TCGv_i64 fp1 = tcg_temp_new_i64();
11217 gen_load_fpr64(ctx, fp0, fs);
11218 gen_load_fpr64(ctx, fp1, ft);
11219 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11220 tcg_temp_free_i64(fp1);
11221 gen_store_fpr64(ctx, fp0, fd);
11222 tcg_temp_free_i64(fp0);
11225 break;
11226 case OPC_CMP_F_D:
11227 case OPC_CMP_UN_D:
11228 case OPC_CMP_EQ_D:
11229 case OPC_CMP_UEQ_D:
11230 case OPC_CMP_OLT_D:
11231 case OPC_CMP_ULT_D:
11232 case OPC_CMP_OLE_D:
11233 case OPC_CMP_ULE_D:
11234 case OPC_CMP_SF_D:
11235 case OPC_CMP_NGLE_D:
11236 case OPC_CMP_SEQ_D:
11237 case OPC_CMP_NGL_D:
11238 case OPC_CMP_LT_D:
11239 case OPC_CMP_NGE_D:
11240 case OPC_CMP_LE_D:
11241 case OPC_CMP_NGT_D:
11242 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11243 if (ctx->opcode & (1 << 6)) {
11244 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
11245 } else {
11246 gen_cmp_d(ctx, func - 48, ft, fs, cc);
11248 break;
11249 case OPC_CVT_S_D:
11250 check_cp1_registers(ctx, fs);
11252 TCGv_i32 fp32 = tcg_temp_new_i32();
11253 TCGv_i64 fp64 = tcg_temp_new_i64();
11255 gen_load_fpr64(ctx, fp64, fs);
11256 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11257 tcg_temp_free_i64(fp64);
11258 gen_store_fpr32(ctx, fp32, fd);
11259 tcg_temp_free_i32(fp32);
11261 break;
11262 case OPC_CVT_W_D:
11263 check_cp1_registers(ctx, fs);
11265 TCGv_i32 fp32 = tcg_temp_new_i32();
11266 TCGv_i64 fp64 = tcg_temp_new_i64();
11268 gen_load_fpr64(ctx, fp64, fs);
11269 if (ctx->nan2008) {
11270 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11271 } else {
11272 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11274 tcg_temp_free_i64(fp64);
11275 gen_store_fpr32(ctx, fp32, fd);
11276 tcg_temp_free_i32(fp32);
11278 break;
11279 case OPC_CVT_L_D:
11280 check_cp1_64bitmode(ctx);
11282 TCGv_i64 fp0 = tcg_temp_new_i64();
11284 gen_load_fpr64(ctx, fp0, fs);
11285 if (ctx->nan2008) {
11286 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11287 } else {
11288 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11290 gen_store_fpr64(ctx, fp0, fd);
11291 tcg_temp_free_i64(fp0);
11293 break;
11294 case OPC_CVT_S_W:
11296 TCGv_i32 fp0 = tcg_temp_new_i32();
11298 gen_load_fpr32(ctx, fp0, fs);
11299 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11300 gen_store_fpr32(ctx, fp0, fd);
11301 tcg_temp_free_i32(fp0);
11303 break;
11304 case OPC_CVT_D_W:
11305 check_cp1_registers(ctx, fd);
11307 TCGv_i32 fp32 = tcg_temp_new_i32();
11308 TCGv_i64 fp64 = tcg_temp_new_i64();
11310 gen_load_fpr32(ctx, fp32, fs);
11311 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11312 tcg_temp_free_i32(fp32);
11313 gen_store_fpr64(ctx, fp64, fd);
11314 tcg_temp_free_i64(fp64);
11316 break;
11317 case OPC_CVT_S_L:
11318 check_cp1_64bitmode(ctx);
11320 TCGv_i32 fp32 = tcg_temp_new_i32();
11321 TCGv_i64 fp64 = tcg_temp_new_i64();
11323 gen_load_fpr64(ctx, fp64, fs);
11324 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11325 tcg_temp_free_i64(fp64);
11326 gen_store_fpr32(ctx, fp32, fd);
11327 tcg_temp_free_i32(fp32);
11329 break;
11330 case OPC_CVT_D_L:
11331 check_cp1_64bitmode(ctx);
11333 TCGv_i64 fp0 = tcg_temp_new_i64();
11335 gen_load_fpr64(ctx, fp0, fs);
11336 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11337 gen_store_fpr64(ctx, fp0, fd);
11338 tcg_temp_free_i64(fp0);
11340 break;
11341 case OPC_CVT_PS_PW:
11342 check_ps(ctx);
11344 TCGv_i64 fp0 = tcg_temp_new_i64();
11346 gen_load_fpr64(ctx, fp0, fs);
11347 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11348 gen_store_fpr64(ctx, fp0, fd);
11349 tcg_temp_free_i64(fp0);
11351 break;
11352 case OPC_ADD_PS:
11353 check_ps(ctx);
11355 TCGv_i64 fp0 = tcg_temp_new_i64();
11356 TCGv_i64 fp1 = tcg_temp_new_i64();
11358 gen_load_fpr64(ctx, fp0, fs);
11359 gen_load_fpr64(ctx, fp1, ft);
11360 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11361 tcg_temp_free_i64(fp1);
11362 gen_store_fpr64(ctx, fp0, fd);
11363 tcg_temp_free_i64(fp0);
11365 break;
11366 case OPC_SUB_PS:
11367 check_ps(ctx);
11369 TCGv_i64 fp0 = tcg_temp_new_i64();
11370 TCGv_i64 fp1 = tcg_temp_new_i64();
11372 gen_load_fpr64(ctx, fp0, fs);
11373 gen_load_fpr64(ctx, fp1, ft);
11374 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11375 tcg_temp_free_i64(fp1);
11376 gen_store_fpr64(ctx, fp0, fd);
11377 tcg_temp_free_i64(fp0);
11379 break;
11380 case OPC_MUL_PS:
11381 check_ps(ctx);
11383 TCGv_i64 fp0 = tcg_temp_new_i64();
11384 TCGv_i64 fp1 = tcg_temp_new_i64();
11386 gen_load_fpr64(ctx, fp0, fs);
11387 gen_load_fpr64(ctx, fp1, ft);
11388 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11389 tcg_temp_free_i64(fp1);
11390 gen_store_fpr64(ctx, fp0, fd);
11391 tcg_temp_free_i64(fp0);
11393 break;
11394 case OPC_ABS_PS:
11395 check_ps(ctx);
11397 TCGv_i64 fp0 = tcg_temp_new_i64();
11399 gen_load_fpr64(ctx, fp0, fs);
11400 gen_helper_float_abs_ps(fp0, fp0);
11401 gen_store_fpr64(ctx, fp0, fd);
11402 tcg_temp_free_i64(fp0);
11404 break;
11405 case OPC_MOV_PS:
11406 check_ps(ctx);
11408 TCGv_i64 fp0 = tcg_temp_new_i64();
11410 gen_load_fpr64(ctx, fp0, fs);
11411 gen_store_fpr64(ctx, fp0, fd);
11412 tcg_temp_free_i64(fp0);
11414 break;
11415 case OPC_NEG_PS:
11416 check_ps(ctx);
11418 TCGv_i64 fp0 = tcg_temp_new_i64();
11420 gen_load_fpr64(ctx, fp0, fs);
11421 gen_helper_float_chs_ps(fp0, fp0);
11422 gen_store_fpr64(ctx, fp0, fd);
11423 tcg_temp_free_i64(fp0);
11425 break;
11426 case OPC_MOVCF_PS:
11427 check_ps(ctx);
11428 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11429 break;
11430 case OPC_MOVZ_PS:
11431 check_ps(ctx);
11433 TCGLabel *l1 = gen_new_label();
11434 TCGv_i64 fp0;
11436 if (ft != 0) {
11437 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11439 fp0 = tcg_temp_new_i64();
11440 gen_load_fpr64(ctx, fp0, fs);
11441 gen_store_fpr64(ctx, fp0, fd);
11442 tcg_temp_free_i64(fp0);
11443 gen_set_label(l1);
11445 break;
11446 case OPC_MOVN_PS:
11447 check_ps(ctx);
11449 TCGLabel *l1 = gen_new_label();
11450 TCGv_i64 fp0;
11452 if (ft != 0) {
11453 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11454 fp0 = tcg_temp_new_i64();
11455 gen_load_fpr64(ctx, fp0, fs);
11456 gen_store_fpr64(ctx, fp0, fd);
11457 tcg_temp_free_i64(fp0);
11458 gen_set_label(l1);
11461 break;
11462 case OPC_ADDR_PS:
11463 check_ps(ctx);
11465 TCGv_i64 fp0 = tcg_temp_new_i64();
11466 TCGv_i64 fp1 = tcg_temp_new_i64();
11468 gen_load_fpr64(ctx, fp0, ft);
11469 gen_load_fpr64(ctx, fp1, fs);
11470 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11471 tcg_temp_free_i64(fp1);
11472 gen_store_fpr64(ctx, fp0, fd);
11473 tcg_temp_free_i64(fp0);
11475 break;
11476 case OPC_MULR_PS:
11477 check_ps(ctx);
11479 TCGv_i64 fp0 = tcg_temp_new_i64();
11480 TCGv_i64 fp1 = tcg_temp_new_i64();
11482 gen_load_fpr64(ctx, fp0, ft);
11483 gen_load_fpr64(ctx, fp1, fs);
11484 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11485 tcg_temp_free_i64(fp1);
11486 gen_store_fpr64(ctx, fp0, fd);
11487 tcg_temp_free_i64(fp0);
11489 break;
11490 case OPC_RECIP2_PS:
11491 check_ps(ctx);
11493 TCGv_i64 fp0 = tcg_temp_new_i64();
11494 TCGv_i64 fp1 = tcg_temp_new_i64();
11496 gen_load_fpr64(ctx, fp0, fs);
11497 gen_load_fpr64(ctx, fp1, ft);
11498 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11499 tcg_temp_free_i64(fp1);
11500 gen_store_fpr64(ctx, fp0, fd);
11501 tcg_temp_free_i64(fp0);
11503 break;
11504 case OPC_RECIP1_PS:
11505 check_ps(ctx);
11507 TCGv_i64 fp0 = tcg_temp_new_i64();
11509 gen_load_fpr64(ctx, fp0, fs);
11510 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11511 gen_store_fpr64(ctx, fp0, fd);
11512 tcg_temp_free_i64(fp0);
11514 break;
11515 case OPC_RSQRT1_PS:
11516 check_ps(ctx);
11518 TCGv_i64 fp0 = tcg_temp_new_i64();
11520 gen_load_fpr64(ctx, fp0, fs);
11521 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11522 gen_store_fpr64(ctx, fp0, fd);
11523 tcg_temp_free_i64(fp0);
11525 break;
11526 case OPC_RSQRT2_PS:
11527 check_ps(ctx);
11529 TCGv_i64 fp0 = tcg_temp_new_i64();
11530 TCGv_i64 fp1 = tcg_temp_new_i64();
11532 gen_load_fpr64(ctx, fp0, fs);
11533 gen_load_fpr64(ctx, fp1, ft);
11534 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11535 tcg_temp_free_i64(fp1);
11536 gen_store_fpr64(ctx, fp0, fd);
11537 tcg_temp_free_i64(fp0);
11539 break;
11540 case OPC_CVT_S_PU:
11541 check_cp1_64bitmode(ctx);
11543 TCGv_i32 fp0 = tcg_temp_new_i32();
11545 gen_load_fpr32h(ctx, fp0, fs);
11546 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11547 gen_store_fpr32(ctx, fp0, fd);
11548 tcg_temp_free_i32(fp0);
11550 break;
11551 case OPC_CVT_PW_PS:
11552 check_ps(ctx);
11554 TCGv_i64 fp0 = tcg_temp_new_i64();
11556 gen_load_fpr64(ctx, fp0, fs);
11557 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11558 gen_store_fpr64(ctx, fp0, fd);
11559 tcg_temp_free_i64(fp0);
11561 break;
11562 case OPC_CVT_S_PL:
11563 check_cp1_64bitmode(ctx);
11565 TCGv_i32 fp0 = tcg_temp_new_i32();
11567 gen_load_fpr32(ctx, fp0, fs);
11568 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11569 gen_store_fpr32(ctx, fp0, fd);
11570 tcg_temp_free_i32(fp0);
11572 break;
11573 case OPC_PLL_PS:
11574 check_ps(ctx);
11576 TCGv_i32 fp0 = tcg_temp_new_i32();
11577 TCGv_i32 fp1 = tcg_temp_new_i32();
11579 gen_load_fpr32(ctx, fp0, fs);
11580 gen_load_fpr32(ctx, fp1, ft);
11581 gen_store_fpr32h(ctx, fp0, fd);
11582 gen_store_fpr32(ctx, fp1, fd);
11583 tcg_temp_free_i32(fp0);
11584 tcg_temp_free_i32(fp1);
11586 break;
11587 case OPC_PLU_PS:
11588 check_ps(ctx);
11590 TCGv_i32 fp0 = tcg_temp_new_i32();
11591 TCGv_i32 fp1 = tcg_temp_new_i32();
11593 gen_load_fpr32(ctx, fp0, fs);
11594 gen_load_fpr32h(ctx, fp1, ft);
11595 gen_store_fpr32(ctx, fp1, fd);
11596 gen_store_fpr32h(ctx, fp0, fd);
11597 tcg_temp_free_i32(fp0);
11598 tcg_temp_free_i32(fp1);
11600 break;
11601 case OPC_PUL_PS:
11602 check_ps(ctx);
11604 TCGv_i32 fp0 = tcg_temp_new_i32();
11605 TCGv_i32 fp1 = tcg_temp_new_i32();
11607 gen_load_fpr32h(ctx, fp0, fs);
11608 gen_load_fpr32(ctx, fp1, ft);
11609 gen_store_fpr32(ctx, fp1, fd);
11610 gen_store_fpr32h(ctx, fp0, fd);
11611 tcg_temp_free_i32(fp0);
11612 tcg_temp_free_i32(fp1);
11614 break;
11615 case OPC_PUU_PS:
11616 check_ps(ctx);
11618 TCGv_i32 fp0 = tcg_temp_new_i32();
11619 TCGv_i32 fp1 = tcg_temp_new_i32();
11621 gen_load_fpr32h(ctx, fp0, fs);
11622 gen_load_fpr32h(ctx, fp1, ft);
11623 gen_store_fpr32(ctx, fp1, fd);
11624 gen_store_fpr32h(ctx, fp0, fd);
11625 tcg_temp_free_i32(fp0);
11626 tcg_temp_free_i32(fp1);
11628 break;
11629 case OPC_CMP_F_PS:
11630 case OPC_CMP_UN_PS:
11631 case OPC_CMP_EQ_PS:
11632 case OPC_CMP_UEQ_PS:
11633 case OPC_CMP_OLT_PS:
11634 case OPC_CMP_ULT_PS:
11635 case OPC_CMP_OLE_PS:
11636 case OPC_CMP_ULE_PS:
11637 case OPC_CMP_SF_PS:
11638 case OPC_CMP_NGLE_PS:
11639 case OPC_CMP_SEQ_PS:
11640 case OPC_CMP_NGL_PS:
11641 case OPC_CMP_LT_PS:
11642 case OPC_CMP_NGE_PS:
11643 case OPC_CMP_LE_PS:
11644 case OPC_CMP_NGT_PS:
11645 if (ctx->opcode & (1 << 6)) {
11646 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
11647 } else {
11648 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
11650 break;
11651 default:
11652 MIPS_INVAL("farith");
11653 gen_reserved_instruction(ctx);
11654 return;
11658 /* Coprocessor 3 (FPU) */
11659 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
11660 int fd, int fs, int base, int index)
11662 TCGv t0 = tcg_temp_new();
11664 if (base == 0) {
11665 gen_load_gpr(t0, index);
11666 } else if (index == 0) {
11667 gen_load_gpr(t0, base);
11668 } else {
11669 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
11672 * Don't do NOP if destination is zero: we must perform the actual
11673 * memory access.
11675 switch (opc) {
11676 case OPC_LWXC1:
11677 check_cop1x(ctx);
11679 TCGv_i32 fp0 = tcg_temp_new_i32();
11681 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
11682 tcg_gen_trunc_tl_i32(fp0, t0);
11683 gen_store_fpr32(ctx, fp0, fd);
11684 tcg_temp_free_i32(fp0);
11686 break;
11687 case OPC_LDXC1:
11688 check_cop1x(ctx);
11689 check_cp1_registers(ctx, fd);
11691 TCGv_i64 fp0 = tcg_temp_new_i64();
11692 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11693 gen_store_fpr64(ctx, fp0, fd);
11694 tcg_temp_free_i64(fp0);
11696 break;
11697 case OPC_LUXC1:
11698 check_cp1_64bitmode(ctx);
11699 tcg_gen_andi_tl(t0, t0, ~0x7);
11701 TCGv_i64 fp0 = tcg_temp_new_i64();
11703 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11704 gen_store_fpr64(ctx, fp0, fd);
11705 tcg_temp_free_i64(fp0);
11707 break;
11708 case OPC_SWXC1:
11709 check_cop1x(ctx);
11711 TCGv_i32 fp0 = tcg_temp_new_i32();
11712 gen_load_fpr32(ctx, fp0, fs);
11713 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
11714 tcg_temp_free_i32(fp0);
11716 break;
11717 case OPC_SDXC1:
11718 check_cop1x(ctx);
11719 check_cp1_registers(ctx, fs);
11721 TCGv_i64 fp0 = tcg_temp_new_i64();
11722 gen_load_fpr64(ctx, fp0, fs);
11723 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11724 tcg_temp_free_i64(fp0);
11726 break;
11727 case OPC_SUXC1:
11728 check_cp1_64bitmode(ctx);
11729 tcg_gen_andi_tl(t0, t0, ~0x7);
11731 TCGv_i64 fp0 = tcg_temp_new_i64();
11732 gen_load_fpr64(ctx, fp0, fs);
11733 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11734 tcg_temp_free_i64(fp0);
11736 break;
11738 tcg_temp_free(t0);
11741 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
11742 int fd, int fr, int fs, int ft)
11744 switch (opc) {
11745 case OPC_ALNV_PS:
11746 check_ps(ctx);
11748 TCGv t0 = tcg_temp_local_new();
11749 TCGv_i32 fp = tcg_temp_new_i32();
11750 TCGv_i32 fph = tcg_temp_new_i32();
11751 TCGLabel *l1 = gen_new_label();
11752 TCGLabel *l2 = gen_new_label();
11754 gen_load_gpr(t0, fr);
11755 tcg_gen_andi_tl(t0, t0, 0x7);
11757 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
11758 gen_load_fpr32(ctx, fp, fs);
11759 gen_load_fpr32h(ctx, fph, fs);
11760 gen_store_fpr32(ctx, fp, fd);
11761 gen_store_fpr32h(ctx, fph, fd);
11762 tcg_gen_br(l2);
11763 gen_set_label(l1);
11764 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
11765 tcg_temp_free(t0);
11766 #ifdef TARGET_WORDS_BIGENDIAN
11767 gen_load_fpr32(ctx, fp, fs);
11768 gen_load_fpr32h(ctx, fph, ft);
11769 gen_store_fpr32h(ctx, fp, fd);
11770 gen_store_fpr32(ctx, fph, fd);
11771 #else
11772 gen_load_fpr32h(ctx, fph, fs);
11773 gen_load_fpr32(ctx, fp, ft);
11774 gen_store_fpr32(ctx, fph, fd);
11775 gen_store_fpr32h(ctx, fp, fd);
11776 #endif
11777 gen_set_label(l2);
11778 tcg_temp_free_i32(fp);
11779 tcg_temp_free_i32(fph);
11781 break;
11782 case OPC_MADD_S:
11783 check_cop1x(ctx);
11785 TCGv_i32 fp0 = tcg_temp_new_i32();
11786 TCGv_i32 fp1 = tcg_temp_new_i32();
11787 TCGv_i32 fp2 = tcg_temp_new_i32();
11789 gen_load_fpr32(ctx, fp0, fs);
11790 gen_load_fpr32(ctx, fp1, ft);
11791 gen_load_fpr32(ctx, fp2, fr);
11792 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
11793 tcg_temp_free_i32(fp0);
11794 tcg_temp_free_i32(fp1);
11795 gen_store_fpr32(ctx, fp2, fd);
11796 tcg_temp_free_i32(fp2);
11798 break;
11799 case OPC_MADD_D:
11800 check_cop1x(ctx);
11801 check_cp1_registers(ctx, fd | fs | ft | fr);
11803 TCGv_i64 fp0 = tcg_temp_new_i64();
11804 TCGv_i64 fp1 = tcg_temp_new_i64();
11805 TCGv_i64 fp2 = tcg_temp_new_i64();
11807 gen_load_fpr64(ctx, fp0, fs);
11808 gen_load_fpr64(ctx, fp1, ft);
11809 gen_load_fpr64(ctx, fp2, fr);
11810 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
11811 tcg_temp_free_i64(fp0);
11812 tcg_temp_free_i64(fp1);
11813 gen_store_fpr64(ctx, fp2, fd);
11814 tcg_temp_free_i64(fp2);
11816 break;
11817 case OPC_MADD_PS:
11818 check_ps(ctx);
11820 TCGv_i64 fp0 = tcg_temp_new_i64();
11821 TCGv_i64 fp1 = tcg_temp_new_i64();
11822 TCGv_i64 fp2 = tcg_temp_new_i64();
11824 gen_load_fpr64(ctx, fp0, fs);
11825 gen_load_fpr64(ctx, fp1, ft);
11826 gen_load_fpr64(ctx, fp2, fr);
11827 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
11828 tcg_temp_free_i64(fp0);
11829 tcg_temp_free_i64(fp1);
11830 gen_store_fpr64(ctx, fp2, fd);
11831 tcg_temp_free_i64(fp2);
11833 break;
11834 case OPC_MSUB_S:
11835 check_cop1x(ctx);
11837 TCGv_i32 fp0 = tcg_temp_new_i32();
11838 TCGv_i32 fp1 = tcg_temp_new_i32();
11839 TCGv_i32 fp2 = tcg_temp_new_i32();
11841 gen_load_fpr32(ctx, fp0, fs);
11842 gen_load_fpr32(ctx, fp1, ft);
11843 gen_load_fpr32(ctx, fp2, fr);
11844 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
11845 tcg_temp_free_i32(fp0);
11846 tcg_temp_free_i32(fp1);
11847 gen_store_fpr32(ctx, fp2, fd);
11848 tcg_temp_free_i32(fp2);
11850 break;
11851 case OPC_MSUB_D:
11852 check_cop1x(ctx);
11853 check_cp1_registers(ctx, fd | fs | ft | fr);
11855 TCGv_i64 fp0 = tcg_temp_new_i64();
11856 TCGv_i64 fp1 = tcg_temp_new_i64();
11857 TCGv_i64 fp2 = tcg_temp_new_i64();
11859 gen_load_fpr64(ctx, fp0, fs);
11860 gen_load_fpr64(ctx, fp1, ft);
11861 gen_load_fpr64(ctx, fp2, fr);
11862 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
11863 tcg_temp_free_i64(fp0);
11864 tcg_temp_free_i64(fp1);
11865 gen_store_fpr64(ctx, fp2, fd);
11866 tcg_temp_free_i64(fp2);
11868 break;
11869 case OPC_MSUB_PS:
11870 check_ps(ctx);
11872 TCGv_i64 fp0 = tcg_temp_new_i64();
11873 TCGv_i64 fp1 = tcg_temp_new_i64();
11874 TCGv_i64 fp2 = tcg_temp_new_i64();
11876 gen_load_fpr64(ctx, fp0, fs);
11877 gen_load_fpr64(ctx, fp1, ft);
11878 gen_load_fpr64(ctx, fp2, fr);
11879 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
11880 tcg_temp_free_i64(fp0);
11881 tcg_temp_free_i64(fp1);
11882 gen_store_fpr64(ctx, fp2, fd);
11883 tcg_temp_free_i64(fp2);
11885 break;
11886 case OPC_NMADD_S:
11887 check_cop1x(ctx);
11889 TCGv_i32 fp0 = tcg_temp_new_i32();
11890 TCGv_i32 fp1 = tcg_temp_new_i32();
11891 TCGv_i32 fp2 = tcg_temp_new_i32();
11893 gen_load_fpr32(ctx, fp0, fs);
11894 gen_load_fpr32(ctx, fp1, ft);
11895 gen_load_fpr32(ctx, fp2, fr);
11896 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
11897 tcg_temp_free_i32(fp0);
11898 tcg_temp_free_i32(fp1);
11899 gen_store_fpr32(ctx, fp2, fd);
11900 tcg_temp_free_i32(fp2);
11902 break;
11903 case OPC_NMADD_D:
11904 check_cop1x(ctx);
11905 check_cp1_registers(ctx, fd | fs | ft | fr);
11907 TCGv_i64 fp0 = tcg_temp_new_i64();
11908 TCGv_i64 fp1 = tcg_temp_new_i64();
11909 TCGv_i64 fp2 = tcg_temp_new_i64();
11911 gen_load_fpr64(ctx, fp0, fs);
11912 gen_load_fpr64(ctx, fp1, ft);
11913 gen_load_fpr64(ctx, fp2, fr);
11914 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
11915 tcg_temp_free_i64(fp0);
11916 tcg_temp_free_i64(fp1);
11917 gen_store_fpr64(ctx, fp2, fd);
11918 tcg_temp_free_i64(fp2);
11920 break;
11921 case OPC_NMADD_PS:
11922 check_ps(ctx);
11924 TCGv_i64 fp0 = tcg_temp_new_i64();
11925 TCGv_i64 fp1 = tcg_temp_new_i64();
11926 TCGv_i64 fp2 = tcg_temp_new_i64();
11928 gen_load_fpr64(ctx, fp0, fs);
11929 gen_load_fpr64(ctx, fp1, ft);
11930 gen_load_fpr64(ctx, fp2, fr);
11931 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
11932 tcg_temp_free_i64(fp0);
11933 tcg_temp_free_i64(fp1);
11934 gen_store_fpr64(ctx, fp2, fd);
11935 tcg_temp_free_i64(fp2);
11937 break;
11938 case OPC_NMSUB_S:
11939 check_cop1x(ctx);
11941 TCGv_i32 fp0 = tcg_temp_new_i32();
11942 TCGv_i32 fp1 = tcg_temp_new_i32();
11943 TCGv_i32 fp2 = tcg_temp_new_i32();
11945 gen_load_fpr32(ctx, fp0, fs);
11946 gen_load_fpr32(ctx, fp1, ft);
11947 gen_load_fpr32(ctx, fp2, fr);
11948 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
11949 tcg_temp_free_i32(fp0);
11950 tcg_temp_free_i32(fp1);
11951 gen_store_fpr32(ctx, fp2, fd);
11952 tcg_temp_free_i32(fp2);
11954 break;
11955 case OPC_NMSUB_D:
11956 check_cop1x(ctx);
11957 check_cp1_registers(ctx, fd | fs | ft | fr);
11959 TCGv_i64 fp0 = tcg_temp_new_i64();
11960 TCGv_i64 fp1 = tcg_temp_new_i64();
11961 TCGv_i64 fp2 = tcg_temp_new_i64();
11963 gen_load_fpr64(ctx, fp0, fs);
11964 gen_load_fpr64(ctx, fp1, ft);
11965 gen_load_fpr64(ctx, fp2, fr);
11966 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
11967 tcg_temp_free_i64(fp0);
11968 tcg_temp_free_i64(fp1);
11969 gen_store_fpr64(ctx, fp2, fd);
11970 tcg_temp_free_i64(fp2);
11972 break;
11973 case OPC_NMSUB_PS:
11974 check_ps(ctx);
11976 TCGv_i64 fp0 = tcg_temp_new_i64();
11977 TCGv_i64 fp1 = tcg_temp_new_i64();
11978 TCGv_i64 fp2 = tcg_temp_new_i64();
11980 gen_load_fpr64(ctx, fp0, fs);
11981 gen_load_fpr64(ctx, fp1, ft);
11982 gen_load_fpr64(ctx, fp2, fr);
11983 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
11984 tcg_temp_free_i64(fp0);
11985 tcg_temp_free_i64(fp1);
11986 gen_store_fpr64(ctx, fp2, fd);
11987 tcg_temp_free_i64(fp2);
11989 break;
11990 default:
11991 MIPS_INVAL("flt3_arith");
11992 gen_reserved_instruction(ctx);
11993 return;
11997 void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
11999 TCGv t0;
12001 #if !defined(CONFIG_USER_ONLY)
12003 * The Linux kernel will emulate rdhwr if it's not supported natively.
12004 * Therefore only check the ISA in system mode.
12006 check_insn(ctx, ISA_MIPS_R2);
12007 #endif
12008 t0 = tcg_temp_new();
12010 switch (rd) {
12011 case 0:
12012 gen_helper_rdhwr_cpunum(t0, cpu_env);
12013 gen_store_gpr(t0, rt);
12014 break;
12015 case 1:
12016 gen_helper_rdhwr_synci_step(t0, cpu_env);
12017 gen_store_gpr(t0, rt);
12018 break;
12019 case 2:
12020 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12021 gen_io_start();
12023 gen_helper_rdhwr_cc(t0, cpu_env);
12024 gen_store_gpr(t0, rt);
12026 * Break the TB to be able to take timer interrupts immediately
12027 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12028 * we break completely out of translated code.
12030 gen_save_pc(ctx->base.pc_next + 4);
12031 ctx->base.is_jmp = DISAS_EXIT;
12032 break;
12033 case 3:
12034 gen_helper_rdhwr_ccres(t0, cpu_env);
12035 gen_store_gpr(t0, rt);
12036 break;
12037 case 4:
12038 check_insn(ctx, ISA_MIPS_R6);
12039 if (sel != 0) {
12041 * Performance counter registers are not implemented other than
12042 * control register 0.
12044 generate_exception(ctx, EXCP_RI);
12046 gen_helper_rdhwr_performance(t0, cpu_env);
12047 gen_store_gpr(t0, rt);
12048 break;
12049 case 5:
12050 check_insn(ctx, ISA_MIPS_R6);
12051 gen_helper_rdhwr_xnp(t0, cpu_env);
12052 gen_store_gpr(t0, rt);
12053 break;
12054 case 29:
12055 #if defined(CONFIG_USER_ONLY)
12056 tcg_gen_ld_tl(t0, cpu_env,
12057 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12058 gen_store_gpr(t0, rt);
12059 break;
12060 #else
12061 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12062 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12063 tcg_gen_ld_tl(t0, cpu_env,
12064 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12065 gen_store_gpr(t0, rt);
12066 } else {
12067 gen_reserved_instruction(ctx);
12069 break;
12070 #endif
12071 default: /* Invalid */
12072 MIPS_INVAL("rdhwr");
12073 gen_reserved_instruction(ctx);
12074 break;
12076 tcg_temp_free(t0);
12079 static inline void clear_branch_hflags(DisasContext *ctx)
12081 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12082 if (ctx->base.is_jmp == DISAS_NEXT) {
12083 save_cpu_state(ctx, 0);
12084 } else {
12086 * It is not safe to save ctx->hflags as hflags may be changed
12087 * in execution time by the instruction in delay / forbidden slot.
12089 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12093 static void gen_branch(DisasContext *ctx, int insn_bytes)
12095 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12096 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12097 /* Branches completion */
12098 clear_branch_hflags(ctx);
12099 ctx->base.is_jmp = DISAS_NORETURN;
12100 /* FIXME: Need to clear can_do_io. */
12101 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12102 case MIPS_HFLAG_FBNSLOT:
12103 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12104 break;
12105 case MIPS_HFLAG_B:
12106 /* unconditional branch */
12107 if (proc_hflags & MIPS_HFLAG_BX) {
12108 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12110 gen_goto_tb(ctx, 0, ctx->btarget);
12111 break;
12112 case MIPS_HFLAG_BL:
12113 /* blikely taken case */
12114 gen_goto_tb(ctx, 0, ctx->btarget);
12115 break;
12116 case MIPS_HFLAG_BC:
12117 /* Conditional branch */
12119 TCGLabel *l1 = gen_new_label();
12121 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12122 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12123 gen_set_label(l1);
12124 gen_goto_tb(ctx, 0, ctx->btarget);
12126 break;
12127 case MIPS_HFLAG_BR:
12128 /* unconditional branch to register */
12129 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12130 TCGv t0 = tcg_temp_new();
12131 TCGv_i32 t1 = tcg_temp_new_i32();
12133 tcg_gen_andi_tl(t0, btarget, 0x1);
12134 tcg_gen_trunc_tl_i32(t1, t0);
12135 tcg_temp_free(t0);
12136 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12137 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12138 tcg_gen_or_i32(hflags, hflags, t1);
12139 tcg_temp_free_i32(t1);
12141 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12142 } else {
12143 tcg_gen_mov_tl(cpu_PC, btarget);
12145 if (ctx->base.singlestep_enabled) {
12146 save_cpu_state(ctx, 0);
12147 gen_helper_raise_exception_debug(cpu_env);
12149 tcg_gen_lookup_and_goto_ptr();
12150 break;
12151 default:
12152 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12153 abort();
12158 /* Compact Branches */
12159 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12160 int rs, int rt, int32_t offset)
12162 int bcond_compute = 0;
12163 TCGv t0 = tcg_temp_new();
12164 TCGv t1 = tcg_temp_new();
12165 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12167 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12168 #ifdef MIPS_DEBUG_DISAS
12169 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12170 "\n", ctx->base.pc_next);
12171 #endif
12172 gen_reserved_instruction(ctx);
12173 goto out;
12176 /* Load needed operands and calculate btarget */
12177 switch (opc) {
12178 /* compact branch */
12179 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12180 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12181 gen_load_gpr(t0, rs);
12182 gen_load_gpr(t1, rt);
12183 bcond_compute = 1;
12184 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12185 if (rs <= rt && rs == 0) {
12186 /* OPC_BEQZALC, OPC_BNEZALC */
12187 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12189 break;
12190 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12191 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12192 gen_load_gpr(t0, rs);
12193 gen_load_gpr(t1, rt);
12194 bcond_compute = 1;
12195 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12196 break;
12197 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12198 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12199 if (rs == 0 || rs == rt) {
12200 /* OPC_BLEZALC, OPC_BGEZALC */
12201 /* OPC_BGTZALC, OPC_BLTZALC */
12202 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12204 gen_load_gpr(t0, rs);
12205 gen_load_gpr(t1, rt);
12206 bcond_compute = 1;
12207 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12208 break;
12209 case OPC_BC:
12210 case OPC_BALC:
12211 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12212 break;
12213 case OPC_BEQZC:
12214 case OPC_BNEZC:
12215 if (rs != 0) {
12216 /* OPC_BEQZC, OPC_BNEZC */
12217 gen_load_gpr(t0, rs);
12218 bcond_compute = 1;
12219 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12220 } else {
12221 /* OPC_JIC, OPC_JIALC */
12222 TCGv tbase = tcg_temp_new();
12223 TCGv toffset = tcg_temp_new();
12225 gen_load_gpr(tbase, rt);
12226 tcg_gen_movi_tl(toffset, offset);
12227 gen_op_addr_add(ctx, btarget, tbase, toffset);
12228 tcg_temp_free(tbase);
12229 tcg_temp_free(toffset);
12231 break;
12232 default:
12233 MIPS_INVAL("Compact branch/jump");
12234 gen_reserved_instruction(ctx);
12235 goto out;
12238 if (bcond_compute == 0) {
12239 /* Uncoditional compact branch */
12240 switch (opc) {
12241 case OPC_JIALC:
12242 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12243 /* Fallthrough */
12244 case OPC_JIC:
12245 ctx->hflags |= MIPS_HFLAG_BR;
12246 break;
12247 case OPC_BALC:
12248 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12249 /* Fallthrough */
12250 case OPC_BC:
12251 ctx->hflags |= MIPS_HFLAG_B;
12252 break;
12253 default:
12254 MIPS_INVAL("Compact branch/jump");
12255 gen_reserved_instruction(ctx);
12256 goto out;
12259 /* Generating branch here as compact branches don't have delay slot */
12260 gen_branch(ctx, 4);
12261 } else {
12262 /* Conditional compact branch */
12263 TCGLabel *fs = gen_new_label();
12264 save_cpu_state(ctx, 0);
12266 switch (opc) {
12267 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12268 if (rs == 0 && rt != 0) {
12269 /* OPC_BLEZALC */
12270 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12271 } else if (rs != 0 && rt != 0 && rs == rt) {
12272 /* OPC_BGEZALC */
12273 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12274 } else {
12275 /* OPC_BGEUC */
12276 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12278 break;
12279 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12280 if (rs == 0 && rt != 0) {
12281 /* OPC_BGTZALC */
12282 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12283 } else if (rs != 0 && rt != 0 && rs == rt) {
12284 /* OPC_BLTZALC */
12285 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12286 } else {
12287 /* OPC_BLTUC */
12288 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12290 break;
12291 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12292 if (rs == 0 && rt != 0) {
12293 /* OPC_BLEZC */
12294 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12295 } else if (rs != 0 && rt != 0 && rs == rt) {
12296 /* OPC_BGEZC */
12297 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12298 } else {
12299 /* OPC_BGEC */
12300 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12302 break;
12303 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12304 if (rs == 0 && rt != 0) {
12305 /* OPC_BGTZC */
12306 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12307 } else if (rs != 0 && rt != 0 && rs == rt) {
12308 /* OPC_BLTZC */
12309 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12310 } else {
12311 /* OPC_BLTC */
12312 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12314 break;
12315 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12316 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12317 if (rs >= rt) {
12318 /* OPC_BOVC, OPC_BNVC */
12319 TCGv t2 = tcg_temp_new();
12320 TCGv t3 = tcg_temp_new();
12321 TCGv t4 = tcg_temp_new();
12322 TCGv input_overflow = tcg_temp_new();
12324 gen_load_gpr(t0, rs);
12325 gen_load_gpr(t1, rt);
12326 tcg_gen_ext32s_tl(t2, t0);
12327 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12328 tcg_gen_ext32s_tl(t3, t1);
12329 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12330 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12332 tcg_gen_add_tl(t4, t2, t3);
12333 tcg_gen_ext32s_tl(t4, t4);
12334 tcg_gen_xor_tl(t2, t2, t3);
12335 tcg_gen_xor_tl(t3, t4, t3);
12336 tcg_gen_andc_tl(t2, t3, t2);
12337 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12338 tcg_gen_or_tl(t4, t4, input_overflow);
12339 if (opc == OPC_BOVC) {
12340 /* OPC_BOVC */
12341 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12342 } else {
12343 /* OPC_BNVC */
12344 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12346 tcg_temp_free(input_overflow);
12347 tcg_temp_free(t4);
12348 tcg_temp_free(t3);
12349 tcg_temp_free(t2);
12350 } else if (rs < rt && rs == 0) {
12351 /* OPC_BEQZALC, OPC_BNEZALC */
12352 if (opc == OPC_BEQZALC) {
12353 /* OPC_BEQZALC */
12354 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12355 } else {
12356 /* OPC_BNEZALC */
12357 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12359 } else {
12360 /* OPC_BEQC, OPC_BNEC */
12361 if (opc == OPC_BEQC) {
12362 /* OPC_BEQC */
12363 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12364 } else {
12365 /* OPC_BNEC */
12366 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12369 break;
12370 case OPC_BEQZC:
12371 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12372 break;
12373 case OPC_BNEZC:
12374 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12375 break;
12376 default:
12377 MIPS_INVAL("Compact conditional branch/jump");
12378 gen_reserved_instruction(ctx);
12379 goto out;
12382 /* Generating branch here as compact branches don't have delay slot */
12383 gen_goto_tb(ctx, 1, ctx->btarget);
12384 gen_set_label(fs);
12386 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12389 out:
12390 tcg_temp_free(t0);
12391 tcg_temp_free(t1);
12394 /* ISA extensions (ASEs) */
12395 /* MIPS16 extension to MIPS32 */
12397 /* MIPS16 major opcodes */
12398 enum {
12399 M16_OPC_ADDIUSP = 0x00,
12400 M16_OPC_ADDIUPC = 0x01,
12401 M16_OPC_B = 0x02,
12402 M16_OPC_JAL = 0x03,
12403 M16_OPC_BEQZ = 0x04,
12404 M16_OPC_BNEQZ = 0x05,
12405 M16_OPC_SHIFT = 0x06,
12406 M16_OPC_LD = 0x07,
12407 M16_OPC_RRIA = 0x08,
12408 M16_OPC_ADDIU8 = 0x09,
12409 M16_OPC_SLTI = 0x0a,
12410 M16_OPC_SLTIU = 0x0b,
12411 M16_OPC_I8 = 0x0c,
12412 M16_OPC_LI = 0x0d,
12413 M16_OPC_CMPI = 0x0e,
12414 M16_OPC_SD = 0x0f,
12415 M16_OPC_LB = 0x10,
12416 M16_OPC_LH = 0x11,
12417 M16_OPC_LWSP = 0x12,
12418 M16_OPC_LW = 0x13,
12419 M16_OPC_LBU = 0x14,
12420 M16_OPC_LHU = 0x15,
12421 M16_OPC_LWPC = 0x16,
12422 M16_OPC_LWU = 0x17,
12423 M16_OPC_SB = 0x18,
12424 M16_OPC_SH = 0x19,
12425 M16_OPC_SWSP = 0x1a,
12426 M16_OPC_SW = 0x1b,
12427 M16_OPC_RRR = 0x1c,
12428 M16_OPC_RR = 0x1d,
12429 M16_OPC_EXTEND = 0x1e,
12430 M16_OPC_I64 = 0x1f
12433 /* I8 funct field */
12434 enum {
12435 I8_BTEQZ = 0x0,
12436 I8_BTNEZ = 0x1,
12437 I8_SWRASP = 0x2,
12438 I8_ADJSP = 0x3,
12439 I8_SVRS = 0x4,
12440 I8_MOV32R = 0x5,
12441 I8_MOVR32 = 0x7
12444 /* RRR f field */
12445 enum {
12446 RRR_DADDU = 0x0,
12447 RRR_ADDU = 0x1,
12448 RRR_DSUBU = 0x2,
12449 RRR_SUBU = 0x3
12452 /* RR funct field */
12453 enum {
12454 RR_JR = 0x00,
12455 RR_SDBBP = 0x01,
12456 RR_SLT = 0x02,
12457 RR_SLTU = 0x03,
12458 RR_SLLV = 0x04,
12459 RR_BREAK = 0x05,
12460 RR_SRLV = 0x06,
12461 RR_SRAV = 0x07,
12462 RR_DSRL = 0x08,
12463 RR_CMP = 0x0a,
12464 RR_NEG = 0x0b,
12465 RR_AND = 0x0c,
12466 RR_OR = 0x0d,
12467 RR_XOR = 0x0e,
12468 RR_NOT = 0x0f,
12469 RR_MFHI = 0x10,
12470 RR_CNVT = 0x11,
12471 RR_MFLO = 0x12,
12472 RR_DSRA = 0x13,
12473 RR_DSLLV = 0x14,
12474 RR_DSRLV = 0x16,
12475 RR_DSRAV = 0x17,
12476 RR_MULT = 0x18,
12477 RR_MULTU = 0x19,
12478 RR_DIV = 0x1a,
12479 RR_DIVU = 0x1b,
12480 RR_DMULT = 0x1c,
12481 RR_DMULTU = 0x1d,
12482 RR_DDIV = 0x1e,
12483 RR_DDIVU = 0x1f
12486 /* I64 funct field */
12487 enum {
12488 I64_LDSP = 0x0,
12489 I64_SDSP = 0x1,
12490 I64_SDRASP = 0x2,
12491 I64_DADJSP = 0x3,
12492 I64_LDPC = 0x4,
12493 I64_DADDIU5 = 0x5,
12494 I64_DADDIUPC = 0x6,
12495 I64_DADDIUSP = 0x7
12498 /* RR ry field for CNVT */
12499 enum {
12500 RR_RY_CNVT_ZEB = 0x0,
12501 RR_RY_CNVT_ZEH = 0x1,
12502 RR_RY_CNVT_ZEW = 0x2,
12503 RR_RY_CNVT_SEB = 0x4,
12504 RR_RY_CNVT_SEH = 0x5,
12505 RR_RY_CNVT_SEW = 0x6,
12508 static int xlat(int r)
12510 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12512 return map[r];
12515 static void gen_mips16_save(DisasContext *ctx,
12516 int xsregs, int aregs,
12517 int do_ra, int do_s0, int do_s1,
12518 int framesize)
12520 TCGv t0 = tcg_temp_new();
12521 TCGv t1 = tcg_temp_new();
12522 TCGv t2 = tcg_temp_new();
12523 int args, astatic;
12525 switch (aregs) {
12526 case 0:
12527 case 1:
12528 case 2:
12529 case 3:
12530 case 11:
12531 args = 0;
12532 break;
12533 case 4:
12534 case 5:
12535 case 6:
12536 case 7:
12537 args = 1;
12538 break;
12539 case 8:
12540 case 9:
12541 case 10:
12542 args = 2;
12543 break;
12544 case 12:
12545 case 13:
12546 args = 3;
12547 break;
12548 case 14:
12549 args = 4;
12550 break;
12551 default:
12552 gen_reserved_instruction(ctx);
12553 return;
12556 switch (args) {
12557 case 4:
12558 gen_base_offset_addr(ctx, t0, 29, 12);
12559 gen_load_gpr(t1, 7);
12560 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12561 /* Fall through */
12562 case 3:
12563 gen_base_offset_addr(ctx, t0, 29, 8);
12564 gen_load_gpr(t1, 6);
12565 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12566 /* Fall through */
12567 case 2:
12568 gen_base_offset_addr(ctx, t0, 29, 4);
12569 gen_load_gpr(t1, 5);
12570 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12571 /* Fall through */
12572 case 1:
12573 gen_base_offset_addr(ctx, t0, 29, 0);
12574 gen_load_gpr(t1, 4);
12575 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12578 gen_load_gpr(t0, 29);
12580 #define DECR_AND_STORE(reg) do { \
12581 tcg_gen_movi_tl(t2, -4); \
12582 gen_op_addr_add(ctx, t0, t0, t2); \
12583 gen_load_gpr(t1, reg); \
12584 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12585 } while (0)
12587 if (do_ra) {
12588 DECR_AND_STORE(31);
12591 switch (xsregs) {
12592 case 7:
12593 DECR_AND_STORE(30);
12594 /* Fall through */
12595 case 6:
12596 DECR_AND_STORE(23);
12597 /* Fall through */
12598 case 5:
12599 DECR_AND_STORE(22);
12600 /* Fall through */
12601 case 4:
12602 DECR_AND_STORE(21);
12603 /* Fall through */
12604 case 3:
12605 DECR_AND_STORE(20);
12606 /* Fall through */
12607 case 2:
12608 DECR_AND_STORE(19);
12609 /* Fall through */
12610 case 1:
12611 DECR_AND_STORE(18);
12614 if (do_s1) {
12615 DECR_AND_STORE(17);
12617 if (do_s0) {
12618 DECR_AND_STORE(16);
12621 switch (aregs) {
12622 case 0:
12623 case 4:
12624 case 8:
12625 case 12:
12626 case 14:
12627 astatic = 0;
12628 break;
12629 case 1:
12630 case 5:
12631 case 9:
12632 case 13:
12633 astatic = 1;
12634 break;
12635 case 2:
12636 case 6:
12637 case 10:
12638 astatic = 2;
12639 break;
12640 case 3:
12641 case 7:
12642 astatic = 3;
12643 break;
12644 case 11:
12645 astatic = 4;
12646 break;
12647 default:
12648 gen_reserved_instruction(ctx);
12649 return;
12652 if (astatic > 0) {
12653 DECR_AND_STORE(7);
12654 if (astatic > 1) {
12655 DECR_AND_STORE(6);
12656 if (astatic > 2) {
12657 DECR_AND_STORE(5);
12658 if (astatic > 3) {
12659 DECR_AND_STORE(4);
12664 #undef DECR_AND_STORE
12666 tcg_gen_movi_tl(t2, -framesize);
12667 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12668 tcg_temp_free(t0);
12669 tcg_temp_free(t1);
12670 tcg_temp_free(t2);
12673 static void gen_mips16_restore(DisasContext *ctx,
12674 int xsregs, int aregs,
12675 int do_ra, int do_s0, int do_s1,
12676 int framesize)
12678 int astatic;
12679 TCGv t0 = tcg_temp_new();
12680 TCGv t1 = tcg_temp_new();
12681 TCGv t2 = tcg_temp_new();
12683 tcg_gen_movi_tl(t2, framesize);
12684 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
12686 #define DECR_AND_LOAD(reg) do { \
12687 tcg_gen_movi_tl(t2, -4); \
12688 gen_op_addr_add(ctx, t0, t0, t2); \
12689 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
12690 gen_store_gpr(t1, reg); \
12691 } while (0)
12693 if (do_ra) {
12694 DECR_AND_LOAD(31);
12697 switch (xsregs) {
12698 case 7:
12699 DECR_AND_LOAD(30);
12700 /* Fall through */
12701 case 6:
12702 DECR_AND_LOAD(23);
12703 /* Fall through */
12704 case 5:
12705 DECR_AND_LOAD(22);
12706 /* Fall through */
12707 case 4:
12708 DECR_AND_LOAD(21);
12709 /* Fall through */
12710 case 3:
12711 DECR_AND_LOAD(20);
12712 /* Fall through */
12713 case 2:
12714 DECR_AND_LOAD(19);
12715 /* Fall through */
12716 case 1:
12717 DECR_AND_LOAD(18);
12720 if (do_s1) {
12721 DECR_AND_LOAD(17);
12723 if (do_s0) {
12724 DECR_AND_LOAD(16);
12727 switch (aregs) {
12728 case 0:
12729 case 4:
12730 case 8:
12731 case 12:
12732 case 14:
12733 astatic = 0;
12734 break;
12735 case 1:
12736 case 5:
12737 case 9:
12738 case 13:
12739 astatic = 1;
12740 break;
12741 case 2:
12742 case 6:
12743 case 10:
12744 astatic = 2;
12745 break;
12746 case 3:
12747 case 7:
12748 astatic = 3;
12749 break;
12750 case 11:
12751 astatic = 4;
12752 break;
12753 default:
12754 gen_reserved_instruction(ctx);
12755 return;
12758 if (astatic > 0) {
12759 DECR_AND_LOAD(7);
12760 if (astatic > 1) {
12761 DECR_AND_LOAD(6);
12762 if (astatic > 2) {
12763 DECR_AND_LOAD(5);
12764 if (astatic > 3) {
12765 DECR_AND_LOAD(4);
12770 #undef DECR_AND_LOAD
12772 tcg_gen_movi_tl(t2, framesize);
12773 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12774 tcg_temp_free(t0);
12775 tcg_temp_free(t1);
12776 tcg_temp_free(t2);
12779 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
12780 int is_64_bit, int extended)
12782 TCGv t0;
12784 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12785 gen_reserved_instruction(ctx);
12786 return;
12789 t0 = tcg_temp_new();
12791 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
12792 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
12793 if (!is_64_bit) {
12794 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12797 tcg_temp_free(t0);
12800 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
12801 int16_t offset)
12803 TCGv_i32 t0 = tcg_const_i32(op);
12804 TCGv t1 = tcg_temp_new();
12805 gen_base_offset_addr(ctx, t1, base, offset);
12806 gen_helper_cache(cpu_env, t1, t0);
12807 tcg_temp_free(t1);
12808 tcg_temp_free_i32(t0);
12811 #if defined(TARGET_MIPS64)
12812 static void decode_i64_mips16(DisasContext *ctx,
12813 int ry, int funct, int16_t offset,
12814 int extended)
12816 switch (funct) {
12817 case I64_LDSP:
12818 check_insn(ctx, ISA_MIPS3);
12819 check_mips_64(ctx);
12820 offset = extended ? offset : offset << 3;
12821 gen_ld(ctx, OPC_LD, ry, 29, offset);
12822 break;
12823 case I64_SDSP:
12824 check_insn(ctx, ISA_MIPS3);
12825 check_mips_64(ctx);
12826 offset = extended ? offset : offset << 3;
12827 gen_st(ctx, OPC_SD, ry, 29, offset);
12828 break;
12829 case I64_SDRASP:
12830 check_insn(ctx, ISA_MIPS3);
12831 check_mips_64(ctx);
12832 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
12833 gen_st(ctx, OPC_SD, 31, 29, offset);
12834 break;
12835 case I64_DADJSP:
12836 check_insn(ctx, ISA_MIPS3);
12837 check_mips_64(ctx);
12838 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
12839 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
12840 break;
12841 case I64_LDPC:
12842 check_insn(ctx, ISA_MIPS3);
12843 check_mips_64(ctx);
12844 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12845 gen_reserved_instruction(ctx);
12846 } else {
12847 offset = extended ? offset : offset << 3;
12848 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
12850 break;
12851 case I64_DADDIU5:
12852 check_insn(ctx, ISA_MIPS3);
12853 check_mips_64(ctx);
12854 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
12855 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
12856 break;
12857 case I64_DADDIUPC:
12858 check_insn(ctx, ISA_MIPS3);
12859 check_mips_64(ctx);
12860 offset = extended ? offset : offset << 2;
12861 gen_addiupc(ctx, ry, offset, 1, extended);
12862 break;
12863 case I64_DADDIUSP:
12864 check_insn(ctx, ISA_MIPS3);
12865 check_mips_64(ctx);
12866 offset = extended ? offset : offset << 2;
12867 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
12868 break;
12871 #endif
12873 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
12875 int extend = translator_lduw(env, ctx->base.pc_next + 2);
12876 int op, rx, ry, funct, sa;
12877 int16_t imm, offset;
12879 ctx->opcode = (ctx->opcode << 16) | extend;
12880 op = (ctx->opcode >> 11) & 0x1f;
12881 sa = (ctx->opcode >> 22) & 0x1f;
12882 funct = (ctx->opcode >> 8) & 0x7;
12883 rx = xlat((ctx->opcode >> 8) & 0x7);
12884 ry = xlat((ctx->opcode >> 5) & 0x7);
12885 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
12886 | ((ctx->opcode >> 21) & 0x3f) << 5
12887 | (ctx->opcode & 0x1f));
12890 * The extended opcodes cleverly reuse the opcodes from their 16-bit
12891 * counterparts.
12893 switch (op) {
12894 case M16_OPC_ADDIUSP:
12895 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
12896 break;
12897 case M16_OPC_ADDIUPC:
12898 gen_addiupc(ctx, rx, imm, 0, 1);
12899 break;
12900 case M16_OPC_B:
12901 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
12902 /* No delay slot, so just process as a normal instruction */
12903 break;
12904 case M16_OPC_BEQZ:
12905 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
12906 /* No delay slot, so just process as a normal instruction */
12907 break;
12908 case M16_OPC_BNEQZ:
12909 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
12910 /* No delay slot, so just process as a normal instruction */
12911 break;
12912 case M16_OPC_SHIFT:
12913 switch (ctx->opcode & 0x3) {
12914 case 0x0:
12915 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
12916 break;
12917 case 0x1:
12918 #if defined(TARGET_MIPS64)
12919 check_mips_64(ctx);
12920 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
12921 #else
12922 gen_reserved_instruction(ctx);
12923 #endif
12924 break;
12925 case 0x2:
12926 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
12927 break;
12928 case 0x3:
12929 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
12930 break;
12932 break;
12933 #if defined(TARGET_MIPS64)
12934 case M16_OPC_LD:
12935 check_insn(ctx, ISA_MIPS3);
12936 check_mips_64(ctx);
12937 gen_ld(ctx, OPC_LD, ry, rx, offset);
12938 break;
12939 #endif
12940 case M16_OPC_RRIA:
12941 imm = ctx->opcode & 0xf;
12942 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
12943 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
12944 imm = (int16_t) (imm << 1) >> 1;
12945 if ((ctx->opcode >> 4) & 0x1) {
12946 #if defined(TARGET_MIPS64)
12947 check_mips_64(ctx);
12948 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12949 #else
12950 gen_reserved_instruction(ctx);
12951 #endif
12952 } else {
12953 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12955 break;
12956 case M16_OPC_ADDIU8:
12957 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12958 break;
12959 case M16_OPC_SLTI:
12960 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12961 break;
12962 case M16_OPC_SLTIU:
12963 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12964 break;
12965 case M16_OPC_I8:
12966 switch (funct) {
12967 case I8_BTEQZ:
12968 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
12969 break;
12970 case I8_BTNEZ:
12971 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
12972 break;
12973 case I8_SWRASP:
12974 gen_st(ctx, OPC_SW, 31, 29, imm);
12975 break;
12976 case I8_ADJSP:
12977 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
12978 break;
12979 case I8_SVRS:
12980 check_insn(ctx, ISA_MIPS_R1);
12982 int xsregs = (ctx->opcode >> 24) & 0x7;
12983 int aregs = (ctx->opcode >> 16) & 0xf;
12984 int do_ra = (ctx->opcode >> 6) & 0x1;
12985 int do_s0 = (ctx->opcode >> 5) & 0x1;
12986 int do_s1 = (ctx->opcode >> 4) & 0x1;
12987 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
12988 | (ctx->opcode & 0xf)) << 3;
12990 if (ctx->opcode & (1 << 7)) {
12991 gen_mips16_save(ctx, xsregs, aregs,
12992 do_ra, do_s0, do_s1,
12993 framesize);
12994 } else {
12995 gen_mips16_restore(ctx, xsregs, aregs,
12996 do_ra, do_s0, do_s1,
12997 framesize);
13000 break;
13001 default:
13002 gen_reserved_instruction(ctx);
13003 break;
13005 break;
13006 case M16_OPC_LI:
13007 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13008 break;
13009 case M16_OPC_CMPI:
13010 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13011 break;
13012 #if defined(TARGET_MIPS64)
13013 case M16_OPC_SD:
13014 check_insn(ctx, ISA_MIPS3);
13015 check_mips_64(ctx);
13016 gen_st(ctx, OPC_SD, ry, rx, offset);
13017 break;
13018 #endif
13019 case M16_OPC_LB:
13020 gen_ld(ctx, OPC_LB, ry, rx, offset);
13021 break;
13022 case M16_OPC_LH:
13023 gen_ld(ctx, OPC_LH, ry, rx, offset);
13024 break;
13025 case M16_OPC_LWSP:
13026 gen_ld(ctx, OPC_LW, rx, 29, offset);
13027 break;
13028 case M16_OPC_LW:
13029 gen_ld(ctx, OPC_LW, ry, rx, offset);
13030 break;
13031 case M16_OPC_LBU:
13032 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13033 break;
13034 case M16_OPC_LHU:
13035 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13036 break;
13037 case M16_OPC_LWPC:
13038 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13039 break;
13040 #if defined(TARGET_MIPS64)
13041 case M16_OPC_LWU:
13042 check_insn(ctx, ISA_MIPS3);
13043 check_mips_64(ctx);
13044 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13045 break;
13046 #endif
13047 case M16_OPC_SB:
13048 gen_st(ctx, OPC_SB, ry, rx, offset);
13049 break;
13050 case M16_OPC_SH:
13051 gen_st(ctx, OPC_SH, ry, rx, offset);
13052 break;
13053 case M16_OPC_SWSP:
13054 gen_st(ctx, OPC_SW, rx, 29, offset);
13055 break;
13056 case M16_OPC_SW:
13057 gen_st(ctx, OPC_SW, ry, rx, offset);
13058 break;
13059 #if defined(TARGET_MIPS64)
13060 case M16_OPC_I64:
13061 decode_i64_mips16(ctx, ry, funct, offset, 1);
13062 break;
13063 #endif
13064 default:
13065 gen_reserved_instruction(ctx);
13066 break;
13069 return 4;
13072 static inline bool is_uhi(int sdbbp_code)
13074 #ifdef CONFIG_USER_ONLY
13075 return false;
13076 #else
13077 return semihosting_enabled() && sdbbp_code == 1;
13078 #endif
13081 #ifdef CONFIG_USER_ONLY
13082 /* The above should dead-code away any calls to this..*/
13083 static inline void gen_helper_do_semihosting(void *env)
13085 g_assert_not_reached();
13087 #endif
13089 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13091 int rx, ry;
13092 int sa;
13093 int op, cnvt_op, op1, offset;
13094 int funct;
13095 int n_bytes;
13097 op = (ctx->opcode >> 11) & 0x1f;
13098 sa = (ctx->opcode >> 2) & 0x7;
13099 sa = sa == 0 ? 8 : sa;
13100 rx = xlat((ctx->opcode >> 8) & 0x7);
13101 cnvt_op = (ctx->opcode >> 5) & 0x7;
13102 ry = xlat((ctx->opcode >> 5) & 0x7);
13103 op1 = offset = ctx->opcode & 0x1f;
13105 n_bytes = 2;
13107 switch (op) {
13108 case M16_OPC_ADDIUSP:
13110 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13112 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13114 break;
13115 case M16_OPC_ADDIUPC:
13116 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13117 break;
13118 case M16_OPC_B:
13119 offset = (ctx->opcode & 0x7ff) << 1;
13120 offset = (int16_t)(offset << 4) >> 4;
13121 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13122 /* No delay slot, so just process as a normal instruction */
13123 break;
13124 case M16_OPC_JAL:
13125 offset = translator_lduw(env, ctx->base.pc_next + 2);
13126 offset = (((ctx->opcode & 0x1f) << 21)
13127 | ((ctx->opcode >> 5) & 0x1f) << 16
13128 | offset) << 2;
13129 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13130 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13131 n_bytes = 4;
13132 break;
13133 case M16_OPC_BEQZ:
13134 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13135 ((int8_t)ctx->opcode) << 1, 0);
13136 /* No delay slot, so just process as a normal instruction */
13137 break;
13138 case M16_OPC_BNEQZ:
13139 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13140 ((int8_t)ctx->opcode) << 1, 0);
13141 /* No delay slot, so just process as a normal instruction */
13142 break;
13143 case M16_OPC_SHIFT:
13144 switch (ctx->opcode & 0x3) {
13145 case 0x0:
13146 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13147 break;
13148 case 0x1:
13149 #if defined(TARGET_MIPS64)
13150 check_insn(ctx, ISA_MIPS3);
13151 check_mips_64(ctx);
13152 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13153 #else
13154 gen_reserved_instruction(ctx);
13155 #endif
13156 break;
13157 case 0x2:
13158 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13159 break;
13160 case 0x3:
13161 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13162 break;
13164 break;
13165 #if defined(TARGET_MIPS64)
13166 case M16_OPC_LD:
13167 check_insn(ctx, ISA_MIPS3);
13168 check_mips_64(ctx);
13169 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13170 break;
13171 #endif
13172 case M16_OPC_RRIA:
13174 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13176 if ((ctx->opcode >> 4) & 1) {
13177 #if defined(TARGET_MIPS64)
13178 check_insn(ctx, ISA_MIPS3);
13179 check_mips_64(ctx);
13180 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13181 #else
13182 gen_reserved_instruction(ctx);
13183 #endif
13184 } else {
13185 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13188 break;
13189 case M16_OPC_ADDIU8:
13191 int16_t imm = (int8_t) ctx->opcode;
13193 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13195 break;
13196 case M16_OPC_SLTI:
13198 int16_t imm = (uint8_t) ctx->opcode;
13199 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13201 break;
13202 case M16_OPC_SLTIU:
13204 int16_t imm = (uint8_t) ctx->opcode;
13205 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13207 break;
13208 case M16_OPC_I8:
13210 int reg32;
13212 funct = (ctx->opcode >> 8) & 0x7;
13213 switch (funct) {
13214 case I8_BTEQZ:
13215 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13216 ((int8_t)ctx->opcode) << 1, 0);
13217 break;
13218 case I8_BTNEZ:
13219 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13220 ((int8_t)ctx->opcode) << 1, 0);
13221 break;
13222 case I8_SWRASP:
13223 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13224 break;
13225 case I8_ADJSP:
13226 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13227 ((int8_t)ctx->opcode) << 3);
13228 break;
13229 case I8_SVRS:
13230 check_insn(ctx, ISA_MIPS_R1);
13232 int do_ra = ctx->opcode & (1 << 6);
13233 int do_s0 = ctx->opcode & (1 << 5);
13234 int do_s1 = ctx->opcode & (1 << 4);
13235 int framesize = ctx->opcode & 0xf;
13237 if (framesize == 0) {
13238 framesize = 128;
13239 } else {
13240 framesize = framesize << 3;
13243 if (ctx->opcode & (1 << 7)) {
13244 gen_mips16_save(ctx, 0, 0,
13245 do_ra, do_s0, do_s1, framesize);
13246 } else {
13247 gen_mips16_restore(ctx, 0, 0,
13248 do_ra, do_s0, do_s1, framesize);
13251 break;
13252 case I8_MOV32R:
13254 int rz = xlat(ctx->opcode & 0x7);
13256 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13257 ((ctx->opcode >> 5) & 0x7);
13258 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13260 break;
13261 case I8_MOVR32:
13262 reg32 = ctx->opcode & 0x1f;
13263 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13264 break;
13265 default:
13266 gen_reserved_instruction(ctx);
13267 break;
13270 break;
13271 case M16_OPC_LI:
13273 int16_t imm = (uint8_t) ctx->opcode;
13275 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13277 break;
13278 case M16_OPC_CMPI:
13280 int16_t imm = (uint8_t) ctx->opcode;
13281 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13283 break;
13284 #if defined(TARGET_MIPS64)
13285 case M16_OPC_SD:
13286 check_insn(ctx, ISA_MIPS3);
13287 check_mips_64(ctx);
13288 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13289 break;
13290 #endif
13291 case M16_OPC_LB:
13292 gen_ld(ctx, OPC_LB, ry, rx, offset);
13293 break;
13294 case M16_OPC_LH:
13295 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13296 break;
13297 case M16_OPC_LWSP:
13298 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13299 break;
13300 case M16_OPC_LW:
13301 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13302 break;
13303 case M16_OPC_LBU:
13304 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13305 break;
13306 case M16_OPC_LHU:
13307 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13308 break;
13309 case M16_OPC_LWPC:
13310 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13311 break;
13312 #if defined(TARGET_MIPS64)
13313 case M16_OPC_LWU:
13314 check_insn(ctx, ISA_MIPS3);
13315 check_mips_64(ctx);
13316 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13317 break;
13318 #endif
13319 case M16_OPC_SB:
13320 gen_st(ctx, OPC_SB, ry, rx, offset);
13321 break;
13322 case M16_OPC_SH:
13323 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13324 break;
13325 case M16_OPC_SWSP:
13326 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13327 break;
13328 case M16_OPC_SW:
13329 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13330 break;
13331 case M16_OPC_RRR:
13333 int rz = xlat((ctx->opcode >> 2) & 0x7);
13334 int mips32_op;
13336 switch (ctx->opcode & 0x3) {
13337 case RRR_ADDU:
13338 mips32_op = OPC_ADDU;
13339 break;
13340 case RRR_SUBU:
13341 mips32_op = OPC_SUBU;
13342 break;
13343 #if defined(TARGET_MIPS64)
13344 case RRR_DADDU:
13345 mips32_op = OPC_DADDU;
13346 check_insn(ctx, ISA_MIPS3);
13347 check_mips_64(ctx);
13348 break;
13349 case RRR_DSUBU:
13350 mips32_op = OPC_DSUBU;
13351 check_insn(ctx, ISA_MIPS3);
13352 check_mips_64(ctx);
13353 break;
13354 #endif
13355 default:
13356 gen_reserved_instruction(ctx);
13357 goto done;
13360 gen_arith(ctx, mips32_op, rz, rx, ry);
13361 done:
13364 break;
13365 case M16_OPC_RR:
13366 switch (op1) {
13367 case RR_JR:
13369 int nd = (ctx->opcode >> 7) & 0x1;
13370 int link = (ctx->opcode >> 6) & 0x1;
13371 int ra = (ctx->opcode >> 5) & 0x1;
13373 if (nd) {
13374 check_insn(ctx, ISA_MIPS_R1);
13377 if (link) {
13378 op = OPC_JALR;
13379 } else {
13380 op = OPC_JR;
13383 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13384 (nd ? 0 : 2));
13386 break;
13387 case RR_SDBBP:
13388 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13389 gen_helper_do_semihosting(cpu_env);
13390 } else {
13392 * XXX: not clear which exception should be raised
13393 * when in debug mode...
13395 check_insn(ctx, ISA_MIPS_R1);
13396 generate_exception_end(ctx, EXCP_DBp);
13398 break;
13399 case RR_SLT:
13400 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13401 break;
13402 case RR_SLTU:
13403 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13404 break;
13405 case RR_BREAK:
13406 generate_exception_end(ctx, EXCP_BREAK);
13407 break;
13408 case RR_SLLV:
13409 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13410 break;
13411 case RR_SRLV:
13412 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13413 break;
13414 case RR_SRAV:
13415 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13416 break;
13417 #if defined(TARGET_MIPS64)
13418 case RR_DSRL:
13419 check_insn(ctx, ISA_MIPS3);
13420 check_mips_64(ctx);
13421 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13422 break;
13423 #endif
13424 case RR_CMP:
13425 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13426 break;
13427 case RR_NEG:
13428 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13429 break;
13430 case RR_AND:
13431 gen_logic(ctx, OPC_AND, rx, rx, ry);
13432 break;
13433 case RR_OR:
13434 gen_logic(ctx, OPC_OR, rx, rx, ry);
13435 break;
13436 case RR_XOR:
13437 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13438 break;
13439 case RR_NOT:
13440 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13441 break;
13442 case RR_MFHI:
13443 gen_HILO(ctx, OPC_MFHI, 0, rx);
13444 break;
13445 case RR_CNVT:
13446 check_insn(ctx, ISA_MIPS_R1);
13447 switch (cnvt_op) {
13448 case RR_RY_CNVT_ZEB:
13449 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13450 break;
13451 case RR_RY_CNVT_ZEH:
13452 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13453 break;
13454 case RR_RY_CNVT_SEB:
13455 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13456 break;
13457 case RR_RY_CNVT_SEH:
13458 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13459 break;
13460 #if defined(TARGET_MIPS64)
13461 case RR_RY_CNVT_ZEW:
13462 check_insn(ctx, ISA_MIPS_R1);
13463 check_mips_64(ctx);
13464 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13465 break;
13466 case RR_RY_CNVT_SEW:
13467 check_insn(ctx, ISA_MIPS_R1);
13468 check_mips_64(ctx);
13469 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13470 break;
13471 #endif
13472 default:
13473 gen_reserved_instruction(ctx);
13474 break;
13476 break;
13477 case RR_MFLO:
13478 gen_HILO(ctx, OPC_MFLO, 0, rx);
13479 break;
13480 #if defined(TARGET_MIPS64)
13481 case RR_DSRA:
13482 check_insn(ctx, ISA_MIPS3);
13483 check_mips_64(ctx);
13484 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13485 break;
13486 case RR_DSLLV:
13487 check_insn(ctx, ISA_MIPS3);
13488 check_mips_64(ctx);
13489 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13490 break;
13491 case RR_DSRLV:
13492 check_insn(ctx, ISA_MIPS3);
13493 check_mips_64(ctx);
13494 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13495 break;
13496 case RR_DSRAV:
13497 check_insn(ctx, ISA_MIPS3);
13498 check_mips_64(ctx);
13499 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13500 break;
13501 #endif
13502 case RR_MULT:
13503 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13504 break;
13505 case RR_MULTU:
13506 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13507 break;
13508 case RR_DIV:
13509 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13510 break;
13511 case RR_DIVU:
13512 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13513 break;
13514 #if defined(TARGET_MIPS64)
13515 case RR_DMULT:
13516 check_insn(ctx, ISA_MIPS3);
13517 check_mips_64(ctx);
13518 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13519 break;
13520 case RR_DMULTU:
13521 check_insn(ctx, ISA_MIPS3);
13522 check_mips_64(ctx);
13523 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13524 break;
13525 case RR_DDIV:
13526 check_insn(ctx, ISA_MIPS3);
13527 check_mips_64(ctx);
13528 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13529 break;
13530 case RR_DDIVU:
13531 check_insn(ctx, ISA_MIPS3);
13532 check_mips_64(ctx);
13533 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13534 break;
13535 #endif
13536 default:
13537 gen_reserved_instruction(ctx);
13538 break;
13540 break;
13541 case M16_OPC_EXTEND:
13542 decode_extended_mips16_opc(env, ctx);
13543 n_bytes = 4;
13544 break;
13545 #if defined(TARGET_MIPS64)
13546 case M16_OPC_I64:
13547 funct = (ctx->opcode >> 8) & 0x7;
13548 decode_i64_mips16(ctx, ry, funct, offset, 0);
13549 break;
13550 #endif
13551 default:
13552 gen_reserved_instruction(ctx);
13553 break;
13556 return n_bytes;
13559 /* microMIPS extension to MIPS32/MIPS64 */
13562 * microMIPS32/microMIPS64 major opcodes
13564 * 1. MIPS Architecture for Programmers Volume II-B:
13565 * The microMIPS32 Instruction Set (Revision 3.05)
13567 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13569 * 2. MIPS Architecture For Programmers Volume II-A:
13570 * The MIPS64 Instruction Set (Revision 3.51)
13573 enum {
13574 POOL32A = 0x00,
13575 POOL16A = 0x01,
13576 LBU16 = 0x02,
13577 MOVE16 = 0x03,
13578 ADDI32 = 0x04,
13579 R6_LUI = 0x04,
13580 AUI = 0x04,
13581 LBU32 = 0x05,
13582 SB32 = 0x06,
13583 LB32 = 0x07,
13585 POOL32B = 0x08,
13586 POOL16B = 0x09,
13587 LHU16 = 0x0a,
13588 ANDI16 = 0x0b,
13589 ADDIU32 = 0x0c,
13590 LHU32 = 0x0d,
13591 SH32 = 0x0e,
13592 LH32 = 0x0f,
13594 POOL32I = 0x10,
13595 POOL16C = 0x11,
13596 LWSP16 = 0x12,
13597 POOL16D = 0x13,
13598 ORI32 = 0x14,
13599 POOL32F = 0x15,
13600 POOL32S = 0x16, /* MIPS64 */
13601 DADDIU32 = 0x17, /* MIPS64 */
13603 POOL32C = 0x18,
13604 LWGP16 = 0x19,
13605 LW16 = 0x1a,
13606 POOL16E = 0x1b,
13607 XORI32 = 0x1c,
13608 JALS32 = 0x1d,
13609 BOVC = 0x1d,
13610 BEQC = 0x1d,
13611 BEQZALC = 0x1d,
13612 ADDIUPC = 0x1e,
13613 PCREL = 0x1e,
13614 BNVC = 0x1f,
13615 BNEC = 0x1f,
13616 BNEZALC = 0x1f,
13618 R6_BEQZC = 0x20,
13619 JIC = 0x20,
13620 POOL16F = 0x21,
13621 SB16 = 0x22,
13622 BEQZ16 = 0x23,
13623 BEQZC16 = 0x23,
13624 SLTI32 = 0x24,
13625 BEQ32 = 0x25,
13626 BC = 0x25,
13627 SWC132 = 0x26,
13628 LWC132 = 0x27,
13630 /* 0x29 is reserved */
13631 RES_29 = 0x29,
13632 R6_BNEZC = 0x28,
13633 JIALC = 0x28,
13634 SH16 = 0x2a,
13635 BNEZ16 = 0x2b,
13636 BNEZC16 = 0x2b,
13637 SLTIU32 = 0x2c,
13638 BNE32 = 0x2d,
13639 BALC = 0x2d,
13640 SDC132 = 0x2e,
13641 LDC132 = 0x2f,
13643 /* 0x31 is reserved */
13644 RES_31 = 0x31,
13645 BLEZALC = 0x30,
13646 BGEZALC = 0x30,
13647 BGEUC = 0x30,
13648 SWSP16 = 0x32,
13649 B16 = 0x33,
13650 BC16 = 0x33,
13651 ANDI32 = 0x34,
13652 J32 = 0x35,
13653 BGTZC = 0x35,
13654 BLTZC = 0x35,
13655 BLTC = 0x35,
13656 SD32 = 0x36, /* MIPS64 */
13657 LD32 = 0x37, /* MIPS64 */
13659 /* 0x39 is reserved */
13660 RES_39 = 0x39,
13661 BGTZALC = 0x38,
13662 BLTZALC = 0x38,
13663 BLTUC = 0x38,
13664 SW16 = 0x3a,
13665 LI16 = 0x3b,
13666 JALX32 = 0x3c,
13667 JAL32 = 0x3d,
13668 BLEZC = 0x3d,
13669 BGEZC = 0x3d,
13670 BGEC = 0x3d,
13671 SW32 = 0x3e,
13672 LW32 = 0x3f
13675 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
13676 enum {
13677 ADDIUPC_00 = 0x00,
13678 ADDIUPC_01 = 0x01,
13679 ADDIUPC_02 = 0x02,
13680 ADDIUPC_03 = 0x03,
13681 ADDIUPC_04 = 0x04,
13682 ADDIUPC_05 = 0x05,
13683 ADDIUPC_06 = 0x06,
13684 ADDIUPC_07 = 0x07,
13685 AUIPC = 0x1e,
13686 ALUIPC = 0x1f,
13687 LWPC_08 = 0x08,
13688 LWPC_09 = 0x09,
13689 LWPC_0A = 0x0A,
13690 LWPC_0B = 0x0B,
13691 LWPC_0C = 0x0C,
13692 LWPC_0D = 0x0D,
13693 LWPC_0E = 0x0E,
13694 LWPC_0F = 0x0F,
13697 /* POOL32A encoding of minor opcode field */
13699 enum {
13701 * These opcodes are distinguished only by bits 9..6; those bits are
13702 * what are recorded below.
13704 SLL32 = 0x0,
13705 SRL32 = 0x1,
13706 SRA = 0x2,
13707 ROTR = 0x3,
13708 SELEQZ = 0x5,
13709 SELNEZ = 0x6,
13710 R6_RDHWR = 0x7,
13712 SLLV = 0x0,
13713 SRLV = 0x1,
13714 SRAV = 0x2,
13715 ROTRV = 0x3,
13716 ADD = 0x4,
13717 ADDU32 = 0x5,
13718 SUB = 0x6,
13719 SUBU32 = 0x7,
13720 MUL = 0x8,
13721 AND = 0x9,
13722 OR32 = 0xa,
13723 NOR = 0xb,
13724 XOR32 = 0xc,
13725 SLT = 0xd,
13726 SLTU = 0xe,
13728 MOVN = 0x0,
13729 R6_MUL = 0x0,
13730 MOVZ = 0x1,
13731 MUH = 0x1,
13732 MULU = 0x2,
13733 MUHU = 0x3,
13734 LWXS = 0x4,
13735 R6_DIV = 0x4,
13736 MOD = 0x5,
13737 R6_DIVU = 0x6,
13738 MODU = 0x7,
13740 /* The following can be distinguished by their lower 6 bits. */
13741 BREAK32 = 0x07,
13742 INS = 0x0c,
13743 LSA = 0x0f,
13744 ALIGN = 0x1f,
13745 EXT = 0x2c,
13746 POOL32AXF = 0x3c,
13747 SIGRIE = 0x3f
13750 /* POOL32AXF encoding of minor opcode field extension */
13753 * 1. MIPS Architecture for Programmers Volume II-B:
13754 * The microMIPS32 Instruction Set (Revision 3.05)
13756 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
13758 * 2. MIPS Architecture for Programmers VolumeIV-e:
13759 * The MIPS DSP Application-Specific Extension
13760 * to the microMIPS32 Architecture (Revision 2.34)
13762 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
13765 enum {
13766 /* bits 11..6 */
13767 TEQ = 0x00,
13768 TGE = 0x08,
13769 TGEU = 0x10,
13770 TLT = 0x20,
13771 TLTU = 0x28,
13772 TNE = 0x30,
13774 MFC0 = 0x03,
13775 MTC0 = 0x0b,
13777 /* begin of microMIPS32 DSP */
13779 /* bits 13..12 for 0x01 */
13780 MFHI_ACC = 0x0,
13781 MFLO_ACC = 0x1,
13782 MTHI_ACC = 0x2,
13783 MTLO_ACC = 0x3,
13785 /* bits 13..12 for 0x2a */
13786 MADD_ACC = 0x0,
13787 MADDU_ACC = 0x1,
13788 MSUB_ACC = 0x2,
13789 MSUBU_ACC = 0x3,
13791 /* bits 13..12 for 0x32 */
13792 MULT_ACC = 0x0,
13793 MULTU_ACC = 0x1,
13795 /* end of microMIPS32 DSP */
13797 /* bits 15..12 for 0x2c */
13798 BITSWAP = 0x0,
13799 SEB = 0x2,
13800 SEH = 0x3,
13801 CLO = 0x4,
13802 CLZ = 0x5,
13803 RDHWR = 0x6,
13804 WSBH = 0x7,
13805 MULT = 0x8,
13806 MULTU = 0x9,
13807 DIV = 0xa,
13808 DIVU = 0xb,
13809 MADD = 0xc,
13810 MADDU = 0xd,
13811 MSUB = 0xe,
13812 MSUBU = 0xf,
13814 /* bits 15..12 for 0x34 */
13815 MFC2 = 0x4,
13816 MTC2 = 0x5,
13817 MFHC2 = 0x8,
13818 MTHC2 = 0x9,
13819 CFC2 = 0xc,
13820 CTC2 = 0xd,
13822 /* bits 15..12 for 0x3c */
13823 JALR = 0x0,
13824 JR = 0x0, /* alias */
13825 JALRC = 0x0,
13826 JRC = 0x0,
13827 JALR_HB = 0x1,
13828 JALRC_HB = 0x1,
13829 JALRS = 0x4,
13830 JALRS_HB = 0x5,
13832 /* bits 15..12 for 0x05 */
13833 RDPGPR = 0xe,
13834 WRPGPR = 0xf,
13836 /* bits 15..12 for 0x0d */
13837 TLBP = 0x0,
13838 TLBR = 0x1,
13839 TLBWI = 0x2,
13840 TLBWR = 0x3,
13841 TLBINV = 0x4,
13842 TLBINVF = 0x5,
13843 WAIT = 0x9,
13844 IRET = 0xd,
13845 DERET = 0xe,
13846 ERET = 0xf,
13848 /* bits 15..12 for 0x15 */
13849 DMT = 0x0,
13850 DVPE = 0x1,
13851 EMT = 0x2,
13852 EVPE = 0x3,
13854 /* bits 15..12 for 0x1d */
13855 DI = 0x4,
13856 EI = 0x5,
13858 /* bits 15..12 for 0x2d */
13859 SYNC = 0x6,
13860 SYSCALL = 0x8,
13861 SDBBP = 0xd,
13863 /* bits 15..12 for 0x35 */
13864 MFHI32 = 0x0,
13865 MFLO32 = 0x1,
13866 MTHI32 = 0x2,
13867 MTLO32 = 0x3,
13870 /* POOL32B encoding of minor opcode field (bits 15..12) */
13872 enum {
13873 LWC2 = 0x0,
13874 LWP = 0x1,
13875 LDP = 0x4,
13876 LWM32 = 0x5,
13877 CACHE = 0x6,
13878 LDM = 0x7,
13879 SWC2 = 0x8,
13880 SWP = 0x9,
13881 SDP = 0xc,
13882 SWM32 = 0xd,
13883 SDM = 0xf
13886 /* POOL32C encoding of minor opcode field (bits 15..12) */
13888 enum {
13889 LWL = 0x0,
13890 SWL = 0x8,
13891 LWR = 0x1,
13892 SWR = 0x9,
13893 PREF = 0x2,
13894 ST_EVA = 0xa,
13895 LL = 0x3,
13896 SC = 0xb,
13897 LDL = 0x4,
13898 SDL = 0xc,
13899 LDR = 0x5,
13900 SDR = 0xd,
13901 LD_EVA = 0x6,
13902 LWU = 0xe,
13903 LLD = 0x7,
13904 SCD = 0xf
13907 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
13909 enum {
13910 LBUE = 0x0,
13911 LHUE = 0x1,
13912 LWLE = 0x2,
13913 LWRE = 0x3,
13914 LBE = 0x4,
13915 LHE = 0x5,
13916 LLE = 0x6,
13917 LWE = 0x7,
13920 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
13922 enum {
13923 SWLE = 0x0,
13924 SWRE = 0x1,
13925 PREFE = 0x2,
13926 CACHEE = 0x3,
13927 SBE = 0x4,
13928 SHE = 0x5,
13929 SCE = 0x6,
13930 SWE = 0x7,
13933 /* POOL32F encoding of minor opcode field (bits 5..0) */
13935 enum {
13936 /* These are the bit 7..6 values */
13937 ADD_FMT = 0x0,
13939 SUB_FMT = 0x1,
13941 MUL_FMT = 0x2,
13943 DIV_FMT = 0x3,
13945 /* These are the bit 8..6 values */
13946 MOVN_FMT = 0x0,
13947 RSQRT2_FMT = 0x0,
13948 MOVF_FMT = 0x0,
13949 RINT_FMT = 0x0,
13950 SELNEZ_FMT = 0x0,
13952 MOVZ_FMT = 0x1,
13953 LWXC1 = 0x1,
13954 MOVT_FMT = 0x1,
13955 CLASS_FMT = 0x1,
13956 SELEQZ_FMT = 0x1,
13958 PLL_PS = 0x2,
13959 SWXC1 = 0x2,
13960 SEL_FMT = 0x2,
13962 PLU_PS = 0x3,
13963 LDXC1 = 0x3,
13965 MOVN_FMT_04 = 0x4,
13966 PUL_PS = 0x4,
13967 SDXC1 = 0x4,
13968 RECIP2_FMT = 0x4,
13970 MOVZ_FMT_05 = 0x05,
13971 PUU_PS = 0x5,
13972 LUXC1 = 0x5,
13974 CVT_PS_S = 0x6,
13975 SUXC1 = 0x6,
13976 ADDR_PS = 0x6,
13977 PREFX = 0x6,
13978 MADDF_FMT = 0x6,
13980 MULR_PS = 0x7,
13981 MSUBF_FMT = 0x7,
13983 MADD_S = 0x01,
13984 MADD_D = 0x09,
13985 MADD_PS = 0x11,
13986 ALNV_PS = 0x19,
13987 MSUB_S = 0x21,
13988 MSUB_D = 0x29,
13989 MSUB_PS = 0x31,
13991 NMADD_S = 0x02,
13992 NMADD_D = 0x0a,
13993 NMADD_PS = 0x12,
13994 NMSUB_S = 0x22,
13995 NMSUB_D = 0x2a,
13996 NMSUB_PS = 0x32,
13998 MIN_FMT = 0x3,
13999 MAX_FMT = 0xb,
14000 MINA_FMT = 0x23,
14001 MAXA_FMT = 0x2b,
14002 POOL32FXF = 0x3b,
14004 CABS_COND_FMT = 0x1c, /* MIPS3D */
14005 C_COND_FMT = 0x3c,
14007 CMP_CONDN_S = 0x5,
14008 CMP_CONDN_D = 0x15
14011 /* POOL32Fxf encoding of minor opcode extension field */
14013 enum {
14014 CVT_L = 0x04,
14015 RSQRT_FMT = 0x08,
14016 FLOOR_L = 0x0c,
14017 CVT_PW_PS = 0x1c,
14018 CVT_W = 0x24,
14019 SQRT_FMT = 0x28,
14020 FLOOR_W = 0x2c,
14021 CVT_PS_PW = 0x3c,
14022 CFC1 = 0x40,
14023 RECIP_FMT = 0x48,
14024 CEIL_L = 0x4c,
14025 CTC1 = 0x60,
14026 CEIL_W = 0x6c,
14027 MFC1 = 0x80,
14028 CVT_S_PL = 0x84,
14029 TRUNC_L = 0x8c,
14030 MTC1 = 0xa0,
14031 CVT_S_PU = 0xa4,
14032 TRUNC_W = 0xac,
14033 MFHC1 = 0xc0,
14034 ROUND_L = 0xcc,
14035 MTHC1 = 0xe0,
14036 ROUND_W = 0xec,
14038 MOV_FMT = 0x01,
14039 MOVF = 0x05,
14040 ABS_FMT = 0x0d,
14041 RSQRT1_FMT = 0x1d,
14042 MOVT = 0x25,
14043 NEG_FMT = 0x2d,
14044 CVT_D = 0x4d,
14045 RECIP1_FMT = 0x5d,
14046 CVT_S = 0x6d
14049 /* POOL32I encoding of minor opcode field (bits 25..21) */
14051 enum {
14052 BLTZ = 0x00,
14053 BLTZAL = 0x01,
14054 BGEZ = 0x02,
14055 BGEZAL = 0x03,
14056 BLEZ = 0x04,
14057 BNEZC = 0x05,
14058 BGTZ = 0x06,
14059 BEQZC = 0x07,
14060 TLTI = 0x08,
14061 BC1EQZC = 0x08,
14062 TGEI = 0x09,
14063 BC1NEZC = 0x09,
14064 TLTIU = 0x0a,
14065 BC2EQZC = 0x0a,
14066 TGEIU = 0x0b,
14067 BC2NEZC = 0x0a,
14068 TNEI = 0x0c,
14069 R6_SYNCI = 0x0c,
14070 LUI = 0x0d,
14071 TEQI = 0x0e,
14072 SYNCI = 0x10,
14073 BLTZALS = 0x11,
14074 BGEZALS = 0x13,
14075 BC2F = 0x14,
14076 BC2T = 0x15,
14077 BPOSGE64 = 0x1a,
14078 BPOSGE32 = 0x1b,
14079 /* These overlap and are distinguished by bit16 of the instruction */
14080 BC1F = 0x1c,
14081 BC1T = 0x1d,
14082 BC1ANY2F = 0x1c,
14083 BC1ANY2T = 0x1d,
14084 BC1ANY4F = 0x1e,
14085 BC1ANY4T = 0x1f
14088 /* POOL16A encoding of minor opcode field */
14090 enum {
14091 ADDU16 = 0x0,
14092 SUBU16 = 0x1
14095 /* POOL16B encoding of minor opcode field */
14097 enum {
14098 SLL16 = 0x0,
14099 SRL16 = 0x1
14102 /* POOL16C encoding of minor opcode field */
14104 enum {
14105 NOT16 = 0x00,
14106 XOR16 = 0x04,
14107 AND16 = 0x08,
14108 OR16 = 0x0c,
14109 LWM16 = 0x10,
14110 SWM16 = 0x14,
14111 JR16 = 0x18,
14112 JRC16 = 0x1a,
14113 JALR16 = 0x1c,
14114 JALR16S = 0x1e,
14115 MFHI16 = 0x20,
14116 MFLO16 = 0x24,
14117 BREAK16 = 0x28,
14118 SDBBP16 = 0x2c,
14119 JRADDIUSP = 0x30
14122 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14124 enum {
14125 R6_NOT16 = 0x00,
14126 R6_AND16 = 0x01,
14127 R6_LWM16 = 0x02,
14128 R6_JRC16 = 0x03,
14129 MOVEP = 0x04,
14130 MOVEP_05 = 0x05,
14131 MOVEP_06 = 0x06,
14132 MOVEP_07 = 0x07,
14133 R6_XOR16 = 0x08,
14134 R6_OR16 = 0x09,
14135 R6_SWM16 = 0x0a,
14136 JALRC16 = 0x0b,
14137 MOVEP_0C = 0x0c,
14138 MOVEP_0D = 0x0d,
14139 MOVEP_0E = 0x0e,
14140 MOVEP_0F = 0x0f,
14141 JRCADDIUSP = 0x13,
14142 R6_BREAK16 = 0x1b,
14143 R6_SDBBP16 = 0x3b
14146 /* POOL16D encoding of minor opcode field */
14148 enum {
14149 ADDIUS5 = 0x0,
14150 ADDIUSP = 0x1
14153 /* POOL16E encoding of minor opcode field */
14155 enum {
14156 ADDIUR2 = 0x0,
14157 ADDIUR1SP = 0x1
14160 static int mmreg(int r)
14162 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14164 return map[r];
14167 /* Used for 16-bit store instructions. */
14168 static int mmreg2(int r)
14170 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14172 return map[r];
14175 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14176 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14177 #define uMIPS_RS2(op) uMIPS_RS(op)
14178 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14179 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14180 #define uMIPS_RS5(op) (op & 0x1f)
14182 /* Signed immediate */
14183 #define SIMM(op, start, width) \
14184 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
14185 << (32 - width)) \
14186 >> (32 - width))
14187 /* Zero-extended immediate */
14188 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
14190 static void gen_addiur1sp(DisasContext *ctx)
14192 int rd = mmreg(uMIPS_RD(ctx->opcode));
14194 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14197 static void gen_addiur2(DisasContext *ctx)
14199 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14200 int rd = mmreg(uMIPS_RD(ctx->opcode));
14201 int rs = mmreg(uMIPS_RS(ctx->opcode));
14203 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14206 static void gen_addiusp(DisasContext *ctx)
14208 int encoded = ZIMM(ctx->opcode, 1, 9);
14209 int decoded;
14211 if (encoded <= 1) {
14212 decoded = 256 + encoded;
14213 } else if (encoded <= 255) {
14214 decoded = encoded;
14215 } else if (encoded <= 509) {
14216 decoded = encoded - 512;
14217 } else {
14218 decoded = encoded - 768;
14221 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14224 static void gen_addius5(DisasContext *ctx)
14226 int imm = SIMM(ctx->opcode, 1, 4);
14227 int rd = (ctx->opcode >> 5) & 0x1f;
14229 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14232 static void gen_andi16(DisasContext *ctx)
14234 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14235 31, 32, 63, 64, 255, 32768, 65535 };
14236 int rd = mmreg(uMIPS_RD(ctx->opcode));
14237 int rs = mmreg(uMIPS_RS(ctx->opcode));
14238 int encoded = ZIMM(ctx->opcode, 0, 4);
14240 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14243 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
14244 int base, int16_t offset)
14246 TCGv t0, t1;
14247 TCGv_i32 t2;
14249 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14250 gen_reserved_instruction(ctx);
14251 return;
14254 t0 = tcg_temp_new();
14256 gen_base_offset_addr(ctx, t0, base, offset);
14258 t1 = tcg_const_tl(reglist);
14259 t2 = tcg_const_i32(ctx->mem_idx);
14261 save_cpu_state(ctx, 1);
14262 switch (opc) {
14263 case LWM32:
14264 gen_helper_lwm(cpu_env, t0, t1, t2);
14265 break;
14266 case SWM32:
14267 gen_helper_swm(cpu_env, t0, t1, t2);
14268 break;
14269 #ifdef TARGET_MIPS64
14270 case LDM:
14271 gen_helper_ldm(cpu_env, t0, t1, t2);
14272 break;
14273 case SDM:
14274 gen_helper_sdm(cpu_env, t0, t1, t2);
14275 break;
14276 #endif
14278 tcg_temp_free(t0);
14279 tcg_temp_free(t1);
14280 tcg_temp_free_i32(t2);
14284 static void gen_pool16c_insn(DisasContext *ctx)
14286 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14287 int rs = mmreg(ctx->opcode & 0x7);
14289 switch (((ctx->opcode) >> 4) & 0x3f) {
14290 case NOT16 + 0:
14291 case NOT16 + 1:
14292 case NOT16 + 2:
14293 case NOT16 + 3:
14294 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14295 break;
14296 case XOR16 + 0:
14297 case XOR16 + 1:
14298 case XOR16 + 2:
14299 case XOR16 + 3:
14300 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14301 break;
14302 case AND16 + 0:
14303 case AND16 + 1:
14304 case AND16 + 2:
14305 case AND16 + 3:
14306 gen_logic(ctx, OPC_AND, rd, rd, rs);
14307 break;
14308 case OR16 + 0:
14309 case OR16 + 1:
14310 case OR16 + 2:
14311 case OR16 + 3:
14312 gen_logic(ctx, OPC_OR, rd, rd, rs);
14313 break;
14314 case LWM16 + 0:
14315 case LWM16 + 1:
14316 case LWM16 + 2:
14317 case LWM16 + 3:
14319 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14320 int offset = ZIMM(ctx->opcode, 0, 4);
14322 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14323 29, offset << 2);
14325 break;
14326 case SWM16 + 0:
14327 case SWM16 + 1:
14328 case SWM16 + 2:
14329 case SWM16 + 3:
14331 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14332 int offset = ZIMM(ctx->opcode, 0, 4);
14334 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14335 29, offset << 2);
14337 break;
14338 case JR16 + 0:
14339 case JR16 + 1:
14341 int reg = ctx->opcode & 0x1f;
14343 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14345 break;
14346 case JRC16 + 0:
14347 case JRC16 + 1:
14349 int reg = ctx->opcode & 0x1f;
14350 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14352 * Let normal delay slot handling in our caller take us
14353 * to the branch target.
14356 break;
14357 case JALR16 + 0:
14358 case JALR16 + 1:
14359 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14360 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14361 break;
14362 case JALR16S + 0:
14363 case JALR16S + 1:
14364 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14365 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14366 break;
14367 case MFHI16 + 0:
14368 case MFHI16 + 1:
14369 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14370 break;
14371 case MFLO16 + 0:
14372 case MFLO16 + 1:
14373 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14374 break;
14375 case BREAK16:
14376 generate_exception_end(ctx, EXCP_BREAK);
14377 break;
14378 case SDBBP16:
14379 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14380 gen_helper_do_semihosting(cpu_env);
14381 } else {
14383 * XXX: not clear which exception should be raised
14384 * when in debug mode...
14386 check_insn(ctx, ISA_MIPS_R1);
14387 generate_exception_end(ctx, EXCP_DBp);
14389 break;
14390 case JRADDIUSP + 0:
14391 case JRADDIUSP + 1:
14393 int imm = ZIMM(ctx->opcode, 0, 5);
14394 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14395 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14397 * Let normal delay slot handling in our caller take us
14398 * to the branch target.
14401 break;
14402 default:
14403 gen_reserved_instruction(ctx);
14404 break;
14408 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14409 int enc_rs)
14411 int rd, re;
14412 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14413 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14414 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14416 rd = rd_enc[enc_dest];
14417 re = re_enc[enc_dest];
14418 gen_load_gpr(cpu_gpr[rd], rs_rt_enc[enc_rs]);
14419 gen_load_gpr(cpu_gpr[re], rs_rt_enc[enc_rt]);
14422 static void gen_pool16c_r6_insn(DisasContext *ctx)
14424 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14425 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14427 switch (ctx->opcode & 0xf) {
14428 case R6_NOT16:
14429 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14430 break;
14431 case R6_AND16:
14432 gen_logic(ctx, OPC_AND, rt, rt, rs);
14433 break;
14434 case R6_LWM16:
14436 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14437 int offset = extract32(ctx->opcode, 4, 4);
14438 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14440 break;
14441 case R6_JRC16: /* JRCADDIUSP */
14442 if ((ctx->opcode >> 4) & 1) {
14443 /* JRCADDIUSP */
14444 int imm = extract32(ctx->opcode, 5, 5);
14445 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14446 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14447 } else {
14448 /* JRC16 */
14449 rs = extract32(ctx->opcode, 5, 5);
14450 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14452 break;
14453 case MOVEP:
14454 case MOVEP_05:
14455 case MOVEP_06:
14456 case MOVEP_07:
14457 case MOVEP_0C:
14458 case MOVEP_0D:
14459 case MOVEP_0E:
14460 case MOVEP_0F:
14462 int enc_dest = uMIPS_RD(ctx->opcode);
14463 int enc_rt = uMIPS_RS2(ctx->opcode);
14464 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14465 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14467 break;
14468 case R6_XOR16:
14469 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14470 break;
14471 case R6_OR16:
14472 gen_logic(ctx, OPC_OR, rt, rt, rs);
14473 break;
14474 case R6_SWM16:
14476 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14477 int offset = extract32(ctx->opcode, 4, 4);
14478 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14480 break;
14481 case JALRC16: /* BREAK16, SDBBP16 */
14482 switch (ctx->opcode & 0x3f) {
14483 case JALRC16:
14484 case JALRC16 + 0x20:
14485 /* JALRC16 */
14486 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14487 31, 0, 0);
14488 break;
14489 case R6_BREAK16:
14490 /* BREAK16 */
14491 generate_exception(ctx, EXCP_BREAK);
14492 break;
14493 case R6_SDBBP16:
14494 /* SDBBP16 */
14495 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14496 gen_helper_do_semihosting(cpu_env);
14497 } else {
14498 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14499 generate_exception(ctx, EXCP_RI);
14500 } else {
14501 generate_exception(ctx, EXCP_DBp);
14504 break;
14506 break;
14507 default:
14508 generate_exception(ctx, EXCP_RI);
14509 break;
14513 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
14515 TCGv t0 = tcg_temp_new();
14516 TCGv t1 = tcg_temp_new();
14518 gen_load_gpr(t0, base);
14520 if (index != 0) {
14521 gen_load_gpr(t1, index);
14522 tcg_gen_shli_tl(t1, t1, 2);
14523 gen_op_addr_add(ctx, t0, t1, t0);
14526 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14527 gen_store_gpr(t1, rd);
14529 tcg_temp_free(t0);
14530 tcg_temp_free(t1);
14533 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
14534 int base, int16_t offset)
14536 TCGv t0, t1;
14538 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14539 gen_reserved_instruction(ctx);
14540 return;
14543 t0 = tcg_temp_new();
14544 t1 = tcg_temp_new();
14546 gen_base_offset_addr(ctx, t0, base, offset);
14548 switch (opc) {
14549 case LWP:
14550 if (rd == base) {
14551 gen_reserved_instruction(ctx);
14552 return;
14554 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14555 gen_store_gpr(t1, rd);
14556 tcg_gen_movi_tl(t1, 4);
14557 gen_op_addr_add(ctx, t0, t0, t1);
14558 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14559 gen_store_gpr(t1, rd + 1);
14560 break;
14561 case SWP:
14562 gen_load_gpr(t1, rd);
14563 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14564 tcg_gen_movi_tl(t1, 4);
14565 gen_op_addr_add(ctx, t0, t0, t1);
14566 gen_load_gpr(t1, rd + 1);
14567 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14568 break;
14569 #ifdef TARGET_MIPS64
14570 case LDP:
14571 if (rd == base) {
14572 gen_reserved_instruction(ctx);
14573 return;
14575 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14576 gen_store_gpr(t1, rd);
14577 tcg_gen_movi_tl(t1, 8);
14578 gen_op_addr_add(ctx, t0, t0, t1);
14579 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14580 gen_store_gpr(t1, rd + 1);
14581 break;
14582 case SDP:
14583 gen_load_gpr(t1, rd);
14584 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14585 tcg_gen_movi_tl(t1, 8);
14586 gen_op_addr_add(ctx, t0, t0, t1);
14587 gen_load_gpr(t1, rd + 1);
14588 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14589 break;
14590 #endif
14592 tcg_temp_free(t0);
14593 tcg_temp_free(t1);
14596 static void gen_sync(int stype)
14598 TCGBar tcg_mo = TCG_BAR_SC;
14600 switch (stype) {
14601 case 0x4: /* SYNC_WMB */
14602 tcg_mo |= TCG_MO_ST_ST;
14603 break;
14604 case 0x10: /* SYNC_MB */
14605 tcg_mo |= TCG_MO_ALL;
14606 break;
14607 case 0x11: /* SYNC_ACQUIRE */
14608 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14609 break;
14610 case 0x12: /* SYNC_RELEASE */
14611 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14612 break;
14613 case 0x13: /* SYNC_RMB */
14614 tcg_mo |= TCG_MO_LD_LD;
14615 break;
14616 default:
14617 tcg_mo |= TCG_MO_ALL;
14618 break;
14621 tcg_gen_mb(tcg_mo);
14624 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14626 int extension = (ctx->opcode >> 6) & 0x3f;
14627 int minor = (ctx->opcode >> 12) & 0xf;
14628 uint32_t mips32_op;
14630 switch (extension) {
14631 case TEQ:
14632 mips32_op = OPC_TEQ;
14633 goto do_trap;
14634 case TGE:
14635 mips32_op = OPC_TGE;
14636 goto do_trap;
14637 case TGEU:
14638 mips32_op = OPC_TGEU;
14639 goto do_trap;
14640 case TLT:
14641 mips32_op = OPC_TLT;
14642 goto do_trap;
14643 case TLTU:
14644 mips32_op = OPC_TLTU;
14645 goto do_trap;
14646 case TNE:
14647 mips32_op = OPC_TNE;
14648 do_trap:
14649 gen_trap(ctx, mips32_op, rs, rt, -1);
14650 break;
14651 #ifndef CONFIG_USER_ONLY
14652 case MFC0:
14653 case MFC0 + 32:
14654 check_cp0_enabled(ctx);
14655 if (rt == 0) {
14656 /* Treat as NOP. */
14657 break;
14659 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
14660 break;
14661 case MTC0:
14662 case MTC0 + 32:
14663 check_cp0_enabled(ctx);
14665 TCGv t0 = tcg_temp_new();
14667 gen_load_gpr(t0, rt);
14668 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
14669 tcg_temp_free(t0);
14671 break;
14672 #endif
14673 case 0x2a:
14674 switch (minor & 3) {
14675 case MADD_ACC:
14676 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
14677 break;
14678 case MADDU_ACC:
14679 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
14680 break;
14681 case MSUB_ACC:
14682 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
14683 break;
14684 case MSUBU_ACC:
14685 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
14686 break;
14687 default:
14688 goto pool32axf_invalid;
14690 break;
14691 case 0x32:
14692 switch (minor & 3) {
14693 case MULT_ACC:
14694 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
14695 break;
14696 case MULTU_ACC:
14697 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
14698 break;
14699 default:
14700 goto pool32axf_invalid;
14702 break;
14703 case 0x2c:
14704 switch (minor) {
14705 case BITSWAP:
14706 check_insn(ctx, ISA_MIPS_R6);
14707 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
14708 break;
14709 case SEB:
14710 gen_bshfl(ctx, OPC_SEB, rs, rt);
14711 break;
14712 case SEH:
14713 gen_bshfl(ctx, OPC_SEH, rs, rt);
14714 break;
14715 case CLO:
14716 mips32_op = OPC_CLO;
14717 goto do_cl;
14718 case CLZ:
14719 mips32_op = OPC_CLZ;
14720 do_cl:
14721 check_insn(ctx, ISA_MIPS_R1);
14722 gen_cl(ctx, mips32_op, rt, rs);
14723 break;
14724 case RDHWR:
14725 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14726 gen_rdhwr(ctx, rt, rs, 0);
14727 break;
14728 case WSBH:
14729 gen_bshfl(ctx, OPC_WSBH, rs, rt);
14730 break;
14731 case MULT:
14732 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14733 mips32_op = OPC_MULT;
14734 goto do_mul;
14735 case MULTU:
14736 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14737 mips32_op = OPC_MULTU;
14738 goto do_mul;
14739 case DIV:
14740 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14741 mips32_op = OPC_DIV;
14742 goto do_div;
14743 case DIVU:
14744 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14745 mips32_op = OPC_DIVU;
14746 goto do_div;
14747 do_div:
14748 check_insn(ctx, ISA_MIPS_R1);
14749 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14750 break;
14751 case MADD:
14752 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14753 mips32_op = OPC_MADD;
14754 goto do_mul;
14755 case MADDU:
14756 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14757 mips32_op = OPC_MADDU;
14758 goto do_mul;
14759 case MSUB:
14760 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14761 mips32_op = OPC_MSUB;
14762 goto do_mul;
14763 case MSUBU:
14764 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14765 mips32_op = OPC_MSUBU;
14766 do_mul:
14767 check_insn(ctx, ISA_MIPS_R1);
14768 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14769 break;
14770 default:
14771 goto pool32axf_invalid;
14773 break;
14774 case 0x34:
14775 switch (minor) {
14776 case MFC2:
14777 case MTC2:
14778 case MFHC2:
14779 case MTHC2:
14780 case CFC2:
14781 case CTC2:
14782 generate_exception_err(ctx, EXCP_CpU, 2);
14783 break;
14784 default:
14785 goto pool32axf_invalid;
14787 break;
14788 case 0x3c:
14789 switch (minor) {
14790 case JALR: /* JALRC */
14791 case JALR_HB: /* JALRC_HB */
14792 if (ctx->insn_flags & ISA_MIPS_R6) {
14793 /* JALRC, JALRC_HB */
14794 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
14795 } else {
14796 /* JALR, JALR_HB */
14797 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
14798 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14800 break;
14801 case JALRS:
14802 case JALRS_HB:
14803 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14804 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
14805 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14806 break;
14807 default:
14808 goto pool32axf_invalid;
14810 break;
14811 case 0x05:
14812 switch (minor) {
14813 case RDPGPR:
14814 check_cp0_enabled(ctx);
14815 check_insn(ctx, ISA_MIPS_R2);
14816 gen_load_srsgpr(rs, rt);
14817 break;
14818 case WRPGPR:
14819 check_cp0_enabled(ctx);
14820 check_insn(ctx, ISA_MIPS_R2);
14821 gen_store_srsgpr(rs, rt);
14822 break;
14823 default:
14824 goto pool32axf_invalid;
14826 break;
14827 #ifndef CONFIG_USER_ONLY
14828 case 0x0d:
14829 switch (minor) {
14830 case TLBP:
14831 mips32_op = OPC_TLBP;
14832 goto do_cp0;
14833 case TLBR:
14834 mips32_op = OPC_TLBR;
14835 goto do_cp0;
14836 case TLBWI:
14837 mips32_op = OPC_TLBWI;
14838 goto do_cp0;
14839 case TLBWR:
14840 mips32_op = OPC_TLBWR;
14841 goto do_cp0;
14842 case TLBINV:
14843 mips32_op = OPC_TLBINV;
14844 goto do_cp0;
14845 case TLBINVF:
14846 mips32_op = OPC_TLBINVF;
14847 goto do_cp0;
14848 case WAIT:
14849 mips32_op = OPC_WAIT;
14850 goto do_cp0;
14851 case DERET:
14852 mips32_op = OPC_DERET;
14853 goto do_cp0;
14854 case ERET:
14855 mips32_op = OPC_ERET;
14856 do_cp0:
14857 gen_cp0(env, ctx, mips32_op, rt, rs);
14858 break;
14859 default:
14860 goto pool32axf_invalid;
14862 break;
14863 case 0x1d:
14864 switch (minor) {
14865 case DI:
14866 check_cp0_enabled(ctx);
14868 TCGv t0 = tcg_temp_new();
14870 save_cpu_state(ctx, 1);
14871 gen_helper_di(t0, cpu_env);
14872 gen_store_gpr(t0, rs);
14874 * Stop translation as we may have switched the execution
14875 * mode.
14877 ctx->base.is_jmp = DISAS_STOP;
14878 tcg_temp_free(t0);
14880 break;
14881 case EI:
14882 check_cp0_enabled(ctx);
14884 TCGv t0 = tcg_temp_new();
14886 save_cpu_state(ctx, 1);
14887 gen_helper_ei(t0, cpu_env);
14888 gen_store_gpr(t0, rs);
14890 * DISAS_STOP isn't sufficient, we need to ensure we break out
14891 * of translated code to check for pending interrupts.
14893 gen_save_pc(ctx->base.pc_next + 4);
14894 ctx->base.is_jmp = DISAS_EXIT;
14895 tcg_temp_free(t0);
14897 break;
14898 default:
14899 goto pool32axf_invalid;
14901 break;
14902 #endif
14903 case 0x2d:
14904 switch (minor) {
14905 case SYNC:
14906 gen_sync(extract32(ctx->opcode, 16, 5));
14907 break;
14908 case SYSCALL:
14909 generate_exception_end(ctx, EXCP_SYSCALL);
14910 break;
14911 case SDBBP:
14912 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
14913 gen_helper_do_semihosting(cpu_env);
14914 } else {
14915 check_insn(ctx, ISA_MIPS_R1);
14916 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14917 gen_reserved_instruction(ctx);
14918 } else {
14919 generate_exception_end(ctx, EXCP_DBp);
14922 break;
14923 default:
14924 goto pool32axf_invalid;
14926 break;
14927 case 0x01:
14928 switch (minor & 3) {
14929 case MFHI_ACC:
14930 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
14931 break;
14932 case MFLO_ACC:
14933 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
14934 break;
14935 case MTHI_ACC:
14936 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
14937 break;
14938 case MTLO_ACC:
14939 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
14940 break;
14941 default:
14942 goto pool32axf_invalid;
14944 break;
14945 case 0x35:
14946 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14947 switch (minor) {
14948 case MFHI32:
14949 gen_HILO(ctx, OPC_MFHI, 0, rs);
14950 break;
14951 case MFLO32:
14952 gen_HILO(ctx, OPC_MFLO, 0, rs);
14953 break;
14954 case MTHI32:
14955 gen_HILO(ctx, OPC_MTHI, 0, rs);
14956 break;
14957 case MTLO32:
14958 gen_HILO(ctx, OPC_MTLO, 0, rs);
14959 break;
14960 default:
14961 goto pool32axf_invalid;
14963 break;
14964 default:
14965 pool32axf_invalid:
14966 MIPS_INVAL("pool32axf");
14967 gen_reserved_instruction(ctx);
14968 break;
14973 * Values for microMIPS fmt field. Variable-width, depending on which
14974 * formats the instruction supports.
14976 enum {
14977 FMT_SD_S = 0,
14978 FMT_SD_D = 1,
14980 FMT_SDPS_S = 0,
14981 FMT_SDPS_D = 1,
14982 FMT_SDPS_PS = 2,
14984 FMT_SWL_S = 0,
14985 FMT_SWL_W = 1,
14986 FMT_SWL_L = 2,
14988 FMT_DWL_D = 0,
14989 FMT_DWL_W = 1,
14990 FMT_DWL_L = 2
14993 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
14995 int extension = (ctx->opcode >> 6) & 0x3ff;
14996 uint32_t mips32_op;
14998 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
14999 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
15000 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
15002 switch (extension) {
15003 case FLOAT_1BIT_FMT(CFC1, 0):
15004 mips32_op = OPC_CFC1;
15005 goto do_cp1;
15006 case FLOAT_1BIT_FMT(CTC1, 0):
15007 mips32_op = OPC_CTC1;
15008 goto do_cp1;
15009 case FLOAT_1BIT_FMT(MFC1, 0):
15010 mips32_op = OPC_MFC1;
15011 goto do_cp1;
15012 case FLOAT_1BIT_FMT(MTC1, 0):
15013 mips32_op = OPC_MTC1;
15014 goto do_cp1;
15015 case FLOAT_1BIT_FMT(MFHC1, 0):
15016 mips32_op = OPC_MFHC1;
15017 goto do_cp1;
15018 case FLOAT_1BIT_FMT(MTHC1, 0):
15019 mips32_op = OPC_MTHC1;
15020 do_cp1:
15021 gen_cp1(ctx, mips32_op, rt, rs);
15022 break;
15024 /* Reciprocal square root */
15025 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15026 mips32_op = OPC_RSQRT_S;
15027 goto do_unaryfp;
15028 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15029 mips32_op = OPC_RSQRT_D;
15030 goto do_unaryfp;
15032 /* Square root */
15033 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15034 mips32_op = OPC_SQRT_S;
15035 goto do_unaryfp;
15036 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15037 mips32_op = OPC_SQRT_D;
15038 goto do_unaryfp;
15040 /* Reciprocal */
15041 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15042 mips32_op = OPC_RECIP_S;
15043 goto do_unaryfp;
15044 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15045 mips32_op = OPC_RECIP_D;
15046 goto do_unaryfp;
15048 /* Floor */
15049 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15050 mips32_op = OPC_FLOOR_L_S;
15051 goto do_unaryfp;
15052 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15053 mips32_op = OPC_FLOOR_L_D;
15054 goto do_unaryfp;
15055 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15056 mips32_op = OPC_FLOOR_W_S;
15057 goto do_unaryfp;
15058 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15059 mips32_op = OPC_FLOOR_W_D;
15060 goto do_unaryfp;
15062 /* Ceiling */
15063 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15064 mips32_op = OPC_CEIL_L_S;
15065 goto do_unaryfp;
15066 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15067 mips32_op = OPC_CEIL_L_D;
15068 goto do_unaryfp;
15069 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15070 mips32_op = OPC_CEIL_W_S;
15071 goto do_unaryfp;
15072 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15073 mips32_op = OPC_CEIL_W_D;
15074 goto do_unaryfp;
15076 /* Truncation */
15077 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15078 mips32_op = OPC_TRUNC_L_S;
15079 goto do_unaryfp;
15080 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15081 mips32_op = OPC_TRUNC_L_D;
15082 goto do_unaryfp;
15083 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15084 mips32_op = OPC_TRUNC_W_S;
15085 goto do_unaryfp;
15086 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15087 mips32_op = OPC_TRUNC_W_D;
15088 goto do_unaryfp;
15090 /* Round */
15091 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15092 mips32_op = OPC_ROUND_L_S;
15093 goto do_unaryfp;
15094 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15095 mips32_op = OPC_ROUND_L_D;
15096 goto do_unaryfp;
15097 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15098 mips32_op = OPC_ROUND_W_S;
15099 goto do_unaryfp;
15100 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15101 mips32_op = OPC_ROUND_W_D;
15102 goto do_unaryfp;
15104 /* Integer to floating-point conversion */
15105 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15106 mips32_op = OPC_CVT_L_S;
15107 goto do_unaryfp;
15108 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15109 mips32_op = OPC_CVT_L_D;
15110 goto do_unaryfp;
15111 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15112 mips32_op = OPC_CVT_W_S;
15113 goto do_unaryfp;
15114 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15115 mips32_op = OPC_CVT_W_D;
15116 goto do_unaryfp;
15118 /* Paired-foo conversions */
15119 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15120 mips32_op = OPC_CVT_S_PL;
15121 goto do_unaryfp;
15122 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15123 mips32_op = OPC_CVT_S_PU;
15124 goto do_unaryfp;
15125 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15126 mips32_op = OPC_CVT_PW_PS;
15127 goto do_unaryfp;
15128 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15129 mips32_op = OPC_CVT_PS_PW;
15130 goto do_unaryfp;
15132 /* Floating-point moves */
15133 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15134 mips32_op = OPC_MOV_S;
15135 goto do_unaryfp;
15136 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15137 mips32_op = OPC_MOV_D;
15138 goto do_unaryfp;
15139 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15140 mips32_op = OPC_MOV_PS;
15141 goto do_unaryfp;
15143 /* Absolute value */
15144 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15145 mips32_op = OPC_ABS_S;
15146 goto do_unaryfp;
15147 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15148 mips32_op = OPC_ABS_D;
15149 goto do_unaryfp;
15150 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15151 mips32_op = OPC_ABS_PS;
15152 goto do_unaryfp;
15154 /* Negation */
15155 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15156 mips32_op = OPC_NEG_S;
15157 goto do_unaryfp;
15158 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15159 mips32_op = OPC_NEG_D;
15160 goto do_unaryfp;
15161 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15162 mips32_op = OPC_NEG_PS;
15163 goto do_unaryfp;
15165 /* Reciprocal square root step */
15166 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15167 mips32_op = OPC_RSQRT1_S;
15168 goto do_unaryfp;
15169 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15170 mips32_op = OPC_RSQRT1_D;
15171 goto do_unaryfp;
15172 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15173 mips32_op = OPC_RSQRT1_PS;
15174 goto do_unaryfp;
15176 /* Reciprocal step */
15177 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15178 mips32_op = OPC_RECIP1_S;
15179 goto do_unaryfp;
15180 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15181 mips32_op = OPC_RECIP1_S;
15182 goto do_unaryfp;
15183 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15184 mips32_op = OPC_RECIP1_PS;
15185 goto do_unaryfp;
15187 /* Conversions from double */
15188 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15189 mips32_op = OPC_CVT_D_S;
15190 goto do_unaryfp;
15191 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15192 mips32_op = OPC_CVT_D_W;
15193 goto do_unaryfp;
15194 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15195 mips32_op = OPC_CVT_D_L;
15196 goto do_unaryfp;
15198 /* Conversions from single */
15199 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15200 mips32_op = OPC_CVT_S_D;
15201 goto do_unaryfp;
15202 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15203 mips32_op = OPC_CVT_S_W;
15204 goto do_unaryfp;
15205 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15206 mips32_op = OPC_CVT_S_L;
15207 do_unaryfp:
15208 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15209 break;
15211 /* Conditional moves on floating-point codes */
15212 case COND_FLOAT_MOV(MOVT, 0):
15213 case COND_FLOAT_MOV(MOVT, 1):
15214 case COND_FLOAT_MOV(MOVT, 2):
15215 case COND_FLOAT_MOV(MOVT, 3):
15216 case COND_FLOAT_MOV(MOVT, 4):
15217 case COND_FLOAT_MOV(MOVT, 5):
15218 case COND_FLOAT_MOV(MOVT, 6):
15219 case COND_FLOAT_MOV(MOVT, 7):
15220 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15221 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15222 break;
15223 case COND_FLOAT_MOV(MOVF, 0):
15224 case COND_FLOAT_MOV(MOVF, 1):
15225 case COND_FLOAT_MOV(MOVF, 2):
15226 case COND_FLOAT_MOV(MOVF, 3):
15227 case COND_FLOAT_MOV(MOVF, 4):
15228 case COND_FLOAT_MOV(MOVF, 5):
15229 case COND_FLOAT_MOV(MOVF, 6):
15230 case COND_FLOAT_MOV(MOVF, 7):
15231 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15232 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15233 break;
15234 default:
15235 MIPS_INVAL("pool32fxf");
15236 gen_reserved_instruction(ctx);
15237 break;
15241 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15243 int32_t offset;
15244 uint16_t insn;
15245 int rt, rs, rd, rr;
15246 int16_t imm;
15247 uint32_t op, minor, minor2, mips32_op;
15248 uint32_t cond, fmt, cc;
15250 insn = translator_lduw(env, ctx->base.pc_next + 2);
15251 ctx->opcode = (ctx->opcode << 16) | insn;
15253 rt = (ctx->opcode >> 21) & 0x1f;
15254 rs = (ctx->opcode >> 16) & 0x1f;
15255 rd = (ctx->opcode >> 11) & 0x1f;
15256 rr = (ctx->opcode >> 6) & 0x1f;
15257 imm = (int16_t) ctx->opcode;
15259 op = (ctx->opcode >> 26) & 0x3f;
15260 switch (op) {
15261 case POOL32A:
15262 minor = ctx->opcode & 0x3f;
15263 switch (minor) {
15264 case 0x00:
15265 minor = (ctx->opcode >> 6) & 0xf;
15266 switch (minor) {
15267 case SLL32:
15268 mips32_op = OPC_SLL;
15269 goto do_shifti;
15270 case SRA:
15271 mips32_op = OPC_SRA;
15272 goto do_shifti;
15273 case SRL32:
15274 mips32_op = OPC_SRL;
15275 goto do_shifti;
15276 case ROTR:
15277 mips32_op = OPC_ROTR;
15278 do_shifti:
15279 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15280 break;
15281 case SELEQZ:
15282 check_insn(ctx, ISA_MIPS_R6);
15283 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15284 break;
15285 case SELNEZ:
15286 check_insn(ctx, ISA_MIPS_R6);
15287 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15288 break;
15289 case R6_RDHWR:
15290 check_insn(ctx, ISA_MIPS_R6);
15291 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15292 break;
15293 default:
15294 goto pool32a_invalid;
15296 break;
15297 case 0x10:
15298 minor = (ctx->opcode >> 6) & 0xf;
15299 switch (minor) {
15300 /* Arithmetic */
15301 case ADD:
15302 mips32_op = OPC_ADD;
15303 goto do_arith;
15304 case ADDU32:
15305 mips32_op = OPC_ADDU;
15306 goto do_arith;
15307 case SUB:
15308 mips32_op = OPC_SUB;
15309 goto do_arith;
15310 case SUBU32:
15311 mips32_op = OPC_SUBU;
15312 goto do_arith;
15313 case MUL:
15314 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15315 mips32_op = OPC_MUL;
15316 do_arith:
15317 gen_arith(ctx, mips32_op, rd, rs, rt);
15318 break;
15319 /* Shifts */
15320 case SLLV:
15321 mips32_op = OPC_SLLV;
15322 goto do_shift;
15323 case SRLV:
15324 mips32_op = OPC_SRLV;
15325 goto do_shift;
15326 case SRAV:
15327 mips32_op = OPC_SRAV;
15328 goto do_shift;
15329 case ROTRV:
15330 mips32_op = OPC_ROTRV;
15331 do_shift:
15332 gen_shift(ctx, mips32_op, rd, rs, rt);
15333 break;
15334 /* Logical operations */
15335 case AND:
15336 mips32_op = OPC_AND;
15337 goto do_logic;
15338 case OR32:
15339 mips32_op = OPC_OR;
15340 goto do_logic;
15341 case NOR:
15342 mips32_op = OPC_NOR;
15343 goto do_logic;
15344 case XOR32:
15345 mips32_op = OPC_XOR;
15346 do_logic:
15347 gen_logic(ctx, mips32_op, rd, rs, rt);
15348 break;
15349 /* Set less than */
15350 case SLT:
15351 mips32_op = OPC_SLT;
15352 goto do_slt;
15353 case SLTU:
15354 mips32_op = OPC_SLTU;
15355 do_slt:
15356 gen_slt(ctx, mips32_op, rd, rs, rt);
15357 break;
15358 default:
15359 goto pool32a_invalid;
15361 break;
15362 case 0x18:
15363 minor = (ctx->opcode >> 6) & 0xf;
15364 switch (minor) {
15365 /* Conditional moves */
15366 case MOVN: /* MUL */
15367 if (ctx->insn_flags & ISA_MIPS_R6) {
15368 /* MUL */
15369 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15370 } else {
15371 /* MOVN */
15372 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15374 break;
15375 case MOVZ: /* MUH */
15376 if (ctx->insn_flags & ISA_MIPS_R6) {
15377 /* MUH */
15378 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15379 } else {
15380 /* MOVZ */
15381 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15383 break;
15384 case MULU:
15385 check_insn(ctx, ISA_MIPS_R6);
15386 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15387 break;
15388 case MUHU:
15389 check_insn(ctx, ISA_MIPS_R6);
15390 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15391 break;
15392 case LWXS: /* DIV */
15393 if (ctx->insn_flags & ISA_MIPS_R6) {
15394 /* DIV */
15395 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15396 } else {
15397 /* LWXS */
15398 gen_ldxs(ctx, rs, rt, rd);
15400 break;
15401 case MOD:
15402 check_insn(ctx, ISA_MIPS_R6);
15403 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15404 break;
15405 case R6_DIVU:
15406 check_insn(ctx, ISA_MIPS_R6);
15407 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15408 break;
15409 case MODU:
15410 check_insn(ctx, ISA_MIPS_R6);
15411 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15412 break;
15413 default:
15414 goto pool32a_invalid;
15416 break;
15417 case INS:
15418 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15419 return;
15420 case LSA:
15421 check_insn(ctx, ISA_MIPS_R6);
15422 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2));
15423 break;
15424 case ALIGN:
15425 check_insn(ctx, ISA_MIPS_R6);
15426 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15427 break;
15428 case EXT:
15429 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15430 return;
15431 case POOL32AXF:
15432 gen_pool32axf(env, ctx, rt, rs);
15433 break;
15434 case BREAK32:
15435 generate_exception_end(ctx, EXCP_BREAK);
15436 break;
15437 case SIGRIE:
15438 check_insn(ctx, ISA_MIPS_R6);
15439 gen_reserved_instruction(ctx);
15440 break;
15441 default:
15442 pool32a_invalid:
15443 MIPS_INVAL("pool32a");
15444 gen_reserved_instruction(ctx);
15445 break;
15447 break;
15448 case POOL32B:
15449 minor = (ctx->opcode >> 12) & 0xf;
15450 switch (minor) {
15451 case CACHE:
15452 check_cp0_enabled(ctx);
15453 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15454 gen_cache_operation(ctx, rt, rs, imm);
15456 break;
15457 case LWC2:
15458 case SWC2:
15459 /* COP2: Not implemented. */
15460 generate_exception_err(ctx, EXCP_CpU, 2);
15461 break;
15462 #ifdef TARGET_MIPS64
15463 case LDP:
15464 case SDP:
15465 check_insn(ctx, ISA_MIPS3);
15466 check_mips_64(ctx);
15467 #endif
15468 /* fall through */
15469 case LWP:
15470 case SWP:
15471 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15472 break;
15473 #ifdef TARGET_MIPS64
15474 case LDM:
15475 case SDM:
15476 check_insn(ctx, ISA_MIPS3);
15477 check_mips_64(ctx);
15478 #endif
15479 /* fall through */
15480 case LWM32:
15481 case SWM32:
15482 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15483 break;
15484 default:
15485 MIPS_INVAL("pool32b");
15486 gen_reserved_instruction(ctx);
15487 break;
15489 break;
15490 case POOL32F:
15491 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15492 minor = ctx->opcode & 0x3f;
15493 check_cp1_enabled(ctx);
15494 switch (minor) {
15495 case ALNV_PS:
15496 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15497 mips32_op = OPC_ALNV_PS;
15498 goto do_madd;
15499 case MADD_S:
15500 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15501 mips32_op = OPC_MADD_S;
15502 goto do_madd;
15503 case MADD_D:
15504 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15505 mips32_op = OPC_MADD_D;
15506 goto do_madd;
15507 case MADD_PS:
15508 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15509 mips32_op = OPC_MADD_PS;
15510 goto do_madd;
15511 case MSUB_S:
15512 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15513 mips32_op = OPC_MSUB_S;
15514 goto do_madd;
15515 case MSUB_D:
15516 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15517 mips32_op = OPC_MSUB_D;
15518 goto do_madd;
15519 case MSUB_PS:
15520 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15521 mips32_op = OPC_MSUB_PS;
15522 goto do_madd;
15523 case NMADD_S:
15524 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15525 mips32_op = OPC_NMADD_S;
15526 goto do_madd;
15527 case NMADD_D:
15528 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15529 mips32_op = OPC_NMADD_D;
15530 goto do_madd;
15531 case NMADD_PS:
15532 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15533 mips32_op = OPC_NMADD_PS;
15534 goto do_madd;
15535 case NMSUB_S:
15536 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15537 mips32_op = OPC_NMSUB_S;
15538 goto do_madd;
15539 case NMSUB_D:
15540 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15541 mips32_op = OPC_NMSUB_D;
15542 goto do_madd;
15543 case NMSUB_PS:
15544 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15545 mips32_op = OPC_NMSUB_PS;
15546 do_madd:
15547 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15548 break;
15549 case CABS_COND_FMT:
15550 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15551 cond = (ctx->opcode >> 6) & 0xf;
15552 cc = (ctx->opcode >> 13) & 0x7;
15553 fmt = (ctx->opcode >> 10) & 0x3;
15554 switch (fmt) {
15555 case 0x0:
15556 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15557 break;
15558 case 0x1:
15559 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15560 break;
15561 case 0x2:
15562 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15563 break;
15564 default:
15565 goto pool32f_invalid;
15567 break;
15568 case C_COND_FMT:
15569 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15570 cond = (ctx->opcode >> 6) & 0xf;
15571 cc = (ctx->opcode >> 13) & 0x7;
15572 fmt = (ctx->opcode >> 10) & 0x3;
15573 switch (fmt) {
15574 case 0x0:
15575 gen_cmp_s(ctx, cond, rt, rs, cc);
15576 break;
15577 case 0x1:
15578 gen_cmp_d(ctx, cond, rt, rs, cc);
15579 break;
15580 case 0x2:
15581 gen_cmp_ps(ctx, cond, rt, rs, cc);
15582 break;
15583 default:
15584 goto pool32f_invalid;
15586 break;
15587 case CMP_CONDN_S:
15588 check_insn(ctx, ISA_MIPS_R6);
15589 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15590 break;
15591 case CMP_CONDN_D:
15592 check_insn(ctx, ISA_MIPS_R6);
15593 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15594 break;
15595 case POOL32FXF:
15596 gen_pool32fxf(ctx, rt, rs);
15597 break;
15598 case 0x00:
15599 /* PLL foo */
15600 switch ((ctx->opcode >> 6) & 0x7) {
15601 case PLL_PS:
15602 mips32_op = OPC_PLL_PS;
15603 goto do_ps;
15604 case PLU_PS:
15605 mips32_op = OPC_PLU_PS;
15606 goto do_ps;
15607 case PUL_PS:
15608 mips32_op = OPC_PUL_PS;
15609 goto do_ps;
15610 case PUU_PS:
15611 mips32_op = OPC_PUU_PS;
15612 goto do_ps;
15613 case CVT_PS_S:
15614 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15615 mips32_op = OPC_CVT_PS_S;
15616 do_ps:
15617 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15618 break;
15619 default:
15620 goto pool32f_invalid;
15622 break;
15623 case MIN_FMT:
15624 check_insn(ctx, ISA_MIPS_R6);
15625 switch ((ctx->opcode >> 9) & 0x3) {
15626 case FMT_SDPS_S:
15627 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15628 break;
15629 case FMT_SDPS_D:
15630 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15631 break;
15632 default:
15633 goto pool32f_invalid;
15635 break;
15636 case 0x08:
15637 /* [LS][WDU]XC1 */
15638 switch ((ctx->opcode >> 6) & 0x7) {
15639 case LWXC1:
15640 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15641 mips32_op = OPC_LWXC1;
15642 goto do_ldst_cp1;
15643 case SWXC1:
15644 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15645 mips32_op = OPC_SWXC1;
15646 goto do_ldst_cp1;
15647 case LDXC1:
15648 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15649 mips32_op = OPC_LDXC1;
15650 goto do_ldst_cp1;
15651 case SDXC1:
15652 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15653 mips32_op = OPC_SDXC1;
15654 goto do_ldst_cp1;
15655 case LUXC1:
15656 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15657 mips32_op = OPC_LUXC1;
15658 goto do_ldst_cp1;
15659 case SUXC1:
15660 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15661 mips32_op = OPC_SUXC1;
15662 do_ldst_cp1:
15663 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15664 break;
15665 default:
15666 goto pool32f_invalid;
15668 break;
15669 case MAX_FMT:
15670 check_insn(ctx, ISA_MIPS_R6);
15671 switch ((ctx->opcode >> 9) & 0x3) {
15672 case FMT_SDPS_S:
15673 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
15674 break;
15675 case FMT_SDPS_D:
15676 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
15677 break;
15678 default:
15679 goto pool32f_invalid;
15681 break;
15682 case 0x18:
15683 /* 3D insns */
15684 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15685 fmt = (ctx->opcode >> 9) & 0x3;
15686 switch ((ctx->opcode >> 6) & 0x7) {
15687 case RSQRT2_FMT:
15688 switch (fmt) {
15689 case FMT_SDPS_S:
15690 mips32_op = OPC_RSQRT2_S;
15691 goto do_3d;
15692 case FMT_SDPS_D:
15693 mips32_op = OPC_RSQRT2_D;
15694 goto do_3d;
15695 case FMT_SDPS_PS:
15696 mips32_op = OPC_RSQRT2_PS;
15697 goto do_3d;
15698 default:
15699 goto pool32f_invalid;
15701 break;
15702 case RECIP2_FMT:
15703 switch (fmt) {
15704 case FMT_SDPS_S:
15705 mips32_op = OPC_RECIP2_S;
15706 goto do_3d;
15707 case FMT_SDPS_D:
15708 mips32_op = OPC_RECIP2_D;
15709 goto do_3d;
15710 case FMT_SDPS_PS:
15711 mips32_op = OPC_RECIP2_PS;
15712 goto do_3d;
15713 default:
15714 goto pool32f_invalid;
15716 break;
15717 case ADDR_PS:
15718 mips32_op = OPC_ADDR_PS;
15719 goto do_3d;
15720 case MULR_PS:
15721 mips32_op = OPC_MULR_PS;
15722 do_3d:
15723 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15724 break;
15725 default:
15726 goto pool32f_invalid;
15728 break;
15729 case 0x20:
15730 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
15731 cc = (ctx->opcode >> 13) & 0x7;
15732 fmt = (ctx->opcode >> 9) & 0x3;
15733 switch ((ctx->opcode >> 6) & 0x7) {
15734 case MOVF_FMT: /* RINT_FMT */
15735 if (ctx->insn_flags & ISA_MIPS_R6) {
15736 /* RINT_FMT */
15737 switch (fmt) {
15738 case FMT_SDPS_S:
15739 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
15740 break;
15741 case FMT_SDPS_D:
15742 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
15743 break;
15744 default:
15745 goto pool32f_invalid;
15747 } else {
15748 /* MOVF_FMT */
15749 switch (fmt) {
15750 case FMT_SDPS_S:
15751 gen_movcf_s(ctx, rs, rt, cc, 0);
15752 break;
15753 case FMT_SDPS_D:
15754 gen_movcf_d(ctx, rs, rt, cc, 0);
15755 break;
15756 case FMT_SDPS_PS:
15757 check_ps(ctx);
15758 gen_movcf_ps(ctx, rs, rt, cc, 0);
15759 break;
15760 default:
15761 goto pool32f_invalid;
15764 break;
15765 case MOVT_FMT: /* CLASS_FMT */
15766 if (ctx->insn_flags & ISA_MIPS_R6) {
15767 /* CLASS_FMT */
15768 switch (fmt) {
15769 case FMT_SDPS_S:
15770 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
15771 break;
15772 case FMT_SDPS_D:
15773 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
15774 break;
15775 default:
15776 goto pool32f_invalid;
15778 } else {
15779 /* MOVT_FMT */
15780 switch (fmt) {
15781 case FMT_SDPS_S:
15782 gen_movcf_s(ctx, rs, rt, cc, 1);
15783 break;
15784 case FMT_SDPS_D:
15785 gen_movcf_d(ctx, rs, rt, cc, 1);
15786 break;
15787 case FMT_SDPS_PS:
15788 check_ps(ctx);
15789 gen_movcf_ps(ctx, rs, rt, cc, 1);
15790 break;
15791 default:
15792 goto pool32f_invalid;
15795 break;
15796 case PREFX:
15797 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15798 break;
15799 default:
15800 goto pool32f_invalid;
15802 break;
15803 #define FINSN_3ARG_SDPS(prfx) \
15804 switch ((ctx->opcode >> 8) & 0x3) { \
15805 case FMT_SDPS_S: \
15806 mips32_op = OPC_##prfx##_S; \
15807 goto do_fpop; \
15808 case FMT_SDPS_D: \
15809 mips32_op = OPC_##prfx##_D; \
15810 goto do_fpop; \
15811 case FMT_SDPS_PS: \
15812 check_ps(ctx); \
15813 mips32_op = OPC_##prfx##_PS; \
15814 goto do_fpop; \
15815 default: \
15816 goto pool32f_invalid; \
15818 case MINA_FMT:
15819 check_insn(ctx, ISA_MIPS_R6);
15820 switch ((ctx->opcode >> 9) & 0x3) {
15821 case FMT_SDPS_S:
15822 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
15823 break;
15824 case FMT_SDPS_D:
15825 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
15826 break;
15827 default:
15828 goto pool32f_invalid;
15830 break;
15831 case MAXA_FMT:
15832 check_insn(ctx, ISA_MIPS_R6);
15833 switch ((ctx->opcode >> 9) & 0x3) {
15834 case FMT_SDPS_S:
15835 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
15836 break;
15837 case FMT_SDPS_D:
15838 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
15839 break;
15840 default:
15841 goto pool32f_invalid;
15843 break;
15844 case 0x30:
15845 /* regular FP ops */
15846 switch ((ctx->opcode >> 6) & 0x3) {
15847 case ADD_FMT:
15848 FINSN_3ARG_SDPS(ADD);
15849 break;
15850 case SUB_FMT:
15851 FINSN_3ARG_SDPS(SUB);
15852 break;
15853 case MUL_FMT:
15854 FINSN_3ARG_SDPS(MUL);
15855 break;
15856 case DIV_FMT:
15857 fmt = (ctx->opcode >> 8) & 0x3;
15858 if (fmt == 1) {
15859 mips32_op = OPC_DIV_D;
15860 } else if (fmt == 0) {
15861 mips32_op = OPC_DIV_S;
15862 } else {
15863 goto pool32f_invalid;
15865 goto do_fpop;
15866 default:
15867 goto pool32f_invalid;
15869 break;
15870 case 0x38:
15871 /* cmovs */
15872 switch ((ctx->opcode >> 6) & 0x7) {
15873 case MOVN_FMT: /* SELEQZ_FMT */
15874 if (ctx->insn_flags & ISA_MIPS_R6) {
15875 /* SELEQZ_FMT */
15876 switch ((ctx->opcode >> 9) & 0x3) {
15877 case FMT_SDPS_S:
15878 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
15879 break;
15880 case FMT_SDPS_D:
15881 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
15882 break;
15883 default:
15884 goto pool32f_invalid;
15886 } else {
15887 /* MOVN_FMT */
15888 FINSN_3ARG_SDPS(MOVN);
15890 break;
15891 case MOVN_FMT_04:
15892 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15893 FINSN_3ARG_SDPS(MOVN);
15894 break;
15895 case MOVZ_FMT: /* SELNEZ_FMT */
15896 if (ctx->insn_flags & ISA_MIPS_R6) {
15897 /* SELNEZ_FMT */
15898 switch ((ctx->opcode >> 9) & 0x3) {
15899 case FMT_SDPS_S:
15900 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
15901 break;
15902 case FMT_SDPS_D:
15903 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
15904 break;
15905 default:
15906 goto pool32f_invalid;
15908 } else {
15909 /* MOVZ_FMT */
15910 FINSN_3ARG_SDPS(MOVZ);
15912 break;
15913 case MOVZ_FMT_05:
15914 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15915 FINSN_3ARG_SDPS(MOVZ);
15916 break;
15917 case SEL_FMT:
15918 check_insn(ctx, ISA_MIPS_R6);
15919 switch ((ctx->opcode >> 9) & 0x3) {
15920 case FMT_SDPS_S:
15921 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
15922 break;
15923 case FMT_SDPS_D:
15924 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
15925 break;
15926 default:
15927 goto pool32f_invalid;
15929 break;
15930 case MADDF_FMT:
15931 check_insn(ctx, ISA_MIPS_R6);
15932 switch ((ctx->opcode >> 9) & 0x3) {
15933 case FMT_SDPS_S:
15934 mips32_op = OPC_MADDF_S;
15935 goto do_fpop;
15936 case FMT_SDPS_D:
15937 mips32_op = OPC_MADDF_D;
15938 goto do_fpop;
15939 default:
15940 goto pool32f_invalid;
15942 break;
15943 case MSUBF_FMT:
15944 check_insn(ctx, ISA_MIPS_R6);
15945 switch ((ctx->opcode >> 9) & 0x3) {
15946 case FMT_SDPS_S:
15947 mips32_op = OPC_MSUBF_S;
15948 goto do_fpop;
15949 case FMT_SDPS_D:
15950 mips32_op = OPC_MSUBF_D;
15951 goto do_fpop;
15952 default:
15953 goto pool32f_invalid;
15955 break;
15956 default:
15957 goto pool32f_invalid;
15959 break;
15960 do_fpop:
15961 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15962 break;
15963 default:
15964 pool32f_invalid:
15965 MIPS_INVAL("pool32f");
15966 gen_reserved_instruction(ctx);
15967 break;
15969 } else {
15970 generate_exception_err(ctx, EXCP_CpU, 1);
15972 break;
15973 case POOL32I:
15974 minor = (ctx->opcode >> 21) & 0x1f;
15975 switch (minor) {
15976 case BLTZ:
15977 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15978 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
15979 break;
15980 case BLTZAL:
15981 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15982 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
15983 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15984 break;
15985 case BLTZALS:
15986 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15987 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
15988 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15989 break;
15990 case BGEZ:
15991 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15992 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
15993 break;
15994 case BGEZAL:
15995 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15996 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
15997 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15998 break;
15999 case BGEZALS:
16000 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16001 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16002 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16003 break;
16004 case BLEZ:
16005 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16006 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16007 break;
16008 case BGTZ:
16009 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16010 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16011 break;
16013 /* Traps */
16014 case TLTI: /* BC1EQZC */
16015 if (ctx->insn_flags & ISA_MIPS_R6) {
16016 /* BC1EQZC */
16017 check_cp1_enabled(ctx);
16018 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16019 } else {
16020 /* TLTI */
16021 mips32_op = OPC_TLTI;
16022 goto do_trapi;
16024 break;
16025 case TGEI: /* BC1NEZC */
16026 if (ctx->insn_flags & ISA_MIPS_R6) {
16027 /* BC1NEZC */
16028 check_cp1_enabled(ctx);
16029 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16030 } else {
16031 /* TGEI */
16032 mips32_op = OPC_TGEI;
16033 goto do_trapi;
16035 break;
16036 case TLTIU:
16037 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16038 mips32_op = OPC_TLTIU;
16039 goto do_trapi;
16040 case TGEIU:
16041 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16042 mips32_op = OPC_TGEIU;
16043 goto do_trapi;
16044 case TNEI: /* SYNCI */
16045 if (ctx->insn_flags & ISA_MIPS_R6) {
16046 /* SYNCI */
16048 * Break the TB to be able to sync copied instructions
16049 * immediately.
16051 ctx->base.is_jmp = DISAS_STOP;
16052 } else {
16053 /* TNEI */
16054 mips32_op = OPC_TNEI;
16055 goto do_trapi;
16057 break;
16058 case TEQI:
16059 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16060 mips32_op = OPC_TEQI;
16061 do_trapi:
16062 gen_trap(ctx, mips32_op, rs, -1, imm);
16063 break;
16065 case BNEZC:
16066 case BEQZC:
16067 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16068 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16069 4, rs, 0, imm << 1, 0);
16071 * Compact branches don't have a delay slot, so just let
16072 * the normal delay slot handling take us to the branch
16073 * target.
16075 break;
16076 case LUI:
16077 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16078 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16079 break;
16080 case SYNCI:
16081 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16083 * Break the TB to be able to sync copied instructions
16084 * immediately.
16086 ctx->base.is_jmp = DISAS_STOP;
16087 break;
16088 case BC2F:
16089 case BC2T:
16090 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16091 /* COP2: Not implemented. */
16092 generate_exception_err(ctx, EXCP_CpU, 2);
16093 break;
16094 case BC1F:
16095 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16096 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16097 goto do_cp1branch;
16098 case BC1T:
16099 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16100 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16101 goto do_cp1branch;
16102 case BC1ANY4F:
16103 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16104 mips32_op = OPC_BC1FANY4;
16105 goto do_cp1mips3d;
16106 case BC1ANY4T:
16107 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16108 mips32_op = OPC_BC1TANY4;
16109 do_cp1mips3d:
16110 check_cop1x(ctx);
16111 check_insn(ctx, ASE_MIPS3D);
16112 /* Fall through */
16113 do_cp1branch:
16114 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16115 check_cp1_enabled(ctx);
16116 gen_compute_branch1(ctx, mips32_op,
16117 (ctx->opcode >> 18) & 0x7, imm << 1);
16118 } else {
16119 generate_exception_err(ctx, EXCP_CpU, 1);
16121 break;
16122 case BPOSGE64:
16123 case BPOSGE32:
16124 /* MIPS DSP: not implemented */
16125 /* Fall through */
16126 default:
16127 MIPS_INVAL("pool32i");
16128 gen_reserved_instruction(ctx);
16129 break;
16131 break;
16132 case POOL32C:
16133 minor = (ctx->opcode >> 12) & 0xf;
16134 offset = sextract32(ctx->opcode, 0,
16135 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
16136 switch (minor) {
16137 case LWL:
16138 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16139 mips32_op = OPC_LWL;
16140 goto do_ld_lr;
16141 case SWL:
16142 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16143 mips32_op = OPC_SWL;
16144 goto do_st_lr;
16145 case LWR:
16146 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16147 mips32_op = OPC_LWR;
16148 goto do_ld_lr;
16149 case SWR:
16150 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16151 mips32_op = OPC_SWR;
16152 goto do_st_lr;
16153 #if defined(TARGET_MIPS64)
16154 case LDL:
16155 check_insn(ctx, ISA_MIPS3);
16156 check_mips_64(ctx);
16157 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16158 mips32_op = OPC_LDL;
16159 goto do_ld_lr;
16160 case SDL:
16161 check_insn(ctx, ISA_MIPS3);
16162 check_mips_64(ctx);
16163 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16164 mips32_op = OPC_SDL;
16165 goto do_st_lr;
16166 case LDR:
16167 check_insn(ctx, ISA_MIPS3);
16168 check_mips_64(ctx);
16169 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16170 mips32_op = OPC_LDR;
16171 goto do_ld_lr;
16172 case SDR:
16173 check_insn(ctx, ISA_MIPS3);
16174 check_mips_64(ctx);
16175 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16176 mips32_op = OPC_SDR;
16177 goto do_st_lr;
16178 case LWU:
16179 check_insn(ctx, ISA_MIPS3);
16180 check_mips_64(ctx);
16181 mips32_op = OPC_LWU;
16182 goto do_ld_lr;
16183 case LLD:
16184 check_insn(ctx, ISA_MIPS3);
16185 check_mips_64(ctx);
16186 mips32_op = OPC_LLD;
16187 goto do_ld_lr;
16188 #endif
16189 case LL:
16190 mips32_op = OPC_LL;
16191 goto do_ld_lr;
16192 do_ld_lr:
16193 gen_ld(ctx, mips32_op, rt, rs, offset);
16194 break;
16195 do_st_lr:
16196 gen_st(ctx, mips32_op, rt, rs, offset);
16197 break;
16198 case SC:
16199 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
16200 break;
16201 #if defined(TARGET_MIPS64)
16202 case SCD:
16203 check_insn(ctx, ISA_MIPS3);
16204 check_mips_64(ctx);
16205 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
16206 break;
16207 #endif
16208 case LD_EVA:
16209 if (!ctx->eva) {
16210 MIPS_INVAL("pool32c ld-eva");
16211 gen_reserved_instruction(ctx);
16212 break;
16214 check_cp0_enabled(ctx);
16216 minor2 = (ctx->opcode >> 9) & 0x7;
16217 offset = sextract32(ctx->opcode, 0, 9);
16218 switch (minor2) {
16219 case LBUE:
16220 mips32_op = OPC_LBUE;
16221 goto do_ld_lr;
16222 case LHUE:
16223 mips32_op = OPC_LHUE;
16224 goto do_ld_lr;
16225 case LWLE:
16226 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16227 mips32_op = OPC_LWLE;
16228 goto do_ld_lr;
16229 case LWRE:
16230 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16231 mips32_op = OPC_LWRE;
16232 goto do_ld_lr;
16233 case LBE:
16234 mips32_op = OPC_LBE;
16235 goto do_ld_lr;
16236 case LHE:
16237 mips32_op = OPC_LHE;
16238 goto do_ld_lr;
16239 case LLE:
16240 mips32_op = OPC_LLE;
16241 goto do_ld_lr;
16242 case LWE:
16243 mips32_op = OPC_LWE;
16244 goto do_ld_lr;
16246 break;
16247 case ST_EVA:
16248 if (!ctx->eva) {
16249 MIPS_INVAL("pool32c st-eva");
16250 gen_reserved_instruction(ctx);
16251 break;
16253 check_cp0_enabled(ctx);
16255 minor2 = (ctx->opcode >> 9) & 0x7;
16256 offset = sextract32(ctx->opcode, 0, 9);
16257 switch (minor2) {
16258 case SWLE:
16259 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16260 mips32_op = OPC_SWLE;
16261 goto do_st_lr;
16262 case SWRE:
16263 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16264 mips32_op = OPC_SWRE;
16265 goto do_st_lr;
16266 case PREFE:
16267 /* Treat as no-op */
16268 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
16269 /* hint codes 24-31 are reserved and signal RI */
16270 generate_exception(ctx, EXCP_RI);
16272 break;
16273 case CACHEE:
16274 /* Treat as no-op */
16275 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16276 gen_cache_operation(ctx, rt, rs, offset);
16278 break;
16279 case SBE:
16280 mips32_op = OPC_SBE;
16281 goto do_st_lr;
16282 case SHE:
16283 mips32_op = OPC_SHE;
16284 goto do_st_lr;
16285 case SCE:
16286 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
16287 break;
16288 case SWE:
16289 mips32_op = OPC_SWE;
16290 goto do_st_lr;
16292 break;
16293 case PREF:
16294 /* Treat as no-op */
16295 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
16296 /* hint codes 24-31 are reserved and signal RI */
16297 generate_exception(ctx, EXCP_RI);
16299 break;
16300 default:
16301 MIPS_INVAL("pool32c");
16302 gen_reserved_instruction(ctx);
16303 break;
16305 break;
16306 case ADDI32: /* AUI, LUI */
16307 if (ctx->insn_flags & ISA_MIPS_R6) {
16308 /* AUI, LUI */
16309 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16310 } else {
16311 /* ADDI32 */
16312 mips32_op = OPC_ADDI;
16313 goto do_addi;
16315 break;
16316 case ADDIU32:
16317 mips32_op = OPC_ADDIU;
16318 do_addi:
16319 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16320 break;
16322 /* Logical operations */
16323 case ORI32:
16324 mips32_op = OPC_ORI;
16325 goto do_logici;
16326 case XORI32:
16327 mips32_op = OPC_XORI;
16328 goto do_logici;
16329 case ANDI32:
16330 mips32_op = OPC_ANDI;
16331 do_logici:
16332 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16333 break;
16335 /* Set less than immediate */
16336 case SLTI32:
16337 mips32_op = OPC_SLTI;
16338 goto do_slti;
16339 case SLTIU32:
16340 mips32_op = OPC_SLTIU;
16341 do_slti:
16342 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16343 break;
16344 case JALX32:
16345 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16346 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16347 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16348 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16349 break;
16350 case JALS32: /* BOVC, BEQC, BEQZALC */
16351 if (ctx->insn_flags & ISA_MIPS_R6) {
16352 if (rs >= rt) {
16353 /* BOVC */
16354 mips32_op = OPC_BOVC;
16355 } else if (rs < rt && rs == 0) {
16356 /* BEQZALC */
16357 mips32_op = OPC_BEQZALC;
16358 } else {
16359 /* BEQC */
16360 mips32_op = OPC_BEQC;
16362 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16363 } else {
16364 /* JALS32 */
16365 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16366 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16367 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16369 break;
16370 case BEQ32: /* BC */
16371 if (ctx->insn_flags & ISA_MIPS_R6) {
16372 /* BC */
16373 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16374 sextract32(ctx->opcode << 1, 0, 27));
16375 } else {
16376 /* BEQ32 */
16377 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16379 break;
16380 case BNE32: /* BALC */
16381 if (ctx->insn_flags & ISA_MIPS_R6) {
16382 /* BALC */
16383 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16384 sextract32(ctx->opcode << 1, 0, 27));
16385 } else {
16386 /* BNE32 */
16387 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16389 break;
16390 case J32: /* BGTZC, BLTZC, BLTC */
16391 if (ctx->insn_flags & ISA_MIPS_R6) {
16392 if (rs == 0 && rt != 0) {
16393 /* BGTZC */
16394 mips32_op = OPC_BGTZC;
16395 } else if (rs != 0 && rt != 0 && rs == rt) {
16396 /* BLTZC */
16397 mips32_op = OPC_BLTZC;
16398 } else {
16399 /* BLTC */
16400 mips32_op = OPC_BLTC;
16402 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16403 } else {
16404 /* J32 */
16405 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16406 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16408 break;
16409 case JAL32: /* BLEZC, BGEZC, BGEC */
16410 if (ctx->insn_flags & ISA_MIPS_R6) {
16411 if (rs == 0 && rt != 0) {
16412 /* BLEZC */
16413 mips32_op = OPC_BLEZC;
16414 } else if (rs != 0 && rt != 0 && rs == rt) {
16415 /* BGEZC */
16416 mips32_op = OPC_BGEZC;
16417 } else {
16418 /* BGEC */
16419 mips32_op = OPC_BGEC;
16421 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16422 } else {
16423 /* JAL32 */
16424 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16425 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16426 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16428 break;
16429 /* Floating point (COP1) */
16430 case LWC132:
16431 mips32_op = OPC_LWC1;
16432 goto do_cop1;
16433 case LDC132:
16434 mips32_op = OPC_LDC1;
16435 goto do_cop1;
16436 case SWC132:
16437 mips32_op = OPC_SWC1;
16438 goto do_cop1;
16439 case SDC132:
16440 mips32_op = OPC_SDC1;
16441 do_cop1:
16442 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16443 break;
16444 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16445 if (ctx->insn_flags & ISA_MIPS_R6) {
16446 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16447 switch ((ctx->opcode >> 16) & 0x1f) {
16448 case ADDIUPC_00:
16449 case ADDIUPC_01:
16450 case ADDIUPC_02:
16451 case ADDIUPC_03:
16452 case ADDIUPC_04:
16453 case ADDIUPC_05:
16454 case ADDIUPC_06:
16455 case ADDIUPC_07:
16456 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16457 break;
16458 case AUIPC:
16459 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16460 break;
16461 case ALUIPC:
16462 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16463 break;
16464 case LWPC_08:
16465 case LWPC_09:
16466 case LWPC_0A:
16467 case LWPC_0B:
16468 case LWPC_0C:
16469 case LWPC_0D:
16470 case LWPC_0E:
16471 case LWPC_0F:
16472 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16473 break;
16474 default:
16475 generate_exception(ctx, EXCP_RI);
16476 break;
16478 } else {
16479 /* ADDIUPC */
16480 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16481 offset = SIMM(ctx->opcode, 0, 23) << 2;
16483 gen_addiupc(ctx, reg, offset, 0, 0);
16485 break;
16486 case BNVC: /* BNEC, BNEZALC */
16487 check_insn(ctx, ISA_MIPS_R6);
16488 if (rs >= rt) {
16489 /* BNVC */
16490 mips32_op = OPC_BNVC;
16491 } else if (rs < rt && rs == 0) {
16492 /* BNEZALC */
16493 mips32_op = OPC_BNEZALC;
16494 } else {
16495 /* BNEC */
16496 mips32_op = OPC_BNEC;
16498 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16499 break;
16500 case R6_BNEZC: /* JIALC */
16501 check_insn(ctx, ISA_MIPS_R6);
16502 if (rt != 0) {
16503 /* BNEZC */
16504 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16505 sextract32(ctx->opcode << 1, 0, 22));
16506 } else {
16507 /* JIALC */
16508 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16510 break;
16511 case R6_BEQZC: /* JIC */
16512 check_insn(ctx, ISA_MIPS_R6);
16513 if (rt != 0) {
16514 /* BEQZC */
16515 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16516 sextract32(ctx->opcode << 1, 0, 22));
16517 } else {
16518 /* JIC */
16519 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16521 break;
16522 case BLEZALC: /* BGEZALC, BGEUC */
16523 check_insn(ctx, ISA_MIPS_R6);
16524 if (rs == 0 && rt != 0) {
16525 /* BLEZALC */
16526 mips32_op = OPC_BLEZALC;
16527 } else if (rs != 0 && rt != 0 && rs == rt) {
16528 /* BGEZALC */
16529 mips32_op = OPC_BGEZALC;
16530 } else {
16531 /* BGEUC */
16532 mips32_op = OPC_BGEUC;
16534 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16535 break;
16536 case BGTZALC: /* BLTZALC, BLTUC */
16537 check_insn(ctx, ISA_MIPS_R6);
16538 if (rs == 0 && rt != 0) {
16539 /* BGTZALC */
16540 mips32_op = OPC_BGTZALC;
16541 } else if (rs != 0 && rt != 0 && rs == rt) {
16542 /* BLTZALC */
16543 mips32_op = OPC_BLTZALC;
16544 } else {
16545 /* BLTUC */
16546 mips32_op = OPC_BLTUC;
16548 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16549 break;
16550 /* Loads and stores */
16551 case LB32:
16552 mips32_op = OPC_LB;
16553 goto do_ld;
16554 case LBU32:
16555 mips32_op = OPC_LBU;
16556 goto do_ld;
16557 case LH32:
16558 mips32_op = OPC_LH;
16559 goto do_ld;
16560 case LHU32:
16561 mips32_op = OPC_LHU;
16562 goto do_ld;
16563 case LW32:
16564 mips32_op = OPC_LW;
16565 goto do_ld;
16566 #ifdef TARGET_MIPS64
16567 case LD32:
16568 check_insn(ctx, ISA_MIPS3);
16569 check_mips_64(ctx);
16570 mips32_op = OPC_LD;
16571 goto do_ld;
16572 case SD32:
16573 check_insn(ctx, ISA_MIPS3);
16574 check_mips_64(ctx);
16575 mips32_op = OPC_SD;
16576 goto do_st;
16577 #endif
16578 case SB32:
16579 mips32_op = OPC_SB;
16580 goto do_st;
16581 case SH32:
16582 mips32_op = OPC_SH;
16583 goto do_st;
16584 case SW32:
16585 mips32_op = OPC_SW;
16586 goto do_st;
16587 do_ld:
16588 gen_ld(ctx, mips32_op, rt, rs, imm);
16589 break;
16590 do_st:
16591 gen_st(ctx, mips32_op, rt, rs, imm);
16592 break;
16593 default:
16594 gen_reserved_instruction(ctx);
16595 break;
16599 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
16601 uint32_t op;
16603 /* make sure instructions are on a halfword boundary */
16604 if (ctx->base.pc_next & 0x1) {
16605 env->CP0_BadVAddr = ctx->base.pc_next;
16606 generate_exception_end(ctx, EXCP_AdEL);
16607 return 2;
16610 op = (ctx->opcode >> 10) & 0x3f;
16611 /* Enforce properly-sized instructions in a delay slot */
16612 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16613 switch (op & 0x7) { /* MSB-3..MSB-5 */
16614 case 0:
16615 /* POOL32A, POOL32B, POOL32I, POOL32C */
16616 case 4:
16617 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16618 case 5:
16619 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16620 case 6:
16621 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16622 case 7:
16623 /* LB32, LH32, LWC132, LDC132, LW32 */
16624 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16625 gen_reserved_instruction(ctx);
16626 return 2;
16628 break;
16629 case 1:
16630 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16631 case 2:
16632 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16633 case 3:
16634 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16635 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16636 gen_reserved_instruction(ctx);
16637 return 2;
16639 break;
16643 switch (op) {
16644 case POOL16A:
16646 int rd = mmreg(uMIPS_RD(ctx->opcode));
16647 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16648 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16649 uint32_t opc = 0;
16651 switch (ctx->opcode & 0x1) {
16652 case ADDU16:
16653 opc = OPC_ADDU;
16654 break;
16655 case SUBU16:
16656 opc = OPC_SUBU;
16657 break;
16659 if (ctx->insn_flags & ISA_MIPS_R6) {
16661 * In the Release 6, the register number location in
16662 * the instruction encoding has changed.
16664 gen_arith(ctx, opc, rs1, rd, rs2);
16665 } else {
16666 gen_arith(ctx, opc, rd, rs1, rs2);
16669 break;
16670 case POOL16B:
16672 int rd = mmreg(uMIPS_RD(ctx->opcode));
16673 int rs = mmreg(uMIPS_RS(ctx->opcode));
16674 int amount = (ctx->opcode >> 1) & 0x7;
16675 uint32_t opc = 0;
16676 amount = amount == 0 ? 8 : amount;
16678 switch (ctx->opcode & 0x1) {
16679 case SLL16:
16680 opc = OPC_SLL;
16681 break;
16682 case SRL16:
16683 opc = OPC_SRL;
16684 break;
16687 gen_shift_imm(ctx, opc, rd, rs, amount);
16689 break;
16690 case POOL16C:
16691 if (ctx->insn_flags & ISA_MIPS_R6) {
16692 gen_pool16c_r6_insn(ctx);
16693 } else {
16694 gen_pool16c_insn(ctx);
16696 break;
16697 case LWGP16:
16699 int rd = mmreg(uMIPS_RD(ctx->opcode));
16700 int rb = 28; /* GP */
16701 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
16703 gen_ld(ctx, OPC_LW, rd, rb, offset);
16705 break;
16706 case POOL16F:
16707 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16708 if (ctx->opcode & 1) {
16709 gen_reserved_instruction(ctx);
16710 } else {
16711 /* MOVEP */
16712 int enc_dest = uMIPS_RD(ctx->opcode);
16713 int enc_rt = uMIPS_RS2(ctx->opcode);
16714 int enc_rs = uMIPS_RS1(ctx->opcode);
16715 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
16717 break;
16718 case LBU16:
16720 int rd = mmreg(uMIPS_RD(ctx->opcode));
16721 int rb = mmreg(uMIPS_RS(ctx->opcode));
16722 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16723 offset = (offset == 0xf ? -1 : offset);
16725 gen_ld(ctx, OPC_LBU, rd, rb, offset);
16727 break;
16728 case LHU16:
16730 int rd = mmreg(uMIPS_RD(ctx->opcode));
16731 int rb = mmreg(uMIPS_RS(ctx->opcode));
16732 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16734 gen_ld(ctx, OPC_LHU, rd, rb, offset);
16736 break;
16737 case LWSP16:
16739 int rd = (ctx->opcode >> 5) & 0x1f;
16740 int rb = 29; /* SP */
16741 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16743 gen_ld(ctx, OPC_LW, rd, rb, offset);
16745 break;
16746 case LW16:
16748 int rd = mmreg(uMIPS_RD(ctx->opcode));
16749 int rb = mmreg(uMIPS_RS(ctx->opcode));
16750 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16752 gen_ld(ctx, OPC_LW, rd, rb, offset);
16754 break;
16755 case SB16:
16757 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16758 int rb = mmreg(uMIPS_RS(ctx->opcode));
16759 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16761 gen_st(ctx, OPC_SB, rd, rb, offset);
16763 break;
16764 case SH16:
16766 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16767 int rb = mmreg(uMIPS_RS(ctx->opcode));
16768 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16770 gen_st(ctx, OPC_SH, rd, rb, offset);
16772 break;
16773 case SWSP16:
16775 int rd = (ctx->opcode >> 5) & 0x1f;
16776 int rb = 29; /* SP */
16777 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16779 gen_st(ctx, OPC_SW, rd, rb, offset);
16781 break;
16782 case SW16:
16784 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16785 int rb = mmreg(uMIPS_RS(ctx->opcode));
16786 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16788 gen_st(ctx, OPC_SW, rd, rb, offset);
16790 break;
16791 case MOVE16:
16793 int rd = uMIPS_RD5(ctx->opcode);
16794 int rs = uMIPS_RS5(ctx->opcode);
16796 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
16798 break;
16799 case ANDI16:
16800 gen_andi16(ctx);
16801 break;
16802 case POOL16D:
16803 switch (ctx->opcode & 0x1) {
16804 case ADDIUS5:
16805 gen_addius5(ctx);
16806 break;
16807 case ADDIUSP:
16808 gen_addiusp(ctx);
16809 break;
16811 break;
16812 case POOL16E:
16813 switch (ctx->opcode & 0x1) {
16814 case ADDIUR2:
16815 gen_addiur2(ctx);
16816 break;
16817 case ADDIUR1SP:
16818 gen_addiur1sp(ctx);
16819 break;
16821 break;
16822 case B16: /* BC16 */
16823 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
16824 sextract32(ctx->opcode, 0, 10) << 1,
16825 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
16826 break;
16827 case BNEZ16: /* BNEZC16 */
16828 case BEQZ16: /* BEQZC16 */
16829 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
16830 mmreg(uMIPS_RD(ctx->opcode)),
16831 0, sextract32(ctx->opcode, 0, 7) << 1,
16832 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
16834 break;
16835 case LI16:
16837 int reg = mmreg(uMIPS_RD(ctx->opcode));
16838 int imm = ZIMM(ctx->opcode, 0, 7);
16840 imm = (imm == 0x7f ? -1 : imm);
16841 tcg_gen_movi_tl(cpu_gpr[reg], imm);
16843 break;
16844 case RES_29:
16845 case RES_31:
16846 case RES_39:
16847 gen_reserved_instruction(ctx);
16848 break;
16849 default:
16850 decode_micromips32_opc(env, ctx);
16851 return 4;
16854 return 2;
16859 * nanoMIPS opcodes
16863 /* MAJOR, P16, and P32 pools opcodes */
16864 enum {
16865 NM_P_ADDIU = 0x00,
16866 NM_ADDIUPC = 0x01,
16867 NM_MOVE_BALC = 0x02,
16868 NM_P16_MV = 0x04,
16869 NM_LW16 = 0x05,
16870 NM_BC16 = 0x06,
16871 NM_P16_SR = 0x07,
16873 NM_POOL32A = 0x08,
16874 NM_P_BAL = 0x0a,
16875 NM_P16_SHIFT = 0x0c,
16876 NM_LWSP16 = 0x0d,
16877 NM_BALC16 = 0x0e,
16878 NM_P16_4X4 = 0x0f,
16880 NM_P_GP_W = 0x10,
16881 NM_P_GP_BH = 0x11,
16882 NM_P_J = 0x12,
16883 NM_P16C = 0x14,
16884 NM_LWGP16 = 0x15,
16885 NM_P16_LB = 0x17,
16887 NM_P48I = 0x18,
16888 NM_P16_A1 = 0x1c,
16889 NM_LW4X4 = 0x1d,
16890 NM_P16_LH = 0x1f,
16892 NM_P_U12 = 0x20,
16893 NM_P_LS_U12 = 0x21,
16894 NM_P_BR1 = 0x22,
16895 NM_P16_A2 = 0x24,
16896 NM_SW16 = 0x25,
16897 NM_BEQZC16 = 0x26,
16899 NM_POOL32F = 0x28,
16900 NM_P_LS_S9 = 0x29,
16901 NM_P_BR2 = 0x2a,
16903 NM_P16_ADDU = 0x2c,
16904 NM_SWSP16 = 0x2d,
16905 NM_BNEZC16 = 0x2e,
16906 NM_MOVEP = 0x2f,
16908 NM_POOL32S = 0x30,
16909 NM_P_BRI = 0x32,
16910 NM_LI16 = 0x34,
16911 NM_SWGP16 = 0x35,
16912 NM_P16_BR = 0x36,
16914 NM_P_LUI = 0x38,
16915 NM_ANDI16 = 0x3c,
16916 NM_SW4X4 = 0x3d,
16917 NM_MOVEPREV = 0x3f,
16920 /* POOL32A instruction pool */
16921 enum {
16922 NM_POOL32A0 = 0x00,
16923 NM_SPECIAL2 = 0x01,
16924 NM_COP2_1 = 0x02,
16925 NM_UDI = 0x03,
16926 NM_POOL32A5 = 0x05,
16927 NM_POOL32A7 = 0x07,
16930 /* P.GP.W instruction pool */
16931 enum {
16932 NM_ADDIUGP_W = 0x00,
16933 NM_LWGP = 0x02,
16934 NM_SWGP = 0x03,
16937 /* P48I instruction pool */
16938 enum {
16939 NM_LI48 = 0x00,
16940 NM_ADDIU48 = 0x01,
16941 NM_ADDIUGP48 = 0x02,
16942 NM_ADDIUPC48 = 0x03,
16943 NM_LWPC48 = 0x0b,
16944 NM_SWPC48 = 0x0f,
16947 /* P.U12 instruction pool */
16948 enum {
16949 NM_ORI = 0x00,
16950 NM_XORI = 0x01,
16951 NM_ANDI = 0x02,
16952 NM_P_SR = 0x03,
16953 NM_SLTI = 0x04,
16954 NM_SLTIU = 0x05,
16955 NM_SEQI = 0x06,
16956 NM_ADDIUNEG = 0x08,
16957 NM_P_SHIFT = 0x0c,
16958 NM_P_ROTX = 0x0d,
16959 NM_P_INS = 0x0e,
16960 NM_P_EXT = 0x0f,
16963 /* POOL32F instruction pool */
16964 enum {
16965 NM_POOL32F_0 = 0x00,
16966 NM_POOL32F_3 = 0x03,
16967 NM_POOL32F_5 = 0x05,
16970 /* POOL32S instruction pool */
16971 enum {
16972 NM_POOL32S_0 = 0x00,
16973 NM_POOL32S_4 = 0x04,
16976 /* P.LUI instruction pool */
16977 enum {
16978 NM_LUI = 0x00,
16979 NM_ALUIPC = 0x01,
16982 /* P.GP.BH instruction pool */
16983 enum {
16984 NM_LBGP = 0x00,
16985 NM_SBGP = 0x01,
16986 NM_LBUGP = 0x02,
16987 NM_ADDIUGP_B = 0x03,
16988 NM_P_GP_LH = 0x04,
16989 NM_P_GP_SH = 0x05,
16990 NM_P_GP_CP1 = 0x06,
16993 /* P.LS.U12 instruction pool */
16994 enum {
16995 NM_LB = 0x00,
16996 NM_SB = 0x01,
16997 NM_LBU = 0x02,
16998 NM_P_PREFU12 = 0x03,
16999 NM_LH = 0x04,
17000 NM_SH = 0x05,
17001 NM_LHU = 0x06,
17002 NM_LWU = 0x07,
17003 NM_LW = 0x08,
17004 NM_SW = 0x09,
17005 NM_LWC1 = 0x0a,
17006 NM_SWC1 = 0x0b,
17007 NM_LDC1 = 0x0e,
17008 NM_SDC1 = 0x0f,
17011 /* P.LS.S9 instruction pool */
17012 enum {
17013 NM_P_LS_S0 = 0x00,
17014 NM_P_LS_S1 = 0x01,
17015 NM_P_LS_E0 = 0x02,
17016 NM_P_LS_WM = 0x04,
17017 NM_P_LS_UAWM = 0x05,
17020 /* P.BAL instruction pool */
17021 enum {
17022 NM_BC = 0x00,
17023 NM_BALC = 0x01,
17026 /* P.J instruction pool */
17027 enum {
17028 NM_JALRC = 0x00,
17029 NM_JALRC_HB = 0x01,
17030 NM_P_BALRSC = 0x08,
17033 /* P.BR1 instruction pool */
17034 enum {
17035 NM_BEQC = 0x00,
17036 NM_P_BR3A = 0x01,
17037 NM_BGEC = 0x02,
17038 NM_BGEUC = 0x03,
17041 /* P.BR2 instruction pool */
17042 enum {
17043 NM_BNEC = 0x00,
17044 NM_BLTC = 0x02,
17045 NM_BLTUC = 0x03,
17048 /* P.BRI instruction pool */
17049 enum {
17050 NM_BEQIC = 0x00,
17051 NM_BBEQZC = 0x01,
17052 NM_BGEIC = 0x02,
17053 NM_BGEIUC = 0x03,
17054 NM_BNEIC = 0x04,
17055 NM_BBNEZC = 0x05,
17056 NM_BLTIC = 0x06,
17057 NM_BLTIUC = 0x07,
17060 /* P16.SHIFT instruction pool */
17061 enum {
17062 NM_SLL16 = 0x00,
17063 NM_SRL16 = 0x01,
17066 /* POOL16C instruction pool */
17067 enum {
17068 NM_POOL16C_0 = 0x00,
17069 NM_LWXS16 = 0x01,
17072 /* P16.A1 instruction pool */
17073 enum {
17074 NM_ADDIUR1SP = 0x01,
17077 /* P16.A2 instruction pool */
17078 enum {
17079 NM_ADDIUR2 = 0x00,
17080 NM_P_ADDIURS5 = 0x01,
17083 /* P16.ADDU instruction pool */
17084 enum {
17085 NM_ADDU16 = 0x00,
17086 NM_SUBU16 = 0x01,
17089 /* P16.SR instruction pool */
17090 enum {
17091 NM_SAVE16 = 0x00,
17092 NM_RESTORE_JRC16 = 0x01,
17095 /* P16.4X4 instruction pool */
17096 enum {
17097 NM_ADDU4X4 = 0x00,
17098 NM_MUL4X4 = 0x01,
17101 /* P16.LB instruction pool */
17102 enum {
17103 NM_LB16 = 0x00,
17104 NM_SB16 = 0x01,
17105 NM_LBU16 = 0x02,
17108 /* P16.LH instruction pool */
17109 enum {
17110 NM_LH16 = 0x00,
17111 NM_SH16 = 0x01,
17112 NM_LHU16 = 0x02,
17115 /* P.RI instruction pool */
17116 enum {
17117 NM_SIGRIE = 0x00,
17118 NM_P_SYSCALL = 0x01,
17119 NM_BREAK = 0x02,
17120 NM_SDBBP = 0x03,
17123 /* POOL32A0 instruction pool */
17124 enum {
17125 NM_P_TRAP = 0x00,
17126 NM_SEB = 0x01,
17127 NM_SLLV = 0x02,
17128 NM_MUL = 0x03,
17129 NM_MFC0 = 0x06,
17130 NM_MFHC0 = 0x07,
17131 NM_SEH = 0x09,
17132 NM_SRLV = 0x0a,
17133 NM_MUH = 0x0b,
17134 NM_MTC0 = 0x0e,
17135 NM_MTHC0 = 0x0f,
17136 NM_SRAV = 0x12,
17137 NM_MULU = 0x13,
17138 NM_ROTRV = 0x1a,
17139 NM_MUHU = 0x1b,
17140 NM_ADD = 0x22,
17141 NM_DIV = 0x23,
17142 NM_ADDU = 0x2a,
17143 NM_MOD = 0x2b,
17144 NM_SUB = 0x32,
17145 NM_DIVU = 0x33,
17146 NM_RDHWR = 0x38,
17147 NM_SUBU = 0x3a,
17148 NM_MODU = 0x3b,
17149 NM_P_CMOVE = 0x42,
17150 NM_FORK = 0x45,
17151 NM_MFTR = 0x46,
17152 NM_MFHTR = 0x47,
17153 NM_AND = 0x4a,
17154 NM_YIELD = 0x4d,
17155 NM_MTTR = 0x4e,
17156 NM_MTHTR = 0x4f,
17157 NM_OR = 0x52,
17158 NM_D_E_MT_VPE = 0x56,
17159 NM_NOR = 0x5a,
17160 NM_XOR = 0x62,
17161 NM_SLT = 0x6a,
17162 NM_P_SLTU = 0x72,
17163 NM_SOV = 0x7a,
17166 /* CRC32 instruction pool */
17167 enum {
17168 NM_CRC32B = 0x00,
17169 NM_CRC32H = 0x01,
17170 NM_CRC32W = 0x02,
17171 NM_CRC32CB = 0x04,
17172 NM_CRC32CH = 0x05,
17173 NM_CRC32CW = 0x06,
17176 /* POOL32A5 instruction pool */
17177 enum {
17178 NM_CMP_EQ_PH = 0x00,
17179 NM_CMP_LT_PH = 0x08,
17180 NM_CMP_LE_PH = 0x10,
17181 NM_CMPGU_EQ_QB = 0x18,
17182 NM_CMPGU_LT_QB = 0x20,
17183 NM_CMPGU_LE_QB = 0x28,
17184 NM_CMPGDU_EQ_QB = 0x30,
17185 NM_CMPGDU_LT_QB = 0x38,
17186 NM_CMPGDU_LE_QB = 0x40,
17187 NM_CMPU_EQ_QB = 0x48,
17188 NM_CMPU_LT_QB = 0x50,
17189 NM_CMPU_LE_QB = 0x58,
17190 NM_ADDQ_S_W = 0x60,
17191 NM_SUBQ_S_W = 0x68,
17192 NM_ADDSC = 0x70,
17193 NM_ADDWC = 0x78,
17195 NM_ADDQ_S_PH = 0x01,
17196 NM_ADDQH_R_PH = 0x09,
17197 NM_ADDQH_R_W = 0x11,
17198 NM_ADDU_S_QB = 0x19,
17199 NM_ADDU_S_PH = 0x21,
17200 NM_ADDUH_R_QB = 0x29,
17201 NM_SHRAV_R_PH = 0x31,
17202 NM_SHRAV_R_QB = 0x39,
17203 NM_SUBQ_S_PH = 0x41,
17204 NM_SUBQH_R_PH = 0x49,
17205 NM_SUBQH_R_W = 0x51,
17206 NM_SUBU_S_QB = 0x59,
17207 NM_SUBU_S_PH = 0x61,
17208 NM_SUBUH_R_QB = 0x69,
17209 NM_SHLLV_S_PH = 0x71,
17210 NM_PRECR_SRA_R_PH_W = 0x79,
17212 NM_MULEU_S_PH_QBL = 0x12,
17213 NM_MULEU_S_PH_QBR = 0x1a,
17214 NM_MULQ_RS_PH = 0x22,
17215 NM_MULQ_S_PH = 0x2a,
17216 NM_MULQ_RS_W = 0x32,
17217 NM_MULQ_S_W = 0x3a,
17218 NM_APPEND = 0x42,
17219 NM_MODSUB = 0x52,
17220 NM_SHRAV_R_W = 0x5a,
17221 NM_SHRLV_PH = 0x62,
17222 NM_SHRLV_QB = 0x6a,
17223 NM_SHLLV_QB = 0x72,
17224 NM_SHLLV_S_W = 0x7a,
17226 NM_SHILO = 0x03,
17228 NM_MULEQ_S_W_PHL = 0x04,
17229 NM_MULEQ_S_W_PHR = 0x0c,
17231 NM_MUL_S_PH = 0x05,
17232 NM_PRECR_QB_PH = 0x0d,
17233 NM_PRECRQ_QB_PH = 0x15,
17234 NM_PRECRQ_PH_W = 0x1d,
17235 NM_PRECRQ_RS_PH_W = 0x25,
17236 NM_PRECRQU_S_QB_PH = 0x2d,
17237 NM_PACKRL_PH = 0x35,
17238 NM_PICK_QB = 0x3d,
17239 NM_PICK_PH = 0x45,
17241 NM_SHRA_R_W = 0x5e,
17242 NM_SHRA_R_PH = 0x66,
17243 NM_SHLL_S_PH = 0x76,
17244 NM_SHLL_S_W = 0x7e,
17246 NM_REPL_PH = 0x07
17249 /* POOL32A7 instruction pool */
17250 enum {
17251 NM_P_LSX = 0x00,
17252 NM_LSA = 0x01,
17253 NM_EXTW = 0x03,
17254 NM_POOL32AXF = 0x07,
17257 /* P.SR instruction pool */
17258 enum {
17259 NM_PP_SR = 0x00,
17260 NM_P_SR_F = 0x01,
17263 /* P.SHIFT instruction pool */
17264 enum {
17265 NM_P_SLL = 0x00,
17266 NM_SRL = 0x02,
17267 NM_SRA = 0x04,
17268 NM_ROTR = 0x06,
17271 /* P.ROTX instruction pool */
17272 enum {
17273 NM_ROTX = 0x00,
17276 /* P.INS instruction pool */
17277 enum {
17278 NM_INS = 0x00,
17281 /* P.EXT instruction pool */
17282 enum {
17283 NM_EXT = 0x00,
17286 /* POOL32F_0 (fmt) instruction pool */
17287 enum {
17288 NM_RINT_S = 0x04,
17289 NM_RINT_D = 0x44,
17290 NM_ADD_S = 0x06,
17291 NM_SELEQZ_S = 0x07,
17292 NM_SELEQZ_D = 0x47,
17293 NM_CLASS_S = 0x0c,
17294 NM_CLASS_D = 0x4c,
17295 NM_SUB_S = 0x0e,
17296 NM_SELNEZ_S = 0x0f,
17297 NM_SELNEZ_D = 0x4f,
17298 NM_MUL_S = 0x16,
17299 NM_SEL_S = 0x17,
17300 NM_SEL_D = 0x57,
17301 NM_DIV_S = 0x1e,
17302 NM_ADD_D = 0x26,
17303 NM_SUB_D = 0x2e,
17304 NM_MUL_D = 0x36,
17305 NM_MADDF_S = 0x37,
17306 NM_MADDF_D = 0x77,
17307 NM_DIV_D = 0x3e,
17308 NM_MSUBF_S = 0x3f,
17309 NM_MSUBF_D = 0x7f,
17312 /* POOL32F_3 instruction pool */
17313 enum {
17314 NM_MIN_FMT = 0x00,
17315 NM_MAX_FMT = 0x01,
17316 NM_MINA_FMT = 0x04,
17317 NM_MAXA_FMT = 0x05,
17318 NM_POOL32FXF = 0x07,
17321 /* POOL32F_5 instruction pool */
17322 enum {
17323 NM_CMP_CONDN_S = 0x00,
17324 NM_CMP_CONDN_D = 0x02,
17327 /* P.GP.LH instruction pool */
17328 enum {
17329 NM_LHGP = 0x00,
17330 NM_LHUGP = 0x01,
17333 /* P.GP.SH instruction pool */
17334 enum {
17335 NM_SHGP = 0x00,
17338 /* P.GP.CP1 instruction pool */
17339 enum {
17340 NM_LWC1GP = 0x00,
17341 NM_SWC1GP = 0x01,
17342 NM_LDC1GP = 0x02,
17343 NM_SDC1GP = 0x03,
17346 /* P.LS.S0 instruction pool */
17347 enum {
17348 NM_LBS9 = 0x00,
17349 NM_LHS9 = 0x04,
17350 NM_LWS9 = 0x08,
17351 NM_LDS9 = 0x0c,
17353 NM_SBS9 = 0x01,
17354 NM_SHS9 = 0x05,
17355 NM_SWS9 = 0x09,
17356 NM_SDS9 = 0x0d,
17358 NM_LBUS9 = 0x02,
17359 NM_LHUS9 = 0x06,
17360 NM_LWC1S9 = 0x0a,
17361 NM_LDC1S9 = 0x0e,
17363 NM_P_PREFS9 = 0x03,
17364 NM_LWUS9 = 0x07,
17365 NM_SWC1S9 = 0x0b,
17366 NM_SDC1S9 = 0x0f,
17369 /* P.LS.S1 instruction pool */
17370 enum {
17371 NM_ASET_ACLR = 0x02,
17372 NM_UALH = 0x04,
17373 NM_UASH = 0x05,
17374 NM_CACHE = 0x07,
17375 NM_P_LL = 0x0a,
17376 NM_P_SC = 0x0b,
17379 /* P.LS.E0 instruction pool */
17380 enum {
17381 NM_LBE = 0x00,
17382 NM_SBE = 0x01,
17383 NM_LBUE = 0x02,
17384 NM_P_PREFE = 0x03,
17385 NM_LHE = 0x04,
17386 NM_SHE = 0x05,
17387 NM_LHUE = 0x06,
17388 NM_CACHEE = 0x07,
17389 NM_LWE = 0x08,
17390 NM_SWE = 0x09,
17391 NM_P_LLE = 0x0a,
17392 NM_P_SCE = 0x0b,
17395 /* P.PREFE instruction pool */
17396 enum {
17397 NM_SYNCIE = 0x00,
17398 NM_PREFE = 0x01,
17401 /* P.LLE instruction pool */
17402 enum {
17403 NM_LLE = 0x00,
17404 NM_LLWPE = 0x01,
17407 /* P.SCE instruction pool */
17408 enum {
17409 NM_SCE = 0x00,
17410 NM_SCWPE = 0x01,
17413 /* P.LS.WM instruction pool */
17414 enum {
17415 NM_LWM = 0x00,
17416 NM_SWM = 0x01,
17419 /* P.LS.UAWM instruction pool */
17420 enum {
17421 NM_UALWM = 0x00,
17422 NM_UASWM = 0x01,
17425 /* P.BR3A instruction pool */
17426 enum {
17427 NM_BC1EQZC = 0x00,
17428 NM_BC1NEZC = 0x01,
17429 NM_BC2EQZC = 0x02,
17430 NM_BC2NEZC = 0x03,
17431 NM_BPOSGE32C = 0x04,
17434 /* P16.RI instruction pool */
17435 enum {
17436 NM_P16_SYSCALL = 0x01,
17437 NM_BREAK16 = 0x02,
17438 NM_SDBBP16 = 0x03,
17441 /* POOL16C_0 instruction pool */
17442 enum {
17443 NM_POOL16C_00 = 0x00,
17446 /* P16.JRC instruction pool */
17447 enum {
17448 NM_JRC = 0x00,
17449 NM_JALRC16 = 0x01,
17452 /* P.SYSCALL instruction pool */
17453 enum {
17454 NM_SYSCALL = 0x00,
17455 NM_HYPCALL = 0x01,
17458 /* P.TRAP instruction pool */
17459 enum {
17460 NM_TEQ = 0x00,
17461 NM_TNE = 0x01,
17464 /* P.CMOVE instruction pool */
17465 enum {
17466 NM_MOVZ = 0x00,
17467 NM_MOVN = 0x01,
17470 /* POOL32Axf instruction pool */
17471 enum {
17472 NM_POOL32AXF_1 = 0x01,
17473 NM_POOL32AXF_2 = 0x02,
17474 NM_POOL32AXF_4 = 0x04,
17475 NM_POOL32AXF_5 = 0x05,
17476 NM_POOL32AXF_7 = 0x07,
17479 /* POOL32Axf_1 instruction pool */
17480 enum {
17481 NM_POOL32AXF_1_0 = 0x00,
17482 NM_POOL32AXF_1_1 = 0x01,
17483 NM_POOL32AXF_1_3 = 0x03,
17484 NM_POOL32AXF_1_4 = 0x04,
17485 NM_POOL32AXF_1_5 = 0x05,
17486 NM_POOL32AXF_1_7 = 0x07,
17489 /* POOL32Axf_2 instruction pool */
17490 enum {
17491 NM_POOL32AXF_2_0_7 = 0x00,
17492 NM_POOL32AXF_2_8_15 = 0x01,
17493 NM_POOL32AXF_2_16_23 = 0x02,
17494 NM_POOL32AXF_2_24_31 = 0x03,
17497 /* POOL32Axf_7 instruction pool */
17498 enum {
17499 NM_SHRA_R_QB = 0x0,
17500 NM_SHRL_PH = 0x1,
17501 NM_REPL_QB = 0x2,
17504 /* POOL32Axf_1_0 instruction pool */
17505 enum {
17506 NM_MFHI = 0x0,
17507 NM_MFLO = 0x1,
17508 NM_MTHI = 0x2,
17509 NM_MTLO = 0x3,
17512 /* POOL32Axf_1_1 instruction pool */
17513 enum {
17514 NM_MTHLIP = 0x0,
17515 NM_SHILOV = 0x1,
17518 /* POOL32Axf_1_3 instruction pool */
17519 enum {
17520 NM_RDDSP = 0x0,
17521 NM_WRDSP = 0x1,
17522 NM_EXTP = 0x2,
17523 NM_EXTPDP = 0x3,
17526 /* POOL32Axf_1_4 instruction pool */
17527 enum {
17528 NM_SHLL_QB = 0x0,
17529 NM_SHRL_QB = 0x1,
17532 /* POOL32Axf_1_5 instruction pool */
17533 enum {
17534 NM_MAQ_S_W_PHR = 0x0,
17535 NM_MAQ_S_W_PHL = 0x1,
17536 NM_MAQ_SA_W_PHR = 0x2,
17537 NM_MAQ_SA_W_PHL = 0x3,
17540 /* POOL32Axf_1_7 instruction pool */
17541 enum {
17542 NM_EXTR_W = 0x0,
17543 NM_EXTR_R_W = 0x1,
17544 NM_EXTR_RS_W = 0x2,
17545 NM_EXTR_S_H = 0x3,
17548 /* POOL32Axf_2_0_7 instruction pool */
17549 enum {
17550 NM_DPA_W_PH = 0x0,
17551 NM_DPAQ_S_W_PH = 0x1,
17552 NM_DPS_W_PH = 0x2,
17553 NM_DPSQ_S_W_PH = 0x3,
17554 NM_BALIGN = 0x4,
17555 NM_MADD = 0x5,
17556 NM_MULT = 0x6,
17557 NM_EXTRV_W = 0x7,
17560 /* POOL32Axf_2_8_15 instruction pool */
17561 enum {
17562 NM_DPAX_W_PH = 0x0,
17563 NM_DPAQ_SA_L_W = 0x1,
17564 NM_DPSX_W_PH = 0x2,
17565 NM_DPSQ_SA_L_W = 0x3,
17566 NM_MADDU = 0x5,
17567 NM_MULTU = 0x6,
17568 NM_EXTRV_R_W = 0x7,
17571 /* POOL32Axf_2_16_23 instruction pool */
17572 enum {
17573 NM_DPAU_H_QBL = 0x0,
17574 NM_DPAQX_S_W_PH = 0x1,
17575 NM_DPSU_H_QBL = 0x2,
17576 NM_DPSQX_S_W_PH = 0x3,
17577 NM_EXTPV = 0x4,
17578 NM_MSUB = 0x5,
17579 NM_MULSA_W_PH = 0x6,
17580 NM_EXTRV_RS_W = 0x7,
17583 /* POOL32Axf_2_24_31 instruction pool */
17584 enum {
17585 NM_DPAU_H_QBR = 0x0,
17586 NM_DPAQX_SA_W_PH = 0x1,
17587 NM_DPSU_H_QBR = 0x2,
17588 NM_DPSQX_SA_W_PH = 0x3,
17589 NM_EXTPDPV = 0x4,
17590 NM_MSUBU = 0x5,
17591 NM_MULSAQ_S_W_PH = 0x6,
17592 NM_EXTRV_S_H = 0x7,
17595 /* POOL32Axf_{4, 5} instruction pool */
17596 enum {
17597 NM_CLO = 0x25,
17598 NM_CLZ = 0x2d,
17600 NM_TLBP = 0x01,
17601 NM_TLBR = 0x09,
17602 NM_TLBWI = 0x11,
17603 NM_TLBWR = 0x19,
17604 NM_TLBINV = 0x03,
17605 NM_TLBINVF = 0x0b,
17606 NM_DI = 0x23,
17607 NM_EI = 0x2b,
17608 NM_RDPGPR = 0x70,
17609 NM_WRPGPR = 0x78,
17610 NM_WAIT = 0x61,
17611 NM_DERET = 0x71,
17612 NM_ERETX = 0x79,
17614 /* nanoMIPS DSP instructions */
17615 NM_ABSQ_S_QB = 0x00,
17616 NM_ABSQ_S_PH = 0x08,
17617 NM_ABSQ_S_W = 0x10,
17618 NM_PRECEQ_W_PHL = 0x28,
17619 NM_PRECEQ_W_PHR = 0x30,
17620 NM_PRECEQU_PH_QBL = 0x38,
17621 NM_PRECEQU_PH_QBR = 0x48,
17622 NM_PRECEU_PH_QBL = 0x58,
17623 NM_PRECEU_PH_QBR = 0x68,
17624 NM_PRECEQU_PH_QBLA = 0x39,
17625 NM_PRECEQU_PH_QBRA = 0x49,
17626 NM_PRECEU_PH_QBLA = 0x59,
17627 NM_PRECEU_PH_QBRA = 0x69,
17628 NM_REPLV_PH = 0x01,
17629 NM_REPLV_QB = 0x09,
17630 NM_BITREV = 0x18,
17631 NM_INSV = 0x20,
17632 NM_RADDU_W_QB = 0x78,
17634 NM_BITSWAP = 0x05,
17635 NM_WSBH = 0x3d,
17638 /* PP.SR instruction pool */
17639 enum {
17640 NM_SAVE = 0x00,
17641 NM_RESTORE = 0x02,
17642 NM_RESTORE_JRC = 0x03,
17645 /* P.SR.F instruction pool */
17646 enum {
17647 NM_SAVEF = 0x00,
17648 NM_RESTOREF = 0x01,
17651 /* P16.SYSCALL instruction pool */
17652 enum {
17653 NM_SYSCALL16 = 0x00,
17654 NM_HYPCALL16 = 0x01,
17657 /* POOL16C_00 instruction pool */
17658 enum {
17659 NM_NOT16 = 0x00,
17660 NM_XOR16 = 0x01,
17661 NM_AND16 = 0x02,
17662 NM_OR16 = 0x03,
17665 /* PP.LSX and PP.LSXS instruction pool */
17666 enum {
17667 NM_LBX = 0x00,
17668 NM_LHX = 0x04,
17669 NM_LWX = 0x08,
17670 NM_LDX = 0x0c,
17672 NM_SBX = 0x01,
17673 NM_SHX = 0x05,
17674 NM_SWX = 0x09,
17675 NM_SDX = 0x0d,
17677 NM_LBUX = 0x02,
17678 NM_LHUX = 0x06,
17679 NM_LWC1X = 0x0a,
17680 NM_LDC1X = 0x0e,
17682 NM_LWUX = 0x07,
17683 NM_SWC1X = 0x0b,
17684 NM_SDC1X = 0x0f,
17686 NM_LHXS = 0x04,
17687 NM_LWXS = 0x08,
17688 NM_LDXS = 0x0c,
17690 NM_SHXS = 0x05,
17691 NM_SWXS = 0x09,
17692 NM_SDXS = 0x0d,
17694 NM_LHUXS = 0x06,
17695 NM_LWC1XS = 0x0a,
17696 NM_LDC1XS = 0x0e,
17698 NM_LWUXS = 0x07,
17699 NM_SWC1XS = 0x0b,
17700 NM_SDC1XS = 0x0f,
17703 /* ERETx instruction pool */
17704 enum {
17705 NM_ERET = 0x00,
17706 NM_ERETNC = 0x01,
17709 /* POOL32FxF_{0, 1} insturction pool */
17710 enum {
17711 NM_CFC1 = 0x40,
17712 NM_CTC1 = 0x60,
17713 NM_MFC1 = 0x80,
17714 NM_MTC1 = 0xa0,
17715 NM_MFHC1 = 0xc0,
17716 NM_MTHC1 = 0xe0,
17718 NM_CVT_S_PL = 0x84,
17719 NM_CVT_S_PU = 0xa4,
17721 NM_CVT_L_S = 0x004,
17722 NM_CVT_L_D = 0x104,
17723 NM_CVT_W_S = 0x024,
17724 NM_CVT_W_D = 0x124,
17726 NM_RSQRT_S = 0x008,
17727 NM_RSQRT_D = 0x108,
17729 NM_SQRT_S = 0x028,
17730 NM_SQRT_D = 0x128,
17732 NM_RECIP_S = 0x048,
17733 NM_RECIP_D = 0x148,
17735 NM_FLOOR_L_S = 0x00c,
17736 NM_FLOOR_L_D = 0x10c,
17738 NM_FLOOR_W_S = 0x02c,
17739 NM_FLOOR_W_D = 0x12c,
17741 NM_CEIL_L_S = 0x04c,
17742 NM_CEIL_L_D = 0x14c,
17743 NM_CEIL_W_S = 0x06c,
17744 NM_CEIL_W_D = 0x16c,
17745 NM_TRUNC_L_S = 0x08c,
17746 NM_TRUNC_L_D = 0x18c,
17747 NM_TRUNC_W_S = 0x0ac,
17748 NM_TRUNC_W_D = 0x1ac,
17749 NM_ROUND_L_S = 0x0cc,
17750 NM_ROUND_L_D = 0x1cc,
17751 NM_ROUND_W_S = 0x0ec,
17752 NM_ROUND_W_D = 0x1ec,
17754 NM_MOV_S = 0x01,
17755 NM_MOV_D = 0x81,
17756 NM_ABS_S = 0x0d,
17757 NM_ABS_D = 0x8d,
17758 NM_NEG_S = 0x2d,
17759 NM_NEG_D = 0xad,
17760 NM_CVT_D_S = 0x04d,
17761 NM_CVT_D_W = 0x0cd,
17762 NM_CVT_D_L = 0x14d,
17763 NM_CVT_S_D = 0x06d,
17764 NM_CVT_S_W = 0x0ed,
17765 NM_CVT_S_L = 0x16d,
17768 /* P.LL instruction pool */
17769 enum {
17770 NM_LL = 0x00,
17771 NM_LLWP = 0x01,
17774 /* P.SC instruction pool */
17775 enum {
17776 NM_SC = 0x00,
17777 NM_SCWP = 0x01,
17780 /* P.DVP instruction pool */
17781 enum {
17782 NM_DVP = 0x00,
17783 NM_EVP = 0x01,
17789 * nanoMIPS decoding engine
17794 /* extraction utilities */
17796 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
17797 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
17798 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
17799 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17800 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17802 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
17803 static inline int decode_gpr_gpr3(int r)
17805 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
17807 return map[r & 0x7];
17810 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
17811 static inline int decode_gpr_gpr3_src_store(int r)
17813 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
17815 return map[r & 0x7];
17818 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
17819 static inline int decode_gpr_gpr4(int r)
17821 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
17822 16, 17, 18, 19, 20, 21, 22, 23 };
17824 return map[r & 0xf];
17827 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
17828 static inline int decode_gpr_gpr4_zero(int r)
17830 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
17831 16, 17, 18, 19, 20, 21, 22, 23 };
17833 return map[r & 0xf];
17837 static void gen_adjust_sp(DisasContext *ctx, int u)
17839 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
17842 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
17843 uint8_t gp, uint16_t u)
17845 int counter = 0;
17846 TCGv va = tcg_temp_new();
17847 TCGv t0 = tcg_temp_new();
17849 while (counter != count) {
17850 bool use_gp = gp && (counter == count - 1);
17851 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17852 int this_offset = -((counter + 1) << 2);
17853 gen_base_offset_addr(ctx, va, 29, this_offset);
17854 gen_load_gpr(t0, this_rt);
17855 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
17856 (MO_TEUL | ctx->default_tcg_memop_mask));
17857 counter++;
17860 /* adjust stack pointer */
17861 gen_adjust_sp(ctx, -u);
17863 tcg_temp_free(t0);
17864 tcg_temp_free(va);
17867 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
17868 uint8_t gp, uint16_t u)
17870 int counter = 0;
17871 TCGv va = tcg_temp_new();
17872 TCGv t0 = tcg_temp_new();
17874 while (counter != count) {
17875 bool use_gp = gp && (counter == count - 1);
17876 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17877 int this_offset = u - ((counter + 1) << 2);
17878 gen_base_offset_addr(ctx, va, 29, this_offset);
17879 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
17880 ctx->default_tcg_memop_mask);
17881 tcg_gen_ext32s_tl(t0, t0);
17882 gen_store_gpr(t0, this_rt);
17883 counter++;
17886 /* adjust stack pointer */
17887 gen_adjust_sp(ctx, u);
17889 tcg_temp_free(t0);
17890 tcg_temp_free(va);
17893 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
17895 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
17896 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
17898 switch (extract32(ctx->opcode, 2, 2)) {
17899 case NM_NOT16:
17900 gen_logic(ctx, OPC_NOR, rt, rs, 0);
17901 break;
17902 case NM_AND16:
17903 gen_logic(ctx, OPC_AND, rt, rt, rs);
17904 break;
17905 case NM_XOR16:
17906 gen_logic(ctx, OPC_XOR, rt, rt, rs);
17907 break;
17908 case NM_OR16:
17909 gen_logic(ctx, OPC_OR, rt, rt, rs);
17910 break;
17914 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
17916 int rt = extract32(ctx->opcode, 21, 5);
17917 int rs = extract32(ctx->opcode, 16, 5);
17918 int rd = extract32(ctx->opcode, 11, 5);
17920 switch (extract32(ctx->opcode, 3, 7)) {
17921 case NM_P_TRAP:
17922 switch (extract32(ctx->opcode, 10, 1)) {
17923 case NM_TEQ:
17924 check_nms(ctx);
17925 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
17926 break;
17927 case NM_TNE:
17928 check_nms(ctx);
17929 gen_trap(ctx, OPC_TNE, rs, rt, -1);
17930 break;
17932 break;
17933 case NM_RDHWR:
17934 check_nms(ctx);
17935 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
17936 break;
17937 case NM_SEB:
17938 check_nms(ctx);
17939 gen_bshfl(ctx, OPC_SEB, rs, rt);
17940 break;
17941 case NM_SEH:
17942 gen_bshfl(ctx, OPC_SEH, rs, rt);
17943 break;
17944 case NM_SLLV:
17945 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
17946 break;
17947 case NM_SRLV:
17948 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
17949 break;
17950 case NM_SRAV:
17951 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
17952 break;
17953 case NM_ROTRV:
17954 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
17955 break;
17956 case NM_ADD:
17957 gen_arith(ctx, OPC_ADD, rd, rs, rt);
17958 break;
17959 case NM_ADDU:
17960 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
17961 break;
17962 case NM_SUB:
17963 check_nms(ctx);
17964 gen_arith(ctx, OPC_SUB, rd, rs, rt);
17965 break;
17966 case NM_SUBU:
17967 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
17968 break;
17969 case NM_P_CMOVE:
17970 switch (extract32(ctx->opcode, 10, 1)) {
17971 case NM_MOVZ:
17972 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
17973 break;
17974 case NM_MOVN:
17975 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
17976 break;
17978 break;
17979 case NM_AND:
17980 gen_logic(ctx, OPC_AND, rd, rs, rt);
17981 break;
17982 case NM_OR:
17983 gen_logic(ctx, OPC_OR, rd, rs, rt);
17984 break;
17985 case NM_NOR:
17986 gen_logic(ctx, OPC_NOR, rd, rs, rt);
17987 break;
17988 case NM_XOR:
17989 gen_logic(ctx, OPC_XOR, rd, rs, rt);
17990 break;
17991 case NM_SLT:
17992 gen_slt(ctx, OPC_SLT, rd, rs, rt);
17993 break;
17994 case NM_P_SLTU:
17995 if (rd == 0) {
17996 /* P_DVP */
17997 #ifndef CONFIG_USER_ONLY
17998 TCGv t0 = tcg_temp_new();
17999 switch (extract32(ctx->opcode, 10, 1)) {
18000 case NM_DVP:
18001 if (ctx->vp) {
18002 check_cp0_enabled(ctx);
18003 gen_helper_dvp(t0, cpu_env);
18004 gen_store_gpr(t0, rt);
18006 break;
18007 case NM_EVP:
18008 if (ctx->vp) {
18009 check_cp0_enabled(ctx);
18010 gen_helper_evp(t0, cpu_env);
18011 gen_store_gpr(t0, rt);
18013 break;
18015 tcg_temp_free(t0);
18016 #endif
18017 } else {
18018 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18020 break;
18021 case NM_SOV:
18023 TCGv t0 = tcg_temp_new();
18024 TCGv t1 = tcg_temp_new();
18025 TCGv t2 = tcg_temp_new();
18027 gen_load_gpr(t1, rs);
18028 gen_load_gpr(t2, rt);
18029 tcg_gen_add_tl(t0, t1, t2);
18030 tcg_gen_ext32s_tl(t0, t0);
18031 tcg_gen_xor_tl(t1, t1, t2);
18032 tcg_gen_xor_tl(t2, t0, t2);
18033 tcg_gen_andc_tl(t1, t2, t1);
18035 /* operands of same sign, result different sign */
18036 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18037 gen_store_gpr(t0, rd);
18039 tcg_temp_free(t0);
18040 tcg_temp_free(t1);
18041 tcg_temp_free(t2);
18043 break;
18044 case NM_MUL:
18045 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18046 break;
18047 case NM_MUH:
18048 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18049 break;
18050 case NM_MULU:
18051 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18052 break;
18053 case NM_MUHU:
18054 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18055 break;
18056 case NM_DIV:
18057 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18058 break;
18059 case NM_MOD:
18060 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18061 break;
18062 case NM_DIVU:
18063 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18064 break;
18065 case NM_MODU:
18066 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18067 break;
18068 #ifndef CONFIG_USER_ONLY
18069 case NM_MFC0:
18070 check_cp0_enabled(ctx);
18071 if (rt == 0) {
18072 /* Treat as NOP. */
18073 break;
18075 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18076 break;
18077 case NM_MTC0:
18078 check_cp0_enabled(ctx);
18080 TCGv t0 = tcg_temp_new();
18082 gen_load_gpr(t0, rt);
18083 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18084 tcg_temp_free(t0);
18086 break;
18087 case NM_D_E_MT_VPE:
18089 uint8_t sc = extract32(ctx->opcode, 10, 1);
18090 TCGv t0 = tcg_temp_new();
18092 switch (sc) {
18093 case 0:
18094 if (rs == 1) {
18095 /* DMT */
18096 check_cp0_mt(ctx);
18097 gen_helper_dmt(t0);
18098 gen_store_gpr(t0, rt);
18099 } else if (rs == 0) {
18100 /* DVPE */
18101 check_cp0_mt(ctx);
18102 gen_helper_dvpe(t0, cpu_env);
18103 gen_store_gpr(t0, rt);
18104 } else {
18105 gen_reserved_instruction(ctx);
18107 break;
18108 case 1:
18109 if (rs == 1) {
18110 /* EMT */
18111 check_cp0_mt(ctx);
18112 gen_helper_emt(t0);
18113 gen_store_gpr(t0, rt);
18114 } else if (rs == 0) {
18115 /* EVPE */
18116 check_cp0_mt(ctx);
18117 gen_helper_evpe(t0, cpu_env);
18118 gen_store_gpr(t0, rt);
18119 } else {
18120 gen_reserved_instruction(ctx);
18122 break;
18125 tcg_temp_free(t0);
18127 break;
18128 case NM_FORK:
18129 check_mt(ctx);
18131 TCGv t0 = tcg_temp_new();
18132 TCGv t1 = tcg_temp_new();
18134 gen_load_gpr(t0, rt);
18135 gen_load_gpr(t1, rs);
18136 gen_helper_fork(t0, t1);
18137 tcg_temp_free(t0);
18138 tcg_temp_free(t1);
18140 break;
18141 case NM_MFTR:
18142 case NM_MFHTR:
18143 check_cp0_enabled(ctx);
18144 if (rd == 0) {
18145 /* Treat as NOP. */
18146 return;
18148 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18149 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18150 break;
18151 case NM_MTTR:
18152 case NM_MTHTR:
18153 check_cp0_enabled(ctx);
18154 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18155 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18156 break;
18157 case NM_YIELD:
18158 check_mt(ctx);
18160 TCGv t0 = tcg_temp_new();
18162 gen_load_gpr(t0, rs);
18163 gen_helper_yield(t0, cpu_env, t0);
18164 gen_store_gpr(t0, rt);
18165 tcg_temp_free(t0);
18167 break;
18168 #endif
18169 default:
18170 gen_reserved_instruction(ctx);
18171 break;
18175 /* dsp */
18176 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18177 int ret, int v1, int v2)
18179 TCGv_i32 t0;
18180 TCGv v0_t;
18181 TCGv v1_t;
18183 t0 = tcg_temp_new_i32();
18185 v0_t = tcg_temp_new();
18186 v1_t = tcg_temp_new();
18188 tcg_gen_movi_i32(t0, v2 >> 3);
18190 gen_load_gpr(v0_t, ret);
18191 gen_load_gpr(v1_t, v1);
18193 switch (opc) {
18194 case NM_MAQ_S_W_PHR:
18195 check_dsp(ctx);
18196 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18197 break;
18198 case NM_MAQ_S_W_PHL:
18199 check_dsp(ctx);
18200 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18201 break;
18202 case NM_MAQ_SA_W_PHR:
18203 check_dsp(ctx);
18204 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18205 break;
18206 case NM_MAQ_SA_W_PHL:
18207 check_dsp(ctx);
18208 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18209 break;
18210 default:
18211 gen_reserved_instruction(ctx);
18212 break;
18215 tcg_temp_free_i32(t0);
18217 tcg_temp_free(v0_t);
18218 tcg_temp_free(v1_t);
18222 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18223 int ret, int v1, int v2)
18225 int16_t imm;
18226 TCGv t0 = tcg_temp_new();
18227 TCGv t1 = tcg_temp_new();
18228 TCGv v0_t = tcg_temp_new();
18230 gen_load_gpr(v0_t, v1);
18232 switch (opc) {
18233 case NM_POOL32AXF_1_0:
18234 check_dsp(ctx);
18235 switch (extract32(ctx->opcode, 12, 2)) {
18236 case NM_MFHI:
18237 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18238 break;
18239 case NM_MFLO:
18240 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18241 break;
18242 case NM_MTHI:
18243 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18244 break;
18245 case NM_MTLO:
18246 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18247 break;
18249 break;
18250 case NM_POOL32AXF_1_1:
18251 check_dsp(ctx);
18252 switch (extract32(ctx->opcode, 12, 2)) {
18253 case NM_MTHLIP:
18254 tcg_gen_movi_tl(t0, v2);
18255 gen_helper_mthlip(t0, v0_t, cpu_env);
18256 break;
18257 case NM_SHILOV:
18258 tcg_gen_movi_tl(t0, v2 >> 3);
18259 gen_helper_shilo(t0, v0_t, cpu_env);
18260 break;
18261 default:
18262 gen_reserved_instruction(ctx);
18263 break;
18265 break;
18266 case NM_POOL32AXF_1_3:
18267 check_dsp(ctx);
18268 imm = extract32(ctx->opcode, 14, 7);
18269 switch (extract32(ctx->opcode, 12, 2)) {
18270 case NM_RDDSP:
18271 tcg_gen_movi_tl(t0, imm);
18272 gen_helper_rddsp(t0, t0, cpu_env);
18273 gen_store_gpr(t0, ret);
18274 break;
18275 case NM_WRDSP:
18276 gen_load_gpr(t0, ret);
18277 tcg_gen_movi_tl(t1, imm);
18278 gen_helper_wrdsp(t0, t1, cpu_env);
18279 break;
18280 case NM_EXTP:
18281 tcg_gen_movi_tl(t0, v2 >> 3);
18282 tcg_gen_movi_tl(t1, v1);
18283 gen_helper_extp(t0, t0, t1, cpu_env);
18284 gen_store_gpr(t0, ret);
18285 break;
18286 case NM_EXTPDP:
18287 tcg_gen_movi_tl(t0, v2 >> 3);
18288 tcg_gen_movi_tl(t1, v1);
18289 gen_helper_extpdp(t0, t0, t1, cpu_env);
18290 gen_store_gpr(t0, ret);
18291 break;
18293 break;
18294 case NM_POOL32AXF_1_4:
18295 check_dsp(ctx);
18296 tcg_gen_movi_tl(t0, v2 >> 2);
18297 switch (extract32(ctx->opcode, 12, 1)) {
18298 case NM_SHLL_QB:
18299 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18300 gen_store_gpr(t0, ret);
18301 break;
18302 case NM_SHRL_QB:
18303 gen_helper_shrl_qb(t0, t0, v0_t);
18304 gen_store_gpr(t0, ret);
18305 break;
18307 break;
18308 case NM_POOL32AXF_1_5:
18309 opc = extract32(ctx->opcode, 12, 2);
18310 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18311 break;
18312 case NM_POOL32AXF_1_7:
18313 check_dsp(ctx);
18314 tcg_gen_movi_tl(t0, v2 >> 3);
18315 tcg_gen_movi_tl(t1, v1);
18316 switch (extract32(ctx->opcode, 12, 2)) {
18317 case NM_EXTR_W:
18318 gen_helper_extr_w(t0, t0, t1, cpu_env);
18319 gen_store_gpr(t0, ret);
18320 break;
18321 case NM_EXTR_R_W:
18322 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18323 gen_store_gpr(t0, ret);
18324 break;
18325 case NM_EXTR_RS_W:
18326 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18327 gen_store_gpr(t0, ret);
18328 break;
18329 case NM_EXTR_S_H:
18330 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18331 gen_store_gpr(t0, ret);
18332 break;
18334 break;
18335 default:
18336 gen_reserved_instruction(ctx);
18337 break;
18340 tcg_temp_free(t0);
18341 tcg_temp_free(t1);
18342 tcg_temp_free(v0_t);
18345 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18346 TCGv v0, TCGv v1, int rd)
18348 TCGv_i32 t0;
18350 t0 = tcg_temp_new_i32();
18352 tcg_gen_movi_i32(t0, rd >> 3);
18354 switch (opc) {
18355 case NM_POOL32AXF_2_0_7:
18356 switch (extract32(ctx->opcode, 9, 3)) {
18357 case NM_DPA_W_PH:
18358 check_dsp_r2(ctx);
18359 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18360 break;
18361 case NM_DPAQ_S_W_PH:
18362 check_dsp(ctx);
18363 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18364 break;
18365 case NM_DPS_W_PH:
18366 check_dsp_r2(ctx);
18367 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18368 break;
18369 case NM_DPSQ_S_W_PH:
18370 check_dsp(ctx);
18371 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18372 break;
18373 default:
18374 gen_reserved_instruction(ctx);
18375 break;
18377 break;
18378 case NM_POOL32AXF_2_8_15:
18379 switch (extract32(ctx->opcode, 9, 3)) {
18380 case NM_DPAX_W_PH:
18381 check_dsp_r2(ctx);
18382 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18383 break;
18384 case NM_DPAQ_SA_L_W:
18385 check_dsp(ctx);
18386 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18387 break;
18388 case NM_DPSX_W_PH:
18389 check_dsp_r2(ctx);
18390 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18391 break;
18392 case NM_DPSQ_SA_L_W:
18393 check_dsp(ctx);
18394 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18395 break;
18396 default:
18397 gen_reserved_instruction(ctx);
18398 break;
18400 break;
18401 case NM_POOL32AXF_2_16_23:
18402 switch (extract32(ctx->opcode, 9, 3)) {
18403 case NM_DPAU_H_QBL:
18404 check_dsp(ctx);
18405 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18406 break;
18407 case NM_DPAQX_S_W_PH:
18408 check_dsp_r2(ctx);
18409 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18410 break;
18411 case NM_DPSU_H_QBL:
18412 check_dsp(ctx);
18413 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18414 break;
18415 case NM_DPSQX_S_W_PH:
18416 check_dsp_r2(ctx);
18417 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18418 break;
18419 case NM_MULSA_W_PH:
18420 check_dsp_r2(ctx);
18421 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18422 break;
18423 default:
18424 gen_reserved_instruction(ctx);
18425 break;
18427 break;
18428 case NM_POOL32AXF_2_24_31:
18429 switch (extract32(ctx->opcode, 9, 3)) {
18430 case NM_DPAU_H_QBR:
18431 check_dsp(ctx);
18432 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18433 break;
18434 case NM_DPAQX_SA_W_PH:
18435 check_dsp_r2(ctx);
18436 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18437 break;
18438 case NM_DPSU_H_QBR:
18439 check_dsp(ctx);
18440 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18441 break;
18442 case NM_DPSQX_SA_W_PH:
18443 check_dsp_r2(ctx);
18444 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18445 break;
18446 case NM_MULSAQ_S_W_PH:
18447 check_dsp(ctx);
18448 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18449 break;
18450 default:
18451 gen_reserved_instruction(ctx);
18452 break;
18454 break;
18455 default:
18456 gen_reserved_instruction(ctx);
18457 break;
18460 tcg_temp_free_i32(t0);
18463 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18464 int rt, int rs, int rd)
18466 int ret = rt;
18467 TCGv t0 = tcg_temp_new();
18468 TCGv t1 = tcg_temp_new();
18469 TCGv v0_t = tcg_temp_new();
18470 TCGv v1_t = tcg_temp_new();
18472 gen_load_gpr(v0_t, rt);
18473 gen_load_gpr(v1_t, rs);
18475 switch (opc) {
18476 case NM_POOL32AXF_2_0_7:
18477 switch (extract32(ctx->opcode, 9, 3)) {
18478 case NM_DPA_W_PH:
18479 case NM_DPAQ_S_W_PH:
18480 case NM_DPS_W_PH:
18481 case NM_DPSQ_S_W_PH:
18482 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18483 break;
18484 case NM_BALIGN:
18485 check_dsp_r2(ctx);
18486 if (rt != 0) {
18487 gen_load_gpr(t0, rs);
18488 rd &= 3;
18489 if (rd != 0 && rd != 2) {
18490 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18491 tcg_gen_ext32u_tl(t0, t0);
18492 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18493 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18495 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18497 break;
18498 case NM_MADD:
18499 check_dsp(ctx);
18501 int acc = extract32(ctx->opcode, 14, 2);
18502 TCGv_i64 t2 = tcg_temp_new_i64();
18503 TCGv_i64 t3 = tcg_temp_new_i64();
18505 gen_load_gpr(t0, rt);
18506 gen_load_gpr(t1, rs);
18507 tcg_gen_ext_tl_i64(t2, t0);
18508 tcg_gen_ext_tl_i64(t3, t1);
18509 tcg_gen_mul_i64(t2, t2, t3);
18510 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18511 tcg_gen_add_i64(t2, t2, t3);
18512 tcg_temp_free_i64(t3);
18513 gen_move_low32(cpu_LO[acc], t2);
18514 gen_move_high32(cpu_HI[acc], t2);
18515 tcg_temp_free_i64(t2);
18517 break;
18518 case NM_MULT:
18519 check_dsp(ctx);
18521 int acc = extract32(ctx->opcode, 14, 2);
18522 TCGv_i32 t2 = tcg_temp_new_i32();
18523 TCGv_i32 t3 = tcg_temp_new_i32();
18525 gen_load_gpr(t0, rs);
18526 gen_load_gpr(t1, rt);
18527 tcg_gen_trunc_tl_i32(t2, t0);
18528 tcg_gen_trunc_tl_i32(t3, t1);
18529 tcg_gen_muls2_i32(t2, t3, t2, t3);
18530 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18531 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18532 tcg_temp_free_i32(t2);
18533 tcg_temp_free_i32(t3);
18535 break;
18536 case NM_EXTRV_W:
18537 check_dsp(ctx);
18538 gen_load_gpr(v1_t, rs);
18539 tcg_gen_movi_tl(t0, rd >> 3);
18540 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18541 gen_store_gpr(t0, ret);
18542 break;
18544 break;
18545 case NM_POOL32AXF_2_8_15:
18546 switch (extract32(ctx->opcode, 9, 3)) {
18547 case NM_DPAX_W_PH:
18548 case NM_DPAQ_SA_L_W:
18549 case NM_DPSX_W_PH:
18550 case NM_DPSQ_SA_L_W:
18551 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18552 break;
18553 case NM_MADDU:
18554 check_dsp(ctx);
18556 int acc = extract32(ctx->opcode, 14, 2);
18557 TCGv_i64 t2 = tcg_temp_new_i64();
18558 TCGv_i64 t3 = tcg_temp_new_i64();
18560 gen_load_gpr(t0, rs);
18561 gen_load_gpr(t1, rt);
18562 tcg_gen_ext32u_tl(t0, t0);
18563 tcg_gen_ext32u_tl(t1, t1);
18564 tcg_gen_extu_tl_i64(t2, t0);
18565 tcg_gen_extu_tl_i64(t3, t1);
18566 tcg_gen_mul_i64(t2, t2, t3);
18567 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18568 tcg_gen_add_i64(t2, t2, t3);
18569 tcg_temp_free_i64(t3);
18570 gen_move_low32(cpu_LO[acc], t2);
18571 gen_move_high32(cpu_HI[acc], t2);
18572 tcg_temp_free_i64(t2);
18574 break;
18575 case NM_MULTU:
18576 check_dsp(ctx);
18578 int acc = extract32(ctx->opcode, 14, 2);
18579 TCGv_i32 t2 = tcg_temp_new_i32();
18580 TCGv_i32 t3 = tcg_temp_new_i32();
18582 gen_load_gpr(t0, rs);
18583 gen_load_gpr(t1, rt);
18584 tcg_gen_trunc_tl_i32(t2, t0);
18585 tcg_gen_trunc_tl_i32(t3, t1);
18586 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18587 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18588 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18589 tcg_temp_free_i32(t2);
18590 tcg_temp_free_i32(t3);
18592 break;
18593 case NM_EXTRV_R_W:
18594 check_dsp(ctx);
18595 tcg_gen_movi_tl(t0, rd >> 3);
18596 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18597 gen_store_gpr(t0, ret);
18598 break;
18599 default:
18600 gen_reserved_instruction(ctx);
18601 break;
18603 break;
18604 case NM_POOL32AXF_2_16_23:
18605 switch (extract32(ctx->opcode, 9, 3)) {
18606 case NM_DPAU_H_QBL:
18607 case NM_DPAQX_S_W_PH:
18608 case NM_DPSU_H_QBL:
18609 case NM_DPSQX_S_W_PH:
18610 case NM_MULSA_W_PH:
18611 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18612 break;
18613 case NM_EXTPV:
18614 check_dsp(ctx);
18615 tcg_gen_movi_tl(t0, rd >> 3);
18616 gen_helper_extp(t0, t0, v1_t, cpu_env);
18617 gen_store_gpr(t0, ret);
18618 break;
18619 case NM_MSUB:
18620 check_dsp(ctx);
18622 int acc = extract32(ctx->opcode, 14, 2);
18623 TCGv_i64 t2 = tcg_temp_new_i64();
18624 TCGv_i64 t3 = tcg_temp_new_i64();
18626 gen_load_gpr(t0, rs);
18627 gen_load_gpr(t1, rt);
18628 tcg_gen_ext_tl_i64(t2, t0);
18629 tcg_gen_ext_tl_i64(t3, t1);
18630 tcg_gen_mul_i64(t2, t2, t3);
18631 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18632 tcg_gen_sub_i64(t2, t3, t2);
18633 tcg_temp_free_i64(t3);
18634 gen_move_low32(cpu_LO[acc], t2);
18635 gen_move_high32(cpu_HI[acc], t2);
18636 tcg_temp_free_i64(t2);
18638 break;
18639 case NM_EXTRV_RS_W:
18640 check_dsp(ctx);
18641 tcg_gen_movi_tl(t0, rd >> 3);
18642 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18643 gen_store_gpr(t0, ret);
18644 break;
18646 break;
18647 case NM_POOL32AXF_2_24_31:
18648 switch (extract32(ctx->opcode, 9, 3)) {
18649 case NM_DPAU_H_QBR:
18650 case NM_DPAQX_SA_W_PH:
18651 case NM_DPSU_H_QBR:
18652 case NM_DPSQX_SA_W_PH:
18653 case NM_MULSAQ_S_W_PH:
18654 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18655 break;
18656 case NM_EXTPDPV:
18657 check_dsp(ctx);
18658 tcg_gen_movi_tl(t0, rd >> 3);
18659 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18660 gen_store_gpr(t0, ret);
18661 break;
18662 case NM_MSUBU:
18663 check_dsp(ctx);
18665 int acc = extract32(ctx->opcode, 14, 2);
18666 TCGv_i64 t2 = tcg_temp_new_i64();
18667 TCGv_i64 t3 = tcg_temp_new_i64();
18669 gen_load_gpr(t0, rs);
18670 gen_load_gpr(t1, rt);
18671 tcg_gen_ext32u_tl(t0, t0);
18672 tcg_gen_ext32u_tl(t1, t1);
18673 tcg_gen_extu_tl_i64(t2, t0);
18674 tcg_gen_extu_tl_i64(t3, t1);
18675 tcg_gen_mul_i64(t2, t2, t3);
18676 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18677 tcg_gen_sub_i64(t2, t3, t2);
18678 tcg_temp_free_i64(t3);
18679 gen_move_low32(cpu_LO[acc], t2);
18680 gen_move_high32(cpu_HI[acc], t2);
18681 tcg_temp_free_i64(t2);
18683 break;
18684 case NM_EXTRV_S_H:
18685 check_dsp(ctx);
18686 tcg_gen_movi_tl(t0, rd >> 3);
18687 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
18688 gen_store_gpr(t0, ret);
18689 break;
18691 break;
18692 default:
18693 gen_reserved_instruction(ctx);
18694 break;
18697 tcg_temp_free(t0);
18698 tcg_temp_free(t1);
18700 tcg_temp_free(v0_t);
18701 tcg_temp_free(v1_t);
18704 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
18705 int rt, int rs)
18707 int ret = rt;
18708 TCGv t0 = tcg_temp_new();
18709 TCGv v0_t = tcg_temp_new();
18711 gen_load_gpr(v0_t, rs);
18713 switch (opc) {
18714 case NM_ABSQ_S_QB:
18715 check_dsp_r2(ctx);
18716 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
18717 gen_store_gpr(v0_t, ret);
18718 break;
18719 case NM_ABSQ_S_PH:
18720 check_dsp(ctx);
18721 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
18722 gen_store_gpr(v0_t, ret);
18723 break;
18724 case NM_ABSQ_S_W:
18725 check_dsp(ctx);
18726 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
18727 gen_store_gpr(v0_t, ret);
18728 break;
18729 case NM_PRECEQ_W_PHL:
18730 check_dsp(ctx);
18731 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
18732 tcg_gen_ext32s_tl(v0_t, v0_t);
18733 gen_store_gpr(v0_t, ret);
18734 break;
18735 case NM_PRECEQ_W_PHR:
18736 check_dsp(ctx);
18737 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
18738 tcg_gen_shli_tl(v0_t, v0_t, 16);
18739 tcg_gen_ext32s_tl(v0_t, v0_t);
18740 gen_store_gpr(v0_t, ret);
18741 break;
18742 case NM_PRECEQU_PH_QBL:
18743 check_dsp(ctx);
18744 gen_helper_precequ_ph_qbl(v0_t, v0_t);
18745 gen_store_gpr(v0_t, ret);
18746 break;
18747 case NM_PRECEQU_PH_QBR:
18748 check_dsp(ctx);
18749 gen_helper_precequ_ph_qbr(v0_t, v0_t);
18750 gen_store_gpr(v0_t, ret);
18751 break;
18752 case NM_PRECEQU_PH_QBLA:
18753 check_dsp(ctx);
18754 gen_helper_precequ_ph_qbla(v0_t, v0_t);
18755 gen_store_gpr(v0_t, ret);
18756 break;
18757 case NM_PRECEQU_PH_QBRA:
18758 check_dsp(ctx);
18759 gen_helper_precequ_ph_qbra(v0_t, v0_t);
18760 gen_store_gpr(v0_t, ret);
18761 break;
18762 case NM_PRECEU_PH_QBL:
18763 check_dsp(ctx);
18764 gen_helper_preceu_ph_qbl(v0_t, v0_t);
18765 gen_store_gpr(v0_t, ret);
18766 break;
18767 case NM_PRECEU_PH_QBR:
18768 check_dsp(ctx);
18769 gen_helper_preceu_ph_qbr(v0_t, v0_t);
18770 gen_store_gpr(v0_t, ret);
18771 break;
18772 case NM_PRECEU_PH_QBLA:
18773 check_dsp(ctx);
18774 gen_helper_preceu_ph_qbla(v0_t, v0_t);
18775 gen_store_gpr(v0_t, ret);
18776 break;
18777 case NM_PRECEU_PH_QBRA:
18778 check_dsp(ctx);
18779 gen_helper_preceu_ph_qbra(v0_t, v0_t);
18780 gen_store_gpr(v0_t, ret);
18781 break;
18782 case NM_REPLV_PH:
18783 check_dsp(ctx);
18784 tcg_gen_ext16u_tl(v0_t, v0_t);
18785 tcg_gen_shli_tl(t0, v0_t, 16);
18786 tcg_gen_or_tl(v0_t, v0_t, t0);
18787 tcg_gen_ext32s_tl(v0_t, v0_t);
18788 gen_store_gpr(v0_t, ret);
18789 break;
18790 case NM_REPLV_QB:
18791 check_dsp(ctx);
18792 tcg_gen_ext8u_tl(v0_t, v0_t);
18793 tcg_gen_shli_tl(t0, v0_t, 8);
18794 tcg_gen_or_tl(v0_t, v0_t, t0);
18795 tcg_gen_shli_tl(t0, v0_t, 16);
18796 tcg_gen_or_tl(v0_t, v0_t, t0);
18797 tcg_gen_ext32s_tl(v0_t, v0_t);
18798 gen_store_gpr(v0_t, ret);
18799 break;
18800 case NM_BITREV:
18801 check_dsp(ctx);
18802 gen_helper_bitrev(v0_t, v0_t);
18803 gen_store_gpr(v0_t, ret);
18804 break;
18805 case NM_INSV:
18806 check_dsp(ctx);
18808 TCGv tv0 = tcg_temp_new();
18810 gen_load_gpr(tv0, rt);
18811 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
18812 gen_store_gpr(v0_t, ret);
18813 tcg_temp_free(tv0);
18815 break;
18816 case NM_RADDU_W_QB:
18817 check_dsp(ctx);
18818 gen_helper_raddu_w_qb(v0_t, v0_t);
18819 gen_store_gpr(v0_t, ret);
18820 break;
18821 case NM_BITSWAP:
18822 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
18823 break;
18824 case NM_CLO:
18825 check_nms(ctx);
18826 gen_cl(ctx, OPC_CLO, ret, rs);
18827 break;
18828 case NM_CLZ:
18829 check_nms(ctx);
18830 gen_cl(ctx, OPC_CLZ, ret, rs);
18831 break;
18832 case NM_WSBH:
18833 gen_bshfl(ctx, OPC_WSBH, ret, rs);
18834 break;
18835 default:
18836 gen_reserved_instruction(ctx);
18837 break;
18840 tcg_temp_free(v0_t);
18841 tcg_temp_free(t0);
18844 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
18845 int rt, int rs, int rd)
18847 TCGv t0 = tcg_temp_new();
18848 TCGv rs_t = tcg_temp_new();
18850 gen_load_gpr(rs_t, rs);
18852 switch (opc) {
18853 case NM_SHRA_R_QB:
18854 check_dsp_r2(ctx);
18855 tcg_gen_movi_tl(t0, rd >> 2);
18856 switch (extract32(ctx->opcode, 12, 1)) {
18857 case 0:
18858 /* NM_SHRA_QB */
18859 gen_helper_shra_qb(t0, t0, rs_t);
18860 gen_store_gpr(t0, rt);
18861 break;
18862 case 1:
18863 /* NM_SHRA_R_QB */
18864 gen_helper_shra_r_qb(t0, t0, rs_t);
18865 gen_store_gpr(t0, rt);
18866 break;
18868 break;
18869 case NM_SHRL_PH:
18870 check_dsp_r2(ctx);
18871 tcg_gen_movi_tl(t0, rd >> 1);
18872 gen_helper_shrl_ph(t0, t0, rs_t);
18873 gen_store_gpr(t0, rt);
18874 break;
18875 case NM_REPL_QB:
18876 check_dsp(ctx);
18878 int16_t imm;
18879 target_long result;
18880 imm = extract32(ctx->opcode, 13, 8);
18881 result = (uint32_t)imm << 24 |
18882 (uint32_t)imm << 16 |
18883 (uint32_t)imm << 8 |
18884 (uint32_t)imm;
18885 result = (int32_t)result;
18886 tcg_gen_movi_tl(t0, result);
18887 gen_store_gpr(t0, rt);
18889 break;
18890 default:
18891 gen_reserved_instruction(ctx);
18892 break;
18894 tcg_temp_free(t0);
18895 tcg_temp_free(rs_t);
18899 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18901 int rt = extract32(ctx->opcode, 21, 5);
18902 int rs = extract32(ctx->opcode, 16, 5);
18903 int rd = extract32(ctx->opcode, 11, 5);
18905 switch (extract32(ctx->opcode, 6, 3)) {
18906 case NM_POOL32AXF_1:
18908 int32_t op1 = extract32(ctx->opcode, 9, 3);
18909 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
18911 break;
18912 case NM_POOL32AXF_2:
18914 int32_t op1 = extract32(ctx->opcode, 12, 2);
18915 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
18917 break;
18918 case NM_POOL32AXF_4:
18920 int32_t op1 = extract32(ctx->opcode, 9, 7);
18921 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
18923 break;
18924 case NM_POOL32AXF_5:
18925 switch (extract32(ctx->opcode, 9, 7)) {
18926 #ifndef CONFIG_USER_ONLY
18927 case NM_TLBP:
18928 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
18929 break;
18930 case NM_TLBR:
18931 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
18932 break;
18933 case NM_TLBWI:
18934 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
18935 break;
18936 case NM_TLBWR:
18937 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
18938 break;
18939 case NM_TLBINV:
18940 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
18941 break;
18942 case NM_TLBINVF:
18943 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
18944 break;
18945 case NM_DI:
18946 check_cp0_enabled(ctx);
18948 TCGv t0 = tcg_temp_new();
18950 save_cpu_state(ctx, 1);
18951 gen_helper_di(t0, cpu_env);
18952 gen_store_gpr(t0, rt);
18953 /* Stop translation as we may have switched the execution mode */
18954 ctx->base.is_jmp = DISAS_STOP;
18955 tcg_temp_free(t0);
18957 break;
18958 case NM_EI:
18959 check_cp0_enabled(ctx);
18961 TCGv t0 = tcg_temp_new();
18963 save_cpu_state(ctx, 1);
18964 gen_helper_ei(t0, cpu_env);
18965 gen_store_gpr(t0, rt);
18966 /* Stop translation as we may have switched the execution mode */
18967 ctx->base.is_jmp = DISAS_STOP;
18968 tcg_temp_free(t0);
18970 break;
18971 case NM_RDPGPR:
18972 gen_load_srsgpr(rs, rt);
18973 break;
18974 case NM_WRPGPR:
18975 gen_store_srsgpr(rs, rt);
18976 break;
18977 case NM_WAIT:
18978 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
18979 break;
18980 case NM_DERET:
18981 gen_cp0(env, ctx, OPC_DERET, 0, 0);
18982 break;
18983 case NM_ERETX:
18984 gen_cp0(env, ctx, OPC_ERET, 0, 0);
18985 break;
18986 #endif
18987 default:
18988 gen_reserved_instruction(ctx);
18989 break;
18991 break;
18992 case NM_POOL32AXF_7:
18994 int32_t op1 = extract32(ctx->opcode, 9, 3);
18995 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
18997 break;
18998 default:
18999 gen_reserved_instruction(ctx);
19000 break;
19004 /* Immediate Value Compact Branches */
19005 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19006 int rt, int32_t imm, int32_t offset)
19008 TCGCond cond = TCG_COND_ALWAYS;
19009 TCGv t0 = tcg_temp_new();
19010 TCGv t1 = tcg_temp_new();
19012 gen_load_gpr(t0, rt);
19013 tcg_gen_movi_tl(t1, imm);
19014 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19016 /* Load needed operands and calculate btarget */
19017 switch (opc) {
19018 case NM_BEQIC:
19019 if (rt == 0 && imm == 0) {
19020 /* Unconditional branch */
19021 } else if (rt == 0 && imm != 0) {
19022 /* Treat as NOP */
19023 goto out;
19024 } else {
19025 cond = TCG_COND_EQ;
19027 break;
19028 case NM_BBEQZC:
19029 case NM_BBNEZC:
19030 check_nms(ctx);
19031 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19032 gen_reserved_instruction(ctx);
19033 goto out;
19034 } else if (rt == 0 && opc == NM_BBEQZC) {
19035 /* Unconditional branch */
19036 } else if (rt == 0 && opc == NM_BBNEZC) {
19037 /* Treat as NOP */
19038 goto out;
19039 } else {
19040 tcg_gen_shri_tl(t0, t0, imm);
19041 tcg_gen_andi_tl(t0, t0, 1);
19042 tcg_gen_movi_tl(t1, 0);
19043 if (opc == NM_BBEQZC) {
19044 cond = TCG_COND_EQ;
19045 } else {
19046 cond = TCG_COND_NE;
19049 break;
19050 case NM_BNEIC:
19051 if (rt == 0 && imm == 0) {
19052 /* Treat as NOP */
19053 goto out;
19054 } else if (rt == 0 && imm != 0) {
19055 /* Unconditional branch */
19056 } else {
19057 cond = TCG_COND_NE;
19059 break;
19060 case NM_BGEIC:
19061 if (rt == 0 && imm == 0) {
19062 /* Unconditional branch */
19063 } else {
19064 cond = TCG_COND_GE;
19066 break;
19067 case NM_BLTIC:
19068 cond = TCG_COND_LT;
19069 break;
19070 case NM_BGEIUC:
19071 if (rt == 0 && imm == 0) {
19072 /* Unconditional branch */
19073 } else {
19074 cond = TCG_COND_GEU;
19076 break;
19077 case NM_BLTIUC:
19078 cond = TCG_COND_LTU;
19079 break;
19080 default:
19081 MIPS_INVAL("Immediate Value Compact branch");
19082 gen_reserved_instruction(ctx);
19083 goto out;
19086 /* branch completion */
19087 clear_branch_hflags(ctx);
19088 ctx->base.is_jmp = DISAS_NORETURN;
19090 if (cond == TCG_COND_ALWAYS) {
19091 /* Uncoditional compact branch */
19092 gen_goto_tb(ctx, 0, ctx->btarget);
19093 } else {
19094 /* Conditional compact branch */
19095 TCGLabel *fs = gen_new_label();
19097 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19099 gen_goto_tb(ctx, 1, ctx->btarget);
19100 gen_set_label(fs);
19102 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19105 out:
19106 tcg_temp_free(t0);
19107 tcg_temp_free(t1);
19110 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19111 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19112 int rt)
19114 TCGv t0 = tcg_temp_new();
19115 TCGv t1 = tcg_temp_new();
19117 /* load rs */
19118 gen_load_gpr(t0, rs);
19120 /* link */
19121 if (rt != 0) {
19122 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19125 /* calculate btarget */
19126 tcg_gen_shli_tl(t0, t0, 1);
19127 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19128 gen_op_addr_add(ctx, btarget, t1, t0);
19130 /* branch completion */
19131 clear_branch_hflags(ctx);
19132 ctx->base.is_jmp = DISAS_NORETURN;
19134 /* unconditional branch to register */
19135 tcg_gen_mov_tl(cpu_PC, btarget);
19136 tcg_gen_lookup_and_goto_ptr();
19138 tcg_temp_free(t0);
19139 tcg_temp_free(t1);
19142 /* nanoMIPS Branches */
19143 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19144 int rs, int rt, int32_t offset)
19146 int bcond_compute = 0;
19147 TCGv t0 = tcg_temp_new();
19148 TCGv t1 = tcg_temp_new();
19150 /* Load needed operands and calculate btarget */
19151 switch (opc) {
19152 /* compact branch */
19153 case OPC_BGEC:
19154 case OPC_BLTC:
19155 gen_load_gpr(t0, rs);
19156 gen_load_gpr(t1, rt);
19157 bcond_compute = 1;
19158 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19159 break;
19160 case OPC_BGEUC:
19161 case OPC_BLTUC:
19162 if (rs == 0 || rs == rt) {
19163 /* OPC_BLEZALC, OPC_BGEZALC */
19164 /* OPC_BGTZALC, OPC_BLTZALC */
19165 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19167 gen_load_gpr(t0, rs);
19168 gen_load_gpr(t1, rt);
19169 bcond_compute = 1;
19170 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19171 break;
19172 case OPC_BC:
19173 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19174 break;
19175 case OPC_BEQZC:
19176 if (rs != 0) {
19177 /* OPC_BEQZC, OPC_BNEZC */
19178 gen_load_gpr(t0, rs);
19179 bcond_compute = 1;
19180 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19181 } else {
19182 /* OPC_JIC, OPC_JIALC */
19183 TCGv tbase = tcg_temp_new();
19184 TCGv toffset = tcg_temp_new();
19186 gen_load_gpr(tbase, rt);
19187 tcg_gen_movi_tl(toffset, offset);
19188 gen_op_addr_add(ctx, btarget, tbase, toffset);
19189 tcg_temp_free(tbase);
19190 tcg_temp_free(toffset);
19192 break;
19193 default:
19194 MIPS_INVAL("Compact branch/jump");
19195 gen_reserved_instruction(ctx);
19196 goto out;
19199 if (bcond_compute == 0) {
19200 /* Uncoditional compact branch */
19201 switch (opc) {
19202 case OPC_BC:
19203 gen_goto_tb(ctx, 0, ctx->btarget);
19204 break;
19205 default:
19206 MIPS_INVAL("Compact branch/jump");
19207 gen_reserved_instruction(ctx);
19208 goto out;
19210 } else {
19211 /* Conditional compact branch */
19212 TCGLabel *fs = gen_new_label();
19214 switch (opc) {
19215 case OPC_BGEUC:
19216 if (rs == 0 && rt != 0) {
19217 /* OPC_BLEZALC */
19218 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19219 } else if (rs != 0 && rt != 0 && rs == rt) {
19220 /* OPC_BGEZALC */
19221 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19222 } else {
19223 /* OPC_BGEUC */
19224 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19226 break;
19227 case OPC_BLTUC:
19228 if (rs == 0 && rt != 0) {
19229 /* OPC_BGTZALC */
19230 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19231 } else if (rs != 0 && rt != 0 && rs == rt) {
19232 /* OPC_BLTZALC */
19233 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19234 } else {
19235 /* OPC_BLTUC */
19236 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19238 break;
19239 case OPC_BGEC:
19240 if (rs == 0 && rt != 0) {
19241 /* OPC_BLEZC */
19242 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19243 } else if (rs != 0 && rt != 0 && rs == rt) {
19244 /* OPC_BGEZC */
19245 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19246 } else {
19247 /* OPC_BGEC */
19248 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19250 break;
19251 case OPC_BLTC:
19252 if (rs == 0 && rt != 0) {
19253 /* OPC_BGTZC */
19254 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19255 } else if (rs != 0 && rt != 0 && rs == rt) {
19256 /* OPC_BLTZC */
19257 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19258 } else {
19259 /* OPC_BLTC */
19260 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19262 break;
19263 case OPC_BEQZC:
19264 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19265 break;
19266 default:
19267 MIPS_INVAL("Compact conditional branch/jump");
19268 gen_reserved_instruction(ctx);
19269 goto out;
19272 /* branch completion */
19273 clear_branch_hflags(ctx);
19274 ctx->base.is_jmp = DISAS_NORETURN;
19276 /* Generating branch here as compact branches don't have delay slot */
19277 gen_goto_tb(ctx, 1, ctx->btarget);
19278 gen_set_label(fs);
19280 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19283 out:
19284 tcg_temp_free(t0);
19285 tcg_temp_free(t1);
19289 /* nanoMIPS CP1 Branches */
19290 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19291 int32_t ft, int32_t offset)
19293 target_ulong btarget;
19294 TCGv_i64 t0 = tcg_temp_new_i64();
19296 gen_load_fpr64(ctx, t0, ft);
19297 tcg_gen_andi_i64(t0, t0, 1);
19299 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19301 switch (op) {
19302 case NM_BC1EQZC:
19303 tcg_gen_xori_i64(t0, t0, 1);
19304 ctx->hflags |= MIPS_HFLAG_BC;
19305 break;
19306 case NM_BC1NEZC:
19307 /* t0 already set */
19308 ctx->hflags |= MIPS_HFLAG_BC;
19309 break;
19310 default:
19311 MIPS_INVAL("cp1 cond branch");
19312 gen_reserved_instruction(ctx);
19313 goto out;
19316 tcg_gen_trunc_i64_tl(bcond, t0);
19318 ctx->btarget = btarget;
19320 out:
19321 tcg_temp_free_i64(t0);
19325 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19327 TCGv t0, t1;
19328 t0 = tcg_temp_new();
19329 t1 = tcg_temp_new();
19331 gen_load_gpr(t0, rs);
19332 gen_load_gpr(t1, rt);
19334 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19335 /* PP.LSXS instructions require shifting */
19336 switch (extract32(ctx->opcode, 7, 4)) {
19337 case NM_SHXS:
19338 check_nms(ctx);
19339 /* fall through */
19340 case NM_LHXS:
19341 case NM_LHUXS:
19342 tcg_gen_shli_tl(t0, t0, 1);
19343 break;
19344 case NM_SWXS:
19345 check_nms(ctx);
19346 /* fall through */
19347 case NM_LWXS:
19348 case NM_LWC1XS:
19349 case NM_SWC1XS:
19350 tcg_gen_shli_tl(t0, t0, 2);
19351 break;
19352 case NM_LDC1XS:
19353 case NM_SDC1XS:
19354 tcg_gen_shli_tl(t0, t0, 3);
19355 break;
19358 gen_op_addr_add(ctx, t0, t0, t1);
19360 switch (extract32(ctx->opcode, 7, 4)) {
19361 case NM_LBX:
19362 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19363 MO_SB);
19364 gen_store_gpr(t0, rd);
19365 break;
19366 case NM_LHX:
19367 /*case NM_LHXS:*/
19368 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19369 MO_TESW);
19370 gen_store_gpr(t0, rd);
19371 break;
19372 case NM_LWX:
19373 /*case NM_LWXS:*/
19374 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19375 MO_TESL);
19376 gen_store_gpr(t0, rd);
19377 break;
19378 case NM_LBUX:
19379 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19380 MO_UB);
19381 gen_store_gpr(t0, rd);
19382 break;
19383 case NM_LHUX:
19384 /*case NM_LHUXS:*/
19385 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19386 MO_TEUW);
19387 gen_store_gpr(t0, rd);
19388 break;
19389 case NM_SBX:
19390 check_nms(ctx);
19391 gen_load_gpr(t1, rd);
19392 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19393 MO_8);
19394 break;
19395 case NM_SHX:
19396 /*case NM_SHXS:*/
19397 check_nms(ctx);
19398 gen_load_gpr(t1, rd);
19399 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19400 MO_TEUW);
19401 break;
19402 case NM_SWX:
19403 /*case NM_SWXS:*/
19404 check_nms(ctx);
19405 gen_load_gpr(t1, rd);
19406 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19407 MO_TEUL);
19408 break;
19409 case NM_LWC1X:
19410 /*case NM_LWC1XS:*/
19411 case NM_LDC1X:
19412 /*case NM_LDC1XS:*/
19413 case NM_SWC1X:
19414 /*case NM_SWC1XS:*/
19415 case NM_SDC1X:
19416 /*case NM_SDC1XS:*/
19417 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19418 check_cp1_enabled(ctx);
19419 switch (extract32(ctx->opcode, 7, 4)) {
19420 case NM_LWC1X:
19421 /*case NM_LWC1XS:*/
19422 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19423 break;
19424 case NM_LDC1X:
19425 /*case NM_LDC1XS:*/
19426 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19427 break;
19428 case NM_SWC1X:
19429 /*case NM_SWC1XS:*/
19430 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19431 break;
19432 case NM_SDC1X:
19433 /*case NM_SDC1XS:*/
19434 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19435 break;
19437 } else {
19438 generate_exception_err(ctx, EXCP_CpU, 1);
19440 break;
19441 default:
19442 gen_reserved_instruction(ctx);
19443 break;
19446 tcg_temp_free(t0);
19447 tcg_temp_free(t1);
19450 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19452 int rt, rs, rd;
19454 rt = extract32(ctx->opcode, 21, 5);
19455 rs = extract32(ctx->opcode, 16, 5);
19456 rd = extract32(ctx->opcode, 11, 5);
19458 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19459 gen_reserved_instruction(ctx);
19460 return;
19462 check_cp1_enabled(ctx);
19463 switch (extract32(ctx->opcode, 0, 3)) {
19464 case NM_POOL32F_0:
19465 switch (extract32(ctx->opcode, 3, 7)) {
19466 case NM_RINT_S:
19467 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19468 break;
19469 case NM_RINT_D:
19470 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19471 break;
19472 case NM_CLASS_S:
19473 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19474 break;
19475 case NM_CLASS_D:
19476 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19477 break;
19478 case NM_ADD_S:
19479 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19480 break;
19481 case NM_ADD_D:
19482 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19483 break;
19484 case NM_SUB_S:
19485 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19486 break;
19487 case NM_SUB_D:
19488 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19489 break;
19490 case NM_MUL_S:
19491 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19492 break;
19493 case NM_MUL_D:
19494 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19495 break;
19496 case NM_DIV_S:
19497 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19498 break;
19499 case NM_DIV_D:
19500 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19501 break;
19502 case NM_SELEQZ_S:
19503 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19504 break;
19505 case NM_SELEQZ_D:
19506 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19507 break;
19508 case NM_SELNEZ_S:
19509 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19510 break;
19511 case NM_SELNEZ_D:
19512 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19513 break;
19514 case NM_SEL_S:
19515 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19516 break;
19517 case NM_SEL_D:
19518 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19519 break;
19520 case NM_MADDF_S:
19521 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19522 break;
19523 case NM_MADDF_D:
19524 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19525 break;
19526 case NM_MSUBF_S:
19527 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19528 break;
19529 case NM_MSUBF_D:
19530 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19531 break;
19532 default:
19533 gen_reserved_instruction(ctx);
19534 break;
19536 break;
19537 case NM_POOL32F_3:
19538 switch (extract32(ctx->opcode, 3, 3)) {
19539 case NM_MIN_FMT:
19540 switch (extract32(ctx->opcode, 9, 1)) {
19541 case FMT_SDPS_S:
19542 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19543 break;
19544 case FMT_SDPS_D:
19545 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19546 break;
19548 break;
19549 case NM_MAX_FMT:
19550 switch (extract32(ctx->opcode, 9, 1)) {
19551 case FMT_SDPS_S:
19552 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19553 break;
19554 case FMT_SDPS_D:
19555 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19556 break;
19558 break;
19559 case NM_MINA_FMT:
19560 switch (extract32(ctx->opcode, 9, 1)) {
19561 case FMT_SDPS_S:
19562 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19563 break;
19564 case FMT_SDPS_D:
19565 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19566 break;
19568 break;
19569 case NM_MAXA_FMT:
19570 switch (extract32(ctx->opcode, 9, 1)) {
19571 case FMT_SDPS_S:
19572 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19573 break;
19574 case FMT_SDPS_D:
19575 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19576 break;
19578 break;
19579 case NM_POOL32FXF:
19580 switch (extract32(ctx->opcode, 6, 8)) {
19581 case NM_CFC1:
19582 gen_cp1(ctx, OPC_CFC1, rt, rs);
19583 break;
19584 case NM_CTC1:
19585 gen_cp1(ctx, OPC_CTC1, rt, rs);
19586 break;
19587 case NM_MFC1:
19588 gen_cp1(ctx, OPC_MFC1, rt, rs);
19589 break;
19590 case NM_MTC1:
19591 gen_cp1(ctx, OPC_MTC1, rt, rs);
19592 break;
19593 case NM_MFHC1:
19594 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19595 break;
19596 case NM_MTHC1:
19597 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19598 break;
19599 case NM_CVT_S_PL:
19600 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19601 break;
19602 case NM_CVT_S_PU:
19603 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19604 break;
19605 default:
19606 switch (extract32(ctx->opcode, 6, 9)) {
19607 case NM_CVT_L_S:
19608 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19609 break;
19610 case NM_CVT_L_D:
19611 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19612 break;
19613 case NM_CVT_W_S:
19614 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19615 break;
19616 case NM_CVT_W_D:
19617 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19618 break;
19619 case NM_RSQRT_S:
19620 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19621 break;
19622 case NM_RSQRT_D:
19623 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19624 break;
19625 case NM_SQRT_S:
19626 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19627 break;
19628 case NM_SQRT_D:
19629 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19630 break;
19631 case NM_RECIP_S:
19632 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19633 break;
19634 case NM_RECIP_D:
19635 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19636 break;
19637 case NM_FLOOR_L_S:
19638 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19639 break;
19640 case NM_FLOOR_L_D:
19641 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19642 break;
19643 case NM_FLOOR_W_S:
19644 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19645 break;
19646 case NM_FLOOR_W_D:
19647 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19648 break;
19649 case NM_CEIL_L_S:
19650 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19651 break;
19652 case NM_CEIL_L_D:
19653 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19654 break;
19655 case NM_CEIL_W_S:
19656 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19657 break;
19658 case NM_CEIL_W_D:
19659 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19660 break;
19661 case NM_TRUNC_L_S:
19662 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19663 break;
19664 case NM_TRUNC_L_D:
19665 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19666 break;
19667 case NM_TRUNC_W_S:
19668 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
19669 break;
19670 case NM_TRUNC_W_D:
19671 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
19672 break;
19673 case NM_ROUND_L_S:
19674 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
19675 break;
19676 case NM_ROUND_L_D:
19677 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
19678 break;
19679 case NM_ROUND_W_S:
19680 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
19681 break;
19682 case NM_ROUND_W_D:
19683 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
19684 break;
19685 case NM_MOV_S:
19686 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
19687 break;
19688 case NM_MOV_D:
19689 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
19690 break;
19691 case NM_ABS_S:
19692 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
19693 break;
19694 case NM_ABS_D:
19695 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
19696 break;
19697 case NM_NEG_S:
19698 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
19699 break;
19700 case NM_NEG_D:
19701 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
19702 break;
19703 case NM_CVT_D_S:
19704 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
19705 break;
19706 case NM_CVT_D_W:
19707 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
19708 break;
19709 case NM_CVT_D_L:
19710 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
19711 break;
19712 case NM_CVT_S_D:
19713 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
19714 break;
19715 case NM_CVT_S_W:
19716 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
19717 break;
19718 case NM_CVT_S_L:
19719 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
19720 break;
19721 default:
19722 gen_reserved_instruction(ctx);
19723 break;
19725 break;
19727 break;
19729 break;
19730 case NM_POOL32F_5:
19731 switch (extract32(ctx->opcode, 3, 3)) {
19732 case NM_CMP_CONDN_S:
19733 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19734 break;
19735 case NM_CMP_CONDN_D:
19736 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19737 break;
19738 default:
19739 gen_reserved_instruction(ctx);
19740 break;
19742 break;
19743 default:
19744 gen_reserved_instruction(ctx);
19745 break;
19749 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
19750 int rd, int rs, int rt)
19752 int ret = rd;
19753 TCGv t0 = tcg_temp_new();
19754 TCGv v1_t = tcg_temp_new();
19755 TCGv v2_t = tcg_temp_new();
19757 gen_load_gpr(v1_t, rs);
19758 gen_load_gpr(v2_t, rt);
19760 switch (opc) {
19761 case NM_CMP_EQ_PH:
19762 check_dsp(ctx);
19763 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
19764 break;
19765 case NM_CMP_LT_PH:
19766 check_dsp(ctx);
19767 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
19768 break;
19769 case NM_CMP_LE_PH:
19770 check_dsp(ctx);
19771 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
19772 break;
19773 case NM_CMPU_EQ_QB:
19774 check_dsp(ctx);
19775 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
19776 break;
19777 case NM_CMPU_LT_QB:
19778 check_dsp(ctx);
19779 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
19780 break;
19781 case NM_CMPU_LE_QB:
19782 check_dsp(ctx);
19783 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
19784 break;
19785 case NM_CMPGU_EQ_QB:
19786 check_dsp(ctx);
19787 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19788 gen_store_gpr(v1_t, ret);
19789 break;
19790 case NM_CMPGU_LT_QB:
19791 check_dsp(ctx);
19792 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19793 gen_store_gpr(v1_t, ret);
19794 break;
19795 case NM_CMPGU_LE_QB:
19796 check_dsp(ctx);
19797 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19798 gen_store_gpr(v1_t, ret);
19799 break;
19800 case NM_CMPGDU_EQ_QB:
19801 check_dsp_r2(ctx);
19802 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19803 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19804 gen_store_gpr(v1_t, ret);
19805 break;
19806 case NM_CMPGDU_LT_QB:
19807 check_dsp_r2(ctx);
19808 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19809 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19810 gen_store_gpr(v1_t, ret);
19811 break;
19812 case NM_CMPGDU_LE_QB:
19813 check_dsp_r2(ctx);
19814 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19815 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19816 gen_store_gpr(v1_t, ret);
19817 break;
19818 case NM_PACKRL_PH:
19819 check_dsp(ctx);
19820 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
19821 gen_store_gpr(v1_t, ret);
19822 break;
19823 case NM_PICK_QB:
19824 check_dsp(ctx);
19825 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
19826 gen_store_gpr(v1_t, ret);
19827 break;
19828 case NM_PICK_PH:
19829 check_dsp(ctx);
19830 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
19831 gen_store_gpr(v1_t, ret);
19832 break;
19833 case NM_ADDQ_S_W:
19834 check_dsp(ctx);
19835 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
19836 gen_store_gpr(v1_t, ret);
19837 break;
19838 case NM_SUBQ_S_W:
19839 check_dsp(ctx);
19840 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
19841 gen_store_gpr(v1_t, ret);
19842 break;
19843 case NM_ADDSC:
19844 check_dsp(ctx);
19845 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
19846 gen_store_gpr(v1_t, ret);
19847 break;
19848 case NM_ADDWC:
19849 check_dsp(ctx);
19850 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
19851 gen_store_gpr(v1_t, ret);
19852 break;
19853 case NM_ADDQ_S_PH:
19854 check_dsp(ctx);
19855 switch (extract32(ctx->opcode, 10, 1)) {
19856 case 0:
19857 /* ADDQ_PH */
19858 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
19859 gen_store_gpr(v1_t, ret);
19860 break;
19861 case 1:
19862 /* ADDQ_S_PH */
19863 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19864 gen_store_gpr(v1_t, ret);
19865 break;
19867 break;
19868 case NM_ADDQH_R_PH:
19869 check_dsp_r2(ctx);
19870 switch (extract32(ctx->opcode, 10, 1)) {
19871 case 0:
19872 /* ADDQH_PH */
19873 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
19874 gen_store_gpr(v1_t, ret);
19875 break;
19876 case 1:
19877 /* ADDQH_R_PH */
19878 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
19879 gen_store_gpr(v1_t, ret);
19880 break;
19882 break;
19883 case NM_ADDQH_R_W:
19884 check_dsp_r2(ctx);
19885 switch (extract32(ctx->opcode, 10, 1)) {
19886 case 0:
19887 /* ADDQH_W */
19888 gen_helper_addqh_w(v1_t, v1_t, v2_t);
19889 gen_store_gpr(v1_t, ret);
19890 break;
19891 case 1:
19892 /* ADDQH_R_W */
19893 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
19894 gen_store_gpr(v1_t, ret);
19895 break;
19897 break;
19898 case NM_ADDU_S_QB:
19899 check_dsp(ctx);
19900 switch (extract32(ctx->opcode, 10, 1)) {
19901 case 0:
19902 /* ADDU_QB */
19903 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
19904 gen_store_gpr(v1_t, ret);
19905 break;
19906 case 1:
19907 /* ADDU_S_QB */
19908 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19909 gen_store_gpr(v1_t, ret);
19910 break;
19912 break;
19913 case NM_ADDU_S_PH:
19914 check_dsp_r2(ctx);
19915 switch (extract32(ctx->opcode, 10, 1)) {
19916 case 0:
19917 /* ADDU_PH */
19918 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
19919 gen_store_gpr(v1_t, ret);
19920 break;
19921 case 1:
19922 /* ADDU_S_PH */
19923 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19924 gen_store_gpr(v1_t, ret);
19925 break;
19927 break;
19928 case NM_ADDUH_R_QB:
19929 check_dsp_r2(ctx);
19930 switch (extract32(ctx->opcode, 10, 1)) {
19931 case 0:
19932 /* ADDUH_QB */
19933 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
19934 gen_store_gpr(v1_t, ret);
19935 break;
19936 case 1:
19937 /* ADDUH_R_QB */
19938 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
19939 gen_store_gpr(v1_t, ret);
19940 break;
19942 break;
19943 case NM_SHRAV_R_PH:
19944 check_dsp(ctx);
19945 switch (extract32(ctx->opcode, 10, 1)) {
19946 case 0:
19947 /* SHRAV_PH */
19948 gen_helper_shra_ph(v1_t, v1_t, v2_t);
19949 gen_store_gpr(v1_t, ret);
19950 break;
19951 case 1:
19952 /* SHRAV_R_PH */
19953 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
19954 gen_store_gpr(v1_t, ret);
19955 break;
19957 break;
19958 case NM_SHRAV_R_QB:
19959 check_dsp_r2(ctx);
19960 switch (extract32(ctx->opcode, 10, 1)) {
19961 case 0:
19962 /* SHRAV_QB */
19963 gen_helper_shra_qb(v1_t, v1_t, v2_t);
19964 gen_store_gpr(v1_t, ret);
19965 break;
19966 case 1:
19967 /* SHRAV_R_QB */
19968 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
19969 gen_store_gpr(v1_t, ret);
19970 break;
19972 break;
19973 case NM_SUBQ_S_PH:
19974 check_dsp(ctx);
19975 switch (extract32(ctx->opcode, 10, 1)) {
19976 case 0:
19977 /* SUBQ_PH */
19978 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
19979 gen_store_gpr(v1_t, ret);
19980 break;
19981 case 1:
19982 /* SUBQ_S_PH */
19983 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19984 gen_store_gpr(v1_t, ret);
19985 break;
19987 break;
19988 case NM_SUBQH_R_PH:
19989 check_dsp_r2(ctx);
19990 switch (extract32(ctx->opcode, 10, 1)) {
19991 case 0:
19992 /* SUBQH_PH */
19993 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
19994 gen_store_gpr(v1_t, ret);
19995 break;
19996 case 1:
19997 /* SUBQH_R_PH */
19998 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
19999 gen_store_gpr(v1_t, ret);
20000 break;
20002 break;
20003 case NM_SUBQH_R_W:
20004 check_dsp_r2(ctx);
20005 switch (extract32(ctx->opcode, 10, 1)) {
20006 case 0:
20007 /* SUBQH_W */
20008 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20009 gen_store_gpr(v1_t, ret);
20010 break;
20011 case 1:
20012 /* SUBQH_R_W */
20013 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20014 gen_store_gpr(v1_t, ret);
20015 break;
20017 break;
20018 case NM_SUBU_S_QB:
20019 check_dsp(ctx);
20020 switch (extract32(ctx->opcode, 10, 1)) {
20021 case 0:
20022 /* SUBU_QB */
20023 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20024 gen_store_gpr(v1_t, ret);
20025 break;
20026 case 1:
20027 /* SUBU_S_QB */
20028 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20029 gen_store_gpr(v1_t, ret);
20030 break;
20032 break;
20033 case NM_SUBU_S_PH:
20034 check_dsp_r2(ctx);
20035 switch (extract32(ctx->opcode, 10, 1)) {
20036 case 0:
20037 /* SUBU_PH */
20038 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20039 gen_store_gpr(v1_t, ret);
20040 break;
20041 case 1:
20042 /* SUBU_S_PH */
20043 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20044 gen_store_gpr(v1_t, ret);
20045 break;
20047 break;
20048 case NM_SUBUH_R_QB:
20049 check_dsp_r2(ctx);
20050 switch (extract32(ctx->opcode, 10, 1)) {
20051 case 0:
20052 /* SUBUH_QB */
20053 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20054 gen_store_gpr(v1_t, ret);
20055 break;
20056 case 1:
20057 /* SUBUH_R_QB */
20058 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20059 gen_store_gpr(v1_t, ret);
20060 break;
20062 break;
20063 case NM_SHLLV_S_PH:
20064 check_dsp(ctx);
20065 switch (extract32(ctx->opcode, 10, 1)) {
20066 case 0:
20067 /* SHLLV_PH */
20068 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20069 gen_store_gpr(v1_t, ret);
20070 break;
20071 case 1:
20072 /* SHLLV_S_PH */
20073 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20074 gen_store_gpr(v1_t, ret);
20075 break;
20077 break;
20078 case NM_PRECR_SRA_R_PH_W:
20079 check_dsp_r2(ctx);
20080 switch (extract32(ctx->opcode, 10, 1)) {
20081 case 0:
20082 /* PRECR_SRA_PH_W */
20084 TCGv_i32 sa_t = tcg_const_i32(rd);
20085 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20086 cpu_gpr[rt]);
20087 gen_store_gpr(v1_t, rt);
20088 tcg_temp_free_i32(sa_t);
20090 break;
20091 case 1:
20092 /* PRECR_SRA_R_PH_W */
20094 TCGv_i32 sa_t = tcg_const_i32(rd);
20095 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20096 cpu_gpr[rt]);
20097 gen_store_gpr(v1_t, rt);
20098 tcg_temp_free_i32(sa_t);
20100 break;
20102 break;
20103 case NM_MULEU_S_PH_QBL:
20104 check_dsp(ctx);
20105 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20106 gen_store_gpr(v1_t, ret);
20107 break;
20108 case NM_MULEU_S_PH_QBR:
20109 check_dsp(ctx);
20110 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20111 gen_store_gpr(v1_t, ret);
20112 break;
20113 case NM_MULQ_RS_PH:
20114 check_dsp(ctx);
20115 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20116 gen_store_gpr(v1_t, ret);
20117 break;
20118 case NM_MULQ_S_PH:
20119 check_dsp_r2(ctx);
20120 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20121 gen_store_gpr(v1_t, ret);
20122 break;
20123 case NM_MULQ_RS_W:
20124 check_dsp_r2(ctx);
20125 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20126 gen_store_gpr(v1_t, ret);
20127 break;
20128 case NM_MULQ_S_W:
20129 check_dsp_r2(ctx);
20130 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20131 gen_store_gpr(v1_t, ret);
20132 break;
20133 case NM_APPEND:
20134 check_dsp_r2(ctx);
20135 gen_load_gpr(t0, rs);
20136 if (rd != 0) {
20137 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20139 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20140 break;
20141 case NM_MODSUB:
20142 check_dsp(ctx);
20143 gen_helper_modsub(v1_t, v1_t, v2_t);
20144 gen_store_gpr(v1_t, ret);
20145 break;
20146 case NM_SHRAV_R_W:
20147 check_dsp(ctx);
20148 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20149 gen_store_gpr(v1_t, ret);
20150 break;
20151 case NM_SHRLV_PH:
20152 check_dsp_r2(ctx);
20153 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20154 gen_store_gpr(v1_t, ret);
20155 break;
20156 case NM_SHRLV_QB:
20157 check_dsp(ctx);
20158 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20159 gen_store_gpr(v1_t, ret);
20160 break;
20161 case NM_SHLLV_QB:
20162 check_dsp(ctx);
20163 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20164 gen_store_gpr(v1_t, ret);
20165 break;
20166 case NM_SHLLV_S_W:
20167 check_dsp(ctx);
20168 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20169 gen_store_gpr(v1_t, ret);
20170 break;
20171 case NM_SHILO:
20172 check_dsp(ctx);
20174 TCGv tv0 = tcg_temp_new();
20175 TCGv tv1 = tcg_temp_new();
20176 int16_t imm = extract32(ctx->opcode, 16, 7);
20178 tcg_gen_movi_tl(tv0, rd >> 3);
20179 tcg_gen_movi_tl(tv1, imm);
20180 gen_helper_shilo(tv0, tv1, cpu_env);
20182 break;
20183 case NM_MULEQ_S_W_PHL:
20184 check_dsp(ctx);
20185 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20186 gen_store_gpr(v1_t, ret);
20187 break;
20188 case NM_MULEQ_S_W_PHR:
20189 check_dsp(ctx);
20190 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20191 gen_store_gpr(v1_t, ret);
20192 break;
20193 case NM_MUL_S_PH:
20194 check_dsp_r2(ctx);
20195 switch (extract32(ctx->opcode, 10, 1)) {
20196 case 0:
20197 /* MUL_PH */
20198 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20199 gen_store_gpr(v1_t, ret);
20200 break;
20201 case 1:
20202 /* MUL_S_PH */
20203 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20204 gen_store_gpr(v1_t, ret);
20205 break;
20207 break;
20208 case NM_PRECR_QB_PH:
20209 check_dsp_r2(ctx);
20210 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20211 gen_store_gpr(v1_t, ret);
20212 break;
20213 case NM_PRECRQ_QB_PH:
20214 check_dsp(ctx);
20215 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20216 gen_store_gpr(v1_t, ret);
20217 break;
20218 case NM_PRECRQ_PH_W:
20219 check_dsp(ctx);
20220 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20221 gen_store_gpr(v1_t, ret);
20222 break;
20223 case NM_PRECRQ_RS_PH_W:
20224 check_dsp(ctx);
20225 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20226 gen_store_gpr(v1_t, ret);
20227 break;
20228 case NM_PRECRQU_S_QB_PH:
20229 check_dsp(ctx);
20230 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20231 gen_store_gpr(v1_t, ret);
20232 break;
20233 case NM_SHRA_R_W:
20234 check_dsp(ctx);
20235 tcg_gen_movi_tl(t0, rd);
20236 gen_helper_shra_r_w(v1_t, t0, v1_t);
20237 gen_store_gpr(v1_t, rt);
20238 break;
20239 case NM_SHRA_R_PH:
20240 check_dsp(ctx);
20241 tcg_gen_movi_tl(t0, rd >> 1);
20242 switch (extract32(ctx->opcode, 10, 1)) {
20243 case 0:
20244 /* SHRA_PH */
20245 gen_helper_shra_ph(v1_t, t0, v1_t);
20246 gen_store_gpr(v1_t, rt);
20247 break;
20248 case 1:
20249 /* SHRA_R_PH */
20250 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20251 gen_store_gpr(v1_t, rt);
20252 break;
20254 break;
20255 case NM_SHLL_S_PH:
20256 check_dsp(ctx);
20257 tcg_gen_movi_tl(t0, rd >> 1);
20258 switch (extract32(ctx->opcode, 10, 2)) {
20259 case 0:
20260 /* SHLL_PH */
20261 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20262 gen_store_gpr(v1_t, rt);
20263 break;
20264 case 2:
20265 /* SHLL_S_PH */
20266 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20267 gen_store_gpr(v1_t, rt);
20268 break;
20269 default:
20270 gen_reserved_instruction(ctx);
20271 break;
20273 break;
20274 case NM_SHLL_S_W:
20275 check_dsp(ctx);
20276 tcg_gen_movi_tl(t0, rd);
20277 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20278 gen_store_gpr(v1_t, rt);
20279 break;
20280 case NM_REPL_PH:
20281 check_dsp(ctx);
20283 int16_t imm;
20284 imm = sextract32(ctx->opcode, 11, 11);
20285 imm = (int16_t)(imm << 6) >> 6;
20286 if (rt != 0) {
20287 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20290 break;
20291 default:
20292 gen_reserved_instruction(ctx);
20293 break;
20297 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20299 uint16_t insn;
20300 uint32_t op;
20301 int rt, rs, rd;
20302 int offset;
20303 int imm;
20305 insn = translator_lduw(env, ctx->base.pc_next + 2);
20306 ctx->opcode = (ctx->opcode << 16) | insn;
20308 rt = extract32(ctx->opcode, 21, 5);
20309 rs = extract32(ctx->opcode, 16, 5);
20310 rd = extract32(ctx->opcode, 11, 5);
20312 op = extract32(ctx->opcode, 26, 6);
20313 switch (op) {
20314 case NM_P_ADDIU:
20315 if (rt == 0) {
20316 /* P.RI */
20317 switch (extract32(ctx->opcode, 19, 2)) {
20318 case NM_SIGRIE:
20319 default:
20320 gen_reserved_instruction(ctx);
20321 break;
20322 case NM_P_SYSCALL:
20323 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20324 generate_exception_end(ctx, EXCP_SYSCALL);
20325 } else {
20326 gen_reserved_instruction(ctx);
20328 break;
20329 case NM_BREAK:
20330 generate_exception_end(ctx, EXCP_BREAK);
20331 break;
20332 case NM_SDBBP:
20333 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20334 gen_helper_do_semihosting(cpu_env);
20335 } else {
20336 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20337 gen_reserved_instruction(ctx);
20338 } else {
20339 generate_exception_end(ctx, EXCP_DBp);
20342 break;
20344 } else {
20345 /* NM_ADDIU */
20346 imm = extract32(ctx->opcode, 0, 16);
20347 if (rs != 0) {
20348 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20349 } else {
20350 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20352 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20354 break;
20355 case NM_ADDIUPC:
20356 if (rt != 0) {
20357 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20358 extract32(ctx->opcode, 1, 20) << 1;
20359 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20360 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20362 break;
20363 case NM_POOL32A:
20364 switch (ctx->opcode & 0x07) {
20365 case NM_POOL32A0:
20366 gen_pool32a0_nanomips_insn(env, ctx);
20367 break;
20368 case NM_POOL32A5:
20370 int32_t op1 = extract32(ctx->opcode, 3, 7);
20371 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20373 break;
20374 case NM_POOL32A7:
20375 switch (extract32(ctx->opcode, 3, 3)) {
20376 case NM_P_LSX:
20377 gen_p_lsx(ctx, rd, rs, rt);
20378 break;
20379 case NM_LSA:
20381 * In nanoMIPS, the shift field directly encodes the shift
20382 * amount, meaning that the supported shift values are in
20383 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
20385 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2) - 1);
20386 break;
20387 case NM_EXTW:
20388 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20389 break;
20390 case NM_POOL32AXF:
20391 gen_pool32axf_nanomips_insn(env, ctx);
20392 break;
20393 default:
20394 gen_reserved_instruction(ctx);
20395 break;
20397 break;
20398 default:
20399 gen_reserved_instruction(ctx);
20400 break;
20402 break;
20403 case NM_P_GP_W:
20404 switch (ctx->opcode & 0x03) {
20405 case NM_ADDIUGP_W:
20406 if (rt != 0) {
20407 offset = extract32(ctx->opcode, 0, 21);
20408 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20410 break;
20411 case NM_LWGP:
20412 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20413 break;
20414 case NM_SWGP:
20415 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20416 break;
20417 default:
20418 gen_reserved_instruction(ctx);
20419 break;
20421 break;
20422 case NM_P48I:
20424 insn = translator_lduw(env, ctx->base.pc_next + 4);
20425 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20426 switch (extract32(ctx->opcode, 16, 5)) {
20427 case NM_LI48:
20428 check_nms(ctx);
20429 if (rt != 0) {
20430 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20432 break;
20433 case NM_ADDIU48:
20434 check_nms(ctx);
20435 if (rt != 0) {
20436 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20437 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20439 break;
20440 case NM_ADDIUGP48:
20441 check_nms(ctx);
20442 if (rt != 0) {
20443 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20445 break;
20446 case NM_ADDIUPC48:
20447 check_nms(ctx);
20448 if (rt != 0) {
20449 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20450 addr_off);
20452 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20454 break;
20455 case NM_LWPC48:
20456 check_nms(ctx);
20457 if (rt != 0) {
20458 TCGv t0;
20459 t0 = tcg_temp_new();
20461 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20462 addr_off);
20464 tcg_gen_movi_tl(t0, addr);
20465 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20466 tcg_temp_free(t0);
20468 break;
20469 case NM_SWPC48:
20470 check_nms(ctx);
20472 TCGv t0, t1;
20473 t0 = tcg_temp_new();
20474 t1 = tcg_temp_new();
20476 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20477 addr_off);
20479 tcg_gen_movi_tl(t0, addr);
20480 gen_load_gpr(t1, rt);
20482 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20484 tcg_temp_free(t0);
20485 tcg_temp_free(t1);
20487 break;
20488 default:
20489 gen_reserved_instruction(ctx);
20490 break;
20492 return 6;
20494 case NM_P_U12:
20495 switch (extract32(ctx->opcode, 12, 4)) {
20496 case NM_ORI:
20497 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20498 break;
20499 case NM_XORI:
20500 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20501 break;
20502 case NM_ANDI:
20503 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20504 break;
20505 case NM_P_SR:
20506 switch (extract32(ctx->opcode, 20, 1)) {
20507 case NM_PP_SR:
20508 switch (ctx->opcode & 3) {
20509 case NM_SAVE:
20510 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20511 extract32(ctx->opcode, 2, 1),
20512 extract32(ctx->opcode, 3, 9) << 3);
20513 break;
20514 case NM_RESTORE:
20515 case NM_RESTORE_JRC:
20516 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20517 extract32(ctx->opcode, 2, 1),
20518 extract32(ctx->opcode, 3, 9) << 3);
20519 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20520 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20522 break;
20523 default:
20524 gen_reserved_instruction(ctx);
20525 break;
20527 break;
20528 case NM_P_SR_F:
20529 gen_reserved_instruction(ctx);
20530 break;
20532 break;
20533 case NM_SLTI:
20534 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20535 break;
20536 case NM_SLTIU:
20537 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20538 break;
20539 case NM_SEQI:
20541 TCGv t0 = tcg_temp_new();
20543 imm = extract32(ctx->opcode, 0, 12);
20544 gen_load_gpr(t0, rs);
20545 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20546 gen_store_gpr(t0, rt);
20548 tcg_temp_free(t0);
20550 break;
20551 case NM_ADDIUNEG:
20552 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20553 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20554 break;
20555 case NM_P_SHIFT:
20557 int shift = extract32(ctx->opcode, 0, 5);
20558 switch (extract32(ctx->opcode, 5, 4)) {
20559 case NM_P_SLL:
20560 if (rt == 0 && shift == 0) {
20561 /* NOP */
20562 } else if (rt == 0 && shift == 3) {
20563 /* EHB - treat as NOP */
20564 } else if (rt == 0 && shift == 5) {
20565 /* PAUSE - treat as NOP */
20566 } else if (rt == 0 && shift == 6) {
20567 /* SYNC */
20568 gen_sync(extract32(ctx->opcode, 16, 5));
20569 } else {
20570 /* SLL */
20571 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20572 extract32(ctx->opcode, 0, 5));
20574 break;
20575 case NM_SRL:
20576 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20577 extract32(ctx->opcode, 0, 5));
20578 break;
20579 case NM_SRA:
20580 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20581 extract32(ctx->opcode, 0, 5));
20582 break;
20583 case NM_ROTR:
20584 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20585 extract32(ctx->opcode, 0, 5));
20586 break;
20589 break;
20590 case NM_P_ROTX:
20591 check_nms(ctx);
20592 if (rt != 0) {
20593 TCGv t0 = tcg_temp_new();
20594 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20595 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20596 << 1);
20597 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20599 gen_load_gpr(t0, rs);
20600 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20601 tcg_temp_free(t0);
20603 tcg_temp_free_i32(shift);
20604 tcg_temp_free_i32(shiftx);
20605 tcg_temp_free_i32(stripe);
20607 break;
20608 case NM_P_INS:
20609 switch (((ctx->opcode >> 10) & 2) |
20610 (extract32(ctx->opcode, 5, 1))) {
20611 case NM_INS:
20612 check_nms(ctx);
20613 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20614 extract32(ctx->opcode, 6, 5));
20615 break;
20616 default:
20617 gen_reserved_instruction(ctx);
20618 break;
20620 break;
20621 case NM_P_EXT:
20622 switch (((ctx->opcode >> 10) & 2) |
20623 (extract32(ctx->opcode, 5, 1))) {
20624 case NM_EXT:
20625 check_nms(ctx);
20626 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20627 extract32(ctx->opcode, 6, 5));
20628 break;
20629 default:
20630 gen_reserved_instruction(ctx);
20631 break;
20633 break;
20634 default:
20635 gen_reserved_instruction(ctx);
20636 break;
20638 break;
20639 case NM_POOL32F:
20640 gen_pool32f_nanomips_insn(ctx);
20641 break;
20642 case NM_POOL32S:
20643 break;
20644 case NM_P_LUI:
20645 switch (extract32(ctx->opcode, 1, 1)) {
20646 case NM_LUI:
20647 if (rt != 0) {
20648 tcg_gen_movi_tl(cpu_gpr[rt],
20649 sextract32(ctx->opcode, 0, 1) << 31 |
20650 extract32(ctx->opcode, 2, 10) << 21 |
20651 extract32(ctx->opcode, 12, 9) << 12);
20653 break;
20654 case NM_ALUIPC:
20655 if (rt != 0) {
20656 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20657 extract32(ctx->opcode, 2, 10) << 21 |
20658 extract32(ctx->opcode, 12, 9) << 12;
20659 target_long addr;
20660 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20661 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20663 break;
20665 break;
20666 case NM_P_GP_BH:
20668 uint32_t u = extract32(ctx->opcode, 0, 18);
20670 switch (extract32(ctx->opcode, 18, 3)) {
20671 case NM_LBGP:
20672 gen_ld(ctx, OPC_LB, rt, 28, u);
20673 break;
20674 case NM_SBGP:
20675 gen_st(ctx, OPC_SB, rt, 28, u);
20676 break;
20677 case NM_LBUGP:
20678 gen_ld(ctx, OPC_LBU, rt, 28, u);
20679 break;
20680 case NM_ADDIUGP_B:
20681 if (rt != 0) {
20682 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
20684 break;
20685 case NM_P_GP_LH:
20686 u &= ~1;
20687 switch (ctx->opcode & 1) {
20688 case NM_LHGP:
20689 gen_ld(ctx, OPC_LH, rt, 28, u);
20690 break;
20691 case NM_LHUGP:
20692 gen_ld(ctx, OPC_LHU, rt, 28, u);
20693 break;
20695 break;
20696 case NM_P_GP_SH:
20697 u &= ~1;
20698 switch (ctx->opcode & 1) {
20699 case NM_SHGP:
20700 gen_st(ctx, OPC_SH, rt, 28, u);
20701 break;
20702 default:
20703 gen_reserved_instruction(ctx);
20704 break;
20706 break;
20707 case NM_P_GP_CP1:
20708 u &= ~0x3;
20709 switch (ctx->opcode & 0x3) {
20710 case NM_LWC1GP:
20711 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
20712 break;
20713 case NM_LDC1GP:
20714 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
20715 break;
20716 case NM_SWC1GP:
20717 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
20718 break;
20719 case NM_SDC1GP:
20720 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
20721 break;
20723 break;
20724 default:
20725 gen_reserved_instruction(ctx);
20726 break;
20729 break;
20730 case NM_P_LS_U12:
20732 uint32_t u = extract32(ctx->opcode, 0, 12);
20734 switch (extract32(ctx->opcode, 12, 4)) {
20735 case NM_P_PREFU12:
20736 if (rt == 31) {
20737 /* SYNCI */
20739 * Break the TB to be able to sync copied instructions
20740 * immediately.
20742 ctx->base.is_jmp = DISAS_STOP;
20743 } else {
20744 /* PREF */
20745 /* Treat as NOP. */
20747 break;
20748 case NM_LB:
20749 gen_ld(ctx, OPC_LB, rt, rs, u);
20750 break;
20751 case NM_LH:
20752 gen_ld(ctx, OPC_LH, rt, rs, u);
20753 break;
20754 case NM_LW:
20755 gen_ld(ctx, OPC_LW, rt, rs, u);
20756 break;
20757 case NM_LBU:
20758 gen_ld(ctx, OPC_LBU, rt, rs, u);
20759 break;
20760 case NM_LHU:
20761 gen_ld(ctx, OPC_LHU, rt, rs, u);
20762 break;
20763 case NM_SB:
20764 gen_st(ctx, OPC_SB, rt, rs, u);
20765 break;
20766 case NM_SH:
20767 gen_st(ctx, OPC_SH, rt, rs, u);
20768 break;
20769 case NM_SW:
20770 gen_st(ctx, OPC_SW, rt, rs, u);
20771 break;
20772 case NM_LWC1:
20773 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
20774 break;
20775 case NM_LDC1:
20776 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
20777 break;
20778 case NM_SWC1:
20779 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
20780 break;
20781 case NM_SDC1:
20782 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
20783 break;
20784 default:
20785 gen_reserved_instruction(ctx);
20786 break;
20789 break;
20790 case NM_P_LS_S9:
20792 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
20793 extract32(ctx->opcode, 0, 8);
20795 switch (extract32(ctx->opcode, 8, 3)) {
20796 case NM_P_LS_S0:
20797 switch (extract32(ctx->opcode, 11, 4)) {
20798 case NM_LBS9:
20799 gen_ld(ctx, OPC_LB, rt, rs, s);
20800 break;
20801 case NM_LHS9:
20802 gen_ld(ctx, OPC_LH, rt, rs, s);
20803 break;
20804 case NM_LWS9:
20805 gen_ld(ctx, OPC_LW, rt, rs, s);
20806 break;
20807 case NM_LBUS9:
20808 gen_ld(ctx, OPC_LBU, rt, rs, s);
20809 break;
20810 case NM_LHUS9:
20811 gen_ld(ctx, OPC_LHU, rt, rs, s);
20812 break;
20813 case NM_SBS9:
20814 gen_st(ctx, OPC_SB, rt, rs, s);
20815 break;
20816 case NM_SHS9:
20817 gen_st(ctx, OPC_SH, rt, rs, s);
20818 break;
20819 case NM_SWS9:
20820 gen_st(ctx, OPC_SW, rt, rs, s);
20821 break;
20822 case NM_LWC1S9:
20823 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
20824 break;
20825 case NM_LDC1S9:
20826 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
20827 break;
20828 case NM_SWC1S9:
20829 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
20830 break;
20831 case NM_SDC1S9:
20832 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
20833 break;
20834 case NM_P_PREFS9:
20835 if (rt == 31) {
20836 /* SYNCI */
20838 * Break the TB to be able to sync copied instructions
20839 * immediately.
20841 ctx->base.is_jmp = DISAS_STOP;
20842 } else {
20843 /* PREF */
20844 /* Treat as NOP. */
20846 break;
20847 default:
20848 gen_reserved_instruction(ctx);
20849 break;
20851 break;
20852 case NM_P_LS_S1:
20853 switch (extract32(ctx->opcode, 11, 4)) {
20854 case NM_UALH:
20855 case NM_UASH:
20856 check_nms(ctx);
20858 TCGv t0 = tcg_temp_new();
20859 TCGv t1 = tcg_temp_new();
20861 gen_base_offset_addr(ctx, t0, rs, s);
20863 switch (extract32(ctx->opcode, 11, 4)) {
20864 case NM_UALH:
20865 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
20866 MO_UNALN);
20867 gen_store_gpr(t0, rt);
20868 break;
20869 case NM_UASH:
20870 gen_load_gpr(t1, rt);
20871 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
20872 MO_UNALN);
20873 break;
20875 tcg_temp_free(t0);
20876 tcg_temp_free(t1);
20878 break;
20879 case NM_P_LL:
20880 switch (ctx->opcode & 0x03) {
20881 case NM_LL:
20882 gen_ld(ctx, OPC_LL, rt, rs, s);
20883 break;
20884 case NM_LLWP:
20885 check_xnp(ctx);
20886 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
20887 break;
20889 break;
20890 case NM_P_SC:
20891 switch (ctx->opcode & 0x03) {
20892 case NM_SC:
20893 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
20894 break;
20895 case NM_SCWP:
20896 check_xnp(ctx);
20897 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
20898 false);
20899 break;
20901 break;
20902 case NM_CACHE:
20903 check_cp0_enabled(ctx);
20904 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
20905 gen_cache_operation(ctx, rt, rs, s);
20907 break;
20909 break;
20910 case NM_P_LS_E0:
20911 switch (extract32(ctx->opcode, 11, 4)) {
20912 case NM_LBE:
20913 check_eva(ctx);
20914 check_cp0_enabled(ctx);
20915 gen_ld(ctx, OPC_LBE, rt, rs, s);
20916 break;
20917 case NM_SBE:
20918 check_eva(ctx);
20919 check_cp0_enabled(ctx);
20920 gen_st(ctx, OPC_SBE, rt, rs, s);
20921 break;
20922 case NM_LBUE:
20923 check_eva(ctx);
20924 check_cp0_enabled(ctx);
20925 gen_ld(ctx, OPC_LBUE, rt, rs, s);
20926 break;
20927 case NM_P_PREFE:
20928 if (rt == 31) {
20929 /* case NM_SYNCIE */
20930 check_eva(ctx);
20931 check_cp0_enabled(ctx);
20933 * Break the TB to be able to sync copied instructions
20934 * immediately.
20936 ctx->base.is_jmp = DISAS_STOP;
20937 } else {
20938 /* case NM_PREFE */
20939 check_eva(ctx);
20940 check_cp0_enabled(ctx);
20941 /* Treat as NOP. */
20943 break;
20944 case NM_LHE:
20945 check_eva(ctx);
20946 check_cp0_enabled(ctx);
20947 gen_ld(ctx, OPC_LHE, rt, rs, s);
20948 break;
20949 case NM_SHE:
20950 check_eva(ctx);
20951 check_cp0_enabled(ctx);
20952 gen_st(ctx, OPC_SHE, rt, rs, s);
20953 break;
20954 case NM_LHUE:
20955 check_eva(ctx);
20956 check_cp0_enabled(ctx);
20957 gen_ld(ctx, OPC_LHUE, rt, rs, s);
20958 break;
20959 case NM_CACHEE:
20960 check_nms_dl_il_sl_tl_l2c(ctx);
20961 gen_cache_operation(ctx, rt, rs, s);
20962 break;
20963 case NM_LWE:
20964 check_eva(ctx);
20965 check_cp0_enabled(ctx);
20966 gen_ld(ctx, OPC_LWE, rt, rs, s);
20967 break;
20968 case NM_SWE:
20969 check_eva(ctx);
20970 check_cp0_enabled(ctx);
20971 gen_st(ctx, OPC_SWE, rt, rs, s);
20972 break;
20973 case NM_P_LLE:
20974 switch (extract32(ctx->opcode, 2, 2)) {
20975 case NM_LLE:
20976 check_xnp(ctx);
20977 check_eva(ctx);
20978 check_cp0_enabled(ctx);
20979 gen_ld(ctx, OPC_LLE, rt, rs, s);
20980 break;
20981 case NM_LLWPE:
20982 check_xnp(ctx);
20983 check_eva(ctx);
20984 check_cp0_enabled(ctx);
20985 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
20986 break;
20987 default:
20988 gen_reserved_instruction(ctx);
20989 break;
20991 break;
20992 case NM_P_SCE:
20993 switch (extract32(ctx->opcode, 2, 2)) {
20994 case NM_SCE:
20995 check_xnp(ctx);
20996 check_eva(ctx);
20997 check_cp0_enabled(ctx);
20998 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
20999 break;
21000 case NM_SCWPE:
21001 check_xnp(ctx);
21002 check_eva(ctx);
21003 check_cp0_enabled(ctx);
21004 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21005 true);
21006 break;
21007 default:
21008 gen_reserved_instruction(ctx);
21009 break;
21011 break;
21013 break;
21014 case NM_P_LS_WM:
21015 case NM_P_LS_UAWM:
21016 check_nms(ctx);
21018 int count = extract32(ctx->opcode, 12, 3);
21019 int counter = 0;
21021 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21022 extract32(ctx->opcode, 0, 8);
21023 TCGv va = tcg_temp_new();
21024 TCGv t1 = tcg_temp_new();
21025 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21026 NM_P_LS_UAWM ? MO_UNALN : 0;
21028 count = (count == 0) ? 8 : count;
21029 while (counter != count) {
21030 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21031 int this_offset = offset + (counter << 2);
21033 gen_base_offset_addr(ctx, va, rs, this_offset);
21035 switch (extract32(ctx->opcode, 11, 1)) {
21036 case NM_LWM:
21037 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21038 memop | MO_TESL);
21039 gen_store_gpr(t1, this_rt);
21040 if ((this_rt == rs) &&
21041 (counter != (count - 1))) {
21042 /* UNPREDICTABLE */
21044 break;
21045 case NM_SWM:
21046 this_rt = (rt == 0) ? 0 : this_rt;
21047 gen_load_gpr(t1, this_rt);
21048 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21049 memop | MO_TEUL);
21050 break;
21052 counter++;
21054 tcg_temp_free(va);
21055 tcg_temp_free(t1);
21057 break;
21058 default:
21059 gen_reserved_instruction(ctx);
21060 break;
21063 break;
21064 case NM_MOVE_BALC:
21065 check_nms(ctx);
21067 TCGv t0 = tcg_temp_new();
21068 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21069 extract32(ctx->opcode, 1, 20) << 1;
21070 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21071 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21072 extract32(ctx->opcode, 21, 3));
21073 gen_load_gpr(t0, rt);
21074 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21075 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21076 tcg_temp_free(t0);
21078 break;
21079 case NM_P_BAL:
21081 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21082 extract32(ctx->opcode, 1, 24) << 1;
21084 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21085 /* BC */
21086 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21087 } else {
21088 /* BALC */
21089 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21092 break;
21093 case NM_P_J:
21094 switch (extract32(ctx->opcode, 12, 4)) {
21095 case NM_JALRC:
21096 case NM_JALRC_HB:
21097 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21098 break;
21099 case NM_P_BALRSC:
21100 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21101 break;
21102 default:
21103 gen_reserved_instruction(ctx);
21104 break;
21106 break;
21107 case NM_P_BR1:
21109 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21110 extract32(ctx->opcode, 1, 13) << 1;
21111 switch (extract32(ctx->opcode, 14, 2)) {
21112 case NM_BEQC:
21113 check_nms(ctx);
21114 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21115 break;
21116 case NM_P_BR3A:
21117 s = sextract32(ctx->opcode, 0, 1) << 14 |
21118 extract32(ctx->opcode, 1, 13) << 1;
21119 check_cp1_enabled(ctx);
21120 switch (extract32(ctx->opcode, 16, 5)) {
21121 case NM_BC1EQZC:
21122 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21123 break;
21124 case NM_BC1NEZC:
21125 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21126 break;
21127 case NM_BPOSGE32C:
21128 check_dsp_r3(ctx);
21130 int32_t imm = extract32(ctx->opcode, 1, 13) |
21131 extract32(ctx->opcode, 0, 1) << 13;
21133 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21134 imm);
21136 break;
21137 default:
21138 gen_reserved_instruction(ctx);
21139 break;
21141 break;
21142 case NM_BGEC:
21143 if (rs == rt) {
21144 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21145 } else {
21146 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21148 break;
21149 case NM_BGEUC:
21150 if (rs == rt || rt == 0) {
21151 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21152 } else if (rs == 0) {
21153 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21154 } else {
21155 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21157 break;
21160 break;
21161 case NM_P_BR2:
21163 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21164 extract32(ctx->opcode, 1, 13) << 1;
21165 switch (extract32(ctx->opcode, 14, 2)) {
21166 case NM_BNEC:
21167 check_nms(ctx);
21168 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21169 break;
21170 case NM_BLTC:
21171 if (rs != 0 && rt != 0 && rs == rt) {
21172 /* NOP */
21173 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21174 } else {
21175 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21177 break;
21178 case NM_BLTUC:
21179 if (rs == 0 || rs == rt) {
21180 /* NOP */
21181 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21182 } else {
21183 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21185 break;
21186 default:
21187 gen_reserved_instruction(ctx);
21188 break;
21191 break;
21192 case NM_P_BRI:
21194 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21195 extract32(ctx->opcode, 1, 10) << 1;
21196 uint32_t u = extract32(ctx->opcode, 11, 7);
21198 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21199 rt, u, s);
21201 break;
21202 default:
21203 gen_reserved_instruction(ctx);
21204 break;
21206 return 4;
21209 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21211 uint32_t op;
21212 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
21213 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21214 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
21215 int offset;
21216 int imm;
21218 /* make sure instructions are on a halfword boundary */
21219 if (ctx->base.pc_next & 0x1) {
21220 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21221 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21222 tcg_temp_free(tmp);
21223 generate_exception_end(ctx, EXCP_AdEL);
21224 return 2;
21227 op = extract32(ctx->opcode, 10, 6);
21228 switch (op) {
21229 case NM_P16_MV:
21230 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21231 if (rt != 0) {
21232 /* MOVE */
21233 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21234 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21235 } else {
21236 /* P16.RI */
21237 switch (extract32(ctx->opcode, 3, 2)) {
21238 case NM_P16_SYSCALL:
21239 if (extract32(ctx->opcode, 2, 1) == 0) {
21240 generate_exception_end(ctx, EXCP_SYSCALL);
21241 } else {
21242 gen_reserved_instruction(ctx);
21244 break;
21245 case NM_BREAK16:
21246 generate_exception_end(ctx, EXCP_BREAK);
21247 break;
21248 case NM_SDBBP16:
21249 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21250 gen_helper_do_semihosting(cpu_env);
21251 } else {
21252 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21253 gen_reserved_instruction(ctx);
21254 } else {
21255 generate_exception_end(ctx, EXCP_DBp);
21258 break;
21259 default:
21260 gen_reserved_instruction(ctx);
21261 break;
21264 break;
21265 case NM_P16_SHIFT:
21267 int shift = extract32(ctx->opcode, 0, 3);
21268 uint32_t opc = 0;
21269 shift = (shift == 0) ? 8 : shift;
21271 switch (extract32(ctx->opcode, 3, 1)) {
21272 case NM_SLL16:
21273 opc = OPC_SLL;
21274 break;
21275 case NM_SRL16:
21276 opc = OPC_SRL;
21277 break;
21279 gen_shift_imm(ctx, opc, rt, rs, shift);
21281 break;
21282 case NM_P16C:
21283 switch (ctx->opcode & 1) {
21284 case NM_POOL16C_0:
21285 gen_pool16c_nanomips_insn(ctx);
21286 break;
21287 case NM_LWXS16:
21288 gen_ldxs(ctx, rt, rs, rd);
21289 break;
21291 break;
21292 case NM_P16_A1:
21293 switch (extract32(ctx->opcode, 6, 1)) {
21294 case NM_ADDIUR1SP:
21295 imm = extract32(ctx->opcode, 0, 6) << 2;
21296 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21297 break;
21298 default:
21299 gen_reserved_instruction(ctx);
21300 break;
21302 break;
21303 case NM_P16_A2:
21304 switch (extract32(ctx->opcode, 3, 1)) {
21305 case NM_ADDIUR2:
21306 imm = extract32(ctx->opcode, 0, 3) << 2;
21307 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21308 break;
21309 case NM_P_ADDIURS5:
21310 rt = extract32(ctx->opcode, 5, 5);
21311 if (rt != 0) {
21312 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21313 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21314 (extract32(ctx->opcode, 0, 3));
21315 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21317 break;
21319 break;
21320 case NM_P16_ADDU:
21321 switch (ctx->opcode & 0x1) {
21322 case NM_ADDU16:
21323 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21324 break;
21325 case NM_SUBU16:
21326 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21327 break;
21329 break;
21330 case NM_P16_4X4:
21331 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21332 extract32(ctx->opcode, 5, 3);
21333 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21334 extract32(ctx->opcode, 0, 3);
21335 rt = decode_gpr_gpr4(rt);
21336 rs = decode_gpr_gpr4(rs);
21337 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21338 (extract32(ctx->opcode, 3, 1))) {
21339 case NM_ADDU4X4:
21340 check_nms(ctx);
21341 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21342 break;
21343 case NM_MUL4X4:
21344 check_nms(ctx);
21345 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21346 break;
21347 default:
21348 gen_reserved_instruction(ctx);
21349 break;
21351 break;
21352 case NM_LI16:
21354 int imm = extract32(ctx->opcode, 0, 7);
21355 imm = (imm == 0x7f ? -1 : imm);
21356 if (rt != 0) {
21357 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21360 break;
21361 case NM_ANDI16:
21363 uint32_t u = extract32(ctx->opcode, 0, 4);
21364 u = (u == 12) ? 0xff :
21365 (u == 13) ? 0xffff : u;
21366 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21368 break;
21369 case NM_P16_LB:
21370 offset = extract32(ctx->opcode, 0, 2);
21371 switch (extract32(ctx->opcode, 2, 2)) {
21372 case NM_LB16:
21373 gen_ld(ctx, OPC_LB, rt, rs, offset);
21374 break;
21375 case NM_SB16:
21376 rt = decode_gpr_gpr3_src_store(
21377 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21378 gen_st(ctx, OPC_SB, rt, rs, offset);
21379 break;
21380 case NM_LBU16:
21381 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21382 break;
21383 default:
21384 gen_reserved_instruction(ctx);
21385 break;
21387 break;
21388 case NM_P16_LH:
21389 offset = extract32(ctx->opcode, 1, 2) << 1;
21390 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21391 case NM_LH16:
21392 gen_ld(ctx, OPC_LH, rt, rs, offset);
21393 break;
21394 case NM_SH16:
21395 rt = decode_gpr_gpr3_src_store(
21396 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21397 gen_st(ctx, OPC_SH, rt, rs, offset);
21398 break;
21399 case NM_LHU16:
21400 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21401 break;
21402 default:
21403 gen_reserved_instruction(ctx);
21404 break;
21406 break;
21407 case NM_LW16:
21408 offset = extract32(ctx->opcode, 0, 4) << 2;
21409 gen_ld(ctx, OPC_LW, rt, rs, offset);
21410 break;
21411 case NM_LWSP16:
21412 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21413 offset = extract32(ctx->opcode, 0, 5) << 2;
21414 gen_ld(ctx, OPC_LW, rt, 29, offset);
21415 break;
21416 case NM_LW4X4:
21417 check_nms(ctx);
21418 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21419 extract32(ctx->opcode, 5, 3);
21420 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21421 extract32(ctx->opcode, 0, 3);
21422 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21423 (extract32(ctx->opcode, 8, 1) << 2);
21424 rt = decode_gpr_gpr4(rt);
21425 rs = decode_gpr_gpr4(rs);
21426 gen_ld(ctx, OPC_LW, rt, rs, offset);
21427 break;
21428 case NM_SW4X4:
21429 check_nms(ctx);
21430 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21431 extract32(ctx->opcode, 5, 3);
21432 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21433 extract32(ctx->opcode, 0, 3);
21434 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21435 (extract32(ctx->opcode, 8, 1) << 2);
21436 rt = decode_gpr_gpr4_zero(rt);
21437 rs = decode_gpr_gpr4(rs);
21438 gen_st(ctx, OPC_SW, rt, rs, offset);
21439 break;
21440 case NM_LWGP16:
21441 offset = extract32(ctx->opcode, 0, 7) << 2;
21442 gen_ld(ctx, OPC_LW, rt, 28, offset);
21443 break;
21444 case NM_SWSP16:
21445 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21446 offset = extract32(ctx->opcode, 0, 5) << 2;
21447 gen_st(ctx, OPC_SW, rt, 29, offset);
21448 break;
21449 case NM_SW16:
21450 rt = decode_gpr_gpr3_src_store(
21451 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21452 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21453 offset = extract32(ctx->opcode, 0, 4) << 2;
21454 gen_st(ctx, OPC_SW, rt, rs, offset);
21455 break;
21456 case NM_SWGP16:
21457 rt = decode_gpr_gpr3_src_store(
21458 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21459 offset = extract32(ctx->opcode, 0, 7) << 2;
21460 gen_st(ctx, OPC_SW, rt, 28, offset);
21461 break;
21462 case NM_BC16:
21463 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21464 (sextract32(ctx->opcode, 0, 1) << 10) |
21465 (extract32(ctx->opcode, 1, 9) << 1));
21466 break;
21467 case NM_BALC16:
21468 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21469 (sextract32(ctx->opcode, 0, 1) << 10) |
21470 (extract32(ctx->opcode, 1, 9) << 1));
21471 break;
21472 case NM_BEQZC16:
21473 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21474 (sextract32(ctx->opcode, 0, 1) << 7) |
21475 (extract32(ctx->opcode, 1, 6) << 1));
21476 break;
21477 case NM_BNEZC16:
21478 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21479 (sextract32(ctx->opcode, 0, 1) << 7) |
21480 (extract32(ctx->opcode, 1, 6) << 1));
21481 break;
21482 case NM_P16_BR:
21483 switch (ctx->opcode & 0xf) {
21484 case 0:
21485 /* P16.JRC */
21486 switch (extract32(ctx->opcode, 4, 1)) {
21487 case NM_JRC:
21488 gen_compute_branch_nm(ctx, OPC_JR, 2,
21489 extract32(ctx->opcode, 5, 5), 0, 0);
21490 break;
21491 case NM_JALRC16:
21492 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21493 extract32(ctx->opcode, 5, 5), 31, 0);
21494 break;
21496 break;
21497 default:
21499 /* P16.BRI */
21500 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21501 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21502 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21503 extract32(ctx->opcode, 0, 4) << 1);
21505 break;
21507 break;
21508 case NM_P16_SR:
21510 int count = extract32(ctx->opcode, 0, 4);
21511 int u = extract32(ctx->opcode, 4, 4) << 4;
21513 rt = 30 + extract32(ctx->opcode, 9, 1);
21514 switch (extract32(ctx->opcode, 8, 1)) {
21515 case NM_SAVE16:
21516 gen_save(ctx, rt, count, 0, u);
21517 break;
21518 case NM_RESTORE_JRC16:
21519 gen_restore(ctx, rt, count, 0, u);
21520 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21521 break;
21524 break;
21525 case NM_MOVEP:
21526 case NM_MOVEPREV:
21527 check_nms(ctx);
21529 static const int gpr2reg1[] = {4, 5, 6, 7};
21530 static const int gpr2reg2[] = {5, 6, 7, 8};
21531 int re;
21532 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21533 extract32(ctx->opcode, 8, 1);
21534 int r1 = gpr2reg1[rd2];
21535 int r2 = gpr2reg2[rd2];
21536 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21537 extract32(ctx->opcode, 0, 3);
21538 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21539 extract32(ctx->opcode, 5, 3);
21540 TCGv t0 = tcg_temp_new();
21541 TCGv t1 = tcg_temp_new();
21542 if (op == NM_MOVEP) {
21543 rd = r1;
21544 re = r2;
21545 rs = decode_gpr_gpr4_zero(r3);
21546 rt = decode_gpr_gpr4_zero(r4);
21547 } else {
21548 rd = decode_gpr_gpr4(r3);
21549 re = decode_gpr_gpr4(r4);
21550 rs = r1;
21551 rt = r2;
21553 gen_load_gpr(t0, rs);
21554 gen_load_gpr(t1, rt);
21555 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21556 tcg_gen_mov_tl(cpu_gpr[re], t1);
21557 tcg_temp_free(t0);
21558 tcg_temp_free(t1);
21560 break;
21561 default:
21562 return decode_nanomips_32_48_opc(env, ctx);
21565 return 2;
21569 /* SmartMIPS extension to MIPS32 */
21571 #if defined(TARGET_MIPS64)
21573 /* MDMX extension to MIPS64 */
21575 #endif
21577 /* MIPSDSP functions. */
21578 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21579 int rd, int base, int offset)
21581 TCGv t0;
21583 check_dsp(ctx);
21584 t0 = tcg_temp_new();
21586 if (base == 0) {
21587 gen_load_gpr(t0, offset);
21588 } else if (offset == 0) {
21589 gen_load_gpr(t0, base);
21590 } else {
21591 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21594 switch (opc) {
21595 case OPC_LBUX:
21596 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21597 gen_store_gpr(t0, rd);
21598 break;
21599 case OPC_LHX:
21600 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21601 gen_store_gpr(t0, rd);
21602 break;
21603 case OPC_LWX:
21604 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21605 gen_store_gpr(t0, rd);
21606 break;
21607 #if defined(TARGET_MIPS64)
21608 case OPC_LDX:
21609 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21610 gen_store_gpr(t0, rd);
21611 break;
21612 #endif
21614 tcg_temp_free(t0);
21617 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21618 int ret, int v1, int v2)
21620 TCGv v1_t;
21621 TCGv v2_t;
21623 if (ret == 0) {
21624 /* Treat as NOP. */
21625 return;
21628 v1_t = tcg_temp_new();
21629 v2_t = tcg_temp_new();
21631 gen_load_gpr(v1_t, v1);
21632 gen_load_gpr(v2_t, v2);
21634 switch (op1) {
21635 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21636 case OPC_MULT_G_2E:
21637 check_dsp_r2(ctx);
21638 switch (op2) {
21639 case OPC_ADDUH_QB:
21640 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21641 break;
21642 case OPC_ADDUH_R_QB:
21643 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21644 break;
21645 case OPC_ADDQH_PH:
21646 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21647 break;
21648 case OPC_ADDQH_R_PH:
21649 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21650 break;
21651 case OPC_ADDQH_W:
21652 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21653 break;
21654 case OPC_ADDQH_R_W:
21655 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21656 break;
21657 case OPC_SUBUH_QB:
21658 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21659 break;
21660 case OPC_SUBUH_R_QB:
21661 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21662 break;
21663 case OPC_SUBQH_PH:
21664 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
21665 break;
21666 case OPC_SUBQH_R_PH:
21667 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21668 break;
21669 case OPC_SUBQH_W:
21670 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
21671 break;
21672 case OPC_SUBQH_R_W:
21673 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21674 break;
21676 break;
21677 case OPC_ABSQ_S_PH_DSP:
21678 switch (op2) {
21679 case OPC_ABSQ_S_QB:
21680 check_dsp_r2(ctx);
21681 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
21682 break;
21683 case OPC_ABSQ_S_PH:
21684 check_dsp(ctx);
21685 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
21686 break;
21687 case OPC_ABSQ_S_W:
21688 check_dsp(ctx);
21689 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
21690 break;
21691 case OPC_PRECEQ_W_PHL:
21692 check_dsp(ctx);
21693 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
21694 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21695 break;
21696 case OPC_PRECEQ_W_PHR:
21697 check_dsp(ctx);
21698 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
21699 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
21700 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21701 break;
21702 case OPC_PRECEQU_PH_QBL:
21703 check_dsp(ctx);
21704 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
21705 break;
21706 case OPC_PRECEQU_PH_QBR:
21707 check_dsp(ctx);
21708 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
21709 break;
21710 case OPC_PRECEQU_PH_QBLA:
21711 check_dsp(ctx);
21712 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
21713 break;
21714 case OPC_PRECEQU_PH_QBRA:
21715 check_dsp(ctx);
21716 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
21717 break;
21718 case OPC_PRECEU_PH_QBL:
21719 check_dsp(ctx);
21720 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
21721 break;
21722 case OPC_PRECEU_PH_QBR:
21723 check_dsp(ctx);
21724 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
21725 break;
21726 case OPC_PRECEU_PH_QBLA:
21727 check_dsp(ctx);
21728 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
21729 break;
21730 case OPC_PRECEU_PH_QBRA:
21731 check_dsp(ctx);
21732 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
21733 break;
21735 break;
21736 case OPC_ADDU_QB_DSP:
21737 switch (op2) {
21738 case OPC_ADDQ_PH:
21739 check_dsp(ctx);
21740 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21741 break;
21742 case OPC_ADDQ_S_PH:
21743 check_dsp(ctx);
21744 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21745 break;
21746 case OPC_ADDQ_S_W:
21747 check_dsp(ctx);
21748 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21749 break;
21750 case OPC_ADDU_QB:
21751 check_dsp(ctx);
21752 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21753 break;
21754 case OPC_ADDU_S_QB:
21755 check_dsp(ctx);
21756 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21757 break;
21758 case OPC_ADDU_PH:
21759 check_dsp_r2(ctx);
21760 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21761 break;
21762 case OPC_ADDU_S_PH:
21763 check_dsp_r2(ctx);
21764 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21765 break;
21766 case OPC_SUBQ_PH:
21767 check_dsp(ctx);
21768 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21769 break;
21770 case OPC_SUBQ_S_PH:
21771 check_dsp(ctx);
21772 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21773 break;
21774 case OPC_SUBQ_S_W:
21775 check_dsp(ctx);
21776 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21777 break;
21778 case OPC_SUBU_QB:
21779 check_dsp(ctx);
21780 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21781 break;
21782 case OPC_SUBU_S_QB:
21783 check_dsp(ctx);
21784 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21785 break;
21786 case OPC_SUBU_PH:
21787 check_dsp_r2(ctx);
21788 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21789 break;
21790 case OPC_SUBU_S_PH:
21791 check_dsp_r2(ctx);
21792 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21793 break;
21794 case OPC_ADDSC:
21795 check_dsp(ctx);
21796 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21797 break;
21798 case OPC_ADDWC:
21799 check_dsp(ctx);
21800 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21801 break;
21802 case OPC_MODSUB:
21803 check_dsp(ctx);
21804 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
21805 break;
21806 case OPC_RADDU_W_QB:
21807 check_dsp(ctx);
21808 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
21809 break;
21811 break;
21812 case OPC_CMPU_EQ_QB_DSP:
21813 switch (op2) {
21814 case OPC_PRECR_QB_PH:
21815 check_dsp_r2(ctx);
21816 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21817 break;
21818 case OPC_PRECRQ_QB_PH:
21819 check_dsp(ctx);
21820 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21821 break;
21822 case OPC_PRECR_SRA_PH_W:
21823 check_dsp_r2(ctx);
21825 TCGv_i32 sa_t = tcg_const_i32(v2);
21826 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
21827 cpu_gpr[ret]);
21828 tcg_temp_free_i32(sa_t);
21829 break;
21831 case OPC_PRECR_SRA_R_PH_W:
21832 check_dsp_r2(ctx);
21834 TCGv_i32 sa_t = tcg_const_i32(v2);
21835 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
21836 cpu_gpr[ret]);
21837 tcg_temp_free_i32(sa_t);
21838 break;
21840 case OPC_PRECRQ_PH_W:
21841 check_dsp(ctx);
21842 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
21843 break;
21844 case OPC_PRECRQ_RS_PH_W:
21845 check_dsp(ctx);
21846 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21847 break;
21848 case OPC_PRECRQU_S_QB_PH:
21849 check_dsp(ctx);
21850 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21851 break;
21853 break;
21854 #ifdef TARGET_MIPS64
21855 case OPC_ABSQ_S_QH_DSP:
21856 switch (op2) {
21857 case OPC_PRECEQ_L_PWL:
21858 check_dsp(ctx);
21859 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
21860 break;
21861 case OPC_PRECEQ_L_PWR:
21862 check_dsp(ctx);
21863 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
21864 break;
21865 case OPC_PRECEQ_PW_QHL:
21866 check_dsp(ctx);
21867 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
21868 break;
21869 case OPC_PRECEQ_PW_QHR:
21870 check_dsp(ctx);
21871 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
21872 break;
21873 case OPC_PRECEQ_PW_QHLA:
21874 check_dsp(ctx);
21875 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
21876 break;
21877 case OPC_PRECEQ_PW_QHRA:
21878 check_dsp(ctx);
21879 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
21880 break;
21881 case OPC_PRECEQU_QH_OBL:
21882 check_dsp(ctx);
21883 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
21884 break;
21885 case OPC_PRECEQU_QH_OBR:
21886 check_dsp(ctx);
21887 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
21888 break;
21889 case OPC_PRECEQU_QH_OBLA:
21890 check_dsp(ctx);
21891 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
21892 break;
21893 case OPC_PRECEQU_QH_OBRA:
21894 check_dsp(ctx);
21895 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
21896 break;
21897 case OPC_PRECEU_QH_OBL:
21898 check_dsp(ctx);
21899 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
21900 break;
21901 case OPC_PRECEU_QH_OBR:
21902 check_dsp(ctx);
21903 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
21904 break;
21905 case OPC_PRECEU_QH_OBLA:
21906 check_dsp(ctx);
21907 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
21908 break;
21909 case OPC_PRECEU_QH_OBRA:
21910 check_dsp(ctx);
21911 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
21912 break;
21913 case OPC_ABSQ_S_OB:
21914 check_dsp_r2(ctx);
21915 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
21916 break;
21917 case OPC_ABSQ_S_PW:
21918 check_dsp(ctx);
21919 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
21920 break;
21921 case OPC_ABSQ_S_QH:
21922 check_dsp(ctx);
21923 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
21924 break;
21926 break;
21927 case OPC_ADDU_OB_DSP:
21928 switch (op2) {
21929 case OPC_RADDU_L_OB:
21930 check_dsp(ctx);
21931 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
21932 break;
21933 case OPC_SUBQ_PW:
21934 check_dsp(ctx);
21935 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21936 break;
21937 case OPC_SUBQ_S_PW:
21938 check_dsp(ctx);
21939 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21940 break;
21941 case OPC_SUBQ_QH:
21942 check_dsp(ctx);
21943 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21944 break;
21945 case OPC_SUBQ_S_QH:
21946 check_dsp(ctx);
21947 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21948 break;
21949 case OPC_SUBU_OB:
21950 check_dsp(ctx);
21951 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21952 break;
21953 case OPC_SUBU_S_OB:
21954 check_dsp(ctx);
21955 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21956 break;
21957 case OPC_SUBU_QH:
21958 check_dsp_r2(ctx);
21959 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21960 break;
21961 case OPC_SUBU_S_QH:
21962 check_dsp_r2(ctx);
21963 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21964 break;
21965 case OPC_SUBUH_OB:
21966 check_dsp_r2(ctx);
21967 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
21968 break;
21969 case OPC_SUBUH_R_OB:
21970 check_dsp_r2(ctx);
21971 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21972 break;
21973 case OPC_ADDQ_PW:
21974 check_dsp(ctx);
21975 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21976 break;
21977 case OPC_ADDQ_S_PW:
21978 check_dsp(ctx);
21979 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21980 break;
21981 case OPC_ADDQ_QH:
21982 check_dsp(ctx);
21983 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21984 break;
21985 case OPC_ADDQ_S_QH:
21986 check_dsp(ctx);
21987 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21988 break;
21989 case OPC_ADDU_OB:
21990 check_dsp(ctx);
21991 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21992 break;
21993 case OPC_ADDU_S_OB:
21994 check_dsp(ctx);
21995 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21996 break;
21997 case OPC_ADDU_QH:
21998 check_dsp_r2(ctx);
21999 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22000 break;
22001 case OPC_ADDU_S_QH:
22002 check_dsp_r2(ctx);
22003 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22004 break;
22005 case OPC_ADDUH_OB:
22006 check_dsp_r2(ctx);
22007 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22008 break;
22009 case OPC_ADDUH_R_OB:
22010 check_dsp_r2(ctx);
22011 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22012 break;
22014 break;
22015 case OPC_CMPU_EQ_OB_DSP:
22016 switch (op2) {
22017 case OPC_PRECR_OB_QH:
22018 check_dsp_r2(ctx);
22019 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22020 break;
22021 case OPC_PRECR_SRA_QH_PW:
22022 check_dsp_r2(ctx);
22024 TCGv_i32 ret_t = tcg_const_i32(ret);
22025 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22026 tcg_temp_free_i32(ret_t);
22027 break;
22029 case OPC_PRECR_SRA_R_QH_PW:
22030 check_dsp_r2(ctx);
22032 TCGv_i32 sa_v = tcg_const_i32(ret);
22033 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22034 tcg_temp_free_i32(sa_v);
22035 break;
22037 case OPC_PRECRQ_OB_QH:
22038 check_dsp(ctx);
22039 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22040 break;
22041 case OPC_PRECRQ_PW_L:
22042 check_dsp(ctx);
22043 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22044 break;
22045 case OPC_PRECRQ_QH_PW:
22046 check_dsp(ctx);
22047 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22048 break;
22049 case OPC_PRECRQ_RS_QH_PW:
22050 check_dsp(ctx);
22051 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22052 break;
22053 case OPC_PRECRQU_S_OB_QH:
22054 check_dsp(ctx);
22055 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22056 break;
22058 break;
22059 #endif
22062 tcg_temp_free(v1_t);
22063 tcg_temp_free(v2_t);
22066 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22067 int ret, int v1, int v2)
22069 uint32_t op2;
22070 TCGv t0;
22071 TCGv v1_t;
22072 TCGv v2_t;
22074 if (ret == 0) {
22075 /* Treat as NOP. */
22076 return;
22079 t0 = tcg_temp_new();
22080 v1_t = tcg_temp_new();
22081 v2_t = tcg_temp_new();
22083 tcg_gen_movi_tl(t0, v1);
22084 gen_load_gpr(v1_t, v1);
22085 gen_load_gpr(v2_t, v2);
22087 switch (opc) {
22088 case OPC_SHLL_QB_DSP:
22090 op2 = MASK_SHLL_QB(ctx->opcode);
22091 switch (op2) {
22092 case OPC_SHLL_QB:
22093 check_dsp(ctx);
22094 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22095 break;
22096 case OPC_SHLLV_QB:
22097 check_dsp(ctx);
22098 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22099 break;
22100 case OPC_SHLL_PH:
22101 check_dsp(ctx);
22102 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22103 break;
22104 case OPC_SHLLV_PH:
22105 check_dsp(ctx);
22106 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22107 break;
22108 case OPC_SHLL_S_PH:
22109 check_dsp(ctx);
22110 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22111 break;
22112 case OPC_SHLLV_S_PH:
22113 check_dsp(ctx);
22114 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22115 break;
22116 case OPC_SHLL_S_W:
22117 check_dsp(ctx);
22118 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22119 break;
22120 case OPC_SHLLV_S_W:
22121 check_dsp(ctx);
22122 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22123 break;
22124 case OPC_SHRL_QB:
22125 check_dsp(ctx);
22126 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22127 break;
22128 case OPC_SHRLV_QB:
22129 check_dsp(ctx);
22130 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22131 break;
22132 case OPC_SHRL_PH:
22133 check_dsp_r2(ctx);
22134 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22135 break;
22136 case OPC_SHRLV_PH:
22137 check_dsp_r2(ctx);
22138 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22139 break;
22140 case OPC_SHRA_QB:
22141 check_dsp_r2(ctx);
22142 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22143 break;
22144 case OPC_SHRA_R_QB:
22145 check_dsp_r2(ctx);
22146 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22147 break;
22148 case OPC_SHRAV_QB:
22149 check_dsp_r2(ctx);
22150 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22151 break;
22152 case OPC_SHRAV_R_QB:
22153 check_dsp_r2(ctx);
22154 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22155 break;
22156 case OPC_SHRA_PH:
22157 check_dsp(ctx);
22158 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22159 break;
22160 case OPC_SHRA_R_PH:
22161 check_dsp(ctx);
22162 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22163 break;
22164 case OPC_SHRAV_PH:
22165 check_dsp(ctx);
22166 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22167 break;
22168 case OPC_SHRAV_R_PH:
22169 check_dsp(ctx);
22170 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22171 break;
22172 case OPC_SHRA_R_W:
22173 check_dsp(ctx);
22174 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22175 break;
22176 case OPC_SHRAV_R_W:
22177 check_dsp(ctx);
22178 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22179 break;
22180 default: /* Invalid */
22181 MIPS_INVAL("MASK SHLL.QB");
22182 gen_reserved_instruction(ctx);
22183 break;
22185 break;
22187 #ifdef TARGET_MIPS64
22188 case OPC_SHLL_OB_DSP:
22189 op2 = MASK_SHLL_OB(ctx->opcode);
22190 switch (op2) {
22191 case OPC_SHLL_PW:
22192 check_dsp(ctx);
22193 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22194 break;
22195 case OPC_SHLLV_PW:
22196 check_dsp(ctx);
22197 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22198 break;
22199 case OPC_SHLL_S_PW:
22200 check_dsp(ctx);
22201 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22202 break;
22203 case OPC_SHLLV_S_PW:
22204 check_dsp(ctx);
22205 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22206 break;
22207 case OPC_SHLL_OB:
22208 check_dsp(ctx);
22209 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22210 break;
22211 case OPC_SHLLV_OB:
22212 check_dsp(ctx);
22213 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22214 break;
22215 case OPC_SHLL_QH:
22216 check_dsp(ctx);
22217 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22218 break;
22219 case OPC_SHLLV_QH:
22220 check_dsp(ctx);
22221 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22222 break;
22223 case OPC_SHLL_S_QH:
22224 check_dsp(ctx);
22225 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22226 break;
22227 case OPC_SHLLV_S_QH:
22228 check_dsp(ctx);
22229 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22230 break;
22231 case OPC_SHRA_OB:
22232 check_dsp_r2(ctx);
22233 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22234 break;
22235 case OPC_SHRAV_OB:
22236 check_dsp_r2(ctx);
22237 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22238 break;
22239 case OPC_SHRA_R_OB:
22240 check_dsp_r2(ctx);
22241 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22242 break;
22243 case OPC_SHRAV_R_OB:
22244 check_dsp_r2(ctx);
22245 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22246 break;
22247 case OPC_SHRA_PW:
22248 check_dsp(ctx);
22249 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22250 break;
22251 case OPC_SHRAV_PW:
22252 check_dsp(ctx);
22253 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22254 break;
22255 case OPC_SHRA_R_PW:
22256 check_dsp(ctx);
22257 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22258 break;
22259 case OPC_SHRAV_R_PW:
22260 check_dsp(ctx);
22261 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22262 break;
22263 case OPC_SHRA_QH:
22264 check_dsp(ctx);
22265 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22266 break;
22267 case OPC_SHRAV_QH:
22268 check_dsp(ctx);
22269 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22270 break;
22271 case OPC_SHRA_R_QH:
22272 check_dsp(ctx);
22273 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22274 break;
22275 case OPC_SHRAV_R_QH:
22276 check_dsp(ctx);
22277 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22278 break;
22279 case OPC_SHRL_OB:
22280 check_dsp(ctx);
22281 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22282 break;
22283 case OPC_SHRLV_OB:
22284 check_dsp(ctx);
22285 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22286 break;
22287 case OPC_SHRL_QH:
22288 check_dsp_r2(ctx);
22289 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22290 break;
22291 case OPC_SHRLV_QH:
22292 check_dsp_r2(ctx);
22293 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22294 break;
22295 default: /* Invalid */
22296 MIPS_INVAL("MASK SHLL.OB");
22297 gen_reserved_instruction(ctx);
22298 break;
22300 break;
22301 #endif
22304 tcg_temp_free(t0);
22305 tcg_temp_free(v1_t);
22306 tcg_temp_free(v2_t);
22309 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22310 int ret, int v1, int v2, int check_ret)
22312 TCGv_i32 t0;
22313 TCGv v1_t;
22314 TCGv v2_t;
22316 if ((ret == 0) && (check_ret == 1)) {
22317 /* Treat as NOP. */
22318 return;
22321 t0 = tcg_temp_new_i32();
22322 v1_t = tcg_temp_new();
22323 v2_t = tcg_temp_new();
22325 tcg_gen_movi_i32(t0, ret);
22326 gen_load_gpr(v1_t, v1);
22327 gen_load_gpr(v2_t, v2);
22329 switch (op1) {
22331 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22332 * the same mask and op1.
22334 case OPC_MULT_G_2E:
22335 check_dsp_r2(ctx);
22336 switch (op2) {
22337 case OPC_MUL_PH:
22338 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22339 break;
22340 case OPC_MUL_S_PH:
22341 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22342 break;
22343 case OPC_MULQ_S_W:
22344 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22345 break;
22346 case OPC_MULQ_RS_W:
22347 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22348 break;
22350 break;
22351 case OPC_DPA_W_PH_DSP:
22352 switch (op2) {
22353 case OPC_DPAU_H_QBL:
22354 check_dsp(ctx);
22355 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22356 break;
22357 case OPC_DPAU_H_QBR:
22358 check_dsp(ctx);
22359 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22360 break;
22361 case OPC_DPSU_H_QBL:
22362 check_dsp(ctx);
22363 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22364 break;
22365 case OPC_DPSU_H_QBR:
22366 check_dsp(ctx);
22367 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22368 break;
22369 case OPC_DPA_W_PH:
22370 check_dsp_r2(ctx);
22371 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22372 break;
22373 case OPC_DPAX_W_PH:
22374 check_dsp_r2(ctx);
22375 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22376 break;
22377 case OPC_DPAQ_S_W_PH:
22378 check_dsp(ctx);
22379 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22380 break;
22381 case OPC_DPAQX_S_W_PH:
22382 check_dsp_r2(ctx);
22383 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22384 break;
22385 case OPC_DPAQX_SA_W_PH:
22386 check_dsp_r2(ctx);
22387 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22388 break;
22389 case OPC_DPS_W_PH:
22390 check_dsp_r2(ctx);
22391 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22392 break;
22393 case OPC_DPSX_W_PH:
22394 check_dsp_r2(ctx);
22395 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22396 break;
22397 case OPC_DPSQ_S_W_PH:
22398 check_dsp(ctx);
22399 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22400 break;
22401 case OPC_DPSQX_S_W_PH:
22402 check_dsp_r2(ctx);
22403 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22404 break;
22405 case OPC_DPSQX_SA_W_PH:
22406 check_dsp_r2(ctx);
22407 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22408 break;
22409 case OPC_MULSAQ_S_W_PH:
22410 check_dsp(ctx);
22411 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22412 break;
22413 case OPC_DPAQ_SA_L_W:
22414 check_dsp(ctx);
22415 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22416 break;
22417 case OPC_DPSQ_SA_L_W:
22418 check_dsp(ctx);
22419 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22420 break;
22421 case OPC_MAQ_S_W_PHL:
22422 check_dsp(ctx);
22423 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22424 break;
22425 case OPC_MAQ_S_W_PHR:
22426 check_dsp(ctx);
22427 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22428 break;
22429 case OPC_MAQ_SA_W_PHL:
22430 check_dsp(ctx);
22431 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22432 break;
22433 case OPC_MAQ_SA_W_PHR:
22434 check_dsp(ctx);
22435 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22436 break;
22437 case OPC_MULSA_W_PH:
22438 check_dsp_r2(ctx);
22439 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22440 break;
22442 break;
22443 #ifdef TARGET_MIPS64
22444 case OPC_DPAQ_W_QH_DSP:
22446 int ac = ret & 0x03;
22447 tcg_gen_movi_i32(t0, ac);
22449 switch (op2) {
22450 case OPC_DMADD:
22451 check_dsp(ctx);
22452 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22453 break;
22454 case OPC_DMADDU:
22455 check_dsp(ctx);
22456 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22457 break;
22458 case OPC_DMSUB:
22459 check_dsp(ctx);
22460 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22461 break;
22462 case OPC_DMSUBU:
22463 check_dsp(ctx);
22464 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22465 break;
22466 case OPC_DPA_W_QH:
22467 check_dsp_r2(ctx);
22468 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22469 break;
22470 case OPC_DPAQ_S_W_QH:
22471 check_dsp(ctx);
22472 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22473 break;
22474 case OPC_DPAQ_SA_L_PW:
22475 check_dsp(ctx);
22476 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22477 break;
22478 case OPC_DPAU_H_OBL:
22479 check_dsp(ctx);
22480 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22481 break;
22482 case OPC_DPAU_H_OBR:
22483 check_dsp(ctx);
22484 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22485 break;
22486 case OPC_DPS_W_QH:
22487 check_dsp_r2(ctx);
22488 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22489 break;
22490 case OPC_DPSQ_S_W_QH:
22491 check_dsp(ctx);
22492 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22493 break;
22494 case OPC_DPSQ_SA_L_PW:
22495 check_dsp(ctx);
22496 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22497 break;
22498 case OPC_DPSU_H_OBL:
22499 check_dsp(ctx);
22500 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22501 break;
22502 case OPC_DPSU_H_OBR:
22503 check_dsp(ctx);
22504 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22505 break;
22506 case OPC_MAQ_S_L_PWL:
22507 check_dsp(ctx);
22508 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22509 break;
22510 case OPC_MAQ_S_L_PWR:
22511 check_dsp(ctx);
22512 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22513 break;
22514 case OPC_MAQ_S_W_QHLL:
22515 check_dsp(ctx);
22516 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22517 break;
22518 case OPC_MAQ_SA_W_QHLL:
22519 check_dsp(ctx);
22520 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22521 break;
22522 case OPC_MAQ_S_W_QHLR:
22523 check_dsp(ctx);
22524 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22525 break;
22526 case OPC_MAQ_SA_W_QHLR:
22527 check_dsp(ctx);
22528 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22529 break;
22530 case OPC_MAQ_S_W_QHRL:
22531 check_dsp(ctx);
22532 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22533 break;
22534 case OPC_MAQ_SA_W_QHRL:
22535 check_dsp(ctx);
22536 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22537 break;
22538 case OPC_MAQ_S_W_QHRR:
22539 check_dsp(ctx);
22540 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22541 break;
22542 case OPC_MAQ_SA_W_QHRR:
22543 check_dsp(ctx);
22544 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22545 break;
22546 case OPC_MULSAQ_S_L_PW:
22547 check_dsp(ctx);
22548 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22549 break;
22550 case OPC_MULSAQ_S_W_QH:
22551 check_dsp(ctx);
22552 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22553 break;
22556 break;
22557 #endif
22558 case OPC_ADDU_QB_DSP:
22559 switch (op2) {
22560 case OPC_MULEU_S_PH_QBL:
22561 check_dsp(ctx);
22562 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22563 break;
22564 case OPC_MULEU_S_PH_QBR:
22565 check_dsp(ctx);
22566 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22567 break;
22568 case OPC_MULQ_RS_PH:
22569 check_dsp(ctx);
22570 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22571 break;
22572 case OPC_MULEQ_S_W_PHL:
22573 check_dsp(ctx);
22574 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22575 break;
22576 case OPC_MULEQ_S_W_PHR:
22577 check_dsp(ctx);
22578 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22579 break;
22580 case OPC_MULQ_S_PH:
22581 check_dsp_r2(ctx);
22582 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22583 break;
22585 break;
22586 #ifdef TARGET_MIPS64
22587 case OPC_ADDU_OB_DSP:
22588 switch (op2) {
22589 case OPC_MULEQ_S_PW_QHL:
22590 check_dsp(ctx);
22591 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22592 break;
22593 case OPC_MULEQ_S_PW_QHR:
22594 check_dsp(ctx);
22595 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22596 break;
22597 case OPC_MULEU_S_QH_OBL:
22598 check_dsp(ctx);
22599 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22600 break;
22601 case OPC_MULEU_S_QH_OBR:
22602 check_dsp(ctx);
22603 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22604 break;
22605 case OPC_MULQ_RS_QH:
22606 check_dsp(ctx);
22607 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22608 break;
22610 break;
22611 #endif
22614 tcg_temp_free_i32(t0);
22615 tcg_temp_free(v1_t);
22616 tcg_temp_free(v2_t);
22619 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22620 int ret, int val)
22622 int16_t imm;
22623 TCGv t0;
22624 TCGv val_t;
22626 if (ret == 0) {
22627 /* Treat as NOP. */
22628 return;
22631 t0 = tcg_temp_new();
22632 val_t = tcg_temp_new();
22633 gen_load_gpr(val_t, val);
22635 switch (op1) {
22636 case OPC_ABSQ_S_PH_DSP:
22637 switch (op2) {
22638 case OPC_BITREV:
22639 check_dsp(ctx);
22640 gen_helper_bitrev(cpu_gpr[ret], val_t);
22641 break;
22642 case OPC_REPL_QB:
22643 check_dsp(ctx);
22645 target_long result;
22646 imm = (ctx->opcode >> 16) & 0xFF;
22647 result = (uint32_t)imm << 24 |
22648 (uint32_t)imm << 16 |
22649 (uint32_t)imm << 8 |
22650 (uint32_t)imm;
22651 result = (int32_t)result;
22652 tcg_gen_movi_tl(cpu_gpr[ret], result);
22654 break;
22655 case OPC_REPLV_QB:
22656 check_dsp(ctx);
22657 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22658 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22659 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22660 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22661 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22662 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22663 break;
22664 case OPC_REPL_PH:
22665 check_dsp(ctx);
22667 imm = (ctx->opcode >> 16) & 0x03FF;
22668 imm = (int16_t)(imm << 6) >> 6;
22669 tcg_gen_movi_tl(cpu_gpr[ret], \
22670 (target_long)((int32_t)imm << 16 | \
22671 (uint16_t)imm));
22673 break;
22674 case OPC_REPLV_PH:
22675 check_dsp(ctx);
22676 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22677 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22678 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22679 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22680 break;
22682 break;
22683 #ifdef TARGET_MIPS64
22684 case OPC_ABSQ_S_QH_DSP:
22685 switch (op2) {
22686 case OPC_REPL_OB:
22687 check_dsp(ctx);
22689 target_long temp;
22691 imm = (ctx->opcode >> 16) & 0xFF;
22692 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
22693 temp = (temp << 16) | temp;
22694 temp = (temp << 32) | temp;
22695 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22696 break;
22698 case OPC_REPL_PW:
22699 check_dsp(ctx);
22701 target_long temp;
22703 imm = (ctx->opcode >> 16) & 0x03FF;
22704 imm = (int16_t)(imm << 6) >> 6;
22705 temp = ((target_long)imm << 32) \
22706 | ((target_long)imm & 0xFFFFFFFF);
22707 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22708 break;
22710 case OPC_REPL_QH:
22711 check_dsp(ctx);
22713 target_long temp;
22715 imm = (ctx->opcode >> 16) & 0x03FF;
22716 imm = (int16_t)(imm << 6) >> 6;
22718 temp = ((uint64_t)(uint16_t)imm << 48) |
22719 ((uint64_t)(uint16_t)imm << 32) |
22720 ((uint64_t)(uint16_t)imm << 16) |
22721 (uint64_t)(uint16_t)imm;
22722 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22723 break;
22725 case OPC_REPLV_OB:
22726 check_dsp(ctx);
22727 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22728 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22729 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22730 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22731 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22732 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22733 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22734 break;
22735 case OPC_REPLV_PW:
22736 check_dsp(ctx);
22737 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
22738 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22739 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22740 break;
22741 case OPC_REPLV_QH:
22742 check_dsp(ctx);
22743 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22744 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22745 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22746 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22747 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22748 break;
22750 break;
22751 #endif
22753 tcg_temp_free(t0);
22754 tcg_temp_free(val_t);
22757 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
22758 uint32_t op1, uint32_t op2,
22759 int ret, int v1, int v2, int check_ret)
22761 TCGv t1;
22762 TCGv v1_t;
22763 TCGv v2_t;
22765 if ((ret == 0) && (check_ret == 1)) {
22766 /* Treat as NOP. */
22767 return;
22770 t1 = tcg_temp_new();
22771 v1_t = tcg_temp_new();
22772 v2_t = tcg_temp_new();
22774 gen_load_gpr(v1_t, v1);
22775 gen_load_gpr(v2_t, v2);
22777 switch (op1) {
22778 case OPC_CMPU_EQ_QB_DSP:
22779 switch (op2) {
22780 case OPC_CMPU_EQ_QB:
22781 check_dsp(ctx);
22782 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
22783 break;
22784 case OPC_CMPU_LT_QB:
22785 check_dsp(ctx);
22786 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
22787 break;
22788 case OPC_CMPU_LE_QB:
22789 check_dsp(ctx);
22790 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
22791 break;
22792 case OPC_CMPGU_EQ_QB:
22793 check_dsp(ctx);
22794 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
22795 break;
22796 case OPC_CMPGU_LT_QB:
22797 check_dsp(ctx);
22798 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
22799 break;
22800 case OPC_CMPGU_LE_QB:
22801 check_dsp(ctx);
22802 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
22803 break;
22804 case OPC_CMPGDU_EQ_QB:
22805 check_dsp_r2(ctx);
22806 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
22807 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22808 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22809 tcg_gen_shli_tl(t1, t1, 24);
22810 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22811 break;
22812 case OPC_CMPGDU_LT_QB:
22813 check_dsp_r2(ctx);
22814 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
22815 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22816 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22817 tcg_gen_shli_tl(t1, t1, 24);
22818 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22819 break;
22820 case OPC_CMPGDU_LE_QB:
22821 check_dsp_r2(ctx);
22822 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
22823 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22824 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22825 tcg_gen_shli_tl(t1, t1, 24);
22826 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22827 break;
22828 case OPC_CMP_EQ_PH:
22829 check_dsp(ctx);
22830 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
22831 break;
22832 case OPC_CMP_LT_PH:
22833 check_dsp(ctx);
22834 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
22835 break;
22836 case OPC_CMP_LE_PH:
22837 check_dsp(ctx);
22838 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
22839 break;
22840 case OPC_PICK_QB:
22841 check_dsp(ctx);
22842 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22843 break;
22844 case OPC_PICK_PH:
22845 check_dsp(ctx);
22846 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22847 break;
22848 case OPC_PACKRL_PH:
22849 check_dsp(ctx);
22850 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
22851 break;
22853 break;
22854 #ifdef TARGET_MIPS64
22855 case OPC_CMPU_EQ_OB_DSP:
22856 switch (op2) {
22857 case OPC_CMP_EQ_PW:
22858 check_dsp(ctx);
22859 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
22860 break;
22861 case OPC_CMP_LT_PW:
22862 check_dsp(ctx);
22863 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
22864 break;
22865 case OPC_CMP_LE_PW:
22866 check_dsp(ctx);
22867 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
22868 break;
22869 case OPC_CMP_EQ_QH:
22870 check_dsp(ctx);
22871 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
22872 break;
22873 case OPC_CMP_LT_QH:
22874 check_dsp(ctx);
22875 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
22876 break;
22877 case OPC_CMP_LE_QH:
22878 check_dsp(ctx);
22879 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
22880 break;
22881 case OPC_CMPGDU_EQ_OB:
22882 check_dsp_r2(ctx);
22883 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22884 break;
22885 case OPC_CMPGDU_LT_OB:
22886 check_dsp_r2(ctx);
22887 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22888 break;
22889 case OPC_CMPGDU_LE_OB:
22890 check_dsp_r2(ctx);
22891 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22892 break;
22893 case OPC_CMPGU_EQ_OB:
22894 check_dsp(ctx);
22895 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
22896 break;
22897 case OPC_CMPGU_LT_OB:
22898 check_dsp(ctx);
22899 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
22900 break;
22901 case OPC_CMPGU_LE_OB:
22902 check_dsp(ctx);
22903 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
22904 break;
22905 case OPC_CMPU_EQ_OB:
22906 check_dsp(ctx);
22907 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
22908 break;
22909 case OPC_CMPU_LT_OB:
22910 check_dsp(ctx);
22911 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
22912 break;
22913 case OPC_CMPU_LE_OB:
22914 check_dsp(ctx);
22915 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
22916 break;
22917 case OPC_PACKRL_PW:
22918 check_dsp(ctx);
22919 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
22920 break;
22921 case OPC_PICK_OB:
22922 check_dsp(ctx);
22923 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22924 break;
22925 case OPC_PICK_PW:
22926 check_dsp(ctx);
22927 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22928 break;
22929 case OPC_PICK_QH:
22930 check_dsp(ctx);
22931 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22932 break;
22934 break;
22935 #endif
22938 tcg_temp_free(t1);
22939 tcg_temp_free(v1_t);
22940 tcg_temp_free(v2_t);
22943 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
22944 uint32_t op1, int rt, int rs, int sa)
22946 TCGv t0;
22948 check_dsp_r2(ctx);
22950 if (rt == 0) {
22951 /* Treat as NOP. */
22952 return;
22955 t0 = tcg_temp_new();
22956 gen_load_gpr(t0, rs);
22958 switch (op1) {
22959 case OPC_APPEND_DSP:
22960 switch (MASK_APPEND(ctx->opcode)) {
22961 case OPC_APPEND:
22962 if (sa != 0) {
22963 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
22965 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22966 break;
22967 case OPC_PREPEND:
22968 if (sa != 0) {
22969 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
22970 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22971 tcg_gen_shli_tl(t0, t0, 32 - sa);
22972 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22974 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22975 break;
22976 case OPC_BALIGN:
22977 sa &= 3;
22978 if (sa != 0 && sa != 2) {
22979 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22980 tcg_gen_ext32u_tl(t0, t0);
22981 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
22982 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22984 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22985 break;
22986 default: /* Invalid */
22987 MIPS_INVAL("MASK APPEND");
22988 gen_reserved_instruction(ctx);
22989 break;
22991 break;
22992 #ifdef TARGET_MIPS64
22993 case OPC_DAPPEND_DSP:
22994 switch (MASK_DAPPEND(ctx->opcode)) {
22995 case OPC_DAPPEND:
22996 if (sa != 0) {
22997 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
22999 break;
23000 case OPC_PREPENDD:
23001 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23002 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23003 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23004 break;
23005 case OPC_PREPENDW:
23006 if (sa != 0) {
23007 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23008 tcg_gen_shli_tl(t0, t0, 64 - sa);
23009 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23011 break;
23012 case OPC_DBALIGN:
23013 sa &= 7;
23014 if (sa != 0 && sa != 2 && sa != 4) {
23015 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23016 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23017 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23019 break;
23020 default: /* Invalid */
23021 MIPS_INVAL("MASK DAPPEND");
23022 gen_reserved_instruction(ctx);
23023 break;
23025 break;
23026 #endif
23028 tcg_temp_free(t0);
23031 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23032 int ret, int v1, int v2, int check_ret)
23035 TCGv t0;
23036 TCGv t1;
23037 TCGv v1_t;
23038 TCGv v2_t;
23039 int16_t imm;
23041 if ((ret == 0) && (check_ret == 1)) {
23042 /* Treat as NOP. */
23043 return;
23046 t0 = tcg_temp_new();
23047 t1 = tcg_temp_new();
23048 v1_t = tcg_temp_new();
23049 v2_t = tcg_temp_new();
23051 gen_load_gpr(v1_t, v1);
23052 gen_load_gpr(v2_t, v2);
23054 switch (op1) {
23055 case OPC_EXTR_W_DSP:
23056 check_dsp(ctx);
23057 switch (op2) {
23058 case OPC_EXTR_W:
23059 tcg_gen_movi_tl(t0, v2);
23060 tcg_gen_movi_tl(t1, v1);
23061 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23062 break;
23063 case OPC_EXTR_R_W:
23064 tcg_gen_movi_tl(t0, v2);
23065 tcg_gen_movi_tl(t1, v1);
23066 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23067 break;
23068 case OPC_EXTR_RS_W:
23069 tcg_gen_movi_tl(t0, v2);
23070 tcg_gen_movi_tl(t1, v1);
23071 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23072 break;
23073 case OPC_EXTR_S_H:
23074 tcg_gen_movi_tl(t0, v2);
23075 tcg_gen_movi_tl(t1, v1);
23076 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23077 break;
23078 case OPC_EXTRV_S_H:
23079 tcg_gen_movi_tl(t0, v2);
23080 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23081 break;
23082 case OPC_EXTRV_W:
23083 tcg_gen_movi_tl(t0, v2);
23084 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23085 break;
23086 case OPC_EXTRV_R_W:
23087 tcg_gen_movi_tl(t0, v2);
23088 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23089 break;
23090 case OPC_EXTRV_RS_W:
23091 tcg_gen_movi_tl(t0, v2);
23092 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23093 break;
23094 case OPC_EXTP:
23095 tcg_gen_movi_tl(t0, v2);
23096 tcg_gen_movi_tl(t1, v1);
23097 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23098 break;
23099 case OPC_EXTPV:
23100 tcg_gen_movi_tl(t0, v2);
23101 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23102 break;
23103 case OPC_EXTPDP:
23104 tcg_gen_movi_tl(t0, v2);
23105 tcg_gen_movi_tl(t1, v1);
23106 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23107 break;
23108 case OPC_EXTPDPV:
23109 tcg_gen_movi_tl(t0, v2);
23110 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23111 break;
23112 case OPC_SHILO:
23113 imm = (ctx->opcode >> 20) & 0x3F;
23114 tcg_gen_movi_tl(t0, ret);
23115 tcg_gen_movi_tl(t1, imm);
23116 gen_helper_shilo(t0, t1, cpu_env);
23117 break;
23118 case OPC_SHILOV:
23119 tcg_gen_movi_tl(t0, ret);
23120 gen_helper_shilo(t0, v1_t, cpu_env);
23121 break;
23122 case OPC_MTHLIP:
23123 tcg_gen_movi_tl(t0, ret);
23124 gen_helper_mthlip(t0, v1_t, cpu_env);
23125 break;
23126 case OPC_WRDSP:
23127 imm = (ctx->opcode >> 11) & 0x3FF;
23128 tcg_gen_movi_tl(t0, imm);
23129 gen_helper_wrdsp(v1_t, t0, cpu_env);
23130 break;
23131 case OPC_RDDSP:
23132 imm = (ctx->opcode >> 16) & 0x03FF;
23133 tcg_gen_movi_tl(t0, imm);
23134 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23135 break;
23137 break;
23138 #ifdef TARGET_MIPS64
23139 case OPC_DEXTR_W_DSP:
23140 check_dsp(ctx);
23141 switch (op2) {
23142 case OPC_DMTHLIP:
23143 tcg_gen_movi_tl(t0, ret);
23144 gen_helper_dmthlip(v1_t, t0, cpu_env);
23145 break;
23146 case OPC_DSHILO:
23148 int shift = (ctx->opcode >> 19) & 0x7F;
23149 int ac = (ctx->opcode >> 11) & 0x03;
23150 tcg_gen_movi_tl(t0, shift);
23151 tcg_gen_movi_tl(t1, ac);
23152 gen_helper_dshilo(t0, t1, cpu_env);
23153 break;
23155 case OPC_DSHILOV:
23157 int ac = (ctx->opcode >> 11) & 0x03;
23158 tcg_gen_movi_tl(t0, ac);
23159 gen_helper_dshilo(v1_t, t0, cpu_env);
23160 break;
23162 case OPC_DEXTP:
23163 tcg_gen_movi_tl(t0, v2);
23164 tcg_gen_movi_tl(t1, v1);
23166 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23167 break;
23168 case OPC_DEXTPV:
23169 tcg_gen_movi_tl(t0, v2);
23170 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23171 break;
23172 case OPC_DEXTPDP:
23173 tcg_gen_movi_tl(t0, v2);
23174 tcg_gen_movi_tl(t1, v1);
23175 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23176 break;
23177 case OPC_DEXTPDPV:
23178 tcg_gen_movi_tl(t0, v2);
23179 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23180 break;
23181 case OPC_DEXTR_L:
23182 tcg_gen_movi_tl(t0, v2);
23183 tcg_gen_movi_tl(t1, v1);
23184 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23185 break;
23186 case OPC_DEXTR_R_L:
23187 tcg_gen_movi_tl(t0, v2);
23188 tcg_gen_movi_tl(t1, v1);
23189 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23190 break;
23191 case OPC_DEXTR_RS_L:
23192 tcg_gen_movi_tl(t0, v2);
23193 tcg_gen_movi_tl(t1, v1);
23194 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23195 break;
23196 case OPC_DEXTR_W:
23197 tcg_gen_movi_tl(t0, v2);
23198 tcg_gen_movi_tl(t1, v1);
23199 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23200 break;
23201 case OPC_DEXTR_R_W:
23202 tcg_gen_movi_tl(t0, v2);
23203 tcg_gen_movi_tl(t1, v1);
23204 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23205 break;
23206 case OPC_DEXTR_RS_W:
23207 tcg_gen_movi_tl(t0, v2);
23208 tcg_gen_movi_tl(t1, v1);
23209 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23210 break;
23211 case OPC_DEXTR_S_H:
23212 tcg_gen_movi_tl(t0, v2);
23213 tcg_gen_movi_tl(t1, v1);
23214 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23215 break;
23216 case OPC_DEXTRV_S_H:
23217 tcg_gen_movi_tl(t0, v2);
23218 tcg_gen_movi_tl(t1, v1);
23219 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23220 break;
23221 case OPC_DEXTRV_L:
23222 tcg_gen_movi_tl(t0, v2);
23223 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23224 break;
23225 case OPC_DEXTRV_R_L:
23226 tcg_gen_movi_tl(t0, v2);
23227 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23228 break;
23229 case OPC_DEXTRV_RS_L:
23230 tcg_gen_movi_tl(t0, v2);
23231 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23232 break;
23233 case OPC_DEXTRV_W:
23234 tcg_gen_movi_tl(t0, v2);
23235 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23236 break;
23237 case OPC_DEXTRV_R_W:
23238 tcg_gen_movi_tl(t0, v2);
23239 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23240 break;
23241 case OPC_DEXTRV_RS_W:
23242 tcg_gen_movi_tl(t0, v2);
23243 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23244 break;
23246 break;
23247 #endif
23250 tcg_temp_free(t0);
23251 tcg_temp_free(t1);
23252 tcg_temp_free(v1_t);
23253 tcg_temp_free(v2_t);
23256 /* End MIPSDSP functions. */
23258 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23260 int rs, rt, rd, sa;
23261 uint32_t op1, op2;
23263 rs = (ctx->opcode >> 21) & 0x1f;
23264 rt = (ctx->opcode >> 16) & 0x1f;
23265 rd = (ctx->opcode >> 11) & 0x1f;
23266 sa = (ctx->opcode >> 6) & 0x1f;
23268 op1 = MASK_SPECIAL(ctx->opcode);
23269 switch (op1) {
23270 case OPC_MULT:
23271 case OPC_MULTU:
23272 case OPC_DIV:
23273 case OPC_DIVU:
23274 op2 = MASK_R6_MULDIV(ctx->opcode);
23275 switch (op2) {
23276 case R6_OPC_MUL:
23277 case R6_OPC_MUH:
23278 case R6_OPC_MULU:
23279 case R6_OPC_MUHU:
23280 case R6_OPC_DIV:
23281 case R6_OPC_MOD:
23282 case R6_OPC_DIVU:
23283 case R6_OPC_MODU:
23284 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23285 break;
23286 default:
23287 MIPS_INVAL("special_r6 muldiv");
23288 gen_reserved_instruction(ctx);
23289 break;
23291 break;
23292 case OPC_SELEQZ:
23293 case OPC_SELNEZ:
23294 gen_cond_move(ctx, op1, rd, rs, rt);
23295 break;
23296 case R6_OPC_CLO:
23297 case R6_OPC_CLZ:
23298 if (rt == 0 && sa == 1) {
23300 * Major opcode and function field is shared with preR6 MFHI/MTHI.
23301 * We need additionally to check other fields.
23303 gen_cl(ctx, op1, rd, rs);
23304 } else {
23305 gen_reserved_instruction(ctx);
23307 break;
23308 case R6_OPC_SDBBP:
23309 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23310 gen_helper_do_semihosting(cpu_env);
23311 } else {
23312 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23313 gen_reserved_instruction(ctx);
23314 } else {
23315 generate_exception_end(ctx, EXCP_DBp);
23318 break;
23319 #if defined(TARGET_MIPS64)
23320 case R6_OPC_DCLO:
23321 case R6_OPC_DCLZ:
23322 if (rt == 0 && sa == 1) {
23324 * Major opcode and function field is shared with preR6 MFHI/MTHI.
23325 * We need additionally to check other fields.
23327 check_mips_64(ctx);
23328 gen_cl(ctx, op1, rd, rs);
23329 } else {
23330 gen_reserved_instruction(ctx);
23332 break;
23333 case OPC_DMULT:
23334 case OPC_DMULTU:
23335 case OPC_DDIV:
23336 case OPC_DDIVU:
23338 op2 = MASK_R6_MULDIV(ctx->opcode);
23339 switch (op2) {
23340 case R6_OPC_DMUL:
23341 case R6_OPC_DMUH:
23342 case R6_OPC_DMULU:
23343 case R6_OPC_DMUHU:
23344 case R6_OPC_DDIV:
23345 case R6_OPC_DMOD:
23346 case R6_OPC_DDIVU:
23347 case R6_OPC_DMODU:
23348 check_mips_64(ctx);
23349 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23350 break;
23351 default:
23352 MIPS_INVAL("special_r6 muldiv");
23353 gen_reserved_instruction(ctx);
23354 break;
23356 break;
23357 #endif
23358 default: /* Invalid */
23359 MIPS_INVAL("special_r6");
23360 gen_reserved_instruction(ctx);
23361 break;
23365 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
23367 int rs = extract32(ctx->opcode, 21, 5);
23368 int rt = extract32(ctx->opcode, 16, 5);
23369 int rd = extract32(ctx->opcode, 11, 5);
23370 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
23372 switch (op1) {
23373 case OPC_MOVN: /* Conditional move */
23374 case OPC_MOVZ:
23375 gen_cond_move(ctx, op1, rd, rs, rt);
23376 break;
23377 case OPC_MFHI: /* Move from HI/LO */
23378 case OPC_MFLO:
23379 gen_HILO(ctx, op1, 0, rd);
23380 break;
23381 case OPC_MTHI:
23382 case OPC_MTLO: /* Move to HI/LO */
23383 gen_HILO(ctx, op1, 0, rs);
23384 break;
23385 case OPC_MULT:
23386 case OPC_MULTU:
23387 gen_mul_txx9(ctx, op1, rd, rs, rt);
23388 break;
23389 case OPC_DIV:
23390 case OPC_DIVU:
23391 gen_muldiv(ctx, op1, 0, rs, rt);
23392 break;
23393 #if defined(TARGET_MIPS64)
23394 case OPC_DMULT:
23395 case OPC_DMULTU:
23396 case OPC_DDIV:
23397 case OPC_DDIVU:
23398 check_insn_opc_user_only(ctx, INSN_R5900);
23399 gen_muldiv(ctx, op1, 0, rs, rt);
23400 break;
23401 #endif
23402 case OPC_JR:
23403 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
23404 break;
23405 default: /* Invalid */
23406 MIPS_INVAL("special_tx79");
23407 gen_reserved_instruction(ctx);
23408 break;
23412 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23414 int rs, rt, rd, sa;
23415 uint32_t op1;
23417 rs = (ctx->opcode >> 21) & 0x1f;
23418 rt = (ctx->opcode >> 16) & 0x1f;
23419 rd = (ctx->opcode >> 11) & 0x1f;
23420 sa = (ctx->opcode >> 6) & 0x1f;
23422 op1 = MASK_SPECIAL(ctx->opcode);
23423 switch (op1) {
23424 case OPC_MOVN: /* Conditional move */
23425 case OPC_MOVZ:
23426 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
23427 INSN_LOONGSON2E | INSN_LOONGSON2F);
23428 gen_cond_move(ctx, op1, rd, rs, rt);
23429 break;
23430 case OPC_MFHI: /* Move from HI/LO */
23431 case OPC_MFLO:
23432 gen_HILO(ctx, op1, rs & 3, rd);
23433 break;
23434 case OPC_MTHI:
23435 case OPC_MTLO: /* Move to HI/LO */
23436 gen_HILO(ctx, op1, rd & 3, rs);
23437 break;
23438 case OPC_MOVCI:
23439 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
23440 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23441 check_cp1_enabled(ctx);
23442 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23443 (ctx->opcode >> 16) & 1);
23444 } else {
23445 generate_exception_err(ctx, EXCP_CpU, 1);
23447 break;
23448 case OPC_MULT:
23449 case OPC_MULTU:
23450 if (sa) {
23451 check_insn(ctx, INSN_VR54XX);
23452 op1 = MASK_MUL_VR54XX(ctx->opcode);
23453 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23454 } else {
23455 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23457 break;
23458 case OPC_DIV:
23459 case OPC_DIVU:
23460 gen_muldiv(ctx, op1, 0, rs, rt);
23461 break;
23462 #if defined(TARGET_MIPS64)
23463 case OPC_DMULT:
23464 case OPC_DMULTU:
23465 case OPC_DDIV:
23466 case OPC_DDIVU:
23467 check_insn(ctx, ISA_MIPS3);
23468 check_mips_64(ctx);
23469 gen_muldiv(ctx, op1, 0, rs, rt);
23470 break;
23471 #endif
23472 case OPC_JR:
23473 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23474 break;
23475 case OPC_SPIM:
23476 #ifdef MIPS_STRICT_STANDARD
23477 MIPS_INVAL("SPIM");
23478 gen_reserved_instruction(ctx);
23479 #else
23480 /* Implemented as RI exception for now. */
23481 MIPS_INVAL("spim (unofficial)");
23482 gen_reserved_instruction(ctx);
23483 #endif
23484 break;
23485 default: /* Invalid */
23486 MIPS_INVAL("special_legacy");
23487 gen_reserved_instruction(ctx);
23488 break;
23492 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23494 int rs, rt, rd, sa;
23495 uint32_t op1;
23497 rs = (ctx->opcode >> 21) & 0x1f;
23498 rt = (ctx->opcode >> 16) & 0x1f;
23499 rd = (ctx->opcode >> 11) & 0x1f;
23500 sa = (ctx->opcode >> 6) & 0x1f;
23502 op1 = MASK_SPECIAL(ctx->opcode);
23503 switch (op1) {
23504 case OPC_SLL: /* Shift with immediate */
23505 if (sa == 5 && rd == 0 &&
23506 rs == 0 && rt == 0) { /* PAUSE */
23507 if ((ctx->insn_flags & ISA_MIPS_R6) &&
23508 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23509 gen_reserved_instruction(ctx);
23510 break;
23513 /* Fallthrough */
23514 case OPC_SRA:
23515 gen_shift_imm(ctx, op1, rd, rt, sa);
23516 break;
23517 case OPC_SRL:
23518 switch ((ctx->opcode >> 21) & 0x1f) {
23519 case 1:
23520 /* rotr is decoded as srl on non-R2 CPUs */
23521 if (ctx->insn_flags & ISA_MIPS_R2) {
23522 op1 = OPC_ROTR;
23524 /* Fallthrough */
23525 case 0:
23526 gen_shift_imm(ctx, op1, rd, rt, sa);
23527 break;
23528 default:
23529 gen_reserved_instruction(ctx);
23530 break;
23532 break;
23533 case OPC_ADD:
23534 case OPC_ADDU:
23535 case OPC_SUB:
23536 case OPC_SUBU:
23537 gen_arith(ctx, op1, rd, rs, rt);
23538 break;
23539 case OPC_SLLV: /* Shifts */
23540 case OPC_SRAV:
23541 gen_shift(ctx, op1, rd, rs, rt);
23542 break;
23543 case OPC_SRLV:
23544 switch ((ctx->opcode >> 6) & 0x1f) {
23545 case 1:
23546 /* rotrv is decoded as srlv on non-R2 CPUs */
23547 if (ctx->insn_flags & ISA_MIPS_R2) {
23548 op1 = OPC_ROTRV;
23550 /* Fallthrough */
23551 case 0:
23552 gen_shift(ctx, op1, rd, rs, rt);
23553 break;
23554 default:
23555 gen_reserved_instruction(ctx);
23556 break;
23558 break;
23559 case OPC_SLT: /* Set on less than */
23560 case OPC_SLTU:
23561 gen_slt(ctx, op1, rd, rs, rt);
23562 break;
23563 case OPC_AND: /* Logic*/
23564 case OPC_OR:
23565 case OPC_NOR:
23566 case OPC_XOR:
23567 gen_logic(ctx, op1, rd, rs, rt);
23568 break;
23569 case OPC_JALR:
23570 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23571 break;
23572 case OPC_TGE: /* Traps */
23573 case OPC_TGEU:
23574 case OPC_TLT:
23575 case OPC_TLTU:
23576 case OPC_TEQ:
23577 case OPC_TNE:
23578 check_insn(ctx, ISA_MIPS2);
23579 gen_trap(ctx, op1, rs, rt, -1);
23580 break;
23581 case OPC_PMON:
23582 /* Pmon entry point, also R4010 selsl */
23583 #ifdef MIPS_STRICT_STANDARD
23584 MIPS_INVAL("PMON / selsl");
23585 gen_reserved_instruction(ctx);
23586 #else
23587 gen_helper_0e0i(pmon, sa);
23588 #endif
23589 break;
23590 case OPC_SYSCALL:
23591 generate_exception_end(ctx, EXCP_SYSCALL);
23592 break;
23593 case OPC_BREAK:
23594 generate_exception_end(ctx, EXCP_BREAK);
23595 break;
23596 case OPC_SYNC:
23597 check_insn(ctx, ISA_MIPS2);
23598 gen_sync(extract32(ctx->opcode, 6, 5));
23599 break;
23601 #if defined(TARGET_MIPS64)
23602 /* MIPS64 specific opcodes */
23603 case OPC_DSLL:
23604 case OPC_DSRA:
23605 case OPC_DSLL32:
23606 case OPC_DSRA32:
23607 check_insn(ctx, ISA_MIPS3);
23608 check_mips_64(ctx);
23609 gen_shift_imm(ctx, op1, rd, rt, sa);
23610 break;
23611 case OPC_DSRL:
23612 switch ((ctx->opcode >> 21) & 0x1f) {
23613 case 1:
23614 /* drotr is decoded as dsrl on non-R2 CPUs */
23615 if (ctx->insn_flags & ISA_MIPS_R2) {
23616 op1 = OPC_DROTR;
23618 /* Fallthrough */
23619 case 0:
23620 check_insn(ctx, ISA_MIPS3);
23621 check_mips_64(ctx);
23622 gen_shift_imm(ctx, op1, rd, rt, sa);
23623 break;
23624 default:
23625 gen_reserved_instruction(ctx);
23626 break;
23628 break;
23629 case OPC_DSRL32:
23630 switch ((ctx->opcode >> 21) & 0x1f) {
23631 case 1:
23632 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23633 if (ctx->insn_flags & ISA_MIPS_R2) {
23634 op1 = OPC_DROTR32;
23636 /* Fallthrough */
23637 case 0:
23638 check_insn(ctx, ISA_MIPS3);
23639 check_mips_64(ctx);
23640 gen_shift_imm(ctx, op1, rd, rt, sa);
23641 break;
23642 default:
23643 gen_reserved_instruction(ctx);
23644 break;
23646 break;
23647 case OPC_DADD:
23648 case OPC_DADDU:
23649 case OPC_DSUB:
23650 case OPC_DSUBU:
23651 check_insn(ctx, ISA_MIPS3);
23652 check_mips_64(ctx);
23653 gen_arith(ctx, op1, rd, rs, rt);
23654 break;
23655 case OPC_DSLLV:
23656 case OPC_DSRAV:
23657 check_insn(ctx, ISA_MIPS3);
23658 check_mips_64(ctx);
23659 gen_shift(ctx, op1, rd, rs, rt);
23660 break;
23661 case OPC_DSRLV:
23662 switch ((ctx->opcode >> 6) & 0x1f) {
23663 case 1:
23664 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23665 if (ctx->insn_flags & ISA_MIPS_R2) {
23666 op1 = OPC_DROTRV;
23668 /* Fallthrough */
23669 case 0:
23670 check_insn(ctx, ISA_MIPS3);
23671 check_mips_64(ctx);
23672 gen_shift(ctx, op1, rd, rs, rt);
23673 break;
23674 default:
23675 gen_reserved_instruction(ctx);
23676 break;
23678 break;
23679 #endif
23680 default:
23681 if (ctx->insn_flags & ISA_MIPS_R6) {
23682 decode_opc_special_r6(env, ctx);
23683 } else if (ctx->insn_flags & INSN_R5900) {
23684 decode_opc_special_tx79(env, ctx);
23685 } else {
23686 decode_opc_special_legacy(env, ctx);
23692 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
23694 int rs, rt, rd;
23695 uint32_t op1;
23697 rs = (ctx->opcode >> 21) & 0x1f;
23698 rt = (ctx->opcode >> 16) & 0x1f;
23699 rd = (ctx->opcode >> 11) & 0x1f;
23701 op1 = MASK_SPECIAL2(ctx->opcode);
23702 switch (op1) {
23703 case OPC_MADD: /* Multiply and add/sub */
23704 case OPC_MADDU:
23705 case OPC_MSUB:
23706 case OPC_MSUBU:
23707 check_insn(ctx, ISA_MIPS_R1);
23708 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23709 break;
23710 case OPC_MUL:
23711 gen_arith(ctx, op1, rd, rs, rt);
23712 break;
23713 case OPC_DIV_G_2F:
23714 case OPC_DIVU_G_2F:
23715 case OPC_MULT_G_2F:
23716 case OPC_MULTU_G_2F:
23717 case OPC_MOD_G_2F:
23718 case OPC_MODU_G_2F:
23719 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
23720 gen_loongson_integer(ctx, op1, rd, rs, rt);
23721 break;
23722 case OPC_CLO:
23723 case OPC_CLZ:
23724 check_insn(ctx, ISA_MIPS_R1);
23725 gen_cl(ctx, op1, rd, rs);
23726 break;
23727 case OPC_SDBBP:
23728 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23729 gen_helper_do_semihosting(cpu_env);
23730 } else {
23732 * XXX: not clear which exception should be raised
23733 * when in debug mode...
23735 check_insn(ctx, ISA_MIPS_R1);
23736 generate_exception_end(ctx, EXCP_DBp);
23738 break;
23739 #if defined(TARGET_MIPS64)
23740 case OPC_DCLO:
23741 case OPC_DCLZ:
23742 check_insn(ctx, ISA_MIPS_R1);
23743 check_mips_64(ctx);
23744 gen_cl(ctx, op1, rd, rs);
23745 break;
23746 case OPC_DMULT_G_2F:
23747 case OPC_DMULTU_G_2F:
23748 case OPC_DDIV_G_2F:
23749 case OPC_DDIVU_G_2F:
23750 case OPC_DMOD_G_2F:
23751 case OPC_DMODU_G_2F:
23752 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
23753 gen_loongson_integer(ctx, op1, rd, rs, rt);
23754 break;
23755 #endif
23756 default: /* Invalid */
23757 MIPS_INVAL("special2_legacy");
23758 gen_reserved_instruction(ctx);
23759 break;
23763 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
23765 int rs, rt, rd, sa;
23766 uint32_t op1, op2;
23767 int16_t imm;
23769 rs = (ctx->opcode >> 21) & 0x1f;
23770 rt = (ctx->opcode >> 16) & 0x1f;
23771 rd = (ctx->opcode >> 11) & 0x1f;
23772 sa = (ctx->opcode >> 6) & 0x1f;
23773 imm = (int16_t)ctx->opcode >> 7;
23775 op1 = MASK_SPECIAL3(ctx->opcode);
23776 switch (op1) {
23777 case R6_OPC_PREF:
23778 if (rt >= 24) {
23779 /* hint codes 24-31 are reserved and signal RI */
23780 gen_reserved_instruction(ctx);
23782 /* Treat as NOP. */
23783 break;
23784 case R6_OPC_CACHE:
23785 check_cp0_enabled(ctx);
23786 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23787 gen_cache_operation(ctx, rt, rs, imm);
23789 break;
23790 case R6_OPC_SC:
23791 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
23792 break;
23793 case R6_OPC_LL:
23794 gen_ld(ctx, op1, rt, rs, imm);
23795 break;
23796 case OPC_BSHFL:
23798 if (rd == 0) {
23799 /* Treat as NOP. */
23800 break;
23802 op2 = MASK_BSHFL(ctx->opcode);
23803 switch (op2) {
23804 case OPC_ALIGN:
23805 case OPC_ALIGN_1:
23806 case OPC_ALIGN_2:
23807 case OPC_ALIGN_3:
23808 gen_align(ctx, 32, rd, rs, rt, sa & 3);
23809 break;
23810 case OPC_BITSWAP:
23811 gen_bitswap(ctx, op2, rd, rt);
23812 break;
23815 break;
23816 #ifndef CONFIG_USER_ONLY
23817 case OPC_GINV:
23818 if (unlikely(ctx->gi <= 1)) {
23819 gen_reserved_instruction(ctx);
23821 check_cp0_enabled(ctx);
23822 switch ((ctx->opcode >> 6) & 3) {
23823 case 0: /* GINVI */
23824 /* Treat as NOP. */
23825 break;
23826 case 2: /* GINVT */
23827 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
23828 break;
23829 default:
23830 gen_reserved_instruction(ctx);
23831 break;
23833 break;
23834 #endif
23835 #if defined(TARGET_MIPS64)
23836 case R6_OPC_SCD:
23837 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
23838 break;
23839 case R6_OPC_LLD:
23840 gen_ld(ctx, op1, rt, rs, imm);
23841 break;
23842 case OPC_DBSHFL:
23843 check_mips_64(ctx);
23845 if (rd == 0) {
23846 /* Treat as NOP. */
23847 break;
23849 op2 = MASK_DBSHFL(ctx->opcode);
23850 switch (op2) {
23851 case OPC_DALIGN:
23852 case OPC_DALIGN_1:
23853 case OPC_DALIGN_2:
23854 case OPC_DALIGN_3:
23855 case OPC_DALIGN_4:
23856 case OPC_DALIGN_5:
23857 case OPC_DALIGN_6:
23858 case OPC_DALIGN_7:
23859 gen_align(ctx, 64, rd, rs, rt, sa & 7);
23860 break;
23861 case OPC_DBITSWAP:
23862 gen_bitswap(ctx, op2, rd, rt);
23863 break;
23867 break;
23868 #endif
23869 default: /* Invalid */
23870 MIPS_INVAL("special3_r6");
23871 gen_reserved_instruction(ctx);
23872 break;
23876 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
23878 int rs, rt, rd;
23879 uint32_t op1, op2;
23881 rs = (ctx->opcode >> 21) & 0x1f;
23882 rt = (ctx->opcode >> 16) & 0x1f;
23883 rd = (ctx->opcode >> 11) & 0x1f;
23885 op1 = MASK_SPECIAL3(ctx->opcode);
23886 switch (op1) {
23887 case OPC_DIV_G_2E:
23888 case OPC_DIVU_G_2E:
23889 case OPC_MOD_G_2E:
23890 case OPC_MODU_G_2E:
23891 case OPC_MULT_G_2E:
23892 case OPC_MULTU_G_2E:
23894 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23895 * the same mask and op1.
23897 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
23898 op2 = MASK_ADDUH_QB(ctx->opcode);
23899 switch (op2) {
23900 case OPC_ADDUH_QB:
23901 case OPC_ADDUH_R_QB:
23902 case OPC_ADDQH_PH:
23903 case OPC_ADDQH_R_PH:
23904 case OPC_ADDQH_W:
23905 case OPC_ADDQH_R_W:
23906 case OPC_SUBUH_QB:
23907 case OPC_SUBUH_R_QB:
23908 case OPC_SUBQH_PH:
23909 case OPC_SUBQH_R_PH:
23910 case OPC_SUBQH_W:
23911 case OPC_SUBQH_R_W:
23912 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23913 break;
23914 case OPC_MUL_PH:
23915 case OPC_MUL_S_PH:
23916 case OPC_MULQ_S_W:
23917 case OPC_MULQ_RS_W:
23918 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23919 break;
23920 default:
23921 MIPS_INVAL("MASK ADDUH.QB");
23922 gen_reserved_instruction(ctx);
23923 break;
23925 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
23926 gen_loongson_integer(ctx, op1, rd, rs, rt);
23927 } else {
23928 gen_reserved_instruction(ctx);
23930 break;
23931 case OPC_LX_DSP:
23932 op2 = MASK_LX(ctx->opcode);
23933 switch (op2) {
23934 #if defined(TARGET_MIPS64)
23935 case OPC_LDX:
23936 #endif
23937 case OPC_LBUX:
23938 case OPC_LHX:
23939 case OPC_LWX:
23940 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
23941 break;
23942 default: /* Invalid */
23943 MIPS_INVAL("MASK LX");
23944 gen_reserved_instruction(ctx);
23945 break;
23947 break;
23948 case OPC_ABSQ_S_PH_DSP:
23949 op2 = MASK_ABSQ_S_PH(ctx->opcode);
23950 switch (op2) {
23951 case OPC_ABSQ_S_QB:
23952 case OPC_ABSQ_S_PH:
23953 case OPC_ABSQ_S_W:
23954 case OPC_PRECEQ_W_PHL:
23955 case OPC_PRECEQ_W_PHR:
23956 case OPC_PRECEQU_PH_QBL:
23957 case OPC_PRECEQU_PH_QBR:
23958 case OPC_PRECEQU_PH_QBLA:
23959 case OPC_PRECEQU_PH_QBRA:
23960 case OPC_PRECEU_PH_QBL:
23961 case OPC_PRECEU_PH_QBR:
23962 case OPC_PRECEU_PH_QBLA:
23963 case OPC_PRECEU_PH_QBRA:
23964 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23965 break;
23966 case OPC_BITREV:
23967 case OPC_REPL_QB:
23968 case OPC_REPLV_QB:
23969 case OPC_REPL_PH:
23970 case OPC_REPLV_PH:
23971 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23972 break;
23973 default:
23974 MIPS_INVAL("MASK ABSQ_S.PH");
23975 gen_reserved_instruction(ctx);
23976 break;
23978 break;
23979 case OPC_ADDU_QB_DSP:
23980 op2 = MASK_ADDU_QB(ctx->opcode);
23981 switch (op2) {
23982 case OPC_ADDQ_PH:
23983 case OPC_ADDQ_S_PH:
23984 case OPC_ADDQ_S_W:
23985 case OPC_ADDU_QB:
23986 case OPC_ADDU_S_QB:
23987 case OPC_ADDU_PH:
23988 case OPC_ADDU_S_PH:
23989 case OPC_SUBQ_PH:
23990 case OPC_SUBQ_S_PH:
23991 case OPC_SUBQ_S_W:
23992 case OPC_SUBU_QB:
23993 case OPC_SUBU_S_QB:
23994 case OPC_SUBU_PH:
23995 case OPC_SUBU_S_PH:
23996 case OPC_ADDSC:
23997 case OPC_ADDWC:
23998 case OPC_MODSUB:
23999 case OPC_RADDU_W_QB:
24000 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24001 break;
24002 case OPC_MULEU_S_PH_QBL:
24003 case OPC_MULEU_S_PH_QBR:
24004 case OPC_MULQ_RS_PH:
24005 case OPC_MULEQ_S_W_PHL:
24006 case OPC_MULEQ_S_W_PHR:
24007 case OPC_MULQ_S_PH:
24008 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24009 break;
24010 default: /* Invalid */
24011 MIPS_INVAL("MASK ADDU.QB");
24012 gen_reserved_instruction(ctx);
24013 break;
24016 break;
24017 case OPC_CMPU_EQ_QB_DSP:
24018 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
24019 switch (op2) {
24020 case OPC_PRECR_SRA_PH_W:
24021 case OPC_PRECR_SRA_R_PH_W:
24022 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24023 break;
24024 case OPC_PRECR_QB_PH:
24025 case OPC_PRECRQ_QB_PH:
24026 case OPC_PRECRQ_PH_W:
24027 case OPC_PRECRQ_RS_PH_W:
24028 case OPC_PRECRQU_S_QB_PH:
24029 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24030 break;
24031 case OPC_CMPU_EQ_QB:
24032 case OPC_CMPU_LT_QB:
24033 case OPC_CMPU_LE_QB:
24034 case OPC_CMP_EQ_PH:
24035 case OPC_CMP_LT_PH:
24036 case OPC_CMP_LE_PH:
24037 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24038 break;
24039 case OPC_CMPGU_EQ_QB:
24040 case OPC_CMPGU_LT_QB:
24041 case OPC_CMPGU_LE_QB:
24042 case OPC_CMPGDU_EQ_QB:
24043 case OPC_CMPGDU_LT_QB:
24044 case OPC_CMPGDU_LE_QB:
24045 case OPC_PICK_QB:
24046 case OPC_PICK_PH:
24047 case OPC_PACKRL_PH:
24048 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24049 break;
24050 default: /* Invalid */
24051 MIPS_INVAL("MASK CMPU.EQ.QB");
24052 gen_reserved_instruction(ctx);
24053 break;
24055 break;
24056 case OPC_SHLL_QB_DSP:
24057 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24058 break;
24059 case OPC_DPA_W_PH_DSP:
24060 op2 = MASK_DPA_W_PH(ctx->opcode);
24061 switch (op2) {
24062 case OPC_DPAU_H_QBL:
24063 case OPC_DPAU_H_QBR:
24064 case OPC_DPSU_H_QBL:
24065 case OPC_DPSU_H_QBR:
24066 case OPC_DPA_W_PH:
24067 case OPC_DPAX_W_PH:
24068 case OPC_DPAQ_S_W_PH:
24069 case OPC_DPAQX_S_W_PH:
24070 case OPC_DPAQX_SA_W_PH:
24071 case OPC_DPS_W_PH:
24072 case OPC_DPSX_W_PH:
24073 case OPC_DPSQ_S_W_PH:
24074 case OPC_DPSQX_S_W_PH:
24075 case OPC_DPSQX_SA_W_PH:
24076 case OPC_MULSAQ_S_W_PH:
24077 case OPC_DPAQ_SA_L_W:
24078 case OPC_DPSQ_SA_L_W:
24079 case OPC_MAQ_S_W_PHL:
24080 case OPC_MAQ_S_W_PHR:
24081 case OPC_MAQ_SA_W_PHL:
24082 case OPC_MAQ_SA_W_PHR:
24083 case OPC_MULSA_W_PH:
24084 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24085 break;
24086 default: /* Invalid */
24087 MIPS_INVAL("MASK DPAW.PH");
24088 gen_reserved_instruction(ctx);
24089 break;
24091 break;
24092 case OPC_INSV_DSP:
24093 op2 = MASK_INSV(ctx->opcode);
24094 switch (op2) {
24095 case OPC_INSV:
24096 check_dsp(ctx);
24098 TCGv t0, t1;
24100 if (rt == 0) {
24101 break;
24104 t0 = tcg_temp_new();
24105 t1 = tcg_temp_new();
24107 gen_load_gpr(t0, rt);
24108 gen_load_gpr(t1, rs);
24110 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
24112 tcg_temp_free(t0);
24113 tcg_temp_free(t1);
24114 break;
24116 default: /* Invalid */
24117 MIPS_INVAL("MASK INSV");
24118 gen_reserved_instruction(ctx);
24119 break;
24121 break;
24122 case OPC_APPEND_DSP:
24123 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24124 break;
24125 case OPC_EXTR_W_DSP:
24126 op2 = MASK_EXTR_W(ctx->opcode);
24127 switch (op2) {
24128 case OPC_EXTR_W:
24129 case OPC_EXTR_R_W:
24130 case OPC_EXTR_RS_W:
24131 case OPC_EXTR_S_H:
24132 case OPC_EXTRV_S_H:
24133 case OPC_EXTRV_W:
24134 case OPC_EXTRV_R_W:
24135 case OPC_EXTRV_RS_W:
24136 case OPC_EXTP:
24137 case OPC_EXTPV:
24138 case OPC_EXTPDP:
24139 case OPC_EXTPDPV:
24140 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24141 break;
24142 case OPC_RDDSP:
24143 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
24144 break;
24145 case OPC_SHILO:
24146 case OPC_SHILOV:
24147 case OPC_MTHLIP:
24148 case OPC_WRDSP:
24149 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24150 break;
24151 default: /* Invalid */
24152 MIPS_INVAL("MASK EXTR.W");
24153 gen_reserved_instruction(ctx);
24154 break;
24156 break;
24157 #if defined(TARGET_MIPS64)
24158 case OPC_DDIV_G_2E:
24159 case OPC_DDIVU_G_2E:
24160 case OPC_DMULT_G_2E:
24161 case OPC_DMULTU_G_2E:
24162 case OPC_DMOD_G_2E:
24163 case OPC_DMODU_G_2E:
24164 check_insn(ctx, INSN_LOONGSON2E);
24165 gen_loongson_integer(ctx, op1, rd, rs, rt);
24166 break;
24167 case OPC_ABSQ_S_QH_DSP:
24168 op2 = MASK_ABSQ_S_QH(ctx->opcode);
24169 switch (op2) {
24170 case OPC_PRECEQ_L_PWL:
24171 case OPC_PRECEQ_L_PWR:
24172 case OPC_PRECEQ_PW_QHL:
24173 case OPC_PRECEQ_PW_QHR:
24174 case OPC_PRECEQ_PW_QHLA:
24175 case OPC_PRECEQ_PW_QHRA:
24176 case OPC_PRECEQU_QH_OBL:
24177 case OPC_PRECEQU_QH_OBR:
24178 case OPC_PRECEQU_QH_OBLA:
24179 case OPC_PRECEQU_QH_OBRA:
24180 case OPC_PRECEU_QH_OBL:
24181 case OPC_PRECEU_QH_OBR:
24182 case OPC_PRECEU_QH_OBLA:
24183 case OPC_PRECEU_QH_OBRA:
24184 case OPC_ABSQ_S_OB:
24185 case OPC_ABSQ_S_PW:
24186 case OPC_ABSQ_S_QH:
24187 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24188 break;
24189 case OPC_REPL_OB:
24190 case OPC_REPL_PW:
24191 case OPC_REPL_QH:
24192 case OPC_REPLV_OB:
24193 case OPC_REPLV_PW:
24194 case OPC_REPLV_QH:
24195 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24196 break;
24197 default: /* Invalid */
24198 MIPS_INVAL("MASK ABSQ_S.QH");
24199 gen_reserved_instruction(ctx);
24200 break;
24202 break;
24203 case OPC_ADDU_OB_DSP:
24204 op2 = MASK_ADDU_OB(ctx->opcode);
24205 switch (op2) {
24206 case OPC_RADDU_L_OB:
24207 case OPC_SUBQ_PW:
24208 case OPC_SUBQ_S_PW:
24209 case OPC_SUBQ_QH:
24210 case OPC_SUBQ_S_QH:
24211 case OPC_SUBU_OB:
24212 case OPC_SUBU_S_OB:
24213 case OPC_SUBU_QH:
24214 case OPC_SUBU_S_QH:
24215 case OPC_SUBUH_OB:
24216 case OPC_SUBUH_R_OB:
24217 case OPC_ADDQ_PW:
24218 case OPC_ADDQ_S_PW:
24219 case OPC_ADDQ_QH:
24220 case OPC_ADDQ_S_QH:
24221 case OPC_ADDU_OB:
24222 case OPC_ADDU_S_OB:
24223 case OPC_ADDU_QH:
24224 case OPC_ADDU_S_QH:
24225 case OPC_ADDUH_OB:
24226 case OPC_ADDUH_R_OB:
24227 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24228 break;
24229 case OPC_MULEQ_S_PW_QHL:
24230 case OPC_MULEQ_S_PW_QHR:
24231 case OPC_MULEU_S_QH_OBL:
24232 case OPC_MULEU_S_QH_OBR:
24233 case OPC_MULQ_RS_QH:
24234 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24235 break;
24236 default: /* Invalid */
24237 MIPS_INVAL("MASK ADDU.OB");
24238 gen_reserved_instruction(ctx);
24239 break;
24241 break;
24242 case OPC_CMPU_EQ_OB_DSP:
24243 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
24244 switch (op2) {
24245 case OPC_PRECR_SRA_QH_PW:
24246 case OPC_PRECR_SRA_R_QH_PW:
24247 /* Return value is rt. */
24248 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24249 break;
24250 case OPC_PRECR_OB_QH:
24251 case OPC_PRECRQ_OB_QH:
24252 case OPC_PRECRQ_PW_L:
24253 case OPC_PRECRQ_QH_PW:
24254 case OPC_PRECRQ_RS_QH_PW:
24255 case OPC_PRECRQU_S_OB_QH:
24256 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24257 break;
24258 case OPC_CMPU_EQ_OB:
24259 case OPC_CMPU_LT_OB:
24260 case OPC_CMPU_LE_OB:
24261 case OPC_CMP_EQ_QH:
24262 case OPC_CMP_LT_QH:
24263 case OPC_CMP_LE_QH:
24264 case OPC_CMP_EQ_PW:
24265 case OPC_CMP_LT_PW:
24266 case OPC_CMP_LE_PW:
24267 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24268 break;
24269 case OPC_CMPGDU_EQ_OB:
24270 case OPC_CMPGDU_LT_OB:
24271 case OPC_CMPGDU_LE_OB:
24272 case OPC_CMPGU_EQ_OB:
24273 case OPC_CMPGU_LT_OB:
24274 case OPC_CMPGU_LE_OB:
24275 case OPC_PACKRL_PW:
24276 case OPC_PICK_OB:
24277 case OPC_PICK_PW:
24278 case OPC_PICK_QH:
24279 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24280 break;
24281 default: /* Invalid */
24282 MIPS_INVAL("MASK CMPU_EQ.OB");
24283 gen_reserved_instruction(ctx);
24284 break;
24286 break;
24287 case OPC_DAPPEND_DSP:
24288 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24289 break;
24290 case OPC_DEXTR_W_DSP:
24291 op2 = MASK_DEXTR_W(ctx->opcode);
24292 switch (op2) {
24293 case OPC_DEXTP:
24294 case OPC_DEXTPDP:
24295 case OPC_DEXTPDPV:
24296 case OPC_DEXTPV:
24297 case OPC_DEXTR_L:
24298 case OPC_DEXTR_R_L:
24299 case OPC_DEXTR_RS_L:
24300 case OPC_DEXTR_W:
24301 case OPC_DEXTR_R_W:
24302 case OPC_DEXTR_RS_W:
24303 case OPC_DEXTR_S_H:
24304 case OPC_DEXTRV_L:
24305 case OPC_DEXTRV_R_L:
24306 case OPC_DEXTRV_RS_L:
24307 case OPC_DEXTRV_S_H:
24308 case OPC_DEXTRV_W:
24309 case OPC_DEXTRV_R_W:
24310 case OPC_DEXTRV_RS_W:
24311 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24312 break;
24313 case OPC_DMTHLIP:
24314 case OPC_DSHILO:
24315 case OPC_DSHILOV:
24316 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24317 break;
24318 default: /* Invalid */
24319 MIPS_INVAL("MASK EXTR.W");
24320 gen_reserved_instruction(ctx);
24321 break;
24323 break;
24324 case OPC_DPAQ_W_QH_DSP:
24325 op2 = MASK_DPAQ_W_QH(ctx->opcode);
24326 switch (op2) {
24327 case OPC_DPAU_H_OBL:
24328 case OPC_DPAU_H_OBR:
24329 case OPC_DPSU_H_OBL:
24330 case OPC_DPSU_H_OBR:
24331 case OPC_DPA_W_QH:
24332 case OPC_DPAQ_S_W_QH:
24333 case OPC_DPS_W_QH:
24334 case OPC_DPSQ_S_W_QH:
24335 case OPC_MULSAQ_S_W_QH:
24336 case OPC_DPAQ_SA_L_PW:
24337 case OPC_DPSQ_SA_L_PW:
24338 case OPC_MULSAQ_S_L_PW:
24339 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24340 break;
24341 case OPC_MAQ_S_W_QHLL:
24342 case OPC_MAQ_S_W_QHLR:
24343 case OPC_MAQ_S_W_QHRL:
24344 case OPC_MAQ_S_W_QHRR:
24345 case OPC_MAQ_SA_W_QHLL:
24346 case OPC_MAQ_SA_W_QHLR:
24347 case OPC_MAQ_SA_W_QHRL:
24348 case OPC_MAQ_SA_W_QHRR:
24349 case OPC_MAQ_S_L_PWL:
24350 case OPC_MAQ_S_L_PWR:
24351 case OPC_DMADD:
24352 case OPC_DMADDU:
24353 case OPC_DMSUB:
24354 case OPC_DMSUBU:
24355 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24356 break;
24357 default: /* Invalid */
24358 MIPS_INVAL("MASK DPAQ.W.QH");
24359 gen_reserved_instruction(ctx);
24360 break;
24362 break;
24363 case OPC_DINSV_DSP:
24364 op2 = MASK_INSV(ctx->opcode);
24365 switch (op2) {
24366 case OPC_DINSV:
24368 TCGv t0, t1;
24370 if (rt == 0) {
24371 break;
24373 check_dsp(ctx);
24375 t0 = tcg_temp_new();
24376 t1 = tcg_temp_new();
24378 gen_load_gpr(t0, rt);
24379 gen_load_gpr(t1, rs);
24381 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
24383 tcg_temp_free(t0);
24384 tcg_temp_free(t1);
24385 break;
24387 default: /* Invalid */
24388 MIPS_INVAL("MASK DINSV");
24389 gen_reserved_instruction(ctx);
24390 break;
24392 break;
24393 case OPC_SHLL_OB_DSP:
24394 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24395 break;
24396 #endif
24397 default: /* Invalid */
24398 MIPS_INVAL("special3_legacy");
24399 gen_reserved_instruction(ctx);
24400 break;
24405 #if defined(TARGET_MIPS64)
24407 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
24409 uint32_t opc = MASK_MMI(ctx->opcode);
24410 int rs = extract32(ctx->opcode, 21, 5);
24411 int rt = extract32(ctx->opcode, 16, 5);
24412 int rd = extract32(ctx->opcode, 11, 5);
24414 switch (opc) {
24415 case MMI_OPC_MULT1:
24416 case MMI_OPC_MULTU1:
24417 case MMI_OPC_MADD:
24418 case MMI_OPC_MADDU:
24419 case MMI_OPC_MADD1:
24420 case MMI_OPC_MADDU1:
24421 gen_mul_txx9(ctx, opc, rd, rs, rt);
24422 break;
24423 case MMI_OPC_DIV1:
24424 case MMI_OPC_DIVU1:
24425 gen_div1_tx79(ctx, opc, rs, rt);
24426 break;
24427 default:
24428 MIPS_INVAL("TX79 MMI class");
24429 gen_reserved_instruction(ctx);
24430 break;
24434 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
24436 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_LQ */
24439 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
24441 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
24445 * The TX79-specific instruction Store Quadword
24447 * +--------+-------+-------+------------------------+
24448 * | 011111 | base | rt | offset | SQ
24449 * +--------+-------+-------+------------------------+
24450 * 6 5 5 16
24452 * has the same opcode as the Read Hardware Register instruction
24454 * +--------+-------+-------+-------+-------+--------+
24455 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
24456 * +--------+-------+-------+-------+-------+--------+
24457 * 6 5 5 5 5 6
24459 * that is required, trapped and emulated by the Linux kernel. However, all
24460 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
24461 * offset is odd. Therefore all valid SQ instructions can execute normally.
24462 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
24463 * between SQ and RDHWR, as the Linux kernel does.
24465 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
24467 int base = extract32(ctx->opcode, 21, 5);
24468 int rt = extract32(ctx->opcode, 16, 5);
24469 int offset = extract32(ctx->opcode, 0, 16);
24471 #ifdef CONFIG_USER_ONLY
24472 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
24473 uint32_t op2 = extract32(ctx->opcode, 6, 5);
24475 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
24476 int rd = extract32(ctx->opcode, 11, 5);
24478 gen_rdhwr(ctx, rt, rd, 0);
24479 return;
24481 #endif
24483 gen_mmi_sq(ctx, base, rt, offset);
24486 #endif
24488 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
24490 int rs, rt, rd, sa;
24491 uint32_t op1, op2;
24492 int16_t imm;
24494 rs = (ctx->opcode >> 21) & 0x1f;
24495 rt = (ctx->opcode >> 16) & 0x1f;
24496 rd = (ctx->opcode >> 11) & 0x1f;
24497 sa = (ctx->opcode >> 6) & 0x1f;
24498 imm = sextract32(ctx->opcode, 7, 9);
24500 op1 = MASK_SPECIAL3(ctx->opcode);
24503 * EVA loads and stores overlap Loongson 2E instructions decoded by
24504 * decode_opc_special3_legacy(), so be careful to allow their decoding when
24505 * EVA is absent.
24507 if (ctx->eva) {
24508 switch (op1) {
24509 case OPC_LWLE:
24510 case OPC_LWRE:
24511 case OPC_LBUE:
24512 case OPC_LHUE:
24513 case OPC_LBE:
24514 case OPC_LHE:
24515 case OPC_LLE:
24516 case OPC_LWE:
24517 check_cp0_enabled(ctx);
24518 gen_ld(ctx, op1, rt, rs, imm);
24519 return;
24520 case OPC_SWLE:
24521 case OPC_SWRE:
24522 case OPC_SBE:
24523 case OPC_SHE:
24524 case OPC_SWE:
24525 check_cp0_enabled(ctx);
24526 gen_st(ctx, op1, rt, rs, imm);
24527 return;
24528 case OPC_SCE:
24529 check_cp0_enabled(ctx);
24530 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
24531 return;
24532 case OPC_CACHEE:
24533 check_cp0_enabled(ctx);
24534 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24535 gen_cache_operation(ctx, rt, rs, imm);
24537 /* Treat as NOP. */
24538 return;
24539 case OPC_PREFE:
24540 check_cp0_enabled(ctx);
24541 /* Treat as NOP. */
24542 return;
24546 switch (op1) {
24547 case OPC_EXT:
24548 case OPC_INS:
24549 check_insn(ctx, ISA_MIPS_R2);
24550 gen_bitops(ctx, op1, rt, rs, sa, rd);
24551 break;
24552 case OPC_BSHFL:
24553 op2 = MASK_BSHFL(ctx->opcode);
24554 switch (op2) {
24555 case OPC_ALIGN:
24556 case OPC_ALIGN_1:
24557 case OPC_ALIGN_2:
24558 case OPC_ALIGN_3:
24559 case OPC_BITSWAP:
24560 check_insn(ctx, ISA_MIPS_R6);
24561 decode_opc_special3_r6(env, ctx);
24562 break;
24563 default:
24564 check_insn(ctx, ISA_MIPS_R2);
24565 gen_bshfl(ctx, op2, rt, rd);
24566 break;
24568 break;
24569 #if defined(TARGET_MIPS64)
24570 case OPC_DEXTM:
24571 case OPC_DEXTU:
24572 case OPC_DEXT:
24573 case OPC_DINSM:
24574 case OPC_DINSU:
24575 case OPC_DINS:
24576 check_insn(ctx, ISA_MIPS_R2);
24577 check_mips_64(ctx);
24578 gen_bitops(ctx, op1, rt, rs, sa, rd);
24579 break;
24580 case OPC_DBSHFL:
24581 op2 = MASK_DBSHFL(ctx->opcode);
24582 switch (op2) {
24583 case OPC_DALIGN:
24584 case OPC_DALIGN_1:
24585 case OPC_DALIGN_2:
24586 case OPC_DALIGN_3:
24587 case OPC_DALIGN_4:
24588 case OPC_DALIGN_5:
24589 case OPC_DALIGN_6:
24590 case OPC_DALIGN_7:
24591 case OPC_DBITSWAP:
24592 check_insn(ctx, ISA_MIPS_R6);
24593 decode_opc_special3_r6(env, ctx);
24594 break;
24595 default:
24596 check_insn(ctx, ISA_MIPS_R2);
24597 check_mips_64(ctx);
24598 op2 = MASK_DBSHFL(ctx->opcode);
24599 gen_bshfl(ctx, op2, rt, rd);
24600 break;
24602 break;
24603 #endif
24604 case OPC_RDHWR:
24605 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
24606 break;
24607 case OPC_FORK:
24608 check_mt(ctx);
24610 TCGv t0 = tcg_temp_new();
24611 TCGv t1 = tcg_temp_new();
24613 gen_load_gpr(t0, rt);
24614 gen_load_gpr(t1, rs);
24615 gen_helper_fork(t0, t1);
24616 tcg_temp_free(t0);
24617 tcg_temp_free(t1);
24619 break;
24620 case OPC_YIELD:
24621 check_mt(ctx);
24623 TCGv t0 = tcg_temp_new();
24625 gen_load_gpr(t0, rs);
24626 gen_helper_yield(t0, cpu_env, t0);
24627 gen_store_gpr(t0, rd);
24628 tcg_temp_free(t0);
24630 break;
24631 default:
24632 if (ctx->insn_flags & ISA_MIPS_R6) {
24633 decode_opc_special3_r6(env, ctx);
24634 } else {
24635 decode_opc_special3_legacy(env, ctx);
24640 static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
24642 int32_t offset;
24643 int rs, rt, rd, sa;
24644 uint32_t op, op1;
24645 int16_t imm;
24647 op = MASK_OP_MAJOR(ctx->opcode);
24648 rs = (ctx->opcode >> 21) & 0x1f;
24649 rt = (ctx->opcode >> 16) & 0x1f;
24650 rd = (ctx->opcode >> 11) & 0x1f;
24651 sa = (ctx->opcode >> 6) & 0x1f;
24652 imm = (int16_t)ctx->opcode;
24653 switch (op) {
24654 case OPC_SPECIAL:
24655 decode_opc_special(env, ctx);
24656 break;
24657 case OPC_SPECIAL2:
24658 #if defined(TARGET_MIPS64)
24659 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
24660 decode_mmi(env, ctx);
24661 break;
24663 #endif
24664 if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) {
24665 if (MASK_SPECIAL2(ctx->opcode) == OPC_MUL) {
24666 gen_arith(ctx, OPC_MUL, rd, rs, rt);
24667 } else {
24668 decode_ase_mxu(ctx, ctx->opcode);
24670 break;
24672 decode_opc_special2_legacy(env, ctx);
24673 break;
24674 case OPC_SPECIAL3:
24675 #if defined(TARGET_MIPS64)
24676 if (ctx->insn_flags & INSN_R5900) {
24677 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
24678 } else {
24679 decode_opc_special3(env, ctx);
24681 #else
24682 decode_opc_special3(env, ctx);
24683 #endif
24684 break;
24685 case OPC_REGIMM:
24686 op1 = MASK_REGIMM(ctx->opcode);
24687 switch (op1) {
24688 case OPC_BLTZL: /* REGIMM branches */
24689 case OPC_BGEZL:
24690 case OPC_BLTZALL:
24691 case OPC_BGEZALL:
24692 check_insn(ctx, ISA_MIPS2);
24693 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24694 /* Fallthrough */
24695 case OPC_BLTZ:
24696 case OPC_BGEZ:
24697 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
24698 break;
24699 case OPC_BLTZAL:
24700 case OPC_BGEZAL:
24701 if (ctx->insn_flags & ISA_MIPS_R6) {
24702 if (rs == 0) {
24703 /* OPC_NAL, OPC_BAL */
24704 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
24705 } else {
24706 gen_reserved_instruction(ctx);
24708 } else {
24709 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
24711 break;
24712 case OPC_TGEI: /* REGIMM traps */
24713 case OPC_TGEIU:
24714 case OPC_TLTI:
24715 case OPC_TLTIU:
24716 case OPC_TEQI:
24718 case OPC_TNEI:
24719 check_insn(ctx, ISA_MIPS2);
24720 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24721 gen_trap(ctx, op1, rs, -1, imm);
24722 break;
24723 case OPC_SIGRIE:
24724 check_insn(ctx, ISA_MIPS_R6);
24725 gen_reserved_instruction(ctx);
24726 break;
24727 case OPC_SYNCI:
24728 check_insn(ctx, ISA_MIPS_R2);
24730 * Break the TB to be able to sync copied instructions
24731 * immediately.
24733 ctx->base.is_jmp = DISAS_STOP;
24734 break;
24735 case OPC_BPOSGE32: /* MIPS DSP branch */
24736 #if defined(TARGET_MIPS64)
24737 case OPC_BPOSGE64:
24738 #endif
24739 check_dsp(ctx);
24740 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
24741 break;
24742 #if defined(TARGET_MIPS64)
24743 case OPC_DAHI:
24744 check_insn(ctx, ISA_MIPS_R6);
24745 check_mips_64(ctx);
24746 if (rs != 0) {
24747 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
24749 break;
24750 case OPC_DATI:
24751 check_insn(ctx, ISA_MIPS_R6);
24752 check_mips_64(ctx);
24753 if (rs != 0) {
24754 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
24756 break;
24757 #endif
24758 default: /* Invalid */
24759 MIPS_INVAL("regimm");
24760 gen_reserved_instruction(ctx);
24761 break;
24763 break;
24764 case OPC_CP0:
24765 check_cp0_enabled(ctx);
24766 op1 = MASK_CP0(ctx->opcode);
24767 switch (op1) {
24768 case OPC_MFC0:
24769 case OPC_MTC0:
24770 case OPC_MFTR:
24771 case OPC_MTTR:
24772 case OPC_MFHC0:
24773 case OPC_MTHC0:
24774 #if defined(TARGET_MIPS64)
24775 case OPC_DMFC0:
24776 case OPC_DMTC0:
24777 #endif
24778 #ifndef CONFIG_USER_ONLY
24779 gen_cp0(env, ctx, op1, rt, rd);
24780 #endif /* !CONFIG_USER_ONLY */
24781 break;
24782 case OPC_C0:
24783 case OPC_C0_1:
24784 case OPC_C0_2:
24785 case OPC_C0_3:
24786 case OPC_C0_4:
24787 case OPC_C0_5:
24788 case OPC_C0_6:
24789 case OPC_C0_7:
24790 case OPC_C0_8:
24791 case OPC_C0_9:
24792 case OPC_C0_A:
24793 case OPC_C0_B:
24794 case OPC_C0_C:
24795 case OPC_C0_D:
24796 case OPC_C0_E:
24797 case OPC_C0_F:
24798 #ifndef CONFIG_USER_ONLY
24799 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
24800 #endif /* !CONFIG_USER_ONLY */
24801 break;
24802 case OPC_MFMC0:
24803 #ifndef CONFIG_USER_ONLY
24805 uint32_t op2;
24806 TCGv t0 = tcg_temp_new();
24808 op2 = MASK_MFMC0(ctx->opcode);
24809 switch (op2) {
24810 case OPC_DMT:
24811 check_cp0_mt(ctx);
24812 gen_helper_dmt(t0);
24813 gen_store_gpr(t0, rt);
24814 break;
24815 case OPC_EMT:
24816 check_cp0_mt(ctx);
24817 gen_helper_emt(t0);
24818 gen_store_gpr(t0, rt);
24819 break;
24820 case OPC_DVPE:
24821 check_cp0_mt(ctx);
24822 gen_helper_dvpe(t0, cpu_env);
24823 gen_store_gpr(t0, rt);
24824 break;
24825 case OPC_EVPE:
24826 check_cp0_mt(ctx);
24827 gen_helper_evpe(t0, cpu_env);
24828 gen_store_gpr(t0, rt);
24829 break;
24830 case OPC_DVP:
24831 check_insn(ctx, ISA_MIPS_R6);
24832 if (ctx->vp) {
24833 gen_helper_dvp(t0, cpu_env);
24834 gen_store_gpr(t0, rt);
24836 break;
24837 case OPC_EVP:
24838 check_insn(ctx, ISA_MIPS_R6);
24839 if (ctx->vp) {
24840 gen_helper_evp(t0, cpu_env);
24841 gen_store_gpr(t0, rt);
24843 break;
24844 case OPC_DI:
24845 check_insn(ctx, ISA_MIPS_R2);
24846 save_cpu_state(ctx, 1);
24847 gen_helper_di(t0, cpu_env);
24848 gen_store_gpr(t0, rt);
24850 * Stop translation as we may have switched
24851 * the execution mode.
24853 ctx->base.is_jmp = DISAS_STOP;
24854 break;
24855 case OPC_EI:
24856 check_insn(ctx, ISA_MIPS_R2);
24857 save_cpu_state(ctx, 1);
24858 gen_helper_ei(t0, cpu_env);
24859 gen_store_gpr(t0, rt);
24861 * DISAS_STOP isn't sufficient, we need to ensure we break
24862 * out of translated code to check for pending interrupts.
24864 gen_save_pc(ctx->base.pc_next + 4);
24865 ctx->base.is_jmp = DISAS_EXIT;
24866 break;
24867 default: /* Invalid */
24868 MIPS_INVAL("mfmc0");
24869 gen_reserved_instruction(ctx);
24870 break;
24872 tcg_temp_free(t0);
24874 #endif /* !CONFIG_USER_ONLY */
24875 break;
24876 case OPC_RDPGPR:
24877 check_insn(ctx, ISA_MIPS_R2);
24878 gen_load_srsgpr(rt, rd);
24879 break;
24880 case OPC_WRPGPR:
24881 check_insn(ctx, ISA_MIPS_R2);
24882 gen_store_srsgpr(rt, rd);
24883 break;
24884 default:
24885 MIPS_INVAL("cp0");
24886 gen_reserved_instruction(ctx);
24887 break;
24889 break;
24890 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
24891 if (ctx->insn_flags & ISA_MIPS_R6) {
24892 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
24893 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24894 } else {
24895 /* OPC_ADDI */
24896 /* Arithmetic with immediate opcode */
24897 gen_arith_imm(ctx, op, rt, rs, imm);
24899 break;
24900 case OPC_ADDIU:
24901 gen_arith_imm(ctx, op, rt, rs, imm);
24902 break;
24903 case OPC_SLTI: /* Set on less than with immediate opcode */
24904 case OPC_SLTIU:
24905 gen_slt_imm(ctx, op, rt, rs, imm);
24906 break;
24907 case OPC_ANDI: /* Arithmetic with immediate opcode */
24908 case OPC_LUI: /* OPC_AUI */
24909 case OPC_ORI:
24910 case OPC_XORI:
24911 gen_logic_imm(ctx, op, rt, rs, imm);
24912 break;
24913 case OPC_J: /* Jump */
24914 case OPC_JAL:
24915 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
24916 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
24917 break;
24918 /* Branch */
24919 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
24920 if (ctx->insn_flags & ISA_MIPS_R6) {
24921 if (rt == 0) {
24922 gen_reserved_instruction(ctx);
24923 break;
24925 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
24926 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24927 } else {
24928 /* OPC_BLEZL */
24929 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24931 break;
24932 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
24933 if (ctx->insn_flags & ISA_MIPS_R6) {
24934 if (rt == 0) {
24935 gen_reserved_instruction(ctx);
24936 break;
24938 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
24939 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24940 } else {
24941 /* OPC_BGTZL */
24942 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24944 break;
24945 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
24946 if (rt == 0) {
24947 /* OPC_BLEZ */
24948 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24949 } else {
24950 check_insn(ctx, ISA_MIPS_R6);
24951 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
24952 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24954 break;
24955 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
24956 if (rt == 0) {
24957 /* OPC_BGTZ */
24958 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24959 } else {
24960 check_insn(ctx, ISA_MIPS_R6);
24961 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
24962 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24964 break;
24965 case OPC_BEQL:
24966 case OPC_BNEL:
24967 check_insn(ctx, ISA_MIPS2);
24968 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24969 /* Fallthrough */
24970 case OPC_BEQ:
24971 case OPC_BNE:
24972 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24973 break;
24974 case OPC_LL: /* Load and stores */
24975 check_insn(ctx, ISA_MIPS2);
24976 if (ctx->insn_flags & INSN_R5900) {
24977 check_insn_opc_user_only(ctx, INSN_R5900);
24979 /* Fallthrough */
24980 case OPC_LWL:
24981 case OPC_LWR:
24982 case OPC_LB:
24983 case OPC_LH:
24984 case OPC_LW:
24985 case OPC_LWPC:
24986 case OPC_LBU:
24987 case OPC_LHU:
24988 gen_ld(ctx, op, rt, rs, imm);
24989 break;
24990 case OPC_SWL:
24991 case OPC_SWR:
24992 case OPC_SB:
24993 case OPC_SH:
24994 case OPC_SW:
24995 gen_st(ctx, op, rt, rs, imm);
24996 break;
24997 case OPC_SC:
24998 check_insn(ctx, ISA_MIPS2);
24999 if (ctx->insn_flags & INSN_R5900) {
25000 check_insn_opc_user_only(ctx, INSN_R5900);
25002 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
25003 break;
25004 case OPC_CACHE:
25005 check_cp0_enabled(ctx);
25006 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
25007 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25008 gen_cache_operation(ctx, rt, rs, imm);
25010 /* Treat as NOP. */
25011 break;
25012 case OPC_PREF:
25013 if (ctx->insn_flags & INSN_R5900) {
25014 /* Treat as NOP. */
25015 } else {
25016 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
25017 /* Treat as NOP. */
25019 break;
25021 /* Floating point (COP1). */
25022 case OPC_LWC1:
25023 case OPC_LDC1:
25024 case OPC_SWC1:
25025 case OPC_SDC1:
25026 gen_cop1_ldst(ctx, op, rt, rs, imm);
25027 break;
25029 case OPC_CP1:
25030 op1 = MASK_CP1(ctx->opcode);
25032 switch (op1) {
25033 case OPC_MFHC1:
25034 case OPC_MTHC1:
25035 check_cp1_enabled(ctx);
25036 check_insn(ctx, ISA_MIPS_R2);
25037 /* fall through */
25038 case OPC_MFC1:
25039 case OPC_CFC1:
25040 case OPC_MTC1:
25041 case OPC_CTC1:
25042 check_cp1_enabled(ctx);
25043 gen_cp1(ctx, op1, rt, rd);
25044 break;
25045 #if defined(TARGET_MIPS64)
25046 case OPC_DMFC1:
25047 case OPC_DMTC1:
25048 check_cp1_enabled(ctx);
25049 check_insn(ctx, ISA_MIPS3);
25050 check_mips_64(ctx);
25051 gen_cp1(ctx, op1, rt, rd);
25052 break;
25053 #endif
25054 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
25055 check_cp1_enabled(ctx);
25056 if (ctx->insn_flags & ISA_MIPS_R6) {
25057 /* OPC_BC1EQZ */
25058 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25059 rt, imm << 2, 4);
25060 } else {
25061 /* OPC_BC1ANY2 */
25062 check_cop1x(ctx);
25063 check_insn(ctx, ASE_MIPS3D);
25064 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25065 (rt >> 2) & 0x7, imm << 2);
25067 break;
25068 case OPC_BC1NEZ:
25069 check_cp1_enabled(ctx);
25070 check_insn(ctx, ISA_MIPS_R6);
25071 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25072 rt, imm << 2, 4);
25073 break;
25074 case OPC_BC1ANY4:
25075 check_cp1_enabled(ctx);
25076 check_insn_opc_removed(ctx, ISA_MIPS_R6);
25077 check_cop1x(ctx);
25078 check_insn(ctx, ASE_MIPS3D);
25079 /* fall through */
25080 case OPC_BC1:
25081 check_cp1_enabled(ctx);
25082 check_insn_opc_removed(ctx, ISA_MIPS_R6);
25083 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25084 (rt >> 2) & 0x7, imm << 2);
25085 break;
25086 case OPC_PS_FMT:
25087 check_ps(ctx);
25088 /* fall through */
25089 case OPC_S_FMT:
25090 case OPC_D_FMT:
25091 check_cp1_enabled(ctx);
25092 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25093 (imm >> 8) & 0x7);
25094 break;
25095 case OPC_W_FMT:
25096 case OPC_L_FMT:
25098 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
25099 check_cp1_enabled(ctx);
25100 if (ctx->insn_flags & ISA_MIPS_R6) {
25101 switch (r6_op) {
25102 case R6_OPC_CMP_AF_S:
25103 case R6_OPC_CMP_UN_S:
25104 case R6_OPC_CMP_EQ_S:
25105 case R6_OPC_CMP_UEQ_S:
25106 case R6_OPC_CMP_LT_S:
25107 case R6_OPC_CMP_ULT_S:
25108 case R6_OPC_CMP_LE_S:
25109 case R6_OPC_CMP_ULE_S:
25110 case R6_OPC_CMP_SAF_S:
25111 case R6_OPC_CMP_SUN_S:
25112 case R6_OPC_CMP_SEQ_S:
25113 case R6_OPC_CMP_SEUQ_S:
25114 case R6_OPC_CMP_SLT_S:
25115 case R6_OPC_CMP_SULT_S:
25116 case R6_OPC_CMP_SLE_S:
25117 case R6_OPC_CMP_SULE_S:
25118 case R6_OPC_CMP_OR_S:
25119 case R6_OPC_CMP_UNE_S:
25120 case R6_OPC_CMP_NE_S:
25121 case R6_OPC_CMP_SOR_S:
25122 case R6_OPC_CMP_SUNE_S:
25123 case R6_OPC_CMP_SNE_S:
25124 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25125 break;
25126 case R6_OPC_CMP_AF_D:
25127 case R6_OPC_CMP_UN_D:
25128 case R6_OPC_CMP_EQ_D:
25129 case R6_OPC_CMP_UEQ_D:
25130 case R6_OPC_CMP_LT_D:
25131 case R6_OPC_CMP_ULT_D:
25132 case R6_OPC_CMP_LE_D:
25133 case R6_OPC_CMP_ULE_D:
25134 case R6_OPC_CMP_SAF_D:
25135 case R6_OPC_CMP_SUN_D:
25136 case R6_OPC_CMP_SEQ_D:
25137 case R6_OPC_CMP_SEUQ_D:
25138 case R6_OPC_CMP_SLT_D:
25139 case R6_OPC_CMP_SULT_D:
25140 case R6_OPC_CMP_SLE_D:
25141 case R6_OPC_CMP_SULE_D:
25142 case R6_OPC_CMP_OR_D:
25143 case R6_OPC_CMP_UNE_D:
25144 case R6_OPC_CMP_NE_D:
25145 case R6_OPC_CMP_SOR_D:
25146 case R6_OPC_CMP_SUNE_D:
25147 case R6_OPC_CMP_SNE_D:
25148 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25149 break;
25150 default:
25151 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
25152 rt, rd, sa, (imm >> 8) & 0x7);
25154 break;
25156 } else {
25157 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25158 (imm >> 8) & 0x7);
25160 break;
25162 default:
25163 MIPS_INVAL("cp1");
25164 gen_reserved_instruction(ctx);
25165 break;
25167 break;
25169 /* Compact branches [R6] and COP2 [non-R6] */
25170 case OPC_BC: /* OPC_LWC2 */
25171 case OPC_BALC: /* OPC_SWC2 */
25172 if (ctx->insn_flags & ISA_MIPS_R6) {
25173 /* OPC_BC, OPC_BALC */
25174 gen_compute_compact_branch(ctx, op, 0, 0,
25175 sextract32(ctx->opcode << 2, 0, 28));
25176 } else if (ctx->insn_flags & ASE_LEXT) {
25177 gen_loongson_lswc2(ctx, rt, rs, rd);
25178 } else {
25179 /* OPC_LWC2, OPC_SWC2 */
25180 /* COP2: Not implemented. */
25181 generate_exception_err(ctx, EXCP_CpU, 2);
25183 break;
25184 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
25185 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
25186 if (ctx->insn_flags & ISA_MIPS_R6) {
25187 if (rs != 0) {
25188 /* OPC_BEQZC, OPC_BNEZC */
25189 gen_compute_compact_branch(ctx, op, rs, 0,
25190 sextract32(ctx->opcode << 2, 0, 23));
25191 } else {
25192 /* OPC_JIC, OPC_JIALC */
25193 gen_compute_compact_branch(ctx, op, 0, rt, imm);
25195 } else if (ctx->insn_flags & ASE_LEXT) {
25196 gen_loongson_lsdc2(ctx, rt, rs, rd);
25197 } else {
25198 /* OPC_LWC2, OPC_SWC2 */
25199 /* COP2: Not implemented. */
25200 generate_exception_err(ctx, EXCP_CpU, 2);
25202 break;
25203 case OPC_CP2:
25204 check_insn(ctx, ASE_LMMI);
25205 /* Note that these instructions use different fields. */
25206 gen_loongson_multimedia(ctx, sa, rd, rt);
25207 break;
25209 case OPC_CP3:
25210 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
25211 check_cp1_enabled(ctx);
25212 op1 = MASK_CP3(ctx->opcode);
25213 switch (op1) {
25214 case OPC_LUXC1:
25215 case OPC_SUXC1:
25216 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
25217 /* Fallthrough */
25218 case OPC_LWXC1:
25219 case OPC_LDXC1:
25220 case OPC_SWXC1:
25221 case OPC_SDXC1:
25222 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25223 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
25224 break;
25225 case OPC_PREFX:
25226 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25227 /* Treat as NOP. */
25228 break;
25229 case OPC_ALNV_PS:
25230 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
25231 /* Fallthrough */
25232 case OPC_MADD_S:
25233 case OPC_MADD_D:
25234 case OPC_MADD_PS:
25235 case OPC_MSUB_S:
25236 case OPC_MSUB_D:
25237 case OPC_MSUB_PS:
25238 case OPC_NMADD_S:
25239 case OPC_NMADD_D:
25240 case OPC_NMADD_PS:
25241 case OPC_NMSUB_S:
25242 case OPC_NMSUB_D:
25243 case OPC_NMSUB_PS:
25244 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25245 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
25246 break;
25247 default:
25248 MIPS_INVAL("cp3");
25249 gen_reserved_instruction(ctx);
25250 break;
25252 } else {
25253 generate_exception_err(ctx, EXCP_CpU, 1);
25255 break;
25257 #if defined(TARGET_MIPS64)
25258 /* MIPS64 opcodes */
25259 case OPC_LLD:
25260 if (ctx->insn_flags & INSN_R5900) {
25261 check_insn_opc_user_only(ctx, INSN_R5900);
25263 /* fall through */
25264 case OPC_LDL:
25265 case OPC_LDR:
25266 case OPC_LWU:
25267 case OPC_LD:
25268 check_insn(ctx, ISA_MIPS3);
25269 check_mips_64(ctx);
25270 gen_ld(ctx, op, rt, rs, imm);
25271 break;
25272 case OPC_SDL:
25273 case OPC_SDR:
25274 case OPC_SD:
25275 check_insn(ctx, ISA_MIPS3);
25276 check_mips_64(ctx);
25277 gen_st(ctx, op, rt, rs, imm);
25278 break;
25279 case OPC_SCD:
25280 check_insn(ctx, ISA_MIPS3);
25281 if (ctx->insn_flags & INSN_R5900) {
25282 check_insn_opc_user_only(ctx, INSN_R5900);
25284 check_mips_64(ctx);
25285 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
25286 break;
25287 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
25288 if (ctx->insn_flags & ISA_MIPS_R6) {
25289 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
25290 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25291 } else {
25292 /* OPC_DADDI */
25293 check_insn(ctx, ISA_MIPS3);
25294 check_mips_64(ctx);
25295 gen_arith_imm(ctx, op, rt, rs, imm);
25297 break;
25298 case OPC_DADDIU:
25299 check_insn(ctx, ISA_MIPS3);
25300 check_mips_64(ctx);
25301 gen_arith_imm(ctx, op, rt, rs, imm);
25302 break;
25303 #else
25304 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
25305 if (ctx->insn_flags & ISA_MIPS_R6) {
25306 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25307 } else {
25308 MIPS_INVAL("major opcode");
25309 gen_reserved_instruction(ctx);
25311 break;
25312 #endif
25313 case OPC_DAUI: /* OPC_JALX */
25314 if (ctx->insn_flags & ISA_MIPS_R6) {
25315 #if defined(TARGET_MIPS64)
25316 /* OPC_DAUI */
25317 check_mips_64(ctx);
25318 if (rs == 0) {
25319 generate_exception(ctx, EXCP_RI);
25320 } else if (rt != 0) {
25321 TCGv t0 = tcg_temp_new();
25322 gen_load_gpr(t0, rs);
25323 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
25324 tcg_temp_free(t0);
25326 #else
25327 gen_reserved_instruction(ctx);
25328 MIPS_INVAL("major opcode");
25329 #endif
25330 } else {
25331 /* OPC_JALX */
25332 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
25333 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
25334 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
25336 break;
25337 case OPC_MDMX: /* MMI_OPC_LQ */
25338 if (ctx->insn_flags & INSN_R5900) {
25339 #if defined(TARGET_MIPS64)
25340 gen_mmi_lq(env, ctx);
25341 #endif
25342 } else {
25343 /* MDMX: Not implemented. */
25345 break;
25346 case OPC_PCREL:
25347 check_insn(ctx, ISA_MIPS_R6);
25348 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
25349 break;
25350 default: /* Invalid */
25351 MIPS_INVAL("major opcode");
25352 return false;
25354 return true;
25357 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
25359 /* make sure instructions are on a word boundary */
25360 if (ctx->base.pc_next & 0x3) {
25361 env->CP0_BadVAddr = ctx->base.pc_next;
25362 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
25363 return;
25366 /* Handle blikely not taken case */
25367 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
25368 TCGLabel *l1 = gen_new_label();
25370 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
25371 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
25372 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
25373 gen_set_label(l1);
25376 /* Transition to the auto-generated decoder. */
25378 /* ISA extensions */
25379 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
25380 return;
25383 /* ISA (from latest to oldest) */
25384 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
25385 return;
25387 if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
25388 return;
25391 if (decode_opc_legacy(env, ctx)) {
25392 return;
25395 gen_reserved_instruction(ctx);
25398 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
25400 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25401 CPUMIPSState *env = cs->env_ptr;
25403 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
25404 ctx->saved_pc = -1;
25405 ctx->insn_flags = env->insn_flags;
25406 ctx->CP0_Config1 = env->CP0_Config1;
25407 ctx->CP0_Config2 = env->CP0_Config2;
25408 ctx->CP0_Config3 = env->CP0_Config3;
25409 ctx->CP0_Config5 = env->CP0_Config5;
25410 ctx->btarget = 0;
25411 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
25412 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
25413 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
25414 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
25415 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
25416 ctx->PAMask = env->PAMask;
25417 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
25418 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
25419 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
25420 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
25421 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
25422 /* Restore delay slot state from the tb context. */
25423 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
25424 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
25425 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
25426 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
25427 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
25428 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
25429 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
25430 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
25431 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
25432 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
25433 restore_cpu_state(env, ctx);
25434 #ifdef CONFIG_USER_ONLY
25435 ctx->mem_idx = MIPS_HFLAG_UM;
25436 #else
25437 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
25438 #endif
25439 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
25440 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
25442 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
25443 ctx->hflags);
25446 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
25450 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
25452 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25454 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
25455 ctx->btarget);
25458 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
25459 const CPUBreakpoint *bp)
25461 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25463 save_cpu_state(ctx, 1);
25464 ctx->base.is_jmp = DISAS_NORETURN;
25465 gen_helper_raise_exception_debug(cpu_env);
25467 * The address covered by the breakpoint must be included in
25468 * [tb->pc, tb->pc + tb->size) in order to for it to be
25469 * properly cleared -- thus we increment the PC here so that
25470 * the logic setting tb->size below does the right thing.
25472 ctx->base.pc_next += 4;
25473 return true;
25476 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
25478 CPUMIPSState *env = cs->env_ptr;
25479 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25480 int insn_bytes;
25481 int is_slot;
25483 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
25484 if (ctx->insn_flags & ISA_NANOMIPS32) {
25485 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
25486 insn_bytes = decode_nanomips_opc(env, ctx);
25487 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
25488 ctx->opcode = translator_ldl(env, ctx->base.pc_next);
25489 insn_bytes = 4;
25490 decode_opc(env, ctx);
25491 } else if (ctx->insn_flags & ASE_MICROMIPS) {
25492 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
25493 insn_bytes = decode_micromips_opc(env, ctx);
25494 } else if (ctx->insn_flags & ASE_MIPS16) {
25495 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
25496 insn_bytes = decode_mips16_opc(env, ctx);
25497 } else {
25498 gen_reserved_instruction(ctx);
25499 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
25500 return;
25503 if (ctx->hflags & MIPS_HFLAG_BMASK) {
25504 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
25505 MIPS_HFLAG_FBNSLOT))) {
25507 * Force to generate branch as there is neither delay nor
25508 * forbidden slot.
25510 is_slot = 1;
25512 if ((ctx->hflags & MIPS_HFLAG_M16) &&
25513 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
25515 * Force to generate branch as microMIPS R6 doesn't restrict
25516 * branches in the forbidden slot.
25518 is_slot = 1;
25521 if (is_slot) {
25522 gen_branch(ctx, insn_bytes);
25524 ctx->base.pc_next += insn_bytes;
25526 if (ctx->base.is_jmp != DISAS_NEXT) {
25527 return;
25530 * Execute a branch and its delay slot as a single instruction.
25531 * This is what GDB expects and is consistent with what the
25532 * hardware does (e.g. if a delay slot instruction faults, the
25533 * reported PC is the PC of the branch).
25535 if (ctx->base.singlestep_enabled &&
25536 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
25537 ctx->base.is_jmp = DISAS_TOO_MANY;
25539 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
25540 ctx->base.is_jmp = DISAS_TOO_MANY;
25544 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
25546 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25548 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
25549 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
25550 gen_helper_raise_exception_debug(cpu_env);
25551 } else {
25552 switch (ctx->base.is_jmp) {
25553 case DISAS_STOP:
25554 gen_save_pc(ctx->base.pc_next);
25555 tcg_gen_lookup_and_goto_ptr();
25556 break;
25557 case DISAS_NEXT:
25558 case DISAS_TOO_MANY:
25559 save_cpu_state(ctx, 0);
25560 gen_goto_tb(ctx, 0, ctx->base.pc_next);
25561 break;
25562 case DISAS_EXIT:
25563 tcg_gen_exit_tb(NULL, 0);
25564 break;
25565 case DISAS_NORETURN:
25566 break;
25567 default:
25568 g_assert_not_reached();
25573 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
25575 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
25576 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
25579 static const TranslatorOps mips_tr_ops = {
25580 .init_disas_context = mips_tr_init_disas_context,
25581 .tb_start = mips_tr_tb_start,
25582 .insn_start = mips_tr_insn_start,
25583 .breakpoint_check = mips_tr_breakpoint_check,
25584 .translate_insn = mips_tr_translate_insn,
25585 .tb_stop = mips_tr_tb_stop,
25586 .disas_log = mips_tr_disas_log,
25589 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
25591 DisasContext ctx;
25593 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
25596 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
25598 int i;
25599 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
25601 #define printfpr(fp) \
25602 do { \
25603 if (is_fpu64) \
25604 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
25605 " fd:%13g fs:%13g psu: %13g\n", \
25606 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
25607 (double)(fp)->fd, \
25608 (double)(fp)->fs[FP_ENDIAN_IDX], \
25609 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
25610 else { \
25611 fpr_t tmp; \
25612 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
25613 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
25614 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
25615 " fd:%13g fs:%13g psu:%13g\n", \
25616 tmp.w[FP_ENDIAN_IDX], tmp.d, \
25617 (double)tmp.fd, \
25618 (double)tmp.fs[FP_ENDIAN_IDX], \
25619 (double)tmp.fs[!FP_ENDIAN_IDX]); \
25621 } while (0)
25624 qemu_fprintf(f,
25625 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
25626 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
25627 get_float_exception_flags(&env->active_fpu.fp_status));
25628 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
25629 qemu_fprintf(f, "%3s: ", fregnames[i]);
25630 printfpr(&env->active_fpu.fpr[i]);
25633 #undef printfpr
25636 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
25638 MIPSCPU *cpu = MIPS_CPU(cs);
25639 CPUMIPSState *env = &cpu->env;
25640 int i;
25642 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
25643 " LO=0x" TARGET_FMT_lx " ds %04x "
25644 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
25645 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
25646 env->hflags, env->btarget, env->bcond);
25647 for (i = 0; i < 32; i++) {
25648 if ((i & 3) == 0) {
25649 qemu_fprintf(f, "GPR%02d:", i);
25651 qemu_fprintf(f, " %s " TARGET_FMT_lx,
25652 regnames[i], env->active_tc.gpr[i]);
25653 if ((i & 3) == 3) {
25654 qemu_fprintf(f, "\n");
25658 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
25659 TARGET_FMT_lx "\n",
25660 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
25661 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
25662 PRIx64 "\n",
25663 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
25664 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
25665 env->CP0_Config2, env->CP0_Config3);
25666 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
25667 env->CP0_Config4, env->CP0_Config5);
25668 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
25669 fpu_dump_state(env, f, flags);
25673 void mips_tcg_init(void)
25675 int i;
25677 cpu_gpr[0] = NULL;
25678 for (i = 1; i < 32; i++)
25679 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
25680 offsetof(CPUMIPSState,
25681 active_tc.gpr[i]),
25682 regnames[i]);
25683 #if defined(TARGET_MIPS64)
25684 cpu_gpr_hi[0] = NULL;
25686 for (unsigned i = 1; i < 32; i++) {
25687 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
25689 cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env,
25690 offsetof(CPUMIPSState,
25691 active_tc.gpr_hi[i]),
25692 rname);
25694 #endif /* !TARGET_MIPS64 */
25695 for (i = 0; i < 32; i++) {
25696 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
25698 fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
25700 msa_translate_init();
25701 cpu_PC = tcg_global_mem_new(cpu_env,
25702 offsetof(CPUMIPSState, active_tc.PC), "PC");
25703 for (i = 0; i < MIPS_DSP_ACC; i++) {
25704 cpu_HI[i] = tcg_global_mem_new(cpu_env,
25705 offsetof(CPUMIPSState, active_tc.HI[i]),
25706 regnames_HI[i]);
25707 cpu_LO[i] = tcg_global_mem_new(cpu_env,
25708 offsetof(CPUMIPSState, active_tc.LO[i]),
25709 regnames_LO[i]);
25711 cpu_dspctrl = tcg_global_mem_new(cpu_env,
25712 offsetof(CPUMIPSState,
25713 active_tc.DSPControl),
25714 "DSPControl");
25715 bcond = tcg_global_mem_new(cpu_env,
25716 offsetof(CPUMIPSState, bcond), "bcond");
25717 btarget = tcg_global_mem_new(cpu_env,
25718 offsetof(CPUMIPSState, btarget), "btarget");
25719 hflags = tcg_global_mem_new_i32(cpu_env,
25720 offsetof(CPUMIPSState, hflags), "hflags");
25722 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
25723 offsetof(CPUMIPSState, active_fpu.fcr0),
25724 "fcr0");
25725 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
25726 offsetof(CPUMIPSState, active_fpu.fcr31),
25727 "fcr31");
25728 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
25729 "lladdr");
25730 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
25731 "llval");
25733 if (TARGET_LONG_BITS == 32) {
25734 mxu_translate_init();
25738 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
25739 target_ulong *data)
25741 env->active_tc.PC = data[0];
25742 env->hflags &= ~MIPS_HFLAG_BMASK;
25743 env->hflags |= data[1];
25744 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
25745 case MIPS_HFLAG_BR:
25746 break;
25747 case MIPS_HFLAG_BC:
25748 case MIPS_HFLAG_BL:
25749 case MIPS_HFLAG_B:
25750 env->btarget = data[2];
25751 break;