target/mips/tx79: Move MTHI1 / MTLO1 opcodes to decodetree
[qemu/ar7.git] / target / mips / translate.c
blob256e2956c4b01909a148fd676a925e28947099ca
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 * Overview of the TX79-specific instruction set
1134 * =============================================
1136 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
1137 * are only used by the specific quadword (128-bit) LQ/SQ load/store
1138 * instructions and certain multimedia instructions (MMIs). These MMIs
1139 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
1140 * or sixteen 8-bit paths.
1142 * Reference:
1144 * The Toshiba TX System RISC TX79 Core Architecture manual,
1145 * https://wiki.qemu.org/File:C790.pdf
1147 * Three-Operand Multiply and Multiply-Add (4 instructions)
1148 * --------------------------------------------------------
1149 * MADD [rd,] rs, rt Multiply/Add
1150 * MADDU [rd,] rs, rt Multiply/Add Unsigned
1151 * MULT [rd,] rs, rt Multiply (3-operand)
1152 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
1154 * Multiply Instructions for Pipeline 1 (10 instructions)
1155 * ------------------------------------------------------
1156 * MULT1 [rd,] rs, rt Multiply Pipeline 1
1157 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
1158 * DIV1 rs, rt Divide Pipeline 1
1159 * DIVU1 rs, rt Divide Unsigned Pipeline 1
1160 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
1161 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
1162 * MFHI1 rd Move From HI1 Register
1163 * MFLO1 rd Move From LO1 Register
1164 * MTHI1 rs Move To HI1 Register
1165 * MTLO1 rs Move To LO1 Register
1167 * Arithmetic (19 instructions)
1168 * ----------------------------
1169 * PADDB rd, rs, rt Parallel Add Byte
1170 * PSUBB rd, rs, rt Parallel Subtract Byte
1171 * PADDH rd, rs, rt Parallel Add Halfword
1172 * PSUBH rd, rs, rt Parallel Subtract Halfword
1173 * PADDW rd, rs, rt Parallel Add Word
1174 * PSUBW rd, rs, rt Parallel Subtract Word
1175 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
1176 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
1177 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
1178 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
1179 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
1180 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
1181 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
1182 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
1183 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
1184 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
1185 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
1186 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
1187 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
1189 * Min/Max (4 instructions)
1190 * ------------------------
1191 * PMAXH rd, rs, rt Parallel Maximum Halfword
1192 * PMINH rd, rs, rt Parallel Minimum Halfword
1193 * PMAXW rd, rs, rt Parallel Maximum Word
1194 * PMINW rd, rs, rt Parallel Minimum Word
1196 * Absolute (2 instructions)
1197 * -------------------------
1198 * PABSH rd, rt Parallel Absolute Halfword
1199 * PABSW rd, rt Parallel Absolute Word
1201 * Logical (4 instructions)
1202 * ------------------------
1203 * PAND rd, rs, rt Parallel AND
1204 * POR rd, rs, rt Parallel OR
1205 * PXOR rd, rs, rt Parallel XOR
1206 * PNOR rd, rs, rt Parallel NOR
1208 * Shift (9 instructions)
1209 * ----------------------
1210 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
1211 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
1212 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
1213 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
1214 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
1215 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
1216 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
1217 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
1218 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
1220 * Compare (6 instructions)
1221 * ------------------------
1222 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
1223 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
1224 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
1225 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
1226 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
1227 * PCEQW rd, rs, rt Parallel Compare for Equal Word
1229 * LZC (1 instruction)
1230 * -------------------
1231 * PLZCW rd, rs Parallel Leading Zero or One Count Word
1233 * Quadword Load and Store (2 instructions)
1234 * ----------------------------------------
1235 * LQ rt, offset(base) Load Quadword
1236 * SQ rt, offset(base) Store Quadword
1238 * Multiply and Divide (19 instructions)
1239 * -------------------------------------
1240 * PMULTW rd, rs, rt Parallel Multiply Word
1241 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
1242 * PDIVW rs, rt Parallel Divide Word
1243 * PDIVUW rs, rt Parallel Divide Unsigned Word
1244 * PMADDW rd, rs, rt Parallel Multiply-Add Word
1245 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
1246 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
1247 * PMULTH rd, rs, rt Parallel Multiply Halfword
1248 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
1249 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
1250 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
1251 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
1252 * PDIVBW rs, rt Parallel Divide Broadcast Word
1253 * PMFHI rd Parallel Move From HI Register
1254 * PMFLO rd Parallel Move From LO Register
1255 * PMTHI rs Parallel Move To HI Register
1256 * PMTLO rs Parallel Move To LO Register
1257 * PMFHL rd Parallel Move From HI/LO Register
1258 * PMTHL rs Parallel Move To HI/LO Register
1260 * Pack/Extend (11 instructions)
1261 * -----------------------------
1262 * PPAC5 rd, rt Parallel Pack to 5 bits
1263 * PPACB rd, rs, rt Parallel Pack to Byte
1264 * PPACH rd, rs, rt Parallel Pack to Halfword
1265 * PPACW rd, rs, rt Parallel Pack to Word
1266 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
1267 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
1268 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
1269 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
1270 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
1271 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
1272 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
1274 * Others (16 instructions)
1275 * ------------------------
1276 * PCPYH rd, rt Parallel Copy Halfword
1277 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
1278 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
1279 * PREVH rd, rt Parallel Reverse Halfword
1280 * PINTH rd, rs, rt Parallel Interleave Halfword
1281 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
1282 * PEXEH rd, rt Parallel Exchange Even Halfword
1283 * PEXCH rd, rt Parallel Exchange Center Halfword
1284 * PEXEW rd, rt Parallel Exchange Even Word
1285 * PEXCW rd, rt Parallel Exchange Center Word
1286 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
1287 * MFSA rd Move from Shift Amount Register
1288 * MTSA rs Move to Shift Amount Register
1289 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
1290 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
1291 * PROT3W rd, rt Parallel Rotate 3 Words
1293 * MMI (MultiMedia Instruction) encodings
1294 * ======================================
1296 * MMI instructions encoding table keys:
1298 * * This code is reserved for future use. An attempt to execute it
1299 * causes a Reserved Instruction exception.
1300 * % This code indicates an instruction class. The instruction word
1301 * must be further decoded by examining additional tables that show
1302 * the values for other instruction fields.
1303 * # This code is reserved for the unsupported instructions DMULT,
1304 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
1305 * to execute it causes a Reserved Instruction exception.
1307 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
1309 * 31 26 0
1310 * +--------+----------------------------------------+
1311 * | opcode | |
1312 * +--------+----------------------------------------+
1314 * opcode bits 28..26
1315 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1316 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1317 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1318 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
1319 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
1320 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
1321 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
1322 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
1323 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
1324 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
1325 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
1328 enum {
1329 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
1330 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
1331 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
1335 * MMI instructions with opcode field = MMI:
1337 * 31 26 5 0
1338 * +--------+-------------------------------+--------+
1339 * | MMI | |function|
1340 * +--------+-------------------------------+--------+
1342 * function bits 2..0
1343 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1344 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1345 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1346 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
1347 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
1348 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
1349 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
1350 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
1351 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
1352 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
1353 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
1356 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
1357 enum {
1358 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
1359 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
1360 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
1361 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
1362 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
1363 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
1364 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
1365 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
1366 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
1367 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
1368 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
1369 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
1370 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
1371 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
1372 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
1373 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
1374 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
1375 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
1376 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
1377 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
1378 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
1382 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
1384 * 31 26 10 6 5 0
1385 * +--------+----------------------+--------+--------+
1386 * | MMI | |function| MMI0 |
1387 * +--------+----------------------+--------+--------+
1389 * function bits 7..6
1390 * bits | 0 | 1 | 2 | 3
1391 * 10..8 | 00 | 01 | 10 | 11
1392 * -------+-------+-------+-------+-------
1393 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
1394 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
1395 * 2 010 | PADDB | PSUBB | PCGTB | *
1396 * 3 011 | * | * | * | *
1397 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
1398 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
1399 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
1400 * 7 111 | * | * | PEXT5 | PPAC5
1403 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
1404 enum {
1405 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
1406 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
1407 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
1408 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
1409 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
1410 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
1411 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
1412 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
1413 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
1414 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
1415 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
1416 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
1417 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
1418 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
1419 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
1420 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
1421 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
1422 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
1423 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
1424 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
1425 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
1426 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
1427 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
1428 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
1429 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
1433 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
1435 * 31 26 10 6 5 0
1436 * +--------+----------------------+--------+--------+
1437 * | MMI | |function| MMI1 |
1438 * +--------+----------------------+--------+--------+
1440 * function bits 7..6
1441 * bits | 0 | 1 | 2 | 3
1442 * 10..8 | 00 | 01 | 10 | 11
1443 * -------+-------+-------+-------+-------
1444 * 0 000 | * | PABSW | PCEQW | PMINW
1445 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
1446 * 2 010 | * | * | PCEQB | *
1447 * 3 011 | * | * | * | *
1448 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
1449 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
1450 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
1451 * 7 111 | * | * | * | *
1454 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
1455 enum {
1456 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
1457 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
1458 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
1459 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
1460 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
1461 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
1462 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
1463 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
1464 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
1465 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
1466 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
1467 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
1468 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
1469 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
1470 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
1471 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
1472 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
1473 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
1477 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
1479 * 31 26 10 6 5 0
1480 * +--------+----------------------+--------+--------+
1481 * | MMI | |function| MMI2 |
1482 * +--------+----------------------+--------+--------+
1484 * function bits 7..6
1485 * bits | 0 | 1 | 2 | 3
1486 * 10..8 | 00 | 01 | 10 | 11
1487 * -------+-------+-------+-------+-------
1488 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
1489 * 1 001 | PMSUBW| * | * | *
1490 * 2 010 | PMFHI | PMFLO | PINTH | *
1491 * 3 011 | PMULTW| PDIVW | PCPYLD| *
1492 * 4 100 | PMADDH| PHMADH| PAND | PXOR
1493 * 5 101 | PMSUBH| PHMSBH| * | *
1494 * 6 110 | * | * | PEXEH | PREVH
1495 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
1498 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
1499 enum {
1500 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
1501 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
1502 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
1503 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
1504 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
1505 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
1506 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
1507 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
1508 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
1509 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
1510 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
1511 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
1512 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
1513 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
1514 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
1515 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
1516 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
1517 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
1518 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
1519 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
1520 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
1521 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
1525 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
1527 * 31 26 10 6 5 0
1528 * +--------+----------------------+--------+--------+
1529 * | MMI | |function| MMI3 |
1530 * +--------+----------------------+--------+--------+
1532 * function bits 7..6
1533 * bits | 0 | 1 | 2 | 3
1534 * 10..8 | 00 | 01 | 10 | 11
1535 * -------+-------+-------+-------+-------
1536 * 0 000 |PMADDUW| * | * | PSRAVW
1537 * 1 001 | * | * | * | *
1538 * 2 010 | PMTHI | PMTLO | PINTEH| *
1539 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
1540 * 4 100 | * | * | POR | PNOR
1541 * 5 101 | * | * | * | *
1542 * 6 110 | * | * | PEXCH | PCPYH
1543 * 7 111 | * | * | PEXCW | *
1546 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
1547 enum {
1548 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
1549 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
1550 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
1551 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
1552 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
1553 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
1554 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
1555 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
1556 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
1557 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
1558 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
1559 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
1560 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
1563 /* global register indices */
1564 TCGv cpu_gpr[32], cpu_PC;
1566 * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[])
1567 * and the upper halves in cpu_gpr_hi[].
1569 TCGv_i64 cpu_gpr_hi[32];
1570 TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1571 static TCGv cpu_dspctrl, btarget;
1572 TCGv bcond;
1573 static TCGv cpu_lladdr, cpu_llval;
1574 static TCGv_i32 hflags;
1575 TCGv_i32 fpu_fcr0, fpu_fcr31;
1576 TCGv_i64 fpu_f64[32];
1578 #include "exec/gen-icount.h"
1580 #define gen_helper_0e0i(name, arg) do { \
1581 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1582 gen_helper_##name(cpu_env, helper_tmp); \
1583 tcg_temp_free_i32(helper_tmp); \
1584 } while (0)
1586 #define gen_helper_0e1i(name, arg1, arg2) do { \
1587 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1588 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1589 tcg_temp_free_i32(helper_tmp); \
1590 } while (0)
1592 #define gen_helper_1e0i(name, ret, arg1) do { \
1593 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1594 gen_helper_##name(ret, cpu_env, helper_tmp); \
1595 tcg_temp_free_i32(helper_tmp); \
1596 } while (0)
1598 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1599 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1600 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1601 tcg_temp_free_i32(helper_tmp); \
1602 } while (0)
1604 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1605 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1606 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1607 tcg_temp_free_i32(helper_tmp); \
1608 } while (0)
1610 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1611 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1612 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1613 tcg_temp_free_i32(helper_tmp); \
1614 } while (0)
1616 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1617 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1618 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1619 tcg_temp_free_i32(helper_tmp); \
1620 } while (0)
1622 #define DISAS_STOP DISAS_TARGET_0
1623 #define DISAS_EXIT DISAS_TARGET_1
1625 static const char * const regnames[] = {
1626 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1627 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1628 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1629 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1632 static const char * const regnames_HI[] = {
1633 "HI0", "HI1", "HI2", "HI3",
1636 static const char * const regnames_LO[] = {
1637 "LO0", "LO1", "LO2", "LO3",
1640 static const char * const fregnames[] = {
1641 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1642 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1643 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1644 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1647 /* General purpose registers moves. */
1648 void gen_load_gpr(TCGv t, int reg)
1650 if (reg == 0) {
1651 tcg_gen_movi_tl(t, 0);
1652 } else {
1653 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1657 void gen_store_gpr(TCGv t, int reg)
1659 if (reg != 0) {
1660 tcg_gen_mov_tl(cpu_gpr[reg], t);
1664 #if defined(TARGET_MIPS64)
1665 void gen_load_gpr_hi(TCGv_i64 t, int reg)
1667 if (reg == 0) {
1668 tcg_gen_movi_i64(t, 0);
1669 } else {
1670 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
1674 void gen_store_gpr_hi(TCGv_i64 t, int reg)
1676 if (reg != 0) {
1677 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
1680 #endif /* TARGET_MIPS64 */
1682 /* Moves to/from shadow registers. */
1683 static inline void gen_load_srsgpr(int from, int to)
1685 TCGv t0 = tcg_temp_new();
1687 if (from == 0) {
1688 tcg_gen_movi_tl(t0, 0);
1689 } else {
1690 TCGv_i32 t2 = tcg_temp_new_i32();
1691 TCGv_ptr addr = tcg_temp_new_ptr();
1693 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1694 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1695 tcg_gen_andi_i32(t2, t2, 0xf);
1696 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1697 tcg_gen_ext_i32_ptr(addr, t2);
1698 tcg_gen_add_ptr(addr, cpu_env, addr);
1700 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1701 tcg_temp_free_ptr(addr);
1702 tcg_temp_free_i32(t2);
1704 gen_store_gpr(t0, to);
1705 tcg_temp_free(t0);
1708 static inline void gen_store_srsgpr(int from, int to)
1710 if (to != 0) {
1711 TCGv t0 = tcg_temp_new();
1712 TCGv_i32 t2 = tcg_temp_new_i32();
1713 TCGv_ptr addr = tcg_temp_new_ptr();
1715 gen_load_gpr(t0, from);
1716 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1717 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1718 tcg_gen_andi_i32(t2, t2, 0xf);
1719 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1720 tcg_gen_ext_i32_ptr(addr, t2);
1721 tcg_gen_add_ptr(addr, cpu_env, addr);
1723 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1724 tcg_temp_free_ptr(addr);
1725 tcg_temp_free_i32(t2);
1726 tcg_temp_free(t0);
1730 /* Tests */
1731 static inline void gen_save_pc(target_ulong pc)
1733 tcg_gen_movi_tl(cpu_PC, pc);
1736 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1738 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1739 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1740 gen_save_pc(ctx->base.pc_next);
1741 ctx->saved_pc = ctx->base.pc_next;
1743 if (ctx->hflags != ctx->saved_hflags) {
1744 tcg_gen_movi_i32(hflags, ctx->hflags);
1745 ctx->saved_hflags = ctx->hflags;
1746 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1747 case MIPS_HFLAG_BR:
1748 break;
1749 case MIPS_HFLAG_BC:
1750 case MIPS_HFLAG_BL:
1751 case MIPS_HFLAG_B:
1752 tcg_gen_movi_tl(btarget, ctx->btarget);
1753 break;
1758 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1760 ctx->saved_hflags = ctx->hflags;
1761 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1762 case MIPS_HFLAG_BR:
1763 break;
1764 case MIPS_HFLAG_BC:
1765 case MIPS_HFLAG_BL:
1766 case MIPS_HFLAG_B:
1767 ctx->btarget = env->btarget;
1768 break;
1772 void generate_exception_err(DisasContext *ctx, int excp, int err)
1774 TCGv_i32 texcp = tcg_const_i32(excp);
1775 TCGv_i32 terr = tcg_const_i32(err);
1776 save_cpu_state(ctx, 1);
1777 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1778 tcg_temp_free_i32(terr);
1779 tcg_temp_free_i32(texcp);
1780 ctx->base.is_jmp = DISAS_NORETURN;
1783 void generate_exception(DisasContext *ctx, int excp)
1785 gen_helper_0e0i(raise_exception, excp);
1788 void generate_exception_end(DisasContext *ctx, int excp)
1790 generate_exception_err(ctx, excp, 0);
1793 void gen_reserved_instruction(DisasContext *ctx)
1795 generate_exception_end(ctx, EXCP_RI);
1798 /* Floating point register moves. */
1799 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1801 if (ctx->hflags & MIPS_HFLAG_FRE) {
1802 generate_exception(ctx, EXCP_RI);
1804 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1807 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1809 TCGv_i64 t64;
1810 if (ctx->hflags & MIPS_HFLAG_FRE) {
1811 generate_exception(ctx, EXCP_RI);
1813 t64 = tcg_temp_new_i64();
1814 tcg_gen_extu_i32_i64(t64, t);
1815 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1816 tcg_temp_free_i64(t64);
1819 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1821 if (ctx->hflags & MIPS_HFLAG_F64) {
1822 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1823 } else {
1824 gen_load_fpr32(ctx, t, reg | 1);
1828 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1830 if (ctx->hflags & MIPS_HFLAG_F64) {
1831 TCGv_i64 t64 = tcg_temp_new_i64();
1832 tcg_gen_extu_i32_i64(t64, t);
1833 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1834 tcg_temp_free_i64(t64);
1835 } else {
1836 gen_store_fpr32(ctx, t, reg | 1);
1840 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1842 if (ctx->hflags & MIPS_HFLAG_F64) {
1843 tcg_gen_mov_i64(t, fpu_f64[reg]);
1844 } else {
1845 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1849 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1851 if (ctx->hflags & MIPS_HFLAG_F64) {
1852 tcg_gen_mov_i64(fpu_f64[reg], t);
1853 } else {
1854 TCGv_i64 t0;
1855 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1856 t0 = tcg_temp_new_i64();
1857 tcg_gen_shri_i64(t0, t, 32);
1858 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1859 tcg_temp_free_i64(t0);
1863 int get_fp_bit(int cc)
1865 if (cc) {
1866 return 24 + cc;
1867 } else {
1868 return 23;
1872 /* Addresses computation */
1873 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1875 tcg_gen_add_tl(ret, arg0, arg1);
1877 #if defined(TARGET_MIPS64)
1878 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1879 tcg_gen_ext32s_i64(ret, ret);
1881 #endif
1884 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
1885 target_long ofs)
1887 tcg_gen_addi_tl(ret, base, ofs);
1889 #if defined(TARGET_MIPS64)
1890 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1891 tcg_gen_ext32s_i64(ret, ret);
1893 #endif
1896 /* Addresses computation (translation time) */
1897 static target_long addr_add(DisasContext *ctx, target_long base,
1898 target_long offset)
1900 target_long sum = base + offset;
1902 #if defined(TARGET_MIPS64)
1903 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1904 sum = (int32_t)sum;
1906 #endif
1907 return sum;
1910 /* Sign-extract the low 32-bits to a target_long. */
1911 void gen_move_low32(TCGv ret, TCGv_i64 arg)
1913 #if defined(TARGET_MIPS64)
1914 tcg_gen_ext32s_i64(ret, arg);
1915 #else
1916 tcg_gen_extrl_i64_i32(ret, arg);
1917 #endif
1920 /* Sign-extract the high 32-bits to a target_long. */
1921 void gen_move_high32(TCGv ret, TCGv_i64 arg)
1923 #if defined(TARGET_MIPS64)
1924 tcg_gen_sari_i64(ret, arg, 32);
1925 #else
1926 tcg_gen_extrh_i64_i32(ret, arg);
1927 #endif
1930 void check_cp0_enabled(DisasContext *ctx)
1932 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1933 generate_exception_end(ctx, EXCP_CpU);
1937 void check_cp1_enabled(DisasContext *ctx)
1939 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
1940 generate_exception_err(ctx, EXCP_CpU, 1);
1945 * Verify that the processor is running with COP1X instructions enabled.
1946 * This is associated with the nabla symbol in the MIPS32 and MIPS64
1947 * opcode tables.
1949 void check_cop1x(DisasContext *ctx)
1951 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
1952 gen_reserved_instruction(ctx);
1957 * Verify that the processor is running with 64-bit floating-point
1958 * operations enabled.
1960 void check_cp1_64bitmode(DisasContext *ctx)
1962 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
1963 gen_reserved_instruction(ctx);
1968 * Verify if floating point register is valid; an operation is not defined
1969 * if bit 0 of any register specification is set and the FR bit in the
1970 * Status register equals zero, since the register numbers specify an
1971 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1972 * in the Status register equals one, both even and odd register numbers
1973 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1975 * Multiple 64 bit wide registers can be checked by calling
1976 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1978 void check_cp1_registers(DisasContext *ctx, int regs)
1980 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
1981 gen_reserved_instruction(ctx);
1986 * Verify that the processor is running with DSP instructions enabled.
1987 * This is enabled by CP0 Status register MX(24) bit.
1989 static inline void check_dsp(DisasContext *ctx)
1991 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1992 if (ctx->insn_flags & ASE_DSP) {
1993 generate_exception_end(ctx, EXCP_DSPDIS);
1994 } else {
1995 gen_reserved_instruction(ctx);
2000 static inline void check_dsp_r2(DisasContext *ctx)
2002 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2003 if (ctx->insn_flags & ASE_DSP) {
2004 generate_exception_end(ctx, EXCP_DSPDIS);
2005 } else {
2006 gen_reserved_instruction(ctx);
2011 static inline void check_dsp_r3(DisasContext *ctx)
2013 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2014 if (ctx->insn_flags & ASE_DSP) {
2015 generate_exception_end(ctx, EXCP_DSPDIS);
2016 } else {
2017 gen_reserved_instruction(ctx);
2023 * This code generates a "reserved instruction" exception if the
2024 * CPU does not support the instruction set corresponding to flags.
2026 void check_insn(DisasContext *ctx, uint64_t flags)
2028 if (unlikely(!(ctx->insn_flags & flags))) {
2029 gen_reserved_instruction(ctx);
2034 * This code generates a "reserved instruction" exception if the
2035 * CPU has corresponding flag set which indicates that the instruction
2036 * has been removed.
2038 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2040 if (unlikely(ctx->insn_flags & flags)) {
2041 gen_reserved_instruction(ctx);
2046 * The Linux kernel traps certain reserved instruction exceptions to
2047 * emulate the corresponding instructions. QEMU is the kernel in user
2048 * mode, so those traps are emulated by accepting the instructions.
2050 * A reserved instruction exception is generated for flagged CPUs if
2051 * QEMU runs in system mode.
2053 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
2055 #ifndef CONFIG_USER_ONLY
2056 check_insn_opc_removed(ctx, flags);
2057 #endif
2061 * This code generates a "reserved instruction" exception if the
2062 * CPU does not support 64-bit paired-single (PS) floating point data type.
2064 static inline void check_ps(DisasContext *ctx)
2066 if (unlikely(!ctx->ps)) {
2067 generate_exception(ctx, EXCP_RI);
2069 check_cp1_64bitmode(ctx);
2073 * This code generates a "reserved instruction" exception if cpu is not
2074 * 64-bit or 64-bit instructions are not enabled.
2076 void check_mips_64(DisasContext *ctx)
2078 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
2079 gen_reserved_instruction(ctx);
2083 #ifndef CONFIG_USER_ONLY
2084 static inline void check_mvh(DisasContext *ctx)
2086 if (unlikely(!ctx->mvh)) {
2087 generate_exception(ctx, EXCP_RI);
2090 #endif
2093 * This code generates a "reserved instruction" exception if the
2094 * Config5 XNP bit is set.
2096 static inline void check_xnp(DisasContext *ctx)
2098 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2099 gen_reserved_instruction(ctx);
2103 #ifndef CONFIG_USER_ONLY
2105 * This code generates a "reserved instruction" exception if the
2106 * Config3 PW bit is NOT set.
2108 static inline void check_pw(DisasContext *ctx)
2110 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2111 gen_reserved_instruction(ctx);
2114 #endif
2117 * This code generates a "reserved instruction" exception if the
2118 * Config3 MT bit is NOT set.
2120 static inline void check_mt(DisasContext *ctx)
2122 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2123 gen_reserved_instruction(ctx);
2127 #ifndef CONFIG_USER_ONLY
2129 * This code generates a "coprocessor unusable" exception if CP0 is not
2130 * available, and, if that is not the case, generates a "reserved instruction"
2131 * exception if the Config5 MT bit is NOT set. This is needed for availability
2132 * control of some of MT ASE instructions.
2134 static inline void check_cp0_mt(DisasContext *ctx)
2136 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2137 generate_exception_end(ctx, EXCP_CpU);
2138 } else {
2139 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2140 gen_reserved_instruction(ctx);
2144 #endif
2147 * This code generates a "reserved instruction" exception if the
2148 * Config5 NMS bit is set.
2150 static inline void check_nms(DisasContext *ctx)
2152 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2153 gen_reserved_instruction(ctx);
2158 * This code generates a "reserved instruction" exception if the
2159 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
2160 * Config2 TL, and Config5 L2C are unset.
2162 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
2164 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
2165 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
2166 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
2167 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
2168 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
2169 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
2170 gen_reserved_instruction(ctx);
2175 * This code generates a "reserved instruction" exception if the
2176 * Config5 EVA bit is NOT set.
2178 static inline void check_eva(DisasContext *ctx)
2180 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
2181 gen_reserved_instruction(ctx);
2187 * Define small wrappers for gen_load_fpr* so that we have a uniform
2188 * calling interface for 32 and 64-bit FPRs. No sense in changing
2189 * all callers for gen_load_fpr32 when we need the CTX parameter for
2190 * this one use.
2192 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
2193 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
2194 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
2195 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
2196 int ft, int fs, int cc) \
2198 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
2199 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
2200 switch (ifmt) { \
2201 case FMT_PS: \
2202 check_ps(ctx); \
2203 break; \
2204 case FMT_D: \
2205 if (abs) { \
2206 check_cop1x(ctx); \
2208 check_cp1_registers(ctx, fs | ft); \
2209 break; \
2210 case FMT_S: \
2211 if (abs) { \
2212 check_cop1x(ctx); \
2214 break; \
2216 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
2217 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
2218 switch (n) { \
2219 case 0: \
2220 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
2221 break; \
2222 case 1: \
2223 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
2224 break; \
2225 case 2: \
2226 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
2227 break; \
2228 case 3: \
2229 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
2230 break; \
2231 case 4: \
2232 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
2233 break; \
2234 case 5: \
2235 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
2236 break; \
2237 case 6: \
2238 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
2239 break; \
2240 case 7: \
2241 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
2242 break; \
2243 case 8: \
2244 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
2245 break; \
2246 case 9: \
2247 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
2248 break; \
2249 case 10: \
2250 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
2251 break; \
2252 case 11: \
2253 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
2254 break; \
2255 case 12: \
2256 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
2257 break; \
2258 case 13: \
2259 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
2260 break; \
2261 case 14: \
2262 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
2263 break; \
2264 case 15: \
2265 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
2266 break; \
2267 default: \
2268 abort(); \
2270 tcg_temp_free_i##bits(fp0); \
2271 tcg_temp_free_i##bits(fp1); \
2274 FOP_CONDS(, 0, d, FMT_D, 64)
2275 FOP_CONDS(abs, 1, d, FMT_D, 64)
2276 FOP_CONDS(, 0, s, FMT_S, 32)
2277 FOP_CONDS(abs, 1, s, FMT_S, 32)
2278 FOP_CONDS(, 0, ps, FMT_PS, 64)
2279 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
2280 #undef FOP_CONDS
2282 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
2283 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
2284 int ft, int fs, int fd) \
2286 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
2287 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
2288 if (ifmt == FMT_D) { \
2289 check_cp1_registers(ctx, fs | ft | fd); \
2291 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
2292 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
2293 switch (n) { \
2294 case 0: \
2295 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
2296 break; \
2297 case 1: \
2298 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
2299 break; \
2300 case 2: \
2301 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
2302 break; \
2303 case 3: \
2304 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
2305 break; \
2306 case 4: \
2307 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
2308 break; \
2309 case 5: \
2310 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
2311 break; \
2312 case 6: \
2313 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
2314 break; \
2315 case 7: \
2316 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
2317 break; \
2318 case 8: \
2319 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
2320 break; \
2321 case 9: \
2322 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
2323 break; \
2324 case 10: \
2325 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2326 break; \
2327 case 11: \
2328 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2329 break; \
2330 case 12: \
2331 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2332 break; \
2333 case 13: \
2334 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2335 break; \
2336 case 14: \
2337 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
2338 break; \
2339 case 15: \
2340 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
2341 break; \
2342 case 17: \
2343 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
2344 break; \
2345 case 18: \
2346 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2347 break; \
2348 case 19: \
2349 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2350 break; \
2351 case 25: \
2352 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2353 break; \
2354 case 26: \
2355 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2356 break; \
2357 case 27: \
2358 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2359 break; \
2360 default: \
2361 abort(); \
2363 STORE; \
2364 tcg_temp_free_i ## bits(fp0); \
2365 tcg_temp_free_i ## bits(fp1); \
2368 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2369 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2370 #undef FOP_CONDNS
2371 #undef gen_ldcmp_fpr32
2372 #undef gen_ldcmp_fpr64
2374 /* load/store instructions. */
2375 #ifdef CONFIG_USER_ONLY
2376 #define OP_LD_ATOMIC(insn, fname) \
2377 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2378 DisasContext *ctx) \
2380 TCGv t0 = tcg_temp_new(); \
2381 tcg_gen_mov_tl(t0, arg1); \
2382 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2383 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2384 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2385 tcg_temp_free(t0); \
2387 #else
2388 #define OP_LD_ATOMIC(insn, fname) \
2389 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2390 DisasContext *ctx) \
2392 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2394 #endif
2395 OP_LD_ATOMIC(ll, ld32s);
2396 #if defined(TARGET_MIPS64)
2397 OP_LD_ATOMIC(lld, ld64);
2398 #endif
2399 #undef OP_LD_ATOMIC
2401 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
2403 if (base == 0) {
2404 tcg_gen_movi_tl(addr, offset);
2405 } else if (offset == 0) {
2406 gen_load_gpr(addr, base);
2407 } else {
2408 tcg_gen_movi_tl(addr, offset);
2409 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2413 static target_ulong pc_relative_pc(DisasContext *ctx)
2415 target_ulong pc = ctx->base.pc_next;
2417 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2418 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2420 pc -= branch_bytes;
2423 pc &= ~(target_ulong)3;
2424 return pc;
2427 /* Load */
2428 static void gen_ld(DisasContext *ctx, uint32_t opc,
2429 int rt, int base, int offset)
2431 TCGv t0, t1, t2;
2432 int mem_idx = ctx->mem_idx;
2434 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
2435 INSN_LOONGSON3A)) {
2437 * Loongson CPU uses a load to zero register for prefetch.
2438 * We emulate it as a NOP. On other CPU we must perform the
2439 * actual memory access.
2441 return;
2444 t0 = tcg_temp_new();
2445 gen_base_offset_addr(ctx, t0, base, offset);
2447 switch (opc) {
2448 #if defined(TARGET_MIPS64)
2449 case OPC_LWU:
2450 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
2451 ctx->default_tcg_memop_mask);
2452 gen_store_gpr(t0, rt);
2453 break;
2454 case OPC_LD:
2455 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
2456 ctx->default_tcg_memop_mask);
2457 gen_store_gpr(t0, rt);
2458 break;
2459 case OPC_LLD:
2460 case R6_OPC_LLD:
2461 op_ld_lld(t0, t0, mem_idx, ctx);
2462 gen_store_gpr(t0, rt);
2463 break;
2464 case OPC_LDL:
2465 t1 = tcg_temp_new();
2467 * Do a byte access to possibly trigger a page
2468 * fault with the unaligned address.
2470 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2471 tcg_gen_andi_tl(t1, t0, 7);
2472 #ifndef TARGET_WORDS_BIGENDIAN
2473 tcg_gen_xori_tl(t1, t1, 7);
2474 #endif
2475 tcg_gen_shli_tl(t1, t1, 3);
2476 tcg_gen_andi_tl(t0, t0, ~7);
2477 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2478 tcg_gen_shl_tl(t0, t0, t1);
2479 t2 = tcg_const_tl(-1);
2480 tcg_gen_shl_tl(t2, t2, t1);
2481 gen_load_gpr(t1, rt);
2482 tcg_gen_andc_tl(t1, t1, t2);
2483 tcg_temp_free(t2);
2484 tcg_gen_or_tl(t0, t0, t1);
2485 tcg_temp_free(t1);
2486 gen_store_gpr(t0, rt);
2487 break;
2488 case OPC_LDR:
2489 t1 = tcg_temp_new();
2491 * Do a byte access to possibly trigger a page
2492 * fault with the unaligned address.
2494 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2495 tcg_gen_andi_tl(t1, t0, 7);
2496 #ifdef TARGET_WORDS_BIGENDIAN
2497 tcg_gen_xori_tl(t1, t1, 7);
2498 #endif
2499 tcg_gen_shli_tl(t1, t1, 3);
2500 tcg_gen_andi_tl(t0, t0, ~7);
2501 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2502 tcg_gen_shr_tl(t0, t0, t1);
2503 tcg_gen_xori_tl(t1, t1, 63);
2504 t2 = tcg_const_tl(0xfffffffffffffffeull);
2505 tcg_gen_shl_tl(t2, t2, t1);
2506 gen_load_gpr(t1, rt);
2507 tcg_gen_and_tl(t1, t1, t2);
2508 tcg_temp_free(t2);
2509 tcg_gen_or_tl(t0, t0, t1);
2510 tcg_temp_free(t1);
2511 gen_store_gpr(t0, rt);
2512 break;
2513 case OPC_LDPC:
2514 t1 = tcg_const_tl(pc_relative_pc(ctx));
2515 gen_op_addr_add(ctx, t0, t0, t1);
2516 tcg_temp_free(t1);
2517 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2518 gen_store_gpr(t0, rt);
2519 break;
2520 #endif
2521 case OPC_LWPC:
2522 t1 = tcg_const_tl(pc_relative_pc(ctx));
2523 gen_op_addr_add(ctx, t0, t0, t1);
2524 tcg_temp_free(t1);
2525 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
2526 gen_store_gpr(t0, rt);
2527 break;
2528 case OPC_LWE:
2529 mem_idx = MIPS_HFLAG_UM;
2530 /* fall through */
2531 case OPC_LW:
2532 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
2533 ctx->default_tcg_memop_mask);
2534 gen_store_gpr(t0, rt);
2535 break;
2536 case OPC_LHE:
2537 mem_idx = MIPS_HFLAG_UM;
2538 /* fall through */
2539 case OPC_LH:
2540 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
2541 ctx->default_tcg_memop_mask);
2542 gen_store_gpr(t0, rt);
2543 break;
2544 case OPC_LHUE:
2545 mem_idx = MIPS_HFLAG_UM;
2546 /* fall through */
2547 case OPC_LHU:
2548 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
2549 ctx->default_tcg_memop_mask);
2550 gen_store_gpr(t0, rt);
2551 break;
2552 case OPC_LBE:
2553 mem_idx = MIPS_HFLAG_UM;
2554 /* fall through */
2555 case OPC_LB:
2556 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2557 gen_store_gpr(t0, rt);
2558 break;
2559 case OPC_LBUE:
2560 mem_idx = MIPS_HFLAG_UM;
2561 /* fall through */
2562 case OPC_LBU:
2563 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2564 gen_store_gpr(t0, rt);
2565 break;
2566 case OPC_LWLE:
2567 mem_idx = MIPS_HFLAG_UM;
2568 /* fall through */
2569 case OPC_LWL:
2570 t1 = tcg_temp_new();
2572 * Do a byte access to possibly trigger a page
2573 * fault with the unaligned address.
2575 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2576 tcg_gen_andi_tl(t1, t0, 3);
2577 #ifndef TARGET_WORDS_BIGENDIAN
2578 tcg_gen_xori_tl(t1, t1, 3);
2579 #endif
2580 tcg_gen_shli_tl(t1, t1, 3);
2581 tcg_gen_andi_tl(t0, t0, ~3);
2582 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2583 tcg_gen_shl_tl(t0, t0, t1);
2584 t2 = tcg_const_tl(-1);
2585 tcg_gen_shl_tl(t2, t2, t1);
2586 gen_load_gpr(t1, rt);
2587 tcg_gen_andc_tl(t1, t1, t2);
2588 tcg_temp_free(t2);
2589 tcg_gen_or_tl(t0, t0, t1);
2590 tcg_temp_free(t1);
2591 tcg_gen_ext32s_tl(t0, t0);
2592 gen_store_gpr(t0, rt);
2593 break;
2594 case OPC_LWRE:
2595 mem_idx = MIPS_HFLAG_UM;
2596 /* fall through */
2597 case OPC_LWR:
2598 t1 = tcg_temp_new();
2600 * Do a byte access to possibly trigger a page
2601 * fault with the unaligned address.
2603 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2604 tcg_gen_andi_tl(t1, t0, 3);
2605 #ifdef TARGET_WORDS_BIGENDIAN
2606 tcg_gen_xori_tl(t1, t1, 3);
2607 #endif
2608 tcg_gen_shli_tl(t1, t1, 3);
2609 tcg_gen_andi_tl(t0, t0, ~3);
2610 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2611 tcg_gen_shr_tl(t0, t0, t1);
2612 tcg_gen_xori_tl(t1, t1, 31);
2613 t2 = tcg_const_tl(0xfffffffeull);
2614 tcg_gen_shl_tl(t2, t2, t1);
2615 gen_load_gpr(t1, rt);
2616 tcg_gen_and_tl(t1, t1, t2);
2617 tcg_temp_free(t2);
2618 tcg_gen_or_tl(t0, t0, t1);
2619 tcg_temp_free(t1);
2620 tcg_gen_ext32s_tl(t0, t0);
2621 gen_store_gpr(t0, rt);
2622 break;
2623 case OPC_LLE:
2624 mem_idx = MIPS_HFLAG_UM;
2625 /* fall through */
2626 case OPC_LL:
2627 case R6_OPC_LL:
2628 op_ld_ll(t0, t0, mem_idx, ctx);
2629 gen_store_gpr(t0, rt);
2630 break;
2632 tcg_temp_free(t0);
2635 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
2636 uint32_t reg1, uint32_t reg2)
2638 TCGv taddr = tcg_temp_new();
2639 TCGv_i64 tval = tcg_temp_new_i64();
2640 TCGv tmp1 = tcg_temp_new();
2641 TCGv tmp2 = tcg_temp_new();
2643 gen_base_offset_addr(ctx, taddr, base, offset);
2644 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
2645 #ifdef TARGET_WORDS_BIGENDIAN
2646 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
2647 #else
2648 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
2649 #endif
2650 gen_store_gpr(tmp1, reg1);
2651 tcg_temp_free(tmp1);
2652 gen_store_gpr(tmp2, reg2);
2653 tcg_temp_free(tmp2);
2654 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2655 tcg_temp_free_i64(tval);
2656 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
2657 tcg_temp_free(taddr);
2660 /* Store */
2661 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
2662 int base, int offset)
2664 TCGv t0 = tcg_temp_new();
2665 TCGv t1 = tcg_temp_new();
2666 int mem_idx = ctx->mem_idx;
2668 gen_base_offset_addr(ctx, t0, base, offset);
2669 gen_load_gpr(t1, rt);
2670 switch (opc) {
2671 #if defined(TARGET_MIPS64)
2672 case OPC_SD:
2673 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
2674 ctx->default_tcg_memop_mask);
2675 break;
2676 case OPC_SDL:
2677 gen_helper_0e2i(sdl, t1, t0, mem_idx);
2678 break;
2679 case OPC_SDR:
2680 gen_helper_0e2i(sdr, t1, t0, mem_idx);
2681 break;
2682 #endif
2683 case OPC_SWE:
2684 mem_idx = MIPS_HFLAG_UM;
2685 /* fall through */
2686 case OPC_SW:
2687 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
2688 ctx->default_tcg_memop_mask);
2689 break;
2690 case OPC_SHE:
2691 mem_idx = MIPS_HFLAG_UM;
2692 /* fall through */
2693 case OPC_SH:
2694 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
2695 ctx->default_tcg_memop_mask);
2696 break;
2697 case OPC_SBE:
2698 mem_idx = MIPS_HFLAG_UM;
2699 /* fall through */
2700 case OPC_SB:
2701 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
2702 break;
2703 case OPC_SWLE:
2704 mem_idx = MIPS_HFLAG_UM;
2705 /* fall through */
2706 case OPC_SWL:
2707 gen_helper_0e2i(swl, t1, t0, mem_idx);
2708 break;
2709 case OPC_SWRE:
2710 mem_idx = MIPS_HFLAG_UM;
2711 /* fall through */
2712 case OPC_SWR:
2713 gen_helper_0e2i(swr, t1, t0, mem_idx);
2714 break;
2716 tcg_temp_free(t0);
2717 tcg_temp_free(t1);
2721 /* Store conditional */
2722 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
2723 MemOp tcg_mo, bool eva)
2725 TCGv addr, t0, val;
2726 TCGLabel *l1 = gen_new_label();
2727 TCGLabel *done = gen_new_label();
2729 t0 = tcg_temp_new();
2730 addr = tcg_temp_new();
2731 /* compare the address against that of the preceding LL */
2732 gen_base_offset_addr(ctx, addr, base, offset);
2733 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
2734 tcg_temp_free(addr);
2735 tcg_gen_movi_tl(t0, 0);
2736 gen_store_gpr(t0, rt);
2737 tcg_gen_br(done);
2739 gen_set_label(l1);
2740 /* generate cmpxchg */
2741 val = tcg_temp_new();
2742 gen_load_gpr(val, rt);
2743 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
2744 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
2745 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
2746 gen_store_gpr(t0, rt);
2747 tcg_temp_free(val);
2749 gen_set_label(done);
2750 tcg_temp_free(t0);
2754 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
2755 uint32_t reg1, uint32_t reg2, bool eva)
2757 TCGv taddr = tcg_temp_local_new();
2758 TCGv lladdr = tcg_temp_local_new();
2759 TCGv_i64 tval = tcg_temp_new_i64();
2760 TCGv_i64 llval = tcg_temp_new_i64();
2761 TCGv_i64 val = tcg_temp_new_i64();
2762 TCGv tmp1 = tcg_temp_new();
2763 TCGv tmp2 = tcg_temp_new();
2764 TCGLabel *lab_fail = gen_new_label();
2765 TCGLabel *lab_done = gen_new_label();
2767 gen_base_offset_addr(ctx, taddr, base, offset);
2769 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2770 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
2772 gen_load_gpr(tmp1, reg1);
2773 gen_load_gpr(tmp2, reg2);
2775 #ifdef TARGET_WORDS_BIGENDIAN
2776 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
2777 #else
2778 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
2779 #endif
2781 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2782 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
2783 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
2784 if (reg1 != 0) {
2785 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
2787 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
2789 gen_set_label(lab_fail);
2791 if (reg1 != 0) {
2792 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
2794 gen_set_label(lab_done);
2795 tcg_gen_movi_tl(lladdr, -1);
2796 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2799 /* Load and store */
2800 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
2801 TCGv t0)
2804 * Don't do NOP if destination is zero: we must perform the actual
2805 * memory access.
2807 switch (opc) {
2808 case OPC_LWC1:
2810 TCGv_i32 fp0 = tcg_temp_new_i32();
2811 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2812 ctx->default_tcg_memop_mask);
2813 gen_store_fpr32(ctx, fp0, ft);
2814 tcg_temp_free_i32(fp0);
2816 break;
2817 case OPC_SWC1:
2819 TCGv_i32 fp0 = tcg_temp_new_i32();
2820 gen_load_fpr32(ctx, fp0, ft);
2821 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2822 ctx->default_tcg_memop_mask);
2823 tcg_temp_free_i32(fp0);
2825 break;
2826 case OPC_LDC1:
2828 TCGv_i64 fp0 = tcg_temp_new_i64();
2829 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2830 ctx->default_tcg_memop_mask);
2831 gen_store_fpr64(ctx, fp0, ft);
2832 tcg_temp_free_i64(fp0);
2834 break;
2835 case OPC_SDC1:
2837 TCGv_i64 fp0 = tcg_temp_new_i64();
2838 gen_load_fpr64(ctx, fp0, ft);
2839 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2840 ctx->default_tcg_memop_mask);
2841 tcg_temp_free_i64(fp0);
2843 break;
2844 default:
2845 MIPS_INVAL("flt_ldst");
2846 gen_reserved_instruction(ctx);
2847 break;
2851 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2852 int rs, int16_t imm)
2854 TCGv t0 = tcg_temp_new();
2856 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2857 check_cp1_enabled(ctx);
2858 switch (op) {
2859 case OPC_LDC1:
2860 case OPC_SDC1:
2861 check_insn(ctx, ISA_MIPS2);
2862 /* Fallthrough */
2863 default:
2864 gen_base_offset_addr(ctx, t0, rs, imm);
2865 gen_flt_ldst(ctx, op, rt, t0);
2867 } else {
2868 generate_exception_err(ctx, EXCP_CpU, 1);
2870 tcg_temp_free(t0);
2873 /* Arithmetic with immediate operand */
2874 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2875 int rt, int rs, int imm)
2877 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2879 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2881 * If no destination, treat it as a NOP.
2882 * For addi, we must generate the overflow exception when needed.
2884 return;
2886 switch (opc) {
2887 case OPC_ADDI:
2889 TCGv t0 = tcg_temp_local_new();
2890 TCGv t1 = tcg_temp_new();
2891 TCGv t2 = tcg_temp_new();
2892 TCGLabel *l1 = gen_new_label();
2894 gen_load_gpr(t1, rs);
2895 tcg_gen_addi_tl(t0, t1, uimm);
2896 tcg_gen_ext32s_tl(t0, t0);
2898 tcg_gen_xori_tl(t1, t1, ~uimm);
2899 tcg_gen_xori_tl(t2, t0, uimm);
2900 tcg_gen_and_tl(t1, t1, t2);
2901 tcg_temp_free(t2);
2902 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2903 tcg_temp_free(t1);
2904 /* operands of same sign, result different sign */
2905 generate_exception(ctx, EXCP_OVERFLOW);
2906 gen_set_label(l1);
2907 tcg_gen_ext32s_tl(t0, t0);
2908 gen_store_gpr(t0, rt);
2909 tcg_temp_free(t0);
2911 break;
2912 case OPC_ADDIU:
2913 if (rs != 0) {
2914 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2915 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2916 } else {
2917 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2919 break;
2920 #if defined(TARGET_MIPS64)
2921 case OPC_DADDI:
2923 TCGv t0 = tcg_temp_local_new();
2924 TCGv t1 = tcg_temp_new();
2925 TCGv t2 = tcg_temp_new();
2926 TCGLabel *l1 = gen_new_label();
2928 gen_load_gpr(t1, rs);
2929 tcg_gen_addi_tl(t0, t1, uimm);
2931 tcg_gen_xori_tl(t1, t1, ~uimm);
2932 tcg_gen_xori_tl(t2, t0, uimm);
2933 tcg_gen_and_tl(t1, t1, t2);
2934 tcg_temp_free(t2);
2935 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2936 tcg_temp_free(t1);
2937 /* operands of same sign, result different sign */
2938 generate_exception(ctx, EXCP_OVERFLOW);
2939 gen_set_label(l1);
2940 gen_store_gpr(t0, rt);
2941 tcg_temp_free(t0);
2943 break;
2944 case OPC_DADDIU:
2945 if (rs != 0) {
2946 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2947 } else {
2948 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2950 break;
2951 #endif
2955 /* Logic with immediate operand */
2956 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2957 int rt, int rs, int16_t imm)
2959 target_ulong uimm;
2961 if (rt == 0) {
2962 /* If no destination, treat it as a NOP. */
2963 return;
2965 uimm = (uint16_t)imm;
2966 switch (opc) {
2967 case OPC_ANDI:
2968 if (likely(rs != 0)) {
2969 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2970 } else {
2971 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2973 break;
2974 case OPC_ORI:
2975 if (rs != 0) {
2976 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2977 } else {
2978 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2980 break;
2981 case OPC_XORI:
2982 if (likely(rs != 0)) {
2983 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2984 } else {
2985 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2987 break;
2988 case OPC_LUI:
2989 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
2990 /* OPC_AUI */
2991 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2992 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2993 } else {
2994 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2996 break;
2998 default:
2999 break;
3003 /* Set on less than with immediate operand */
3004 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3005 int rt, int rs, int16_t imm)
3007 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3008 TCGv t0;
3010 if (rt == 0) {
3011 /* If no destination, treat it as a NOP. */
3012 return;
3014 t0 = tcg_temp_new();
3015 gen_load_gpr(t0, rs);
3016 switch (opc) {
3017 case OPC_SLTI:
3018 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3019 break;
3020 case OPC_SLTIU:
3021 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3022 break;
3024 tcg_temp_free(t0);
3027 /* Shifts with immediate operand */
3028 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3029 int rt, int rs, int16_t imm)
3031 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3032 TCGv t0;
3034 if (rt == 0) {
3035 /* If no destination, treat it as a NOP. */
3036 return;
3039 t0 = tcg_temp_new();
3040 gen_load_gpr(t0, rs);
3041 switch (opc) {
3042 case OPC_SLL:
3043 tcg_gen_shli_tl(t0, t0, uimm);
3044 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3045 break;
3046 case OPC_SRA:
3047 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3048 break;
3049 case OPC_SRL:
3050 if (uimm != 0) {
3051 tcg_gen_ext32u_tl(t0, t0);
3052 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3053 } else {
3054 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3056 break;
3057 case OPC_ROTR:
3058 if (uimm != 0) {
3059 TCGv_i32 t1 = tcg_temp_new_i32();
3061 tcg_gen_trunc_tl_i32(t1, t0);
3062 tcg_gen_rotri_i32(t1, t1, uimm);
3063 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3064 tcg_temp_free_i32(t1);
3065 } else {
3066 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3068 break;
3069 #if defined(TARGET_MIPS64)
3070 case OPC_DSLL:
3071 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3072 break;
3073 case OPC_DSRA:
3074 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3075 break;
3076 case OPC_DSRL:
3077 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3078 break;
3079 case OPC_DROTR:
3080 if (uimm != 0) {
3081 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3082 } else {
3083 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3085 break;
3086 case OPC_DSLL32:
3087 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3088 break;
3089 case OPC_DSRA32:
3090 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3091 break;
3092 case OPC_DSRL32:
3093 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3094 break;
3095 case OPC_DROTR32:
3096 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3097 break;
3098 #endif
3100 tcg_temp_free(t0);
3103 /* Arithmetic */
3104 static void gen_arith(DisasContext *ctx, uint32_t opc,
3105 int rd, int rs, int rt)
3107 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3108 && opc != OPC_DADD && opc != OPC_DSUB) {
3110 * If no destination, treat it as a NOP.
3111 * For add & sub, we must generate the overflow exception when needed.
3113 return;
3116 switch (opc) {
3117 case OPC_ADD:
3119 TCGv t0 = tcg_temp_local_new();
3120 TCGv t1 = tcg_temp_new();
3121 TCGv t2 = tcg_temp_new();
3122 TCGLabel *l1 = gen_new_label();
3124 gen_load_gpr(t1, rs);
3125 gen_load_gpr(t2, rt);
3126 tcg_gen_add_tl(t0, t1, t2);
3127 tcg_gen_ext32s_tl(t0, t0);
3128 tcg_gen_xor_tl(t1, t1, t2);
3129 tcg_gen_xor_tl(t2, t0, t2);
3130 tcg_gen_andc_tl(t1, t2, t1);
3131 tcg_temp_free(t2);
3132 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3133 tcg_temp_free(t1);
3134 /* operands of same sign, result different sign */
3135 generate_exception(ctx, EXCP_OVERFLOW);
3136 gen_set_label(l1);
3137 gen_store_gpr(t0, rd);
3138 tcg_temp_free(t0);
3140 break;
3141 case OPC_ADDU:
3142 if (rs != 0 && rt != 0) {
3143 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3144 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3145 } else if (rs == 0 && rt != 0) {
3146 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3147 } else if (rs != 0 && rt == 0) {
3148 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3149 } else {
3150 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3152 break;
3153 case OPC_SUB:
3155 TCGv t0 = tcg_temp_local_new();
3156 TCGv t1 = tcg_temp_new();
3157 TCGv t2 = tcg_temp_new();
3158 TCGLabel *l1 = gen_new_label();
3160 gen_load_gpr(t1, rs);
3161 gen_load_gpr(t2, rt);
3162 tcg_gen_sub_tl(t0, t1, t2);
3163 tcg_gen_ext32s_tl(t0, t0);
3164 tcg_gen_xor_tl(t2, t1, t2);
3165 tcg_gen_xor_tl(t1, t0, t1);
3166 tcg_gen_and_tl(t1, t1, t2);
3167 tcg_temp_free(t2);
3168 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3169 tcg_temp_free(t1);
3171 * operands of different sign, first operand and the result
3172 * of different sign
3174 generate_exception(ctx, EXCP_OVERFLOW);
3175 gen_set_label(l1);
3176 gen_store_gpr(t0, rd);
3177 tcg_temp_free(t0);
3179 break;
3180 case OPC_SUBU:
3181 if (rs != 0 && rt != 0) {
3182 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3183 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3184 } else if (rs == 0 && rt != 0) {
3185 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3186 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3187 } else if (rs != 0 && rt == 0) {
3188 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3189 } else {
3190 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3192 break;
3193 #if defined(TARGET_MIPS64)
3194 case OPC_DADD:
3196 TCGv t0 = tcg_temp_local_new();
3197 TCGv t1 = tcg_temp_new();
3198 TCGv t2 = tcg_temp_new();
3199 TCGLabel *l1 = gen_new_label();
3201 gen_load_gpr(t1, rs);
3202 gen_load_gpr(t2, rt);
3203 tcg_gen_add_tl(t0, t1, t2);
3204 tcg_gen_xor_tl(t1, t1, t2);
3205 tcg_gen_xor_tl(t2, t0, t2);
3206 tcg_gen_andc_tl(t1, t2, t1);
3207 tcg_temp_free(t2);
3208 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3209 tcg_temp_free(t1);
3210 /* operands of same sign, result different sign */
3211 generate_exception(ctx, EXCP_OVERFLOW);
3212 gen_set_label(l1);
3213 gen_store_gpr(t0, rd);
3214 tcg_temp_free(t0);
3216 break;
3217 case OPC_DADDU:
3218 if (rs != 0 && rt != 0) {
3219 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3220 } else if (rs == 0 && rt != 0) {
3221 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3222 } else if (rs != 0 && rt == 0) {
3223 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3224 } else {
3225 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3227 break;
3228 case OPC_DSUB:
3230 TCGv t0 = tcg_temp_local_new();
3231 TCGv t1 = tcg_temp_new();
3232 TCGv t2 = tcg_temp_new();
3233 TCGLabel *l1 = gen_new_label();
3235 gen_load_gpr(t1, rs);
3236 gen_load_gpr(t2, rt);
3237 tcg_gen_sub_tl(t0, t1, t2);
3238 tcg_gen_xor_tl(t2, t1, t2);
3239 tcg_gen_xor_tl(t1, t0, t1);
3240 tcg_gen_and_tl(t1, t1, t2);
3241 tcg_temp_free(t2);
3242 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3243 tcg_temp_free(t1);
3245 * Operands of different sign, first operand and result different
3246 * sign.
3248 generate_exception(ctx, EXCP_OVERFLOW);
3249 gen_set_label(l1);
3250 gen_store_gpr(t0, rd);
3251 tcg_temp_free(t0);
3253 break;
3254 case OPC_DSUBU:
3255 if (rs != 0 && rt != 0) {
3256 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3257 } else if (rs == 0 && rt != 0) {
3258 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3259 } else if (rs != 0 && rt == 0) {
3260 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3261 } else {
3262 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3264 break;
3265 #endif
3266 case OPC_MUL:
3267 if (likely(rs != 0 && rt != 0)) {
3268 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3269 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3270 } else {
3271 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3273 break;
3277 /* Conditional move */
3278 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
3279 int rd, int rs, int rt)
3281 TCGv t0, t1, t2;
3283 if (rd == 0) {
3284 /* If no destination, treat it as a NOP. */
3285 return;
3288 t0 = tcg_temp_new();
3289 gen_load_gpr(t0, rt);
3290 t1 = tcg_const_tl(0);
3291 t2 = tcg_temp_new();
3292 gen_load_gpr(t2, rs);
3293 switch (opc) {
3294 case OPC_MOVN:
3295 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3296 break;
3297 case OPC_MOVZ:
3298 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3299 break;
3300 case OPC_SELNEZ:
3301 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
3302 break;
3303 case OPC_SELEQZ:
3304 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
3305 break;
3307 tcg_temp_free(t2);
3308 tcg_temp_free(t1);
3309 tcg_temp_free(t0);
3312 /* Logic */
3313 static void gen_logic(DisasContext *ctx, uint32_t opc,
3314 int rd, int rs, int rt)
3316 if (rd == 0) {
3317 /* If no destination, treat it as a NOP. */
3318 return;
3321 switch (opc) {
3322 case OPC_AND:
3323 if (likely(rs != 0 && rt != 0)) {
3324 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3325 } else {
3326 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3328 break;
3329 case OPC_NOR:
3330 if (rs != 0 && rt != 0) {
3331 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3332 } else if (rs == 0 && rt != 0) {
3333 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
3334 } else if (rs != 0 && rt == 0) {
3335 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
3336 } else {
3337 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
3339 break;
3340 case OPC_OR:
3341 if (likely(rs != 0 && rt != 0)) {
3342 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3343 } else if (rs == 0 && rt != 0) {
3344 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3345 } else if (rs != 0 && rt == 0) {
3346 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3347 } else {
3348 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3350 break;
3351 case OPC_XOR:
3352 if (likely(rs != 0 && rt != 0)) {
3353 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3354 } else if (rs == 0 && rt != 0) {
3355 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3356 } else if (rs != 0 && rt == 0) {
3357 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3358 } else {
3359 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3361 break;
3365 /* Set on lower than */
3366 static void gen_slt(DisasContext *ctx, uint32_t opc,
3367 int rd, int rs, int rt)
3369 TCGv t0, t1;
3371 if (rd == 0) {
3372 /* If no destination, treat it as a NOP. */
3373 return;
3376 t0 = tcg_temp_new();
3377 t1 = tcg_temp_new();
3378 gen_load_gpr(t0, rs);
3379 gen_load_gpr(t1, rt);
3380 switch (opc) {
3381 case OPC_SLT:
3382 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3383 break;
3384 case OPC_SLTU:
3385 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3386 break;
3388 tcg_temp_free(t0);
3389 tcg_temp_free(t1);
3392 /* Shifts */
3393 static void gen_shift(DisasContext *ctx, uint32_t opc,
3394 int rd, int rs, int rt)
3396 TCGv t0, t1;
3398 if (rd == 0) {
3400 * If no destination, treat it as a NOP.
3401 * For add & sub, we must generate the overflow exception when needed.
3403 return;
3406 t0 = tcg_temp_new();
3407 t1 = tcg_temp_new();
3408 gen_load_gpr(t0, rs);
3409 gen_load_gpr(t1, rt);
3410 switch (opc) {
3411 case OPC_SLLV:
3412 tcg_gen_andi_tl(t0, t0, 0x1f);
3413 tcg_gen_shl_tl(t0, t1, t0);
3414 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3415 break;
3416 case OPC_SRAV:
3417 tcg_gen_andi_tl(t0, t0, 0x1f);
3418 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3419 break;
3420 case OPC_SRLV:
3421 tcg_gen_ext32u_tl(t1, t1);
3422 tcg_gen_andi_tl(t0, t0, 0x1f);
3423 tcg_gen_shr_tl(t0, t1, t0);
3424 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3425 break;
3426 case OPC_ROTRV:
3428 TCGv_i32 t2 = tcg_temp_new_i32();
3429 TCGv_i32 t3 = tcg_temp_new_i32();
3431 tcg_gen_trunc_tl_i32(t2, t0);
3432 tcg_gen_trunc_tl_i32(t3, t1);
3433 tcg_gen_andi_i32(t2, t2, 0x1f);
3434 tcg_gen_rotr_i32(t2, t3, t2);
3435 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3436 tcg_temp_free_i32(t2);
3437 tcg_temp_free_i32(t3);
3439 break;
3440 #if defined(TARGET_MIPS64)
3441 case OPC_DSLLV:
3442 tcg_gen_andi_tl(t0, t0, 0x3f);
3443 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3444 break;
3445 case OPC_DSRAV:
3446 tcg_gen_andi_tl(t0, t0, 0x3f);
3447 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3448 break;
3449 case OPC_DSRLV:
3450 tcg_gen_andi_tl(t0, t0, 0x3f);
3451 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3452 break;
3453 case OPC_DROTRV:
3454 tcg_gen_andi_tl(t0, t0, 0x3f);
3455 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3456 break;
3457 #endif
3459 tcg_temp_free(t0);
3460 tcg_temp_free(t1);
3463 /* Arithmetic on HI/LO registers */
3464 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3466 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3467 /* Treat as NOP. */
3468 return;
3471 if (acc != 0) {
3472 check_dsp(ctx);
3475 switch (opc) {
3476 case OPC_MFHI:
3477 #if defined(TARGET_MIPS64)
3478 if (acc != 0) {
3479 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3480 } else
3481 #endif
3483 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3485 break;
3486 case OPC_MFLO:
3487 #if defined(TARGET_MIPS64)
3488 if (acc != 0) {
3489 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3490 } else
3491 #endif
3493 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3495 break;
3496 case OPC_MTHI:
3497 if (reg != 0) {
3498 #if defined(TARGET_MIPS64)
3499 if (acc != 0) {
3500 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3501 } else
3502 #endif
3504 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3506 } else {
3507 tcg_gen_movi_tl(cpu_HI[acc], 0);
3509 break;
3510 case OPC_MTLO:
3511 if (reg != 0) {
3512 #if defined(TARGET_MIPS64)
3513 if (acc != 0) {
3514 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3515 } else
3516 #endif
3518 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3520 } else {
3521 tcg_gen_movi_tl(cpu_LO[acc], 0);
3523 break;
3527 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3528 MemOp memop)
3530 TCGv t0 = tcg_const_tl(addr);
3531 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3532 gen_store_gpr(t0, reg);
3533 tcg_temp_free(t0);
3536 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3537 int rs)
3539 target_long offset;
3540 target_long addr;
3542 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3543 case OPC_ADDIUPC:
3544 if (rs != 0) {
3545 offset = sextract32(ctx->opcode << 2, 0, 21);
3546 addr = addr_add(ctx, pc, offset);
3547 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3549 break;
3550 case R6_OPC_LWPC:
3551 offset = sextract32(ctx->opcode << 2, 0, 21);
3552 addr = addr_add(ctx, pc, offset);
3553 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3554 break;
3555 #if defined(TARGET_MIPS64)
3556 case OPC_LWUPC:
3557 check_mips_64(ctx);
3558 offset = sextract32(ctx->opcode << 2, 0, 21);
3559 addr = addr_add(ctx, pc, offset);
3560 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3561 break;
3562 #endif
3563 default:
3564 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3565 case OPC_AUIPC:
3566 if (rs != 0) {
3567 offset = sextract32(ctx->opcode, 0, 16) << 16;
3568 addr = addr_add(ctx, pc, offset);
3569 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3571 break;
3572 case OPC_ALUIPC:
3573 if (rs != 0) {
3574 offset = sextract32(ctx->opcode, 0, 16) << 16;
3575 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3576 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3578 break;
3579 #if defined(TARGET_MIPS64)
3580 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3581 case R6_OPC_LDPC + (1 << 16):
3582 case R6_OPC_LDPC + (2 << 16):
3583 case R6_OPC_LDPC + (3 << 16):
3584 check_mips_64(ctx);
3585 offset = sextract32(ctx->opcode << 3, 0, 21);
3586 addr = addr_add(ctx, (pc & ~0x7), offset);
3587 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3588 break;
3589 #endif
3590 default:
3591 MIPS_INVAL("OPC_PCREL");
3592 gen_reserved_instruction(ctx);
3593 break;
3595 break;
3599 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3601 TCGv t0, t1;
3603 if (rd == 0) {
3604 /* Treat as NOP. */
3605 return;
3608 t0 = tcg_temp_new();
3609 t1 = tcg_temp_new();
3611 gen_load_gpr(t0, rs);
3612 gen_load_gpr(t1, rt);
3614 switch (opc) {
3615 case R6_OPC_DIV:
3617 TCGv t2 = tcg_temp_new();
3618 TCGv t3 = tcg_temp_new();
3619 tcg_gen_ext32s_tl(t0, t0);
3620 tcg_gen_ext32s_tl(t1, t1);
3621 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3622 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3623 tcg_gen_and_tl(t2, t2, t3);
3624 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3625 tcg_gen_or_tl(t2, t2, t3);
3626 tcg_gen_movi_tl(t3, 0);
3627 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3628 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3629 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3630 tcg_temp_free(t3);
3631 tcg_temp_free(t2);
3633 break;
3634 case R6_OPC_MOD:
3636 TCGv t2 = tcg_temp_new();
3637 TCGv t3 = tcg_temp_new();
3638 tcg_gen_ext32s_tl(t0, t0);
3639 tcg_gen_ext32s_tl(t1, t1);
3640 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3641 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3642 tcg_gen_and_tl(t2, t2, t3);
3643 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3644 tcg_gen_or_tl(t2, t2, t3);
3645 tcg_gen_movi_tl(t3, 0);
3646 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3647 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3648 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3649 tcg_temp_free(t3);
3650 tcg_temp_free(t2);
3652 break;
3653 case R6_OPC_DIVU:
3655 TCGv t2 = tcg_const_tl(0);
3656 TCGv t3 = tcg_const_tl(1);
3657 tcg_gen_ext32u_tl(t0, t0);
3658 tcg_gen_ext32u_tl(t1, t1);
3659 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3660 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3661 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3662 tcg_temp_free(t3);
3663 tcg_temp_free(t2);
3665 break;
3666 case R6_OPC_MODU:
3668 TCGv t2 = tcg_const_tl(0);
3669 TCGv t3 = tcg_const_tl(1);
3670 tcg_gen_ext32u_tl(t0, t0);
3671 tcg_gen_ext32u_tl(t1, t1);
3672 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3673 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3674 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3675 tcg_temp_free(t3);
3676 tcg_temp_free(t2);
3678 break;
3679 case R6_OPC_MUL:
3681 TCGv_i32 t2 = tcg_temp_new_i32();
3682 TCGv_i32 t3 = tcg_temp_new_i32();
3683 tcg_gen_trunc_tl_i32(t2, t0);
3684 tcg_gen_trunc_tl_i32(t3, t1);
3685 tcg_gen_mul_i32(t2, t2, t3);
3686 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3687 tcg_temp_free_i32(t2);
3688 tcg_temp_free_i32(t3);
3690 break;
3691 case R6_OPC_MUH:
3693 TCGv_i32 t2 = tcg_temp_new_i32();
3694 TCGv_i32 t3 = tcg_temp_new_i32();
3695 tcg_gen_trunc_tl_i32(t2, t0);
3696 tcg_gen_trunc_tl_i32(t3, t1);
3697 tcg_gen_muls2_i32(t2, t3, t2, t3);
3698 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3699 tcg_temp_free_i32(t2);
3700 tcg_temp_free_i32(t3);
3702 break;
3703 case R6_OPC_MULU:
3705 TCGv_i32 t2 = tcg_temp_new_i32();
3706 TCGv_i32 t3 = tcg_temp_new_i32();
3707 tcg_gen_trunc_tl_i32(t2, t0);
3708 tcg_gen_trunc_tl_i32(t3, t1);
3709 tcg_gen_mul_i32(t2, t2, t3);
3710 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3711 tcg_temp_free_i32(t2);
3712 tcg_temp_free_i32(t3);
3714 break;
3715 case R6_OPC_MUHU:
3717 TCGv_i32 t2 = tcg_temp_new_i32();
3718 TCGv_i32 t3 = tcg_temp_new_i32();
3719 tcg_gen_trunc_tl_i32(t2, t0);
3720 tcg_gen_trunc_tl_i32(t3, t1);
3721 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3722 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3723 tcg_temp_free_i32(t2);
3724 tcg_temp_free_i32(t3);
3726 break;
3727 #if defined(TARGET_MIPS64)
3728 case R6_OPC_DDIV:
3730 TCGv t2 = tcg_temp_new();
3731 TCGv t3 = tcg_temp_new();
3732 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3733 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3734 tcg_gen_and_tl(t2, t2, t3);
3735 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3736 tcg_gen_or_tl(t2, t2, t3);
3737 tcg_gen_movi_tl(t3, 0);
3738 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3739 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3740 tcg_temp_free(t3);
3741 tcg_temp_free(t2);
3743 break;
3744 case R6_OPC_DMOD:
3746 TCGv t2 = tcg_temp_new();
3747 TCGv t3 = tcg_temp_new();
3748 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3749 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3750 tcg_gen_and_tl(t2, t2, t3);
3751 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3752 tcg_gen_or_tl(t2, t2, t3);
3753 tcg_gen_movi_tl(t3, 0);
3754 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3755 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3756 tcg_temp_free(t3);
3757 tcg_temp_free(t2);
3759 break;
3760 case R6_OPC_DDIVU:
3762 TCGv t2 = tcg_const_tl(0);
3763 TCGv t3 = tcg_const_tl(1);
3764 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3765 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3766 tcg_temp_free(t3);
3767 tcg_temp_free(t2);
3769 break;
3770 case R6_OPC_DMODU:
3772 TCGv t2 = tcg_const_tl(0);
3773 TCGv t3 = tcg_const_tl(1);
3774 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3775 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3776 tcg_temp_free(t3);
3777 tcg_temp_free(t2);
3779 break;
3780 case R6_OPC_DMUL:
3781 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3782 break;
3783 case R6_OPC_DMUH:
3785 TCGv t2 = tcg_temp_new();
3786 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3787 tcg_temp_free(t2);
3789 break;
3790 case R6_OPC_DMULU:
3791 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3792 break;
3793 case R6_OPC_DMUHU:
3795 TCGv t2 = tcg_temp_new();
3796 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3797 tcg_temp_free(t2);
3799 break;
3800 #endif
3801 default:
3802 MIPS_INVAL("r6 mul/div");
3803 gen_reserved_instruction(ctx);
3804 goto out;
3806 out:
3807 tcg_temp_free(t0);
3808 tcg_temp_free(t1);
3811 #if defined(TARGET_MIPS64)
3812 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
3814 TCGv t0, t1;
3816 t0 = tcg_temp_new();
3817 t1 = tcg_temp_new();
3819 gen_load_gpr(t0, rs);
3820 gen_load_gpr(t1, rt);
3822 switch (opc) {
3823 case MMI_OPC_DIV1:
3825 TCGv t2 = tcg_temp_new();
3826 TCGv t3 = tcg_temp_new();
3827 tcg_gen_ext32s_tl(t0, t0);
3828 tcg_gen_ext32s_tl(t1, t1);
3829 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3830 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3831 tcg_gen_and_tl(t2, t2, t3);
3832 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3833 tcg_gen_or_tl(t2, t2, t3);
3834 tcg_gen_movi_tl(t3, 0);
3835 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3836 tcg_gen_div_tl(cpu_LO[1], t0, t1);
3837 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
3838 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3839 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3840 tcg_temp_free(t3);
3841 tcg_temp_free(t2);
3843 break;
3844 case MMI_OPC_DIVU1:
3846 TCGv t2 = tcg_const_tl(0);
3847 TCGv t3 = tcg_const_tl(1);
3848 tcg_gen_ext32u_tl(t0, t0);
3849 tcg_gen_ext32u_tl(t1, t1);
3850 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3851 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
3852 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
3853 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3854 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3855 tcg_temp_free(t3);
3856 tcg_temp_free(t2);
3858 break;
3859 default:
3860 MIPS_INVAL("div1 TX79");
3861 gen_reserved_instruction(ctx);
3862 goto out;
3864 out:
3865 tcg_temp_free(t0);
3866 tcg_temp_free(t1);
3868 #endif
3870 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3871 int acc, int rs, int rt)
3873 TCGv t0, t1;
3875 t0 = tcg_temp_new();
3876 t1 = tcg_temp_new();
3878 gen_load_gpr(t0, rs);
3879 gen_load_gpr(t1, rt);
3881 if (acc != 0) {
3882 check_dsp(ctx);
3885 switch (opc) {
3886 case OPC_DIV:
3888 TCGv t2 = tcg_temp_new();
3889 TCGv t3 = tcg_temp_new();
3890 tcg_gen_ext32s_tl(t0, t0);
3891 tcg_gen_ext32s_tl(t1, t1);
3892 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3893 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3894 tcg_gen_and_tl(t2, t2, t3);
3895 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3896 tcg_gen_or_tl(t2, t2, t3);
3897 tcg_gen_movi_tl(t3, 0);
3898 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3899 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3900 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3901 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3902 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3903 tcg_temp_free(t3);
3904 tcg_temp_free(t2);
3906 break;
3907 case OPC_DIVU:
3909 TCGv t2 = tcg_const_tl(0);
3910 TCGv t3 = tcg_const_tl(1);
3911 tcg_gen_ext32u_tl(t0, t0);
3912 tcg_gen_ext32u_tl(t1, t1);
3913 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3914 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3915 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3916 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3917 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3918 tcg_temp_free(t3);
3919 tcg_temp_free(t2);
3921 break;
3922 case OPC_MULT:
3924 TCGv_i32 t2 = tcg_temp_new_i32();
3925 TCGv_i32 t3 = tcg_temp_new_i32();
3926 tcg_gen_trunc_tl_i32(t2, t0);
3927 tcg_gen_trunc_tl_i32(t3, t1);
3928 tcg_gen_muls2_i32(t2, t3, t2, t3);
3929 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3930 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3931 tcg_temp_free_i32(t2);
3932 tcg_temp_free_i32(t3);
3934 break;
3935 case OPC_MULTU:
3937 TCGv_i32 t2 = tcg_temp_new_i32();
3938 TCGv_i32 t3 = tcg_temp_new_i32();
3939 tcg_gen_trunc_tl_i32(t2, t0);
3940 tcg_gen_trunc_tl_i32(t3, t1);
3941 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3942 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3943 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3944 tcg_temp_free_i32(t2);
3945 tcg_temp_free_i32(t3);
3947 break;
3948 #if defined(TARGET_MIPS64)
3949 case OPC_DDIV:
3951 TCGv t2 = tcg_temp_new();
3952 TCGv t3 = tcg_temp_new();
3953 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3954 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3955 tcg_gen_and_tl(t2, t2, t3);
3956 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3957 tcg_gen_or_tl(t2, t2, t3);
3958 tcg_gen_movi_tl(t3, 0);
3959 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3960 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3961 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3962 tcg_temp_free(t3);
3963 tcg_temp_free(t2);
3965 break;
3966 case OPC_DDIVU:
3968 TCGv t2 = tcg_const_tl(0);
3969 TCGv t3 = tcg_const_tl(1);
3970 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3971 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3972 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3973 tcg_temp_free(t3);
3974 tcg_temp_free(t2);
3976 break;
3977 case OPC_DMULT:
3978 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3979 break;
3980 case OPC_DMULTU:
3981 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3982 break;
3983 #endif
3984 case OPC_MADD:
3986 TCGv_i64 t2 = tcg_temp_new_i64();
3987 TCGv_i64 t3 = tcg_temp_new_i64();
3989 tcg_gen_ext_tl_i64(t2, t0);
3990 tcg_gen_ext_tl_i64(t3, t1);
3991 tcg_gen_mul_i64(t2, t2, t3);
3992 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3993 tcg_gen_add_i64(t2, t2, t3);
3994 tcg_temp_free_i64(t3);
3995 gen_move_low32(cpu_LO[acc], t2);
3996 gen_move_high32(cpu_HI[acc], t2);
3997 tcg_temp_free_i64(t2);
3999 break;
4000 case OPC_MADDU:
4002 TCGv_i64 t2 = tcg_temp_new_i64();
4003 TCGv_i64 t3 = tcg_temp_new_i64();
4005 tcg_gen_ext32u_tl(t0, t0);
4006 tcg_gen_ext32u_tl(t1, t1);
4007 tcg_gen_extu_tl_i64(t2, t0);
4008 tcg_gen_extu_tl_i64(t3, t1);
4009 tcg_gen_mul_i64(t2, t2, t3);
4010 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4011 tcg_gen_add_i64(t2, t2, t3);
4012 tcg_temp_free_i64(t3);
4013 gen_move_low32(cpu_LO[acc], t2);
4014 gen_move_high32(cpu_HI[acc], t2);
4015 tcg_temp_free_i64(t2);
4017 break;
4018 case OPC_MSUB:
4020 TCGv_i64 t2 = tcg_temp_new_i64();
4021 TCGv_i64 t3 = tcg_temp_new_i64();
4023 tcg_gen_ext_tl_i64(t2, t0);
4024 tcg_gen_ext_tl_i64(t3, t1);
4025 tcg_gen_mul_i64(t2, t2, t3);
4026 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4027 tcg_gen_sub_i64(t2, t3, t2);
4028 tcg_temp_free_i64(t3);
4029 gen_move_low32(cpu_LO[acc], t2);
4030 gen_move_high32(cpu_HI[acc], t2);
4031 tcg_temp_free_i64(t2);
4033 break;
4034 case OPC_MSUBU:
4036 TCGv_i64 t2 = tcg_temp_new_i64();
4037 TCGv_i64 t3 = tcg_temp_new_i64();
4039 tcg_gen_ext32u_tl(t0, t0);
4040 tcg_gen_ext32u_tl(t1, t1);
4041 tcg_gen_extu_tl_i64(t2, t0);
4042 tcg_gen_extu_tl_i64(t3, t1);
4043 tcg_gen_mul_i64(t2, t2, t3);
4044 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4045 tcg_gen_sub_i64(t2, t3, t2);
4046 tcg_temp_free_i64(t3);
4047 gen_move_low32(cpu_LO[acc], t2);
4048 gen_move_high32(cpu_HI[acc], t2);
4049 tcg_temp_free_i64(t2);
4051 break;
4052 default:
4053 MIPS_INVAL("mul/div");
4054 gen_reserved_instruction(ctx);
4055 goto out;
4057 out:
4058 tcg_temp_free(t0);
4059 tcg_temp_free(t1);
4063 * These MULT[U] and MADD[U] instructions implemented in for example
4064 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
4065 * architectures are special three-operand variants with the syntax
4067 * MULT[U][1] rd, rs, rt
4069 * such that
4071 * (rd, LO, HI) <- rs * rt
4073 * and
4075 * MADD[U][1] rd, rs, rt
4077 * such that
4079 * (rd, LO, HI) <- (LO, HI) + rs * rt
4081 * where the low-order 32-bits of the result is placed into both the
4082 * GPR rd and the special register LO. The high-order 32-bits of the
4083 * result is placed into the special register HI.
4085 * If the GPR rd is omitted in assembly language, it is taken to be 0,
4086 * which is the zero register that always reads as 0.
4088 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
4089 int rd, int rs, int rt)
4091 TCGv t0 = tcg_temp_new();
4092 TCGv t1 = tcg_temp_new();
4093 int acc = 0;
4095 gen_load_gpr(t0, rs);
4096 gen_load_gpr(t1, rt);
4098 switch (opc) {
4099 case MMI_OPC_MULT1:
4100 acc = 1;
4101 /* Fall through */
4102 case OPC_MULT:
4104 TCGv_i32 t2 = tcg_temp_new_i32();
4105 TCGv_i32 t3 = tcg_temp_new_i32();
4106 tcg_gen_trunc_tl_i32(t2, t0);
4107 tcg_gen_trunc_tl_i32(t3, t1);
4108 tcg_gen_muls2_i32(t2, t3, t2, t3);
4109 if (rd) {
4110 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4112 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4113 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4114 tcg_temp_free_i32(t2);
4115 tcg_temp_free_i32(t3);
4117 break;
4118 case MMI_OPC_MULTU1:
4119 acc = 1;
4120 /* Fall through */
4121 case OPC_MULTU:
4123 TCGv_i32 t2 = tcg_temp_new_i32();
4124 TCGv_i32 t3 = tcg_temp_new_i32();
4125 tcg_gen_trunc_tl_i32(t2, t0);
4126 tcg_gen_trunc_tl_i32(t3, t1);
4127 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4128 if (rd) {
4129 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4131 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4132 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4133 tcg_temp_free_i32(t2);
4134 tcg_temp_free_i32(t3);
4136 break;
4137 case MMI_OPC_MADD1:
4138 acc = 1;
4139 /* Fall through */
4140 case MMI_OPC_MADD:
4142 TCGv_i64 t2 = tcg_temp_new_i64();
4143 TCGv_i64 t3 = tcg_temp_new_i64();
4145 tcg_gen_ext_tl_i64(t2, t0);
4146 tcg_gen_ext_tl_i64(t3, t1);
4147 tcg_gen_mul_i64(t2, t2, t3);
4148 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4149 tcg_gen_add_i64(t2, t2, t3);
4150 tcg_temp_free_i64(t3);
4151 gen_move_low32(cpu_LO[acc], t2);
4152 gen_move_high32(cpu_HI[acc], t2);
4153 if (rd) {
4154 gen_move_low32(cpu_gpr[rd], t2);
4156 tcg_temp_free_i64(t2);
4158 break;
4159 case MMI_OPC_MADDU1:
4160 acc = 1;
4161 /* Fall through */
4162 case MMI_OPC_MADDU:
4164 TCGv_i64 t2 = tcg_temp_new_i64();
4165 TCGv_i64 t3 = tcg_temp_new_i64();
4167 tcg_gen_ext32u_tl(t0, t0);
4168 tcg_gen_ext32u_tl(t1, t1);
4169 tcg_gen_extu_tl_i64(t2, t0);
4170 tcg_gen_extu_tl_i64(t3, t1);
4171 tcg_gen_mul_i64(t2, t2, t3);
4172 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4173 tcg_gen_add_i64(t2, t2, t3);
4174 tcg_temp_free_i64(t3);
4175 gen_move_low32(cpu_LO[acc], t2);
4176 gen_move_high32(cpu_HI[acc], t2);
4177 if (rd) {
4178 gen_move_low32(cpu_gpr[rd], t2);
4180 tcg_temp_free_i64(t2);
4182 break;
4183 default:
4184 MIPS_INVAL("mul/madd TXx9");
4185 gen_reserved_instruction(ctx);
4186 goto out;
4189 out:
4190 tcg_temp_free(t0);
4191 tcg_temp_free(t1);
4194 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
4195 int rd, int rs, int rt)
4197 TCGv t0 = tcg_temp_new();
4198 TCGv t1 = tcg_temp_new();
4200 gen_load_gpr(t0, rs);
4201 gen_load_gpr(t1, rt);
4203 switch (opc) {
4204 case OPC_VR54XX_MULS:
4205 gen_helper_muls(t0, cpu_env, t0, t1);
4206 break;
4207 case OPC_VR54XX_MULSU:
4208 gen_helper_mulsu(t0, cpu_env, t0, t1);
4209 break;
4210 case OPC_VR54XX_MACC:
4211 gen_helper_macc(t0, cpu_env, t0, t1);
4212 break;
4213 case OPC_VR54XX_MACCU:
4214 gen_helper_maccu(t0, cpu_env, t0, t1);
4215 break;
4216 case OPC_VR54XX_MSAC:
4217 gen_helper_msac(t0, cpu_env, t0, t1);
4218 break;
4219 case OPC_VR54XX_MSACU:
4220 gen_helper_msacu(t0, cpu_env, t0, t1);
4221 break;
4222 case OPC_VR54XX_MULHI:
4223 gen_helper_mulhi(t0, cpu_env, t0, t1);
4224 break;
4225 case OPC_VR54XX_MULHIU:
4226 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4227 break;
4228 case OPC_VR54XX_MULSHI:
4229 gen_helper_mulshi(t0, cpu_env, t0, t1);
4230 break;
4231 case OPC_VR54XX_MULSHIU:
4232 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4233 break;
4234 case OPC_VR54XX_MACCHI:
4235 gen_helper_macchi(t0, cpu_env, t0, t1);
4236 break;
4237 case OPC_VR54XX_MACCHIU:
4238 gen_helper_macchiu(t0, cpu_env, t0, t1);
4239 break;
4240 case OPC_VR54XX_MSACHI:
4241 gen_helper_msachi(t0, cpu_env, t0, t1);
4242 break;
4243 case OPC_VR54XX_MSACHIU:
4244 gen_helper_msachiu(t0, cpu_env, t0, t1);
4245 break;
4246 default:
4247 MIPS_INVAL("mul vr54xx");
4248 gen_reserved_instruction(ctx);
4249 goto out;
4251 gen_store_gpr(t0, rd);
4253 out:
4254 tcg_temp_free(t0);
4255 tcg_temp_free(t1);
4258 static void gen_cl(DisasContext *ctx, uint32_t opc,
4259 int rd, int rs)
4261 TCGv t0;
4263 if (rd == 0) {
4264 /* Treat as NOP. */
4265 return;
4267 t0 = cpu_gpr[rd];
4268 gen_load_gpr(t0, rs);
4270 switch (opc) {
4271 case OPC_CLO:
4272 case R6_OPC_CLO:
4273 #if defined(TARGET_MIPS64)
4274 case OPC_DCLO:
4275 case R6_OPC_DCLO:
4276 #endif
4277 tcg_gen_not_tl(t0, t0);
4278 break;
4281 switch (opc) {
4282 case OPC_CLO:
4283 case R6_OPC_CLO:
4284 case OPC_CLZ:
4285 case R6_OPC_CLZ:
4286 tcg_gen_ext32u_tl(t0, t0);
4287 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4288 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
4289 break;
4290 #if defined(TARGET_MIPS64)
4291 case OPC_DCLO:
4292 case R6_OPC_DCLO:
4293 case OPC_DCLZ:
4294 case R6_OPC_DCLZ:
4295 tcg_gen_clzi_i64(t0, t0, 64);
4296 break;
4297 #endif
4301 /* Godson integer instructions */
4302 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
4303 int rd, int rs, int rt)
4305 TCGv t0, t1;
4307 if (rd == 0) {
4308 /* Treat as NOP. */
4309 return;
4312 switch (opc) {
4313 case OPC_MULT_G_2E:
4314 case OPC_MULT_G_2F:
4315 case OPC_MULTU_G_2E:
4316 case OPC_MULTU_G_2F:
4317 #if defined(TARGET_MIPS64)
4318 case OPC_DMULT_G_2E:
4319 case OPC_DMULT_G_2F:
4320 case OPC_DMULTU_G_2E:
4321 case OPC_DMULTU_G_2F:
4322 #endif
4323 t0 = tcg_temp_new();
4324 t1 = tcg_temp_new();
4325 break;
4326 default:
4327 t0 = tcg_temp_local_new();
4328 t1 = tcg_temp_local_new();
4329 break;
4332 gen_load_gpr(t0, rs);
4333 gen_load_gpr(t1, rt);
4335 switch (opc) {
4336 case OPC_MULT_G_2E:
4337 case OPC_MULT_G_2F:
4338 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4339 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4340 break;
4341 case OPC_MULTU_G_2E:
4342 case OPC_MULTU_G_2F:
4343 tcg_gen_ext32u_tl(t0, t0);
4344 tcg_gen_ext32u_tl(t1, t1);
4345 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4346 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4347 break;
4348 case OPC_DIV_G_2E:
4349 case OPC_DIV_G_2F:
4351 TCGLabel *l1 = gen_new_label();
4352 TCGLabel *l2 = gen_new_label();
4353 TCGLabel *l3 = gen_new_label();
4354 tcg_gen_ext32s_tl(t0, t0);
4355 tcg_gen_ext32s_tl(t1, t1);
4356 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4357 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4358 tcg_gen_br(l3);
4359 gen_set_label(l1);
4360 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4361 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4362 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4363 tcg_gen_br(l3);
4364 gen_set_label(l2);
4365 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4366 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4367 gen_set_label(l3);
4369 break;
4370 case OPC_DIVU_G_2E:
4371 case OPC_DIVU_G_2F:
4373 TCGLabel *l1 = gen_new_label();
4374 TCGLabel *l2 = gen_new_label();
4375 tcg_gen_ext32u_tl(t0, t0);
4376 tcg_gen_ext32u_tl(t1, t1);
4377 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4378 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4379 tcg_gen_br(l2);
4380 gen_set_label(l1);
4381 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4382 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4383 gen_set_label(l2);
4385 break;
4386 case OPC_MOD_G_2E:
4387 case OPC_MOD_G_2F:
4389 TCGLabel *l1 = gen_new_label();
4390 TCGLabel *l2 = gen_new_label();
4391 TCGLabel *l3 = gen_new_label();
4392 tcg_gen_ext32u_tl(t0, t0);
4393 tcg_gen_ext32u_tl(t1, t1);
4394 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4395 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4396 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4397 gen_set_label(l1);
4398 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4399 tcg_gen_br(l3);
4400 gen_set_label(l2);
4401 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4402 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4403 gen_set_label(l3);
4405 break;
4406 case OPC_MODU_G_2E:
4407 case OPC_MODU_G_2F:
4409 TCGLabel *l1 = gen_new_label();
4410 TCGLabel *l2 = gen_new_label();
4411 tcg_gen_ext32u_tl(t0, t0);
4412 tcg_gen_ext32u_tl(t1, t1);
4413 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4414 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4415 tcg_gen_br(l2);
4416 gen_set_label(l1);
4417 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4418 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4419 gen_set_label(l2);
4421 break;
4422 #if defined(TARGET_MIPS64)
4423 case OPC_DMULT_G_2E:
4424 case OPC_DMULT_G_2F:
4425 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4426 break;
4427 case OPC_DMULTU_G_2E:
4428 case OPC_DMULTU_G_2F:
4429 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4430 break;
4431 case OPC_DDIV_G_2E:
4432 case OPC_DDIV_G_2F:
4434 TCGLabel *l1 = gen_new_label();
4435 TCGLabel *l2 = gen_new_label();
4436 TCGLabel *l3 = gen_new_label();
4437 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4438 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4439 tcg_gen_br(l3);
4440 gen_set_label(l1);
4441 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4442 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4443 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4444 tcg_gen_br(l3);
4445 gen_set_label(l2);
4446 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4447 gen_set_label(l3);
4449 break;
4450 case OPC_DDIVU_G_2E:
4451 case OPC_DDIVU_G_2F:
4453 TCGLabel *l1 = gen_new_label();
4454 TCGLabel *l2 = gen_new_label();
4455 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4456 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4457 tcg_gen_br(l2);
4458 gen_set_label(l1);
4459 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4460 gen_set_label(l2);
4462 break;
4463 case OPC_DMOD_G_2E:
4464 case OPC_DMOD_G_2F:
4466 TCGLabel *l1 = gen_new_label();
4467 TCGLabel *l2 = gen_new_label();
4468 TCGLabel *l3 = gen_new_label();
4469 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4470 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4471 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4472 gen_set_label(l1);
4473 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4474 tcg_gen_br(l3);
4475 gen_set_label(l2);
4476 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4477 gen_set_label(l3);
4479 break;
4480 case OPC_DMODU_G_2E:
4481 case OPC_DMODU_G_2F:
4483 TCGLabel *l1 = gen_new_label();
4484 TCGLabel *l2 = gen_new_label();
4485 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4486 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4487 tcg_gen_br(l2);
4488 gen_set_label(l1);
4489 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4490 gen_set_label(l2);
4492 break;
4493 #endif
4496 tcg_temp_free(t0);
4497 tcg_temp_free(t1);
4500 /* Loongson multimedia instructions */
4501 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4503 uint32_t opc, shift_max;
4504 TCGv_i64 t0, t1;
4505 TCGCond cond;
4507 opc = MASK_LMMI(ctx->opcode);
4508 switch (opc) {
4509 case OPC_ADD_CP2:
4510 case OPC_SUB_CP2:
4511 case OPC_DADD_CP2:
4512 case OPC_DSUB_CP2:
4513 t0 = tcg_temp_local_new_i64();
4514 t1 = tcg_temp_local_new_i64();
4515 break;
4516 default:
4517 t0 = tcg_temp_new_i64();
4518 t1 = tcg_temp_new_i64();
4519 break;
4522 check_cp1_enabled(ctx);
4523 gen_load_fpr64(ctx, t0, rs);
4524 gen_load_fpr64(ctx, t1, rt);
4526 switch (opc) {
4527 case OPC_PADDSH:
4528 gen_helper_paddsh(t0, t0, t1);
4529 break;
4530 case OPC_PADDUSH:
4531 gen_helper_paddush(t0, t0, t1);
4532 break;
4533 case OPC_PADDH:
4534 gen_helper_paddh(t0, t0, t1);
4535 break;
4536 case OPC_PADDW:
4537 gen_helper_paddw(t0, t0, t1);
4538 break;
4539 case OPC_PADDSB:
4540 gen_helper_paddsb(t0, t0, t1);
4541 break;
4542 case OPC_PADDUSB:
4543 gen_helper_paddusb(t0, t0, t1);
4544 break;
4545 case OPC_PADDB:
4546 gen_helper_paddb(t0, t0, t1);
4547 break;
4549 case OPC_PSUBSH:
4550 gen_helper_psubsh(t0, t0, t1);
4551 break;
4552 case OPC_PSUBUSH:
4553 gen_helper_psubush(t0, t0, t1);
4554 break;
4555 case OPC_PSUBH:
4556 gen_helper_psubh(t0, t0, t1);
4557 break;
4558 case OPC_PSUBW:
4559 gen_helper_psubw(t0, t0, t1);
4560 break;
4561 case OPC_PSUBSB:
4562 gen_helper_psubsb(t0, t0, t1);
4563 break;
4564 case OPC_PSUBUSB:
4565 gen_helper_psubusb(t0, t0, t1);
4566 break;
4567 case OPC_PSUBB:
4568 gen_helper_psubb(t0, t0, t1);
4569 break;
4571 case OPC_PSHUFH:
4572 gen_helper_pshufh(t0, t0, t1);
4573 break;
4574 case OPC_PACKSSWH:
4575 gen_helper_packsswh(t0, t0, t1);
4576 break;
4577 case OPC_PACKSSHB:
4578 gen_helper_packsshb(t0, t0, t1);
4579 break;
4580 case OPC_PACKUSHB:
4581 gen_helper_packushb(t0, t0, t1);
4582 break;
4584 case OPC_PUNPCKLHW:
4585 gen_helper_punpcklhw(t0, t0, t1);
4586 break;
4587 case OPC_PUNPCKHHW:
4588 gen_helper_punpckhhw(t0, t0, t1);
4589 break;
4590 case OPC_PUNPCKLBH:
4591 gen_helper_punpcklbh(t0, t0, t1);
4592 break;
4593 case OPC_PUNPCKHBH:
4594 gen_helper_punpckhbh(t0, t0, t1);
4595 break;
4596 case OPC_PUNPCKLWD:
4597 gen_helper_punpcklwd(t0, t0, t1);
4598 break;
4599 case OPC_PUNPCKHWD:
4600 gen_helper_punpckhwd(t0, t0, t1);
4601 break;
4603 case OPC_PAVGH:
4604 gen_helper_pavgh(t0, t0, t1);
4605 break;
4606 case OPC_PAVGB:
4607 gen_helper_pavgb(t0, t0, t1);
4608 break;
4609 case OPC_PMAXSH:
4610 gen_helper_pmaxsh(t0, t0, t1);
4611 break;
4612 case OPC_PMINSH:
4613 gen_helper_pminsh(t0, t0, t1);
4614 break;
4615 case OPC_PMAXUB:
4616 gen_helper_pmaxub(t0, t0, t1);
4617 break;
4618 case OPC_PMINUB:
4619 gen_helper_pminub(t0, t0, t1);
4620 break;
4622 case OPC_PCMPEQW:
4623 gen_helper_pcmpeqw(t0, t0, t1);
4624 break;
4625 case OPC_PCMPGTW:
4626 gen_helper_pcmpgtw(t0, t0, t1);
4627 break;
4628 case OPC_PCMPEQH:
4629 gen_helper_pcmpeqh(t0, t0, t1);
4630 break;
4631 case OPC_PCMPGTH:
4632 gen_helper_pcmpgth(t0, t0, t1);
4633 break;
4634 case OPC_PCMPEQB:
4635 gen_helper_pcmpeqb(t0, t0, t1);
4636 break;
4637 case OPC_PCMPGTB:
4638 gen_helper_pcmpgtb(t0, t0, t1);
4639 break;
4641 case OPC_PSLLW:
4642 gen_helper_psllw(t0, t0, t1);
4643 break;
4644 case OPC_PSLLH:
4645 gen_helper_psllh(t0, t0, t1);
4646 break;
4647 case OPC_PSRLW:
4648 gen_helper_psrlw(t0, t0, t1);
4649 break;
4650 case OPC_PSRLH:
4651 gen_helper_psrlh(t0, t0, t1);
4652 break;
4653 case OPC_PSRAW:
4654 gen_helper_psraw(t0, t0, t1);
4655 break;
4656 case OPC_PSRAH:
4657 gen_helper_psrah(t0, t0, t1);
4658 break;
4660 case OPC_PMULLH:
4661 gen_helper_pmullh(t0, t0, t1);
4662 break;
4663 case OPC_PMULHH:
4664 gen_helper_pmulhh(t0, t0, t1);
4665 break;
4666 case OPC_PMULHUH:
4667 gen_helper_pmulhuh(t0, t0, t1);
4668 break;
4669 case OPC_PMADDHW:
4670 gen_helper_pmaddhw(t0, t0, t1);
4671 break;
4673 case OPC_PASUBUB:
4674 gen_helper_pasubub(t0, t0, t1);
4675 break;
4676 case OPC_BIADD:
4677 gen_helper_biadd(t0, t0);
4678 break;
4679 case OPC_PMOVMSKB:
4680 gen_helper_pmovmskb(t0, t0);
4681 break;
4683 case OPC_PADDD:
4684 tcg_gen_add_i64(t0, t0, t1);
4685 break;
4686 case OPC_PSUBD:
4687 tcg_gen_sub_i64(t0, t0, t1);
4688 break;
4689 case OPC_XOR_CP2:
4690 tcg_gen_xor_i64(t0, t0, t1);
4691 break;
4692 case OPC_NOR_CP2:
4693 tcg_gen_nor_i64(t0, t0, t1);
4694 break;
4695 case OPC_AND_CP2:
4696 tcg_gen_and_i64(t0, t0, t1);
4697 break;
4698 case OPC_OR_CP2:
4699 tcg_gen_or_i64(t0, t0, t1);
4700 break;
4702 case OPC_PANDN:
4703 tcg_gen_andc_i64(t0, t1, t0);
4704 break;
4706 case OPC_PINSRH_0:
4707 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4708 break;
4709 case OPC_PINSRH_1:
4710 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4711 break;
4712 case OPC_PINSRH_2:
4713 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4714 break;
4715 case OPC_PINSRH_3:
4716 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4717 break;
4719 case OPC_PEXTRH:
4720 tcg_gen_andi_i64(t1, t1, 3);
4721 tcg_gen_shli_i64(t1, t1, 4);
4722 tcg_gen_shr_i64(t0, t0, t1);
4723 tcg_gen_ext16u_i64(t0, t0);
4724 break;
4726 case OPC_ADDU_CP2:
4727 tcg_gen_add_i64(t0, t0, t1);
4728 tcg_gen_ext32s_i64(t0, t0);
4729 break;
4730 case OPC_SUBU_CP2:
4731 tcg_gen_sub_i64(t0, t0, t1);
4732 tcg_gen_ext32s_i64(t0, t0);
4733 break;
4735 case OPC_SLL_CP2:
4736 shift_max = 32;
4737 goto do_shift;
4738 case OPC_SRL_CP2:
4739 shift_max = 32;
4740 goto do_shift;
4741 case OPC_SRA_CP2:
4742 shift_max = 32;
4743 goto do_shift;
4744 case OPC_DSLL_CP2:
4745 shift_max = 64;
4746 goto do_shift;
4747 case OPC_DSRL_CP2:
4748 shift_max = 64;
4749 goto do_shift;
4750 case OPC_DSRA_CP2:
4751 shift_max = 64;
4752 goto do_shift;
4753 do_shift:
4754 /* Make sure shift count isn't TCG undefined behaviour. */
4755 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4757 switch (opc) {
4758 case OPC_SLL_CP2:
4759 case OPC_DSLL_CP2:
4760 tcg_gen_shl_i64(t0, t0, t1);
4761 break;
4762 case OPC_SRA_CP2:
4763 case OPC_DSRA_CP2:
4765 * Since SRA is UndefinedResult without sign-extended inputs,
4766 * we can treat SRA and DSRA the same.
4768 tcg_gen_sar_i64(t0, t0, t1);
4769 break;
4770 case OPC_SRL_CP2:
4771 /* We want to shift in zeros for SRL; zero-extend first. */
4772 tcg_gen_ext32u_i64(t0, t0);
4773 /* FALLTHRU */
4774 case OPC_DSRL_CP2:
4775 tcg_gen_shr_i64(t0, t0, t1);
4776 break;
4779 if (shift_max == 32) {
4780 tcg_gen_ext32s_i64(t0, t0);
4783 /* Shifts larger than MAX produce zero. */
4784 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4785 tcg_gen_neg_i64(t1, t1);
4786 tcg_gen_and_i64(t0, t0, t1);
4787 break;
4789 case OPC_ADD_CP2:
4790 case OPC_DADD_CP2:
4792 TCGv_i64 t2 = tcg_temp_new_i64();
4793 TCGLabel *lab = gen_new_label();
4795 tcg_gen_mov_i64(t2, t0);
4796 tcg_gen_add_i64(t0, t1, t2);
4797 if (opc == OPC_ADD_CP2) {
4798 tcg_gen_ext32s_i64(t0, t0);
4800 tcg_gen_xor_i64(t1, t1, t2);
4801 tcg_gen_xor_i64(t2, t2, t0);
4802 tcg_gen_andc_i64(t1, t2, t1);
4803 tcg_temp_free_i64(t2);
4804 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4805 generate_exception(ctx, EXCP_OVERFLOW);
4806 gen_set_label(lab);
4807 break;
4810 case OPC_SUB_CP2:
4811 case OPC_DSUB_CP2:
4813 TCGv_i64 t2 = tcg_temp_new_i64();
4814 TCGLabel *lab = gen_new_label();
4816 tcg_gen_mov_i64(t2, t0);
4817 tcg_gen_sub_i64(t0, t1, t2);
4818 if (opc == OPC_SUB_CP2) {
4819 tcg_gen_ext32s_i64(t0, t0);
4821 tcg_gen_xor_i64(t1, t1, t2);
4822 tcg_gen_xor_i64(t2, t2, t0);
4823 tcg_gen_and_i64(t1, t1, t2);
4824 tcg_temp_free_i64(t2);
4825 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4826 generate_exception(ctx, EXCP_OVERFLOW);
4827 gen_set_label(lab);
4828 break;
4831 case OPC_PMULUW:
4832 tcg_gen_ext32u_i64(t0, t0);
4833 tcg_gen_ext32u_i64(t1, t1);
4834 tcg_gen_mul_i64(t0, t0, t1);
4835 break;
4837 case OPC_SEQU_CP2:
4838 case OPC_SEQ_CP2:
4839 cond = TCG_COND_EQ;
4840 goto do_cc_cond;
4841 break;
4842 case OPC_SLTU_CP2:
4843 cond = TCG_COND_LTU;
4844 goto do_cc_cond;
4845 break;
4846 case OPC_SLT_CP2:
4847 cond = TCG_COND_LT;
4848 goto do_cc_cond;
4849 break;
4850 case OPC_SLEU_CP2:
4851 cond = TCG_COND_LEU;
4852 goto do_cc_cond;
4853 break;
4854 case OPC_SLE_CP2:
4855 cond = TCG_COND_LE;
4856 do_cc_cond:
4858 int cc = (ctx->opcode >> 8) & 0x7;
4859 TCGv_i64 t64 = tcg_temp_new_i64();
4860 TCGv_i32 t32 = tcg_temp_new_i32();
4862 tcg_gen_setcond_i64(cond, t64, t0, t1);
4863 tcg_gen_extrl_i64_i32(t32, t64);
4864 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
4865 get_fp_bit(cc), 1);
4867 tcg_temp_free_i32(t32);
4868 tcg_temp_free_i64(t64);
4870 goto no_rd;
4871 break;
4872 default:
4873 MIPS_INVAL("loongson_cp2");
4874 gen_reserved_instruction(ctx);
4875 return;
4878 gen_store_fpr64(ctx, t0, rd);
4880 no_rd:
4881 tcg_temp_free_i64(t0);
4882 tcg_temp_free_i64(t1);
4885 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
4886 int rs, int rd)
4888 TCGv t0, t1, t2;
4889 TCGv_i32 fp0;
4890 #if defined(TARGET_MIPS64)
4891 int lsq_rt1 = ctx->opcode & 0x1f;
4892 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
4893 #endif
4894 int shf_offset = sextract32(ctx->opcode, 6, 8);
4896 t0 = tcg_temp_new();
4898 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
4899 #if defined(TARGET_MIPS64)
4900 case OPC_GSLQ:
4901 t1 = tcg_temp_new();
4902 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4903 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4904 ctx->default_tcg_memop_mask);
4905 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4906 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4907 ctx->default_tcg_memop_mask);
4908 gen_store_gpr(t1, rt);
4909 gen_store_gpr(t0, lsq_rt1);
4910 tcg_temp_free(t1);
4911 break;
4912 case OPC_GSLQC1:
4913 check_cp1_enabled(ctx);
4914 t1 = tcg_temp_new();
4915 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4916 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4917 ctx->default_tcg_memop_mask);
4918 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4919 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4920 ctx->default_tcg_memop_mask);
4921 gen_store_fpr64(ctx, t1, rt);
4922 gen_store_fpr64(ctx, t0, lsq_rt1);
4923 tcg_temp_free(t1);
4924 break;
4925 case OPC_GSSQ:
4926 t1 = tcg_temp_new();
4927 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4928 gen_load_gpr(t1, rt);
4929 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4930 ctx->default_tcg_memop_mask);
4931 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4932 gen_load_gpr(t1, lsq_rt1);
4933 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4934 ctx->default_tcg_memop_mask);
4935 tcg_temp_free(t1);
4936 break;
4937 case OPC_GSSQC1:
4938 check_cp1_enabled(ctx);
4939 t1 = tcg_temp_new();
4940 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4941 gen_load_fpr64(ctx, t1, rt);
4942 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4943 ctx->default_tcg_memop_mask);
4944 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4945 gen_load_fpr64(ctx, t1, lsq_rt1);
4946 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4947 ctx->default_tcg_memop_mask);
4948 tcg_temp_free(t1);
4949 break;
4950 #endif
4951 case OPC_GSSHFL:
4952 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4953 case OPC_GSLWLC1:
4954 check_cp1_enabled(ctx);
4955 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4956 t1 = tcg_temp_new();
4957 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4958 tcg_gen_andi_tl(t1, t0, 3);
4959 #ifndef TARGET_WORDS_BIGENDIAN
4960 tcg_gen_xori_tl(t1, t1, 3);
4961 #endif
4962 tcg_gen_shli_tl(t1, t1, 3);
4963 tcg_gen_andi_tl(t0, t0, ~3);
4964 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4965 tcg_gen_shl_tl(t0, t0, t1);
4966 t2 = tcg_const_tl(-1);
4967 tcg_gen_shl_tl(t2, t2, t1);
4968 fp0 = tcg_temp_new_i32();
4969 gen_load_fpr32(ctx, fp0, rt);
4970 tcg_gen_ext_i32_tl(t1, fp0);
4971 tcg_gen_andc_tl(t1, t1, t2);
4972 tcg_temp_free(t2);
4973 tcg_gen_or_tl(t0, t0, t1);
4974 tcg_temp_free(t1);
4975 #if defined(TARGET_MIPS64)
4976 tcg_gen_extrl_i64_i32(fp0, t0);
4977 #else
4978 tcg_gen_ext32s_tl(fp0, t0);
4979 #endif
4980 gen_store_fpr32(ctx, fp0, rt);
4981 tcg_temp_free_i32(fp0);
4982 break;
4983 case OPC_GSLWRC1:
4984 check_cp1_enabled(ctx);
4985 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4986 t1 = tcg_temp_new();
4987 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4988 tcg_gen_andi_tl(t1, t0, 3);
4989 #ifdef TARGET_WORDS_BIGENDIAN
4990 tcg_gen_xori_tl(t1, t1, 3);
4991 #endif
4992 tcg_gen_shli_tl(t1, t1, 3);
4993 tcg_gen_andi_tl(t0, t0, ~3);
4994 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4995 tcg_gen_shr_tl(t0, t0, t1);
4996 tcg_gen_xori_tl(t1, t1, 31);
4997 t2 = tcg_const_tl(0xfffffffeull);
4998 tcg_gen_shl_tl(t2, t2, t1);
4999 fp0 = tcg_temp_new_i32();
5000 gen_load_fpr32(ctx, fp0, rt);
5001 tcg_gen_ext_i32_tl(t1, fp0);
5002 tcg_gen_and_tl(t1, t1, t2);
5003 tcg_temp_free(t2);
5004 tcg_gen_or_tl(t0, t0, t1);
5005 tcg_temp_free(t1);
5006 #if defined(TARGET_MIPS64)
5007 tcg_gen_extrl_i64_i32(fp0, t0);
5008 #else
5009 tcg_gen_ext32s_tl(fp0, t0);
5010 #endif
5011 gen_store_fpr32(ctx, fp0, rt);
5012 tcg_temp_free_i32(fp0);
5013 break;
5014 #if defined(TARGET_MIPS64)
5015 case OPC_GSLDLC1:
5016 check_cp1_enabled(ctx);
5017 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5018 t1 = tcg_temp_new();
5019 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5020 tcg_gen_andi_tl(t1, t0, 7);
5021 #ifndef TARGET_WORDS_BIGENDIAN
5022 tcg_gen_xori_tl(t1, t1, 7);
5023 #endif
5024 tcg_gen_shli_tl(t1, t1, 3);
5025 tcg_gen_andi_tl(t0, t0, ~7);
5026 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
5027 tcg_gen_shl_tl(t0, t0, t1);
5028 t2 = tcg_const_tl(-1);
5029 tcg_gen_shl_tl(t2, t2, t1);
5030 gen_load_fpr64(ctx, t1, rt);
5031 tcg_gen_andc_tl(t1, t1, t2);
5032 tcg_temp_free(t2);
5033 tcg_gen_or_tl(t0, t0, t1);
5034 tcg_temp_free(t1);
5035 gen_store_fpr64(ctx, t0, rt);
5036 break;
5037 case OPC_GSLDRC1:
5038 check_cp1_enabled(ctx);
5039 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5040 t1 = tcg_temp_new();
5041 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5042 tcg_gen_andi_tl(t1, t0, 7);
5043 #ifdef TARGET_WORDS_BIGENDIAN
5044 tcg_gen_xori_tl(t1, t1, 7);
5045 #endif
5046 tcg_gen_shli_tl(t1, t1, 3);
5047 tcg_gen_andi_tl(t0, t0, ~7);
5048 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
5049 tcg_gen_shr_tl(t0, t0, t1);
5050 tcg_gen_xori_tl(t1, t1, 63);
5051 t2 = tcg_const_tl(0xfffffffffffffffeull);
5052 tcg_gen_shl_tl(t2, t2, t1);
5053 gen_load_fpr64(ctx, t1, rt);
5054 tcg_gen_and_tl(t1, t1, t2);
5055 tcg_temp_free(t2);
5056 tcg_gen_or_tl(t0, t0, t1);
5057 tcg_temp_free(t1);
5058 gen_store_fpr64(ctx, t0, rt);
5059 break;
5060 #endif
5061 default:
5062 MIPS_INVAL("loongson_gsshfl");
5063 gen_reserved_instruction(ctx);
5064 break;
5066 break;
5067 case OPC_GSSHFS:
5068 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
5069 case OPC_GSSWLC1:
5070 check_cp1_enabled(ctx);
5071 t1 = tcg_temp_new();
5072 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5073 fp0 = tcg_temp_new_i32();
5074 gen_load_fpr32(ctx, fp0, rt);
5075 tcg_gen_ext_i32_tl(t1, fp0);
5076 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
5077 tcg_temp_free_i32(fp0);
5078 tcg_temp_free(t1);
5079 break;
5080 case OPC_GSSWRC1:
5081 check_cp1_enabled(ctx);
5082 t1 = tcg_temp_new();
5083 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5084 fp0 = tcg_temp_new_i32();
5085 gen_load_fpr32(ctx, fp0, rt);
5086 tcg_gen_ext_i32_tl(t1, fp0);
5087 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
5088 tcg_temp_free_i32(fp0);
5089 tcg_temp_free(t1);
5090 break;
5091 #if defined(TARGET_MIPS64)
5092 case OPC_GSSDLC1:
5093 check_cp1_enabled(ctx);
5094 t1 = tcg_temp_new();
5095 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5096 gen_load_fpr64(ctx, t1, rt);
5097 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
5098 tcg_temp_free(t1);
5099 break;
5100 case OPC_GSSDRC1:
5101 check_cp1_enabled(ctx);
5102 t1 = tcg_temp_new();
5103 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5104 gen_load_fpr64(ctx, t1, rt);
5105 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
5106 tcg_temp_free(t1);
5107 break;
5108 #endif
5109 default:
5110 MIPS_INVAL("loongson_gsshfs");
5111 gen_reserved_instruction(ctx);
5112 break;
5114 break;
5115 default:
5116 MIPS_INVAL("loongson_gslsq");
5117 gen_reserved_instruction(ctx);
5118 break;
5120 tcg_temp_free(t0);
5123 /* Loongson EXT LDC2/SDC2 */
5124 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
5125 int rs, int rd)
5127 int offset = sextract32(ctx->opcode, 3, 8);
5128 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
5129 TCGv t0, t1;
5130 TCGv_i32 fp0;
5132 /* Pre-conditions */
5133 switch (opc) {
5134 case OPC_GSLBX:
5135 case OPC_GSLHX:
5136 case OPC_GSLWX:
5137 case OPC_GSLDX:
5138 /* prefetch, implement as NOP */
5139 if (rt == 0) {
5140 return;
5142 break;
5143 case OPC_GSSBX:
5144 case OPC_GSSHX:
5145 case OPC_GSSWX:
5146 case OPC_GSSDX:
5147 break;
5148 case OPC_GSLWXC1:
5149 #if defined(TARGET_MIPS64)
5150 case OPC_GSLDXC1:
5151 #endif
5152 check_cp1_enabled(ctx);
5153 /* prefetch, implement as NOP */
5154 if (rt == 0) {
5155 return;
5157 break;
5158 case OPC_GSSWXC1:
5159 #if defined(TARGET_MIPS64)
5160 case OPC_GSSDXC1:
5161 #endif
5162 check_cp1_enabled(ctx);
5163 break;
5164 default:
5165 MIPS_INVAL("loongson_lsdc2");
5166 gen_reserved_instruction(ctx);
5167 return;
5168 break;
5171 t0 = tcg_temp_new();
5173 gen_base_offset_addr(ctx, t0, rs, offset);
5174 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5176 switch (opc) {
5177 case OPC_GSLBX:
5178 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
5179 gen_store_gpr(t0, rt);
5180 break;
5181 case OPC_GSLHX:
5182 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
5183 ctx->default_tcg_memop_mask);
5184 gen_store_gpr(t0, rt);
5185 break;
5186 case OPC_GSLWX:
5187 gen_base_offset_addr(ctx, t0, rs, offset);
5188 if (rd) {
5189 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5191 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
5192 ctx->default_tcg_memop_mask);
5193 gen_store_gpr(t0, rt);
5194 break;
5195 #if defined(TARGET_MIPS64)
5196 case OPC_GSLDX:
5197 gen_base_offset_addr(ctx, t0, rs, offset);
5198 if (rd) {
5199 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5201 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5202 ctx->default_tcg_memop_mask);
5203 gen_store_gpr(t0, rt);
5204 break;
5205 #endif
5206 case OPC_GSLWXC1:
5207 check_cp1_enabled(ctx);
5208 gen_base_offset_addr(ctx, t0, rs, offset);
5209 if (rd) {
5210 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5212 fp0 = tcg_temp_new_i32();
5213 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
5214 ctx->default_tcg_memop_mask);
5215 gen_store_fpr32(ctx, fp0, rt);
5216 tcg_temp_free_i32(fp0);
5217 break;
5218 #if defined(TARGET_MIPS64)
5219 case OPC_GSLDXC1:
5220 check_cp1_enabled(ctx);
5221 gen_base_offset_addr(ctx, t0, rs, offset);
5222 if (rd) {
5223 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5225 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5226 ctx->default_tcg_memop_mask);
5227 gen_store_fpr64(ctx, t0, rt);
5228 break;
5229 #endif
5230 case OPC_GSSBX:
5231 t1 = tcg_temp_new();
5232 gen_load_gpr(t1, rt);
5233 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
5234 tcg_temp_free(t1);
5235 break;
5236 case OPC_GSSHX:
5237 t1 = tcg_temp_new();
5238 gen_load_gpr(t1, rt);
5239 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
5240 ctx->default_tcg_memop_mask);
5241 tcg_temp_free(t1);
5242 break;
5243 case OPC_GSSWX:
5244 t1 = tcg_temp_new();
5245 gen_load_gpr(t1, rt);
5246 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
5247 ctx->default_tcg_memop_mask);
5248 tcg_temp_free(t1);
5249 break;
5250 #if defined(TARGET_MIPS64)
5251 case OPC_GSSDX:
5252 t1 = tcg_temp_new();
5253 gen_load_gpr(t1, rt);
5254 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5255 ctx->default_tcg_memop_mask);
5256 tcg_temp_free(t1);
5257 break;
5258 #endif
5259 case OPC_GSSWXC1:
5260 fp0 = tcg_temp_new_i32();
5261 gen_load_fpr32(ctx, fp0, rt);
5262 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
5263 ctx->default_tcg_memop_mask);
5264 tcg_temp_free_i32(fp0);
5265 break;
5266 #if defined(TARGET_MIPS64)
5267 case OPC_GSSDXC1:
5268 t1 = tcg_temp_new();
5269 gen_load_fpr64(ctx, t1, rt);
5270 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
5271 ctx->default_tcg_memop_mask);
5272 tcg_temp_free(t1);
5273 break;
5274 #endif
5275 default:
5276 break;
5279 tcg_temp_free(t0);
5282 /* Traps */
5283 static void gen_trap(DisasContext *ctx, uint32_t opc,
5284 int rs, int rt, int16_t imm)
5286 int cond;
5287 TCGv t0 = tcg_temp_new();
5288 TCGv t1 = tcg_temp_new();
5290 cond = 0;
5291 /* Load needed operands */
5292 switch (opc) {
5293 case OPC_TEQ:
5294 case OPC_TGE:
5295 case OPC_TGEU:
5296 case OPC_TLT:
5297 case OPC_TLTU:
5298 case OPC_TNE:
5299 /* Compare two registers */
5300 if (rs != rt) {
5301 gen_load_gpr(t0, rs);
5302 gen_load_gpr(t1, rt);
5303 cond = 1;
5305 break;
5306 case OPC_TEQI:
5307 case OPC_TGEI:
5308 case OPC_TGEIU:
5309 case OPC_TLTI:
5310 case OPC_TLTIU:
5311 case OPC_TNEI:
5312 /* Compare register to immediate */
5313 if (rs != 0 || imm != 0) {
5314 gen_load_gpr(t0, rs);
5315 tcg_gen_movi_tl(t1, (int32_t)imm);
5316 cond = 1;
5318 break;
5320 if (cond == 0) {
5321 switch (opc) {
5322 case OPC_TEQ: /* rs == rs */
5323 case OPC_TEQI: /* r0 == 0 */
5324 case OPC_TGE: /* rs >= rs */
5325 case OPC_TGEI: /* r0 >= 0 */
5326 case OPC_TGEU: /* rs >= rs unsigned */
5327 case OPC_TGEIU: /* r0 >= 0 unsigned */
5328 /* Always trap */
5329 generate_exception_end(ctx, EXCP_TRAP);
5330 break;
5331 case OPC_TLT: /* rs < rs */
5332 case OPC_TLTI: /* r0 < 0 */
5333 case OPC_TLTU: /* rs < rs unsigned */
5334 case OPC_TLTIU: /* r0 < 0 unsigned */
5335 case OPC_TNE: /* rs != rs */
5336 case OPC_TNEI: /* r0 != 0 */
5337 /* Never trap: treat as NOP. */
5338 break;
5340 } else {
5341 TCGLabel *l1 = gen_new_label();
5343 switch (opc) {
5344 case OPC_TEQ:
5345 case OPC_TEQI:
5346 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5347 break;
5348 case OPC_TGE:
5349 case OPC_TGEI:
5350 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5351 break;
5352 case OPC_TGEU:
5353 case OPC_TGEIU:
5354 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5355 break;
5356 case OPC_TLT:
5357 case OPC_TLTI:
5358 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5359 break;
5360 case OPC_TLTU:
5361 case OPC_TLTIU:
5362 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5363 break;
5364 case OPC_TNE:
5365 case OPC_TNEI:
5366 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5367 break;
5369 generate_exception(ctx, EXCP_TRAP);
5370 gen_set_label(l1);
5372 tcg_temp_free(t0);
5373 tcg_temp_free(t1);
5376 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5378 if (unlikely(ctx->base.singlestep_enabled)) {
5379 return false;
5382 #ifndef CONFIG_USER_ONLY
5383 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5384 #else
5385 return true;
5386 #endif
5389 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5391 if (use_goto_tb(ctx, dest)) {
5392 tcg_gen_goto_tb(n);
5393 gen_save_pc(dest);
5394 tcg_gen_exit_tb(ctx->base.tb, n);
5395 } else {
5396 gen_save_pc(dest);
5397 if (ctx->base.singlestep_enabled) {
5398 save_cpu_state(ctx, 0);
5399 gen_helper_raise_exception_debug(cpu_env);
5401 tcg_gen_lookup_and_goto_ptr();
5405 /* Branches (before delay slot) */
5406 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
5407 int insn_bytes,
5408 int rs, int rt, int32_t offset,
5409 int delayslot_size)
5411 target_ulong btgt = -1;
5412 int blink = 0;
5413 int bcond_compute = 0;
5414 TCGv t0 = tcg_temp_new();
5415 TCGv t1 = tcg_temp_new();
5417 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5418 #ifdef MIPS_DEBUG_DISAS
5419 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5420 TARGET_FMT_lx "\n", ctx->base.pc_next);
5421 #endif
5422 gen_reserved_instruction(ctx);
5423 goto out;
5426 /* Load needed operands */
5427 switch (opc) {
5428 case OPC_BEQ:
5429 case OPC_BEQL:
5430 case OPC_BNE:
5431 case OPC_BNEL:
5432 /* Compare two registers */
5433 if (rs != rt) {
5434 gen_load_gpr(t0, rs);
5435 gen_load_gpr(t1, rt);
5436 bcond_compute = 1;
5438 btgt = ctx->base.pc_next + insn_bytes + offset;
5439 break;
5440 case OPC_BGEZ:
5441 case OPC_BGEZAL:
5442 case OPC_BGEZALL:
5443 case OPC_BGEZL:
5444 case OPC_BGTZ:
5445 case OPC_BGTZL:
5446 case OPC_BLEZ:
5447 case OPC_BLEZL:
5448 case OPC_BLTZ:
5449 case OPC_BLTZAL:
5450 case OPC_BLTZALL:
5451 case OPC_BLTZL:
5452 /* Compare to zero */
5453 if (rs != 0) {
5454 gen_load_gpr(t0, rs);
5455 bcond_compute = 1;
5457 btgt = ctx->base.pc_next + insn_bytes + offset;
5458 break;
5459 case OPC_BPOSGE32:
5460 #if defined(TARGET_MIPS64)
5461 case OPC_BPOSGE64:
5462 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5463 #else
5464 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5465 #endif
5466 bcond_compute = 1;
5467 btgt = ctx->base.pc_next + insn_bytes + offset;
5468 break;
5469 case OPC_J:
5470 case OPC_JAL:
5471 case OPC_JALX:
5472 /* Jump to immediate */
5473 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5474 (uint32_t)offset;
5475 break;
5476 case OPC_JR:
5477 case OPC_JALR:
5478 /* Jump to register */
5479 if (offset != 0 && offset != 16) {
5481 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5482 * others are reserved.
5484 MIPS_INVAL("jump hint");
5485 gen_reserved_instruction(ctx);
5486 goto out;
5488 gen_load_gpr(btarget, rs);
5489 break;
5490 default:
5491 MIPS_INVAL("branch/jump");
5492 gen_reserved_instruction(ctx);
5493 goto out;
5495 if (bcond_compute == 0) {
5496 /* No condition to be computed */
5497 switch (opc) {
5498 case OPC_BEQ: /* rx == rx */
5499 case OPC_BEQL: /* rx == rx likely */
5500 case OPC_BGEZ: /* 0 >= 0 */
5501 case OPC_BGEZL: /* 0 >= 0 likely */
5502 case OPC_BLEZ: /* 0 <= 0 */
5503 case OPC_BLEZL: /* 0 <= 0 likely */
5504 /* Always take */
5505 ctx->hflags |= MIPS_HFLAG_B;
5506 break;
5507 case OPC_BGEZAL: /* 0 >= 0 */
5508 case OPC_BGEZALL: /* 0 >= 0 likely */
5509 /* Always take and link */
5510 blink = 31;
5511 ctx->hflags |= MIPS_HFLAG_B;
5512 break;
5513 case OPC_BNE: /* rx != rx */
5514 case OPC_BGTZ: /* 0 > 0 */
5515 case OPC_BLTZ: /* 0 < 0 */
5516 /* Treat as NOP. */
5517 goto out;
5518 case OPC_BLTZAL: /* 0 < 0 */
5520 * Handle as an unconditional branch to get correct delay
5521 * slot checking.
5523 blink = 31;
5524 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5525 ctx->hflags |= MIPS_HFLAG_B;
5526 break;
5527 case OPC_BLTZALL: /* 0 < 0 likely */
5528 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5529 /* Skip the instruction in the delay slot */
5530 ctx->base.pc_next += 4;
5531 goto out;
5532 case OPC_BNEL: /* rx != rx likely */
5533 case OPC_BGTZL: /* 0 > 0 likely */
5534 case OPC_BLTZL: /* 0 < 0 likely */
5535 /* Skip the instruction in the delay slot */
5536 ctx->base.pc_next += 4;
5537 goto out;
5538 case OPC_J:
5539 ctx->hflags |= MIPS_HFLAG_B;
5540 break;
5541 case OPC_JALX:
5542 ctx->hflags |= MIPS_HFLAG_BX;
5543 /* Fallthrough */
5544 case OPC_JAL:
5545 blink = 31;
5546 ctx->hflags |= MIPS_HFLAG_B;
5547 break;
5548 case OPC_JR:
5549 ctx->hflags |= MIPS_HFLAG_BR;
5550 break;
5551 case OPC_JALR:
5552 blink = rt;
5553 ctx->hflags |= MIPS_HFLAG_BR;
5554 break;
5555 default:
5556 MIPS_INVAL("branch/jump");
5557 gen_reserved_instruction(ctx);
5558 goto out;
5560 } else {
5561 switch (opc) {
5562 case OPC_BEQ:
5563 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5564 goto not_likely;
5565 case OPC_BEQL:
5566 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5567 goto likely;
5568 case OPC_BNE:
5569 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5570 goto not_likely;
5571 case OPC_BNEL:
5572 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5573 goto likely;
5574 case OPC_BGEZ:
5575 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5576 goto not_likely;
5577 case OPC_BGEZL:
5578 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5579 goto likely;
5580 case OPC_BGEZAL:
5581 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5582 blink = 31;
5583 goto not_likely;
5584 case OPC_BGEZALL:
5585 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5586 blink = 31;
5587 goto likely;
5588 case OPC_BGTZ:
5589 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5590 goto not_likely;
5591 case OPC_BGTZL:
5592 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5593 goto likely;
5594 case OPC_BLEZ:
5595 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5596 goto not_likely;
5597 case OPC_BLEZL:
5598 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5599 goto likely;
5600 case OPC_BLTZ:
5601 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5602 goto not_likely;
5603 case OPC_BLTZL:
5604 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5605 goto likely;
5606 case OPC_BPOSGE32:
5607 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5608 goto not_likely;
5609 #if defined(TARGET_MIPS64)
5610 case OPC_BPOSGE64:
5611 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5612 goto not_likely;
5613 #endif
5614 case OPC_BLTZAL:
5615 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5616 blink = 31;
5617 not_likely:
5618 ctx->hflags |= MIPS_HFLAG_BC;
5619 break;
5620 case OPC_BLTZALL:
5621 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5622 blink = 31;
5623 likely:
5624 ctx->hflags |= MIPS_HFLAG_BL;
5625 break;
5626 default:
5627 MIPS_INVAL("conditional branch/jump");
5628 gen_reserved_instruction(ctx);
5629 goto out;
5633 ctx->btarget = btgt;
5635 switch (delayslot_size) {
5636 case 2:
5637 ctx->hflags |= MIPS_HFLAG_BDS16;
5638 break;
5639 case 4:
5640 ctx->hflags |= MIPS_HFLAG_BDS32;
5641 break;
5644 if (blink > 0) {
5645 int post_delay = insn_bytes + delayslot_size;
5646 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5648 tcg_gen_movi_tl(cpu_gpr[blink],
5649 ctx->base.pc_next + post_delay + lowbit);
5652 out:
5653 if (insn_bytes == 2) {
5654 ctx->hflags |= MIPS_HFLAG_B16;
5656 tcg_temp_free(t0);
5657 tcg_temp_free(t1);
5661 /* nanoMIPS Branches */
5662 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5663 int insn_bytes,
5664 int rs, int rt, int32_t offset)
5666 target_ulong btgt = -1;
5667 int bcond_compute = 0;
5668 TCGv t0 = tcg_temp_new();
5669 TCGv t1 = tcg_temp_new();
5671 /* Load needed operands */
5672 switch (opc) {
5673 case OPC_BEQ:
5674 case OPC_BNE:
5675 /* Compare two registers */
5676 if (rs != rt) {
5677 gen_load_gpr(t0, rs);
5678 gen_load_gpr(t1, rt);
5679 bcond_compute = 1;
5681 btgt = ctx->base.pc_next + insn_bytes + offset;
5682 break;
5683 case OPC_BGEZAL:
5684 /* Compare to zero */
5685 if (rs != 0) {
5686 gen_load_gpr(t0, rs);
5687 bcond_compute = 1;
5689 btgt = ctx->base.pc_next + insn_bytes + offset;
5690 break;
5691 case OPC_BPOSGE32:
5692 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5693 bcond_compute = 1;
5694 btgt = ctx->base.pc_next + insn_bytes + offset;
5695 break;
5696 case OPC_JR:
5697 case OPC_JALR:
5698 /* Jump to register */
5699 if (offset != 0 && offset != 16) {
5701 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5702 * others are reserved.
5704 MIPS_INVAL("jump hint");
5705 gen_reserved_instruction(ctx);
5706 goto out;
5708 gen_load_gpr(btarget, rs);
5709 break;
5710 default:
5711 MIPS_INVAL("branch/jump");
5712 gen_reserved_instruction(ctx);
5713 goto out;
5715 if (bcond_compute == 0) {
5716 /* No condition to be computed */
5717 switch (opc) {
5718 case OPC_BEQ: /* rx == rx */
5719 /* Always take */
5720 ctx->hflags |= MIPS_HFLAG_B;
5721 break;
5722 case OPC_BGEZAL: /* 0 >= 0 */
5723 /* Always take and link */
5724 tcg_gen_movi_tl(cpu_gpr[31],
5725 ctx->base.pc_next + insn_bytes);
5726 ctx->hflags |= MIPS_HFLAG_B;
5727 break;
5728 case OPC_BNE: /* rx != rx */
5729 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5730 /* Skip the instruction in the delay slot */
5731 ctx->base.pc_next += 4;
5732 goto out;
5733 case OPC_JR:
5734 ctx->hflags |= MIPS_HFLAG_BR;
5735 break;
5736 case OPC_JALR:
5737 if (rt > 0) {
5738 tcg_gen_movi_tl(cpu_gpr[rt],
5739 ctx->base.pc_next + insn_bytes);
5741 ctx->hflags |= MIPS_HFLAG_BR;
5742 break;
5743 default:
5744 MIPS_INVAL("branch/jump");
5745 gen_reserved_instruction(ctx);
5746 goto out;
5748 } else {
5749 switch (opc) {
5750 case OPC_BEQ:
5751 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5752 goto not_likely;
5753 case OPC_BNE:
5754 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5755 goto not_likely;
5756 case OPC_BGEZAL:
5757 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5758 tcg_gen_movi_tl(cpu_gpr[31],
5759 ctx->base.pc_next + insn_bytes);
5760 goto not_likely;
5761 case OPC_BPOSGE32:
5762 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5763 not_likely:
5764 ctx->hflags |= MIPS_HFLAG_BC;
5765 break;
5766 default:
5767 MIPS_INVAL("conditional branch/jump");
5768 gen_reserved_instruction(ctx);
5769 goto out;
5773 ctx->btarget = btgt;
5775 out:
5776 if (insn_bytes == 2) {
5777 ctx->hflags |= MIPS_HFLAG_B16;
5779 tcg_temp_free(t0);
5780 tcg_temp_free(t1);
5784 /* special3 bitfield operations */
5785 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
5786 int rs, int lsb, int msb)
5788 TCGv t0 = tcg_temp_new();
5789 TCGv t1 = tcg_temp_new();
5791 gen_load_gpr(t1, rs);
5792 switch (opc) {
5793 case OPC_EXT:
5794 if (lsb + msb > 31) {
5795 goto fail;
5797 if (msb != 31) {
5798 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5799 } else {
5801 * The two checks together imply that lsb == 0,
5802 * so this is a simple sign-extension.
5804 tcg_gen_ext32s_tl(t0, t1);
5806 break;
5807 #if defined(TARGET_MIPS64)
5808 case OPC_DEXTU:
5809 lsb += 32;
5810 goto do_dext;
5811 case OPC_DEXTM:
5812 msb += 32;
5813 goto do_dext;
5814 case OPC_DEXT:
5815 do_dext:
5816 if (lsb + msb > 63) {
5817 goto fail;
5819 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5820 break;
5821 #endif
5822 case OPC_INS:
5823 if (lsb > msb) {
5824 goto fail;
5826 gen_load_gpr(t0, rt);
5827 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5828 tcg_gen_ext32s_tl(t0, t0);
5829 break;
5830 #if defined(TARGET_MIPS64)
5831 case OPC_DINSU:
5832 lsb += 32;
5833 /* FALLTHRU */
5834 case OPC_DINSM:
5835 msb += 32;
5836 /* FALLTHRU */
5837 case OPC_DINS:
5838 if (lsb > msb) {
5839 goto fail;
5841 gen_load_gpr(t0, rt);
5842 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5843 break;
5844 #endif
5845 default:
5846 fail:
5847 MIPS_INVAL("bitops");
5848 gen_reserved_instruction(ctx);
5849 tcg_temp_free(t0);
5850 tcg_temp_free(t1);
5851 return;
5853 gen_store_gpr(t0, rt);
5854 tcg_temp_free(t0);
5855 tcg_temp_free(t1);
5858 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
5860 TCGv t0;
5862 if (rd == 0) {
5863 /* If no destination, treat it as a NOP. */
5864 return;
5867 t0 = tcg_temp_new();
5868 gen_load_gpr(t0, rt);
5869 switch (op2) {
5870 case OPC_WSBH:
5872 TCGv t1 = tcg_temp_new();
5873 TCGv t2 = tcg_const_tl(0x00FF00FF);
5875 tcg_gen_shri_tl(t1, t0, 8);
5876 tcg_gen_and_tl(t1, t1, t2);
5877 tcg_gen_and_tl(t0, t0, t2);
5878 tcg_gen_shli_tl(t0, t0, 8);
5879 tcg_gen_or_tl(t0, t0, t1);
5880 tcg_temp_free(t2);
5881 tcg_temp_free(t1);
5882 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5884 break;
5885 case OPC_SEB:
5886 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
5887 break;
5888 case OPC_SEH:
5889 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
5890 break;
5891 #if defined(TARGET_MIPS64)
5892 case OPC_DSBH:
5894 TCGv t1 = tcg_temp_new();
5895 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
5897 tcg_gen_shri_tl(t1, t0, 8);
5898 tcg_gen_and_tl(t1, t1, t2);
5899 tcg_gen_and_tl(t0, t0, t2);
5900 tcg_gen_shli_tl(t0, t0, 8);
5901 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5902 tcg_temp_free(t2);
5903 tcg_temp_free(t1);
5905 break;
5906 case OPC_DSHD:
5908 TCGv t1 = tcg_temp_new();
5909 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
5911 tcg_gen_shri_tl(t1, t0, 16);
5912 tcg_gen_and_tl(t1, t1, t2);
5913 tcg_gen_and_tl(t0, t0, t2);
5914 tcg_gen_shli_tl(t0, t0, 16);
5915 tcg_gen_or_tl(t0, t0, t1);
5916 tcg_gen_shri_tl(t1, t0, 32);
5917 tcg_gen_shli_tl(t0, t0, 32);
5918 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5919 tcg_temp_free(t2);
5920 tcg_temp_free(t1);
5922 break;
5923 #endif
5924 default:
5925 MIPS_INVAL("bsfhl");
5926 gen_reserved_instruction(ctx);
5927 tcg_temp_free(t0);
5928 return;
5930 tcg_temp_free(t0);
5933 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
5934 int rt, int bits)
5936 TCGv t0;
5937 if (rd == 0) {
5938 /* Treat as NOP. */
5939 return;
5941 t0 = tcg_temp_new();
5942 if (bits == 0 || bits == wordsz) {
5943 if (bits == 0) {
5944 gen_load_gpr(t0, rt);
5945 } else {
5946 gen_load_gpr(t0, rs);
5948 switch (wordsz) {
5949 case 32:
5950 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5951 break;
5952 #if defined(TARGET_MIPS64)
5953 case 64:
5954 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5955 break;
5956 #endif
5958 } else {
5959 TCGv t1 = tcg_temp_new();
5960 gen_load_gpr(t0, rt);
5961 gen_load_gpr(t1, rs);
5962 switch (wordsz) {
5963 case 32:
5965 TCGv_i64 t2 = tcg_temp_new_i64();
5966 tcg_gen_concat_tl_i64(t2, t1, t0);
5967 tcg_gen_shri_i64(t2, t2, 32 - bits);
5968 gen_move_low32(cpu_gpr[rd], t2);
5969 tcg_temp_free_i64(t2);
5971 break;
5972 #if defined(TARGET_MIPS64)
5973 case 64:
5974 tcg_gen_shli_tl(t0, t0, bits);
5975 tcg_gen_shri_tl(t1, t1, 64 - bits);
5976 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5977 break;
5978 #endif
5980 tcg_temp_free(t1);
5983 tcg_temp_free(t0);
5986 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5987 int bp)
5989 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5992 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5993 int shift)
5995 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5998 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6000 TCGv t0;
6001 if (rd == 0) {
6002 /* Treat as NOP. */
6003 return;
6005 t0 = tcg_temp_new();
6006 gen_load_gpr(t0, rt);
6007 switch (opc) {
6008 case OPC_BITSWAP:
6009 gen_helper_bitswap(cpu_gpr[rd], t0);
6010 break;
6011 #if defined(TARGET_MIPS64)
6012 case OPC_DBITSWAP:
6013 gen_helper_dbitswap(cpu_gpr[rd], t0);
6014 break;
6015 #endif
6017 tcg_temp_free(t0);
6020 #ifndef CONFIG_USER_ONLY
6021 /* CP0 (MMU and control) */
6022 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6024 TCGv_i64 t0 = tcg_temp_new_i64();
6025 TCGv_i64 t1 = tcg_temp_new_i64();
6027 tcg_gen_ext_tl_i64(t0, arg);
6028 tcg_gen_ld_i64(t1, cpu_env, off);
6029 #if defined(TARGET_MIPS64)
6030 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6031 #else
6032 tcg_gen_concat32_i64(t1, t1, t0);
6033 #endif
6034 tcg_gen_st_i64(t1, cpu_env, off);
6035 tcg_temp_free_i64(t1);
6036 tcg_temp_free_i64(t0);
6039 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6041 TCGv_i64 t0 = tcg_temp_new_i64();
6042 TCGv_i64 t1 = tcg_temp_new_i64();
6044 tcg_gen_ext_tl_i64(t0, arg);
6045 tcg_gen_ld_i64(t1, cpu_env, off);
6046 tcg_gen_concat32_i64(t1, t1, t0);
6047 tcg_gen_st_i64(t1, cpu_env, off);
6048 tcg_temp_free_i64(t1);
6049 tcg_temp_free_i64(t0);
6052 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6054 TCGv_i64 t0 = tcg_temp_new_i64();
6056 tcg_gen_ld_i64(t0, cpu_env, off);
6057 #if defined(TARGET_MIPS64)
6058 tcg_gen_shri_i64(t0, t0, 30);
6059 #else
6060 tcg_gen_shri_i64(t0, t0, 32);
6061 #endif
6062 gen_move_low32(arg, t0);
6063 tcg_temp_free_i64(t0);
6066 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6068 TCGv_i64 t0 = tcg_temp_new_i64();
6070 tcg_gen_ld_i64(t0, cpu_env, off);
6071 tcg_gen_shri_i64(t0, t0, 32 + shift);
6072 gen_move_low32(arg, t0);
6073 tcg_temp_free_i64(t0);
6076 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
6078 TCGv_i32 t0 = tcg_temp_new_i32();
6080 tcg_gen_ld_i32(t0, cpu_env, off);
6081 tcg_gen_ext_i32_tl(arg, t0);
6082 tcg_temp_free_i32(t0);
6085 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
6087 tcg_gen_ld_tl(arg, cpu_env, off);
6088 tcg_gen_ext32s_tl(arg, arg);
6091 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
6093 TCGv_i32 t0 = tcg_temp_new_i32();
6095 tcg_gen_trunc_tl_i32(t0, arg);
6096 tcg_gen_st_i32(t0, cpu_env, off);
6097 tcg_temp_free_i32(t0);
6100 #define CP0_CHECK(c) \
6101 do { \
6102 if (!(c)) { \
6103 goto cp0_unimplemented; \
6105 } while (0)
6107 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6109 const char *register_name = "invalid";
6111 switch (reg) {
6112 case CP0_REGISTER_02:
6113 switch (sel) {
6114 case 0:
6115 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6116 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6117 register_name = "EntryLo0";
6118 break;
6119 default:
6120 goto cp0_unimplemented;
6122 break;
6123 case CP0_REGISTER_03:
6124 switch (sel) {
6125 case CP0_REG03__ENTRYLO1:
6126 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6127 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6128 register_name = "EntryLo1";
6129 break;
6130 default:
6131 goto cp0_unimplemented;
6133 break;
6134 case CP0_REGISTER_09:
6135 switch (sel) {
6136 case CP0_REG09__SAAR:
6137 CP0_CHECK(ctx->saar);
6138 gen_helper_mfhc0_saar(arg, cpu_env);
6139 register_name = "SAAR";
6140 break;
6141 default:
6142 goto cp0_unimplemented;
6144 break;
6145 case CP0_REGISTER_17:
6146 switch (sel) {
6147 case CP0_REG17__LLADDR:
6148 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
6149 ctx->CP0_LLAddr_shift);
6150 register_name = "LLAddr";
6151 break;
6152 case CP0_REG17__MAAR:
6153 CP0_CHECK(ctx->mrp);
6154 gen_helper_mfhc0_maar(arg, cpu_env);
6155 register_name = "MAAR";
6156 break;
6157 default:
6158 goto cp0_unimplemented;
6160 break;
6161 case CP0_REGISTER_19:
6162 switch (sel) {
6163 case CP0_REG19__WATCHHI0:
6164 case CP0_REG19__WATCHHI1:
6165 case CP0_REG19__WATCHHI2:
6166 case CP0_REG19__WATCHHI3:
6167 case CP0_REG19__WATCHHI4:
6168 case CP0_REG19__WATCHHI5:
6169 case CP0_REG19__WATCHHI6:
6170 case CP0_REG19__WATCHHI7:
6171 /* upper 32 bits are only available when Config5MI != 0 */
6172 CP0_CHECK(ctx->mi);
6173 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
6174 register_name = "WatchHi";
6175 break;
6176 default:
6177 goto cp0_unimplemented;
6179 break;
6180 case CP0_REGISTER_28:
6181 switch (sel) {
6182 case 0:
6183 case 2:
6184 case 4:
6185 case 6:
6186 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6187 register_name = "TagLo";
6188 break;
6189 default:
6190 goto cp0_unimplemented;
6192 break;
6193 default:
6194 goto cp0_unimplemented;
6196 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6197 return;
6199 cp0_unimplemented:
6200 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6201 register_name, reg, sel);
6202 tcg_gen_movi_tl(arg, 0);
6205 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6207 const char *register_name = "invalid";
6208 uint64_t mask = ctx->PAMask >> 36;
6210 switch (reg) {
6211 case CP0_REGISTER_02:
6212 switch (sel) {
6213 case 0:
6214 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6215 tcg_gen_andi_tl(arg, arg, mask);
6216 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6217 register_name = "EntryLo0";
6218 break;
6219 default:
6220 goto cp0_unimplemented;
6222 break;
6223 case CP0_REGISTER_03:
6224 switch (sel) {
6225 case CP0_REG03__ENTRYLO1:
6226 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6227 tcg_gen_andi_tl(arg, arg, mask);
6228 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6229 register_name = "EntryLo1";
6230 break;
6231 default:
6232 goto cp0_unimplemented;
6234 break;
6235 case CP0_REGISTER_09:
6236 switch (sel) {
6237 case CP0_REG09__SAAR:
6238 CP0_CHECK(ctx->saar);
6239 gen_helper_mthc0_saar(cpu_env, arg);
6240 register_name = "SAAR";
6241 break;
6242 default:
6243 goto cp0_unimplemented;
6245 break;
6246 case CP0_REGISTER_17:
6247 switch (sel) {
6248 case CP0_REG17__LLADDR:
6250 * LLAddr is read-only (the only exception is bit 0 if LLB is
6251 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6252 * relevant for modern MIPS cores supporting MTHC0, therefore
6253 * treating MTHC0 to LLAddr as NOP.
6255 register_name = "LLAddr";
6256 break;
6257 case CP0_REG17__MAAR:
6258 CP0_CHECK(ctx->mrp);
6259 gen_helper_mthc0_maar(cpu_env, arg);
6260 register_name = "MAAR";
6261 break;
6262 default:
6263 goto cp0_unimplemented;
6265 break;
6266 case CP0_REGISTER_19:
6267 switch (sel) {
6268 case CP0_REG19__WATCHHI0:
6269 case CP0_REG19__WATCHHI1:
6270 case CP0_REG19__WATCHHI2:
6271 case CP0_REG19__WATCHHI3:
6272 case CP0_REG19__WATCHHI4:
6273 case CP0_REG19__WATCHHI5:
6274 case CP0_REG19__WATCHHI6:
6275 case CP0_REG19__WATCHHI7:
6276 /* upper 32 bits are only available when Config5MI != 0 */
6277 CP0_CHECK(ctx->mi);
6278 gen_helper_0e1i(mthc0_watchhi, arg, sel);
6279 register_name = "WatchHi";
6280 break;
6281 default:
6282 goto cp0_unimplemented;
6284 break;
6285 case CP0_REGISTER_28:
6286 switch (sel) {
6287 case 0:
6288 case 2:
6289 case 4:
6290 case 6:
6291 tcg_gen_andi_tl(arg, arg, mask);
6292 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6293 register_name = "TagLo";
6294 break;
6295 default:
6296 goto cp0_unimplemented;
6298 break;
6299 default:
6300 goto cp0_unimplemented;
6302 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6304 cp0_unimplemented:
6305 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6306 register_name, reg, sel);
6309 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6311 if (ctx->insn_flags & ISA_MIPS_R6) {
6312 tcg_gen_movi_tl(arg, 0);
6313 } else {
6314 tcg_gen_movi_tl(arg, ~0);
6318 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6320 const char *register_name = "invalid";
6322 if (sel != 0) {
6323 check_insn(ctx, ISA_MIPS_R1);
6326 switch (reg) {
6327 case CP0_REGISTER_00:
6328 switch (sel) {
6329 case CP0_REG00__INDEX:
6330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6331 register_name = "Index";
6332 break;
6333 case CP0_REG00__MVPCONTROL:
6334 CP0_CHECK(ctx->insn_flags & ASE_MT);
6335 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6336 register_name = "MVPControl";
6337 break;
6338 case CP0_REG00__MVPCONF0:
6339 CP0_CHECK(ctx->insn_flags & ASE_MT);
6340 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6341 register_name = "MVPConf0";
6342 break;
6343 case CP0_REG00__MVPCONF1:
6344 CP0_CHECK(ctx->insn_flags & ASE_MT);
6345 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6346 register_name = "MVPConf1";
6347 break;
6348 case CP0_REG00__VPCONTROL:
6349 CP0_CHECK(ctx->vp);
6350 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6351 register_name = "VPControl";
6352 break;
6353 default:
6354 goto cp0_unimplemented;
6356 break;
6357 case CP0_REGISTER_01:
6358 switch (sel) {
6359 case CP0_REG01__RANDOM:
6360 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6361 gen_helper_mfc0_random(arg, cpu_env);
6362 register_name = "Random";
6363 break;
6364 case CP0_REG01__VPECONTROL:
6365 CP0_CHECK(ctx->insn_flags & ASE_MT);
6366 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6367 register_name = "VPEControl";
6368 break;
6369 case CP0_REG01__VPECONF0:
6370 CP0_CHECK(ctx->insn_flags & ASE_MT);
6371 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6372 register_name = "VPEConf0";
6373 break;
6374 case CP0_REG01__VPECONF1:
6375 CP0_CHECK(ctx->insn_flags & ASE_MT);
6376 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6377 register_name = "VPEConf1";
6378 break;
6379 case CP0_REG01__YQMASK:
6380 CP0_CHECK(ctx->insn_flags & ASE_MT);
6381 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6382 register_name = "YQMask";
6383 break;
6384 case CP0_REG01__VPESCHEDULE:
6385 CP0_CHECK(ctx->insn_flags & ASE_MT);
6386 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6387 register_name = "VPESchedule";
6388 break;
6389 case CP0_REG01__VPESCHEFBACK:
6390 CP0_CHECK(ctx->insn_flags & ASE_MT);
6391 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6392 register_name = "VPEScheFBack";
6393 break;
6394 case CP0_REG01__VPEOPT:
6395 CP0_CHECK(ctx->insn_flags & ASE_MT);
6396 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6397 register_name = "VPEOpt";
6398 break;
6399 default:
6400 goto cp0_unimplemented;
6402 break;
6403 case CP0_REGISTER_02:
6404 switch (sel) {
6405 case CP0_REG02__ENTRYLO0:
6407 TCGv_i64 tmp = tcg_temp_new_i64();
6408 tcg_gen_ld_i64(tmp, cpu_env,
6409 offsetof(CPUMIPSState, CP0_EntryLo0));
6410 #if defined(TARGET_MIPS64)
6411 if (ctx->rxi) {
6412 /* Move RI/XI fields to bits 31:30 */
6413 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6414 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6416 #endif
6417 gen_move_low32(arg, tmp);
6418 tcg_temp_free_i64(tmp);
6420 register_name = "EntryLo0";
6421 break;
6422 case CP0_REG02__TCSTATUS:
6423 CP0_CHECK(ctx->insn_flags & ASE_MT);
6424 gen_helper_mfc0_tcstatus(arg, cpu_env);
6425 register_name = "TCStatus";
6426 break;
6427 case CP0_REG02__TCBIND:
6428 CP0_CHECK(ctx->insn_flags & ASE_MT);
6429 gen_helper_mfc0_tcbind(arg, cpu_env);
6430 register_name = "TCBind";
6431 break;
6432 case CP0_REG02__TCRESTART:
6433 CP0_CHECK(ctx->insn_flags & ASE_MT);
6434 gen_helper_mfc0_tcrestart(arg, cpu_env);
6435 register_name = "TCRestart";
6436 break;
6437 case CP0_REG02__TCHALT:
6438 CP0_CHECK(ctx->insn_flags & ASE_MT);
6439 gen_helper_mfc0_tchalt(arg, cpu_env);
6440 register_name = "TCHalt";
6441 break;
6442 case CP0_REG02__TCCONTEXT:
6443 CP0_CHECK(ctx->insn_flags & ASE_MT);
6444 gen_helper_mfc0_tccontext(arg, cpu_env);
6445 register_name = "TCContext";
6446 break;
6447 case CP0_REG02__TCSCHEDULE:
6448 CP0_CHECK(ctx->insn_flags & ASE_MT);
6449 gen_helper_mfc0_tcschedule(arg, cpu_env);
6450 register_name = "TCSchedule";
6451 break;
6452 case CP0_REG02__TCSCHEFBACK:
6453 CP0_CHECK(ctx->insn_flags & ASE_MT);
6454 gen_helper_mfc0_tcschefback(arg, cpu_env);
6455 register_name = "TCScheFBack";
6456 break;
6457 default:
6458 goto cp0_unimplemented;
6460 break;
6461 case CP0_REGISTER_03:
6462 switch (sel) {
6463 case CP0_REG03__ENTRYLO1:
6465 TCGv_i64 tmp = tcg_temp_new_i64();
6466 tcg_gen_ld_i64(tmp, cpu_env,
6467 offsetof(CPUMIPSState, CP0_EntryLo1));
6468 #if defined(TARGET_MIPS64)
6469 if (ctx->rxi) {
6470 /* Move RI/XI fields to bits 31:30 */
6471 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6472 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6474 #endif
6475 gen_move_low32(arg, tmp);
6476 tcg_temp_free_i64(tmp);
6478 register_name = "EntryLo1";
6479 break;
6480 case CP0_REG03__GLOBALNUM:
6481 CP0_CHECK(ctx->vp);
6482 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6483 register_name = "GlobalNumber";
6484 break;
6485 default:
6486 goto cp0_unimplemented;
6488 break;
6489 case CP0_REGISTER_04:
6490 switch (sel) {
6491 case CP0_REG04__CONTEXT:
6492 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6493 tcg_gen_ext32s_tl(arg, arg);
6494 register_name = "Context";
6495 break;
6496 case CP0_REG04__CONTEXTCONFIG:
6497 /* SmartMIPS ASE */
6498 /* gen_helper_mfc0_contextconfig(arg); */
6499 register_name = "ContextConfig";
6500 goto cp0_unimplemented;
6501 case CP0_REG04__USERLOCAL:
6502 CP0_CHECK(ctx->ulri);
6503 tcg_gen_ld_tl(arg, cpu_env,
6504 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6505 tcg_gen_ext32s_tl(arg, arg);
6506 register_name = "UserLocal";
6507 break;
6508 case CP0_REG04__MMID:
6509 CP0_CHECK(ctx->mi);
6510 gen_helper_mtc0_memorymapid(cpu_env, arg);
6511 register_name = "MMID";
6512 break;
6513 default:
6514 goto cp0_unimplemented;
6516 break;
6517 case CP0_REGISTER_05:
6518 switch (sel) {
6519 case CP0_REG05__PAGEMASK:
6520 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6521 register_name = "PageMask";
6522 break;
6523 case CP0_REG05__PAGEGRAIN:
6524 check_insn(ctx, ISA_MIPS_R2);
6525 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6526 register_name = "PageGrain";
6527 break;
6528 case CP0_REG05__SEGCTL0:
6529 CP0_CHECK(ctx->sc);
6530 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6531 tcg_gen_ext32s_tl(arg, arg);
6532 register_name = "SegCtl0";
6533 break;
6534 case CP0_REG05__SEGCTL1:
6535 CP0_CHECK(ctx->sc);
6536 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6537 tcg_gen_ext32s_tl(arg, arg);
6538 register_name = "SegCtl1";
6539 break;
6540 case CP0_REG05__SEGCTL2:
6541 CP0_CHECK(ctx->sc);
6542 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6543 tcg_gen_ext32s_tl(arg, arg);
6544 register_name = "SegCtl2";
6545 break;
6546 case CP0_REG05__PWBASE:
6547 check_pw(ctx);
6548 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6549 register_name = "PWBase";
6550 break;
6551 case CP0_REG05__PWFIELD:
6552 check_pw(ctx);
6553 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6554 register_name = "PWField";
6555 break;
6556 case CP0_REG05__PWSIZE:
6557 check_pw(ctx);
6558 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6559 register_name = "PWSize";
6560 break;
6561 default:
6562 goto cp0_unimplemented;
6564 break;
6565 case CP0_REGISTER_06:
6566 switch (sel) {
6567 case CP0_REG06__WIRED:
6568 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6569 register_name = "Wired";
6570 break;
6571 case CP0_REG06__SRSCONF0:
6572 check_insn(ctx, ISA_MIPS_R2);
6573 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6574 register_name = "SRSConf0";
6575 break;
6576 case CP0_REG06__SRSCONF1:
6577 check_insn(ctx, ISA_MIPS_R2);
6578 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6579 register_name = "SRSConf1";
6580 break;
6581 case CP0_REG06__SRSCONF2:
6582 check_insn(ctx, ISA_MIPS_R2);
6583 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6584 register_name = "SRSConf2";
6585 break;
6586 case CP0_REG06__SRSCONF3:
6587 check_insn(ctx, ISA_MIPS_R2);
6588 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6589 register_name = "SRSConf3";
6590 break;
6591 case CP0_REG06__SRSCONF4:
6592 check_insn(ctx, ISA_MIPS_R2);
6593 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6594 register_name = "SRSConf4";
6595 break;
6596 case CP0_REG06__PWCTL:
6597 check_pw(ctx);
6598 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6599 register_name = "PWCtl";
6600 break;
6601 default:
6602 goto cp0_unimplemented;
6604 break;
6605 case CP0_REGISTER_07:
6606 switch (sel) {
6607 case CP0_REG07__HWRENA:
6608 check_insn(ctx, ISA_MIPS_R2);
6609 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6610 register_name = "HWREna";
6611 break;
6612 default:
6613 goto cp0_unimplemented;
6615 break;
6616 case CP0_REGISTER_08:
6617 switch (sel) {
6618 case CP0_REG08__BADVADDR:
6619 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6620 tcg_gen_ext32s_tl(arg, arg);
6621 register_name = "BadVAddr";
6622 break;
6623 case CP0_REG08__BADINSTR:
6624 CP0_CHECK(ctx->bi);
6625 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6626 register_name = "BadInstr";
6627 break;
6628 case CP0_REG08__BADINSTRP:
6629 CP0_CHECK(ctx->bp);
6630 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6631 register_name = "BadInstrP";
6632 break;
6633 case CP0_REG08__BADINSTRX:
6634 CP0_CHECK(ctx->bi);
6635 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6636 tcg_gen_andi_tl(arg, arg, ~0xffff);
6637 register_name = "BadInstrX";
6638 break;
6639 default:
6640 goto cp0_unimplemented;
6642 break;
6643 case CP0_REGISTER_09:
6644 switch (sel) {
6645 case CP0_REG09__COUNT:
6646 /* Mark as an IO operation because we read the time. */
6647 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6648 gen_io_start();
6650 gen_helper_mfc0_count(arg, cpu_env);
6652 * Break the TB to be able to take timer interrupts immediately
6653 * after reading count. DISAS_STOP isn't sufficient, we need to
6654 * ensure we break completely out of translated code.
6656 gen_save_pc(ctx->base.pc_next + 4);
6657 ctx->base.is_jmp = DISAS_EXIT;
6658 register_name = "Count";
6659 break;
6660 case CP0_REG09__SAARI:
6661 CP0_CHECK(ctx->saar);
6662 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
6663 register_name = "SAARI";
6664 break;
6665 case CP0_REG09__SAAR:
6666 CP0_CHECK(ctx->saar);
6667 gen_helper_mfc0_saar(arg, cpu_env);
6668 register_name = "SAAR";
6669 break;
6670 default:
6671 goto cp0_unimplemented;
6673 break;
6674 case CP0_REGISTER_10:
6675 switch (sel) {
6676 case CP0_REG10__ENTRYHI:
6677 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6678 tcg_gen_ext32s_tl(arg, arg);
6679 register_name = "EntryHi";
6680 break;
6681 default:
6682 goto cp0_unimplemented;
6684 break;
6685 case CP0_REGISTER_11:
6686 switch (sel) {
6687 case CP0_REG11__COMPARE:
6688 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6689 register_name = "Compare";
6690 break;
6691 /* 6,7 are implementation dependent */
6692 default:
6693 goto cp0_unimplemented;
6695 break;
6696 case CP0_REGISTER_12:
6697 switch (sel) {
6698 case CP0_REG12__STATUS:
6699 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6700 register_name = "Status";
6701 break;
6702 case CP0_REG12__INTCTL:
6703 check_insn(ctx, ISA_MIPS_R2);
6704 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6705 register_name = "IntCtl";
6706 break;
6707 case CP0_REG12__SRSCTL:
6708 check_insn(ctx, ISA_MIPS_R2);
6709 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6710 register_name = "SRSCtl";
6711 break;
6712 case CP0_REG12__SRSMAP:
6713 check_insn(ctx, ISA_MIPS_R2);
6714 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6715 register_name = "SRSMap";
6716 break;
6717 default:
6718 goto cp0_unimplemented;
6720 break;
6721 case CP0_REGISTER_13:
6722 switch (sel) {
6723 case CP0_REG13__CAUSE:
6724 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6725 register_name = "Cause";
6726 break;
6727 default:
6728 goto cp0_unimplemented;
6730 break;
6731 case CP0_REGISTER_14:
6732 switch (sel) {
6733 case CP0_REG14__EPC:
6734 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6735 tcg_gen_ext32s_tl(arg, arg);
6736 register_name = "EPC";
6737 break;
6738 default:
6739 goto cp0_unimplemented;
6741 break;
6742 case CP0_REGISTER_15:
6743 switch (sel) {
6744 case CP0_REG15__PRID:
6745 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6746 register_name = "PRid";
6747 break;
6748 case CP0_REG15__EBASE:
6749 check_insn(ctx, ISA_MIPS_R2);
6750 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6751 tcg_gen_ext32s_tl(arg, arg);
6752 register_name = "EBase";
6753 break;
6754 case CP0_REG15__CMGCRBASE:
6755 check_insn(ctx, ISA_MIPS_R2);
6756 CP0_CHECK(ctx->cmgcr);
6757 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6758 tcg_gen_ext32s_tl(arg, arg);
6759 register_name = "CMGCRBase";
6760 break;
6761 default:
6762 goto cp0_unimplemented;
6764 break;
6765 case CP0_REGISTER_16:
6766 switch (sel) {
6767 case CP0_REG16__CONFIG:
6768 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6769 register_name = "Config";
6770 break;
6771 case CP0_REG16__CONFIG1:
6772 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6773 register_name = "Config1";
6774 break;
6775 case CP0_REG16__CONFIG2:
6776 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6777 register_name = "Config2";
6778 break;
6779 case CP0_REG16__CONFIG3:
6780 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6781 register_name = "Config3";
6782 break;
6783 case CP0_REG16__CONFIG4:
6784 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6785 register_name = "Config4";
6786 break;
6787 case CP0_REG16__CONFIG5:
6788 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6789 register_name = "Config5";
6790 break;
6791 /* 6,7 are implementation dependent */
6792 case CP0_REG16__CONFIG6:
6793 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6794 register_name = "Config6";
6795 break;
6796 case CP0_REG16__CONFIG7:
6797 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6798 register_name = "Config7";
6799 break;
6800 default:
6801 goto cp0_unimplemented;
6803 break;
6804 case CP0_REGISTER_17:
6805 switch (sel) {
6806 case CP0_REG17__LLADDR:
6807 gen_helper_mfc0_lladdr(arg, cpu_env);
6808 register_name = "LLAddr";
6809 break;
6810 case CP0_REG17__MAAR:
6811 CP0_CHECK(ctx->mrp);
6812 gen_helper_mfc0_maar(arg, cpu_env);
6813 register_name = "MAAR";
6814 break;
6815 case CP0_REG17__MAARI:
6816 CP0_CHECK(ctx->mrp);
6817 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6818 register_name = "MAARI";
6819 break;
6820 default:
6821 goto cp0_unimplemented;
6823 break;
6824 case CP0_REGISTER_18:
6825 switch (sel) {
6826 case CP0_REG18__WATCHLO0:
6827 case CP0_REG18__WATCHLO1:
6828 case CP0_REG18__WATCHLO2:
6829 case CP0_REG18__WATCHLO3:
6830 case CP0_REG18__WATCHLO4:
6831 case CP0_REG18__WATCHLO5:
6832 case CP0_REG18__WATCHLO6:
6833 case CP0_REG18__WATCHLO7:
6834 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6835 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6836 register_name = "WatchLo";
6837 break;
6838 default:
6839 goto cp0_unimplemented;
6841 break;
6842 case CP0_REGISTER_19:
6843 switch (sel) {
6844 case CP0_REG19__WATCHHI0:
6845 case CP0_REG19__WATCHHI1:
6846 case CP0_REG19__WATCHHI2:
6847 case CP0_REG19__WATCHHI3:
6848 case CP0_REG19__WATCHHI4:
6849 case CP0_REG19__WATCHHI5:
6850 case CP0_REG19__WATCHHI6:
6851 case CP0_REG19__WATCHHI7:
6852 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6853 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6854 register_name = "WatchHi";
6855 break;
6856 default:
6857 goto cp0_unimplemented;
6859 break;
6860 case CP0_REGISTER_20:
6861 switch (sel) {
6862 case CP0_REG20__XCONTEXT:
6863 #if defined(TARGET_MIPS64)
6864 check_insn(ctx, ISA_MIPS3);
6865 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6866 tcg_gen_ext32s_tl(arg, arg);
6867 register_name = "XContext";
6868 break;
6869 #endif
6870 default:
6871 goto cp0_unimplemented;
6873 break;
6874 case CP0_REGISTER_21:
6875 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6876 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6877 switch (sel) {
6878 case 0:
6879 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6880 register_name = "Framemask";
6881 break;
6882 default:
6883 goto cp0_unimplemented;
6885 break;
6886 case CP0_REGISTER_22:
6887 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6888 register_name = "'Diagnostic"; /* implementation dependent */
6889 break;
6890 case CP0_REGISTER_23:
6891 switch (sel) {
6892 case CP0_REG23__DEBUG:
6893 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6894 register_name = "Debug";
6895 break;
6896 case CP0_REG23__TRACECONTROL:
6897 /* PDtrace support */
6898 /* gen_helper_mfc0_tracecontrol(arg); */
6899 register_name = "TraceControl";
6900 goto cp0_unimplemented;
6901 case CP0_REG23__TRACECONTROL2:
6902 /* PDtrace support */
6903 /* gen_helper_mfc0_tracecontrol2(arg); */
6904 register_name = "TraceControl2";
6905 goto cp0_unimplemented;
6906 case CP0_REG23__USERTRACEDATA1:
6907 /* PDtrace support */
6908 /* gen_helper_mfc0_usertracedata1(arg);*/
6909 register_name = "UserTraceData1";
6910 goto cp0_unimplemented;
6911 case CP0_REG23__TRACEIBPC:
6912 /* PDtrace support */
6913 /* gen_helper_mfc0_traceibpc(arg); */
6914 register_name = "TraceIBPC";
6915 goto cp0_unimplemented;
6916 case CP0_REG23__TRACEDBPC:
6917 /* PDtrace support */
6918 /* gen_helper_mfc0_tracedbpc(arg); */
6919 register_name = "TraceDBPC";
6920 goto cp0_unimplemented;
6921 default:
6922 goto cp0_unimplemented;
6924 break;
6925 case CP0_REGISTER_24:
6926 switch (sel) {
6927 case CP0_REG24__DEPC:
6928 /* EJTAG support */
6929 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6930 tcg_gen_ext32s_tl(arg, arg);
6931 register_name = "DEPC";
6932 break;
6933 default:
6934 goto cp0_unimplemented;
6936 break;
6937 case CP0_REGISTER_25:
6938 switch (sel) {
6939 case CP0_REG25__PERFCTL0:
6940 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6941 register_name = "Performance0";
6942 break;
6943 case CP0_REG25__PERFCNT0:
6944 /* gen_helper_mfc0_performance1(arg); */
6945 register_name = "Performance1";
6946 goto cp0_unimplemented;
6947 case CP0_REG25__PERFCTL1:
6948 /* gen_helper_mfc0_performance2(arg); */
6949 register_name = "Performance2";
6950 goto cp0_unimplemented;
6951 case CP0_REG25__PERFCNT1:
6952 /* gen_helper_mfc0_performance3(arg); */
6953 register_name = "Performance3";
6954 goto cp0_unimplemented;
6955 case CP0_REG25__PERFCTL2:
6956 /* gen_helper_mfc0_performance4(arg); */
6957 register_name = "Performance4";
6958 goto cp0_unimplemented;
6959 case CP0_REG25__PERFCNT2:
6960 /* gen_helper_mfc0_performance5(arg); */
6961 register_name = "Performance5";
6962 goto cp0_unimplemented;
6963 case CP0_REG25__PERFCTL3:
6964 /* gen_helper_mfc0_performance6(arg); */
6965 register_name = "Performance6";
6966 goto cp0_unimplemented;
6967 case CP0_REG25__PERFCNT3:
6968 /* gen_helper_mfc0_performance7(arg); */
6969 register_name = "Performance7";
6970 goto cp0_unimplemented;
6971 default:
6972 goto cp0_unimplemented;
6974 break;
6975 case CP0_REGISTER_26:
6976 switch (sel) {
6977 case CP0_REG26__ERRCTL:
6978 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6979 register_name = "ErrCtl";
6980 break;
6981 default:
6982 goto cp0_unimplemented;
6984 break;
6985 case CP0_REGISTER_27:
6986 switch (sel) {
6987 case CP0_REG27__CACHERR:
6988 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6989 register_name = "CacheErr";
6990 break;
6991 default:
6992 goto cp0_unimplemented;
6994 break;
6995 case CP0_REGISTER_28:
6996 switch (sel) {
6997 case CP0_REG28__TAGLO:
6998 case CP0_REG28__TAGLO1:
6999 case CP0_REG28__TAGLO2:
7000 case CP0_REG28__TAGLO3:
7002 TCGv_i64 tmp = tcg_temp_new_i64();
7003 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7004 gen_move_low32(arg, tmp);
7005 tcg_temp_free_i64(tmp);
7007 register_name = "TagLo";
7008 break;
7009 case CP0_REG28__DATALO:
7010 case CP0_REG28__DATALO1:
7011 case CP0_REG28__DATALO2:
7012 case CP0_REG28__DATALO3:
7013 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7014 register_name = "DataLo";
7015 break;
7016 default:
7017 goto cp0_unimplemented;
7019 break;
7020 case CP0_REGISTER_29:
7021 switch (sel) {
7022 case CP0_REG29__TAGHI:
7023 case CP0_REG29__TAGHI1:
7024 case CP0_REG29__TAGHI2:
7025 case CP0_REG29__TAGHI3:
7026 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7027 register_name = "TagHi";
7028 break;
7029 case CP0_REG29__DATAHI:
7030 case CP0_REG29__DATAHI1:
7031 case CP0_REG29__DATAHI2:
7032 case CP0_REG29__DATAHI3:
7033 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7034 register_name = "DataHi";
7035 break;
7036 default:
7037 goto cp0_unimplemented;
7039 break;
7040 case CP0_REGISTER_30:
7041 switch (sel) {
7042 case CP0_REG30__ERROREPC:
7043 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7044 tcg_gen_ext32s_tl(arg, arg);
7045 register_name = "ErrorEPC";
7046 break;
7047 default:
7048 goto cp0_unimplemented;
7050 break;
7051 case CP0_REGISTER_31:
7052 switch (sel) {
7053 case CP0_REG31__DESAVE:
7054 /* EJTAG support */
7055 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7056 register_name = "DESAVE";
7057 break;
7058 case CP0_REG31__KSCRATCH1:
7059 case CP0_REG31__KSCRATCH2:
7060 case CP0_REG31__KSCRATCH3:
7061 case CP0_REG31__KSCRATCH4:
7062 case CP0_REG31__KSCRATCH5:
7063 case CP0_REG31__KSCRATCH6:
7064 CP0_CHECK(ctx->kscrexist & (1 << sel));
7065 tcg_gen_ld_tl(arg, cpu_env,
7066 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7067 tcg_gen_ext32s_tl(arg, arg);
7068 register_name = "KScratch";
7069 break;
7070 default:
7071 goto cp0_unimplemented;
7073 break;
7074 default:
7075 goto cp0_unimplemented;
7077 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7078 return;
7080 cp0_unimplemented:
7081 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7082 register_name, reg, sel);
7083 gen_mfc0_unimplemented(ctx, arg);
7086 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7088 const char *register_name = "invalid";
7090 if (sel != 0) {
7091 check_insn(ctx, ISA_MIPS_R1);
7094 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7095 gen_io_start();
7098 switch (reg) {
7099 case CP0_REGISTER_00:
7100 switch (sel) {
7101 case CP0_REG00__INDEX:
7102 gen_helper_mtc0_index(cpu_env, arg);
7103 register_name = "Index";
7104 break;
7105 case CP0_REG00__MVPCONTROL:
7106 CP0_CHECK(ctx->insn_flags & ASE_MT);
7107 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7108 register_name = "MVPControl";
7109 break;
7110 case CP0_REG00__MVPCONF0:
7111 CP0_CHECK(ctx->insn_flags & ASE_MT);
7112 /* ignored */
7113 register_name = "MVPConf0";
7114 break;
7115 case CP0_REG00__MVPCONF1:
7116 CP0_CHECK(ctx->insn_flags & ASE_MT);
7117 /* ignored */
7118 register_name = "MVPConf1";
7119 break;
7120 case CP0_REG00__VPCONTROL:
7121 CP0_CHECK(ctx->vp);
7122 /* ignored */
7123 register_name = "VPControl";
7124 break;
7125 default:
7126 goto cp0_unimplemented;
7128 break;
7129 case CP0_REGISTER_01:
7130 switch (sel) {
7131 case CP0_REG01__RANDOM:
7132 /* ignored */
7133 register_name = "Random";
7134 break;
7135 case CP0_REG01__VPECONTROL:
7136 CP0_CHECK(ctx->insn_flags & ASE_MT);
7137 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7138 register_name = "VPEControl";
7139 break;
7140 case CP0_REG01__VPECONF0:
7141 CP0_CHECK(ctx->insn_flags & ASE_MT);
7142 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7143 register_name = "VPEConf0";
7144 break;
7145 case CP0_REG01__VPECONF1:
7146 CP0_CHECK(ctx->insn_flags & ASE_MT);
7147 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7148 register_name = "VPEConf1";
7149 break;
7150 case CP0_REG01__YQMASK:
7151 CP0_CHECK(ctx->insn_flags & ASE_MT);
7152 gen_helper_mtc0_yqmask(cpu_env, arg);
7153 register_name = "YQMask";
7154 break;
7155 case CP0_REG01__VPESCHEDULE:
7156 CP0_CHECK(ctx->insn_flags & ASE_MT);
7157 tcg_gen_st_tl(arg, cpu_env,
7158 offsetof(CPUMIPSState, CP0_VPESchedule));
7159 register_name = "VPESchedule";
7160 break;
7161 case CP0_REG01__VPESCHEFBACK:
7162 CP0_CHECK(ctx->insn_flags & ASE_MT);
7163 tcg_gen_st_tl(arg, cpu_env,
7164 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7165 register_name = "VPEScheFBack";
7166 break;
7167 case CP0_REG01__VPEOPT:
7168 CP0_CHECK(ctx->insn_flags & ASE_MT);
7169 gen_helper_mtc0_vpeopt(cpu_env, arg);
7170 register_name = "VPEOpt";
7171 break;
7172 default:
7173 goto cp0_unimplemented;
7175 break;
7176 case CP0_REGISTER_02:
7177 switch (sel) {
7178 case CP0_REG02__ENTRYLO0:
7179 gen_helper_mtc0_entrylo0(cpu_env, arg);
7180 register_name = "EntryLo0";
7181 break;
7182 case CP0_REG02__TCSTATUS:
7183 CP0_CHECK(ctx->insn_flags & ASE_MT);
7184 gen_helper_mtc0_tcstatus(cpu_env, arg);
7185 register_name = "TCStatus";
7186 break;
7187 case CP0_REG02__TCBIND:
7188 CP0_CHECK(ctx->insn_flags & ASE_MT);
7189 gen_helper_mtc0_tcbind(cpu_env, arg);
7190 register_name = "TCBind";
7191 break;
7192 case CP0_REG02__TCRESTART:
7193 CP0_CHECK(ctx->insn_flags & ASE_MT);
7194 gen_helper_mtc0_tcrestart(cpu_env, arg);
7195 register_name = "TCRestart";
7196 break;
7197 case CP0_REG02__TCHALT:
7198 CP0_CHECK(ctx->insn_flags & ASE_MT);
7199 gen_helper_mtc0_tchalt(cpu_env, arg);
7200 register_name = "TCHalt";
7201 break;
7202 case CP0_REG02__TCCONTEXT:
7203 CP0_CHECK(ctx->insn_flags & ASE_MT);
7204 gen_helper_mtc0_tccontext(cpu_env, arg);
7205 register_name = "TCContext";
7206 break;
7207 case CP0_REG02__TCSCHEDULE:
7208 CP0_CHECK(ctx->insn_flags & ASE_MT);
7209 gen_helper_mtc0_tcschedule(cpu_env, arg);
7210 register_name = "TCSchedule";
7211 break;
7212 case CP0_REG02__TCSCHEFBACK:
7213 CP0_CHECK(ctx->insn_flags & ASE_MT);
7214 gen_helper_mtc0_tcschefback(cpu_env, arg);
7215 register_name = "TCScheFBack";
7216 break;
7217 default:
7218 goto cp0_unimplemented;
7220 break;
7221 case CP0_REGISTER_03:
7222 switch (sel) {
7223 case CP0_REG03__ENTRYLO1:
7224 gen_helper_mtc0_entrylo1(cpu_env, arg);
7225 register_name = "EntryLo1";
7226 break;
7227 case CP0_REG03__GLOBALNUM:
7228 CP0_CHECK(ctx->vp);
7229 /* ignored */
7230 register_name = "GlobalNumber";
7231 break;
7232 default:
7233 goto cp0_unimplemented;
7235 break;
7236 case CP0_REGISTER_04:
7237 switch (sel) {
7238 case CP0_REG04__CONTEXT:
7239 gen_helper_mtc0_context(cpu_env, arg);
7240 register_name = "Context";
7241 break;
7242 case CP0_REG04__CONTEXTCONFIG:
7243 /* SmartMIPS ASE */
7244 /* gen_helper_mtc0_contextconfig(arg); */
7245 register_name = "ContextConfig";
7246 goto cp0_unimplemented;
7247 case CP0_REG04__USERLOCAL:
7248 CP0_CHECK(ctx->ulri);
7249 tcg_gen_st_tl(arg, cpu_env,
7250 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7251 register_name = "UserLocal";
7252 break;
7253 case CP0_REG04__MMID:
7254 CP0_CHECK(ctx->mi);
7255 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
7256 register_name = "MMID";
7257 break;
7258 default:
7259 goto cp0_unimplemented;
7261 break;
7262 case CP0_REGISTER_05:
7263 switch (sel) {
7264 case CP0_REG05__PAGEMASK:
7265 gen_helper_mtc0_pagemask(cpu_env, arg);
7266 register_name = "PageMask";
7267 break;
7268 case CP0_REG05__PAGEGRAIN:
7269 check_insn(ctx, ISA_MIPS_R2);
7270 gen_helper_mtc0_pagegrain(cpu_env, arg);
7271 register_name = "PageGrain";
7272 ctx->base.is_jmp = DISAS_STOP;
7273 break;
7274 case CP0_REG05__SEGCTL0:
7275 CP0_CHECK(ctx->sc);
7276 gen_helper_mtc0_segctl0(cpu_env, arg);
7277 register_name = "SegCtl0";
7278 break;
7279 case CP0_REG05__SEGCTL1:
7280 CP0_CHECK(ctx->sc);
7281 gen_helper_mtc0_segctl1(cpu_env, arg);
7282 register_name = "SegCtl1";
7283 break;
7284 case CP0_REG05__SEGCTL2:
7285 CP0_CHECK(ctx->sc);
7286 gen_helper_mtc0_segctl2(cpu_env, arg);
7287 register_name = "SegCtl2";
7288 break;
7289 case CP0_REG05__PWBASE:
7290 check_pw(ctx);
7291 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7292 register_name = "PWBase";
7293 break;
7294 case CP0_REG05__PWFIELD:
7295 check_pw(ctx);
7296 gen_helper_mtc0_pwfield(cpu_env, arg);
7297 register_name = "PWField";
7298 break;
7299 case CP0_REG05__PWSIZE:
7300 check_pw(ctx);
7301 gen_helper_mtc0_pwsize(cpu_env, arg);
7302 register_name = "PWSize";
7303 break;
7304 default:
7305 goto cp0_unimplemented;
7307 break;
7308 case CP0_REGISTER_06:
7309 switch (sel) {
7310 case CP0_REG06__WIRED:
7311 gen_helper_mtc0_wired(cpu_env, arg);
7312 register_name = "Wired";
7313 break;
7314 case CP0_REG06__SRSCONF0:
7315 check_insn(ctx, ISA_MIPS_R2);
7316 gen_helper_mtc0_srsconf0(cpu_env, arg);
7317 register_name = "SRSConf0";
7318 break;
7319 case CP0_REG06__SRSCONF1:
7320 check_insn(ctx, ISA_MIPS_R2);
7321 gen_helper_mtc0_srsconf1(cpu_env, arg);
7322 register_name = "SRSConf1";
7323 break;
7324 case CP0_REG06__SRSCONF2:
7325 check_insn(ctx, ISA_MIPS_R2);
7326 gen_helper_mtc0_srsconf2(cpu_env, arg);
7327 register_name = "SRSConf2";
7328 break;
7329 case CP0_REG06__SRSCONF3:
7330 check_insn(ctx, ISA_MIPS_R2);
7331 gen_helper_mtc0_srsconf3(cpu_env, arg);
7332 register_name = "SRSConf3";
7333 break;
7334 case CP0_REG06__SRSCONF4:
7335 check_insn(ctx, ISA_MIPS_R2);
7336 gen_helper_mtc0_srsconf4(cpu_env, arg);
7337 register_name = "SRSConf4";
7338 break;
7339 case CP0_REG06__PWCTL:
7340 check_pw(ctx);
7341 gen_helper_mtc0_pwctl(cpu_env, arg);
7342 register_name = "PWCtl";
7343 break;
7344 default:
7345 goto cp0_unimplemented;
7347 break;
7348 case CP0_REGISTER_07:
7349 switch (sel) {
7350 case CP0_REG07__HWRENA:
7351 check_insn(ctx, ISA_MIPS_R2);
7352 gen_helper_mtc0_hwrena(cpu_env, arg);
7353 ctx->base.is_jmp = DISAS_STOP;
7354 register_name = "HWREna";
7355 break;
7356 default:
7357 goto cp0_unimplemented;
7359 break;
7360 case CP0_REGISTER_08:
7361 switch (sel) {
7362 case CP0_REG08__BADVADDR:
7363 /* ignored */
7364 register_name = "BadVAddr";
7365 break;
7366 case CP0_REG08__BADINSTR:
7367 /* ignored */
7368 register_name = "BadInstr";
7369 break;
7370 case CP0_REG08__BADINSTRP:
7371 /* ignored */
7372 register_name = "BadInstrP";
7373 break;
7374 case CP0_REG08__BADINSTRX:
7375 /* ignored */
7376 register_name = "BadInstrX";
7377 break;
7378 default:
7379 goto cp0_unimplemented;
7381 break;
7382 case CP0_REGISTER_09:
7383 switch (sel) {
7384 case CP0_REG09__COUNT:
7385 gen_helper_mtc0_count(cpu_env, arg);
7386 register_name = "Count";
7387 break;
7388 case CP0_REG09__SAARI:
7389 CP0_CHECK(ctx->saar);
7390 gen_helper_mtc0_saari(cpu_env, arg);
7391 register_name = "SAARI";
7392 break;
7393 case CP0_REG09__SAAR:
7394 CP0_CHECK(ctx->saar);
7395 gen_helper_mtc0_saar(cpu_env, arg);
7396 register_name = "SAAR";
7397 break;
7398 default:
7399 goto cp0_unimplemented;
7401 break;
7402 case CP0_REGISTER_10:
7403 switch (sel) {
7404 case CP0_REG10__ENTRYHI:
7405 gen_helper_mtc0_entryhi(cpu_env, arg);
7406 register_name = "EntryHi";
7407 break;
7408 default:
7409 goto cp0_unimplemented;
7411 break;
7412 case CP0_REGISTER_11:
7413 switch (sel) {
7414 case CP0_REG11__COMPARE:
7415 gen_helper_mtc0_compare(cpu_env, arg);
7416 register_name = "Compare";
7417 break;
7418 /* 6,7 are implementation dependent */
7419 default:
7420 goto cp0_unimplemented;
7422 break;
7423 case CP0_REGISTER_12:
7424 switch (sel) {
7425 case CP0_REG12__STATUS:
7426 save_cpu_state(ctx, 1);
7427 gen_helper_mtc0_status(cpu_env, arg);
7428 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7429 gen_save_pc(ctx->base.pc_next + 4);
7430 ctx->base.is_jmp = DISAS_EXIT;
7431 register_name = "Status";
7432 break;
7433 case CP0_REG12__INTCTL:
7434 check_insn(ctx, ISA_MIPS_R2);
7435 gen_helper_mtc0_intctl(cpu_env, arg);
7436 /* Stop translation as we may have switched the execution mode */
7437 ctx->base.is_jmp = DISAS_STOP;
7438 register_name = "IntCtl";
7439 break;
7440 case CP0_REG12__SRSCTL:
7441 check_insn(ctx, ISA_MIPS_R2);
7442 gen_helper_mtc0_srsctl(cpu_env, arg);
7443 /* Stop translation as we may have switched the execution mode */
7444 ctx->base.is_jmp = DISAS_STOP;
7445 register_name = "SRSCtl";
7446 break;
7447 case CP0_REG12__SRSMAP:
7448 check_insn(ctx, ISA_MIPS_R2);
7449 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7450 /* Stop translation as we may have switched the execution mode */
7451 ctx->base.is_jmp = DISAS_STOP;
7452 register_name = "SRSMap";
7453 break;
7454 default:
7455 goto cp0_unimplemented;
7457 break;
7458 case CP0_REGISTER_13:
7459 switch (sel) {
7460 case CP0_REG13__CAUSE:
7461 save_cpu_state(ctx, 1);
7462 gen_helper_mtc0_cause(cpu_env, arg);
7464 * Stop translation as we may have triggered an interrupt.
7465 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7466 * translated code to check for pending interrupts.
7468 gen_save_pc(ctx->base.pc_next + 4);
7469 ctx->base.is_jmp = DISAS_EXIT;
7470 register_name = "Cause";
7471 break;
7472 default:
7473 goto cp0_unimplemented;
7475 break;
7476 case CP0_REGISTER_14:
7477 switch (sel) {
7478 case CP0_REG14__EPC:
7479 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7480 register_name = "EPC";
7481 break;
7482 default:
7483 goto cp0_unimplemented;
7485 break;
7486 case CP0_REGISTER_15:
7487 switch (sel) {
7488 case CP0_REG15__PRID:
7489 /* ignored */
7490 register_name = "PRid";
7491 break;
7492 case CP0_REG15__EBASE:
7493 check_insn(ctx, ISA_MIPS_R2);
7494 gen_helper_mtc0_ebase(cpu_env, arg);
7495 register_name = "EBase";
7496 break;
7497 default:
7498 goto cp0_unimplemented;
7500 break;
7501 case CP0_REGISTER_16:
7502 switch (sel) {
7503 case CP0_REG16__CONFIG:
7504 gen_helper_mtc0_config0(cpu_env, arg);
7505 register_name = "Config";
7506 /* Stop translation as we may have switched the execution mode */
7507 ctx->base.is_jmp = DISAS_STOP;
7508 break;
7509 case CP0_REG16__CONFIG1:
7510 /* ignored, read only */
7511 register_name = "Config1";
7512 break;
7513 case CP0_REG16__CONFIG2:
7514 gen_helper_mtc0_config2(cpu_env, arg);
7515 register_name = "Config2";
7516 /* Stop translation as we may have switched the execution mode */
7517 ctx->base.is_jmp = DISAS_STOP;
7518 break;
7519 case CP0_REG16__CONFIG3:
7520 gen_helper_mtc0_config3(cpu_env, arg);
7521 register_name = "Config3";
7522 /* Stop translation as we may have switched the execution mode */
7523 ctx->base.is_jmp = DISAS_STOP;
7524 break;
7525 case CP0_REG16__CONFIG4:
7526 gen_helper_mtc0_config4(cpu_env, arg);
7527 register_name = "Config4";
7528 ctx->base.is_jmp = DISAS_STOP;
7529 break;
7530 case CP0_REG16__CONFIG5:
7531 gen_helper_mtc0_config5(cpu_env, arg);
7532 register_name = "Config5";
7533 /* Stop translation as we may have switched the execution mode */
7534 ctx->base.is_jmp = DISAS_STOP;
7535 break;
7536 /* 6,7 are implementation dependent */
7537 case CP0_REG16__CONFIG6:
7538 /* ignored */
7539 register_name = "Config6";
7540 break;
7541 case CP0_REG16__CONFIG7:
7542 /* ignored */
7543 register_name = "Config7";
7544 break;
7545 default:
7546 register_name = "Invalid config selector";
7547 goto cp0_unimplemented;
7549 break;
7550 case CP0_REGISTER_17:
7551 switch (sel) {
7552 case CP0_REG17__LLADDR:
7553 gen_helper_mtc0_lladdr(cpu_env, arg);
7554 register_name = "LLAddr";
7555 break;
7556 case CP0_REG17__MAAR:
7557 CP0_CHECK(ctx->mrp);
7558 gen_helper_mtc0_maar(cpu_env, arg);
7559 register_name = "MAAR";
7560 break;
7561 case CP0_REG17__MAARI:
7562 CP0_CHECK(ctx->mrp);
7563 gen_helper_mtc0_maari(cpu_env, arg);
7564 register_name = "MAARI";
7565 break;
7566 default:
7567 goto cp0_unimplemented;
7569 break;
7570 case CP0_REGISTER_18:
7571 switch (sel) {
7572 case CP0_REG18__WATCHLO0:
7573 case CP0_REG18__WATCHLO1:
7574 case CP0_REG18__WATCHLO2:
7575 case CP0_REG18__WATCHLO3:
7576 case CP0_REG18__WATCHLO4:
7577 case CP0_REG18__WATCHLO5:
7578 case CP0_REG18__WATCHLO6:
7579 case CP0_REG18__WATCHLO7:
7580 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7581 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7582 register_name = "WatchLo";
7583 break;
7584 default:
7585 goto cp0_unimplemented;
7587 break;
7588 case CP0_REGISTER_19:
7589 switch (sel) {
7590 case CP0_REG19__WATCHHI0:
7591 case CP0_REG19__WATCHHI1:
7592 case CP0_REG19__WATCHHI2:
7593 case CP0_REG19__WATCHHI3:
7594 case CP0_REG19__WATCHHI4:
7595 case CP0_REG19__WATCHHI5:
7596 case CP0_REG19__WATCHHI6:
7597 case CP0_REG19__WATCHHI7:
7598 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7599 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7600 register_name = "WatchHi";
7601 break;
7602 default:
7603 goto cp0_unimplemented;
7605 break;
7606 case CP0_REGISTER_20:
7607 switch (sel) {
7608 case CP0_REG20__XCONTEXT:
7609 #if defined(TARGET_MIPS64)
7610 check_insn(ctx, ISA_MIPS3);
7611 gen_helper_mtc0_xcontext(cpu_env, arg);
7612 register_name = "XContext";
7613 break;
7614 #endif
7615 default:
7616 goto cp0_unimplemented;
7618 break;
7619 case CP0_REGISTER_21:
7620 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7621 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7622 switch (sel) {
7623 case 0:
7624 gen_helper_mtc0_framemask(cpu_env, arg);
7625 register_name = "Framemask";
7626 break;
7627 default:
7628 goto cp0_unimplemented;
7630 break;
7631 case CP0_REGISTER_22:
7632 /* ignored */
7633 register_name = "Diagnostic"; /* implementation dependent */
7634 break;
7635 case CP0_REGISTER_23:
7636 switch (sel) {
7637 case CP0_REG23__DEBUG:
7638 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7639 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7640 gen_save_pc(ctx->base.pc_next + 4);
7641 ctx->base.is_jmp = DISAS_EXIT;
7642 register_name = "Debug";
7643 break;
7644 case CP0_REG23__TRACECONTROL:
7645 /* PDtrace support */
7646 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
7647 register_name = "TraceControl";
7648 /* Stop translation as we may have switched the execution mode */
7649 ctx->base.is_jmp = DISAS_STOP;
7650 goto cp0_unimplemented;
7651 case CP0_REG23__TRACECONTROL2:
7652 /* PDtrace support */
7653 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
7654 register_name = "TraceControl2";
7655 /* Stop translation as we may have switched the execution mode */
7656 ctx->base.is_jmp = DISAS_STOP;
7657 goto cp0_unimplemented;
7658 case CP0_REG23__USERTRACEDATA1:
7659 /* Stop translation as we may have switched the execution mode */
7660 ctx->base.is_jmp = DISAS_STOP;
7661 /* PDtrace support */
7662 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
7663 register_name = "UserTraceData";
7664 /* Stop translation as we may have switched the execution mode */
7665 ctx->base.is_jmp = DISAS_STOP;
7666 goto cp0_unimplemented;
7667 case CP0_REG23__TRACEIBPC:
7668 /* PDtrace support */
7669 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
7670 /* Stop translation as we may have switched the execution mode */
7671 ctx->base.is_jmp = DISAS_STOP;
7672 register_name = "TraceIBPC";
7673 goto cp0_unimplemented;
7674 case CP0_REG23__TRACEDBPC:
7675 /* PDtrace support */
7676 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
7677 /* Stop translation as we may have switched the execution mode */
7678 ctx->base.is_jmp = DISAS_STOP;
7679 register_name = "TraceDBPC";
7680 goto cp0_unimplemented;
7681 default:
7682 goto cp0_unimplemented;
7684 break;
7685 case CP0_REGISTER_24:
7686 switch (sel) {
7687 case CP0_REG24__DEPC:
7688 /* EJTAG support */
7689 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7690 register_name = "DEPC";
7691 break;
7692 default:
7693 goto cp0_unimplemented;
7695 break;
7696 case CP0_REGISTER_25:
7697 switch (sel) {
7698 case CP0_REG25__PERFCTL0:
7699 gen_helper_mtc0_performance0(cpu_env, arg);
7700 register_name = "Performance0";
7701 break;
7702 case CP0_REG25__PERFCNT0:
7703 /* gen_helper_mtc0_performance1(arg); */
7704 register_name = "Performance1";
7705 goto cp0_unimplemented;
7706 case CP0_REG25__PERFCTL1:
7707 /* gen_helper_mtc0_performance2(arg); */
7708 register_name = "Performance2";
7709 goto cp0_unimplemented;
7710 case CP0_REG25__PERFCNT1:
7711 /* gen_helper_mtc0_performance3(arg); */
7712 register_name = "Performance3";
7713 goto cp0_unimplemented;
7714 case CP0_REG25__PERFCTL2:
7715 /* gen_helper_mtc0_performance4(arg); */
7716 register_name = "Performance4";
7717 goto cp0_unimplemented;
7718 case CP0_REG25__PERFCNT2:
7719 /* gen_helper_mtc0_performance5(arg); */
7720 register_name = "Performance5";
7721 goto cp0_unimplemented;
7722 case CP0_REG25__PERFCTL3:
7723 /* gen_helper_mtc0_performance6(arg); */
7724 register_name = "Performance6";
7725 goto cp0_unimplemented;
7726 case CP0_REG25__PERFCNT3:
7727 /* gen_helper_mtc0_performance7(arg); */
7728 register_name = "Performance7";
7729 goto cp0_unimplemented;
7730 default:
7731 goto cp0_unimplemented;
7733 break;
7734 case CP0_REGISTER_26:
7735 switch (sel) {
7736 case CP0_REG26__ERRCTL:
7737 gen_helper_mtc0_errctl(cpu_env, arg);
7738 ctx->base.is_jmp = DISAS_STOP;
7739 register_name = "ErrCtl";
7740 break;
7741 default:
7742 goto cp0_unimplemented;
7744 break;
7745 case CP0_REGISTER_27:
7746 switch (sel) {
7747 case CP0_REG27__CACHERR:
7748 /* ignored */
7749 register_name = "CacheErr";
7750 break;
7751 default:
7752 goto cp0_unimplemented;
7754 break;
7755 case CP0_REGISTER_28:
7756 switch (sel) {
7757 case CP0_REG28__TAGLO:
7758 case CP0_REG28__TAGLO1:
7759 case CP0_REG28__TAGLO2:
7760 case CP0_REG28__TAGLO3:
7761 gen_helper_mtc0_taglo(cpu_env, arg);
7762 register_name = "TagLo";
7763 break;
7764 case CP0_REG28__DATALO:
7765 case CP0_REG28__DATALO1:
7766 case CP0_REG28__DATALO2:
7767 case CP0_REG28__DATALO3:
7768 gen_helper_mtc0_datalo(cpu_env, arg);
7769 register_name = "DataLo";
7770 break;
7771 default:
7772 goto cp0_unimplemented;
7774 break;
7775 case CP0_REGISTER_29:
7776 switch (sel) {
7777 case CP0_REG29__TAGHI:
7778 case CP0_REG29__TAGHI1:
7779 case CP0_REG29__TAGHI2:
7780 case CP0_REG29__TAGHI3:
7781 gen_helper_mtc0_taghi(cpu_env, arg);
7782 register_name = "TagHi";
7783 break;
7784 case CP0_REG29__DATAHI:
7785 case CP0_REG29__DATAHI1:
7786 case CP0_REG29__DATAHI2:
7787 case CP0_REG29__DATAHI3:
7788 gen_helper_mtc0_datahi(cpu_env, arg);
7789 register_name = "DataHi";
7790 break;
7791 default:
7792 register_name = "invalid sel";
7793 goto cp0_unimplemented;
7795 break;
7796 case CP0_REGISTER_30:
7797 switch (sel) {
7798 case CP0_REG30__ERROREPC:
7799 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7800 register_name = "ErrorEPC";
7801 break;
7802 default:
7803 goto cp0_unimplemented;
7805 break;
7806 case CP0_REGISTER_31:
7807 switch (sel) {
7808 case CP0_REG31__DESAVE:
7809 /* EJTAG support */
7810 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7811 register_name = "DESAVE";
7812 break;
7813 case CP0_REG31__KSCRATCH1:
7814 case CP0_REG31__KSCRATCH2:
7815 case CP0_REG31__KSCRATCH3:
7816 case CP0_REG31__KSCRATCH4:
7817 case CP0_REG31__KSCRATCH5:
7818 case CP0_REG31__KSCRATCH6:
7819 CP0_CHECK(ctx->kscrexist & (1 << sel));
7820 tcg_gen_st_tl(arg, cpu_env,
7821 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7822 register_name = "KScratch";
7823 break;
7824 default:
7825 goto cp0_unimplemented;
7827 break;
7828 default:
7829 goto cp0_unimplemented;
7831 trace_mips_translate_c0("mtc0", register_name, reg, sel);
7833 /* For simplicity assume that all writes can cause interrupts. */
7834 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7836 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7837 * translated code to check for pending interrupts.
7839 gen_save_pc(ctx->base.pc_next + 4);
7840 ctx->base.is_jmp = DISAS_EXIT;
7842 return;
7844 cp0_unimplemented:
7845 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
7846 register_name, reg, sel);
7849 #if defined(TARGET_MIPS64)
7850 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7852 const char *register_name = "invalid";
7854 if (sel != 0) {
7855 check_insn(ctx, ISA_MIPS_R1);
7858 switch (reg) {
7859 case CP0_REGISTER_00:
7860 switch (sel) {
7861 case CP0_REG00__INDEX:
7862 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7863 register_name = "Index";
7864 break;
7865 case CP0_REG00__MVPCONTROL:
7866 CP0_CHECK(ctx->insn_flags & ASE_MT);
7867 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7868 register_name = "MVPControl";
7869 break;
7870 case CP0_REG00__MVPCONF0:
7871 CP0_CHECK(ctx->insn_flags & ASE_MT);
7872 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7873 register_name = "MVPConf0";
7874 break;
7875 case CP0_REG00__MVPCONF1:
7876 CP0_CHECK(ctx->insn_flags & ASE_MT);
7877 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7878 register_name = "MVPConf1";
7879 break;
7880 case CP0_REG00__VPCONTROL:
7881 CP0_CHECK(ctx->vp);
7882 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7883 register_name = "VPControl";
7884 break;
7885 default:
7886 goto cp0_unimplemented;
7888 break;
7889 case CP0_REGISTER_01:
7890 switch (sel) {
7891 case CP0_REG01__RANDOM:
7892 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7893 gen_helper_mfc0_random(arg, cpu_env);
7894 register_name = "Random";
7895 break;
7896 case CP0_REG01__VPECONTROL:
7897 CP0_CHECK(ctx->insn_flags & ASE_MT);
7898 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7899 register_name = "VPEControl";
7900 break;
7901 case CP0_REG01__VPECONF0:
7902 CP0_CHECK(ctx->insn_flags & ASE_MT);
7903 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7904 register_name = "VPEConf0";
7905 break;
7906 case CP0_REG01__VPECONF1:
7907 CP0_CHECK(ctx->insn_flags & ASE_MT);
7908 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7909 register_name = "VPEConf1";
7910 break;
7911 case CP0_REG01__YQMASK:
7912 CP0_CHECK(ctx->insn_flags & ASE_MT);
7913 tcg_gen_ld_tl(arg, cpu_env,
7914 offsetof(CPUMIPSState, CP0_YQMask));
7915 register_name = "YQMask";
7916 break;
7917 case CP0_REG01__VPESCHEDULE:
7918 CP0_CHECK(ctx->insn_flags & ASE_MT);
7919 tcg_gen_ld_tl(arg, cpu_env,
7920 offsetof(CPUMIPSState, CP0_VPESchedule));
7921 register_name = "VPESchedule";
7922 break;
7923 case CP0_REG01__VPESCHEFBACK:
7924 CP0_CHECK(ctx->insn_flags & ASE_MT);
7925 tcg_gen_ld_tl(arg, cpu_env,
7926 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7927 register_name = "VPEScheFBack";
7928 break;
7929 case CP0_REG01__VPEOPT:
7930 CP0_CHECK(ctx->insn_flags & ASE_MT);
7931 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7932 register_name = "VPEOpt";
7933 break;
7934 default:
7935 goto cp0_unimplemented;
7937 break;
7938 case CP0_REGISTER_02:
7939 switch (sel) {
7940 case CP0_REG02__ENTRYLO0:
7941 tcg_gen_ld_tl(arg, cpu_env,
7942 offsetof(CPUMIPSState, CP0_EntryLo0));
7943 register_name = "EntryLo0";
7944 break;
7945 case CP0_REG02__TCSTATUS:
7946 CP0_CHECK(ctx->insn_flags & ASE_MT);
7947 gen_helper_mfc0_tcstatus(arg, cpu_env);
7948 register_name = "TCStatus";
7949 break;
7950 case CP0_REG02__TCBIND:
7951 CP0_CHECK(ctx->insn_flags & ASE_MT);
7952 gen_helper_mfc0_tcbind(arg, cpu_env);
7953 register_name = "TCBind";
7954 break;
7955 case CP0_REG02__TCRESTART:
7956 CP0_CHECK(ctx->insn_flags & ASE_MT);
7957 gen_helper_dmfc0_tcrestart(arg, cpu_env);
7958 register_name = "TCRestart";
7959 break;
7960 case CP0_REG02__TCHALT:
7961 CP0_CHECK(ctx->insn_flags & ASE_MT);
7962 gen_helper_dmfc0_tchalt(arg, cpu_env);
7963 register_name = "TCHalt";
7964 break;
7965 case CP0_REG02__TCCONTEXT:
7966 CP0_CHECK(ctx->insn_flags & ASE_MT);
7967 gen_helper_dmfc0_tccontext(arg, cpu_env);
7968 register_name = "TCContext";
7969 break;
7970 case CP0_REG02__TCSCHEDULE:
7971 CP0_CHECK(ctx->insn_flags & ASE_MT);
7972 gen_helper_dmfc0_tcschedule(arg, cpu_env);
7973 register_name = "TCSchedule";
7974 break;
7975 case CP0_REG02__TCSCHEFBACK:
7976 CP0_CHECK(ctx->insn_flags & ASE_MT);
7977 gen_helper_dmfc0_tcschefback(arg, cpu_env);
7978 register_name = "TCScheFBack";
7979 break;
7980 default:
7981 goto cp0_unimplemented;
7983 break;
7984 case CP0_REGISTER_03:
7985 switch (sel) {
7986 case CP0_REG03__ENTRYLO1:
7987 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
7988 register_name = "EntryLo1";
7989 break;
7990 case CP0_REG03__GLOBALNUM:
7991 CP0_CHECK(ctx->vp);
7992 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7993 register_name = "GlobalNumber";
7994 break;
7995 default:
7996 goto cp0_unimplemented;
7998 break;
7999 case CP0_REGISTER_04:
8000 switch (sel) {
8001 case CP0_REG04__CONTEXT:
8002 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8003 register_name = "Context";
8004 break;
8005 case CP0_REG04__CONTEXTCONFIG:
8006 /* SmartMIPS ASE */
8007 /* gen_helper_dmfc0_contextconfig(arg); */
8008 register_name = "ContextConfig";
8009 goto cp0_unimplemented;
8010 case CP0_REG04__USERLOCAL:
8011 CP0_CHECK(ctx->ulri);
8012 tcg_gen_ld_tl(arg, cpu_env,
8013 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8014 register_name = "UserLocal";
8015 break;
8016 case CP0_REG04__MMID:
8017 CP0_CHECK(ctx->mi);
8018 gen_helper_mtc0_memorymapid(cpu_env, arg);
8019 register_name = "MMID";
8020 break;
8021 default:
8022 goto cp0_unimplemented;
8024 break;
8025 case CP0_REGISTER_05:
8026 switch (sel) {
8027 case CP0_REG05__PAGEMASK:
8028 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8029 register_name = "PageMask";
8030 break;
8031 case CP0_REG05__PAGEGRAIN:
8032 check_insn(ctx, ISA_MIPS_R2);
8033 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8034 register_name = "PageGrain";
8035 break;
8036 case CP0_REG05__SEGCTL0:
8037 CP0_CHECK(ctx->sc);
8038 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8039 register_name = "SegCtl0";
8040 break;
8041 case CP0_REG05__SEGCTL1:
8042 CP0_CHECK(ctx->sc);
8043 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8044 register_name = "SegCtl1";
8045 break;
8046 case CP0_REG05__SEGCTL2:
8047 CP0_CHECK(ctx->sc);
8048 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8049 register_name = "SegCtl2";
8050 break;
8051 case CP0_REG05__PWBASE:
8052 check_pw(ctx);
8053 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8054 register_name = "PWBase";
8055 break;
8056 case CP0_REG05__PWFIELD:
8057 check_pw(ctx);
8058 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8059 register_name = "PWField";
8060 break;
8061 case CP0_REG05__PWSIZE:
8062 check_pw(ctx);
8063 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8064 register_name = "PWSize";
8065 break;
8066 default:
8067 goto cp0_unimplemented;
8069 break;
8070 case CP0_REGISTER_06:
8071 switch (sel) {
8072 case CP0_REG06__WIRED:
8073 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8074 register_name = "Wired";
8075 break;
8076 case CP0_REG06__SRSCONF0:
8077 check_insn(ctx, ISA_MIPS_R2);
8078 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8079 register_name = "SRSConf0";
8080 break;
8081 case CP0_REG06__SRSCONF1:
8082 check_insn(ctx, ISA_MIPS_R2);
8083 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8084 register_name = "SRSConf1";
8085 break;
8086 case CP0_REG06__SRSCONF2:
8087 check_insn(ctx, ISA_MIPS_R2);
8088 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8089 register_name = "SRSConf2";
8090 break;
8091 case CP0_REG06__SRSCONF3:
8092 check_insn(ctx, ISA_MIPS_R2);
8093 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8094 register_name = "SRSConf3";
8095 break;
8096 case CP0_REG06__SRSCONF4:
8097 check_insn(ctx, ISA_MIPS_R2);
8098 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8099 register_name = "SRSConf4";
8100 break;
8101 case CP0_REG06__PWCTL:
8102 check_pw(ctx);
8103 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8104 register_name = "PWCtl";
8105 break;
8106 default:
8107 goto cp0_unimplemented;
8109 break;
8110 case CP0_REGISTER_07:
8111 switch (sel) {
8112 case CP0_REG07__HWRENA:
8113 check_insn(ctx, ISA_MIPS_R2);
8114 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8115 register_name = "HWREna";
8116 break;
8117 default:
8118 goto cp0_unimplemented;
8120 break;
8121 case CP0_REGISTER_08:
8122 switch (sel) {
8123 case CP0_REG08__BADVADDR:
8124 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8125 register_name = "BadVAddr";
8126 break;
8127 case CP0_REG08__BADINSTR:
8128 CP0_CHECK(ctx->bi);
8129 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8130 register_name = "BadInstr";
8131 break;
8132 case CP0_REG08__BADINSTRP:
8133 CP0_CHECK(ctx->bp);
8134 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8135 register_name = "BadInstrP";
8136 break;
8137 case CP0_REG08__BADINSTRX:
8138 CP0_CHECK(ctx->bi);
8139 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8140 tcg_gen_andi_tl(arg, arg, ~0xffff);
8141 register_name = "BadInstrX";
8142 break;
8143 default:
8144 goto cp0_unimplemented;
8146 break;
8147 case CP0_REGISTER_09:
8148 switch (sel) {
8149 case CP0_REG09__COUNT:
8150 /* Mark as an IO operation because we read the time. */
8151 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8152 gen_io_start();
8154 gen_helper_mfc0_count(arg, cpu_env);
8156 * Break the TB to be able to take timer interrupts immediately
8157 * after reading count. DISAS_STOP isn't sufficient, we need to
8158 * ensure we break completely out of translated code.
8160 gen_save_pc(ctx->base.pc_next + 4);
8161 ctx->base.is_jmp = DISAS_EXIT;
8162 register_name = "Count";
8163 break;
8164 case CP0_REG09__SAARI:
8165 CP0_CHECK(ctx->saar);
8166 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8167 register_name = "SAARI";
8168 break;
8169 case CP0_REG09__SAAR:
8170 CP0_CHECK(ctx->saar);
8171 gen_helper_dmfc0_saar(arg, cpu_env);
8172 register_name = "SAAR";
8173 break;
8174 default:
8175 goto cp0_unimplemented;
8177 break;
8178 case CP0_REGISTER_10:
8179 switch (sel) {
8180 case CP0_REG10__ENTRYHI:
8181 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8182 register_name = "EntryHi";
8183 break;
8184 default:
8185 goto cp0_unimplemented;
8187 break;
8188 case CP0_REGISTER_11:
8189 switch (sel) {
8190 case CP0_REG11__COMPARE:
8191 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8192 register_name = "Compare";
8193 break;
8194 /* 6,7 are implementation dependent */
8195 default:
8196 goto cp0_unimplemented;
8198 break;
8199 case CP0_REGISTER_12:
8200 switch (sel) {
8201 case CP0_REG12__STATUS:
8202 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8203 register_name = "Status";
8204 break;
8205 case CP0_REG12__INTCTL:
8206 check_insn(ctx, ISA_MIPS_R2);
8207 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8208 register_name = "IntCtl";
8209 break;
8210 case CP0_REG12__SRSCTL:
8211 check_insn(ctx, ISA_MIPS_R2);
8212 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8213 register_name = "SRSCtl";
8214 break;
8215 case CP0_REG12__SRSMAP:
8216 check_insn(ctx, ISA_MIPS_R2);
8217 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8218 register_name = "SRSMap";
8219 break;
8220 default:
8221 goto cp0_unimplemented;
8223 break;
8224 case CP0_REGISTER_13:
8225 switch (sel) {
8226 case CP0_REG13__CAUSE:
8227 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8228 register_name = "Cause";
8229 break;
8230 default:
8231 goto cp0_unimplemented;
8233 break;
8234 case CP0_REGISTER_14:
8235 switch (sel) {
8236 case CP0_REG14__EPC:
8237 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8238 register_name = "EPC";
8239 break;
8240 default:
8241 goto cp0_unimplemented;
8243 break;
8244 case CP0_REGISTER_15:
8245 switch (sel) {
8246 case CP0_REG15__PRID:
8247 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8248 register_name = "PRid";
8249 break;
8250 case CP0_REG15__EBASE:
8251 check_insn(ctx, ISA_MIPS_R2);
8252 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8253 register_name = "EBase";
8254 break;
8255 case CP0_REG15__CMGCRBASE:
8256 check_insn(ctx, ISA_MIPS_R2);
8257 CP0_CHECK(ctx->cmgcr);
8258 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8259 register_name = "CMGCRBase";
8260 break;
8261 default:
8262 goto cp0_unimplemented;
8264 break;
8265 case CP0_REGISTER_16:
8266 switch (sel) {
8267 case CP0_REG16__CONFIG:
8268 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8269 register_name = "Config";
8270 break;
8271 case CP0_REG16__CONFIG1:
8272 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8273 register_name = "Config1";
8274 break;
8275 case CP0_REG16__CONFIG2:
8276 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8277 register_name = "Config2";
8278 break;
8279 case CP0_REG16__CONFIG3:
8280 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8281 register_name = "Config3";
8282 break;
8283 case CP0_REG16__CONFIG4:
8284 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8285 register_name = "Config4";
8286 break;
8287 case CP0_REG16__CONFIG5:
8288 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8289 register_name = "Config5";
8290 break;
8291 /* 6,7 are implementation dependent */
8292 case CP0_REG16__CONFIG6:
8293 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8294 register_name = "Config6";
8295 break;
8296 case CP0_REG16__CONFIG7:
8297 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8298 register_name = "Config7";
8299 break;
8300 default:
8301 goto cp0_unimplemented;
8303 break;
8304 case CP0_REGISTER_17:
8305 switch (sel) {
8306 case CP0_REG17__LLADDR:
8307 gen_helper_dmfc0_lladdr(arg, cpu_env);
8308 register_name = "LLAddr";
8309 break;
8310 case CP0_REG17__MAAR:
8311 CP0_CHECK(ctx->mrp);
8312 gen_helper_dmfc0_maar(arg, cpu_env);
8313 register_name = "MAAR";
8314 break;
8315 case CP0_REG17__MAARI:
8316 CP0_CHECK(ctx->mrp);
8317 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8318 register_name = "MAARI";
8319 break;
8320 default:
8321 goto cp0_unimplemented;
8323 break;
8324 case CP0_REGISTER_18:
8325 switch (sel) {
8326 case CP0_REG18__WATCHLO0:
8327 case CP0_REG18__WATCHLO1:
8328 case CP0_REG18__WATCHLO2:
8329 case CP0_REG18__WATCHLO3:
8330 case CP0_REG18__WATCHLO4:
8331 case CP0_REG18__WATCHLO5:
8332 case CP0_REG18__WATCHLO6:
8333 case CP0_REG18__WATCHLO7:
8334 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8335 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8336 register_name = "WatchLo";
8337 break;
8338 default:
8339 goto cp0_unimplemented;
8341 break;
8342 case CP0_REGISTER_19:
8343 switch (sel) {
8344 case CP0_REG19__WATCHHI0:
8345 case CP0_REG19__WATCHHI1:
8346 case CP0_REG19__WATCHHI2:
8347 case CP0_REG19__WATCHHI3:
8348 case CP0_REG19__WATCHHI4:
8349 case CP0_REG19__WATCHHI5:
8350 case CP0_REG19__WATCHHI6:
8351 case CP0_REG19__WATCHHI7:
8352 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8353 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
8354 register_name = "WatchHi";
8355 break;
8356 default:
8357 goto cp0_unimplemented;
8359 break;
8360 case CP0_REGISTER_20:
8361 switch (sel) {
8362 case CP0_REG20__XCONTEXT:
8363 check_insn(ctx, ISA_MIPS3);
8364 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8365 register_name = "XContext";
8366 break;
8367 default:
8368 goto cp0_unimplemented;
8370 break;
8371 case CP0_REGISTER_21:
8372 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8373 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8374 switch (sel) {
8375 case 0:
8376 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8377 register_name = "Framemask";
8378 break;
8379 default:
8380 goto cp0_unimplemented;
8382 break;
8383 case CP0_REGISTER_22:
8384 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8385 register_name = "'Diagnostic"; /* implementation dependent */
8386 break;
8387 case CP0_REGISTER_23:
8388 switch (sel) {
8389 case CP0_REG23__DEBUG:
8390 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8391 register_name = "Debug";
8392 break;
8393 case CP0_REG23__TRACECONTROL:
8394 /* PDtrace support */
8395 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
8396 register_name = "TraceControl";
8397 goto cp0_unimplemented;
8398 case CP0_REG23__TRACECONTROL2:
8399 /* PDtrace support */
8400 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
8401 register_name = "TraceControl2";
8402 goto cp0_unimplemented;
8403 case CP0_REG23__USERTRACEDATA1:
8404 /* PDtrace support */
8405 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
8406 register_name = "UserTraceData1";
8407 goto cp0_unimplemented;
8408 case CP0_REG23__TRACEIBPC:
8409 /* PDtrace support */
8410 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
8411 register_name = "TraceIBPC";
8412 goto cp0_unimplemented;
8413 case CP0_REG23__TRACEDBPC:
8414 /* PDtrace support */
8415 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
8416 register_name = "TraceDBPC";
8417 goto cp0_unimplemented;
8418 default:
8419 goto cp0_unimplemented;
8421 break;
8422 case CP0_REGISTER_24:
8423 switch (sel) {
8424 case CP0_REG24__DEPC:
8425 /* EJTAG support */
8426 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8427 register_name = "DEPC";
8428 break;
8429 default:
8430 goto cp0_unimplemented;
8432 break;
8433 case CP0_REGISTER_25:
8434 switch (sel) {
8435 case CP0_REG25__PERFCTL0:
8436 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8437 register_name = "Performance0";
8438 break;
8439 case CP0_REG25__PERFCNT0:
8440 /* gen_helper_dmfc0_performance1(arg); */
8441 register_name = "Performance1";
8442 goto cp0_unimplemented;
8443 case CP0_REG25__PERFCTL1:
8444 /* gen_helper_dmfc0_performance2(arg); */
8445 register_name = "Performance2";
8446 goto cp0_unimplemented;
8447 case CP0_REG25__PERFCNT1:
8448 /* gen_helper_dmfc0_performance3(arg); */
8449 register_name = "Performance3";
8450 goto cp0_unimplemented;
8451 case CP0_REG25__PERFCTL2:
8452 /* gen_helper_dmfc0_performance4(arg); */
8453 register_name = "Performance4";
8454 goto cp0_unimplemented;
8455 case CP0_REG25__PERFCNT2:
8456 /* gen_helper_dmfc0_performance5(arg); */
8457 register_name = "Performance5";
8458 goto cp0_unimplemented;
8459 case CP0_REG25__PERFCTL3:
8460 /* gen_helper_dmfc0_performance6(arg); */
8461 register_name = "Performance6";
8462 goto cp0_unimplemented;
8463 case CP0_REG25__PERFCNT3:
8464 /* gen_helper_dmfc0_performance7(arg); */
8465 register_name = "Performance7";
8466 goto cp0_unimplemented;
8467 default:
8468 goto cp0_unimplemented;
8470 break;
8471 case CP0_REGISTER_26:
8472 switch (sel) {
8473 case CP0_REG26__ERRCTL:
8474 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8475 register_name = "ErrCtl";
8476 break;
8477 default:
8478 goto cp0_unimplemented;
8480 break;
8481 case CP0_REGISTER_27:
8482 switch (sel) {
8483 /* ignored */
8484 case CP0_REG27__CACHERR:
8485 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8486 register_name = "CacheErr";
8487 break;
8488 default:
8489 goto cp0_unimplemented;
8491 break;
8492 case CP0_REGISTER_28:
8493 switch (sel) {
8494 case CP0_REG28__TAGLO:
8495 case CP0_REG28__TAGLO1:
8496 case CP0_REG28__TAGLO2:
8497 case CP0_REG28__TAGLO3:
8498 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8499 register_name = "TagLo";
8500 break;
8501 case CP0_REG28__DATALO:
8502 case CP0_REG28__DATALO1:
8503 case CP0_REG28__DATALO2:
8504 case CP0_REG28__DATALO3:
8505 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8506 register_name = "DataLo";
8507 break;
8508 default:
8509 goto cp0_unimplemented;
8511 break;
8512 case CP0_REGISTER_29:
8513 switch (sel) {
8514 case CP0_REG29__TAGHI:
8515 case CP0_REG29__TAGHI1:
8516 case CP0_REG29__TAGHI2:
8517 case CP0_REG29__TAGHI3:
8518 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8519 register_name = "TagHi";
8520 break;
8521 case CP0_REG29__DATAHI:
8522 case CP0_REG29__DATAHI1:
8523 case CP0_REG29__DATAHI2:
8524 case CP0_REG29__DATAHI3:
8525 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8526 register_name = "DataHi";
8527 break;
8528 default:
8529 goto cp0_unimplemented;
8531 break;
8532 case CP0_REGISTER_30:
8533 switch (sel) {
8534 case CP0_REG30__ERROREPC:
8535 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8536 register_name = "ErrorEPC";
8537 break;
8538 default:
8539 goto cp0_unimplemented;
8541 break;
8542 case CP0_REGISTER_31:
8543 switch (sel) {
8544 case CP0_REG31__DESAVE:
8545 /* EJTAG support */
8546 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8547 register_name = "DESAVE";
8548 break;
8549 case CP0_REG31__KSCRATCH1:
8550 case CP0_REG31__KSCRATCH2:
8551 case CP0_REG31__KSCRATCH3:
8552 case CP0_REG31__KSCRATCH4:
8553 case CP0_REG31__KSCRATCH5:
8554 case CP0_REG31__KSCRATCH6:
8555 CP0_CHECK(ctx->kscrexist & (1 << sel));
8556 tcg_gen_ld_tl(arg, cpu_env,
8557 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8558 register_name = "KScratch";
8559 break;
8560 default:
8561 goto cp0_unimplemented;
8563 break;
8564 default:
8565 goto cp0_unimplemented;
8567 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
8568 return;
8570 cp0_unimplemented:
8571 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
8572 register_name, reg, sel);
8573 gen_mfc0_unimplemented(ctx, arg);
8576 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8578 const char *register_name = "invalid";
8580 if (sel != 0) {
8581 check_insn(ctx, ISA_MIPS_R1);
8584 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8585 gen_io_start();
8588 switch (reg) {
8589 case CP0_REGISTER_00:
8590 switch (sel) {
8591 case CP0_REG00__INDEX:
8592 gen_helper_mtc0_index(cpu_env, arg);
8593 register_name = "Index";
8594 break;
8595 case CP0_REG00__MVPCONTROL:
8596 CP0_CHECK(ctx->insn_flags & ASE_MT);
8597 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8598 register_name = "MVPControl";
8599 break;
8600 case CP0_REG00__MVPCONF0:
8601 CP0_CHECK(ctx->insn_flags & ASE_MT);
8602 /* ignored */
8603 register_name = "MVPConf0";
8604 break;
8605 case CP0_REG00__MVPCONF1:
8606 CP0_CHECK(ctx->insn_flags & ASE_MT);
8607 /* ignored */
8608 register_name = "MVPConf1";
8609 break;
8610 case CP0_REG00__VPCONTROL:
8611 CP0_CHECK(ctx->vp);
8612 /* ignored */
8613 register_name = "VPControl";
8614 break;
8615 default:
8616 goto cp0_unimplemented;
8618 break;
8619 case CP0_REGISTER_01:
8620 switch (sel) {
8621 case CP0_REG01__RANDOM:
8622 /* ignored */
8623 register_name = "Random";
8624 break;
8625 case CP0_REG01__VPECONTROL:
8626 CP0_CHECK(ctx->insn_flags & ASE_MT);
8627 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8628 register_name = "VPEControl";
8629 break;
8630 case CP0_REG01__VPECONF0:
8631 CP0_CHECK(ctx->insn_flags & ASE_MT);
8632 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8633 register_name = "VPEConf0";
8634 break;
8635 case CP0_REG01__VPECONF1:
8636 CP0_CHECK(ctx->insn_flags & ASE_MT);
8637 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8638 register_name = "VPEConf1";
8639 break;
8640 case CP0_REG01__YQMASK:
8641 CP0_CHECK(ctx->insn_flags & ASE_MT);
8642 gen_helper_mtc0_yqmask(cpu_env, arg);
8643 register_name = "YQMask";
8644 break;
8645 case CP0_REG01__VPESCHEDULE:
8646 CP0_CHECK(ctx->insn_flags & ASE_MT);
8647 tcg_gen_st_tl(arg, cpu_env,
8648 offsetof(CPUMIPSState, CP0_VPESchedule));
8649 register_name = "VPESchedule";
8650 break;
8651 case CP0_REG01__VPESCHEFBACK:
8652 CP0_CHECK(ctx->insn_flags & ASE_MT);
8653 tcg_gen_st_tl(arg, cpu_env,
8654 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8655 register_name = "VPEScheFBack";
8656 break;
8657 case CP0_REG01__VPEOPT:
8658 CP0_CHECK(ctx->insn_flags & ASE_MT);
8659 gen_helper_mtc0_vpeopt(cpu_env, arg);
8660 register_name = "VPEOpt";
8661 break;
8662 default:
8663 goto cp0_unimplemented;
8665 break;
8666 case CP0_REGISTER_02:
8667 switch (sel) {
8668 case CP0_REG02__ENTRYLO0:
8669 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8670 register_name = "EntryLo0";
8671 break;
8672 case CP0_REG02__TCSTATUS:
8673 CP0_CHECK(ctx->insn_flags & ASE_MT);
8674 gen_helper_mtc0_tcstatus(cpu_env, arg);
8675 register_name = "TCStatus";
8676 break;
8677 case CP0_REG02__TCBIND:
8678 CP0_CHECK(ctx->insn_flags & ASE_MT);
8679 gen_helper_mtc0_tcbind(cpu_env, arg);
8680 register_name = "TCBind";
8681 break;
8682 case CP0_REG02__TCRESTART:
8683 CP0_CHECK(ctx->insn_flags & ASE_MT);
8684 gen_helper_mtc0_tcrestart(cpu_env, arg);
8685 register_name = "TCRestart";
8686 break;
8687 case CP0_REG02__TCHALT:
8688 CP0_CHECK(ctx->insn_flags & ASE_MT);
8689 gen_helper_mtc0_tchalt(cpu_env, arg);
8690 register_name = "TCHalt";
8691 break;
8692 case CP0_REG02__TCCONTEXT:
8693 CP0_CHECK(ctx->insn_flags & ASE_MT);
8694 gen_helper_mtc0_tccontext(cpu_env, arg);
8695 register_name = "TCContext";
8696 break;
8697 case CP0_REG02__TCSCHEDULE:
8698 CP0_CHECK(ctx->insn_flags & ASE_MT);
8699 gen_helper_mtc0_tcschedule(cpu_env, arg);
8700 register_name = "TCSchedule";
8701 break;
8702 case CP0_REG02__TCSCHEFBACK:
8703 CP0_CHECK(ctx->insn_flags & ASE_MT);
8704 gen_helper_mtc0_tcschefback(cpu_env, arg);
8705 register_name = "TCScheFBack";
8706 break;
8707 default:
8708 goto cp0_unimplemented;
8710 break;
8711 case CP0_REGISTER_03:
8712 switch (sel) {
8713 case CP0_REG03__ENTRYLO1:
8714 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8715 register_name = "EntryLo1";
8716 break;
8717 case CP0_REG03__GLOBALNUM:
8718 CP0_CHECK(ctx->vp);
8719 /* ignored */
8720 register_name = "GlobalNumber";
8721 break;
8722 default:
8723 goto cp0_unimplemented;
8725 break;
8726 case CP0_REGISTER_04:
8727 switch (sel) {
8728 case CP0_REG04__CONTEXT:
8729 gen_helper_mtc0_context(cpu_env, arg);
8730 register_name = "Context";
8731 break;
8732 case CP0_REG04__CONTEXTCONFIG:
8733 /* SmartMIPS ASE */
8734 /* gen_helper_dmtc0_contextconfig(arg); */
8735 register_name = "ContextConfig";
8736 goto cp0_unimplemented;
8737 case CP0_REG04__USERLOCAL:
8738 CP0_CHECK(ctx->ulri);
8739 tcg_gen_st_tl(arg, cpu_env,
8740 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8741 register_name = "UserLocal";
8742 break;
8743 case CP0_REG04__MMID:
8744 CP0_CHECK(ctx->mi);
8745 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8746 register_name = "MMID";
8747 break;
8748 default:
8749 goto cp0_unimplemented;
8751 break;
8752 case CP0_REGISTER_05:
8753 switch (sel) {
8754 case CP0_REG05__PAGEMASK:
8755 gen_helper_mtc0_pagemask(cpu_env, arg);
8756 register_name = "PageMask";
8757 break;
8758 case CP0_REG05__PAGEGRAIN:
8759 check_insn(ctx, ISA_MIPS_R2);
8760 gen_helper_mtc0_pagegrain(cpu_env, arg);
8761 register_name = "PageGrain";
8762 break;
8763 case CP0_REG05__SEGCTL0:
8764 CP0_CHECK(ctx->sc);
8765 gen_helper_mtc0_segctl0(cpu_env, arg);
8766 register_name = "SegCtl0";
8767 break;
8768 case CP0_REG05__SEGCTL1:
8769 CP0_CHECK(ctx->sc);
8770 gen_helper_mtc0_segctl1(cpu_env, arg);
8771 register_name = "SegCtl1";
8772 break;
8773 case CP0_REG05__SEGCTL2:
8774 CP0_CHECK(ctx->sc);
8775 gen_helper_mtc0_segctl2(cpu_env, arg);
8776 register_name = "SegCtl2";
8777 break;
8778 case CP0_REG05__PWBASE:
8779 check_pw(ctx);
8780 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8781 register_name = "PWBase";
8782 break;
8783 case CP0_REG05__PWFIELD:
8784 check_pw(ctx);
8785 gen_helper_mtc0_pwfield(cpu_env, arg);
8786 register_name = "PWField";
8787 break;
8788 case CP0_REG05__PWSIZE:
8789 check_pw(ctx);
8790 gen_helper_mtc0_pwsize(cpu_env, arg);
8791 register_name = "PWSize";
8792 break;
8793 default:
8794 goto cp0_unimplemented;
8796 break;
8797 case CP0_REGISTER_06:
8798 switch (sel) {
8799 case CP0_REG06__WIRED:
8800 gen_helper_mtc0_wired(cpu_env, arg);
8801 register_name = "Wired";
8802 break;
8803 case CP0_REG06__SRSCONF0:
8804 check_insn(ctx, ISA_MIPS_R2);
8805 gen_helper_mtc0_srsconf0(cpu_env, arg);
8806 register_name = "SRSConf0";
8807 break;
8808 case CP0_REG06__SRSCONF1:
8809 check_insn(ctx, ISA_MIPS_R2);
8810 gen_helper_mtc0_srsconf1(cpu_env, arg);
8811 register_name = "SRSConf1";
8812 break;
8813 case CP0_REG06__SRSCONF2:
8814 check_insn(ctx, ISA_MIPS_R2);
8815 gen_helper_mtc0_srsconf2(cpu_env, arg);
8816 register_name = "SRSConf2";
8817 break;
8818 case CP0_REG06__SRSCONF3:
8819 check_insn(ctx, ISA_MIPS_R2);
8820 gen_helper_mtc0_srsconf3(cpu_env, arg);
8821 register_name = "SRSConf3";
8822 break;
8823 case CP0_REG06__SRSCONF4:
8824 check_insn(ctx, ISA_MIPS_R2);
8825 gen_helper_mtc0_srsconf4(cpu_env, arg);
8826 register_name = "SRSConf4";
8827 break;
8828 case CP0_REG06__PWCTL:
8829 check_pw(ctx);
8830 gen_helper_mtc0_pwctl(cpu_env, arg);
8831 register_name = "PWCtl";
8832 break;
8833 default:
8834 goto cp0_unimplemented;
8836 break;
8837 case CP0_REGISTER_07:
8838 switch (sel) {
8839 case CP0_REG07__HWRENA:
8840 check_insn(ctx, ISA_MIPS_R2);
8841 gen_helper_mtc0_hwrena(cpu_env, arg);
8842 ctx->base.is_jmp = DISAS_STOP;
8843 register_name = "HWREna";
8844 break;
8845 default:
8846 goto cp0_unimplemented;
8848 break;
8849 case CP0_REGISTER_08:
8850 switch (sel) {
8851 case CP0_REG08__BADVADDR:
8852 /* ignored */
8853 register_name = "BadVAddr";
8854 break;
8855 case CP0_REG08__BADINSTR:
8856 /* ignored */
8857 register_name = "BadInstr";
8858 break;
8859 case CP0_REG08__BADINSTRP:
8860 /* ignored */
8861 register_name = "BadInstrP";
8862 break;
8863 case CP0_REG08__BADINSTRX:
8864 /* ignored */
8865 register_name = "BadInstrX";
8866 break;
8867 default:
8868 goto cp0_unimplemented;
8870 break;
8871 case CP0_REGISTER_09:
8872 switch (sel) {
8873 case CP0_REG09__COUNT:
8874 gen_helper_mtc0_count(cpu_env, arg);
8875 register_name = "Count";
8876 break;
8877 case CP0_REG09__SAARI:
8878 CP0_CHECK(ctx->saar);
8879 gen_helper_mtc0_saari(cpu_env, arg);
8880 register_name = "SAARI";
8881 break;
8882 case CP0_REG09__SAAR:
8883 CP0_CHECK(ctx->saar);
8884 gen_helper_mtc0_saar(cpu_env, arg);
8885 register_name = "SAAR";
8886 break;
8887 default:
8888 goto cp0_unimplemented;
8890 /* Stop translation as we may have switched the execution mode */
8891 ctx->base.is_jmp = DISAS_STOP;
8892 break;
8893 case CP0_REGISTER_10:
8894 switch (sel) {
8895 case CP0_REG10__ENTRYHI:
8896 gen_helper_mtc0_entryhi(cpu_env, arg);
8897 register_name = "EntryHi";
8898 break;
8899 default:
8900 goto cp0_unimplemented;
8902 break;
8903 case CP0_REGISTER_11:
8904 switch (sel) {
8905 case CP0_REG11__COMPARE:
8906 gen_helper_mtc0_compare(cpu_env, arg);
8907 register_name = "Compare";
8908 break;
8909 /* 6,7 are implementation dependent */
8910 default:
8911 goto cp0_unimplemented;
8913 /* Stop translation as we may have switched the execution mode */
8914 ctx->base.is_jmp = DISAS_STOP;
8915 break;
8916 case CP0_REGISTER_12:
8917 switch (sel) {
8918 case CP0_REG12__STATUS:
8919 save_cpu_state(ctx, 1);
8920 gen_helper_mtc0_status(cpu_env, arg);
8921 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8922 gen_save_pc(ctx->base.pc_next + 4);
8923 ctx->base.is_jmp = DISAS_EXIT;
8924 register_name = "Status";
8925 break;
8926 case CP0_REG12__INTCTL:
8927 check_insn(ctx, ISA_MIPS_R2);
8928 gen_helper_mtc0_intctl(cpu_env, arg);
8929 /* Stop translation as we may have switched the execution mode */
8930 ctx->base.is_jmp = DISAS_STOP;
8931 register_name = "IntCtl";
8932 break;
8933 case CP0_REG12__SRSCTL:
8934 check_insn(ctx, ISA_MIPS_R2);
8935 gen_helper_mtc0_srsctl(cpu_env, arg);
8936 /* Stop translation as we may have switched the execution mode */
8937 ctx->base.is_jmp = DISAS_STOP;
8938 register_name = "SRSCtl";
8939 break;
8940 case CP0_REG12__SRSMAP:
8941 check_insn(ctx, ISA_MIPS_R2);
8942 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8943 /* Stop translation as we may have switched the execution mode */
8944 ctx->base.is_jmp = DISAS_STOP;
8945 register_name = "SRSMap";
8946 break;
8947 default:
8948 goto cp0_unimplemented;
8950 break;
8951 case CP0_REGISTER_13:
8952 switch (sel) {
8953 case CP0_REG13__CAUSE:
8954 save_cpu_state(ctx, 1);
8955 gen_helper_mtc0_cause(cpu_env, arg);
8957 * Stop translation as we may have triggered an interrupt.
8958 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8959 * translated code to check for pending interrupts.
8961 gen_save_pc(ctx->base.pc_next + 4);
8962 ctx->base.is_jmp = DISAS_EXIT;
8963 register_name = "Cause";
8964 break;
8965 default:
8966 goto cp0_unimplemented;
8968 break;
8969 case CP0_REGISTER_14:
8970 switch (sel) {
8971 case CP0_REG14__EPC:
8972 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8973 register_name = "EPC";
8974 break;
8975 default:
8976 goto cp0_unimplemented;
8978 break;
8979 case CP0_REGISTER_15:
8980 switch (sel) {
8981 case CP0_REG15__PRID:
8982 /* ignored */
8983 register_name = "PRid";
8984 break;
8985 case CP0_REG15__EBASE:
8986 check_insn(ctx, ISA_MIPS_R2);
8987 gen_helper_mtc0_ebase(cpu_env, arg);
8988 register_name = "EBase";
8989 break;
8990 default:
8991 goto cp0_unimplemented;
8993 break;
8994 case CP0_REGISTER_16:
8995 switch (sel) {
8996 case CP0_REG16__CONFIG:
8997 gen_helper_mtc0_config0(cpu_env, arg);
8998 register_name = "Config";
8999 /* Stop translation as we may have switched the execution mode */
9000 ctx->base.is_jmp = DISAS_STOP;
9001 break;
9002 case CP0_REG16__CONFIG1:
9003 /* ignored, read only */
9004 register_name = "Config1";
9005 break;
9006 case CP0_REG16__CONFIG2:
9007 gen_helper_mtc0_config2(cpu_env, arg);
9008 register_name = "Config2";
9009 /* Stop translation as we may have switched the execution mode */
9010 ctx->base.is_jmp = DISAS_STOP;
9011 break;
9012 case CP0_REG16__CONFIG3:
9013 gen_helper_mtc0_config3(cpu_env, arg);
9014 register_name = "Config3";
9015 /* Stop translation as we may have switched the execution mode */
9016 ctx->base.is_jmp = DISAS_STOP;
9017 break;
9018 case CP0_REG16__CONFIG4:
9019 /* currently ignored */
9020 register_name = "Config4";
9021 break;
9022 case CP0_REG16__CONFIG5:
9023 gen_helper_mtc0_config5(cpu_env, arg);
9024 register_name = "Config5";
9025 /* Stop translation as we may have switched the execution mode */
9026 ctx->base.is_jmp = DISAS_STOP;
9027 break;
9028 /* 6,7 are implementation dependent */
9029 default:
9030 register_name = "Invalid config selector";
9031 goto cp0_unimplemented;
9033 break;
9034 case CP0_REGISTER_17:
9035 switch (sel) {
9036 case CP0_REG17__LLADDR:
9037 gen_helper_mtc0_lladdr(cpu_env, arg);
9038 register_name = "LLAddr";
9039 break;
9040 case CP0_REG17__MAAR:
9041 CP0_CHECK(ctx->mrp);
9042 gen_helper_mtc0_maar(cpu_env, arg);
9043 register_name = "MAAR";
9044 break;
9045 case CP0_REG17__MAARI:
9046 CP0_CHECK(ctx->mrp);
9047 gen_helper_mtc0_maari(cpu_env, arg);
9048 register_name = "MAARI";
9049 break;
9050 default:
9051 goto cp0_unimplemented;
9053 break;
9054 case CP0_REGISTER_18:
9055 switch (sel) {
9056 case CP0_REG18__WATCHLO0:
9057 case CP0_REG18__WATCHLO1:
9058 case CP0_REG18__WATCHLO2:
9059 case CP0_REG18__WATCHLO3:
9060 case CP0_REG18__WATCHLO4:
9061 case CP0_REG18__WATCHLO5:
9062 case CP0_REG18__WATCHLO6:
9063 case CP0_REG18__WATCHLO7:
9064 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9065 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9066 register_name = "WatchLo";
9067 break;
9068 default:
9069 goto cp0_unimplemented;
9071 break;
9072 case CP0_REGISTER_19:
9073 switch (sel) {
9074 case CP0_REG19__WATCHHI0:
9075 case CP0_REG19__WATCHHI1:
9076 case CP0_REG19__WATCHHI2:
9077 case CP0_REG19__WATCHHI3:
9078 case CP0_REG19__WATCHHI4:
9079 case CP0_REG19__WATCHHI5:
9080 case CP0_REG19__WATCHHI6:
9081 case CP0_REG19__WATCHHI7:
9082 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9083 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9084 register_name = "WatchHi";
9085 break;
9086 default:
9087 goto cp0_unimplemented;
9089 break;
9090 case CP0_REGISTER_20:
9091 switch (sel) {
9092 case CP0_REG20__XCONTEXT:
9093 check_insn(ctx, ISA_MIPS3);
9094 gen_helper_mtc0_xcontext(cpu_env, arg);
9095 register_name = "XContext";
9096 break;
9097 default:
9098 goto cp0_unimplemented;
9100 break;
9101 case CP0_REGISTER_21:
9102 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9103 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9104 switch (sel) {
9105 case 0:
9106 gen_helper_mtc0_framemask(cpu_env, arg);
9107 register_name = "Framemask";
9108 break;
9109 default:
9110 goto cp0_unimplemented;
9112 break;
9113 case CP0_REGISTER_22:
9114 /* ignored */
9115 register_name = "Diagnostic"; /* implementation dependent */
9116 break;
9117 case CP0_REGISTER_23:
9118 switch (sel) {
9119 case CP0_REG23__DEBUG:
9120 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9121 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9122 gen_save_pc(ctx->base.pc_next + 4);
9123 ctx->base.is_jmp = DISAS_EXIT;
9124 register_name = "Debug";
9125 break;
9126 case CP0_REG23__TRACECONTROL:
9127 /* PDtrace support */
9128 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
9129 /* Stop translation as we may have switched the execution mode */
9130 ctx->base.is_jmp = DISAS_STOP;
9131 register_name = "TraceControl";
9132 goto cp0_unimplemented;
9133 case CP0_REG23__TRACECONTROL2:
9134 /* PDtrace support */
9135 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
9136 /* Stop translation as we may have switched the execution mode */
9137 ctx->base.is_jmp = DISAS_STOP;
9138 register_name = "TraceControl2";
9139 goto cp0_unimplemented;
9140 case CP0_REG23__USERTRACEDATA1:
9141 /* PDtrace support */
9142 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
9143 /* Stop translation as we may have switched the execution mode */
9144 ctx->base.is_jmp = DISAS_STOP;
9145 register_name = "UserTraceData1";
9146 goto cp0_unimplemented;
9147 case CP0_REG23__TRACEIBPC:
9148 /* PDtrace support */
9149 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
9150 /* Stop translation as we may have switched the execution mode */
9151 ctx->base.is_jmp = DISAS_STOP;
9152 register_name = "TraceIBPC";
9153 goto cp0_unimplemented;
9154 case CP0_REG23__TRACEDBPC:
9155 /* PDtrace support */
9156 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
9157 /* Stop translation as we may have switched the execution mode */
9158 ctx->base.is_jmp = DISAS_STOP;
9159 register_name = "TraceDBPC";
9160 goto cp0_unimplemented;
9161 default:
9162 goto cp0_unimplemented;
9164 break;
9165 case CP0_REGISTER_24:
9166 switch (sel) {
9167 case CP0_REG24__DEPC:
9168 /* EJTAG support */
9169 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9170 register_name = "DEPC";
9171 break;
9172 default:
9173 goto cp0_unimplemented;
9175 break;
9176 case CP0_REGISTER_25:
9177 switch (sel) {
9178 case CP0_REG25__PERFCTL0:
9179 gen_helper_mtc0_performance0(cpu_env, arg);
9180 register_name = "Performance0";
9181 break;
9182 case CP0_REG25__PERFCNT0:
9183 /* gen_helper_mtc0_performance1(cpu_env, arg); */
9184 register_name = "Performance1";
9185 goto cp0_unimplemented;
9186 case CP0_REG25__PERFCTL1:
9187 /* gen_helper_mtc0_performance2(cpu_env, arg); */
9188 register_name = "Performance2";
9189 goto cp0_unimplemented;
9190 case CP0_REG25__PERFCNT1:
9191 /* gen_helper_mtc0_performance3(cpu_env, arg); */
9192 register_name = "Performance3";
9193 goto cp0_unimplemented;
9194 case CP0_REG25__PERFCTL2:
9195 /* gen_helper_mtc0_performance4(cpu_env, arg); */
9196 register_name = "Performance4";
9197 goto cp0_unimplemented;
9198 case CP0_REG25__PERFCNT2:
9199 /* gen_helper_mtc0_performance5(cpu_env, arg); */
9200 register_name = "Performance5";
9201 goto cp0_unimplemented;
9202 case CP0_REG25__PERFCTL3:
9203 /* gen_helper_mtc0_performance6(cpu_env, arg); */
9204 register_name = "Performance6";
9205 goto cp0_unimplemented;
9206 case CP0_REG25__PERFCNT3:
9207 /* gen_helper_mtc0_performance7(cpu_env, arg); */
9208 register_name = "Performance7";
9209 goto cp0_unimplemented;
9210 default:
9211 goto cp0_unimplemented;
9213 break;
9214 case CP0_REGISTER_26:
9215 switch (sel) {
9216 case CP0_REG26__ERRCTL:
9217 gen_helper_mtc0_errctl(cpu_env, arg);
9218 ctx->base.is_jmp = DISAS_STOP;
9219 register_name = "ErrCtl";
9220 break;
9221 default:
9222 goto cp0_unimplemented;
9224 break;
9225 case CP0_REGISTER_27:
9226 switch (sel) {
9227 case CP0_REG27__CACHERR:
9228 /* ignored */
9229 register_name = "CacheErr";
9230 break;
9231 default:
9232 goto cp0_unimplemented;
9234 break;
9235 case CP0_REGISTER_28:
9236 switch (sel) {
9237 case CP0_REG28__TAGLO:
9238 case CP0_REG28__TAGLO1:
9239 case CP0_REG28__TAGLO2:
9240 case CP0_REG28__TAGLO3:
9241 gen_helper_mtc0_taglo(cpu_env, arg);
9242 register_name = "TagLo";
9243 break;
9244 case CP0_REG28__DATALO:
9245 case CP0_REG28__DATALO1:
9246 case CP0_REG28__DATALO2:
9247 case CP0_REG28__DATALO3:
9248 gen_helper_mtc0_datalo(cpu_env, arg);
9249 register_name = "DataLo";
9250 break;
9251 default:
9252 goto cp0_unimplemented;
9254 break;
9255 case CP0_REGISTER_29:
9256 switch (sel) {
9257 case CP0_REG29__TAGHI:
9258 case CP0_REG29__TAGHI1:
9259 case CP0_REG29__TAGHI2:
9260 case CP0_REG29__TAGHI3:
9261 gen_helper_mtc0_taghi(cpu_env, arg);
9262 register_name = "TagHi";
9263 break;
9264 case CP0_REG29__DATAHI:
9265 case CP0_REG29__DATAHI1:
9266 case CP0_REG29__DATAHI2:
9267 case CP0_REG29__DATAHI3:
9268 gen_helper_mtc0_datahi(cpu_env, arg);
9269 register_name = "DataHi";
9270 break;
9271 default:
9272 register_name = "invalid sel";
9273 goto cp0_unimplemented;
9275 break;
9276 case CP0_REGISTER_30:
9277 switch (sel) {
9278 case CP0_REG30__ERROREPC:
9279 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9280 register_name = "ErrorEPC";
9281 break;
9282 default:
9283 goto cp0_unimplemented;
9285 break;
9286 case CP0_REGISTER_31:
9287 switch (sel) {
9288 case CP0_REG31__DESAVE:
9289 /* EJTAG support */
9290 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9291 register_name = "DESAVE";
9292 break;
9293 case CP0_REG31__KSCRATCH1:
9294 case CP0_REG31__KSCRATCH2:
9295 case CP0_REG31__KSCRATCH3:
9296 case CP0_REG31__KSCRATCH4:
9297 case CP0_REG31__KSCRATCH5:
9298 case CP0_REG31__KSCRATCH6:
9299 CP0_CHECK(ctx->kscrexist & (1 << sel));
9300 tcg_gen_st_tl(arg, cpu_env,
9301 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9302 register_name = "KScratch";
9303 break;
9304 default:
9305 goto cp0_unimplemented;
9307 break;
9308 default:
9309 goto cp0_unimplemented;
9311 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9313 /* For simplicity assume that all writes can cause interrupts. */
9314 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9316 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9317 * translated code to check for pending interrupts.
9319 gen_save_pc(ctx->base.pc_next + 4);
9320 ctx->base.is_jmp = DISAS_EXIT;
9322 return;
9324 cp0_unimplemented:
9325 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9326 register_name, reg, sel);
9328 #endif /* TARGET_MIPS64 */
9330 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9331 int u, int sel, int h)
9333 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9334 TCGv t0 = tcg_temp_local_new();
9336 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9337 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9338 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9339 tcg_gen_movi_tl(t0, -1);
9340 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9341 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9342 tcg_gen_movi_tl(t0, -1);
9343 } else if (u == 0) {
9344 switch (rt) {
9345 case 1:
9346 switch (sel) {
9347 case 1:
9348 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9349 break;
9350 case 2:
9351 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9352 break;
9353 default:
9354 goto die;
9355 break;
9357 break;
9358 case 2:
9359 switch (sel) {
9360 case 1:
9361 gen_helper_mftc0_tcstatus(t0, cpu_env);
9362 break;
9363 case 2:
9364 gen_helper_mftc0_tcbind(t0, cpu_env);
9365 break;
9366 case 3:
9367 gen_helper_mftc0_tcrestart(t0, cpu_env);
9368 break;
9369 case 4:
9370 gen_helper_mftc0_tchalt(t0, cpu_env);
9371 break;
9372 case 5:
9373 gen_helper_mftc0_tccontext(t0, cpu_env);
9374 break;
9375 case 6:
9376 gen_helper_mftc0_tcschedule(t0, cpu_env);
9377 break;
9378 case 7:
9379 gen_helper_mftc0_tcschefback(t0, cpu_env);
9380 break;
9381 default:
9382 gen_mfc0(ctx, t0, rt, sel);
9383 break;
9385 break;
9386 case 10:
9387 switch (sel) {
9388 case 0:
9389 gen_helper_mftc0_entryhi(t0, cpu_env);
9390 break;
9391 default:
9392 gen_mfc0(ctx, t0, rt, sel);
9393 break;
9395 break;
9396 case 12:
9397 switch (sel) {
9398 case 0:
9399 gen_helper_mftc0_status(t0, cpu_env);
9400 break;
9401 default:
9402 gen_mfc0(ctx, t0, rt, sel);
9403 break;
9405 break;
9406 case 13:
9407 switch (sel) {
9408 case 0:
9409 gen_helper_mftc0_cause(t0, cpu_env);
9410 break;
9411 default:
9412 goto die;
9413 break;
9415 break;
9416 case 14:
9417 switch (sel) {
9418 case 0:
9419 gen_helper_mftc0_epc(t0, cpu_env);
9420 break;
9421 default:
9422 goto die;
9423 break;
9425 break;
9426 case 15:
9427 switch (sel) {
9428 case 1:
9429 gen_helper_mftc0_ebase(t0, cpu_env);
9430 break;
9431 default:
9432 goto die;
9433 break;
9435 break;
9436 case 16:
9437 switch (sel) {
9438 case 0:
9439 case 1:
9440 case 2:
9441 case 3:
9442 case 4:
9443 case 5:
9444 case 6:
9445 case 7:
9446 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9447 break;
9448 default:
9449 goto die;
9450 break;
9452 break;
9453 case 23:
9454 switch (sel) {
9455 case 0:
9456 gen_helper_mftc0_debug(t0, cpu_env);
9457 break;
9458 default:
9459 gen_mfc0(ctx, t0, rt, sel);
9460 break;
9462 break;
9463 default:
9464 gen_mfc0(ctx, t0, rt, sel);
9466 } else {
9467 switch (sel) {
9468 /* GPR registers. */
9469 case 0:
9470 gen_helper_1e0i(mftgpr, t0, rt);
9471 break;
9472 /* Auxiliary CPU registers */
9473 case 1:
9474 switch (rt) {
9475 case 0:
9476 gen_helper_1e0i(mftlo, t0, 0);
9477 break;
9478 case 1:
9479 gen_helper_1e0i(mfthi, t0, 0);
9480 break;
9481 case 2:
9482 gen_helper_1e0i(mftacx, t0, 0);
9483 break;
9484 case 4:
9485 gen_helper_1e0i(mftlo, t0, 1);
9486 break;
9487 case 5:
9488 gen_helper_1e0i(mfthi, t0, 1);
9489 break;
9490 case 6:
9491 gen_helper_1e0i(mftacx, t0, 1);
9492 break;
9493 case 8:
9494 gen_helper_1e0i(mftlo, t0, 2);
9495 break;
9496 case 9:
9497 gen_helper_1e0i(mfthi, t0, 2);
9498 break;
9499 case 10:
9500 gen_helper_1e0i(mftacx, t0, 2);
9501 break;
9502 case 12:
9503 gen_helper_1e0i(mftlo, t0, 3);
9504 break;
9505 case 13:
9506 gen_helper_1e0i(mfthi, t0, 3);
9507 break;
9508 case 14:
9509 gen_helper_1e0i(mftacx, t0, 3);
9510 break;
9511 case 16:
9512 gen_helper_mftdsp(t0, cpu_env);
9513 break;
9514 default:
9515 goto die;
9517 break;
9518 /* Floating point (COP1). */
9519 case 2:
9520 /* XXX: For now we support only a single FPU context. */
9521 if (h == 0) {
9522 TCGv_i32 fp0 = tcg_temp_new_i32();
9524 gen_load_fpr32(ctx, fp0, rt);
9525 tcg_gen_ext_i32_tl(t0, fp0);
9526 tcg_temp_free_i32(fp0);
9527 } else {
9528 TCGv_i32 fp0 = tcg_temp_new_i32();
9530 gen_load_fpr32h(ctx, fp0, rt);
9531 tcg_gen_ext_i32_tl(t0, fp0);
9532 tcg_temp_free_i32(fp0);
9534 break;
9535 case 3:
9536 /* XXX: For now we support only a single FPU context. */
9537 gen_helper_1e0i(cfc1, t0, rt);
9538 break;
9539 /* COP2: Not implemented. */
9540 case 4:
9541 case 5:
9542 /* fall through */
9543 default:
9544 goto die;
9547 trace_mips_translate_tr("mftr", rt, u, sel, h);
9548 gen_store_gpr(t0, rd);
9549 tcg_temp_free(t0);
9550 return;
9552 die:
9553 tcg_temp_free(t0);
9554 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9555 gen_reserved_instruction(ctx);
9558 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9559 int u, int sel, int h)
9561 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9562 TCGv t0 = tcg_temp_local_new();
9564 gen_load_gpr(t0, rt);
9565 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9566 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9567 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9568 /* NOP */
9570 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9571 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9572 /* NOP */
9574 } else if (u == 0) {
9575 switch (rd) {
9576 case 1:
9577 switch (sel) {
9578 case 1:
9579 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9580 break;
9581 case 2:
9582 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9583 break;
9584 default:
9585 goto die;
9586 break;
9588 break;
9589 case 2:
9590 switch (sel) {
9591 case 1:
9592 gen_helper_mttc0_tcstatus(cpu_env, t0);
9593 break;
9594 case 2:
9595 gen_helper_mttc0_tcbind(cpu_env, t0);
9596 break;
9597 case 3:
9598 gen_helper_mttc0_tcrestart(cpu_env, t0);
9599 break;
9600 case 4:
9601 gen_helper_mttc0_tchalt(cpu_env, t0);
9602 break;
9603 case 5:
9604 gen_helper_mttc0_tccontext(cpu_env, t0);
9605 break;
9606 case 6:
9607 gen_helper_mttc0_tcschedule(cpu_env, t0);
9608 break;
9609 case 7:
9610 gen_helper_mttc0_tcschefback(cpu_env, t0);
9611 break;
9612 default:
9613 gen_mtc0(ctx, t0, rd, sel);
9614 break;
9616 break;
9617 case 10:
9618 switch (sel) {
9619 case 0:
9620 gen_helper_mttc0_entryhi(cpu_env, t0);
9621 break;
9622 default:
9623 gen_mtc0(ctx, t0, rd, sel);
9624 break;
9626 break;
9627 case 12:
9628 switch (sel) {
9629 case 0:
9630 gen_helper_mttc0_status(cpu_env, t0);
9631 break;
9632 default:
9633 gen_mtc0(ctx, t0, rd, sel);
9634 break;
9636 break;
9637 case 13:
9638 switch (sel) {
9639 case 0:
9640 gen_helper_mttc0_cause(cpu_env, t0);
9641 break;
9642 default:
9643 goto die;
9644 break;
9646 break;
9647 case 15:
9648 switch (sel) {
9649 case 1:
9650 gen_helper_mttc0_ebase(cpu_env, t0);
9651 break;
9652 default:
9653 goto die;
9654 break;
9656 break;
9657 case 23:
9658 switch (sel) {
9659 case 0:
9660 gen_helper_mttc0_debug(cpu_env, t0);
9661 break;
9662 default:
9663 gen_mtc0(ctx, t0, rd, sel);
9664 break;
9666 break;
9667 default:
9668 gen_mtc0(ctx, t0, rd, sel);
9670 } else {
9671 switch (sel) {
9672 /* GPR registers. */
9673 case 0:
9674 gen_helper_0e1i(mttgpr, t0, rd);
9675 break;
9676 /* Auxiliary CPU registers */
9677 case 1:
9678 switch (rd) {
9679 case 0:
9680 gen_helper_0e1i(mttlo, t0, 0);
9681 break;
9682 case 1:
9683 gen_helper_0e1i(mtthi, t0, 0);
9684 break;
9685 case 2:
9686 gen_helper_0e1i(mttacx, t0, 0);
9687 break;
9688 case 4:
9689 gen_helper_0e1i(mttlo, t0, 1);
9690 break;
9691 case 5:
9692 gen_helper_0e1i(mtthi, t0, 1);
9693 break;
9694 case 6:
9695 gen_helper_0e1i(mttacx, t0, 1);
9696 break;
9697 case 8:
9698 gen_helper_0e1i(mttlo, t0, 2);
9699 break;
9700 case 9:
9701 gen_helper_0e1i(mtthi, t0, 2);
9702 break;
9703 case 10:
9704 gen_helper_0e1i(mttacx, t0, 2);
9705 break;
9706 case 12:
9707 gen_helper_0e1i(mttlo, t0, 3);
9708 break;
9709 case 13:
9710 gen_helper_0e1i(mtthi, t0, 3);
9711 break;
9712 case 14:
9713 gen_helper_0e1i(mttacx, t0, 3);
9714 break;
9715 case 16:
9716 gen_helper_mttdsp(cpu_env, t0);
9717 break;
9718 default:
9719 goto die;
9721 break;
9722 /* Floating point (COP1). */
9723 case 2:
9724 /* XXX: For now we support only a single FPU context. */
9725 if (h == 0) {
9726 TCGv_i32 fp0 = tcg_temp_new_i32();
9728 tcg_gen_trunc_tl_i32(fp0, t0);
9729 gen_store_fpr32(ctx, fp0, rd);
9730 tcg_temp_free_i32(fp0);
9731 } else {
9732 TCGv_i32 fp0 = tcg_temp_new_i32();
9734 tcg_gen_trunc_tl_i32(fp0, t0);
9735 gen_store_fpr32h(ctx, fp0, rd);
9736 tcg_temp_free_i32(fp0);
9738 break;
9739 case 3:
9740 /* XXX: For now we support only a single FPU context. */
9742 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9744 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9745 tcg_temp_free_i32(fs_tmp);
9747 /* Stop translation as we may have changed hflags */
9748 ctx->base.is_jmp = DISAS_STOP;
9749 break;
9750 /* COP2: Not implemented. */
9751 case 4:
9752 case 5:
9753 /* fall through */
9754 default:
9755 goto die;
9758 trace_mips_translate_tr("mttr", rd, u, sel, h);
9759 tcg_temp_free(t0);
9760 return;
9762 die:
9763 tcg_temp_free(t0);
9764 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9765 gen_reserved_instruction(ctx);
9768 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
9769 int rt, int rd)
9771 const char *opn = "ldst";
9773 check_cp0_enabled(ctx);
9774 switch (opc) {
9775 case OPC_MFC0:
9776 if (rt == 0) {
9777 /* Treat as NOP. */
9778 return;
9780 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9781 opn = "mfc0";
9782 break;
9783 case OPC_MTC0:
9785 TCGv t0 = tcg_temp_new();
9787 gen_load_gpr(t0, rt);
9788 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9789 tcg_temp_free(t0);
9791 opn = "mtc0";
9792 break;
9793 #if defined(TARGET_MIPS64)
9794 case OPC_DMFC0:
9795 check_insn(ctx, ISA_MIPS3);
9796 if (rt == 0) {
9797 /* Treat as NOP. */
9798 return;
9800 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9801 opn = "dmfc0";
9802 break;
9803 case OPC_DMTC0:
9804 check_insn(ctx, ISA_MIPS3);
9806 TCGv t0 = tcg_temp_new();
9808 gen_load_gpr(t0, rt);
9809 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9810 tcg_temp_free(t0);
9812 opn = "dmtc0";
9813 break;
9814 #endif
9815 case OPC_MFHC0:
9816 check_mvh(ctx);
9817 if (rt == 0) {
9818 /* Treat as NOP. */
9819 return;
9821 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9822 opn = "mfhc0";
9823 break;
9824 case OPC_MTHC0:
9825 check_mvh(ctx);
9827 TCGv t0 = tcg_temp_new();
9828 gen_load_gpr(t0, rt);
9829 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9830 tcg_temp_free(t0);
9832 opn = "mthc0";
9833 break;
9834 case OPC_MFTR:
9835 check_cp0_enabled(ctx);
9836 if (rd == 0) {
9837 /* Treat as NOP. */
9838 return;
9840 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9841 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9842 opn = "mftr";
9843 break;
9844 case OPC_MTTR:
9845 check_cp0_enabled(ctx);
9846 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9847 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9848 opn = "mttr";
9849 break;
9850 case OPC_TLBWI:
9851 opn = "tlbwi";
9852 if (!env->tlb->helper_tlbwi) {
9853 goto die;
9855 gen_helper_tlbwi(cpu_env);
9856 break;
9857 case OPC_TLBINV:
9858 opn = "tlbinv";
9859 if (ctx->ie >= 2) {
9860 if (!env->tlb->helper_tlbinv) {
9861 goto die;
9863 gen_helper_tlbinv(cpu_env);
9864 } /* treat as nop if TLBINV not supported */
9865 break;
9866 case OPC_TLBINVF:
9867 opn = "tlbinvf";
9868 if (ctx->ie >= 2) {
9869 if (!env->tlb->helper_tlbinvf) {
9870 goto die;
9872 gen_helper_tlbinvf(cpu_env);
9873 } /* treat as nop if TLBINV not supported */
9874 break;
9875 case OPC_TLBWR:
9876 opn = "tlbwr";
9877 if (!env->tlb->helper_tlbwr) {
9878 goto die;
9880 gen_helper_tlbwr(cpu_env);
9881 break;
9882 case OPC_TLBP:
9883 opn = "tlbp";
9884 if (!env->tlb->helper_tlbp) {
9885 goto die;
9887 gen_helper_tlbp(cpu_env);
9888 break;
9889 case OPC_TLBR:
9890 opn = "tlbr";
9891 if (!env->tlb->helper_tlbr) {
9892 goto die;
9894 gen_helper_tlbr(cpu_env);
9895 break;
9896 case OPC_ERET: /* OPC_ERETNC */
9897 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9898 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9899 goto die;
9900 } else {
9901 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9902 if (ctx->opcode & (1 << bit_shift)) {
9903 /* OPC_ERETNC */
9904 opn = "eretnc";
9905 check_insn(ctx, ISA_MIPS_R5);
9906 gen_helper_eretnc(cpu_env);
9907 } else {
9908 /* OPC_ERET */
9909 opn = "eret";
9910 check_insn(ctx, ISA_MIPS2);
9911 gen_helper_eret(cpu_env);
9913 ctx->base.is_jmp = DISAS_EXIT;
9915 break;
9916 case OPC_DERET:
9917 opn = "deret";
9918 check_insn(ctx, ISA_MIPS_R1);
9919 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9920 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9921 goto die;
9923 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9924 MIPS_INVAL(opn);
9925 gen_reserved_instruction(ctx);
9926 } else {
9927 gen_helper_deret(cpu_env);
9928 ctx->base.is_jmp = DISAS_EXIT;
9930 break;
9931 case OPC_WAIT:
9932 opn = "wait";
9933 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
9934 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9935 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9936 goto die;
9938 /* If we get an exception, we want to restart at next instruction */
9939 ctx->base.pc_next += 4;
9940 save_cpu_state(ctx, 1);
9941 ctx->base.pc_next -= 4;
9942 gen_helper_wait(cpu_env);
9943 ctx->base.is_jmp = DISAS_NORETURN;
9944 break;
9945 default:
9946 die:
9947 MIPS_INVAL(opn);
9948 gen_reserved_instruction(ctx);
9949 return;
9951 (void)opn; /* avoid a compiler warning */
9953 #endif /* !CONFIG_USER_ONLY */
9955 /* CP1 Branches (before delay slot) */
9956 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9957 int32_t cc, int32_t offset)
9959 target_ulong btarget;
9960 TCGv_i32 t0 = tcg_temp_new_i32();
9962 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9963 gen_reserved_instruction(ctx);
9964 goto out;
9967 if (cc != 0) {
9968 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
9971 btarget = ctx->base.pc_next + 4 + offset;
9973 switch (op) {
9974 case OPC_BC1F:
9975 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9976 tcg_gen_not_i32(t0, t0);
9977 tcg_gen_andi_i32(t0, t0, 1);
9978 tcg_gen_extu_i32_tl(bcond, t0);
9979 goto not_likely;
9980 case OPC_BC1FL:
9981 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9982 tcg_gen_not_i32(t0, t0);
9983 tcg_gen_andi_i32(t0, t0, 1);
9984 tcg_gen_extu_i32_tl(bcond, t0);
9985 goto likely;
9986 case OPC_BC1T:
9987 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9988 tcg_gen_andi_i32(t0, t0, 1);
9989 tcg_gen_extu_i32_tl(bcond, t0);
9990 goto not_likely;
9991 case OPC_BC1TL:
9992 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9993 tcg_gen_andi_i32(t0, t0, 1);
9994 tcg_gen_extu_i32_tl(bcond, t0);
9995 likely:
9996 ctx->hflags |= MIPS_HFLAG_BL;
9997 break;
9998 case OPC_BC1FANY2:
10000 TCGv_i32 t1 = tcg_temp_new_i32();
10001 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10002 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10003 tcg_gen_nand_i32(t0, t0, t1);
10004 tcg_temp_free_i32(t1);
10005 tcg_gen_andi_i32(t0, t0, 1);
10006 tcg_gen_extu_i32_tl(bcond, t0);
10008 goto not_likely;
10009 case OPC_BC1TANY2:
10011 TCGv_i32 t1 = tcg_temp_new_i32();
10012 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10013 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10014 tcg_gen_or_i32(t0, t0, t1);
10015 tcg_temp_free_i32(t1);
10016 tcg_gen_andi_i32(t0, t0, 1);
10017 tcg_gen_extu_i32_tl(bcond, t0);
10019 goto not_likely;
10020 case OPC_BC1FANY4:
10022 TCGv_i32 t1 = tcg_temp_new_i32();
10023 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10024 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10025 tcg_gen_and_i32(t0, t0, t1);
10026 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10027 tcg_gen_and_i32(t0, t0, t1);
10028 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10029 tcg_gen_nand_i32(t0, t0, t1);
10030 tcg_temp_free_i32(t1);
10031 tcg_gen_andi_i32(t0, t0, 1);
10032 tcg_gen_extu_i32_tl(bcond, t0);
10034 goto not_likely;
10035 case OPC_BC1TANY4:
10037 TCGv_i32 t1 = tcg_temp_new_i32();
10038 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10039 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10040 tcg_gen_or_i32(t0, t0, t1);
10041 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10042 tcg_gen_or_i32(t0, t0, t1);
10043 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10044 tcg_gen_or_i32(t0, t0, t1);
10045 tcg_temp_free_i32(t1);
10046 tcg_gen_andi_i32(t0, t0, 1);
10047 tcg_gen_extu_i32_tl(bcond, t0);
10049 not_likely:
10050 ctx->hflags |= MIPS_HFLAG_BC;
10051 break;
10052 default:
10053 MIPS_INVAL("cp1 cond branch");
10054 gen_reserved_instruction(ctx);
10055 goto out;
10057 ctx->btarget = btarget;
10058 ctx->hflags |= MIPS_HFLAG_BDS32;
10059 out:
10060 tcg_temp_free_i32(t0);
10063 /* R6 CP1 Branches */
10064 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10065 int32_t ft, int32_t offset,
10066 int delayslot_size)
10068 target_ulong btarget;
10069 TCGv_i64 t0 = tcg_temp_new_i64();
10071 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10072 #ifdef MIPS_DEBUG_DISAS
10073 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10074 "\n", ctx->base.pc_next);
10075 #endif
10076 gen_reserved_instruction(ctx);
10077 goto out;
10080 gen_load_fpr64(ctx, t0, ft);
10081 tcg_gen_andi_i64(t0, t0, 1);
10083 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10085 switch (op) {
10086 case OPC_BC1EQZ:
10087 tcg_gen_xori_i64(t0, t0, 1);
10088 ctx->hflags |= MIPS_HFLAG_BC;
10089 break;
10090 case OPC_BC1NEZ:
10091 /* t0 already set */
10092 ctx->hflags |= MIPS_HFLAG_BC;
10093 break;
10094 default:
10095 MIPS_INVAL("cp1 cond branch");
10096 gen_reserved_instruction(ctx);
10097 goto out;
10100 tcg_gen_trunc_i64_tl(bcond, t0);
10102 ctx->btarget = btarget;
10104 switch (delayslot_size) {
10105 case 2:
10106 ctx->hflags |= MIPS_HFLAG_BDS16;
10107 break;
10108 case 4:
10109 ctx->hflags |= MIPS_HFLAG_BDS32;
10110 break;
10113 out:
10114 tcg_temp_free_i64(t0);
10117 /* Coprocessor 1 (FPU) */
10119 #define FOP(func, fmt) (((fmt) << 21) | (func))
10121 enum fopcode {
10122 OPC_ADD_S = FOP(0, FMT_S),
10123 OPC_SUB_S = FOP(1, FMT_S),
10124 OPC_MUL_S = FOP(2, FMT_S),
10125 OPC_DIV_S = FOP(3, FMT_S),
10126 OPC_SQRT_S = FOP(4, FMT_S),
10127 OPC_ABS_S = FOP(5, FMT_S),
10128 OPC_MOV_S = FOP(6, FMT_S),
10129 OPC_NEG_S = FOP(7, FMT_S),
10130 OPC_ROUND_L_S = FOP(8, FMT_S),
10131 OPC_TRUNC_L_S = FOP(9, FMT_S),
10132 OPC_CEIL_L_S = FOP(10, FMT_S),
10133 OPC_FLOOR_L_S = FOP(11, FMT_S),
10134 OPC_ROUND_W_S = FOP(12, FMT_S),
10135 OPC_TRUNC_W_S = FOP(13, FMT_S),
10136 OPC_CEIL_W_S = FOP(14, FMT_S),
10137 OPC_FLOOR_W_S = FOP(15, FMT_S),
10138 OPC_SEL_S = FOP(16, FMT_S),
10139 OPC_MOVCF_S = FOP(17, FMT_S),
10140 OPC_MOVZ_S = FOP(18, FMT_S),
10141 OPC_MOVN_S = FOP(19, FMT_S),
10142 OPC_SELEQZ_S = FOP(20, FMT_S),
10143 OPC_RECIP_S = FOP(21, FMT_S),
10144 OPC_RSQRT_S = FOP(22, FMT_S),
10145 OPC_SELNEZ_S = FOP(23, FMT_S),
10146 OPC_MADDF_S = FOP(24, FMT_S),
10147 OPC_MSUBF_S = FOP(25, FMT_S),
10148 OPC_RINT_S = FOP(26, FMT_S),
10149 OPC_CLASS_S = FOP(27, FMT_S),
10150 OPC_MIN_S = FOP(28, FMT_S),
10151 OPC_RECIP2_S = FOP(28, FMT_S),
10152 OPC_MINA_S = FOP(29, FMT_S),
10153 OPC_RECIP1_S = FOP(29, FMT_S),
10154 OPC_MAX_S = FOP(30, FMT_S),
10155 OPC_RSQRT1_S = FOP(30, FMT_S),
10156 OPC_MAXA_S = FOP(31, FMT_S),
10157 OPC_RSQRT2_S = FOP(31, FMT_S),
10158 OPC_CVT_D_S = FOP(33, FMT_S),
10159 OPC_CVT_W_S = FOP(36, FMT_S),
10160 OPC_CVT_L_S = FOP(37, FMT_S),
10161 OPC_CVT_PS_S = FOP(38, FMT_S),
10162 OPC_CMP_F_S = FOP(48, FMT_S),
10163 OPC_CMP_UN_S = FOP(49, FMT_S),
10164 OPC_CMP_EQ_S = FOP(50, FMT_S),
10165 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10166 OPC_CMP_OLT_S = FOP(52, FMT_S),
10167 OPC_CMP_ULT_S = FOP(53, FMT_S),
10168 OPC_CMP_OLE_S = FOP(54, FMT_S),
10169 OPC_CMP_ULE_S = FOP(55, FMT_S),
10170 OPC_CMP_SF_S = FOP(56, FMT_S),
10171 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10172 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10173 OPC_CMP_NGL_S = FOP(59, FMT_S),
10174 OPC_CMP_LT_S = FOP(60, FMT_S),
10175 OPC_CMP_NGE_S = FOP(61, FMT_S),
10176 OPC_CMP_LE_S = FOP(62, FMT_S),
10177 OPC_CMP_NGT_S = FOP(63, FMT_S),
10179 OPC_ADD_D = FOP(0, FMT_D),
10180 OPC_SUB_D = FOP(1, FMT_D),
10181 OPC_MUL_D = FOP(2, FMT_D),
10182 OPC_DIV_D = FOP(3, FMT_D),
10183 OPC_SQRT_D = FOP(4, FMT_D),
10184 OPC_ABS_D = FOP(5, FMT_D),
10185 OPC_MOV_D = FOP(6, FMT_D),
10186 OPC_NEG_D = FOP(7, FMT_D),
10187 OPC_ROUND_L_D = FOP(8, FMT_D),
10188 OPC_TRUNC_L_D = FOP(9, FMT_D),
10189 OPC_CEIL_L_D = FOP(10, FMT_D),
10190 OPC_FLOOR_L_D = FOP(11, FMT_D),
10191 OPC_ROUND_W_D = FOP(12, FMT_D),
10192 OPC_TRUNC_W_D = FOP(13, FMT_D),
10193 OPC_CEIL_W_D = FOP(14, FMT_D),
10194 OPC_FLOOR_W_D = FOP(15, FMT_D),
10195 OPC_SEL_D = FOP(16, FMT_D),
10196 OPC_MOVCF_D = FOP(17, FMT_D),
10197 OPC_MOVZ_D = FOP(18, FMT_D),
10198 OPC_MOVN_D = FOP(19, FMT_D),
10199 OPC_SELEQZ_D = FOP(20, FMT_D),
10200 OPC_RECIP_D = FOP(21, FMT_D),
10201 OPC_RSQRT_D = FOP(22, FMT_D),
10202 OPC_SELNEZ_D = FOP(23, FMT_D),
10203 OPC_MADDF_D = FOP(24, FMT_D),
10204 OPC_MSUBF_D = FOP(25, FMT_D),
10205 OPC_RINT_D = FOP(26, FMT_D),
10206 OPC_CLASS_D = FOP(27, FMT_D),
10207 OPC_MIN_D = FOP(28, FMT_D),
10208 OPC_RECIP2_D = FOP(28, FMT_D),
10209 OPC_MINA_D = FOP(29, FMT_D),
10210 OPC_RECIP1_D = FOP(29, FMT_D),
10211 OPC_MAX_D = FOP(30, FMT_D),
10212 OPC_RSQRT1_D = FOP(30, FMT_D),
10213 OPC_MAXA_D = FOP(31, FMT_D),
10214 OPC_RSQRT2_D = FOP(31, FMT_D),
10215 OPC_CVT_S_D = FOP(32, FMT_D),
10216 OPC_CVT_W_D = FOP(36, FMT_D),
10217 OPC_CVT_L_D = FOP(37, FMT_D),
10218 OPC_CMP_F_D = FOP(48, FMT_D),
10219 OPC_CMP_UN_D = FOP(49, FMT_D),
10220 OPC_CMP_EQ_D = FOP(50, FMT_D),
10221 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10222 OPC_CMP_OLT_D = FOP(52, FMT_D),
10223 OPC_CMP_ULT_D = FOP(53, FMT_D),
10224 OPC_CMP_OLE_D = FOP(54, FMT_D),
10225 OPC_CMP_ULE_D = FOP(55, FMT_D),
10226 OPC_CMP_SF_D = FOP(56, FMT_D),
10227 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10228 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10229 OPC_CMP_NGL_D = FOP(59, FMT_D),
10230 OPC_CMP_LT_D = FOP(60, FMT_D),
10231 OPC_CMP_NGE_D = FOP(61, FMT_D),
10232 OPC_CMP_LE_D = FOP(62, FMT_D),
10233 OPC_CMP_NGT_D = FOP(63, FMT_D),
10235 OPC_CVT_S_W = FOP(32, FMT_W),
10236 OPC_CVT_D_W = FOP(33, FMT_W),
10237 OPC_CVT_S_L = FOP(32, FMT_L),
10238 OPC_CVT_D_L = FOP(33, FMT_L),
10239 OPC_CVT_PS_PW = FOP(38, FMT_W),
10241 OPC_ADD_PS = FOP(0, FMT_PS),
10242 OPC_SUB_PS = FOP(1, FMT_PS),
10243 OPC_MUL_PS = FOP(2, FMT_PS),
10244 OPC_DIV_PS = FOP(3, FMT_PS),
10245 OPC_ABS_PS = FOP(5, FMT_PS),
10246 OPC_MOV_PS = FOP(6, FMT_PS),
10247 OPC_NEG_PS = FOP(7, FMT_PS),
10248 OPC_MOVCF_PS = FOP(17, FMT_PS),
10249 OPC_MOVZ_PS = FOP(18, FMT_PS),
10250 OPC_MOVN_PS = FOP(19, FMT_PS),
10251 OPC_ADDR_PS = FOP(24, FMT_PS),
10252 OPC_MULR_PS = FOP(26, FMT_PS),
10253 OPC_RECIP2_PS = FOP(28, FMT_PS),
10254 OPC_RECIP1_PS = FOP(29, FMT_PS),
10255 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10256 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10258 OPC_CVT_S_PU = FOP(32, FMT_PS),
10259 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10260 OPC_CVT_S_PL = FOP(40, FMT_PS),
10261 OPC_PLL_PS = FOP(44, FMT_PS),
10262 OPC_PLU_PS = FOP(45, FMT_PS),
10263 OPC_PUL_PS = FOP(46, FMT_PS),
10264 OPC_PUU_PS = FOP(47, FMT_PS),
10265 OPC_CMP_F_PS = FOP(48, FMT_PS),
10266 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10267 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10268 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10269 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10270 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10271 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10272 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10273 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10274 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10275 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10276 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10277 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10278 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10279 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10280 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
10283 enum r6_f_cmp_op {
10284 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10285 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10286 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10287 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10288 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10289 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10290 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10291 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10292 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10293 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10294 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10295 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10296 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10297 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10298 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10299 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10300 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10301 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10302 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10303 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10304 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10305 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10307 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10308 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10309 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10310 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10311 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10312 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10313 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10314 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10315 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10316 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10317 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10318 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10319 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10320 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10321 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10322 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10323 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10324 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10325 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10326 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10327 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10328 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10331 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
10333 TCGv t0 = tcg_temp_new();
10335 switch (opc) {
10336 case OPC_MFC1:
10338 TCGv_i32 fp0 = tcg_temp_new_i32();
10340 gen_load_fpr32(ctx, fp0, fs);
10341 tcg_gen_ext_i32_tl(t0, fp0);
10342 tcg_temp_free_i32(fp0);
10344 gen_store_gpr(t0, rt);
10345 break;
10346 case OPC_MTC1:
10347 gen_load_gpr(t0, rt);
10349 TCGv_i32 fp0 = tcg_temp_new_i32();
10351 tcg_gen_trunc_tl_i32(fp0, t0);
10352 gen_store_fpr32(ctx, fp0, fs);
10353 tcg_temp_free_i32(fp0);
10355 break;
10356 case OPC_CFC1:
10357 gen_helper_1e0i(cfc1, t0, fs);
10358 gen_store_gpr(t0, rt);
10359 break;
10360 case OPC_CTC1:
10361 gen_load_gpr(t0, rt);
10362 save_cpu_state(ctx, 0);
10364 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10366 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10367 tcg_temp_free_i32(fs_tmp);
10369 /* Stop translation as we may have changed hflags */
10370 ctx->base.is_jmp = DISAS_STOP;
10371 break;
10372 #if defined(TARGET_MIPS64)
10373 case OPC_DMFC1:
10374 gen_load_fpr64(ctx, t0, fs);
10375 gen_store_gpr(t0, rt);
10376 break;
10377 case OPC_DMTC1:
10378 gen_load_gpr(t0, rt);
10379 gen_store_fpr64(ctx, t0, fs);
10380 break;
10381 #endif
10382 case OPC_MFHC1:
10384 TCGv_i32 fp0 = tcg_temp_new_i32();
10386 gen_load_fpr32h(ctx, fp0, fs);
10387 tcg_gen_ext_i32_tl(t0, fp0);
10388 tcg_temp_free_i32(fp0);
10390 gen_store_gpr(t0, rt);
10391 break;
10392 case OPC_MTHC1:
10393 gen_load_gpr(t0, rt);
10395 TCGv_i32 fp0 = tcg_temp_new_i32();
10397 tcg_gen_trunc_tl_i32(fp0, t0);
10398 gen_store_fpr32h(ctx, fp0, fs);
10399 tcg_temp_free_i32(fp0);
10401 break;
10402 default:
10403 MIPS_INVAL("cp1 move");
10404 gen_reserved_instruction(ctx);
10405 goto out;
10408 out:
10409 tcg_temp_free(t0);
10412 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
10414 TCGLabel *l1;
10415 TCGCond cond;
10416 TCGv_i32 t0;
10418 if (rd == 0) {
10419 /* Treat as NOP. */
10420 return;
10423 if (tf) {
10424 cond = TCG_COND_EQ;
10425 } else {
10426 cond = TCG_COND_NE;
10429 l1 = gen_new_label();
10430 t0 = tcg_temp_new_i32();
10431 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10432 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10433 tcg_temp_free_i32(t0);
10434 gen_load_gpr(cpu_gpr[rd], rs);
10435 gen_set_label(l1);
10438 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10439 int tf)
10441 int cond;
10442 TCGv_i32 t0 = tcg_temp_new_i32();
10443 TCGLabel *l1 = gen_new_label();
10445 if (tf) {
10446 cond = TCG_COND_EQ;
10447 } else {
10448 cond = TCG_COND_NE;
10451 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10452 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10453 gen_load_fpr32(ctx, t0, fs);
10454 gen_store_fpr32(ctx, t0, fd);
10455 gen_set_label(l1);
10456 tcg_temp_free_i32(t0);
10459 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
10460 int tf)
10462 int cond;
10463 TCGv_i32 t0 = tcg_temp_new_i32();
10464 TCGv_i64 fp0;
10465 TCGLabel *l1 = gen_new_label();
10467 if (tf) {
10468 cond = TCG_COND_EQ;
10469 } else {
10470 cond = TCG_COND_NE;
10473 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10474 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10475 tcg_temp_free_i32(t0);
10476 fp0 = tcg_temp_new_i64();
10477 gen_load_fpr64(ctx, fp0, fs);
10478 gen_store_fpr64(ctx, fp0, fd);
10479 tcg_temp_free_i64(fp0);
10480 gen_set_label(l1);
10483 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10484 int cc, int tf)
10486 int cond;
10487 TCGv_i32 t0 = tcg_temp_new_i32();
10488 TCGLabel *l1 = gen_new_label();
10489 TCGLabel *l2 = gen_new_label();
10491 if (tf) {
10492 cond = TCG_COND_EQ;
10493 } else {
10494 cond = TCG_COND_NE;
10497 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10498 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10499 gen_load_fpr32(ctx, t0, fs);
10500 gen_store_fpr32(ctx, t0, fd);
10501 gen_set_label(l1);
10503 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
10504 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10505 gen_load_fpr32h(ctx, t0, fs);
10506 gen_store_fpr32h(ctx, t0, fd);
10507 tcg_temp_free_i32(t0);
10508 gen_set_label(l2);
10511 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10512 int fs)
10514 TCGv_i32 t1 = tcg_const_i32(0);
10515 TCGv_i32 fp0 = tcg_temp_new_i32();
10516 TCGv_i32 fp1 = tcg_temp_new_i32();
10517 TCGv_i32 fp2 = tcg_temp_new_i32();
10518 gen_load_fpr32(ctx, fp0, fd);
10519 gen_load_fpr32(ctx, fp1, ft);
10520 gen_load_fpr32(ctx, fp2, fs);
10522 switch (op1) {
10523 case OPC_SEL_S:
10524 tcg_gen_andi_i32(fp0, fp0, 1);
10525 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10526 break;
10527 case OPC_SELEQZ_S:
10528 tcg_gen_andi_i32(fp1, fp1, 1);
10529 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10530 break;
10531 case OPC_SELNEZ_S:
10532 tcg_gen_andi_i32(fp1, fp1, 1);
10533 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10534 break;
10535 default:
10536 MIPS_INVAL("gen_sel_s");
10537 gen_reserved_instruction(ctx);
10538 break;
10541 gen_store_fpr32(ctx, fp0, fd);
10542 tcg_temp_free_i32(fp2);
10543 tcg_temp_free_i32(fp1);
10544 tcg_temp_free_i32(fp0);
10545 tcg_temp_free_i32(t1);
10548 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10549 int fs)
10551 TCGv_i64 t1 = tcg_const_i64(0);
10552 TCGv_i64 fp0 = tcg_temp_new_i64();
10553 TCGv_i64 fp1 = tcg_temp_new_i64();
10554 TCGv_i64 fp2 = tcg_temp_new_i64();
10555 gen_load_fpr64(ctx, fp0, fd);
10556 gen_load_fpr64(ctx, fp1, ft);
10557 gen_load_fpr64(ctx, fp2, fs);
10559 switch (op1) {
10560 case OPC_SEL_D:
10561 tcg_gen_andi_i64(fp0, fp0, 1);
10562 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10563 break;
10564 case OPC_SELEQZ_D:
10565 tcg_gen_andi_i64(fp1, fp1, 1);
10566 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10567 break;
10568 case OPC_SELNEZ_D:
10569 tcg_gen_andi_i64(fp1, fp1, 1);
10570 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10571 break;
10572 default:
10573 MIPS_INVAL("gen_sel_d");
10574 gen_reserved_instruction(ctx);
10575 break;
10578 gen_store_fpr64(ctx, fp0, fd);
10579 tcg_temp_free_i64(fp2);
10580 tcg_temp_free_i64(fp1);
10581 tcg_temp_free_i64(fp0);
10582 tcg_temp_free_i64(t1);
10585 static void gen_farith(DisasContext *ctx, enum fopcode op1,
10586 int ft, int fs, int fd, int cc)
10588 uint32_t func = ctx->opcode & 0x3f;
10589 switch (op1) {
10590 case OPC_ADD_S:
10592 TCGv_i32 fp0 = tcg_temp_new_i32();
10593 TCGv_i32 fp1 = tcg_temp_new_i32();
10595 gen_load_fpr32(ctx, fp0, fs);
10596 gen_load_fpr32(ctx, fp1, ft);
10597 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10598 tcg_temp_free_i32(fp1);
10599 gen_store_fpr32(ctx, fp0, fd);
10600 tcg_temp_free_i32(fp0);
10602 break;
10603 case OPC_SUB_S:
10605 TCGv_i32 fp0 = tcg_temp_new_i32();
10606 TCGv_i32 fp1 = tcg_temp_new_i32();
10608 gen_load_fpr32(ctx, fp0, fs);
10609 gen_load_fpr32(ctx, fp1, ft);
10610 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10611 tcg_temp_free_i32(fp1);
10612 gen_store_fpr32(ctx, fp0, fd);
10613 tcg_temp_free_i32(fp0);
10615 break;
10616 case OPC_MUL_S:
10618 TCGv_i32 fp0 = tcg_temp_new_i32();
10619 TCGv_i32 fp1 = tcg_temp_new_i32();
10621 gen_load_fpr32(ctx, fp0, fs);
10622 gen_load_fpr32(ctx, fp1, ft);
10623 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10624 tcg_temp_free_i32(fp1);
10625 gen_store_fpr32(ctx, fp0, fd);
10626 tcg_temp_free_i32(fp0);
10628 break;
10629 case OPC_DIV_S:
10631 TCGv_i32 fp0 = tcg_temp_new_i32();
10632 TCGv_i32 fp1 = tcg_temp_new_i32();
10634 gen_load_fpr32(ctx, fp0, fs);
10635 gen_load_fpr32(ctx, fp1, ft);
10636 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10637 tcg_temp_free_i32(fp1);
10638 gen_store_fpr32(ctx, fp0, fd);
10639 tcg_temp_free_i32(fp0);
10641 break;
10642 case OPC_SQRT_S:
10644 TCGv_i32 fp0 = tcg_temp_new_i32();
10646 gen_load_fpr32(ctx, fp0, fs);
10647 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10648 gen_store_fpr32(ctx, fp0, fd);
10649 tcg_temp_free_i32(fp0);
10651 break;
10652 case OPC_ABS_S:
10654 TCGv_i32 fp0 = tcg_temp_new_i32();
10656 gen_load_fpr32(ctx, fp0, fs);
10657 if (ctx->abs2008) {
10658 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10659 } else {
10660 gen_helper_float_abs_s(fp0, fp0);
10662 gen_store_fpr32(ctx, fp0, fd);
10663 tcg_temp_free_i32(fp0);
10665 break;
10666 case OPC_MOV_S:
10668 TCGv_i32 fp0 = tcg_temp_new_i32();
10670 gen_load_fpr32(ctx, fp0, fs);
10671 gen_store_fpr32(ctx, fp0, fd);
10672 tcg_temp_free_i32(fp0);
10674 break;
10675 case OPC_NEG_S:
10677 TCGv_i32 fp0 = tcg_temp_new_i32();
10679 gen_load_fpr32(ctx, fp0, fs);
10680 if (ctx->abs2008) {
10681 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10682 } else {
10683 gen_helper_float_chs_s(fp0, fp0);
10685 gen_store_fpr32(ctx, fp0, fd);
10686 tcg_temp_free_i32(fp0);
10688 break;
10689 case OPC_ROUND_L_S:
10690 check_cp1_64bitmode(ctx);
10692 TCGv_i32 fp32 = tcg_temp_new_i32();
10693 TCGv_i64 fp64 = tcg_temp_new_i64();
10695 gen_load_fpr32(ctx, fp32, fs);
10696 if (ctx->nan2008) {
10697 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10698 } else {
10699 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10701 tcg_temp_free_i32(fp32);
10702 gen_store_fpr64(ctx, fp64, fd);
10703 tcg_temp_free_i64(fp64);
10705 break;
10706 case OPC_TRUNC_L_S:
10707 check_cp1_64bitmode(ctx);
10709 TCGv_i32 fp32 = tcg_temp_new_i32();
10710 TCGv_i64 fp64 = tcg_temp_new_i64();
10712 gen_load_fpr32(ctx, fp32, fs);
10713 if (ctx->nan2008) {
10714 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10715 } else {
10716 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10718 tcg_temp_free_i32(fp32);
10719 gen_store_fpr64(ctx, fp64, fd);
10720 tcg_temp_free_i64(fp64);
10722 break;
10723 case OPC_CEIL_L_S:
10724 check_cp1_64bitmode(ctx);
10726 TCGv_i32 fp32 = tcg_temp_new_i32();
10727 TCGv_i64 fp64 = tcg_temp_new_i64();
10729 gen_load_fpr32(ctx, fp32, fs);
10730 if (ctx->nan2008) {
10731 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10732 } else {
10733 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10735 tcg_temp_free_i32(fp32);
10736 gen_store_fpr64(ctx, fp64, fd);
10737 tcg_temp_free_i64(fp64);
10739 break;
10740 case OPC_FLOOR_L_S:
10741 check_cp1_64bitmode(ctx);
10743 TCGv_i32 fp32 = tcg_temp_new_i32();
10744 TCGv_i64 fp64 = tcg_temp_new_i64();
10746 gen_load_fpr32(ctx, fp32, fs);
10747 if (ctx->nan2008) {
10748 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10749 } else {
10750 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10752 tcg_temp_free_i32(fp32);
10753 gen_store_fpr64(ctx, fp64, fd);
10754 tcg_temp_free_i64(fp64);
10756 break;
10757 case OPC_ROUND_W_S:
10759 TCGv_i32 fp0 = tcg_temp_new_i32();
10761 gen_load_fpr32(ctx, fp0, fs);
10762 if (ctx->nan2008) {
10763 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10764 } else {
10765 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10767 gen_store_fpr32(ctx, fp0, fd);
10768 tcg_temp_free_i32(fp0);
10770 break;
10771 case OPC_TRUNC_W_S:
10773 TCGv_i32 fp0 = tcg_temp_new_i32();
10775 gen_load_fpr32(ctx, fp0, fs);
10776 if (ctx->nan2008) {
10777 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10778 } else {
10779 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10781 gen_store_fpr32(ctx, fp0, fd);
10782 tcg_temp_free_i32(fp0);
10784 break;
10785 case OPC_CEIL_W_S:
10787 TCGv_i32 fp0 = tcg_temp_new_i32();
10789 gen_load_fpr32(ctx, fp0, fs);
10790 if (ctx->nan2008) {
10791 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10792 } else {
10793 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10795 gen_store_fpr32(ctx, fp0, fd);
10796 tcg_temp_free_i32(fp0);
10798 break;
10799 case OPC_FLOOR_W_S:
10801 TCGv_i32 fp0 = tcg_temp_new_i32();
10803 gen_load_fpr32(ctx, fp0, fs);
10804 if (ctx->nan2008) {
10805 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10806 } else {
10807 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10809 gen_store_fpr32(ctx, fp0, fd);
10810 tcg_temp_free_i32(fp0);
10812 break;
10813 case OPC_SEL_S:
10814 check_insn(ctx, ISA_MIPS_R6);
10815 gen_sel_s(ctx, op1, fd, ft, fs);
10816 break;
10817 case OPC_SELEQZ_S:
10818 check_insn(ctx, ISA_MIPS_R6);
10819 gen_sel_s(ctx, op1, fd, ft, fs);
10820 break;
10821 case OPC_SELNEZ_S:
10822 check_insn(ctx, ISA_MIPS_R6);
10823 gen_sel_s(ctx, op1, fd, ft, fs);
10824 break;
10825 case OPC_MOVCF_S:
10826 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10827 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10828 break;
10829 case OPC_MOVZ_S:
10830 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10832 TCGLabel *l1 = gen_new_label();
10833 TCGv_i32 fp0;
10835 if (ft != 0) {
10836 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10838 fp0 = tcg_temp_new_i32();
10839 gen_load_fpr32(ctx, fp0, fs);
10840 gen_store_fpr32(ctx, fp0, fd);
10841 tcg_temp_free_i32(fp0);
10842 gen_set_label(l1);
10844 break;
10845 case OPC_MOVN_S:
10846 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10848 TCGLabel *l1 = gen_new_label();
10849 TCGv_i32 fp0;
10851 if (ft != 0) {
10852 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10853 fp0 = tcg_temp_new_i32();
10854 gen_load_fpr32(ctx, fp0, fs);
10855 gen_store_fpr32(ctx, fp0, fd);
10856 tcg_temp_free_i32(fp0);
10857 gen_set_label(l1);
10860 break;
10861 case OPC_RECIP_S:
10863 TCGv_i32 fp0 = tcg_temp_new_i32();
10865 gen_load_fpr32(ctx, fp0, fs);
10866 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10867 gen_store_fpr32(ctx, fp0, fd);
10868 tcg_temp_free_i32(fp0);
10870 break;
10871 case OPC_RSQRT_S:
10873 TCGv_i32 fp0 = tcg_temp_new_i32();
10875 gen_load_fpr32(ctx, fp0, fs);
10876 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10877 gen_store_fpr32(ctx, fp0, fd);
10878 tcg_temp_free_i32(fp0);
10880 break;
10881 case OPC_MADDF_S:
10882 check_insn(ctx, ISA_MIPS_R6);
10884 TCGv_i32 fp0 = tcg_temp_new_i32();
10885 TCGv_i32 fp1 = tcg_temp_new_i32();
10886 TCGv_i32 fp2 = tcg_temp_new_i32();
10887 gen_load_fpr32(ctx, fp0, fs);
10888 gen_load_fpr32(ctx, fp1, ft);
10889 gen_load_fpr32(ctx, fp2, fd);
10890 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10891 gen_store_fpr32(ctx, fp2, fd);
10892 tcg_temp_free_i32(fp2);
10893 tcg_temp_free_i32(fp1);
10894 tcg_temp_free_i32(fp0);
10896 break;
10897 case OPC_MSUBF_S:
10898 check_insn(ctx, ISA_MIPS_R6);
10900 TCGv_i32 fp0 = tcg_temp_new_i32();
10901 TCGv_i32 fp1 = tcg_temp_new_i32();
10902 TCGv_i32 fp2 = tcg_temp_new_i32();
10903 gen_load_fpr32(ctx, fp0, fs);
10904 gen_load_fpr32(ctx, fp1, ft);
10905 gen_load_fpr32(ctx, fp2, fd);
10906 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10907 gen_store_fpr32(ctx, fp2, fd);
10908 tcg_temp_free_i32(fp2);
10909 tcg_temp_free_i32(fp1);
10910 tcg_temp_free_i32(fp0);
10912 break;
10913 case OPC_RINT_S:
10914 check_insn(ctx, ISA_MIPS_R6);
10916 TCGv_i32 fp0 = tcg_temp_new_i32();
10917 gen_load_fpr32(ctx, fp0, fs);
10918 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10919 gen_store_fpr32(ctx, fp0, fd);
10920 tcg_temp_free_i32(fp0);
10922 break;
10923 case OPC_CLASS_S:
10924 check_insn(ctx, ISA_MIPS_R6);
10926 TCGv_i32 fp0 = tcg_temp_new_i32();
10927 gen_load_fpr32(ctx, fp0, fs);
10928 gen_helper_float_class_s(fp0, cpu_env, fp0);
10929 gen_store_fpr32(ctx, fp0, fd);
10930 tcg_temp_free_i32(fp0);
10932 break;
10933 case OPC_MIN_S: /* OPC_RECIP2_S */
10934 if (ctx->insn_flags & ISA_MIPS_R6) {
10935 /* OPC_MIN_S */
10936 TCGv_i32 fp0 = tcg_temp_new_i32();
10937 TCGv_i32 fp1 = tcg_temp_new_i32();
10938 TCGv_i32 fp2 = tcg_temp_new_i32();
10939 gen_load_fpr32(ctx, fp0, fs);
10940 gen_load_fpr32(ctx, fp1, ft);
10941 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10942 gen_store_fpr32(ctx, fp2, fd);
10943 tcg_temp_free_i32(fp2);
10944 tcg_temp_free_i32(fp1);
10945 tcg_temp_free_i32(fp0);
10946 } else {
10947 /* OPC_RECIP2_S */
10948 check_cp1_64bitmode(ctx);
10950 TCGv_i32 fp0 = tcg_temp_new_i32();
10951 TCGv_i32 fp1 = tcg_temp_new_i32();
10953 gen_load_fpr32(ctx, fp0, fs);
10954 gen_load_fpr32(ctx, fp1, ft);
10955 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10956 tcg_temp_free_i32(fp1);
10957 gen_store_fpr32(ctx, fp0, fd);
10958 tcg_temp_free_i32(fp0);
10961 break;
10962 case OPC_MINA_S: /* OPC_RECIP1_S */
10963 if (ctx->insn_flags & ISA_MIPS_R6) {
10964 /* OPC_MINA_S */
10965 TCGv_i32 fp0 = tcg_temp_new_i32();
10966 TCGv_i32 fp1 = tcg_temp_new_i32();
10967 TCGv_i32 fp2 = tcg_temp_new_i32();
10968 gen_load_fpr32(ctx, fp0, fs);
10969 gen_load_fpr32(ctx, fp1, ft);
10970 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10971 gen_store_fpr32(ctx, fp2, fd);
10972 tcg_temp_free_i32(fp2);
10973 tcg_temp_free_i32(fp1);
10974 tcg_temp_free_i32(fp0);
10975 } else {
10976 /* OPC_RECIP1_S */
10977 check_cp1_64bitmode(ctx);
10979 TCGv_i32 fp0 = tcg_temp_new_i32();
10981 gen_load_fpr32(ctx, fp0, fs);
10982 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10983 gen_store_fpr32(ctx, fp0, fd);
10984 tcg_temp_free_i32(fp0);
10987 break;
10988 case OPC_MAX_S: /* OPC_RSQRT1_S */
10989 if (ctx->insn_flags & ISA_MIPS_R6) {
10990 /* OPC_MAX_S */
10991 TCGv_i32 fp0 = tcg_temp_new_i32();
10992 TCGv_i32 fp1 = tcg_temp_new_i32();
10993 gen_load_fpr32(ctx, fp0, fs);
10994 gen_load_fpr32(ctx, fp1, ft);
10995 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10996 gen_store_fpr32(ctx, fp1, fd);
10997 tcg_temp_free_i32(fp1);
10998 tcg_temp_free_i32(fp0);
10999 } else {
11000 /* OPC_RSQRT1_S */
11001 check_cp1_64bitmode(ctx);
11003 TCGv_i32 fp0 = tcg_temp_new_i32();
11005 gen_load_fpr32(ctx, fp0, fs);
11006 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11007 gen_store_fpr32(ctx, fp0, fd);
11008 tcg_temp_free_i32(fp0);
11011 break;
11012 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11013 if (ctx->insn_flags & ISA_MIPS_R6) {
11014 /* OPC_MAXA_S */
11015 TCGv_i32 fp0 = tcg_temp_new_i32();
11016 TCGv_i32 fp1 = tcg_temp_new_i32();
11017 gen_load_fpr32(ctx, fp0, fs);
11018 gen_load_fpr32(ctx, fp1, ft);
11019 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11020 gen_store_fpr32(ctx, fp1, fd);
11021 tcg_temp_free_i32(fp1);
11022 tcg_temp_free_i32(fp0);
11023 } else {
11024 /* OPC_RSQRT2_S */
11025 check_cp1_64bitmode(ctx);
11027 TCGv_i32 fp0 = tcg_temp_new_i32();
11028 TCGv_i32 fp1 = tcg_temp_new_i32();
11030 gen_load_fpr32(ctx, fp0, fs);
11031 gen_load_fpr32(ctx, fp1, ft);
11032 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11033 tcg_temp_free_i32(fp1);
11034 gen_store_fpr32(ctx, fp0, fd);
11035 tcg_temp_free_i32(fp0);
11038 break;
11039 case OPC_CVT_D_S:
11040 check_cp1_registers(ctx, fd);
11042 TCGv_i32 fp32 = tcg_temp_new_i32();
11043 TCGv_i64 fp64 = tcg_temp_new_i64();
11045 gen_load_fpr32(ctx, fp32, fs);
11046 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11047 tcg_temp_free_i32(fp32);
11048 gen_store_fpr64(ctx, fp64, fd);
11049 tcg_temp_free_i64(fp64);
11051 break;
11052 case OPC_CVT_W_S:
11054 TCGv_i32 fp0 = tcg_temp_new_i32();
11056 gen_load_fpr32(ctx, fp0, fs);
11057 if (ctx->nan2008) {
11058 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11059 } else {
11060 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11062 gen_store_fpr32(ctx, fp0, fd);
11063 tcg_temp_free_i32(fp0);
11065 break;
11066 case OPC_CVT_L_S:
11067 check_cp1_64bitmode(ctx);
11069 TCGv_i32 fp32 = tcg_temp_new_i32();
11070 TCGv_i64 fp64 = tcg_temp_new_i64();
11072 gen_load_fpr32(ctx, fp32, fs);
11073 if (ctx->nan2008) {
11074 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11075 } else {
11076 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11078 tcg_temp_free_i32(fp32);
11079 gen_store_fpr64(ctx, fp64, fd);
11080 tcg_temp_free_i64(fp64);
11082 break;
11083 case OPC_CVT_PS_S:
11084 check_ps(ctx);
11086 TCGv_i64 fp64 = tcg_temp_new_i64();
11087 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11088 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11090 gen_load_fpr32(ctx, fp32_0, fs);
11091 gen_load_fpr32(ctx, fp32_1, ft);
11092 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11093 tcg_temp_free_i32(fp32_1);
11094 tcg_temp_free_i32(fp32_0);
11095 gen_store_fpr64(ctx, fp64, fd);
11096 tcg_temp_free_i64(fp64);
11098 break;
11099 case OPC_CMP_F_S:
11100 case OPC_CMP_UN_S:
11101 case OPC_CMP_EQ_S:
11102 case OPC_CMP_UEQ_S:
11103 case OPC_CMP_OLT_S:
11104 case OPC_CMP_ULT_S:
11105 case OPC_CMP_OLE_S:
11106 case OPC_CMP_ULE_S:
11107 case OPC_CMP_SF_S:
11108 case OPC_CMP_NGLE_S:
11109 case OPC_CMP_SEQ_S:
11110 case OPC_CMP_NGL_S:
11111 case OPC_CMP_LT_S:
11112 case OPC_CMP_NGE_S:
11113 case OPC_CMP_LE_S:
11114 case OPC_CMP_NGT_S:
11115 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11116 if (ctx->opcode & (1 << 6)) {
11117 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
11118 } else {
11119 gen_cmp_s(ctx, func - 48, ft, fs, cc);
11121 break;
11122 case OPC_ADD_D:
11123 check_cp1_registers(ctx, fs | ft | fd);
11125 TCGv_i64 fp0 = tcg_temp_new_i64();
11126 TCGv_i64 fp1 = tcg_temp_new_i64();
11128 gen_load_fpr64(ctx, fp0, fs);
11129 gen_load_fpr64(ctx, fp1, ft);
11130 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11131 tcg_temp_free_i64(fp1);
11132 gen_store_fpr64(ctx, fp0, fd);
11133 tcg_temp_free_i64(fp0);
11135 break;
11136 case OPC_SUB_D:
11137 check_cp1_registers(ctx, fs | ft | fd);
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_sub_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);
11149 break;
11150 case OPC_MUL_D:
11151 check_cp1_registers(ctx, fs | ft | fd);
11153 TCGv_i64 fp0 = tcg_temp_new_i64();
11154 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_mul_d(fp0, cpu_env, fp0, fp1);
11159 tcg_temp_free_i64(fp1);
11160 gen_store_fpr64(ctx, fp0, fd);
11161 tcg_temp_free_i64(fp0);
11163 break;
11164 case OPC_DIV_D:
11165 check_cp1_registers(ctx, fs | ft | fd);
11167 TCGv_i64 fp0 = tcg_temp_new_i64();
11168 TCGv_i64 fp1 = tcg_temp_new_i64();
11170 gen_load_fpr64(ctx, fp0, fs);
11171 gen_load_fpr64(ctx, fp1, ft);
11172 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11173 tcg_temp_free_i64(fp1);
11174 gen_store_fpr64(ctx, fp0, fd);
11175 tcg_temp_free_i64(fp0);
11177 break;
11178 case OPC_SQRT_D:
11179 check_cp1_registers(ctx, fs | fd);
11181 TCGv_i64 fp0 = tcg_temp_new_i64();
11183 gen_load_fpr64(ctx, fp0, fs);
11184 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11185 gen_store_fpr64(ctx, fp0, fd);
11186 tcg_temp_free_i64(fp0);
11188 break;
11189 case OPC_ABS_D:
11190 check_cp1_registers(ctx, fs | fd);
11192 TCGv_i64 fp0 = tcg_temp_new_i64();
11194 gen_load_fpr64(ctx, fp0, fs);
11195 if (ctx->abs2008) {
11196 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11197 } else {
11198 gen_helper_float_abs_d(fp0, fp0);
11200 gen_store_fpr64(ctx, fp0, fd);
11201 tcg_temp_free_i64(fp0);
11203 break;
11204 case OPC_MOV_D:
11205 check_cp1_registers(ctx, fs | fd);
11207 TCGv_i64 fp0 = tcg_temp_new_i64();
11209 gen_load_fpr64(ctx, fp0, fs);
11210 gen_store_fpr64(ctx, fp0, fd);
11211 tcg_temp_free_i64(fp0);
11213 break;
11214 case OPC_NEG_D:
11215 check_cp1_registers(ctx, fs | fd);
11217 TCGv_i64 fp0 = tcg_temp_new_i64();
11219 gen_load_fpr64(ctx, fp0, fs);
11220 if (ctx->abs2008) {
11221 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11222 } else {
11223 gen_helper_float_chs_d(fp0, fp0);
11225 gen_store_fpr64(ctx, fp0, fd);
11226 tcg_temp_free_i64(fp0);
11228 break;
11229 case OPC_ROUND_L_D:
11230 check_cp1_64bitmode(ctx);
11232 TCGv_i64 fp0 = tcg_temp_new_i64();
11234 gen_load_fpr64(ctx, fp0, fs);
11235 if (ctx->nan2008) {
11236 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11237 } else {
11238 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11240 gen_store_fpr64(ctx, fp0, fd);
11241 tcg_temp_free_i64(fp0);
11243 break;
11244 case OPC_TRUNC_L_D:
11245 check_cp1_64bitmode(ctx);
11247 TCGv_i64 fp0 = tcg_temp_new_i64();
11249 gen_load_fpr64(ctx, fp0, fs);
11250 if (ctx->nan2008) {
11251 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11252 } else {
11253 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11255 gen_store_fpr64(ctx, fp0, fd);
11256 tcg_temp_free_i64(fp0);
11258 break;
11259 case OPC_CEIL_L_D:
11260 check_cp1_64bitmode(ctx);
11262 TCGv_i64 fp0 = tcg_temp_new_i64();
11264 gen_load_fpr64(ctx, fp0, fs);
11265 if (ctx->nan2008) {
11266 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11267 } else {
11268 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11270 gen_store_fpr64(ctx, fp0, fd);
11271 tcg_temp_free_i64(fp0);
11273 break;
11274 case OPC_FLOOR_L_D:
11275 check_cp1_64bitmode(ctx);
11277 TCGv_i64 fp0 = tcg_temp_new_i64();
11279 gen_load_fpr64(ctx, fp0, fs);
11280 if (ctx->nan2008) {
11281 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11282 } else {
11283 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11285 gen_store_fpr64(ctx, fp0, fd);
11286 tcg_temp_free_i64(fp0);
11288 break;
11289 case OPC_ROUND_W_D:
11290 check_cp1_registers(ctx, fs);
11292 TCGv_i32 fp32 = tcg_temp_new_i32();
11293 TCGv_i64 fp64 = tcg_temp_new_i64();
11295 gen_load_fpr64(ctx, fp64, fs);
11296 if (ctx->nan2008) {
11297 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11298 } else {
11299 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11301 tcg_temp_free_i64(fp64);
11302 gen_store_fpr32(ctx, fp32, fd);
11303 tcg_temp_free_i32(fp32);
11305 break;
11306 case OPC_TRUNC_W_D:
11307 check_cp1_registers(ctx, fs);
11309 TCGv_i32 fp32 = tcg_temp_new_i32();
11310 TCGv_i64 fp64 = tcg_temp_new_i64();
11312 gen_load_fpr64(ctx, fp64, fs);
11313 if (ctx->nan2008) {
11314 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11315 } else {
11316 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11318 tcg_temp_free_i64(fp64);
11319 gen_store_fpr32(ctx, fp32, fd);
11320 tcg_temp_free_i32(fp32);
11322 break;
11323 case OPC_CEIL_W_D:
11324 check_cp1_registers(ctx, fs);
11326 TCGv_i32 fp32 = tcg_temp_new_i32();
11327 TCGv_i64 fp64 = tcg_temp_new_i64();
11329 gen_load_fpr64(ctx, fp64, fs);
11330 if (ctx->nan2008) {
11331 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11332 } else {
11333 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11335 tcg_temp_free_i64(fp64);
11336 gen_store_fpr32(ctx, fp32, fd);
11337 tcg_temp_free_i32(fp32);
11339 break;
11340 case OPC_FLOOR_W_D:
11341 check_cp1_registers(ctx, fs);
11343 TCGv_i32 fp32 = tcg_temp_new_i32();
11344 TCGv_i64 fp64 = tcg_temp_new_i64();
11346 gen_load_fpr64(ctx, fp64, fs);
11347 if (ctx->nan2008) {
11348 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11349 } else {
11350 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11352 tcg_temp_free_i64(fp64);
11353 gen_store_fpr32(ctx, fp32, fd);
11354 tcg_temp_free_i32(fp32);
11356 break;
11357 case OPC_SEL_D:
11358 check_insn(ctx, ISA_MIPS_R6);
11359 gen_sel_d(ctx, op1, fd, ft, fs);
11360 break;
11361 case OPC_SELEQZ_D:
11362 check_insn(ctx, ISA_MIPS_R6);
11363 gen_sel_d(ctx, op1, fd, ft, fs);
11364 break;
11365 case OPC_SELNEZ_D:
11366 check_insn(ctx, ISA_MIPS_R6);
11367 gen_sel_d(ctx, op1, fd, ft, fs);
11368 break;
11369 case OPC_MOVCF_D:
11370 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11371 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11372 break;
11373 case OPC_MOVZ_D:
11374 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11376 TCGLabel *l1 = gen_new_label();
11377 TCGv_i64 fp0;
11379 if (ft != 0) {
11380 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11382 fp0 = tcg_temp_new_i64();
11383 gen_load_fpr64(ctx, fp0, fs);
11384 gen_store_fpr64(ctx, fp0, fd);
11385 tcg_temp_free_i64(fp0);
11386 gen_set_label(l1);
11388 break;
11389 case OPC_MOVN_D:
11390 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11392 TCGLabel *l1 = gen_new_label();
11393 TCGv_i64 fp0;
11395 if (ft != 0) {
11396 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11397 fp0 = tcg_temp_new_i64();
11398 gen_load_fpr64(ctx, fp0, fs);
11399 gen_store_fpr64(ctx, fp0, fd);
11400 tcg_temp_free_i64(fp0);
11401 gen_set_label(l1);
11404 break;
11405 case OPC_RECIP_D:
11406 check_cp1_registers(ctx, fs | fd);
11408 TCGv_i64 fp0 = tcg_temp_new_i64();
11410 gen_load_fpr64(ctx, fp0, fs);
11411 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11412 gen_store_fpr64(ctx, fp0, fd);
11413 tcg_temp_free_i64(fp0);
11415 break;
11416 case OPC_RSQRT_D:
11417 check_cp1_registers(ctx, fs | fd);
11419 TCGv_i64 fp0 = tcg_temp_new_i64();
11421 gen_load_fpr64(ctx, fp0, fs);
11422 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11423 gen_store_fpr64(ctx, fp0, fd);
11424 tcg_temp_free_i64(fp0);
11426 break;
11427 case OPC_MADDF_D:
11428 check_insn(ctx, ISA_MIPS_R6);
11430 TCGv_i64 fp0 = tcg_temp_new_i64();
11431 TCGv_i64 fp1 = tcg_temp_new_i64();
11432 TCGv_i64 fp2 = tcg_temp_new_i64();
11433 gen_load_fpr64(ctx, fp0, fs);
11434 gen_load_fpr64(ctx, fp1, ft);
11435 gen_load_fpr64(ctx, fp2, fd);
11436 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11437 gen_store_fpr64(ctx, fp2, fd);
11438 tcg_temp_free_i64(fp2);
11439 tcg_temp_free_i64(fp1);
11440 tcg_temp_free_i64(fp0);
11442 break;
11443 case OPC_MSUBF_D:
11444 check_insn(ctx, ISA_MIPS_R6);
11446 TCGv_i64 fp0 = tcg_temp_new_i64();
11447 TCGv_i64 fp1 = tcg_temp_new_i64();
11448 TCGv_i64 fp2 = tcg_temp_new_i64();
11449 gen_load_fpr64(ctx, fp0, fs);
11450 gen_load_fpr64(ctx, fp1, ft);
11451 gen_load_fpr64(ctx, fp2, fd);
11452 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11453 gen_store_fpr64(ctx, fp2, fd);
11454 tcg_temp_free_i64(fp2);
11455 tcg_temp_free_i64(fp1);
11456 tcg_temp_free_i64(fp0);
11458 break;
11459 case OPC_RINT_D:
11460 check_insn(ctx, ISA_MIPS_R6);
11462 TCGv_i64 fp0 = tcg_temp_new_i64();
11463 gen_load_fpr64(ctx, fp0, fs);
11464 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11465 gen_store_fpr64(ctx, fp0, fd);
11466 tcg_temp_free_i64(fp0);
11468 break;
11469 case OPC_CLASS_D:
11470 check_insn(ctx, ISA_MIPS_R6);
11472 TCGv_i64 fp0 = tcg_temp_new_i64();
11473 gen_load_fpr64(ctx, fp0, fs);
11474 gen_helper_float_class_d(fp0, cpu_env, fp0);
11475 gen_store_fpr64(ctx, fp0, fd);
11476 tcg_temp_free_i64(fp0);
11478 break;
11479 case OPC_MIN_D: /* OPC_RECIP2_D */
11480 if (ctx->insn_flags & ISA_MIPS_R6) {
11481 /* OPC_MIN_D */
11482 TCGv_i64 fp0 = tcg_temp_new_i64();
11483 TCGv_i64 fp1 = tcg_temp_new_i64();
11484 gen_load_fpr64(ctx, fp0, fs);
11485 gen_load_fpr64(ctx, fp1, ft);
11486 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11487 gen_store_fpr64(ctx, fp1, fd);
11488 tcg_temp_free_i64(fp1);
11489 tcg_temp_free_i64(fp0);
11490 } else {
11491 /* OPC_RECIP2_D */
11492 check_cp1_64bitmode(ctx);
11494 TCGv_i64 fp0 = tcg_temp_new_i64();
11495 TCGv_i64 fp1 = tcg_temp_new_i64();
11497 gen_load_fpr64(ctx, fp0, fs);
11498 gen_load_fpr64(ctx, fp1, ft);
11499 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11500 tcg_temp_free_i64(fp1);
11501 gen_store_fpr64(ctx, fp0, fd);
11502 tcg_temp_free_i64(fp0);
11505 break;
11506 case OPC_MINA_D: /* OPC_RECIP1_D */
11507 if (ctx->insn_flags & ISA_MIPS_R6) {
11508 /* OPC_MINA_D */
11509 TCGv_i64 fp0 = tcg_temp_new_i64();
11510 TCGv_i64 fp1 = tcg_temp_new_i64();
11511 gen_load_fpr64(ctx, fp0, fs);
11512 gen_load_fpr64(ctx, fp1, ft);
11513 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11514 gen_store_fpr64(ctx, fp1, fd);
11515 tcg_temp_free_i64(fp1);
11516 tcg_temp_free_i64(fp0);
11517 } else {
11518 /* OPC_RECIP1_D */
11519 check_cp1_64bitmode(ctx);
11521 TCGv_i64 fp0 = tcg_temp_new_i64();
11523 gen_load_fpr64(ctx, fp0, fs);
11524 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11525 gen_store_fpr64(ctx, fp0, fd);
11526 tcg_temp_free_i64(fp0);
11529 break;
11530 case OPC_MAX_D: /* OPC_RSQRT1_D */
11531 if (ctx->insn_flags & ISA_MIPS_R6) {
11532 /* OPC_MAX_D */
11533 TCGv_i64 fp0 = tcg_temp_new_i64();
11534 TCGv_i64 fp1 = tcg_temp_new_i64();
11535 gen_load_fpr64(ctx, fp0, fs);
11536 gen_load_fpr64(ctx, fp1, ft);
11537 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11538 gen_store_fpr64(ctx, fp1, fd);
11539 tcg_temp_free_i64(fp1);
11540 tcg_temp_free_i64(fp0);
11541 } else {
11542 /* OPC_RSQRT1_D */
11543 check_cp1_64bitmode(ctx);
11545 TCGv_i64 fp0 = tcg_temp_new_i64();
11547 gen_load_fpr64(ctx, fp0, fs);
11548 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11549 gen_store_fpr64(ctx, fp0, fd);
11550 tcg_temp_free_i64(fp0);
11553 break;
11554 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11555 if (ctx->insn_flags & ISA_MIPS_R6) {
11556 /* OPC_MAXA_D */
11557 TCGv_i64 fp0 = tcg_temp_new_i64();
11558 TCGv_i64 fp1 = tcg_temp_new_i64();
11559 gen_load_fpr64(ctx, fp0, fs);
11560 gen_load_fpr64(ctx, fp1, ft);
11561 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11562 gen_store_fpr64(ctx, fp1, fd);
11563 tcg_temp_free_i64(fp1);
11564 tcg_temp_free_i64(fp0);
11565 } else {
11566 /* OPC_RSQRT2_D */
11567 check_cp1_64bitmode(ctx);
11569 TCGv_i64 fp0 = tcg_temp_new_i64();
11570 TCGv_i64 fp1 = tcg_temp_new_i64();
11572 gen_load_fpr64(ctx, fp0, fs);
11573 gen_load_fpr64(ctx, fp1, ft);
11574 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11575 tcg_temp_free_i64(fp1);
11576 gen_store_fpr64(ctx, fp0, fd);
11577 tcg_temp_free_i64(fp0);
11580 break;
11581 case OPC_CMP_F_D:
11582 case OPC_CMP_UN_D:
11583 case OPC_CMP_EQ_D:
11584 case OPC_CMP_UEQ_D:
11585 case OPC_CMP_OLT_D:
11586 case OPC_CMP_ULT_D:
11587 case OPC_CMP_OLE_D:
11588 case OPC_CMP_ULE_D:
11589 case OPC_CMP_SF_D:
11590 case OPC_CMP_NGLE_D:
11591 case OPC_CMP_SEQ_D:
11592 case OPC_CMP_NGL_D:
11593 case OPC_CMP_LT_D:
11594 case OPC_CMP_NGE_D:
11595 case OPC_CMP_LE_D:
11596 case OPC_CMP_NGT_D:
11597 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11598 if (ctx->opcode & (1 << 6)) {
11599 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
11600 } else {
11601 gen_cmp_d(ctx, func - 48, ft, fs, cc);
11603 break;
11604 case OPC_CVT_S_D:
11605 check_cp1_registers(ctx, fs);
11607 TCGv_i32 fp32 = tcg_temp_new_i32();
11608 TCGv_i64 fp64 = tcg_temp_new_i64();
11610 gen_load_fpr64(ctx, fp64, fs);
11611 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11612 tcg_temp_free_i64(fp64);
11613 gen_store_fpr32(ctx, fp32, fd);
11614 tcg_temp_free_i32(fp32);
11616 break;
11617 case OPC_CVT_W_D:
11618 check_cp1_registers(ctx, fs);
11620 TCGv_i32 fp32 = tcg_temp_new_i32();
11621 TCGv_i64 fp64 = tcg_temp_new_i64();
11623 gen_load_fpr64(ctx, fp64, fs);
11624 if (ctx->nan2008) {
11625 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11626 } else {
11627 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11629 tcg_temp_free_i64(fp64);
11630 gen_store_fpr32(ctx, fp32, fd);
11631 tcg_temp_free_i32(fp32);
11633 break;
11634 case OPC_CVT_L_D:
11635 check_cp1_64bitmode(ctx);
11637 TCGv_i64 fp0 = tcg_temp_new_i64();
11639 gen_load_fpr64(ctx, fp0, fs);
11640 if (ctx->nan2008) {
11641 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11642 } else {
11643 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11645 gen_store_fpr64(ctx, fp0, fd);
11646 tcg_temp_free_i64(fp0);
11648 break;
11649 case OPC_CVT_S_W:
11651 TCGv_i32 fp0 = tcg_temp_new_i32();
11653 gen_load_fpr32(ctx, fp0, fs);
11654 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11655 gen_store_fpr32(ctx, fp0, fd);
11656 tcg_temp_free_i32(fp0);
11658 break;
11659 case OPC_CVT_D_W:
11660 check_cp1_registers(ctx, fd);
11662 TCGv_i32 fp32 = tcg_temp_new_i32();
11663 TCGv_i64 fp64 = tcg_temp_new_i64();
11665 gen_load_fpr32(ctx, fp32, fs);
11666 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11667 tcg_temp_free_i32(fp32);
11668 gen_store_fpr64(ctx, fp64, fd);
11669 tcg_temp_free_i64(fp64);
11671 break;
11672 case OPC_CVT_S_L:
11673 check_cp1_64bitmode(ctx);
11675 TCGv_i32 fp32 = tcg_temp_new_i32();
11676 TCGv_i64 fp64 = tcg_temp_new_i64();
11678 gen_load_fpr64(ctx, fp64, fs);
11679 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11680 tcg_temp_free_i64(fp64);
11681 gen_store_fpr32(ctx, fp32, fd);
11682 tcg_temp_free_i32(fp32);
11684 break;
11685 case OPC_CVT_D_L:
11686 check_cp1_64bitmode(ctx);
11688 TCGv_i64 fp0 = tcg_temp_new_i64();
11690 gen_load_fpr64(ctx, fp0, fs);
11691 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11692 gen_store_fpr64(ctx, fp0, fd);
11693 tcg_temp_free_i64(fp0);
11695 break;
11696 case OPC_CVT_PS_PW:
11697 check_ps(ctx);
11699 TCGv_i64 fp0 = tcg_temp_new_i64();
11701 gen_load_fpr64(ctx, fp0, fs);
11702 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11703 gen_store_fpr64(ctx, fp0, fd);
11704 tcg_temp_free_i64(fp0);
11706 break;
11707 case OPC_ADD_PS:
11708 check_ps(ctx);
11710 TCGv_i64 fp0 = tcg_temp_new_i64();
11711 TCGv_i64 fp1 = tcg_temp_new_i64();
11713 gen_load_fpr64(ctx, fp0, fs);
11714 gen_load_fpr64(ctx, fp1, ft);
11715 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11716 tcg_temp_free_i64(fp1);
11717 gen_store_fpr64(ctx, fp0, fd);
11718 tcg_temp_free_i64(fp0);
11720 break;
11721 case OPC_SUB_PS:
11722 check_ps(ctx);
11724 TCGv_i64 fp0 = tcg_temp_new_i64();
11725 TCGv_i64 fp1 = tcg_temp_new_i64();
11727 gen_load_fpr64(ctx, fp0, fs);
11728 gen_load_fpr64(ctx, fp1, ft);
11729 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11730 tcg_temp_free_i64(fp1);
11731 gen_store_fpr64(ctx, fp0, fd);
11732 tcg_temp_free_i64(fp0);
11734 break;
11735 case OPC_MUL_PS:
11736 check_ps(ctx);
11738 TCGv_i64 fp0 = tcg_temp_new_i64();
11739 TCGv_i64 fp1 = tcg_temp_new_i64();
11741 gen_load_fpr64(ctx, fp0, fs);
11742 gen_load_fpr64(ctx, fp1, ft);
11743 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11744 tcg_temp_free_i64(fp1);
11745 gen_store_fpr64(ctx, fp0, fd);
11746 tcg_temp_free_i64(fp0);
11748 break;
11749 case OPC_ABS_PS:
11750 check_ps(ctx);
11752 TCGv_i64 fp0 = tcg_temp_new_i64();
11754 gen_load_fpr64(ctx, fp0, fs);
11755 gen_helper_float_abs_ps(fp0, fp0);
11756 gen_store_fpr64(ctx, fp0, fd);
11757 tcg_temp_free_i64(fp0);
11759 break;
11760 case OPC_MOV_PS:
11761 check_ps(ctx);
11763 TCGv_i64 fp0 = tcg_temp_new_i64();
11765 gen_load_fpr64(ctx, fp0, fs);
11766 gen_store_fpr64(ctx, fp0, fd);
11767 tcg_temp_free_i64(fp0);
11769 break;
11770 case OPC_NEG_PS:
11771 check_ps(ctx);
11773 TCGv_i64 fp0 = tcg_temp_new_i64();
11775 gen_load_fpr64(ctx, fp0, fs);
11776 gen_helper_float_chs_ps(fp0, fp0);
11777 gen_store_fpr64(ctx, fp0, fd);
11778 tcg_temp_free_i64(fp0);
11780 break;
11781 case OPC_MOVCF_PS:
11782 check_ps(ctx);
11783 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11784 break;
11785 case OPC_MOVZ_PS:
11786 check_ps(ctx);
11788 TCGLabel *l1 = gen_new_label();
11789 TCGv_i64 fp0;
11791 if (ft != 0) {
11792 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11794 fp0 = tcg_temp_new_i64();
11795 gen_load_fpr64(ctx, fp0, fs);
11796 gen_store_fpr64(ctx, fp0, fd);
11797 tcg_temp_free_i64(fp0);
11798 gen_set_label(l1);
11800 break;
11801 case OPC_MOVN_PS:
11802 check_ps(ctx);
11804 TCGLabel *l1 = gen_new_label();
11805 TCGv_i64 fp0;
11807 if (ft != 0) {
11808 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11809 fp0 = tcg_temp_new_i64();
11810 gen_load_fpr64(ctx, fp0, fs);
11811 gen_store_fpr64(ctx, fp0, fd);
11812 tcg_temp_free_i64(fp0);
11813 gen_set_label(l1);
11816 break;
11817 case OPC_ADDR_PS:
11818 check_ps(ctx);
11820 TCGv_i64 fp0 = tcg_temp_new_i64();
11821 TCGv_i64 fp1 = tcg_temp_new_i64();
11823 gen_load_fpr64(ctx, fp0, ft);
11824 gen_load_fpr64(ctx, fp1, fs);
11825 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11826 tcg_temp_free_i64(fp1);
11827 gen_store_fpr64(ctx, fp0, fd);
11828 tcg_temp_free_i64(fp0);
11830 break;
11831 case OPC_MULR_PS:
11832 check_ps(ctx);
11834 TCGv_i64 fp0 = tcg_temp_new_i64();
11835 TCGv_i64 fp1 = tcg_temp_new_i64();
11837 gen_load_fpr64(ctx, fp0, ft);
11838 gen_load_fpr64(ctx, fp1, fs);
11839 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11840 tcg_temp_free_i64(fp1);
11841 gen_store_fpr64(ctx, fp0, fd);
11842 tcg_temp_free_i64(fp0);
11844 break;
11845 case OPC_RECIP2_PS:
11846 check_ps(ctx);
11848 TCGv_i64 fp0 = tcg_temp_new_i64();
11849 TCGv_i64 fp1 = tcg_temp_new_i64();
11851 gen_load_fpr64(ctx, fp0, fs);
11852 gen_load_fpr64(ctx, fp1, ft);
11853 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11854 tcg_temp_free_i64(fp1);
11855 gen_store_fpr64(ctx, fp0, fd);
11856 tcg_temp_free_i64(fp0);
11858 break;
11859 case OPC_RECIP1_PS:
11860 check_ps(ctx);
11862 TCGv_i64 fp0 = tcg_temp_new_i64();
11864 gen_load_fpr64(ctx, fp0, fs);
11865 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11866 gen_store_fpr64(ctx, fp0, fd);
11867 tcg_temp_free_i64(fp0);
11869 break;
11870 case OPC_RSQRT1_PS:
11871 check_ps(ctx);
11873 TCGv_i64 fp0 = tcg_temp_new_i64();
11875 gen_load_fpr64(ctx, fp0, fs);
11876 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11877 gen_store_fpr64(ctx, fp0, fd);
11878 tcg_temp_free_i64(fp0);
11880 break;
11881 case OPC_RSQRT2_PS:
11882 check_ps(ctx);
11884 TCGv_i64 fp0 = tcg_temp_new_i64();
11885 TCGv_i64 fp1 = tcg_temp_new_i64();
11887 gen_load_fpr64(ctx, fp0, fs);
11888 gen_load_fpr64(ctx, fp1, ft);
11889 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11890 tcg_temp_free_i64(fp1);
11891 gen_store_fpr64(ctx, fp0, fd);
11892 tcg_temp_free_i64(fp0);
11894 break;
11895 case OPC_CVT_S_PU:
11896 check_cp1_64bitmode(ctx);
11898 TCGv_i32 fp0 = tcg_temp_new_i32();
11900 gen_load_fpr32h(ctx, fp0, fs);
11901 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11902 gen_store_fpr32(ctx, fp0, fd);
11903 tcg_temp_free_i32(fp0);
11905 break;
11906 case OPC_CVT_PW_PS:
11907 check_ps(ctx);
11909 TCGv_i64 fp0 = tcg_temp_new_i64();
11911 gen_load_fpr64(ctx, fp0, fs);
11912 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11913 gen_store_fpr64(ctx, fp0, fd);
11914 tcg_temp_free_i64(fp0);
11916 break;
11917 case OPC_CVT_S_PL:
11918 check_cp1_64bitmode(ctx);
11920 TCGv_i32 fp0 = tcg_temp_new_i32();
11922 gen_load_fpr32(ctx, fp0, fs);
11923 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11924 gen_store_fpr32(ctx, fp0, fd);
11925 tcg_temp_free_i32(fp0);
11927 break;
11928 case OPC_PLL_PS:
11929 check_ps(ctx);
11931 TCGv_i32 fp0 = tcg_temp_new_i32();
11932 TCGv_i32 fp1 = tcg_temp_new_i32();
11934 gen_load_fpr32(ctx, fp0, fs);
11935 gen_load_fpr32(ctx, fp1, ft);
11936 gen_store_fpr32h(ctx, fp0, fd);
11937 gen_store_fpr32(ctx, fp1, fd);
11938 tcg_temp_free_i32(fp0);
11939 tcg_temp_free_i32(fp1);
11941 break;
11942 case OPC_PLU_PS:
11943 check_ps(ctx);
11945 TCGv_i32 fp0 = tcg_temp_new_i32();
11946 TCGv_i32 fp1 = tcg_temp_new_i32();
11948 gen_load_fpr32(ctx, fp0, fs);
11949 gen_load_fpr32h(ctx, fp1, ft);
11950 gen_store_fpr32(ctx, fp1, fd);
11951 gen_store_fpr32h(ctx, fp0, fd);
11952 tcg_temp_free_i32(fp0);
11953 tcg_temp_free_i32(fp1);
11955 break;
11956 case OPC_PUL_PS:
11957 check_ps(ctx);
11959 TCGv_i32 fp0 = tcg_temp_new_i32();
11960 TCGv_i32 fp1 = tcg_temp_new_i32();
11962 gen_load_fpr32h(ctx, fp0, fs);
11963 gen_load_fpr32(ctx, fp1, ft);
11964 gen_store_fpr32(ctx, fp1, fd);
11965 gen_store_fpr32h(ctx, fp0, fd);
11966 tcg_temp_free_i32(fp0);
11967 tcg_temp_free_i32(fp1);
11969 break;
11970 case OPC_PUU_PS:
11971 check_ps(ctx);
11973 TCGv_i32 fp0 = tcg_temp_new_i32();
11974 TCGv_i32 fp1 = tcg_temp_new_i32();
11976 gen_load_fpr32h(ctx, fp0, fs);
11977 gen_load_fpr32h(ctx, fp1, ft);
11978 gen_store_fpr32(ctx, fp1, fd);
11979 gen_store_fpr32h(ctx, fp0, fd);
11980 tcg_temp_free_i32(fp0);
11981 tcg_temp_free_i32(fp1);
11983 break;
11984 case OPC_CMP_F_PS:
11985 case OPC_CMP_UN_PS:
11986 case OPC_CMP_EQ_PS:
11987 case OPC_CMP_UEQ_PS:
11988 case OPC_CMP_OLT_PS:
11989 case OPC_CMP_ULT_PS:
11990 case OPC_CMP_OLE_PS:
11991 case OPC_CMP_ULE_PS:
11992 case OPC_CMP_SF_PS:
11993 case OPC_CMP_NGLE_PS:
11994 case OPC_CMP_SEQ_PS:
11995 case OPC_CMP_NGL_PS:
11996 case OPC_CMP_LT_PS:
11997 case OPC_CMP_NGE_PS:
11998 case OPC_CMP_LE_PS:
11999 case OPC_CMP_NGT_PS:
12000 if (ctx->opcode & (1 << 6)) {
12001 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
12002 } else {
12003 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
12005 break;
12006 default:
12007 MIPS_INVAL("farith");
12008 gen_reserved_instruction(ctx);
12009 return;
12013 /* Coprocessor 3 (FPU) */
12014 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12015 int fd, int fs, int base, int index)
12017 TCGv t0 = tcg_temp_new();
12019 if (base == 0) {
12020 gen_load_gpr(t0, index);
12021 } else if (index == 0) {
12022 gen_load_gpr(t0, base);
12023 } else {
12024 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12027 * Don't do NOP if destination is zero: we must perform the actual
12028 * memory access.
12030 switch (opc) {
12031 case OPC_LWXC1:
12032 check_cop1x(ctx);
12034 TCGv_i32 fp0 = tcg_temp_new_i32();
12036 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12037 tcg_gen_trunc_tl_i32(fp0, t0);
12038 gen_store_fpr32(ctx, fp0, fd);
12039 tcg_temp_free_i32(fp0);
12041 break;
12042 case OPC_LDXC1:
12043 check_cop1x(ctx);
12044 check_cp1_registers(ctx, fd);
12046 TCGv_i64 fp0 = tcg_temp_new_i64();
12047 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12048 gen_store_fpr64(ctx, fp0, fd);
12049 tcg_temp_free_i64(fp0);
12051 break;
12052 case OPC_LUXC1:
12053 check_cp1_64bitmode(ctx);
12054 tcg_gen_andi_tl(t0, t0, ~0x7);
12056 TCGv_i64 fp0 = tcg_temp_new_i64();
12058 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12059 gen_store_fpr64(ctx, fp0, fd);
12060 tcg_temp_free_i64(fp0);
12062 break;
12063 case OPC_SWXC1:
12064 check_cop1x(ctx);
12066 TCGv_i32 fp0 = tcg_temp_new_i32();
12067 gen_load_fpr32(ctx, fp0, fs);
12068 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12069 tcg_temp_free_i32(fp0);
12071 break;
12072 case OPC_SDXC1:
12073 check_cop1x(ctx);
12074 check_cp1_registers(ctx, fs);
12076 TCGv_i64 fp0 = tcg_temp_new_i64();
12077 gen_load_fpr64(ctx, fp0, fs);
12078 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12079 tcg_temp_free_i64(fp0);
12081 break;
12082 case OPC_SUXC1:
12083 check_cp1_64bitmode(ctx);
12084 tcg_gen_andi_tl(t0, t0, ~0x7);
12086 TCGv_i64 fp0 = tcg_temp_new_i64();
12087 gen_load_fpr64(ctx, fp0, fs);
12088 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12089 tcg_temp_free_i64(fp0);
12091 break;
12093 tcg_temp_free(t0);
12096 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12097 int fd, int fr, int fs, int ft)
12099 switch (opc) {
12100 case OPC_ALNV_PS:
12101 check_ps(ctx);
12103 TCGv t0 = tcg_temp_local_new();
12104 TCGv_i32 fp = tcg_temp_new_i32();
12105 TCGv_i32 fph = tcg_temp_new_i32();
12106 TCGLabel *l1 = gen_new_label();
12107 TCGLabel *l2 = gen_new_label();
12109 gen_load_gpr(t0, fr);
12110 tcg_gen_andi_tl(t0, t0, 0x7);
12112 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12113 gen_load_fpr32(ctx, fp, fs);
12114 gen_load_fpr32h(ctx, fph, fs);
12115 gen_store_fpr32(ctx, fp, fd);
12116 gen_store_fpr32h(ctx, fph, fd);
12117 tcg_gen_br(l2);
12118 gen_set_label(l1);
12119 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12120 tcg_temp_free(t0);
12121 #ifdef TARGET_WORDS_BIGENDIAN
12122 gen_load_fpr32(ctx, fp, fs);
12123 gen_load_fpr32h(ctx, fph, ft);
12124 gen_store_fpr32h(ctx, fp, fd);
12125 gen_store_fpr32(ctx, fph, fd);
12126 #else
12127 gen_load_fpr32h(ctx, fph, fs);
12128 gen_load_fpr32(ctx, fp, ft);
12129 gen_store_fpr32(ctx, fph, fd);
12130 gen_store_fpr32h(ctx, fp, fd);
12131 #endif
12132 gen_set_label(l2);
12133 tcg_temp_free_i32(fp);
12134 tcg_temp_free_i32(fph);
12136 break;
12137 case OPC_MADD_S:
12138 check_cop1x(ctx);
12140 TCGv_i32 fp0 = tcg_temp_new_i32();
12141 TCGv_i32 fp1 = tcg_temp_new_i32();
12142 TCGv_i32 fp2 = tcg_temp_new_i32();
12144 gen_load_fpr32(ctx, fp0, fs);
12145 gen_load_fpr32(ctx, fp1, ft);
12146 gen_load_fpr32(ctx, fp2, fr);
12147 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12148 tcg_temp_free_i32(fp0);
12149 tcg_temp_free_i32(fp1);
12150 gen_store_fpr32(ctx, fp2, fd);
12151 tcg_temp_free_i32(fp2);
12153 break;
12154 case OPC_MADD_D:
12155 check_cop1x(ctx);
12156 check_cp1_registers(ctx, fd | fs | ft | fr);
12158 TCGv_i64 fp0 = tcg_temp_new_i64();
12159 TCGv_i64 fp1 = tcg_temp_new_i64();
12160 TCGv_i64 fp2 = tcg_temp_new_i64();
12162 gen_load_fpr64(ctx, fp0, fs);
12163 gen_load_fpr64(ctx, fp1, ft);
12164 gen_load_fpr64(ctx, fp2, fr);
12165 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12166 tcg_temp_free_i64(fp0);
12167 tcg_temp_free_i64(fp1);
12168 gen_store_fpr64(ctx, fp2, fd);
12169 tcg_temp_free_i64(fp2);
12171 break;
12172 case OPC_MADD_PS:
12173 check_ps(ctx);
12175 TCGv_i64 fp0 = tcg_temp_new_i64();
12176 TCGv_i64 fp1 = tcg_temp_new_i64();
12177 TCGv_i64 fp2 = tcg_temp_new_i64();
12179 gen_load_fpr64(ctx, fp0, fs);
12180 gen_load_fpr64(ctx, fp1, ft);
12181 gen_load_fpr64(ctx, fp2, fr);
12182 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12183 tcg_temp_free_i64(fp0);
12184 tcg_temp_free_i64(fp1);
12185 gen_store_fpr64(ctx, fp2, fd);
12186 tcg_temp_free_i64(fp2);
12188 break;
12189 case OPC_MSUB_S:
12190 check_cop1x(ctx);
12192 TCGv_i32 fp0 = tcg_temp_new_i32();
12193 TCGv_i32 fp1 = tcg_temp_new_i32();
12194 TCGv_i32 fp2 = tcg_temp_new_i32();
12196 gen_load_fpr32(ctx, fp0, fs);
12197 gen_load_fpr32(ctx, fp1, ft);
12198 gen_load_fpr32(ctx, fp2, fr);
12199 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12200 tcg_temp_free_i32(fp0);
12201 tcg_temp_free_i32(fp1);
12202 gen_store_fpr32(ctx, fp2, fd);
12203 tcg_temp_free_i32(fp2);
12205 break;
12206 case OPC_MSUB_D:
12207 check_cop1x(ctx);
12208 check_cp1_registers(ctx, fd | fs | ft | fr);
12210 TCGv_i64 fp0 = tcg_temp_new_i64();
12211 TCGv_i64 fp1 = tcg_temp_new_i64();
12212 TCGv_i64 fp2 = tcg_temp_new_i64();
12214 gen_load_fpr64(ctx, fp0, fs);
12215 gen_load_fpr64(ctx, fp1, ft);
12216 gen_load_fpr64(ctx, fp2, fr);
12217 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12218 tcg_temp_free_i64(fp0);
12219 tcg_temp_free_i64(fp1);
12220 gen_store_fpr64(ctx, fp2, fd);
12221 tcg_temp_free_i64(fp2);
12223 break;
12224 case OPC_MSUB_PS:
12225 check_ps(ctx);
12227 TCGv_i64 fp0 = tcg_temp_new_i64();
12228 TCGv_i64 fp1 = tcg_temp_new_i64();
12229 TCGv_i64 fp2 = tcg_temp_new_i64();
12231 gen_load_fpr64(ctx, fp0, fs);
12232 gen_load_fpr64(ctx, fp1, ft);
12233 gen_load_fpr64(ctx, fp2, fr);
12234 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12235 tcg_temp_free_i64(fp0);
12236 tcg_temp_free_i64(fp1);
12237 gen_store_fpr64(ctx, fp2, fd);
12238 tcg_temp_free_i64(fp2);
12240 break;
12241 case OPC_NMADD_S:
12242 check_cop1x(ctx);
12244 TCGv_i32 fp0 = tcg_temp_new_i32();
12245 TCGv_i32 fp1 = tcg_temp_new_i32();
12246 TCGv_i32 fp2 = tcg_temp_new_i32();
12248 gen_load_fpr32(ctx, fp0, fs);
12249 gen_load_fpr32(ctx, fp1, ft);
12250 gen_load_fpr32(ctx, fp2, fr);
12251 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12252 tcg_temp_free_i32(fp0);
12253 tcg_temp_free_i32(fp1);
12254 gen_store_fpr32(ctx, fp2, fd);
12255 tcg_temp_free_i32(fp2);
12257 break;
12258 case OPC_NMADD_D:
12259 check_cop1x(ctx);
12260 check_cp1_registers(ctx, fd | fs | ft | fr);
12262 TCGv_i64 fp0 = tcg_temp_new_i64();
12263 TCGv_i64 fp1 = tcg_temp_new_i64();
12264 TCGv_i64 fp2 = tcg_temp_new_i64();
12266 gen_load_fpr64(ctx, fp0, fs);
12267 gen_load_fpr64(ctx, fp1, ft);
12268 gen_load_fpr64(ctx, fp2, fr);
12269 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12270 tcg_temp_free_i64(fp0);
12271 tcg_temp_free_i64(fp1);
12272 gen_store_fpr64(ctx, fp2, fd);
12273 tcg_temp_free_i64(fp2);
12275 break;
12276 case OPC_NMADD_PS:
12277 check_ps(ctx);
12279 TCGv_i64 fp0 = tcg_temp_new_i64();
12280 TCGv_i64 fp1 = tcg_temp_new_i64();
12281 TCGv_i64 fp2 = tcg_temp_new_i64();
12283 gen_load_fpr64(ctx, fp0, fs);
12284 gen_load_fpr64(ctx, fp1, ft);
12285 gen_load_fpr64(ctx, fp2, fr);
12286 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12287 tcg_temp_free_i64(fp0);
12288 tcg_temp_free_i64(fp1);
12289 gen_store_fpr64(ctx, fp2, fd);
12290 tcg_temp_free_i64(fp2);
12292 break;
12293 case OPC_NMSUB_S:
12294 check_cop1x(ctx);
12296 TCGv_i32 fp0 = tcg_temp_new_i32();
12297 TCGv_i32 fp1 = tcg_temp_new_i32();
12298 TCGv_i32 fp2 = tcg_temp_new_i32();
12300 gen_load_fpr32(ctx, fp0, fs);
12301 gen_load_fpr32(ctx, fp1, ft);
12302 gen_load_fpr32(ctx, fp2, fr);
12303 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12304 tcg_temp_free_i32(fp0);
12305 tcg_temp_free_i32(fp1);
12306 gen_store_fpr32(ctx, fp2, fd);
12307 tcg_temp_free_i32(fp2);
12309 break;
12310 case OPC_NMSUB_D:
12311 check_cop1x(ctx);
12312 check_cp1_registers(ctx, fd | fs | ft | fr);
12314 TCGv_i64 fp0 = tcg_temp_new_i64();
12315 TCGv_i64 fp1 = tcg_temp_new_i64();
12316 TCGv_i64 fp2 = tcg_temp_new_i64();
12318 gen_load_fpr64(ctx, fp0, fs);
12319 gen_load_fpr64(ctx, fp1, ft);
12320 gen_load_fpr64(ctx, fp2, fr);
12321 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12322 tcg_temp_free_i64(fp0);
12323 tcg_temp_free_i64(fp1);
12324 gen_store_fpr64(ctx, fp2, fd);
12325 tcg_temp_free_i64(fp2);
12327 break;
12328 case OPC_NMSUB_PS:
12329 check_ps(ctx);
12331 TCGv_i64 fp0 = tcg_temp_new_i64();
12332 TCGv_i64 fp1 = tcg_temp_new_i64();
12333 TCGv_i64 fp2 = tcg_temp_new_i64();
12335 gen_load_fpr64(ctx, fp0, fs);
12336 gen_load_fpr64(ctx, fp1, ft);
12337 gen_load_fpr64(ctx, fp2, fr);
12338 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12339 tcg_temp_free_i64(fp0);
12340 tcg_temp_free_i64(fp1);
12341 gen_store_fpr64(ctx, fp2, fd);
12342 tcg_temp_free_i64(fp2);
12344 break;
12345 default:
12346 MIPS_INVAL("flt3_arith");
12347 gen_reserved_instruction(ctx);
12348 return;
12352 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12354 TCGv t0;
12356 #if !defined(CONFIG_USER_ONLY)
12358 * The Linux kernel will emulate rdhwr if it's not supported natively.
12359 * Therefore only check the ISA in system mode.
12361 check_insn(ctx, ISA_MIPS_R2);
12362 #endif
12363 t0 = tcg_temp_new();
12365 switch (rd) {
12366 case 0:
12367 gen_helper_rdhwr_cpunum(t0, cpu_env);
12368 gen_store_gpr(t0, rt);
12369 break;
12370 case 1:
12371 gen_helper_rdhwr_synci_step(t0, cpu_env);
12372 gen_store_gpr(t0, rt);
12373 break;
12374 case 2:
12375 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12376 gen_io_start();
12378 gen_helper_rdhwr_cc(t0, cpu_env);
12379 gen_store_gpr(t0, rt);
12381 * Break the TB to be able to take timer interrupts immediately
12382 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12383 * we break completely out of translated code.
12385 gen_save_pc(ctx->base.pc_next + 4);
12386 ctx->base.is_jmp = DISAS_EXIT;
12387 break;
12388 case 3:
12389 gen_helper_rdhwr_ccres(t0, cpu_env);
12390 gen_store_gpr(t0, rt);
12391 break;
12392 case 4:
12393 check_insn(ctx, ISA_MIPS_R6);
12394 if (sel != 0) {
12396 * Performance counter registers are not implemented other than
12397 * control register 0.
12399 generate_exception(ctx, EXCP_RI);
12401 gen_helper_rdhwr_performance(t0, cpu_env);
12402 gen_store_gpr(t0, rt);
12403 break;
12404 case 5:
12405 check_insn(ctx, ISA_MIPS_R6);
12406 gen_helper_rdhwr_xnp(t0, cpu_env);
12407 gen_store_gpr(t0, rt);
12408 break;
12409 case 29:
12410 #if defined(CONFIG_USER_ONLY)
12411 tcg_gen_ld_tl(t0, cpu_env,
12412 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12413 gen_store_gpr(t0, rt);
12414 break;
12415 #else
12416 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12417 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12418 tcg_gen_ld_tl(t0, cpu_env,
12419 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12420 gen_store_gpr(t0, rt);
12421 } else {
12422 gen_reserved_instruction(ctx);
12424 break;
12425 #endif
12426 default: /* Invalid */
12427 MIPS_INVAL("rdhwr");
12428 gen_reserved_instruction(ctx);
12429 break;
12431 tcg_temp_free(t0);
12434 static inline void clear_branch_hflags(DisasContext *ctx)
12436 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12437 if (ctx->base.is_jmp == DISAS_NEXT) {
12438 save_cpu_state(ctx, 0);
12439 } else {
12441 * It is not safe to save ctx->hflags as hflags may be changed
12442 * in execution time by the instruction in delay / forbidden slot.
12444 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12448 static void gen_branch(DisasContext *ctx, int insn_bytes)
12450 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12451 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12452 /* Branches completion */
12453 clear_branch_hflags(ctx);
12454 ctx->base.is_jmp = DISAS_NORETURN;
12455 /* FIXME: Need to clear can_do_io. */
12456 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12457 case MIPS_HFLAG_FBNSLOT:
12458 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12459 break;
12460 case MIPS_HFLAG_B:
12461 /* unconditional branch */
12462 if (proc_hflags & MIPS_HFLAG_BX) {
12463 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12465 gen_goto_tb(ctx, 0, ctx->btarget);
12466 break;
12467 case MIPS_HFLAG_BL:
12468 /* blikely taken case */
12469 gen_goto_tb(ctx, 0, ctx->btarget);
12470 break;
12471 case MIPS_HFLAG_BC:
12472 /* Conditional branch */
12474 TCGLabel *l1 = gen_new_label();
12476 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12477 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12478 gen_set_label(l1);
12479 gen_goto_tb(ctx, 0, ctx->btarget);
12481 break;
12482 case MIPS_HFLAG_BR:
12483 /* unconditional branch to register */
12484 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12485 TCGv t0 = tcg_temp_new();
12486 TCGv_i32 t1 = tcg_temp_new_i32();
12488 tcg_gen_andi_tl(t0, btarget, 0x1);
12489 tcg_gen_trunc_tl_i32(t1, t0);
12490 tcg_temp_free(t0);
12491 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12492 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12493 tcg_gen_or_i32(hflags, hflags, t1);
12494 tcg_temp_free_i32(t1);
12496 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12497 } else {
12498 tcg_gen_mov_tl(cpu_PC, btarget);
12500 if (ctx->base.singlestep_enabled) {
12501 save_cpu_state(ctx, 0);
12502 gen_helper_raise_exception_debug(cpu_env);
12504 tcg_gen_lookup_and_goto_ptr();
12505 break;
12506 default:
12507 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12508 abort();
12513 /* Compact Branches */
12514 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12515 int rs, int rt, int32_t offset)
12517 int bcond_compute = 0;
12518 TCGv t0 = tcg_temp_new();
12519 TCGv t1 = tcg_temp_new();
12520 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12522 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12523 #ifdef MIPS_DEBUG_DISAS
12524 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12525 "\n", ctx->base.pc_next);
12526 #endif
12527 gen_reserved_instruction(ctx);
12528 goto out;
12531 /* Load needed operands and calculate btarget */
12532 switch (opc) {
12533 /* compact branch */
12534 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12535 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12536 gen_load_gpr(t0, rs);
12537 gen_load_gpr(t1, rt);
12538 bcond_compute = 1;
12539 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12540 if (rs <= rt && rs == 0) {
12541 /* OPC_BEQZALC, OPC_BNEZALC */
12542 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12544 break;
12545 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12546 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12547 gen_load_gpr(t0, rs);
12548 gen_load_gpr(t1, rt);
12549 bcond_compute = 1;
12550 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12551 break;
12552 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12553 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12554 if (rs == 0 || rs == rt) {
12555 /* OPC_BLEZALC, OPC_BGEZALC */
12556 /* OPC_BGTZALC, OPC_BLTZALC */
12557 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12559 gen_load_gpr(t0, rs);
12560 gen_load_gpr(t1, rt);
12561 bcond_compute = 1;
12562 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12563 break;
12564 case OPC_BC:
12565 case OPC_BALC:
12566 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12567 break;
12568 case OPC_BEQZC:
12569 case OPC_BNEZC:
12570 if (rs != 0) {
12571 /* OPC_BEQZC, OPC_BNEZC */
12572 gen_load_gpr(t0, rs);
12573 bcond_compute = 1;
12574 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12575 } else {
12576 /* OPC_JIC, OPC_JIALC */
12577 TCGv tbase = tcg_temp_new();
12578 TCGv toffset = tcg_temp_new();
12580 gen_load_gpr(tbase, rt);
12581 tcg_gen_movi_tl(toffset, offset);
12582 gen_op_addr_add(ctx, btarget, tbase, toffset);
12583 tcg_temp_free(tbase);
12584 tcg_temp_free(toffset);
12586 break;
12587 default:
12588 MIPS_INVAL("Compact branch/jump");
12589 gen_reserved_instruction(ctx);
12590 goto out;
12593 if (bcond_compute == 0) {
12594 /* Uncoditional compact branch */
12595 switch (opc) {
12596 case OPC_JIALC:
12597 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12598 /* Fallthrough */
12599 case OPC_JIC:
12600 ctx->hflags |= MIPS_HFLAG_BR;
12601 break;
12602 case OPC_BALC:
12603 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12604 /* Fallthrough */
12605 case OPC_BC:
12606 ctx->hflags |= MIPS_HFLAG_B;
12607 break;
12608 default:
12609 MIPS_INVAL("Compact branch/jump");
12610 gen_reserved_instruction(ctx);
12611 goto out;
12614 /* Generating branch here as compact branches don't have delay slot */
12615 gen_branch(ctx, 4);
12616 } else {
12617 /* Conditional compact branch */
12618 TCGLabel *fs = gen_new_label();
12619 save_cpu_state(ctx, 0);
12621 switch (opc) {
12622 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12623 if (rs == 0 && rt != 0) {
12624 /* OPC_BLEZALC */
12625 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12626 } else if (rs != 0 && rt != 0 && rs == rt) {
12627 /* OPC_BGEZALC */
12628 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12629 } else {
12630 /* OPC_BGEUC */
12631 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12633 break;
12634 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12635 if (rs == 0 && rt != 0) {
12636 /* OPC_BGTZALC */
12637 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12638 } else if (rs != 0 && rt != 0 && rs == rt) {
12639 /* OPC_BLTZALC */
12640 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12641 } else {
12642 /* OPC_BLTUC */
12643 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12645 break;
12646 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12647 if (rs == 0 && rt != 0) {
12648 /* OPC_BLEZC */
12649 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12650 } else if (rs != 0 && rt != 0 && rs == rt) {
12651 /* OPC_BGEZC */
12652 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12653 } else {
12654 /* OPC_BGEC */
12655 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12657 break;
12658 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12659 if (rs == 0 && rt != 0) {
12660 /* OPC_BGTZC */
12661 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12662 } else if (rs != 0 && rt != 0 && rs == rt) {
12663 /* OPC_BLTZC */
12664 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12665 } else {
12666 /* OPC_BLTC */
12667 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12669 break;
12670 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12671 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12672 if (rs >= rt) {
12673 /* OPC_BOVC, OPC_BNVC */
12674 TCGv t2 = tcg_temp_new();
12675 TCGv t3 = tcg_temp_new();
12676 TCGv t4 = tcg_temp_new();
12677 TCGv input_overflow = tcg_temp_new();
12679 gen_load_gpr(t0, rs);
12680 gen_load_gpr(t1, rt);
12681 tcg_gen_ext32s_tl(t2, t0);
12682 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12683 tcg_gen_ext32s_tl(t3, t1);
12684 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12685 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12687 tcg_gen_add_tl(t4, t2, t3);
12688 tcg_gen_ext32s_tl(t4, t4);
12689 tcg_gen_xor_tl(t2, t2, t3);
12690 tcg_gen_xor_tl(t3, t4, t3);
12691 tcg_gen_andc_tl(t2, t3, t2);
12692 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12693 tcg_gen_or_tl(t4, t4, input_overflow);
12694 if (opc == OPC_BOVC) {
12695 /* OPC_BOVC */
12696 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12697 } else {
12698 /* OPC_BNVC */
12699 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12701 tcg_temp_free(input_overflow);
12702 tcg_temp_free(t4);
12703 tcg_temp_free(t3);
12704 tcg_temp_free(t2);
12705 } else if (rs < rt && rs == 0) {
12706 /* OPC_BEQZALC, OPC_BNEZALC */
12707 if (opc == OPC_BEQZALC) {
12708 /* OPC_BEQZALC */
12709 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12710 } else {
12711 /* OPC_BNEZALC */
12712 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12714 } else {
12715 /* OPC_BEQC, OPC_BNEC */
12716 if (opc == OPC_BEQC) {
12717 /* OPC_BEQC */
12718 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12719 } else {
12720 /* OPC_BNEC */
12721 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12724 break;
12725 case OPC_BEQZC:
12726 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12727 break;
12728 case OPC_BNEZC:
12729 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12730 break;
12731 default:
12732 MIPS_INVAL("Compact conditional branch/jump");
12733 gen_reserved_instruction(ctx);
12734 goto out;
12737 /* Generating branch here as compact branches don't have delay slot */
12738 gen_goto_tb(ctx, 1, ctx->btarget);
12739 gen_set_label(fs);
12741 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12744 out:
12745 tcg_temp_free(t0);
12746 tcg_temp_free(t1);
12749 /* ISA extensions (ASEs) */
12750 /* MIPS16 extension to MIPS32 */
12752 /* MIPS16 major opcodes */
12753 enum {
12754 M16_OPC_ADDIUSP = 0x00,
12755 M16_OPC_ADDIUPC = 0x01,
12756 M16_OPC_B = 0x02,
12757 M16_OPC_JAL = 0x03,
12758 M16_OPC_BEQZ = 0x04,
12759 M16_OPC_BNEQZ = 0x05,
12760 M16_OPC_SHIFT = 0x06,
12761 M16_OPC_LD = 0x07,
12762 M16_OPC_RRIA = 0x08,
12763 M16_OPC_ADDIU8 = 0x09,
12764 M16_OPC_SLTI = 0x0a,
12765 M16_OPC_SLTIU = 0x0b,
12766 M16_OPC_I8 = 0x0c,
12767 M16_OPC_LI = 0x0d,
12768 M16_OPC_CMPI = 0x0e,
12769 M16_OPC_SD = 0x0f,
12770 M16_OPC_LB = 0x10,
12771 M16_OPC_LH = 0x11,
12772 M16_OPC_LWSP = 0x12,
12773 M16_OPC_LW = 0x13,
12774 M16_OPC_LBU = 0x14,
12775 M16_OPC_LHU = 0x15,
12776 M16_OPC_LWPC = 0x16,
12777 M16_OPC_LWU = 0x17,
12778 M16_OPC_SB = 0x18,
12779 M16_OPC_SH = 0x19,
12780 M16_OPC_SWSP = 0x1a,
12781 M16_OPC_SW = 0x1b,
12782 M16_OPC_RRR = 0x1c,
12783 M16_OPC_RR = 0x1d,
12784 M16_OPC_EXTEND = 0x1e,
12785 M16_OPC_I64 = 0x1f
12788 /* I8 funct field */
12789 enum {
12790 I8_BTEQZ = 0x0,
12791 I8_BTNEZ = 0x1,
12792 I8_SWRASP = 0x2,
12793 I8_ADJSP = 0x3,
12794 I8_SVRS = 0x4,
12795 I8_MOV32R = 0x5,
12796 I8_MOVR32 = 0x7
12799 /* RRR f field */
12800 enum {
12801 RRR_DADDU = 0x0,
12802 RRR_ADDU = 0x1,
12803 RRR_DSUBU = 0x2,
12804 RRR_SUBU = 0x3
12807 /* RR funct field */
12808 enum {
12809 RR_JR = 0x00,
12810 RR_SDBBP = 0x01,
12811 RR_SLT = 0x02,
12812 RR_SLTU = 0x03,
12813 RR_SLLV = 0x04,
12814 RR_BREAK = 0x05,
12815 RR_SRLV = 0x06,
12816 RR_SRAV = 0x07,
12817 RR_DSRL = 0x08,
12818 RR_CMP = 0x0a,
12819 RR_NEG = 0x0b,
12820 RR_AND = 0x0c,
12821 RR_OR = 0x0d,
12822 RR_XOR = 0x0e,
12823 RR_NOT = 0x0f,
12824 RR_MFHI = 0x10,
12825 RR_CNVT = 0x11,
12826 RR_MFLO = 0x12,
12827 RR_DSRA = 0x13,
12828 RR_DSLLV = 0x14,
12829 RR_DSRLV = 0x16,
12830 RR_DSRAV = 0x17,
12831 RR_MULT = 0x18,
12832 RR_MULTU = 0x19,
12833 RR_DIV = 0x1a,
12834 RR_DIVU = 0x1b,
12835 RR_DMULT = 0x1c,
12836 RR_DMULTU = 0x1d,
12837 RR_DDIV = 0x1e,
12838 RR_DDIVU = 0x1f
12841 /* I64 funct field */
12842 enum {
12843 I64_LDSP = 0x0,
12844 I64_SDSP = 0x1,
12845 I64_SDRASP = 0x2,
12846 I64_DADJSP = 0x3,
12847 I64_LDPC = 0x4,
12848 I64_DADDIU5 = 0x5,
12849 I64_DADDIUPC = 0x6,
12850 I64_DADDIUSP = 0x7
12853 /* RR ry field for CNVT */
12854 enum {
12855 RR_RY_CNVT_ZEB = 0x0,
12856 RR_RY_CNVT_ZEH = 0x1,
12857 RR_RY_CNVT_ZEW = 0x2,
12858 RR_RY_CNVT_SEB = 0x4,
12859 RR_RY_CNVT_SEH = 0x5,
12860 RR_RY_CNVT_SEW = 0x6,
12863 static int xlat(int r)
12865 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12867 return map[r];
12870 static void gen_mips16_save(DisasContext *ctx,
12871 int xsregs, int aregs,
12872 int do_ra, int do_s0, int do_s1,
12873 int framesize)
12875 TCGv t0 = tcg_temp_new();
12876 TCGv t1 = tcg_temp_new();
12877 TCGv t2 = tcg_temp_new();
12878 int args, astatic;
12880 switch (aregs) {
12881 case 0:
12882 case 1:
12883 case 2:
12884 case 3:
12885 case 11:
12886 args = 0;
12887 break;
12888 case 4:
12889 case 5:
12890 case 6:
12891 case 7:
12892 args = 1;
12893 break;
12894 case 8:
12895 case 9:
12896 case 10:
12897 args = 2;
12898 break;
12899 case 12:
12900 case 13:
12901 args = 3;
12902 break;
12903 case 14:
12904 args = 4;
12905 break;
12906 default:
12907 gen_reserved_instruction(ctx);
12908 return;
12911 switch (args) {
12912 case 4:
12913 gen_base_offset_addr(ctx, t0, 29, 12);
12914 gen_load_gpr(t1, 7);
12915 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12916 /* Fall through */
12917 case 3:
12918 gen_base_offset_addr(ctx, t0, 29, 8);
12919 gen_load_gpr(t1, 6);
12920 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12921 /* Fall through */
12922 case 2:
12923 gen_base_offset_addr(ctx, t0, 29, 4);
12924 gen_load_gpr(t1, 5);
12925 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12926 /* Fall through */
12927 case 1:
12928 gen_base_offset_addr(ctx, t0, 29, 0);
12929 gen_load_gpr(t1, 4);
12930 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12933 gen_load_gpr(t0, 29);
12935 #define DECR_AND_STORE(reg) do { \
12936 tcg_gen_movi_tl(t2, -4); \
12937 gen_op_addr_add(ctx, t0, t0, t2); \
12938 gen_load_gpr(t1, reg); \
12939 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12940 } while (0)
12942 if (do_ra) {
12943 DECR_AND_STORE(31);
12946 switch (xsregs) {
12947 case 7:
12948 DECR_AND_STORE(30);
12949 /* Fall through */
12950 case 6:
12951 DECR_AND_STORE(23);
12952 /* Fall through */
12953 case 5:
12954 DECR_AND_STORE(22);
12955 /* Fall through */
12956 case 4:
12957 DECR_AND_STORE(21);
12958 /* Fall through */
12959 case 3:
12960 DECR_AND_STORE(20);
12961 /* Fall through */
12962 case 2:
12963 DECR_AND_STORE(19);
12964 /* Fall through */
12965 case 1:
12966 DECR_AND_STORE(18);
12969 if (do_s1) {
12970 DECR_AND_STORE(17);
12972 if (do_s0) {
12973 DECR_AND_STORE(16);
12976 switch (aregs) {
12977 case 0:
12978 case 4:
12979 case 8:
12980 case 12:
12981 case 14:
12982 astatic = 0;
12983 break;
12984 case 1:
12985 case 5:
12986 case 9:
12987 case 13:
12988 astatic = 1;
12989 break;
12990 case 2:
12991 case 6:
12992 case 10:
12993 astatic = 2;
12994 break;
12995 case 3:
12996 case 7:
12997 astatic = 3;
12998 break;
12999 case 11:
13000 astatic = 4;
13001 break;
13002 default:
13003 gen_reserved_instruction(ctx);
13004 return;
13007 if (astatic > 0) {
13008 DECR_AND_STORE(7);
13009 if (astatic > 1) {
13010 DECR_AND_STORE(6);
13011 if (astatic > 2) {
13012 DECR_AND_STORE(5);
13013 if (astatic > 3) {
13014 DECR_AND_STORE(4);
13019 #undef DECR_AND_STORE
13021 tcg_gen_movi_tl(t2, -framesize);
13022 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13023 tcg_temp_free(t0);
13024 tcg_temp_free(t1);
13025 tcg_temp_free(t2);
13028 static void gen_mips16_restore(DisasContext *ctx,
13029 int xsregs, int aregs,
13030 int do_ra, int do_s0, int do_s1,
13031 int framesize)
13033 int astatic;
13034 TCGv t0 = tcg_temp_new();
13035 TCGv t1 = tcg_temp_new();
13036 TCGv t2 = tcg_temp_new();
13038 tcg_gen_movi_tl(t2, framesize);
13039 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13041 #define DECR_AND_LOAD(reg) do { \
13042 tcg_gen_movi_tl(t2, -4); \
13043 gen_op_addr_add(ctx, t0, t0, t2); \
13044 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13045 gen_store_gpr(t1, reg); \
13046 } while (0)
13048 if (do_ra) {
13049 DECR_AND_LOAD(31);
13052 switch (xsregs) {
13053 case 7:
13054 DECR_AND_LOAD(30);
13055 /* Fall through */
13056 case 6:
13057 DECR_AND_LOAD(23);
13058 /* Fall through */
13059 case 5:
13060 DECR_AND_LOAD(22);
13061 /* Fall through */
13062 case 4:
13063 DECR_AND_LOAD(21);
13064 /* Fall through */
13065 case 3:
13066 DECR_AND_LOAD(20);
13067 /* Fall through */
13068 case 2:
13069 DECR_AND_LOAD(19);
13070 /* Fall through */
13071 case 1:
13072 DECR_AND_LOAD(18);
13075 if (do_s1) {
13076 DECR_AND_LOAD(17);
13078 if (do_s0) {
13079 DECR_AND_LOAD(16);
13082 switch (aregs) {
13083 case 0:
13084 case 4:
13085 case 8:
13086 case 12:
13087 case 14:
13088 astatic = 0;
13089 break;
13090 case 1:
13091 case 5:
13092 case 9:
13093 case 13:
13094 astatic = 1;
13095 break;
13096 case 2:
13097 case 6:
13098 case 10:
13099 astatic = 2;
13100 break;
13101 case 3:
13102 case 7:
13103 astatic = 3;
13104 break;
13105 case 11:
13106 astatic = 4;
13107 break;
13108 default:
13109 gen_reserved_instruction(ctx);
13110 return;
13113 if (astatic > 0) {
13114 DECR_AND_LOAD(7);
13115 if (astatic > 1) {
13116 DECR_AND_LOAD(6);
13117 if (astatic > 2) {
13118 DECR_AND_LOAD(5);
13119 if (astatic > 3) {
13120 DECR_AND_LOAD(4);
13125 #undef DECR_AND_LOAD
13127 tcg_gen_movi_tl(t2, framesize);
13128 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13129 tcg_temp_free(t0);
13130 tcg_temp_free(t1);
13131 tcg_temp_free(t2);
13134 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13135 int is_64_bit, int extended)
13137 TCGv t0;
13139 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13140 gen_reserved_instruction(ctx);
13141 return;
13144 t0 = tcg_temp_new();
13146 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13147 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13148 if (!is_64_bit) {
13149 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13152 tcg_temp_free(t0);
13155 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13156 int16_t offset)
13158 TCGv_i32 t0 = tcg_const_i32(op);
13159 TCGv t1 = tcg_temp_new();
13160 gen_base_offset_addr(ctx, t1, base, offset);
13161 gen_helper_cache(cpu_env, t1, t0);
13164 #if defined(TARGET_MIPS64)
13165 static void decode_i64_mips16(DisasContext *ctx,
13166 int ry, int funct, int16_t offset,
13167 int extended)
13169 switch (funct) {
13170 case I64_LDSP:
13171 check_insn(ctx, ISA_MIPS3);
13172 check_mips_64(ctx);
13173 offset = extended ? offset : offset << 3;
13174 gen_ld(ctx, OPC_LD, ry, 29, offset);
13175 break;
13176 case I64_SDSP:
13177 check_insn(ctx, ISA_MIPS3);
13178 check_mips_64(ctx);
13179 offset = extended ? offset : offset << 3;
13180 gen_st(ctx, OPC_SD, ry, 29, offset);
13181 break;
13182 case I64_SDRASP:
13183 check_insn(ctx, ISA_MIPS3);
13184 check_mips_64(ctx);
13185 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13186 gen_st(ctx, OPC_SD, 31, 29, offset);
13187 break;
13188 case I64_DADJSP:
13189 check_insn(ctx, ISA_MIPS3);
13190 check_mips_64(ctx);
13191 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13192 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13193 break;
13194 case I64_LDPC:
13195 check_insn(ctx, ISA_MIPS3);
13196 check_mips_64(ctx);
13197 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13198 gen_reserved_instruction(ctx);
13199 } else {
13200 offset = extended ? offset : offset << 3;
13201 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13203 break;
13204 case I64_DADDIU5:
13205 check_insn(ctx, ISA_MIPS3);
13206 check_mips_64(ctx);
13207 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13208 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13209 break;
13210 case I64_DADDIUPC:
13211 check_insn(ctx, ISA_MIPS3);
13212 check_mips_64(ctx);
13213 offset = extended ? offset : offset << 2;
13214 gen_addiupc(ctx, ry, offset, 1, extended);
13215 break;
13216 case I64_DADDIUSP:
13217 check_insn(ctx, ISA_MIPS3);
13218 check_mips_64(ctx);
13219 offset = extended ? offset : offset << 2;
13220 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13221 break;
13224 #endif
13226 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13228 int extend = translator_lduw(env, ctx->base.pc_next + 2);
13229 int op, rx, ry, funct, sa;
13230 int16_t imm, offset;
13232 ctx->opcode = (ctx->opcode << 16) | extend;
13233 op = (ctx->opcode >> 11) & 0x1f;
13234 sa = (ctx->opcode >> 22) & 0x1f;
13235 funct = (ctx->opcode >> 8) & 0x7;
13236 rx = xlat((ctx->opcode >> 8) & 0x7);
13237 ry = xlat((ctx->opcode >> 5) & 0x7);
13238 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13239 | ((ctx->opcode >> 21) & 0x3f) << 5
13240 | (ctx->opcode & 0x1f));
13243 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13244 * counterparts.
13246 switch (op) {
13247 case M16_OPC_ADDIUSP:
13248 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13249 break;
13250 case M16_OPC_ADDIUPC:
13251 gen_addiupc(ctx, rx, imm, 0, 1);
13252 break;
13253 case M16_OPC_B:
13254 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13255 /* No delay slot, so just process as a normal instruction */
13256 break;
13257 case M16_OPC_BEQZ:
13258 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13259 /* No delay slot, so just process as a normal instruction */
13260 break;
13261 case M16_OPC_BNEQZ:
13262 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13263 /* No delay slot, so just process as a normal instruction */
13264 break;
13265 case M16_OPC_SHIFT:
13266 switch (ctx->opcode & 0x3) {
13267 case 0x0:
13268 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13269 break;
13270 case 0x1:
13271 #if defined(TARGET_MIPS64)
13272 check_mips_64(ctx);
13273 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13274 #else
13275 gen_reserved_instruction(ctx);
13276 #endif
13277 break;
13278 case 0x2:
13279 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13280 break;
13281 case 0x3:
13282 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13283 break;
13285 break;
13286 #if defined(TARGET_MIPS64)
13287 case M16_OPC_LD:
13288 check_insn(ctx, ISA_MIPS3);
13289 check_mips_64(ctx);
13290 gen_ld(ctx, OPC_LD, ry, rx, offset);
13291 break;
13292 #endif
13293 case M16_OPC_RRIA:
13294 imm = ctx->opcode & 0xf;
13295 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13296 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13297 imm = (int16_t) (imm << 1) >> 1;
13298 if ((ctx->opcode >> 4) & 0x1) {
13299 #if defined(TARGET_MIPS64)
13300 check_mips_64(ctx);
13301 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13302 #else
13303 gen_reserved_instruction(ctx);
13304 #endif
13305 } else {
13306 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13308 break;
13309 case M16_OPC_ADDIU8:
13310 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13311 break;
13312 case M16_OPC_SLTI:
13313 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13314 break;
13315 case M16_OPC_SLTIU:
13316 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13317 break;
13318 case M16_OPC_I8:
13319 switch (funct) {
13320 case I8_BTEQZ:
13321 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13322 break;
13323 case I8_BTNEZ:
13324 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13325 break;
13326 case I8_SWRASP:
13327 gen_st(ctx, OPC_SW, 31, 29, imm);
13328 break;
13329 case I8_ADJSP:
13330 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13331 break;
13332 case I8_SVRS:
13333 check_insn(ctx, ISA_MIPS_R1);
13335 int xsregs = (ctx->opcode >> 24) & 0x7;
13336 int aregs = (ctx->opcode >> 16) & 0xf;
13337 int do_ra = (ctx->opcode >> 6) & 0x1;
13338 int do_s0 = (ctx->opcode >> 5) & 0x1;
13339 int do_s1 = (ctx->opcode >> 4) & 0x1;
13340 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13341 | (ctx->opcode & 0xf)) << 3;
13343 if (ctx->opcode & (1 << 7)) {
13344 gen_mips16_save(ctx, xsregs, aregs,
13345 do_ra, do_s0, do_s1,
13346 framesize);
13347 } else {
13348 gen_mips16_restore(ctx, xsregs, aregs,
13349 do_ra, do_s0, do_s1,
13350 framesize);
13353 break;
13354 default:
13355 gen_reserved_instruction(ctx);
13356 break;
13358 break;
13359 case M16_OPC_LI:
13360 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13361 break;
13362 case M16_OPC_CMPI:
13363 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13364 break;
13365 #if defined(TARGET_MIPS64)
13366 case M16_OPC_SD:
13367 check_insn(ctx, ISA_MIPS3);
13368 check_mips_64(ctx);
13369 gen_st(ctx, OPC_SD, ry, rx, offset);
13370 break;
13371 #endif
13372 case M16_OPC_LB:
13373 gen_ld(ctx, OPC_LB, ry, rx, offset);
13374 break;
13375 case M16_OPC_LH:
13376 gen_ld(ctx, OPC_LH, ry, rx, offset);
13377 break;
13378 case M16_OPC_LWSP:
13379 gen_ld(ctx, OPC_LW, rx, 29, offset);
13380 break;
13381 case M16_OPC_LW:
13382 gen_ld(ctx, OPC_LW, ry, rx, offset);
13383 break;
13384 case M16_OPC_LBU:
13385 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13386 break;
13387 case M16_OPC_LHU:
13388 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13389 break;
13390 case M16_OPC_LWPC:
13391 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13392 break;
13393 #if defined(TARGET_MIPS64)
13394 case M16_OPC_LWU:
13395 check_insn(ctx, ISA_MIPS3);
13396 check_mips_64(ctx);
13397 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13398 break;
13399 #endif
13400 case M16_OPC_SB:
13401 gen_st(ctx, OPC_SB, ry, rx, offset);
13402 break;
13403 case M16_OPC_SH:
13404 gen_st(ctx, OPC_SH, ry, rx, offset);
13405 break;
13406 case M16_OPC_SWSP:
13407 gen_st(ctx, OPC_SW, rx, 29, offset);
13408 break;
13409 case M16_OPC_SW:
13410 gen_st(ctx, OPC_SW, ry, rx, offset);
13411 break;
13412 #if defined(TARGET_MIPS64)
13413 case M16_OPC_I64:
13414 decode_i64_mips16(ctx, ry, funct, offset, 1);
13415 break;
13416 #endif
13417 default:
13418 gen_reserved_instruction(ctx);
13419 break;
13422 return 4;
13425 static inline bool is_uhi(int sdbbp_code)
13427 #ifdef CONFIG_USER_ONLY
13428 return false;
13429 #else
13430 return semihosting_enabled() && sdbbp_code == 1;
13431 #endif
13434 #ifdef CONFIG_USER_ONLY
13435 /* The above should dead-code away any calls to this..*/
13436 static inline void gen_helper_do_semihosting(void *env)
13438 g_assert_not_reached();
13440 #endif
13442 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13444 int rx, ry;
13445 int sa;
13446 int op, cnvt_op, op1, offset;
13447 int funct;
13448 int n_bytes;
13450 op = (ctx->opcode >> 11) & 0x1f;
13451 sa = (ctx->opcode >> 2) & 0x7;
13452 sa = sa == 0 ? 8 : sa;
13453 rx = xlat((ctx->opcode >> 8) & 0x7);
13454 cnvt_op = (ctx->opcode >> 5) & 0x7;
13455 ry = xlat((ctx->opcode >> 5) & 0x7);
13456 op1 = offset = ctx->opcode & 0x1f;
13458 n_bytes = 2;
13460 switch (op) {
13461 case M16_OPC_ADDIUSP:
13463 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13465 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13467 break;
13468 case M16_OPC_ADDIUPC:
13469 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13470 break;
13471 case M16_OPC_B:
13472 offset = (ctx->opcode & 0x7ff) << 1;
13473 offset = (int16_t)(offset << 4) >> 4;
13474 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13475 /* No delay slot, so just process as a normal instruction */
13476 break;
13477 case M16_OPC_JAL:
13478 offset = translator_lduw(env, ctx->base.pc_next + 2);
13479 offset = (((ctx->opcode & 0x1f) << 21)
13480 | ((ctx->opcode >> 5) & 0x1f) << 16
13481 | offset) << 2;
13482 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13483 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13484 n_bytes = 4;
13485 break;
13486 case M16_OPC_BEQZ:
13487 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13488 ((int8_t)ctx->opcode) << 1, 0);
13489 /* No delay slot, so just process as a normal instruction */
13490 break;
13491 case M16_OPC_BNEQZ:
13492 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13493 ((int8_t)ctx->opcode) << 1, 0);
13494 /* No delay slot, so just process as a normal instruction */
13495 break;
13496 case M16_OPC_SHIFT:
13497 switch (ctx->opcode & 0x3) {
13498 case 0x0:
13499 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13500 break;
13501 case 0x1:
13502 #if defined(TARGET_MIPS64)
13503 check_insn(ctx, ISA_MIPS3);
13504 check_mips_64(ctx);
13505 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13506 #else
13507 gen_reserved_instruction(ctx);
13508 #endif
13509 break;
13510 case 0x2:
13511 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13512 break;
13513 case 0x3:
13514 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13515 break;
13517 break;
13518 #if defined(TARGET_MIPS64)
13519 case M16_OPC_LD:
13520 check_insn(ctx, ISA_MIPS3);
13521 check_mips_64(ctx);
13522 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13523 break;
13524 #endif
13525 case M16_OPC_RRIA:
13527 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13529 if ((ctx->opcode >> 4) & 1) {
13530 #if defined(TARGET_MIPS64)
13531 check_insn(ctx, ISA_MIPS3);
13532 check_mips_64(ctx);
13533 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13534 #else
13535 gen_reserved_instruction(ctx);
13536 #endif
13537 } else {
13538 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13541 break;
13542 case M16_OPC_ADDIU8:
13544 int16_t imm = (int8_t) ctx->opcode;
13546 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13548 break;
13549 case M16_OPC_SLTI:
13551 int16_t imm = (uint8_t) ctx->opcode;
13552 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13554 break;
13555 case M16_OPC_SLTIU:
13557 int16_t imm = (uint8_t) ctx->opcode;
13558 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13560 break;
13561 case M16_OPC_I8:
13563 int reg32;
13565 funct = (ctx->opcode >> 8) & 0x7;
13566 switch (funct) {
13567 case I8_BTEQZ:
13568 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13569 ((int8_t)ctx->opcode) << 1, 0);
13570 break;
13571 case I8_BTNEZ:
13572 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13573 ((int8_t)ctx->opcode) << 1, 0);
13574 break;
13575 case I8_SWRASP:
13576 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13577 break;
13578 case I8_ADJSP:
13579 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13580 ((int8_t)ctx->opcode) << 3);
13581 break;
13582 case I8_SVRS:
13583 check_insn(ctx, ISA_MIPS_R1);
13585 int do_ra = ctx->opcode & (1 << 6);
13586 int do_s0 = ctx->opcode & (1 << 5);
13587 int do_s1 = ctx->opcode & (1 << 4);
13588 int framesize = ctx->opcode & 0xf;
13590 if (framesize == 0) {
13591 framesize = 128;
13592 } else {
13593 framesize = framesize << 3;
13596 if (ctx->opcode & (1 << 7)) {
13597 gen_mips16_save(ctx, 0, 0,
13598 do_ra, do_s0, do_s1, framesize);
13599 } else {
13600 gen_mips16_restore(ctx, 0, 0,
13601 do_ra, do_s0, do_s1, framesize);
13604 break;
13605 case I8_MOV32R:
13607 int rz = xlat(ctx->opcode & 0x7);
13609 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13610 ((ctx->opcode >> 5) & 0x7);
13611 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13613 break;
13614 case I8_MOVR32:
13615 reg32 = ctx->opcode & 0x1f;
13616 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13617 break;
13618 default:
13619 gen_reserved_instruction(ctx);
13620 break;
13623 break;
13624 case M16_OPC_LI:
13626 int16_t imm = (uint8_t) ctx->opcode;
13628 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13630 break;
13631 case M16_OPC_CMPI:
13633 int16_t imm = (uint8_t) ctx->opcode;
13634 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13636 break;
13637 #if defined(TARGET_MIPS64)
13638 case M16_OPC_SD:
13639 check_insn(ctx, ISA_MIPS3);
13640 check_mips_64(ctx);
13641 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13642 break;
13643 #endif
13644 case M16_OPC_LB:
13645 gen_ld(ctx, OPC_LB, ry, rx, offset);
13646 break;
13647 case M16_OPC_LH:
13648 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13649 break;
13650 case M16_OPC_LWSP:
13651 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13652 break;
13653 case M16_OPC_LW:
13654 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13655 break;
13656 case M16_OPC_LBU:
13657 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13658 break;
13659 case M16_OPC_LHU:
13660 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13661 break;
13662 case M16_OPC_LWPC:
13663 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13664 break;
13665 #if defined(TARGET_MIPS64)
13666 case M16_OPC_LWU:
13667 check_insn(ctx, ISA_MIPS3);
13668 check_mips_64(ctx);
13669 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13670 break;
13671 #endif
13672 case M16_OPC_SB:
13673 gen_st(ctx, OPC_SB, ry, rx, offset);
13674 break;
13675 case M16_OPC_SH:
13676 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13677 break;
13678 case M16_OPC_SWSP:
13679 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13680 break;
13681 case M16_OPC_SW:
13682 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13683 break;
13684 case M16_OPC_RRR:
13686 int rz = xlat((ctx->opcode >> 2) & 0x7);
13687 int mips32_op;
13689 switch (ctx->opcode & 0x3) {
13690 case RRR_ADDU:
13691 mips32_op = OPC_ADDU;
13692 break;
13693 case RRR_SUBU:
13694 mips32_op = OPC_SUBU;
13695 break;
13696 #if defined(TARGET_MIPS64)
13697 case RRR_DADDU:
13698 mips32_op = OPC_DADDU;
13699 check_insn(ctx, ISA_MIPS3);
13700 check_mips_64(ctx);
13701 break;
13702 case RRR_DSUBU:
13703 mips32_op = OPC_DSUBU;
13704 check_insn(ctx, ISA_MIPS3);
13705 check_mips_64(ctx);
13706 break;
13707 #endif
13708 default:
13709 gen_reserved_instruction(ctx);
13710 goto done;
13713 gen_arith(ctx, mips32_op, rz, rx, ry);
13714 done:
13717 break;
13718 case M16_OPC_RR:
13719 switch (op1) {
13720 case RR_JR:
13722 int nd = (ctx->opcode >> 7) & 0x1;
13723 int link = (ctx->opcode >> 6) & 0x1;
13724 int ra = (ctx->opcode >> 5) & 0x1;
13726 if (nd) {
13727 check_insn(ctx, ISA_MIPS_R1);
13730 if (link) {
13731 op = OPC_JALR;
13732 } else {
13733 op = OPC_JR;
13736 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13737 (nd ? 0 : 2));
13739 break;
13740 case RR_SDBBP:
13741 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13742 gen_helper_do_semihosting(cpu_env);
13743 } else {
13745 * XXX: not clear which exception should be raised
13746 * when in debug mode...
13748 check_insn(ctx, ISA_MIPS_R1);
13749 generate_exception_end(ctx, EXCP_DBp);
13751 break;
13752 case RR_SLT:
13753 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13754 break;
13755 case RR_SLTU:
13756 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13757 break;
13758 case RR_BREAK:
13759 generate_exception_end(ctx, EXCP_BREAK);
13760 break;
13761 case RR_SLLV:
13762 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13763 break;
13764 case RR_SRLV:
13765 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13766 break;
13767 case RR_SRAV:
13768 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13769 break;
13770 #if defined(TARGET_MIPS64)
13771 case RR_DSRL:
13772 check_insn(ctx, ISA_MIPS3);
13773 check_mips_64(ctx);
13774 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13775 break;
13776 #endif
13777 case RR_CMP:
13778 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13779 break;
13780 case RR_NEG:
13781 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13782 break;
13783 case RR_AND:
13784 gen_logic(ctx, OPC_AND, rx, rx, ry);
13785 break;
13786 case RR_OR:
13787 gen_logic(ctx, OPC_OR, rx, rx, ry);
13788 break;
13789 case RR_XOR:
13790 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13791 break;
13792 case RR_NOT:
13793 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13794 break;
13795 case RR_MFHI:
13796 gen_HILO(ctx, OPC_MFHI, 0, rx);
13797 break;
13798 case RR_CNVT:
13799 check_insn(ctx, ISA_MIPS_R1);
13800 switch (cnvt_op) {
13801 case RR_RY_CNVT_ZEB:
13802 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13803 break;
13804 case RR_RY_CNVT_ZEH:
13805 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13806 break;
13807 case RR_RY_CNVT_SEB:
13808 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13809 break;
13810 case RR_RY_CNVT_SEH:
13811 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13812 break;
13813 #if defined(TARGET_MIPS64)
13814 case RR_RY_CNVT_ZEW:
13815 check_insn(ctx, ISA_MIPS_R1);
13816 check_mips_64(ctx);
13817 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13818 break;
13819 case RR_RY_CNVT_SEW:
13820 check_insn(ctx, ISA_MIPS_R1);
13821 check_mips_64(ctx);
13822 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13823 break;
13824 #endif
13825 default:
13826 gen_reserved_instruction(ctx);
13827 break;
13829 break;
13830 case RR_MFLO:
13831 gen_HILO(ctx, OPC_MFLO, 0, rx);
13832 break;
13833 #if defined(TARGET_MIPS64)
13834 case RR_DSRA:
13835 check_insn(ctx, ISA_MIPS3);
13836 check_mips_64(ctx);
13837 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13838 break;
13839 case RR_DSLLV:
13840 check_insn(ctx, ISA_MIPS3);
13841 check_mips_64(ctx);
13842 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13843 break;
13844 case RR_DSRLV:
13845 check_insn(ctx, ISA_MIPS3);
13846 check_mips_64(ctx);
13847 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13848 break;
13849 case RR_DSRAV:
13850 check_insn(ctx, ISA_MIPS3);
13851 check_mips_64(ctx);
13852 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13853 break;
13854 #endif
13855 case RR_MULT:
13856 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13857 break;
13858 case RR_MULTU:
13859 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13860 break;
13861 case RR_DIV:
13862 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13863 break;
13864 case RR_DIVU:
13865 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13866 break;
13867 #if defined(TARGET_MIPS64)
13868 case RR_DMULT:
13869 check_insn(ctx, ISA_MIPS3);
13870 check_mips_64(ctx);
13871 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13872 break;
13873 case RR_DMULTU:
13874 check_insn(ctx, ISA_MIPS3);
13875 check_mips_64(ctx);
13876 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13877 break;
13878 case RR_DDIV:
13879 check_insn(ctx, ISA_MIPS3);
13880 check_mips_64(ctx);
13881 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13882 break;
13883 case RR_DDIVU:
13884 check_insn(ctx, ISA_MIPS3);
13885 check_mips_64(ctx);
13886 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13887 break;
13888 #endif
13889 default:
13890 gen_reserved_instruction(ctx);
13891 break;
13893 break;
13894 case M16_OPC_EXTEND:
13895 decode_extended_mips16_opc(env, ctx);
13896 n_bytes = 4;
13897 break;
13898 #if defined(TARGET_MIPS64)
13899 case M16_OPC_I64:
13900 funct = (ctx->opcode >> 8) & 0x7;
13901 decode_i64_mips16(ctx, ry, funct, offset, 0);
13902 break;
13903 #endif
13904 default:
13905 gen_reserved_instruction(ctx);
13906 break;
13909 return n_bytes;
13912 /* microMIPS extension to MIPS32/MIPS64 */
13915 * microMIPS32/microMIPS64 major opcodes
13917 * 1. MIPS Architecture for Programmers Volume II-B:
13918 * The microMIPS32 Instruction Set (Revision 3.05)
13920 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13922 * 2. MIPS Architecture For Programmers Volume II-A:
13923 * The MIPS64 Instruction Set (Revision 3.51)
13926 enum {
13927 POOL32A = 0x00,
13928 POOL16A = 0x01,
13929 LBU16 = 0x02,
13930 MOVE16 = 0x03,
13931 ADDI32 = 0x04,
13932 R6_LUI = 0x04,
13933 AUI = 0x04,
13934 LBU32 = 0x05,
13935 SB32 = 0x06,
13936 LB32 = 0x07,
13938 POOL32B = 0x08,
13939 POOL16B = 0x09,
13940 LHU16 = 0x0a,
13941 ANDI16 = 0x0b,
13942 ADDIU32 = 0x0c,
13943 LHU32 = 0x0d,
13944 SH32 = 0x0e,
13945 LH32 = 0x0f,
13947 POOL32I = 0x10,
13948 POOL16C = 0x11,
13949 LWSP16 = 0x12,
13950 POOL16D = 0x13,
13951 ORI32 = 0x14,
13952 POOL32F = 0x15,
13953 POOL32S = 0x16, /* MIPS64 */
13954 DADDIU32 = 0x17, /* MIPS64 */
13956 POOL32C = 0x18,
13957 LWGP16 = 0x19,
13958 LW16 = 0x1a,
13959 POOL16E = 0x1b,
13960 XORI32 = 0x1c,
13961 JALS32 = 0x1d,
13962 BOVC = 0x1d,
13963 BEQC = 0x1d,
13964 BEQZALC = 0x1d,
13965 ADDIUPC = 0x1e,
13966 PCREL = 0x1e,
13967 BNVC = 0x1f,
13968 BNEC = 0x1f,
13969 BNEZALC = 0x1f,
13971 R6_BEQZC = 0x20,
13972 JIC = 0x20,
13973 POOL16F = 0x21,
13974 SB16 = 0x22,
13975 BEQZ16 = 0x23,
13976 BEQZC16 = 0x23,
13977 SLTI32 = 0x24,
13978 BEQ32 = 0x25,
13979 BC = 0x25,
13980 SWC132 = 0x26,
13981 LWC132 = 0x27,
13983 /* 0x29 is reserved */
13984 RES_29 = 0x29,
13985 R6_BNEZC = 0x28,
13986 JIALC = 0x28,
13987 SH16 = 0x2a,
13988 BNEZ16 = 0x2b,
13989 BNEZC16 = 0x2b,
13990 SLTIU32 = 0x2c,
13991 BNE32 = 0x2d,
13992 BALC = 0x2d,
13993 SDC132 = 0x2e,
13994 LDC132 = 0x2f,
13996 /* 0x31 is reserved */
13997 RES_31 = 0x31,
13998 BLEZALC = 0x30,
13999 BGEZALC = 0x30,
14000 BGEUC = 0x30,
14001 SWSP16 = 0x32,
14002 B16 = 0x33,
14003 BC16 = 0x33,
14004 ANDI32 = 0x34,
14005 J32 = 0x35,
14006 BGTZC = 0x35,
14007 BLTZC = 0x35,
14008 BLTC = 0x35,
14009 SD32 = 0x36, /* MIPS64 */
14010 LD32 = 0x37, /* MIPS64 */
14012 /* 0x39 is reserved */
14013 RES_39 = 0x39,
14014 BGTZALC = 0x38,
14015 BLTZALC = 0x38,
14016 BLTUC = 0x38,
14017 SW16 = 0x3a,
14018 LI16 = 0x3b,
14019 JALX32 = 0x3c,
14020 JAL32 = 0x3d,
14021 BLEZC = 0x3d,
14022 BGEZC = 0x3d,
14023 BGEC = 0x3d,
14024 SW32 = 0x3e,
14025 LW32 = 0x3f
14028 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14029 enum {
14030 ADDIUPC_00 = 0x00,
14031 ADDIUPC_01 = 0x01,
14032 ADDIUPC_02 = 0x02,
14033 ADDIUPC_03 = 0x03,
14034 ADDIUPC_04 = 0x04,
14035 ADDIUPC_05 = 0x05,
14036 ADDIUPC_06 = 0x06,
14037 ADDIUPC_07 = 0x07,
14038 AUIPC = 0x1e,
14039 ALUIPC = 0x1f,
14040 LWPC_08 = 0x08,
14041 LWPC_09 = 0x09,
14042 LWPC_0A = 0x0A,
14043 LWPC_0B = 0x0B,
14044 LWPC_0C = 0x0C,
14045 LWPC_0D = 0x0D,
14046 LWPC_0E = 0x0E,
14047 LWPC_0F = 0x0F,
14050 /* POOL32A encoding of minor opcode field */
14052 enum {
14054 * These opcodes are distinguished only by bits 9..6; those bits are
14055 * what are recorded below.
14057 SLL32 = 0x0,
14058 SRL32 = 0x1,
14059 SRA = 0x2,
14060 ROTR = 0x3,
14061 SELEQZ = 0x5,
14062 SELNEZ = 0x6,
14063 R6_RDHWR = 0x7,
14065 SLLV = 0x0,
14066 SRLV = 0x1,
14067 SRAV = 0x2,
14068 ROTRV = 0x3,
14069 ADD = 0x4,
14070 ADDU32 = 0x5,
14071 SUB = 0x6,
14072 SUBU32 = 0x7,
14073 MUL = 0x8,
14074 AND = 0x9,
14075 OR32 = 0xa,
14076 NOR = 0xb,
14077 XOR32 = 0xc,
14078 SLT = 0xd,
14079 SLTU = 0xe,
14081 MOVN = 0x0,
14082 R6_MUL = 0x0,
14083 MOVZ = 0x1,
14084 MUH = 0x1,
14085 MULU = 0x2,
14086 MUHU = 0x3,
14087 LWXS = 0x4,
14088 R6_DIV = 0x4,
14089 MOD = 0x5,
14090 R6_DIVU = 0x6,
14091 MODU = 0x7,
14093 /* The following can be distinguished by their lower 6 bits. */
14094 BREAK32 = 0x07,
14095 INS = 0x0c,
14096 LSA = 0x0f,
14097 ALIGN = 0x1f,
14098 EXT = 0x2c,
14099 POOL32AXF = 0x3c,
14100 SIGRIE = 0x3f
14103 /* POOL32AXF encoding of minor opcode field extension */
14106 * 1. MIPS Architecture for Programmers Volume II-B:
14107 * The microMIPS32 Instruction Set (Revision 3.05)
14109 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14111 * 2. MIPS Architecture for Programmers VolumeIV-e:
14112 * The MIPS DSP Application-Specific Extension
14113 * to the microMIPS32 Architecture (Revision 2.34)
14115 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14118 enum {
14119 /* bits 11..6 */
14120 TEQ = 0x00,
14121 TGE = 0x08,
14122 TGEU = 0x10,
14123 TLT = 0x20,
14124 TLTU = 0x28,
14125 TNE = 0x30,
14127 MFC0 = 0x03,
14128 MTC0 = 0x0b,
14130 /* begin of microMIPS32 DSP */
14132 /* bits 13..12 for 0x01 */
14133 MFHI_ACC = 0x0,
14134 MFLO_ACC = 0x1,
14135 MTHI_ACC = 0x2,
14136 MTLO_ACC = 0x3,
14138 /* bits 13..12 for 0x2a */
14139 MADD_ACC = 0x0,
14140 MADDU_ACC = 0x1,
14141 MSUB_ACC = 0x2,
14142 MSUBU_ACC = 0x3,
14144 /* bits 13..12 for 0x32 */
14145 MULT_ACC = 0x0,
14146 MULTU_ACC = 0x1,
14148 /* end of microMIPS32 DSP */
14150 /* bits 15..12 for 0x2c */
14151 BITSWAP = 0x0,
14152 SEB = 0x2,
14153 SEH = 0x3,
14154 CLO = 0x4,
14155 CLZ = 0x5,
14156 RDHWR = 0x6,
14157 WSBH = 0x7,
14158 MULT = 0x8,
14159 MULTU = 0x9,
14160 DIV = 0xa,
14161 DIVU = 0xb,
14162 MADD = 0xc,
14163 MADDU = 0xd,
14164 MSUB = 0xe,
14165 MSUBU = 0xf,
14167 /* bits 15..12 for 0x34 */
14168 MFC2 = 0x4,
14169 MTC2 = 0x5,
14170 MFHC2 = 0x8,
14171 MTHC2 = 0x9,
14172 CFC2 = 0xc,
14173 CTC2 = 0xd,
14175 /* bits 15..12 for 0x3c */
14176 JALR = 0x0,
14177 JR = 0x0, /* alias */
14178 JALRC = 0x0,
14179 JRC = 0x0,
14180 JALR_HB = 0x1,
14181 JALRC_HB = 0x1,
14182 JALRS = 0x4,
14183 JALRS_HB = 0x5,
14185 /* bits 15..12 for 0x05 */
14186 RDPGPR = 0xe,
14187 WRPGPR = 0xf,
14189 /* bits 15..12 for 0x0d */
14190 TLBP = 0x0,
14191 TLBR = 0x1,
14192 TLBWI = 0x2,
14193 TLBWR = 0x3,
14194 TLBINV = 0x4,
14195 TLBINVF = 0x5,
14196 WAIT = 0x9,
14197 IRET = 0xd,
14198 DERET = 0xe,
14199 ERET = 0xf,
14201 /* bits 15..12 for 0x15 */
14202 DMT = 0x0,
14203 DVPE = 0x1,
14204 EMT = 0x2,
14205 EVPE = 0x3,
14207 /* bits 15..12 for 0x1d */
14208 DI = 0x4,
14209 EI = 0x5,
14211 /* bits 15..12 for 0x2d */
14212 SYNC = 0x6,
14213 SYSCALL = 0x8,
14214 SDBBP = 0xd,
14216 /* bits 15..12 for 0x35 */
14217 MFHI32 = 0x0,
14218 MFLO32 = 0x1,
14219 MTHI32 = 0x2,
14220 MTLO32 = 0x3,
14223 /* POOL32B encoding of minor opcode field (bits 15..12) */
14225 enum {
14226 LWC2 = 0x0,
14227 LWP = 0x1,
14228 LDP = 0x4,
14229 LWM32 = 0x5,
14230 CACHE = 0x6,
14231 LDM = 0x7,
14232 SWC2 = 0x8,
14233 SWP = 0x9,
14234 SDP = 0xc,
14235 SWM32 = 0xd,
14236 SDM = 0xf
14239 /* POOL32C encoding of minor opcode field (bits 15..12) */
14241 enum {
14242 LWL = 0x0,
14243 SWL = 0x8,
14244 LWR = 0x1,
14245 SWR = 0x9,
14246 PREF = 0x2,
14247 ST_EVA = 0xa,
14248 LL = 0x3,
14249 SC = 0xb,
14250 LDL = 0x4,
14251 SDL = 0xc,
14252 LDR = 0x5,
14253 SDR = 0xd,
14254 LD_EVA = 0x6,
14255 LWU = 0xe,
14256 LLD = 0x7,
14257 SCD = 0xf
14260 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14262 enum {
14263 LBUE = 0x0,
14264 LHUE = 0x1,
14265 LWLE = 0x2,
14266 LWRE = 0x3,
14267 LBE = 0x4,
14268 LHE = 0x5,
14269 LLE = 0x6,
14270 LWE = 0x7,
14273 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14275 enum {
14276 SWLE = 0x0,
14277 SWRE = 0x1,
14278 PREFE = 0x2,
14279 CACHEE = 0x3,
14280 SBE = 0x4,
14281 SHE = 0x5,
14282 SCE = 0x6,
14283 SWE = 0x7,
14286 /* POOL32F encoding of minor opcode field (bits 5..0) */
14288 enum {
14289 /* These are the bit 7..6 values */
14290 ADD_FMT = 0x0,
14292 SUB_FMT = 0x1,
14294 MUL_FMT = 0x2,
14296 DIV_FMT = 0x3,
14298 /* These are the bit 8..6 values */
14299 MOVN_FMT = 0x0,
14300 RSQRT2_FMT = 0x0,
14301 MOVF_FMT = 0x0,
14302 RINT_FMT = 0x0,
14303 SELNEZ_FMT = 0x0,
14305 MOVZ_FMT = 0x1,
14306 LWXC1 = 0x1,
14307 MOVT_FMT = 0x1,
14308 CLASS_FMT = 0x1,
14309 SELEQZ_FMT = 0x1,
14311 PLL_PS = 0x2,
14312 SWXC1 = 0x2,
14313 SEL_FMT = 0x2,
14315 PLU_PS = 0x3,
14316 LDXC1 = 0x3,
14318 MOVN_FMT_04 = 0x4,
14319 PUL_PS = 0x4,
14320 SDXC1 = 0x4,
14321 RECIP2_FMT = 0x4,
14323 MOVZ_FMT_05 = 0x05,
14324 PUU_PS = 0x5,
14325 LUXC1 = 0x5,
14327 CVT_PS_S = 0x6,
14328 SUXC1 = 0x6,
14329 ADDR_PS = 0x6,
14330 PREFX = 0x6,
14331 MADDF_FMT = 0x6,
14333 MULR_PS = 0x7,
14334 MSUBF_FMT = 0x7,
14336 MADD_S = 0x01,
14337 MADD_D = 0x09,
14338 MADD_PS = 0x11,
14339 ALNV_PS = 0x19,
14340 MSUB_S = 0x21,
14341 MSUB_D = 0x29,
14342 MSUB_PS = 0x31,
14344 NMADD_S = 0x02,
14345 NMADD_D = 0x0a,
14346 NMADD_PS = 0x12,
14347 NMSUB_S = 0x22,
14348 NMSUB_D = 0x2a,
14349 NMSUB_PS = 0x32,
14351 MIN_FMT = 0x3,
14352 MAX_FMT = 0xb,
14353 MINA_FMT = 0x23,
14354 MAXA_FMT = 0x2b,
14355 POOL32FXF = 0x3b,
14357 CABS_COND_FMT = 0x1c, /* MIPS3D */
14358 C_COND_FMT = 0x3c,
14360 CMP_CONDN_S = 0x5,
14361 CMP_CONDN_D = 0x15
14364 /* POOL32Fxf encoding of minor opcode extension field */
14366 enum {
14367 CVT_L = 0x04,
14368 RSQRT_FMT = 0x08,
14369 FLOOR_L = 0x0c,
14370 CVT_PW_PS = 0x1c,
14371 CVT_W = 0x24,
14372 SQRT_FMT = 0x28,
14373 FLOOR_W = 0x2c,
14374 CVT_PS_PW = 0x3c,
14375 CFC1 = 0x40,
14376 RECIP_FMT = 0x48,
14377 CEIL_L = 0x4c,
14378 CTC1 = 0x60,
14379 CEIL_W = 0x6c,
14380 MFC1 = 0x80,
14381 CVT_S_PL = 0x84,
14382 TRUNC_L = 0x8c,
14383 MTC1 = 0xa0,
14384 CVT_S_PU = 0xa4,
14385 TRUNC_W = 0xac,
14386 MFHC1 = 0xc0,
14387 ROUND_L = 0xcc,
14388 MTHC1 = 0xe0,
14389 ROUND_W = 0xec,
14391 MOV_FMT = 0x01,
14392 MOVF = 0x05,
14393 ABS_FMT = 0x0d,
14394 RSQRT1_FMT = 0x1d,
14395 MOVT = 0x25,
14396 NEG_FMT = 0x2d,
14397 CVT_D = 0x4d,
14398 RECIP1_FMT = 0x5d,
14399 CVT_S = 0x6d
14402 /* POOL32I encoding of minor opcode field (bits 25..21) */
14404 enum {
14405 BLTZ = 0x00,
14406 BLTZAL = 0x01,
14407 BGEZ = 0x02,
14408 BGEZAL = 0x03,
14409 BLEZ = 0x04,
14410 BNEZC = 0x05,
14411 BGTZ = 0x06,
14412 BEQZC = 0x07,
14413 TLTI = 0x08,
14414 BC1EQZC = 0x08,
14415 TGEI = 0x09,
14416 BC1NEZC = 0x09,
14417 TLTIU = 0x0a,
14418 BC2EQZC = 0x0a,
14419 TGEIU = 0x0b,
14420 BC2NEZC = 0x0a,
14421 TNEI = 0x0c,
14422 R6_SYNCI = 0x0c,
14423 LUI = 0x0d,
14424 TEQI = 0x0e,
14425 SYNCI = 0x10,
14426 BLTZALS = 0x11,
14427 BGEZALS = 0x13,
14428 BC2F = 0x14,
14429 BC2T = 0x15,
14430 BPOSGE64 = 0x1a,
14431 BPOSGE32 = 0x1b,
14432 /* These overlap and are distinguished by bit16 of the instruction */
14433 BC1F = 0x1c,
14434 BC1T = 0x1d,
14435 BC1ANY2F = 0x1c,
14436 BC1ANY2T = 0x1d,
14437 BC1ANY4F = 0x1e,
14438 BC1ANY4T = 0x1f
14441 /* POOL16A encoding of minor opcode field */
14443 enum {
14444 ADDU16 = 0x0,
14445 SUBU16 = 0x1
14448 /* POOL16B encoding of minor opcode field */
14450 enum {
14451 SLL16 = 0x0,
14452 SRL16 = 0x1
14455 /* POOL16C encoding of minor opcode field */
14457 enum {
14458 NOT16 = 0x00,
14459 XOR16 = 0x04,
14460 AND16 = 0x08,
14461 OR16 = 0x0c,
14462 LWM16 = 0x10,
14463 SWM16 = 0x14,
14464 JR16 = 0x18,
14465 JRC16 = 0x1a,
14466 JALR16 = 0x1c,
14467 JALR16S = 0x1e,
14468 MFHI16 = 0x20,
14469 MFLO16 = 0x24,
14470 BREAK16 = 0x28,
14471 SDBBP16 = 0x2c,
14472 JRADDIUSP = 0x30
14475 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14477 enum {
14478 R6_NOT16 = 0x00,
14479 R6_AND16 = 0x01,
14480 R6_LWM16 = 0x02,
14481 R6_JRC16 = 0x03,
14482 MOVEP = 0x04,
14483 MOVEP_05 = 0x05,
14484 MOVEP_06 = 0x06,
14485 MOVEP_07 = 0x07,
14486 R6_XOR16 = 0x08,
14487 R6_OR16 = 0x09,
14488 R6_SWM16 = 0x0a,
14489 JALRC16 = 0x0b,
14490 MOVEP_0C = 0x0c,
14491 MOVEP_0D = 0x0d,
14492 MOVEP_0E = 0x0e,
14493 MOVEP_0F = 0x0f,
14494 JRCADDIUSP = 0x13,
14495 R6_BREAK16 = 0x1b,
14496 R6_SDBBP16 = 0x3b
14499 /* POOL16D encoding of minor opcode field */
14501 enum {
14502 ADDIUS5 = 0x0,
14503 ADDIUSP = 0x1
14506 /* POOL16E encoding of minor opcode field */
14508 enum {
14509 ADDIUR2 = 0x0,
14510 ADDIUR1SP = 0x1
14513 static int mmreg(int r)
14515 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14517 return map[r];
14520 /* Used for 16-bit store instructions. */
14521 static int mmreg2(int r)
14523 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14525 return map[r];
14528 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14529 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14530 #define uMIPS_RS2(op) uMIPS_RS(op)
14531 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14532 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14533 #define uMIPS_RS5(op) (op & 0x1f)
14535 /* Signed immediate */
14536 #define SIMM(op, start, width) \
14537 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
14538 << (32 - width)) \
14539 >> (32 - width))
14540 /* Zero-extended immediate */
14541 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
14543 static void gen_addiur1sp(DisasContext *ctx)
14545 int rd = mmreg(uMIPS_RD(ctx->opcode));
14547 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14550 static void gen_addiur2(DisasContext *ctx)
14552 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14553 int rd = mmreg(uMIPS_RD(ctx->opcode));
14554 int rs = mmreg(uMIPS_RS(ctx->opcode));
14556 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14559 static void gen_addiusp(DisasContext *ctx)
14561 int encoded = ZIMM(ctx->opcode, 1, 9);
14562 int decoded;
14564 if (encoded <= 1) {
14565 decoded = 256 + encoded;
14566 } else if (encoded <= 255) {
14567 decoded = encoded;
14568 } else if (encoded <= 509) {
14569 decoded = encoded - 512;
14570 } else {
14571 decoded = encoded - 768;
14574 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14577 static void gen_addius5(DisasContext *ctx)
14579 int imm = SIMM(ctx->opcode, 1, 4);
14580 int rd = (ctx->opcode >> 5) & 0x1f;
14582 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14585 static void gen_andi16(DisasContext *ctx)
14587 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14588 31, 32, 63, 64, 255, 32768, 65535 };
14589 int rd = mmreg(uMIPS_RD(ctx->opcode));
14590 int rs = mmreg(uMIPS_RS(ctx->opcode));
14591 int encoded = ZIMM(ctx->opcode, 0, 4);
14593 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14596 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
14597 int base, int16_t offset)
14599 TCGv t0, t1;
14600 TCGv_i32 t2;
14602 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14603 gen_reserved_instruction(ctx);
14604 return;
14607 t0 = tcg_temp_new();
14609 gen_base_offset_addr(ctx, t0, base, offset);
14611 t1 = tcg_const_tl(reglist);
14612 t2 = tcg_const_i32(ctx->mem_idx);
14614 save_cpu_state(ctx, 1);
14615 switch (opc) {
14616 case LWM32:
14617 gen_helper_lwm(cpu_env, t0, t1, t2);
14618 break;
14619 case SWM32:
14620 gen_helper_swm(cpu_env, t0, t1, t2);
14621 break;
14622 #ifdef TARGET_MIPS64
14623 case LDM:
14624 gen_helper_ldm(cpu_env, t0, t1, t2);
14625 break;
14626 case SDM:
14627 gen_helper_sdm(cpu_env, t0, t1, t2);
14628 break;
14629 #endif
14631 tcg_temp_free(t0);
14632 tcg_temp_free(t1);
14633 tcg_temp_free_i32(t2);
14637 static void gen_pool16c_insn(DisasContext *ctx)
14639 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14640 int rs = mmreg(ctx->opcode & 0x7);
14642 switch (((ctx->opcode) >> 4) & 0x3f) {
14643 case NOT16 + 0:
14644 case NOT16 + 1:
14645 case NOT16 + 2:
14646 case NOT16 + 3:
14647 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14648 break;
14649 case XOR16 + 0:
14650 case XOR16 + 1:
14651 case XOR16 + 2:
14652 case XOR16 + 3:
14653 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14654 break;
14655 case AND16 + 0:
14656 case AND16 + 1:
14657 case AND16 + 2:
14658 case AND16 + 3:
14659 gen_logic(ctx, OPC_AND, rd, rd, rs);
14660 break;
14661 case OR16 + 0:
14662 case OR16 + 1:
14663 case OR16 + 2:
14664 case OR16 + 3:
14665 gen_logic(ctx, OPC_OR, rd, rd, rs);
14666 break;
14667 case LWM16 + 0:
14668 case LWM16 + 1:
14669 case LWM16 + 2:
14670 case LWM16 + 3:
14672 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14673 int offset = ZIMM(ctx->opcode, 0, 4);
14675 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14676 29, offset << 2);
14678 break;
14679 case SWM16 + 0:
14680 case SWM16 + 1:
14681 case SWM16 + 2:
14682 case SWM16 + 3:
14684 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14685 int offset = ZIMM(ctx->opcode, 0, 4);
14687 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14688 29, offset << 2);
14690 break;
14691 case JR16 + 0:
14692 case JR16 + 1:
14694 int reg = ctx->opcode & 0x1f;
14696 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14698 break;
14699 case JRC16 + 0:
14700 case JRC16 + 1:
14702 int reg = ctx->opcode & 0x1f;
14703 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14705 * Let normal delay slot handling in our caller take us
14706 * to the branch target.
14709 break;
14710 case JALR16 + 0:
14711 case JALR16 + 1:
14712 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14713 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14714 break;
14715 case JALR16S + 0:
14716 case JALR16S + 1:
14717 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14718 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14719 break;
14720 case MFHI16 + 0:
14721 case MFHI16 + 1:
14722 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14723 break;
14724 case MFLO16 + 0:
14725 case MFLO16 + 1:
14726 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14727 break;
14728 case BREAK16:
14729 generate_exception_end(ctx, EXCP_BREAK);
14730 break;
14731 case SDBBP16:
14732 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14733 gen_helper_do_semihosting(cpu_env);
14734 } else {
14736 * XXX: not clear which exception should be raised
14737 * when in debug mode...
14739 check_insn(ctx, ISA_MIPS_R1);
14740 generate_exception_end(ctx, EXCP_DBp);
14742 break;
14743 case JRADDIUSP + 0:
14744 case JRADDIUSP + 1:
14746 int imm = ZIMM(ctx->opcode, 0, 5);
14747 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14748 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14750 * Let normal delay slot handling in our caller take us
14751 * to the branch target.
14754 break;
14755 default:
14756 gen_reserved_instruction(ctx);
14757 break;
14761 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14762 int enc_rs)
14764 int rd, re;
14765 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14766 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14767 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14769 rd = rd_enc[enc_dest];
14770 re = re_enc[enc_dest];
14771 gen_load_gpr(cpu_gpr[rd], rs_rt_enc[enc_rs]);
14772 gen_load_gpr(cpu_gpr[re], rs_rt_enc[enc_rt]);
14775 static void gen_pool16c_r6_insn(DisasContext *ctx)
14777 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14778 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14780 switch (ctx->opcode & 0xf) {
14781 case R6_NOT16:
14782 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14783 break;
14784 case R6_AND16:
14785 gen_logic(ctx, OPC_AND, rt, rt, rs);
14786 break;
14787 case R6_LWM16:
14789 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14790 int offset = extract32(ctx->opcode, 4, 4);
14791 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14793 break;
14794 case R6_JRC16: /* JRCADDIUSP */
14795 if ((ctx->opcode >> 4) & 1) {
14796 /* JRCADDIUSP */
14797 int imm = extract32(ctx->opcode, 5, 5);
14798 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14799 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14800 } else {
14801 /* JRC16 */
14802 rs = extract32(ctx->opcode, 5, 5);
14803 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14805 break;
14806 case MOVEP:
14807 case MOVEP_05:
14808 case MOVEP_06:
14809 case MOVEP_07:
14810 case MOVEP_0C:
14811 case MOVEP_0D:
14812 case MOVEP_0E:
14813 case MOVEP_0F:
14815 int enc_dest = uMIPS_RD(ctx->opcode);
14816 int enc_rt = uMIPS_RS2(ctx->opcode);
14817 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14818 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14820 break;
14821 case R6_XOR16:
14822 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14823 break;
14824 case R6_OR16:
14825 gen_logic(ctx, OPC_OR, rt, rt, rs);
14826 break;
14827 case R6_SWM16:
14829 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14830 int offset = extract32(ctx->opcode, 4, 4);
14831 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14833 break;
14834 case JALRC16: /* BREAK16, SDBBP16 */
14835 switch (ctx->opcode & 0x3f) {
14836 case JALRC16:
14837 case JALRC16 + 0x20:
14838 /* JALRC16 */
14839 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14840 31, 0, 0);
14841 break;
14842 case R6_BREAK16:
14843 /* BREAK16 */
14844 generate_exception(ctx, EXCP_BREAK);
14845 break;
14846 case R6_SDBBP16:
14847 /* SDBBP16 */
14848 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14849 gen_helper_do_semihosting(cpu_env);
14850 } else {
14851 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14852 generate_exception(ctx, EXCP_RI);
14853 } else {
14854 generate_exception(ctx, EXCP_DBp);
14857 break;
14859 break;
14860 default:
14861 generate_exception(ctx, EXCP_RI);
14862 break;
14866 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
14868 TCGv t0 = tcg_temp_new();
14869 TCGv t1 = tcg_temp_new();
14871 gen_load_gpr(t0, base);
14873 if (index != 0) {
14874 gen_load_gpr(t1, index);
14875 tcg_gen_shli_tl(t1, t1, 2);
14876 gen_op_addr_add(ctx, t0, t1, t0);
14879 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14880 gen_store_gpr(t1, rd);
14882 tcg_temp_free(t0);
14883 tcg_temp_free(t1);
14886 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
14887 int base, int16_t offset)
14889 TCGv t0, t1;
14891 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14892 gen_reserved_instruction(ctx);
14893 return;
14896 t0 = tcg_temp_new();
14897 t1 = tcg_temp_new();
14899 gen_base_offset_addr(ctx, t0, base, offset);
14901 switch (opc) {
14902 case LWP:
14903 if (rd == base) {
14904 gen_reserved_instruction(ctx);
14905 return;
14907 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14908 gen_store_gpr(t1, rd);
14909 tcg_gen_movi_tl(t1, 4);
14910 gen_op_addr_add(ctx, t0, t0, t1);
14911 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14912 gen_store_gpr(t1, rd + 1);
14913 break;
14914 case SWP:
14915 gen_load_gpr(t1, rd);
14916 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14917 tcg_gen_movi_tl(t1, 4);
14918 gen_op_addr_add(ctx, t0, t0, t1);
14919 gen_load_gpr(t1, rd + 1);
14920 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14921 break;
14922 #ifdef TARGET_MIPS64
14923 case LDP:
14924 if (rd == base) {
14925 gen_reserved_instruction(ctx);
14926 return;
14928 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14929 gen_store_gpr(t1, rd);
14930 tcg_gen_movi_tl(t1, 8);
14931 gen_op_addr_add(ctx, t0, t0, t1);
14932 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14933 gen_store_gpr(t1, rd + 1);
14934 break;
14935 case SDP:
14936 gen_load_gpr(t1, rd);
14937 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14938 tcg_gen_movi_tl(t1, 8);
14939 gen_op_addr_add(ctx, t0, t0, t1);
14940 gen_load_gpr(t1, rd + 1);
14941 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14942 break;
14943 #endif
14945 tcg_temp_free(t0);
14946 tcg_temp_free(t1);
14949 static void gen_sync(int stype)
14951 TCGBar tcg_mo = TCG_BAR_SC;
14953 switch (stype) {
14954 case 0x4: /* SYNC_WMB */
14955 tcg_mo |= TCG_MO_ST_ST;
14956 break;
14957 case 0x10: /* SYNC_MB */
14958 tcg_mo |= TCG_MO_ALL;
14959 break;
14960 case 0x11: /* SYNC_ACQUIRE */
14961 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14962 break;
14963 case 0x12: /* SYNC_RELEASE */
14964 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14965 break;
14966 case 0x13: /* SYNC_RMB */
14967 tcg_mo |= TCG_MO_LD_LD;
14968 break;
14969 default:
14970 tcg_mo |= TCG_MO_ALL;
14971 break;
14974 tcg_gen_mb(tcg_mo);
14977 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14979 int extension = (ctx->opcode >> 6) & 0x3f;
14980 int minor = (ctx->opcode >> 12) & 0xf;
14981 uint32_t mips32_op;
14983 switch (extension) {
14984 case TEQ:
14985 mips32_op = OPC_TEQ;
14986 goto do_trap;
14987 case TGE:
14988 mips32_op = OPC_TGE;
14989 goto do_trap;
14990 case TGEU:
14991 mips32_op = OPC_TGEU;
14992 goto do_trap;
14993 case TLT:
14994 mips32_op = OPC_TLT;
14995 goto do_trap;
14996 case TLTU:
14997 mips32_op = OPC_TLTU;
14998 goto do_trap;
14999 case TNE:
15000 mips32_op = OPC_TNE;
15001 do_trap:
15002 gen_trap(ctx, mips32_op, rs, rt, -1);
15003 break;
15004 #ifndef CONFIG_USER_ONLY
15005 case MFC0:
15006 case MFC0 + 32:
15007 check_cp0_enabled(ctx);
15008 if (rt == 0) {
15009 /* Treat as NOP. */
15010 break;
15012 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15013 break;
15014 case MTC0:
15015 case MTC0 + 32:
15016 check_cp0_enabled(ctx);
15018 TCGv t0 = tcg_temp_new();
15020 gen_load_gpr(t0, rt);
15021 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15022 tcg_temp_free(t0);
15024 break;
15025 #endif
15026 case 0x2a:
15027 switch (minor & 3) {
15028 case MADD_ACC:
15029 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15030 break;
15031 case MADDU_ACC:
15032 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15033 break;
15034 case MSUB_ACC:
15035 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15036 break;
15037 case MSUBU_ACC:
15038 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15039 break;
15040 default:
15041 goto pool32axf_invalid;
15043 break;
15044 case 0x32:
15045 switch (minor & 3) {
15046 case MULT_ACC:
15047 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15048 break;
15049 case MULTU_ACC:
15050 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15051 break;
15052 default:
15053 goto pool32axf_invalid;
15055 break;
15056 case 0x2c:
15057 switch (minor) {
15058 case BITSWAP:
15059 check_insn(ctx, ISA_MIPS_R6);
15060 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15061 break;
15062 case SEB:
15063 gen_bshfl(ctx, OPC_SEB, rs, rt);
15064 break;
15065 case SEH:
15066 gen_bshfl(ctx, OPC_SEH, rs, rt);
15067 break;
15068 case CLO:
15069 mips32_op = OPC_CLO;
15070 goto do_cl;
15071 case CLZ:
15072 mips32_op = OPC_CLZ;
15073 do_cl:
15074 check_insn(ctx, ISA_MIPS_R1);
15075 gen_cl(ctx, mips32_op, rt, rs);
15076 break;
15077 case RDHWR:
15078 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15079 gen_rdhwr(ctx, rt, rs, 0);
15080 break;
15081 case WSBH:
15082 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15083 break;
15084 case MULT:
15085 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15086 mips32_op = OPC_MULT;
15087 goto do_mul;
15088 case MULTU:
15089 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15090 mips32_op = OPC_MULTU;
15091 goto do_mul;
15092 case DIV:
15093 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15094 mips32_op = OPC_DIV;
15095 goto do_div;
15096 case DIVU:
15097 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15098 mips32_op = OPC_DIVU;
15099 goto do_div;
15100 do_div:
15101 check_insn(ctx, ISA_MIPS_R1);
15102 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15103 break;
15104 case MADD:
15105 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15106 mips32_op = OPC_MADD;
15107 goto do_mul;
15108 case MADDU:
15109 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15110 mips32_op = OPC_MADDU;
15111 goto do_mul;
15112 case MSUB:
15113 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15114 mips32_op = OPC_MSUB;
15115 goto do_mul;
15116 case MSUBU:
15117 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15118 mips32_op = OPC_MSUBU;
15119 do_mul:
15120 check_insn(ctx, ISA_MIPS_R1);
15121 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15122 break;
15123 default:
15124 goto pool32axf_invalid;
15126 break;
15127 case 0x34:
15128 switch (minor) {
15129 case MFC2:
15130 case MTC2:
15131 case MFHC2:
15132 case MTHC2:
15133 case CFC2:
15134 case CTC2:
15135 generate_exception_err(ctx, EXCP_CpU, 2);
15136 break;
15137 default:
15138 goto pool32axf_invalid;
15140 break;
15141 case 0x3c:
15142 switch (minor) {
15143 case JALR: /* JALRC */
15144 case JALR_HB: /* JALRC_HB */
15145 if (ctx->insn_flags & ISA_MIPS_R6) {
15146 /* JALRC, JALRC_HB */
15147 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15148 } else {
15149 /* JALR, JALR_HB */
15150 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15151 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15153 break;
15154 case JALRS:
15155 case JALRS_HB:
15156 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15157 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15158 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15159 break;
15160 default:
15161 goto pool32axf_invalid;
15163 break;
15164 case 0x05:
15165 switch (minor) {
15166 case RDPGPR:
15167 check_cp0_enabled(ctx);
15168 check_insn(ctx, ISA_MIPS_R2);
15169 gen_load_srsgpr(rs, rt);
15170 break;
15171 case WRPGPR:
15172 check_cp0_enabled(ctx);
15173 check_insn(ctx, ISA_MIPS_R2);
15174 gen_store_srsgpr(rs, rt);
15175 break;
15176 default:
15177 goto pool32axf_invalid;
15179 break;
15180 #ifndef CONFIG_USER_ONLY
15181 case 0x0d:
15182 switch (minor) {
15183 case TLBP:
15184 mips32_op = OPC_TLBP;
15185 goto do_cp0;
15186 case TLBR:
15187 mips32_op = OPC_TLBR;
15188 goto do_cp0;
15189 case TLBWI:
15190 mips32_op = OPC_TLBWI;
15191 goto do_cp0;
15192 case TLBWR:
15193 mips32_op = OPC_TLBWR;
15194 goto do_cp0;
15195 case TLBINV:
15196 mips32_op = OPC_TLBINV;
15197 goto do_cp0;
15198 case TLBINVF:
15199 mips32_op = OPC_TLBINVF;
15200 goto do_cp0;
15201 case WAIT:
15202 mips32_op = OPC_WAIT;
15203 goto do_cp0;
15204 case DERET:
15205 mips32_op = OPC_DERET;
15206 goto do_cp0;
15207 case ERET:
15208 mips32_op = OPC_ERET;
15209 do_cp0:
15210 gen_cp0(env, ctx, mips32_op, rt, rs);
15211 break;
15212 default:
15213 goto pool32axf_invalid;
15215 break;
15216 case 0x1d:
15217 switch (minor) {
15218 case DI:
15219 check_cp0_enabled(ctx);
15221 TCGv t0 = tcg_temp_new();
15223 save_cpu_state(ctx, 1);
15224 gen_helper_di(t0, cpu_env);
15225 gen_store_gpr(t0, rs);
15227 * Stop translation as we may have switched the execution
15228 * mode.
15230 ctx->base.is_jmp = DISAS_STOP;
15231 tcg_temp_free(t0);
15233 break;
15234 case EI:
15235 check_cp0_enabled(ctx);
15237 TCGv t0 = tcg_temp_new();
15239 save_cpu_state(ctx, 1);
15240 gen_helper_ei(t0, cpu_env);
15241 gen_store_gpr(t0, rs);
15243 * DISAS_STOP isn't sufficient, we need to ensure we break out
15244 * of translated code to check for pending interrupts.
15246 gen_save_pc(ctx->base.pc_next + 4);
15247 ctx->base.is_jmp = DISAS_EXIT;
15248 tcg_temp_free(t0);
15250 break;
15251 default:
15252 goto pool32axf_invalid;
15254 break;
15255 #endif
15256 case 0x2d:
15257 switch (minor) {
15258 case SYNC:
15259 gen_sync(extract32(ctx->opcode, 16, 5));
15260 break;
15261 case SYSCALL:
15262 generate_exception_end(ctx, EXCP_SYSCALL);
15263 break;
15264 case SDBBP:
15265 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15266 gen_helper_do_semihosting(cpu_env);
15267 } else {
15268 check_insn(ctx, ISA_MIPS_R1);
15269 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15270 gen_reserved_instruction(ctx);
15271 } else {
15272 generate_exception_end(ctx, EXCP_DBp);
15275 break;
15276 default:
15277 goto pool32axf_invalid;
15279 break;
15280 case 0x01:
15281 switch (minor & 3) {
15282 case MFHI_ACC:
15283 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15284 break;
15285 case MFLO_ACC:
15286 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15287 break;
15288 case MTHI_ACC:
15289 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15290 break;
15291 case MTLO_ACC:
15292 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15293 break;
15294 default:
15295 goto pool32axf_invalid;
15297 break;
15298 case 0x35:
15299 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15300 switch (minor) {
15301 case MFHI32:
15302 gen_HILO(ctx, OPC_MFHI, 0, rs);
15303 break;
15304 case MFLO32:
15305 gen_HILO(ctx, OPC_MFLO, 0, rs);
15306 break;
15307 case MTHI32:
15308 gen_HILO(ctx, OPC_MTHI, 0, rs);
15309 break;
15310 case MTLO32:
15311 gen_HILO(ctx, OPC_MTLO, 0, rs);
15312 break;
15313 default:
15314 goto pool32axf_invalid;
15316 break;
15317 default:
15318 pool32axf_invalid:
15319 MIPS_INVAL("pool32axf");
15320 gen_reserved_instruction(ctx);
15321 break;
15326 * Values for microMIPS fmt field. Variable-width, depending on which
15327 * formats the instruction supports.
15329 enum {
15330 FMT_SD_S = 0,
15331 FMT_SD_D = 1,
15333 FMT_SDPS_S = 0,
15334 FMT_SDPS_D = 1,
15335 FMT_SDPS_PS = 2,
15337 FMT_SWL_S = 0,
15338 FMT_SWL_W = 1,
15339 FMT_SWL_L = 2,
15341 FMT_DWL_D = 0,
15342 FMT_DWL_W = 1,
15343 FMT_DWL_L = 2
15346 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15348 int extension = (ctx->opcode >> 6) & 0x3ff;
15349 uint32_t mips32_op;
15351 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
15352 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
15353 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
15355 switch (extension) {
15356 case FLOAT_1BIT_FMT(CFC1, 0):
15357 mips32_op = OPC_CFC1;
15358 goto do_cp1;
15359 case FLOAT_1BIT_FMT(CTC1, 0):
15360 mips32_op = OPC_CTC1;
15361 goto do_cp1;
15362 case FLOAT_1BIT_FMT(MFC1, 0):
15363 mips32_op = OPC_MFC1;
15364 goto do_cp1;
15365 case FLOAT_1BIT_FMT(MTC1, 0):
15366 mips32_op = OPC_MTC1;
15367 goto do_cp1;
15368 case FLOAT_1BIT_FMT(MFHC1, 0):
15369 mips32_op = OPC_MFHC1;
15370 goto do_cp1;
15371 case FLOAT_1BIT_FMT(MTHC1, 0):
15372 mips32_op = OPC_MTHC1;
15373 do_cp1:
15374 gen_cp1(ctx, mips32_op, rt, rs);
15375 break;
15377 /* Reciprocal square root */
15378 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15379 mips32_op = OPC_RSQRT_S;
15380 goto do_unaryfp;
15381 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15382 mips32_op = OPC_RSQRT_D;
15383 goto do_unaryfp;
15385 /* Square root */
15386 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15387 mips32_op = OPC_SQRT_S;
15388 goto do_unaryfp;
15389 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15390 mips32_op = OPC_SQRT_D;
15391 goto do_unaryfp;
15393 /* Reciprocal */
15394 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15395 mips32_op = OPC_RECIP_S;
15396 goto do_unaryfp;
15397 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15398 mips32_op = OPC_RECIP_D;
15399 goto do_unaryfp;
15401 /* Floor */
15402 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15403 mips32_op = OPC_FLOOR_L_S;
15404 goto do_unaryfp;
15405 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15406 mips32_op = OPC_FLOOR_L_D;
15407 goto do_unaryfp;
15408 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15409 mips32_op = OPC_FLOOR_W_S;
15410 goto do_unaryfp;
15411 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15412 mips32_op = OPC_FLOOR_W_D;
15413 goto do_unaryfp;
15415 /* Ceiling */
15416 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15417 mips32_op = OPC_CEIL_L_S;
15418 goto do_unaryfp;
15419 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15420 mips32_op = OPC_CEIL_L_D;
15421 goto do_unaryfp;
15422 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15423 mips32_op = OPC_CEIL_W_S;
15424 goto do_unaryfp;
15425 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15426 mips32_op = OPC_CEIL_W_D;
15427 goto do_unaryfp;
15429 /* Truncation */
15430 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15431 mips32_op = OPC_TRUNC_L_S;
15432 goto do_unaryfp;
15433 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15434 mips32_op = OPC_TRUNC_L_D;
15435 goto do_unaryfp;
15436 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15437 mips32_op = OPC_TRUNC_W_S;
15438 goto do_unaryfp;
15439 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15440 mips32_op = OPC_TRUNC_W_D;
15441 goto do_unaryfp;
15443 /* Round */
15444 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15445 mips32_op = OPC_ROUND_L_S;
15446 goto do_unaryfp;
15447 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15448 mips32_op = OPC_ROUND_L_D;
15449 goto do_unaryfp;
15450 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15451 mips32_op = OPC_ROUND_W_S;
15452 goto do_unaryfp;
15453 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15454 mips32_op = OPC_ROUND_W_D;
15455 goto do_unaryfp;
15457 /* Integer to floating-point conversion */
15458 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15459 mips32_op = OPC_CVT_L_S;
15460 goto do_unaryfp;
15461 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15462 mips32_op = OPC_CVT_L_D;
15463 goto do_unaryfp;
15464 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15465 mips32_op = OPC_CVT_W_S;
15466 goto do_unaryfp;
15467 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15468 mips32_op = OPC_CVT_W_D;
15469 goto do_unaryfp;
15471 /* Paired-foo conversions */
15472 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15473 mips32_op = OPC_CVT_S_PL;
15474 goto do_unaryfp;
15475 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15476 mips32_op = OPC_CVT_S_PU;
15477 goto do_unaryfp;
15478 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15479 mips32_op = OPC_CVT_PW_PS;
15480 goto do_unaryfp;
15481 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15482 mips32_op = OPC_CVT_PS_PW;
15483 goto do_unaryfp;
15485 /* Floating-point moves */
15486 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15487 mips32_op = OPC_MOV_S;
15488 goto do_unaryfp;
15489 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15490 mips32_op = OPC_MOV_D;
15491 goto do_unaryfp;
15492 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15493 mips32_op = OPC_MOV_PS;
15494 goto do_unaryfp;
15496 /* Absolute value */
15497 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15498 mips32_op = OPC_ABS_S;
15499 goto do_unaryfp;
15500 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15501 mips32_op = OPC_ABS_D;
15502 goto do_unaryfp;
15503 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15504 mips32_op = OPC_ABS_PS;
15505 goto do_unaryfp;
15507 /* Negation */
15508 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15509 mips32_op = OPC_NEG_S;
15510 goto do_unaryfp;
15511 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15512 mips32_op = OPC_NEG_D;
15513 goto do_unaryfp;
15514 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15515 mips32_op = OPC_NEG_PS;
15516 goto do_unaryfp;
15518 /* Reciprocal square root step */
15519 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15520 mips32_op = OPC_RSQRT1_S;
15521 goto do_unaryfp;
15522 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15523 mips32_op = OPC_RSQRT1_D;
15524 goto do_unaryfp;
15525 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15526 mips32_op = OPC_RSQRT1_PS;
15527 goto do_unaryfp;
15529 /* Reciprocal step */
15530 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15531 mips32_op = OPC_RECIP1_S;
15532 goto do_unaryfp;
15533 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15534 mips32_op = OPC_RECIP1_S;
15535 goto do_unaryfp;
15536 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15537 mips32_op = OPC_RECIP1_PS;
15538 goto do_unaryfp;
15540 /* Conversions from double */
15541 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15542 mips32_op = OPC_CVT_D_S;
15543 goto do_unaryfp;
15544 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15545 mips32_op = OPC_CVT_D_W;
15546 goto do_unaryfp;
15547 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15548 mips32_op = OPC_CVT_D_L;
15549 goto do_unaryfp;
15551 /* Conversions from single */
15552 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15553 mips32_op = OPC_CVT_S_D;
15554 goto do_unaryfp;
15555 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15556 mips32_op = OPC_CVT_S_W;
15557 goto do_unaryfp;
15558 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15559 mips32_op = OPC_CVT_S_L;
15560 do_unaryfp:
15561 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15562 break;
15564 /* Conditional moves on floating-point codes */
15565 case COND_FLOAT_MOV(MOVT, 0):
15566 case COND_FLOAT_MOV(MOVT, 1):
15567 case COND_FLOAT_MOV(MOVT, 2):
15568 case COND_FLOAT_MOV(MOVT, 3):
15569 case COND_FLOAT_MOV(MOVT, 4):
15570 case COND_FLOAT_MOV(MOVT, 5):
15571 case COND_FLOAT_MOV(MOVT, 6):
15572 case COND_FLOAT_MOV(MOVT, 7):
15573 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15574 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15575 break;
15576 case COND_FLOAT_MOV(MOVF, 0):
15577 case COND_FLOAT_MOV(MOVF, 1):
15578 case COND_FLOAT_MOV(MOVF, 2):
15579 case COND_FLOAT_MOV(MOVF, 3):
15580 case COND_FLOAT_MOV(MOVF, 4):
15581 case COND_FLOAT_MOV(MOVF, 5):
15582 case COND_FLOAT_MOV(MOVF, 6):
15583 case COND_FLOAT_MOV(MOVF, 7):
15584 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15585 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15586 break;
15587 default:
15588 MIPS_INVAL("pool32fxf");
15589 gen_reserved_instruction(ctx);
15590 break;
15594 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15596 int32_t offset;
15597 uint16_t insn;
15598 int rt, rs, rd, rr;
15599 int16_t imm;
15600 uint32_t op, minor, minor2, mips32_op;
15601 uint32_t cond, fmt, cc;
15603 insn = translator_lduw(env, ctx->base.pc_next + 2);
15604 ctx->opcode = (ctx->opcode << 16) | insn;
15606 rt = (ctx->opcode >> 21) & 0x1f;
15607 rs = (ctx->opcode >> 16) & 0x1f;
15608 rd = (ctx->opcode >> 11) & 0x1f;
15609 rr = (ctx->opcode >> 6) & 0x1f;
15610 imm = (int16_t) ctx->opcode;
15612 op = (ctx->opcode >> 26) & 0x3f;
15613 switch (op) {
15614 case POOL32A:
15615 minor = ctx->opcode & 0x3f;
15616 switch (minor) {
15617 case 0x00:
15618 minor = (ctx->opcode >> 6) & 0xf;
15619 switch (minor) {
15620 case SLL32:
15621 mips32_op = OPC_SLL;
15622 goto do_shifti;
15623 case SRA:
15624 mips32_op = OPC_SRA;
15625 goto do_shifti;
15626 case SRL32:
15627 mips32_op = OPC_SRL;
15628 goto do_shifti;
15629 case ROTR:
15630 mips32_op = OPC_ROTR;
15631 do_shifti:
15632 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15633 break;
15634 case SELEQZ:
15635 check_insn(ctx, ISA_MIPS_R6);
15636 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15637 break;
15638 case SELNEZ:
15639 check_insn(ctx, ISA_MIPS_R6);
15640 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15641 break;
15642 case R6_RDHWR:
15643 check_insn(ctx, ISA_MIPS_R6);
15644 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15645 break;
15646 default:
15647 goto pool32a_invalid;
15649 break;
15650 case 0x10:
15651 minor = (ctx->opcode >> 6) & 0xf;
15652 switch (minor) {
15653 /* Arithmetic */
15654 case ADD:
15655 mips32_op = OPC_ADD;
15656 goto do_arith;
15657 case ADDU32:
15658 mips32_op = OPC_ADDU;
15659 goto do_arith;
15660 case SUB:
15661 mips32_op = OPC_SUB;
15662 goto do_arith;
15663 case SUBU32:
15664 mips32_op = OPC_SUBU;
15665 goto do_arith;
15666 case MUL:
15667 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15668 mips32_op = OPC_MUL;
15669 do_arith:
15670 gen_arith(ctx, mips32_op, rd, rs, rt);
15671 break;
15672 /* Shifts */
15673 case SLLV:
15674 mips32_op = OPC_SLLV;
15675 goto do_shift;
15676 case SRLV:
15677 mips32_op = OPC_SRLV;
15678 goto do_shift;
15679 case SRAV:
15680 mips32_op = OPC_SRAV;
15681 goto do_shift;
15682 case ROTRV:
15683 mips32_op = OPC_ROTRV;
15684 do_shift:
15685 gen_shift(ctx, mips32_op, rd, rs, rt);
15686 break;
15687 /* Logical operations */
15688 case AND:
15689 mips32_op = OPC_AND;
15690 goto do_logic;
15691 case OR32:
15692 mips32_op = OPC_OR;
15693 goto do_logic;
15694 case NOR:
15695 mips32_op = OPC_NOR;
15696 goto do_logic;
15697 case XOR32:
15698 mips32_op = OPC_XOR;
15699 do_logic:
15700 gen_logic(ctx, mips32_op, rd, rs, rt);
15701 break;
15702 /* Set less than */
15703 case SLT:
15704 mips32_op = OPC_SLT;
15705 goto do_slt;
15706 case SLTU:
15707 mips32_op = OPC_SLTU;
15708 do_slt:
15709 gen_slt(ctx, mips32_op, rd, rs, rt);
15710 break;
15711 default:
15712 goto pool32a_invalid;
15714 break;
15715 case 0x18:
15716 minor = (ctx->opcode >> 6) & 0xf;
15717 switch (minor) {
15718 /* Conditional moves */
15719 case MOVN: /* MUL */
15720 if (ctx->insn_flags & ISA_MIPS_R6) {
15721 /* MUL */
15722 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15723 } else {
15724 /* MOVN */
15725 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15727 break;
15728 case MOVZ: /* MUH */
15729 if (ctx->insn_flags & ISA_MIPS_R6) {
15730 /* MUH */
15731 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15732 } else {
15733 /* MOVZ */
15734 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15736 break;
15737 case MULU:
15738 check_insn(ctx, ISA_MIPS_R6);
15739 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15740 break;
15741 case MUHU:
15742 check_insn(ctx, ISA_MIPS_R6);
15743 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15744 break;
15745 case LWXS: /* DIV */
15746 if (ctx->insn_flags & ISA_MIPS_R6) {
15747 /* DIV */
15748 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15749 } else {
15750 /* LWXS */
15751 gen_ldxs(ctx, rs, rt, rd);
15753 break;
15754 case MOD:
15755 check_insn(ctx, ISA_MIPS_R6);
15756 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15757 break;
15758 case R6_DIVU:
15759 check_insn(ctx, ISA_MIPS_R6);
15760 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15761 break;
15762 case MODU:
15763 check_insn(ctx, ISA_MIPS_R6);
15764 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15765 break;
15766 default:
15767 goto pool32a_invalid;
15769 break;
15770 case INS:
15771 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15772 return;
15773 case LSA:
15774 check_insn(ctx, ISA_MIPS_R6);
15775 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2));
15776 break;
15777 case ALIGN:
15778 check_insn(ctx, ISA_MIPS_R6);
15779 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15780 break;
15781 case EXT:
15782 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15783 return;
15784 case POOL32AXF:
15785 gen_pool32axf(env, ctx, rt, rs);
15786 break;
15787 case BREAK32:
15788 generate_exception_end(ctx, EXCP_BREAK);
15789 break;
15790 case SIGRIE:
15791 check_insn(ctx, ISA_MIPS_R6);
15792 gen_reserved_instruction(ctx);
15793 break;
15794 default:
15795 pool32a_invalid:
15796 MIPS_INVAL("pool32a");
15797 gen_reserved_instruction(ctx);
15798 break;
15800 break;
15801 case POOL32B:
15802 minor = (ctx->opcode >> 12) & 0xf;
15803 switch (minor) {
15804 case CACHE:
15805 check_cp0_enabled(ctx);
15806 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15807 gen_cache_operation(ctx, rt, rs, imm);
15809 break;
15810 case LWC2:
15811 case SWC2:
15812 /* COP2: Not implemented. */
15813 generate_exception_err(ctx, EXCP_CpU, 2);
15814 break;
15815 #ifdef TARGET_MIPS64
15816 case LDP:
15817 case SDP:
15818 check_insn(ctx, ISA_MIPS3);
15819 check_mips_64(ctx);
15820 #endif
15821 /* fall through */
15822 case LWP:
15823 case SWP:
15824 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15825 break;
15826 #ifdef TARGET_MIPS64
15827 case LDM:
15828 case SDM:
15829 check_insn(ctx, ISA_MIPS3);
15830 check_mips_64(ctx);
15831 #endif
15832 /* fall through */
15833 case LWM32:
15834 case SWM32:
15835 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15836 break;
15837 default:
15838 MIPS_INVAL("pool32b");
15839 gen_reserved_instruction(ctx);
15840 break;
15842 break;
15843 case POOL32F:
15844 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15845 minor = ctx->opcode & 0x3f;
15846 check_cp1_enabled(ctx);
15847 switch (minor) {
15848 case ALNV_PS:
15849 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15850 mips32_op = OPC_ALNV_PS;
15851 goto do_madd;
15852 case MADD_S:
15853 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15854 mips32_op = OPC_MADD_S;
15855 goto do_madd;
15856 case MADD_D:
15857 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15858 mips32_op = OPC_MADD_D;
15859 goto do_madd;
15860 case MADD_PS:
15861 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15862 mips32_op = OPC_MADD_PS;
15863 goto do_madd;
15864 case MSUB_S:
15865 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15866 mips32_op = OPC_MSUB_S;
15867 goto do_madd;
15868 case MSUB_D:
15869 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15870 mips32_op = OPC_MSUB_D;
15871 goto do_madd;
15872 case MSUB_PS:
15873 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15874 mips32_op = OPC_MSUB_PS;
15875 goto do_madd;
15876 case NMADD_S:
15877 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15878 mips32_op = OPC_NMADD_S;
15879 goto do_madd;
15880 case NMADD_D:
15881 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15882 mips32_op = OPC_NMADD_D;
15883 goto do_madd;
15884 case NMADD_PS:
15885 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15886 mips32_op = OPC_NMADD_PS;
15887 goto do_madd;
15888 case NMSUB_S:
15889 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15890 mips32_op = OPC_NMSUB_S;
15891 goto do_madd;
15892 case NMSUB_D:
15893 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15894 mips32_op = OPC_NMSUB_D;
15895 goto do_madd;
15896 case NMSUB_PS:
15897 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15898 mips32_op = OPC_NMSUB_PS;
15899 do_madd:
15900 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15901 break;
15902 case CABS_COND_FMT:
15903 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15904 cond = (ctx->opcode >> 6) & 0xf;
15905 cc = (ctx->opcode >> 13) & 0x7;
15906 fmt = (ctx->opcode >> 10) & 0x3;
15907 switch (fmt) {
15908 case 0x0:
15909 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15910 break;
15911 case 0x1:
15912 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15913 break;
15914 case 0x2:
15915 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15916 break;
15917 default:
15918 goto pool32f_invalid;
15920 break;
15921 case C_COND_FMT:
15922 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15923 cond = (ctx->opcode >> 6) & 0xf;
15924 cc = (ctx->opcode >> 13) & 0x7;
15925 fmt = (ctx->opcode >> 10) & 0x3;
15926 switch (fmt) {
15927 case 0x0:
15928 gen_cmp_s(ctx, cond, rt, rs, cc);
15929 break;
15930 case 0x1:
15931 gen_cmp_d(ctx, cond, rt, rs, cc);
15932 break;
15933 case 0x2:
15934 gen_cmp_ps(ctx, cond, rt, rs, cc);
15935 break;
15936 default:
15937 goto pool32f_invalid;
15939 break;
15940 case CMP_CONDN_S:
15941 check_insn(ctx, ISA_MIPS_R6);
15942 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15943 break;
15944 case CMP_CONDN_D:
15945 check_insn(ctx, ISA_MIPS_R6);
15946 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15947 break;
15948 case POOL32FXF:
15949 gen_pool32fxf(ctx, rt, rs);
15950 break;
15951 case 0x00:
15952 /* PLL foo */
15953 switch ((ctx->opcode >> 6) & 0x7) {
15954 case PLL_PS:
15955 mips32_op = OPC_PLL_PS;
15956 goto do_ps;
15957 case PLU_PS:
15958 mips32_op = OPC_PLU_PS;
15959 goto do_ps;
15960 case PUL_PS:
15961 mips32_op = OPC_PUL_PS;
15962 goto do_ps;
15963 case PUU_PS:
15964 mips32_op = OPC_PUU_PS;
15965 goto do_ps;
15966 case CVT_PS_S:
15967 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15968 mips32_op = OPC_CVT_PS_S;
15969 do_ps:
15970 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15971 break;
15972 default:
15973 goto pool32f_invalid;
15975 break;
15976 case MIN_FMT:
15977 check_insn(ctx, ISA_MIPS_R6);
15978 switch ((ctx->opcode >> 9) & 0x3) {
15979 case FMT_SDPS_S:
15980 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15981 break;
15982 case FMT_SDPS_D:
15983 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15984 break;
15985 default:
15986 goto pool32f_invalid;
15988 break;
15989 case 0x08:
15990 /* [LS][WDU]XC1 */
15991 switch ((ctx->opcode >> 6) & 0x7) {
15992 case LWXC1:
15993 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15994 mips32_op = OPC_LWXC1;
15995 goto do_ldst_cp1;
15996 case SWXC1:
15997 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15998 mips32_op = OPC_SWXC1;
15999 goto do_ldst_cp1;
16000 case LDXC1:
16001 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16002 mips32_op = OPC_LDXC1;
16003 goto do_ldst_cp1;
16004 case SDXC1:
16005 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16006 mips32_op = OPC_SDXC1;
16007 goto do_ldst_cp1;
16008 case LUXC1:
16009 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16010 mips32_op = OPC_LUXC1;
16011 goto do_ldst_cp1;
16012 case SUXC1:
16013 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16014 mips32_op = OPC_SUXC1;
16015 do_ldst_cp1:
16016 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16017 break;
16018 default:
16019 goto pool32f_invalid;
16021 break;
16022 case MAX_FMT:
16023 check_insn(ctx, ISA_MIPS_R6);
16024 switch ((ctx->opcode >> 9) & 0x3) {
16025 case FMT_SDPS_S:
16026 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16027 break;
16028 case FMT_SDPS_D:
16029 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16030 break;
16031 default:
16032 goto pool32f_invalid;
16034 break;
16035 case 0x18:
16036 /* 3D insns */
16037 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16038 fmt = (ctx->opcode >> 9) & 0x3;
16039 switch ((ctx->opcode >> 6) & 0x7) {
16040 case RSQRT2_FMT:
16041 switch (fmt) {
16042 case FMT_SDPS_S:
16043 mips32_op = OPC_RSQRT2_S;
16044 goto do_3d;
16045 case FMT_SDPS_D:
16046 mips32_op = OPC_RSQRT2_D;
16047 goto do_3d;
16048 case FMT_SDPS_PS:
16049 mips32_op = OPC_RSQRT2_PS;
16050 goto do_3d;
16051 default:
16052 goto pool32f_invalid;
16054 break;
16055 case RECIP2_FMT:
16056 switch (fmt) {
16057 case FMT_SDPS_S:
16058 mips32_op = OPC_RECIP2_S;
16059 goto do_3d;
16060 case FMT_SDPS_D:
16061 mips32_op = OPC_RECIP2_D;
16062 goto do_3d;
16063 case FMT_SDPS_PS:
16064 mips32_op = OPC_RECIP2_PS;
16065 goto do_3d;
16066 default:
16067 goto pool32f_invalid;
16069 break;
16070 case ADDR_PS:
16071 mips32_op = OPC_ADDR_PS;
16072 goto do_3d;
16073 case MULR_PS:
16074 mips32_op = OPC_MULR_PS;
16075 do_3d:
16076 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16077 break;
16078 default:
16079 goto pool32f_invalid;
16081 break;
16082 case 0x20:
16083 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16084 cc = (ctx->opcode >> 13) & 0x7;
16085 fmt = (ctx->opcode >> 9) & 0x3;
16086 switch ((ctx->opcode >> 6) & 0x7) {
16087 case MOVF_FMT: /* RINT_FMT */
16088 if (ctx->insn_flags & ISA_MIPS_R6) {
16089 /* RINT_FMT */
16090 switch (fmt) {
16091 case FMT_SDPS_S:
16092 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16093 break;
16094 case FMT_SDPS_D:
16095 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16096 break;
16097 default:
16098 goto pool32f_invalid;
16100 } else {
16101 /* MOVF_FMT */
16102 switch (fmt) {
16103 case FMT_SDPS_S:
16104 gen_movcf_s(ctx, rs, rt, cc, 0);
16105 break;
16106 case FMT_SDPS_D:
16107 gen_movcf_d(ctx, rs, rt, cc, 0);
16108 break;
16109 case FMT_SDPS_PS:
16110 check_ps(ctx);
16111 gen_movcf_ps(ctx, rs, rt, cc, 0);
16112 break;
16113 default:
16114 goto pool32f_invalid;
16117 break;
16118 case MOVT_FMT: /* CLASS_FMT */
16119 if (ctx->insn_flags & ISA_MIPS_R6) {
16120 /* CLASS_FMT */
16121 switch (fmt) {
16122 case FMT_SDPS_S:
16123 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16124 break;
16125 case FMT_SDPS_D:
16126 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16127 break;
16128 default:
16129 goto pool32f_invalid;
16131 } else {
16132 /* MOVT_FMT */
16133 switch (fmt) {
16134 case FMT_SDPS_S:
16135 gen_movcf_s(ctx, rs, rt, cc, 1);
16136 break;
16137 case FMT_SDPS_D:
16138 gen_movcf_d(ctx, rs, rt, cc, 1);
16139 break;
16140 case FMT_SDPS_PS:
16141 check_ps(ctx);
16142 gen_movcf_ps(ctx, rs, rt, cc, 1);
16143 break;
16144 default:
16145 goto pool32f_invalid;
16148 break;
16149 case PREFX:
16150 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16151 break;
16152 default:
16153 goto pool32f_invalid;
16155 break;
16156 #define FINSN_3ARG_SDPS(prfx) \
16157 switch ((ctx->opcode >> 8) & 0x3) { \
16158 case FMT_SDPS_S: \
16159 mips32_op = OPC_##prfx##_S; \
16160 goto do_fpop; \
16161 case FMT_SDPS_D: \
16162 mips32_op = OPC_##prfx##_D; \
16163 goto do_fpop; \
16164 case FMT_SDPS_PS: \
16165 check_ps(ctx); \
16166 mips32_op = OPC_##prfx##_PS; \
16167 goto do_fpop; \
16168 default: \
16169 goto pool32f_invalid; \
16171 case MINA_FMT:
16172 check_insn(ctx, ISA_MIPS_R6);
16173 switch ((ctx->opcode >> 9) & 0x3) {
16174 case FMT_SDPS_S:
16175 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16176 break;
16177 case FMT_SDPS_D:
16178 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16179 break;
16180 default:
16181 goto pool32f_invalid;
16183 break;
16184 case MAXA_FMT:
16185 check_insn(ctx, ISA_MIPS_R6);
16186 switch ((ctx->opcode >> 9) & 0x3) {
16187 case FMT_SDPS_S:
16188 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16189 break;
16190 case FMT_SDPS_D:
16191 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16192 break;
16193 default:
16194 goto pool32f_invalid;
16196 break;
16197 case 0x30:
16198 /* regular FP ops */
16199 switch ((ctx->opcode >> 6) & 0x3) {
16200 case ADD_FMT:
16201 FINSN_3ARG_SDPS(ADD);
16202 break;
16203 case SUB_FMT:
16204 FINSN_3ARG_SDPS(SUB);
16205 break;
16206 case MUL_FMT:
16207 FINSN_3ARG_SDPS(MUL);
16208 break;
16209 case DIV_FMT:
16210 fmt = (ctx->opcode >> 8) & 0x3;
16211 if (fmt == 1) {
16212 mips32_op = OPC_DIV_D;
16213 } else if (fmt == 0) {
16214 mips32_op = OPC_DIV_S;
16215 } else {
16216 goto pool32f_invalid;
16218 goto do_fpop;
16219 default:
16220 goto pool32f_invalid;
16222 break;
16223 case 0x38:
16224 /* cmovs */
16225 switch ((ctx->opcode >> 6) & 0x7) {
16226 case MOVN_FMT: /* SELEQZ_FMT */
16227 if (ctx->insn_flags & ISA_MIPS_R6) {
16228 /* SELEQZ_FMT */
16229 switch ((ctx->opcode >> 9) & 0x3) {
16230 case FMT_SDPS_S:
16231 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16232 break;
16233 case FMT_SDPS_D:
16234 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16235 break;
16236 default:
16237 goto pool32f_invalid;
16239 } else {
16240 /* MOVN_FMT */
16241 FINSN_3ARG_SDPS(MOVN);
16243 break;
16244 case MOVN_FMT_04:
16245 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16246 FINSN_3ARG_SDPS(MOVN);
16247 break;
16248 case MOVZ_FMT: /* SELNEZ_FMT */
16249 if (ctx->insn_flags & ISA_MIPS_R6) {
16250 /* SELNEZ_FMT */
16251 switch ((ctx->opcode >> 9) & 0x3) {
16252 case FMT_SDPS_S:
16253 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16254 break;
16255 case FMT_SDPS_D:
16256 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16257 break;
16258 default:
16259 goto pool32f_invalid;
16261 } else {
16262 /* MOVZ_FMT */
16263 FINSN_3ARG_SDPS(MOVZ);
16265 break;
16266 case MOVZ_FMT_05:
16267 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16268 FINSN_3ARG_SDPS(MOVZ);
16269 break;
16270 case SEL_FMT:
16271 check_insn(ctx, ISA_MIPS_R6);
16272 switch ((ctx->opcode >> 9) & 0x3) {
16273 case FMT_SDPS_S:
16274 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16275 break;
16276 case FMT_SDPS_D:
16277 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16278 break;
16279 default:
16280 goto pool32f_invalid;
16282 break;
16283 case MADDF_FMT:
16284 check_insn(ctx, ISA_MIPS_R6);
16285 switch ((ctx->opcode >> 9) & 0x3) {
16286 case FMT_SDPS_S:
16287 mips32_op = OPC_MADDF_S;
16288 goto do_fpop;
16289 case FMT_SDPS_D:
16290 mips32_op = OPC_MADDF_D;
16291 goto do_fpop;
16292 default:
16293 goto pool32f_invalid;
16295 break;
16296 case MSUBF_FMT:
16297 check_insn(ctx, ISA_MIPS_R6);
16298 switch ((ctx->opcode >> 9) & 0x3) {
16299 case FMT_SDPS_S:
16300 mips32_op = OPC_MSUBF_S;
16301 goto do_fpop;
16302 case FMT_SDPS_D:
16303 mips32_op = OPC_MSUBF_D;
16304 goto do_fpop;
16305 default:
16306 goto pool32f_invalid;
16308 break;
16309 default:
16310 goto pool32f_invalid;
16312 break;
16313 do_fpop:
16314 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16315 break;
16316 default:
16317 pool32f_invalid:
16318 MIPS_INVAL("pool32f");
16319 gen_reserved_instruction(ctx);
16320 break;
16322 } else {
16323 generate_exception_err(ctx, EXCP_CpU, 1);
16325 break;
16326 case POOL32I:
16327 minor = (ctx->opcode >> 21) & 0x1f;
16328 switch (minor) {
16329 case BLTZ:
16330 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16331 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16332 break;
16333 case BLTZAL:
16334 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16335 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16336 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16337 break;
16338 case BLTZALS:
16339 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16340 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16341 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16342 break;
16343 case BGEZ:
16344 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16345 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16346 break;
16347 case BGEZAL:
16348 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16349 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16350 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16351 break;
16352 case BGEZALS:
16353 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16354 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16355 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16356 break;
16357 case BLEZ:
16358 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16359 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16360 break;
16361 case BGTZ:
16362 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16363 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16364 break;
16366 /* Traps */
16367 case TLTI: /* BC1EQZC */
16368 if (ctx->insn_flags & ISA_MIPS_R6) {
16369 /* BC1EQZC */
16370 check_cp1_enabled(ctx);
16371 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16372 } else {
16373 /* TLTI */
16374 mips32_op = OPC_TLTI;
16375 goto do_trapi;
16377 break;
16378 case TGEI: /* BC1NEZC */
16379 if (ctx->insn_flags & ISA_MIPS_R6) {
16380 /* BC1NEZC */
16381 check_cp1_enabled(ctx);
16382 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16383 } else {
16384 /* TGEI */
16385 mips32_op = OPC_TGEI;
16386 goto do_trapi;
16388 break;
16389 case TLTIU:
16390 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16391 mips32_op = OPC_TLTIU;
16392 goto do_trapi;
16393 case TGEIU:
16394 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16395 mips32_op = OPC_TGEIU;
16396 goto do_trapi;
16397 case TNEI: /* SYNCI */
16398 if (ctx->insn_flags & ISA_MIPS_R6) {
16399 /* SYNCI */
16401 * Break the TB to be able to sync copied instructions
16402 * immediately.
16404 ctx->base.is_jmp = DISAS_STOP;
16405 } else {
16406 /* TNEI */
16407 mips32_op = OPC_TNEI;
16408 goto do_trapi;
16410 break;
16411 case TEQI:
16412 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16413 mips32_op = OPC_TEQI;
16414 do_trapi:
16415 gen_trap(ctx, mips32_op, rs, -1, imm);
16416 break;
16418 case BNEZC:
16419 case BEQZC:
16420 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16421 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16422 4, rs, 0, imm << 1, 0);
16424 * Compact branches don't have a delay slot, so just let
16425 * the normal delay slot handling take us to the branch
16426 * target.
16428 break;
16429 case LUI:
16430 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16431 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16432 break;
16433 case SYNCI:
16434 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16436 * Break the TB to be able to sync copied instructions
16437 * immediately.
16439 ctx->base.is_jmp = DISAS_STOP;
16440 break;
16441 case BC2F:
16442 case BC2T:
16443 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16444 /* COP2: Not implemented. */
16445 generate_exception_err(ctx, EXCP_CpU, 2);
16446 break;
16447 case BC1F:
16448 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16449 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16450 goto do_cp1branch;
16451 case BC1T:
16452 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16453 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16454 goto do_cp1branch;
16455 case BC1ANY4F:
16456 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16457 mips32_op = OPC_BC1FANY4;
16458 goto do_cp1mips3d;
16459 case BC1ANY4T:
16460 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16461 mips32_op = OPC_BC1TANY4;
16462 do_cp1mips3d:
16463 check_cop1x(ctx);
16464 check_insn(ctx, ASE_MIPS3D);
16465 /* Fall through */
16466 do_cp1branch:
16467 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16468 check_cp1_enabled(ctx);
16469 gen_compute_branch1(ctx, mips32_op,
16470 (ctx->opcode >> 18) & 0x7, imm << 1);
16471 } else {
16472 generate_exception_err(ctx, EXCP_CpU, 1);
16474 break;
16475 case BPOSGE64:
16476 case BPOSGE32:
16477 /* MIPS DSP: not implemented */
16478 /* Fall through */
16479 default:
16480 MIPS_INVAL("pool32i");
16481 gen_reserved_instruction(ctx);
16482 break;
16484 break;
16485 case POOL32C:
16486 minor = (ctx->opcode >> 12) & 0xf;
16487 offset = sextract32(ctx->opcode, 0,
16488 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
16489 switch (minor) {
16490 case LWL:
16491 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16492 mips32_op = OPC_LWL;
16493 goto do_ld_lr;
16494 case SWL:
16495 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16496 mips32_op = OPC_SWL;
16497 goto do_st_lr;
16498 case LWR:
16499 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16500 mips32_op = OPC_LWR;
16501 goto do_ld_lr;
16502 case SWR:
16503 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16504 mips32_op = OPC_SWR;
16505 goto do_st_lr;
16506 #if defined(TARGET_MIPS64)
16507 case LDL:
16508 check_insn(ctx, ISA_MIPS3);
16509 check_mips_64(ctx);
16510 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16511 mips32_op = OPC_LDL;
16512 goto do_ld_lr;
16513 case SDL:
16514 check_insn(ctx, ISA_MIPS3);
16515 check_mips_64(ctx);
16516 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16517 mips32_op = OPC_SDL;
16518 goto do_st_lr;
16519 case LDR:
16520 check_insn(ctx, ISA_MIPS3);
16521 check_mips_64(ctx);
16522 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16523 mips32_op = OPC_LDR;
16524 goto do_ld_lr;
16525 case SDR:
16526 check_insn(ctx, ISA_MIPS3);
16527 check_mips_64(ctx);
16528 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16529 mips32_op = OPC_SDR;
16530 goto do_st_lr;
16531 case LWU:
16532 check_insn(ctx, ISA_MIPS3);
16533 check_mips_64(ctx);
16534 mips32_op = OPC_LWU;
16535 goto do_ld_lr;
16536 case LLD:
16537 check_insn(ctx, ISA_MIPS3);
16538 check_mips_64(ctx);
16539 mips32_op = OPC_LLD;
16540 goto do_ld_lr;
16541 #endif
16542 case LL:
16543 mips32_op = OPC_LL;
16544 goto do_ld_lr;
16545 do_ld_lr:
16546 gen_ld(ctx, mips32_op, rt, rs, offset);
16547 break;
16548 do_st_lr:
16549 gen_st(ctx, mips32_op, rt, rs, offset);
16550 break;
16551 case SC:
16552 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
16553 break;
16554 #if defined(TARGET_MIPS64)
16555 case SCD:
16556 check_insn(ctx, ISA_MIPS3);
16557 check_mips_64(ctx);
16558 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
16559 break;
16560 #endif
16561 case LD_EVA:
16562 if (!ctx->eva) {
16563 MIPS_INVAL("pool32c ld-eva");
16564 gen_reserved_instruction(ctx);
16565 break;
16567 check_cp0_enabled(ctx);
16569 minor2 = (ctx->opcode >> 9) & 0x7;
16570 offset = sextract32(ctx->opcode, 0, 9);
16571 switch (minor2) {
16572 case LBUE:
16573 mips32_op = OPC_LBUE;
16574 goto do_ld_lr;
16575 case LHUE:
16576 mips32_op = OPC_LHUE;
16577 goto do_ld_lr;
16578 case LWLE:
16579 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16580 mips32_op = OPC_LWLE;
16581 goto do_ld_lr;
16582 case LWRE:
16583 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16584 mips32_op = OPC_LWRE;
16585 goto do_ld_lr;
16586 case LBE:
16587 mips32_op = OPC_LBE;
16588 goto do_ld_lr;
16589 case LHE:
16590 mips32_op = OPC_LHE;
16591 goto do_ld_lr;
16592 case LLE:
16593 mips32_op = OPC_LLE;
16594 goto do_ld_lr;
16595 case LWE:
16596 mips32_op = OPC_LWE;
16597 goto do_ld_lr;
16599 break;
16600 case ST_EVA:
16601 if (!ctx->eva) {
16602 MIPS_INVAL("pool32c st-eva");
16603 gen_reserved_instruction(ctx);
16604 break;
16606 check_cp0_enabled(ctx);
16608 minor2 = (ctx->opcode >> 9) & 0x7;
16609 offset = sextract32(ctx->opcode, 0, 9);
16610 switch (minor2) {
16611 case SWLE:
16612 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16613 mips32_op = OPC_SWLE;
16614 goto do_st_lr;
16615 case SWRE:
16616 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16617 mips32_op = OPC_SWRE;
16618 goto do_st_lr;
16619 case PREFE:
16620 /* Treat as no-op */
16621 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
16622 /* hint codes 24-31 are reserved and signal RI */
16623 generate_exception(ctx, EXCP_RI);
16625 break;
16626 case CACHEE:
16627 /* Treat as no-op */
16628 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16629 gen_cache_operation(ctx, rt, rs, offset);
16631 break;
16632 case SBE:
16633 mips32_op = OPC_SBE;
16634 goto do_st_lr;
16635 case SHE:
16636 mips32_op = OPC_SHE;
16637 goto do_st_lr;
16638 case SCE:
16639 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
16640 break;
16641 case SWE:
16642 mips32_op = OPC_SWE;
16643 goto do_st_lr;
16645 break;
16646 case PREF:
16647 /* Treat as no-op */
16648 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
16649 /* hint codes 24-31 are reserved and signal RI */
16650 generate_exception(ctx, EXCP_RI);
16652 break;
16653 default:
16654 MIPS_INVAL("pool32c");
16655 gen_reserved_instruction(ctx);
16656 break;
16658 break;
16659 case ADDI32: /* AUI, LUI */
16660 if (ctx->insn_flags & ISA_MIPS_R6) {
16661 /* AUI, LUI */
16662 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16663 } else {
16664 /* ADDI32 */
16665 mips32_op = OPC_ADDI;
16666 goto do_addi;
16668 break;
16669 case ADDIU32:
16670 mips32_op = OPC_ADDIU;
16671 do_addi:
16672 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16673 break;
16675 /* Logical operations */
16676 case ORI32:
16677 mips32_op = OPC_ORI;
16678 goto do_logici;
16679 case XORI32:
16680 mips32_op = OPC_XORI;
16681 goto do_logici;
16682 case ANDI32:
16683 mips32_op = OPC_ANDI;
16684 do_logici:
16685 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16686 break;
16688 /* Set less than immediate */
16689 case SLTI32:
16690 mips32_op = OPC_SLTI;
16691 goto do_slti;
16692 case SLTIU32:
16693 mips32_op = OPC_SLTIU;
16694 do_slti:
16695 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16696 break;
16697 case JALX32:
16698 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16699 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16700 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16701 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16702 break;
16703 case JALS32: /* BOVC, BEQC, BEQZALC */
16704 if (ctx->insn_flags & ISA_MIPS_R6) {
16705 if (rs >= rt) {
16706 /* BOVC */
16707 mips32_op = OPC_BOVC;
16708 } else if (rs < rt && rs == 0) {
16709 /* BEQZALC */
16710 mips32_op = OPC_BEQZALC;
16711 } else {
16712 /* BEQC */
16713 mips32_op = OPC_BEQC;
16715 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16716 } else {
16717 /* JALS32 */
16718 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16719 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16720 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16722 break;
16723 case BEQ32: /* BC */
16724 if (ctx->insn_flags & ISA_MIPS_R6) {
16725 /* BC */
16726 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16727 sextract32(ctx->opcode << 1, 0, 27));
16728 } else {
16729 /* BEQ32 */
16730 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16732 break;
16733 case BNE32: /* BALC */
16734 if (ctx->insn_flags & ISA_MIPS_R6) {
16735 /* BALC */
16736 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16737 sextract32(ctx->opcode << 1, 0, 27));
16738 } else {
16739 /* BNE32 */
16740 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16742 break;
16743 case J32: /* BGTZC, BLTZC, BLTC */
16744 if (ctx->insn_flags & ISA_MIPS_R6) {
16745 if (rs == 0 && rt != 0) {
16746 /* BGTZC */
16747 mips32_op = OPC_BGTZC;
16748 } else if (rs != 0 && rt != 0 && rs == rt) {
16749 /* BLTZC */
16750 mips32_op = OPC_BLTZC;
16751 } else {
16752 /* BLTC */
16753 mips32_op = OPC_BLTC;
16755 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16756 } else {
16757 /* J32 */
16758 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16759 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16761 break;
16762 case JAL32: /* BLEZC, BGEZC, BGEC */
16763 if (ctx->insn_flags & ISA_MIPS_R6) {
16764 if (rs == 0 && rt != 0) {
16765 /* BLEZC */
16766 mips32_op = OPC_BLEZC;
16767 } else if (rs != 0 && rt != 0 && rs == rt) {
16768 /* BGEZC */
16769 mips32_op = OPC_BGEZC;
16770 } else {
16771 /* BGEC */
16772 mips32_op = OPC_BGEC;
16774 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16775 } else {
16776 /* JAL32 */
16777 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16778 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16779 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16781 break;
16782 /* Floating point (COP1) */
16783 case LWC132:
16784 mips32_op = OPC_LWC1;
16785 goto do_cop1;
16786 case LDC132:
16787 mips32_op = OPC_LDC1;
16788 goto do_cop1;
16789 case SWC132:
16790 mips32_op = OPC_SWC1;
16791 goto do_cop1;
16792 case SDC132:
16793 mips32_op = OPC_SDC1;
16794 do_cop1:
16795 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16796 break;
16797 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16798 if (ctx->insn_flags & ISA_MIPS_R6) {
16799 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16800 switch ((ctx->opcode >> 16) & 0x1f) {
16801 case ADDIUPC_00:
16802 case ADDIUPC_01:
16803 case ADDIUPC_02:
16804 case ADDIUPC_03:
16805 case ADDIUPC_04:
16806 case ADDIUPC_05:
16807 case ADDIUPC_06:
16808 case ADDIUPC_07:
16809 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16810 break;
16811 case AUIPC:
16812 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16813 break;
16814 case ALUIPC:
16815 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16816 break;
16817 case LWPC_08:
16818 case LWPC_09:
16819 case LWPC_0A:
16820 case LWPC_0B:
16821 case LWPC_0C:
16822 case LWPC_0D:
16823 case LWPC_0E:
16824 case LWPC_0F:
16825 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16826 break;
16827 default:
16828 generate_exception(ctx, EXCP_RI);
16829 break;
16831 } else {
16832 /* ADDIUPC */
16833 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16834 offset = SIMM(ctx->opcode, 0, 23) << 2;
16836 gen_addiupc(ctx, reg, offset, 0, 0);
16838 break;
16839 case BNVC: /* BNEC, BNEZALC */
16840 check_insn(ctx, ISA_MIPS_R6);
16841 if (rs >= rt) {
16842 /* BNVC */
16843 mips32_op = OPC_BNVC;
16844 } else if (rs < rt && rs == 0) {
16845 /* BNEZALC */
16846 mips32_op = OPC_BNEZALC;
16847 } else {
16848 /* BNEC */
16849 mips32_op = OPC_BNEC;
16851 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16852 break;
16853 case R6_BNEZC: /* JIALC */
16854 check_insn(ctx, ISA_MIPS_R6);
16855 if (rt != 0) {
16856 /* BNEZC */
16857 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16858 sextract32(ctx->opcode << 1, 0, 22));
16859 } else {
16860 /* JIALC */
16861 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16863 break;
16864 case R6_BEQZC: /* JIC */
16865 check_insn(ctx, ISA_MIPS_R6);
16866 if (rt != 0) {
16867 /* BEQZC */
16868 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16869 sextract32(ctx->opcode << 1, 0, 22));
16870 } else {
16871 /* JIC */
16872 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16874 break;
16875 case BLEZALC: /* BGEZALC, BGEUC */
16876 check_insn(ctx, ISA_MIPS_R6);
16877 if (rs == 0 && rt != 0) {
16878 /* BLEZALC */
16879 mips32_op = OPC_BLEZALC;
16880 } else if (rs != 0 && rt != 0 && rs == rt) {
16881 /* BGEZALC */
16882 mips32_op = OPC_BGEZALC;
16883 } else {
16884 /* BGEUC */
16885 mips32_op = OPC_BGEUC;
16887 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16888 break;
16889 case BGTZALC: /* BLTZALC, BLTUC */
16890 check_insn(ctx, ISA_MIPS_R6);
16891 if (rs == 0 && rt != 0) {
16892 /* BGTZALC */
16893 mips32_op = OPC_BGTZALC;
16894 } else if (rs != 0 && rt != 0 && rs == rt) {
16895 /* BLTZALC */
16896 mips32_op = OPC_BLTZALC;
16897 } else {
16898 /* BLTUC */
16899 mips32_op = OPC_BLTUC;
16901 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16902 break;
16903 /* Loads and stores */
16904 case LB32:
16905 mips32_op = OPC_LB;
16906 goto do_ld;
16907 case LBU32:
16908 mips32_op = OPC_LBU;
16909 goto do_ld;
16910 case LH32:
16911 mips32_op = OPC_LH;
16912 goto do_ld;
16913 case LHU32:
16914 mips32_op = OPC_LHU;
16915 goto do_ld;
16916 case LW32:
16917 mips32_op = OPC_LW;
16918 goto do_ld;
16919 #ifdef TARGET_MIPS64
16920 case LD32:
16921 check_insn(ctx, ISA_MIPS3);
16922 check_mips_64(ctx);
16923 mips32_op = OPC_LD;
16924 goto do_ld;
16925 case SD32:
16926 check_insn(ctx, ISA_MIPS3);
16927 check_mips_64(ctx);
16928 mips32_op = OPC_SD;
16929 goto do_st;
16930 #endif
16931 case SB32:
16932 mips32_op = OPC_SB;
16933 goto do_st;
16934 case SH32:
16935 mips32_op = OPC_SH;
16936 goto do_st;
16937 case SW32:
16938 mips32_op = OPC_SW;
16939 goto do_st;
16940 do_ld:
16941 gen_ld(ctx, mips32_op, rt, rs, imm);
16942 break;
16943 do_st:
16944 gen_st(ctx, mips32_op, rt, rs, imm);
16945 break;
16946 default:
16947 gen_reserved_instruction(ctx);
16948 break;
16952 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
16954 uint32_t op;
16956 /* make sure instructions are on a halfword boundary */
16957 if (ctx->base.pc_next & 0x1) {
16958 env->CP0_BadVAddr = ctx->base.pc_next;
16959 generate_exception_end(ctx, EXCP_AdEL);
16960 return 2;
16963 op = (ctx->opcode >> 10) & 0x3f;
16964 /* Enforce properly-sized instructions in a delay slot */
16965 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16966 switch (op & 0x7) { /* MSB-3..MSB-5 */
16967 case 0:
16968 /* POOL32A, POOL32B, POOL32I, POOL32C */
16969 case 4:
16970 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16971 case 5:
16972 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16973 case 6:
16974 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16975 case 7:
16976 /* LB32, LH32, LWC132, LDC132, LW32 */
16977 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16978 gen_reserved_instruction(ctx);
16979 return 2;
16981 break;
16982 case 1:
16983 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16984 case 2:
16985 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16986 case 3:
16987 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16988 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16989 gen_reserved_instruction(ctx);
16990 return 2;
16992 break;
16996 switch (op) {
16997 case POOL16A:
16999 int rd = mmreg(uMIPS_RD(ctx->opcode));
17000 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17001 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17002 uint32_t opc = 0;
17004 switch (ctx->opcode & 0x1) {
17005 case ADDU16:
17006 opc = OPC_ADDU;
17007 break;
17008 case SUBU16:
17009 opc = OPC_SUBU;
17010 break;
17012 if (ctx->insn_flags & ISA_MIPS_R6) {
17014 * In the Release 6, the register number location in
17015 * the instruction encoding has changed.
17017 gen_arith(ctx, opc, rs1, rd, rs2);
17018 } else {
17019 gen_arith(ctx, opc, rd, rs1, rs2);
17022 break;
17023 case POOL16B:
17025 int rd = mmreg(uMIPS_RD(ctx->opcode));
17026 int rs = mmreg(uMIPS_RS(ctx->opcode));
17027 int amount = (ctx->opcode >> 1) & 0x7;
17028 uint32_t opc = 0;
17029 amount = amount == 0 ? 8 : amount;
17031 switch (ctx->opcode & 0x1) {
17032 case SLL16:
17033 opc = OPC_SLL;
17034 break;
17035 case SRL16:
17036 opc = OPC_SRL;
17037 break;
17040 gen_shift_imm(ctx, opc, rd, rs, amount);
17042 break;
17043 case POOL16C:
17044 if (ctx->insn_flags & ISA_MIPS_R6) {
17045 gen_pool16c_r6_insn(ctx);
17046 } else {
17047 gen_pool16c_insn(ctx);
17049 break;
17050 case LWGP16:
17052 int rd = mmreg(uMIPS_RD(ctx->opcode));
17053 int rb = 28; /* GP */
17054 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17056 gen_ld(ctx, OPC_LW, rd, rb, offset);
17058 break;
17059 case POOL16F:
17060 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17061 if (ctx->opcode & 1) {
17062 gen_reserved_instruction(ctx);
17063 } else {
17064 /* MOVEP */
17065 int enc_dest = uMIPS_RD(ctx->opcode);
17066 int enc_rt = uMIPS_RS2(ctx->opcode);
17067 int enc_rs = uMIPS_RS1(ctx->opcode);
17068 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17070 break;
17071 case LBU16:
17073 int rd = mmreg(uMIPS_RD(ctx->opcode));
17074 int rb = mmreg(uMIPS_RS(ctx->opcode));
17075 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17076 offset = (offset == 0xf ? -1 : offset);
17078 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17080 break;
17081 case LHU16:
17083 int rd = mmreg(uMIPS_RD(ctx->opcode));
17084 int rb = mmreg(uMIPS_RS(ctx->opcode));
17085 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17087 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17089 break;
17090 case LWSP16:
17092 int rd = (ctx->opcode >> 5) & 0x1f;
17093 int rb = 29; /* SP */
17094 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17096 gen_ld(ctx, OPC_LW, rd, rb, offset);
17098 break;
17099 case LW16:
17101 int rd = mmreg(uMIPS_RD(ctx->opcode));
17102 int rb = mmreg(uMIPS_RS(ctx->opcode));
17103 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17105 gen_ld(ctx, OPC_LW, rd, rb, offset);
17107 break;
17108 case SB16:
17110 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17111 int rb = mmreg(uMIPS_RS(ctx->opcode));
17112 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17114 gen_st(ctx, OPC_SB, rd, rb, offset);
17116 break;
17117 case SH16:
17119 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17120 int rb = mmreg(uMIPS_RS(ctx->opcode));
17121 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17123 gen_st(ctx, OPC_SH, rd, rb, offset);
17125 break;
17126 case SWSP16:
17128 int rd = (ctx->opcode >> 5) & 0x1f;
17129 int rb = 29; /* SP */
17130 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17132 gen_st(ctx, OPC_SW, rd, rb, offset);
17134 break;
17135 case SW16:
17137 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17138 int rb = mmreg(uMIPS_RS(ctx->opcode));
17139 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17141 gen_st(ctx, OPC_SW, rd, rb, offset);
17143 break;
17144 case MOVE16:
17146 int rd = uMIPS_RD5(ctx->opcode);
17147 int rs = uMIPS_RS5(ctx->opcode);
17149 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17151 break;
17152 case ANDI16:
17153 gen_andi16(ctx);
17154 break;
17155 case POOL16D:
17156 switch (ctx->opcode & 0x1) {
17157 case ADDIUS5:
17158 gen_addius5(ctx);
17159 break;
17160 case ADDIUSP:
17161 gen_addiusp(ctx);
17162 break;
17164 break;
17165 case POOL16E:
17166 switch (ctx->opcode & 0x1) {
17167 case ADDIUR2:
17168 gen_addiur2(ctx);
17169 break;
17170 case ADDIUR1SP:
17171 gen_addiur1sp(ctx);
17172 break;
17174 break;
17175 case B16: /* BC16 */
17176 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17177 sextract32(ctx->opcode, 0, 10) << 1,
17178 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
17179 break;
17180 case BNEZ16: /* BNEZC16 */
17181 case BEQZ16: /* BEQZC16 */
17182 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17183 mmreg(uMIPS_RD(ctx->opcode)),
17184 0, sextract32(ctx->opcode, 0, 7) << 1,
17185 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
17187 break;
17188 case LI16:
17190 int reg = mmreg(uMIPS_RD(ctx->opcode));
17191 int imm = ZIMM(ctx->opcode, 0, 7);
17193 imm = (imm == 0x7f ? -1 : imm);
17194 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17196 break;
17197 case RES_29:
17198 case RES_31:
17199 case RES_39:
17200 gen_reserved_instruction(ctx);
17201 break;
17202 default:
17203 decode_micromips32_opc(env, ctx);
17204 return 4;
17207 return 2;
17212 * nanoMIPS opcodes
17216 /* MAJOR, P16, and P32 pools opcodes */
17217 enum {
17218 NM_P_ADDIU = 0x00,
17219 NM_ADDIUPC = 0x01,
17220 NM_MOVE_BALC = 0x02,
17221 NM_P16_MV = 0x04,
17222 NM_LW16 = 0x05,
17223 NM_BC16 = 0x06,
17224 NM_P16_SR = 0x07,
17226 NM_POOL32A = 0x08,
17227 NM_P_BAL = 0x0a,
17228 NM_P16_SHIFT = 0x0c,
17229 NM_LWSP16 = 0x0d,
17230 NM_BALC16 = 0x0e,
17231 NM_P16_4X4 = 0x0f,
17233 NM_P_GP_W = 0x10,
17234 NM_P_GP_BH = 0x11,
17235 NM_P_J = 0x12,
17236 NM_P16C = 0x14,
17237 NM_LWGP16 = 0x15,
17238 NM_P16_LB = 0x17,
17240 NM_P48I = 0x18,
17241 NM_P16_A1 = 0x1c,
17242 NM_LW4X4 = 0x1d,
17243 NM_P16_LH = 0x1f,
17245 NM_P_U12 = 0x20,
17246 NM_P_LS_U12 = 0x21,
17247 NM_P_BR1 = 0x22,
17248 NM_P16_A2 = 0x24,
17249 NM_SW16 = 0x25,
17250 NM_BEQZC16 = 0x26,
17252 NM_POOL32F = 0x28,
17253 NM_P_LS_S9 = 0x29,
17254 NM_P_BR2 = 0x2a,
17256 NM_P16_ADDU = 0x2c,
17257 NM_SWSP16 = 0x2d,
17258 NM_BNEZC16 = 0x2e,
17259 NM_MOVEP = 0x2f,
17261 NM_POOL32S = 0x30,
17262 NM_P_BRI = 0x32,
17263 NM_LI16 = 0x34,
17264 NM_SWGP16 = 0x35,
17265 NM_P16_BR = 0x36,
17267 NM_P_LUI = 0x38,
17268 NM_ANDI16 = 0x3c,
17269 NM_SW4X4 = 0x3d,
17270 NM_MOVEPREV = 0x3f,
17273 /* POOL32A instruction pool */
17274 enum {
17275 NM_POOL32A0 = 0x00,
17276 NM_SPECIAL2 = 0x01,
17277 NM_COP2_1 = 0x02,
17278 NM_UDI = 0x03,
17279 NM_POOL32A5 = 0x05,
17280 NM_POOL32A7 = 0x07,
17283 /* P.GP.W instruction pool */
17284 enum {
17285 NM_ADDIUGP_W = 0x00,
17286 NM_LWGP = 0x02,
17287 NM_SWGP = 0x03,
17290 /* P48I instruction pool */
17291 enum {
17292 NM_LI48 = 0x00,
17293 NM_ADDIU48 = 0x01,
17294 NM_ADDIUGP48 = 0x02,
17295 NM_ADDIUPC48 = 0x03,
17296 NM_LWPC48 = 0x0b,
17297 NM_SWPC48 = 0x0f,
17300 /* P.U12 instruction pool */
17301 enum {
17302 NM_ORI = 0x00,
17303 NM_XORI = 0x01,
17304 NM_ANDI = 0x02,
17305 NM_P_SR = 0x03,
17306 NM_SLTI = 0x04,
17307 NM_SLTIU = 0x05,
17308 NM_SEQI = 0x06,
17309 NM_ADDIUNEG = 0x08,
17310 NM_P_SHIFT = 0x0c,
17311 NM_P_ROTX = 0x0d,
17312 NM_P_INS = 0x0e,
17313 NM_P_EXT = 0x0f,
17316 /* POOL32F instruction pool */
17317 enum {
17318 NM_POOL32F_0 = 0x00,
17319 NM_POOL32F_3 = 0x03,
17320 NM_POOL32F_5 = 0x05,
17323 /* POOL32S instruction pool */
17324 enum {
17325 NM_POOL32S_0 = 0x00,
17326 NM_POOL32S_4 = 0x04,
17329 /* P.LUI instruction pool */
17330 enum {
17331 NM_LUI = 0x00,
17332 NM_ALUIPC = 0x01,
17335 /* P.GP.BH instruction pool */
17336 enum {
17337 NM_LBGP = 0x00,
17338 NM_SBGP = 0x01,
17339 NM_LBUGP = 0x02,
17340 NM_ADDIUGP_B = 0x03,
17341 NM_P_GP_LH = 0x04,
17342 NM_P_GP_SH = 0x05,
17343 NM_P_GP_CP1 = 0x06,
17346 /* P.LS.U12 instruction pool */
17347 enum {
17348 NM_LB = 0x00,
17349 NM_SB = 0x01,
17350 NM_LBU = 0x02,
17351 NM_P_PREFU12 = 0x03,
17352 NM_LH = 0x04,
17353 NM_SH = 0x05,
17354 NM_LHU = 0x06,
17355 NM_LWU = 0x07,
17356 NM_LW = 0x08,
17357 NM_SW = 0x09,
17358 NM_LWC1 = 0x0a,
17359 NM_SWC1 = 0x0b,
17360 NM_LDC1 = 0x0e,
17361 NM_SDC1 = 0x0f,
17364 /* P.LS.S9 instruction pool */
17365 enum {
17366 NM_P_LS_S0 = 0x00,
17367 NM_P_LS_S1 = 0x01,
17368 NM_P_LS_E0 = 0x02,
17369 NM_P_LS_WM = 0x04,
17370 NM_P_LS_UAWM = 0x05,
17373 /* P.BAL instruction pool */
17374 enum {
17375 NM_BC = 0x00,
17376 NM_BALC = 0x01,
17379 /* P.J instruction pool */
17380 enum {
17381 NM_JALRC = 0x00,
17382 NM_JALRC_HB = 0x01,
17383 NM_P_BALRSC = 0x08,
17386 /* P.BR1 instruction pool */
17387 enum {
17388 NM_BEQC = 0x00,
17389 NM_P_BR3A = 0x01,
17390 NM_BGEC = 0x02,
17391 NM_BGEUC = 0x03,
17394 /* P.BR2 instruction pool */
17395 enum {
17396 NM_BNEC = 0x00,
17397 NM_BLTC = 0x02,
17398 NM_BLTUC = 0x03,
17401 /* P.BRI instruction pool */
17402 enum {
17403 NM_BEQIC = 0x00,
17404 NM_BBEQZC = 0x01,
17405 NM_BGEIC = 0x02,
17406 NM_BGEIUC = 0x03,
17407 NM_BNEIC = 0x04,
17408 NM_BBNEZC = 0x05,
17409 NM_BLTIC = 0x06,
17410 NM_BLTIUC = 0x07,
17413 /* P16.SHIFT instruction pool */
17414 enum {
17415 NM_SLL16 = 0x00,
17416 NM_SRL16 = 0x01,
17419 /* POOL16C instruction pool */
17420 enum {
17421 NM_POOL16C_0 = 0x00,
17422 NM_LWXS16 = 0x01,
17425 /* P16.A1 instruction pool */
17426 enum {
17427 NM_ADDIUR1SP = 0x01,
17430 /* P16.A2 instruction pool */
17431 enum {
17432 NM_ADDIUR2 = 0x00,
17433 NM_P_ADDIURS5 = 0x01,
17436 /* P16.ADDU instruction pool */
17437 enum {
17438 NM_ADDU16 = 0x00,
17439 NM_SUBU16 = 0x01,
17442 /* P16.SR instruction pool */
17443 enum {
17444 NM_SAVE16 = 0x00,
17445 NM_RESTORE_JRC16 = 0x01,
17448 /* P16.4X4 instruction pool */
17449 enum {
17450 NM_ADDU4X4 = 0x00,
17451 NM_MUL4X4 = 0x01,
17454 /* P16.LB instruction pool */
17455 enum {
17456 NM_LB16 = 0x00,
17457 NM_SB16 = 0x01,
17458 NM_LBU16 = 0x02,
17461 /* P16.LH instruction pool */
17462 enum {
17463 NM_LH16 = 0x00,
17464 NM_SH16 = 0x01,
17465 NM_LHU16 = 0x02,
17468 /* P.RI instruction pool */
17469 enum {
17470 NM_SIGRIE = 0x00,
17471 NM_P_SYSCALL = 0x01,
17472 NM_BREAK = 0x02,
17473 NM_SDBBP = 0x03,
17476 /* POOL32A0 instruction pool */
17477 enum {
17478 NM_P_TRAP = 0x00,
17479 NM_SEB = 0x01,
17480 NM_SLLV = 0x02,
17481 NM_MUL = 0x03,
17482 NM_MFC0 = 0x06,
17483 NM_MFHC0 = 0x07,
17484 NM_SEH = 0x09,
17485 NM_SRLV = 0x0a,
17486 NM_MUH = 0x0b,
17487 NM_MTC0 = 0x0e,
17488 NM_MTHC0 = 0x0f,
17489 NM_SRAV = 0x12,
17490 NM_MULU = 0x13,
17491 NM_ROTRV = 0x1a,
17492 NM_MUHU = 0x1b,
17493 NM_ADD = 0x22,
17494 NM_DIV = 0x23,
17495 NM_ADDU = 0x2a,
17496 NM_MOD = 0x2b,
17497 NM_SUB = 0x32,
17498 NM_DIVU = 0x33,
17499 NM_RDHWR = 0x38,
17500 NM_SUBU = 0x3a,
17501 NM_MODU = 0x3b,
17502 NM_P_CMOVE = 0x42,
17503 NM_FORK = 0x45,
17504 NM_MFTR = 0x46,
17505 NM_MFHTR = 0x47,
17506 NM_AND = 0x4a,
17507 NM_YIELD = 0x4d,
17508 NM_MTTR = 0x4e,
17509 NM_MTHTR = 0x4f,
17510 NM_OR = 0x52,
17511 NM_D_E_MT_VPE = 0x56,
17512 NM_NOR = 0x5a,
17513 NM_XOR = 0x62,
17514 NM_SLT = 0x6a,
17515 NM_P_SLTU = 0x72,
17516 NM_SOV = 0x7a,
17519 /* CRC32 instruction pool */
17520 enum {
17521 NM_CRC32B = 0x00,
17522 NM_CRC32H = 0x01,
17523 NM_CRC32W = 0x02,
17524 NM_CRC32CB = 0x04,
17525 NM_CRC32CH = 0x05,
17526 NM_CRC32CW = 0x06,
17529 /* POOL32A5 instruction pool */
17530 enum {
17531 NM_CMP_EQ_PH = 0x00,
17532 NM_CMP_LT_PH = 0x08,
17533 NM_CMP_LE_PH = 0x10,
17534 NM_CMPGU_EQ_QB = 0x18,
17535 NM_CMPGU_LT_QB = 0x20,
17536 NM_CMPGU_LE_QB = 0x28,
17537 NM_CMPGDU_EQ_QB = 0x30,
17538 NM_CMPGDU_LT_QB = 0x38,
17539 NM_CMPGDU_LE_QB = 0x40,
17540 NM_CMPU_EQ_QB = 0x48,
17541 NM_CMPU_LT_QB = 0x50,
17542 NM_CMPU_LE_QB = 0x58,
17543 NM_ADDQ_S_W = 0x60,
17544 NM_SUBQ_S_W = 0x68,
17545 NM_ADDSC = 0x70,
17546 NM_ADDWC = 0x78,
17548 NM_ADDQ_S_PH = 0x01,
17549 NM_ADDQH_R_PH = 0x09,
17550 NM_ADDQH_R_W = 0x11,
17551 NM_ADDU_S_QB = 0x19,
17552 NM_ADDU_S_PH = 0x21,
17553 NM_ADDUH_R_QB = 0x29,
17554 NM_SHRAV_R_PH = 0x31,
17555 NM_SHRAV_R_QB = 0x39,
17556 NM_SUBQ_S_PH = 0x41,
17557 NM_SUBQH_R_PH = 0x49,
17558 NM_SUBQH_R_W = 0x51,
17559 NM_SUBU_S_QB = 0x59,
17560 NM_SUBU_S_PH = 0x61,
17561 NM_SUBUH_R_QB = 0x69,
17562 NM_SHLLV_S_PH = 0x71,
17563 NM_PRECR_SRA_R_PH_W = 0x79,
17565 NM_MULEU_S_PH_QBL = 0x12,
17566 NM_MULEU_S_PH_QBR = 0x1a,
17567 NM_MULQ_RS_PH = 0x22,
17568 NM_MULQ_S_PH = 0x2a,
17569 NM_MULQ_RS_W = 0x32,
17570 NM_MULQ_S_W = 0x3a,
17571 NM_APPEND = 0x42,
17572 NM_MODSUB = 0x52,
17573 NM_SHRAV_R_W = 0x5a,
17574 NM_SHRLV_PH = 0x62,
17575 NM_SHRLV_QB = 0x6a,
17576 NM_SHLLV_QB = 0x72,
17577 NM_SHLLV_S_W = 0x7a,
17579 NM_SHILO = 0x03,
17581 NM_MULEQ_S_W_PHL = 0x04,
17582 NM_MULEQ_S_W_PHR = 0x0c,
17584 NM_MUL_S_PH = 0x05,
17585 NM_PRECR_QB_PH = 0x0d,
17586 NM_PRECRQ_QB_PH = 0x15,
17587 NM_PRECRQ_PH_W = 0x1d,
17588 NM_PRECRQ_RS_PH_W = 0x25,
17589 NM_PRECRQU_S_QB_PH = 0x2d,
17590 NM_PACKRL_PH = 0x35,
17591 NM_PICK_QB = 0x3d,
17592 NM_PICK_PH = 0x45,
17594 NM_SHRA_R_W = 0x5e,
17595 NM_SHRA_R_PH = 0x66,
17596 NM_SHLL_S_PH = 0x76,
17597 NM_SHLL_S_W = 0x7e,
17599 NM_REPL_PH = 0x07
17602 /* POOL32A7 instruction pool */
17603 enum {
17604 NM_P_LSX = 0x00,
17605 NM_LSA = 0x01,
17606 NM_EXTW = 0x03,
17607 NM_POOL32AXF = 0x07,
17610 /* P.SR instruction pool */
17611 enum {
17612 NM_PP_SR = 0x00,
17613 NM_P_SR_F = 0x01,
17616 /* P.SHIFT instruction pool */
17617 enum {
17618 NM_P_SLL = 0x00,
17619 NM_SRL = 0x02,
17620 NM_SRA = 0x04,
17621 NM_ROTR = 0x06,
17624 /* P.ROTX instruction pool */
17625 enum {
17626 NM_ROTX = 0x00,
17629 /* P.INS instruction pool */
17630 enum {
17631 NM_INS = 0x00,
17634 /* P.EXT instruction pool */
17635 enum {
17636 NM_EXT = 0x00,
17639 /* POOL32F_0 (fmt) instruction pool */
17640 enum {
17641 NM_RINT_S = 0x04,
17642 NM_RINT_D = 0x44,
17643 NM_ADD_S = 0x06,
17644 NM_SELEQZ_S = 0x07,
17645 NM_SELEQZ_D = 0x47,
17646 NM_CLASS_S = 0x0c,
17647 NM_CLASS_D = 0x4c,
17648 NM_SUB_S = 0x0e,
17649 NM_SELNEZ_S = 0x0f,
17650 NM_SELNEZ_D = 0x4f,
17651 NM_MUL_S = 0x16,
17652 NM_SEL_S = 0x17,
17653 NM_SEL_D = 0x57,
17654 NM_DIV_S = 0x1e,
17655 NM_ADD_D = 0x26,
17656 NM_SUB_D = 0x2e,
17657 NM_MUL_D = 0x36,
17658 NM_MADDF_S = 0x37,
17659 NM_MADDF_D = 0x77,
17660 NM_DIV_D = 0x3e,
17661 NM_MSUBF_S = 0x3f,
17662 NM_MSUBF_D = 0x7f,
17665 /* POOL32F_3 instruction pool */
17666 enum {
17667 NM_MIN_FMT = 0x00,
17668 NM_MAX_FMT = 0x01,
17669 NM_MINA_FMT = 0x04,
17670 NM_MAXA_FMT = 0x05,
17671 NM_POOL32FXF = 0x07,
17674 /* POOL32F_5 instruction pool */
17675 enum {
17676 NM_CMP_CONDN_S = 0x00,
17677 NM_CMP_CONDN_D = 0x02,
17680 /* P.GP.LH instruction pool */
17681 enum {
17682 NM_LHGP = 0x00,
17683 NM_LHUGP = 0x01,
17686 /* P.GP.SH instruction pool */
17687 enum {
17688 NM_SHGP = 0x00,
17691 /* P.GP.CP1 instruction pool */
17692 enum {
17693 NM_LWC1GP = 0x00,
17694 NM_SWC1GP = 0x01,
17695 NM_LDC1GP = 0x02,
17696 NM_SDC1GP = 0x03,
17699 /* P.LS.S0 instruction pool */
17700 enum {
17701 NM_LBS9 = 0x00,
17702 NM_LHS9 = 0x04,
17703 NM_LWS9 = 0x08,
17704 NM_LDS9 = 0x0c,
17706 NM_SBS9 = 0x01,
17707 NM_SHS9 = 0x05,
17708 NM_SWS9 = 0x09,
17709 NM_SDS9 = 0x0d,
17711 NM_LBUS9 = 0x02,
17712 NM_LHUS9 = 0x06,
17713 NM_LWC1S9 = 0x0a,
17714 NM_LDC1S9 = 0x0e,
17716 NM_P_PREFS9 = 0x03,
17717 NM_LWUS9 = 0x07,
17718 NM_SWC1S9 = 0x0b,
17719 NM_SDC1S9 = 0x0f,
17722 /* P.LS.S1 instruction pool */
17723 enum {
17724 NM_ASET_ACLR = 0x02,
17725 NM_UALH = 0x04,
17726 NM_UASH = 0x05,
17727 NM_CACHE = 0x07,
17728 NM_P_LL = 0x0a,
17729 NM_P_SC = 0x0b,
17732 /* P.LS.E0 instruction pool */
17733 enum {
17734 NM_LBE = 0x00,
17735 NM_SBE = 0x01,
17736 NM_LBUE = 0x02,
17737 NM_P_PREFE = 0x03,
17738 NM_LHE = 0x04,
17739 NM_SHE = 0x05,
17740 NM_LHUE = 0x06,
17741 NM_CACHEE = 0x07,
17742 NM_LWE = 0x08,
17743 NM_SWE = 0x09,
17744 NM_P_LLE = 0x0a,
17745 NM_P_SCE = 0x0b,
17748 /* P.PREFE instruction pool */
17749 enum {
17750 NM_SYNCIE = 0x00,
17751 NM_PREFE = 0x01,
17754 /* P.LLE instruction pool */
17755 enum {
17756 NM_LLE = 0x00,
17757 NM_LLWPE = 0x01,
17760 /* P.SCE instruction pool */
17761 enum {
17762 NM_SCE = 0x00,
17763 NM_SCWPE = 0x01,
17766 /* P.LS.WM instruction pool */
17767 enum {
17768 NM_LWM = 0x00,
17769 NM_SWM = 0x01,
17772 /* P.LS.UAWM instruction pool */
17773 enum {
17774 NM_UALWM = 0x00,
17775 NM_UASWM = 0x01,
17778 /* P.BR3A instruction pool */
17779 enum {
17780 NM_BC1EQZC = 0x00,
17781 NM_BC1NEZC = 0x01,
17782 NM_BC2EQZC = 0x02,
17783 NM_BC2NEZC = 0x03,
17784 NM_BPOSGE32C = 0x04,
17787 /* P16.RI instruction pool */
17788 enum {
17789 NM_P16_SYSCALL = 0x01,
17790 NM_BREAK16 = 0x02,
17791 NM_SDBBP16 = 0x03,
17794 /* POOL16C_0 instruction pool */
17795 enum {
17796 NM_POOL16C_00 = 0x00,
17799 /* P16.JRC instruction pool */
17800 enum {
17801 NM_JRC = 0x00,
17802 NM_JALRC16 = 0x01,
17805 /* P.SYSCALL instruction pool */
17806 enum {
17807 NM_SYSCALL = 0x00,
17808 NM_HYPCALL = 0x01,
17811 /* P.TRAP instruction pool */
17812 enum {
17813 NM_TEQ = 0x00,
17814 NM_TNE = 0x01,
17817 /* P.CMOVE instruction pool */
17818 enum {
17819 NM_MOVZ = 0x00,
17820 NM_MOVN = 0x01,
17823 /* POOL32Axf instruction pool */
17824 enum {
17825 NM_POOL32AXF_1 = 0x01,
17826 NM_POOL32AXF_2 = 0x02,
17827 NM_POOL32AXF_4 = 0x04,
17828 NM_POOL32AXF_5 = 0x05,
17829 NM_POOL32AXF_7 = 0x07,
17832 /* POOL32Axf_1 instruction pool */
17833 enum {
17834 NM_POOL32AXF_1_0 = 0x00,
17835 NM_POOL32AXF_1_1 = 0x01,
17836 NM_POOL32AXF_1_3 = 0x03,
17837 NM_POOL32AXF_1_4 = 0x04,
17838 NM_POOL32AXF_1_5 = 0x05,
17839 NM_POOL32AXF_1_7 = 0x07,
17842 /* POOL32Axf_2 instruction pool */
17843 enum {
17844 NM_POOL32AXF_2_0_7 = 0x00,
17845 NM_POOL32AXF_2_8_15 = 0x01,
17846 NM_POOL32AXF_2_16_23 = 0x02,
17847 NM_POOL32AXF_2_24_31 = 0x03,
17850 /* POOL32Axf_7 instruction pool */
17851 enum {
17852 NM_SHRA_R_QB = 0x0,
17853 NM_SHRL_PH = 0x1,
17854 NM_REPL_QB = 0x2,
17857 /* POOL32Axf_1_0 instruction pool */
17858 enum {
17859 NM_MFHI = 0x0,
17860 NM_MFLO = 0x1,
17861 NM_MTHI = 0x2,
17862 NM_MTLO = 0x3,
17865 /* POOL32Axf_1_1 instruction pool */
17866 enum {
17867 NM_MTHLIP = 0x0,
17868 NM_SHILOV = 0x1,
17871 /* POOL32Axf_1_3 instruction pool */
17872 enum {
17873 NM_RDDSP = 0x0,
17874 NM_WRDSP = 0x1,
17875 NM_EXTP = 0x2,
17876 NM_EXTPDP = 0x3,
17879 /* POOL32Axf_1_4 instruction pool */
17880 enum {
17881 NM_SHLL_QB = 0x0,
17882 NM_SHRL_QB = 0x1,
17885 /* POOL32Axf_1_5 instruction pool */
17886 enum {
17887 NM_MAQ_S_W_PHR = 0x0,
17888 NM_MAQ_S_W_PHL = 0x1,
17889 NM_MAQ_SA_W_PHR = 0x2,
17890 NM_MAQ_SA_W_PHL = 0x3,
17893 /* POOL32Axf_1_7 instruction pool */
17894 enum {
17895 NM_EXTR_W = 0x0,
17896 NM_EXTR_R_W = 0x1,
17897 NM_EXTR_RS_W = 0x2,
17898 NM_EXTR_S_H = 0x3,
17901 /* POOL32Axf_2_0_7 instruction pool */
17902 enum {
17903 NM_DPA_W_PH = 0x0,
17904 NM_DPAQ_S_W_PH = 0x1,
17905 NM_DPS_W_PH = 0x2,
17906 NM_DPSQ_S_W_PH = 0x3,
17907 NM_BALIGN = 0x4,
17908 NM_MADD = 0x5,
17909 NM_MULT = 0x6,
17910 NM_EXTRV_W = 0x7,
17913 /* POOL32Axf_2_8_15 instruction pool */
17914 enum {
17915 NM_DPAX_W_PH = 0x0,
17916 NM_DPAQ_SA_L_W = 0x1,
17917 NM_DPSX_W_PH = 0x2,
17918 NM_DPSQ_SA_L_W = 0x3,
17919 NM_MADDU = 0x5,
17920 NM_MULTU = 0x6,
17921 NM_EXTRV_R_W = 0x7,
17924 /* POOL32Axf_2_16_23 instruction pool */
17925 enum {
17926 NM_DPAU_H_QBL = 0x0,
17927 NM_DPAQX_S_W_PH = 0x1,
17928 NM_DPSU_H_QBL = 0x2,
17929 NM_DPSQX_S_W_PH = 0x3,
17930 NM_EXTPV = 0x4,
17931 NM_MSUB = 0x5,
17932 NM_MULSA_W_PH = 0x6,
17933 NM_EXTRV_RS_W = 0x7,
17936 /* POOL32Axf_2_24_31 instruction pool */
17937 enum {
17938 NM_DPAU_H_QBR = 0x0,
17939 NM_DPAQX_SA_W_PH = 0x1,
17940 NM_DPSU_H_QBR = 0x2,
17941 NM_DPSQX_SA_W_PH = 0x3,
17942 NM_EXTPDPV = 0x4,
17943 NM_MSUBU = 0x5,
17944 NM_MULSAQ_S_W_PH = 0x6,
17945 NM_EXTRV_S_H = 0x7,
17948 /* POOL32Axf_{4, 5} instruction pool */
17949 enum {
17950 NM_CLO = 0x25,
17951 NM_CLZ = 0x2d,
17953 NM_TLBP = 0x01,
17954 NM_TLBR = 0x09,
17955 NM_TLBWI = 0x11,
17956 NM_TLBWR = 0x19,
17957 NM_TLBINV = 0x03,
17958 NM_TLBINVF = 0x0b,
17959 NM_DI = 0x23,
17960 NM_EI = 0x2b,
17961 NM_RDPGPR = 0x70,
17962 NM_WRPGPR = 0x78,
17963 NM_WAIT = 0x61,
17964 NM_DERET = 0x71,
17965 NM_ERETX = 0x79,
17967 /* nanoMIPS DSP instructions */
17968 NM_ABSQ_S_QB = 0x00,
17969 NM_ABSQ_S_PH = 0x08,
17970 NM_ABSQ_S_W = 0x10,
17971 NM_PRECEQ_W_PHL = 0x28,
17972 NM_PRECEQ_W_PHR = 0x30,
17973 NM_PRECEQU_PH_QBL = 0x38,
17974 NM_PRECEQU_PH_QBR = 0x48,
17975 NM_PRECEU_PH_QBL = 0x58,
17976 NM_PRECEU_PH_QBR = 0x68,
17977 NM_PRECEQU_PH_QBLA = 0x39,
17978 NM_PRECEQU_PH_QBRA = 0x49,
17979 NM_PRECEU_PH_QBLA = 0x59,
17980 NM_PRECEU_PH_QBRA = 0x69,
17981 NM_REPLV_PH = 0x01,
17982 NM_REPLV_QB = 0x09,
17983 NM_BITREV = 0x18,
17984 NM_INSV = 0x20,
17985 NM_RADDU_W_QB = 0x78,
17987 NM_BITSWAP = 0x05,
17988 NM_WSBH = 0x3d,
17991 /* PP.SR instruction pool */
17992 enum {
17993 NM_SAVE = 0x00,
17994 NM_RESTORE = 0x02,
17995 NM_RESTORE_JRC = 0x03,
17998 /* P.SR.F instruction pool */
17999 enum {
18000 NM_SAVEF = 0x00,
18001 NM_RESTOREF = 0x01,
18004 /* P16.SYSCALL instruction pool */
18005 enum {
18006 NM_SYSCALL16 = 0x00,
18007 NM_HYPCALL16 = 0x01,
18010 /* POOL16C_00 instruction pool */
18011 enum {
18012 NM_NOT16 = 0x00,
18013 NM_XOR16 = 0x01,
18014 NM_AND16 = 0x02,
18015 NM_OR16 = 0x03,
18018 /* PP.LSX and PP.LSXS instruction pool */
18019 enum {
18020 NM_LBX = 0x00,
18021 NM_LHX = 0x04,
18022 NM_LWX = 0x08,
18023 NM_LDX = 0x0c,
18025 NM_SBX = 0x01,
18026 NM_SHX = 0x05,
18027 NM_SWX = 0x09,
18028 NM_SDX = 0x0d,
18030 NM_LBUX = 0x02,
18031 NM_LHUX = 0x06,
18032 NM_LWC1X = 0x0a,
18033 NM_LDC1X = 0x0e,
18035 NM_LWUX = 0x07,
18036 NM_SWC1X = 0x0b,
18037 NM_SDC1X = 0x0f,
18039 NM_LHXS = 0x04,
18040 NM_LWXS = 0x08,
18041 NM_LDXS = 0x0c,
18043 NM_SHXS = 0x05,
18044 NM_SWXS = 0x09,
18045 NM_SDXS = 0x0d,
18047 NM_LHUXS = 0x06,
18048 NM_LWC1XS = 0x0a,
18049 NM_LDC1XS = 0x0e,
18051 NM_LWUXS = 0x07,
18052 NM_SWC1XS = 0x0b,
18053 NM_SDC1XS = 0x0f,
18056 /* ERETx instruction pool */
18057 enum {
18058 NM_ERET = 0x00,
18059 NM_ERETNC = 0x01,
18062 /* POOL32FxF_{0, 1} insturction pool */
18063 enum {
18064 NM_CFC1 = 0x40,
18065 NM_CTC1 = 0x60,
18066 NM_MFC1 = 0x80,
18067 NM_MTC1 = 0xa0,
18068 NM_MFHC1 = 0xc0,
18069 NM_MTHC1 = 0xe0,
18071 NM_CVT_S_PL = 0x84,
18072 NM_CVT_S_PU = 0xa4,
18074 NM_CVT_L_S = 0x004,
18075 NM_CVT_L_D = 0x104,
18076 NM_CVT_W_S = 0x024,
18077 NM_CVT_W_D = 0x124,
18079 NM_RSQRT_S = 0x008,
18080 NM_RSQRT_D = 0x108,
18082 NM_SQRT_S = 0x028,
18083 NM_SQRT_D = 0x128,
18085 NM_RECIP_S = 0x048,
18086 NM_RECIP_D = 0x148,
18088 NM_FLOOR_L_S = 0x00c,
18089 NM_FLOOR_L_D = 0x10c,
18091 NM_FLOOR_W_S = 0x02c,
18092 NM_FLOOR_W_D = 0x12c,
18094 NM_CEIL_L_S = 0x04c,
18095 NM_CEIL_L_D = 0x14c,
18096 NM_CEIL_W_S = 0x06c,
18097 NM_CEIL_W_D = 0x16c,
18098 NM_TRUNC_L_S = 0x08c,
18099 NM_TRUNC_L_D = 0x18c,
18100 NM_TRUNC_W_S = 0x0ac,
18101 NM_TRUNC_W_D = 0x1ac,
18102 NM_ROUND_L_S = 0x0cc,
18103 NM_ROUND_L_D = 0x1cc,
18104 NM_ROUND_W_S = 0x0ec,
18105 NM_ROUND_W_D = 0x1ec,
18107 NM_MOV_S = 0x01,
18108 NM_MOV_D = 0x81,
18109 NM_ABS_S = 0x0d,
18110 NM_ABS_D = 0x8d,
18111 NM_NEG_S = 0x2d,
18112 NM_NEG_D = 0xad,
18113 NM_CVT_D_S = 0x04d,
18114 NM_CVT_D_W = 0x0cd,
18115 NM_CVT_D_L = 0x14d,
18116 NM_CVT_S_D = 0x06d,
18117 NM_CVT_S_W = 0x0ed,
18118 NM_CVT_S_L = 0x16d,
18121 /* P.LL instruction pool */
18122 enum {
18123 NM_LL = 0x00,
18124 NM_LLWP = 0x01,
18127 /* P.SC instruction pool */
18128 enum {
18129 NM_SC = 0x00,
18130 NM_SCWP = 0x01,
18133 /* P.DVP instruction pool */
18134 enum {
18135 NM_DVP = 0x00,
18136 NM_EVP = 0x01,
18142 * nanoMIPS decoding engine
18147 /* extraction utilities */
18149 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18150 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18151 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18152 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18153 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18155 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18156 static inline int decode_gpr_gpr3(int r)
18158 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18160 return map[r & 0x7];
18163 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18164 static inline int decode_gpr_gpr3_src_store(int r)
18166 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18168 return map[r & 0x7];
18171 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18172 static inline int decode_gpr_gpr4(int r)
18174 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18175 16, 17, 18, 19, 20, 21, 22, 23 };
18177 return map[r & 0xf];
18180 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18181 static inline int decode_gpr_gpr4_zero(int r)
18183 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18184 16, 17, 18, 19, 20, 21, 22, 23 };
18186 return map[r & 0xf];
18190 static void gen_adjust_sp(DisasContext *ctx, int u)
18192 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18195 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18196 uint8_t gp, uint16_t u)
18198 int counter = 0;
18199 TCGv va = tcg_temp_new();
18200 TCGv t0 = tcg_temp_new();
18202 while (counter != count) {
18203 bool use_gp = gp && (counter == count - 1);
18204 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18205 int this_offset = -((counter + 1) << 2);
18206 gen_base_offset_addr(ctx, va, 29, this_offset);
18207 gen_load_gpr(t0, this_rt);
18208 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18209 (MO_TEUL | ctx->default_tcg_memop_mask));
18210 counter++;
18213 /* adjust stack pointer */
18214 gen_adjust_sp(ctx, -u);
18216 tcg_temp_free(t0);
18217 tcg_temp_free(va);
18220 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18221 uint8_t gp, uint16_t u)
18223 int counter = 0;
18224 TCGv va = tcg_temp_new();
18225 TCGv t0 = tcg_temp_new();
18227 while (counter != count) {
18228 bool use_gp = gp && (counter == count - 1);
18229 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18230 int this_offset = u - ((counter + 1) << 2);
18231 gen_base_offset_addr(ctx, va, 29, this_offset);
18232 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18233 ctx->default_tcg_memop_mask);
18234 tcg_gen_ext32s_tl(t0, t0);
18235 gen_store_gpr(t0, this_rt);
18236 counter++;
18239 /* adjust stack pointer */
18240 gen_adjust_sp(ctx, u);
18242 tcg_temp_free(t0);
18243 tcg_temp_free(va);
18246 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18248 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18249 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18251 switch (extract32(ctx->opcode, 2, 2)) {
18252 case NM_NOT16:
18253 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18254 break;
18255 case NM_AND16:
18256 gen_logic(ctx, OPC_AND, rt, rt, rs);
18257 break;
18258 case NM_XOR16:
18259 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18260 break;
18261 case NM_OR16:
18262 gen_logic(ctx, OPC_OR, rt, rt, rs);
18263 break;
18267 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18269 int rt = extract32(ctx->opcode, 21, 5);
18270 int rs = extract32(ctx->opcode, 16, 5);
18271 int rd = extract32(ctx->opcode, 11, 5);
18273 switch (extract32(ctx->opcode, 3, 7)) {
18274 case NM_P_TRAP:
18275 switch (extract32(ctx->opcode, 10, 1)) {
18276 case NM_TEQ:
18277 check_nms(ctx);
18278 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18279 break;
18280 case NM_TNE:
18281 check_nms(ctx);
18282 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18283 break;
18285 break;
18286 case NM_RDHWR:
18287 check_nms(ctx);
18288 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18289 break;
18290 case NM_SEB:
18291 check_nms(ctx);
18292 gen_bshfl(ctx, OPC_SEB, rs, rt);
18293 break;
18294 case NM_SEH:
18295 gen_bshfl(ctx, OPC_SEH, rs, rt);
18296 break;
18297 case NM_SLLV:
18298 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18299 break;
18300 case NM_SRLV:
18301 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18302 break;
18303 case NM_SRAV:
18304 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18305 break;
18306 case NM_ROTRV:
18307 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18308 break;
18309 case NM_ADD:
18310 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18311 break;
18312 case NM_ADDU:
18313 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18314 break;
18315 case NM_SUB:
18316 check_nms(ctx);
18317 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18318 break;
18319 case NM_SUBU:
18320 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18321 break;
18322 case NM_P_CMOVE:
18323 switch (extract32(ctx->opcode, 10, 1)) {
18324 case NM_MOVZ:
18325 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18326 break;
18327 case NM_MOVN:
18328 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18329 break;
18331 break;
18332 case NM_AND:
18333 gen_logic(ctx, OPC_AND, rd, rs, rt);
18334 break;
18335 case NM_OR:
18336 gen_logic(ctx, OPC_OR, rd, rs, rt);
18337 break;
18338 case NM_NOR:
18339 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18340 break;
18341 case NM_XOR:
18342 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18343 break;
18344 case NM_SLT:
18345 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18346 break;
18347 case NM_P_SLTU:
18348 if (rd == 0) {
18349 /* P_DVP */
18350 #ifndef CONFIG_USER_ONLY
18351 TCGv t0 = tcg_temp_new();
18352 switch (extract32(ctx->opcode, 10, 1)) {
18353 case NM_DVP:
18354 if (ctx->vp) {
18355 check_cp0_enabled(ctx);
18356 gen_helper_dvp(t0, cpu_env);
18357 gen_store_gpr(t0, rt);
18359 break;
18360 case NM_EVP:
18361 if (ctx->vp) {
18362 check_cp0_enabled(ctx);
18363 gen_helper_evp(t0, cpu_env);
18364 gen_store_gpr(t0, rt);
18366 break;
18368 tcg_temp_free(t0);
18369 #endif
18370 } else {
18371 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18373 break;
18374 case NM_SOV:
18376 TCGv t0 = tcg_temp_new();
18377 TCGv t1 = tcg_temp_new();
18378 TCGv t2 = tcg_temp_new();
18380 gen_load_gpr(t1, rs);
18381 gen_load_gpr(t2, rt);
18382 tcg_gen_add_tl(t0, t1, t2);
18383 tcg_gen_ext32s_tl(t0, t0);
18384 tcg_gen_xor_tl(t1, t1, t2);
18385 tcg_gen_xor_tl(t2, t0, t2);
18386 tcg_gen_andc_tl(t1, t2, t1);
18388 /* operands of same sign, result different sign */
18389 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18390 gen_store_gpr(t0, rd);
18392 tcg_temp_free(t0);
18393 tcg_temp_free(t1);
18394 tcg_temp_free(t2);
18396 break;
18397 case NM_MUL:
18398 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18399 break;
18400 case NM_MUH:
18401 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18402 break;
18403 case NM_MULU:
18404 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18405 break;
18406 case NM_MUHU:
18407 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18408 break;
18409 case NM_DIV:
18410 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18411 break;
18412 case NM_MOD:
18413 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18414 break;
18415 case NM_DIVU:
18416 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18417 break;
18418 case NM_MODU:
18419 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18420 break;
18421 #ifndef CONFIG_USER_ONLY
18422 case NM_MFC0:
18423 check_cp0_enabled(ctx);
18424 if (rt == 0) {
18425 /* Treat as NOP. */
18426 break;
18428 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18429 break;
18430 case NM_MTC0:
18431 check_cp0_enabled(ctx);
18433 TCGv t0 = tcg_temp_new();
18435 gen_load_gpr(t0, rt);
18436 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18437 tcg_temp_free(t0);
18439 break;
18440 case NM_D_E_MT_VPE:
18442 uint8_t sc = extract32(ctx->opcode, 10, 1);
18443 TCGv t0 = tcg_temp_new();
18445 switch (sc) {
18446 case 0:
18447 if (rs == 1) {
18448 /* DMT */
18449 check_cp0_mt(ctx);
18450 gen_helper_dmt(t0);
18451 gen_store_gpr(t0, rt);
18452 } else if (rs == 0) {
18453 /* DVPE */
18454 check_cp0_mt(ctx);
18455 gen_helper_dvpe(t0, cpu_env);
18456 gen_store_gpr(t0, rt);
18457 } else {
18458 gen_reserved_instruction(ctx);
18460 break;
18461 case 1:
18462 if (rs == 1) {
18463 /* EMT */
18464 check_cp0_mt(ctx);
18465 gen_helper_emt(t0);
18466 gen_store_gpr(t0, rt);
18467 } else if (rs == 0) {
18468 /* EVPE */
18469 check_cp0_mt(ctx);
18470 gen_helper_evpe(t0, cpu_env);
18471 gen_store_gpr(t0, rt);
18472 } else {
18473 gen_reserved_instruction(ctx);
18475 break;
18478 tcg_temp_free(t0);
18480 break;
18481 case NM_FORK:
18482 check_mt(ctx);
18484 TCGv t0 = tcg_temp_new();
18485 TCGv t1 = tcg_temp_new();
18487 gen_load_gpr(t0, rt);
18488 gen_load_gpr(t1, rs);
18489 gen_helper_fork(t0, t1);
18490 tcg_temp_free(t0);
18491 tcg_temp_free(t1);
18493 break;
18494 case NM_MFTR:
18495 case NM_MFHTR:
18496 check_cp0_enabled(ctx);
18497 if (rd == 0) {
18498 /* Treat as NOP. */
18499 return;
18501 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18502 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18503 break;
18504 case NM_MTTR:
18505 case NM_MTHTR:
18506 check_cp0_enabled(ctx);
18507 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18508 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18509 break;
18510 case NM_YIELD:
18511 check_mt(ctx);
18513 TCGv t0 = tcg_temp_new();
18515 gen_load_gpr(t0, rs);
18516 gen_helper_yield(t0, cpu_env, t0);
18517 gen_store_gpr(t0, rt);
18518 tcg_temp_free(t0);
18520 break;
18521 #endif
18522 default:
18523 gen_reserved_instruction(ctx);
18524 break;
18528 /* dsp */
18529 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18530 int ret, int v1, int v2)
18532 TCGv_i32 t0;
18533 TCGv v0_t;
18534 TCGv v1_t;
18536 t0 = tcg_temp_new_i32();
18538 v0_t = tcg_temp_new();
18539 v1_t = tcg_temp_new();
18541 tcg_gen_movi_i32(t0, v2 >> 3);
18543 gen_load_gpr(v0_t, ret);
18544 gen_load_gpr(v1_t, v1);
18546 switch (opc) {
18547 case NM_MAQ_S_W_PHR:
18548 check_dsp(ctx);
18549 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18550 break;
18551 case NM_MAQ_S_W_PHL:
18552 check_dsp(ctx);
18553 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18554 break;
18555 case NM_MAQ_SA_W_PHR:
18556 check_dsp(ctx);
18557 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18558 break;
18559 case NM_MAQ_SA_W_PHL:
18560 check_dsp(ctx);
18561 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18562 break;
18563 default:
18564 gen_reserved_instruction(ctx);
18565 break;
18568 tcg_temp_free_i32(t0);
18570 tcg_temp_free(v0_t);
18571 tcg_temp_free(v1_t);
18575 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18576 int ret, int v1, int v2)
18578 int16_t imm;
18579 TCGv t0 = tcg_temp_new();
18580 TCGv t1 = tcg_temp_new();
18581 TCGv v0_t = tcg_temp_new();
18583 gen_load_gpr(v0_t, v1);
18585 switch (opc) {
18586 case NM_POOL32AXF_1_0:
18587 check_dsp(ctx);
18588 switch (extract32(ctx->opcode, 12, 2)) {
18589 case NM_MFHI:
18590 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18591 break;
18592 case NM_MFLO:
18593 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18594 break;
18595 case NM_MTHI:
18596 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18597 break;
18598 case NM_MTLO:
18599 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18600 break;
18602 break;
18603 case NM_POOL32AXF_1_1:
18604 check_dsp(ctx);
18605 switch (extract32(ctx->opcode, 12, 2)) {
18606 case NM_MTHLIP:
18607 tcg_gen_movi_tl(t0, v2);
18608 gen_helper_mthlip(t0, v0_t, cpu_env);
18609 break;
18610 case NM_SHILOV:
18611 tcg_gen_movi_tl(t0, v2 >> 3);
18612 gen_helper_shilo(t0, v0_t, cpu_env);
18613 break;
18614 default:
18615 gen_reserved_instruction(ctx);
18616 break;
18618 break;
18619 case NM_POOL32AXF_1_3:
18620 check_dsp(ctx);
18621 imm = extract32(ctx->opcode, 14, 7);
18622 switch (extract32(ctx->opcode, 12, 2)) {
18623 case NM_RDDSP:
18624 tcg_gen_movi_tl(t0, imm);
18625 gen_helper_rddsp(t0, t0, cpu_env);
18626 gen_store_gpr(t0, ret);
18627 break;
18628 case NM_WRDSP:
18629 gen_load_gpr(t0, ret);
18630 tcg_gen_movi_tl(t1, imm);
18631 gen_helper_wrdsp(t0, t1, cpu_env);
18632 break;
18633 case NM_EXTP:
18634 tcg_gen_movi_tl(t0, v2 >> 3);
18635 tcg_gen_movi_tl(t1, v1);
18636 gen_helper_extp(t0, t0, t1, cpu_env);
18637 gen_store_gpr(t0, ret);
18638 break;
18639 case NM_EXTPDP:
18640 tcg_gen_movi_tl(t0, v2 >> 3);
18641 tcg_gen_movi_tl(t1, v1);
18642 gen_helper_extpdp(t0, t0, t1, cpu_env);
18643 gen_store_gpr(t0, ret);
18644 break;
18646 break;
18647 case NM_POOL32AXF_1_4:
18648 check_dsp(ctx);
18649 tcg_gen_movi_tl(t0, v2 >> 2);
18650 switch (extract32(ctx->opcode, 12, 1)) {
18651 case NM_SHLL_QB:
18652 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18653 gen_store_gpr(t0, ret);
18654 break;
18655 case NM_SHRL_QB:
18656 gen_helper_shrl_qb(t0, t0, v0_t);
18657 gen_store_gpr(t0, ret);
18658 break;
18660 break;
18661 case NM_POOL32AXF_1_5:
18662 opc = extract32(ctx->opcode, 12, 2);
18663 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18664 break;
18665 case NM_POOL32AXF_1_7:
18666 check_dsp(ctx);
18667 tcg_gen_movi_tl(t0, v2 >> 3);
18668 tcg_gen_movi_tl(t1, v1);
18669 switch (extract32(ctx->opcode, 12, 2)) {
18670 case NM_EXTR_W:
18671 gen_helper_extr_w(t0, t0, t1, cpu_env);
18672 gen_store_gpr(t0, ret);
18673 break;
18674 case NM_EXTR_R_W:
18675 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18676 gen_store_gpr(t0, ret);
18677 break;
18678 case NM_EXTR_RS_W:
18679 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18680 gen_store_gpr(t0, ret);
18681 break;
18682 case NM_EXTR_S_H:
18683 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18684 gen_store_gpr(t0, ret);
18685 break;
18687 break;
18688 default:
18689 gen_reserved_instruction(ctx);
18690 break;
18693 tcg_temp_free(t0);
18694 tcg_temp_free(t1);
18695 tcg_temp_free(v0_t);
18698 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18699 TCGv v0, TCGv v1, int rd)
18701 TCGv_i32 t0;
18703 t0 = tcg_temp_new_i32();
18705 tcg_gen_movi_i32(t0, rd >> 3);
18707 switch (opc) {
18708 case NM_POOL32AXF_2_0_7:
18709 switch (extract32(ctx->opcode, 9, 3)) {
18710 case NM_DPA_W_PH:
18711 check_dsp_r2(ctx);
18712 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18713 break;
18714 case NM_DPAQ_S_W_PH:
18715 check_dsp(ctx);
18716 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18717 break;
18718 case NM_DPS_W_PH:
18719 check_dsp_r2(ctx);
18720 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18721 break;
18722 case NM_DPSQ_S_W_PH:
18723 check_dsp(ctx);
18724 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18725 break;
18726 default:
18727 gen_reserved_instruction(ctx);
18728 break;
18730 break;
18731 case NM_POOL32AXF_2_8_15:
18732 switch (extract32(ctx->opcode, 9, 3)) {
18733 case NM_DPAX_W_PH:
18734 check_dsp_r2(ctx);
18735 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18736 break;
18737 case NM_DPAQ_SA_L_W:
18738 check_dsp(ctx);
18739 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18740 break;
18741 case NM_DPSX_W_PH:
18742 check_dsp_r2(ctx);
18743 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18744 break;
18745 case NM_DPSQ_SA_L_W:
18746 check_dsp(ctx);
18747 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18748 break;
18749 default:
18750 gen_reserved_instruction(ctx);
18751 break;
18753 break;
18754 case NM_POOL32AXF_2_16_23:
18755 switch (extract32(ctx->opcode, 9, 3)) {
18756 case NM_DPAU_H_QBL:
18757 check_dsp(ctx);
18758 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18759 break;
18760 case NM_DPAQX_S_W_PH:
18761 check_dsp_r2(ctx);
18762 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18763 break;
18764 case NM_DPSU_H_QBL:
18765 check_dsp(ctx);
18766 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18767 break;
18768 case NM_DPSQX_S_W_PH:
18769 check_dsp_r2(ctx);
18770 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18771 break;
18772 case NM_MULSA_W_PH:
18773 check_dsp_r2(ctx);
18774 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18775 break;
18776 default:
18777 gen_reserved_instruction(ctx);
18778 break;
18780 break;
18781 case NM_POOL32AXF_2_24_31:
18782 switch (extract32(ctx->opcode, 9, 3)) {
18783 case NM_DPAU_H_QBR:
18784 check_dsp(ctx);
18785 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18786 break;
18787 case NM_DPAQX_SA_W_PH:
18788 check_dsp_r2(ctx);
18789 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18790 break;
18791 case NM_DPSU_H_QBR:
18792 check_dsp(ctx);
18793 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18794 break;
18795 case NM_DPSQX_SA_W_PH:
18796 check_dsp_r2(ctx);
18797 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18798 break;
18799 case NM_MULSAQ_S_W_PH:
18800 check_dsp(ctx);
18801 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18802 break;
18803 default:
18804 gen_reserved_instruction(ctx);
18805 break;
18807 break;
18808 default:
18809 gen_reserved_instruction(ctx);
18810 break;
18813 tcg_temp_free_i32(t0);
18816 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18817 int rt, int rs, int rd)
18819 int ret = rt;
18820 TCGv t0 = tcg_temp_new();
18821 TCGv t1 = tcg_temp_new();
18822 TCGv v0_t = tcg_temp_new();
18823 TCGv v1_t = tcg_temp_new();
18825 gen_load_gpr(v0_t, rt);
18826 gen_load_gpr(v1_t, rs);
18828 switch (opc) {
18829 case NM_POOL32AXF_2_0_7:
18830 switch (extract32(ctx->opcode, 9, 3)) {
18831 case NM_DPA_W_PH:
18832 case NM_DPAQ_S_W_PH:
18833 case NM_DPS_W_PH:
18834 case NM_DPSQ_S_W_PH:
18835 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18836 break;
18837 case NM_BALIGN:
18838 check_dsp_r2(ctx);
18839 if (rt != 0) {
18840 gen_load_gpr(t0, rs);
18841 rd &= 3;
18842 if (rd != 0 && rd != 2) {
18843 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18844 tcg_gen_ext32u_tl(t0, t0);
18845 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18846 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18848 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18850 break;
18851 case NM_MADD:
18852 check_dsp(ctx);
18854 int acc = extract32(ctx->opcode, 14, 2);
18855 TCGv_i64 t2 = tcg_temp_new_i64();
18856 TCGv_i64 t3 = tcg_temp_new_i64();
18858 gen_load_gpr(t0, rt);
18859 gen_load_gpr(t1, rs);
18860 tcg_gen_ext_tl_i64(t2, t0);
18861 tcg_gen_ext_tl_i64(t3, t1);
18862 tcg_gen_mul_i64(t2, t2, t3);
18863 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18864 tcg_gen_add_i64(t2, t2, t3);
18865 tcg_temp_free_i64(t3);
18866 gen_move_low32(cpu_LO[acc], t2);
18867 gen_move_high32(cpu_HI[acc], t2);
18868 tcg_temp_free_i64(t2);
18870 break;
18871 case NM_MULT:
18872 check_dsp(ctx);
18874 int acc = extract32(ctx->opcode, 14, 2);
18875 TCGv_i32 t2 = tcg_temp_new_i32();
18876 TCGv_i32 t3 = tcg_temp_new_i32();
18878 gen_load_gpr(t0, rs);
18879 gen_load_gpr(t1, rt);
18880 tcg_gen_trunc_tl_i32(t2, t0);
18881 tcg_gen_trunc_tl_i32(t3, t1);
18882 tcg_gen_muls2_i32(t2, t3, t2, t3);
18883 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18884 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18885 tcg_temp_free_i32(t2);
18886 tcg_temp_free_i32(t3);
18888 break;
18889 case NM_EXTRV_W:
18890 check_dsp(ctx);
18891 gen_load_gpr(v1_t, rs);
18892 tcg_gen_movi_tl(t0, rd >> 3);
18893 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18894 gen_store_gpr(t0, ret);
18895 break;
18897 break;
18898 case NM_POOL32AXF_2_8_15:
18899 switch (extract32(ctx->opcode, 9, 3)) {
18900 case NM_DPAX_W_PH:
18901 case NM_DPAQ_SA_L_W:
18902 case NM_DPSX_W_PH:
18903 case NM_DPSQ_SA_L_W:
18904 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18905 break;
18906 case NM_MADDU:
18907 check_dsp(ctx);
18909 int acc = extract32(ctx->opcode, 14, 2);
18910 TCGv_i64 t2 = tcg_temp_new_i64();
18911 TCGv_i64 t3 = tcg_temp_new_i64();
18913 gen_load_gpr(t0, rs);
18914 gen_load_gpr(t1, rt);
18915 tcg_gen_ext32u_tl(t0, t0);
18916 tcg_gen_ext32u_tl(t1, t1);
18917 tcg_gen_extu_tl_i64(t2, t0);
18918 tcg_gen_extu_tl_i64(t3, t1);
18919 tcg_gen_mul_i64(t2, t2, t3);
18920 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18921 tcg_gen_add_i64(t2, t2, t3);
18922 tcg_temp_free_i64(t3);
18923 gen_move_low32(cpu_LO[acc], t2);
18924 gen_move_high32(cpu_HI[acc], t2);
18925 tcg_temp_free_i64(t2);
18927 break;
18928 case NM_MULTU:
18929 check_dsp(ctx);
18931 int acc = extract32(ctx->opcode, 14, 2);
18932 TCGv_i32 t2 = tcg_temp_new_i32();
18933 TCGv_i32 t3 = tcg_temp_new_i32();
18935 gen_load_gpr(t0, rs);
18936 gen_load_gpr(t1, rt);
18937 tcg_gen_trunc_tl_i32(t2, t0);
18938 tcg_gen_trunc_tl_i32(t3, t1);
18939 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18940 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18941 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18942 tcg_temp_free_i32(t2);
18943 tcg_temp_free_i32(t3);
18945 break;
18946 case NM_EXTRV_R_W:
18947 check_dsp(ctx);
18948 tcg_gen_movi_tl(t0, rd >> 3);
18949 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18950 gen_store_gpr(t0, ret);
18951 break;
18952 default:
18953 gen_reserved_instruction(ctx);
18954 break;
18956 break;
18957 case NM_POOL32AXF_2_16_23:
18958 switch (extract32(ctx->opcode, 9, 3)) {
18959 case NM_DPAU_H_QBL:
18960 case NM_DPAQX_S_W_PH:
18961 case NM_DPSU_H_QBL:
18962 case NM_DPSQX_S_W_PH:
18963 case NM_MULSA_W_PH:
18964 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18965 break;
18966 case NM_EXTPV:
18967 check_dsp(ctx);
18968 tcg_gen_movi_tl(t0, rd >> 3);
18969 gen_helper_extp(t0, t0, v1_t, cpu_env);
18970 gen_store_gpr(t0, ret);
18971 break;
18972 case NM_MSUB:
18973 check_dsp(ctx);
18975 int acc = extract32(ctx->opcode, 14, 2);
18976 TCGv_i64 t2 = tcg_temp_new_i64();
18977 TCGv_i64 t3 = tcg_temp_new_i64();
18979 gen_load_gpr(t0, rs);
18980 gen_load_gpr(t1, rt);
18981 tcg_gen_ext_tl_i64(t2, t0);
18982 tcg_gen_ext_tl_i64(t3, t1);
18983 tcg_gen_mul_i64(t2, t2, t3);
18984 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18985 tcg_gen_sub_i64(t2, t3, t2);
18986 tcg_temp_free_i64(t3);
18987 gen_move_low32(cpu_LO[acc], t2);
18988 gen_move_high32(cpu_HI[acc], t2);
18989 tcg_temp_free_i64(t2);
18991 break;
18992 case NM_EXTRV_RS_W:
18993 check_dsp(ctx);
18994 tcg_gen_movi_tl(t0, rd >> 3);
18995 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18996 gen_store_gpr(t0, ret);
18997 break;
18999 break;
19000 case NM_POOL32AXF_2_24_31:
19001 switch (extract32(ctx->opcode, 9, 3)) {
19002 case NM_DPAU_H_QBR:
19003 case NM_DPAQX_SA_W_PH:
19004 case NM_DPSU_H_QBR:
19005 case NM_DPSQX_SA_W_PH:
19006 case NM_MULSAQ_S_W_PH:
19007 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19008 break;
19009 case NM_EXTPDPV:
19010 check_dsp(ctx);
19011 tcg_gen_movi_tl(t0, rd >> 3);
19012 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19013 gen_store_gpr(t0, ret);
19014 break;
19015 case NM_MSUBU:
19016 check_dsp(ctx);
19018 int acc = extract32(ctx->opcode, 14, 2);
19019 TCGv_i64 t2 = tcg_temp_new_i64();
19020 TCGv_i64 t3 = tcg_temp_new_i64();
19022 gen_load_gpr(t0, rs);
19023 gen_load_gpr(t1, rt);
19024 tcg_gen_ext32u_tl(t0, t0);
19025 tcg_gen_ext32u_tl(t1, t1);
19026 tcg_gen_extu_tl_i64(t2, t0);
19027 tcg_gen_extu_tl_i64(t3, t1);
19028 tcg_gen_mul_i64(t2, t2, t3);
19029 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19030 tcg_gen_sub_i64(t2, t3, t2);
19031 tcg_temp_free_i64(t3);
19032 gen_move_low32(cpu_LO[acc], t2);
19033 gen_move_high32(cpu_HI[acc], t2);
19034 tcg_temp_free_i64(t2);
19036 break;
19037 case NM_EXTRV_S_H:
19038 check_dsp(ctx);
19039 tcg_gen_movi_tl(t0, rd >> 3);
19040 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19041 gen_store_gpr(t0, ret);
19042 break;
19044 break;
19045 default:
19046 gen_reserved_instruction(ctx);
19047 break;
19050 tcg_temp_free(t0);
19051 tcg_temp_free(t1);
19053 tcg_temp_free(v0_t);
19054 tcg_temp_free(v1_t);
19057 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19058 int rt, int rs)
19060 int ret = rt;
19061 TCGv t0 = tcg_temp_new();
19062 TCGv v0_t = tcg_temp_new();
19064 gen_load_gpr(v0_t, rs);
19066 switch (opc) {
19067 case NM_ABSQ_S_QB:
19068 check_dsp_r2(ctx);
19069 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19070 gen_store_gpr(v0_t, ret);
19071 break;
19072 case NM_ABSQ_S_PH:
19073 check_dsp(ctx);
19074 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19075 gen_store_gpr(v0_t, ret);
19076 break;
19077 case NM_ABSQ_S_W:
19078 check_dsp(ctx);
19079 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19080 gen_store_gpr(v0_t, ret);
19081 break;
19082 case NM_PRECEQ_W_PHL:
19083 check_dsp(ctx);
19084 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19085 tcg_gen_ext32s_tl(v0_t, v0_t);
19086 gen_store_gpr(v0_t, ret);
19087 break;
19088 case NM_PRECEQ_W_PHR:
19089 check_dsp(ctx);
19090 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19091 tcg_gen_shli_tl(v0_t, v0_t, 16);
19092 tcg_gen_ext32s_tl(v0_t, v0_t);
19093 gen_store_gpr(v0_t, ret);
19094 break;
19095 case NM_PRECEQU_PH_QBL:
19096 check_dsp(ctx);
19097 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19098 gen_store_gpr(v0_t, ret);
19099 break;
19100 case NM_PRECEQU_PH_QBR:
19101 check_dsp(ctx);
19102 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19103 gen_store_gpr(v0_t, ret);
19104 break;
19105 case NM_PRECEQU_PH_QBLA:
19106 check_dsp(ctx);
19107 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19108 gen_store_gpr(v0_t, ret);
19109 break;
19110 case NM_PRECEQU_PH_QBRA:
19111 check_dsp(ctx);
19112 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19113 gen_store_gpr(v0_t, ret);
19114 break;
19115 case NM_PRECEU_PH_QBL:
19116 check_dsp(ctx);
19117 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19118 gen_store_gpr(v0_t, ret);
19119 break;
19120 case NM_PRECEU_PH_QBR:
19121 check_dsp(ctx);
19122 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19123 gen_store_gpr(v0_t, ret);
19124 break;
19125 case NM_PRECEU_PH_QBLA:
19126 check_dsp(ctx);
19127 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19128 gen_store_gpr(v0_t, ret);
19129 break;
19130 case NM_PRECEU_PH_QBRA:
19131 check_dsp(ctx);
19132 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19133 gen_store_gpr(v0_t, ret);
19134 break;
19135 case NM_REPLV_PH:
19136 check_dsp(ctx);
19137 tcg_gen_ext16u_tl(v0_t, v0_t);
19138 tcg_gen_shli_tl(t0, v0_t, 16);
19139 tcg_gen_or_tl(v0_t, v0_t, t0);
19140 tcg_gen_ext32s_tl(v0_t, v0_t);
19141 gen_store_gpr(v0_t, ret);
19142 break;
19143 case NM_REPLV_QB:
19144 check_dsp(ctx);
19145 tcg_gen_ext8u_tl(v0_t, v0_t);
19146 tcg_gen_shli_tl(t0, v0_t, 8);
19147 tcg_gen_or_tl(v0_t, v0_t, t0);
19148 tcg_gen_shli_tl(t0, v0_t, 16);
19149 tcg_gen_or_tl(v0_t, v0_t, t0);
19150 tcg_gen_ext32s_tl(v0_t, v0_t);
19151 gen_store_gpr(v0_t, ret);
19152 break;
19153 case NM_BITREV:
19154 check_dsp(ctx);
19155 gen_helper_bitrev(v0_t, v0_t);
19156 gen_store_gpr(v0_t, ret);
19157 break;
19158 case NM_INSV:
19159 check_dsp(ctx);
19161 TCGv tv0 = tcg_temp_new();
19163 gen_load_gpr(tv0, rt);
19164 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19165 gen_store_gpr(v0_t, ret);
19166 tcg_temp_free(tv0);
19168 break;
19169 case NM_RADDU_W_QB:
19170 check_dsp(ctx);
19171 gen_helper_raddu_w_qb(v0_t, v0_t);
19172 gen_store_gpr(v0_t, ret);
19173 break;
19174 case NM_BITSWAP:
19175 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19176 break;
19177 case NM_CLO:
19178 check_nms(ctx);
19179 gen_cl(ctx, OPC_CLO, ret, rs);
19180 break;
19181 case NM_CLZ:
19182 check_nms(ctx);
19183 gen_cl(ctx, OPC_CLZ, ret, rs);
19184 break;
19185 case NM_WSBH:
19186 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19187 break;
19188 default:
19189 gen_reserved_instruction(ctx);
19190 break;
19193 tcg_temp_free(v0_t);
19194 tcg_temp_free(t0);
19197 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19198 int rt, int rs, int rd)
19200 TCGv t0 = tcg_temp_new();
19201 TCGv rs_t = tcg_temp_new();
19203 gen_load_gpr(rs_t, rs);
19205 switch (opc) {
19206 case NM_SHRA_R_QB:
19207 check_dsp_r2(ctx);
19208 tcg_gen_movi_tl(t0, rd >> 2);
19209 switch (extract32(ctx->opcode, 12, 1)) {
19210 case 0:
19211 /* NM_SHRA_QB */
19212 gen_helper_shra_qb(t0, t0, rs_t);
19213 gen_store_gpr(t0, rt);
19214 break;
19215 case 1:
19216 /* NM_SHRA_R_QB */
19217 gen_helper_shra_r_qb(t0, t0, rs_t);
19218 gen_store_gpr(t0, rt);
19219 break;
19221 break;
19222 case NM_SHRL_PH:
19223 check_dsp_r2(ctx);
19224 tcg_gen_movi_tl(t0, rd >> 1);
19225 gen_helper_shrl_ph(t0, t0, rs_t);
19226 gen_store_gpr(t0, rt);
19227 break;
19228 case NM_REPL_QB:
19229 check_dsp(ctx);
19231 int16_t imm;
19232 target_long result;
19233 imm = extract32(ctx->opcode, 13, 8);
19234 result = (uint32_t)imm << 24 |
19235 (uint32_t)imm << 16 |
19236 (uint32_t)imm << 8 |
19237 (uint32_t)imm;
19238 result = (int32_t)result;
19239 tcg_gen_movi_tl(t0, result);
19240 gen_store_gpr(t0, rt);
19242 break;
19243 default:
19244 gen_reserved_instruction(ctx);
19245 break;
19247 tcg_temp_free(t0);
19248 tcg_temp_free(rs_t);
19252 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19254 int rt = extract32(ctx->opcode, 21, 5);
19255 int rs = extract32(ctx->opcode, 16, 5);
19256 int rd = extract32(ctx->opcode, 11, 5);
19258 switch (extract32(ctx->opcode, 6, 3)) {
19259 case NM_POOL32AXF_1:
19261 int32_t op1 = extract32(ctx->opcode, 9, 3);
19262 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19264 break;
19265 case NM_POOL32AXF_2:
19267 int32_t op1 = extract32(ctx->opcode, 12, 2);
19268 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19270 break;
19271 case NM_POOL32AXF_4:
19273 int32_t op1 = extract32(ctx->opcode, 9, 7);
19274 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19276 break;
19277 case NM_POOL32AXF_5:
19278 switch (extract32(ctx->opcode, 9, 7)) {
19279 #ifndef CONFIG_USER_ONLY
19280 case NM_TLBP:
19281 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19282 break;
19283 case NM_TLBR:
19284 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19285 break;
19286 case NM_TLBWI:
19287 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19288 break;
19289 case NM_TLBWR:
19290 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19291 break;
19292 case NM_TLBINV:
19293 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19294 break;
19295 case NM_TLBINVF:
19296 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19297 break;
19298 case NM_DI:
19299 check_cp0_enabled(ctx);
19301 TCGv t0 = tcg_temp_new();
19303 save_cpu_state(ctx, 1);
19304 gen_helper_di(t0, cpu_env);
19305 gen_store_gpr(t0, rt);
19306 /* Stop translation as we may have switched the execution mode */
19307 ctx->base.is_jmp = DISAS_STOP;
19308 tcg_temp_free(t0);
19310 break;
19311 case NM_EI:
19312 check_cp0_enabled(ctx);
19314 TCGv t0 = tcg_temp_new();
19316 save_cpu_state(ctx, 1);
19317 gen_helper_ei(t0, cpu_env);
19318 gen_store_gpr(t0, rt);
19319 /* Stop translation as we may have switched the execution mode */
19320 ctx->base.is_jmp = DISAS_STOP;
19321 tcg_temp_free(t0);
19323 break;
19324 case NM_RDPGPR:
19325 gen_load_srsgpr(rs, rt);
19326 break;
19327 case NM_WRPGPR:
19328 gen_store_srsgpr(rs, rt);
19329 break;
19330 case NM_WAIT:
19331 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19332 break;
19333 case NM_DERET:
19334 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19335 break;
19336 case NM_ERETX:
19337 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19338 break;
19339 #endif
19340 default:
19341 gen_reserved_instruction(ctx);
19342 break;
19344 break;
19345 case NM_POOL32AXF_7:
19347 int32_t op1 = extract32(ctx->opcode, 9, 3);
19348 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19350 break;
19351 default:
19352 gen_reserved_instruction(ctx);
19353 break;
19357 /* Immediate Value Compact Branches */
19358 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19359 int rt, int32_t imm, int32_t offset)
19361 TCGCond cond = TCG_COND_ALWAYS;
19362 TCGv t0 = tcg_temp_new();
19363 TCGv t1 = tcg_temp_new();
19365 gen_load_gpr(t0, rt);
19366 tcg_gen_movi_tl(t1, imm);
19367 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19369 /* Load needed operands and calculate btarget */
19370 switch (opc) {
19371 case NM_BEQIC:
19372 if (rt == 0 && imm == 0) {
19373 /* Unconditional branch */
19374 } else if (rt == 0 && imm != 0) {
19375 /* Treat as NOP */
19376 goto out;
19377 } else {
19378 cond = TCG_COND_EQ;
19380 break;
19381 case NM_BBEQZC:
19382 case NM_BBNEZC:
19383 check_nms(ctx);
19384 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19385 gen_reserved_instruction(ctx);
19386 goto out;
19387 } else if (rt == 0 && opc == NM_BBEQZC) {
19388 /* Unconditional branch */
19389 } else if (rt == 0 && opc == NM_BBNEZC) {
19390 /* Treat as NOP */
19391 goto out;
19392 } else {
19393 tcg_gen_shri_tl(t0, t0, imm);
19394 tcg_gen_andi_tl(t0, t0, 1);
19395 tcg_gen_movi_tl(t1, 0);
19396 if (opc == NM_BBEQZC) {
19397 cond = TCG_COND_EQ;
19398 } else {
19399 cond = TCG_COND_NE;
19402 break;
19403 case NM_BNEIC:
19404 if (rt == 0 && imm == 0) {
19405 /* Treat as NOP */
19406 goto out;
19407 } else if (rt == 0 && imm != 0) {
19408 /* Unconditional branch */
19409 } else {
19410 cond = TCG_COND_NE;
19412 break;
19413 case NM_BGEIC:
19414 if (rt == 0 && imm == 0) {
19415 /* Unconditional branch */
19416 } else {
19417 cond = TCG_COND_GE;
19419 break;
19420 case NM_BLTIC:
19421 cond = TCG_COND_LT;
19422 break;
19423 case NM_BGEIUC:
19424 if (rt == 0 && imm == 0) {
19425 /* Unconditional branch */
19426 } else {
19427 cond = TCG_COND_GEU;
19429 break;
19430 case NM_BLTIUC:
19431 cond = TCG_COND_LTU;
19432 break;
19433 default:
19434 MIPS_INVAL("Immediate Value Compact branch");
19435 gen_reserved_instruction(ctx);
19436 goto out;
19439 /* branch completion */
19440 clear_branch_hflags(ctx);
19441 ctx->base.is_jmp = DISAS_NORETURN;
19443 if (cond == TCG_COND_ALWAYS) {
19444 /* Uncoditional compact branch */
19445 gen_goto_tb(ctx, 0, ctx->btarget);
19446 } else {
19447 /* Conditional compact branch */
19448 TCGLabel *fs = gen_new_label();
19450 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19452 gen_goto_tb(ctx, 1, ctx->btarget);
19453 gen_set_label(fs);
19455 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19458 out:
19459 tcg_temp_free(t0);
19460 tcg_temp_free(t1);
19463 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19464 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19465 int rt)
19467 TCGv t0 = tcg_temp_new();
19468 TCGv t1 = tcg_temp_new();
19470 /* load rs */
19471 gen_load_gpr(t0, rs);
19473 /* link */
19474 if (rt != 0) {
19475 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19478 /* calculate btarget */
19479 tcg_gen_shli_tl(t0, t0, 1);
19480 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19481 gen_op_addr_add(ctx, btarget, t1, t0);
19483 /* branch completion */
19484 clear_branch_hflags(ctx);
19485 ctx->base.is_jmp = DISAS_NORETURN;
19487 /* unconditional branch to register */
19488 tcg_gen_mov_tl(cpu_PC, btarget);
19489 tcg_gen_lookup_and_goto_ptr();
19491 tcg_temp_free(t0);
19492 tcg_temp_free(t1);
19495 /* nanoMIPS Branches */
19496 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19497 int rs, int rt, int32_t offset)
19499 int bcond_compute = 0;
19500 TCGv t0 = tcg_temp_new();
19501 TCGv t1 = tcg_temp_new();
19503 /* Load needed operands and calculate btarget */
19504 switch (opc) {
19505 /* compact branch */
19506 case OPC_BGEC:
19507 case OPC_BLTC:
19508 gen_load_gpr(t0, rs);
19509 gen_load_gpr(t1, rt);
19510 bcond_compute = 1;
19511 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19512 break;
19513 case OPC_BGEUC:
19514 case OPC_BLTUC:
19515 if (rs == 0 || rs == rt) {
19516 /* OPC_BLEZALC, OPC_BGEZALC */
19517 /* OPC_BGTZALC, OPC_BLTZALC */
19518 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19520 gen_load_gpr(t0, rs);
19521 gen_load_gpr(t1, rt);
19522 bcond_compute = 1;
19523 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19524 break;
19525 case OPC_BC:
19526 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19527 break;
19528 case OPC_BEQZC:
19529 if (rs != 0) {
19530 /* OPC_BEQZC, OPC_BNEZC */
19531 gen_load_gpr(t0, rs);
19532 bcond_compute = 1;
19533 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19534 } else {
19535 /* OPC_JIC, OPC_JIALC */
19536 TCGv tbase = tcg_temp_new();
19537 TCGv toffset = tcg_temp_new();
19539 gen_load_gpr(tbase, rt);
19540 tcg_gen_movi_tl(toffset, offset);
19541 gen_op_addr_add(ctx, btarget, tbase, toffset);
19542 tcg_temp_free(tbase);
19543 tcg_temp_free(toffset);
19545 break;
19546 default:
19547 MIPS_INVAL("Compact branch/jump");
19548 gen_reserved_instruction(ctx);
19549 goto out;
19552 if (bcond_compute == 0) {
19553 /* Uncoditional compact branch */
19554 switch (opc) {
19555 case OPC_BC:
19556 gen_goto_tb(ctx, 0, ctx->btarget);
19557 break;
19558 default:
19559 MIPS_INVAL("Compact branch/jump");
19560 gen_reserved_instruction(ctx);
19561 goto out;
19563 } else {
19564 /* Conditional compact branch */
19565 TCGLabel *fs = gen_new_label();
19567 switch (opc) {
19568 case OPC_BGEUC:
19569 if (rs == 0 && rt != 0) {
19570 /* OPC_BLEZALC */
19571 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19572 } else if (rs != 0 && rt != 0 && rs == rt) {
19573 /* OPC_BGEZALC */
19574 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19575 } else {
19576 /* OPC_BGEUC */
19577 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19579 break;
19580 case OPC_BLTUC:
19581 if (rs == 0 && rt != 0) {
19582 /* OPC_BGTZALC */
19583 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19584 } else if (rs != 0 && rt != 0 && rs == rt) {
19585 /* OPC_BLTZALC */
19586 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19587 } else {
19588 /* OPC_BLTUC */
19589 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19591 break;
19592 case OPC_BGEC:
19593 if (rs == 0 && rt != 0) {
19594 /* OPC_BLEZC */
19595 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19596 } else if (rs != 0 && rt != 0 && rs == rt) {
19597 /* OPC_BGEZC */
19598 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19599 } else {
19600 /* OPC_BGEC */
19601 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19603 break;
19604 case OPC_BLTC:
19605 if (rs == 0 && rt != 0) {
19606 /* OPC_BGTZC */
19607 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19608 } else if (rs != 0 && rt != 0 && rs == rt) {
19609 /* OPC_BLTZC */
19610 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19611 } else {
19612 /* OPC_BLTC */
19613 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19615 break;
19616 case OPC_BEQZC:
19617 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19618 break;
19619 default:
19620 MIPS_INVAL("Compact conditional branch/jump");
19621 gen_reserved_instruction(ctx);
19622 goto out;
19625 /* branch completion */
19626 clear_branch_hflags(ctx);
19627 ctx->base.is_jmp = DISAS_NORETURN;
19629 /* Generating branch here as compact branches don't have delay slot */
19630 gen_goto_tb(ctx, 1, ctx->btarget);
19631 gen_set_label(fs);
19633 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19636 out:
19637 tcg_temp_free(t0);
19638 tcg_temp_free(t1);
19642 /* nanoMIPS CP1 Branches */
19643 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19644 int32_t ft, int32_t offset)
19646 target_ulong btarget;
19647 TCGv_i64 t0 = tcg_temp_new_i64();
19649 gen_load_fpr64(ctx, t0, ft);
19650 tcg_gen_andi_i64(t0, t0, 1);
19652 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19654 switch (op) {
19655 case NM_BC1EQZC:
19656 tcg_gen_xori_i64(t0, t0, 1);
19657 ctx->hflags |= MIPS_HFLAG_BC;
19658 break;
19659 case NM_BC1NEZC:
19660 /* t0 already set */
19661 ctx->hflags |= MIPS_HFLAG_BC;
19662 break;
19663 default:
19664 MIPS_INVAL("cp1 cond branch");
19665 gen_reserved_instruction(ctx);
19666 goto out;
19669 tcg_gen_trunc_i64_tl(bcond, t0);
19671 ctx->btarget = btarget;
19673 out:
19674 tcg_temp_free_i64(t0);
19678 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19680 TCGv t0, t1;
19681 t0 = tcg_temp_new();
19682 t1 = tcg_temp_new();
19684 gen_load_gpr(t0, rs);
19685 gen_load_gpr(t1, rt);
19687 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19688 /* PP.LSXS instructions require shifting */
19689 switch (extract32(ctx->opcode, 7, 4)) {
19690 case NM_SHXS:
19691 check_nms(ctx);
19692 /* fall through */
19693 case NM_LHXS:
19694 case NM_LHUXS:
19695 tcg_gen_shli_tl(t0, t0, 1);
19696 break;
19697 case NM_SWXS:
19698 check_nms(ctx);
19699 /* fall through */
19700 case NM_LWXS:
19701 case NM_LWC1XS:
19702 case NM_SWC1XS:
19703 tcg_gen_shli_tl(t0, t0, 2);
19704 break;
19705 case NM_LDC1XS:
19706 case NM_SDC1XS:
19707 tcg_gen_shli_tl(t0, t0, 3);
19708 break;
19711 gen_op_addr_add(ctx, t0, t0, t1);
19713 switch (extract32(ctx->opcode, 7, 4)) {
19714 case NM_LBX:
19715 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19716 MO_SB);
19717 gen_store_gpr(t0, rd);
19718 break;
19719 case NM_LHX:
19720 /*case NM_LHXS:*/
19721 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19722 MO_TESW);
19723 gen_store_gpr(t0, rd);
19724 break;
19725 case NM_LWX:
19726 /*case NM_LWXS:*/
19727 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19728 MO_TESL);
19729 gen_store_gpr(t0, rd);
19730 break;
19731 case NM_LBUX:
19732 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19733 MO_UB);
19734 gen_store_gpr(t0, rd);
19735 break;
19736 case NM_LHUX:
19737 /*case NM_LHUXS:*/
19738 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19739 MO_TEUW);
19740 gen_store_gpr(t0, rd);
19741 break;
19742 case NM_SBX:
19743 check_nms(ctx);
19744 gen_load_gpr(t1, rd);
19745 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19746 MO_8);
19747 break;
19748 case NM_SHX:
19749 /*case NM_SHXS:*/
19750 check_nms(ctx);
19751 gen_load_gpr(t1, rd);
19752 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19753 MO_TEUW);
19754 break;
19755 case NM_SWX:
19756 /*case NM_SWXS:*/
19757 check_nms(ctx);
19758 gen_load_gpr(t1, rd);
19759 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19760 MO_TEUL);
19761 break;
19762 case NM_LWC1X:
19763 /*case NM_LWC1XS:*/
19764 case NM_LDC1X:
19765 /*case NM_LDC1XS:*/
19766 case NM_SWC1X:
19767 /*case NM_SWC1XS:*/
19768 case NM_SDC1X:
19769 /*case NM_SDC1XS:*/
19770 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19771 check_cp1_enabled(ctx);
19772 switch (extract32(ctx->opcode, 7, 4)) {
19773 case NM_LWC1X:
19774 /*case NM_LWC1XS:*/
19775 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19776 break;
19777 case NM_LDC1X:
19778 /*case NM_LDC1XS:*/
19779 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19780 break;
19781 case NM_SWC1X:
19782 /*case NM_SWC1XS:*/
19783 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19784 break;
19785 case NM_SDC1X:
19786 /*case NM_SDC1XS:*/
19787 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19788 break;
19790 } else {
19791 generate_exception_err(ctx, EXCP_CpU, 1);
19793 break;
19794 default:
19795 gen_reserved_instruction(ctx);
19796 break;
19799 tcg_temp_free(t0);
19800 tcg_temp_free(t1);
19803 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19805 int rt, rs, rd;
19807 rt = extract32(ctx->opcode, 21, 5);
19808 rs = extract32(ctx->opcode, 16, 5);
19809 rd = extract32(ctx->opcode, 11, 5);
19811 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19812 gen_reserved_instruction(ctx);
19813 return;
19815 check_cp1_enabled(ctx);
19816 switch (extract32(ctx->opcode, 0, 3)) {
19817 case NM_POOL32F_0:
19818 switch (extract32(ctx->opcode, 3, 7)) {
19819 case NM_RINT_S:
19820 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19821 break;
19822 case NM_RINT_D:
19823 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19824 break;
19825 case NM_CLASS_S:
19826 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19827 break;
19828 case NM_CLASS_D:
19829 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19830 break;
19831 case NM_ADD_S:
19832 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19833 break;
19834 case NM_ADD_D:
19835 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19836 break;
19837 case NM_SUB_S:
19838 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19839 break;
19840 case NM_SUB_D:
19841 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19842 break;
19843 case NM_MUL_S:
19844 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19845 break;
19846 case NM_MUL_D:
19847 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19848 break;
19849 case NM_DIV_S:
19850 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19851 break;
19852 case NM_DIV_D:
19853 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19854 break;
19855 case NM_SELEQZ_S:
19856 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19857 break;
19858 case NM_SELEQZ_D:
19859 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19860 break;
19861 case NM_SELNEZ_S:
19862 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19863 break;
19864 case NM_SELNEZ_D:
19865 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19866 break;
19867 case NM_SEL_S:
19868 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19869 break;
19870 case NM_SEL_D:
19871 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19872 break;
19873 case NM_MADDF_S:
19874 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19875 break;
19876 case NM_MADDF_D:
19877 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19878 break;
19879 case NM_MSUBF_S:
19880 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19881 break;
19882 case NM_MSUBF_D:
19883 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19884 break;
19885 default:
19886 gen_reserved_instruction(ctx);
19887 break;
19889 break;
19890 case NM_POOL32F_3:
19891 switch (extract32(ctx->opcode, 3, 3)) {
19892 case NM_MIN_FMT:
19893 switch (extract32(ctx->opcode, 9, 1)) {
19894 case FMT_SDPS_S:
19895 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19896 break;
19897 case FMT_SDPS_D:
19898 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19899 break;
19901 break;
19902 case NM_MAX_FMT:
19903 switch (extract32(ctx->opcode, 9, 1)) {
19904 case FMT_SDPS_S:
19905 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19906 break;
19907 case FMT_SDPS_D:
19908 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19909 break;
19911 break;
19912 case NM_MINA_FMT:
19913 switch (extract32(ctx->opcode, 9, 1)) {
19914 case FMT_SDPS_S:
19915 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19916 break;
19917 case FMT_SDPS_D:
19918 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19919 break;
19921 break;
19922 case NM_MAXA_FMT:
19923 switch (extract32(ctx->opcode, 9, 1)) {
19924 case FMT_SDPS_S:
19925 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19926 break;
19927 case FMT_SDPS_D:
19928 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19929 break;
19931 break;
19932 case NM_POOL32FXF:
19933 switch (extract32(ctx->opcode, 6, 8)) {
19934 case NM_CFC1:
19935 gen_cp1(ctx, OPC_CFC1, rt, rs);
19936 break;
19937 case NM_CTC1:
19938 gen_cp1(ctx, OPC_CTC1, rt, rs);
19939 break;
19940 case NM_MFC1:
19941 gen_cp1(ctx, OPC_MFC1, rt, rs);
19942 break;
19943 case NM_MTC1:
19944 gen_cp1(ctx, OPC_MTC1, rt, rs);
19945 break;
19946 case NM_MFHC1:
19947 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19948 break;
19949 case NM_MTHC1:
19950 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19951 break;
19952 case NM_CVT_S_PL:
19953 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19954 break;
19955 case NM_CVT_S_PU:
19956 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19957 break;
19958 default:
19959 switch (extract32(ctx->opcode, 6, 9)) {
19960 case NM_CVT_L_S:
19961 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19962 break;
19963 case NM_CVT_L_D:
19964 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19965 break;
19966 case NM_CVT_W_S:
19967 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19968 break;
19969 case NM_CVT_W_D:
19970 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19971 break;
19972 case NM_RSQRT_S:
19973 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19974 break;
19975 case NM_RSQRT_D:
19976 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19977 break;
19978 case NM_SQRT_S:
19979 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19980 break;
19981 case NM_SQRT_D:
19982 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19983 break;
19984 case NM_RECIP_S:
19985 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19986 break;
19987 case NM_RECIP_D:
19988 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19989 break;
19990 case NM_FLOOR_L_S:
19991 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19992 break;
19993 case NM_FLOOR_L_D:
19994 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19995 break;
19996 case NM_FLOOR_W_S:
19997 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19998 break;
19999 case NM_FLOOR_W_D:
20000 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20001 break;
20002 case NM_CEIL_L_S:
20003 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20004 break;
20005 case NM_CEIL_L_D:
20006 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20007 break;
20008 case NM_CEIL_W_S:
20009 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20010 break;
20011 case NM_CEIL_W_D:
20012 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20013 break;
20014 case NM_TRUNC_L_S:
20015 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20016 break;
20017 case NM_TRUNC_L_D:
20018 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20019 break;
20020 case NM_TRUNC_W_S:
20021 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20022 break;
20023 case NM_TRUNC_W_D:
20024 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20025 break;
20026 case NM_ROUND_L_S:
20027 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20028 break;
20029 case NM_ROUND_L_D:
20030 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20031 break;
20032 case NM_ROUND_W_S:
20033 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20034 break;
20035 case NM_ROUND_W_D:
20036 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20037 break;
20038 case NM_MOV_S:
20039 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20040 break;
20041 case NM_MOV_D:
20042 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20043 break;
20044 case NM_ABS_S:
20045 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20046 break;
20047 case NM_ABS_D:
20048 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20049 break;
20050 case NM_NEG_S:
20051 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20052 break;
20053 case NM_NEG_D:
20054 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20055 break;
20056 case NM_CVT_D_S:
20057 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20058 break;
20059 case NM_CVT_D_W:
20060 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20061 break;
20062 case NM_CVT_D_L:
20063 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20064 break;
20065 case NM_CVT_S_D:
20066 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20067 break;
20068 case NM_CVT_S_W:
20069 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20070 break;
20071 case NM_CVT_S_L:
20072 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20073 break;
20074 default:
20075 gen_reserved_instruction(ctx);
20076 break;
20078 break;
20080 break;
20082 break;
20083 case NM_POOL32F_5:
20084 switch (extract32(ctx->opcode, 3, 3)) {
20085 case NM_CMP_CONDN_S:
20086 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20087 break;
20088 case NM_CMP_CONDN_D:
20089 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20090 break;
20091 default:
20092 gen_reserved_instruction(ctx);
20093 break;
20095 break;
20096 default:
20097 gen_reserved_instruction(ctx);
20098 break;
20102 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20103 int rd, int rs, int rt)
20105 int ret = rd;
20106 TCGv t0 = tcg_temp_new();
20107 TCGv v1_t = tcg_temp_new();
20108 TCGv v2_t = tcg_temp_new();
20110 gen_load_gpr(v1_t, rs);
20111 gen_load_gpr(v2_t, rt);
20113 switch (opc) {
20114 case NM_CMP_EQ_PH:
20115 check_dsp(ctx);
20116 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20117 break;
20118 case NM_CMP_LT_PH:
20119 check_dsp(ctx);
20120 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20121 break;
20122 case NM_CMP_LE_PH:
20123 check_dsp(ctx);
20124 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20125 break;
20126 case NM_CMPU_EQ_QB:
20127 check_dsp(ctx);
20128 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20129 break;
20130 case NM_CMPU_LT_QB:
20131 check_dsp(ctx);
20132 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20133 break;
20134 case NM_CMPU_LE_QB:
20135 check_dsp(ctx);
20136 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20137 break;
20138 case NM_CMPGU_EQ_QB:
20139 check_dsp(ctx);
20140 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20141 gen_store_gpr(v1_t, ret);
20142 break;
20143 case NM_CMPGU_LT_QB:
20144 check_dsp(ctx);
20145 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20146 gen_store_gpr(v1_t, ret);
20147 break;
20148 case NM_CMPGU_LE_QB:
20149 check_dsp(ctx);
20150 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20151 gen_store_gpr(v1_t, ret);
20152 break;
20153 case NM_CMPGDU_EQ_QB:
20154 check_dsp_r2(ctx);
20155 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20156 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20157 gen_store_gpr(v1_t, ret);
20158 break;
20159 case NM_CMPGDU_LT_QB:
20160 check_dsp_r2(ctx);
20161 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20162 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20163 gen_store_gpr(v1_t, ret);
20164 break;
20165 case NM_CMPGDU_LE_QB:
20166 check_dsp_r2(ctx);
20167 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20168 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20169 gen_store_gpr(v1_t, ret);
20170 break;
20171 case NM_PACKRL_PH:
20172 check_dsp(ctx);
20173 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20174 gen_store_gpr(v1_t, ret);
20175 break;
20176 case NM_PICK_QB:
20177 check_dsp(ctx);
20178 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20179 gen_store_gpr(v1_t, ret);
20180 break;
20181 case NM_PICK_PH:
20182 check_dsp(ctx);
20183 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20184 gen_store_gpr(v1_t, ret);
20185 break;
20186 case NM_ADDQ_S_W:
20187 check_dsp(ctx);
20188 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20189 gen_store_gpr(v1_t, ret);
20190 break;
20191 case NM_SUBQ_S_W:
20192 check_dsp(ctx);
20193 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20194 gen_store_gpr(v1_t, ret);
20195 break;
20196 case NM_ADDSC:
20197 check_dsp(ctx);
20198 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20199 gen_store_gpr(v1_t, ret);
20200 break;
20201 case NM_ADDWC:
20202 check_dsp(ctx);
20203 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20204 gen_store_gpr(v1_t, ret);
20205 break;
20206 case NM_ADDQ_S_PH:
20207 check_dsp(ctx);
20208 switch (extract32(ctx->opcode, 10, 1)) {
20209 case 0:
20210 /* ADDQ_PH */
20211 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20212 gen_store_gpr(v1_t, ret);
20213 break;
20214 case 1:
20215 /* ADDQ_S_PH */
20216 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20217 gen_store_gpr(v1_t, ret);
20218 break;
20220 break;
20221 case NM_ADDQH_R_PH:
20222 check_dsp_r2(ctx);
20223 switch (extract32(ctx->opcode, 10, 1)) {
20224 case 0:
20225 /* ADDQH_PH */
20226 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20227 gen_store_gpr(v1_t, ret);
20228 break;
20229 case 1:
20230 /* ADDQH_R_PH */
20231 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20232 gen_store_gpr(v1_t, ret);
20233 break;
20235 break;
20236 case NM_ADDQH_R_W:
20237 check_dsp_r2(ctx);
20238 switch (extract32(ctx->opcode, 10, 1)) {
20239 case 0:
20240 /* ADDQH_W */
20241 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20242 gen_store_gpr(v1_t, ret);
20243 break;
20244 case 1:
20245 /* ADDQH_R_W */
20246 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20247 gen_store_gpr(v1_t, ret);
20248 break;
20250 break;
20251 case NM_ADDU_S_QB:
20252 check_dsp(ctx);
20253 switch (extract32(ctx->opcode, 10, 1)) {
20254 case 0:
20255 /* ADDU_QB */
20256 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20257 gen_store_gpr(v1_t, ret);
20258 break;
20259 case 1:
20260 /* ADDU_S_QB */
20261 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20262 gen_store_gpr(v1_t, ret);
20263 break;
20265 break;
20266 case NM_ADDU_S_PH:
20267 check_dsp_r2(ctx);
20268 switch (extract32(ctx->opcode, 10, 1)) {
20269 case 0:
20270 /* ADDU_PH */
20271 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20272 gen_store_gpr(v1_t, ret);
20273 break;
20274 case 1:
20275 /* ADDU_S_PH */
20276 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20277 gen_store_gpr(v1_t, ret);
20278 break;
20280 break;
20281 case NM_ADDUH_R_QB:
20282 check_dsp_r2(ctx);
20283 switch (extract32(ctx->opcode, 10, 1)) {
20284 case 0:
20285 /* ADDUH_QB */
20286 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20287 gen_store_gpr(v1_t, ret);
20288 break;
20289 case 1:
20290 /* ADDUH_R_QB */
20291 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20292 gen_store_gpr(v1_t, ret);
20293 break;
20295 break;
20296 case NM_SHRAV_R_PH:
20297 check_dsp(ctx);
20298 switch (extract32(ctx->opcode, 10, 1)) {
20299 case 0:
20300 /* SHRAV_PH */
20301 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20302 gen_store_gpr(v1_t, ret);
20303 break;
20304 case 1:
20305 /* SHRAV_R_PH */
20306 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20307 gen_store_gpr(v1_t, ret);
20308 break;
20310 break;
20311 case NM_SHRAV_R_QB:
20312 check_dsp_r2(ctx);
20313 switch (extract32(ctx->opcode, 10, 1)) {
20314 case 0:
20315 /* SHRAV_QB */
20316 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20317 gen_store_gpr(v1_t, ret);
20318 break;
20319 case 1:
20320 /* SHRAV_R_QB */
20321 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20322 gen_store_gpr(v1_t, ret);
20323 break;
20325 break;
20326 case NM_SUBQ_S_PH:
20327 check_dsp(ctx);
20328 switch (extract32(ctx->opcode, 10, 1)) {
20329 case 0:
20330 /* SUBQ_PH */
20331 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20332 gen_store_gpr(v1_t, ret);
20333 break;
20334 case 1:
20335 /* SUBQ_S_PH */
20336 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20337 gen_store_gpr(v1_t, ret);
20338 break;
20340 break;
20341 case NM_SUBQH_R_PH:
20342 check_dsp_r2(ctx);
20343 switch (extract32(ctx->opcode, 10, 1)) {
20344 case 0:
20345 /* SUBQH_PH */
20346 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20347 gen_store_gpr(v1_t, ret);
20348 break;
20349 case 1:
20350 /* SUBQH_R_PH */
20351 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20352 gen_store_gpr(v1_t, ret);
20353 break;
20355 break;
20356 case NM_SUBQH_R_W:
20357 check_dsp_r2(ctx);
20358 switch (extract32(ctx->opcode, 10, 1)) {
20359 case 0:
20360 /* SUBQH_W */
20361 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20362 gen_store_gpr(v1_t, ret);
20363 break;
20364 case 1:
20365 /* SUBQH_R_W */
20366 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20367 gen_store_gpr(v1_t, ret);
20368 break;
20370 break;
20371 case NM_SUBU_S_QB:
20372 check_dsp(ctx);
20373 switch (extract32(ctx->opcode, 10, 1)) {
20374 case 0:
20375 /* SUBU_QB */
20376 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20377 gen_store_gpr(v1_t, ret);
20378 break;
20379 case 1:
20380 /* SUBU_S_QB */
20381 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20382 gen_store_gpr(v1_t, ret);
20383 break;
20385 break;
20386 case NM_SUBU_S_PH:
20387 check_dsp_r2(ctx);
20388 switch (extract32(ctx->opcode, 10, 1)) {
20389 case 0:
20390 /* SUBU_PH */
20391 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20392 gen_store_gpr(v1_t, ret);
20393 break;
20394 case 1:
20395 /* SUBU_S_PH */
20396 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20397 gen_store_gpr(v1_t, ret);
20398 break;
20400 break;
20401 case NM_SUBUH_R_QB:
20402 check_dsp_r2(ctx);
20403 switch (extract32(ctx->opcode, 10, 1)) {
20404 case 0:
20405 /* SUBUH_QB */
20406 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20407 gen_store_gpr(v1_t, ret);
20408 break;
20409 case 1:
20410 /* SUBUH_R_QB */
20411 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20412 gen_store_gpr(v1_t, ret);
20413 break;
20415 break;
20416 case NM_SHLLV_S_PH:
20417 check_dsp(ctx);
20418 switch (extract32(ctx->opcode, 10, 1)) {
20419 case 0:
20420 /* SHLLV_PH */
20421 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20422 gen_store_gpr(v1_t, ret);
20423 break;
20424 case 1:
20425 /* SHLLV_S_PH */
20426 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20427 gen_store_gpr(v1_t, ret);
20428 break;
20430 break;
20431 case NM_PRECR_SRA_R_PH_W:
20432 check_dsp_r2(ctx);
20433 switch (extract32(ctx->opcode, 10, 1)) {
20434 case 0:
20435 /* PRECR_SRA_PH_W */
20437 TCGv_i32 sa_t = tcg_const_i32(rd);
20438 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20439 cpu_gpr[rt]);
20440 gen_store_gpr(v1_t, rt);
20441 tcg_temp_free_i32(sa_t);
20443 break;
20444 case 1:
20445 /* PRECR_SRA_R_PH_W */
20447 TCGv_i32 sa_t = tcg_const_i32(rd);
20448 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20449 cpu_gpr[rt]);
20450 gen_store_gpr(v1_t, rt);
20451 tcg_temp_free_i32(sa_t);
20453 break;
20455 break;
20456 case NM_MULEU_S_PH_QBL:
20457 check_dsp(ctx);
20458 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20459 gen_store_gpr(v1_t, ret);
20460 break;
20461 case NM_MULEU_S_PH_QBR:
20462 check_dsp(ctx);
20463 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20464 gen_store_gpr(v1_t, ret);
20465 break;
20466 case NM_MULQ_RS_PH:
20467 check_dsp(ctx);
20468 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20469 gen_store_gpr(v1_t, ret);
20470 break;
20471 case NM_MULQ_S_PH:
20472 check_dsp_r2(ctx);
20473 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20474 gen_store_gpr(v1_t, ret);
20475 break;
20476 case NM_MULQ_RS_W:
20477 check_dsp_r2(ctx);
20478 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20479 gen_store_gpr(v1_t, ret);
20480 break;
20481 case NM_MULQ_S_W:
20482 check_dsp_r2(ctx);
20483 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20484 gen_store_gpr(v1_t, ret);
20485 break;
20486 case NM_APPEND:
20487 check_dsp_r2(ctx);
20488 gen_load_gpr(t0, rs);
20489 if (rd != 0) {
20490 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20492 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20493 break;
20494 case NM_MODSUB:
20495 check_dsp(ctx);
20496 gen_helper_modsub(v1_t, v1_t, v2_t);
20497 gen_store_gpr(v1_t, ret);
20498 break;
20499 case NM_SHRAV_R_W:
20500 check_dsp(ctx);
20501 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20502 gen_store_gpr(v1_t, ret);
20503 break;
20504 case NM_SHRLV_PH:
20505 check_dsp_r2(ctx);
20506 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20507 gen_store_gpr(v1_t, ret);
20508 break;
20509 case NM_SHRLV_QB:
20510 check_dsp(ctx);
20511 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20512 gen_store_gpr(v1_t, ret);
20513 break;
20514 case NM_SHLLV_QB:
20515 check_dsp(ctx);
20516 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20517 gen_store_gpr(v1_t, ret);
20518 break;
20519 case NM_SHLLV_S_W:
20520 check_dsp(ctx);
20521 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20522 gen_store_gpr(v1_t, ret);
20523 break;
20524 case NM_SHILO:
20525 check_dsp(ctx);
20527 TCGv tv0 = tcg_temp_new();
20528 TCGv tv1 = tcg_temp_new();
20529 int16_t imm = extract32(ctx->opcode, 16, 7);
20531 tcg_gen_movi_tl(tv0, rd >> 3);
20532 tcg_gen_movi_tl(tv1, imm);
20533 gen_helper_shilo(tv0, tv1, cpu_env);
20535 break;
20536 case NM_MULEQ_S_W_PHL:
20537 check_dsp(ctx);
20538 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20539 gen_store_gpr(v1_t, ret);
20540 break;
20541 case NM_MULEQ_S_W_PHR:
20542 check_dsp(ctx);
20543 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20544 gen_store_gpr(v1_t, ret);
20545 break;
20546 case NM_MUL_S_PH:
20547 check_dsp_r2(ctx);
20548 switch (extract32(ctx->opcode, 10, 1)) {
20549 case 0:
20550 /* MUL_PH */
20551 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20552 gen_store_gpr(v1_t, ret);
20553 break;
20554 case 1:
20555 /* MUL_S_PH */
20556 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20557 gen_store_gpr(v1_t, ret);
20558 break;
20560 break;
20561 case NM_PRECR_QB_PH:
20562 check_dsp_r2(ctx);
20563 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20564 gen_store_gpr(v1_t, ret);
20565 break;
20566 case NM_PRECRQ_QB_PH:
20567 check_dsp(ctx);
20568 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20569 gen_store_gpr(v1_t, ret);
20570 break;
20571 case NM_PRECRQ_PH_W:
20572 check_dsp(ctx);
20573 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20574 gen_store_gpr(v1_t, ret);
20575 break;
20576 case NM_PRECRQ_RS_PH_W:
20577 check_dsp(ctx);
20578 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20579 gen_store_gpr(v1_t, ret);
20580 break;
20581 case NM_PRECRQU_S_QB_PH:
20582 check_dsp(ctx);
20583 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20584 gen_store_gpr(v1_t, ret);
20585 break;
20586 case NM_SHRA_R_W:
20587 check_dsp(ctx);
20588 tcg_gen_movi_tl(t0, rd);
20589 gen_helper_shra_r_w(v1_t, t0, v1_t);
20590 gen_store_gpr(v1_t, rt);
20591 break;
20592 case NM_SHRA_R_PH:
20593 check_dsp(ctx);
20594 tcg_gen_movi_tl(t0, rd >> 1);
20595 switch (extract32(ctx->opcode, 10, 1)) {
20596 case 0:
20597 /* SHRA_PH */
20598 gen_helper_shra_ph(v1_t, t0, v1_t);
20599 gen_store_gpr(v1_t, rt);
20600 break;
20601 case 1:
20602 /* SHRA_R_PH */
20603 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20604 gen_store_gpr(v1_t, rt);
20605 break;
20607 break;
20608 case NM_SHLL_S_PH:
20609 check_dsp(ctx);
20610 tcg_gen_movi_tl(t0, rd >> 1);
20611 switch (extract32(ctx->opcode, 10, 2)) {
20612 case 0:
20613 /* SHLL_PH */
20614 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20615 gen_store_gpr(v1_t, rt);
20616 break;
20617 case 2:
20618 /* SHLL_S_PH */
20619 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20620 gen_store_gpr(v1_t, rt);
20621 break;
20622 default:
20623 gen_reserved_instruction(ctx);
20624 break;
20626 break;
20627 case NM_SHLL_S_W:
20628 check_dsp(ctx);
20629 tcg_gen_movi_tl(t0, rd);
20630 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20631 gen_store_gpr(v1_t, rt);
20632 break;
20633 case NM_REPL_PH:
20634 check_dsp(ctx);
20636 int16_t imm;
20637 imm = sextract32(ctx->opcode, 11, 11);
20638 imm = (int16_t)(imm << 6) >> 6;
20639 if (rt != 0) {
20640 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20643 break;
20644 default:
20645 gen_reserved_instruction(ctx);
20646 break;
20650 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20652 uint16_t insn;
20653 uint32_t op;
20654 int rt, rs, rd;
20655 int offset;
20656 int imm;
20658 insn = translator_lduw(env, ctx->base.pc_next + 2);
20659 ctx->opcode = (ctx->opcode << 16) | insn;
20661 rt = extract32(ctx->opcode, 21, 5);
20662 rs = extract32(ctx->opcode, 16, 5);
20663 rd = extract32(ctx->opcode, 11, 5);
20665 op = extract32(ctx->opcode, 26, 6);
20666 switch (op) {
20667 case NM_P_ADDIU:
20668 if (rt == 0) {
20669 /* P.RI */
20670 switch (extract32(ctx->opcode, 19, 2)) {
20671 case NM_SIGRIE:
20672 default:
20673 gen_reserved_instruction(ctx);
20674 break;
20675 case NM_P_SYSCALL:
20676 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20677 generate_exception_end(ctx, EXCP_SYSCALL);
20678 } else {
20679 gen_reserved_instruction(ctx);
20681 break;
20682 case NM_BREAK:
20683 generate_exception_end(ctx, EXCP_BREAK);
20684 break;
20685 case NM_SDBBP:
20686 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20687 gen_helper_do_semihosting(cpu_env);
20688 } else {
20689 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20690 gen_reserved_instruction(ctx);
20691 } else {
20692 generate_exception_end(ctx, EXCP_DBp);
20695 break;
20697 } else {
20698 /* NM_ADDIU */
20699 imm = extract32(ctx->opcode, 0, 16);
20700 if (rs != 0) {
20701 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20702 } else {
20703 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20705 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20707 break;
20708 case NM_ADDIUPC:
20709 if (rt != 0) {
20710 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20711 extract32(ctx->opcode, 1, 20) << 1;
20712 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20713 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20715 break;
20716 case NM_POOL32A:
20717 switch (ctx->opcode & 0x07) {
20718 case NM_POOL32A0:
20719 gen_pool32a0_nanomips_insn(env, ctx);
20720 break;
20721 case NM_POOL32A5:
20723 int32_t op1 = extract32(ctx->opcode, 3, 7);
20724 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20726 break;
20727 case NM_POOL32A7:
20728 switch (extract32(ctx->opcode, 3, 3)) {
20729 case NM_P_LSX:
20730 gen_p_lsx(ctx, rd, rs, rt);
20731 break;
20732 case NM_LSA:
20734 * In nanoMIPS, the shift field directly encodes the shift
20735 * amount, meaning that the supported shift values are in
20736 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
20738 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2) - 1);
20739 break;
20740 case NM_EXTW:
20741 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20742 break;
20743 case NM_POOL32AXF:
20744 gen_pool32axf_nanomips_insn(env, ctx);
20745 break;
20746 default:
20747 gen_reserved_instruction(ctx);
20748 break;
20750 break;
20751 default:
20752 gen_reserved_instruction(ctx);
20753 break;
20755 break;
20756 case NM_P_GP_W:
20757 switch (ctx->opcode & 0x03) {
20758 case NM_ADDIUGP_W:
20759 if (rt != 0) {
20760 offset = extract32(ctx->opcode, 0, 21);
20761 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20763 break;
20764 case NM_LWGP:
20765 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20766 break;
20767 case NM_SWGP:
20768 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20769 break;
20770 default:
20771 gen_reserved_instruction(ctx);
20772 break;
20774 break;
20775 case NM_P48I:
20777 insn = translator_lduw(env, ctx->base.pc_next + 4);
20778 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20779 switch (extract32(ctx->opcode, 16, 5)) {
20780 case NM_LI48:
20781 check_nms(ctx);
20782 if (rt != 0) {
20783 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20785 break;
20786 case NM_ADDIU48:
20787 check_nms(ctx);
20788 if (rt != 0) {
20789 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20790 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20792 break;
20793 case NM_ADDIUGP48:
20794 check_nms(ctx);
20795 if (rt != 0) {
20796 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20798 break;
20799 case NM_ADDIUPC48:
20800 check_nms(ctx);
20801 if (rt != 0) {
20802 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20803 addr_off);
20805 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20807 break;
20808 case NM_LWPC48:
20809 check_nms(ctx);
20810 if (rt != 0) {
20811 TCGv t0;
20812 t0 = tcg_temp_new();
20814 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20815 addr_off);
20817 tcg_gen_movi_tl(t0, addr);
20818 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20819 tcg_temp_free(t0);
20821 break;
20822 case NM_SWPC48:
20823 check_nms(ctx);
20825 TCGv t0, t1;
20826 t0 = tcg_temp_new();
20827 t1 = tcg_temp_new();
20829 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20830 addr_off);
20832 tcg_gen_movi_tl(t0, addr);
20833 gen_load_gpr(t1, rt);
20835 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20837 tcg_temp_free(t0);
20838 tcg_temp_free(t1);
20840 break;
20841 default:
20842 gen_reserved_instruction(ctx);
20843 break;
20845 return 6;
20847 case NM_P_U12:
20848 switch (extract32(ctx->opcode, 12, 4)) {
20849 case NM_ORI:
20850 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20851 break;
20852 case NM_XORI:
20853 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20854 break;
20855 case NM_ANDI:
20856 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20857 break;
20858 case NM_P_SR:
20859 switch (extract32(ctx->opcode, 20, 1)) {
20860 case NM_PP_SR:
20861 switch (ctx->opcode & 3) {
20862 case NM_SAVE:
20863 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20864 extract32(ctx->opcode, 2, 1),
20865 extract32(ctx->opcode, 3, 9) << 3);
20866 break;
20867 case NM_RESTORE:
20868 case NM_RESTORE_JRC:
20869 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20870 extract32(ctx->opcode, 2, 1),
20871 extract32(ctx->opcode, 3, 9) << 3);
20872 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20873 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20875 break;
20876 default:
20877 gen_reserved_instruction(ctx);
20878 break;
20880 break;
20881 case NM_P_SR_F:
20882 gen_reserved_instruction(ctx);
20883 break;
20885 break;
20886 case NM_SLTI:
20887 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20888 break;
20889 case NM_SLTIU:
20890 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20891 break;
20892 case NM_SEQI:
20894 TCGv t0 = tcg_temp_new();
20896 imm = extract32(ctx->opcode, 0, 12);
20897 gen_load_gpr(t0, rs);
20898 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20899 gen_store_gpr(t0, rt);
20901 tcg_temp_free(t0);
20903 break;
20904 case NM_ADDIUNEG:
20905 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20906 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20907 break;
20908 case NM_P_SHIFT:
20910 int shift = extract32(ctx->opcode, 0, 5);
20911 switch (extract32(ctx->opcode, 5, 4)) {
20912 case NM_P_SLL:
20913 if (rt == 0 && shift == 0) {
20914 /* NOP */
20915 } else if (rt == 0 && shift == 3) {
20916 /* EHB - treat as NOP */
20917 } else if (rt == 0 && shift == 5) {
20918 /* PAUSE - treat as NOP */
20919 } else if (rt == 0 && shift == 6) {
20920 /* SYNC */
20921 gen_sync(extract32(ctx->opcode, 16, 5));
20922 } else {
20923 /* SLL */
20924 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20925 extract32(ctx->opcode, 0, 5));
20927 break;
20928 case NM_SRL:
20929 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20930 extract32(ctx->opcode, 0, 5));
20931 break;
20932 case NM_SRA:
20933 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20934 extract32(ctx->opcode, 0, 5));
20935 break;
20936 case NM_ROTR:
20937 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20938 extract32(ctx->opcode, 0, 5));
20939 break;
20942 break;
20943 case NM_P_ROTX:
20944 check_nms(ctx);
20945 if (rt != 0) {
20946 TCGv t0 = tcg_temp_new();
20947 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20948 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20949 << 1);
20950 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20952 gen_load_gpr(t0, rs);
20953 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20954 tcg_temp_free(t0);
20956 tcg_temp_free_i32(shift);
20957 tcg_temp_free_i32(shiftx);
20958 tcg_temp_free_i32(stripe);
20960 break;
20961 case NM_P_INS:
20962 switch (((ctx->opcode >> 10) & 2) |
20963 (extract32(ctx->opcode, 5, 1))) {
20964 case NM_INS:
20965 check_nms(ctx);
20966 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20967 extract32(ctx->opcode, 6, 5));
20968 break;
20969 default:
20970 gen_reserved_instruction(ctx);
20971 break;
20973 break;
20974 case NM_P_EXT:
20975 switch (((ctx->opcode >> 10) & 2) |
20976 (extract32(ctx->opcode, 5, 1))) {
20977 case NM_EXT:
20978 check_nms(ctx);
20979 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20980 extract32(ctx->opcode, 6, 5));
20981 break;
20982 default:
20983 gen_reserved_instruction(ctx);
20984 break;
20986 break;
20987 default:
20988 gen_reserved_instruction(ctx);
20989 break;
20991 break;
20992 case NM_POOL32F:
20993 gen_pool32f_nanomips_insn(ctx);
20994 break;
20995 case NM_POOL32S:
20996 break;
20997 case NM_P_LUI:
20998 switch (extract32(ctx->opcode, 1, 1)) {
20999 case NM_LUI:
21000 if (rt != 0) {
21001 tcg_gen_movi_tl(cpu_gpr[rt],
21002 sextract32(ctx->opcode, 0, 1) << 31 |
21003 extract32(ctx->opcode, 2, 10) << 21 |
21004 extract32(ctx->opcode, 12, 9) << 12);
21006 break;
21007 case NM_ALUIPC:
21008 if (rt != 0) {
21009 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21010 extract32(ctx->opcode, 2, 10) << 21 |
21011 extract32(ctx->opcode, 12, 9) << 12;
21012 target_long addr;
21013 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21014 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21016 break;
21018 break;
21019 case NM_P_GP_BH:
21021 uint32_t u = extract32(ctx->opcode, 0, 18);
21023 switch (extract32(ctx->opcode, 18, 3)) {
21024 case NM_LBGP:
21025 gen_ld(ctx, OPC_LB, rt, 28, u);
21026 break;
21027 case NM_SBGP:
21028 gen_st(ctx, OPC_SB, rt, 28, u);
21029 break;
21030 case NM_LBUGP:
21031 gen_ld(ctx, OPC_LBU, rt, 28, u);
21032 break;
21033 case NM_ADDIUGP_B:
21034 if (rt != 0) {
21035 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21037 break;
21038 case NM_P_GP_LH:
21039 u &= ~1;
21040 switch (ctx->opcode & 1) {
21041 case NM_LHGP:
21042 gen_ld(ctx, OPC_LH, rt, 28, u);
21043 break;
21044 case NM_LHUGP:
21045 gen_ld(ctx, OPC_LHU, rt, 28, u);
21046 break;
21048 break;
21049 case NM_P_GP_SH:
21050 u &= ~1;
21051 switch (ctx->opcode & 1) {
21052 case NM_SHGP:
21053 gen_st(ctx, OPC_SH, rt, 28, u);
21054 break;
21055 default:
21056 gen_reserved_instruction(ctx);
21057 break;
21059 break;
21060 case NM_P_GP_CP1:
21061 u &= ~0x3;
21062 switch (ctx->opcode & 0x3) {
21063 case NM_LWC1GP:
21064 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21065 break;
21066 case NM_LDC1GP:
21067 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21068 break;
21069 case NM_SWC1GP:
21070 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21071 break;
21072 case NM_SDC1GP:
21073 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21074 break;
21076 break;
21077 default:
21078 gen_reserved_instruction(ctx);
21079 break;
21082 break;
21083 case NM_P_LS_U12:
21085 uint32_t u = extract32(ctx->opcode, 0, 12);
21087 switch (extract32(ctx->opcode, 12, 4)) {
21088 case NM_P_PREFU12:
21089 if (rt == 31) {
21090 /* SYNCI */
21092 * Break the TB to be able to sync copied instructions
21093 * immediately.
21095 ctx->base.is_jmp = DISAS_STOP;
21096 } else {
21097 /* PREF */
21098 /* Treat as NOP. */
21100 break;
21101 case NM_LB:
21102 gen_ld(ctx, OPC_LB, rt, rs, u);
21103 break;
21104 case NM_LH:
21105 gen_ld(ctx, OPC_LH, rt, rs, u);
21106 break;
21107 case NM_LW:
21108 gen_ld(ctx, OPC_LW, rt, rs, u);
21109 break;
21110 case NM_LBU:
21111 gen_ld(ctx, OPC_LBU, rt, rs, u);
21112 break;
21113 case NM_LHU:
21114 gen_ld(ctx, OPC_LHU, rt, rs, u);
21115 break;
21116 case NM_SB:
21117 gen_st(ctx, OPC_SB, rt, rs, u);
21118 break;
21119 case NM_SH:
21120 gen_st(ctx, OPC_SH, rt, rs, u);
21121 break;
21122 case NM_SW:
21123 gen_st(ctx, OPC_SW, rt, rs, u);
21124 break;
21125 case NM_LWC1:
21126 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21127 break;
21128 case NM_LDC1:
21129 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21130 break;
21131 case NM_SWC1:
21132 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21133 break;
21134 case NM_SDC1:
21135 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21136 break;
21137 default:
21138 gen_reserved_instruction(ctx);
21139 break;
21142 break;
21143 case NM_P_LS_S9:
21145 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21146 extract32(ctx->opcode, 0, 8);
21148 switch (extract32(ctx->opcode, 8, 3)) {
21149 case NM_P_LS_S0:
21150 switch (extract32(ctx->opcode, 11, 4)) {
21151 case NM_LBS9:
21152 gen_ld(ctx, OPC_LB, rt, rs, s);
21153 break;
21154 case NM_LHS9:
21155 gen_ld(ctx, OPC_LH, rt, rs, s);
21156 break;
21157 case NM_LWS9:
21158 gen_ld(ctx, OPC_LW, rt, rs, s);
21159 break;
21160 case NM_LBUS9:
21161 gen_ld(ctx, OPC_LBU, rt, rs, s);
21162 break;
21163 case NM_LHUS9:
21164 gen_ld(ctx, OPC_LHU, rt, rs, s);
21165 break;
21166 case NM_SBS9:
21167 gen_st(ctx, OPC_SB, rt, rs, s);
21168 break;
21169 case NM_SHS9:
21170 gen_st(ctx, OPC_SH, rt, rs, s);
21171 break;
21172 case NM_SWS9:
21173 gen_st(ctx, OPC_SW, rt, rs, s);
21174 break;
21175 case NM_LWC1S9:
21176 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21177 break;
21178 case NM_LDC1S9:
21179 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21180 break;
21181 case NM_SWC1S9:
21182 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21183 break;
21184 case NM_SDC1S9:
21185 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21186 break;
21187 case NM_P_PREFS9:
21188 if (rt == 31) {
21189 /* SYNCI */
21191 * Break the TB to be able to sync copied instructions
21192 * immediately.
21194 ctx->base.is_jmp = DISAS_STOP;
21195 } else {
21196 /* PREF */
21197 /* Treat as NOP. */
21199 break;
21200 default:
21201 gen_reserved_instruction(ctx);
21202 break;
21204 break;
21205 case NM_P_LS_S1:
21206 switch (extract32(ctx->opcode, 11, 4)) {
21207 case NM_UALH:
21208 case NM_UASH:
21209 check_nms(ctx);
21211 TCGv t0 = tcg_temp_new();
21212 TCGv t1 = tcg_temp_new();
21214 gen_base_offset_addr(ctx, t0, rs, s);
21216 switch (extract32(ctx->opcode, 11, 4)) {
21217 case NM_UALH:
21218 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21219 MO_UNALN);
21220 gen_store_gpr(t0, rt);
21221 break;
21222 case NM_UASH:
21223 gen_load_gpr(t1, rt);
21224 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21225 MO_UNALN);
21226 break;
21228 tcg_temp_free(t0);
21229 tcg_temp_free(t1);
21231 break;
21232 case NM_P_LL:
21233 switch (ctx->opcode & 0x03) {
21234 case NM_LL:
21235 gen_ld(ctx, OPC_LL, rt, rs, s);
21236 break;
21237 case NM_LLWP:
21238 check_xnp(ctx);
21239 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21240 break;
21242 break;
21243 case NM_P_SC:
21244 switch (ctx->opcode & 0x03) {
21245 case NM_SC:
21246 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21247 break;
21248 case NM_SCWP:
21249 check_xnp(ctx);
21250 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21251 false);
21252 break;
21254 break;
21255 case NM_CACHE:
21256 check_cp0_enabled(ctx);
21257 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21258 gen_cache_operation(ctx, rt, rs, s);
21260 break;
21262 break;
21263 case NM_P_LS_E0:
21264 switch (extract32(ctx->opcode, 11, 4)) {
21265 case NM_LBE:
21266 check_eva(ctx);
21267 check_cp0_enabled(ctx);
21268 gen_ld(ctx, OPC_LBE, rt, rs, s);
21269 break;
21270 case NM_SBE:
21271 check_eva(ctx);
21272 check_cp0_enabled(ctx);
21273 gen_st(ctx, OPC_SBE, rt, rs, s);
21274 break;
21275 case NM_LBUE:
21276 check_eva(ctx);
21277 check_cp0_enabled(ctx);
21278 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21279 break;
21280 case NM_P_PREFE:
21281 if (rt == 31) {
21282 /* case NM_SYNCIE */
21283 check_eva(ctx);
21284 check_cp0_enabled(ctx);
21286 * Break the TB to be able to sync copied instructions
21287 * immediately.
21289 ctx->base.is_jmp = DISAS_STOP;
21290 } else {
21291 /* case NM_PREFE */
21292 check_eva(ctx);
21293 check_cp0_enabled(ctx);
21294 /* Treat as NOP. */
21296 break;
21297 case NM_LHE:
21298 check_eva(ctx);
21299 check_cp0_enabled(ctx);
21300 gen_ld(ctx, OPC_LHE, rt, rs, s);
21301 break;
21302 case NM_SHE:
21303 check_eva(ctx);
21304 check_cp0_enabled(ctx);
21305 gen_st(ctx, OPC_SHE, rt, rs, s);
21306 break;
21307 case NM_LHUE:
21308 check_eva(ctx);
21309 check_cp0_enabled(ctx);
21310 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21311 break;
21312 case NM_CACHEE:
21313 check_nms_dl_il_sl_tl_l2c(ctx);
21314 gen_cache_operation(ctx, rt, rs, s);
21315 break;
21316 case NM_LWE:
21317 check_eva(ctx);
21318 check_cp0_enabled(ctx);
21319 gen_ld(ctx, OPC_LWE, rt, rs, s);
21320 break;
21321 case NM_SWE:
21322 check_eva(ctx);
21323 check_cp0_enabled(ctx);
21324 gen_st(ctx, OPC_SWE, rt, rs, s);
21325 break;
21326 case NM_P_LLE:
21327 switch (extract32(ctx->opcode, 2, 2)) {
21328 case NM_LLE:
21329 check_xnp(ctx);
21330 check_eva(ctx);
21331 check_cp0_enabled(ctx);
21332 gen_ld(ctx, OPC_LLE, rt, rs, s);
21333 break;
21334 case NM_LLWPE:
21335 check_xnp(ctx);
21336 check_eva(ctx);
21337 check_cp0_enabled(ctx);
21338 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21339 break;
21340 default:
21341 gen_reserved_instruction(ctx);
21342 break;
21344 break;
21345 case NM_P_SCE:
21346 switch (extract32(ctx->opcode, 2, 2)) {
21347 case NM_SCE:
21348 check_xnp(ctx);
21349 check_eva(ctx);
21350 check_cp0_enabled(ctx);
21351 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
21352 break;
21353 case NM_SCWPE:
21354 check_xnp(ctx);
21355 check_eva(ctx);
21356 check_cp0_enabled(ctx);
21357 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21358 true);
21359 break;
21360 default:
21361 gen_reserved_instruction(ctx);
21362 break;
21364 break;
21366 break;
21367 case NM_P_LS_WM:
21368 case NM_P_LS_UAWM:
21369 check_nms(ctx);
21371 int count = extract32(ctx->opcode, 12, 3);
21372 int counter = 0;
21374 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21375 extract32(ctx->opcode, 0, 8);
21376 TCGv va = tcg_temp_new();
21377 TCGv t1 = tcg_temp_new();
21378 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21379 NM_P_LS_UAWM ? MO_UNALN : 0;
21381 count = (count == 0) ? 8 : count;
21382 while (counter != count) {
21383 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21384 int this_offset = offset + (counter << 2);
21386 gen_base_offset_addr(ctx, va, rs, this_offset);
21388 switch (extract32(ctx->opcode, 11, 1)) {
21389 case NM_LWM:
21390 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21391 memop | MO_TESL);
21392 gen_store_gpr(t1, this_rt);
21393 if ((this_rt == rs) &&
21394 (counter != (count - 1))) {
21395 /* UNPREDICTABLE */
21397 break;
21398 case NM_SWM:
21399 this_rt = (rt == 0) ? 0 : this_rt;
21400 gen_load_gpr(t1, this_rt);
21401 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21402 memop | MO_TEUL);
21403 break;
21405 counter++;
21407 tcg_temp_free(va);
21408 tcg_temp_free(t1);
21410 break;
21411 default:
21412 gen_reserved_instruction(ctx);
21413 break;
21416 break;
21417 case NM_MOVE_BALC:
21418 check_nms(ctx);
21420 TCGv t0 = tcg_temp_new();
21421 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21422 extract32(ctx->opcode, 1, 20) << 1;
21423 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21424 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21425 extract32(ctx->opcode, 21, 3));
21426 gen_load_gpr(t0, rt);
21427 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21428 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21429 tcg_temp_free(t0);
21431 break;
21432 case NM_P_BAL:
21434 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21435 extract32(ctx->opcode, 1, 24) << 1;
21437 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21438 /* BC */
21439 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21440 } else {
21441 /* BALC */
21442 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21445 break;
21446 case NM_P_J:
21447 switch (extract32(ctx->opcode, 12, 4)) {
21448 case NM_JALRC:
21449 case NM_JALRC_HB:
21450 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21451 break;
21452 case NM_P_BALRSC:
21453 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21454 break;
21455 default:
21456 gen_reserved_instruction(ctx);
21457 break;
21459 break;
21460 case NM_P_BR1:
21462 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21463 extract32(ctx->opcode, 1, 13) << 1;
21464 switch (extract32(ctx->opcode, 14, 2)) {
21465 case NM_BEQC:
21466 check_nms(ctx);
21467 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21468 break;
21469 case NM_P_BR3A:
21470 s = sextract32(ctx->opcode, 0, 1) << 14 |
21471 extract32(ctx->opcode, 1, 13) << 1;
21472 check_cp1_enabled(ctx);
21473 switch (extract32(ctx->opcode, 16, 5)) {
21474 case NM_BC1EQZC:
21475 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21476 break;
21477 case NM_BC1NEZC:
21478 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21479 break;
21480 case NM_BPOSGE32C:
21481 check_dsp_r3(ctx);
21483 int32_t imm = extract32(ctx->opcode, 1, 13) |
21484 extract32(ctx->opcode, 0, 1) << 13;
21486 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21487 imm);
21489 break;
21490 default:
21491 gen_reserved_instruction(ctx);
21492 break;
21494 break;
21495 case NM_BGEC:
21496 if (rs == rt) {
21497 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21498 } else {
21499 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21501 break;
21502 case NM_BGEUC:
21503 if (rs == rt || rt == 0) {
21504 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21505 } else if (rs == 0) {
21506 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21507 } else {
21508 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21510 break;
21513 break;
21514 case NM_P_BR2:
21516 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21517 extract32(ctx->opcode, 1, 13) << 1;
21518 switch (extract32(ctx->opcode, 14, 2)) {
21519 case NM_BNEC:
21520 check_nms(ctx);
21521 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21522 break;
21523 case NM_BLTC:
21524 if (rs != 0 && rt != 0 && rs == rt) {
21525 /* NOP */
21526 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21527 } else {
21528 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21530 break;
21531 case NM_BLTUC:
21532 if (rs == 0 || rs == rt) {
21533 /* NOP */
21534 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21535 } else {
21536 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21538 break;
21539 default:
21540 gen_reserved_instruction(ctx);
21541 break;
21544 break;
21545 case NM_P_BRI:
21547 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21548 extract32(ctx->opcode, 1, 10) << 1;
21549 uint32_t u = extract32(ctx->opcode, 11, 7);
21551 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21552 rt, u, s);
21554 break;
21555 default:
21556 gen_reserved_instruction(ctx);
21557 break;
21559 return 4;
21562 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21564 uint32_t op;
21565 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
21566 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21567 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
21568 int offset;
21569 int imm;
21571 /* make sure instructions are on a halfword boundary */
21572 if (ctx->base.pc_next & 0x1) {
21573 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21574 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21575 tcg_temp_free(tmp);
21576 generate_exception_end(ctx, EXCP_AdEL);
21577 return 2;
21580 op = extract32(ctx->opcode, 10, 6);
21581 switch (op) {
21582 case NM_P16_MV:
21583 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21584 if (rt != 0) {
21585 /* MOVE */
21586 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21587 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21588 } else {
21589 /* P16.RI */
21590 switch (extract32(ctx->opcode, 3, 2)) {
21591 case NM_P16_SYSCALL:
21592 if (extract32(ctx->opcode, 2, 1) == 0) {
21593 generate_exception_end(ctx, EXCP_SYSCALL);
21594 } else {
21595 gen_reserved_instruction(ctx);
21597 break;
21598 case NM_BREAK16:
21599 generate_exception_end(ctx, EXCP_BREAK);
21600 break;
21601 case NM_SDBBP16:
21602 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21603 gen_helper_do_semihosting(cpu_env);
21604 } else {
21605 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21606 gen_reserved_instruction(ctx);
21607 } else {
21608 generate_exception_end(ctx, EXCP_DBp);
21611 break;
21612 default:
21613 gen_reserved_instruction(ctx);
21614 break;
21617 break;
21618 case NM_P16_SHIFT:
21620 int shift = extract32(ctx->opcode, 0, 3);
21621 uint32_t opc = 0;
21622 shift = (shift == 0) ? 8 : shift;
21624 switch (extract32(ctx->opcode, 3, 1)) {
21625 case NM_SLL16:
21626 opc = OPC_SLL;
21627 break;
21628 case NM_SRL16:
21629 opc = OPC_SRL;
21630 break;
21632 gen_shift_imm(ctx, opc, rt, rs, shift);
21634 break;
21635 case NM_P16C:
21636 switch (ctx->opcode & 1) {
21637 case NM_POOL16C_0:
21638 gen_pool16c_nanomips_insn(ctx);
21639 break;
21640 case NM_LWXS16:
21641 gen_ldxs(ctx, rt, rs, rd);
21642 break;
21644 break;
21645 case NM_P16_A1:
21646 switch (extract32(ctx->opcode, 6, 1)) {
21647 case NM_ADDIUR1SP:
21648 imm = extract32(ctx->opcode, 0, 6) << 2;
21649 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21650 break;
21651 default:
21652 gen_reserved_instruction(ctx);
21653 break;
21655 break;
21656 case NM_P16_A2:
21657 switch (extract32(ctx->opcode, 3, 1)) {
21658 case NM_ADDIUR2:
21659 imm = extract32(ctx->opcode, 0, 3) << 2;
21660 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21661 break;
21662 case NM_P_ADDIURS5:
21663 rt = extract32(ctx->opcode, 5, 5);
21664 if (rt != 0) {
21665 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21666 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21667 (extract32(ctx->opcode, 0, 3));
21668 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21670 break;
21672 break;
21673 case NM_P16_ADDU:
21674 switch (ctx->opcode & 0x1) {
21675 case NM_ADDU16:
21676 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21677 break;
21678 case NM_SUBU16:
21679 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21680 break;
21682 break;
21683 case NM_P16_4X4:
21684 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21685 extract32(ctx->opcode, 5, 3);
21686 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21687 extract32(ctx->opcode, 0, 3);
21688 rt = decode_gpr_gpr4(rt);
21689 rs = decode_gpr_gpr4(rs);
21690 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21691 (extract32(ctx->opcode, 3, 1))) {
21692 case NM_ADDU4X4:
21693 check_nms(ctx);
21694 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21695 break;
21696 case NM_MUL4X4:
21697 check_nms(ctx);
21698 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21699 break;
21700 default:
21701 gen_reserved_instruction(ctx);
21702 break;
21704 break;
21705 case NM_LI16:
21707 int imm = extract32(ctx->opcode, 0, 7);
21708 imm = (imm == 0x7f ? -1 : imm);
21709 if (rt != 0) {
21710 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21713 break;
21714 case NM_ANDI16:
21716 uint32_t u = extract32(ctx->opcode, 0, 4);
21717 u = (u == 12) ? 0xff :
21718 (u == 13) ? 0xffff : u;
21719 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21721 break;
21722 case NM_P16_LB:
21723 offset = extract32(ctx->opcode, 0, 2);
21724 switch (extract32(ctx->opcode, 2, 2)) {
21725 case NM_LB16:
21726 gen_ld(ctx, OPC_LB, rt, rs, offset);
21727 break;
21728 case NM_SB16:
21729 rt = decode_gpr_gpr3_src_store(
21730 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21731 gen_st(ctx, OPC_SB, rt, rs, offset);
21732 break;
21733 case NM_LBU16:
21734 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21735 break;
21736 default:
21737 gen_reserved_instruction(ctx);
21738 break;
21740 break;
21741 case NM_P16_LH:
21742 offset = extract32(ctx->opcode, 1, 2) << 1;
21743 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21744 case NM_LH16:
21745 gen_ld(ctx, OPC_LH, rt, rs, offset);
21746 break;
21747 case NM_SH16:
21748 rt = decode_gpr_gpr3_src_store(
21749 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21750 gen_st(ctx, OPC_SH, rt, rs, offset);
21751 break;
21752 case NM_LHU16:
21753 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21754 break;
21755 default:
21756 gen_reserved_instruction(ctx);
21757 break;
21759 break;
21760 case NM_LW16:
21761 offset = extract32(ctx->opcode, 0, 4) << 2;
21762 gen_ld(ctx, OPC_LW, rt, rs, offset);
21763 break;
21764 case NM_LWSP16:
21765 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21766 offset = extract32(ctx->opcode, 0, 5) << 2;
21767 gen_ld(ctx, OPC_LW, rt, 29, offset);
21768 break;
21769 case NM_LW4X4:
21770 check_nms(ctx);
21771 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21772 extract32(ctx->opcode, 5, 3);
21773 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21774 extract32(ctx->opcode, 0, 3);
21775 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21776 (extract32(ctx->opcode, 8, 1) << 2);
21777 rt = decode_gpr_gpr4(rt);
21778 rs = decode_gpr_gpr4(rs);
21779 gen_ld(ctx, OPC_LW, rt, rs, offset);
21780 break;
21781 case NM_SW4X4:
21782 check_nms(ctx);
21783 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21784 extract32(ctx->opcode, 5, 3);
21785 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21786 extract32(ctx->opcode, 0, 3);
21787 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21788 (extract32(ctx->opcode, 8, 1) << 2);
21789 rt = decode_gpr_gpr4_zero(rt);
21790 rs = decode_gpr_gpr4(rs);
21791 gen_st(ctx, OPC_SW, rt, rs, offset);
21792 break;
21793 case NM_LWGP16:
21794 offset = extract32(ctx->opcode, 0, 7) << 2;
21795 gen_ld(ctx, OPC_LW, rt, 28, offset);
21796 break;
21797 case NM_SWSP16:
21798 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21799 offset = extract32(ctx->opcode, 0, 5) << 2;
21800 gen_st(ctx, OPC_SW, rt, 29, offset);
21801 break;
21802 case NM_SW16:
21803 rt = decode_gpr_gpr3_src_store(
21804 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21805 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21806 offset = extract32(ctx->opcode, 0, 4) << 2;
21807 gen_st(ctx, OPC_SW, rt, rs, offset);
21808 break;
21809 case NM_SWGP16:
21810 rt = decode_gpr_gpr3_src_store(
21811 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21812 offset = extract32(ctx->opcode, 0, 7) << 2;
21813 gen_st(ctx, OPC_SW, rt, 28, offset);
21814 break;
21815 case NM_BC16:
21816 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21817 (sextract32(ctx->opcode, 0, 1) << 10) |
21818 (extract32(ctx->opcode, 1, 9) << 1));
21819 break;
21820 case NM_BALC16:
21821 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21822 (sextract32(ctx->opcode, 0, 1) << 10) |
21823 (extract32(ctx->opcode, 1, 9) << 1));
21824 break;
21825 case NM_BEQZC16:
21826 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21827 (sextract32(ctx->opcode, 0, 1) << 7) |
21828 (extract32(ctx->opcode, 1, 6) << 1));
21829 break;
21830 case NM_BNEZC16:
21831 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21832 (sextract32(ctx->opcode, 0, 1) << 7) |
21833 (extract32(ctx->opcode, 1, 6) << 1));
21834 break;
21835 case NM_P16_BR:
21836 switch (ctx->opcode & 0xf) {
21837 case 0:
21838 /* P16.JRC */
21839 switch (extract32(ctx->opcode, 4, 1)) {
21840 case NM_JRC:
21841 gen_compute_branch_nm(ctx, OPC_JR, 2,
21842 extract32(ctx->opcode, 5, 5), 0, 0);
21843 break;
21844 case NM_JALRC16:
21845 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21846 extract32(ctx->opcode, 5, 5), 31, 0);
21847 break;
21849 break;
21850 default:
21852 /* P16.BRI */
21853 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21854 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21855 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21856 extract32(ctx->opcode, 0, 4) << 1);
21858 break;
21860 break;
21861 case NM_P16_SR:
21863 int count = extract32(ctx->opcode, 0, 4);
21864 int u = extract32(ctx->opcode, 4, 4) << 4;
21866 rt = 30 + extract32(ctx->opcode, 9, 1);
21867 switch (extract32(ctx->opcode, 8, 1)) {
21868 case NM_SAVE16:
21869 gen_save(ctx, rt, count, 0, u);
21870 break;
21871 case NM_RESTORE_JRC16:
21872 gen_restore(ctx, rt, count, 0, u);
21873 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21874 break;
21877 break;
21878 case NM_MOVEP:
21879 case NM_MOVEPREV:
21880 check_nms(ctx);
21882 static const int gpr2reg1[] = {4, 5, 6, 7};
21883 static const int gpr2reg2[] = {5, 6, 7, 8};
21884 int re;
21885 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21886 extract32(ctx->opcode, 8, 1);
21887 int r1 = gpr2reg1[rd2];
21888 int r2 = gpr2reg2[rd2];
21889 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21890 extract32(ctx->opcode, 0, 3);
21891 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21892 extract32(ctx->opcode, 5, 3);
21893 TCGv t0 = tcg_temp_new();
21894 TCGv t1 = tcg_temp_new();
21895 if (op == NM_MOVEP) {
21896 rd = r1;
21897 re = r2;
21898 rs = decode_gpr_gpr4_zero(r3);
21899 rt = decode_gpr_gpr4_zero(r4);
21900 } else {
21901 rd = decode_gpr_gpr4(r3);
21902 re = decode_gpr_gpr4(r4);
21903 rs = r1;
21904 rt = r2;
21906 gen_load_gpr(t0, rs);
21907 gen_load_gpr(t1, rt);
21908 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21909 tcg_gen_mov_tl(cpu_gpr[re], t1);
21910 tcg_temp_free(t0);
21911 tcg_temp_free(t1);
21913 break;
21914 default:
21915 return decode_nanomips_32_48_opc(env, ctx);
21918 return 2;
21922 /* SmartMIPS extension to MIPS32 */
21924 #if defined(TARGET_MIPS64)
21926 /* MDMX extension to MIPS64 */
21928 #endif
21930 /* MIPSDSP functions. */
21931 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21932 int rd, int base, int offset)
21934 TCGv t0;
21936 check_dsp(ctx);
21937 t0 = tcg_temp_new();
21939 if (base == 0) {
21940 gen_load_gpr(t0, offset);
21941 } else if (offset == 0) {
21942 gen_load_gpr(t0, base);
21943 } else {
21944 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21947 switch (opc) {
21948 case OPC_LBUX:
21949 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21950 gen_store_gpr(t0, rd);
21951 break;
21952 case OPC_LHX:
21953 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21954 gen_store_gpr(t0, rd);
21955 break;
21956 case OPC_LWX:
21957 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21958 gen_store_gpr(t0, rd);
21959 break;
21960 #if defined(TARGET_MIPS64)
21961 case OPC_LDX:
21962 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21963 gen_store_gpr(t0, rd);
21964 break;
21965 #endif
21967 tcg_temp_free(t0);
21970 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21971 int ret, int v1, int v2)
21973 TCGv v1_t;
21974 TCGv v2_t;
21976 if (ret == 0) {
21977 /* Treat as NOP. */
21978 return;
21981 v1_t = tcg_temp_new();
21982 v2_t = tcg_temp_new();
21984 gen_load_gpr(v1_t, v1);
21985 gen_load_gpr(v2_t, v2);
21987 switch (op1) {
21988 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21989 case OPC_MULT_G_2E:
21990 check_dsp_r2(ctx);
21991 switch (op2) {
21992 case OPC_ADDUH_QB:
21993 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21994 break;
21995 case OPC_ADDUH_R_QB:
21996 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21997 break;
21998 case OPC_ADDQH_PH:
21999 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22000 break;
22001 case OPC_ADDQH_R_PH:
22002 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22003 break;
22004 case OPC_ADDQH_W:
22005 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22006 break;
22007 case OPC_ADDQH_R_W:
22008 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22009 break;
22010 case OPC_SUBUH_QB:
22011 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22012 break;
22013 case OPC_SUBUH_R_QB:
22014 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22015 break;
22016 case OPC_SUBQH_PH:
22017 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22018 break;
22019 case OPC_SUBQH_R_PH:
22020 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22021 break;
22022 case OPC_SUBQH_W:
22023 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22024 break;
22025 case OPC_SUBQH_R_W:
22026 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22027 break;
22029 break;
22030 case OPC_ABSQ_S_PH_DSP:
22031 switch (op2) {
22032 case OPC_ABSQ_S_QB:
22033 check_dsp_r2(ctx);
22034 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22035 break;
22036 case OPC_ABSQ_S_PH:
22037 check_dsp(ctx);
22038 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22039 break;
22040 case OPC_ABSQ_S_W:
22041 check_dsp(ctx);
22042 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22043 break;
22044 case OPC_PRECEQ_W_PHL:
22045 check_dsp(ctx);
22046 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22047 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22048 break;
22049 case OPC_PRECEQ_W_PHR:
22050 check_dsp(ctx);
22051 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22052 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22053 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22054 break;
22055 case OPC_PRECEQU_PH_QBL:
22056 check_dsp(ctx);
22057 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22058 break;
22059 case OPC_PRECEQU_PH_QBR:
22060 check_dsp(ctx);
22061 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22062 break;
22063 case OPC_PRECEQU_PH_QBLA:
22064 check_dsp(ctx);
22065 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22066 break;
22067 case OPC_PRECEQU_PH_QBRA:
22068 check_dsp(ctx);
22069 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22070 break;
22071 case OPC_PRECEU_PH_QBL:
22072 check_dsp(ctx);
22073 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22074 break;
22075 case OPC_PRECEU_PH_QBR:
22076 check_dsp(ctx);
22077 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22078 break;
22079 case OPC_PRECEU_PH_QBLA:
22080 check_dsp(ctx);
22081 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22082 break;
22083 case OPC_PRECEU_PH_QBRA:
22084 check_dsp(ctx);
22085 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22086 break;
22088 break;
22089 case OPC_ADDU_QB_DSP:
22090 switch (op2) {
22091 case OPC_ADDQ_PH:
22092 check_dsp(ctx);
22093 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22094 break;
22095 case OPC_ADDQ_S_PH:
22096 check_dsp(ctx);
22097 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22098 break;
22099 case OPC_ADDQ_S_W:
22100 check_dsp(ctx);
22101 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22102 break;
22103 case OPC_ADDU_QB:
22104 check_dsp(ctx);
22105 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22106 break;
22107 case OPC_ADDU_S_QB:
22108 check_dsp(ctx);
22109 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22110 break;
22111 case OPC_ADDU_PH:
22112 check_dsp_r2(ctx);
22113 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22114 break;
22115 case OPC_ADDU_S_PH:
22116 check_dsp_r2(ctx);
22117 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22118 break;
22119 case OPC_SUBQ_PH:
22120 check_dsp(ctx);
22121 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22122 break;
22123 case OPC_SUBQ_S_PH:
22124 check_dsp(ctx);
22125 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22126 break;
22127 case OPC_SUBQ_S_W:
22128 check_dsp(ctx);
22129 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22130 break;
22131 case OPC_SUBU_QB:
22132 check_dsp(ctx);
22133 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22134 break;
22135 case OPC_SUBU_S_QB:
22136 check_dsp(ctx);
22137 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22138 break;
22139 case OPC_SUBU_PH:
22140 check_dsp_r2(ctx);
22141 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22142 break;
22143 case OPC_SUBU_S_PH:
22144 check_dsp_r2(ctx);
22145 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22146 break;
22147 case OPC_ADDSC:
22148 check_dsp(ctx);
22149 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22150 break;
22151 case OPC_ADDWC:
22152 check_dsp(ctx);
22153 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22154 break;
22155 case OPC_MODSUB:
22156 check_dsp(ctx);
22157 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22158 break;
22159 case OPC_RADDU_W_QB:
22160 check_dsp(ctx);
22161 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22162 break;
22164 break;
22165 case OPC_CMPU_EQ_QB_DSP:
22166 switch (op2) {
22167 case OPC_PRECR_QB_PH:
22168 check_dsp_r2(ctx);
22169 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22170 break;
22171 case OPC_PRECRQ_QB_PH:
22172 check_dsp(ctx);
22173 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22174 break;
22175 case OPC_PRECR_SRA_PH_W:
22176 check_dsp_r2(ctx);
22178 TCGv_i32 sa_t = tcg_const_i32(v2);
22179 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22180 cpu_gpr[ret]);
22181 tcg_temp_free_i32(sa_t);
22182 break;
22184 case OPC_PRECR_SRA_R_PH_W:
22185 check_dsp_r2(ctx);
22187 TCGv_i32 sa_t = tcg_const_i32(v2);
22188 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22189 cpu_gpr[ret]);
22190 tcg_temp_free_i32(sa_t);
22191 break;
22193 case OPC_PRECRQ_PH_W:
22194 check_dsp(ctx);
22195 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22196 break;
22197 case OPC_PRECRQ_RS_PH_W:
22198 check_dsp(ctx);
22199 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22200 break;
22201 case OPC_PRECRQU_S_QB_PH:
22202 check_dsp(ctx);
22203 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22204 break;
22206 break;
22207 #ifdef TARGET_MIPS64
22208 case OPC_ABSQ_S_QH_DSP:
22209 switch (op2) {
22210 case OPC_PRECEQ_L_PWL:
22211 check_dsp(ctx);
22212 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22213 break;
22214 case OPC_PRECEQ_L_PWR:
22215 check_dsp(ctx);
22216 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22217 break;
22218 case OPC_PRECEQ_PW_QHL:
22219 check_dsp(ctx);
22220 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22221 break;
22222 case OPC_PRECEQ_PW_QHR:
22223 check_dsp(ctx);
22224 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22225 break;
22226 case OPC_PRECEQ_PW_QHLA:
22227 check_dsp(ctx);
22228 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22229 break;
22230 case OPC_PRECEQ_PW_QHRA:
22231 check_dsp(ctx);
22232 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22233 break;
22234 case OPC_PRECEQU_QH_OBL:
22235 check_dsp(ctx);
22236 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22237 break;
22238 case OPC_PRECEQU_QH_OBR:
22239 check_dsp(ctx);
22240 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22241 break;
22242 case OPC_PRECEQU_QH_OBLA:
22243 check_dsp(ctx);
22244 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22245 break;
22246 case OPC_PRECEQU_QH_OBRA:
22247 check_dsp(ctx);
22248 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22249 break;
22250 case OPC_PRECEU_QH_OBL:
22251 check_dsp(ctx);
22252 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22253 break;
22254 case OPC_PRECEU_QH_OBR:
22255 check_dsp(ctx);
22256 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22257 break;
22258 case OPC_PRECEU_QH_OBLA:
22259 check_dsp(ctx);
22260 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22261 break;
22262 case OPC_PRECEU_QH_OBRA:
22263 check_dsp(ctx);
22264 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22265 break;
22266 case OPC_ABSQ_S_OB:
22267 check_dsp_r2(ctx);
22268 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22269 break;
22270 case OPC_ABSQ_S_PW:
22271 check_dsp(ctx);
22272 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22273 break;
22274 case OPC_ABSQ_S_QH:
22275 check_dsp(ctx);
22276 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22277 break;
22279 break;
22280 case OPC_ADDU_OB_DSP:
22281 switch (op2) {
22282 case OPC_RADDU_L_OB:
22283 check_dsp(ctx);
22284 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22285 break;
22286 case OPC_SUBQ_PW:
22287 check_dsp(ctx);
22288 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22289 break;
22290 case OPC_SUBQ_S_PW:
22291 check_dsp(ctx);
22292 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22293 break;
22294 case OPC_SUBQ_QH:
22295 check_dsp(ctx);
22296 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22297 break;
22298 case OPC_SUBQ_S_QH:
22299 check_dsp(ctx);
22300 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22301 break;
22302 case OPC_SUBU_OB:
22303 check_dsp(ctx);
22304 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22305 break;
22306 case OPC_SUBU_S_OB:
22307 check_dsp(ctx);
22308 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22309 break;
22310 case OPC_SUBU_QH:
22311 check_dsp_r2(ctx);
22312 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22313 break;
22314 case OPC_SUBU_S_QH:
22315 check_dsp_r2(ctx);
22316 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22317 break;
22318 case OPC_SUBUH_OB:
22319 check_dsp_r2(ctx);
22320 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22321 break;
22322 case OPC_SUBUH_R_OB:
22323 check_dsp_r2(ctx);
22324 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22325 break;
22326 case OPC_ADDQ_PW:
22327 check_dsp(ctx);
22328 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22329 break;
22330 case OPC_ADDQ_S_PW:
22331 check_dsp(ctx);
22332 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22333 break;
22334 case OPC_ADDQ_QH:
22335 check_dsp(ctx);
22336 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22337 break;
22338 case OPC_ADDQ_S_QH:
22339 check_dsp(ctx);
22340 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22341 break;
22342 case OPC_ADDU_OB:
22343 check_dsp(ctx);
22344 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22345 break;
22346 case OPC_ADDU_S_OB:
22347 check_dsp(ctx);
22348 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22349 break;
22350 case OPC_ADDU_QH:
22351 check_dsp_r2(ctx);
22352 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22353 break;
22354 case OPC_ADDU_S_QH:
22355 check_dsp_r2(ctx);
22356 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22357 break;
22358 case OPC_ADDUH_OB:
22359 check_dsp_r2(ctx);
22360 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22361 break;
22362 case OPC_ADDUH_R_OB:
22363 check_dsp_r2(ctx);
22364 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22365 break;
22367 break;
22368 case OPC_CMPU_EQ_OB_DSP:
22369 switch (op2) {
22370 case OPC_PRECR_OB_QH:
22371 check_dsp_r2(ctx);
22372 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22373 break;
22374 case OPC_PRECR_SRA_QH_PW:
22375 check_dsp_r2(ctx);
22377 TCGv_i32 ret_t = tcg_const_i32(ret);
22378 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22379 tcg_temp_free_i32(ret_t);
22380 break;
22382 case OPC_PRECR_SRA_R_QH_PW:
22383 check_dsp_r2(ctx);
22385 TCGv_i32 sa_v = tcg_const_i32(ret);
22386 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22387 tcg_temp_free_i32(sa_v);
22388 break;
22390 case OPC_PRECRQ_OB_QH:
22391 check_dsp(ctx);
22392 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22393 break;
22394 case OPC_PRECRQ_PW_L:
22395 check_dsp(ctx);
22396 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22397 break;
22398 case OPC_PRECRQ_QH_PW:
22399 check_dsp(ctx);
22400 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22401 break;
22402 case OPC_PRECRQ_RS_QH_PW:
22403 check_dsp(ctx);
22404 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22405 break;
22406 case OPC_PRECRQU_S_OB_QH:
22407 check_dsp(ctx);
22408 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22409 break;
22411 break;
22412 #endif
22415 tcg_temp_free(v1_t);
22416 tcg_temp_free(v2_t);
22419 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22420 int ret, int v1, int v2)
22422 uint32_t op2;
22423 TCGv t0;
22424 TCGv v1_t;
22425 TCGv v2_t;
22427 if (ret == 0) {
22428 /* Treat as NOP. */
22429 return;
22432 t0 = tcg_temp_new();
22433 v1_t = tcg_temp_new();
22434 v2_t = tcg_temp_new();
22436 tcg_gen_movi_tl(t0, v1);
22437 gen_load_gpr(v1_t, v1);
22438 gen_load_gpr(v2_t, v2);
22440 switch (opc) {
22441 case OPC_SHLL_QB_DSP:
22443 op2 = MASK_SHLL_QB(ctx->opcode);
22444 switch (op2) {
22445 case OPC_SHLL_QB:
22446 check_dsp(ctx);
22447 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22448 break;
22449 case OPC_SHLLV_QB:
22450 check_dsp(ctx);
22451 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22452 break;
22453 case OPC_SHLL_PH:
22454 check_dsp(ctx);
22455 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22456 break;
22457 case OPC_SHLLV_PH:
22458 check_dsp(ctx);
22459 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22460 break;
22461 case OPC_SHLL_S_PH:
22462 check_dsp(ctx);
22463 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22464 break;
22465 case OPC_SHLLV_S_PH:
22466 check_dsp(ctx);
22467 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22468 break;
22469 case OPC_SHLL_S_W:
22470 check_dsp(ctx);
22471 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22472 break;
22473 case OPC_SHLLV_S_W:
22474 check_dsp(ctx);
22475 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22476 break;
22477 case OPC_SHRL_QB:
22478 check_dsp(ctx);
22479 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22480 break;
22481 case OPC_SHRLV_QB:
22482 check_dsp(ctx);
22483 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22484 break;
22485 case OPC_SHRL_PH:
22486 check_dsp_r2(ctx);
22487 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22488 break;
22489 case OPC_SHRLV_PH:
22490 check_dsp_r2(ctx);
22491 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22492 break;
22493 case OPC_SHRA_QB:
22494 check_dsp_r2(ctx);
22495 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22496 break;
22497 case OPC_SHRA_R_QB:
22498 check_dsp_r2(ctx);
22499 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22500 break;
22501 case OPC_SHRAV_QB:
22502 check_dsp_r2(ctx);
22503 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22504 break;
22505 case OPC_SHRAV_R_QB:
22506 check_dsp_r2(ctx);
22507 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22508 break;
22509 case OPC_SHRA_PH:
22510 check_dsp(ctx);
22511 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22512 break;
22513 case OPC_SHRA_R_PH:
22514 check_dsp(ctx);
22515 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22516 break;
22517 case OPC_SHRAV_PH:
22518 check_dsp(ctx);
22519 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22520 break;
22521 case OPC_SHRAV_R_PH:
22522 check_dsp(ctx);
22523 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22524 break;
22525 case OPC_SHRA_R_W:
22526 check_dsp(ctx);
22527 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22528 break;
22529 case OPC_SHRAV_R_W:
22530 check_dsp(ctx);
22531 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22532 break;
22533 default: /* Invalid */
22534 MIPS_INVAL("MASK SHLL.QB");
22535 gen_reserved_instruction(ctx);
22536 break;
22538 break;
22540 #ifdef TARGET_MIPS64
22541 case OPC_SHLL_OB_DSP:
22542 op2 = MASK_SHLL_OB(ctx->opcode);
22543 switch (op2) {
22544 case OPC_SHLL_PW:
22545 check_dsp(ctx);
22546 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22547 break;
22548 case OPC_SHLLV_PW:
22549 check_dsp(ctx);
22550 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22551 break;
22552 case OPC_SHLL_S_PW:
22553 check_dsp(ctx);
22554 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22555 break;
22556 case OPC_SHLLV_S_PW:
22557 check_dsp(ctx);
22558 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22559 break;
22560 case OPC_SHLL_OB:
22561 check_dsp(ctx);
22562 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22563 break;
22564 case OPC_SHLLV_OB:
22565 check_dsp(ctx);
22566 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22567 break;
22568 case OPC_SHLL_QH:
22569 check_dsp(ctx);
22570 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22571 break;
22572 case OPC_SHLLV_QH:
22573 check_dsp(ctx);
22574 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22575 break;
22576 case OPC_SHLL_S_QH:
22577 check_dsp(ctx);
22578 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22579 break;
22580 case OPC_SHLLV_S_QH:
22581 check_dsp(ctx);
22582 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22583 break;
22584 case OPC_SHRA_OB:
22585 check_dsp_r2(ctx);
22586 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22587 break;
22588 case OPC_SHRAV_OB:
22589 check_dsp_r2(ctx);
22590 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22591 break;
22592 case OPC_SHRA_R_OB:
22593 check_dsp_r2(ctx);
22594 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22595 break;
22596 case OPC_SHRAV_R_OB:
22597 check_dsp_r2(ctx);
22598 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22599 break;
22600 case OPC_SHRA_PW:
22601 check_dsp(ctx);
22602 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22603 break;
22604 case OPC_SHRAV_PW:
22605 check_dsp(ctx);
22606 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22607 break;
22608 case OPC_SHRA_R_PW:
22609 check_dsp(ctx);
22610 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22611 break;
22612 case OPC_SHRAV_R_PW:
22613 check_dsp(ctx);
22614 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22615 break;
22616 case OPC_SHRA_QH:
22617 check_dsp(ctx);
22618 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22619 break;
22620 case OPC_SHRAV_QH:
22621 check_dsp(ctx);
22622 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22623 break;
22624 case OPC_SHRA_R_QH:
22625 check_dsp(ctx);
22626 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22627 break;
22628 case OPC_SHRAV_R_QH:
22629 check_dsp(ctx);
22630 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22631 break;
22632 case OPC_SHRL_OB:
22633 check_dsp(ctx);
22634 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22635 break;
22636 case OPC_SHRLV_OB:
22637 check_dsp(ctx);
22638 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22639 break;
22640 case OPC_SHRL_QH:
22641 check_dsp_r2(ctx);
22642 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22643 break;
22644 case OPC_SHRLV_QH:
22645 check_dsp_r2(ctx);
22646 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22647 break;
22648 default: /* Invalid */
22649 MIPS_INVAL("MASK SHLL.OB");
22650 gen_reserved_instruction(ctx);
22651 break;
22653 break;
22654 #endif
22657 tcg_temp_free(t0);
22658 tcg_temp_free(v1_t);
22659 tcg_temp_free(v2_t);
22662 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22663 int ret, int v1, int v2, int check_ret)
22665 TCGv_i32 t0;
22666 TCGv v1_t;
22667 TCGv v2_t;
22669 if ((ret == 0) && (check_ret == 1)) {
22670 /* Treat as NOP. */
22671 return;
22674 t0 = tcg_temp_new_i32();
22675 v1_t = tcg_temp_new();
22676 v2_t = tcg_temp_new();
22678 tcg_gen_movi_i32(t0, ret);
22679 gen_load_gpr(v1_t, v1);
22680 gen_load_gpr(v2_t, v2);
22682 switch (op1) {
22684 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22685 * the same mask and op1.
22687 case OPC_MULT_G_2E:
22688 check_dsp_r2(ctx);
22689 switch (op2) {
22690 case OPC_MUL_PH:
22691 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22692 break;
22693 case OPC_MUL_S_PH:
22694 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22695 break;
22696 case OPC_MULQ_S_W:
22697 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22698 break;
22699 case OPC_MULQ_RS_W:
22700 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22701 break;
22703 break;
22704 case OPC_DPA_W_PH_DSP:
22705 switch (op2) {
22706 case OPC_DPAU_H_QBL:
22707 check_dsp(ctx);
22708 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22709 break;
22710 case OPC_DPAU_H_QBR:
22711 check_dsp(ctx);
22712 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22713 break;
22714 case OPC_DPSU_H_QBL:
22715 check_dsp(ctx);
22716 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22717 break;
22718 case OPC_DPSU_H_QBR:
22719 check_dsp(ctx);
22720 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22721 break;
22722 case OPC_DPA_W_PH:
22723 check_dsp_r2(ctx);
22724 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22725 break;
22726 case OPC_DPAX_W_PH:
22727 check_dsp_r2(ctx);
22728 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22729 break;
22730 case OPC_DPAQ_S_W_PH:
22731 check_dsp(ctx);
22732 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22733 break;
22734 case OPC_DPAQX_S_W_PH:
22735 check_dsp_r2(ctx);
22736 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22737 break;
22738 case OPC_DPAQX_SA_W_PH:
22739 check_dsp_r2(ctx);
22740 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22741 break;
22742 case OPC_DPS_W_PH:
22743 check_dsp_r2(ctx);
22744 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22745 break;
22746 case OPC_DPSX_W_PH:
22747 check_dsp_r2(ctx);
22748 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22749 break;
22750 case OPC_DPSQ_S_W_PH:
22751 check_dsp(ctx);
22752 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22753 break;
22754 case OPC_DPSQX_S_W_PH:
22755 check_dsp_r2(ctx);
22756 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22757 break;
22758 case OPC_DPSQX_SA_W_PH:
22759 check_dsp_r2(ctx);
22760 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22761 break;
22762 case OPC_MULSAQ_S_W_PH:
22763 check_dsp(ctx);
22764 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22765 break;
22766 case OPC_DPAQ_SA_L_W:
22767 check_dsp(ctx);
22768 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22769 break;
22770 case OPC_DPSQ_SA_L_W:
22771 check_dsp(ctx);
22772 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22773 break;
22774 case OPC_MAQ_S_W_PHL:
22775 check_dsp(ctx);
22776 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22777 break;
22778 case OPC_MAQ_S_W_PHR:
22779 check_dsp(ctx);
22780 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22781 break;
22782 case OPC_MAQ_SA_W_PHL:
22783 check_dsp(ctx);
22784 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22785 break;
22786 case OPC_MAQ_SA_W_PHR:
22787 check_dsp(ctx);
22788 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22789 break;
22790 case OPC_MULSA_W_PH:
22791 check_dsp_r2(ctx);
22792 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22793 break;
22795 break;
22796 #ifdef TARGET_MIPS64
22797 case OPC_DPAQ_W_QH_DSP:
22799 int ac = ret & 0x03;
22800 tcg_gen_movi_i32(t0, ac);
22802 switch (op2) {
22803 case OPC_DMADD:
22804 check_dsp(ctx);
22805 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22806 break;
22807 case OPC_DMADDU:
22808 check_dsp(ctx);
22809 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22810 break;
22811 case OPC_DMSUB:
22812 check_dsp(ctx);
22813 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22814 break;
22815 case OPC_DMSUBU:
22816 check_dsp(ctx);
22817 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22818 break;
22819 case OPC_DPA_W_QH:
22820 check_dsp_r2(ctx);
22821 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22822 break;
22823 case OPC_DPAQ_S_W_QH:
22824 check_dsp(ctx);
22825 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22826 break;
22827 case OPC_DPAQ_SA_L_PW:
22828 check_dsp(ctx);
22829 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22830 break;
22831 case OPC_DPAU_H_OBL:
22832 check_dsp(ctx);
22833 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22834 break;
22835 case OPC_DPAU_H_OBR:
22836 check_dsp(ctx);
22837 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22838 break;
22839 case OPC_DPS_W_QH:
22840 check_dsp_r2(ctx);
22841 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22842 break;
22843 case OPC_DPSQ_S_W_QH:
22844 check_dsp(ctx);
22845 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22846 break;
22847 case OPC_DPSQ_SA_L_PW:
22848 check_dsp(ctx);
22849 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22850 break;
22851 case OPC_DPSU_H_OBL:
22852 check_dsp(ctx);
22853 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22854 break;
22855 case OPC_DPSU_H_OBR:
22856 check_dsp(ctx);
22857 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22858 break;
22859 case OPC_MAQ_S_L_PWL:
22860 check_dsp(ctx);
22861 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22862 break;
22863 case OPC_MAQ_S_L_PWR:
22864 check_dsp(ctx);
22865 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22866 break;
22867 case OPC_MAQ_S_W_QHLL:
22868 check_dsp(ctx);
22869 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22870 break;
22871 case OPC_MAQ_SA_W_QHLL:
22872 check_dsp(ctx);
22873 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22874 break;
22875 case OPC_MAQ_S_W_QHLR:
22876 check_dsp(ctx);
22877 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22878 break;
22879 case OPC_MAQ_SA_W_QHLR:
22880 check_dsp(ctx);
22881 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22882 break;
22883 case OPC_MAQ_S_W_QHRL:
22884 check_dsp(ctx);
22885 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22886 break;
22887 case OPC_MAQ_SA_W_QHRL:
22888 check_dsp(ctx);
22889 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22890 break;
22891 case OPC_MAQ_S_W_QHRR:
22892 check_dsp(ctx);
22893 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22894 break;
22895 case OPC_MAQ_SA_W_QHRR:
22896 check_dsp(ctx);
22897 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22898 break;
22899 case OPC_MULSAQ_S_L_PW:
22900 check_dsp(ctx);
22901 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22902 break;
22903 case OPC_MULSAQ_S_W_QH:
22904 check_dsp(ctx);
22905 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22906 break;
22909 break;
22910 #endif
22911 case OPC_ADDU_QB_DSP:
22912 switch (op2) {
22913 case OPC_MULEU_S_PH_QBL:
22914 check_dsp(ctx);
22915 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22916 break;
22917 case OPC_MULEU_S_PH_QBR:
22918 check_dsp(ctx);
22919 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22920 break;
22921 case OPC_MULQ_RS_PH:
22922 check_dsp(ctx);
22923 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22924 break;
22925 case OPC_MULEQ_S_W_PHL:
22926 check_dsp(ctx);
22927 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22928 break;
22929 case OPC_MULEQ_S_W_PHR:
22930 check_dsp(ctx);
22931 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22932 break;
22933 case OPC_MULQ_S_PH:
22934 check_dsp_r2(ctx);
22935 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22936 break;
22938 break;
22939 #ifdef TARGET_MIPS64
22940 case OPC_ADDU_OB_DSP:
22941 switch (op2) {
22942 case OPC_MULEQ_S_PW_QHL:
22943 check_dsp(ctx);
22944 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22945 break;
22946 case OPC_MULEQ_S_PW_QHR:
22947 check_dsp(ctx);
22948 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22949 break;
22950 case OPC_MULEU_S_QH_OBL:
22951 check_dsp(ctx);
22952 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22953 break;
22954 case OPC_MULEU_S_QH_OBR:
22955 check_dsp(ctx);
22956 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22957 break;
22958 case OPC_MULQ_RS_QH:
22959 check_dsp(ctx);
22960 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22961 break;
22963 break;
22964 #endif
22967 tcg_temp_free_i32(t0);
22968 tcg_temp_free(v1_t);
22969 tcg_temp_free(v2_t);
22972 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22973 int ret, int val)
22975 int16_t imm;
22976 TCGv t0;
22977 TCGv val_t;
22979 if (ret == 0) {
22980 /* Treat as NOP. */
22981 return;
22984 t0 = tcg_temp_new();
22985 val_t = tcg_temp_new();
22986 gen_load_gpr(val_t, val);
22988 switch (op1) {
22989 case OPC_ABSQ_S_PH_DSP:
22990 switch (op2) {
22991 case OPC_BITREV:
22992 check_dsp(ctx);
22993 gen_helper_bitrev(cpu_gpr[ret], val_t);
22994 break;
22995 case OPC_REPL_QB:
22996 check_dsp(ctx);
22998 target_long result;
22999 imm = (ctx->opcode >> 16) & 0xFF;
23000 result = (uint32_t)imm << 24 |
23001 (uint32_t)imm << 16 |
23002 (uint32_t)imm << 8 |
23003 (uint32_t)imm;
23004 result = (int32_t)result;
23005 tcg_gen_movi_tl(cpu_gpr[ret], result);
23007 break;
23008 case OPC_REPLV_QB:
23009 check_dsp(ctx);
23010 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23011 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23012 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23013 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23014 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23015 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23016 break;
23017 case OPC_REPL_PH:
23018 check_dsp(ctx);
23020 imm = (ctx->opcode >> 16) & 0x03FF;
23021 imm = (int16_t)(imm << 6) >> 6;
23022 tcg_gen_movi_tl(cpu_gpr[ret], \
23023 (target_long)((int32_t)imm << 16 | \
23024 (uint16_t)imm));
23026 break;
23027 case OPC_REPLV_PH:
23028 check_dsp(ctx);
23029 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23030 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23031 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23032 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23033 break;
23035 break;
23036 #ifdef TARGET_MIPS64
23037 case OPC_ABSQ_S_QH_DSP:
23038 switch (op2) {
23039 case OPC_REPL_OB:
23040 check_dsp(ctx);
23042 target_long temp;
23044 imm = (ctx->opcode >> 16) & 0xFF;
23045 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23046 temp = (temp << 16) | temp;
23047 temp = (temp << 32) | temp;
23048 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23049 break;
23051 case OPC_REPL_PW:
23052 check_dsp(ctx);
23054 target_long temp;
23056 imm = (ctx->opcode >> 16) & 0x03FF;
23057 imm = (int16_t)(imm << 6) >> 6;
23058 temp = ((target_long)imm << 32) \
23059 | ((target_long)imm & 0xFFFFFFFF);
23060 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23061 break;
23063 case OPC_REPL_QH:
23064 check_dsp(ctx);
23066 target_long temp;
23068 imm = (ctx->opcode >> 16) & 0x03FF;
23069 imm = (int16_t)(imm << 6) >> 6;
23071 temp = ((uint64_t)(uint16_t)imm << 48) |
23072 ((uint64_t)(uint16_t)imm << 32) |
23073 ((uint64_t)(uint16_t)imm << 16) |
23074 (uint64_t)(uint16_t)imm;
23075 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23076 break;
23078 case OPC_REPLV_OB:
23079 check_dsp(ctx);
23080 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23081 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23082 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23083 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23084 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23085 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23086 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23087 break;
23088 case OPC_REPLV_PW:
23089 check_dsp(ctx);
23090 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23091 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23092 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23093 break;
23094 case OPC_REPLV_QH:
23095 check_dsp(ctx);
23096 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23097 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23098 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23099 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23100 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23101 break;
23103 break;
23104 #endif
23106 tcg_temp_free(t0);
23107 tcg_temp_free(val_t);
23110 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23111 uint32_t op1, uint32_t op2,
23112 int ret, int v1, int v2, int check_ret)
23114 TCGv t1;
23115 TCGv v1_t;
23116 TCGv v2_t;
23118 if ((ret == 0) && (check_ret == 1)) {
23119 /* Treat as NOP. */
23120 return;
23123 t1 = tcg_temp_new();
23124 v1_t = tcg_temp_new();
23125 v2_t = tcg_temp_new();
23127 gen_load_gpr(v1_t, v1);
23128 gen_load_gpr(v2_t, v2);
23130 switch (op1) {
23131 case OPC_CMPU_EQ_QB_DSP:
23132 switch (op2) {
23133 case OPC_CMPU_EQ_QB:
23134 check_dsp(ctx);
23135 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23136 break;
23137 case OPC_CMPU_LT_QB:
23138 check_dsp(ctx);
23139 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23140 break;
23141 case OPC_CMPU_LE_QB:
23142 check_dsp(ctx);
23143 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23144 break;
23145 case OPC_CMPGU_EQ_QB:
23146 check_dsp(ctx);
23147 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23148 break;
23149 case OPC_CMPGU_LT_QB:
23150 check_dsp(ctx);
23151 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23152 break;
23153 case OPC_CMPGU_LE_QB:
23154 check_dsp(ctx);
23155 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23156 break;
23157 case OPC_CMPGDU_EQ_QB:
23158 check_dsp_r2(ctx);
23159 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23160 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23161 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23162 tcg_gen_shli_tl(t1, t1, 24);
23163 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23164 break;
23165 case OPC_CMPGDU_LT_QB:
23166 check_dsp_r2(ctx);
23167 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23168 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23169 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23170 tcg_gen_shli_tl(t1, t1, 24);
23171 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23172 break;
23173 case OPC_CMPGDU_LE_QB:
23174 check_dsp_r2(ctx);
23175 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23176 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23177 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23178 tcg_gen_shli_tl(t1, t1, 24);
23179 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23180 break;
23181 case OPC_CMP_EQ_PH:
23182 check_dsp(ctx);
23183 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23184 break;
23185 case OPC_CMP_LT_PH:
23186 check_dsp(ctx);
23187 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23188 break;
23189 case OPC_CMP_LE_PH:
23190 check_dsp(ctx);
23191 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23192 break;
23193 case OPC_PICK_QB:
23194 check_dsp(ctx);
23195 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23196 break;
23197 case OPC_PICK_PH:
23198 check_dsp(ctx);
23199 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23200 break;
23201 case OPC_PACKRL_PH:
23202 check_dsp(ctx);
23203 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23204 break;
23206 break;
23207 #ifdef TARGET_MIPS64
23208 case OPC_CMPU_EQ_OB_DSP:
23209 switch (op2) {
23210 case OPC_CMP_EQ_PW:
23211 check_dsp(ctx);
23212 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23213 break;
23214 case OPC_CMP_LT_PW:
23215 check_dsp(ctx);
23216 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23217 break;
23218 case OPC_CMP_LE_PW:
23219 check_dsp(ctx);
23220 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23221 break;
23222 case OPC_CMP_EQ_QH:
23223 check_dsp(ctx);
23224 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23225 break;
23226 case OPC_CMP_LT_QH:
23227 check_dsp(ctx);
23228 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23229 break;
23230 case OPC_CMP_LE_QH:
23231 check_dsp(ctx);
23232 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23233 break;
23234 case OPC_CMPGDU_EQ_OB:
23235 check_dsp_r2(ctx);
23236 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23237 break;
23238 case OPC_CMPGDU_LT_OB:
23239 check_dsp_r2(ctx);
23240 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23241 break;
23242 case OPC_CMPGDU_LE_OB:
23243 check_dsp_r2(ctx);
23244 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23245 break;
23246 case OPC_CMPGU_EQ_OB:
23247 check_dsp(ctx);
23248 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23249 break;
23250 case OPC_CMPGU_LT_OB:
23251 check_dsp(ctx);
23252 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23253 break;
23254 case OPC_CMPGU_LE_OB:
23255 check_dsp(ctx);
23256 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23257 break;
23258 case OPC_CMPU_EQ_OB:
23259 check_dsp(ctx);
23260 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23261 break;
23262 case OPC_CMPU_LT_OB:
23263 check_dsp(ctx);
23264 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23265 break;
23266 case OPC_CMPU_LE_OB:
23267 check_dsp(ctx);
23268 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23269 break;
23270 case OPC_PACKRL_PW:
23271 check_dsp(ctx);
23272 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23273 break;
23274 case OPC_PICK_OB:
23275 check_dsp(ctx);
23276 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23277 break;
23278 case OPC_PICK_PW:
23279 check_dsp(ctx);
23280 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23281 break;
23282 case OPC_PICK_QH:
23283 check_dsp(ctx);
23284 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23285 break;
23287 break;
23288 #endif
23291 tcg_temp_free(t1);
23292 tcg_temp_free(v1_t);
23293 tcg_temp_free(v2_t);
23296 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23297 uint32_t op1, int rt, int rs, int sa)
23299 TCGv t0;
23301 check_dsp_r2(ctx);
23303 if (rt == 0) {
23304 /* Treat as NOP. */
23305 return;
23308 t0 = tcg_temp_new();
23309 gen_load_gpr(t0, rs);
23311 switch (op1) {
23312 case OPC_APPEND_DSP:
23313 switch (MASK_APPEND(ctx->opcode)) {
23314 case OPC_APPEND:
23315 if (sa != 0) {
23316 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23318 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23319 break;
23320 case OPC_PREPEND:
23321 if (sa != 0) {
23322 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23323 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23324 tcg_gen_shli_tl(t0, t0, 32 - sa);
23325 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23327 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23328 break;
23329 case OPC_BALIGN:
23330 sa &= 3;
23331 if (sa != 0 && sa != 2) {
23332 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23333 tcg_gen_ext32u_tl(t0, t0);
23334 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23335 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23337 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23338 break;
23339 default: /* Invalid */
23340 MIPS_INVAL("MASK APPEND");
23341 gen_reserved_instruction(ctx);
23342 break;
23344 break;
23345 #ifdef TARGET_MIPS64
23346 case OPC_DAPPEND_DSP:
23347 switch (MASK_DAPPEND(ctx->opcode)) {
23348 case OPC_DAPPEND:
23349 if (sa != 0) {
23350 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23352 break;
23353 case OPC_PREPENDD:
23354 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23355 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23356 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23357 break;
23358 case OPC_PREPENDW:
23359 if (sa != 0) {
23360 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23361 tcg_gen_shli_tl(t0, t0, 64 - sa);
23362 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23364 break;
23365 case OPC_DBALIGN:
23366 sa &= 7;
23367 if (sa != 0 && sa != 2 && sa != 4) {
23368 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23369 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23370 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23372 break;
23373 default: /* Invalid */
23374 MIPS_INVAL("MASK DAPPEND");
23375 gen_reserved_instruction(ctx);
23376 break;
23378 break;
23379 #endif
23381 tcg_temp_free(t0);
23384 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23385 int ret, int v1, int v2, int check_ret)
23388 TCGv t0;
23389 TCGv t1;
23390 TCGv v1_t;
23391 TCGv v2_t;
23392 int16_t imm;
23394 if ((ret == 0) && (check_ret == 1)) {
23395 /* Treat as NOP. */
23396 return;
23399 t0 = tcg_temp_new();
23400 t1 = tcg_temp_new();
23401 v1_t = tcg_temp_new();
23402 v2_t = tcg_temp_new();
23404 gen_load_gpr(v1_t, v1);
23405 gen_load_gpr(v2_t, v2);
23407 switch (op1) {
23408 case OPC_EXTR_W_DSP:
23409 check_dsp(ctx);
23410 switch (op2) {
23411 case OPC_EXTR_W:
23412 tcg_gen_movi_tl(t0, v2);
23413 tcg_gen_movi_tl(t1, v1);
23414 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23415 break;
23416 case OPC_EXTR_R_W:
23417 tcg_gen_movi_tl(t0, v2);
23418 tcg_gen_movi_tl(t1, v1);
23419 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23420 break;
23421 case OPC_EXTR_RS_W:
23422 tcg_gen_movi_tl(t0, v2);
23423 tcg_gen_movi_tl(t1, v1);
23424 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23425 break;
23426 case OPC_EXTR_S_H:
23427 tcg_gen_movi_tl(t0, v2);
23428 tcg_gen_movi_tl(t1, v1);
23429 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23430 break;
23431 case OPC_EXTRV_S_H:
23432 tcg_gen_movi_tl(t0, v2);
23433 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23434 break;
23435 case OPC_EXTRV_W:
23436 tcg_gen_movi_tl(t0, v2);
23437 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23438 break;
23439 case OPC_EXTRV_R_W:
23440 tcg_gen_movi_tl(t0, v2);
23441 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23442 break;
23443 case OPC_EXTRV_RS_W:
23444 tcg_gen_movi_tl(t0, v2);
23445 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23446 break;
23447 case OPC_EXTP:
23448 tcg_gen_movi_tl(t0, v2);
23449 tcg_gen_movi_tl(t1, v1);
23450 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23451 break;
23452 case OPC_EXTPV:
23453 tcg_gen_movi_tl(t0, v2);
23454 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23455 break;
23456 case OPC_EXTPDP:
23457 tcg_gen_movi_tl(t0, v2);
23458 tcg_gen_movi_tl(t1, v1);
23459 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23460 break;
23461 case OPC_EXTPDPV:
23462 tcg_gen_movi_tl(t0, v2);
23463 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23464 break;
23465 case OPC_SHILO:
23466 imm = (ctx->opcode >> 20) & 0x3F;
23467 tcg_gen_movi_tl(t0, ret);
23468 tcg_gen_movi_tl(t1, imm);
23469 gen_helper_shilo(t0, t1, cpu_env);
23470 break;
23471 case OPC_SHILOV:
23472 tcg_gen_movi_tl(t0, ret);
23473 gen_helper_shilo(t0, v1_t, cpu_env);
23474 break;
23475 case OPC_MTHLIP:
23476 tcg_gen_movi_tl(t0, ret);
23477 gen_helper_mthlip(t0, v1_t, cpu_env);
23478 break;
23479 case OPC_WRDSP:
23480 imm = (ctx->opcode >> 11) & 0x3FF;
23481 tcg_gen_movi_tl(t0, imm);
23482 gen_helper_wrdsp(v1_t, t0, cpu_env);
23483 break;
23484 case OPC_RDDSP:
23485 imm = (ctx->opcode >> 16) & 0x03FF;
23486 tcg_gen_movi_tl(t0, imm);
23487 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23488 break;
23490 break;
23491 #ifdef TARGET_MIPS64
23492 case OPC_DEXTR_W_DSP:
23493 check_dsp(ctx);
23494 switch (op2) {
23495 case OPC_DMTHLIP:
23496 tcg_gen_movi_tl(t0, ret);
23497 gen_helper_dmthlip(v1_t, t0, cpu_env);
23498 break;
23499 case OPC_DSHILO:
23501 int shift = (ctx->opcode >> 19) & 0x7F;
23502 int ac = (ctx->opcode >> 11) & 0x03;
23503 tcg_gen_movi_tl(t0, shift);
23504 tcg_gen_movi_tl(t1, ac);
23505 gen_helper_dshilo(t0, t1, cpu_env);
23506 break;
23508 case OPC_DSHILOV:
23510 int ac = (ctx->opcode >> 11) & 0x03;
23511 tcg_gen_movi_tl(t0, ac);
23512 gen_helper_dshilo(v1_t, t0, cpu_env);
23513 break;
23515 case OPC_DEXTP:
23516 tcg_gen_movi_tl(t0, v2);
23517 tcg_gen_movi_tl(t1, v1);
23519 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23520 break;
23521 case OPC_DEXTPV:
23522 tcg_gen_movi_tl(t0, v2);
23523 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23524 break;
23525 case OPC_DEXTPDP:
23526 tcg_gen_movi_tl(t0, v2);
23527 tcg_gen_movi_tl(t1, v1);
23528 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23529 break;
23530 case OPC_DEXTPDPV:
23531 tcg_gen_movi_tl(t0, v2);
23532 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23533 break;
23534 case OPC_DEXTR_L:
23535 tcg_gen_movi_tl(t0, v2);
23536 tcg_gen_movi_tl(t1, v1);
23537 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23538 break;
23539 case OPC_DEXTR_R_L:
23540 tcg_gen_movi_tl(t0, v2);
23541 tcg_gen_movi_tl(t1, v1);
23542 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23543 break;
23544 case OPC_DEXTR_RS_L:
23545 tcg_gen_movi_tl(t0, v2);
23546 tcg_gen_movi_tl(t1, v1);
23547 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23548 break;
23549 case OPC_DEXTR_W:
23550 tcg_gen_movi_tl(t0, v2);
23551 tcg_gen_movi_tl(t1, v1);
23552 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23553 break;
23554 case OPC_DEXTR_R_W:
23555 tcg_gen_movi_tl(t0, v2);
23556 tcg_gen_movi_tl(t1, v1);
23557 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23558 break;
23559 case OPC_DEXTR_RS_W:
23560 tcg_gen_movi_tl(t0, v2);
23561 tcg_gen_movi_tl(t1, v1);
23562 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23563 break;
23564 case OPC_DEXTR_S_H:
23565 tcg_gen_movi_tl(t0, v2);
23566 tcg_gen_movi_tl(t1, v1);
23567 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23568 break;
23569 case OPC_DEXTRV_S_H:
23570 tcg_gen_movi_tl(t0, v2);
23571 tcg_gen_movi_tl(t1, v1);
23572 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23573 break;
23574 case OPC_DEXTRV_L:
23575 tcg_gen_movi_tl(t0, v2);
23576 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23577 break;
23578 case OPC_DEXTRV_R_L:
23579 tcg_gen_movi_tl(t0, v2);
23580 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23581 break;
23582 case OPC_DEXTRV_RS_L:
23583 tcg_gen_movi_tl(t0, v2);
23584 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23585 break;
23586 case OPC_DEXTRV_W:
23587 tcg_gen_movi_tl(t0, v2);
23588 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23589 break;
23590 case OPC_DEXTRV_R_W:
23591 tcg_gen_movi_tl(t0, v2);
23592 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23593 break;
23594 case OPC_DEXTRV_RS_W:
23595 tcg_gen_movi_tl(t0, v2);
23596 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23597 break;
23599 break;
23600 #endif
23603 tcg_temp_free(t0);
23604 tcg_temp_free(t1);
23605 tcg_temp_free(v1_t);
23606 tcg_temp_free(v2_t);
23609 /* End MIPSDSP functions. */
23611 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23613 int rs, rt, rd, sa;
23614 uint32_t op1, op2;
23616 rs = (ctx->opcode >> 21) & 0x1f;
23617 rt = (ctx->opcode >> 16) & 0x1f;
23618 rd = (ctx->opcode >> 11) & 0x1f;
23619 sa = (ctx->opcode >> 6) & 0x1f;
23621 op1 = MASK_SPECIAL(ctx->opcode);
23622 switch (op1) {
23623 case OPC_MULT:
23624 case OPC_MULTU:
23625 case OPC_DIV:
23626 case OPC_DIVU:
23627 op2 = MASK_R6_MULDIV(ctx->opcode);
23628 switch (op2) {
23629 case R6_OPC_MUL:
23630 case R6_OPC_MUH:
23631 case R6_OPC_MULU:
23632 case R6_OPC_MUHU:
23633 case R6_OPC_DIV:
23634 case R6_OPC_MOD:
23635 case R6_OPC_DIVU:
23636 case R6_OPC_MODU:
23637 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23638 break;
23639 default:
23640 MIPS_INVAL("special_r6 muldiv");
23641 gen_reserved_instruction(ctx);
23642 break;
23644 break;
23645 case OPC_SELEQZ:
23646 case OPC_SELNEZ:
23647 gen_cond_move(ctx, op1, rd, rs, rt);
23648 break;
23649 case R6_OPC_CLO:
23650 case R6_OPC_CLZ:
23651 if (rt == 0 && sa == 1) {
23653 * Major opcode and function field is shared with preR6 MFHI/MTHI.
23654 * We need additionally to check other fields.
23656 gen_cl(ctx, op1, rd, rs);
23657 } else {
23658 gen_reserved_instruction(ctx);
23660 break;
23661 case R6_OPC_SDBBP:
23662 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23663 gen_helper_do_semihosting(cpu_env);
23664 } else {
23665 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23666 gen_reserved_instruction(ctx);
23667 } else {
23668 generate_exception_end(ctx, EXCP_DBp);
23671 break;
23672 #if defined(TARGET_MIPS64)
23673 case R6_OPC_DCLO:
23674 case R6_OPC_DCLZ:
23675 if (rt == 0 && sa == 1) {
23677 * Major opcode and function field is shared with preR6 MFHI/MTHI.
23678 * We need additionally to check other fields.
23680 check_mips_64(ctx);
23681 gen_cl(ctx, op1, rd, rs);
23682 } else {
23683 gen_reserved_instruction(ctx);
23685 break;
23686 case OPC_DMULT:
23687 case OPC_DMULTU:
23688 case OPC_DDIV:
23689 case OPC_DDIVU:
23691 op2 = MASK_R6_MULDIV(ctx->opcode);
23692 switch (op2) {
23693 case R6_OPC_DMUL:
23694 case R6_OPC_DMUH:
23695 case R6_OPC_DMULU:
23696 case R6_OPC_DMUHU:
23697 case R6_OPC_DDIV:
23698 case R6_OPC_DMOD:
23699 case R6_OPC_DDIVU:
23700 case R6_OPC_DMODU:
23701 check_mips_64(ctx);
23702 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23703 break;
23704 default:
23705 MIPS_INVAL("special_r6 muldiv");
23706 gen_reserved_instruction(ctx);
23707 break;
23709 break;
23710 #endif
23711 default: /* Invalid */
23712 MIPS_INVAL("special_r6");
23713 gen_reserved_instruction(ctx);
23714 break;
23718 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
23720 int rs = extract32(ctx->opcode, 21, 5);
23721 int rt = extract32(ctx->opcode, 16, 5);
23722 int rd = extract32(ctx->opcode, 11, 5);
23723 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
23725 switch (op1) {
23726 case OPC_MOVN: /* Conditional move */
23727 case OPC_MOVZ:
23728 gen_cond_move(ctx, op1, rd, rs, rt);
23729 break;
23730 case OPC_MFHI: /* Move from HI/LO */
23731 case OPC_MFLO:
23732 gen_HILO(ctx, op1, 0, rd);
23733 break;
23734 case OPC_MTHI:
23735 case OPC_MTLO: /* Move to HI/LO */
23736 gen_HILO(ctx, op1, 0, rs);
23737 break;
23738 case OPC_MULT:
23739 case OPC_MULTU:
23740 gen_mul_txx9(ctx, op1, rd, rs, rt);
23741 break;
23742 case OPC_DIV:
23743 case OPC_DIVU:
23744 gen_muldiv(ctx, op1, 0, rs, rt);
23745 break;
23746 #if defined(TARGET_MIPS64)
23747 case OPC_DMULT:
23748 case OPC_DMULTU:
23749 case OPC_DDIV:
23750 case OPC_DDIVU:
23751 check_insn_opc_user_only(ctx, INSN_R5900);
23752 gen_muldiv(ctx, op1, 0, rs, rt);
23753 break;
23754 #endif
23755 case OPC_JR:
23756 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
23757 break;
23758 default: /* Invalid */
23759 MIPS_INVAL("special_tx79");
23760 gen_reserved_instruction(ctx);
23761 break;
23765 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23767 int rs, rt, rd, sa;
23768 uint32_t op1;
23770 rs = (ctx->opcode >> 21) & 0x1f;
23771 rt = (ctx->opcode >> 16) & 0x1f;
23772 rd = (ctx->opcode >> 11) & 0x1f;
23773 sa = (ctx->opcode >> 6) & 0x1f;
23775 op1 = MASK_SPECIAL(ctx->opcode);
23776 switch (op1) {
23777 case OPC_MOVN: /* Conditional move */
23778 case OPC_MOVZ:
23779 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
23780 INSN_LOONGSON2E | INSN_LOONGSON2F);
23781 gen_cond_move(ctx, op1, rd, rs, rt);
23782 break;
23783 case OPC_MFHI: /* Move from HI/LO */
23784 case OPC_MFLO:
23785 gen_HILO(ctx, op1, rs & 3, rd);
23786 break;
23787 case OPC_MTHI:
23788 case OPC_MTLO: /* Move to HI/LO */
23789 gen_HILO(ctx, op1, rd & 3, rs);
23790 break;
23791 case OPC_MOVCI:
23792 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
23793 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23794 check_cp1_enabled(ctx);
23795 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23796 (ctx->opcode >> 16) & 1);
23797 } else {
23798 generate_exception_err(ctx, EXCP_CpU, 1);
23800 break;
23801 case OPC_MULT:
23802 case OPC_MULTU:
23803 if (sa) {
23804 check_insn(ctx, INSN_VR54XX);
23805 op1 = MASK_MUL_VR54XX(ctx->opcode);
23806 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23807 } else {
23808 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23810 break;
23811 case OPC_DIV:
23812 case OPC_DIVU:
23813 gen_muldiv(ctx, op1, 0, rs, rt);
23814 break;
23815 #if defined(TARGET_MIPS64)
23816 case OPC_DMULT:
23817 case OPC_DMULTU:
23818 case OPC_DDIV:
23819 case OPC_DDIVU:
23820 check_insn(ctx, ISA_MIPS3);
23821 check_mips_64(ctx);
23822 gen_muldiv(ctx, op1, 0, rs, rt);
23823 break;
23824 #endif
23825 case OPC_JR:
23826 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23827 break;
23828 case OPC_SPIM:
23829 #ifdef MIPS_STRICT_STANDARD
23830 MIPS_INVAL("SPIM");
23831 gen_reserved_instruction(ctx);
23832 #else
23833 /* Implemented as RI exception for now. */
23834 MIPS_INVAL("spim (unofficial)");
23835 gen_reserved_instruction(ctx);
23836 #endif
23837 break;
23838 default: /* Invalid */
23839 MIPS_INVAL("special_legacy");
23840 gen_reserved_instruction(ctx);
23841 break;
23845 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23847 int rs, rt, rd, sa;
23848 uint32_t op1;
23850 rs = (ctx->opcode >> 21) & 0x1f;
23851 rt = (ctx->opcode >> 16) & 0x1f;
23852 rd = (ctx->opcode >> 11) & 0x1f;
23853 sa = (ctx->opcode >> 6) & 0x1f;
23855 op1 = MASK_SPECIAL(ctx->opcode);
23856 switch (op1) {
23857 case OPC_SLL: /* Shift with immediate */
23858 if (sa == 5 && rd == 0 &&
23859 rs == 0 && rt == 0) { /* PAUSE */
23860 if ((ctx->insn_flags & ISA_MIPS_R6) &&
23861 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23862 gen_reserved_instruction(ctx);
23863 break;
23866 /* Fallthrough */
23867 case OPC_SRA:
23868 gen_shift_imm(ctx, op1, rd, rt, sa);
23869 break;
23870 case OPC_SRL:
23871 switch ((ctx->opcode >> 21) & 0x1f) {
23872 case 1:
23873 /* rotr is decoded as srl on non-R2 CPUs */
23874 if (ctx->insn_flags & ISA_MIPS_R2) {
23875 op1 = OPC_ROTR;
23877 /* Fallthrough */
23878 case 0:
23879 gen_shift_imm(ctx, op1, rd, rt, sa);
23880 break;
23881 default:
23882 gen_reserved_instruction(ctx);
23883 break;
23885 break;
23886 case OPC_ADD:
23887 case OPC_ADDU:
23888 case OPC_SUB:
23889 case OPC_SUBU:
23890 gen_arith(ctx, op1, rd, rs, rt);
23891 break;
23892 case OPC_SLLV: /* Shifts */
23893 case OPC_SRAV:
23894 gen_shift(ctx, op1, rd, rs, rt);
23895 break;
23896 case OPC_SRLV:
23897 switch ((ctx->opcode >> 6) & 0x1f) {
23898 case 1:
23899 /* rotrv is decoded as srlv on non-R2 CPUs */
23900 if (ctx->insn_flags & ISA_MIPS_R2) {
23901 op1 = OPC_ROTRV;
23903 /* Fallthrough */
23904 case 0:
23905 gen_shift(ctx, op1, rd, rs, rt);
23906 break;
23907 default:
23908 gen_reserved_instruction(ctx);
23909 break;
23911 break;
23912 case OPC_SLT: /* Set on less than */
23913 case OPC_SLTU:
23914 gen_slt(ctx, op1, rd, rs, rt);
23915 break;
23916 case OPC_AND: /* Logic*/
23917 case OPC_OR:
23918 case OPC_NOR:
23919 case OPC_XOR:
23920 gen_logic(ctx, op1, rd, rs, rt);
23921 break;
23922 case OPC_JALR:
23923 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23924 break;
23925 case OPC_TGE: /* Traps */
23926 case OPC_TGEU:
23927 case OPC_TLT:
23928 case OPC_TLTU:
23929 case OPC_TEQ:
23930 case OPC_TNE:
23931 check_insn(ctx, ISA_MIPS2);
23932 gen_trap(ctx, op1, rs, rt, -1);
23933 break;
23934 case OPC_PMON:
23935 /* Pmon entry point, also R4010 selsl */
23936 #ifdef MIPS_STRICT_STANDARD
23937 MIPS_INVAL("PMON / selsl");
23938 gen_reserved_instruction(ctx);
23939 #else
23940 gen_helper_0e0i(pmon, sa);
23941 #endif
23942 break;
23943 case OPC_SYSCALL:
23944 generate_exception_end(ctx, EXCP_SYSCALL);
23945 break;
23946 case OPC_BREAK:
23947 generate_exception_end(ctx, EXCP_BREAK);
23948 break;
23949 case OPC_SYNC:
23950 check_insn(ctx, ISA_MIPS2);
23951 gen_sync(extract32(ctx->opcode, 6, 5));
23952 break;
23954 #if defined(TARGET_MIPS64)
23955 /* MIPS64 specific opcodes */
23956 case OPC_DSLL:
23957 case OPC_DSRA:
23958 case OPC_DSLL32:
23959 case OPC_DSRA32:
23960 check_insn(ctx, ISA_MIPS3);
23961 check_mips_64(ctx);
23962 gen_shift_imm(ctx, op1, rd, rt, sa);
23963 break;
23964 case OPC_DSRL:
23965 switch ((ctx->opcode >> 21) & 0x1f) {
23966 case 1:
23967 /* drotr is decoded as dsrl on non-R2 CPUs */
23968 if (ctx->insn_flags & ISA_MIPS_R2) {
23969 op1 = OPC_DROTR;
23971 /* Fallthrough */
23972 case 0:
23973 check_insn(ctx, ISA_MIPS3);
23974 check_mips_64(ctx);
23975 gen_shift_imm(ctx, op1, rd, rt, sa);
23976 break;
23977 default:
23978 gen_reserved_instruction(ctx);
23979 break;
23981 break;
23982 case OPC_DSRL32:
23983 switch ((ctx->opcode >> 21) & 0x1f) {
23984 case 1:
23985 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23986 if (ctx->insn_flags & ISA_MIPS_R2) {
23987 op1 = OPC_DROTR32;
23989 /* Fallthrough */
23990 case 0:
23991 check_insn(ctx, ISA_MIPS3);
23992 check_mips_64(ctx);
23993 gen_shift_imm(ctx, op1, rd, rt, sa);
23994 break;
23995 default:
23996 gen_reserved_instruction(ctx);
23997 break;
23999 break;
24000 case OPC_DADD:
24001 case OPC_DADDU:
24002 case OPC_DSUB:
24003 case OPC_DSUBU:
24004 check_insn(ctx, ISA_MIPS3);
24005 check_mips_64(ctx);
24006 gen_arith(ctx, op1, rd, rs, rt);
24007 break;
24008 case OPC_DSLLV:
24009 case OPC_DSRAV:
24010 check_insn(ctx, ISA_MIPS3);
24011 check_mips_64(ctx);
24012 gen_shift(ctx, op1, rd, rs, rt);
24013 break;
24014 case OPC_DSRLV:
24015 switch ((ctx->opcode >> 6) & 0x1f) {
24016 case 1:
24017 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24018 if (ctx->insn_flags & ISA_MIPS_R2) {
24019 op1 = OPC_DROTRV;
24021 /* Fallthrough */
24022 case 0:
24023 check_insn(ctx, ISA_MIPS3);
24024 check_mips_64(ctx);
24025 gen_shift(ctx, op1, rd, rs, rt);
24026 break;
24027 default:
24028 gen_reserved_instruction(ctx);
24029 break;
24031 break;
24032 #endif
24033 default:
24034 if (ctx->insn_flags & ISA_MIPS_R6) {
24035 decode_opc_special_r6(env, ctx);
24036 } else if (ctx->insn_flags & INSN_R5900) {
24037 decode_opc_special_tx79(env, ctx);
24038 } else {
24039 decode_opc_special_legacy(env, ctx);
24045 #if defined(TARGET_MIPS64)
24049 * MMI (MultiMedia Interface) ASE instructions
24050 * ===========================================
24054 * MMI instructions category: data communication
24055 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24057 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24058 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24059 * PCPYUD PEXEH PEXTLW PPACW
24060 * PEXEW PEXTUB
24061 * PEXTUH
24062 * PEXTUW
24066 * PCPYH rd, rt
24068 * Parallel Copy Halfword
24070 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24071 * +-----------+---------+---------+---------+---------+-----------+
24072 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24073 * +-----------+---------+---------+---------+---------+-----------+
24075 static void gen_mmi_pcpyh(DisasContext *ctx)
24077 uint32_t pd, rt, rd;
24078 uint32_t opcode;
24080 opcode = ctx->opcode;
24082 pd = extract32(opcode, 21, 5);
24083 rt = extract32(opcode, 16, 5);
24084 rd = extract32(opcode, 11, 5);
24086 if (unlikely(pd != 0)) {
24087 gen_reserved_instruction(ctx);
24088 } else if (rd == 0) {
24089 /* nop */
24090 } else if (rt == 0) {
24091 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24092 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24093 } else {
24094 TCGv_i64 t0 = tcg_temp_new();
24095 TCGv_i64 t1 = tcg_temp_new();
24096 uint64_t mask = (1ULL << 16) - 1;
24098 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24099 tcg_gen_movi_i64(t1, 0);
24100 tcg_gen_or_i64(t1, t0, t1);
24101 tcg_gen_shli_i64(t0, t0, 16);
24102 tcg_gen_or_i64(t1, t0, t1);
24103 tcg_gen_shli_i64(t0, t0, 16);
24104 tcg_gen_or_i64(t1, t0, t1);
24105 tcg_gen_shli_i64(t0, t0, 16);
24106 tcg_gen_or_i64(t1, t0, t1);
24108 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24110 tcg_gen_andi_i64(t0, cpu_gpr_hi[rt], mask);
24111 tcg_gen_movi_i64(t1, 0);
24112 tcg_gen_or_i64(t1, t0, t1);
24113 tcg_gen_shli_i64(t0, t0, 16);
24114 tcg_gen_or_i64(t1, t0, t1);
24115 tcg_gen_shli_i64(t0, t0, 16);
24116 tcg_gen_or_i64(t1, t0, t1);
24117 tcg_gen_shli_i64(t0, t0, 16);
24118 tcg_gen_or_i64(t1, t0, t1);
24120 tcg_gen_mov_i64(cpu_gpr_hi[rd], t1);
24122 tcg_temp_free(t0);
24123 tcg_temp_free(t1);
24128 * PCPYLD rd, rs, rt
24130 * Parallel Copy Lower Doubleword
24132 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24133 * +-----------+---------+---------+---------+---------+-----------+
24134 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24135 * +-----------+---------+---------+---------+---------+-----------+
24137 static void gen_mmi_pcpyld(DisasContext *ctx)
24139 uint32_t rs, rt, rd;
24140 uint32_t opcode;
24142 opcode = ctx->opcode;
24144 rs = extract32(opcode, 21, 5);
24145 rt = extract32(opcode, 16, 5);
24146 rd = extract32(opcode, 11, 5);
24148 if (rd == 0) {
24149 /* nop */
24150 } else {
24151 if (rs == 0) {
24152 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24153 } else {
24154 tcg_gen_mov_i64(cpu_gpr_hi[rd], cpu_gpr[rs]);
24156 if (rt == 0) {
24157 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24158 } else {
24159 if (rd != rt) {
24160 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24167 * PCPYUD rd, rs, rt
24169 * Parallel Copy Upper Doubleword
24171 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24172 * +-----------+---------+---------+---------+---------+-----------+
24173 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24174 * +-----------+---------+---------+---------+---------+-----------+
24176 static void gen_mmi_pcpyud(DisasContext *ctx)
24178 uint32_t rs, rt, rd;
24179 uint32_t opcode;
24181 opcode = ctx->opcode;
24183 rs = extract32(opcode, 21, 5);
24184 rt = extract32(opcode, 16, 5);
24185 rd = extract32(opcode, 11, 5);
24187 if (rd == 0) {
24188 /* nop */
24189 } else {
24190 gen_load_gpr_hi(cpu_gpr[rd], rs);
24191 if (rt == 0) {
24192 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24193 } else {
24194 if (rd != rt) {
24195 tcg_gen_mov_i64(cpu_gpr_hi[rd], cpu_gpr_hi[rt]);
24201 #endif
24203 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
24205 int rs, rt, rd;
24206 uint32_t op1;
24208 rs = (ctx->opcode >> 21) & 0x1f;
24209 rt = (ctx->opcode >> 16) & 0x1f;
24210 rd = (ctx->opcode >> 11) & 0x1f;
24212 op1 = MASK_SPECIAL2(ctx->opcode);
24213 switch (op1) {
24214 case OPC_MADD: /* Multiply and add/sub */
24215 case OPC_MADDU:
24216 case OPC_MSUB:
24217 case OPC_MSUBU:
24218 check_insn(ctx, ISA_MIPS_R1);
24219 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24220 break;
24221 case OPC_MUL:
24222 gen_arith(ctx, op1, rd, rs, rt);
24223 break;
24224 case OPC_DIV_G_2F:
24225 case OPC_DIVU_G_2F:
24226 case OPC_MULT_G_2F:
24227 case OPC_MULTU_G_2F:
24228 case OPC_MOD_G_2F:
24229 case OPC_MODU_G_2F:
24230 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
24231 gen_loongson_integer(ctx, op1, rd, rs, rt);
24232 break;
24233 case OPC_CLO:
24234 case OPC_CLZ:
24235 check_insn(ctx, ISA_MIPS_R1);
24236 gen_cl(ctx, op1, rd, rs);
24237 break;
24238 case OPC_SDBBP:
24239 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24240 gen_helper_do_semihosting(cpu_env);
24241 } else {
24243 * XXX: not clear which exception should be raised
24244 * when in debug mode...
24246 check_insn(ctx, ISA_MIPS_R1);
24247 generate_exception_end(ctx, EXCP_DBp);
24249 break;
24250 #if defined(TARGET_MIPS64)
24251 case OPC_DCLO:
24252 case OPC_DCLZ:
24253 check_insn(ctx, ISA_MIPS_R1);
24254 check_mips_64(ctx);
24255 gen_cl(ctx, op1, rd, rs);
24256 break;
24257 case OPC_DMULT_G_2F:
24258 case OPC_DMULTU_G_2F:
24259 case OPC_DDIV_G_2F:
24260 case OPC_DDIVU_G_2F:
24261 case OPC_DMOD_G_2F:
24262 case OPC_DMODU_G_2F:
24263 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
24264 gen_loongson_integer(ctx, op1, rd, rs, rt);
24265 break;
24266 #endif
24267 default: /* Invalid */
24268 MIPS_INVAL("special2_legacy");
24269 gen_reserved_instruction(ctx);
24270 break;
24274 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
24276 int rs, rt, rd, sa;
24277 uint32_t op1, op2;
24278 int16_t imm;
24280 rs = (ctx->opcode >> 21) & 0x1f;
24281 rt = (ctx->opcode >> 16) & 0x1f;
24282 rd = (ctx->opcode >> 11) & 0x1f;
24283 sa = (ctx->opcode >> 6) & 0x1f;
24284 imm = (int16_t)ctx->opcode >> 7;
24286 op1 = MASK_SPECIAL3(ctx->opcode);
24287 switch (op1) {
24288 case R6_OPC_PREF:
24289 if (rt >= 24) {
24290 /* hint codes 24-31 are reserved and signal RI */
24291 gen_reserved_instruction(ctx);
24293 /* Treat as NOP. */
24294 break;
24295 case R6_OPC_CACHE:
24296 check_cp0_enabled(ctx);
24297 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24298 gen_cache_operation(ctx, rt, rs, imm);
24300 break;
24301 case R6_OPC_SC:
24302 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
24303 break;
24304 case R6_OPC_LL:
24305 gen_ld(ctx, op1, rt, rs, imm);
24306 break;
24307 case OPC_BSHFL:
24309 if (rd == 0) {
24310 /* Treat as NOP. */
24311 break;
24313 op2 = MASK_BSHFL(ctx->opcode);
24314 switch (op2) {
24315 case OPC_ALIGN:
24316 case OPC_ALIGN_1:
24317 case OPC_ALIGN_2:
24318 case OPC_ALIGN_3:
24319 gen_align(ctx, 32, rd, rs, rt, sa & 3);
24320 break;
24321 case OPC_BITSWAP:
24322 gen_bitswap(ctx, op2, rd, rt);
24323 break;
24326 break;
24327 #ifndef CONFIG_USER_ONLY
24328 case OPC_GINV:
24329 if (unlikely(ctx->gi <= 1)) {
24330 gen_reserved_instruction(ctx);
24332 check_cp0_enabled(ctx);
24333 switch ((ctx->opcode >> 6) & 3) {
24334 case 0: /* GINVI */
24335 /* Treat as NOP. */
24336 break;
24337 case 2: /* GINVT */
24338 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
24339 break;
24340 default:
24341 gen_reserved_instruction(ctx);
24342 break;
24344 break;
24345 #endif
24346 #if defined(TARGET_MIPS64)
24347 case R6_OPC_SCD:
24348 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
24349 break;
24350 case R6_OPC_LLD:
24351 gen_ld(ctx, op1, rt, rs, imm);
24352 break;
24353 case OPC_DBSHFL:
24354 check_mips_64(ctx);
24356 if (rd == 0) {
24357 /* Treat as NOP. */
24358 break;
24360 op2 = MASK_DBSHFL(ctx->opcode);
24361 switch (op2) {
24362 case OPC_DALIGN:
24363 case OPC_DALIGN_1:
24364 case OPC_DALIGN_2:
24365 case OPC_DALIGN_3:
24366 case OPC_DALIGN_4:
24367 case OPC_DALIGN_5:
24368 case OPC_DALIGN_6:
24369 case OPC_DALIGN_7:
24370 gen_align(ctx, 64, rd, rs, rt, sa & 7);
24371 break;
24372 case OPC_DBITSWAP:
24373 gen_bitswap(ctx, op2, rd, rt);
24374 break;
24378 break;
24379 #endif
24380 default: /* Invalid */
24381 MIPS_INVAL("special3_r6");
24382 gen_reserved_instruction(ctx);
24383 break;
24387 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
24389 int rs, rt, rd;
24390 uint32_t op1, op2;
24392 rs = (ctx->opcode >> 21) & 0x1f;
24393 rt = (ctx->opcode >> 16) & 0x1f;
24394 rd = (ctx->opcode >> 11) & 0x1f;
24396 op1 = MASK_SPECIAL3(ctx->opcode);
24397 switch (op1) {
24398 case OPC_DIV_G_2E:
24399 case OPC_DIVU_G_2E:
24400 case OPC_MOD_G_2E:
24401 case OPC_MODU_G_2E:
24402 case OPC_MULT_G_2E:
24403 case OPC_MULTU_G_2E:
24405 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
24406 * the same mask and op1.
24408 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
24409 op2 = MASK_ADDUH_QB(ctx->opcode);
24410 switch (op2) {
24411 case OPC_ADDUH_QB:
24412 case OPC_ADDUH_R_QB:
24413 case OPC_ADDQH_PH:
24414 case OPC_ADDQH_R_PH:
24415 case OPC_ADDQH_W:
24416 case OPC_ADDQH_R_W:
24417 case OPC_SUBUH_QB:
24418 case OPC_SUBUH_R_QB:
24419 case OPC_SUBQH_PH:
24420 case OPC_SUBQH_R_PH:
24421 case OPC_SUBQH_W:
24422 case OPC_SUBQH_R_W:
24423 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24424 break;
24425 case OPC_MUL_PH:
24426 case OPC_MUL_S_PH:
24427 case OPC_MULQ_S_W:
24428 case OPC_MULQ_RS_W:
24429 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24430 break;
24431 default:
24432 MIPS_INVAL("MASK ADDUH.QB");
24433 gen_reserved_instruction(ctx);
24434 break;
24436 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
24437 gen_loongson_integer(ctx, op1, rd, rs, rt);
24438 } else {
24439 gen_reserved_instruction(ctx);
24441 break;
24442 case OPC_LX_DSP:
24443 op2 = MASK_LX(ctx->opcode);
24444 switch (op2) {
24445 #if defined(TARGET_MIPS64)
24446 case OPC_LDX:
24447 #endif
24448 case OPC_LBUX:
24449 case OPC_LHX:
24450 case OPC_LWX:
24451 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
24452 break;
24453 default: /* Invalid */
24454 MIPS_INVAL("MASK LX");
24455 gen_reserved_instruction(ctx);
24456 break;
24458 break;
24459 case OPC_ABSQ_S_PH_DSP:
24460 op2 = MASK_ABSQ_S_PH(ctx->opcode);
24461 switch (op2) {
24462 case OPC_ABSQ_S_QB:
24463 case OPC_ABSQ_S_PH:
24464 case OPC_ABSQ_S_W:
24465 case OPC_PRECEQ_W_PHL:
24466 case OPC_PRECEQ_W_PHR:
24467 case OPC_PRECEQU_PH_QBL:
24468 case OPC_PRECEQU_PH_QBR:
24469 case OPC_PRECEQU_PH_QBLA:
24470 case OPC_PRECEQU_PH_QBRA:
24471 case OPC_PRECEU_PH_QBL:
24472 case OPC_PRECEU_PH_QBR:
24473 case OPC_PRECEU_PH_QBLA:
24474 case OPC_PRECEU_PH_QBRA:
24475 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24476 break;
24477 case OPC_BITREV:
24478 case OPC_REPL_QB:
24479 case OPC_REPLV_QB:
24480 case OPC_REPL_PH:
24481 case OPC_REPLV_PH:
24482 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24483 break;
24484 default:
24485 MIPS_INVAL("MASK ABSQ_S.PH");
24486 gen_reserved_instruction(ctx);
24487 break;
24489 break;
24490 case OPC_ADDU_QB_DSP:
24491 op2 = MASK_ADDU_QB(ctx->opcode);
24492 switch (op2) {
24493 case OPC_ADDQ_PH:
24494 case OPC_ADDQ_S_PH:
24495 case OPC_ADDQ_S_W:
24496 case OPC_ADDU_QB:
24497 case OPC_ADDU_S_QB:
24498 case OPC_ADDU_PH:
24499 case OPC_ADDU_S_PH:
24500 case OPC_SUBQ_PH:
24501 case OPC_SUBQ_S_PH:
24502 case OPC_SUBQ_S_W:
24503 case OPC_SUBU_QB:
24504 case OPC_SUBU_S_QB:
24505 case OPC_SUBU_PH:
24506 case OPC_SUBU_S_PH:
24507 case OPC_ADDSC:
24508 case OPC_ADDWC:
24509 case OPC_MODSUB:
24510 case OPC_RADDU_W_QB:
24511 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24512 break;
24513 case OPC_MULEU_S_PH_QBL:
24514 case OPC_MULEU_S_PH_QBR:
24515 case OPC_MULQ_RS_PH:
24516 case OPC_MULEQ_S_W_PHL:
24517 case OPC_MULEQ_S_W_PHR:
24518 case OPC_MULQ_S_PH:
24519 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24520 break;
24521 default: /* Invalid */
24522 MIPS_INVAL("MASK ADDU.QB");
24523 gen_reserved_instruction(ctx);
24524 break;
24527 break;
24528 case OPC_CMPU_EQ_QB_DSP:
24529 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
24530 switch (op2) {
24531 case OPC_PRECR_SRA_PH_W:
24532 case OPC_PRECR_SRA_R_PH_W:
24533 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24534 break;
24535 case OPC_PRECR_QB_PH:
24536 case OPC_PRECRQ_QB_PH:
24537 case OPC_PRECRQ_PH_W:
24538 case OPC_PRECRQ_RS_PH_W:
24539 case OPC_PRECRQU_S_QB_PH:
24540 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24541 break;
24542 case OPC_CMPU_EQ_QB:
24543 case OPC_CMPU_LT_QB:
24544 case OPC_CMPU_LE_QB:
24545 case OPC_CMP_EQ_PH:
24546 case OPC_CMP_LT_PH:
24547 case OPC_CMP_LE_PH:
24548 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24549 break;
24550 case OPC_CMPGU_EQ_QB:
24551 case OPC_CMPGU_LT_QB:
24552 case OPC_CMPGU_LE_QB:
24553 case OPC_CMPGDU_EQ_QB:
24554 case OPC_CMPGDU_LT_QB:
24555 case OPC_CMPGDU_LE_QB:
24556 case OPC_PICK_QB:
24557 case OPC_PICK_PH:
24558 case OPC_PACKRL_PH:
24559 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24560 break;
24561 default: /* Invalid */
24562 MIPS_INVAL("MASK CMPU.EQ.QB");
24563 gen_reserved_instruction(ctx);
24564 break;
24566 break;
24567 case OPC_SHLL_QB_DSP:
24568 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24569 break;
24570 case OPC_DPA_W_PH_DSP:
24571 op2 = MASK_DPA_W_PH(ctx->opcode);
24572 switch (op2) {
24573 case OPC_DPAU_H_QBL:
24574 case OPC_DPAU_H_QBR:
24575 case OPC_DPSU_H_QBL:
24576 case OPC_DPSU_H_QBR:
24577 case OPC_DPA_W_PH:
24578 case OPC_DPAX_W_PH:
24579 case OPC_DPAQ_S_W_PH:
24580 case OPC_DPAQX_S_W_PH:
24581 case OPC_DPAQX_SA_W_PH:
24582 case OPC_DPS_W_PH:
24583 case OPC_DPSX_W_PH:
24584 case OPC_DPSQ_S_W_PH:
24585 case OPC_DPSQX_S_W_PH:
24586 case OPC_DPSQX_SA_W_PH:
24587 case OPC_MULSAQ_S_W_PH:
24588 case OPC_DPAQ_SA_L_W:
24589 case OPC_DPSQ_SA_L_W:
24590 case OPC_MAQ_S_W_PHL:
24591 case OPC_MAQ_S_W_PHR:
24592 case OPC_MAQ_SA_W_PHL:
24593 case OPC_MAQ_SA_W_PHR:
24594 case OPC_MULSA_W_PH:
24595 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24596 break;
24597 default: /* Invalid */
24598 MIPS_INVAL("MASK DPAW.PH");
24599 gen_reserved_instruction(ctx);
24600 break;
24602 break;
24603 case OPC_INSV_DSP:
24604 op2 = MASK_INSV(ctx->opcode);
24605 switch (op2) {
24606 case OPC_INSV:
24607 check_dsp(ctx);
24609 TCGv t0, t1;
24611 if (rt == 0) {
24612 break;
24615 t0 = tcg_temp_new();
24616 t1 = tcg_temp_new();
24618 gen_load_gpr(t0, rt);
24619 gen_load_gpr(t1, rs);
24621 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
24623 tcg_temp_free(t0);
24624 tcg_temp_free(t1);
24625 break;
24627 default: /* Invalid */
24628 MIPS_INVAL("MASK INSV");
24629 gen_reserved_instruction(ctx);
24630 break;
24632 break;
24633 case OPC_APPEND_DSP:
24634 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24635 break;
24636 case OPC_EXTR_W_DSP:
24637 op2 = MASK_EXTR_W(ctx->opcode);
24638 switch (op2) {
24639 case OPC_EXTR_W:
24640 case OPC_EXTR_R_W:
24641 case OPC_EXTR_RS_W:
24642 case OPC_EXTR_S_H:
24643 case OPC_EXTRV_S_H:
24644 case OPC_EXTRV_W:
24645 case OPC_EXTRV_R_W:
24646 case OPC_EXTRV_RS_W:
24647 case OPC_EXTP:
24648 case OPC_EXTPV:
24649 case OPC_EXTPDP:
24650 case OPC_EXTPDPV:
24651 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24652 break;
24653 case OPC_RDDSP:
24654 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
24655 break;
24656 case OPC_SHILO:
24657 case OPC_SHILOV:
24658 case OPC_MTHLIP:
24659 case OPC_WRDSP:
24660 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24661 break;
24662 default: /* Invalid */
24663 MIPS_INVAL("MASK EXTR.W");
24664 gen_reserved_instruction(ctx);
24665 break;
24667 break;
24668 #if defined(TARGET_MIPS64)
24669 case OPC_DDIV_G_2E:
24670 case OPC_DDIVU_G_2E:
24671 case OPC_DMULT_G_2E:
24672 case OPC_DMULTU_G_2E:
24673 case OPC_DMOD_G_2E:
24674 case OPC_DMODU_G_2E:
24675 check_insn(ctx, INSN_LOONGSON2E);
24676 gen_loongson_integer(ctx, op1, rd, rs, rt);
24677 break;
24678 case OPC_ABSQ_S_QH_DSP:
24679 op2 = MASK_ABSQ_S_QH(ctx->opcode);
24680 switch (op2) {
24681 case OPC_PRECEQ_L_PWL:
24682 case OPC_PRECEQ_L_PWR:
24683 case OPC_PRECEQ_PW_QHL:
24684 case OPC_PRECEQ_PW_QHR:
24685 case OPC_PRECEQ_PW_QHLA:
24686 case OPC_PRECEQ_PW_QHRA:
24687 case OPC_PRECEQU_QH_OBL:
24688 case OPC_PRECEQU_QH_OBR:
24689 case OPC_PRECEQU_QH_OBLA:
24690 case OPC_PRECEQU_QH_OBRA:
24691 case OPC_PRECEU_QH_OBL:
24692 case OPC_PRECEU_QH_OBR:
24693 case OPC_PRECEU_QH_OBLA:
24694 case OPC_PRECEU_QH_OBRA:
24695 case OPC_ABSQ_S_OB:
24696 case OPC_ABSQ_S_PW:
24697 case OPC_ABSQ_S_QH:
24698 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24699 break;
24700 case OPC_REPL_OB:
24701 case OPC_REPL_PW:
24702 case OPC_REPL_QH:
24703 case OPC_REPLV_OB:
24704 case OPC_REPLV_PW:
24705 case OPC_REPLV_QH:
24706 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24707 break;
24708 default: /* Invalid */
24709 MIPS_INVAL("MASK ABSQ_S.QH");
24710 gen_reserved_instruction(ctx);
24711 break;
24713 break;
24714 case OPC_ADDU_OB_DSP:
24715 op2 = MASK_ADDU_OB(ctx->opcode);
24716 switch (op2) {
24717 case OPC_RADDU_L_OB:
24718 case OPC_SUBQ_PW:
24719 case OPC_SUBQ_S_PW:
24720 case OPC_SUBQ_QH:
24721 case OPC_SUBQ_S_QH:
24722 case OPC_SUBU_OB:
24723 case OPC_SUBU_S_OB:
24724 case OPC_SUBU_QH:
24725 case OPC_SUBU_S_QH:
24726 case OPC_SUBUH_OB:
24727 case OPC_SUBUH_R_OB:
24728 case OPC_ADDQ_PW:
24729 case OPC_ADDQ_S_PW:
24730 case OPC_ADDQ_QH:
24731 case OPC_ADDQ_S_QH:
24732 case OPC_ADDU_OB:
24733 case OPC_ADDU_S_OB:
24734 case OPC_ADDU_QH:
24735 case OPC_ADDU_S_QH:
24736 case OPC_ADDUH_OB:
24737 case OPC_ADDUH_R_OB:
24738 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24739 break;
24740 case OPC_MULEQ_S_PW_QHL:
24741 case OPC_MULEQ_S_PW_QHR:
24742 case OPC_MULEU_S_QH_OBL:
24743 case OPC_MULEU_S_QH_OBR:
24744 case OPC_MULQ_RS_QH:
24745 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24746 break;
24747 default: /* Invalid */
24748 MIPS_INVAL("MASK ADDU.OB");
24749 gen_reserved_instruction(ctx);
24750 break;
24752 break;
24753 case OPC_CMPU_EQ_OB_DSP:
24754 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
24755 switch (op2) {
24756 case OPC_PRECR_SRA_QH_PW:
24757 case OPC_PRECR_SRA_R_QH_PW:
24758 /* Return value is rt. */
24759 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24760 break;
24761 case OPC_PRECR_OB_QH:
24762 case OPC_PRECRQ_OB_QH:
24763 case OPC_PRECRQ_PW_L:
24764 case OPC_PRECRQ_QH_PW:
24765 case OPC_PRECRQ_RS_QH_PW:
24766 case OPC_PRECRQU_S_OB_QH:
24767 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24768 break;
24769 case OPC_CMPU_EQ_OB:
24770 case OPC_CMPU_LT_OB:
24771 case OPC_CMPU_LE_OB:
24772 case OPC_CMP_EQ_QH:
24773 case OPC_CMP_LT_QH:
24774 case OPC_CMP_LE_QH:
24775 case OPC_CMP_EQ_PW:
24776 case OPC_CMP_LT_PW:
24777 case OPC_CMP_LE_PW:
24778 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24779 break;
24780 case OPC_CMPGDU_EQ_OB:
24781 case OPC_CMPGDU_LT_OB:
24782 case OPC_CMPGDU_LE_OB:
24783 case OPC_CMPGU_EQ_OB:
24784 case OPC_CMPGU_LT_OB:
24785 case OPC_CMPGU_LE_OB:
24786 case OPC_PACKRL_PW:
24787 case OPC_PICK_OB:
24788 case OPC_PICK_PW:
24789 case OPC_PICK_QH:
24790 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24791 break;
24792 default: /* Invalid */
24793 MIPS_INVAL("MASK CMPU_EQ.OB");
24794 gen_reserved_instruction(ctx);
24795 break;
24797 break;
24798 case OPC_DAPPEND_DSP:
24799 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24800 break;
24801 case OPC_DEXTR_W_DSP:
24802 op2 = MASK_DEXTR_W(ctx->opcode);
24803 switch (op2) {
24804 case OPC_DEXTP:
24805 case OPC_DEXTPDP:
24806 case OPC_DEXTPDPV:
24807 case OPC_DEXTPV:
24808 case OPC_DEXTR_L:
24809 case OPC_DEXTR_R_L:
24810 case OPC_DEXTR_RS_L:
24811 case OPC_DEXTR_W:
24812 case OPC_DEXTR_R_W:
24813 case OPC_DEXTR_RS_W:
24814 case OPC_DEXTR_S_H:
24815 case OPC_DEXTRV_L:
24816 case OPC_DEXTRV_R_L:
24817 case OPC_DEXTRV_RS_L:
24818 case OPC_DEXTRV_S_H:
24819 case OPC_DEXTRV_W:
24820 case OPC_DEXTRV_R_W:
24821 case OPC_DEXTRV_RS_W:
24822 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24823 break;
24824 case OPC_DMTHLIP:
24825 case OPC_DSHILO:
24826 case OPC_DSHILOV:
24827 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24828 break;
24829 default: /* Invalid */
24830 MIPS_INVAL("MASK EXTR.W");
24831 gen_reserved_instruction(ctx);
24832 break;
24834 break;
24835 case OPC_DPAQ_W_QH_DSP:
24836 op2 = MASK_DPAQ_W_QH(ctx->opcode);
24837 switch (op2) {
24838 case OPC_DPAU_H_OBL:
24839 case OPC_DPAU_H_OBR:
24840 case OPC_DPSU_H_OBL:
24841 case OPC_DPSU_H_OBR:
24842 case OPC_DPA_W_QH:
24843 case OPC_DPAQ_S_W_QH:
24844 case OPC_DPS_W_QH:
24845 case OPC_DPSQ_S_W_QH:
24846 case OPC_MULSAQ_S_W_QH:
24847 case OPC_DPAQ_SA_L_PW:
24848 case OPC_DPSQ_SA_L_PW:
24849 case OPC_MULSAQ_S_L_PW:
24850 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24851 break;
24852 case OPC_MAQ_S_W_QHLL:
24853 case OPC_MAQ_S_W_QHLR:
24854 case OPC_MAQ_S_W_QHRL:
24855 case OPC_MAQ_S_W_QHRR:
24856 case OPC_MAQ_SA_W_QHLL:
24857 case OPC_MAQ_SA_W_QHLR:
24858 case OPC_MAQ_SA_W_QHRL:
24859 case OPC_MAQ_SA_W_QHRR:
24860 case OPC_MAQ_S_L_PWL:
24861 case OPC_MAQ_S_L_PWR:
24862 case OPC_DMADD:
24863 case OPC_DMADDU:
24864 case OPC_DMSUB:
24865 case OPC_DMSUBU:
24866 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24867 break;
24868 default: /* Invalid */
24869 MIPS_INVAL("MASK DPAQ.W.QH");
24870 gen_reserved_instruction(ctx);
24871 break;
24873 break;
24874 case OPC_DINSV_DSP:
24875 op2 = MASK_INSV(ctx->opcode);
24876 switch (op2) {
24877 case OPC_DINSV:
24879 TCGv t0, t1;
24881 if (rt == 0) {
24882 break;
24884 check_dsp(ctx);
24886 t0 = tcg_temp_new();
24887 t1 = tcg_temp_new();
24889 gen_load_gpr(t0, rt);
24890 gen_load_gpr(t1, rs);
24892 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
24894 tcg_temp_free(t0);
24895 tcg_temp_free(t1);
24896 break;
24898 default: /* Invalid */
24899 MIPS_INVAL("MASK DINSV");
24900 gen_reserved_instruction(ctx);
24901 break;
24903 break;
24904 case OPC_SHLL_OB_DSP:
24905 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24906 break;
24907 #endif
24908 default: /* Invalid */
24909 MIPS_INVAL("special3_legacy");
24910 gen_reserved_instruction(ctx);
24911 break;
24916 #if defined(TARGET_MIPS64)
24918 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
24920 uint32_t opc = MASK_MMI0(ctx->opcode);
24922 switch (opc) {
24923 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
24924 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
24925 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
24926 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
24927 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
24928 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
24929 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
24930 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
24931 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
24932 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
24933 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
24934 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
24935 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
24936 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
24937 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
24938 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
24939 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
24940 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
24941 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
24942 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
24943 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
24944 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
24945 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
24946 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
24947 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
24948 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI0 */
24949 break;
24950 default:
24951 MIPS_INVAL("TX79 MMI class MMI0");
24952 gen_reserved_instruction(ctx);
24953 break;
24957 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
24959 uint32_t opc = MASK_MMI1(ctx->opcode);
24961 switch (opc) {
24962 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
24963 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
24964 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
24965 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
24966 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
24967 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
24968 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
24969 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
24970 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
24971 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
24972 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
24973 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
24974 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
24975 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
24976 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
24977 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
24978 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
24979 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
24980 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI1 */
24981 break;
24982 default:
24983 MIPS_INVAL("TX79 MMI class MMI1");
24984 gen_reserved_instruction(ctx);
24985 break;
24989 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
24991 uint32_t opc = MASK_MMI2(ctx->opcode);
24993 switch (opc) {
24994 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
24995 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
24996 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
24997 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
24998 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
24999 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
25000 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
25001 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
25002 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
25003 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
25004 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
25005 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
25006 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
25007 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
25008 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
25009 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
25010 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
25011 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
25012 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
25013 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
25014 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
25015 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI2 */
25016 break;
25017 case MMI_OPC_2_PCPYLD:
25018 gen_mmi_pcpyld(ctx);
25019 break;
25020 default:
25021 MIPS_INVAL("TX79 MMI class MMI2");
25022 gen_reserved_instruction(ctx);
25023 break;
25027 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
25029 uint32_t opc = MASK_MMI3(ctx->opcode);
25031 switch (opc) {
25032 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
25033 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
25034 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
25035 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
25036 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
25037 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
25038 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
25039 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
25040 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
25041 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
25042 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
25043 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI3 */
25044 break;
25045 case MMI_OPC_3_PCPYH:
25046 gen_mmi_pcpyh(ctx);
25047 break;
25048 case MMI_OPC_3_PCPYUD:
25049 gen_mmi_pcpyud(ctx);
25050 break;
25051 default:
25052 MIPS_INVAL("TX79 MMI class MMI3");
25053 gen_reserved_instruction(ctx);
25054 break;
25058 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
25060 uint32_t opc = MASK_MMI(ctx->opcode);
25061 int rs = extract32(ctx->opcode, 21, 5);
25062 int rt = extract32(ctx->opcode, 16, 5);
25063 int rd = extract32(ctx->opcode, 11, 5);
25065 switch (opc) {
25066 case MMI_OPC_CLASS_MMI0:
25067 decode_mmi0(env, ctx);
25068 break;
25069 case MMI_OPC_CLASS_MMI1:
25070 decode_mmi1(env, ctx);
25071 break;
25072 case MMI_OPC_CLASS_MMI2:
25073 decode_mmi2(env, ctx);
25074 break;
25075 case MMI_OPC_CLASS_MMI3:
25076 decode_mmi3(env, ctx);
25077 break;
25078 case MMI_OPC_MULT1:
25079 case MMI_OPC_MULTU1:
25080 case MMI_OPC_MADD:
25081 case MMI_OPC_MADDU:
25082 case MMI_OPC_MADD1:
25083 case MMI_OPC_MADDU1:
25084 gen_mul_txx9(ctx, opc, rd, rs, rt);
25085 break;
25086 case MMI_OPC_DIV1:
25087 case MMI_OPC_DIVU1:
25088 gen_div1_tx79(ctx, opc, rs, rt);
25089 break;
25090 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
25091 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
25092 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
25093 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
25094 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
25095 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
25096 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
25097 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
25098 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
25099 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI */
25100 break;
25101 default:
25102 MIPS_INVAL("TX79 MMI class");
25103 gen_reserved_instruction(ctx);
25104 break;
25108 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
25110 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_LQ */
25113 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
25115 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
25119 * The TX79-specific instruction Store Quadword
25121 * +--------+-------+-------+------------------------+
25122 * | 011111 | base | rt | offset | SQ
25123 * +--------+-------+-------+------------------------+
25124 * 6 5 5 16
25126 * has the same opcode as the Read Hardware Register instruction
25128 * +--------+-------+-------+-------+-------+--------+
25129 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
25130 * +--------+-------+-------+-------+-------+--------+
25131 * 6 5 5 5 5 6
25133 * that is required, trapped and emulated by the Linux kernel. However, all
25134 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
25135 * offset is odd. Therefore all valid SQ instructions can execute normally.
25136 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
25137 * between SQ and RDHWR, as the Linux kernel does.
25139 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
25141 int base = extract32(ctx->opcode, 21, 5);
25142 int rt = extract32(ctx->opcode, 16, 5);
25143 int offset = extract32(ctx->opcode, 0, 16);
25145 #ifdef CONFIG_USER_ONLY
25146 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
25147 uint32_t op2 = extract32(ctx->opcode, 6, 5);
25149 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
25150 int rd = extract32(ctx->opcode, 11, 5);
25152 gen_rdhwr(ctx, rt, rd, 0);
25153 return;
25155 #endif
25157 gen_mmi_sq(ctx, base, rt, offset);
25160 #endif
25162 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
25164 int rs, rt, rd, sa;
25165 uint32_t op1, op2;
25166 int16_t imm;
25168 rs = (ctx->opcode >> 21) & 0x1f;
25169 rt = (ctx->opcode >> 16) & 0x1f;
25170 rd = (ctx->opcode >> 11) & 0x1f;
25171 sa = (ctx->opcode >> 6) & 0x1f;
25172 imm = sextract32(ctx->opcode, 7, 9);
25174 op1 = MASK_SPECIAL3(ctx->opcode);
25177 * EVA loads and stores overlap Loongson 2E instructions decoded by
25178 * decode_opc_special3_legacy(), so be careful to allow their decoding when
25179 * EVA is absent.
25181 if (ctx->eva) {
25182 switch (op1) {
25183 case OPC_LWLE:
25184 case OPC_LWRE:
25185 case OPC_LBUE:
25186 case OPC_LHUE:
25187 case OPC_LBE:
25188 case OPC_LHE:
25189 case OPC_LLE:
25190 case OPC_LWE:
25191 check_cp0_enabled(ctx);
25192 gen_ld(ctx, op1, rt, rs, imm);
25193 return;
25194 case OPC_SWLE:
25195 case OPC_SWRE:
25196 case OPC_SBE:
25197 case OPC_SHE:
25198 case OPC_SWE:
25199 check_cp0_enabled(ctx);
25200 gen_st(ctx, op1, rt, rs, imm);
25201 return;
25202 case OPC_SCE:
25203 check_cp0_enabled(ctx);
25204 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
25205 return;
25206 case OPC_CACHEE:
25207 check_cp0_enabled(ctx);
25208 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25209 gen_cache_operation(ctx, rt, rs, imm);
25211 /* Treat as NOP. */
25212 return;
25213 case OPC_PREFE:
25214 check_cp0_enabled(ctx);
25215 /* Treat as NOP. */
25216 return;
25220 switch (op1) {
25221 case OPC_EXT:
25222 case OPC_INS:
25223 check_insn(ctx, ISA_MIPS_R2);
25224 gen_bitops(ctx, op1, rt, rs, sa, rd);
25225 break;
25226 case OPC_BSHFL:
25227 op2 = MASK_BSHFL(ctx->opcode);
25228 switch (op2) {
25229 case OPC_ALIGN:
25230 case OPC_ALIGN_1:
25231 case OPC_ALIGN_2:
25232 case OPC_ALIGN_3:
25233 case OPC_BITSWAP:
25234 check_insn(ctx, ISA_MIPS_R6);
25235 decode_opc_special3_r6(env, ctx);
25236 break;
25237 default:
25238 check_insn(ctx, ISA_MIPS_R2);
25239 gen_bshfl(ctx, op2, rt, rd);
25240 break;
25242 break;
25243 #if defined(TARGET_MIPS64)
25244 case OPC_DEXTM:
25245 case OPC_DEXTU:
25246 case OPC_DEXT:
25247 case OPC_DINSM:
25248 case OPC_DINSU:
25249 case OPC_DINS:
25250 check_insn(ctx, ISA_MIPS_R2);
25251 check_mips_64(ctx);
25252 gen_bitops(ctx, op1, rt, rs, sa, rd);
25253 break;
25254 case OPC_DBSHFL:
25255 op2 = MASK_DBSHFL(ctx->opcode);
25256 switch (op2) {
25257 case OPC_DALIGN:
25258 case OPC_DALIGN_1:
25259 case OPC_DALIGN_2:
25260 case OPC_DALIGN_3:
25261 case OPC_DALIGN_4:
25262 case OPC_DALIGN_5:
25263 case OPC_DALIGN_6:
25264 case OPC_DALIGN_7:
25265 case OPC_DBITSWAP:
25266 check_insn(ctx, ISA_MIPS_R6);
25267 decode_opc_special3_r6(env, ctx);
25268 break;
25269 default:
25270 check_insn(ctx, ISA_MIPS_R2);
25271 check_mips_64(ctx);
25272 op2 = MASK_DBSHFL(ctx->opcode);
25273 gen_bshfl(ctx, op2, rt, rd);
25274 break;
25276 break;
25277 #endif
25278 case OPC_RDHWR:
25279 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
25280 break;
25281 case OPC_FORK:
25282 check_mt(ctx);
25284 TCGv t0 = tcg_temp_new();
25285 TCGv t1 = tcg_temp_new();
25287 gen_load_gpr(t0, rt);
25288 gen_load_gpr(t1, rs);
25289 gen_helper_fork(t0, t1);
25290 tcg_temp_free(t0);
25291 tcg_temp_free(t1);
25293 break;
25294 case OPC_YIELD:
25295 check_mt(ctx);
25297 TCGv t0 = tcg_temp_new();
25299 gen_load_gpr(t0, rs);
25300 gen_helper_yield(t0, cpu_env, t0);
25301 gen_store_gpr(t0, rd);
25302 tcg_temp_free(t0);
25304 break;
25305 default:
25306 if (ctx->insn_flags & ISA_MIPS_R6) {
25307 decode_opc_special3_r6(env, ctx);
25308 } else {
25309 decode_opc_special3_legacy(env, ctx);
25314 static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
25316 int32_t offset;
25317 int rs, rt, rd, sa;
25318 uint32_t op, op1;
25319 int16_t imm;
25321 op = MASK_OP_MAJOR(ctx->opcode);
25322 rs = (ctx->opcode >> 21) & 0x1f;
25323 rt = (ctx->opcode >> 16) & 0x1f;
25324 rd = (ctx->opcode >> 11) & 0x1f;
25325 sa = (ctx->opcode >> 6) & 0x1f;
25326 imm = (int16_t)ctx->opcode;
25327 switch (op) {
25328 case OPC_SPECIAL:
25329 decode_opc_special(env, ctx);
25330 break;
25331 case OPC_SPECIAL2:
25332 #if defined(TARGET_MIPS64)
25333 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
25334 decode_mmi(env, ctx);
25335 break;
25337 #endif
25338 if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) {
25339 if (MASK_SPECIAL2(ctx->opcode) == OPC_MUL) {
25340 gen_arith(ctx, OPC_MUL, rd, rs, rt);
25341 } else {
25342 decode_ase_mxu(ctx, ctx->opcode);
25344 break;
25346 decode_opc_special2_legacy(env, ctx);
25347 break;
25348 case OPC_SPECIAL3:
25349 #if defined(TARGET_MIPS64)
25350 if (ctx->insn_flags & INSN_R5900) {
25351 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
25352 } else {
25353 decode_opc_special3(env, ctx);
25355 #else
25356 decode_opc_special3(env, ctx);
25357 #endif
25358 break;
25359 case OPC_REGIMM:
25360 op1 = MASK_REGIMM(ctx->opcode);
25361 switch (op1) {
25362 case OPC_BLTZL: /* REGIMM branches */
25363 case OPC_BGEZL:
25364 case OPC_BLTZALL:
25365 case OPC_BGEZALL:
25366 check_insn(ctx, ISA_MIPS2);
25367 check_insn_opc_removed(ctx, ISA_MIPS_R6);
25368 /* Fallthrough */
25369 case OPC_BLTZ:
25370 case OPC_BGEZ:
25371 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
25372 break;
25373 case OPC_BLTZAL:
25374 case OPC_BGEZAL:
25375 if (ctx->insn_flags & ISA_MIPS_R6) {
25376 if (rs == 0) {
25377 /* OPC_NAL, OPC_BAL */
25378 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
25379 } else {
25380 gen_reserved_instruction(ctx);
25382 } else {
25383 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
25385 break;
25386 case OPC_TGEI: /* REGIMM traps */
25387 case OPC_TGEIU:
25388 case OPC_TLTI:
25389 case OPC_TLTIU:
25390 case OPC_TEQI:
25392 case OPC_TNEI:
25393 check_insn(ctx, ISA_MIPS2);
25394 check_insn_opc_removed(ctx, ISA_MIPS_R6);
25395 gen_trap(ctx, op1, rs, -1, imm);
25396 break;
25397 case OPC_SIGRIE:
25398 check_insn(ctx, ISA_MIPS_R6);
25399 gen_reserved_instruction(ctx);
25400 break;
25401 case OPC_SYNCI:
25402 check_insn(ctx, ISA_MIPS_R2);
25404 * Break the TB to be able to sync copied instructions
25405 * immediately.
25407 ctx->base.is_jmp = DISAS_STOP;
25408 break;
25409 case OPC_BPOSGE32: /* MIPS DSP branch */
25410 #if defined(TARGET_MIPS64)
25411 case OPC_BPOSGE64:
25412 #endif
25413 check_dsp(ctx);
25414 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
25415 break;
25416 #if defined(TARGET_MIPS64)
25417 case OPC_DAHI:
25418 check_insn(ctx, ISA_MIPS_R6);
25419 check_mips_64(ctx);
25420 if (rs != 0) {
25421 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
25423 break;
25424 case OPC_DATI:
25425 check_insn(ctx, ISA_MIPS_R6);
25426 check_mips_64(ctx);
25427 if (rs != 0) {
25428 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
25430 break;
25431 #endif
25432 default: /* Invalid */
25433 MIPS_INVAL("regimm");
25434 gen_reserved_instruction(ctx);
25435 break;
25437 break;
25438 case OPC_CP0:
25439 check_cp0_enabled(ctx);
25440 op1 = MASK_CP0(ctx->opcode);
25441 switch (op1) {
25442 case OPC_MFC0:
25443 case OPC_MTC0:
25444 case OPC_MFTR:
25445 case OPC_MTTR:
25446 case OPC_MFHC0:
25447 case OPC_MTHC0:
25448 #if defined(TARGET_MIPS64)
25449 case OPC_DMFC0:
25450 case OPC_DMTC0:
25451 #endif
25452 #ifndef CONFIG_USER_ONLY
25453 gen_cp0(env, ctx, op1, rt, rd);
25454 #endif /* !CONFIG_USER_ONLY */
25455 break;
25456 case OPC_C0:
25457 case OPC_C0_1:
25458 case OPC_C0_2:
25459 case OPC_C0_3:
25460 case OPC_C0_4:
25461 case OPC_C0_5:
25462 case OPC_C0_6:
25463 case OPC_C0_7:
25464 case OPC_C0_8:
25465 case OPC_C0_9:
25466 case OPC_C0_A:
25467 case OPC_C0_B:
25468 case OPC_C0_C:
25469 case OPC_C0_D:
25470 case OPC_C0_E:
25471 case OPC_C0_F:
25472 #ifndef CONFIG_USER_ONLY
25473 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
25474 #endif /* !CONFIG_USER_ONLY */
25475 break;
25476 case OPC_MFMC0:
25477 #ifndef CONFIG_USER_ONLY
25479 uint32_t op2;
25480 TCGv t0 = tcg_temp_new();
25482 op2 = MASK_MFMC0(ctx->opcode);
25483 switch (op2) {
25484 case OPC_DMT:
25485 check_cp0_mt(ctx);
25486 gen_helper_dmt(t0);
25487 gen_store_gpr(t0, rt);
25488 break;
25489 case OPC_EMT:
25490 check_cp0_mt(ctx);
25491 gen_helper_emt(t0);
25492 gen_store_gpr(t0, rt);
25493 break;
25494 case OPC_DVPE:
25495 check_cp0_mt(ctx);
25496 gen_helper_dvpe(t0, cpu_env);
25497 gen_store_gpr(t0, rt);
25498 break;
25499 case OPC_EVPE:
25500 check_cp0_mt(ctx);
25501 gen_helper_evpe(t0, cpu_env);
25502 gen_store_gpr(t0, rt);
25503 break;
25504 case OPC_DVP:
25505 check_insn(ctx, ISA_MIPS_R6);
25506 if (ctx->vp) {
25507 gen_helper_dvp(t0, cpu_env);
25508 gen_store_gpr(t0, rt);
25510 break;
25511 case OPC_EVP:
25512 check_insn(ctx, ISA_MIPS_R6);
25513 if (ctx->vp) {
25514 gen_helper_evp(t0, cpu_env);
25515 gen_store_gpr(t0, rt);
25517 break;
25518 case OPC_DI:
25519 check_insn(ctx, ISA_MIPS_R2);
25520 save_cpu_state(ctx, 1);
25521 gen_helper_di(t0, cpu_env);
25522 gen_store_gpr(t0, rt);
25524 * Stop translation as we may have switched
25525 * the execution mode.
25527 ctx->base.is_jmp = DISAS_STOP;
25528 break;
25529 case OPC_EI:
25530 check_insn(ctx, ISA_MIPS_R2);
25531 save_cpu_state(ctx, 1);
25532 gen_helper_ei(t0, cpu_env);
25533 gen_store_gpr(t0, rt);
25535 * DISAS_STOP isn't sufficient, we need to ensure we break
25536 * out of translated code to check for pending interrupts.
25538 gen_save_pc(ctx->base.pc_next + 4);
25539 ctx->base.is_jmp = DISAS_EXIT;
25540 break;
25541 default: /* Invalid */
25542 MIPS_INVAL("mfmc0");
25543 gen_reserved_instruction(ctx);
25544 break;
25546 tcg_temp_free(t0);
25548 #endif /* !CONFIG_USER_ONLY */
25549 break;
25550 case OPC_RDPGPR:
25551 check_insn(ctx, ISA_MIPS_R2);
25552 gen_load_srsgpr(rt, rd);
25553 break;
25554 case OPC_WRPGPR:
25555 check_insn(ctx, ISA_MIPS_R2);
25556 gen_store_srsgpr(rt, rd);
25557 break;
25558 default:
25559 MIPS_INVAL("cp0");
25560 gen_reserved_instruction(ctx);
25561 break;
25563 break;
25564 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
25565 if (ctx->insn_flags & ISA_MIPS_R6) {
25566 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
25567 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25568 } else {
25569 /* OPC_ADDI */
25570 /* Arithmetic with immediate opcode */
25571 gen_arith_imm(ctx, op, rt, rs, imm);
25573 break;
25574 case OPC_ADDIU:
25575 gen_arith_imm(ctx, op, rt, rs, imm);
25576 break;
25577 case OPC_SLTI: /* Set on less than with immediate opcode */
25578 case OPC_SLTIU:
25579 gen_slt_imm(ctx, op, rt, rs, imm);
25580 break;
25581 case OPC_ANDI: /* Arithmetic with immediate opcode */
25582 case OPC_LUI: /* OPC_AUI */
25583 case OPC_ORI:
25584 case OPC_XORI:
25585 gen_logic_imm(ctx, op, rt, rs, imm);
25586 break;
25587 case OPC_J: /* Jump */
25588 case OPC_JAL:
25589 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
25590 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
25591 break;
25592 /* Branch */
25593 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
25594 if (ctx->insn_flags & ISA_MIPS_R6) {
25595 if (rt == 0) {
25596 gen_reserved_instruction(ctx);
25597 break;
25599 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
25600 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25601 } else {
25602 /* OPC_BLEZL */
25603 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25605 break;
25606 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
25607 if (ctx->insn_flags & ISA_MIPS_R6) {
25608 if (rt == 0) {
25609 gen_reserved_instruction(ctx);
25610 break;
25612 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
25613 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25614 } else {
25615 /* OPC_BGTZL */
25616 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25618 break;
25619 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
25620 if (rt == 0) {
25621 /* OPC_BLEZ */
25622 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25623 } else {
25624 check_insn(ctx, ISA_MIPS_R6);
25625 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
25626 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25628 break;
25629 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
25630 if (rt == 0) {
25631 /* OPC_BGTZ */
25632 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25633 } else {
25634 check_insn(ctx, ISA_MIPS_R6);
25635 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
25636 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25638 break;
25639 case OPC_BEQL:
25640 case OPC_BNEL:
25641 check_insn(ctx, ISA_MIPS2);
25642 check_insn_opc_removed(ctx, ISA_MIPS_R6);
25643 /* Fallthrough */
25644 case OPC_BEQ:
25645 case OPC_BNE:
25646 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25647 break;
25648 case OPC_LL: /* Load and stores */
25649 check_insn(ctx, ISA_MIPS2);
25650 if (ctx->insn_flags & INSN_R5900) {
25651 check_insn_opc_user_only(ctx, INSN_R5900);
25653 /* Fallthrough */
25654 case OPC_LWL:
25655 case OPC_LWR:
25656 case OPC_LB:
25657 case OPC_LH:
25658 case OPC_LW:
25659 case OPC_LWPC:
25660 case OPC_LBU:
25661 case OPC_LHU:
25662 gen_ld(ctx, op, rt, rs, imm);
25663 break;
25664 case OPC_SWL:
25665 case OPC_SWR:
25666 case OPC_SB:
25667 case OPC_SH:
25668 case OPC_SW:
25669 gen_st(ctx, op, rt, rs, imm);
25670 break;
25671 case OPC_SC:
25672 check_insn(ctx, ISA_MIPS2);
25673 if (ctx->insn_flags & INSN_R5900) {
25674 check_insn_opc_user_only(ctx, INSN_R5900);
25676 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
25677 break;
25678 case OPC_CACHE:
25679 check_cp0_enabled(ctx);
25680 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
25681 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25682 gen_cache_operation(ctx, rt, rs, imm);
25684 /* Treat as NOP. */
25685 break;
25686 case OPC_PREF:
25687 if (ctx->insn_flags & INSN_R5900) {
25688 /* Treat as NOP. */
25689 } else {
25690 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
25691 /* Treat as NOP. */
25693 break;
25695 /* Floating point (COP1). */
25696 case OPC_LWC1:
25697 case OPC_LDC1:
25698 case OPC_SWC1:
25699 case OPC_SDC1:
25700 gen_cop1_ldst(ctx, op, rt, rs, imm);
25701 break;
25703 case OPC_CP1:
25704 op1 = MASK_CP1(ctx->opcode);
25706 switch (op1) {
25707 case OPC_MFHC1:
25708 case OPC_MTHC1:
25709 check_cp1_enabled(ctx);
25710 check_insn(ctx, ISA_MIPS_R2);
25711 /* fall through */
25712 case OPC_MFC1:
25713 case OPC_CFC1:
25714 case OPC_MTC1:
25715 case OPC_CTC1:
25716 check_cp1_enabled(ctx);
25717 gen_cp1(ctx, op1, rt, rd);
25718 break;
25719 #if defined(TARGET_MIPS64)
25720 case OPC_DMFC1:
25721 case OPC_DMTC1:
25722 check_cp1_enabled(ctx);
25723 check_insn(ctx, ISA_MIPS3);
25724 check_mips_64(ctx);
25725 gen_cp1(ctx, op1, rt, rd);
25726 break;
25727 #endif
25728 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
25729 check_cp1_enabled(ctx);
25730 if (ctx->insn_flags & ISA_MIPS_R6) {
25731 /* OPC_BC1EQZ */
25732 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25733 rt, imm << 2, 4);
25734 } else {
25735 /* OPC_BC1ANY2 */
25736 check_cop1x(ctx);
25737 check_insn(ctx, ASE_MIPS3D);
25738 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25739 (rt >> 2) & 0x7, imm << 2);
25741 break;
25742 case OPC_BC1NEZ:
25743 check_cp1_enabled(ctx);
25744 check_insn(ctx, ISA_MIPS_R6);
25745 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25746 rt, imm << 2, 4);
25747 break;
25748 case OPC_BC1ANY4:
25749 check_cp1_enabled(ctx);
25750 check_insn_opc_removed(ctx, ISA_MIPS_R6);
25751 check_cop1x(ctx);
25752 check_insn(ctx, ASE_MIPS3D);
25753 /* fall through */
25754 case OPC_BC1:
25755 check_cp1_enabled(ctx);
25756 check_insn_opc_removed(ctx, ISA_MIPS_R6);
25757 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25758 (rt >> 2) & 0x7, imm << 2);
25759 break;
25760 case OPC_PS_FMT:
25761 check_ps(ctx);
25762 /* fall through */
25763 case OPC_S_FMT:
25764 case OPC_D_FMT:
25765 check_cp1_enabled(ctx);
25766 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25767 (imm >> 8) & 0x7);
25768 break;
25769 case OPC_W_FMT:
25770 case OPC_L_FMT:
25772 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
25773 check_cp1_enabled(ctx);
25774 if (ctx->insn_flags & ISA_MIPS_R6) {
25775 switch (r6_op) {
25776 case R6_OPC_CMP_AF_S:
25777 case R6_OPC_CMP_UN_S:
25778 case R6_OPC_CMP_EQ_S:
25779 case R6_OPC_CMP_UEQ_S:
25780 case R6_OPC_CMP_LT_S:
25781 case R6_OPC_CMP_ULT_S:
25782 case R6_OPC_CMP_LE_S:
25783 case R6_OPC_CMP_ULE_S:
25784 case R6_OPC_CMP_SAF_S:
25785 case R6_OPC_CMP_SUN_S:
25786 case R6_OPC_CMP_SEQ_S:
25787 case R6_OPC_CMP_SEUQ_S:
25788 case R6_OPC_CMP_SLT_S:
25789 case R6_OPC_CMP_SULT_S:
25790 case R6_OPC_CMP_SLE_S:
25791 case R6_OPC_CMP_SULE_S:
25792 case R6_OPC_CMP_OR_S:
25793 case R6_OPC_CMP_UNE_S:
25794 case R6_OPC_CMP_NE_S:
25795 case R6_OPC_CMP_SOR_S:
25796 case R6_OPC_CMP_SUNE_S:
25797 case R6_OPC_CMP_SNE_S:
25798 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25799 break;
25800 case R6_OPC_CMP_AF_D:
25801 case R6_OPC_CMP_UN_D:
25802 case R6_OPC_CMP_EQ_D:
25803 case R6_OPC_CMP_UEQ_D:
25804 case R6_OPC_CMP_LT_D:
25805 case R6_OPC_CMP_ULT_D:
25806 case R6_OPC_CMP_LE_D:
25807 case R6_OPC_CMP_ULE_D:
25808 case R6_OPC_CMP_SAF_D:
25809 case R6_OPC_CMP_SUN_D:
25810 case R6_OPC_CMP_SEQ_D:
25811 case R6_OPC_CMP_SEUQ_D:
25812 case R6_OPC_CMP_SLT_D:
25813 case R6_OPC_CMP_SULT_D:
25814 case R6_OPC_CMP_SLE_D:
25815 case R6_OPC_CMP_SULE_D:
25816 case R6_OPC_CMP_OR_D:
25817 case R6_OPC_CMP_UNE_D:
25818 case R6_OPC_CMP_NE_D:
25819 case R6_OPC_CMP_SOR_D:
25820 case R6_OPC_CMP_SUNE_D:
25821 case R6_OPC_CMP_SNE_D:
25822 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25823 break;
25824 default:
25825 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
25826 rt, rd, sa, (imm >> 8) & 0x7);
25828 break;
25830 } else {
25831 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25832 (imm >> 8) & 0x7);
25834 break;
25836 default:
25837 MIPS_INVAL("cp1");
25838 gen_reserved_instruction(ctx);
25839 break;
25841 break;
25843 /* Compact branches [R6] and COP2 [non-R6] */
25844 case OPC_BC: /* OPC_LWC2 */
25845 case OPC_BALC: /* OPC_SWC2 */
25846 if (ctx->insn_flags & ISA_MIPS_R6) {
25847 /* OPC_BC, OPC_BALC */
25848 gen_compute_compact_branch(ctx, op, 0, 0,
25849 sextract32(ctx->opcode << 2, 0, 28));
25850 } else if (ctx->insn_flags & ASE_LEXT) {
25851 gen_loongson_lswc2(ctx, rt, rs, rd);
25852 } else {
25853 /* OPC_LWC2, OPC_SWC2 */
25854 /* COP2: Not implemented. */
25855 generate_exception_err(ctx, EXCP_CpU, 2);
25857 break;
25858 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
25859 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
25860 if (ctx->insn_flags & ISA_MIPS_R6) {
25861 if (rs != 0) {
25862 /* OPC_BEQZC, OPC_BNEZC */
25863 gen_compute_compact_branch(ctx, op, rs, 0,
25864 sextract32(ctx->opcode << 2, 0, 23));
25865 } else {
25866 /* OPC_JIC, OPC_JIALC */
25867 gen_compute_compact_branch(ctx, op, 0, rt, imm);
25869 } else if (ctx->insn_flags & ASE_LEXT) {
25870 gen_loongson_lsdc2(ctx, rt, rs, rd);
25871 } else {
25872 /* OPC_LWC2, OPC_SWC2 */
25873 /* COP2: Not implemented. */
25874 generate_exception_err(ctx, EXCP_CpU, 2);
25876 break;
25877 case OPC_CP2:
25878 check_insn(ctx, ASE_LMMI);
25879 /* Note that these instructions use different fields. */
25880 gen_loongson_multimedia(ctx, sa, rd, rt);
25881 break;
25883 case OPC_CP3:
25884 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
25885 check_cp1_enabled(ctx);
25886 op1 = MASK_CP3(ctx->opcode);
25887 switch (op1) {
25888 case OPC_LUXC1:
25889 case OPC_SUXC1:
25890 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
25891 /* Fallthrough */
25892 case OPC_LWXC1:
25893 case OPC_LDXC1:
25894 case OPC_SWXC1:
25895 case OPC_SDXC1:
25896 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25897 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
25898 break;
25899 case OPC_PREFX:
25900 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25901 /* Treat as NOP. */
25902 break;
25903 case OPC_ALNV_PS:
25904 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
25905 /* Fallthrough */
25906 case OPC_MADD_S:
25907 case OPC_MADD_D:
25908 case OPC_MADD_PS:
25909 case OPC_MSUB_S:
25910 case OPC_MSUB_D:
25911 case OPC_MSUB_PS:
25912 case OPC_NMADD_S:
25913 case OPC_NMADD_D:
25914 case OPC_NMADD_PS:
25915 case OPC_NMSUB_S:
25916 case OPC_NMSUB_D:
25917 case OPC_NMSUB_PS:
25918 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25919 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
25920 break;
25921 default:
25922 MIPS_INVAL("cp3");
25923 gen_reserved_instruction(ctx);
25924 break;
25926 } else {
25927 generate_exception_err(ctx, EXCP_CpU, 1);
25929 break;
25931 #if defined(TARGET_MIPS64)
25932 /* MIPS64 opcodes */
25933 case OPC_LLD:
25934 if (ctx->insn_flags & INSN_R5900) {
25935 check_insn_opc_user_only(ctx, INSN_R5900);
25937 /* fall through */
25938 case OPC_LDL:
25939 case OPC_LDR:
25940 case OPC_LWU:
25941 case OPC_LD:
25942 check_insn(ctx, ISA_MIPS3);
25943 check_mips_64(ctx);
25944 gen_ld(ctx, op, rt, rs, imm);
25945 break;
25946 case OPC_SDL:
25947 case OPC_SDR:
25948 case OPC_SD:
25949 check_insn(ctx, ISA_MIPS3);
25950 check_mips_64(ctx);
25951 gen_st(ctx, op, rt, rs, imm);
25952 break;
25953 case OPC_SCD:
25954 check_insn(ctx, ISA_MIPS3);
25955 if (ctx->insn_flags & INSN_R5900) {
25956 check_insn_opc_user_only(ctx, INSN_R5900);
25958 check_mips_64(ctx);
25959 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
25960 break;
25961 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
25962 if (ctx->insn_flags & ISA_MIPS_R6) {
25963 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
25964 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25965 } else {
25966 /* OPC_DADDI */
25967 check_insn(ctx, ISA_MIPS3);
25968 check_mips_64(ctx);
25969 gen_arith_imm(ctx, op, rt, rs, imm);
25971 break;
25972 case OPC_DADDIU:
25973 check_insn(ctx, ISA_MIPS3);
25974 check_mips_64(ctx);
25975 gen_arith_imm(ctx, op, rt, rs, imm);
25976 break;
25977 #else
25978 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
25979 if (ctx->insn_flags & ISA_MIPS_R6) {
25980 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25981 } else {
25982 MIPS_INVAL("major opcode");
25983 gen_reserved_instruction(ctx);
25985 break;
25986 #endif
25987 case OPC_DAUI: /* OPC_JALX */
25988 if (ctx->insn_flags & ISA_MIPS_R6) {
25989 #if defined(TARGET_MIPS64)
25990 /* OPC_DAUI */
25991 check_mips_64(ctx);
25992 if (rs == 0) {
25993 generate_exception(ctx, EXCP_RI);
25994 } else if (rt != 0) {
25995 TCGv t0 = tcg_temp_new();
25996 gen_load_gpr(t0, rs);
25997 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
25998 tcg_temp_free(t0);
26000 #else
26001 gen_reserved_instruction(ctx);
26002 MIPS_INVAL("major opcode");
26003 #endif
26004 } else {
26005 /* OPC_JALX */
26006 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
26007 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
26008 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
26010 break;
26011 case OPC_MDMX: /* MMI_OPC_LQ */
26012 if (ctx->insn_flags & INSN_R5900) {
26013 #if defined(TARGET_MIPS64)
26014 gen_mmi_lq(env, ctx);
26015 #endif
26016 } else {
26017 /* MDMX: Not implemented. */
26019 break;
26020 case OPC_PCREL:
26021 check_insn(ctx, ISA_MIPS_R6);
26022 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
26023 break;
26024 default: /* Invalid */
26025 MIPS_INVAL("major opcode");
26026 return false;
26028 return true;
26031 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
26033 /* make sure instructions are on a word boundary */
26034 if (ctx->base.pc_next & 0x3) {
26035 env->CP0_BadVAddr = ctx->base.pc_next;
26036 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
26037 return;
26040 /* Handle blikely not taken case */
26041 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
26042 TCGLabel *l1 = gen_new_label();
26044 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
26045 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
26046 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
26047 gen_set_label(l1);
26050 /* Transition to the auto-generated decoder. */
26052 /* ISA extensions */
26053 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
26054 return;
26057 /* ISA (from latest to oldest) */
26058 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
26059 return;
26061 if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
26062 return;
26065 if (decode_opc_legacy(env, ctx)) {
26066 return;
26069 gen_reserved_instruction(ctx);
26072 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
26074 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26075 CPUMIPSState *env = cs->env_ptr;
26077 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
26078 ctx->saved_pc = -1;
26079 ctx->insn_flags = env->insn_flags;
26080 ctx->CP0_Config1 = env->CP0_Config1;
26081 ctx->CP0_Config2 = env->CP0_Config2;
26082 ctx->CP0_Config3 = env->CP0_Config3;
26083 ctx->CP0_Config5 = env->CP0_Config5;
26084 ctx->btarget = 0;
26085 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
26086 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
26087 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
26088 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
26089 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
26090 ctx->PAMask = env->PAMask;
26091 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
26092 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
26093 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
26094 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
26095 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
26096 /* Restore delay slot state from the tb context. */
26097 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
26098 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
26099 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
26100 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
26101 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
26102 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
26103 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
26104 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
26105 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
26106 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
26107 restore_cpu_state(env, ctx);
26108 #ifdef CONFIG_USER_ONLY
26109 ctx->mem_idx = MIPS_HFLAG_UM;
26110 #else
26111 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
26112 #endif
26113 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
26114 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
26116 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
26117 ctx->hflags);
26120 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
26124 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
26126 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26128 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
26129 ctx->btarget);
26132 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
26133 const CPUBreakpoint *bp)
26135 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26137 save_cpu_state(ctx, 1);
26138 ctx->base.is_jmp = DISAS_NORETURN;
26139 gen_helper_raise_exception_debug(cpu_env);
26141 * The address covered by the breakpoint must be included in
26142 * [tb->pc, tb->pc + tb->size) in order to for it to be
26143 * properly cleared -- thus we increment the PC here so that
26144 * the logic setting tb->size below does the right thing.
26146 ctx->base.pc_next += 4;
26147 return true;
26150 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
26152 CPUMIPSState *env = cs->env_ptr;
26153 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26154 int insn_bytes;
26155 int is_slot;
26157 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
26158 if (ctx->insn_flags & ISA_NANOMIPS32) {
26159 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
26160 insn_bytes = decode_nanomips_opc(env, ctx);
26161 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
26162 ctx->opcode = translator_ldl(env, ctx->base.pc_next);
26163 insn_bytes = 4;
26164 decode_opc(env, ctx);
26165 } else if (ctx->insn_flags & ASE_MICROMIPS) {
26166 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
26167 insn_bytes = decode_micromips_opc(env, ctx);
26168 } else if (ctx->insn_flags & ASE_MIPS16) {
26169 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
26170 insn_bytes = decode_mips16_opc(env, ctx);
26171 } else {
26172 gen_reserved_instruction(ctx);
26173 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
26174 return;
26177 if (ctx->hflags & MIPS_HFLAG_BMASK) {
26178 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
26179 MIPS_HFLAG_FBNSLOT))) {
26181 * Force to generate branch as there is neither delay nor
26182 * forbidden slot.
26184 is_slot = 1;
26186 if ((ctx->hflags & MIPS_HFLAG_M16) &&
26187 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
26189 * Force to generate branch as microMIPS R6 doesn't restrict
26190 * branches in the forbidden slot.
26192 is_slot = 1;
26195 if (is_slot) {
26196 gen_branch(ctx, insn_bytes);
26198 ctx->base.pc_next += insn_bytes;
26200 if (ctx->base.is_jmp != DISAS_NEXT) {
26201 return;
26204 * Execute a branch and its delay slot as a single instruction.
26205 * This is what GDB expects and is consistent with what the
26206 * hardware does (e.g. if a delay slot instruction faults, the
26207 * reported PC is the PC of the branch).
26209 if (ctx->base.singlestep_enabled &&
26210 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
26211 ctx->base.is_jmp = DISAS_TOO_MANY;
26213 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
26214 ctx->base.is_jmp = DISAS_TOO_MANY;
26218 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
26220 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26222 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
26223 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
26224 gen_helper_raise_exception_debug(cpu_env);
26225 } else {
26226 switch (ctx->base.is_jmp) {
26227 case DISAS_STOP:
26228 gen_save_pc(ctx->base.pc_next);
26229 tcg_gen_lookup_and_goto_ptr();
26230 break;
26231 case DISAS_NEXT:
26232 case DISAS_TOO_MANY:
26233 save_cpu_state(ctx, 0);
26234 gen_goto_tb(ctx, 0, ctx->base.pc_next);
26235 break;
26236 case DISAS_EXIT:
26237 tcg_gen_exit_tb(NULL, 0);
26238 break;
26239 case DISAS_NORETURN:
26240 break;
26241 default:
26242 g_assert_not_reached();
26247 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
26249 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
26250 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
26253 static const TranslatorOps mips_tr_ops = {
26254 .init_disas_context = mips_tr_init_disas_context,
26255 .tb_start = mips_tr_tb_start,
26256 .insn_start = mips_tr_insn_start,
26257 .breakpoint_check = mips_tr_breakpoint_check,
26258 .translate_insn = mips_tr_translate_insn,
26259 .tb_stop = mips_tr_tb_stop,
26260 .disas_log = mips_tr_disas_log,
26263 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
26265 DisasContext ctx;
26267 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
26270 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
26272 int i;
26273 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
26275 #define printfpr(fp) \
26276 do { \
26277 if (is_fpu64) \
26278 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
26279 " fd:%13g fs:%13g psu: %13g\n", \
26280 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
26281 (double)(fp)->fd, \
26282 (double)(fp)->fs[FP_ENDIAN_IDX], \
26283 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
26284 else { \
26285 fpr_t tmp; \
26286 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
26287 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
26288 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
26289 " fd:%13g fs:%13g psu:%13g\n", \
26290 tmp.w[FP_ENDIAN_IDX], tmp.d, \
26291 (double)tmp.fd, \
26292 (double)tmp.fs[FP_ENDIAN_IDX], \
26293 (double)tmp.fs[!FP_ENDIAN_IDX]); \
26295 } while (0)
26298 qemu_fprintf(f,
26299 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
26300 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
26301 get_float_exception_flags(&env->active_fpu.fp_status));
26302 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
26303 qemu_fprintf(f, "%3s: ", fregnames[i]);
26304 printfpr(&env->active_fpu.fpr[i]);
26307 #undef printfpr
26310 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
26312 MIPSCPU *cpu = MIPS_CPU(cs);
26313 CPUMIPSState *env = &cpu->env;
26314 int i;
26316 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
26317 " LO=0x" TARGET_FMT_lx " ds %04x "
26318 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
26319 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
26320 env->hflags, env->btarget, env->bcond);
26321 for (i = 0; i < 32; i++) {
26322 if ((i & 3) == 0) {
26323 qemu_fprintf(f, "GPR%02d:", i);
26325 qemu_fprintf(f, " %s " TARGET_FMT_lx,
26326 regnames[i], env->active_tc.gpr[i]);
26327 if ((i & 3) == 3) {
26328 qemu_fprintf(f, "\n");
26332 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
26333 TARGET_FMT_lx "\n",
26334 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
26335 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
26336 PRIx64 "\n",
26337 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
26338 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
26339 env->CP0_Config2, env->CP0_Config3);
26340 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
26341 env->CP0_Config4, env->CP0_Config5);
26342 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
26343 fpu_dump_state(env, f, flags);
26347 void mips_tcg_init(void)
26349 int i;
26351 cpu_gpr[0] = NULL;
26352 for (i = 1; i < 32; i++)
26353 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
26354 offsetof(CPUMIPSState,
26355 active_tc.gpr[i]),
26356 regnames[i]);
26357 #if defined(TARGET_MIPS64)
26358 cpu_gpr_hi[0] = NULL;
26360 for (unsigned i = 1; i < 32; i++) {
26361 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
26363 cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env,
26364 offsetof(CPUMIPSState,
26365 active_tc.gpr_hi[i]),
26366 rname);
26368 #endif /* !TARGET_MIPS64 */
26369 for (i = 0; i < 32; i++) {
26370 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
26372 fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
26374 msa_translate_init();
26375 cpu_PC = tcg_global_mem_new(cpu_env,
26376 offsetof(CPUMIPSState, active_tc.PC), "PC");
26377 for (i = 0; i < MIPS_DSP_ACC; i++) {
26378 cpu_HI[i] = tcg_global_mem_new(cpu_env,
26379 offsetof(CPUMIPSState, active_tc.HI[i]),
26380 regnames_HI[i]);
26381 cpu_LO[i] = tcg_global_mem_new(cpu_env,
26382 offsetof(CPUMIPSState, active_tc.LO[i]),
26383 regnames_LO[i]);
26385 cpu_dspctrl = tcg_global_mem_new(cpu_env,
26386 offsetof(CPUMIPSState,
26387 active_tc.DSPControl),
26388 "DSPControl");
26389 bcond = tcg_global_mem_new(cpu_env,
26390 offsetof(CPUMIPSState, bcond), "bcond");
26391 btarget = tcg_global_mem_new(cpu_env,
26392 offsetof(CPUMIPSState, btarget), "btarget");
26393 hflags = tcg_global_mem_new_i32(cpu_env,
26394 offsetof(CPUMIPSState, hflags), "hflags");
26396 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
26397 offsetof(CPUMIPSState, active_fpu.fcr0),
26398 "fcr0");
26399 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
26400 offsetof(CPUMIPSState, active_fpu.fcr31),
26401 "fcr31");
26402 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
26403 "lladdr");
26404 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
26405 "llval");
26407 if (TARGET_LONG_BITS == 32) {
26408 mxu_translate_init();
26412 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
26413 target_ulong *data)
26415 env->active_tc.PC = data[0];
26416 env->hflags &= ~MIPS_HFLAG_BMASK;
26417 env->hflags |= data[1];
26418 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
26419 case MIPS_HFLAG_BR:
26420 break;
26421 case MIPS_HFLAG_BC:
26422 case MIPS_HFLAG_BL:
26423 case MIPS_HFLAG_B:
26424 env->btarget = data[2];
26425 break;