target/mips: Move MUL opcode check from decode_mxu() to decode_legacy()
[qemu.git] / target / mips / translate.c
blob17cf608d0bd69ae4990ce44dbcd2b5510a1e5523
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,
1134 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1135 * ============================================
1138 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1139 * instructions set. It is designed to fit the needs of signal, graphical and
1140 * video processing applications. MXU instruction set is used in Xburst family
1141 * of microprocessors by Ingenic.
1143 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1144 * the control register.
1147 * The notation used in MXU assembler mnemonics
1148 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1150 * Register operands:
1152 * XRa, XRb, XRc, XRd - MXU registers
1153 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1155 * Non-register operands:
1157 * aptn1 - 1-bit accumulate add/subtract pattern
1158 * aptn2 - 2-bit accumulate add/subtract pattern
1159 * eptn2 - 2-bit execute add/subtract pattern
1160 * optn2 - 2-bit operand pattern
1161 * optn3 - 3-bit operand pattern
1162 * sft4 - 4-bit shift amount
1163 * strd2 - 2-bit stride amount
1165 * Prefixes:
1167 * Level of parallelism: Operand size:
1168 * S - single operation at a time 32 - word
1169 * D - two operations in parallel 16 - half word
1170 * Q - four operations in parallel 8 - byte
1172 * Operations:
1174 * ADD - Add or subtract
1175 * ADDC - Add with carry-in
1176 * ACC - Accumulate
1177 * ASUM - Sum together then accumulate (add or subtract)
1178 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1179 * AVG - Average between 2 operands
1180 * ABD - Absolute difference
1181 * ALN - Align data
1182 * AND - Logical bitwise 'and' operation
1183 * CPS - Copy sign
1184 * EXTR - Extract bits
1185 * I2M - Move from GPR register to MXU register
1186 * LDD - Load data from memory to XRF
1187 * LDI - Load data from memory to XRF (and increase the address base)
1188 * LUI - Load unsigned immediate
1189 * MUL - Multiply
1190 * MULU - Unsigned multiply
1191 * MADD - 64-bit operand add 32x32 product
1192 * MSUB - 64-bit operand subtract 32x32 product
1193 * MAC - Multiply and accumulate (add or subtract)
1194 * MAD - Multiply and add or subtract
1195 * MAX - Maximum between 2 operands
1196 * MIN - Minimum between 2 operands
1197 * M2I - Move from MXU register to GPR register
1198 * MOVZ - Move if zero
1199 * MOVN - Move if non-zero
1200 * NOR - Logical bitwise 'nor' operation
1201 * OR - Logical bitwise 'or' operation
1202 * STD - Store data from XRF to memory
1203 * SDI - Store data from XRF to memory (and increase the address base)
1204 * SLT - Set of less than comparison
1205 * SAD - Sum of absolute differences
1206 * SLL - Logical shift left
1207 * SLR - Logical shift right
1208 * SAR - Arithmetic shift right
1209 * SAT - Saturation
1210 * SFL - Shuffle
1211 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1212 * XOR - Logical bitwise 'exclusive or' operation
1214 * Suffixes:
1216 * E - Expand results
1217 * F - Fixed point multiplication
1218 * L - Low part result
1219 * R - Doing rounding
1220 * V - Variable instead of immediate
1221 * W - Combine above L and V
1224 * The list of MXU instructions grouped by functionality
1225 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1227 * Load/Store instructions Multiplication instructions
1228 * ----------------------- ---------------------------
1230 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1231 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1232 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1233 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1234 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1235 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1236 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1237 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1238 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1239 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1240 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1241 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1242 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1243 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1244 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1245 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1246 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1247 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1248 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1249 * S16SDI XRa, Rb, s10, eptn2
1250 * S8LDD XRa, Rb, s8, eptn3
1251 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1252 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1253 * S8SDI XRa, Rb, s8, eptn3
1254 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1255 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1256 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1257 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1258 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1259 * S32CPS XRa, XRb, XRc
1260 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1261 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1262 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1263 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1264 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1265 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1266 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1267 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1268 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1269 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1270 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1271 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1272 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1273 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1274 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1275 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1276 * Q8SLT XRa, XRb, XRc
1277 * Q8SLTU XRa, XRb, XRc
1278 * Q8MOVZ XRa, XRb, XRc Shift instructions
1279 * Q8MOVN XRa, XRb, XRc ------------------
1281 * D32SLL XRa, XRb, XRc, XRd, sft4
1282 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1283 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1284 * D32SARL XRa, XRb, XRc, sft4
1285 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1286 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1287 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1288 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1289 * Q16SLL XRa, XRb, XRc, XRd, sft4
1290 * Q16SLR XRa, XRb, XRc, XRd, sft4
1291 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1292 * ------------------------- Q16SLLV XRa, XRb, Rb
1293 * Q16SLRV XRa, XRb, Rb
1294 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1295 * S32ALN XRa, XRb, XRc, Rb
1296 * S32ALNI XRa, XRb, XRc, s3
1297 * S32LUI XRa, s8, optn3 Move instructions
1298 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1299 * S32EXTRV XRa, XRb, Rs, Rt
1300 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1301 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1304 * The opcode organization of MXU instructions
1305 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1307 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1308 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1309 * other bits up to the instruction level is as follows:
1311 * bits
1312 * 05..00
1314 * ┌─ 000000 ─ OPC_MXU_S32MADD
1315 * ├─ 000001 ─ OPC_MXU_S32MADDU
1316 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1317 * │
1318 * │ 20..18
1319 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1320 * │ ├─ 001 ─ OPC_MXU_S32MIN
1321 * │ ├─ 010 ─ OPC_MXU_D16MAX
1322 * │ ├─ 011 ─ OPC_MXU_D16MIN
1323 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1324 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1325 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1326 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1327 * ├─ 000100 ─ OPC_MXU_S32MSUB
1328 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1329 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1330 * │ ├─ 001 ─ OPC_MXU_D16SLT
1331 * │ ├─ 010 ─ OPC_MXU_D16AVG
1332 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1333 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1334 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1335 * │ └─ 111 ─ OPC_MXU_Q8ADD
1336 * │
1337 * │ 20..18
1338 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1339 * │ ├─ 010 ─ OPC_MXU_D16CPS
1340 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1341 * │ └─ 110 ─ OPC_MXU_Q16SAT
1342 * ├─ 001000 ─ OPC_MXU_D16MUL
1343 * │ 25..24
1344 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1345 * │ └─ 01 ─ OPC_MXU_D16MULE
1346 * ├─ 001010 ─ OPC_MXU_D16MAC
1347 * ├─ 001011 ─ OPC_MXU_D16MACF
1348 * ├─ 001100 ─ OPC_MXU_D16MADL
1349 * ├─ 001101 ─ OPC_MXU_S16MAD
1350 * ├─ 001110 ─ OPC_MXU_Q16ADD
1351 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1352 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1353 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1354 * │
1355 * │ 23
1356 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1357 * │ └─ 1 ─ OPC_MXU_S32STDR
1358 * │
1359 * │ 13..10
1360 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1361 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1362 * │
1363 * │ 13..10
1364 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1365 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1366 * │
1367 * │ 23
1368 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1369 * │ └─ 1 ─ OPC_MXU_S32LDIR
1370 * │
1371 * │ 23
1372 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1373 * │ └─ 1 ─ OPC_MXU_S32SDIR
1374 * │
1375 * │ 13..10
1376 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1377 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1378 * │
1379 * │ 13..10
1380 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1381 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1382 * ├─ 011000 ─ OPC_MXU_D32ADD
1383 * │ 23..22
1384 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1385 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1386 * │ └─ 10 ─ OPC_MXU_D32ASUM
1387 * ├─ 011010 ─ <not assigned>
1388 * │ 23..22
1389 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1390 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1391 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1392 * │
1393 * │ 23..22
1394 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1395 * │ ├─ 01 ─ OPC_MXU_D8SUM
1396 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1397 * ├─ 011110 ─ <not assigned>
1398 * ├─ 011111 ─ <not assigned>
1399 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1400 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1401 * ├─ 100010 ─ OPC_MXU_S8LDD
1402 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1403 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1404 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1405 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1406 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1407 * │
1408 * │ 20..18
1409 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1410 * │ ├─ 001 ─ OPC_MXU_S32ALN
1411 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1412 * │ ├─ 011 ─ OPC_MXU_S32LUI
1413 * │ ├─ 100 ─ OPC_MXU_S32NOR
1414 * │ ├─ 101 ─ OPC_MXU_S32AND
1415 * │ ├─ 110 ─ OPC_MXU_S32OR
1416 * │ └─ 111 ─ OPC_MXU_S32XOR
1417 * │
1418 * │ 7..5
1419 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1420 * │ ├─ 001 ─ OPC_MXU_LXH
1421 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1422 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1423 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1424 * ├─ 101100 ─ OPC_MXU_S16LDI
1425 * ├─ 101101 ─ OPC_MXU_S16SDI
1426 * ├─ 101110 ─ OPC_MXU_S32M2I
1427 * ├─ 101111 ─ OPC_MXU_S32I2M
1428 * ├─ 110000 ─ OPC_MXU_D32SLL
1429 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1430 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1431 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1432 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1433 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1434 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1435 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1436 * │
1437 * ├─ 110111 ─ OPC_MXU_Q16SAR
1438 * │ 23..22
1439 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1440 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1441 * │
1442 * │ 20..18
1443 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1444 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1445 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1446 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1447 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1448 * │ └─ 101 ─ OPC_MXU_S32MOVN
1449 * │
1450 * │ 23..22
1451 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1452 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1453 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1454 * ├─ 111100 ─ OPC_MXU_Q8MADL
1455 * ├─ 111101 ─ OPC_MXU_S32SFL
1456 * ├─ 111110 ─ OPC_MXU_Q8SAD
1457 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1460 * Compiled after:
1462 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1463 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1466 enum {
1467 OPC_MXU__POOL00 = 0x03,
1468 OPC_MXU_D16MUL = 0x08,
1469 OPC_MXU_D16MAC = 0x0A,
1470 OPC_MXU__POOL04 = 0x10,
1471 OPC_MXU_S8LDD = 0x22,
1472 OPC_MXU__POOL16 = 0x27,
1473 OPC_MXU_S32M2I = 0x2E,
1474 OPC_MXU_S32I2M = 0x2F,
1475 OPC_MXU__POOL19 = 0x38,
1480 * MXU pool 00
1482 enum {
1483 OPC_MXU_S32MAX = 0x00,
1484 OPC_MXU_S32MIN = 0x01,
1485 OPC_MXU_D16MAX = 0x02,
1486 OPC_MXU_D16MIN = 0x03,
1487 OPC_MXU_Q8MAX = 0x04,
1488 OPC_MXU_Q8MIN = 0x05,
1492 * MXU pool 04
1494 enum {
1495 OPC_MXU_S32LDD = 0x00,
1496 OPC_MXU_S32LDDR = 0x01,
1500 * MXU pool 16
1502 enum {
1503 OPC_MXU_S32ALNI = 0x02,
1504 OPC_MXU_S32NOR = 0x04,
1505 OPC_MXU_S32AND = 0x05,
1506 OPC_MXU_S32OR = 0x06,
1507 OPC_MXU_S32XOR = 0x07,
1511 * MXU pool 19
1513 enum {
1514 OPC_MXU_Q8MUL = 0x00,
1515 OPC_MXU_Q8MULSU = 0x01,
1519 * Overview of the TX79-specific instruction set
1520 * =============================================
1522 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
1523 * are only used by the specific quadword (128-bit) LQ/SQ load/store
1524 * instructions and certain multimedia instructions (MMIs). These MMIs
1525 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
1526 * or sixteen 8-bit paths.
1528 * Reference:
1530 * The Toshiba TX System RISC TX79 Core Architecture manual,
1531 * https://wiki.qemu.org/File:C790.pdf
1533 * Three-Operand Multiply and Multiply-Add (4 instructions)
1534 * --------------------------------------------------------
1535 * MADD [rd,] rs, rt Multiply/Add
1536 * MADDU [rd,] rs, rt Multiply/Add Unsigned
1537 * MULT [rd,] rs, rt Multiply (3-operand)
1538 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
1540 * Multiply Instructions for Pipeline 1 (10 instructions)
1541 * ------------------------------------------------------
1542 * MULT1 [rd,] rs, rt Multiply Pipeline 1
1543 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
1544 * DIV1 rs, rt Divide Pipeline 1
1545 * DIVU1 rs, rt Divide Unsigned Pipeline 1
1546 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
1547 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
1548 * MFHI1 rd Move From HI1 Register
1549 * MFLO1 rd Move From LO1 Register
1550 * MTHI1 rs Move To HI1 Register
1551 * MTLO1 rs Move To LO1 Register
1553 * Arithmetic (19 instructions)
1554 * ----------------------------
1555 * PADDB rd, rs, rt Parallel Add Byte
1556 * PSUBB rd, rs, rt Parallel Subtract Byte
1557 * PADDH rd, rs, rt Parallel Add Halfword
1558 * PSUBH rd, rs, rt Parallel Subtract Halfword
1559 * PADDW rd, rs, rt Parallel Add Word
1560 * PSUBW rd, rs, rt Parallel Subtract Word
1561 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
1562 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
1563 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
1564 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
1565 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
1566 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
1567 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
1568 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
1569 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
1570 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
1571 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
1572 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
1573 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
1575 * Min/Max (4 instructions)
1576 * ------------------------
1577 * PMAXH rd, rs, rt Parallel Maximum Halfword
1578 * PMINH rd, rs, rt Parallel Minimum Halfword
1579 * PMAXW rd, rs, rt Parallel Maximum Word
1580 * PMINW rd, rs, rt Parallel Minimum Word
1582 * Absolute (2 instructions)
1583 * -------------------------
1584 * PABSH rd, rt Parallel Absolute Halfword
1585 * PABSW rd, rt Parallel Absolute Word
1587 * Logical (4 instructions)
1588 * ------------------------
1589 * PAND rd, rs, rt Parallel AND
1590 * POR rd, rs, rt Parallel OR
1591 * PXOR rd, rs, rt Parallel XOR
1592 * PNOR rd, rs, rt Parallel NOR
1594 * Shift (9 instructions)
1595 * ----------------------
1596 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
1597 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
1598 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
1599 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
1600 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
1601 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
1602 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
1603 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
1604 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
1606 * Compare (6 instructions)
1607 * ------------------------
1608 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
1609 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
1610 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
1611 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
1612 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
1613 * PCEQW rd, rs, rt Parallel Compare for Equal Word
1615 * LZC (1 instruction)
1616 * -------------------
1617 * PLZCW rd, rs Parallel Leading Zero or One Count Word
1619 * Quadword Load and Store (2 instructions)
1620 * ----------------------------------------
1621 * LQ rt, offset(base) Load Quadword
1622 * SQ rt, offset(base) Store Quadword
1624 * Multiply and Divide (19 instructions)
1625 * -------------------------------------
1626 * PMULTW rd, rs, rt Parallel Multiply Word
1627 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
1628 * PDIVW rs, rt Parallel Divide Word
1629 * PDIVUW rs, rt Parallel Divide Unsigned Word
1630 * PMADDW rd, rs, rt Parallel Multiply-Add Word
1631 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
1632 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
1633 * PMULTH rd, rs, rt Parallel Multiply Halfword
1634 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
1635 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
1636 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
1637 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
1638 * PDIVBW rs, rt Parallel Divide Broadcast Word
1639 * PMFHI rd Parallel Move From HI Register
1640 * PMFLO rd Parallel Move From LO Register
1641 * PMTHI rs Parallel Move To HI Register
1642 * PMTLO rs Parallel Move To LO Register
1643 * PMFHL rd Parallel Move From HI/LO Register
1644 * PMTHL rs Parallel Move To HI/LO Register
1646 * Pack/Extend (11 instructions)
1647 * -----------------------------
1648 * PPAC5 rd, rt Parallel Pack to 5 bits
1649 * PPACB rd, rs, rt Parallel Pack to Byte
1650 * PPACH rd, rs, rt Parallel Pack to Halfword
1651 * PPACW rd, rs, rt Parallel Pack to Word
1652 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
1653 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
1654 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
1655 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
1656 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
1657 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
1658 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
1660 * Others (16 instructions)
1661 * ------------------------
1662 * PCPYH rd, rt Parallel Copy Halfword
1663 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
1664 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
1665 * PREVH rd, rt Parallel Reverse Halfword
1666 * PINTH rd, rs, rt Parallel Interleave Halfword
1667 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
1668 * PEXEH rd, rt Parallel Exchange Even Halfword
1669 * PEXCH rd, rt Parallel Exchange Center Halfword
1670 * PEXEW rd, rt Parallel Exchange Even Word
1671 * PEXCW rd, rt Parallel Exchange Center Word
1672 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
1673 * MFSA rd Move from Shift Amount Register
1674 * MTSA rs Move to Shift Amount Register
1675 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
1676 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
1677 * PROT3W rd, rt Parallel Rotate 3 Words
1679 * MMI (MultiMedia Instruction) encodings
1680 * ======================================
1682 * MMI instructions encoding table keys:
1684 * * This code is reserved for future use. An attempt to execute it
1685 * causes a Reserved Instruction exception.
1686 * % This code indicates an instruction class. The instruction word
1687 * must be further decoded by examining additional tables that show
1688 * the values for other instruction fields.
1689 * # This code is reserved for the unsupported instructions DMULT,
1690 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
1691 * to execute it causes a Reserved Instruction exception.
1693 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
1695 * 31 26 0
1696 * +--------+----------------------------------------+
1697 * | opcode | |
1698 * +--------+----------------------------------------+
1700 * opcode bits 28..26
1701 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1702 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1703 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1704 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
1705 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
1706 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
1707 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
1708 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
1709 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
1710 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
1711 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
1714 enum {
1715 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
1716 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
1717 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
1721 * MMI instructions with opcode field = MMI:
1723 * 31 26 5 0
1724 * +--------+-------------------------------+--------+
1725 * | MMI | |function|
1726 * +--------+-------------------------------+--------+
1728 * function bits 2..0
1729 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1730 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1731 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1732 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
1733 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
1734 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
1735 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
1736 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
1737 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
1738 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
1739 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
1742 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
1743 enum {
1744 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
1745 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
1746 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
1747 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
1748 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
1749 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
1750 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
1751 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
1752 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
1753 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
1754 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
1755 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
1756 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
1757 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
1758 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
1759 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
1760 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
1761 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
1762 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
1763 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
1764 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
1765 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
1766 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
1767 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
1768 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
1772 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
1774 * 31 26 10 6 5 0
1775 * +--------+----------------------+--------+--------+
1776 * | MMI | |function| MMI0 |
1777 * +--------+----------------------+--------+--------+
1779 * function bits 7..6
1780 * bits | 0 | 1 | 2 | 3
1781 * 10..8 | 00 | 01 | 10 | 11
1782 * -------+-------+-------+-------+-------
1783 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
1784 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
1785 * 2 010 | PADDB | PSUBB | PCGTB | *
1786 * 3 011 | * | * | * | *
1787 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
1788 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
1789 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
1790 * 7 111 | * | * | PEXT5 | PPAC5
1793 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
1794 enum {
1795 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
1796 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
1797 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
1798 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
1799 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
1800 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
1801 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
1802 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
1803 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
1804 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
1805 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
1806 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
1807 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
1808 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
1809 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
1810 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
1811 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
1812 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
1813 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
1814 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
1815 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
1816 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
1817 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
1818 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
1819 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
1823 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
1825 * 31 26 10 6 5 0
1826 * +--------+----------------------+--------+--------+
1827 * | MMI | |function| MMI1 |
1828 * +--------+----------------------+--------+--------+
1830 * function bits 7..6
1831 * bits | 0 | 1 | 2 | 3
1832 * 10..8 | 00 | 01 | 10 | 11
1833 * -------+-------+-------+-------+-------
1834 * 0 000 | * | PABSW | PCEQW | PMINW
1835 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
1836 * 2 010 | * | * | PCEQB | *
1837 * 3 011 | * | * | * | *
1838 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
1839 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
1840 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
1841 * 7 111 | * | * | * | *
1844 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
1845 enum {
1846 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
1847 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
1848 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
1849 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
1850 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
1851 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
1852 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
1853 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
1854 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
1855 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
1856 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
1857 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
1858 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
1859 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
1860 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
1861 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
1862 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
1863 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
1867 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
1869 * 31 26 10 6 5 0
1870 * +--------+----------------------+--------+--------+
1871 * | MMI | |function| MMI2 |
1872 * +--------+----------------------+--------+--------+
1874 * function bits 7..6
1875 * bits | 0 | 1 | 2 | 3
1876 * 10..8 | 00 | 01 | 10 | 11
1877 * -------+-------+-------+-------+-------
1878 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
1879 * 1 001 | PMSUBW| * | * | *
1880 * 2 010 | PMFHI | PMFLO | PINTH | *
1881 * 3 011 | PMULTW| PDIVW | PCPYLD| *
1882 * 4 100 | PMADDH| PHMADH| PAND | PXOR
1883 * 5 101 | PMSUBH| PHMSBH| * | *
1884 * 6 110 | * | * | PEXEH | PREVH
1885 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
1888 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
1889 enum {
1890 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
1891 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
1892 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
1893 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
1894 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
1895 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
1896 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
1897 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
1898 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
1899 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
1900 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
1901 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
1902 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
1903 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
1904 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
1905 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
1906 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
1907 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
1908 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
1909 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
1910 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
1911 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
1915 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
1917 * 31 26 10 6 5 0
1918 * +--------+----------------------+--------+--------+
1919 * | MMI | |function| MMI3 |
1920 * +--------+----------------------+--------+--------+
1922 * function bits 7..6
1923 * bits | 0 | 1 | 2 | 3
1924 * 10..8 | 00 | 01 | 10 | 11
1925 * -------+-------+-------+-------+-------
1926 * 0 000 |PMADDUW| * | * | PSRAVW
1927 * 1 001 | * | * | * | *
1928 * 2 010 | PMTHI | PMTLO | PINTEH| *
1929 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
1930 * 4 100 | * | * | POR | PNOR
1931 * 5 101 | * | * | * | *
1932 * 6 110 | * | * | PEXCH | PCPYH
1933 * 7 111 | * | * | PEXCW | *
1936 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
1937 enum {
1938 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
1939 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
1940 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
1941 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
1942 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
1943 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
1944 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
1945 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
1946 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
1947 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
1948 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
1949 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
1950 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
1953 /* global register indices */
1954 TCGv cpu_gpr[32], cpu_PC;
1956 * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[])
1957 * and the upper halves in cpu_gpr_hi[].
1959 TCGv_i64 cpu_gpr_hi[32];
1960 TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1961 static TCGv cpu_dspctrl, btarget;
1962 TCGv bcond;
1963 static TCGv cpu_lladdr, cpu_llval;
1964 static TCGv_i32 hflags;
1965 TCGv_i32 fpu_fcr0, fpu_fcr31;
1966 TCGv_i64 fpu_f64[32];
1968 #if !defined(TARGET_MIPS64)
1969 /* MXU registers */
1970 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
1971 static TCGv mxu_CR;
1972 #endif
1974 #include "exec/gen-icount.h"
1976 #define gen_helper_0e0i(name, arg) do { \
1977 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1978 gen_helper_##name(cpu_env, helper_tmp); \
1979 tcg_temp_free_i32(helper_tmp); \
1980 } while (0)
1982 #define gen_helper_0e1i(name, arg1, arg2) do { \
1983 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1984 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1985 tcg_temp_free_i32(helper_tmp); \
1986 } while (0)
1988 #define gen_helper_1e0i(name, ret, arg1) do { \
1989 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1990 gen_helper_##name(ret, cpu_env, helper_tmp); \
1991 tcg_temp_free_i32(helper_tmp); \
1992 } while (0)
1994 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1995 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1996 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1997 tcg_temp_free_i32(helper_tmp); \
1998 } while (0)
2000 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2001 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2002 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2003 tcg_temp_free_i32(helper_tmp); \
2004 } while (0)
2006 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2007 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2008 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2009 tcg_temp_free_i32(helper_tmp); \
2010 } while (0)
2012 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2013 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2014 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2015 tcg_temp_free_i32(helper_tmp); \
2016 } while (0)
2018 #define DISAS_STOP DISAS_TARGET_0
2019 #define DISAS_EXIT DISAS_TARGET_1
2021 static const char * const regnames[] = {
2022 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2023 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2024 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2025 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2028 static const char * const regnames_HI[] = {
2029 "HI0", "HI1", "HI2", "HI3",
2032 static const char * const regnames_LO[] = {
2033 "LO0", "LO1", "LO2", "LO3",
2036 static const char * const fregnames[] = {
2037 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2038 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2039 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2040 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2043 #if !defined(TARGET_MIPS64)
2044 static const char * const mxuregnames[] = {
2045 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2046 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2048 #endif
2050 /* General purpose registers moves. */
2051 void gen_load_gpr(TCGv t, int reg)
2053 if (reg == 0) {
2054 tcg_gen_movi_tl(t, 0);
2055 } else {
2056 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2060 void gen_store_gpr(TCGv t, int reg)
2062 if (reg != 0) {
2063 tcg_gen_mov_tl(cpu_gpr[reg], t);
2067 #if defined(TARGET_MIPS64)
2068 void gen_load_gpr_hi(TCGv_i64 t, int reg)
2070 if (reg == 0) {
2071 tcg_gen_movi_i64(t, 0);
2072 } else {
2073 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
2077 void gen_store_gpr_hi(TCGv_i64 t, int reg)
2079 if (reg != 0) {
2080 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
2083 #endif /* TARGET_MIPS64 */
2085 /* Moves to/from shadow registers. */
2086 static inline void gen_load_srsgpr(int from, int to)
2088 TCGv t0 = tcg_temp_new();
2090 if (from == 0) {
2091 tcg_gen_movi_tl(t0, 0);
2092 } else {
2093 TCGv_i32 t2 = tcg_temp_new_i32();
2094 TCGv_ptr addr = tcg_temp_new_ptr();
2096 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2097 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2098 tcg_gen_andi_i32(t2, t2, 0xf);
2099 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2100 tcg_gen_ext_i32_ptr(addr, t2);
2101 tcg_gen_add_ptr(addr, cpu_env, addr);
2103 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2104 tcg_temp_free_ptr(addr);
2105 tcg_temp_free_i32(t2);
2107 gen_store_gpr(t0, to);
2108 tcg_temp_free(t0);
2111 static inline void gen_store_srsgpr(int from, int to)
2113 if (to != 0) {
2114 TCGv t0 = tcg_temp_new();
2115 TCGv_i32 t2 = tcg_temp_new_i32();
2116 TCGv_ptr addr = tcg_temp_new_ptr();
2118 gen_load_gpr(t0, from);
2119 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2120 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2121 tcg_gen_andi_i32(t2, t2, 0xf);
2122 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2123 tcg_gen_ext_i32_ptr(addr, t2);
2124 tcg_gen_add_ptr(addr, cpu_env, addr);
2126 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2127 tcg_temp_free_ptr(addr);
2128 tcg_temp_free_i32(t2);
2129 tcg_temp_free(t0);
2133 #if !defined(TARGET_MIPS64)
2134 /* MXU General purpose registers moves. */
2135 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2137 if (reg == 0) {
2138 tcg_gen_movi_tl(t, 0);
2139 } else if (reg <= 15) {
2140 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2144 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2146 if (reg > 0 && reg <= 15) {
2147 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2151 /* MXU control register moves. */
2152 static inline void gen_load_mxu_cr(TCGv t)
2154 tcg_gen_mov_tl(t, mxu_CR);
2157 static inline void gen_store_mxu_cr(TCGv t)
2159 /* TODO: Add handling of RW rules for MXU_CR. */
2160 tcg_gen_mov_tl(mxu_CR, t);
2162 #endif
2165 /* Tests */
2166 static inline void gen_save_pc(target_ulong pc)
2168 tcg_gen_movi_tl(cpu_PC, pc);
2171 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2173 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2174 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2175 gen_save_pc(ctx->base.pc_next);
2176 ctx->saved_pc = ctx->base.pc_next;
2178 if (ctx->hflags != ctx->saved_hflags) {
2179 tcg_gen_movi_i32(hflags, ctx->hflags);
2180 ctx->saved_hflags = ctx->hflags;
2181 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2182 case MIPS_HFLAG_BR:
2183 break;
2184 case MIPS_HFLAG_BC:
2185 case MIPS_HFLAG_BL:
2186 case MIPS_HFLAG_B:
2187 tcg_gen_movi_tl(btarget, ctx->btarget);
2188 break;
2193 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2195 ctx->saved_hflags = ctx->hflags;
2196 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2197 case MIPS_HFLAG_BR:
2198 break;
2199 case MIPS_HFLAG_BC:
2200 case MIPS_HFLAG_BL:
2201 case MIPS_HFLAG_B:
2202 ctx->btarget = env->btarget;
2203 break;
2207 void generate_exception_err(DisasContext *ctx, int excp, int err)
2209 TCGv_i32 texcp = tcg_const_i32(excp);
2210 TCGv_i32 terr = tcg_const_i32(err);
2211 save_cpu_state(ctx, 1);
2212 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2213 tcg_temp_free_i32(terr);
2214 tcg_temp_free_i32(texcp);
2215 ctx->base.is_jmp = DISAS_NORETURN;
2218 void generate_exception(DisasContext *ctx, int excp)
2220 gen_helper_0e0i(raise_exception, excp);
2223 void generate_exception_end(DisasContext *ctx, int excp)
2225 generate_exception_err(ctx, excp, 0);
2228 void gen_reserved_instruction(DisasContext *ctx)
2230 generate_exception_end(ctx, EXCP_RI);
2233 /* Floating point register moves. */
2234 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2236 if (ctx->hflags & MIPS_HFLAG_FRE) {
2237 generate_exception(ctx, EXCP_RI);
2239 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2242 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2244 TCGv_i64 t64;
2245 if (ctx->hflags & MIPS_HFLAG_FRE) {
2246 generate_exception(ctx, EXCP_RI);
2248 t64 = tcg_temp_new_i64();
2249 tcg_gen_extu_i32_i64(t64, t);
2250 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2251 tcg_temp_free_i64(t64);
2254 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2256 if (ctx->hflags & MIPS_HFLAG_F64) {
2257 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2258 } else {
2259 gen_load_fpr32(ctx, t, reg | 1);
2263 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2265 if (ctx->hflags & MIPS_HFLAG_F64) {
2266 TCGv_i64 t64 = tcg_temp_new_i64();
2267 tcg_gen_extu_i32_i64(t64, t);
2268 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2269 tcg_temp_free_i64(t64);
2270 } else {
2271 gen_store_fpr32(ctx, t, reg | 1);
2275 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2277 if (ctx->hflags & MIPS_HFLAG_F64) {
2278 tcg_gen_mov_i64(t, fpu_f64[reg]);
2279 } else {
2280 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2284 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2286 if (ctx->hflags & MIPS_HFLAG_F64) {
2287 tcg_gen_mov_i64(fpu_f64[reg], t);
2288 } else {
2289 TCGv_i64 t0;
2290 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2291 t0 = tcg_temp_new_i64();
2292 tcg_gen_shri_i64(t0, t, 32);
2293 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2294 tcg_temp_free_i64(t0);
2298 int get_fp_bit(int cc)
2300 if (cc) {
2301 return 24 + cc;
2302 } else {
2303 return 23;
2307 /* Addresses computation */
2308 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2310 tcg_gen_add_tl(ret, arg0, arg1);
2312 #if defined(TARGET_MIPS64)
2313 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2314 tcg_gen_ext32s_i64(ret, ret);
2316 #endif
2319 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2320 target_long ofs)
2322 tcg_gen_addi_tl(ret, base, ofs);
2324 #if defined(TARGET_MIPS64)
2325 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2326 tcg_gen_ext32s_i64(ret, ret);
2328 #endif
2331 /* Addresses computation (translation time) */
2332 static target_long addr_add(DisasContext *ctx, target_long base,
2333 target_long offset)
2335 target_long sum = base + offset;
2337 #if defined(TARGET_MIPS64)
2338 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2339 sum = (int32_t)sum;
2341 #endif
2342 return sum;
2345 /* Sign-extract the low 32-bits to a target_long. */
2346 void gen_move_low32(TCGv ret, TCGv_i64 arg)
2348 #if defined(TARGET_MIPS64)
2349 tcg_gen_ext32s_i64(ret, arg);
2350 #else
2351 tcg_gen_extrl_i64_i32(ret, arg);
2352 #endif
2355 /* Sign-extract the high 32-bits to a target_long. */
2356 void gen_move_high32(TCGv ret, TCGv_i64 arg)
2358 #if defined(TARGET_MIPS64)
2359 tcg_gen_sari_i64(ret, arg, 32);
2360 #else
2361 tcg_gen_extrh_i64_i32(ret, arg);
2362 #endif
2365 void check_cp0_enabled(DisasContext *ctx)
2367 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2368 generate_exception_end(ctx, EXCP_CpU);
2372 void check_cp1_enabled(DisasContext *ctx)
2374 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2375 generate_exception_err(ctx, EXCP_CpU, 1);
2380 * Verify that the processor is running with COP1X instructions enabled.
2381 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2382 * opcode tables.
2384 void check_cop1x(DisasContext *ctx)
2386 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2387 gen_reserved_instruction(ctx);
2392 * Verify that the processor is running with 64-bit floating-point
2393 * operations enabled.
2395 void check_cp1_64bitmode(DisasContext *ctx)
2397 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2398 gen_reserved_instruction(ctx);
2403 * Verify if floating point register is valid; an operation is not defined
2404 * if bit 0 of any register specification is set and the FR bit in the
2405 * Status register equals zero, since the register numbers specify an
2406 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2407 * in the Status register equals one, both even and odd register numbers
2408 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2410 * Multiple 64 bit wide registers can be checked by calling
2411 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2413 void check_cp1_registers(DisasContext *ctx, int regs)
2415 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
2416 gen_reserved_instruction(ctx);
2421 * Verify that the processor is running with DSP instructions enabled.
2422 * This is enabled by CP0 Status register MX(24) bit.
2424 static inline void check_dsp(DisasContext *ctx)
2426 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2427 if (ctx->insn_flags & ASE_DSP) {
2428 generate_exception_end(ctx, EXCP_DSPDIS);
2429 } else {
2430 gen_reserved_instruction(ctx);
2435 static inline void check_dsp_r2(DisasContext *ctx)
2437 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2438 if (ctx->insn_flags & ASE_DSP) {
2439 generate_exception_end(ctx, EXCP_DSPDIS);
2440 } else {
2441 gen_reserved_instruction(ctx);
2446 static inline void check_dsp_r3(DisasContext *ctx)
2448 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2449 if (ctx->insn_flags & ASE_DSP) {
2450 generate_exception_end(ctx, EXCP_DSPDIS);
2451 } else {
2452 gen_reserved_instruction(ctx);
2458 * This code generates a "reserved instruction" exception if the
2459 * CPU does not support the instruction set corresponding to flags.
2461 void check_insn(DisasContext *ctx, uint64_t flags)
2463 if (unlikely(!(ctx->insn_flags & flags))) {
2464 gen_reserved_instruction(ctx);
2469 * This code generates a "reserved instruction" exception if the
2470 * CPU has corresponding flag set which indicates that the instruction
2471 * has been removed.
2473 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2475 if (unlikely(ctx->insn_flags & flags)) {
2476 gen_reserved_instruction(ctx);
2481 * The Linux kernel traps certain reserved instruction exceptions to
2482 * emulate the corresponding instructions. QEMU is the kernel in user
2483 * mode, so those traps are emulated by accepting the instructions.
2485 * A reserved instruction exception is generated for flagged CPUs if
2486 * QEMU runs in system mode.
2488 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
2490 #ifndef CONFIG_USER_ONLY
2491 check_insn_opc_removed(ctx, flags);
2492 #endif
2496 * This code generates a "reserved instruction" exception if the
2497 * CPU does not support 64-bit paired-single (PS) floating point data type.
2499 static inline void check_ps(DisasContext *ctx)
2501 if (unlikely(!ctx->ps)) {
2502 generate_exception(ctx, EXCP_RI);
2504 check_cp1_64bitmode(ctx);
2508 * This code generates a "reserved instruction" exception if cpu is not
2509 * 64-bit or 64-bit instructions are not enabled.
2511 void check_mips_64(DisasContext *ctx)
2513 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
2514 gen_reserved_instruction(ctx);
2518 #ifndef CONFIG_USER_ONLY
2519 static inline void check_mvh(DisasContext *ctx)
2521 if (unlikely(!ctx->mvh)) {
2522 generate_exception(ctx, EXCP_RI);
2525 #endif
2528 * This code generates a "reserved instruction" exception if the
2529 * Config5 XNP bit is set.
2531 static inline void check_xnp(DisasContext *ctx)
2533 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2534 gen_reserved_instruction(ctx);
2538 #ifndef CONFIG_USER_ONLY
2540 * This code generates a "reserved instruction" exception if the
2541 * Config3 PW bit is NOT set.
2543 static inline void check_pw(DisasContext *ctx)
2545 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2546 gen_reserved_instruction(ctx);
2549 #endif
2552 * This code generates a "reserved instruction" exception if the
2553 * Config3 MT bit is NOT set.
2555 static inline void check_mt(DisasContext *ctx)
2557 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2558 gen_reserved_instruction(ctx);
2562 #ifndef CONFIG_USER_ONLY
2564 * This code generates a "coprocessor unusable" exception if CP0 is not
2565 * available, and, if that is not the case, generates a "reserved instruction"
2566 * exception if the Config5 MT bit is NOT set. This is needed for availability
2567 * control of some of MT ASE instructions.
2569 static inline void check_cp0_mt(DisasContext *ctx)
2571 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2572 generate_exception_end(ctx, EXCP_CpU);
2573 } else {
2574 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2575 gen_reserved_instruction(ctx);
2579 #endif
2582 * This code generates a "reserved instruction" exception if the
2583 * Config5 NMS bit is set.
2585 static inline void check_nms(DisasContext *ctx)
2587 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2588 gen_reserved_instruction(ctx);
2593 * This code generates a "reserved instruction" exception if the
2594 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
2595 * Config2 TL, and Config5 L2C are unset.
2597 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
2599 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
2600 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
2601 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
2602 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
2603 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
2604 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
2605 gen_reserved_instruction(ctx);
2610 * This code generates a "reserved instruction" exception if the
2611 * Config5 EVA bit is NOT set.
2613 static inline void check_eva(DisasContext *ctx)
2615 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
2616 gen_reserved_instruction(ctx);
2622 * Define small wrappers for gen_load_fpr* so that we have a uniform
2623 * calling interface for 32 and 64-bit FPRs. No sense in changing
2624 * all callers for gen_load_fpr32 when we need the CTX parameter for
2625 * this one use.
2627 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
2628 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
2629 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
2630 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
2631 int ft, int fs, int cc) \
2633 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
2634 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
2635 switch (ifmt) { \
2636 case FMT_PS: \
2637 check_ps(ctx); \
2638 break; \
2639 case FMT_D: \
2640 if (abs) { \
2641 check_cop1x(ctx); \
2643 check_cp1_registers(ctx, fs | ft); \
2644 break; \
2645 case FMT_S: \
2646 if (abs) { \
2647 check_cop1x(ctx); \
2649 break; \
2651 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
2652 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
2653 switch (n) { \
2654 case 0: \
2655 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
2656 break; \
2657 case 1: \
2658 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
2659 break; \
2660 case 2: \
2661 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
2662 break; \
2663 case 3: \
2664 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
2665 break; \
2666 case 4: \
2667 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
2668 break; \
2669 case 5: \
2670 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
2671 break; \
2672 case 6: \
2673 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
2674 break; \
2675 case 7: \
2676 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
2677 break; \
2678 case 8: \
2679 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
2680 break; \
2681 case 9: \
2682 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
2683 break; \
2684 case 10: \
2685 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
2686 break; \
2687 case 11: \
2688 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
2689 break; \
2690 case 12: \
2691 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
2692 break; \
2693 case 13: \
2694 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
2695 break; \
2696 case 14: \
2697 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
2698 break; \
2699 case 15: \
2700 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
2701 break; \
2702 default: \
2703 abort(); \
2705 tcg_temp_free_i##bits(fp0); \
2706 tcg_temp_free_i##bits(fp1); \
2709 FOP_CONDS(, 0, d, FMT_D, 64)
2710 FOP_CONDS(abs, 1, d, FMT_D, 64)
2711 FOP_CONDS(, 0, s, FMT_S, 32)
2712 FOP_CONDS(abs, 1, s, FMT_S, 32)
2713 FOP_CONDS(, 0, ps, FMT_PS, 64)
2714 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
2715 #undef FOP_CONDS
2717 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
2718 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
2719 int ft, int fs, int fd) \
2721 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
2722 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
2723 if (ifmt == FMT_D) { \
2724 check_cp1_registers(ctx, fs | ft | fd); \
2726 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
2727 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
2728 switch (n) { \
2729 case 0: \
2730 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
2731 break; \
2732 case 1: \
2733 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
2734 break; \
2735 case 2: \
2736 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
2737 break; \
2738 case 3: \
2739 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
2740 break; \
2741 case 4: \
2742 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
2743 break; \
2744 case 5: \
2745 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
2746 break; \
2747 case 6: \
2748 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
2749 break; \
2750 case 7: \
2751 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
2752 break; \
2753 case 8: \
2754 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
2755 break; \
2756 case 9: \
2757 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
2758 break; \
2759 case 10: \
2760 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2761 break; \
2762 case 11: \
2763 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2764 break; \
2765 case 12: \
2766 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2767 break; \
2768 case 13: \
2769 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2770 break; \
2771 case 14: \
2772 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
2773 break; \
2774 case 15: \
2775 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
2776 break; \
2777 case 17: \
2778 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
2779 break; \
2780 case 18: \
2781 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2782 break; \
2783 case 19: \
2784 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2785 break; \
2786 case 25: \
2787 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2788 break; \
2789 case 26: \
2790 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2791 break; \
2792 case 27: \
2793 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2794 break; \
2795 default: \
2796 abort(); \
2798 STORE; \
2799 tcg_temp_free_i ## bits(fp0); \
2800 tcg_temp_free_i ## bits(fp1); \
2803 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2804 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2805 #undef FOP_CONDNS
2806 #undef gen_ldcmp_fpr32
2807 #undef gen_ldcmp_fpr64
2809 /* load/store instructions. */
2810 #ifdef CONFIG_USER_ONLY
2811 #define OP_LD_ATOMIC(insn, fname) \
2812 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2813 DisasContext *ctx) \
2815 TCGv t0 = tcg_temp_new(); \
2816 tcg_gen_mov_tl(t0, arg1); \
2817 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2818 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2819 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2820 tcg_temp_free(t0); \
2822 #else
2823 #define OP_LD_ATOMIC(insn, fname) \
2824 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2825 DisasContext *ctx) \
2827 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2829 #endif
2830 OP_LD_ATOMIC(ll, ld32s);
2831 #if defined(TARGET_MIPS64)
2832 OP_LD_ATOMIC(lld, ld64);
2833 #endif
2834 #undef OP_LD_ATOMIC
2836 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
2838 if (base == 0) {
2839 tcg_gen_movi_tl(addr, offset);
2840 } else if (offset == 0) {
2841 gen_load_gpr(addr, base);
2842 } else {
2843 tcg_gen_movi_tl(addr, offset);
2844 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2848 static target_ulong pc_relative_pc(DisasContext *ctx)
2850 target_ulong pc = ctx->base.pc_next;
2852 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2853 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2855 pc -= branch_bytes;
2858 pc &= ~(target_ulong)3;
2859 return pc;
2862 /* Load */
2863 static void gen_ld(DisasContext *ctx, uint32_t opc,
2864 int rt, int base, int offset)
2866 TCGv t0, t1, t2;
2867 int mem_idx = ctx->mem_idx;
2869 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
2870 INSN_LOONGSON3A)) {
2872 * Loongson CPU uses a load to zero register for prefetch.
2873 * We emulate it as a NOP. On other CPU we must perform the
2874 * actual memory access.
2876 return;
2879 t0 = tcg_temp_new();
2880 gen_base_offset_addr(ctx, t0, base, offset);
2882 switch (opc) {
2883 #if defined(TARGET_MIPS64)
2884 case OPC_LWU:
2885 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
2886 ctx->default_tcg_memop_mask);
2887 gen_store_gpr(t0, rt);
2888 break;
2889 case OPC_LD:
2890 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
2891 ctx->default_tcg_memop_mask);
2892 gen_store_gpr(t0, rt);
2893 break;
2894 case OPC_LLD:
2895 case R6_OPC_LLD:
2896 op_ld_lld(t0, t0, mem_idx, ctx);
2897 gen_store_gpr(t0, rt);
2898 break;
2899 case OPC_LDL:
2900 t1 = tcg_temp_new();
2902 * Do a byte access to possibly trigger a page
2903 * fault with the unaligned address.
2905 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2906 tcg_gen_andi_tl(t1, t0, 7);
2907 #ifndef TARGET_WORDS_BIGENDIAN
2908 tcg_gen_xori_tl(t1, t1, 7);
2909 #endif
2910 tcg_gen_shli_tl(t1, t1, 3);
2911 tcg_gen_andi_tl(t0, t0, ~7);
2912 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2913 tcg_gen_shl_tl(t0, t0, t1);
2914 t2 = tcg_const_tl(-1);
2915 tcg_gen_shl_tl(t2, t2, t1);
2916 gen_load_gpr(t1, rt);
2917 tcg_gen_andc_tl(t1, t1, t2);
2918 tcg_temp_free(t2);
2919 tcg_gen_or_tl(t0, t0, t1);
2920 tcg_temp_free(t1);
2921 gen_store_gpr(t0, rt);
2922 break;
2923 case OPC_LDR:
2924 t1 = tcg_temp_new();
2926 * Do a byte access to possibly trigger a page
2927 * fault with the unaligned address.
2929 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2930 tcg_gen_andi_tl(t1, t0, 7);
2931 #ifdef TARGET_WORDS_BIGENDIAN
2932 tcg_gen_xori_tl(t1, t1, 7);
2933 #endif
2934 tcg_gen_shli_tl(t1, t1, 3);
2935 tcg_gen_andi_tl(t0, t0, ~7);
2936 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2937 tcg_gen_shr_tl(t0, t0, t1);
2938 tcg_gen_xori_tl(t1, t1, 63);
2939 t2 = tcg_const_tl(0xfffffffffffffffeull);
2940 tcg_gen_shl_tl(t2, t2, t1);
2941 gen_load_gpr(t1, rt);
2942 tcg_gen_and_tl(t1, t1, t2);
2943 tcg_temp_free(t2);
2944 tcg_gen_or_tl(t0, t0, t1);
2945 tcg_temp_free(t1);
2946 gen_store_gpr(t0, rt);
2947 break;
2948 case OPC_LDPC:
2949 t1 = tcg_const_tl(pc_relative_pc(ctx));
2950 gen_op_addr_add(ctx, t0, t0, t1);
2951 tcg_temp_free(t1);
2952 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2953 gen_store_gpr(t0, rt);
2954 break;
2955 #endif
2956 case OPC_LWPC:
2957 t1 = tcg_const_tl(pc_relative_pc(ctx));
2958 gen_op_addr_add(ctx, t0, t0, t1);
2959 tcg_temp_free(t1);
2960 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
2961 gen_store_gpr(t0, rt);
2962 break;
2963 case OPC_LWE:
2964 mem_idx = MIPS_HFLAG_UM;
2965 /* fall through */
2966 case OPC_LW:
2967 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
2968 ctx->default_tcg_memop_mask);
2969 gen_store_gpr(t0, rt);
2970 break;
2971 case OPC_LHE:
2972 mem_idx = MIPS_HFLAG_UM;
2973 /* fall through */
2974 case OPC_LH:
2975 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
2976 ctx->default_tcg_memop_mask);
2977 gen_store_gpr(t0, rt);
2978 break;
2979 case OPC_LHUE:
2980 mem_idx = MIPS_HFLAG_UM;
2981 /* fall through */
2982 case OPC_LHU:
2983 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
2984 ctx->default_tcg_memop_mask);
2985 gen_store_gpr(t0, rt);
2986 break;
2987 case OPC_LBE:
2988 mem_idx = MIPS_HFLAG_UM;
2989 /* fall through */
2990 case OPC_LB:
2991 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2992 gen_store_gpr(t0, rt);
2993 break;
2994 case OPC_LBUE:
2995 mem_idx = MIPS_HFLAG_UM;
2996 /* fall through */
2997 case OPC_LBU:
2998 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2999 gen_store_gpr(t0, rt);
3000 break;
3001 case OPC_LWLE:
3002 mem_idx = MIPS_HFLAG_UM;
3003 /* fall through */
3004 case OPC_LWL:
3005 t1 = tcg_temp_new();
3007 * Do a byte access to possibly trigger a page
3008 * fault with the unaligned address.
3010 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3011 tcg_gen_andi_tl(t1, t0, 3);
3012 #ifndef TARGET_WORDS_BIGENDIAN
3013 tcg_gen_xori_tl(t1, t1, 3);
3014 #endif
3015 tcg_gen_shli_tl(t1, t1, 3);
3016 tcg_gen_andi_tl(t0, t0, ~3);
3017 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3018 tcg_gen_shl_tl(t0, t0, t1);
3019 t2 = tcg_const_tl(-1);
3020 tcg_gen_shl_tl(t2, t2, t1);
3021 gen_load_gpr(t1, rt);
3022 tcg_gen_andc_tl(t1, t1, t2);
3023 tcg_temp_free(t2);
3024 tcg_gen_or_tl(t0, t0, t1);
3025 tcg_temp_free(t1);
3026 tcg_gen_ext32s_tl(t0, t0);
3027 gen_store_gpr(t0, rt);
3028 break;
3029 case OPC_LWRE:
3030 mem_idx = MIPS_HFLAG_UM;
3031 /* fall through */
3032 case OPC_LWR:
3033 t1 = tcg_temp_new();
3035 * Do a byte access to possibly trigger a page
3036 * fault with the unaligned address.
3038 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3039 tcg_gen_andi_tl(t1, t0, 3);
3040 #ifdef TARGET_WORDS_BIGENDIAN
3041 tcg_gen_xori_tl(t1, t1, 3);
3042 #endif
3043 tcg_gen_shli_tl(t1, t1, 3);
3044 tcg_gen_andi_tl(t0, t0, ~3);
3045 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3046 tcg_gen_shr_tl(t0, t0, t1);
3047 tcg_gen_xori_tl(t1, t1, 31);
3048 t2 = tcg_const_tl(0xfffffffeull);
3049 tcg_gen_shl_tl(t2, t2, t1);
3050 gen_load_gpr(t1, rt);
3051 tcg_gen_and_tl(t1, t1, t2);
3052 tcg_temp_free(t2);
3053 tcg_gen_or_tl(t0, t0, t1);
3054 tcg_temp_free(t1);
3055 tcg_gen_ext32s_tl(t0, t0);
3056 gen_store_gpr(t0, rt);
3057 break;
3058 case OPC_LLE:
3059 mem_idx = MIPS_HFLAG_UM;
3060 /* fall through */
3061 case OPC_LL:
3062 case R6_OPC_LL:
3063 op_ld_ll(t0, t0, mem_idx, ctx);
3064 gen_store_gpr(t0, rt);
3065 break;
3067 tcg_temp_free(t0);
3070 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3071 uint32_t reg1, uint32_t reg2)
3073 TCGv taddr = tcg_temp_new();
3074 TCGv_i64 tval = tcg_temp_new_i64();
3075 TCGv tmp1 = tcg_temp_new();
3076 TCGv tmp2 = tcg_temp_new();
3078 gen_base_offset_addr(ctx, taddr, base, offset);
3079 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3080 #ifdef TARGET_WORDS_BIGENDIAN
3081 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3082 #else
3083 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3084 #endif
3085 gen_store_gpr(tmp1, reg1);
3086 tcg_temp_free(tmp1);
3087 gen_store_gpr(tmp2, reg2);
3088 tcg_temp_free(tmp2);
3089 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3090 tcg_temp_free_i64(tval);
3091 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3092 tcg_temp_free(taddr);
3095 /* Store */
3096 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3097 int base, int offset)
3099 TCGv t0 = tcg_temp_new();
3100 TCGv t1 = tcg_temp_new();
3101 int mem_idx = ctx->mem_idx;
3103 gen_base_offset_addr(ctx, t0, base, offset);
3104 gen_load_gpr(t1, rt);
3105 switch (opc) {
3106 #if defined(TARGET_MIPS64)
3107 case OPC_SD:
3108 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3109 ctx->default_tcg_memop_mask);
3110 break;
3111 case OPC_SDL:
3112 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3113 break;
3114 case OPC_SDR:
3115 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3116 break;
3117 #endif
3118 case OPC_SWE:
3119 mem_idx = MIPS_HFLAG_UM;
3120 /* fall through */
3121 case OPC_SW:
3122 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3123 ctx->default_tcg_memop_mask);
3124 break;
3125 case OPC_SHE:
3126 mem_idx = MIPS_HFLAG_UM;
3127 /* fall through */
3128 case OPC_SH:
3129 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3130 ctx->default_tcg_memop_mask);
3131 break;
3132 case OPC_SBE:
3133 mem_idx = MIPS_HFLAG_UM;
3134 /* fall through */
3135 case OPC_SB:
3136 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3137 break;
3138 case OPC_SWLE:
3139 mem_idx = MIPS_HFLAG_UM;
3140 /* fall through */
3141 case OPC_SWL:
3142 gen_helper_0e2i(swl, t1, t0, mem_idx);
3143 break;
3144 case OPC_SWRE:
3145 mem_idx = MIPS_HFLAG_UM;
3146 /* fall through */
3147 case OPC_SWR:
3148 gen_helper_0e2i(swr, t1, t0, mem_idx);
3149 break;
3151 tcg_temp_free(t0);
3152 tcg_temp_free(t1);
3156 /* Store conditional */
3157 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3158 MemOp tcg_mo, bool eva)
3160 TCGv addr, t0, val;
3161 TCGLabel *l1 = gen_new_label();
3162 TCGLabel *done = gen_new_label();
3164 t0 = tcg_temp_new();
3165 addr = tcg_temp_new();
3166 /* compare the address against that of the preceding LL */
3167 gen_base_offset_addr(ctx, addr, base, offset);
3168 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3169 tcg_temp_free(addr);
3170 tcg_gen_movi_tl(t0, 0);
3171 gen_store_gpr(t0, rt);
3172 tcg_gen_br(done);
3174 gen_set_label(l1);
3175 /* generate cmpxchg */
3176 val = tcg_temp_new();
3177 gen_load_gpr(val, rt);
3178 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3179 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3180 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3181 gen_store_gpr(t0, rt);
3182 tcg_temp_free(val);
3184 gen_set_label(done);
3185 tcg_temp_free(t0);
3189 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3190 uint32_t reg1, uint32_t reg2, bool eva)
3192 TCGv taddr = tcg_temp_local_new();
3193 TCGv lladdr = tcg_temp_local_new();
3194 TCGv_i64 tval = tcg_temp_new_i64();
3195 TCGv_i64 llval = tcg_temp_new_i64();
3196 TCGv_i64 val = tcg_temp_new_i64();
3197 TCGv tmp1 = tcg_temp_new();
3198 TCGv tmp2 = tcg_temp_new();
3199 TCGLabel *lab_fail = gen_new_label();
3200 TCGLabel *lab_done = gen_new_label();
3202 gen_base_offset_addr(ctx, taddr, base, offset);
3204 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3205 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3207 gen_load_gpr(tmp1, reg1);
3208 gen_load_gpr(tmp2, reg2);
3210 #ifdef TARGET_WORDS_BIGENDIAN
3211 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3212 #else
3213 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3214 #endif
3216 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3217 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3218 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3219 if (reg1 != 0) {
3220 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3222 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3224 gen_set_label(lab_fail);
3226 if (reg1 != 0) {
3227 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3229 gen_set_label(lab_done);
3230 tcg_gen_movi_tl(lladdr, -1);
3231 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3234 /* Load and store */
3235 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3236 TCGv t0)
3239 * Don't do NOP if destination is zero: we must perform the actual
3240 * memory access.
3242 switch (opc) {
3243 case OPC_LWC1:
3245 TCGv_i32 fp0 = tcg_temp_new_i32();
3246 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3247 ctx->default_tcg_memop_mask);
3248 gen_store_fpr32(ctx, fp0, ft);
3249 tcg_temp_free_i32(fp0);
3251 break;
3252 case OPC_SWC1:
3254 TCGv_i32 fp0 = tcg_temp_new_i32();
3255 gen_load_fpr32(ctx, fp0, ft);
3256 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3257 ctx->default_tcg_memop_mask);
3258 tcg_temp_free_i32(fp0);
3260 break;
3261 case OPC_LDC1:
3263 TCGv_i64 fp0 = tcg_temp_new_i64();
3264 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3265 ctx->default_tcg_memop_mask);
3266 gen_store_fpr64(ctx, fp0, ft);
3267 tcg_temp_free_i64(fp0);
3269 break;
3270 case OPC_SDC1:
3272 TCGv_i64 fp0 = tcg_temp_new_i64();
3273 gen_load_fpr64(ctx, fp0, ft);
3274 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3275 ctx->default_tcg_memop_mask);
3276 tcg_temp_free_i64(fp0);
3278 break;
3279 default:
3280 MIPS_INVAL("flt_ldst");
3281 gen_reserved_instruction(ctx);
3282 break;
3286 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3287 int rs, int16_t imm)
3289 TCGv t0 = tcg_temp_new();
3291 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3292 check_cp1_enabled(ctx);
3293 switch (op) {
3294 case OPC_LDC1:
3295 case OPC_SDC1:
3296 check_insn(ctx, ISA_MIPS2);
3297 /* Fallthrough */
3298 default:
3299 gen_base_offset_addr(ctx, t0, rs, imm);
3300 gen_flt_ldst(ctx, op, rt, t0);
3302 } else {
3303 generate_exception_err(ctx, EXCP_CpU, 1);
3305 tcg_temp_free(t0);
3308 /* Arithmetic with immediate operand */
3309 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3310 int rt, int rs, int imm)
3312 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3314 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3316 * If no destination, treat it as a NOP.
3317 * For addi, we must generate the overflow exception when needed.
3319 return;
3321 switch (opc) {
3322 case OPC_ADDI:
3324 TCGv t0 = tcg_temp_local_new();
3325 TCGv t1 = tcg_temp_new();
3326 TCGv t2 = tcg_temp_new();
3327 TCGLabel *l1 = gen_new_label();
3329 gen_load_gpr(t1, rs);
3330 tcg_gen_addi_tl(t0, t1, uimm);
3331 tcg_gen_ext32s_tl(t0, t0);
3333 tcg_gen_xori_tl(t1, t1, ~uimm);
3334 tcg_gen_xori_tl(t2, t0, uimm);
3335 tcg_gen_and_tl(t1, t1, t2);
3336 tcg_temp_free(t2);
3337 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3338 tcg_temp_free(t1);
3339 /* operands of same sign, result different sign */
3340 generate_exception(ctx, EXCP_OVERFLOW);
3341 gen_set_label(l1);
3342 tcg_gen_ext32s_tl(t0, t0);
3343 gen_store_gpr(t0, rt);
3344 tcg_temp_free(t0);
3346 break;
3347 case OPC_ADDIU:
3348 if (rs != 0) {
3349 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3350 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3351 } else {
3352 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3354 break;
3355 #if defined(TARGET_MIPS64)
3356 case OPC_DADDI:
3358 TCGv t0 = tcg_temp_local_new();
3359 TCGv t1 = tcg_temp_new();
3360 TCGv t2 = tcg_temp_new();
3361 TCGLabel *l1 = gen_new_label();
3363 gen_load_gpr(t1, rs);
3364 tcg_gen_addi_tl(t0, t1, uimm);
3366 tcg_gen_xori_tl(t1, t1, ~uimm);
3367 tcg_gen_xori_tl(t2, t0, uimm);
3368 tcg_gen_and_tl(t1, t1, t2);
3369 tcg_temp_free(t2);
3370 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3371 tcg_temp_free(t1);
3372 /* operands of same sign, result different sign */
3373 generate_exception(ctx, EXCP_OVERFLOW);
3374 gen_set_label(l1);
3375 gen_store_gpr(t0, rt);
3376 tcg_temp_free(t0);
3378 break;
3379 case OPC_DADDIU:
3380 if (rs != 0) {
3381 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3382 } else {
3383 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3385 break;
3386 #endif
3390 /* Logic with immediate operand */
3391 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3392 int rt, int rs, int16_t imm)
3394 target_ulong uimm;
3396 if (rt == 0) {
3397 /* If no destination, treat it as a NOP. */
3398 return;
3400 uimm = (uint16_t)imm;
3401 switch (opc) {
3402 case OPC_ANDI:
3403 if (likely(rs != 0)) {
3404 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3405 } else {
3406 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3408 break;
3409 case OPC_ORI:
3410 if (rs != 0) {
3411 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3412 } else {
3413 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3415 break;
3416 case OPC_XORI:
3417 if (likely(rs != 0)) {
3418 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3419 } else {
3420 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3422 break;
3423 case OPC_LUI:
3424 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
3425 /* OPC_AUI */
3426 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3427 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3428 } else {
3429 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3431 break;
3433 default:
3434 break;
3438 /* Set on less than with immediate operand */
3439 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3440 int rt, int rs, int16_t imm)
3442 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3443 TCGv t0;
3445 if (rt == 0) {
3446 /* If no destination, treat it as a NOP. */
3447 return;
3449 t0 = tcg_temp_new();
3450 gen_load_gpr(t0, rs);
3451 switch (opc) {
3452 case OPC_SLTI:
3453 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3454 break;
3455 case OPC_SLTIU:
3456 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3457 break;
3459 tcg_temp_free(t0);
3462 /* Shifts with immediate operand */
3463 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3464 int rt, int rs, int16_t imm)
3466 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3467 TCGv t0;
3469 if (rt == 0) {
3470 /* If no destination, treat it as a NOP. */
3471 return;
3474 t0 = tcg_temp_new();
3475 gen_load_gpr(t0, rs);
3476 switch (opc) {
3477 case OPC_SLL:
3478 tcg_gen_shli_tl(t0, t0, uimm);
3479 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3480 break;
3481 case OPC_SRA:
3482 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3483 break;
3484 case OPC_SRL:
3485 if (uimm != 0) {
3486 tcg_gen_ext32u_tl(t0, t0);
3487 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3488 } else {
3489 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3491 break;
3492 case OPC_ROTR:
3493 if (uimm != 0) {
3494 TCGv_i32 t1 = tcg_temp_new_i32();
3496 tcg_gen_trunc_tl_i32(t1, t0);
3497 tcg_gen_rotri_i32(t1, t1, uimm);
3498 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3499 tcg_temp_free_i32(t1);
3500 } else {
3501 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3503 break;
3504 #if defined(TARGET_MIPS64)
3505 case OPC_DSLL:
3506 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3507 break;
3508 case OPC_DSRA:
3509 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3510 break;
3511 case OPC_DSRL:
3512 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3513 break;
3514 case OPC_DROTR:
3515 if (uimm != 0) {
3516 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3517 } else {
3518 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3520 break;
3521 case OPC_DSLL32:
3522 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3523 break;
3524 case OPC_DSRA32:
3525 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3526 break;
3527 case OPC_DSRL32:
3528 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3529 break;
3530 case OPC_DROTR32:
3531 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3532 break;
3533 #endif
3535 tcg_temp_free(t0);
3538 /* Arithmetic */
3539 static void gen_arith(DisasContext *ctx, uint32_t opc,
3540 int rd, int rs, int rt)
3542 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3543 && opc != OPC_DADD && opc != OPC_DSUB) {
3545 * If no destination, treat it as a NOP.
3546 * For add & sub, we must generate the overflow exception when needed.
3548 return;
3551 switch (opc) {
3552 case OPC_ADD:
3554 TCGv t0 = tcg_temp_local_new();
3555 TCGv t1 = tcg_temp_new();
3556 TCGv t2 = tcg_temp_new();
3557 TCGLabel *l1 = gen_new_label();
3559 gen_load_gpr(t1, rs);
3560 gen_load_gpr(t2, rt);
3561 tcg_gen_add_tl(t0, t1, t2);
3562 tcg_gen_ext32s_tl(t0, t0);
3563 tcg_gen_xor_tl(t1, t1, t2);
3564 tcg_gen_xor_tl(t2, t0, t2);
3565 tcg_gen_andc_tl(t1, t2, t1);
3566 tcg_temp_free(t2);
3567 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3568 tcg_temp_free(t1);
3569 /* operands of same sign, result different sign */
3570 generate_exception(ctx, EXCP_OVERFLOW);
3571 gen_set_label(l1);
3572 gen_store_gpr(t0, rd);
3573 tcg_temp_free(t0);
3575 break;
3576 case OPC_ADDU:
3577 if (rs != 0 && rt != 0) {
3578 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3579 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3580 } else if (rs == 0 && rt != 0) {
3581 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3582 } else if (rs != 0 && rt == 0) {
3583 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3584 } else {
3585 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3587 break;
3588 case OPC_SUB:
3590 TCGv t0 = tcg_temp_local_new();
3591 TCGv t1 = tcg_temp_new();
3592 TCGv t2 = tcg_temp_new();
3593 TCGLabel *l1 = gen_new_label();
3595 gen_load_gpr(t1, rs);
3596 gen_load_gpr(t2, rt);
3597 tcg_gen_sub_tl(t0, t1, t2);
3598 tcg_gen_ext32s_tl(t0, t0);
3599 tcg_gen_xor_tl(t2, t1, t2);
3600 tcg_gen_xor_tl(t1, t0, t1);
3601 tcg_gen_and_tl(t1, t1, t2);
3602 tcg_temp_free(t2);
3603 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3604 tcg_temp_free(t1);
3606 * operands of different sign, first operand and the result
3607 * of different sign
3609 generate_exception(ctx, EXCP_OVERFLOW);
3610 gen_set_label(l1);
3611 gen_store_gpr(t0, rd);
3612 tcg_temp_free(t0);
3614 break;
3615 case OPC_SUBU:
3616 if (rs != 0 && rt != 0) {
3617 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3618 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3619 } else if (rs == 0 && rt != 0) {
3620 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3621 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3622 } else if (rs != 0 && rt == 0) {
3623 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3624 } else {
3625 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3627 break;
3628 #if defined(TARGET_MIPS64)
3629 case OPC_DADD:
3631 TCGv t0 = tcg_temp_local_new();
3632 TCGv t1 = tcg_temp_new();
3633 TCGv t2 = tcg_temp_new();
3634 TCGLabel *l1 = gen_new_label();
3636 gen_load_gpr(t1, rs);
3637 gen_load_gpr(t2, rt);
3638 tcg_gen_add_tl(t0, t1, t2);
3639 tcg_gen_xor_tl(t1, t1, t2);
3640 tcg_gen_xor_tl(t2, t0, t2);
3641 tcg_gen_andc_tl(t1, t2, t1);
3642 tcg_temp_free(t2);
3643 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3644 tcg_temp_free(t1);
3645 /* operands of same sign, result different sign */
3646 generate_exception(ctx, EXCP_OVERFLOW);
3647 gen_set_label(l1);
3648 gen_store_gpr(t0, rd);
3649 tcg_temp_free(t0);
3651 break;
3652 case OPC_DADDU:
3653 if (rs != 0 && rt != 0) {
3654 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3655 } else if (rs == 0 && rt != 0) {
3656 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3657 } else if (rs != 0 && rt == 0) {
3658 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3659 } else {
3660 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3662 break;
3663 case OPC_DSUB:
3665 TCGv t0 = tcg_temp_local_new();
3666 TCGv t1 = tcg_temp_new();
3667 TCGv t2 = tcg_temp_new();
3668 TCGLabel *l1 = gen_new_label();
3670 gen_load_gpr(t1, rs);
3671 gen_load_gpr(t2, rt);
3672 tcg_gen_sub_tl(t0, t1, t2);
3673 tcg_gen_xor_tl(t2, t1, t2);
3674 tcg_gen_xor_tl(t1, t0, t1);
3675 tcg_gen_and_tl(t1, t1, t2);
3676 tcg_temp_free(t2);
3677 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3678 tcg_temp_free(t1);
3680 * Operands of different sign, first operand and result different
3681 * sign.
3683 generate_exception(ctx, EXCP_OVERFLOW);
3684 gen_set_label(l1);
3685 gen_store_gpr(t0, rd);
3686 tcg_temp_free(t0);
3688 break;
3689 case OPC_DSUBU:
3690 if (rs != 0 && rt != 0) {
3691 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3692 } else if (rs == 0 && rt != 0) {
3693 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3694 } else if (rs != 0 && rt == 0) {
3695 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3696 } else {
3697 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3699 break;
3700 #endif
3701 case OPC_MUL:
3702 if (likely(rs != 0 && rt != 0)) {
3703 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3704 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3705 } else {
3706 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3708 break;
3712 /* Conditional move */
3713 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
3714 int rd, int rs, int rt)
3716 TCGv t0, t1, t2;
3718 if (rd == 0) {
3719 /* If no destination, treat it as a NOP. */
3720 return;
3723 t0 = tcg_temp_new();
3724 gen_load_gpr(t0, rt);
3725 t1 = tcg_const_tl(0);
3726 t2 = tcg_temp_new();
3727 gen_load_gpr(t2, rs);
3728 switch (opc) {
3729 case OPC_MOVN:
3730 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3731 break;
3732 case OPC_MOVZ:
3733 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3734 break;
3735 case OPC_SELNEZ:
3736 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
3737 break;
3738 case OPC_SELEQZ:
3739 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
3740 break;
3742 tcg_temp_free(t2);
3743 tcg_temp_free(t1);
3744 tcg_temp_free(t0);
3747 /* Logic */
3748 static void gen_logic(DisasContext *ctx, uint32_t opc,
3749 int rd, int rs, int rt)
3751 if (rd == 0) {
3752 /* If no destination, treat it as a NOP. */
3753 return;
3756 switch (opc) {
3757 case OPC_AND:
3758 if (likely(rs != 0 && rt != 0)) {
3759 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3760 } else {
3761 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3763 break;
3764 case OPC_NOR:
3765 if (rs != 0 && rt != 0) {
3766 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3767 } else if (rs == 0 && rt != 0) {
3768 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
3769 } else if (rs != 0 && rt == 0) {
3770 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
3771 } else {
3772 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
3774 break;
3775 case OPC_OR:
3776 if (likely(rs != 0 && rt != 0)) {
3777 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3778 } else if (rs == 0 && rt != 0) {
3779 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3780 } else if (rs != 0 && rt == 0) {
3781 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3782 } else {
3783 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3785 break;
3786 case OPC_XOR:
3787 if (likely(rs != 0 && rt != 0)) {
3788 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3789 } else if (rs == 0 && rt != 0) {
3790 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3791 } else if (rs != 0 && rt == 0) {
3792 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3793 } else {
3794 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3796 break;
3800 /* Set on lower than */
3801 static void gen_slt(DisasContext *ctx, uint32_t opc,
3802 int rd, int rs, int rt)
3804 TCGv t0, t1;
3806 if (rd == 0) {
3807 /* If no destination, treat it as a NOP. */
3808 return;
3811 t0 = tcg_temp_new();
3812 t1 = tcg_temp_new();
3813 gen_load_gpr(t0, rs);
3814 gen_load_gpr(t1, rt);
3815 switch (opc) {
3816 case OPC_SLT:
3817 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3818 break;
3819 case OPC_SLTU:
3820 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3821 break;
3823 tcg_temp_free(t0);
3824 tcg_temp_free(t1);
3827 /* Shifts */
3828 static void gen_shift(DisasContext *ctx, uint32_t opc,
3829 int rd, int rs, int rt)
3831 TCGv t0, t1;
3833 if (rd == 0) {
3835 * If no destination, treat it as a NOP.
3836 * For add & sub, we must generate the overflow exception when needed.
3838 return;
3841 t0 = tcg_temp_new();
3842 t1 = tcg_temp_new();
3843 gen_load_gpr(t0, rs);
3844 gen_load_gpr(t1, rt);
3845 switch (opc) {
3846 case OPC_SLLV:
3847 tcg_gen_andi_tl(t0, t0, 0x1f);
3848 tcg_gen_shl_tl(t0, t1, t0);
3849 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3850 break;
3851 case OPC_SRAV:
3852 tcg_gen_andi_tl(t0, t0, 0x1f);
3853 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3854 break;
3855 case OPC_SRLV:
3856 tcg_gen_ext32u_tl(t1, t1);
3857 tcg_gen_andi_tl(t0, t0, 0x1f);
3858 tcg_gen_shr_tl(t0, t1, t0);
3859 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3860 break;
3861 case OPC_ROTRV:
3863 TCGv_i32 t2 = tcg_temp_new_i32();
3864 TCGv_i32 t3 = tcg_temp_new_i32();
3866 tcg_gen_trunc_tl_i32(t2, t0);
3867 tcg_gen_trunc_tl_i32(t3, t1);
3868 tcg_gen_andi_i32(t2, t2, 0x1f);
3869 tcg_gen_rotr_i32(t2, t3, t2);
3870 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3871 tcg_temp_free_i32(t2);
3872 tcg_temp_free_i32(t3);
3874 break;
3875 #if defined(TARGET_MIPS64)
3876 case OPC_DSLLV:
3877 tcg_gen_andi_tl(t0, t0, 0x3f);
3878 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3879 break;
3880 case OPC_DSRAV:
3881 tcg_gen_andi_tl(t0, t0, 0x3f);
3882 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3883 break;
3884 case OPC_DSRLV:
3885 tcg_gen_andi_tl(t0, t0, 0x3f);
3886 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3887 break;
3888 case OPC_DROTRV:
3889 tcg_gen_andi_tl(t0, t0, 0x3f);
3890 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3891 break;
3892 #endif
3894 tcg_temp_free(t0);
3895 tcg_temp_free(t1);
3898 #if defined(TARGET_MIPS64)
3899 /* Copy GPR to and from TX79 HI1/LO1 register. */
3900 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
3902 switch (opc) {
3903 case MMI_OPC_MFHI1:
3904 gen_store_gpr(cpu_HI[1], reg);
3905 break;
3906 case MMI_OPC_MFLO1:
3907 gen_store_gpr(cpu_LO[1], reg);
3908 break;
3909 case MMI_OPC_MTHI1:
3910 gen_load_gpr(cpu_HI[1], reg);
3911 break;
3912 case MMI_OPC_MTLO1:
3913 gen_load_gpr(cpu_LO[1], reg);
3914 break;
3915 default:
3916 MIPS_INVAL("mfthilo1 TX79");
3917 gen_reserved_instruction(ctx);
3918 break;
3921 #endif
3923 /* Arithmetic on HI/LO registers */
3924 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3926 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3927 /* Treat as NOP. */
3928 return;
3931 if (acc != 0) {
3932 check_dsp(ctx);
3935 switch (opc) {
3936 case OPC_MFHI:
3937 #if defined(TARGET_MIPS64)
3938 if (acc != 0) {
3939 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3940 } else
3941 #endif
3943 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3945 break;
3946 case OPC_MFLO:
3947 #if defined(TARGET_MIPS64)
3948 if (acc != 0) {
3949 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3950 } else
3951 #endif
3953 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3955 break;
3956 case OPC_MTHI:
3957 if (reg != 0) {
3958 #if defined(TARGET_MIPS64)
3959 if (acc != 0) {
3960 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3961 } else
3962 #endif
3964 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3966 } else {
3967 tcg_gen_movi_tl(cpu_HI[acc], 0);
3969 break;
3970 case OPC_MTLO:
3971 if (reg != 0) {
3972 #if defined(TARGET_MIPS64)
3973 if (acc != 0) {
3974 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3975 } else
3976 #endif
3978 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3980 } else {
3981 tcg_gen_movi_tl(cpu_LO[acc], 0);
3983 break;
3987 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3988 MemOp memop)
3990 TCGv t0 = tcg_const_tl(addr);
3991 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3992 gen_store_gpr(t0, reg);
3993 tcg_temp_free(t0);
3996 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3997 int rs)
3999 target_long offset;
4000 target_long addr;
4002 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4003 case OPC_ADDIUPC:
4004 if (rs != 0) {
4005 offset = sextract32(ctx->opcode << 2, 0, 21);
4006 addr = addr_add(ctx, pc, offset);
4007 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4009 break;
4010 case R6_OPC_LWPC:
4011 offset = sextract32(ctx->opcode << 2, 0, 21);
4012 addr = addr_add(ctx, pc, offset);
4013 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4014 break;
4015 #if defined(TARGET_MIPS64)
4016 case OPC_LWUPC:
4017 check_mips_64(ctx);
4018 offset = sextract32(ctx->opcode << 2, 0, 21);
4019 addr = addr_add(ctx, pc, offset);
4020 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4021 break;
4022 #endif
4023 default:
4024 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4025 case OPC_AUIPC:
4026 if (rs != 0) {
4027 offset = sextract32(ctx->opcode, 0, 16) << 16;
4028 addr = addr_add(ctx, pc, offset);
4029 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4031 break;
4032 case OPC_ALUIPC:
4033 if (rs != 0) {
4034 offset = sextract32(ctx->opcode, 0, 16) << 16;
4035 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4036 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4038 break;
4039 #if defined(TARGET_MIPS64)
4040 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4041 case R6_OPC_LDPC + (1 << 16):
4042 case R6_OPC_LDPC + (2 << 16):
4043 case R6_OPC_LDPC + (3 << 16):
4044 check_mips_64(ctx);
4045 offset = sextract32(ctx->opcode << 3, 0, 21);
4046 addr = addr_add(ctx, (pc & ~0x7), offset);
4047 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4048 break;
4049 #endif
4050 default:
4051 MIPS_INVAL("OPC_PCREL");
4052 gen_reserved_instruction(ctx);
4053 break;
4055 break;
4059 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4061 TCGv t0, t1;
4063 if (rd == 0) {
4064 /* Treat as NOP. */
4065 return;
4068 t0 = tcg_temp_new();
4069 t1 = tcg_temp_new();
4071 gen_load_gpr(t0, rs);
4072 gen_load_gpr(t1, rt);
4074 switch (opc) {
4075 case R6_OPC_DIV:
4077 TCGv t2 = tcg_temp_new();
4078 TCGv t3 = tcg_temp_new();
4079 tcg_gen_ext32s_tl(t0, t0);
4080 tcg_gen_ext32s_tl(t1, t1);
4081 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4082 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4083 tcg_gen_and_tl(t2, t2, t3);
4084 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4085 tcg_gen_or_tl(t2, t2, t3);
4086 tcg_gen_movi_tl(t3, 0);
4087 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4088 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4089 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4090 tcg_temp_free(t3);
4091 tcg_temp_free(t2);
4093 break;
4094 case R6_OPC_MOD:
4096 TCGv t2 = tcg_temp_new();
4097 TCGv t3 = tcg_temp_new();
4098 tcg_gen_ext32s_tl(t0, t0);
4099 tcg_gen_ext32s_tl(t1, t1);
4100 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4101 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4102 tcg_gen_and_tl(t2, t2, t3);
4103 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4104 tcg_gen_or_tl(t2, t2, t3);
4105 tcg_gen_movi_tl(t3, 0);
4106 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4107 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4108 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4109 tcg_temp_free(t3);
4110 tcg_temp_free(t2);
4112 break;
4113 case R6_OPC_DIVU:
4115 TCGv t2 = tcg_const_tl(0);
4116 TCGv t3 = tcg_const_tl(1);
4117 tcg_gen_ext32u_tl(t0, t0);
4118 tcg_gen_ext32u_tl(t1, t1);
4119 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4120 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4121 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4122 tcg_temp_free(t3);
4123 tcg_temp_free(t2);
4125 break;
4126 case R6_OPC_MODU:
4128 TCGv t2 = tcg_const_tl(0);
4129 TCGv t3 = tcg_const_tl(1);
4130 tcg_gen_ext32u_tl(t0, t0);
4131 tcg_gen_ext32u_tl(t1, t1);
4132 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4133 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4134 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4135 tcg_temp_free(t3);
4136 tcg_temp_free(t2);
4138 break;
4139 case R6_OPC_MUL:
4141 TCGv_i32 t2 = tcg_temp_new_i32();
4142 TCGv_i32 t3 = tcg_temp_new_i32();
4143 tcg_gen_trunc_tl_i32(t2, t0);
4144 tcg_gen_trunc_tl_i32(t3, t1);
4145 tcg_gen_mul_i32(t2, t2, t3);
4146 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4147 tcg_temp_free_i32(t2);
4148 tcg_temp_free_i32(t3);
4150 break;
4151 case R6_OPC_MUH:
4153 TCGv_i32 t2 = tcg_temp_new_i32();
4154 TCGv_i32 t3 = tcg_temp_new_i32();
4155 tcg_gen_trunc_tl_i32(t2, t0);
4156 tcg_gen_trunc_tl_i32(t3, t1);
4157 tcg_gen_muls2_i32(t2, t3, t2, t3);
4158 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4159 tcg_temp_free_i32(t2);
4160 tcg_temp_free_i32(t3);
4162 break;
4163 case R6_OPC_MULU:
4165 TCGv_i32 t2 = tcg_temp_new_i32();
4166 TCGv_i32 t3 = tcg_temp_new_i32();
4167 tcg_gen_trunc_tl_i32(t2, t0);
4168 tcg_gen_trunc_tl_i32(t3, t1);
4169 tcg_gen_mul_i32(t2, t2, t3);
4170 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4171 tcg_temp_free_i32(t2);
4172 tcg_temp_free_i32(t3);
4174 break;
4175 case R6_OPC_MUHU:
4177 TCGv_i32 t2 = tcg_temp_new_i32();
4178 TCGv_i32 t3 = tcg_temp_new_i32();
4179 tcg_gen_trunc_tl_i32(t2, t0);
4180 tcg_gen_trunc_tl_i32(t3, t1);
4181 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4182 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4183 tcg_temp_free_i32(t2);
4184 tcg_temp_free_i32(t3);
4186 break;
4187 #if defined(TARGET_MIPS64)
4188 case R6_OPC_DDIV:
4190 TCGv t2 = tcg_temp_new();
4191 TCGv t3 = tcg_temp_new();
4192 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4193 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4194 tcg_gen_and_tl(t2, t2, t3);
4195 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4196 tcg_gen_or_tl(t2, t2, t3);
4197 tcg_gen_movi_tl(t3, 0);
4198 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4199 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4200 tcg_temp_free(t3);
4201 tcg_temp_free(t2);
4203 break;
4204 case R6_OPC_DMOD:
4206 TCGv t2 = tcg_temp_new();
4207 TCGv t3 = tcg_temp_new();
4208 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4209 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4210 tcg_gen_and_tl(t2, t2, t3);
4211 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4212 tcg_gen_or_tl(t2, t2, t3);
4213 tcg_gen_movi_tl(t3, 0);
4214 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4215 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4216 tcg_temp_free(t3);
4217 tcg_temp_free(t2);
4219 break;
4220 case R6_OPC_DDIVU:
4222 TCGv t2 = tcg_const_tl(0);
4223 TCGv t3 = tcg_const_tl(1);
4224 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4225 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4226 tcg_temp_free(t3);
4227 tcg_temp_free(t2);
4229 break;
4230 case R6_OPC_DMODU:
4232 TCGv t2 = tcg_const_tl(0);
4233 TCGv t3 = tcg_const_tl(1);
4234 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4235 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4236 tcg_temp_free(t3);
4237 tcg_temp_free(t2);
4239 break;
4240 case R6_OPC_DMUL:
4241 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4242 break;
4243 case R6_OPC_DMUH:
4245 TCGv t2 = tcg_temp_new();
4246 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4247 tcg_temp_free(t2);
4249 break;
4250 case R6_OPC_DMULU:
4251 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4252 break;
4253 case R6_OPC_DMUHU:
4255 TCGv t2 = tcg_temp_new();
4256 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4257 tcg_temp_free(t2);
4259 break;
4260 #endif
4261 default:
4262 MIPS_INVAL("r6 mul/div");
4263 gen_reserved_instruction(ctx);
4264 goto out;
4266 out:
4267 tcg_temp_free(t0);
4268 tcg_temp_free(t1);
4271 #if defined(TARGET_MIPS64)
4272 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4274 TCGv t0, t1;
4276 t0 = tcg_temp_new();
4277 t1 = tcg_temp_new();
4279 gen_load_gpr(t0, rs);
4280 gen_load_gpr(t1, rt);
4282 switch (opc) {
4283 case MMI_OPC_DIV1:
4285 TCGv t2 = tcg_temp_new();
4286 TCGv t3 = tcg_temp_new();
4287 tcg_gen_ext32s_tl(t0, t0);
4288 tcg_gen_ext32s_tl(t1, t1);
4289 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4290 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4291 tcg_gen_and_tl(t2, t2, t3);
4292 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4293 tcg_gen_or_tl(t2, t2, t3);
4294 tcg_gen_movi_tl(t3, 0);
4295 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4296 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4297 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4298 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4299 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4300 tcg_temp_free(t3);
4301 tcg_temp_free(t2);
4303 break;
4304 case MMI_OPC_DIVU1:
4306 TCGv t2 = tcg_const_tl(0);
4307 TCGv t3 = tcg_const_tl(1);
4308 tcg_gen_ext32u_tl(t0, t0);
4309 tcg_gen_ext32u_tl(t1, t1);
4310 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4311 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4312 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4313 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4314 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4315 tcg_temp_free(t3);
4316 tcg_temp_free(t2);
4318 break;
4319 default:
4320 MIPS_INVAL("div1 TX79");
4321 gen_reserved_instruction(ctx);
4322 goto out;
4324 out:
4325 tcg_temp_free(t0);
4326 tcg_temp_free(t1);
4328 #endif
4330 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4331 int acc, int rs, int rt)
4333 TCGv t0, t1;
4335 t0 = tcg_temp_new();
4336 t1 = tcg_temp_new();
4338 gen_load_gpr(t0, rs);
4339 gen_load_gpr(t1, rt);
4341 if (acc != 0) {
4342 check_dsp(ctx);
4345 switch (opc) {
4346 case OPC_DIV:
4348 TCGv t2 = tcg_temp_new();
4349 TCGv t3 = tcg_temp_new();
4350 tcg_gen_ext32s_tl(t0, t0);
4351 tcg_gen_ext32s_tl(t1, t1);
4352 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4353 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4354 tcg_gen_and_tl(t2, t2, t3);
4355 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4356 tcg_gen_or_tl(t2, t2, t3);
4357 tcg_gen_movi_tl(t3, 0);
4358 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4359 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4360 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4361 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4362 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4363 tcg_temp_free(t3);
4364 tcg_temp_free(t2);
4366 break;
4367 case OPC_DIVU:
4369 TCGv t2 = tcg_const_tl(0);
4370 TCGv t3 = tcg_const_tl(1);
4371 tcg_gen_ext32u_tl(t0, t0);
4372 tcg_gen_ext32u_tl(t1, t1);
4373 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4374 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4375 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4376 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4377 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4378 tcg_temp_free(t3);
4379 tcg_temp_free(t2);
4381 break;
4382 case OPC_MULT:
4384 TCGv_i32 t2 = tcg_temp_new_i32();
4385 TCGv_i32 t3 = tcg_temp_new_i32();
4386 tcg_gen_trunc_tl_i32(t2, t0);
4387 tcg_gen_trunc_tl_i32(t3, t1);
4388 tcg_gen_muls2_i32(t2, t3, t2, t3);
4389 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4390 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4391 tcg_temp_free_i32(t2);
4392 tcg_temp_free_i32(t3);
4394 break;
4395 case OPC_MULTU:
4397 TCGv_i32 t2 = tcg_temp_new_i32();
4398 TCGv_i32 t3 = tcg_temp_new_i32();
4399 tcg_gen_trunc_tl_i32(t2, t0);
4400 tcg_gen_trunc_tl_i32(t3, t1);
4401 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4402 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4403 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4404 tcg_temp_free_i32(t2);
4405 tcg_temp_free_i32(t3);
4407 break;
4408 #if defined(TARGET_MIPS64)
4409 case OPC_DDIV:
4411 TCGv t2 = tcg_temp_new();
4412 TCGv t3 = tcg_temp_new();
4413 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4414 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4415 tcg_gen_and_tl(t2, t2, t3);
4416 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4417 tcg_gen_or_tl(t2, t2, t3);
4418 tcg_gen_movi_tl(t3, 0);
4419 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4420 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4421 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4422 tcg_temp_free(t3);
4423 tcg_temp_free(t2);
4425 break;
4426 case OPC_DDIVU:
4428 TCGv t2 = tcg_const_tl(0);
4429 TCGv t3 = tcg_const_tl(1);
4430 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4431 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4432 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4433 tcg_temp_free(t3);
4434 tcg_temp_free(t2);
4436 break;
4437 case OPC_DMULT:
4438 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4439 break;
4440 case OPC_DMULTU:
4441 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4442 break;
4443 #endif
4444 case OPC_MADD:
4446 TCGv_i64 t2 = tcg_temp_new_i64();
4447 TCGv_i64 t3 = tcg_temp_new_i64();
4449 tcg_gen_ext_tl_i64(t2, t0);
4450 tcg_gen_ext_tl_i64(t3, t1);
4451 tcg_gen_mul_i64(t2, t2, t3);
4452 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4453 tcg_gen_add_i64(t2, t2, t3);
4454 tcg_temp_free_i64(t3);
4455 gen_move_low32(cpu_LO[acc], t2);
4456 gen_move_high32(cpu_HI[acc], t2);
4457 tcg_temp_free_i64(t2);
4459 break;
4460 case OPC_MADDU:
4462 TCGv_i64 t2 = tcg_temp_new_i64();
4463 TCGv_i64 t3 = tcg_temp_new_i64();
4465 tcg_gen_ext32u_tl(t0, t0);
4466 tcg_gen_ext32u_tl(t1, t1);
4467 tcg_gen_extu_tl_i64(t2, t0);
4468 tcg_gen_extu_tl_i64(t3, t1);
4469 tcg_gen_mul_i64(t2, t2, t3);
4470 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4471 tcg_gen_add_i64(t2, t2, t3);
4472 tcg_temp_free_i64(t3);
4473 gen_move_low32(cpu_LO[acc], t2);
4474 gen_move_high32(cpu_HI[acc], t2);
4475 tcg_temp_free_i64(t2);
4477 break;
4478 case OPC_MSUB:
4480 TCGv_i64 t2 = tcg_temp_new_i64();
4481 TCGv_i64 t3 = tcg_temp_new_i64();
4483 tcg_gen_ext_tl_i64(t2, t0);
4484 tcg_gen_ext_tl_i64(t3, t1);
4485 tcg_gen_mul_i64(t2, t2, t3);
4486 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4487 tcg_gen_sub_i64(t2, t3, t2);
4488 tcg_temp_free_i64(t3);
4489 gen_move_low32(cpu_LO[acc], t2);
4490 gen_move_high32(cpu_HI[acc], t2);
4491 tcg_temp_free_i64(t2);
4493 break;
4494 case OPC_MSUBU:
4496 TCGv_i64 t2 = tcg_temp_new_i64();
4497 TCGv_i64 t3 = tcg_temp_new_i64();
4499 tcg_gen_ext32u_tl(t0, t0);
4500 tcg_gen_ext32u_tl(t1, t1);
4501 tcg_gen_extu_tl_i64(t2, t0);
4502 tcg_gen_extu_tl_i64(t3, t1);
4503 tcg_gen_mul_i64(t2, t2, t3);
4504 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4505 tcg_gen_sub_i64(t2, t3, t2);
4506 tcg_temp_free_i64(t3);
4507 gen_move_low32(cpu_LO[acc], t2);
4508 gen_move_high32(cpu_HI[acc], t2);
4509 tcg_temp_free_i64(t2);
4511 break;
4512 default:
4513 MIPS_INVAL("mul/div");
4514 gen_reserved_instruction(ctx);
4515 goto out;
4517 out:
4518 tcg_temp_free(t0);
4519 tcg_temp_free(t1);
4523 * These MULT[U] and MADD[U] instructions implemented in for example
4524 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
4525 * architectures are special three-operand variants with the syntax
4527 * MULT[U][1] rd, rs, rt
4529 * such that
4531 * (rd, LO, HI) <- rs * rt
4533 * and
4535 * MADD[U][1] rd, rs, rt
4537 * such that
4539 * (rd, LO, HI) <- (LO, HI) + rs * rt
4541 * where the low-order 32-bits of the result is placed into both the
4542 * GPR rd and the special register LO. The high-order 32-bits of the
4543 * result is placed into the special register HI.
4545 * If the GPR rd is omitted in assembly language, it is taken to be 0,
4546 * which is the zero register that always reads as 0.
4548 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
4549 int rd, int rs, int rt)
4551 TCGv t0 = tcg_temp_new();
4552 TCGv t1 = tcg_temp_new();
4553 int acc = 0;
4555 gen_load_gpr(t0, rs);
4556 gen_load_gpr(t1, rt);
4558 switch (opc) {
4559 case MMI_OPC_MULT1:
4560 acc = 1;
4561 /* Fall through */
4562 case OPC_MULT:
4564 TCGv_i32 t2 = tcg_temp_new_i32();
4565 TCGv_i32 t3 = tcg_temp_new_i32();
4566 tcg_gen_trunc_tl_i32(t2, t0);
4567 tcg_gen_trunc_tl_i32(t3, t1);
4568 tcg_gen_muls2_i32(t2, t3, t2, t3);
4569 if (rd) {
4570 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4572 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4573 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4574 tcg_temp_free_i32(t2);
4575 tcg_temp_free_i32(t3);
4577 break;
4578 case MMI_OPC_MULTU1:
4579 acc = 1;
4580 /* Fall through */
4581 case OPC_MULTU:
4583 TCGv_i32 t2 = tcg_temp_new_i32();
4584 TCGv_i32 t3 = tcg_temp_new_i32();
4585 tcg_gen_trunc_tl_i32(t2, t0);
4586 tcg_gen_trunc_tl_i32(t3, t1);
4587 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4588 if (rd) {
4589 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4591 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4592 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4593 tcg_temp_free_i32(t2);
4594 tcg_temp_free_i32(t3);
4596 break;
4597 case MMI_OPC_MADD1:
4598 acc = 1;
4599 /* Fall through */
4600 case MMI_OPC_MADD:
4602 TCGv_i64 t2 = tcg_temp_new_i64();
4603 TCGv_i64 t3 = tcg_temp_new_i64();
4605 tcg_gen_ext_tl_i64(t2, t0);
4606 tcg_gen_ext_tl_i64(t3, t1);
4607 tcg_gen_mul_i64(t2, t2, t3);
4608 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4609 tcg_gen_add_i64(t2, t2, t3);
4610 tcg_temp_free_i64(t3);
4611 gen_move_low32(cpu_LO[acc], t2);
4612 gen_move_high32(cpu_HI[acc], t2);
4613 if (rd) {
4614 gen_move_low32(cpu_gpr[rd], t2);
4616 tcg_temp_free_i64(t2);
4618 break;
4619 case MMI_OPC_MADDU1:
4620 acc = 1;
4621 /* Fall through */
4622 case MMI_OPC_MADDU:
4624 TCGv_i64 t2 = tcg_temp_new_i64();
4625 TCGv_i64 t3 = tcg_temp_new_i64();
4627 tcg_gen_ext32u_tl(t0, t0);
4628 tcg_gen_ext32u_tl(t1, t1);
4629 tcg_gen_extu_tl_i64(t2, t0);
4630 tcg_gen_extu_tl_i64(t3, t1);
4631 tcg_gen_mul_i64(t2, t2, t3);
4632 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4633 tcg_gen_add_i64(t2, t2, t3);
4634 tcg_temp_free_i64(t3);
4635 gen_move_low32(cpu_LO[acc], t2);
4636 gen_move_high32(cpu_HI[acc], t2);
4637 if (rd) {
4638 gen_move_low32(cpu_gpr[rd], t2);
4640 tcg_temp_free_i64(t2);
4642 break;
4643 default:
4644 MIPS_INVAL("mul/madd TXx9");
4645 gen_reserved_instruction(ctx);
4646 goto out;
4649 out:
4650 tcg_temp_free(t0);
4651 tcg_temp_free(t1);
4654 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
4655 int rd, int rs, int rt)
4657 TCGv t0 = tcg_temp_new();
4658 TCGv t1 = tcg_temp_new();
4660 gen_load_gpr(t0, rs);
4661 gen_load_gpr(t1, rt);
4663 switch (opc) {
4664 case OPC_VR54XX_MULS:
4665 gen_helper_muls(t0, cpu_env, t0, t1);
4666 break;
4667 case OPC_VR54XX_MULSU:
4668 gen_helper_mulsu(t0, cpu_env, t0, t1);
4669 break;
4670 case OPC_VR54XX_MACC:
4671 gen_helper_macc(t0, cpu_env, t0, t1);
4672 break;
4673 case OPC_VR54XX_MACCU:
4674 gen_helper_maccu(t0, cpu_env, t0, t1);
4675 break;
4676 case OPC_VR54XX_MSAC:
4677 gen_helper_msac(t0, cpu_env, t0, t1);
4678 break;
4679 case OPC_VR54XX_MSACU:
4680 gen_helper_msacu(t0, cpu_env, t0, t1);
4681 break;
4682 case OPC_VR54XX_MULHI:
4683 gen_helper_mulhi(t0, cpu_env, t0, t1);
4684 break;
4685 case OPC_VR54XX_MULHIU:
4686 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4687 break;
4688 case OPC_VR54XX_MULSHI:
4689 gen_helper_mulshi(t0, cpu_env, t0, t1);
4690 break;
4691 case OPC_VR54XX_MULSHIU:
4692 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4693 break;
4694 case OPC_VR54XX_MACCHI:
4695 gen_helper_macchi(t0, cpu_env, t0, t1);
4696 break;
4697 case OPC_VR54XX_MACCHIU:
4698 gen_helper_macchiu(t0, cpu_env, t0, t1);
4699 break;
4700 case OPC_VR54XX_MSACHI:
4701 gen_helper_msachi(t0, cpu_env, t0, t1);
4702 break;
4703 case OPC_VR54XX_MSACHIU:
4704 gen_helper_msachiu(t0, cpu_env, t0, t1);
4705 break;
4706 default:
4707 MIPS_INVAL("mul vr54xx");
4708 gen_reserved_instruction(ctx);
4709 goto out;
4711 gen_store_gpr(t0, rd);
4713 out:
4714 tcg_temp_free(t0);
4715 tcg_temp_free(t1);
4718 static void gen_cl(DisasContext *ctx, uint32_t opc,
4719 int rd, int rs)
4721 TCGv t0;
4723 if (rd == 0) {
4724 /* Treat as NOP. */
4725 return;
4727 t0 = cpu_gpr[rd];
4728 gen_load_gpr(t0, rs);
4730 switch (opc) {
4731 case OPC_CLO:
4732 case R6_OPC_CLO:
4733 #if defined(TARGET_MIPS64)
4734 case OPC_DCLO:
4735 case R6_OPC_DCLO:
4736 #endif
4737 tcg_gen_not_tl(t0, t0);
4738 break;
4741 switch (opc) {
4742 case OPC_CLO:
4743 case R6_OPC_CLO:
4744 case OPC_CLZ:
4745 case R6_OPC_CLZ:
4746 tcg_gen_ext32u_tl(t0, t0);
4747 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4748 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
4749 break;
4750 #if defined(TARGET_MIPS64)
4751 case OPC_DCLO:
4752 case R6_OPC_DCLO:
4753 case OPC_DCLZ:
4754 case R6_OPC_DCLZ:
4755 tcg_gen_clzi_i64(t0, t0, 64);
4756 break;
4757 #endif
4761 /* Godson integer instructions */
4762 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
4763 int rd, int rs, int rt)
4765 TCGv t0, t1;
4767 if (rd == 0) {
4768 /* Treat as NOP. */
4769 return;
4772 switch (opc) {
4773 case OPC_MULT_G_2E:
4774 case OPC_MULT_G_2F:
4775 case OPC_MULTU_G_2E:
4776 case OPC_MULTU_G_2F:
4777 #if defined(TARGET_MIPS64)
4778 case OPC_DMULT_G_2E:
4779 case OPC_DMULT_G_2F:
4780 case OPC_DMULTU_G_2E:
4781 case OPC_DMULTU_G_2F:
4782 #endif
4783 t0 = tcg_temp_new();
4784 t1 = tcg_temp_new();
4785 break;
4786 default:
4787 t0 = tcg_temp_local_new();
4788 t1 = tcg_temp_local_new();
4789 break;
4792 gen_load_gpr(t0, rs);
4793 gen_load_gpr(t1, rt);
4795 switch (opc) {
4796 case OPC_MULT_G_2E:
4797 case OPC_MULT_G_2F:
4798 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4799 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4800 break;
4801 case OPC_MULTU_G_2E:
4802 case OPC_MULTU_G_2F:
4803 tcg_gen_ext32u_tl(t0, t0);
4804 tcg_gen_ext32u_tl(t1, t1);
4805 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4806 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4807 break;
4808 case OPC_DIV_G_2E:
4809 case OPC_DIV_G_2F:
4811 TCGLabel *l1 = gen_new_label();
4812 TCGLabel *l2 = gen_new_label();
4813 TCGLabel *l3 = gen_new_label();
4814 tcg_gen_ext32s_tl(t0, t0);
4815 tcg_gen_ext32s_tl(t1, t1);
4816 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4817 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4818 tcg_gen_br(l3);
4819 gen_set_label(l1);
4820 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4821 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4822 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4823 tcg_gen_br(l3);
4824 gen_set_label(l2);
4825 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4826 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4827 gen_set_label(l3);
4829 break;
4830 case OPC_DIVU_G_2E:
4831 case OPC_DIVU_G_2F:
4833 TCGLabel *l1 = gen_new_label();
4834 TCGLabel *l2 = gen_new_label();
4835 tcg_gen_ext32u_tl(t0, t0);
4836 tcg_gen_ext32u_tl(t1, t1);
4837 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4838 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4839 tcg_gen_br(l2);
4840 gen_set_label(l1);
4841 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4842 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4843 gen_set_label(l2);
4845 break;
4846 case OPC_MOD_G_2E:
4847 case OPC_MOD_G_2F:
4849 TCGLabel *l1 = gen_new_label();
4850 TCGLabel *l2 = gen_new_label();
4851 TCGLabel *l3 = gen_new_label();
4852 tcg_gen_ext32u_tl(t0, t0);
4853 tcg_gen_ext32u_tl(t1, t1);
4854 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4855 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4856 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4857 gen_set_label(l1);
4858 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4859 tcg_gen_br(l3);
4860 gen_set_label(l2);
4861 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4862 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4863 gen_set_label(l3);
4865 break;
4866 case OPC_MODU_G_2E:
4867 case OPC_MODU_G_2F:
4869 TCGLabel *l1 = gen_new_label();
4870 TCGLabel *l2 = gen_new_label();
4871 tcg_gen_ext32u_tl(t0, t0);
4872 tcg_gen_ext32u_tl(t1, t1);
4873 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4874 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4875 tcg_gen_br(l2);
4876 gen_set_label(l1);
4877 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4878 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4879 gen_set_label(l2);
4881 break;
4882 #if defined(TARGET_MIPS64)
4883 case OPC_DMULT_G_2E:
4884 case OPC_DMULT_G_2F:
4885 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4886 break;
4887 case OPC_DMULTU_G_2E:
4888 case OPC_DMULTU_G_2F:
4889 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4890 break;
4891 case OPC_DDIV_G_2E:
4892 case OPC_DDIV_G_2F:
4894 TCGLabel *l1 = gen_new_label();
4895 TCGLabel *l2 = gen_new_label();
4896 TCGLabel *l3 = gen_new_label();
4897 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4898 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4899 tcg_gen_br(l3);
4900 gen_set_label(l1);
4901 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4902 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4903 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4904 tcg_gen_br(l3);
4905 gen_set_label(l2);
4906 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4907 gen_set_label(l3);
4909 break;
4910 case OPC_DDIVU_G_2E:
4911 case OPC_DDIVU_G_2F:
4913 TCGLabel *l1 = gen_new_label();
4914 TCGLabel *l2 = gen_new_label();
4915 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4916 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4917 tcg_gen_br(l2);
4918 gen_set_label(l1);
4919 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4920 gen_set_label(l2);
4922 break;
4923 case OPC_DMOD_G_2E:
4924 case OPC_DMOD_G_2F:
4926 TCGLabel *l1 = gen_new_label();
4927 TCGLabel *l2 = gen_new_label();
4928 TCGLabel *l3 = gen_new_label();
4929 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4930 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4931 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4932 gen_set_label(l1);
4933 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4934 tcg_gen_br(l3);
4935 gen_set_label(l2);
4936 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4937 gen_set_label(l3);
4939 break;
4940 case OPC_DMODU_G_2E:
4941 case OPC_DMODU_G_2F:
4943 TCGLabel *l1 = gen_new_label();
4944 TCGLabel *l2 = gen_new_label();
4945 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4946 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4947 tcg_gen_br(l2);
4948 gen_set_label(l1);
4949 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4950 gen_set_label(l2);
4952 break;
4953 #endif
4956 tcg_temp_free(t0);
4957 tcg_temp_free(t1);
4960 /* Loongson multimedia instructions */
4961 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4963 uint32_t opc, shift_max;
4964 TCGv_i64 t0, t1;
4965 TCGCond cond;
4967 opc = MASK_LMMI(ctx->opcode);
4968 switch (opc) {
4969 case OPC_ADD_CP2:
4970 case OPC_SUB_CP2:
4971 case OPC_DADD_CP2:
4972 case OPC_DSUB_CP2:
4973 t0 = tcg_temp_local_new_i64();
4974 t1 = tcg_temp_local_new_i64();
4975 break;
4976 default:
4977 t0 = tcg_temp_new_i64();
4978 t1 = tcg_temp_new_i64();
4979 break;
4982 check_cp1_enabled(ctx);
4983 gen_load_fpr64(ctx, t0, rs);
4984 gen_load_fpr64(ctx, t1, rt);
4986 switch (opc) {
4987 case OPC_PADDSH:
4988 gen_helper_paddsh(t0, t0, t1);
4989 break;
4990 case OPC_PADDUSH:
4991 gen_helper_paddush(t0, t0, t1);
4992 break;
4993 case OPC_PADDH:
4994 gen_helper_paddh(t0, t0, t1);
4995 break;
4996 case OPC_PADDW:
4997 gen_helper_paddw(t0, t0, t1);
4998 break;
4999 case OPC_PADDSB:
5000 gen_helper_paddsb(t0, t0, t1);
5001 break;
5002 case OPC_PADDUSB:
5003 gen_helper_paddusb(t0, t0, t1);
5004 break;
5005 case OPC_PADDB:
5006 gen_helper_paddb(t0, t0, t1);
5007 break;
5009 case OPC_PSUBSH:
5010 gen_helper_psubsh(t0, t0, t1);
5011 break;
5012 case OPC_PSUBUSH:
5013 gen_helper_psubush(t0, t0, t1);
5014 break;
5015 case OPC_PSUBH:
5016 gen_helper_psubh(t0, t0, t1);
5017 break;
5018 case OPC_PSUBW:
5019 gen_helper_psubw(t0, t0, t1);
5020 break;
5021 case OPC_PSUBSB:
5022 gen_helper_psubsb(t0, t0, t1);
5023 break;
5024 case OPC_PSUBUSB:
5025 gen_helper_psubusb(t0, t0, t1);
5026 break;
5027 case OPC_PSUBB:
5028 gen_helper_psubb(t0, t0, t1);
5029 break;
5031 case OPC_PSHUFH:
5032 gen_helper_pshufh(t0, t0, t1);
5033 break;
5034 case OPC_PACKSSWH:
5035 gen_helper_packsswh(t0, t0, t1);
5036 break;
5037 case OPC_PACKSSHB:
5038 gen_helper_packsshb(t0, t0, t1);
5039 break;
5040 case OPC_PACKUSHB:
5041 gen_helper_packushb(t0, t0, t1);
5042 break;
5044 case OPC_PUNPCKLHW:
5045 gen_helper_punpcklhw(t0, t0, t1);
5046 break;
5047 case OPC_PUNPCKHHW:
5048 gen_helper_punpckhhw(t0, t0, t1);
5049 break;
5050 case OPC_PUNPCKLBH:
5051 gen_helper_punpcklbh(t0, t0, t1);
5052 break;
5053 case OPC_PUNPCKHBH:
5054 gen_helper_punpckhbh(t0, t0, t1);
5055 break;
5056 case OPC_PUNPCKLWD:
5057 gen_helper_punpcklwd(t0, t0, t1);
5058 break;
5059 case OPC_PUNPCKHWD:
5060 gen_helper_punpckhwd(t0, t0, t1);
5061 break;
5063 case OPC_PAVGH:
5064 gen_helper_pavgh(t0, t0, t1);
5065 break;
5066 case OPC_PAVGB:
5067 gen_helper_pavgb(t0, t0, t1);
5068 break;
5069 case OPC_PMAXSH:
5070 gen_helper_pmaxsh(t0, t0, t1);
5071 break;
5072 case OPC_PMINSH:
5073 gen_helper_pminsh(t0, t0, t1);
5074 break;
5075 case OPC_PMAXUB:
5076 gen_helper_pmaxub(t0, t0, t1);
5077 break;
5078 case OPC_PMINUB:
5079 gen_helper_pminub(t0, t0, t1);
5080 break;
5082 case OPC_PCMPEQW:
5083 gen_helper_pcmpeqw(t0, t0, t1);
5084 break;
5085 case OPC_PCMPGTW:
5086 gen_helper_pcmpgtw(t0, t0, t1);
5087 break;
5088 case OPC_PCMPEQH:
5089 gen_helper_pcmpeqh(t0, t0, t1);
5090 break;
5091 case OPC_PCMPGTH:
5092 gen_helper_pcmpgth(t0, t0, t1);
5093 break;
5094 case OPC_PCMPEQB:
5095 gen_helper_pcmpeqb(t0, t0, t1);
5096 break;
5097 case OPC_PCMPGTB:
5098 gen_helper_pcmpgtb(t0, t0, t1);
5099 break;
5101 case OPC_PSLLW:
5102 gen_helper_psllw(t0, t0, t1);
5103 break;
5104 case OPC_PSLLH:
5105 gen_helper_psllh(t0, t0, t1);
5106 break;
5107 case OPC_PSRLW:
5108 gen_helper_psrlw(t0, t0, t1);
5109 break;
5110 case OPC_PSRLH:
5111 gen_helper_psrlh(t0, t0, t1);
5112 break;
5113 case OPC_PSRAW:
5114 gen_helper_psraw(t0, t0, t1);
5115 break;
5116 case OPC_PSRAH:
5117 gen_helper_psrah(t0, t0, t1);
5118 break;
5120 case OPC_PMULLH:
5121 gen_helper_pmullh(t0, t0, t1);
5122 break;
5123 case OPC_PMULHH:
5124 gen_helper_pmulhh(t0, t0, t1);
5125 break;
5126 case OPC_PMULHUH:
5127 gen_helper_pmulhuh(t0, t0, t1);
5128 break;
5129 case OPC_PMADDHW:
5130 gen_helper_pmaddhw(t0, t0, t1);
5131 break;
5133 case OPC_PASUBUB:
5134 gen_helper_pasubub(t0, t0, t1);
5135 break;
5136 case OPC_BIADD:
5137 gen_helper_biadd(t0, t0);
5138 break;
5139 case OPC_PMOVMSKB:
5140 gen_helper_pmovmskb(t0, t0);
5141 break;
5143 case OPC_PADDD:
5144 tcg_gen_add_i64(t0, t0, t1);
5145 break;
5146 case OPC_PSUBD:
5147 tcg_gen_sub_i64(t0, t0, t1);
5148 break;
5149 case OPC_XOR_CP2:
5150 tcg_gen_xor_i64(t0, t0, t1);
5151 break;
5152 case OPC_NOR_CP2:
5153 tcg_gen_nor_i64(t0, t0, t1);
5154 break;
5155 case OPC_AND_CP2:
5156 tcg_gen_and_i64(t0, t0, t1);
5157 break;
5158 case OPC_OR_CP2:
5159 tcg_gen_or_i64(t0, t0, t1);
5160 break;
5162 case OPC_PANDN:
5163 tcg_gen_andc_i64(t0, t1, t0);
5164 break;
5166 case OPC_PINSRH_0:
5167 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5168 break;
5169 case OPC_PINSRH_1:
5170 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5171 break;
5172 case OPC_PINSRH_2:
5173 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5174 break;
5175 case OPC_PINSRH_3:
5176 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5177 break;
5179 case OPC_PEXTRH:
5180 tcg_gen_andi_i64(t1, t1, 3);
5181 tcg_gen_shli_i64(t1, t1, 4);
5182 tcg_gen_shr_i64(t0, t0, t1);
5183 tcg_gen_ext16u_i64(t0, t0);
5184 break;
5186 case OPC_ADDU_CP2:
5187 tcg_gen_add_i64(t0, t0, t1);
5188 tcg_gen_ext32s_i64(t0, t0);
5189 break;
5190 case OPC_SUBU_CP2:
5191 tcg_gen_sub_i64(t0, t0, t1);
5192 tcg_gen_ext32s_i64(t0, t0);
5193 break;
5195 case OPC_SLL_CP2:
5196 shift_max = 32;
5197 goto do_shift;
5198 case OPC_SRL_CP2:
5199 shift_max = 32;
5200 goto do_shift;
5201 case OPC_SRA_CP2:
5202 shift_max = 32;
5203 goto do_shift;
5204 case OPC_DSLL_CP2:
5205 shift_max = 64;
5206 goto do_shift;
5207 case OPC_DSRL_CP2:
5208 shift_max = 64;
5209 goto do_shift;
5210 case OPC_DSRA_CP2:
5211 shift_max = 64;
5212 goto do_shift;
5213 do_shift:
5214 /* Make sure shift count isn't TCG undefined behaviour. */
5215 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5217 switch (opc) {
5218 case OPC_SLL_CP2:
5219 case OPC_DSLL_CP2:
5220 tcg_gen_shl_i64(t0, t0, t1);
5221 break;
5222 case OPC_SRA_CP2:
5223 case OPC_DSRA_CP2:
5225 * Since SRA is UndefinedResult without sign-extended inputs,
5226 * we can treat SRA and DSRA the same.
5228 tcg_gen_sar_i64(t0, t0, t1);
5229 break;
5230 case OPC_SRL_CP2:
5231 /* We want to shift in zeros for SRL; zero-extend first. */
5232 tcg_gen_ext32u_i64(t0, t0);
5233 /* FALLTHRU */
5234 case OPC_DSRL_CP2:
5235 tcg_gen_shr_i64(t0, t0, t1);
5236 break;
5239 if (shift_max == 32) {
5240 tcg_gen_ext32s_i64(t0, t0);
5243 /* Shifts larger than MAX produce zero. */
5244 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5245 tcg_gen_neg_i64(t1, t1);
5246 tcg_gen_and_i64(t0, t0, t1);
5247 break;
5249 case OPC_ADD_CP2:
5250 case OPC_DADD_CP2:
5252 TCGv_i64 t2 = tcg_temp_new_i64();
5253 TCGLabel *lab = gen_new_label();
5255 tcg_gen_mov_i64(t2, t0);
5256 tcg_gen_add_i64(t0, t1, t2);
5257 if (opc == OPC_ADD_CP2) {
5258 tcg_gen_ext32s_i64(t0, t0);
5260 tcg_gen_xor_i64(t1, t1, t2);
5261 tcg_gen_xor_i64(t2, t2, t0);
5262 tcg_gen_andc_i64(t1, t2, t1);
5263 tcg_temp_free_i64(t2);
5264 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5265 generate_exception(ctx, EXCP_OVERFLOW);
5266 gen_set_label(lab);
5267 break;
5270 case OPC_SUB_CP2:
5271 case OPC_DSUB_CP2:
5273 TCGv_i64 t2 = tcg_temp_new_i64();
5274 TCGLabel *lab = gen_new_label();
5276 tcg_gen_mov_i64(t2, t0);
5277 tcg_gen_sub_i64(t0, t1, t2);
5278 if (opc == OPC_SUB_CP2) {
5279 tcg_gen_ext32s_i64(t0, t0);
5281 tcg_gen_xor_i64(t1, t1, t2);
5282 tcg_gen_xor_i64(t2, t2, t0);
5283 tcg_gen_and_i64(t1, t1, t2);
5284 tcg_temp_free_i64(t2);
5285 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5286 generate_exception(ctx, EXCP_OVERFLOW);
5287 gen_set_label(lab);
5288 break;
5291 case OPC_PMULUW:
5292 tcg_gen_ext32u_i64(t0, t0);
5293 tcg_gen_ext32u_i64(t1, t1);
5294 tcg_gen_mul_i64(t0, t0, t1);
5295 break;
5297 case OPC_SEQU_CP2:
5298 case OPC_SEQ_CP2:
5299 cond = TCG_COND_EQ;
5300 goto do_cc_cond;
5301 break;
5302 case OPC_SLTU_CP2:
5303 cond = TCG_COND_LTU;
5304 goto do_cc_cond;
5305 break;
5306 case OPC_SLT_CP2:
5307 cond = TCG_COND_LT;
5308 goto do_cc_cond;
5309 break;
5310 case OPC_SLEU_CP2:
5311 cond = TCG_COND_LEU;
5312 goto do_cc_cond;
5313 break;
5314 case OPC_SLE_CP2:
5315 cond = TCG_COND_LE;
5316 do_cc_cond:
5318 int cc = (ctx->opcode >> 8) & 0x7;
5319 TCGv_i64 t64 = tcg_temp_new_i64();
5320 TCGv_i32 t32 = tcg_temp_new_i32();
5322 tcg_gen_setcond_i64(cond, t64, t0, t1);
5323 tcg_gen_extrl_i64_i32(t32, t64);
5324 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
5325 get_fp_bit(cc), 1);
5327 tcg_temp_free_i32(t32);
5328 tcg_temp_free_i64(t64);
5330 goto no_rd;
5331 break;
5332 default:
5333 MIPS_INVAL("loongson_cp2");
5334 gen_reserved_instruction(ctx);
5335 return;
5338 gen_store_fpr64(ctx, t0, rd);
5340 no_rd:
5341 tcg_temp_free_i64(t0);
5342 tcg_temp_free_i64(t1);
5345 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
5346 int rs, int rd)
5348 TCGv t0, t1, t2;
5349 TCGv_i32 fp0;
5350 #if defined(TARGET_MIPS64)
5351 int lsq_rt1 = ctx->opcode & 0x1f;
5352 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
5353 #endif
5354 int shf_offset = sextract32(ctx->opcode, 6, 8);
5356 t0 = tcg_temp_new();
5358 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
5359 #if defined(TARGET_MIPS64)
5360 case OPC_GSLQ:
5361 t1 = tcg_temp_new();
5362 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5363 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5364 ctx->default_tcg_memop_mask);
5365 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5366 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5367 ctx->default_tcg_memop_mask);
5368 gen_store_gpr(t1, rt);
5369 gen_store_gpr(t0, lsq_rt1);
5370 tcg_temp_free(t1);
5371 break;
5372 case OPC_GSLQC1:
5373 check_cp1_enabled(ctx);
5374 t1 = tcg_temp_new();
5375 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5376 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5377 ctx->default_tcg_memop_mask);
5378 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5379 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5380 ctx->default_tcg_memop_mask);
5381 gen_store_fpr64(ctx, t1, rt);
5382 gen_store_fpr64(ctx, t0, lsq_rt1);
5383 tcg_temp_free(t1);
5384 break;
5385 case OPC_GSSQ:
5386 t1 = tcg_temp_new();
5387 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5388 gen_load_gpr(t1, rt);
5389 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5390 ctx->default_tcg_memop_mask);
5391 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5392 gen_load_gpr(t1, lsq_rt1);
5393 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5394 ctx->default_tcg_memop_mask);
5395 tcg_temp_free(t1);
5396 break;
5397 case OPC_GSSQC1:
5398 check_cp1_enabled(ctx);
5399 t1 = tcg_temp_new();
5400 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5401 gen_load_fpr64(ctx, t1, rt);
5402 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5403 ctx->default_tcg_memop_mask);
5404 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5405 gen_load_fpr64(ctx, t1, lsq_rt1);
5406 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5407 ctx->default_tcg_memop_mask);
5408 tcg_temp_free(t1);
5409 break;
5410 #endif
5411 case OPC_GSSHFL:
5412 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
5413 case OPC_GSLWLC1:
5414 check_cp1_enabled(ctx);
5415 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5416 t1 = tcg_temp_new();
5417 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5418 tcg_gen_andi_tl(t1, t0, 3);
5419 #ifndef TARGET_WORDS_BIGENDIAN
5420 tcg_gen_xori_tl(t1, t1, 3);
5421 #endif
5422 tcg_gen_shli_tl(t1, t1, 3);
5423 tcg_gen_andi_tl(t0, t0, ~3);
5424 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
5425 tcg_gen_shl_tl(t0, t0, t1);
5426 t2 = tcg_const_tl(-1);
5427 tcg_gen_shl_tl(t2, t2, t1);
5428 fp0 = tcg_temp_new_i32();
5429 gen_load_fpr32(ctx, fp0, rt);
5430 tcg_gen_ext_i32_tl(t1, fp0);
5431 tcg_gen_andc_tl(t1, t1, t2);
5432 tcg_temp_free(t2);
5433 tcg_gen_or_tl(t0, t0, t1);
5434 tcg_temp_free(t1);
5435 #if defined(TARGET_MIPS64)
5436 tcg_gen_extrl_i64_i32(fp0, t0);
5437 #else
5438 tcg_gen_ext32s_tl(fp0, t0);
5439 #endif
5440 gen_store_fpr32(ctx, fp0, rt);
5441 tcg_temp_free_i32(fp0);
5442 break;
5443 case OPC_GSLWRC1:
5444 check_cp1_enabled(ctx);
5445 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5446 t1 = tcg_temp_new();
5447 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5448 tcg_gen_andi_tl(t1, t0, 3);
5449 #ifdef TARGET_WORDS_BIGENDIAN
5450 tcg_gen_xori_tl(t1, t1, 3);
5451 #endif
5452 tcg_gen_shli_tl(t1, t1, 3);
5453 tcg_gen_andi_tl(t0, t0, ~3);
5454 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
5455 tcg_gen_shr_tl(t0, t0, t1);
5456 tcg_gen_xori_tl(t1, t1, 31);
5457 t2 = tcg_const_tl(0xfffffffeull);
5458 tcg_gen_shl_tl(t2, t2, t1);
5459 fp0 = tcg_temp_new_i32();
5460 gen_load_fpr32(ctx, fp0, rt);
5461 tcg_gen_ext_i32_tl(t1, fp0);
5462 tcg_gen_and_tl(t1, t1, t2);
5463 tcg_temp_free(t2);
5464 tcg_gen_or_tl(t0, t0, t1);
5465 tcg_temp_free(t1);
5466 #if defined(TARGET_MIPS64)
5467 tcg_gen_extrl_i64_i32(fp0, t0);
5468 #else
5469 tcg_gen_ext32s_tl(fp0, t0);
5470 #endif
5471 gen_store_fpr32(ctx, fp0, rt);
5472 tcg_temp_free_i32(fp0);
5473 break;
5474 #if defined(TARGET_MIPS64)
5475 case OPC_GSLDLC1:
5476 check_cp1_enabled(ctx);
5477 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5478 t1 = tcg_temp_new();
5479 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5480 tcg_gen_andi_tl(t1, t0, 7);
5481 #ifndef TARGET_WORDS_BIGENDIAN
5482 tcg_gen_xori_tl(t1, t1, 7);
5483 #endif
5484 tcg_gen_shli_tl(t1, t1, 3);
5485 tcg_gen_andi_tl(t0, t0, ~7);
5486 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
5487 tcg_gen_shl_tl(t0, t0, t1);
5488 t2 = tcg_const_tl(-1);
5489 tcg_gen_shl_tl(t2, t2, t1);
5490 gen_load_fpr64(ctx, t1, rt);
5491 tcg_gen_andc_tl(t1, t1, t2);
5492 tcg_temp_free(t2);
5493 tcg_gen_or_tl(t0, t0, t1);
5494 tcg_temp_free(t1);
5495 gen_store_fpr64(ctx, t0, rt);
5496 break;
5497 case OPC_GSLDRC1:
5498 check_cp1_enabled(ctx);
5499 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5500 t1 = tcg_temp_new();
5501 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5502 tcg_gen_andi_tl(t1, t0, 7);
5503 #ifdef TARGET_WORDS_BIGENDIAN
5504 tcg_gen_xori_tl(t1, t1, 7);
5505 #endif
5506 tcg_gen_shli_tl(t1, t1, 3);
5507 tcg_gen_andi_tl(t0, t0, ~7);
5508 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
5509 tcg_gen_shr_tl(t0, t0, t1);
5510 tcg_gen_xori_tl(t1, t1, 63);
5511 t2 = tcg_const_tl(0xfffffffffffffffeull);
5512 tcg_gen_shl_tl(t2, t2, t1);
5513 gen_load_fpr64(ctx, t1, rt);
5514 tcg_gen_and_tl(t1, t1, t2);
5515 tcg_temp_free(t2);
5516 tcg_gen_or_tl(t0, t0, t1);
5517 tcg_temp_free(t1);
5518 gen_store_fpr64(ctx, t0, rt);
5519 break;
5520 #endif
5521 default:
5522 MIPS_INVAL("loongson_gsshfl");
5523 gen_reserved_instruction(ctx);
5524 break;
5526 break;
5527 case OPC_GSSHFS:
5528 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
5529 case OPC_GSSWLC1:
5530 check_cp1_enabled(ctx);
5531 t1 = tcg_temp_new();
5532 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5533 fp0 = tcg_temp_new_i32();
5534 gen_load_fpr32(ctx, fp0, rt);
5535 tcg_gen_ext_i32_tl(t1, fp0);
5536 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
5537 tcg_temp_free_i32(fp0);
5538 tcg_temp_free(t1);
5539 break;
5540 case OPC_GSSWRC1:
5541 check_cp1_enabled(ctx);
5542 t1 = tcg_temp_new();
5543 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5544 fp0 = tcg_temp_new_i32();
5545 gen_load_fpr32(ctx, fp0, rt);
5546 tcg_gen_ext_i32_tl(t1, fp0);
5547 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
5548 tcg_temp_free_i32(fp0);
5549 tcg_temp_free(t1);
5550 break;
5551 #if defined(TARGET_MIPS64)
5552 case OPC_GSSDLC1:
5553 check_cp1_enabled(ctx);
5554 t1 = tcg_temp_new();
5555 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5556 gen_load_fpr64(ctx, t1, rt);
5557 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
5558 tcg_temp_free(t1);
5559 break;
5560 case OPC_GSSDRC1:
5561 check_cp1_enabled(ctx);
5562 t1 = tcg_temp_new();
5563 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5564 gen_load_fpr64(ctx, t1, rt);
5565 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
5566 tcg_temp_free(t1);
5567 break;
5568 #endif
5569 default:
5570 MIPS_INVAL("loongson_gsshfs");
5571 gen_reserved_instruction(ctx);
5572 break;
5574 break;
5575 default:
5576 MIPS_INVAL("loongson_gslsq");
5577 gen_reserved_instruction(ctx);
5578 break;
5580 tcg_temp_free(t0);
5583 /* Loongson EXT LDC2/SDC2 */
5584 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
5585 int rs, int rd)
5587 int offset = sextract32(ctx->opcode, 3, 8);
5588 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
5589 TCGv t0, t1;
5590 TCGv_i32 fp0;
5592 /* Pre-conditions */
5593 switch (opc) {
5594 case OPC_GSLBX:
5595 case OPC_GSLHX:
5596 case OPC_GSLWX:
5597 case OPC_GSLDX:
5598 /* prefetch, implement as NOP */
5599 if (rt == 0) {
5600 return;
5602 break;
5603 case OPC_GSSBX:
5604 case OPC_GSSHX:
5605 case OPC_GSSWX:
5606 case OPC_GSSDX:
5607 break;
5608 case OPC_GSLWXC1:
5609 #if defined(TARGET_MIPS64)
5610 case OPC_GSLDXC1:
5611 #endif
5612 check_cp1_enabled(ctx);
5613 /* prefetch, implement as NOP */
5614 if (rt == 0) {
5615 return;
5617 break;
5618 case OPC_GSSWXC1:
5619 #if defined(TARGET_MIPS64)
5620 case OPC_GSSDXC1:
5621 #endif
5622 check_cp1_enabled(ctx);
5623 break;
5624 default:
5625 MIPS_INVAL("loongson_lsdc2");
5626 gen_reserved_instruction(ctx);
5627 return;
5628 break;
5631 t0 = tcg_temp_new();
5633 gen_base_offset_addr(ctx, t0, rs, offset);
5634 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5636 switch (opc) {
5637 case OPC_GSLBX:
5638 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
5639 gen_store_gpr(t0, rt);
5640 break;
5641 case OPC_GSLHX:
5642 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
5643 ctx->default_tcg_memop_mask);
5644 gen_store_gpr(t0, rt);
5645 break;
5646 case OPC_GSLWX:
5647 gen_base_offset_addr(ctx, t0, rs, offset);
5648 if (rd) {
5649 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5651 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
5652 ctx->default_tcg_memop_mask);
5653 gen_store_gpr(t0, rt);
5654 break;
5655 #if defined(TARGET_MIPS64)
5656 case OPC_GSLDX:
5657 gen_base_offset_addr(ctx, t0, rs, offset);
5658 if (rd) {
5659 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5661 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5662 ctx->default_tcg_memop_mask);
5663 gen_store_gpr(t0, rt);
5664 break;
5665 #endif
5666 case OPC_GSLWXC1:
5667 check_cp1_enabled(ctx);
5668 gen_base_offset_addr(ctx, t0, rs, offset);
5669 if (rd) {
5670 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5672 fp0 = tcg_temp_new_i32();
5673 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
5674 ctx->default_tcg_memop_mask);
5675 gen_store_fpr32(ctx, fp0, rt);
5676 tcg_temp_free_i32(fp0);
5677 break;
5678 #if defined(TARGET_MIPS64)
5679 case OPC_GSLDXC1:
5680 check_cp1_enabled(ctx);
5681 gen_base_offset_addr(ctx, t0, rs, offset);
5682 if (rd) {
5683 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5685 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5686 ctx->default_tcg_memop_mask);
5687 gen_store_fpr64(ctx, t0, rt);
5688 break;
5689 #endif
5690 case OPC_GSSBX:
5691 t1 = tcg_temp_new();
5692 gen_load_gpr(t1, rt);
5693 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
5694 tcg_temp_free(t1);
5695 break;
5696 case OPC_GSSHX:
5697 t1 = tcg_temp_new();
5698 gen_load_gpr(t1, rt);
5699 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
5700 ctx->default_tcg_memop_mask);
5701 tcg_temp_free(t1);
5702 break;
5703 case OPC_GSSWX:
5704 t1 = tcg_temp_new();
5705 gen_load_gpr(t1, rt);
5706 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
5707 ctx->default_tcg_memop_mask);
5708 tcg_temp_free(t1);
5709 break;
5710 #if defined(TARGET_MIPS64)
5711 case OPC_GSSDX:
5712 t1 = tcg_temp_new();
5713 gen_load_gpr(t1, rt);
5714 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5715 ctx->default_tcg_memop_mask);
5716 tcg_temp_free(t1);
5717 break;
5718 #endif
5719 case OPC_GSSWXC1:
5720 fp0 = tcg_temp_new_i32();
5721 gen_load_fpr32(ctx, fp0, rt);
5722 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
5723 ctx->default_tcg_memop_mask);
5724 tcg_temp_free_i32(fp0);
5725 break;
5726 #if defined(TARGET_MIPS64)
5727 case OPC_GSSDXC1:
5728 t1 = tcg_temp_new();
5729 gen_load_fpr64(ctx, t1, rt);
5730 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
5731 ctx->default_tcg_memop_mask);
5732 tcg_temp_free(t1);
5733 break;
5734 #endif
5735 default:
5736 break;
5739 tcg_temp_free(t0);
5742 /* Traps */
5743 static void gen_trap(DisasContext *ctx, uint32_t opc,
5744 int rs, int rt, int16_t imm)
5746 int cond;
5747 TCGv t0 = tcg_temp_new();
5748 TCGv t1 = tcg_temp_new();
5750 cond = 0;
5751 /* Load needed operands */
5752 switch (opc) {
5753 case OPC_TEQ:
5754 case OPC_TGE:
5755 case OPC_TGEU:
5756 case OPC_TLT:
5757 case OPC_TLTU:
5758 case OPC_TNE:
5759 /* Compare two registers */
5760 if (rs != rt) {
5761 gen_load_gpr(t0, rs);
5762 gen_load_gpr(t1, rt);
5763 cond = 1;
5765 break;
5766 case OPC_TEQI:
5767 case OPC_TGEI:
5768 case OPC_TGEIU:
5769 case OPC_TLTI:
5770 case OPC_TLTIU:
5771 case OPC_TNEI:
5772 /* Compare register to immediate */
5773 if (rs != 0 || imm != 0) {
5774 gen_load_gpr(t0, rs);
5775 tcg_gen_movi_tl(t1, (int32_t)imm);
5776 cond = 1;
5778 break;
5780 if (cond == 0) {
5781 switch (opc) {
5782 case OPC_TEQ: /* rs == rs */
5783 case OPC_TEQI: /* r0 == 0 */
5784 case OPC_TGE: /* rs >= rs */
5785 case OPC_TGEI: /* r0 >= 0 */
5786 case OPC_TGEU: /* rs >= rs unsigned */
5787 case OPC_TGEIU: /* r0 >= 0 unsigned */
5788 /* Always trap */
5789 generate_exception_end(ctx, EXCP_TRAP);
5790 break;
5791 case OPC_TLT: /* rs < rs */
5792 case OPC_TLTI: /* r0 < 0 */
5793 case OPC_TLTU: /* rs < rs unsigned */
5794 case OPC_TLTIU: /* r0 < 0 unsigned */
5795 case OPC_TNE: /* rs != rs */
5796 case OPC_TNEI: /* r0 != 0 */
5797 /* Never trap: treat as NOP. */
5798 break;
5800 } else {
5801 TCGLabel *l1 = gen_new_label();
5803 switch (opc) {
5804 case OPC_TEQ:
5805 case OPC_TEQI:
5806 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5807 break;
5808 case OPC_TGE:
5809 case OPC_TGEI:
5810 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5811 break;
5812 case OPC_TGEU:
5813 case OPC_TGEIU:
5814 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5815 break;
5816 case OPC_TLT:
5817 case OPC_TLTI:
5818 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5819 break;
5820 case OPC_TLTU:
5821 case OPC_TLTIU:
5822 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5823 break;
5824 case OPC_TNE:
5825 case OPC_TNEI:
5826 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5827 break;
5829 generate_exception(ctx, EXCP_TRAP);
5830 gen_set_label(l1);
5832 tcg_temp_free(t0);
5833 tcg_temp_free(t1);
5836 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5838 if (unlikely(ctx->base.singlestep_enabled)) {
5839 return false;
5842 #ifndef CONFIG_USER_ONLY
5843 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5844 #else
5845 return true;
5846 #endif
5849 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5851 if (use_goto_tb(ctx, dest)) {
5852 tcg_gen_goto_tb(n);
5853 gen_save_pc(dest);
5854 tcg_gen_exit_tb(ctx->base.tb, n);
5855 } else {
5856 gen_save_pc(dest);
5857 if (ctx->base.singlestep_enabled) {
5858 save_cpu_state(ctx, 0);
5859 gen_helper_raise_exception_debug(cpu_env);
5861 tcg_gen_lookup_and_goto_ptr();
5865 /* Branches (before delay slot) */
5866 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
5867 int insn_bytes,
5868 int rs, int rt, int32_t offset,
5869 int delayslot_size)
5871 target_ulong btgt = -1;
5872 int blink = 0;
5873 int bcond_compute = 0;
5874 TCGv t0 = tcg_temp_new();
5875 TCGv t1 = tcg_temp_new();
5877 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5878 #ifdef MIPS_DEBUG_DISAS
5879 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5880 TARGET_FMT_lx "\n", ctx->base.pc_next);
5881 #endif
5882 gen_reserved_instruction(ctx);
5883 goto out;
5886 /* Load needed operands */
5887 switch (opc) {
5888 case OPC_BEQ:
5889 case OPC_BEQL:
5890 case OPC_BNE:
5891 case OPC_BNEL:
5892 /* Compare two registers */
5893 if (rs != rt) {
5894 gen_load_gpr(t0, rs);
5895 gen_load_gpr(t1, rt);
5896 bcond_compute = 1;
5898 btgt = ctx->base.pc_next + insn_bytes + offset;
5899 break;
5900 case OPC_BGEZ:
5901 case OPC_BGEZAL:
5902 case OPC_BGEZALL:
5903 case OPC_BGEZL:
5904 case OPC_BGTZ:
5905 case OPC_BGTZL:
5906 case OPC_BLEZ:
5907 case OPC_BLEZL:
5908 case OPC_BLTZ:
5909 case OPC_BLTZAL:
5910 case OPC_BLTZALL:
5911 case OPC_BLTZL:
5912 /* Compare to zero */
5913 if (rs != 0) {
5914 gen_load_gpr(t0, rs);
5915 bcond_compute = 1;
5917 btgt = ctx->base.pc_next + insn_bytes + offset;
5918 break;
5919 case OPC_BPOSGE32:
5920 #if defined(TARGET_MIPS64)
5921 case OPC_BPOSGE64:
5922 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5923 #else
5924 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5925 #endif
5926 bcond_compute = 1;
5927 btgt = ctx->base.pc_next + insn_bytes + offset;
5928 break;
5929 case OPC_J:
5930 case OPC_JAL:
5931 case OPC_JALX:
5932 /* Jump to immediate */
5933 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5934 (uint32_t)offset;
5935 break;
5936 case OPC_JR:
5937 case OPC_JALR:
5938 /* Jump to register */
5939 if (offset != 0 && offset != 16) {
5941 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5942 * others are reserved.
5944 MIPS_INVAL("jump hint");
5945 gen_reserved_instruction(ctx);
5946 goto out;
5948 gen_load_gpr(btarget, rs);
5949 break;
5950 default:
5951 MIPS_INVAL("branch/jump");
5952 gen_reserved_instruction(ctx);
5953 goto out;
5955 if (bcond_compute == 0) {
5956 /* No condition to be computed */
5957 switch (opc) {
5958 case OPC_BEQ: /* rx == rx */
5959 case OPC_BEQL: /* rx == rx likely */
5960 case OPC_BGEZ: /* 0 >= 0 */
5961 case OPC_BGEZL: /* 0 >= 0 likely */
5962 case OPC_BLEZ: /* 0 <= 0 */
5963 case OPC_BLEZL: /* 0 <= 0 likely */
5964 /* Always take */
5965 ctx->hflags |= MIPS_HFLAG_B;
5966 break;
5967 case OPC_BGEZAL: /* 0 >= 0 */
5968 case OPC_BGEZALL: /* 0 >= 0 likely */
5969 /* Always take and link */
5970 blink = 31;
5971 ctx->hflags |= MIPS_HFLAG_B;
5972 break;
5973 case OPC_BNE: /* rx != rx */
5974 case OPC_BGTZ: /* 0 > 0 */
5975 case OPC_BLTZ: /* 0 < 0 */
5976 /* Treat as NOP. */
5977 goto out;
5978 case OPC_BLTZAL: /* 0 < 0 */
5980 * Handle as an unconditional branch to get correct delay
5981 * slot checking.
5983 blink = 31;
5984 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5985 ctx->hflags |= MIPS_HFLAG_B;
5986 break;
5987 case OPC_BLTZALL: /* 0 < 0 likely */
5988 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5989 /* Skip the instruction in the delay slot */
5990 ctx->base.pc_next += 4;
5991 goto out;
5992 case OPC_BNEL: /* rx != rx likely */
5993 case OPC_BGTZL: /* 0 > 0 likely */
5994 case OPC_BLTZL: /* 0 < 0 likely */
5995 /* Skip the instruction in the delay slot */
5996 ctx->base.pc_next += 4;
5997 goto out;
5998 case OPC_J:
5999 ctx->hflags |= MIPS_HFLAG_B;
6000 break;
6001 case OPC_JALX:
6002 ctx->hflags |= MIPS_HFLAG_BX;
6003 /* Fallthrough */
6004 case OPC_JAL:
6005 blink = 31;
6006 ctx->hflags |= MIPS_HFLAG_B;
6007 break;
6008 case OPC_JR:
6009 ctx->hflags |= MIPS_HFLAG_BR;
6010 break;
6011 case OPC_JALR:
6012 blink = rt;
6013 ctx->hflags |= MIPS_HFLAG_BR;
6014 break;
6015 default:
6016 MIPS_INVAL("branch/jump");
6017 gen_reserved_instruction(ctx);
6018 goto out;
6020 } else {
6021 switch (opc) {
6022 case OPC_BEQ:
6023 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6024 goto not_likely;
6025 case OPC_BEQL:
6026 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6027 goto likely;
6028 case OPC_BNE:
6029 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6030 goto not_likely;
6031 case OPC_BNEL:
6032 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6033 goto likely;
6034 case OPC_BGEZ:
6035 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6036 goto not_likely;
6037 case OPC_BGEZL:
6038 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6039 goto likely;
6040 case OPC_BGEZAL:
6041 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6042 blink = 31;
6043 goto not_likely;
6044 case OPC_BGEZALL:
6045 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6046 blink = 31;
6047 goto likely;
6048 case OPC_BGTZ:
6049 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6050 goto not_likely;
6051 case OPC_BGTZL:
6052 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6053 goto likely;
6054 case OPC_BLEZ:
6055 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6056 goto not_likely;
6057 case OPC_BLEZL:
6058 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6059 goto likely;
6060 case OPC_BLTZ:
6061 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6062 goto not_likely;
6063 case OPC_BLTZL:
6064 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6065 goto likely;
6066 case OPC_BPOSGE32:
6067 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6068 goto not_likely;
6069 #if defined(TARGET_MIPS64)
6070 case OPC_BPOSGE64:
6071 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6072 goto not_likely;
6073 #endif
6074 case OPC_BLTZAL:
6075 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6076 blink = 31;
6077 not_likely:
6078 ctx->hflags |= MIPS_HFLAG_BC;
6079 break;
6080 case OPC_BLTZALL:
6081 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6082 blink = 31;
6083 likely:
6084 ctx->hflags |= MIPS_HFLAG_BL;
6085 break;
6086 default:
6087 MIPS_INVAL("conditional branch/jump");
6088 gen_reserved_instruction(ctx);
6089 goto out;
6093 ctx->btarget = btgt;
6095 switch (delayslot_size) {
6096 case 2:
6097 ctx->hflags |= MIPS_HFLAG_BDS16;
6098 break;
6099 case 4:
6100 ctx->hflags |= MIPS_HFLAG_BDS32;
6101 break;
6104 if (blink > 0) {
6105 int post_delay = insn_bytes + delayslot_size;
6106 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6108 tcg_gen_movi_tl(cpu_gpr[blink],
6109 ctx->base.pc_next + post_delay + lowbit);
6112 out:
6113 if (insn_bytes == 2) {
6114 ctx->hflags |= MIPS_HFLAG_B16;
6116 tcg_temp_free(t0);
6117 tcg_temp_free(t1);
6121 /* nanoMIPS Branches */
6122 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6123 int insn_bytes,
6124 int rs, int rt, int32_t offset)
6126 target_ulong btgt = -1;
6127 int bcond_compute = 0;
6128 TCGv t0 = tcg_temp_new();
6129 TCGv t1 = tcg_temp_new();
6131 /* Load needed operands */
6132 switch (opc) {
6133 case OPC_BEQ:
6134 case OPC_BNE:
6135 /* Compare two registers */
6136 if (rs != rt) {
6137 gen_load_gpr(t0, rs);
6138 gen_load_gpr(t1, rt);
6139 bcond_compute = 1;
6141 btgt = ctx->base.pc_next + insn_bytes + offset;
6142 break;
6143 case OPC_BGEZAL:
6144 /* Compare to zero */
6145 if (rs != 0) {
6146 gen_load_gpr(t0, rs);
6147 bcond_compute = 1;
6149 btgt = ctx->base.pc_next + insn_bytes + offset;
6150 break;
6151 case OPC_BPOSGE32:
6152 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6153 bcond_compute = 1;
6154 btgt = ctx->base.pc_next + insn_bytes + offset;
6155 break;
6156 case OPC_JR:
6157 case OPC_JALR:
6158 /* Jump to register */
6159 if (offset != 0 && offset != 16) {
6161 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6162 * others are reserved.
6164 MIPS_INVAL("jump hint");
6165 gen_reserved_instruction(ctx);
6166 goto out;
6168 gen_load_gpr(btarget, rs);
6169 break;
6170 default:
6171 MIPS_INVAL("branch/jump");
6172 gen_reserved_instruction(ctx);
6173 goto out;
6175 if (bcond_compute == 0) {
6176 /* No condition to be computed */
6177 switch (opc) {
6178 case OPC_BEQ: /* rx == rx */
6179 /* Always take */
6180 ctx->hflags |= MIPS_HFLAG_B;
6181 break;
6182 case OPC_BGEZAL: /* 0 >= 0 */
6183 /* Always take and link */
6184 tcg_gen_movi_tl(cpu_gpr[31],
6185 ctx->base.pc_next + insn_bytes);
6186 ctx->hflags |= MIPS_HFLAG_B;
6187 break;
6188 case OPC_BNE: /* rx != rx */
6189 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6190 /* Skip the instruction in the delay slot */
6191 ctx->base.pc_next += 4;
6192 goto out;
6193 case OPC_JR:
6194 ctx->hflags |= MIPS_HFLAG_BR;
6195 break;
6196 case OPC_JALR:
6197 if (rt > 0) {
6198 tcg_gen_movi_tl(cpu_gpr[rt],
6199 ctx->base.pc_next + insn_bytes);
6201 ctx->hflags |= MIPS_HFLAG_BR;
6202 break;
6203 default:
6204 MIPS_INVAL("branch/jump");
6205 gen_reserved_instruction(ctx);
6206 goto out;
6208 } else {
6209 switch (opc) {
6210 case OPC_BEQ:
6211 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6212 goto not_likely;
6213 case OPC_BNE:
6214 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6215 goto not_likely;
6216 case OPC_BGEZAL:
6217 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6218 tcg_gen_movi_tl(cpu_gpr[31],
6219 ctx->base.pc_next + insn_bytes);
6220 goto not_likely;
6221 case OPC_BPOSGE32:
6222 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6223 not_likely:
6224 ctx->hflags |= MIPS_HFLAG_BC;
6225 break;
6226 default:
6227 MIPS_INVAL("conditional branch/jump");
6228 gen_reserved_instruction(ctx);
6229 goto out;
6233 ctx->btarget = btgt;
6235 out:
6236 if (insn_bytes == 2) {
6237 ctx->hflags |= MIPS_HFLAG_B16;
6239 tcg_temp_free(t0);
6240 tcg_temp_free(t1);
6244 /* special3 bitfield operations */
6245 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6246 int rs, int lsb, int msb)
6248 TCGv t0 = tcg_temp_new();
6249 TCGv t1 = tcg_temp_new();
6251 gen_load_gpr(t1, rs);
6252 switch (opc) {
6253 case OPC_EXT:
6254 if (lsb + msb > 31) {
6255 goto fail;
6257 if (msb != 31) {
6258 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6259 } else {
6261 * The two checks together imply that lsb == 0,
6262 * so this is a simple sign-extension.
6264 tcg_gen_ext32s_tl(t0, t1);
6266 break;
6267 #if defined(TARGET_MIPS64)
6268 case OPC_DEXTU:
6269 lsb += 32;
6270 goto do_dext;
6271 case OPC_DEXTM:
6272 msb += 32;
6273 goto do_dext;
6274 case OPC_DEXT:
6275 do_dext:
6276 if (lsb + msb > 63) {
6277 goto fail;
6279 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6280 break;
6281 #endif
6282 case OPC_INS:
6283 if (lsb > msb) {
6284 goto fail;
6286 gen_load_gpr(t0, rt);
6287 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6288 tcg_gen_ext32s_tl(t0, t0);
6289 break;
6290 #if defined(TARGET_MIPS64)
6291 case OPC_DINSU:
6292 lsb += 32;
6293 /* FALLTHRU */
6294 case OPC_DINSM:
6295 msb += 32;
6296 /* FALLTHRU */
6297 case OPC_DINS:
6298 if (lsb > msb) {
6299 goto fail;
6301 gen_load_gpr(t0, rt);
6302 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6303 break;
6304 #endif
6305 default:
6306 fail:
6307 MIPS_INVAL("bitops");
6308 gen_reserved_instruction(ctx);
6309 tcg_temp_free(t0);
6310 tcg_temp_free(t1);
6311 return;
6313 gen_store_gpr(t0, rt);
6314 tcg_temp_free(t0);
6315 tcg_temp_free(t1);
6318 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6320 TCGv t0;
6322 if (rd == 0) {
6323 /* If no destination, treat it as a NOP. */
6324 return;
6327 t0 = tcg_temp_new();
6328 gen_load_gpr(t0, rt);
6329 switch (op2) {
6330 case OPC_WSBH:
6332 TCGv t1 = tcg_temp_new();
6333 TCGv t2 = tcg_const_tl(0x00FF00FF);
6335 tcg_gen_shri_tl(t1, t0, 8);
6336 tcg_gen_and_tl(t1, t1, t2);
6337 tcg_gen_and_tl(t0, t0, t2);
6338 tcg_gen_shli_tl(t0, t0, 8);
6339 tcg_gen_or_tl(t0, t0, t1);
6340 tcg_temp_free(t2);
6341 tcg_temp_free(t1);
6342 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6344 break;
6345 case OPC_SEB:
6346 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6347 break;
6348 case OPC_SEH:
6349 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6350 break;
6351 #if defined(TARGET_MIPS64)
6352 case OPC_DSBH:
6354 TCGv t1 = tcg_temp_new();
6355 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6357 tcg_gen_shri_tl(t1, t0, 8);
6358 tcg_gen_and_tl(t1, t1, t2);
6359 tcg_gen_and_tl(t0, t0, t2);
6360 tcg_gen_shli_tl(t0, t0, 8);
6361 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6362 tcg_temp_free(t2);
6363 tcg_temp_free(t1);
6365 break;
6366 case OPC_DSHD:
6368 TCGv t1 = tcg_temp_new();
6369 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6371 tcg_gen_shri_tl(t1, t0, 16);
6372 tcg_gen_and_tl(t1, t1, t2);
6373 tcg_gen_and_tl(t0, t0, t2);
6374 tcg_gen_shli_tl(t0, t0, 16);
6375 tcg_gen_or_tl(t0, t0, t1);
6376 tcg_gen_shri_tl(t1, t0, 32);
6377 tcg_gen_shli_tl(t0, t0, 32);
6378 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6379 tcg_temp_free(t2);
6380 tcg_temp_free(t1);
6382 break;
6383 #endif
6384 default:
6385 MIPS_INVAL("bsfhl");
6386 gen_reserved_instruction(ctx);
6387 tcg_temp_free(t0);
6388 return;
6390 tcg_temp_free(t0);
6393 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6394 int rt, int bits)
6396 TCGv t0;
6397 if (rd == 0) {
6398 /* Treat as NOP. */
6399 return;
6401 t0 = tcg_temp_new();
6402 if (bits == 0 || bits == wordsz) {
6403 if (bits == 0) {
6404 gen_load_gpr(t0, rt);
6405 } else {
6406 gen_load_gpr(t0, rs);
6408 switch (wordsz) {
6409 case 32:
6410 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6411 break;
6412 #if defined(TARGET_MIPS64)
6413 case 64:
6414 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6415 break;
6416 #endif
6418 } else {
6419 TCGv t1 = tcg_temp_new();
6420 gen_load_gpr(t0, rt);
6421 gen_load_gpr(t1, rs);
6422 switch (wordsz) {
6423 case 32:
6425 TCGv_i64 t2 = tcg_temp_new_i64();
6426 tcg_gen_concat_tl_i64(t2, t1, t0);
6427 tcg_gen_shri_i64(t2, t2, 32 - bits);
6428 gen_move_low32(cpu_gpr[rd], t2);
6429 tcg_temp_free_i64(t2);
6431 break;
6432 #if defined(TARGET_MIPS64)
6433 case 64:
6434 tcg_gen_shli_tl(t0, t0, bits);
6435 tcg_gen_shri_tl(t1, t1, 64 - bits);
6436 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6437 break;
6438 #endif
6440 tcg_temp_free(t1);
6443 tcg_temp_free(t0);
6446 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6447 int bp)
6449 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6452 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6453 int shift)
6455 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6458 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6460 TCGv t0;
6461 if (rd == 0) {
6462 /* Treat as NOP. */
6463 return;
6465 t0 = tcg_temp_new();
6466 gen_load_gpr(t0, rt);
6467 switch (opc) {
6468 case OPC_BITSWAP:
6469 gen_helper_bitswap(cpu_gpr[rd], t0);
6470 break;
6471 #if defined(TARGET_MIPS64)
6472 case OPC_DBITSWAP:
6473 gen_helper_dbitswap(cpu_gpr[rd], t0);
6474 break;
6475 #endif
6477 tcg_temp_free(t0);
6480 #ifndef CONFIG_USER_ONLY
6481 /* CP0 (MMU and control) */
6482 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6484 TCGv_i64 t0 = tcg_temp_new_i64();
6485 TCGv_i64 t1 = tcg_temp_new_i64();
6487 tcg_gen_ext_tl_i64(t0, arg);
6488 tcg_gen_ld_i64(t1, cpu_env, off);
6489 #if defined(TARGET_MIPS64)
6490 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6491 #else
6492 tcg_gen_concat32_i64(t1, t1, t0);
6493 #endif
6494 tcg_gen_st_i64(t1, cpu_env, off);
6495 tcg_temp_free_i64(t1);
6496 tcg_temp_free_i64(t0);
6499 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6501 TCGv_i64 t0 = tcg_temp_new_i64();
6502 TCGv_i64 t1 = tcg_temp_new_i64();
6504 tcg_gen_ext_tl_i64(t0, arg);
6505 tcg_gen_ld_i64(t1, cpu_env, off);
6506 tcg_gen_concat32_i64(t1, t1, t0);
6507 tcg_gen_st_i64(t1, cpu_env, off);
6508 tcg_temp_free_i64(t1);
6509 tcg_temp_free_i64(t0);
6512 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6514 TCGv_i64 t0 = tcg_temp_new_i64();
6516 tcg_gen_ld_i64(t0, cpu_env, off);
6517 #if defined(TARGET_MIPS64)
6518 tcg_gen_shri_i64(t0, t0, 30);
6519 #else
6520 tcg_gen_shri_i64(t0, t0, 32);
6521 #endif
6522 gen_move_low32(arg, t0);
6523 tcg_temp_free_i64(t0);
6526 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6528 TCGv_i64 t0 = tcg_temp_new_i64();
6530 tcg_gen_ld_i64(t0, cpu_env, off);
6531 tcg_gen_shri_i64(t0, t0, 32 + shift);
6532 gen_move_low32(arg, t0);
6533 tcg_temp_free_i64(t0);
6536 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
6538 TCGv_i32 t0 = tcg_temp_new_i32();
6540 tcg_gen_ld_i32(t0, cpu_env, off);
6541 tcg_gen_ext_i32_tl(arg, t0);
6542 tcg_temp_free_i32(t0);
6545 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
6547 tcg_gen_ld_tl(arg, cpu_env, off);
6548 tcg_gen_ext32s_tl(arg, arg);
6551 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
6553 TCGv_i32 t0 = tcg_temp_new_i32();
6555 tcg_gen_trunc_tl_i32(t0, arg);
6556 tcg_gen_st_i32(t0, cpu_env, off);
6557 tcg_temp_free_i32(t0);
6560 #define CP0_CHECK(c) \
6561 do { \
6562 if (!(c)) { \
6563 goto cp0_unimplemented; \
6565 } while (0)
6567 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6569 const char *register_name = "invalid";
6571 switch (reg) {
6572 case CP0_REGISTER_02:
6573 switch (sel) {
6574 case 0:
6575 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6576 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6577 register_name = "EntryLo0";
6578 break;
6579 default:
6580 goto cp0_unimplemented;
6582 break;
6583 case CP0_REGISTER_03:
6584 switch (sel) {
6585 case CP0_REG03__ENTRYLO1:
6586 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6587 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6588 register_name = "EntryLo1";
6589 break;
6590 default:
6591 goto cp0_unimplemented;
6593 break;
6594 case CP0_REGISTER_09:
6595 switch (sel) {
6596 case CP0_REG09__SAAR:
6597 CP0_CHECK(ctx->saar);
6598 gen_helper_mfhc0_saar(arg, cpu_env);
6599 register_name = "SAAR";
6600 break;
6601 default:
6602 goto cp0_unimplemented;
6604 break;
6605 case CP0_REGISTER_17:
6606 switch (sel) {
6607 case CP0_REG17__LLADDR:
6608 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
6609 ctx->CP0_LLAddr_shift);
6610 register_name = "LLAddr";
6611 break;
6612 case CP0_REG17__MAAR:
6613 CP0_CHECK(ctx->mrp);
6614 gen_helper_mfhc0_maar(arg, cpu_env);
6615 register_name = "MAAR";
6616 break;
6617 default:
6618 goto cp0_unimplemented;
6620 break;
6621 case CP0_REGISTER_19:
6622 switch (sel) {
6623 case CP0_REG19__WATCHHI0:
6624 case CP0_REG19__WATCHHI1:
6625 case CP0_REG19__WATCHHI2:
6626 case CP0_REG19__WATCHHI3:
6627 case CP0_REG19__WATCHHI4:
6628 case CP0_REG19__WATCHHI5:
6629 case CP0_REG19__WATCHHI6:
6630 case CP0_REG19__WATCHHI7:
6631 /* upper 32 bits are only available when Config5MI != 0 */
6632 CP0_CHECK(ctx->mi);
6633 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
6634 register_name = "WatchHi";
6635 break;
6636 default:
6637 goto cp0_unimplemented;
6639 break;
6640 case CP0_REGISTER_28:
6641 switch (sel) {
6642 case 0:
6643 case 2:
6644 case 4:
6645 case 6:
6646 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6647 register_name = "TagLo";
6648 break;
6649 default:
6650 goto cp0_unimplemented;
6652 break;
6653 default:
6654 goto cp0_unimplemented;
6656 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6657 return;
6659 cp0_unimplemented:
6660 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6661 register_name, reg, sel);
6662 tcg_gen_movi_tl(arg, 0);
6665 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6667 const char *register_name = "invalid";
6668 uint64_t mask = ctx->PAMask >> 36;
6670 switch (reg) {
6671 case CP0_REGISTER_02:
6672 switch (sel) {
6673 case 0:
6674 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6675 tcg_gen_andi_tl(arg, arg, mask);
6676 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6677 register_name = "EntryLo0";
6678 break;
6679 default:
6680 goto cp0_unimplemented;
6682 break;
6683 case CP0_REGISTER_03:
6684 switch (sel) {
6685 case CP0_REG03__ENTRYLO1:
6686 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6687 tcg_gen_andi_tl(arg, arg, mask);
6688 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6689 register_name = "EntryLo1";
6690 break;
6691 default:
6692 goto cp0_unimplemented;
6694 break;
6695 case CP0_REGISTER_09:
6696 switch (sel) {
6697 case CP0_REG09__SAAR:
6698 CP0_CHECK(ctx->saar);
6699 gen_helper_mthc0_saar(cpu_env, arg);
6700 register_name = "SAAR";
6701 break;
6702 default:
6703 goto cp0_unimplemented;
6705 break;
6706 case CP0_REGISTER_17:
6707 switch (sel) {
6708 case CP0_REG17__LLADDR:
6710 * LLAddr is read-only (the only exception is bit 0 if LLB is
6711 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6712 * relevant for modern MIPS cores supporting MTHC0, therefore
6713 * treating MTHC0 to LLAddr as NOP.
6715 register_name = "LLAddr";
6716 break;
6717 case CP0_REG17__MAAR:
6718 CP0_CHECK(ctx->mrp);
6719 gen_helper_mthc0_maar(cpu_env, arg);
6720 register_name = "MAAR";
6721 break;
6722 default:
6723 goto cp0_unimplemented;
6725 break;
6726 case CP0_REGISTER_19:
6727 switch (sel) {
6728 case CP0_REG19__WATCHHI0:
6729 case CP0_REG19__WATCHHI1:
6730 case CP0_REG19__WATCHHI2:
6731 case CP0_REG19__WATCHHI3:
6732 case CP0_REG19__WATCHHI4:
6733 case CP0_REG19__WATCHHI5:
6734 case CP0_REG19__WATCHHI6:
6735 case CP0_REG19__WATCHHI7:
6736 /* upper 32 bits are only available when Config5MI != 0 */
6737 CP0_CHECK(ctx->mi);
6738 gen_helper_0e1i(mthc0_watchhi, arg, sel);
6739 register_name = "WatchHi";
6740 break;
6741 default:
6742 goto cp0_unimplemented;
6744 break;
6745 case CP0_REGISTER_28:
6746 switch (sel) {
6747 case 0:
6748 case 2:
6749 case 4:
6750 case 6:
6751 tcg_gen_andi_tl(arg, arg, mask);
6752 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6753 register_name = "TagLo";
6754 break;
6755 default:
6756 goto cp0_unimplemented;
6758 break;
6759 default:
6760 goto cp0_unimplemented;
6762 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6764 cp0_unimplemented:
6765 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6766 register_name, reg, sel);
6769 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6771 if (ctx->insn_flags & ISA_MIPS_R6) {
6772 tcg_gen_movi_tl(arg, 0);
6773 } else {
6774 tcg_gen_movi_tl(arg, ~0);
6778 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6780 const char *register_name = "invalid";
6782 if (sel != 0) {
6783 check_insn(ctx, ISA_MIPS_R1);
6786 switch (reg) {
6787 case CP0_REGISTER_00:
6788 switch (sel) {
6789 case CP0_REG00__INDEX:
6790 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6791 register_name = "Index";
6792 break;
6793 case CP0_REG00__MVPCONTROL:
6794 CP0_CHECK(ctx->insn_flags & ASE_MT);
6795 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6796 register_name = "MVPControl";
6797 break;
6798 case CP0_REG00__MVPCONF0:
6799 CP0_CHECK(ctx->insn_flags & ASE_MT);
6800 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6801 register_name = "MVPConf0";
6802 break;
6803 case CP0_REG00__MVPCONF1:
6804 CP0_CHECK(ctx->insn_flags & ASE_MT);
6805 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6806 register_name = "MVPConf1";
6807 break;
6808 case CP0_REG00__VPCONTROL:
6809 CP0_CHECK(ctx->vp);
6810 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6811 register_name = "VPControl";
6812 break;
6813 default:
6814 goto cp0_unimplemented;
6816 break;
6817 case CP0_REGISTER_01:
6818 switch (sel) {
6819 case CP0_REG01__RANDOM:
6820 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6821 gen_helper_mfc0_random(arg, cpu_env);
6822 register_name = "Random";
6823 break;
6824 case CP0_REG01__VPECONTROL:
6825 CP0_CHECK(ctx->insn_flags & ASE_MT);
6826 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6827 register_name = "VPEControl";
6828 break;
6829 case CP0_REG01__VPECONF0:
6830 CP0_CHECK(ctx->insn_flags & ASE_MT);
6831 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6832 register_name = "VPEConf0";
6833 break;
6834 case CP0_REG01__VPECONF1:
6835 CP0_CHECK(ctx->insn_flags & ASE_MT);
6836 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6837 register_name = "VPEConf1";
6838 break;
6839 case CP0_REG01__YQMASK:
6840 CP0_CHECK(ctx->insn_flags & ASE_MT);
6841 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6842 register_name = "YQMask";
6843 break;
6844 case CP0_REG01__VPESCHEDULE:
6845 CP0_CHECK(ctx->insn_flags & ASE_MT);
6846 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6847 register_name = "VPESchedule";
6848 break;
6849 case CP0_REG01__VPESCHEFBACK:
6850 CP0_CHECK(ctx->insn_flags & ASE_MT);
6851 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6852 register_name = "VPEScheFBack";
6853 break;
6854 case CP0_REG01__VPEOPT:
6855 CP0_CHECK(ctx->insn_flags & ASE_MT);
6856 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6857 register_name = "VPEOpt";
6858 break;
6859 default:
6860 goto cp0_unimplemented;
6862 break;
6863 case CP0_REGISTER_02:
6864 switch (sel) {
6865 case CP0_REG02__ENTRYLO0:
6867 TCGv_i64 tmp = tcg_temp_new_i64();
6868 tcg_gen_ld_i64(tmp, cpu_env,
6869 offsetof(CPUMIPSState, CP0_EntryLo0));
6870 #if defined(TARGET_MIPS64)
6871 if (ctx->rxi) {
6872 /* Move RI/XI fields to bits 31:30 */
6873 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6874 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6876 #endif
6877 gen_move_low32(arg, tmp);
6878 tcg_temp_free_i64(tmp);
6880 register_name = "EntryLo0";
6881 break;
6882 case CP0_REG02__TCSTATUS:
6883 CP0_CHECK(ctx->insn_flags & ASE_MT);
6884 gen_helper_mfc0_tcstatus(arg, cpu_env);
6885 register_name = "TCStatus";
6886 break;
6887 case CP0_REG02__TCBIND:
6888 CP0_CHECK(ctx->insn_flags & ASE_MT);
6889 gen_helper_mfc0_tcbind(arg, cpu_env);
6890 register_name = "TCBind";
6891 break;
6892 case CP0_REG02__TCRESTART:
6893 CP0_CHECK(ctx->insn_flags & ASE_MT);
6894 gen_helper_mfc0_tcrestart(arg, cpu_env);
6895 register_name = "TCRestart";
6896 break;
6897 case CP0_REG02__TCHALT:
6898 CP0_CHECK(ctx->insn_flags & ASE_MT);
6899 gen_helper_mfc0_tchalt(arg, cpu_env);
6900 register_name = "TCHalt";
6901 break;
6902 case CP0_REG02__TCCONTEXT:
6903 CP0_CHECK(ctx->insn_flags & ASE_MT);
6904 gen_helper_mfc0_tccontext(arg, cpu_env);
6905 register_name = "TCContext";
6906 break;
6907 case CP0_REG02__TCSCHEDULE:
6908 CP0_CHECK(ctx->insn_flags & ASE_MT);
6909 gen_helper_mfc0_tcschedule(arg, cpu_env);
6910 register_name = "TCSchedule";
6911 break;
6912 case CP0_REG02__TCSCHEFBACK:
6913 CP0_CHECK(ctx->insn_flags & ASE_MT);
6914 gen_helper_mfc0_tcschefback(arg, cpu_env);
6915 register_name = "TCScheFBack";
6916 break;
6917 default:
6918 goto cp0_unimplemented;
6920 break;
6921 case CP0_REGISTER_03:
6922 switch (sel) {
6923 case CP0_REG03__ENTRYLO1:
6925 TCGv_i64 tmp = tcg_temp_new_i64();
6926 tcg_gen_ld_i64(tmp, cpu_env,
6927 offsetof(CPUMIPSState, CP0_EntryLo1));
6928 #if defined(TARGET_MIPS64)
6929 if (ctx->rxi) {
6930 /* Move RI/XI fields to bits 31:30 */
6931 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6932 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6934 #endif
6935 gen_move_low32(arg, tmp);
6936 tcg_temp_free_i64(tmp);
6938 register_name = "EntryLo1";
6939 break;
6940 case CP0_REG03__GLOBALNUM:
6941 CP0_CHECK(ctx->vp);
6942 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6943 register_name = "GlobalNumber";
6944 break;
6945 default:
6946 goto cp0_unimplemented;
6948 break;
6949 case CP0_REGISTER_04:
6950 switch (sel) {
6951 case CP0_REG04__CONTEXT:
6952 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6953 tcg_gen_ext32s_tl(arg, arg);
6954 register_name = "Context";
6955 break;
6956 case CP0_REG04__CONTEXTCONFIG:
6957 /* SmartMIPS ASE */
6958 /* gen_helper_mfc0_contextconfig(arg); */
6959 register_name = "ContextConfig";
6960 goto cp0_unimplemented;
6961 case CP0_REG04__USERLOCAL:
6962 CP0_CHECK(ctx->ulri);
6963 tcg_gen_ld_tl(arg, cpu_env,
6964 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6965 tcg_gen_ext32s_tl(arg, arg);
6966 register_name = "UserLocal";
6967 break;
6968 case CP0_REG04__MMID:
6969 CP0_CHECK(ctx->mi);
6970 gen_helper_mtc0_memorymapid(cpu_env, arg);
6971 register_name = "MMID";
6972 break;
6973 default:
6974 goto cp0_unimplemented;
6976 break;
6977 case CP0_REGISTER_05:
6978 switch (sel) {
6979 case CP0_REG05__PAGEMASK:
6980 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6981 register_name = "PageMask";
6982 break;
6983 case CP0_REG05__PAGEGRAIN:
6984 check_insn(ctx, ISA_MIPS_R2);
6985 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6986 register_name = "PageGrain";
6987 break;
6988 case CP0_REG05__SEGCTL0:
6989 CP0_CHECK(ctx->sc);
6990 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6991 tcg_gen_ext32s_tl(arg, arg);
6992 register_name = "SegCtl0";
6993 break;
6994 case CP0_REG05__SEGCTL1:
6995 CP0_CHECK(ctx->sc);
6996 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6997 tcg_gen_ext32s_tl(arg, arg);
6998 register_name = "SegCtl1";
6999 break;
7000 case CP0_REG05__SEGCTL2:
7001 CP0_CHECK(ctx->sc);
7002 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7003 tcg_gen_ext32s_tl(arg, arg);
7004 register_name = "SegCtl2";
7005 break;
7006 case CP0_REG05__PWBASE:
7007 check_pw(ctx);
7008 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7009 register_name = "PWBase";
7010 break;
7011 case CP0_REG05__PWFIELD:
7012 check_pw(ctx);
7013 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7014 register_name = "PWField";
7015 break;
7016 case CP0_REG05__PWSIZE:
7017 check_pw(ctx);
7018 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7019 register_name = "PWSize";
7020 break;
7021 default:
7022 goto cp0_unimplemented;
7024 break;
7025 case CP0_REGISTER_06:
7026 switch (sel) {
7027 case CP0_REG06__WIRED:
7028 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7029 register_name = "Wired";
7030 break;
7031 case CP0_REG06__SRSCONF0:
7032 check_insn(ctx, ISA_MIPS_R2);
7033 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7034 register_name = "SRSConf0";
7035 break;
7036 case CP0_REG06__SRSCONF1:
7037 check_insn(ctx, ISA_MIPS_R2);
7038 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7039 register_name = "SRSConf1";
7040 break;
7041 case CP0_REG06__SRSCONF2:
7042 check_insn(ctx, ISA_MIPS_R2);
7043 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7044 register_name = "SRSConf2";
7045 break;
7046 case CP0_REG06__SRSCONF3:
7047 check_insn(ctx, ISA_MIPS_R2);
7048 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7049 register_name = "SRSConf3";
7050 break;
7051 case CP0_REG06__SRSCONF4:
7052 check_insn(ctx, ISA_MIPS_R2);
7053 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7054 register_name = "SRSConf4";
7055 break;
7056 case CP0_REG06__PWCTL:
7057 check_pw(ctx);
7058 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7059 register_name = "PWCtl";
7060 break;
7061 default:
7062 goto cp0_unimplemented;
7064 break;
7065 case CP0_REGISTER_07:
7066 switch (sel) {
7067 case CP0_REG07__HWRENA:
7068 check_insn(ctx, ISA_MIPS_R2);
7069 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7070 register_name = "HWREna";
7071 break;
7072 default:
7073 goto cp0_unimplemented;
7075 break;
7076 case CP0_REGISTER_08:
7077 switch (sel) {
7078 case CP0_REG08__BADVADDR:
7079 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7080 tcg_gen_ext32s_tl(arg, arg);
7081 register_name = "BadVAddr";
7082 break;
7083 case CP0_REG08__BADINSTR:
7084 CP0_CHECK(ctx->bi);
7085 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7086 register_name = "BadInstr";
7087 break;
7088 case CP0_REG08__BADINSTRP:
7089 CP0_CHECK(ctx->bp);
7090 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7091 register_name = "BadInstrP";
7092 break;
7093 case CP0_REG08__BADINSTRX:
7094 CP0_CHECK(ctx->bi);
7095 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7096 tcg_gen_andi_tl(arg, arg, ~0xffff);
7097 register_name = "BadInstrX";
7098 break;
7099 default:
7100 goto cp0_unimplemented;
7102 break;
7103 case CP0_REGISTER_09:
7104 switch (sel) {
7105 case CP0_REG09__COUNT:
7106 /* Mark as an IO operation because we read the time. */
7107 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7108 gen_io_start();
7110 gen_helper_mfc0_count(arg, cpu_env);
7112 * Break the TB to be able to take timer interrupts immediately
7113 * after reading count. DISAS_STOP isn't sufficient, we need to
7114 * ensure we break completely out of translated code.
7116 gen_save_pc(ctx->base.pc_next + 4);
7117 ctx->base.is_jmp = DISAS_EXIT;
7118 register_name = "Count";
7119 break;
7120 case CP0_REG09__SAARI:
7121 CP0_CHECK(ctx->saar);
7122 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7123 register_name = "SAARI";
7124 break;
7125 case CP0_REG09__SAAR:
7126 CP0_CHECK(ctx->saar);
7127 gen_helper_mfc0_saar(arg, cpu_env);
7128 register_name = "SAAR";
7129 break;
7130 default:
7131 goto cp0_unimplemented;
7133 break;
7134 case CP0_REGISTER_10:
7135 switch (sel) {
7136 case CP0_REG10__ENTRYHI:
7137 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7138 tcg_gen_ext32s_tl(arg, arg);
7139 register_name = "EntryHi";
7140 break;
7141 default:
7142 goto cp0_unimplemented;
7144 break;
7145 case CP0_REGISTER_11:
7146 switch (sel) {
7147 case CP0_REG11__COMPARE:
7148 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7149 register_name = "Compare";
7150 break;
7151 /* 6,7 are implementation dependent */
7152 default:
7153 goto cp0_unimplemented;
7155 break;
7156 case CP0_REGISTER_12:
7157 switch (sel) {
7158 case CP0_REG12__STATUS:
7159 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7160 register_name = "Status";
7161 break;
7162 case CP0_REG12__INTCTL:
7163 check_insn(ctx, ISA_MIPS_R2);
7164 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7165 register_name = "IntCtl";
7166 break;
7167 case CP0_REG12__SRSCTL:
7168 check_insn(ctx, ISA_MIPS_R2);
7169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7170 register_name = "SRSCtl";
7171 break;
7172 case CP0_REG12__SRSMAP:
7173 check_insn(ctx, ISA_MIPS_R2);
7174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7175 register_name = "SRSMap";
7176 break;
7177 default:
7178 goto cp0_unimplemented;
7180 break;
7181 case CP0_REGISTER_13:
7182 switch (sel) {
7183 case CP0_REG13__CAUSE:
7184 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7185 register_name = "Cause";
7186 break;
7187 default:
7188 goto cp0_unimplemented;
7190 break;
7191 case CP0_REGISTER_14:
7192 switch (sel) {
7193 case CP0_REG14__EPC:
7194 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7195 tcg_gen_ext32s_tl(arg, arg);
7196 register_name = "EPC";
7197 break;
7198 default:
7199 goto cp0_unimplemented;
7201 break;
7202 case CP0_REGISTER_15:
7203 switch (sel) {
7204 case CP0_REG15__PRID:
7205 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7206 register_name = "PRid";
7207 break;
7208 case CP0_REG15__EBASE:
7209 check_insn(ctx, ISA_MIPS_R2);
7210 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7211 tcg_gen_ext32s_tl(arg, arg);
7212 register_name = "EBase";
7213 break;
7214 case CP0_REG15__CMGCRBASE:
7215 check_insn(ctx, ISA_MIPS_R2);
7216 CP0_CHECK(ctx->cmgcr);
7217 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7218 tcg_gen_ext32s_tl(arg, arg);
7219 register_name = "CMGCRBase";
7220 break;
7221 default:
7222 goto cp0_unimplemented;
7224 break;
7225 case CP0_REGISTER_16:
7226 switch (sel) {
7227 case CP0_REG16__CONFIG:
7228 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7229 register_name = "Config";
7230 break;
7231 case CP0_REG16__CONFIG1:
7232 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7233 register_name = "Config1";
7234 break;
7235 case CP0_REG16__CONFIG2:
7236 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7237 register_name = "Config2";
7238 break;
7239 case CP0_REG16__CONFIG3:
7240 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7241 register_name = "Config3";
7242 break;
7243 case CP0_REG16__CONFIG4:
7244 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7245 register_name = "Config4";
7246 break;
7247 case CP0_REG16__CONFIG5:
7248 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7249 register_name = "Config5";
7250 break;
7251 /* 6,7 are implementation dependent */
7252 case CP0_REG16__CONFIG6:
7253 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7254 register_name = "Config6";
7255 break;
7256 case CP0_REG16__CONFIG7:
7257 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7258 register_name = "Config7";
7259 break;
7260 default:
7261 goto cp0_unimplemented;
7263 break;
7264 case CP0_REGISTER_17:
7265 switch (sel) {
7266 case CP0_REG17__LLADDR:
7267 gen_helper_mfc0_lladdr(arg, cpu_env);
7268 register_name = "LLAddr";
7269 break;
7270 case CP0_REG17__MAAR:
7271 CP0_CHECK(ctx->mrp);
7272 gen_helper_mfc0_maar(arg, cpu_env);
7273 register_name = "MAAR";
7274 break;
7275 case CP0_REG17__MAARI:
7276 CP0_CHECK(ctx->mrp);
7277 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7278 register_name = "MAARI";
7279 break;
7280 default:
7281 goto cp0_unimplemented;
7283 break;
7284 case CP0_REGISTER_18:
7285 switch (sel) {
7286 case CP0_REG18__WATCHLO0:
7287 case CP0_REG18__WATCHLO1:
7288 case CP0_REG18__WATCHLO2:
7289 case CP0_REG18__WATCHLO3:
7290 case CP0_REG18__WATCHLO4:
7291 case CP0_REG18__WATCHLO5:
7292 case CP0_REG18__WATCHLO6:
7293 case CP0_REG18__WATCHLO7:
7294 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7295 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7296 register_name = "WatchLo";
7297 break;
7298 default:
7299 goto cp0_unimplemented;
7301 break;
7302 case CP0_REGISTER_19:
7303 switch (sel) {
7304 case CP0_REG19__WATCHHI0:
7305 case CP0_REG19__WATCHHI1:
7306 case CP0_REG19__WATCHHI2:
7307 case CP0_REG19__WATCHHI3:
7308 case CP0_REG19__WATCHHI4:
7309 case CP0_REG19__WATCHHI5:
7310 case CP0_REG19__WATCHHI6:
7311 case CP0_REG19__WATCHHI7:
7312 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7313 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7314 register_name = "WatchHi";
7315 break;
7316 default:
7317 goto cp0_unimplemented;
7319 break;
7320 case CP0_REGISTER_20:
7321 switch (sel) {
7322 case CP0_REG20__XCONTEXT:
7323 #if defined(TARGET_MIPS64)
7324 check_insn(ctx, ISA_MIPS3);
7325 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7326 tcg_gen_ext32s_tl(arg, arg);
7327 register_name = "XContext";
7328 break;
7329 #endif
7330 default:
7331 goto cp0_unimplemented;
7333 break;
7334 case CP0_REGISTER_21:
7335 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7336 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7337 switch (sel) {
7338 case 0:
7339 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7340 register_name = "Framemask";
7341 break;
7342 default:
7343 goto cp0_unimplemented;
7345 break;
7346 case CP0_REGISTER_22:
7347 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7348 register_name = "'Diagnostic"; /* implementation dependent */
7349 break;
7350 case CP0_REGISTER_23:
7351 switch (sel) {
7352 case CP0_REG23__DEBUG:
7353 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7354 register_name = "Debug";
7355 break;
7356 case CP0_REG23__TRACECONTROL:
7357 /* PDtrace support */
7358 /* gen_helper_mfc0_tracecontrol(arg); */
7359 register_name = "TraceControl";
7360 goto cp0_unimplemented;
7361 case CP0_REG23__TRACECONTROL2:
7362 /* PDtrace support */
7363 /* gen_helper_mfc0_tracecontrol2(arg); */
7364 register_name = "TraceControl2";
7365 goto cp0_unimplemented;
7366 case CP0_REG23__USERTRACEDATA1:
7367 /* PDtrace support */
7368 /* gen_helper_mfc0_usertracedata1(arg);*/
7369 register_name = "UserTraceData1";
7370 goto cp0_unimplemented;
7371 case CP0_REG23__TRACEIBPC:
7372 /* PDtrace support */
7373 /* gen_helper_mfc0_traceibpc(arg); */
7374 register_name = "TraceIBPC";
7375 goto cp0_unimplemented;
7376 case CP0_REG23__TRACEDBPC:
7377 /* PDtrace support */
7378 /* gen_helper_mfc0_tracedbpc(arg); */
7379 register_name = "TraceDBPC";
7380 goto cp0_unimplemented;
7381 default:
7382 goto cp0_unimplemented;
7384 break;
7385 case CP0_REGISTER_24:
7386 switch (sel) {
7387 case CP0_REG24__DEPC:
7388 /* EJTAG support */
7389 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7390 tcg_gen_ext32s_tl(arg, arg);
7391 register_name = "DEPC";
7392 break;
7393 default:
7394 goto cp0_unimplemented;
7396 break;
7397 case CP0_REGISTER_25:
7398 switch (sel) {
7399 case CP0_REG25__PERFCTL0:
7400 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7401 register_name = "Performance0";
7402 break;
7403 case CP0_REG25__PERFCNT0:
7404 /* gen_helper_mfc0_performance1(arg); */
7405 register_name = "Performance1";
7406 goto cp0_unimplemented;
7407 case CP0_REG25__PERFCTL1:
7408 /* gen_helper_mfc0_performance2(arg); */
7409 register_name = "Performance2";
7410 goto cp0_unimplemented;
7411 case CP0_REG25__PERFCNT1:
7412 /* gen_helper_mfc0_performance3(arg); */
7413 register_name = "Performance3";
7414 goto cp0_unimplemented;
7415 case CP0_REG25__PERFCTL2:
7416 /* gen_helper_mfc0_performance4(arg); */
7417 register_name = "Performance4";
7418 goto cp0_unimplemented;
7419 case CP0_REG25__PERFCNT2:
7420 /* gen_helper_mfc0_performance5(arg); */
7421 register_name = "Performance5";
7422 goto cp0_unimplemented;
7423 case CP0_REG25__PERFCTL3:
7424 /* gen_helper_mfc0_performance6(arg); */
7425 register_name = "Performance6";
7426 goto cp0_unimplemented;
7427 case CP0_REG25__PERFCNT3:
7428 /* gen_helper_mfc0_performance7(arg); */
7429 register_name = "Performance7";
7430 goto cp0_unimplemented;
7431 default:
7432 goto cp0_unimplemented;
7434 break;
7435 case CP0_REGISTER_26:
7436 switch (sel) {
7437 case CP0_REG26__ERRCTL:
7438 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7439 register_name = "ErrCtl";
7440 break;
7441 default:
7442 goto cp0_unimplemented;
7444 break;
7445 case CP0_REGISTER_27:
7446 switch (sel) {
7447 case CP0_REG27__CACHERR:
7448 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7449 register_name = "CacheErr";
7450 break;
7451 default:
7452 goto cp0_unimplemented;
7454 break;
7455 case CP0_REGISTER_28:
7456 switch (sel) {
7457 case CP0_REG28__TAGLO:
7458 case CP0_REG28__TAGLO1:
7459 case CP0_REG28__TAGLO2:
7460 case CP0_REG28__TAGLO3:
7462 TCGv_i64 tmp = tcg_temp_new_i64();
7463 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7464 gen_move_low32(arg, tmp);
7465 tcg_temp_free_i64(tmp);
7467 register_name = "TagLo";
7468 break;
7469 case CP0_REG28__DATALO:
7470 case CP0_REG28__DATALO1:
7471 case CP0_REG28__DATALO2:
7472 case CP0_REG28__DATALO3:
7473 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7474 register_name = "DataLo";
7475 break;
7476 default:
7477 goto cp0_unimplemented;
7479 break;
7480 case CP0_REGISTER_29:
7481 switch (sel) {
7482 case CP0_REG29__TAGHI:
7483 case CP0_REG29__TAGHI1:
7484 case CP0_REG29__TAGHI2:
7485 case CP0_REG29__TAGHI3:
7486 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7487 register_name = "TagHi";
7488 break;
7489 case CP0_REG29__DATAHI:
7490 case CP0_REG29__DATAHI1:
7491 case CP0_REG29__DATAHI2:
7492 case CP0_REG29__DATAHI3:
7493 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7494 register_name = "DataHi";
7495 break;
7496 default:
7497 goto cp0_unimplemented;
7499 break;
7500 case CP0_REGISTER_30:
7501 switch (sel) {
7502 case CP0_REG30__ERROREPC:
7503 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7504 tcg_gen_ext32s_tl(arg, arg);
7505 register_name = "ErrorEPC";
7506 break;
7507 default:
7508 goto cp0_unimplemented;
7510 break;
7511 case CP0_REGISTER_31:
7512 switch (sel) {
7513 case CP0_REG31__DESAVE:
7514 /* EJTAG support */
7515 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7516 register_name = "DESAVE";
7517 break;
7518 case CP0_REG31__KSCRATCH1:
7519 case CP0_REG31__KSCRATCH2:
7520 case CP0_REG31__KSCRATCH3:
7521 case CP0_REG31__KSCRATCH4:
7522 case CP0_REG31__KSCRATCH5:
7523 case CP0_REG31__KSCRATCH6:
7524 CP0_CHECK(ctx->kscrexist & (1 << sel));
7525 tcg_gen_ld_tl(arg, cpu_env,
7526 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7527 tcg_gen_ext32s_tl(arg, arg);
7528 register_name = "KScratch";
7529 break;
7530 default:
7531 goto cp0_unimplemented;
7533 break;
7534 default:
7535 goto cp0_unimplemented;
7537 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7538 return;
7540 cp0_unimplemented:
7541 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7542 register_name, reg, sel);
7543 gen_mfc0_unimplemented(ctx, arg);
7546 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7548 const char *register_name = "invalid";
7550 if (sel != 0) {
7551 check_insn(ctx, ISA_MIPS_R1);
7554 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7555 gen_io_start();
7558 switch (reg) {
7559 case CP0_REGISTER_00:
7560 switch (sel) {
7561 case CP0_REG00__INDEX:
7562 gen_helper_mtc0_index(cpu_env, arg);
7563 register_name = "Index";
7564 break;
7565 case CP0_REG00__MVPCONTROL:
7566 CP0_CHECK(ctx->insn_flags & ASE_MT);
7567 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7568 register_name = "MVPControl";
7569 break;
7570 case CP0_REG00__MVPCONF0:
7571 CP0_CHECK(ctx->insn_flags & ASE_MT);
7572 /* ignored */
7573 register_name = "MVPConf0";
7574 break;
7575 case CP0_REG00__MVPCONF1:
7576 CP0_CHECK(ctx->insn_flags & ASE_MT);
7577 /* ignored */
7578 register_name = "MVPConf1";
7579 break;
7580 case CP0_REG00__VPCONTROL:
7581 CP0_CHECK(ctx->vp);
7582 /* ignored */
7583 register_name = "VPControl";
7584 break;
7585 default:
7586 goto cp0_unimplemented;
7588 break;
7589 case CP0_REGISTER_01:
7590 switch (sel) {
7591 case CP0_REG01__RANDOM:
7592 /* ignored */
7593 register_name = "Random";
7594 break;
7595 case CP0_REG01__VPECONTROL:
7596 CP0_CHECK(ctx->insn_flags & ASE_MT);
7597 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7598 register_name = "VPEControl";
7599 break;
7600 case CP0_REG01__VPECONF0:
7601 CP0_CHECK(ctx->insn_flags & ASE_MT);
7602 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7603 register_name = "VPEConf0";
7604 break;
7605 case CP0_REG01__VPECONF1:
7606 CP0_CHECK(ctx->insn_flags & ASE_MT);
7607 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7608 register_name = "VPEConf1";
7609 break;
7610 case CP0_REG01__YQMASK:
7611 CP0_CHECK(ctx->insn_flags & ASE_MT);
7612 gen_helper_mtc0_yqmask(cpu_env, arg);
7613 register_name = "YQMask";
7614 break;
7615 case CP0_REG01__VPESCHEDULE:
7616 CP0_CHECK(ctx->insn_flags & ASE_MT);
7617 tcg_gen_st_tl(arg, cpu_env,
7618 offsetof(CPUMIPSState, CP0_VPESchedule));
7619 register_name = "VPESchedule";
7620 break;
7621 case CP0_REG01__VPESCHEFBACK:
7622 CP0_CHECK(ctx->insn_flags & ASE_MT);
7623 tcg_gen_st_tl(arg, cpu_env,
7624 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7625 register_name = "VPEScheFBack";
7626 break;
7627 case CP0_REG01__VPEOPT:
7628 CP0_CHECK(ctx->insn_flags & ASE_MT);
7629 gen_helper_mtc0_vpeopt(cpu_env, arg);
7630 register_name = "VPEOpt";
7631 break;
7632 default:
7633 goto cp0_unimplemented;
7635 break;
7636 case CP0_REGISTER_02:
7637 switch (sel) {
7638 case CP0_REG02__ENTRYLO0:
7639 gen_helper_mtc0_entrylo0(cpu_env, arg);
7640 register_name = "EntryLo0";
7641 break;
7642 case CP0_REG02__TCSTATUS:
7643 CP0_CHECK(ctx->insn_flags & ASE_MT);
7644 gen_helper_mtc0_tcstatus(cpu_env, arg);
7645 register_name = "TCStatus";
7646 break;
7647 case CP0_REG02__TCBIND:
7648 CP0_CHECK(ctx->insn_flags & ASE_MT);
7649 gen_helper_mtc0_tcbind(cpu_env, arg);
7650 register_name = "TCBind";
7651 break;
7652 case CP0_REG02__TCRESTART:
7653 CP0_CHECK(ctx->insn_flags & ASE_MT);
7654 gen_helper_mtc0_tcrestart(cpu_env, arg);
7655 register_name = "TCRestart";
7656 break;
7657 case CP0_REG02__TCHALT:
7658 CP0_CHECK(ctx->insn_flags & ASE_MT);
7659 gen_helper_mtc0_tchalt(cpu_env, arg);
7660 register_name = "TCHalt";
7661 break;
7662 case CP0_REG02__TCCONTEXT:
7663 CP0_CHECK(ctx->insn_flags & ASE_MT);
7664 gen_helper_mtc0_tccontext(cpu_env, arg);
7665 register_name = "TCContext";
7666 break;
7667 case CP0_REG02__TCSCHEDULE:
7668 CP0_CHECK(ctx->insn_flags & ASE_MT);
7669 gen_helper_mtc0_tcschedule(cpu_env, arg);
7670 register_name = "TCSchedule";
7671 break;
7672 case CP0_REG02__TCSCHEFBACK:
7673 CP0_CHECK(ctx->insn_flags & ASE_MT);
7674 gen_helper_mtc0_tcschefback(cpu_env, arg);
7675 register_name = "TCScheFBack";
7676 break;
7677 default:
7678 goto cp0_unimplemented;
7680 break;
7681 case CP0_REGISTER_03:
7682 switch (sel) {
7683 case CP0_REG03__ENTRYLO1:
7684 gen_helper_mtc0_entrylo1(cpu_env, arg);
7685 register_name = "EntryLo1";
7686 break;
7687 case CP0_REG03__GLOBALNUM:
7688 CP0_CHECK(ctx->vp);
7689 /* ignored */
7690 register_name = "GlobalNumber";
7691 break;
7692 default:
7693 goto cp0_unimplemented;
7695 break;
7696 case CP0_REGISTER_04:
7697 switch (sel) {
7698 case CP0_REG04__CONTEXT:
7699 gen_helper_mtc0_context(cpu_env, arg);
7700 register_name = "Context";
7701 break;
7702 case CP0_REG04__CONTEXTCONFIG:
7703 /* SmartMIPS ASE */
7704 /* gen_helper_mtc0_contextconfig(arg); */
7705 register_name = "ContextConfig";
7706 goto cp0_unimplemented;
7707 case CP0_REG04__USERLOCAL:
7708 CP0_CHECK(ctx->ulri);
7709 tcg_gen_st_tl(arg, cpu_env,
7710 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7711 register_name = "UserLocal";
7712 break;
7713 case CP0_REG04__MMID:
7714 CP0_CHECK(ctx->mi);
7715 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
7716 register_name = "MMID";
7717 break;
7718 default:
7719 goto cp0_unimplemented;
7721 break;
7722 case CP0_REGISTER_05:
7723 switch (sel) {
7724 case CP0_REG05__PAGEMASK:
7725 gen_helper_mtc0_pagemask(cpu_env, arg);
7726 register_name = "PageMask";
7727 break;
7728 case CP0_REG05__PAGEGRAIN:
7729 check_insn(ctx, ISA_MIPS_R2);
7730 gen_helper_mtc0_pagegrain(cpu_env, arg);
7731 register_name = "PageGrain";
7732 ctx->base.is_jmp = DISAS_STOP;
7733 break;
7734 case CP0_REG05__SEGCTL0:
7735 CP0_CHECK(ctx->sc);
7736 gen_helper_mtc0_segctl0(cpu_env, arg);
7737 register_name = "SegCtl0";
7738 break;
7739 case CP0_REG05__SEGCTL1:
7740 CP0_CHECK(ctx->sc);
7741 gen_helper_mtc0_segctl1(cpu_env, arg);
7742 register_name = "SegCtl1";
7743 break;
7744 case CP0_REG05__SEGCTL2:
7745 CP0_CHECK(ctx->sc);
7746 gen_helper_mtc0_segctl2(cpu_env, arg);
7747 register_name = "SegCtl2";
7748 break;
7749 case CP0_REG05__PWBASE:
7750 check_pw(ctx);
7751 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7752 register_name = "PWBase";
7753 break;
7754 case CP0_REG05__PWFIELD:
7755 check_pw(ctx);
7756 gen_helper_mtc0_pwfield(cpu_env, arg);
7757 register_name = "PWField";
7758 break;
7759 case CP0_REG05__PWSIZE:
7760 check_pw(ctx);
7761 gen_helper_mtc0_pwsize(cpu_env, arg);
7762 register_name = "PWSize";
7763 break;
7764 default:
7765 goto cp0_unimplemented;
7767 break;
7768 case CP0_REGISTER_06:
7769 switch (sel) {
7770 case CP0_REG06__WIRED:
7771 gen_helper_mtc0_wired(cpu_env, arg);
7772 register_name = "Wired";
7773 break;
7774 case CP0_REG06__SRSCONF0:
7775 check_insn(ctx, ISA_MIPS_R2);
7776 gen_helper_mtc0_srsconf0(cpu_env, arg);
7777 register_name = "SRSConf0";
7778 break;
7779 case CP0_REG06__SRSCONF1:
7780 check_insn(ctx, ISA_MIPS_R2);
7781 gen_helper_mtc0_srsconf1(cpu_env, arg);
7782 register_name = "SRSConf1";
7783 break;
7784 case CP0_REG06__SRSCONF2:
7785 check_insn(ctx, ISA_MIPS_R2);
7786 gen_helper_mtc0_srsconf2(cpu_env, arg);
7787 register_name = "SRSConf2";
7788 break;
7789 case CP0_REG06__SRSCONF3:
7790 check_insn(ctx, ISA_MIPS_R2);
7791 gen_helper_mtc0_srsconf3(cpu_env, arg);
7792 register_name = "SRSConf3";
7793 break;
7794 case CP0_REG06__SRSCONF4:
7795 check_insn(ctx, ISA_MIPS_R2);
7796 gen_helper_mtc0_srsconf4(cpu_env, arg);
7797 register_name = "SRSConf4";
7798 break;
7799 case CP0_REG06__PWCTL:
7800 check_pw(ctx);
7801 gen_helper_mtc0_pwctl(cpu_env, arg);
7802 register_name = "PWCtl";
7803 break;
7804 default:
7805 goto cp0_unimplemented;
7807 break;
7808 case CP0_REGISTER_07:
7809 switch (sel) {
7810 case CP0_REG07__HWRENA:
7811 check_insn(ctx, ISA_MIPS_R2);
7812 gen_helper_mtc0_hwrena(cpu_env, arg);
7813 ctx->base.is_jmp = DISAS_STOP;
7814 register_name = "HWREna";
7815 break;
7816 default:
7817 goto cp0_unimplemented;
7819 break;
7820 case CP0_REGISTER_08:
7821 switch (sel) {
7822 case CP0_REG08__BADVADDR:
7823 /* ignored */
7824 register_name = "BadVAddr";
7825 break;
7826 case CP0_REG08__BADINSTR:
7827 /* ignored */
7828 register_name = "BadInstr";
7829 break;
7830 case CP0_REG08__BADINSTRP:
7831 /* ignored */
7832 register_name = "BadInstrP";
7833 break;
7834 case CP0_REG08__BADINSTRX:
7835 /* ignored */
7836 register_name = "BadInstrX";
7837 break;
7838 default:
7839 goto cp0_unimplemented;
7841 break;
7842 case CP0_REGISTER_09:
7843 switch (sel) {
7844 case CP0_REG09__COUNT:
7845 gen_helper_mtc0_count(cpu_env, arg);
7846 register_name = "Count";
7847 break;
7848 case CP0_REG09__SAARI:
7849 CP0_CHECK(ctx->saar);
7850 gen_helper_mtc0_saari(cpu_env, arg);
7851 register_name = "SAARI";
7852 break;
7853 case CP0_REG09__SAAR:
7854 CP0_CHECK(ctx->saar);
7855 gen_helper_mtc0_saar(cpu_env, arg);
7856 register_name = "SAAR";
7857 break;
7858 default:
7859 goto cp0_unimplemented;
7861 break;
7862 case CP0_REGISTER_10:
7863 switch (sel) {
7864 case CP0_REG10__ENTRYHI:
7865 gen_helper_mtc0_entryhi(cpu_env, arg);
7866 register_name = "EntryHi";
7867 break;
7868 default:
7869 goto cp0_unimplemented;
7871 break;
7872 case CP0_REGISTER_11:
7873 switch (sel) {
7874 case CP0_REG11__COMPARE:
7875 gen_helper_mtc0_compare(cpu_env, arg);
7876 register_name = "Compare";
7877 break;
7878 /* 6,7 are implementation dependent */
7879 default:
7880 goto cp0_unimplemented;
7882 break;
7883 case CP0_REGISTER_12:
7884 switch (sel) {
7885 case CP0_REG12__STATUS:
7886 save_cpu_state(ctx, 1);
7887 gen_helper_mtc0_status(cpu_env, arg);
7888 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7889 gen_save_pc(ctx->base.pc_next + 4);
7890 ctx->base.is_jmp = DISAS_EXIT;
7891 register_name = "Status";
7892 break;
7893 case CP0_REG12__INTCTL:
7894 check_insn(ctx, ISA_MIPS_R2);
7895 gen_helper_mtc0_intctl(cpu_env, arg);
7896 /* Stop translation as we may have switched the execution mode */
7897 ctx->base.is_jmp = DISAS_STOP;
7898 register_name = "IntCtl";
7899 break;
7900 case CP0_REG12__SRSCTL:
7901 check_insn(ctx, ISA_MIPS_R2);
7902 gen_helper_mtc0_srsctl(cpu_env, arg);
7903 /* Stop translation as we may have switched the execution mode */
7904 ctx->base.is_jmp = DISAS_STOP;
7905 register_name = "SRSCtl";
7906 break;
7907 case CP0_REG12__SRSMAP:
7908 check_insn(ctx, ISA_MIPS_R2);
7909 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7910 /* Stop translation as we may have switched the execution mode */
7911 ctx->base.is_jmp = DISAS_STOP;
7912 register_name = "SRSMap";
7913 break;
7914 default:
7915 goto cp0_unimplemented;
7917 break;
7918 case CP0_REGISTER_13:
7919 switch (sel) {
7920 case CP0_REG13__CAUSE:
7921 save_cpu_state(ctx, 1);
7922 gen_helper_mtc0_cause(cpu_env, arg);
7924 * Stop translation as we may have triggered an interrupt.
7925 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7926 * translated code to check for pending interrupts.
7928 gen_save_pc(ctx->base.pc_next + 4);
7929 ctx->base.is_jmp = DISAS_EXIT;
7930 register_name = "Cause";
7931 break;
7932 default:
7933 goto cp0_unimplemented;
7935 break;
7936 case CP0_REGISTER_14:
7937 switch (sel) {
7938 case CP0_REG14__EPC:
7939 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7940 register_name = "EPC";
7941 break;
7942 default:
7943 goto cp0_unimplemented;
7945 break;
7946 case CP0_REGISTER_15:
7947 switch (sel) {
7948 case CP0_REG15__PRID:
7949 /* ignored */
7950 register_name = "PRid";
7951 break;
7952 case CP0_REG15__EBASE:
7953 check_insn(ctx, ISA_MIPS_R2);
7954 gen_helper_mtc0_ebase(cpu_env, arg);
7955 register_name = "EBase";
7956 break;
7957 default:
7958 goto cp0_unimplemented;
7960 break;
7961 case CP0_REGISTER_16:
7962 switch (sel) {
7963 case CP0_REG16__CONFIG:
7964 gen_helper_mtc0_config0(cpu_env, arg);
7965 register_name = "Config";
7966 /* Stop translation as we may have switched the execution mode */
7967 ctx->base.is_jmp = DISAS_STOP;
7968 break;
7969 case CP0_REG16__CONFIG1:
7970 /* ignored, read only */
7971 register_name = "Config1";
7972 break;
7973 case CP0_REG16__CONFIG2:
7974 gen_helper_mtc0_config2(cpu_env, arg);
7975 register_name = "Config2";
7976 /* Stop translation as we may have switched the execution mode */
7977 ctx->base.is_jmp = DISAS_STOP;
7978 break;
7979 case CP0_REG16__CONFIG3:
7980 gen_helper_mtc0_config3(cpu_env, arg);
7981 register_name = "Config3";
7982 /* Stop translation as we may have switched the execution mode */
7983 ctx->base.is_jmp = DISAS_STOP;
7984 break;
7985 case CP0_REG16__CONFIG4:
7986 gen_helper_mtc0_config4(cpu_env, arg);
7987 register_name = "Config4";
7988 ctx->base.is_jmp = DISAS_STOP;
7989 break;
7990 case CP0_REG16__CONFIG5:
7991 gen_helper_mtc0_config5(cpu_env, arg);
7992 register_name = "Config5";
7993 /* Stop translation as we may have switched the execution mode */
7994 ctx->base.is_jmp = DISAS_STOP;
7995 break;
7996 /* 6,7 are implementation dependent */
7997 case CP0_REG16__CONFIG6:
7998 /* ignored */
7999 register_name = "Config6";
8000 break;
8001 case CP0_REG16__CONFIG7:
8002 /* ignored */
8003 register_name = "Config7";
8004 break;
8005 default:
8006 register_name = "Invalid config selector";
8007 goto cp0_unimplemented;
8009 break;
8010 case CP0_REGISTER_17:
8011 switch (sel) {
8012 case CP0_REG17__LLADDR:
8013 gen_helper_mtc0_lladdr(cpu_env, arg);
8014 register_name = "LLAddr";
8015 break;
8016 case CP0_REG17__MAAR:
8017 CP0_CHECK(ctx->mrp);
8018 gen_helper_mtc0_maar(cpu_env, arg);
8019 register_name = "MAAR";
8020 break;
8021 case CP0_REG17__MAARI:
8022 CP0_CHECK(ctx->mrp);
8023 gen_helper_mtc0_maari(cpu_env, arg);
8024 register_name = "MAARI";
8025 break;
8026 default:
8027 goto cp0_unimplemented;
8029 break;
8030 case CP0_REGISTER_18:
8031 switch (sel) {
8032 case CP0_REG18__WATCHLO0:
8033 case CP0_REG18__WATCHLO1:
8034 case CP0_REG18__WATCHLO2:
8035 case CP0_REG18__WATCHLO3:
8036 case CP0_REG18__WATCHLO4:
8037 case CP0_REG18__WATCHLO5:
8038 case CP0_REG18__WATCHLO6:
8039 case CP0_REG18__WATCHLO7:
8040 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8041 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8042 register_name = "WatchLo";
8043 break;
8044 default:
8045 goto cp0_unimplemented;
8047 break;
8048 case CP0_REGISTER_19:
8049 switch (sel) {
8050 case CP0_REG19__WATCHHI0:
8051 case CP0_REG19__WATCHHI1:
8052 case CP0_REG19__WATCHHI2:
8053 case CP0_REG19__WATCHHI3:
8054 case CP0_REG19__WATCHHI4:
8055 case CP0_REG19__WATCHHI5:
8056 case CP0_REG19__WATCHHI6:
8057 case CP0_REG19__WATCHHI7:
8058 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8059 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8060 register_name = "WatchHi";
8061 break;
8062 default:
8063 goto cp0_unimplemented;
8065 break;
8066 case CP0_REGISTER_20:
8067 switch (sel) {
8068 case CP0_REG20__XCONTEXT:
8069 #if defined(TARGET_MIPS64)
8070 check_insn(ctx, ISA_MIPS3);
8071 gen_helper_mtc0_xcontext(cpu_env, arg);
8072 register_name = "XContext";
8073 break;
8074 #endif
8075 default:
8076 goto cp0_unimplemented;
8078 break;
8079 case CP0_REGISTER_21:
8080 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8081 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8082 switch (sel) {
8083 case 0:
8084 gen_helper_mtc0_framemask(cpu_env, arg);
8085 register_name = "Framemask";
8086 break;
8087 default:
8088 goto cp0_unimplemented;
8090 break;
8091 case CP0_REGISTER_22:
8092 /* ignored */
8093 register_name = "Diagnostic"; /* implementation dependent */
8094 break;
8095 case CP0_REGISTER_23:
8096 switch (sel) {
8097 case CP0_REG23__DEBUG:
8098 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8099 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8100 gen_save_pc(ctx->base.pc_next + 4);
8101 ctx->base.is_jmp = DISAS_EXIT;
8102 register_name = "Debug";
8103 break;
8104 case CP0_REG23__TRACECONTROL:
8105 /* PDtrace support */
8106 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8107 register_name = "TraceControl";
8108 /* Stop translation as we may have switched the execution mode */
8109 ctx->base.is_jmp = DISAS_STOP;
8110 goto cp0_unimplemented;
8111 case CP0_REG23__TRACECONTROL2:
8112 /* PDtrace support */
8113 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8114 register_name = "TraceControl2";
8115 /* Stop translation as we may have switched the execution mode */
8116 ctx->base.is_jmp = DISAS_STOP;
8117 goto cp0_unimplemented;
8118 case CP0_REG23__USERTRACEDATA1:
8119 /* Stop translation as we may have switched the execution mode */
8120 ctx->base.is_jmp = DISAS_STOP;
8121 /* PDtrace support */
8122 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8123 register_name = "UserTraceData";
8124 /* Stop translation as we may have switched the execution mode */
8125 ctx->base.is_jmp = DISAS_STOP;
8126 goto cp0_unimplemented;
8127 case CP0_REG23__TRACEIBPC:
8128 /* PDtrace support */
8129 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8130 /* Stop translation as we may have switched the execution mode */
8131 ctx->base.is_jmp = DISAS_STOP;
8132 register_name = "TraceIBPC";
8133 goto cp0_unimplemented;
8134 case CP0_REG23__TRACEDBPC:
8135 /* PDtrace support */
8136 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8137 /* Stop translation as we may have switched the execution mode */
8138 ctx->base.is_jmp = DISAS_STOP;
8139 register_name = "TraceDBPC";
8140 goto cp0_unimplemented;
8141 default:
8142 goto cp0_unimplemented;
8144 break;
8145 case CP0_REGISTER_24:
8146 switch (sel) {
8147 case CP0_REG24__DEPC:
8148 /* EJTAG support */
8149 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8150 register_name = "DEPC";
8151 break;
8152 default:
8153 goto cp0_unimplemented;
8155 break;
8156 case CP0_REGISTER_25:
8157 switch (sel) {
8158 case CP0_REG25__PERFCTL0:
8159 gen_helper_mtc0_performance0(cpu_env, arg);
8160 register_name = "Performance0";
8161 break;
8162 case CP0_REG25__PERFCNT0:
8163 /* gen_helper_mtc0_performance1(arg); */
8164 register_name = "Performance1";
8165 goto cp0_unimplemented;
8166 case CP0_REG25__PERFCTL1:
8167 /* gen_helper_mtc0_performance2(arg); */
8168 register_name = "Performance2";
8169 goto cp0_unimplemented;
8170 case CP0_REG25__PERFCNT1:
8171 /* gen_helper_mtc0_performance3(arg); */
8172 register_name = "Performance3";
8173 goto cp0_unimplemented;
8174 case CP0_REG25__PERFCTL2:
8175 /* gen_helper_mtc0_performance4(arg); */
8176 register_name = "Performance4";
8177 goto cp0_unimplemented;
8178 case CP0_REG25__PERFCNT2:
8179 /* gen_helper_mtc0_performance5(arg); */
8180 register_name = "Performance5";
8181 goto cp0_unimplemented;
8182 case CP0_REG25__PERFCTL3:
8183 /* gen_helper_mtc0_performance6(arg); */
8184 register_name = "Performance6";
8185 goto cp0_unimplemented;
8186 case CP0_REG25__PERFCNT3:
8187 /* gen_helper_mtc0_performance7(arg); */
8188 register_name = "Performance7";
8189 goto cp0_unimplemented;
8190 default:
8191 goto cp0_unimplemented;
8193 break;
8194 case CP0_REGISTER_26:
8195 switch (sel) {
8196 case CP0_REG26__ERRCTL:
8197 gen_helper_mtc0_errctl(cpu_env, arg);
8198 ctx->base.is_jmp = DISAS_STOP;
8199 register_name = "ErrCtl";
8200 break;
8201 default:
8202 goto cp0_unimplemented;
8204 break;
8205 case CP0_REGISTER_27:
8206 switch (sel) {
8207 case CP0_REG27__CACHERR:
8208 /* ignored */
8209 register_name = "CacheErr";
8210 break;
8211 default:
8212 goto cp0_unimplemented;
8214 break;
8215 case CP0_REGISTER_28:
8216 switch (sel) {
8217 case CP0_REG28__TAGLO:
8218 case CP0_REG28__TAGLO1:
8219 case CP0_REG28__TAGLO2:
8220 case CP0_REG28__TAGLO3:
8221 gen_helper_mtc0_taglo(cpu_env, arg);
8222 register_name = "TagLo";
8223 break;
8224 case CP0_REG28__DATALO:
8225 case CP0_REG28__DATALO1:
8226 case CP0_REG28__DATALO2:
8227 case CP0_REG28__DATALO3:
8228 gen_helper_mtc0_datalo(cpu_env, arg);
8229 register_name = "DataLo";
8230 break;
8231 default:
8232 goto cp0_unimplemented;
8234 break;
8235 case CP0_REGISTER_29:
8236 switch (sel) {
8237 case CP0_REG29__TAGHI:
8238 case CP0_REG29__TAGHI1:
8239 case CP0_REG29__TAGHI2:
8240 case CP0_REG29__TAGHI3:
8241 gen_helper_mtc0_taghi(cpu_env, arg);
8242 register_name = "TagHi";
8243 break;
8244 case CP0_REG29__DATAHI:
8245 case CP0_REG29__DATAHI1:
8246 case CP0_REG29__DATAHI2:
8247 case CP0_REG29__DATAHI3:
8248 gen_helper_mtc0_datahi(cpu_env, arg);
8249 register_name = "DataHi";
8250 break;
8251 default:
8252 register_name = "invalid sel";
8253 goto cp0_unimplemented;
8255 break;
8256 case CP0_REGISTER_30:
8257 switch (sel) {
8258 case CP0_REG30__ERROREPC:
8259 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8260 register_name = "ErrorEPC";
8261 break;
8262 default:
8263 goto cp0_unimplemented;
8265 break;
8266 case CP0_REGISTER_31:
8267 switch (sel) {
8268 case CP0_REG31__DESAVE:
8269 /* EJTAG support */
8270 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8271 register_name = "DESAVE";
8272 break;
8273 case CP0_REG31__KSCRATCH1:
8274 case CP0_REG31__KSCRATCH2:
8275 case CP0_REG31__KSCRATCH3:
8276 case CP0_REG31__KSCRATCH4:
8277 case CP0_REG31__KSCRATCH5:
8278 case CP0_REG31__KSCRATCH6:
8279 CP0_CHECK(ctx->kscrexist & (1 << sel));
8280 tcg_gen_st_tl(arg, cpu_env,
8281 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8282 register_name = "KScratch";
8283 break;
8284 default:
8285 goto cp0_unimplemented;
8287 break;
8288 default:
8289 goto cp0_unimplemented;
8291 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8293 /* For simplicity assume that all writes can cause interrupts. */
8294 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8296 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8297 * translated code to check for pending interrupts.
8299 gen_save_pc(ctx->base.pc_next + 4);
8300 ctx->base.is_jmp = DISAS_EXIT;
8302 return;
8304 cp0_unimplemented:
8305 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8306 register_name, reg, sel);
8309 #if defined(TARGET_MIPS64)
8310 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8312 const char *register_name = "invalid";
8314 if (sel != 0) {
8315 check_insn(ctx, ISA_MIPS_R1);
8318 switch (reg) {
8319 case CP0_REGISTER_00:
8320 switch (sel) {
8321 case CP0_REG00__INDEX:
8322 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8323 register_name = "Index";
8324 break;
8325 case CP0_REG00__MVPCONTROL:
8326 CP0_CHECK(ctx->insn_flags & ASE_MT);
8327 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8328 register_name = "MVPControl";
8329 break;
8330 case CP0_REG00__MVPCONF0:
8331 CP0_CHECK(ctx->insn_flags & ASE_MT);
8332 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8333 register_name = "MVPConf0";
8334 break;
8335 case CP0_REG00__MVPCONF1:
8336 CP0_CHECK(ctx->insn_flags & ASE_MT);
8337 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8338 register_name = "MVPConf1";
8339 break;
8340 case CP0_REG00__VPCONTROL:
8341 CP0_CHECK(ctx->vp);
8342 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8343 register_name = "VPControl";
8344 break;
8345 default:
8346 goto cp0_unimplemented;
8348 break;
8349 case CP0_REGISTER_01:
8350 switch (sel) {
8351 case CP0_REG01__RANDOM:
8352 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8353 gen_helper_mfc0_random(arg, cpu_env);
8354 register_name = "Random";
8355 break;
8356 case CP0_REG01__VPECONTROL:
8357 CP0_CHECK(ctx->insn_flags & ASE_MT);
8358 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8359 register_name = "VPEControl";
8360 break;
8361 case CP0_REG01__VPECONF0:
8362 CP0_CHECK(ctx->insn_flags & ASE_MT);
8363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8364 register_name = "VPEConf0";
8365 break;
8366 case CP0_REG01__VPECONF1:
8367 CP0_CHECK(ctx->insn_flags & ASE_MT);
8368 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8369 register_name = "VPEConf1";
8370 break;
8371 case CP0_REG01__YQMASK:
8372 CP0_CHECK(ctx->insn_flags & ASE_MT);
8373 tcg_gen_ld_tl(arg, cpu_env,
8374 offsetof(CPUMIPSState, CP0_YQMask));
8375 register_name = "YQMask";
8376 break;
8377 case CP0_REG01__VPESCHEDULE:
8378 CP0_CHECK(ctx->insn_flags & ASE_MT);
8379 tcg_gen_ld_tl(arg, cpu_env,
8380 offsetof(CPUMIPSState, CP0_VPESchedule));
8381 register_name = "VPESchedule";
8382 break;
8383 case CP0_REG01__VPESCHEFBACK:
8384 CP0_CHECK(ctx->insn_flags & ASE_MT);
8385 tcg_gen_ld_tl(arg, cpu_env,
8386 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8387 register_name = "VPEScheFBack";
8388 break;
8389 case CP0_REG01__VPEOPT:
8390 CP0_CHECK(ctx->insn_flags & ASE_MT);
8391 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8392 register_name = "VPEOpt";
8393 break;
8394 default:
8395 goto cp0_unimplemented;
8397 break;
8398 case CP0_REGISTER_02:
8399 switch (sel) {
8400 case CP0_REG02__ENTRYLO0:
8401 tcg_gen_ld_tl(arg, cpu_env,
8402 offsetof(CPUMIPSState, CP0_EntryLo0));
8403 register_name = "EntryLo0";
8404 break;
8405 case CP0_REG02__TCSTATUS:
8406 CP0_CHECK(ctx->insn_flags & ASE_MT);
8407 gen_helper_mfc0_tcstatus(arg, cpu_env);
8408 register_name = "TCStatus";
8409 break;
8410 case CP0_REG02__TCBIND:
8411 CP0_CHECK(ctx->insn_flags & ASE_MT);
8412 gen_helper_mfc0_tcbind(arg, cpu_env);
8413 register_name = "TCBind";
8414 break;
8415 case CP0_REG02__TCRESTART:
8416 CP0_CHECK(ctx->insn_flags & ASE_MT);
8417 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8418 register_name = "TCRestart";
8419 break;
8420 case CP0_REG02__TCHALT:
8421 CP0_CHECK(ctx->insn_flags & ASE_MT);
8422 gen_helper_dmfc0_tchalt(arg, cpu_env);
8423 register_name = "TCHalt";
8424 break;
8425 case CP0_REG02__TCCONTEXT:
8426 CP0_CHECK(ctx->insn_flags & ASE_MT);
8427 gen_helper_dmfc0_tccontext(arg, cpu_env);
8428 register_name = "TCContext";
8429 break;
8430 case CP0_REG02__TCSCHEDULE:
8431 CP0_CHECK(ctx->insn_flags & ASE_MT);
8432 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8433 register_name = "TCSchedule";
8434 break;
8435 case CP0_REG02__TCSCHEFBACK:
8436 CP0_CHECK(ctx->insn_flags & ASE_MT);
8437 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8438 register_name = "TCScheFBack";
8439 break;
8440 default:
8441 goto cp0_unimplemented;
8443 break;
8444 case CP0_REGISTER_03:
8445 switch (sel) {
8446 case CP0_REG03__ENTRYLO1:
8447 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8448 register_name = "EntryLo1";
8449 break;
8450 case CP0_REG03__GLOBALNUM:
8451 CP0_CHECK(ctx->vp);
8452 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8453 register_name = "GlobalNumber";
8454 break;
8455 default:
8456 goto cp0_unimplemented;
8458 break;
8459 case CP0_REGISTER_04:
8460 switch (sel) {
8461 case CP0_REG04__CONTEXT:
8462 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8463 register_name = "Context";
8464 break;
8465 case CP0_REG04__CONTEXTCONFIG:
8466 /* SmartMIPS ASE */
8467 /* gen_helper_dmfc0_contextconfig(arg); */
8468 register_name = "ContextConfig";
8469 goto cp0_unimplemented;
8470 case CP0_REG04__USERLOCAL:
8471 CP0_CHECK(ctx->ulri);
8472 tcg_gen_ld_tl(arg, cpu_env,
8473 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8474 register_name = "UserLocal";
8475 break;
8476 case CP0_REG04__MMID:
8477 CP0_CHECK(ctx->mi);
8478 gen_helper_mtc0_memorymapid(cpu_env, arg);
8479 register_name = "MMID";
8480 break;
8481 default:
8482 goto cp0_unimplemented;
8484 break;
8485 case CP0_REGISTER_05:
8486 switch (sel) {
8487 case CP0_REG05__PAGEMASK:
8488 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8489 register_name = "PageMask";
8490 break;
8491 case CP0_REG05__PAGEGRAIN:
8492 check_insn(ctx, ISA_MIPS_R2);
8493 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8494 register_name = "PageGrain";
8495 break;
8496 case CP0_REG05__SEGCTL0:
8497 CP0_CHECK(ctx->sc);
8498 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8499 register_name = "SegCtl0";
8500 break;
8501 case CP0_REG05__SEGCTL1:
8502 CP0_CHECK(ctx->sc);
8503 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8504 register_name = "SegCtl1";
8505 break;
8506 case CP0_REG05__SEGCTL2:
8507 CP0_CHECK(ctx->sc);
8508 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8509 register_name = "SegCtl2";
8510 break;
8511 case CP0_REG05__PWBASE:
8512 check_pw(ctx);
8513 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8514 register_name = "PWBase";
8515 break;
8516 case CP0_REG05__PWFIELD:
8517 check_pw(ctx);
8518 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8519 register_name = "PWField";
8520 break;
8521 case CP0_REG05__PWSIZE:
8522 check_pw(ctx);
8523 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8524 register_name = "PWSize";
8525 break;
8526 default:
8527 goto cp0_unimplemented;
8529 break;
8530 case CP0_REGISTER_06:
8531 switch (sel) {
8532 case CP0_REG06__WIRED:
8533 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8534 register_name = "Wired";
8535 break;
8536 case CP0_REG06__SRSCONF0:
8537 check_insn(ctx, ISA_MIPS_R2);
8538 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8539 register_name = "SRSConf0";
8540 break;
8541 case CP0_REG06__SRSCONF1:
8542 check_insn(ctx, ISA_MIPS_R2);
8543 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8544 register_name = "SRSConf1";
8545 break;
8546 case CP0_REG06__SRSCONF2:
8547 check_insn(ctx, ISA_MIPS_R2);
8548 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8549 register_name = "SRSConf2";
8550 break;
8551 case CP0_REG06__SRSCONF3:
8552 check_insn(ctx, ISA_MIPS_R2);
8553 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8554 register_name = "SRSConf3";
8555 break;
8556 case CP0_REG06__SRSCONF4:
8557 check_insn(ctx, ISA_MIPS_R2);
8558 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8559 register_name = "SRSConf4";
8560 break;
8561 case CP0_REG06__PWCTL:
8562 check_pw(ctx);
8563 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8564 register_name = "PWCtl";
8565 break;
8566 default:
8567 goto cp0_unimplemented;
8569 break;
8570 case CP0_REGISTER_07:
8571 switch (sel) {
8572 case CP0_REG07__HWRENA:
8573 check_insn(ctx, ISA_MIPS_R2);
8574 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8575 register_name = "HWREna";
8576 break;
8577 default:
8578 goto cp0_unimplemented;
8580 break;
8581 case CP0_REGISTER_08:
8582 switch (sel) {
8583 case CP0_REG08__BADVADDR:
8584 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8585 register_name = "BadVAddr";
8586 break;
8587 case CP0_REG08__BADINSTR:
8588 CP0_CHECK(ctx->bi);
8589 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8590 register_name = "BadInstr";
8591 break;
8592 case CP0_REG08__BADINSTRP:
8593 CP0_CHECK(ctx->bp);
8594 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8595 register_name = "BadInstrP";
8596 break;
8597 case CP0_REG08__BADINSTRX:
8598 CP0_CHECK(ctx->bi);
8599 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8600 tcg_gen_andi_tl(arg, arg, ~0xffff);
8601 register_name = "BadInstrX";
8602 break;
8603 default:
8604 goto cp0_unimplemented;
8606 break;
8607 case CP0_REGISTER_09:
8608 switch (sel) {
8609 case CP0_REG09__COUNT:
8610 /* Mark as an IO operation because we read the time. */
8611 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8612 gen_io_start();
8614 gen_helper_mfc0_count(arg, cpu_env);
8616 * Break the TB to be able to take timer interrupts immediately
8617 * after reading count. DISAS_STOP isn't sufficient, we need to
8618 * ensure we break completely out of translated code.
8620 gen_save_pc(ctx->base.pc_next + 4);
8621 ctx->base.is_jmp = DISAS_EXIT;
8622 register_name = "Count";
8623 break;
8624 case CP0_REG09__SAARI:
8625 CP0_CHECK(ctx->saar);
8626 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8627 register_name = "SAARI";
8628 break;
8629 case CP0_REG09__SAAR:
8630 CP0_CHECK(ctx->saar);
8631 gen_helper_dmfc0_saar(arg, cpu_env);
8632 register_name = "SAAR";
8633 break;
8634 default:
8635 goto cp0_unimplemented;
8637 break;
8638 case CP0_REGISTER_10:
8639 switch (sel) {
8640 case CP0_REG10__ENTRYHI:
8641 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8642 register_name = "EntryHi";
8643 break;
8644 default:
8645 goto cp0_unimplemented;
8647 break;
8648 case CP0_REGISTER_11:
8649 switch (sel) {
8650 case CP0_REG11__COMPARE:
8651 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8652 register_name = "Compare";
8653 break;
8654 /* 6,7 are implementation dependent */
8655 default:
8656 goto cp0_unimplemented;
8658 break;
8659 case CP0_REGISTER_12:
8660 switch (sel) {
8661 case CP0_REG12__STATUS:
8662 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8663 register_name = "Status";
8664 break;
8665 case CP0_REG12__INTCTL:
8666 check_insn(ctx, ISA_MIPS_R2);
8667 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8668 register_name = "IntCtl";
8669 break;
8670 case CP0_REG12__SRSCTL:
8671 check_insn(ctx, ISA_MIPS_R2);
8672 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8673 register_name = "SRSCtl";
8674 break;
8675 case CP0_REG12__SRSMAP:
8676 check_insn(ctx, ISA_MIPS_R2);
8677 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8678 register_name = "SRSMap";
8679 break;
8680 default:
8681 goto cp0_unimplemented;
8683 break;
8684 case CP0_REGISTER_13:
8685 switch (sel) {
8686 case CP0_REG13__CAUSE:
8687 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8688 register_name = "Cause";
8689 break;
8690 default:
8691 goto cp0_unimplemented;
8693 break;
8694 case CP0_REGISTER_14:
8695 switch (sel) {
8696 case CP0_REG14__EPC:
8697 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8698 register_name = "EPC";
8699 break;
8700 default:
8701 goto cp0_unimplemented;
8703 break;
8704 case CP0_REGISTER_15:
8705 switch (sel) {
8706 case CP0_REG15__PRID:
8707 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8708 register_name = "PRid";
8709 break;
8710 case CP0_REG15__EBASE:
8711 check_insn(ctx, ISA_MIPS_R2);
8712 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8713 register_name = "EBase";
8714 break;
8715 case CP0_REG15__CMGCRBASE:
8716 check_insn(ctx, ISA_MIPS_R2);
8717 CP0_CHECK(ctx->cmgcr);
8718 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8719 register_name = "CMGCRBase";
8720 break;
8721 default:
8722 goto cp0_unimplemented;
8724 break;
8725 case CP0_REGISTER_16:
8726 switch (sel) {
8727 case CP0_REG16__CONFIG:
8728 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8729 register_name = "Config";
8730 break;
8731 case CP0_REG16__CONFIG1:
8732 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8733 register_name = "Config1";
8734 break;
8735 case CP0_REG16__CONFIG2:
8736 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8737 register_name = "Config2";
8738 break;
8739 case CP0_REG16__CONFIG3:
8740 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8741 register_name = "Config3";
8742 break;
8743 case CP0_REG16__CONFIG4:
8744 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8745 register_name = "Config4";
8746 break;
8747 case CP0_REG16__CONFIG5:
8748 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8749 register_name = "Config5";
8750 break;
8751 /* 6,7 are implementation dependent */
8752 case CP0_REG16__CONFIG6:
8753 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8754 register_name = "Config6";
8755 break;
8756 case CP0_REG16__CONFIG7:
8757 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8758 register_name = "Config7";
8759 break;
8760 default:
8761 goto cp0_unimplemented;
8763 break;
8764 case CP0_REGISTER_17:
8765 switch (sel) {
8766 case CP0_REG17__LLADDR:
8767 gen_helper_dmfc0_lladdr(arg, cpu_env);
8768 register_name = "LLAddr";
8769 break;
8770 case CP0_REG17__MAAR:
8771 CP0_CHECK(ctx->mrp);
8772 gen_helper_dmfc0_maar(arg, cpu_env);
8773 register_name = "MAAR";
8774 break;
8775 case CP0_REG17__MAARI:
8776 CP0_CHECK(ctx->mrp);
8777 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8778 register_name = "MAARI";
8779 break;
8780 default:
8781 goto cp0_unimplemented;
8783 break;
8784 case CP0_REGISTER_18:
8785 switch (sel) {
8786 case CP0_REG18__WATCHLO0:
8787 case CP0_REG18__WATCHLO1:
8788 case CP0_REG18__WATCHLO2:
8789 case CP0_REG18__WATCHLO3:
8790 case CP0_REG18__WATCHLO4:
8791 case CP0_REG18__WATCHLO5:
8792 case CP0_REG18__WATCHLO6:
8793 case CP0_REG18__WATCHLO7:
8794 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8795 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8796 register_name = "WatchLo";
8797 break;
8798 default:
8799 goto cp0_unimplemented;
8801 break;
8802 case CP0_REGISTER_19:
8803 switch (sel) {
8804 case CP0_REG19__WATCHHI0:
8805 case CP0_REG19__WATCHHI1:
8806 case CP0_REG19__WATCHHI2:
8807 case CP0_REG19__WATCHHI3:
8808 case CP0_REG19__WATCHHI4:
8809 case CP0_REG19__WATCHHI5:
8810 case CP0_REG19__WATCHHI6:
8811 case CP0_REG19__WATCHHI7:
8812 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8813 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
8814 register_name = "WatchHi";
8815 break;
8816 default:
8817 goto cp0_unimplemented;
8819 break;
8820 case CP0_REGISTER_20:
8821 switch (sel) {
8822 case CP0_REG20__XCONTEXT:
8823 check_insn(ctx, ISA_MIPS3);
8824 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8825 register_name = "XContext";
8826 break;
8827 default:
8828 goto cp0_unimplemented;
8830 break;
8831 case CP0_REGISTER_21:
8832 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8833 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8834 switch (sel) {
8835 case 0:
8836 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8837 register_name = "Framemask";
8838 break;
8839 default:
8840 goto cp0_unimplemented;
8842 break;
8843 case CP0_REGISTER_22:
8844 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8845 register_name = "'Diagnostic"; /* implementation dependent */
8846 break;
8847 case CP0_REGISTER_23:
8848 switch (sel) {
8849 case CP0_REG23__DEBUG:
8850 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8851 register_name = "Debug";
8852 break;
8853 case CP0_REG23__TRACECONTROL:
8854 /* PDtrace support */
8855 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
8856 register_name = "TraceControl";
8857 goto cp0_unimplemented;
8858 case CP0_REG23__TRACECONTROL2:
8859 /* PDtrace support */
8860 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
8861 register_name = "TraceControl2";
8862 goto cp0_unimplemented;
8863 case CP0_REG23__USERTRACEDATA1:
8864 /* PDtrace support */
8865 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
8866 register_name = "UserTraceData1";
8867 goto cp0_unimplemented;
8868 case CP0_REG23__TRACEIBPC:
8869 /* PDtrace support */
8870 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
8871 register_name = "TraceIBPC";
8872 goto cp0_unimplemented;
8873 case CP0_REG23__TRACEDBPC:
8874 /* PDtrace support */
8875 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
8876 register_name = "TraceDBPC";
8877 goto cp0_unimplemented;
8878 default:
8879 goto cp0_unimplemented;
8881 break;
8882 case CP0_REGISTER_24:
8883 switch (sel) {
8884 case CP0_REG24__DEPC:
8885 /* EJTAG support */
8886 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8887 register_name = "DEPC";
8888 break;
8889 default:
8890 goto cp0_unimplemented;
8892 break;
8893 case CP0_REGISTER_25:
8894 switch (sel) {
8895 case CP0_REG25__PERFCTL0:
8896 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8897 register_name = "Performance0";
8898 break;
8899 case CP0_REG25__PERFCNT0:
8900 /* gen_helper_dmfc0_performance1(arg); */
8901 register_name = "Performance1";
8902 goto cp0_unimplemented;
8903 case CP0_REG25__PERFCTL1:
8904 /* gen_helper_dmfc0_performance2(arg); */
8905 register_name = "Performance2";
8906 goto cp0_unimplemented;
8907 case CP0_REG25__PERFCNT1:
8908 /* gen_helper_dmfc0_performance3(arg); */
8909 register_name = "Performance3";
8910 goto cp0_unimplemented;
8911 case CP0_REG25__PERFCTL2:
8912 /* gen_helper_dmfc0_performance4(arg); */
8913 register_name = "Performance4";
8914 goto cp0_unimplemented;
8915 case CP0_REG25__PERFCNT2:
8916 /* gen_helper_dmfc0_performance5(arg); */
8917 register_name = "Performance5";
8918 goto cp0_unimplemented;
8919 case CP0_REG25__PERFCTL3:
8920 /* gen_helper_dmfc0_performance6(arg); */
8921 register_name = "Performance6";
8922 goto cp0_unimplemented;
8923 case CP0_REG25__PERFCNT3:
8924 /* gen_helper_dmfc0_performance7(arg); */
8925 register_name = "Performance7";
8926 goto cp0_unimplemented;
8927 default:
8928 goto cp0_unimplemented;
8930 break;
8931 case CP0_REGISTER_26:
8932 switch (sel) {
8933 case CP0_REG26__ERRCTL:
8934 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8935 register_name = "ErrCtl";
8936 break;
8937 default:
8938 goto cp0_unimplemented;
8940 break;
8941 case CP0_REGISTER_27:
8942 switch (sel) {
8943 /* ignored */
8944 case CP0_REG27__CACHERR:
8945 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8946 register_name = "CacheErr";
8947 break;
8948 default:
8949 goto cp0_unimplemented;
8951 break;
8952 case CP0_REGISTER_28:
8953 switch (sel) {
8954 case CP0_REG28__TAGLO:
8955 case CP0_REG28__TAGLO1:
8956 case CP0_REG28__TAGLO2:
8957 case CP0_REG28__TAGLO3:
8958 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8959 register_name = "TagLo";
8960 break;
8961 case CP0_REG28__DATALO:
8962 case CP0_REG28__DATALO1:
8963 case CP0_REG28__DATALO2:
8964 case CP0_REG28__DATALO3:
8965 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8966 register_name = "DataLo";
8967 break;
8968 default:
8969 goto cp0_unimplemented;
8971 break;
8972 case CP0_REGISTER_29:
8973 switch (sel) {
8974 case CP0_REG29__TAGHI:
8975 case CP0_REG29__TAGHI1:
8976 case CP0_REG29__TAGHI2:
8977 case CP0_REG29__TAGHI3:
8978 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8979 register_name = "TagHi";
8980 break;
8981 case CP0_REG29__DATAHI:
8982 case CP0_REG29__DATAHI1:
8983 case CP0_REG29__DATAHI2:
8984 case CP0_REG29__DATAHI3:
8985 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8986 register_name = "DataHi";
8987 break;
8988 default:
8989 goto cp0_unimplemented;
8991 break;
8992 case CP0_REGISTER_30:
8993 switch (sel) {
8994 case CP0_REG30__ERROREPC:
8995 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8996 register_name = "ErrorEPC";
8997 break;
8998 default:
8999 goto cp0_unimplemented;
9001 break;
9002 case CP0_REGISTER_31:
9003 switch (sel) {
9004 case CP0_REG31__DESAVE:
9005 /* EJTAG support */
9006 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9007 register_name = "DESAVE";
9008 break;
9009 case CP0_REG31__KSCRATCH1:
9010 case CP0_REG31__KSCRATCH2:
9011 case CP0_REG31__KSCRATCH3:
9012 case CP0_REG31__KSCRATCH4:
9013 case CP0_REG31__KSCRATCH5:
9014 case CP0_REG31__KSCRATCH6:
9015 CP0_CHECK(ctx->kscrexist & (1 << sel));
9016 tcg_gen_ld_tl(arg, cpu_env,
9017 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9018 register_name = "KScratch";
9019 break;
9020 default:
9021 goto cp0_unimplemented;
9023 break;
9024 default:
9025 goto cp0_unimplemented;
9027 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9028 return;
9030 cp0_unimplemented:
9031 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9032 register_name, reg, sel);
9033 gen_mfc0_unimplemented(ctx, arg);
9036 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9038 const char *register_name = "invalid";
9040 if (sel != 0) {
9041 check_insn(ctx, ISA_MIPS_R1);
9044 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9045 gen_io_start();
9048 switch (reg) {
9049 case CP0_REGISTER_00:
9050 switch (sel) {
9051 case CP0_REG00__INDEX:
9052 gen_helper_mtc0_index(cpu_env, arg);
9053 register_name = "Index";
9054 break;
9055 case CP0_REG00__MVPCONTROL:
9056 CP0_CHECK(ctx->insn_flags & ASE_MT);
9057 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9058 register_name = "MVPControl";
9059 break;
9060 case CP0_REG00__MVPCONF0:
9061 CP0_CHECK(ctx->insn_flags & ASE_MT);
9062 /* ignored */
9063 register_name = "MVPConf0";
9064 break;
9065 case CP0_REG00__MVPCONF1:
9066 CP0_CHECK(ctx->insn_flags & ASE_MT);
9067 /* ignored */
9068 register_name = "MVPConf1";
9069 break;
9070 case CP0_REG00__VPCONTROL:
9071 CP0_CHECK(ctx->vp);
9072 /* ignored */
9073 register_name = "VPControl";
9074 break;
9075 default:
9076 goto cp0_unimplemented;
9078 break;
9079 case CP0_REGISTER_01:
9080 switch (sel) {
9081 case CP0_REG01__RANDOM:
9082 /* ignored */
9083 register_name = "Random";
9084 break;
9085 case CP0_REG01__VPECONTROL:
9086 CP0_CHECK(ctx->insn_flags & ASE_MT);
9087 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9088 register_name = "VPEControl";
9089 break;
9090 case CP0_REG01__VPECONF0:
9091 CP0_CHECK(ctx->insn_flags & ASE_MT);
9092 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9093 register_name = "VPEConf0";
9094 break;
9095 case CP0_REG01__VPECONF1:
9096 CP0_CHECK(ctx->insn_flags & ASE_MT);
9097 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9098 register_name = "VPEConf1";
9099 break;
9100 case CP0_REG01__YQMASK:
9101 CP0_CHECK(ctx->insn_flags & ASE_MT);
9102 gen_helper_mtc0_yqmask(cpu_env, arg);
9103 register_name = "YQMask";
9104 break;
9105 case CP0_REG01__VPESCHEDULE:
9106 CP0_CHECK(ctx->insn_flags & ASE_MT);
9107 tcg_gen_st_tl(arg, cpu_env,
9108 offsetof(CPUMIPSState, CP0_VPESchedule));
9109 register_name = "VPESchedule";
9110 break;
9111 case CP0_REG01__VPESCHEFBACK:
9112 CP0_CHECK(ctx->insn_flags & ASE_MT);
9113 tcg_gen_st_tl(arg, cpu_env,
9114 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9115 register_name = "VPEScheFBack";
9116 break;
9117 case CP0_REG01__VPEOPT:
9118 CP0_CHECK(ctx->insn_flags & ASE_MT);
9119 gen_helper_mtc0_vpeopt(cpu_env, arg);
9120 register_name = "VPEOpt";
9121 break;
9122 default:
9123 goto cp0_unimplemented;
9125 break;
9126 case CP0_REGISTER_02:
9127 switch (sel) {
9128 case CP0_REG02__ENTRYLO0:
9129 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9130 register_name = "EntryLo0";
9131 break;
9132 case CP0_REG02__TCSTATUS:
9133 CP0_CHECK(ctx->insn_flags & ASE_MT);
9134 gen_helper_mtc0_tcstatus(cpu_env, arg);
9135 register_name = "TCStatus";
9136 break;
9137 case CP0_REG02__TCBIND:
9138 CP0_CHECK(ctx->insn_flags & ASE_MT);
9139 gen_helper_mtc0_tcbind(cpu_env, arg);
9140 register_name = "TCBind";
9141 break;
9142 case CP0_REG02__TCRESTART:
9143 CP0_CHECK(ctx->insn_flags & ASE_MT);
9144 gen_helper_mtc0_tcrestart(cpu_env, arg);
9145 register_name = "TCRestart";
9146 break;
9147 case CP0_REG02__TCHALT:
9148 CP0_CHECK(ctx->insn_flags & ASE_MT);
9149 gen_helper_mtc0_tchalt(cpu_env, arg);
9150 register_name = "TCHalt";
9151 break;
9152 case CP0_REG02__TCCONTEXT:
9153 CP0_CHECK(ctx->insn_flags & ASE_MT);
9154 gen_helper_mtc0_tccontext(cpu_env, arg);
9155 register_name = "TCContext";
9156 break;
9157 case CP0_REG02__TCSCHEDULE:
9158 CP0_CHECK(ctx->insn_flags & ASE_MT);
9159 gen_helper_mtc0_tcschedule(cpu_env, arg);
9160 register_name = "TCSchedule";
9161 break;
9162 case CP0_REG02__TCSCHEFBACK:
9163 CP0_CHECK(ctx->insn_flags & ASE_MT);
9164 gen_helper_mtc0_tcschefback(cpu_env, arg);
9165 register_name = "TCScheFBack";
9166 break;
9167 default:
9168 goto cp0_unimplemented;
9170 break;
9171 case CP0_REGISTER_03:
9172 switch (sel) {
9173 case CP0_REG03__ENTRYLO1:
9174 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9175 register_name = "EntryLo1";
9176 break;
9177 case CP0_REG03__GLOBALNUM:
9178 CP0_CHECK(ctx->vp);
9179 /* ignored */
9180 register_name = "GlobalNumber";
9181 break;
9182 default:
9183 goto cp0_unimplemented;
9185 break;
9186 case CP0_REGISTER_04:
9187 switch (sel) {
9188 case CP0_REG04__CONTEXT:
9189 gen_helper_mtc0_context(cpu_env, arg);
9190 register_name = "Context";
9191 break;
9192 case CP0_REG04__CONTEXTCONFIG:
9193 /* SmartMIPS ASE */
9194 /* gen_helper_dmtc0_contextconfig(arg); */
9195 register_name = "ContextConfig";
9196 goto cp0_unimplemented;
9197 case CP0_REG04__USERLOCAL:
9198 CP0_CHECK(ctx->ulri);
9199 tcg_gen_st_tl(arg, cpu_env,
9200 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9201 register_name = "UserLocal";
9202 break;
9203 case CP0_REG04__MMID:
9204 CP0_CHECK(ctx->mi);
9205 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
9206 register_name = "MMID";
9207 break;
9208 default:
9209 goto cp0_unimplemented;
9211 break;
9212 case CP0_REGISTER_05:
9213 switch (sel) {
9214 case CP0_REG05__PAGEMASK:
9215 gen_helper_mtc0_pagemask(cpu_env, arg);
9216 register_name = "PageMask";
9217 break;
9218 case CP0_REG05__PAGEGRAIN:
9219 check_insn(ctx, ISA_MIPS_R2);
9220 gen_helper_mtc0_pagegrain(cpu_env, arg);
9221 register_name = "PageGrain";
9222 break;
9223 case CP0_REG05__SEGCTL0:
9224 CP0_CHECK(ctx->sc);
9225 gen_helper_mtc0_segctl0(cpu_env, arg);
9226 register_name = "SegCtl0";
9227 break;
9228 case CP0_REG05__SEGCTL1:
9229 CP0_CHECK(ctx->sc);
9230 gen_helper_mtc0_segctl1(cpu_env, arg);
9231 register_name = "SegCtl1";
9232 break;
9233 case CP0_REG05__SEGCTL2:
9234 CP0_CHECK(ctx->sc);
9235 gen_helper_mtc0_segctl2(cpu_env, arg);
9236 register_name = "SegCtl2";
9237 break;
9238 case CP0_REG05__PWBASE:
9239 check_pw(ctx);
9240 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9241 register_name = "PWBase";
9242 break;
9243 case CP0_REG05__PWFIELD:
9244 check_pw(ctx);
9245 gen_helper_mtc0_pwfield(cpu_env, arg);
9246 register_name = "PWField";
9247 break;
9248 case CP0_REG05__PWSIZE:
9249 check_pw(ctx);
9250 gen_helper_mtc0_pwsize(cpu_env, arg);
9251 register_name = "PWSize";
9252 break;
9253 default:
9254 goto cp0_unimplemented;
9256 break;
9257 case CP0_REGISTER_06:
9258 switch (sel) {
9259 case CP0_REG06__WIRED:
9260 gen_helper_mtc0_wired(cpu_env, arg);
9261 register_name = "Wired";
9262 break;
9263 case CP0_REG06__SRSCONF0:
9264 check_insn(ctx, ISA_MIPS_R2);
9265 gen_helper_mtc0_srsconf0(cpu_env, arg);
9266 register_name = "SRSConf0";
9267 break;
9268 case CP0_REG06__SRSCONF1:
9269 check_insn(ctx, ISA_MIPS_R2);
9270 gen_helper_mtc0_srsconf1(cpu_env, arg);
9271 register_name = "SRSConf1";
9272 break;
9273 case CP0_REG06__SRSCONF2:
9274 check_insn(ctx, ISA_MIPS_R2);
9275 gen_helper_mtc0_srsconf2(cpu_env, arg);
9276 register_name = "SRSConf2";
9277 break;
9278 case CP0_REG06__SRSCONF3:
9279 check_insn(ctx, ISA_MIPS_R2);
9280 gen_helper_mtc0_srsconf3(cpu_env, arg);
9281 register_name = "SRSConf3";
9282 break;
9283 case CP0_REG06__SRSCONF4:
9284 check_insn(ctx, ISA_MIPS_R2);
9285 gen_helper_mtc0_srsconf4(cpu_env, arg);
9286 register_name = "SRSConf4";
9287 break;
9288 case CP0_REG06__PWCTL:
9289 check_pw(ctx);
9290 gen_helper_mtc0_pwctl(cpu_env, arg);
9291 register_name = "PWCtl";
9292 break;
9293 default:
9294 goto cp0_unimplemented;
9296 break;
9297 case CP0_REGISTER_07:
9298 switch (sel) {
9299 case CP0_REG07__HWRENA:
9300 check_insn(ctx, ISA_MIPS_R2);
9301 gen_helper_mtc0_hwrena(cpu_env, arg);
9302 ctx->base.is_jmp = DISAS_STOP;
9303 register_name = "HWREna";
9304 break;
9305 default:
9306 goto cp0_unimplemented;
9308 break;
9309 case CP0_REGISTER_08:
9310 switch (sel) {
9311 case CP0_REG08__BADVADDR:
9312 /* ignored */
9313 register_name = "BadVAddr";
9314 break;
9315 case CP0_REG08__BADINSTR:
9316 /* ignored */
9317 register_name = "BadInstr";
9318 break;
9319 case CP0_REG08__BADINSTRP:
9320 /* ignored */
9321 register_name = "BadInstrP";
9322 break;
9323 case CP0_REG08__BADINSTRX:
9324 /* ignored */
9325 register_name = "BadInstrX";
9326 break;
9327 default:
9328 goto cp0_unimplemented;
9330 break;
9331 case CP0_REGISTER_09:
9332 switch (sel) {
9333 case CP0_REG09__COUNT:
9334 gen_helper_mtc0_count(cpu_env, arg);
9335 register_name = "Count";
9336 break;
9337 case CP0_REG09__SAARI:
9338 CP0_CHECK(ctx->saar);
9339 gen_helper_mtc0_saari(cpu_env, arg);
9340 register_name = "SAARI";
9341 break;
9342 case CP0_REG09__SAAR:
9343 CP0_CHECK(ctx->saar);
9344 gen_helper_mtc0_saar(cpu_env, arg);
9345 register_name = "SAAR";
9346 break;
9347 default:
9348 goto cp0_unimplemented;
9350 /* Stop translation as we may have switched the execution mode */
9351 ctx->base.is_jmp = DISAS_STOP;
9352 break;
9353 case CP0_REGISTER_10:
9354 switch (sel) {
9355 case CP0_REG10__ENTRYHI:
9356 gen_helper_mtc0_entryhi(cpu_env, arg);
9357 register_name = "EntryHi";
9358 break;
9359 default:
9360 goto cp0_unimplemented;
9362 break;
9363 case CP0_REGISTER_11:
9364 switch (sel) {
9365 case CP0_REG11__COMPARE:
9366 gen_helper_mtc0_compare(cpu_env, arg);
9367 register_name = "Compare";
9368 break;
9369 /* 6,7 are implementation dependent */
9370 default:
9371 goto cp0_unimplemented;
9373 /* Stop translation as we may have switched the execution mode */
9374 ctx->base.is_jmp = DISAS_STOP;
9375 break;
9376 case CP0_REGISTER_12:
9377 switch (sel) {
9378 case CP0_REG12__STATUS:
9379 save_cpu_state(ctx, 1);
9380 gen_helper_mtc0_status(cpu_env, arg);
9381 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9382 gen_save_pc(ctx->base.pc_next + 4);
9383 ctx->base.is_jmp = DISAS_EXIT;
9384 register_name = "Status";
9385 break;
9386 case CP0_REG12__INTCTL:
9387 check_insn(ctx, ISA_MIPS_R2);
9388 gen_helper_mtc0_intctl(cpu_env, arg);
9389 /* Stop translation as we may have switched the execution mode */
9390 ctx->base.is_jmp = DISAS_STOP;
9391 register_name = "IntCtl";
9392 break;
9393 case CP0_REG12__SRSCTL:
9394 check_insn(ctx, ISA_MIPS_R2);
9395 gen_helper_mtc0_srsctl(cpu_env, arg);
9396 /* Stop translation as we may have switched the execution mode */
9397 ctx->base.is_jmp = DISAS_STOP;
9398 register_name = "SRSCtl";
9399 break;
9400 case CP0_REG12__SRSMAP:
9401 check_insn(ctx, ISA_MIPS_R2);
9402 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9403 /* Stop translation as we may have switched the execution mode */
9404 ctx->base.is_jmp = DISAS_STOP;
9405 register_name = "SRSMap";
9406 break;
9407 default:
9408 goto cp0_unimplemented;
9410 break;
9411 case CP0_REGISTER_13:
9412 switch (sel) {
9413 case CP0_REG13__CAUSE:
9414 save_cpu_state(ctx, 1);
9415 gen_helper_mtc0_cause(cpu_env, arg);
9417 * Stop translation as we may have triggered an interrupt.
9418 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9419 * translated code to check for pending interrupts.
9421 gen_save_pc(ctx->base.pc_next + 4);
9422 ctx->base.is_jmp = DISAS_EXIT;
9423 register_name = "Cause";
9424 break;
9425 default:
9426 goto cp0_unimplemented;
9428 break;
9429 case CP0_REGISTER_14:
9430 switch (sel) {
9431 case CP0_REG14__EPC:
9432 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9433 register_name = "EPC";
9434 break;
9435 default:
9436 goto cp0_unimplemented;
9438 break;
9439 case CP0_REGISTER_15:
9440 switch (sel) {
9441 case CP0_REG15__PRID:
9442 /* ignored */
9443 register_name = "PRid";
9444 break;
9445 case CP0_REG15__EBASE:
9446 check_insn(ctx, ISA_MIPS_R2);
9447 gen_helper_mtc0_ebase(cpu_env, arg);
9448 register_name = "EBase";
9449 break;
9450 default:
9451 goto cp0_unimplemented;
9453 break;
9454 case CP0_REGISTER_16:
9455 switch (sel) {
9456 case CP0_REG16__CONFIG:
9457 gen_helper_mtc0_config0(cpu_env, arg);
9458 register_name = "Config";
9459 /* Stop translation as we may have switched the execution mode */
9460 ctx->base.is_jmp = DISAS_STOP;
9461 break;
9462 case CP0_REG16__CONFIG1:
9463 /* ignored, read only */
9464 register_name = "Config1";
9465 break;
9466 case CP0_REG16__CONFIG2:
9467 gen_helper_mtc0_config2(cpu_env, arg);
9468 register_name = "Config2";
9469 /* Stop translation as we may have switched the execution mode */
9470 ctx->base.is_jmp = DISAS_STOP;
9471 break;
9472 case CP0_REG16__CONFIG3:
9473 gen_helper_mtc0_config3(cpu_env, arg);
9474 register_name = "Config3";
9475 /* Stop translation as we may have switched the execution mode */
9476 ctx->base.is_jmp = DISAS_STOP;
9477 break;
9478 case CP0_REG16__CONFIG4:
9479 /* currently ignored */
9480 register_name = "Config4";
9481 break;
9482 case CP0_REG16__CONFIG5:
9483 gen_helper_mtc0_config5(cpu_env, arg);
9484 register_name = "Config5";
9485 /* Stop translation as we may have switched the execution mode */
9486 ctx->base.is_jmp = DISAS_STOP;
9487 break;
9488 /* 6,7 are implementation dependent */
9489 default:
9490 register_name = "Invalid config selector";
9491 goto cp0_unimplemented;
9493 break;
9494 case CP0_REGISTER_17:
9495 switch (sel) {
9496 case CP0_REG17__LLADDR:
9497 gen_helper_mtc0_lladdr(cpu_env, arg);
9498 register_name = "LLAddr";
9499 break;
9500 case CP0_REG17__MAAR:
9501 CP0_CHECK(ctx->mrp);
9502 gen_helper_mtc0_maar(cpu_env, arg);
9503 register_name = "MAAR";
9504 break;
9505 case CP0_REG17__MAARI:
9506 CP0_CHECK(ctx->mrp);
9507 gen_helper_mtc0_maari(cpu_env, arg);
9508 register_name = "MAARI";
9509 break;
9510 default:
9511 goto cp0_unimplemented;
9513 break;
9514 case CP0_REGISTER_18:
9515 switch (sel) {
9516 case CP0_REG18__WATCHLO0:
9517 case CP0_REG18__WATCHLO1:
9518 case CP0_REG18__WATCHLO2:
9519 case CP0_REG18__WATCHLO3:
9520 case CP0_REG18__WATCHLO4:
9521 case CP0_REG18__WATCHLO5:
9522 case CP0_REG18__WATCHLO6:
9523 case CP0_REG18__WATCHLO7:
9524 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9525 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9526 register_name = "WatchLo";
9527 break;
9528 default:
9529 goto cp0_unimplemented;
9531 break;
9532 case CP0_REGISTER_19:
9533 switch (sel) {
9534 case CP0_REG19__WATCHHI0:
9535 case CP0_REG19__WATCHHI1:
9536 case CP0_REG19__WATCHHI2:
9537 case CP0_REG19__WATCHHI3:
9538 case CP0_REG19__WATCHHI4:
9539 case CP0_REG19__WATCHHI5:
9540 case CP0_REG19__WATCHHI6:
9541 case CP0_REG19__WATCHHI7:
9542 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9543 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9544 register_name = "WatchHi";
9545 break;
9546 default:
9547 goto cp0_unimplemented;
9549 break;
9550 case CP0_REGISTER_20:
9551 switch (sel) {
9552 case CP0_REG20__XCONTEXT:
9553 check_insn(ctx, ISA_MIPS3);
9554 gen_helper_mtc0_xcontext(cpu_env, arg);
9555 register_name = "XContext";
9556 break;
9557 default:
9558 goto cp0_unimplemented;
9560 break;
9561 case CP0_REGISTER_21:
9562 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9563 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9564 switch (sel) {
9565 case 0:
9566 gen_helper_mtc0_framemask(cpu_env, arg);
9567 register_name = "Framemask";
9568 break;
9569 default:
9570 goto cp0_unimplemented;
9572 break;
9573 case CP0_REGISTER_22:
9574 /* ignored */
9575 register_name = "Diagnostic"; /* implementation dependent */
9576 break;
9577 case CP0_REGISTER_23:
9578 switch (sel) {
9579 case CP0_REG23__DEBUG:
9580 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9581 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9582 gen_save_pc(ctx->base.pc_next + 4);
9583 ctx->base.is_jmp = DISAS_EXIT;
9584 register_name = "Debug";
9585 break;
9586 case CP0_REG23__TRACECONTROL:
9587 /* PDtrace support */
9588 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
9589 /* Stop translation as we may have switched the execution mode */
9590 ctx->base.is_jmp = DISAS_STOP;
9591 register_name = "TraceControl";
9592 goto cp0_unimplemented;
9593 case CP0_REG23__TRACECONTROL2:
9594 /* PDtrace support */
9595 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
9596 /* Stop translation as we may have switched the execution mode */
9597 ctx->base.is_jmp = DISAS_STOP;
9598 register_name = "TraceControl2";
9599 goto cp0_unimplemented;
9600 case CP0_REG23__USERTRACEDATA1:
9601 /* PDtrace support */
9602 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
9603 /* Stop translation as we may have switched the execution mode */
9604 ctx->base.is_jmp = DISAS_STOP;
9605 register_name = "UserTraceData1";
9606 goto cp0_unimplemented;
9607 case CP0_REG23__TRACEIBPC:
9608 /* PDtrace support */
9609 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
9610 /* Stop translation as we may have switched the execution mode */
9611 ctx->base.is_jmp = DISAS_STOP;
9612 register_name = "TraceIBPC";
9613 goto cp0_unimplemented;
9614 case CP0_REG23__TRACEDBPC:
9615 /* PDtrace support */
9616 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
9617 /* Stop translation as we may have switched the execution mode */
9618 ctx->base.is_jmp = DISAS_STOP;
9619 register_name = "TraceDBPC";
9620 goto cp0_unimplemented;
9621 default:
9622 goto cp0_unimplemented;
9624 break;
9625 case CP0_REGISTER_24:
9626 switch (sel) {
9627 case CP0_REG24__DEPC:
9628 /* EJTAG support */
9629 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9630 register_name = "DEPC";
9631 break;
9632 default:
9633 goto cp0_unimplemented;
9635 break;
9636 case CP0_REGISTER_25:
9637 switch (sel) {
9638 case CP0_REG25__PERFCTL0:
9639 gen_helper_mtc0_performance0(cpu_env, arg);
9640 register_name = "Performance0";
9641 break;
9642 case CP0_REG25__PERFCNT0:
9643 /* gen_helper_mtc0_performance1(cpu_env, arg); */
9644 register_name = "Performance1";
9645 goto cp0_unimplemented;
9646 case CP0_REG25__PERFCTL1:
9647 /* gen_helper_mtc0_performance2(cpu_env, arg); */
9648 register_name = "Performance2";
9649 goto cp0_unimplemented;
9650 case CP0_REG25__PERFCNT1:
9651 /* gen_helper_mtc0_performance3(cpu_env, arg); */
9652 register_name = "Performance3";
9653 goto cp0_unimplemented;
9654 case CP0_REG25__PERFCTL2:
9655 /* gen_helper_mtc0_performance4(cpu_env, arg); */
9656 register_name = "Performance4";
9657 goto cp0_unimplemented;
9658 case CP0_REG25__PERFCNT2:
9659 /* gen_helper_mtc0_performance5(cpu_env, arg); */
9660 register_name = "Performance5";
9661 goto cp0_unimplemented;
9662 case CP0_REG25__PERFCTL3:
9663 /* gen_helper_mtc0_performance6(cpu_env, arg); */
9664 register_name = "Performance6";
9665 goto cp0_unimplemented;
9666 case CP0_REG25__PERFCNT3:
9667 /* gen_helper_mtc0_performance7(cpu_env, arg); */
9668 register_name = "Performance7";
9669 goto cp0_unimplemented;
9670 default:
9671 goto cp0_unimplemented;
9673 break;
9674 case CP0_REGISTER_26:
9675 switch (sel) {
9676 case CP0_REG26__ERRCTL:
9677 gen_helper_mtc0_errctl(cpu_env, arg);
9678 ctx->base.is_jmp = DISAS_STOP;
9679 register_name = "ErrCtl";
9680 break;
9681 default:
9682 goto cp0_unimplemented;
9684 break;
9685 case CP0_REGISTER_27:
9686 switch (sel) {
9687 case CP0_REG27__CACHERR:
9688 /* ignored */
9689 register_name = "CacheErr";
9690 break;
9691 default:
9692 goto cp0_unimplemented;
9694 break;
9695 case CP0_REGISTER_28:
9696 switch (sel) {
9697 case CP0_REG28__TAGLO:
9698 case CP0_REG28__TAGLO1:
9699 case CP0_REG28__TAGLO2:
9700 case CP0_REG28__TAGLO3:
9701 gen_helper_mtc0_taglo(cpu_env, arg);
9702 register_name = "TagLo";
9703 break;
9704 case CP0_REG28__DATALO:
9705 case CP0_REG28__DATALO1:
9706 case CP0_REG28__DATALO2:
9707 case CP0_REG28__DATALO3:
9708 gen_helper_mtc0_datalo(cpu_env, arg);
9709 register_name = "DataLo";
9710 break;
9711 default:
9712 goto cp0_unimplemented;
9714 break;
9715 case CP0_REGISTER_29:
9716 switch (sel) {
9717 case CP0_REG29__TAGHI:
9718 case CP0_REG29__TAGHI1:
9719 case CP0_REG29__TAGHI2:
9720 case CP0_REG29__TAGHI3:
9721 gen_helper_mtc0_taghi(cpu_env, arg);
9722 register_name = "TagHi";
9723 break;
9724 case CP0_REG29__DATAHI:
9725 case CP0_REG29__DATAHI1:
9726 case CP0_REG29__DATAHI2:
9727 case CP0_REG29__DATAHI3:
9728 gen_helper_mtc0_datahi(cpu_env, arg);
9729 register_name = "DataHi";
9730 break;
9731 default:
9732 register_name = "invalid sel";
9733 goto cp0_unimplemented;
9735 break;
9736 case CP0_REGISTER_30:
9737 switch (sel) {
9738 case CP0_REG30__ERROREPC:
9739 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9740 register_name = "ErrorEPC";
9741 break;
9742 default:
9743 goto cp0_unimplemented;
9745 break;
9746 case CP0_REGISTER_31:
9747 switch (sel) {
9748 case CP0_REG31__DESAVE:
9749 /* EJTAG support */
9750 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9751 register_name = "DESAVE";
9752 break;
9753 case CP0_REG31__KSCRATCH1:
9754 case CP0_REG31__KSCRATCH2:
9755 case CP0_REG31__KSCRATCH3:
9756 case CP0_REG31__KSCRATCH4:
9757 case CP0_REG31__KSCRATCH5:
9758 case CP0_REG31__KSCRATCH6:
9759 CP0_CHECK(ctx->kscrexist & (1 << sel));
9760 tcg_gen_st_tl(arg, cpu_env,
9761 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9762 register_name = "KScratch";
9763 break;
9764 default:
9765 goto cp0_unimplemented;
9767 break;
9768 default:
9769 goto cp0_unimplemented;
9771 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9773 /* For simplicity assume that all writes can cause interrupts. */
9774 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9776 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9777 * translated code to check for pending interrupts.
9779 gen_save_pc(ctx->base.pc_next + 4);
9780 ctx->base.is_jmp = DISAS_EXIT;
9782 return;
9784 cp0_unimplemented:
9785 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9786 register_name, reg, sel);
9788 #endif /* TARGET_MIPS64 */
9790 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9791 int u, int sel, int h)
9793 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9794 TCGv t0 = tcg_temp_local_new();
9796 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9797 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9798 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9799 tcg_gen_movi_tl(t0, -1);
9800 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9801 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9802 tcg_gen_movi_tl(t0, -1);
9803 } else if (u == 0) {
9804 switch (rt) {
9805 case 1:
9806 switch (sel) {
9807 case 1:
9808 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9809 break;
9810 case 2:
9811 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9812 break;
9813 default:
9814 goto die;
9815 break;
9817 break;
9818 case 2:
9819 switch (sel) {
9820 case 1:
9821 gen_helper_mftc0_tcstatus(t0, cpu_env);
9822 break;
9823 case 2:
9824 gen_helper_mftc0_tcbind(t0, cpu_env);
9825 break;
9826 case 3:
9827 gen_helper_mftc0_tcrestart(t0, cpu_env);
9828 break;
9829 case 4:
9830 gen_helper_mftc0_tchalt(t0, cpu_env);
9831 break;
9832 case 5:
9833 gen_helper_mftc0_tccontext(t0, cpu_env);
9834 break;
9835 case 6:
9836 gen_helper_mftc0_tcschedule(t0, cpu_env);
9837 break;
9838 case 7:
9839 gen_helper_mftc0_tcschefback(t0, cpu_env);
9840 break;
9841 default:
9842 gen_mfc0(ctx, t0, rt, sel);
9843 break;
9845 break;
9846 case 10:
9847 switch (sel) {
9848 case 0:
9849 gen_helper_mftc0_entryhi(t0, cpu_env);
9850 break;
9851 default:
9852 gen_mfc0(ctx, t0, rt, sel);
9853 break;
9855 break;
9856 case 12:
9857 switch (sel) {
9858 case 0:
9859 gen_helper_mftc0_status(t0, cpu_env);
9860 break;
9861 default:
9862 gen_mfc0(ctx, t0, rt, sel);
9863 break;
9865 break;
9866 case 13:
9867 switch (sel) {
9868 case 0:
9869 gen_helper_mftc0_cause(t0, cpu_env);
9870 break;
9871 default:
9872 goto die;
9873 break;
9875 break;
9876 case 14:
9877 switch (sel) {
9878 case 0:
9879 gen_helper_mftc0_epc(t0, cpu_env);
9880 break;
9881 default:
9882 goto die;
9883 break;
9885 break;
9886 case 15:
9887 switch (sel) {
9888 case 1:
9889 gen_helper_mftc0_ebase(t0, cpu_env);
9890 break;
9891 default:
9892 goto die;
9893 break;
9895 break;
9896 case 16:
9897 switch (sel) {
9898 case 0:
9899 case 1:
9900 case 2:
9901 case 3:
9902 case 4:
9903 case 5:
9904 case 6:
9905 case 7:
9906 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9907 break;
9908 default:
9909 goto die;
9910 break;
9912 break;
9913 case 23:
9914 switch (sel) {
9915 case 0:
9916 gen_helper_mftc0_debug(t0, cpu_env);
9917 break;
9918 default:
9919 gen_mfc0(ctx, t0, rt, sel);
9920 break;
9922 break;
9923 default:
9924 gen_mfc0(ctx, t0, rt, sel);
9926 } else {
9927 switch (sel) {
9928 /* GPR registers. */
9929 case 0:
9930 gen_helper_1e0i(mftgpr, t0, rt);
9931 break;
9932 /* Auxiliary CPU registers */
9933 case 1:
9934 switch (rt) {
9935 case 0:
9936 gen_helper_1e0i(mftlo, t0, 0);
9937 break;
9938 case 1:
9939 gen_helper_1e0i(mfthi, t0, 0);
9940 break;
9941 case 2:
9942 gen_helper_1e0i(mftacx, t0, 0);
9943 break;
9944 case 4:
9945 gen_helper_1e0i(mftlo, t0, 1);
9946 break;
9947 case 5:
9948 gen_helper_1e0i(mfthi, t0, 1);
9949 break;
9950 case 6:
9951 gen_helper_1e0i(mftacx, t0, 1);
9952 break;
9953 case 8:
9954 gen_helper_1e0i(mftlo, t0, 2);
9955 break;
9956 case 9:
9957 gen_helper_1e0i(mfthi, t0, 2);
9958 break;
9959 case 10:
9960 gen_helper_1e0i(mftacx, t0, 2);
9961 break;
9962 case 12:
9963 gen_helper_1e0i(mftlo, t0, 3);
9964 break;
9965 case 13:
9966 gen_helper_1e0i(mfthi, t0, 3);
9967 break;
9968 case 14:
9969 gen_helper_1e0i(mftacx, t0, 3);
9970 break;
9971 case 16:
9972 gen_helper_mftdsp(t0, cpu_env);
9973 break;
9974 default:
9975 goto die;
9977 break;
9978 /* Floating point (COP1). */
9979 case 2:
9980 /* XXX: For now we support only a single FPU context. */
9981 if (h == 0) {
9982 TCGv_i32 fp0 = tcg_temp_new_i32();
9984 gen_load_fpr32(ctx, fp0, rt);
9985 tcg_gen_ext_i32_tl(t0, fp0);
9986 tcg_temp_free_i32(fp0);
9987 } else {
9988 TCGv_i32 fp0 = tcg_temp_new_i32();
9990 gen_load_fpr32h(ctx, fp0, rt);
9991 tcg_gen_ext_i32_tl(t0, fp0);
9992 tcg_temp_free_i32(fp0);
9994 break;
9995 case 3:
9996 /* XXX: For now we support only a single FPU context. */
9997 gen_helper_1e0i(cfc1, t0, rt);
9998 break;
9999 /* COP2: Not implemented. */
10000 case 4:
10001 case 5:
10002 /* fall through */
10003 default:
10004 goto die;
10007 trace_mips_translate_tr("mftr", rt, u, sel, h);
10008 gen_store_gpr(t0, rd);
10009 tcg_temp_free(t0);
10010 return;
10012 die:
10013 tcg_temp_free(t0);
10014 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
10015 gen_reserved_instruction(ctx);
10018 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
10019 int u, int sel, int h)
10021 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10022 TCGv t0 = tcg_temp_local_new();
10024 gen_load_gpr(t0, rt);
10025 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10026 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10027 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10028 /* NOP */
10030 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10031 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10032 /* NOP */
10034 } else if (u == 0) {
10035 switch (rd) {
10036 case 1:
10037 switch (sel) {
10038 case 1:
10039 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10040 break;
10041 case 2:
10042 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10043 break;
10044 default:
10045 goto die;
10046 break;
10048 break;
10049 case 2:
10050 switch (sel) {
10051 case 1:
10052 gen_helper_mttc0_tcstatus(cpu_env, t0);
10053 break;
10054 case 2:
10055 gen_helper_mttc0_tcbind(cpu_env, t0);
10056 break;
10057 case 3:
10058 gen_helper_mttc0_tcrestart(cpu_env, t0);
10059 break;
10060 case 4:
10061 gen_helper_mttc0_tchalt(cpu_env, t0);
10062 break;
10063 case 5:
10064 gen_helper_mttc0_tccontext(cpu_env, t0);
10065 break;
10066 case 6:
10067 gen_helper_mttc0_tcschedule(cpu_env, t0);
10068 break;
10069 case 7:
10070 gen_helper_mttc0_tcschefback(cpu_env, t0);
10071 break;
10072 default:
10073 gen_mtc0(ctx, t0, rd, sel);
10074 break;
10076 break;
10077 case 10:
10078 switch (sel) {
10079 case 0:
10080 gen_helper_mttc0_entryhi(cpu_env, t0);
10081 break;
10082 default:
10083 gen_mtc0(ctx, t0, rd, sel);
10084 break;
10086 break;
10087 case 12:
10088 switch (sel) {
10089 case 0:
10090 gen_helper_mttc0_status(cpu_env, t0);
10091 break;
10092 default:
10093 gen_mtc0(ctx, t0, rd, sel);
10094 break;
10096 break;
10097 case 13:
10098 switch (sel) {
10099 case 0:
10100 gen_helper_mttc0_cause(cpu_env, t0);
10101 break;
10102 default:
10103 goto die;
10104 break;
10106 break;
10107 case 15:
10108 switch (sel) {
10109 case 1:
10110 gen_helper_mttc0_ebase(cpu_env, t0);
10111 break;
10112 default:
10113 goto die;
10114 break;
10116 break;
10117 case 23:
10118 switch (sel) {
10119 case 0:
10120 gen_helper_mttc0_debug(cpu_env, t0);
10121 break;
10122 default:
10123 gen_mtc0(ctx, t0, rd, sel);
10124 break;
10126 break;
10127 default:
10128 gen_mtc0(ctx, t0, rd, sel);
10130 } else {
10131 switch (sel) {
10132 /* GPR registers. */
10133 case 0:
10134 gen_helper_0e1i(mttgpr, t0, rd);
10135 break;
10136 /* Auxiliary CPU registers */
10137 case 1:
10138 switch (rd) {
10139 case 0:
10140 gen_helper_0e1i(mttlo, t0, 0);
10141 break;
10142 case 1:
10143 gen_helper_0e1i(mtthi, t0, 0);
10144 break;
10145 case 2:
10146 gen_helper_0e1i(mttacx, t0, 0);
10147 break;
10148 case 4:
10149 gen_helper_0e1i(mttlo, t0, 1);
10150 break;
10151 case 5:
10152 gen_helper_0e1i(mtthi, t0, 1);
10153 break;
10154 case 6:
10155 gen_helper_0e1i(mttacx, t0, 1);
10156 break;
10157 case 8:
10158 gen_helper_0e1i(mttlo, t0, 2);
10159 break;
10160 case 9:
10161 gen_helper_0e1i(mtthi, t0, 2);
10162 break;
10163 case 10:
10164 gen_helper_0e1i(mttacx, t0, 2);
10165 break;
10166 case 12:
10167 gen_helper_0e1i(mttlo, t0, 3);
10168 break;
10169 case 13:
10170 gen_helper_0e1i(mtthi, t0, 3);
10171 break;
10172 case 14:
10173 gen_helper_0e1i(mttacx, t0, 3);
10174 break;
10175 case 16:
10176 gen_helper_mttdsp(cpu_env, t0);
10177 break;
10178 default:
10179 goto die;
10181 break;
10182 /* Floating point (COP1). */
10183 case 2:
10184 /* XXX: For now we support only a single FPU context. */
10185 if (h == 0) {
10186 TCGv_i32 fp0 = tcg_temp_new_i32();
10188 tcg_gen_trunc_tl_i32(fp0, t0);
10189 gen_store_fpr32(ctx, fp0, rd);
10190 tcg_temp_free_i32(fp0);
10191 } else {
10192 TCGv_i32 fp0 = tcg_temp_new_i32();
10194 tcg_gen_trunc_tl_i32(fp0, t0);
10195 gen_store_fpr32h(ctx, fp0, rd);
10196 tcg_temp_free_i32(fp0);
10198 break;
10199 case 3:
10200 /* XXX: For now we support only a single FPU context. */
10202 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10204 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10205 tcg_temp_free_i32(fs_tmp);
10207 /* Stop translation as we may have changed hflags */
10208 ctx->base.is_jmp = DISAS_STOP;
10209 break;
10210 /* COP2: Not implemented. */
10211 case 4:
10212 case 5:
10213 /* fall through */
10214 default:
10215 goto die;
10218 trace_mips_translate_tr("mttr", rd, u, sel, h);
10219 tcg_temp_free(t0);
10220 return;
10222 die:
10223 tcg_temp_free(t0);
10224 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10225 gen_reserved_instruction(ctx);
10228 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10229 int rt, int rd)
10231 const char *opn = "ldst";
10233 check_cp0_enabled(ctx);
10234 switch (opc) {
10235 case OPC_MFC0:
10236 if (rt == 0) {
10237 /* Treat as NOP. */
10238 return;
10240 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10241 opn = "mfc0";
10242 break;
10243 case OPC_MTC0:
10245 TCGv t0 = tcg_temp_new();
10247 gen_load_gpr(t0, rt);
10248 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10249 tcg_temp_free(t0);
10251 opn = "mtc0";
10252 break;
10253 #if defined(TARGET_MIPS64)
10254 case OPC_DMFC0:
10255 check_insn(ctx, ISA_MIPS3);
10256 if (rt == 0) {
10257 /* Treat as NOP. */
10258 return;
10260 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10261 opn = "dmfc0";
10262 break;
10263 case OPC_DMTC0:
10264 check_insn(ctx, ISA_MIPS3);
10266 TCGv t0 = tcg_temp_new();
10268 gen_load_gpr(t0, rt);
10269 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10270 tcg_temp_free(t0);
10272 opn = "dmtc0";
10273 break;
10274 #endif
10275 case OPC_MFHC0:
10276 check_mvh(ctx);
10277 if (rt == 0) {
10278 /* Treat as NOP. */
10279 return;
10281 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10282 opn = "mfhc0";
10283 break;
10284 case OPC_MTHC0:
10285 check_mvh(ctx);
10287 TCGv t0 = tcg_temp_new();
10288 gen_load_gpr(t0, rt);
10289 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10290 tcg_temp_free(t0);
10292 opn = "mthc0";
10293 break;
10294 case OPC_MFTR:
10295 check_cp0_enabled(ctx);
10296 if (rd == 0) {
10297 /* Treat as NOP. */
10298 return;
10300 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10301 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10302 opn = "mftr";
10303 break;
10304 case OPC_MTTR:
10305 check_cp0_enabled(ctx);
10306 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10307 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10308 opn = "mttr";
10309 break;
10310 case OPC_TLBWI:
10311 opn = "tlbwi";
10312 if (!env->tlb->helper_tlbwi) {
10313 goto die;
10315 gen_helper_tlbwi(cpu_env);
10316 break;
10317 case OPC_TLBINV:
10318 opn = "tlbinv";
10319 if (ctx->ie >= 2) {
10320 if (!env->tlb->helper_tlbinv) {
10321 goto die;
10323 gen_helper_tlbinv(cpu_env);
10324 } /* treat as nop if TLBINV not supported */
10325 break;
10326 case OPC_TLBINVF:
10327 opn = "tlbinvf";
10328 if (ctx->ie >= 2) {
10329 if (!env->tlb->helper_tlbinvf) {
10330 goto die;
10332 gen_helper_tlbinvf(cpu_env);
10333 } /* treat as nop if TLBINV not supported */
10334 break;
10335 case OPC_TLBWR:
10336 opn = "tlbwr";
10337 if (!env->tlb->helper_tlbwr) {
10338 goto die;
10340 gen_helper_tlbwr(cpu_env);
10341 break;
10342 case OPC_TLBP:
10343 opn = "tlbp";
10344 if (!env->tlb->helper_tlbp) {
10345 goto die;
10347 gen_helper_tlbp(cpu_env);
10348 break;
10349 case OPC_TLBR:
10350 opn = "tlbr";
10351 if (!env->tlb->helper_tlbr) {
10352 goto die;
10354 gen_helper_tlbr(cpu_env);
10355 break;
10356 case OPC_ERET: /* OPC_ERETNC */
10357 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10358 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10359 goto die;
10360 } else {
10361 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10362 if (ctx->opcode & (1 << bit_shift)) {
10363 /* OPC_ERETNC */
10364 opn = "eretnc";
10365 check_insn(ctx, ISA_MIPS_R5);
10366 gen_helper_eretnc(cpu_env);
10367 } else {
10368 /* OPC_ERET */
10369 opn = "eret";
10370 check_insn(ctx, ISA_MIPS2);
10371 gen_helper_eret(cpu_env);
10373 ctx->base.is_jmp = DISAS_EXIT;
10375 break;
10376 case OPC_DERET:
10377 opn = "deret";
10378 check_insn(ctx, ISA_MIPS_R1);
10379 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10380 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10381 goto die;
10383 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10384 MIPS_INVAL(opn);
10385 gen_reserved_instruction(ctx);
10386 } else {
10387 gen_helper_deret(cpu_env);
10388 ctx->base.is_jmp = DISAS_EXIT;
10390 break;
10391 case OPC_WAIT:
10392 opn = "wait";
10393 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
10394 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10395 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10396 goto die;
10398 /* If we get an exception, we want to restart at next instruction */
10399 ctx->base.pc_next += 4;
10400 save_cpu_state(ctx, 1);
10401 ctx->base.pc_next -= 4;
10402 gen_helper_wait(cpu_env);
10403 ctx->base.is_jmp = DISAS_NORETURN;
10404 break;
10405 default:
10406 die:
10407 MIPS_INVAL(opn);
10408 gen_reserved_instruction(ctx);
10409 return;
10411 (void)opn; /* avoid a compiler warning */
10413 #endif /* !CONFIG_USER_ONLY */
10415 /* CP1 Branches (before delay slot) */
10416 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10417 int32_t cc, int32_t offset)
10419 target_ulong btarget;
10420 TCGv_i32 t0 = tcg_temp_new_i32();
10422 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10423 gen_reserved_instruction(ctx);
10424 goto out;
10427 if (cc != 0) {
10428 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
10431 btarget = ctx->base.pc_next + 4 + offset;
10433 switch (op) {
10434 case OPC_BC1F:
10435 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10436 tcg_gen_not_i32(t0, t0);
10437 tcg_gen_andi_i32(t0, t0, 1);
10438 tcg_gen_extu_i32_tl(bcond, t0);
10439 goto not_likely;
10440 case OPC_BC1FL:
10441 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10442 tcg_gen_not_i32(t0, t0);
10443 tcg_gen_andi_i32(t0, t0, 1);
10444 tcg_gen_extu_i32_tl(bcond, t0);
10445 goto likely;
10446 case OPC_BC1T:
10447 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10448 tcg_gen_andi_i32(t0, t0, 1);
10449 tcg_gen_extu_i32_tl(bcond, t0);
10450 goto not_likely;
10451 case OPC_BC1TL:
10452 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10453 tcg_gen_andi_i32(t0, t0, 1);
10454 tcg_gen_extu_i32_tl(bcond, t0);
10455 likely:
10456 ctx->hflags |= MIPS_HFLAG_BL;
10457 break;
10458 case OPC_BC1FANY2:
10460 TCGv_i32 t1 = tcg_temp_new_i32();
10461 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10462 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10463 tcg_gen_nand_i32(t0, t0, t1);
10464 tcg_temp_free_i32(t1);
10465 tcg_gen_andi_i32(t0, t0, 1);
10466 tcg_gen_extu_i32_tl(bcond, t0);
10468 goto not_likely;
10469 case OPC_BC1TANY2:
10471 TCGv_i32 t1 = tcg_temp_new_i32();
10472 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10473 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10474 tcg_gen_or_i32(t0, t0, t1);
10475 tcg_temp_free_i32(t1);
10476 tcg_gen_andi_i32(t0, t0, 1);
10477 tcg_gen_extu_i32_tl(bcond, t0);
10479 goto not_likely;
10480 case OPC_BC1FANY4:
10482 TCGv_i32 t1 = tcg_temp_new_i32();
10483 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10484 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10485 tcg_gen_and_i32(t0, t0, t1);
10486 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10487 tcg_gen_and_i32(t0, t0, t1);
10488 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10489 tcg_gen_nand_i32(t0, t0, t1);
10490 tcg_temp_free_i32(t1);
10491 tcg_gen_andi_i32(t0, t0, 1);
10492 tcg_gen_extu_i32_tl(bcond, t0);
10494 goto not_likely;
10495 case OPC_BC1TANY4:
10497 TCGv_i32 t1 = tcg_temp_new_i32();
10498 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10499 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10500 tcg_gen_or_i32(t0, t0, t1);
10501 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10502 tcg_gen_or_i32(t0, t0, t1);
10503 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10504 tcg_gen_or_i32(t0, t0, t1);
10505 tcg_temp_free_i32(t1);
10506 tcg_gen_andi_i32(t0, t0, 1);
10507 tcg_gen_extu_i32_tl(bcond, t0);
10509 not_likely:
10510 ctx->hflags |= MIPS_HFLAG_BC;
10511 break;
10512 default:
10513 MIPS_INVAL("cp1 cond branch");
10514 gen_reserved_instruction(ctx);
10515 goto out;
10517 ctx->btarget = btarget;
10518 ctx->hflags |= MIPS_HFLAG_BDS32;
10519 out:
10520 tcg_temp_free_i32(t0);
10523 /* R6 CP1 Branches */
10524 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10525 int32_t ft, int32_t offset,
10526 int delayslot_size)
10528 target_ulong btarget;
10529 TCGv_i64 t0 = tcg_temp_new_i64();
10531 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10532 #ifdef MIPS_DEBUG_DISAS
10533 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10534 "\n", ctx->base.pc_next);
10535 #endif
10536 gen_reserved_instruction(ctx);
10537 goto out;
10540 gen_load_fpr64(ctx, t0, ft);
10541 tcg_gen_andi_i64(t0, t0, 1);
10543 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10545 switch (op) {
10546 case OPC_BC1EQZ:
10547 tcg_gen_xori_i64(t0, t0, 1);
10548 ctx->hflags |= MIPS_HFLAG_BC;
10549 break;
10550 case OPC_BC1NEZ:
10551 /* t0 already set */
10552 ctx->hflags |= MIPS_HFLAG_BC;
10553 break;
10554 default:
10555 MIPS_INVAL("cp1 cond branch");
10556 gen_reserved_instruction(ctx);
10557 goto out;
10560 tcg_gen_trunc_i64_tl(bcond, t0);
10562 ctx->btarget = btarget;
10564 switch (delayslot_size) {
10565 case 2:
10566 ctx->hflags |= MIPS_HFLAG_BDS16;
10567 break;
10568 case 4:
10569 ctx->hflags |= MIPS_HFLAG_BDS32;
10570 break;
10573 out:
10574 tcg_temp_free_i64(t0);
10577 /* Coprocessor 1 (FPU) */
10579 #define FOP(func, fmt) (((fmt) << 21) | (func))
10581 enum fopcode {
10582 OPC_ADD_S = FOP(0, FMT_S),
10583 OPC_SUB_S = FOP(1, FMT_S),
10584 OPC_MUL_S = FOP(2, FMT_S),
10585 OPC_DIV_S = FOP(3, FMT_S),
10586 OPC_SQRT_S = FOP(4, FMT_S),
10587 OPC_ABS_S = FOP(5, FMT_S),
10588 OPC_MOV_S = FOP(6, FMT_S),
10589 OPC_NEG_S = FOP(7, FMT_S),
10590 OPC_ROUND_L_S = FOP(8, FMT_S),
10591 OPC_TRUNC_L_S = FOP(9, FMT_S),
10592 OPC_CEIL_L_S = FOP(10, FMT_S),
10593 OPC_FLOOR_L_S = FOP(11, FMT_S),
10594 OPC_ROUND_W_S = FOP(12, FMT_S),
10595 OPC_TRUNC_W_S = FOP(13, FMT_S),
10596 OPC_CEIL_W_S = FOP(14, FMT_S),
10597 OPC_FLOOR_W_S = FOP(15, FMT_S),
10598 OPC_SEL_S = FOP(16, FMT_S),
10599 OPC_MOVCF_S = FOP(17, FMT_S),
10600 OPC_MOVZ_S = FOP(18, FMT_S),
10601 OPC_MOVN_S = FOP(19, FMT_S),
10602 OPC_SELEQZ_S = FOP(20, FMT_S),
10603 OPC_RECIP_S = FOP(21, FMT_S),
10604 OPC_RSQRT_S = FOP(22, FMT_S),
10605 OPC_SELNEZ_S = FOP(23, FMT_S),
10606 OPC_MADDF_S = FOP(24, FMT_S),
10607 OPC_MSUBF_S = FOP(25, FMT_S),
10608 OPC_RINT_S = FOP(26, FMT_S),
10609 OPC_CLASS_S = FOP(27, FMT_S),
10610 OPC_MIN_S = FOP(28, FMT_S),
10611 OPC_RECIP2_S = FOP(28, FMT_S),
10612 OPC_MINA_S = FOP(29, FMT_S),
10613 OPC_RECIP1_S = FOP(29, FMT_S),
10614 OPC_MAX_S = FOP(30, FMT_S),
10615 OPC_RSQRT1_S = FOP(30, FMT_S),
10616 OPC_MAXA_S = FOP(31, FMT_S),
10617 OPC_RSQRT2_S = FOP(31, FMT_S),
10618 OPC_CVT_D_S = FOP(33, FMT_S),
10619 OPC_CVT_W_S = FOP(36, FMT_S),
10620 OPC_CVT_L_S = FOP(37, FMT_S),
10621 OPC_CVT_PS_S = FOP(38, FMT_S),
10622 OPC_CMP_F_S = FOP(48, FMT_S),
10623 OPC_CMP_UN_S = FOP(49, FMT_S),
10624 OPC_CMP_EQ_S = FOP(50, FMT_S),
10625 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10626 OPC_CMP_OLT_S = FOP(52, FMT_S),
10627 OPC_CMP_ULT_S = FOP(53, FMT_S),
10628 OPC_CMP_OLE_S = FOP(54, FMT_S),
10629 OPC_CMP_ULE_S = FOP(55, FMT_S),
10630 OPC_CMP_SF_S = FOP(56, FMT_S),
10631 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10632 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10633 OPC_CMP_NGL_S = FOP(59, FMT_S),
10634 OPC_CMP_LT_S = FOP(60, FMT_S),
10635 OPC_CMP_NGE_S = FOP(61, FMT_S),
10636 OPC_CMP_LE_S = FOP(62, FMT_S),
10637 OPC_CMP_NGT_S = FOP(63, FMT_S),
10639 OPC_ADD_D = FOP(0, FMT_D),
10640 OPC_SUB_D = FOP(1, FMT_D),
10641 OPC_MUL_D = FOP(2, FMT_D),
10642 OPC_DIV_D = FOP(3, FMT_D),
10643 OPC_SQRT_D = FOP(4, FMT_D),
10644 OPC_ABS_D = FOP(5, FMT_D),
10645 OPC_MOV_D = FOP(6, FMT_D),
10646 OPC_NEG_D = FOP(7, FMT_D),
10647 OPC_ROUND_L_D = FOP(8, FMT_D),
10648 OPC_TRUNC_L_D = FOP(9, FMT_D),
10649 OPC_CEIL_L_D = FOP(10, FMT_D),
10650 OPC_FLOOR_L_D = FOP(11, FMT_D),
10651 OPC_ROUND_W_D = FOP(12, FMT_D),
10652 OPC_TRUNC_W_D = FOP(13, FMT_D),
10653 OPC_CEIL_W_D = FOP(14, FMT_D),
10654 OPC_FLOOR_W_D = FOP(15, FMT_D),
10655 OPC_SEL_D = FOP(16, FMT_D),
10656 OPC_MOVCF_D = FOP(17, FMT_D),
10657 OPC_MOVZ_D = FOP(18, FMT_D),
10658 OPC_MOVN_D = FOP(19, FMT_D),
10659 OPC_SELEQZ_D = FOP(20, FMT_D),
10660 OPC_RECIP_D = FOP(21, FMT_D),
10661 OPC_RSQRT_D = FOP(22, FMT_D),
10662 OPC_SELNEZ_D = FOP(23, FMT_D),
10663 OPC_MADDF_D = FOP(24, FMT_D),
10664 OPC_MSUBF_D = FOP(25, FMT_D),
10665 OPC_RINT_D = FOP(26, FMT_D),
10666 OPC_CLASS_D = FOP(27, FMT_D),
10667 OPC_MIN_D = FOP(28, FMT_D),
10668 OPC_RECIP2_D = FOP(28, FMT_D),
10669 OPC_MINA_D = FOP(29, FMT_D),
10670 OPC_RECIP1_D = FOP(29, FMT_D),
10671 OPC_MAX_D = FOP(30, FMT_D),
10672 OPC_RSQRT1_D = FOP(30, FMT_D),
10673 OPC_MAXA_D = FOP(31, FMT_D),
10674 OPC_RSQRT2_D = FOP(31, FMT_D),
10675 OPC_CVT_S_D = FOP(32, FMT_D),
10676 OPC_CVT_W_D = FOP(36, FMT_D),
10677 OPC_CVT_L_D = FOP(37, FMT_D),
10678 OPC_CMP_F_D = FOP(48, FMT_D),
10679 OPC_CMP_UN_D = FOP(49, FMT_D),
10680 OPC_CMP_EQ_D = FOP(50, FMT_D),
10681 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10682 OPC_CMP_OLT_D = FOP(52, FMT_D),
10683 OPC_CMP_ULT_D = FOP(53, FMT_D),
10684 OPC_CMP_OLE_D = FOP(54, FMT_D),
10685 OPC_CMP_ULE_D = FOP(55, FMT_D),
10686 OPC_CMP_SF_D = FOP(56, FMT_D),
10687 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10688 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10689 OPC_CMP_NGL_D = FOP(59, FMT_D),
10690 OPC_CMP_LT_D = FOP(60, FMT_D),
10691 OPC_CMP_NGE_D = FOP(61, FMT_D),
10692 OPC_CMP_LE_D = FOP(62, FMT_D),
10693 OPC_CMP_NGT_D = FOP(63, FMT_D),
10695 OPC_CVT_S_W = FOP(32, FMT_W),
10696 OPC_CVT_D_W = FOP(33, FMT_W),
10697 OPC_CVT_S_L = FOP(32, FMT_L),
10698 OPC_CVT_D_L = FOP(33, FMT_L),
10699 OPC_CVT_PS_PW = FOP(38, FMT_W),
10701 OPC_ADD_PS = FOP(0, FMT_PS),
10702 OPC_SUB_PS = FOP(1, FMT_PS),
10703 OPC_MUL_PS = FOP(2, FMT_PS),
10704 OPC_DIV_PS = FOP(3, FMT_PS),
10705 OPC_ABS_PS = FOP(5, FMT_PS),
10706 OPC_MOV_PS = FOP(6, FMT_PS),
10707 OPC_NEG_PS = FOP(7, FMT_PS),
10708 OPC_MOVCF_PS = FOP(17, FMT_PS),
10709 OPC_MOVZ_PS = FOP(18, FMT_PS),
10710 OPC_MOVN_PS = FOP(19, FMT_PS),
10711 OPC_ADDR_PS = FOP(24, FMT_PS),
10712 OPC_MULR_PS = FOP(26, FMT_PS),
10713 OPC_RECIP2_PS = FOP(28, FMT_PS),
10714 OPC_RECIP1_PS = FOP(29, FMT_PS),
10715 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10716 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10718 OPC_CVT_S_PU = FOP(32, FMT_PS),
10719 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10720 OPC_CVT_S_PL = FOP(40, FMT_PS),
10721 OPC_PLL_PS = FOP(44, FMT_PS),
10722 OPC_PLU_PS = FOP(45, FMT_PS),
10723 OPC_PUL_PS = FOP(46, FMT_PS),
10724 OPC_PUU_PS = FOP(47, FMT_PS),
10725 OPC_CMP_F_PS = FOP(48, FMT_PS),
10726 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10727 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10728 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10729 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10730 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10731 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10732 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10733 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10734 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10735 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10736 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10737 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10738 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10739 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10740 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
10743 enum r6_f_cmp_op {
10744 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10745 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10746 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10747 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10748 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10749 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10750 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10751 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10752 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10753 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10754 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10755 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10756 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10757 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10758 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10759 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10760 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10761 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10762 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10763 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10764 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10765 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10767 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10768 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10769 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10770 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10771 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10772 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10773 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10774 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10775 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10776 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10777 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10778 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10779 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10780 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10781 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10782 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10783 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10784 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10785 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10786 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10787 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10788 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10791 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
10793 TCGv t0 = tcg_temp_new();
10795 switch (opc) {
10796 case OPC_MFC1:
10798 TCGv_i32 fp0 = tcg_temp_new_i32();
10800 gen_load_fpr32(ctx, fp0, fs);
10801 tcg_gen_ext_i32_tl(t0, fp0);
10802 tcg_temp_free_i32(fp0);
10804 gen_store_gpr(t0, rt);
10805 break;
10806 case OPC_MTC1:
10807 gen_load_gpr(t0, rt);
10809 TCGv_i32 fp0 = tcg_temp_new_i32();
10811 tcg_gen_trunc_tl_i32(fp0, t0);
10812 gen_store_fpr32(ctx, fp0, fs);
10813 tcg_temp_free_i32(fp0);
10815 break;
10816 case OPC_CFC1:
10817 gen_helper_1e0i(cfc1, t0, fs);
10818 gen_store_gpr(t0, rt);
10819 break;
10820 case OPC_CTC1:
10821 gen_load_gpr(t0, rt);
10822 save_cpu_state(ctx, 0);
10824 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10826 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10827 tcg_temp_free_i32(fs_tmp);
10829 /* Stop translation as we may have changed hflags */
10830 ctx->base.is_jmp = DISAS_STOP;
10831 break;
10832 #if defined(TARGET_MIPS64)
10833 case OPC_DMFC1:
10834 gen_load_fpr64(ctx, t0, fs);
10835 gen_store_gpr(t0, rt);
10836 break;
10837 case OPC_DMTC1:
10838 gen_load_gpr(t0, rt);
10839 gen_store_fpr64(ctx, t0, fs);
10840 break;
10841 #endif
10842 case OPC_MFHC1:
10844 TCGv_i32 fp0 = tcg_temp_new_i32();
10846 gen_load_fpr32h(ctx, fp0, fs);
10847 tcg_gen_ext_i32_tl(t0, fp0);
10848 tcg_temp_free_i32(fp0);
10850 gen_store_gpr(t0, rt);
10851 break;
10852 case OPC_MTHC1:
10853 gen_load_gpr(t0, rt);
10855 TCGv_i32 fp0 = tcg_temp_new_i32();
10857 tcg_gen_trunc_tl_i32(fp0, t0);
10858 gen_store_fpr32h(ctx, fp0, fs);
10859 tcg_temp_free_i32(fp0);
10861 break;
10862 default:
10863 MIPS_INVAL("cp1 move");
10864 gen_reserved_instruction(ctx);
10865 goto out;
10868 out:
10869 tcg_temp_free(t0);
10872 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
10874 TCGLabel *l1;
10875 TCGCond cond;
10876 TCGv_i32 t0;
10878 if (rd == 0) {
10879 /* Treat as NOP. */
10880 return;
10883 if (tf) {
10884 cond = TCG_COND_EQ;
10885 } else {
10886 cond = TCG_COND_NE;
10889 l1 = gen_new_label();
10890 t0 = tcg_temp_new_i32();
10891 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10892 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10893 tcg_temp_free_i32(t0);
10894 if (rs == 0) {
10895 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10896 } else {
10897 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10899 gen_set_label(l1);
10902 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10903 int tf)
10905 int cond;
10906 TCGv_i32 t0 = tcg_temp_new_i32();
10907 TCGLabel *l1 = gen_new_label();
10909 if (tf) {
10910 cond = TCG_COND_EQ;
10911 } else {
10912 cond = TCG_COND_NE;
10915 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10916 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10917 gen_load_fpr32(ctx, t0, fs);
10918 gen_store_fpr32(ctx, t0, fd);
10919 gen_set_label(l1);
10920 tcg_temp_free_i32(t0);
10923 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
10924 int tf)
10926 int cond;
10927 TCGv_i32 t0 = tcg_temp_new_i32();
10928 TCGv_i64 fp0;
10929 TCGLabel *l1 = gen_new_label();
10931 if (tf) {
10932 cond = TCG_COND_EQ;
10933 } else {
10934 cond = TCG_COND_NE;
10937 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10938 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10939 tcg_temp_free_i32(t0);
10940 fp0 = tcg_temp_new_i64();
10941 gen_load_fpr64(ctx, fp0, fs);
10942 gen_store_fpr64(ctx, fp0, fd);
10943 tcg_temp_free_i64(fp0);
10944 gen_set_label(l1);
10947 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10948 int cc, int tf)
10950 int cond;
10951 TCGv_i32 t0 = tcg_temp_new_i32();
10952 TCGLabel *l1 = gen_new_label();
10953 TCGLabel *l2 = gen_new_label();
10955 if (tf) {
10956 cond = TCG_COND_EQ;
10957 } else {
10958 cond = TCG_COND_NE;
10961 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10962 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10963 gen_load_fpr32(ctx, t0, fs);
10964 gen_store_fpr32(ctx, t0, fd);
10965 gen_set_label(l1);
10967 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
10968 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10969 gen_load_fpr32h(ctx, t0, fs);
10970 gen_store_fpr32h(ctx, t0, fd);
10971 tcg_temp_free_i32(t0);
10972 gen_set_label(l2);
10975 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10976 int fs)
10978 TCGv_i32 t1 = tcg_const_i32(0);
10979 TCGv_i32 fp0 = tcg_temp_new_i32();
10980 TCGv_i32 fp1 = tcg_temp_new_i32();
10981 TCGv_i32 fp2 = tcg_temp_new_i32();
10982 gen_load_fpr32(ctx, fp0, fd);
10983 gen_load_fpr32(ctx, fp1, ft);
10984 gen_load_fpr32(ctx, fp2, fs);
10986 switch (op1) {
10987 case OPC_SEL_S:
10988 tcg_gen_andi_i32(fp0, fp0, 1);
10989 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10990 break;
10991 case OPC_SELEQZ_S:
10992 tcg_gen_andi_i32(fp1, fp1, 1);
10993 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10994 break;
10995 case OPC_SELNEZ_S:
10996 tcg_gen_andi_i32(fp1, fp1, 1);
10997 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10998 break;
10999 default:
11000 MIPS_INVAL("gen_sel_s");
11001 gen_reserved_instruction(ctx);
11002 break;
11005 gen_store_fpr32(ctx, fp0, fd);
11006 tcg_temp_free_i32(fp2);
11007 tcg_temp_free_i32(fp1);
11008 tcg_temp_free_i32(fp0);
11009 tcg_temp_free_i32(t1);
11012 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11013 int fs)
11015 TCGv_i64 t1 = tcg_const_i64(0);
11016 TCGv_i64 fp0 = tcg_temp_new_i64();
11017 TCGv_i64 fp1 = tcg_temp_new_i64();
11018 TCGv_i64 fp2 = tcg_temp_new_i64();
11019 gen_load_fpr64(ctx, fp0, fd);
11020 gen_load_fpr64(ctx, fp1, ft);
11021 gen_load_fpr64(ctx, fp2, fs);
11023 switch (op1) {
11024 case OPC_SEL_D:
11025 tcg_gen_andi_i64(fp0, fp0, 1);
11026 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11027 break;
11028 case OPC_SELEQZ_D:
11029 tcg_gen_andi_i64(fp1, fp1, 1);
11030 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11031 break;
11032 case OPC_SELNEZ_D:
11033 tcg_gen_andi_i64(fp1, fp1, 1);
11034 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11035 break;
11036 default:
11037 MIPS_INVAL("gen_sel_d");
11038 gen_reserved_instruction(ctx);
11039 break;
11042 gen_store_fpr64(ctx, fp0, fd);
11043 tcg_temp_free_i64(fp2);
11044 tcg_temp_free_i64(fp1);
11045 tcg_temp_free_i64(fp0);
11046 tcg_temp_free_i64(t1);
11049 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11050 int ft, int fs, int fd, int cc)
11052 uint32_t func = ctx->opcode & 0x3f;
11053 switch (op1) {
11054 case OPC_ADD_S:
11056 TCGv_i32 fp0 = tcg_temp_new_i32();
11057 TCGv_i32 fp1 = tcg_temp_new_i32();
11059 gen_load_fpr32(ctx, fp0, fs);
11060 gen_load_fpr32(ctx, fp1, ft);
11061 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
11062 tcg_temp_free_i32(fp1);
11063 gen_store_fpr32(ctx, fp0, fd);
11064 tcg_temp_free_i32(fp0);
11066 break;
11067 case OPC_SUB_S:
11069 TCGv_i32 fp0 = tcg_temp_new_i32();
11070 TCGv_i32 fp1 = tcg_temp_new_i32();
11072 gen_load_fpr32(ctx, fp0, fs);
11073 gen_load_fpr32(ctx, fp1, ft);
11074 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
11075 tcg_temp_free_i32(fp1);
11076 gen_store_fpr32(ctx, fp0, fd);
11077 tcg_temp_free_i32(fp0);
11079 break;
11080 case OPC_MUL_S:
11082 TCGv_i32 fp0 = tcg_temp_new_i32();
11083 TCGv_i32 fp1 = tcg_temp_new_i32();
11085 gen_load_fpr32(ctx, fp0, fs);
11086 gen_load_fpr32(ctx, fp1, ft);
11087 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
11088 tcg_temp_free_i32(fp1);
11089 gen_store_fpr32(ctx, fp0, fd);
11090 tcg_temp_free_i32(fp0);
11092 break;
11093 case OPC_DIV_S:
11095 TCGv_i32 fp0 = tcg_temp_new_i32();
11096 TCGv_i32 fp1 = tcg_temp_new_i32();
11098 gen_load_fpr32(ctx, fp0, fs);
11099 gen_load_fpr32(ctx, fp1, ft);
11100 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11101 tcg_temp_free_i32(fp1);
11102 gen_store_fpr32(ctx, fp0, fd);
11103 tcg_temp_free_i32(fp0);
11105 break;
11106 case OPC_SQRT_S:
11108 TCGv_i32 fp0 = tcg_temp_new_i32();
11110 gen_load_fpr32(ctx, fp0, fs);
11111 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11112 gen_store_fpr32(ctx, fp0, fd);
11113 tcg_temp_free_i32(fp0);
11115 break;
11116 case OPC_ABS_S:
11118 TCGv_i32 fp0 = tcg_temp_new_i32();
11120 gen_load_fpr32(ctx, fp0, fs);
11121 if (ctx->abs2008) {
11122 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11123 } else {
11124 gen_helper_float_abs_s(fp0, fp0);
11126 gen_store_fpr32(ctx, fp0, fd);
11127 tcg_temp_free_i32(fp0);
11129 break;
11130 case OPC_MOV_S:
11132 TCGv_i32 fp0 = tcg_temp_new_i32();
11134 gen_load_fpr32(ctx, fp0, fs);
11135 gen_store_fpr32(ctx, fp0, fd);
11136 tcg_temp_free_i32(fp0);
11138 break;
11139 case OPC_NEG_S:
11141 TCGv_i32 fp0 = tcg_temp_new_i32();
11143 gen_load_fpr32(ctx, fp0, fs);
11144 if (ctx->abs2008) {
11145 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11146 } else {
11147 gen_helper_float_chs_s(fp0, fp0);
11149 gen_store_fpr32(ctx, fp0, fd);
11150 tcg_temp_free_i32(fp0);
11152 break;
11153 case OPC_ROUND_L_S:
11154 check_cp1_64bitmode(ctx);
11156 TCGv_i32 fp32 = tcg_temp_new_i32();
11157 TCGv_i64 fp64 = tcg_temp_new_i64();
11159 gen_load_fpr32(ctx, fp32, fs);
11160 if (ctx->nan2008) {
11161 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11162 } else {
11163 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11165 tcg_temp_free_i32(fp32);
11166 gen_store_fpr64(ctx, fp64, fd);
11167 tcg_temp_free_i64(fp64);
11169 break;
11170 case OPC_TRUNC_L_S:
11171 check_cp1_64bitmode(ctx);
11173 TCGv_i32 fp32 = tcg_temp_new_i32();
11174 TCGv_i64 fp64 = tcg_temp_new_i64();
11176 gen_load_fpr32(ctx, fp32, fs);
11177 if (ctx->nan2008) {
11178 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11179 } else {
11180 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11182 tcg_temp_free_i32(fp32);
11183 gen_store_fpr64(ctx, fp64, fd);
11184 tcg_temp_free_i64(fp64);
11186 break;
11187 case OPC_CEIL_L_S:
11188 check_cp1_64bitmode(ctx);
11190 TCGv_i32 fp32 = tcg_temp_new_i32();
11191 TCGv_i64 fp64 = tcg_temp_new_i64();
11193 gen_load_fpr32(ctx, fp32, fs);
11194 if (ctx->nan2008) {
11195 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11196 } else {
11197 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11199 tcg_temp_free_i32(fp32);
11200 gen_store_fpr64(ctx, fp64, fd);
11201 tcg_temp_free_i64(fp64);
11203 break;
11204 case OPC_FLOOR_L_S:
11205 check_cp1_64bitmode(ctx);
11207 TCGv_i32 fp32 = tcg_temp_new_i32();
11208 TCGv_i64 fp64 = tcg_temp_new_i64();
11210 gen_load_fpr32(ctx, fp32, fs);
11211 if (ctx->nan2008) {
11212 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11213 } else {
11214 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11216 tcg_temp_free_i32(fp32);
11217 gen_store_fpr64(ctx, fp64, fd);
11218 tcg_temp_free_i64(fp64);
11220 break;
11221 case OPC_ROUND_W_S:
11223 TCGv_i32 fp0 = tcg_temp_new_i32();
11225 gen_load_fpr32(ctx, fp0, fs);
11226 if (ctx->nan2008) {
11227 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11228 } else {
11229 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11231 gen_store_fpr32(ctx, fp0, fd);
11232 tcg_temp_free_i32(fp0);
11234 break;
11235 case OPC_TRUNC_W_S:
11237 TCGv_i32 fp0 = tcg_temp_new_i32();
11239 gen_load_fpr32(ctx, fp0, fs);
11240 if (ctx->nan2008) {
11241 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11242 } else {
11243 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11245 gen_store_fpr32(ctx, fp0, fd);
11246 tcg_temp_free_i32(fp0);
11248 break;
11249 case OPC_CEIL_W_S:
11251 TCGv_i32 fp0 = tcg_temp_new_i32();
11253 gen_load_fpr32(ctx, fp0, fs);
11254 if (ctx->nan2008) {
11255 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11256 } else {
11257 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11259 gen_store_fpr32(ctx, fp0, fd);
11260 tcg_temp_free_i32(fp0);
11262 break;
11263 case OPC_FLOOR_W_S:
11265 TCGv_i32 fp0 = tcg_temp_new_i32();
11267 gen_load_fpr32(ctx, fp0, fs);
11268 if (ctx->nan2008) {
11269 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11270 } else {
11271 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11273 gen_store_fpr32(ctx, fp0, fd);
11274 tcg_temp_free_i32(fp0);
11276 break;
11277 case OPC_SEL_S:
11278 check_insn(ctx, ISA_MIPS_R6);
11279 gen_sel_s(ctx, op1, fd, ft, fs);
11280 break;
11281 case OPC_SELEQZ_S:
11282 check_insn(ctx, ISA_MIPS_R6);
11283 gen_sel_s(ctx, op1, fd, ft, fs);
11284 break;
11285 case OPC_SELNEZ_S:
11286 check_insn(ctx, ISA_MIPS_R6);
11287 gen_sel_s(ctx, op1, fd, ft, fs);
11288 break;
11289 case OPC_MOVCF_S:
11290 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11291 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11292 break;
11293 case OPC_MOVZ_S:
11294 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11296 TCGLabel *l1 = gen_new_label();
11297 TCGv_i32 fp0;
11299 if (ft != 0) {
11300 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11302 fp0 = tcg_temp_new_i32();
11303 gen_load_fpr32(ctx, fp0, fs);
11304 gen_store_fpr32(ctx, fp0, fd);
11305 tcg_temp_free_i32(fp0);
11306 gen_set_label(l1);
11308 break;
11309 case OPC_MOVN_S:
11310 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11312 TCGLabel *l1 = gen_new_label();
11313 TCGv_i32 fp0;
11315 if (ft != 0) {
11316 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11317 fp0 = tcg_temp_new_i32();
11318 gen_load_fpr32(ctx, fp0, fs);
11319 gen_store_fpr32(ctx, fp0, fd);
11320 tcg_temp_free_i32(fp0);
11321 gen_set_label(l1);
11324 break;
11325 case OPC_RECIP_S:
11327 TCGv_i32 fp0 = tcg_temp_new_i32();
11329 gen_load_fpr32(ctx, fp0, fs);
11330 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11331 gen_store_fpr32(ctx, fp0, fd);
11332 tcg_temp_free_i32(fp0);
11334 break;
11335 case OPC_RSQRT_S:
11337 TCGv_i32 fp0 = tcg_temp_new_i32();
11339 gen_load_fpr32(ctx, fp0, fs);
11340 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11341 gen_store_fpr32(ctx, fp0, fd);
11342 tcg_temp_free_i32(fp0);
11344 break;
11345 case OPC_MADDF_S:
11346 check_insn(ctx, ISA_MIPS_R6);
11348 TCGv_i32 fp0 = tcg_temp_new_i32();
11349 TCGv_i32 fp1 = tcg_temp_new_i32();
11350 TCGv_i32 fp2 = tcg_temp_new_i32();
11351 gen_load_fpr32(ctx, fp0, fs);
11352 gen_load_fpr32(ctx, fp1, ft);
11353 gen_load_fpr32(ctx, fp2, fd);
11354 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11355 gen_store_fpr32(ctx, fp2, fd);
11356 tcg_temp_free_i32(fp2);
11357 tcg_temp_free_i32(fp1);
11358 tcg_temp_free_i32(fp0);
11360 break;
11361 case OPC_MSUBF_S:
11362 check_insn(ctx, ISA_MIPS_R6);
11364 TCGv_i32 fp0 = tcg_temp_new_i32();
11365 TCGv_i32 fp1 = tcg_temp_new_i32();
11366 TCGv_i32 fp2 = tcg_temp_new_i32();
11367 gen_load_fpr32(ctx, fp0, fs);
11368 gen_load_fpr32(ctx, fp1, ft);
11369 gen_load_fpr32(ctx, fp2, fd);
11370 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11371 gen_store_fpr32(ctx, fp2, fd);
11372 tcg_temp_free_i32(fp2);
11373 tcg_temp_free_i32(fp1);
11374 tcg_temp_free_i32(fp0);
11376 break;
11377 case OPC_RINT_S:
11378 check_insn(ctx, ISA_MIPS_R6);
11380 TCGv_i32 fp0 = tcg_temp_new_i32();
11381 gen_load_fpr32(ctx, fp0, fs);
11382 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11383 gen_store_fpr32(ctx, fp0, fd);
11384 tcg_temp_free_i32(fp0);
11386 break;
11387 case OPC_CLASS_S:
11388 check_insn(ctx, ISA_MIPS_R6);
11390 TCGv_i32 fp0 = tcg_temp_new_i32();
11391 gen_load_fpr32(ctx, fp0, fs);
11392 gen_helper_float_class_s(fp0, cpu_env, fp0);
11393 gen_store_fpr32(ctx, fp0, fd);
11394 tcg_temp_free_i32(fp0);
11396 break;
11397 case OPC_MIN_S: /* OPC_RECIP2_S */
11398 if (ctx->insn_flags & ISA_MIPS_R6) {
11399 /* OPC_MIN_S */
11400 TCGv_i32 fp0 = tcg_temp_new_i32();
11401 TCGv_i32 fp1 = tcg_temp_new_i32();
11402 TCGv_i32 fp2 = tcg_temp_new_i32();
11403 gen_load_fpr32(ctx, fp0, fs);
11404 gen_load_fpr32(ctx, fp1, ft);
11405 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11406 gen_store_fpr32(ctx, fp2, fd);
11407 tcg_temp_free_i32(fp2);
11408 tcg_temp_free_i32(fp1);
11409 tcg_temp_free_i32(fp0);
11410 } else {
11411 /* OPC_RECIP2_S */
11412 check_cp1_64bitmode(ctx);
11414 TCGv_i32 fp0 = tcg_temp_new_i32();
11415 TCGv_i32 fp1 = tcg_temp_new_i32();
11417 gen_load_fpr32(ctx, fp0, fs);
11418 gen_load_fpr32(ctx, fp1, ft);
11419 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11420 tcg_temp_free_i32(fp1);
11421 gen_store_fpr32(ctx, fp0, fd);
11422 tcg_temp_free_i32(fp0);
11425 break;
11426 case OPC_MINA_S: /* OPC_RECIP1_S */
11427 if (ctx->insn_flags & ISA_MIPS_R6) {
11428 /* OPC_MINA_S */
11429 TCGv_i32 fp0 = tcg_temp_new_i32();
11430 TCGv_i32 fp1 = tcg_temp_new_i32();
11431 TCGv_i32 fp2 = tcg_temp_new_i32();
11432 gen_load_fpr32(ctx, fp0, fs);
11433 gen_load_fpr32(ctx, fp1, ft);
11434 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11435 gen_store_fpr32(ctx, fp2, fd);
11436 tcg_temp_free_i32(fp2);
11437 tcg_temp_free_i32(fp1);
11438 tcg_temp_free_i32(fp0);
11439 } else {
11440 /* OPC_RECIP1_S */
11441 check_cp1_64bitmode(ctx);
11443 TCGv_i32 fp0 = tcg_temp_new_i32();
11445 gen_load_fpr32(ctx, fp0, fs);
11446 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11447 gen_store_fpr32(ctx, fp0, fd);
11448 tcg_temp_free_i32(fp0);
11451 break;
11452 case OPC_MAX_S: /* OPC_RSQRT1_S */
11453 if (ctx->insn_flags & ISA_MIPS_R6) {
11454 /* OPC_MAX_S */
11455 TCGv_i32 fp0 = tcg_temp_new_i32();
11456 TCGv_i32 fp1 = tcg_temp_new_i32();
11457 gen_load_fpr32(ctx, fp0, fs);
11458 gen_load_fpr32(ctx, fp1, ft);
11459 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11460 gen_store_fpr32(ctx, fp1, fd);
11461 tcg_temp_free_i32(fp1);
11462 tcg_temp_free_i32(fp0);
11463 } else {
11464 /* OPC_RSQRT1_S */
11465 check_cp1_64bitmode(ctx);
11467 TCGv_i32 fp0 = tcg_temp_new_i32();
11469 gen_load_fpr32(ctx, fp0, fs);
11470 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11471 gen_store_fpr32(ctx, fp0, fd);
11472 tcg_temp_free_i32(fp0);
11475 break;
11476 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11477 if (ctx->insn_flags & ISA_MIPS_R6) {
11478 /* OPC_MAXA_S */
11479 TCGv_i32 fp0 = tcg_temp_new_i32();
11480 TCGv_i32 fp1 = tcg_temp_new_i32();
11481 gen_load_fpr32(ctx, fp0, fs);
11482 gen_load_fpr32(ctx, fp1, ft);
11483 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11484 gen_store_fpr32(ctx, fp1, fd);
11485 tcg_temp_free_i32(fp1);
11486 tcg_temp_free_i32(fp0);
11487 } else {
11488 /* OPC_RSQRT2_S */
11489 check_cp1_64bitmode(ctx);
11491 TCGv_i32 fp0 = tcg_temp_new_i32();
11492 TCGv_i32 fp1 = tcg_temp_new_i32();
11494 gen_load_fpr32(ctx, fp0, fs);
11495 gen_load_fpr32(ctx, fp1, ft);
11496 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11497 tcg_temp_free_i32(fp1);
11498 gen_store_fpr32(ctx, fp0, fd);
11499 tcg_temp_free_i32(fp0);
11502 break;
11503 case OPC_CVT_D_S:
11504 check_cp1_registers(ctx, fd);
11506 TCGv_i32 fp32 = tcg_temp_new_i32();
11507 TCGv_i64 fp64 = tcg_temp_new_i64();
11509 gen_load_fpr32(ctx, fp32, fs);
11510 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11511 tcg_temp_free_i32(fp32);
11512 gen_store_fpr64(ctx, fp64, fd);
11513 tcg_temp_free_i64(fp64);
11515 break;
11516 case OPC_CVT_W_S:
11518 TCGv_i32 fp0 = tcg_temp_new_i32();
11520 gen_load_fpr32(ctx, fp0, fs);
11521 if (ctx->nan2008) {
11522 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11523 } else {
11524 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11526 gen_store_fpr32(ctx, fp0, fd);
11527 tcg_temp_free_i32(fp0);
11529 break;
11530 case OPC_CVT_L_S:
11531 check_cp1_64bitmode(ctx);
11533 TCGv_i32 fp32 = tcg_temp_new_i32();
11534 TCGv_i64 fp64 = tcg_temp_new_i64();
11536 gen_load_fpr32(ctx, fp32, fs);
11537 if (ctx->nan2008) {
11538 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11539 } else {
11540 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11542 tcg_temp_free_i32(fp32);
11543 gen_store_fpr64(ctx, fp64, fd);
11544 tcg_temp_free_i64(fp64);
11546 break;
11547 case OPC_CVT_PS_S:
11548 check_ps(ctx);
11550 TCGv_i64 fp64 = tcg_temp_new_i64();
11551 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11552 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11554 gen_load_fpr32(ctx, fp32_0, fs);
11555 gen_load_fpr32(ctx, fp32_1, ft);
11556 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11557 tcg_temp_free_i32(fp32_1);
11558 tcg_temp_free_i32(fp32_0);
11559 gen_store_fpr64(ctx, fp64, fd);
11560 tcg_temp_free_i64(fp64);
11562 break;
11563 case OPC_CMP_F_S:
11564 case OPC_CMP_UN_S:
11565 case OPC_CMP_EQ_S:
11566 case OPC_CMP_UEQ_S:
11567 case OPC_CMP_OLT_S:
11568 case OPC_CMP_ULT_S:
11569 case OPC_CMP_OLE_S:
11570 case OPC_CMP_ULE_S:
11571 case OPC_CMP_SF_S:
11572 case OPC_CMP_NGLE_S:
11573 case OPC_CMP_SEQ_S:
11574 case OPC_CMP_NGL_S:
11575 case OPC_CMP_LT_S:
11576 case OPC_CMP_NGE_S:
11577 case OPC_CMP_LE_S:
11578 case OPC_CMP_NGT_S:
11579 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11580 if (ctx->opcode & (1 << 6)) {
11581 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
11582 } else {
11583 gen_cmp_s(ctx, func - 48, ft, fs, cc);
11585 break;
11586 case OPC_ADD_D:
11587 check_cp1_registers(ctx, fs | ft | fd);
11589 TCGv_i64 fp0 = tcg_temp_new_i64();
11590 TCGv_i64 fp1 = tcg_temp_new_i64();
11592 gen_load_fpr64(ctx, fp0, fs);
11593 gen_load_fpr64(ctx, fp1, ft);
11594 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11595 tcg_temp_free_i64(fp1);
11596 gen_store_fpr64(ctx, fp0, fd);
11597 tcg_temp_free_i64(fp0);
11599 break;
11600 case OPC_SUB_D:
11601 check_cp1_registers(ctx, fs | ft | fd);
11603 TCGv_i64 fp0 = tcg_temp_new_i64();
11604 TCGv_i64 fp1 = tcg_temp_new_i64();
11606 gen_load_fpr64(ctx, fp0, fs);
11607 gen_load_fpr64(ctx, fp1, ft);
11608 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11609 tcg_temp_free_i64(fp1);
11610 gen_store_fpr64(ctx, fp0, fd);
11611 tcg_temp_free_i64(fp0);
11613 break;
11614 case OPC_MUL_D:
11615 check_cp1_registers(ctx, fs | ft | fd);
11617 TCGv_i64 fp0 = tcg_temp_new_i64();
11618 TCGv_i64 fp1 = tcg_temp_new_i64();
11620 gen_load_fpr64(ctx, fp0, fs);
11621 gen_load_fpr64(ctx, fp1, ft);
11622 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11623 tcg_temp_free_i64(fp1);
11624 gen_store_fpr64(ctx, fp0, fd);
11625 tcg_temp_free_i64(fp0);
11627 break;
11628 case OPC_DIV_D:
11629 check_cp1_registers(ctx, fs | ft | fd);
11631 TCGv_i64 fp0 = tcg_temp_new_i64();
11632 TCGv_i64 fp1 = tcg_temp_new_i64();
11634 gen_load_fpr64(ctx, fp0, fs);
11635 gen_load_fpr64(ctx, fp1, ft);
11636 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11637 tcg_temp_free_i64(fp1);
11638 gen_store_fpr64(ctx, fp0, fd);
11639 tcg_temp_free_i64(fp0);
11641 break;
11642 case OPC_SQRT_D:
11643 check_cp1_registers(ctx, fs | fd);
11645 TCGv_i64 fp0 = tcg_temp_new_i64();
11647 gen_load_fpr64(ctx, fp0, fs);
11648 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11649 gen_store_fpr64(ctx, fp0, fd);
11650 tcg_temp_free_i64(fp0);
11652 break;
11653 case OPC_ABS_D:
11654 check_cp1_registers(ctx, fs | fd);
11656 TCGv_i64 fp0 = tcg_temp_new_i64();
11658 gen_load_fpr64(ctx, fp0, fs);
11659 if (ctx->abs2008) {
11660 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11661 } else {
11662 gen_helper_float_abs_d(fp0, fp0);
11664 gen_store_fpr64(ctx, fp0, fd);
11665 tcg_temp_free_i64(fp0);
11667 break;
11668 case OPC_MOV_D:
11669 check_cp1_registers(ctx, fs | fd);
11671 TCGv_i64 fp0 = tcg_temp_new_i64();
11673 gen_load_fpr64(ctx, fp0, fs);
11674 gen_store_fpr64(ctx, fp0, fd);
11675 tcg_temp_free_i64(fp0);
11677 break;
11678 case OPC_NEG_D:
11679 check_cp1_registers(ctx, fs | fd);
11681 TCGv_i64 fp0 = tcg_temp_new_i64();
11683 gen_load_fpr64(ctx, fp0, fs);
11684 if (ctx->abs2008) {
11685 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11686 } else {
11687 gen_helper_float_chs_d(fp0, fp0);
11689 gen_store_fpr64(ctx, fp0, fd);
11690 tcg_temp_free_i64(fp0);
11692 break;
11693 case OPC_ROUND_L_D:
11694 check_cp1_64bitmode(ctx);
11696 TCGv_i64 fp0 = tcg_temp_new_i64();
11698 gen_load_fpr64(ctx, fp0, fs);
11699 if (ctx->nan2008) {
11700 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11701 } else {
11702 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11704 gen_store_fpr64(ctx, fp0, fd);
11705 tcg_temp_free_i64(fp0);
11707 break;
11708 case OPC_TRUNC_L_D:
11709 check_cp1_64bitmode(ctx);
11711 TCGv_i64 fp0 = tcg_temp_new_i64();
11713 gen_load_fpr64(ctx, fp0, fs);
11714 if (ctx->nan2008) {
11715 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11716 } else {
11717 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11719 gen_store_fpr64(ctx, fp0, fd);
11720 tcg_temp_free_i64(fp0);
11722 break;
11723 case OPC_CEIL_L_D:
11724 check_cp1_64bitmode(ctx);
11726 TCGv_i64 fp0 = tcg_temp_new_i64();
11728 gen_load_fpr64(ctx, fp0, fs);
11729 if (ctx->nan2008) {
11730 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11731 } else {
11732 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11734 gen_store_fpr64(ctx, fp0, fd);
11735 tcg_temp_free_i64(fp0);
11737 break;
11738 case OPC_FLOOR_L_D:
11739 check_cp1_64bitmode(ctx);
11741 TCGv_i64 fp0 = tcg_temp_new_i64();
11743 gen_load_fpr64(ctx, fp0, fs);
11744 if (ctx->nan2008) {
11745 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11746 } else {
11747 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11749 gen_store_fpr64(ctx, fp0, fd);
11750 tcg_temp_free_i64(fp0);
11752 break;
11753 case OPC_ROUND_W_D:
11754 check_cp1_registers(ctx, fs);
11756 TCGv_i32 fp32 = tcg_temp_new_i32();
11757 TCGv_i64 fp64 = tcg_temp_new_i64();
11759 gen_load_fpr64(ctx, fp64, fs);
11760 if (ctx->nan2008) {
11761 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11762 } else {
11763 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11765 tcg_temp_free_i64(fp64);
11766 gen_store_fpr32(ctx, fp32, fd);
11767 tcg_temp_free_i32(fp32);
11769 break;
11770 case OPC_TRUNC_W_D:
11771 check_cp1_registers(ctx, fs);
11773 TCGv_i32 fp32 = tcg_temp_new_i32();
11774 TCGv_i64 fp64 = tcg_temp_new_i64();
11776 gen_load_fpr64(ctx, fp64, fs);
11777 if (ctx->nan2008) {
11778 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11779 } else {
11780 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11782 tcg_temp_free_i64(fp64);
11783 gen_store_fpr32(ctx, fp32, fd);
11784 tcg_temp_free_i32(fp32);
11786 break;
11787 case OPC_CEIL_W_D:
11788 check_cp1_registers(ctx, fs);
11790 TCGv_i32 fp32 = tcg_temp_new_i32();
11791 TCGv_i64 fp64 = tcg_temp_new_i64();
11793 gen_load_fpr64(ctx, fp64, fs);
11794 if (ctx->nan2008) {
11795 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11796 } else {
11797 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11799 tcg_temp_free_i64(fp64);
11800 gen_store_fpr32(ctx, fp32, fd);
11801 tcg_temp_free_i32(fp32);
11803 break;
11804 case OPC_FLOOR_W_D:
11805 check_cp1_registers(ctx, fs);
11807 TCGv_i32 fp32 = tcg_temp_new_i32();
11808 TCGv_i64 fp64 = tcg_temp_new_i64();
11810 gen_load_fpr64(ctx, fp64, fs);
11811 if (ctx->nan2008) {
11812 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11813 } else {
11814 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11816 tcg_temp_free_i64(fp64);
11817 gen_store_fpr32(ctx, fp32, fd);
11818 tcg_temp_free_i32(fp32);
11820 break;
11821 case OPC_SEL_D:
11822 check_insn(ctx, ISA_MIPS_R6);
11823 gen_sel_d(ctx, op1, fd, ft, fs);
11824 break;
11825 case OPC_SELEQZ_D:
11826 check_insn(ctx, ISA_MIPS_R6);
11827 gen_sel_d(ctx, op1, fd, ft, fs);
11828 break;
11829 case OPC_SELNEZ_D:
11830 check_insn(ctx, ISA_MIPS_R6);
11831 gen_sel_d(ctx, op1, fd, ft, fs);
11832 break;
11833 case OPC_MOVCF_D:
11834 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11835 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11836 break;
11837 case OPC_MOVZ_D:
11838 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11840 TCGLabel *l1 = gen_new_label();
11841 TCGv_i64 fp0;
11843 if (ft != 0) {
11844 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11846 fp0 = tcg_temp_new_i64();
11847 gen_load_fpr64(ctx, fp0, fs);
11848 gen_store_fpr64(ctx, fp0, fd);
11849 tcg_temp_free_i64(fp0);
11850 gen_set_label(l1);
11852 break;
11853 case OPC_MOVN_D:
11854 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11856 TCGLabel *l1 = gen_new_label();
11857 TCGv_i64 fp0;
11859 if (ft != 0) {
11860 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11861 fp0 = tcg_temp_new_i64();
11862 gen_load_fpr64(ctx, fp0, fs);
11863 gen_store_fpr64(ctx, fp0, fd);
11864 tcg_temp_free_i64(fp0);
11865 gen_set_label(l1);
11868 break;
11869 case OPC_RECIP_D:
11870 check_cp1_registers(ctx, fs | fd);
11872 TCGv_i64 fp0 = tcg_temp_new_i64();
11874 gen_load_fpr64(ctx, fp0, fs);
11875 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11876 gen_store_fpr64(ctx, fp0, fd);
11877 tcg_temp_free_i64(fp0);
11879 break;
11880 case OPC_RSQRT_D:
11881 check_cp1_registers(ctx, fs | fd);
11883 TCGv_i64 fp0 = tcg_temp_new_i64();
11885 gen_load_fpr64(ctx, fp0, fs);
11886 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11887 gen_store_fpr64(ctx, fp0, fd);
11888 tcg_temp_free_i64(fp0);
11890 break;
11891 case OPC_MADDF_D:
11892 check_insn(ctx, ISA_MIPS_R6);
11894 TCGv_i64 fp0 = tcg_temp_new_i64();
11895 TCGv_i64 fp1 = tcg_temp_new_i64();
11896 TCGv_i64 fp2 = tcg_temp_new_i64();
11897 gen_load_fpr64(ctx, fp0, fs);
11898 gen_load_fpr64(ctx, fp1, ft);
11899 gen_load_fpr64(ctx, fp2, fd);
11900 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11901 gen_store_fpr64(ctx, fp2, fd);
11902 tcg_temp_free_i64(fp2);
11903 tcg_temp_free_i64(fp1);
11904 tcg_temp_free_i64(fp0);
11906 break;
11907 case OPC_MSUBF_D:
11908 check_insn(ctx, ISA_MIPS_R6);
11910 TCGv_i64 fp0 = tcg_temp_new_i64();
11911 TCGv_i64 fp1 = tcg_temp_new_i64();
11912 TCGv_i64 fp2 = tcg_temp_new_i64();
11913 gen_load_fpr64(ctx, fp0, fs);
11914 gen_load_fpr64(ctx, fp1, ft);
11915 gen_load_fpr64(ctx, fp2, fd);
11916 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11917 gen_store_fpr64(ctx, fp2, fd);
11918 tcg_temp_free_i64(fp2);
11919 tcg_temp_free_i64(fp1);
11920 tcg_temp_free_i64(fp0);
11922 break;
11923 case OPC_RINT_D:
11924 check_insn(ctx, ISA_MIPS_R6);
11926 TCGv_i64 fp0 = tcg_temp_new_i64();
11927 gen_load_fpr64(ctx, fp0, fs);
11928 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11929 gen_store_fpr64(ctx, fp0, fd);
11930 tcg_temp_free_i64(fp0);
11932 break;
11933 case OPC_CLASS_D:
11934 check_insn(ctx, ISA_MIPS_R6);
11936 TCGv_i64 fp0 = tcg_temp_new_i64();
11937 gen_load_fpr64(ctx, fp0, fs);
11938 gen_helper_float_class_d(fp0, cpu_env, fp0);
11939 gen_store_fpr64(ctx, fp0, fd);
11940 tcg_temp_free_i64(fp0);
11942 break;
11943 case OPC_MIN_D: /* OPC_RECIP2_D */
11944 if (ctx->insn_flags & ISA_MIPS_R6) {
11945 /* OPC_MIN_D */
11946 TCGv_i64 fp0 = tcg_temp_new_i64();
11947 TCGv_i64 fp1 = tcg_temp_new_i64();
11948 gen_load_fpr64(ctx, fp0, fs);
11949 gen_load_fpr64(ctx, fp1, ft);
11950 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11951 gen_store_fpr64(ctx, fp1, fd);
11952 tcg_temp_free_i64(fp1);
11953 tcg_temp_free_i64(fp0);
11954 } else {
11955 /* OPC_RECIP2_D */
11956 check_cp1_64bitmode(ctx);
11958 TCGv_i64 fp0 = tcg_temp_new_i64();
11959 TCGv_i64 fp1 = tcg_temp_new_i64();
11961 gen_load_fpr64(ctx, fp0, fs);
11962 gen_load_fpr64(ctx, fp1, ft);
11963 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11964 tcg_temp_free_i64(fp1);
11965 gen_store_fpr64(ctx, fp0, fd);
11966 tcg_temp_free_i64(fp0);
11969 break;
11970 case OPC_MINA_D: /* OPC_RECIP1_D */
11971 if (ctx->insn_flags & ISA_MIPS_R6) {
11972 /* OPC_MINA_D */
11973 TCGv_i64 fp0 = tcg_temp_new_i64();
11974 TCGv_i64 fp1 = tcg_temp_new_i64();
11975 gen_load_fpr64(ctx, fp0, fs);
11976 gen_load_fpr64(ctx, fp1, ft);
11977 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11978 gen_store_fpr64(ctx, fp1, fd);
11979 tcg_temp_free_i64(fp1);
11980 tcg_temp_free_i64(fp0);
11981 } else {
11982 /* OPC_RECIP1_D */
11983 check_cp1_64bitmode(ctx);
11985 TCGv_i64 fp0 = tcg_temp_new_i64();
11987 gen_load_fpr64(ctx, fp0, fs);
11988 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11989 gen_store_fpr64(ctx, fp0, fd);
11990 tcg_temp_free_i64(fp0);
11993 break;
11994 case OPC_MAX_D: /* OPC_RSQRT1_D */
11995 if (ctx->insn_flags & ISA_MIPS_R6) {
11996 /* OPC_MAX_D */
11997 TCGv_i64 fp0 = tcg_temp_new_i64();
11998 TCGv_i64 fp1 = tcg_temp_new_i64();
11999 gen_load_fpr64(ctx, fp0, fs);
12000 gen_load_fpr64(ctx, fp1, ft);
12001 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12002 gen_store_fpr64(ctx, fp1, fd);
12003 tcg_temp_free_i64(fp1);
12004 tcg_temp_free_i64(fp0);
12005 } else {
12006 /* OPC_RSQRT1_D */
12007 check_cp1_64bitmode(ctx);
12009 TCGv_i64 fp0 = tcg_temp_new_i64();
12011 gen_load_fpr64(ctx, fp0, fs);
12012 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12013 gen_store_fpr64(ctx, fp0, fd);
12014 tcg_temp_free_i64(fp0);
12017 break;
12018 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12019 if (ctx->insn_flags & ISA_MIPS_R6) {
12020 /* OPC_MAXA_D */
12021 TCGv_i64 fp0 = tcg_temp_new_i64();
12022 TCGv_i64 fp1 = tcg_temp_new_i64();
12023 gen_load_fpr64(ctx, fp0, fs);
12024 gen_load_fpr64(ctx, fp1, ft);
12025 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12026 gen_store_fpr64(ctx, fp1, fd);
12027 tcg_temp_free_i64(fp1);
12028 tcg_temp_free_i64(fp0);
12029 } else {
12030 /* OPC_RSQRT2_D */
12031 check_cp1_64bitmode(ctx);
12033 TCGv_i64 fp0 = tcg_temp_new_i64();
12034 TCGv_i64 fp1 = tcg_temp_new_i64();
12036 gen_load_fpr64(ctx, fp0, fs);
12037 gen_load_fpr64(ctx, fp1, ft);
12038 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12039 tcg_temp_free_i64(fp1);
12040 gen_store_fpr64(ctx, fp0, fd);
12041 tcg_temp_free_i64(fp0);
12044 break;
12045 case OPC_CMP_F_D:
12046 case OPC_CMP_UN_D:
12047 case OPC_CMP_EQ_D:
12048 case OPC_CMP_UEQ_D:
12049 case OPC_CMP_OLT_D:
12050 case OPC_CMP_ULT_D:
12051 case OPC_CMP_OLE_D:
12052 case OPC_CMP_ULE_D:
12053 case OPC_CMP_SF_D:
12054 case OPC_CMP_NGLE_D:
12055 case OPC_CMP_SEQ_D:
12056 case OPC_CMP_NGL_D:
12057 case OPC_CMP_LT_D:
12058 case OPC_CMP_NGE_D:
12059 case OPC_CMP_LE_D:
12060 case OPC_CMP_NGT_D:
12061 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12062 if (ctx->opcode & (1 << 6)) {
12063 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12064 } else {
12065 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12067 break;
12068 case OPC_CVT_S_D:
12069 check_cp1_registers(ctx, fs);
12071 TCGv_i32 fp32 = tcg_temp_new_i32();
12072 TCGv_i64 fp64 = tcg_temp_new_i64();
12074 gen_load_fpr64(ctx, fp64, fs);
12075 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12076 tcg_temp_free_i64(fp64);
12077 gen_store_fpr32(ctx, fp32, fd);
12078 tcg_temp_free_i32(fp32);
12080 break;
12081 case OPC_CVT_W_D:
12082 check_cp1_registers(ctx, fs);
12084 TCGv_i32 fp32 = tcg_temp_new_i32();
12085 TCGv_i64 fp64 = tcg_temp_new_i64();
12087 gen_load_fpr64(ctx, fp64, fs);
12088 if (ctx->nan2008) {
12089 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12090 } else {
12091 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12093 tcg_temp_free_i64(fp64);
12094 gen_store_fpr32(ctx, fp32, fd);
12095 tcg_temp_free_i32(fp32);
12097 break;
12098 case OPC_CVT_L_D:
12099 check_cp1_64bitmode(ctx);
12101 TCGv_i64 fp0 = tcg_temp_new_i64();
12103 gen_load_fpr64(ctx, fp0, fs);
12104 if (ctx->nan2008) {
12105 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12106 } else {
12107 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12109 gen_store_fpr64(ctx, fp0, fd);
12110 tcg_temp_free_i64(fp0);
12112 break;
12113 case OPC_CVT_S_W:
12115 TCGv_i32 fp0 = tcg_temp_new_i32();
12117 gen_load_fpr32(ctx, fp0, fs);
12118 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12119 gen_store_fpr32(ctx, fp0, fd);
12120 tcg_temp_free_i32(fp0);
12122 break;
12123 case OPC_CVT_D_W:
12124 check_cp1_registers(ctx, fd);
12126 TCGv_i32 fp32 = tcg_temp_new_i32();
12127 TCGv_i64 fp64 = tcg_temp_new_i64();
12129 gen_load_fpr32(ctx, fp32, fs);
12130 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12131 tcg_temp_free_i32(fp32);
12132 gen_store_fpr64(ctx, fp64, fd);
12133 tcg_temp_free_i64(fp64);
12135 break;
12136 case OPC_CVT_S_L:
12137 check_cp1_64bitmode(ctx);
12139 TCGv_i32 fp32 = tcg_temp_new_i32();
12140 TCGv_i64 fp64 = tcg_temp_new_i64();
12142 gen_load_fpr64(ctx, fp64, fs);
12143 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12144 tcg_temp_free_i64(fp64);
12145 gen_store_fpr32(ctx, fp32, fd);
12146 tcg_temp_free_i32(fp32);
12148 break;
12149 case OPC_CVT_D_L:
12150 check_cp1_64bitmode(ctx);
12152 TCGv_i64 fp0 = tcg_temp_new_i64();
12154 gen_load_fpr64(ctx, fp0, fs);
12155 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12156 gen_store_fpr64(ctx, fp0, fd);
12157 tcg_temp_free_i64(fp0);
12159 break;
12160 case OPC_CVT_PS_PW:
12161 check_ps(ctx);
12163 TCGv_i64 fp0 = tcg_temp_new_i64();
12165 gen_load_fpr64(ctx, fp0, fs);
12166 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12167 gen_store_fpr64(ctx, fp0, fd);
12168 tcg_temp_free_i64(fp0);
12170 break;
12171 case OPC_ADD_PS:
12172 check_ps(ctx);
12174 TCGv_i64 fp0 = tcg_temp_new_i64();
12175 TCGv_i64 fp1 = tcg_temp_new_i64();
12177 gen_load_fpr64(ctx, fp0, fs);
12178 gen_load_fpr64(ctx, fp1, ft);
12179 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12180 tcg_temp_free_i64(fp1);
12181 gen_store_fpr64(ctx, fp0, fd);
12182 tcg_temp_free_i64(fp0);
12184 break;
12185 case OPC_SUB_PS:
12186 check_ps(ctx);
12188 TCGv_i64 fp0 = tcg_temp_new_i64();
12189 TCGv_i64 fp1 = tcg_temp_new_i64();
12191 gen_load_fpr64(ctx, fp0, fs);
12192 gen_load_fpr64(ctx, fp1, ft);
12193 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12194 tcg_temp_free_i64(fp1);
12195 gen_store_fpr64(ctx, fp0, fd);
12196 tcg_temp_free_i64(fp0);
12198 break;
12199 case OPC_MUL_PS:
12200 check_ps(ctx);
12202 TCGv_i64 fp0 = tcg_temp_new_i64();
12203 TCGv_i64 fp1 = tcg_temp_new_i64();
12205 gen_load_fpr64(ctx, fp0, fs);
12206 gen_load_fpr64(ctx, fp1, ft);
12207 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12208 tcg_temp_free_i64(fp1);
12209 gen_store_fpr64(ctx, fp0, fd);
12210 tcg_temp_free_i64(fp0);
12212 break;
12213 case OPC_ABS_PS:
12214 check_ps(ctx);
12216 TCGv_i64 fp0 = tcg_temp_new_i64();
12218 gen_load_fpr64(ctx, fp0, fs);
12219 gen_helper_float_abs_ps(fp0, fp0);
12220 gen_store_fpr64(ctx, fp0, fd);
12221 tcg_temp_free_i64(fp0);
12223 break;
12224 case OPC_MOV_PS:
12225 check_ps(ctx);
12227 TCGv_i64 fp0 = tcg_temp_new_i64();
12229 gen_load_fpr64(ctx, fp0, fs);
12230 gen_store_fpr64(ctx, fp0, fd);
12231 tcg_temp_free_i64(fp0);
12233 break;
12234 case OPC_NEG_PS:
12235 check_ps(ctx);
12237 TCGv_i64 fp0 = tcg_temp_new_i64();
12239 gen_load_fpr64(ctx, fp0, fs);
12240 gen_helper_float_chs_ps(fp0, fp0);
12241 gen_store_fpr64(ctx, fp0, fd);
12242 tcg_temp_free_i64(fp0);
12244 break;
12245 case OPC_MOVCF_PS:
12246 check_ps(ctx);
12247 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12248 break;
12249 case OPC_MOVZ_PS:
12250 check_ps(ctx);
12252 TCGLabel *l1 = gen_new_label();
12253 TCGv_i64 fp0;
12255 if (ft != 0) {
12256 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12258 fp0 = tcg_temp_new_i64();
12259 gen_load_fpr64(ctx, fp0, fs);
12260 gen_store_fpr64(ctx, fp0, fd);
12261 tcg_temp_free_i64(fp0);
12262 gen_set_label(l1);
12264 break;
12265 case OPC_MOVN_PS:
12266 check_ps(ctx);
12268 TCGLabel *l1 = gen_new_label();
12269 TCGv_i64 fp0;
12271 if (ft != 0) {
12272 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12273 fp0 = tcg_temp_new_i64();
12274 gen_load_fpr64(ctx, fp0, fs);
12275 gen_store_fpr64(ctx, fp0, fd);
12276 tcg_temp_free_i64(fp0);
12277 gen_set_label(l1);
12280 break;
12281 case OPC_ADDR_PS:
12282 check_ps(ctx);
12284 TCGv_i64 fp0 = tcg_temp_new_i64();
12285 TCGv_i64 fp1 = tcg_temp_new_i64();
12287 gen_load_fpr64(ctx, fp0, ft);
12288 gen_load_fpr64(ctx, fp1, fs);
12289 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12290 tcg_temp_free_i64(fp1);
12291 gen_store_fpr64(ctx, fp0, fd);
12292 tcg_temp_free_i64(fp0);
12294 break;
12295 case OPC_MULR_PS:
12296 check_ps(ctx);
12298 TCGv_i64 fp0 = tcg_temp_new_i64();
12299 TCGv_i64 fp1 = tcg_temp_new_i64();
12301 gen_load_fpr64(ctx, fp0, ft);
12302 gen_load_fpr64(ctx, fp1, fs);
12303 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12304 tcg_temp_free_i64(fp1);
12305 gen_store_fpr64(ctx, fp0, fd);
12306 tcg_temp_free_i64(fp0);
12308 break;
12309 case OPC_RECIP2_PS:
12310 check_ps(ctx);
12312 TCGv_i64 fp0 = tcg_temp_new_i64();
12313 TCGv_i64 fp1 = tcg_temp_new_i64();
12315 gen_load_fpr64(ctx, fp0, fs);
12316 gen_load_fpr64(ctx, fp1, ft);
12317 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12318 tcg_temp_free_i64(fp1);
12319 gen_store_fpr64(ctx, fp0, fd);
12320 tcg_temp_free_i64(fp0);
12322 break;
12323 case OPC_RECIP1_PS:
12324 check_ps(ctx);
12326 TCGv_i64 fp0 = tcg_temp_new_i64();
12328 gen_load_fpr64(ctx, fp0, fs);
12329 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12330 gen_store_fpr64(ctx, fp0, fd);
12331 tcg_temp_free_i64(fp0);
12333 break;
12334 case OPC_RSQRT1_PS:
12335 check_ps(ctx);
12337 TCGv_i64 fp0 = tcg_temp_new_i64();
12339 gen_load_fpr64(ctx, fp0, fs);
12340 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12341 gen_store_fpr64(ctx, fp0, fd);
12342 tcg_temp_free_i64(fp0);
12344 break;
12345 case OPC_RSQRT2_PS:
12346 check_ps(ctx);
12348 TCGv_i64 fp0 = tcg_temp_new_i64();
12349 TCGv_i64 fp1 = tcg_temp_new_i64();
12351 gen_load_fpr64(ctx, fp0, fs);
12352 gen_load_fpr64(ctx, fp1, ft);
12353 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12354 tcg_temp_free_i64(fp1);
12355 gen_store_fpr64(ctx, fp0, fd);
12356 tcg_temp_free_i64(fp0);
12358 break;
12359 case OPC_CVT_S_PU:
12360 check_cp1_64bitmode(ctx);
12362 TCGv_i32 fp0 = tcg_temp_new_i32();
12364 gen_load_fpr32h(ctx, fp0, fs);
12365 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12366 gen_store_fpr32(ctx, fp0, fd);
12367 tcg_temp_free_i32(fp0);
12369 break;
12370 case OPC_CVT_PW_PS:
12371 check_ps(ctx);
12373 TCGv_i64 fp0 = tcg_temp_new_i64();
12375 gen_load_fpr64(ctx, fp0, fs);
12376 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12377 gen_store_fpr64(ctx, fp0, fd);
12378 tcg_temp_free_i64(fp0);
12380 break;
12381 case OPC_CVT_S_PL:
12382 check_cp1_64bitmode(ctx);
12384 TCGv_i32 fp0 = tcg_temp_new_i32();
12386 gen_load_fpr32(ctx, fp0, fs);
12387 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12388 gen_store_fpr32(ctx, fp0, fd);
12389 tcg_temp_free_i32(fp0);
12391 break;
12392 case OPC_PLL_PS:
12393 check_ps(ctx);
12395 TCGv_i32 fp0 = tcg_temp_new_i32();
12396 TCGv_i32 fp1 = tcg_temp_new_i32();
12398 gen_load_fpr32(ctx, fp0, fs);
12399 gen_load_fpr32(ctx, fp1, ft);
12400 gen_store_fpr32h(ctx, fp0, fd);
12401 gen_store_fpr32(ctx, fp1, fd);
12402 tcg_temp_free_i32(fp0);
12403 tcg_temp_free_i32(fp1);
12405 break;
12406 case OPC_PLU_PS:
12407 check_ps(ctx);
12409 TCGv_i32 fp0 = tcg_temp_new_i32();
12410 TCGv_i32 fp1 = tcg_temp_new_i32();
12412 gen_load_fpr32(ctx, fp0, fs);
12413 gen_load_fpr32h(ctx, fp1, ft);
12414 gen_store_fpr32(ctx, fp1, fd);
12415 gen_store_fpr32h(ctx, fp0, fd);
12416 tcg_temp_free_i32(fp0);
12417 tcg_temp_free_i32(fp1);
12419 break;
12420 case OPC_PUL_PS:
12421 check_ps(ctx);
12423 TCGv_i32 fp0 = tcg_temp_new_i32();
12424 TCGv_i32 fp1 = tcg_temp_new_i32();
12426 gen_load_fpr32h(ctx, fp0, fs);
12427 gen_load_fpr32(ctx, fp1, ft);
12428 gen_store_fpr32(ctx, fp1, fd);
12429 gen_store_fpr32h(ctx, fp0, fd);
12430 tcg_temp_free_i32(fp0);
12431 tcg_temp_free_i32(fp1);
12433 break;
12434 case OPC_PUU_PS:
12435 check_ps(ctx);
12437 TCGv_i32 fp0 = tcg_temp_new_i32();
12438 TCGv_i32 fp1 = tcg_temp_new_i32();
12440 gen_load_fpr32h(ctx, fp0, fs);
12441 gen_load_fpr32h(ctx, fp1, ft);
12442 gen_store_fpr32(ctx, fp1, fd);
12443 gen_store_fpr32h(ctx, fp0, fd);
12444 tcg_temp_free_i32(fp0);
12445 tcg_temp_free_i32(fp1);
12447 break;
12448 case OPC_CMP_F_PS:
12449 case OPC_CMP_UN_PS:
12450 case OPC_CMP_EQ_PS:
12451 case OPC_CMP_UEQ_PS:
12452 case OPC_CMP_OLT_PS:
12453 case OPC_CMP_ULT_PS:
12454 case OPC_CMP_OLE_PS:
12455 case OPC_CMP_ULE_PS:
12456 case OPC_CMP_SF_PS:
12457 case OPC_CMP_NGLE_PS:
12458 case OPC_CMP_SEQ_PS:
12459 case OPC_CMP_NGL_PS:
12460 case OPC_CMP_LT_PS:
12461 case OPC_CMP_NGE_PS:
12462 case OPC_CMP_LE_PS:
12463 case OPC_CMP_NGT_PS:
12464 if (ctx->opcode & (1 << 6)) {
12465 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
12466 } else {
12467 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
12469 break;
12470 default:
12471 MIPS_INVAL("farith");
12472 gen_reserved_instruction(ctx);
12473 return;
12477 /* Coprocessor 3 (FPU) */
12478 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12479 int fd, int fs, int base, int index)
12481 TCGv t0 = tcg_temp_new();
12483 if (base == 0) {
12484 gen_load_gpr(t0, index);
12485 } else if (index == 0) {
12486 gen_load_gpr(t0, base);
12487 } else {
12488 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12491 * Don't do NOP if destination is zero: we must perform the actual
12492 * memory access.
12494 switch (opc) {
12495 case OPC_LWXC1:
12496 check_cop1x(ctx);
12498 TCGv_i32 fp0 = tcg_temp_new_i32();
12500 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12501 tcg_gen_trunc_tl_i32(fp0, t0);
12502 gen_store_fpr32(ctx, fp0, fd);
12503 tcg_temp_free_i32(fp0);
12505 break;
12506 case OPC_LDXC1:
12507 check_cop1x(ctx);
12508 check_cp1_registers(ctx, fd);
12510 TCGv_i64 fp0 = tcg_temp_new_i64();
12511 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12512 gen_store_fpr64(ctx, fp0, fd);
12513 tcg_temp_free_i64(fp0);
12515 break;
12516 case OPC_LUXC1:
12517 check_cp1_64bitmode(ctx);
12518 tcg_gen_andi_tl(t0, t0, ~0x7);
12520 TCGv_i64 fp0 = tcg_temp_new_i64();
12522 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12523 gen_store_fpr64(ctx, fp0, fd);
12524 tcg_temp_free_i64(fp0);
12526 break;
12527 case OPC_SWXC1:
12528 check_cop1x(ctx);
12530 TCGv_i32 fp0 = tcg_temp_new_i32();
12531 gen_load_fpr32(ctx, fp0, fs);
12532 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12533 tcg_temp_free_i32(fp0);
12535 break;
12536 case OPC_SDXC1:
12537 check_cop1x(ctx);
12538 check_cp1_registers(ctx, fs);
12540 TCGv_i64 fp0 = tcg_temp_new_i64();
12541 gen_load_fpr64(ctx, fp0, fs);
12542 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12543 tcg_temp_free_i64(fp0);
12545 break;
12546 case OPC_SUXC1:
12547 check_cp1_64bitmode(ctx);
12548 tcg_gen_andi_tl(t0, t0, ~0x7);
12550 TCGv_i64 fp0 = tcg_temp_new_i64();
12551 gen_load_fpr64(ctx, fp0, fs);
12552 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12553 tcg_temp_free_i64(fp0);
12555 break;
12557 tcg_temp_free(t0);
12560 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12561 int fd, int fr, int fs, int ft)
12563 switch (opc) {
12564 case OPC_ALNV_PS:
12565 check_ps(ctx);
12567 TCGv t0 = tcg_temp_local_new();
12568 TCGv_i32 fp = tcg_temp_new_i32();
12569 TCGv_i32 fph = tcg_temp_new_i32();
12570 TCGLabel *l1 = gen_new_label();
12571 TCGLabel *l2 = gen_new_label();
12573 gen_load_gpr(t0, fr);
12574 tcg_gen_andi_tl(t0, t0, 0x7);
12576 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12577 gen_load_fpr32(ctx, fp, fs);
12578 gen_load_fpr32h(ctx, fph, fs);
12579 gen_store_fpr32(ctx, fp, fd);
12580 gen_store_fpr32h(ctx, fph, fd);
12581 tcg_gen_br(l2);
12582 gen_set_label(l1);
12583 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12584 tcg_temp_free(t0);
12585 #ifdef TARGET_WORDS_BIGENDIAN
12586 gen_load_fpr32(ctx, fp, fs);
12587 gen_load_fpr32h(ctx, fph, ft);
12588 gen_store_fpr32h(ctx, fp, fd);
12589 gen_store_fpr32(ctx, fph, fd);
12590 #else
12591 gen_load_fpr32h(ctx, fph, fs);
12592 gen_load_fpr32(ctx, fp, ft);
12593 gen_store_fpr32(ctx, fph, fd);
12594 gen_store_fpr32h(ctx, fp, fd);
12595 #endif
12596 gen_set_label(l2);
12597 tcg_temp_free_i32(fp);
12598 tcg_temp_free_i32(fph);
12600 break;
12601 case OPC_MADD_S:
12602 check_cop1x(ctx);
12604 TCGv_i32 fp0 = tcg_temp_new_i32();
12605 TCGv_i32 fp1 = tcg_temp_new_i32();
12606 TCGv_i32 fp2 = tcg_temp_new_i32();
12608 gen_load_fpr32(ctx, fp0, fs);
12609 gen_load_fpr32(ctx, fp1, ft);
12610 gen_load_fpr32(ctx, fp2, fr);
12611 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12612 tcg_temp_free_i32(fp0);
12613 tcg_temp_free_i32(fp1);
12614 gen_store_fpr32(ctx, fp2, fd);
12615 tcg_temp_free_i32(fp2);
12617 break;
12618 case OPC_MADD_D:
12619 check_cop1x(ctx);
12620 check_cp1_registers(ctx, fd | fs | ft | fr);
12622 TCGv_i64 fp0 = tcg_temp_new_i64();
12623 TCGv_i64 fp1 = tcg_temp_new_i64();
12624 TCGv_i64 fp2 = tcg_temp_new_i64();
12626 gen_load_fpr64(ctx, fp0, fs);
12627 gen_load_fpr64(ctx, fp1, ft);
12628 gen_load_fpr64(ctx, fp2, fr);
12629 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12630 tcg_temp_free_i64(fp0);
12631 tcg_temp_free_i64(fp1);
12632 gen_store_fpr64(ctx, fp2, fd);
12633 tcg_temp_free_i64(fp2);
12635 break;
12636 case OPC_MADD_PS:
12637 check_ps(ctx);
12639 TCGv_i64 fp0 = tcg_temp_new_i64();
12640 TCGv_i64 fp1 = tcg_temp_new_i64();
12641 TCGv_i64 fp2 = tcg_temp_new_i64();
12643 gen_load_fpr64(ctx, fp0, fs);
12644 gen_load_fpr64(ctx, fp1, ft);
12645 gen_load_fpr64(ctx, fp2, fr);
12646 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12647 tcg_temp_free_i64(fp0);
12648 tcg_temp_free_i64(fp1);
12649 gen_store_fpr64(ctx, fp2, fd);
12650 tcg_temp_free_i64(fp2);
12652 break;
12653 case OPC_MSUB_S:
12654 check_cop1x(ctx);
12656 TCGv_i32 fp0 = tcg_temp_new_i32();
12657 TCGv_i32 fp1 = tcg_temp_new_i32();
12658 TCGv_i32 fp2 = tcg_temp_new_i32();
12660 gen_load_fpr32(ctx, fp0, fs);
12661 gen_load_fpr32(ctx, fp1, ft);
12662 gen_load_fpr32(ctx, fp2, fr);
12663 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12664 tcg_temp_free_i32(fp0);
12665 tcg_temp_free_i32(fp1);
12666 gen_store_fpr32(ctx, fp2, fd);
12667 tcg_temp_free_i32(fp2);
12669 break;
12670 case OPC_MSUB_D:
12671 check_cop1x(ctx);
12672 check_cp1_registers(ctx, fd | fs | ft | fr);
12674 TCGv_i64 fp0 = tcg_temp_new_i64();
12675 TCGv_i64 fp1 = tcg_temp_new_i64();
12676 TCGv_i64 fp2 = tcg_temp_new_i64();
12678 gen_load_fpr64(ctx, fp0, fs);
12679 gen_load_fpr64(ctx, fp1, ft);
12680 gen_load_fpr64(ctx, fp2, fr);
12681 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12682 tcg_temp_free_i64(fp0);
12683 tcg_temp_free_i64(fp1);
12684 gen_store_fpr64(ctx, fp2, fd);
12685 tcg_temp_free_i64(fp2);
12687 break;
12688 case OPC_MSUB_PS:
12689 check_ps(ctx);
12691 TCGv_i64 fp0 = tcg_temp_new_i64();
12692 TCGv_i64 fp1 = tcg_temp_new_i64();
12693 TCGv_i64 fp2 = tcg_temp_new_i64();
12695 gen_load_fpr64(ctx, fp0, fs);
12696 gen_load_fpr64(ctx, fp1, ft);
12697 gen_load_fpr64(ctx, fp2, fr);
12698 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12699 tcg_temp_free_i64(fp0);
12700 tcg_temp_free_i64(fp1);
12701 gen_store_fpr64(ctx, fp2, fd);
12702 tcg_temp_free_i64(fp2);
12704 break;
12705 case OPC_NMADD_S:
12706 check_cop1x(ctx);
12708 TCGv_i32 fp0 = tcg_temp_new_i32();
12709 TCGv_i32 fp1 = tcg_temp_new_i32();
12710 TCGv_i32 fp2 = tcg_temp_new_i32();
12712 gen_load_fpr32(ctx, fp0, fs);
12713 gen_load_fpr32(ctx, fp1, ft);
12714 gen_load_fpr32(ctx, fp2, fr);
12715 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12716 tcg_temp_free_i32(fp0);
12717 tcg_temp_free_i32(fp1);
12718 gen_store_fpr32(ctx, fp2, fd);
12719 tcg_temp_free_i32(fp2);
12721 break;
12722 case OPC_NMADD_D:
12723 check_cop1x(ctx);
12724 check_cp1_registers(ctx, fd | fs | ft | fr);
12726 TCGv_i64 fp0 = tcg_temp_new_i64();
12727 TCGv_i64 fp1 = tcg_temp_new_i64();
12728 TCGv_i64 fp2 = tcg_temp_new_i64();
12730 gen_load_fpr64(ctx, fp0, fs);
12731 gen_load_fpr64(ctx, fp1, ft);
12732 gen_load_fpr64(ctx, fp2, fr);
12733 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12734 tcg_temp_free_i64(fp0);
12735 tcg_temp_free_i64(fp1);
12736 gen_store_fpr64(ctx, fp2, fd);
12737 tcg_temp_free_i64(fp2);
12739 break;
12740 case OPC_NMADD_PS:
12741 check_ps(ctx);
12743 TCGv_i64 fp0 = tcg_temp_new_i64();
12744 TCGv_i64 fp1 = tcg_temp_new_i64();
12745 TCGv_i64 fp2 = tcg_temp_new_i64();
12747 gen_load_fpr64(ctx, fp0, fs);
12748 gen_load_fpr64(ctx, fp1, ft);
12749 gen_load_fpr64(ctx, fp2, fr);
12750 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12751 tcg_temp_free_i64(fp0);
12752 tcg_temp_free_i64(fp1);
12753 gen_store_fpr64(ctx, fp2, fd);
12754 tcg_temp_free_i64(fp2);
12756 break;
12757 case OPC_NMSUB_S:
12758 check_cop1x(ctx);
12760 TCGv_i32 fp0 = tcg_temp_new_i32();
12761 TCGv_i32 fp1 = tcg_temp_new_i32();
12762 TCGv_i32 fp2 = tcg_temp_new_i32();
12764 gen_load_fpr32(ctx, fp0, fs);
12765 gen_load_fpr32(ctx, fp1, ft);
12766 gen_load_fpr32(ctx, fp2, fr);
12767 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12768 tcg_temp_free_i32(fp0);
12769 tcg_temp_free_i32(fp1);
12770 gen_store_fpr32(ctx, fp2, fd);
12771 tcg_temp_free_i32(fp2);
12773 break;
12774 case OPC_NMSUB_D:
12775 check_cop1x(ctx);
12776 check_cp1_registers(ctx, fd | fs | ft | fr);
12778 TCGv_i64 fp0 = tcg_temp_new_i64();
12779 TCGv_i64 fp1 = tcg_temp_new_i64();
12780 TCGv_i64 fp2 = tcg_temp_new_i64();
12782 gen_load_fpr64(ctx, fp0, fs);
12783 gen_load_fpr64(ctx, fp1, ft);
12784 gen_load_fpr64(ctx, fp2, fr);
12785 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12786 tcg_temp_free_i64(fp0);
12787 tcg_temp_free_i64(fp1);
12788 gen_store_fpr64(ctx, fp2, fd);
12789 tcg_temp_free_i64(fp2);
12791 break;
12792 case OPC_NMSUB_PS:
12793 check_ps(ctx);
12795 TCGv_i64 fp0 = tcg_temp_new_i64();
12796 TCGv_i64 fp1 = tcg_temp_new_i64();
12797 TCGv_i64 fp2 = tcg_temp_new_i64();
12799 gen_load_fpr64(ctx, fp0, fs);
12800 gen_load_fpr64(ctx, fp1, ft);
12801 gen_load_fpr64(ctx, fp2, fr);
12802 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12803 tcg_temp_free_i64(fp0);
12804 tcg_temp_free_i64(fp1);
12805 gen_store_fpr64(ctx, fp2, fd);
12806 tcg_temp_free_i64(fp2);
12808 break;
12809 default:
12810 MIPS_INVAL("flt3_arith");
12811 gen_reserved_instruction(ctx);
12812 return;
12816 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12818 TCGv t0;
12820 #if !defined(CONFIG_USER_ONLY)
12822 * The Linux kernel will emulate rdhwr if it's not supported natively.
12823 * Therefore only check the ISA in system mode.
12825 check_insn(ctx, ISA_MIPS_R2);
12826 #endif
12827 t0 = tcg_temp_new();
12829 switch (rd) {
12830 case 0:
12831 gen_helper_rdhwr_cpunum(t0, cpu_env);
12832 gen_store_gpr(t0, rt);
12833 break;
12834 case 1:
12835 gen_helper_rdhwr_synci_step(t0, cpu_env);
12836 gen_store_gpr(t0, rt);
12837 break;
12838 case 2:
12839 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12840 gen_io_start();
12842 gen_helper_rdhwr_cc(t0, cpu_env);
12843 gen_store_gpr(t0, rt);
12845 * Break the TB to be able to take timer interrupts immediately
12846 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12847 * we break completely out of translated code.
12849 gen_save_pc(ctx->base.pc_next + 4);
12850 ctx->base.is_jmp = DISAS_EXIT;
12851 break;
12852 case 3:
12853 gen_helper_rdhwr_ccres(t0, cpu_env);
12854 gen_store_gpr(t0, rt);
12855 break;
12856 case 4:
12857 check_insn(ctx, ISA_MIPS_R6);
12858 if (sel != 0) {
12860 * Performance counter registers are not implemented other than
12861 * control register 0.
12863 generate_exception(ctx, EXCP_RI);
12865 gen_helper_rdhwr_performance(t0, cpu_env);
12866 gen_store_gpr(t0, rt);
12867 break;
12868 case 5:
12869 check_insn(ctx, ISA_MIPS_R6);
12870 gen_helper_rdhwr_xnp(t0, cpu_env);
12871 gen_store_gpr(t0, rt);
12872 break;
12873 case 29:
12874 #if defined(CONFIG_USER_ONLY)
12875 tcg_gen_ld_tl(t0, cpu_env,
12876 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12877 gen_store_gpr(t0, rt);
12878 break;
12879 #else
12880 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12881 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12882 tcg_gen_ld_tl(t0, cpu_env,
12883 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12884 gen_store_gpr(t0, rt);
12885 } else {
12886 gen_reserved_instruction(ctx);
12888 break;
12889 #endif
12890 default: /* Invalid */
12891 MIPS_INVAL("rdhwr");
12892 gen_reserved_instruction(ctx);
12893 break;
12895 tcg_temp_free(t0);
12898 static inline void clear_branch_hflags(DisasContext *ctx)
12900 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12901 if (ctx->base.is_jmp == DISAS_NEXT) {
12902 save_cpu_state(ctx, 0);
12903 } else {
12905 * It is not safe to save ctx->hflags as hflags may be changed
12906 * in execution time by the instruction in delay / forbidden slot.
12908 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12912 static void gen_branch(DisasContext *ctx, int insn_bytes)
12914 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12915 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12916 /* Branches completion */
12917 clear_branch_hflags(ctx);
12918 ctx->base.is_jmp = DISAS_NORETURN;
12919 /* FIXME: Need to clear can_do_io. */
12920 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12921 case MIPS_HFLAG_FBNSLOT:
12922 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12923 break;
12924 case MIPS_HFLAG_B:
12925 /* unconditional branch */
12926 if (proc_hflags & MIPS_HFLAG_BX) {
12927 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12929 gen_goto_tb(ctx, 0, ctx->btarget);
12930 break;
12931 case MIPS_HFLAG_BL:
12932 /* blikely taken case */
12933 gen_goto_tb(ctx, 0, ctx->btarget);
12934 break;
12935 case MIPS_HFLAG_BC:
12936 /* Conditional branch */
12938 TCGLabel *l1 = gen_new_label();
12940 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12941 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12942 gen_set_label(l1);
12943 gen_goto_tb(ctx, 0, ctx->btarget);
12945 break;
12946 case MIPS_HFLAG_BR:
12947 /* unconditional branch to register */
12948 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12949 TCGv t0 = tcg_temp_new();
12950 TCGv_i32 t1 = tcg_temp_new_i32();
12952 tcg_gen_andi_tl(t0, btarget, 0x1);
12953 tcg_gen_trunc_tl_i32(t1, t0);
12954 tcg_temp_free(t0);
12955 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12956 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12957 tcg_gen_or_i32(hflags, hflags, t1);
12958 tcg_temp_free_i32(t1);
12960 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12961 } else {
12962 tcg_gen_mov_tl(cpu_PC, btarget);
12964 if (ctx->base.singlestep_enabled) {
12965 save_cpu_state(ctx, 0);
12966 gen_helper_raise_exception_debug(cpu_env);
12968 tcg_gen_lookup_and_goto_ptr();
12969 break;
12970 default:
12971 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12972 abort();
12977 /* Compact Branches */
12978 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12979 int rs, int rt, int32_t offset)
12981 int bcond_compute = 0;
12982 TCGv t0 = tcg_temp_new();
12983 TCGv t1 = tcg_temp_new();
12984 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12986 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12987 #ifdef MIPS_DEBUG_DISAS
12988 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12989 "\n", ctx->base.pc_next);
12990 #endif
12991 gen_reserved_instruction(ctx);
12992 goto out;
12995 /* Load needed operands and calculate btarget */
12996 switch (opc) {
12997 /* compact branch */
12998 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12999 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13000 gen_load_gpr(t0, rs);
13001 gen_load_gpr(t1, rt);
13002 bcond_compute = 1;
13003 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13004 if (rs <= rt && rs == 0) {
13005 /* OPC_BEQZALC, OPC_BNEZALC */
13006 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13008 break;
13009 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13010 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13011 gen_load_gpr(t0, rs);
13012 gen_load_gpr(t1, rt);
13013 bcond_compute = 1;
13014 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13015 break;
13016 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13017 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13018 if (rs == 0 || rs == rt) {
13019 /* OPC_BLEZALC, OPC_BGEZALC */
13020 /* OPC_BGTZALC, OPC_BLTZALC */
13021 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13023 gen_load_gpr(t0, rs);
13024 gen_load_gpr(t1, rt);
13025 bcond_compute = 1;
13026 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13027 break;
13028 case OPC_BC:
13029 case OPC_BALC:
13030 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13031 break;
13032 case OPC_BEQZC:
13033 case OPC_BNEZC:
13034 if (rs != 0) {
13035 /* OPC_BEQZC, OPC_BNEZC */
13036 gen_load_gpr(t0, rs);
13037 bcond_compute = 1;
13038 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13039 } else {
13040 /* OPC_JIC, OPC_JIALC */
13041 TCGv tbase = tcg_temp_new();
13042 TCGv toffset = tcg_temp_new();
13044 gen_load_gpr(tbase, rt);
13045 tcg_gen_movi_tl(toffset, offset);
13046 gen_op_addr_add(ctx, btarget, tbase, toffset);
13047 tcg_temp_free(tbase);
13048 tcg_temp_free(toffset);
13050 break;
13051 default:
13052 MIPS_INVAL("Compact branch/jump");
13053 gen_reserved_instruction(ctx);
13054 goto out;
13057 if (bcond_compute == 0) {
13058 /* Uncoditional compact branch */
13059 switch (opc) {
13060 case OPC_JIALC:
13061 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13062 /* Fallthrough */
13063 case OPC_JIC:
13064 ctx->hflags |= MIPS_HFLAG_BR;
13065 break;
13066 case OPC_BALC:
13067 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13068 /* Fallthrough */
13069 case OPC_BC:
13070 ctx->hflags |= MIPS_HFLAG_B;
13071 break;
13072 default:
13073 MIPS_INVAL("Compact branch/jump");
13074 gen_reserved_instruction(ctx);
13075 goto out;
13078 /* Generating branch here as compact branches don't have delay slot */
13079 gen_branch(ctx, 4);
13080 } else {
13081 /* Conditional compact branch */
13082 TCGLabel *fs = gen_new_label();
13083 save_cpu_state(ctx, 0);
13085 switch (opc) {
13086 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13087 if (rs == 0 && rt != 0) {
13088 /* OPC_BLEZALC */
13089 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13090 } else if (rs != 0 && rt != 0 && rs == rt) {
13091 /* OPC_BGEZALC */
13092 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13093 } else {
13094 /* OPC_BGEUC */
13095 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13097 break;
13098 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13099 if (rs == 0 && rt != 0) {
13100 /* OPC_BGTZALC */
13101 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13102 } else if (rs != 0 && rt != 0 && rs == rt) {
13103 /* OPC_BLTZALC */
13104 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13105 } else {
13106 /* OPC_BLTUC */
13107 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13109 break;
13110 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13111 if (rs == 0 && rt != 0) {
13112 /* OPC_BLEZC */
13113 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13114 } else if (rs != 0 && rt != 0 && rs == rt) {
13115 /* OPC_BGEZC */
13116 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13117 } else {
13118 /* OPC_BGEC */
13119 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13121 break;
13122 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13123 if (rs == 0 && rt != 0) {
13124 /* OPC_BGTZC */
13125 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13126 } else if (rs != 0 && rt != 0 && rs == rt) {
13127 /* OPC_BLTZC */
13128 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13129 } else {
13130 /* OPC_BLTC */
13131 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13133 break;
13134 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13135 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13136 if (rs >= rt) {
13137 /* OPC_BOVC, OPC_BNVC */
13138 TCGv t2 = tcg_temp_new();
13139 TCGv t3 = tcg_temp_new();
13140 TCGv t4 = tcg_temp_new();
13141 TCGv input_overflow = tcg_temp_new();
13143 gen_load_gpr(t0, rs);
13144 gen_load_gpr(t1, rt);
13145 tcg_gen_ext32s_tl(t2, t0);
13146 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13147 tcg_gen_ext32s_tl(t3, t1);
13148 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13149 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13151 tcg_gen_add_tl(t4, t2, t3);
13152 tcg_gen_ext32s_tl(t4, t4);
13153 tcg_gen_xor_tl(t2, t2, t3);
13154 tcg_gen_xor_tl(t3, t4, t3);
13155 tcg_gen_andc_tl(t2, t3, t2);
13156 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13157 tcg_gen_or_tl(t4, t4, input_overflow);
13158 if (opc == OPC_BOVC) {
13159 /* OPC_BOVC */
13160 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13161 } else {
13162 /* OPC_BNVC */
13163 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13165 tcg_temp_free(input_overflow);
13166 tcg_temp_free(t4);
13167 tcg_temp_free(t3);
13168 tcg_temp_free(t2);
13169 } else if (rs < rt && rs == 0) {
13170 /* OPC_BEQZALC, OPC_BNEZALC */
13171 if (opc == OPC_BEQZALC) {
13172 /* OPC_BEQZALC */
13173 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13174 } else {
13175 /* OPC_BNEZALC */
13176 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13178 } else {
13179 /* OPC_BEQC, OPC_BNEC */
13180 if (opc == OPC_BEQC) {
13181 /* OPC_BEQC */
13182 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13183 } else {
13184 /* OPC_BNEC */
13185 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13188 break;
13189 case OPC_BEQZC:
13190 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13191 break;
13192 case OPC_BNEZC:
13193 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13194 break;
13195 default:
13196 MIPS_INVAL("Compact conditional branch/jump");
13197 gen_reserved_instruction(ctx);
13198 goto out;
13201 /* Generating branch here as compact branches don't have delay slot */
13202 gen_goto_tb(ctx, 1, ctx->btarget);
13203 gen_set_label(fs);
13205 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13208 out:
13209 tcg_temp_free(t0);
13210 tcg_temp_free(t1);
13213 /* ISA extensions (ASEs) */
13214 /* MIPS16 extension to MIPS32 */
13216 /* MIPS16 major opcodes */
13217 enum {
13218 M16_OPC_ADDIUSP = 0x00,
13219 M16_OPC_ADDIUPC = 0x01,
13220 M16_OPC_B = 0x02,
13221 M16_OPC_JAL = 0x03,
13222 M16_OPC_BEQZ = 0x04,
13223 M16_OPC_BNEQZ = 0x05,
13224 M16_OPC_SHIFT = 0x06,
13225 M16_OPC_LD = 0x07,
13226 M16_OPC_RRIA = 0x08,
13227 M16_OPC_ADDIU8 = 0x09,
13228 M16_OPC_SLTI = 0x0a,
13229 M16_OPC_SLTIU = 0x0b,
13230 M16_OPC_I8 = 0x0c,
13231 M16_OPC_LI = 0x0d,
13232 M16_OPC_CMPI = 0x0e,
13233 M16_OPC_SD = 0x0f,
13234 M16_OPC_LB = 0x10,
13235 M16_OPC_LH = 0x11,
13236 M16_OPC_LWSP = 0x12,
13237 M16_OPC_LW = 0x13,
13238 M16_OPC_LBU = 0x14,
13239 M16_OPC_LHU = 0x15,
13240 M16_OPC_LWPC = 0x16,
13241 M16_OPC_LWU = 0x17,
13242 M16_OPC_SB = 0x18,
13243 M16_OPC_SH = 0x19,
13244 M16_OPC_SWSP = 0x1a,
13245 M16_OPC_SW = 0x1b,
13246 M16_OPC_RRR = 0x1c,
13247 M16_OPC_RR = 0x1d,
13248 M16_OPC_EXTEND = 0x1e,
13249 M16_OPC_I64 = 0x1f
13252 /* I8 funct field */
13253 enum {
13254 I8_BTEQZ = 0x0,
13255 I8_BTNEZ = 0x1,
13256 I8_SWRASP = 0x2,
13257 I8_ADJSP = 0x3,
13258 I8_SVRS = 0x4,
13259 I8_MOV32R = 0x5,
13260 I8_MOVR32 = 0x7
13263 /* RRR f field */
13264 enum {
13265 RRR_DADDU = 0x0,
13266 RRR_ADDU = 0x1,
13267 RRR_DSUBU = 0x2,
13268 RRR_SUBU = 0x3
13271 /* RR funct field */
13272 enum {
13273 RR_JR = 0x00,
13274 RR_SDBBP = 0x01,
13275 RR_SLT = 0x02,
13276 RR_SLTU = 0x03,
13277 RR_SLLV = 0x04,
13278 RR_BREAK = 0x05,
13279 RR_SRLV = 0x06,
13280 RR_SRAV = 0x07,
13281 RR_DSRL = 0x08,
13282 RR_CMP = 0x0a,
13283 RR_NEG = 0x0b,
13284 RR_AND = 0x0c,
13285 RR_OR = 0x0d,
13286 RR_XOR = 0x0e,
13287 RR_NOT = 0x0f,
13288 RR_MFHI = 0x10,
13289 RR_CNVT = 0x11,
13290 RR_MFLO = 0x12,
13291 RR_DSRA = 0x13,
13292 RR_DSLLV = 0x14,
13293 RR_DSRLV = 0x16,
13294 RR_DSRAV = 0x17,
13295 RR_MULT = 0x18,
13296 RR_MULTU = 0x19,
13297 RR_DIV = 0x1a,
13298 RR_DIVU = 0x1b,
13299 RR_DMULT = 0x1c,
13300 RR_DMULTU = 0x1d,
13301 RR_DDIV = 0x1e,
13302 RR_DDIVU = 0x1f
13305 /* I64 funct field */
13306 enum {
13307 I64_LDSP = 0x0,
13308 I64_SDSP = 0x1,
13309 I64_SDRASP = 0x2,
13310 I64_DADJSP = 0x3,
13311 I64_LDPC = 0x4,
13312 I64_DADDIU5 = 0x5,
13313 I64_DADDIUPC = 0x6,
13314 I64_DADDIUSP = 0x7
13317 /* RR ry field for CNVT */
13318 enum {
13319 RR_RY_CNVT_ZEB = 0x0,
13320 RR_RY_CNVT_ZEH = 0x1,
13321 RR_RY_CNVT_ZEW = 0x2,
13322 RR_RY_CNVT_SEB = 0x4,
13323 RR_RY_CNVT_SEH = 0x5,
13324 RR_RY_CNVT_SEW = 0x6,
13327 static int xlat(int r)
13329 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13331 return map[r];
13334 static void gen_mips16_save(DisasContext *ctx,
13335 int xsregs, int aregs,
13336 int do_ra, int do_s0, int do_s1,
13337 int framesize)
13339 TCGv t0 = tcg_temp_new();
13340 TCGv t1 = tcg_temp_new();
13341 TCGv t2 = tcg_temp_new();
13342 int args, astatic;
13344 switch (aregs) {
13345 case 0:
13346 case 1:
13347 case 2:
13348 case 3:
13349 case 11:
13350 args = 0;
13351 break;
13352 case 4:
13353 case 5:
13354 case 6:
13355 case 7:
13356 args = 1;
13357 break;
13358 case 8:
13359 case 9:
13360 case 10:
13361 args = 2;
13362 break;
13363 case 12:
13364 case 13:
13365 args = 3;
13366 break;
13367 case 14:
13368 args = 4;
13369 break;
13370 default:
13371 gen_reserved_instruction(ctx);
13372 return;
13375 switch (args) {
13376 case 4:
13377 gen_base_offset_addr(ctx, t0, 29, 12);
13378 gen_load_gpr(t1, 7);
13379 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13380 /* Fall through */
13381 case 3:
13382 gen_base_offset_addr(ctx, t0, 29, 8);
13383 gen_load_gpr(t1, 6);
13384 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13385 /* Fall through */
13386 case 2:
13387 gen_base_offset_addr(ctx, t0, 29, 4);
13388 gen_load_gpr(t1, 5);
13389 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13390 /* Fall through */
13391 case 1:
13392 gen_base_offset_addr(ctx, t0, 29, 0);
13393 gen_load_gpr(t1, 4);
13394 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13397 gen_load_gpr(t0, 29);
13399 #define DECR_AND_STORE(reg) do { \
13400 tcg_gen_movi_tl(t2, -4); \
13401 gen_op_addr_add(ctx, t0, t0, t2); \
13402 gen_load_gpr(t1, reg); \
13403 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13404 } while (0)
13406 if (do_ra) {
13407 DECR_AND_STORE(31);
13410 switch (xsregs) {
13411 case 7:
13412 DECR_AND_STORE(30);
13413 /* Fall through */
13414 case 6:
13415 DECR_AND_STORE(23);
13416 /* Fall through */
13417 case 5:
13418 DECR_AND_STORE(22);
13419 /* Fall through */
13420 case 4:
13421 DECR_AND_STORE(21);
13422 /* Fall through */
13423 case 3:
13424 DECR_AND_STORE(20);
13425 /* Fall through */
13426 case 2:
13427 DECR_AND_STORE(19);
13428 /* Fall through */
13429 case 1:
13430 DECR_AND_STORE(18);
13433 if (do_s1) {
13434 DECR_AND_STORE(17);
13436 if (do_s0) {
13437 DECR_AND_STORE(16);
13440 switch (aregs) {
13441 case 0:
13442 case 4:
13443 case 8:
13444 case 12:
13445 case 14:
13446 astatic = 0;
13447 break;
13448 case 1:
13449 case 5:
13450 case 9:
13451 case 13:
13452 astatic = 1;
13453 break;
13454 case 2:
13455 case 6:
13456 case 10:
13457 astatic = 2;
13458 break;
13459 case 3:
13460 case 7:
13461 astatic = 3;
13462 break;
13463 case 11:
13464 astatic = 4;
13465 break;
13466 default:
13467 gen_reserved_instruction(ctx);
13468 return;
13471 if (astatic > 0) {
13472 DECR_AND_STORE(7);
13473 if (astatic > 1) {
13474 DECR_AND_STORE(6);
13475 if (astatic > 2) {
13476 DECR_AND_STORE(5);
13477 if (astatic > 3) {
13478 DECR_AND_STORE(4);
13483 #undef DECR_AND_STORE
13485 tcg_gen_movi_tl(t2, -framesize);
13486 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13487 tcg_temp_free(t0);
13488 tcg_temp_free(t1);
13489 tcg_temp_free(t2);
13492 static void gen_mips16_restore(DisasContext *ctx,
13493 int xsregs, int aregs,
13494 int do_ra, int do_s0, int do_s1,
13495 int framesize)
13497 int astatic;
13498 TCGv t0 = tcg_temp_new();
13499 TCGv t1 = tcg_temp_new();
13500 TCGv t2 = tcg_temp_new();
13502 tcg_gen_movi_tl(t2, framesize);
13503 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13505 #define DECR_AND_LOAD(reg) do { \
13506 tcg_gen_movi_tl(t2, -4); \
13507 gen_op_addr_add(ctx, t0, t0, t2); \
13508 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13509 gen_store_gpr(t1, reg); \
13510 } while (0)
13512 if (do_ra) {
13513 DECR_AND_LOAD(31);
13516 switch (xsregs) {
13517 case 7:
13518 DECR_AND_LOAD(30);
13519 /* Fall through */
13520 case 6:
13521 DECR_AND_LOAD(23);
13522 /* Fall through */
13523 case 5:
13524 DECR_AND_LOAD(22);
13525 /* Fall through */
13526 case 4:
13527 DECR_AND_LOAD(21);
13528 /* Fall through */
13529 case 3:
13530 DECR_AND_LOAD(20);
13531 /* Fall through */
13532 case 2:
13533 DECR_AND_LOAD(19);
13534 /* Fall through */
13535 case 1:
13536 DECR_AND_LOAD(18);
13539 if (do_s1) {
13540 DECR_AND_LOAD(17);
13542 if (do_s0) {
13543 DECR_AND_LOAD(16);
13546 switch (aregs) {
13547 case 0:
13548 case 4:
13549 case 8:
13550 case 12:
13551 case 14:
13552 astatic = 0;
13553 break;
13554 case 1:
13555 case 5:
13556 case 9:
13557 case 13:
13558 astatic = 1;
13559 break;
13560 case 2:
13561 case 6:
13562 case 10:
13563 astatic = 2;
13564 break;
13565 case 3:
13566 case 7:
13567 astatic = 3;
13568 break;
13569 case 11:
13570 astatic = 4;
13571 break;
13572 default:
13573 gen_reserved_instruction(ctx);
13574 return;
13577 if (astatic > 0) {
13578 DECR_AND_LOAD(7);
13579 if (astatic > 1) {
13580 DECR_AND_LOAD(6);
13581 if (astatic > 2) {
13582 DECR_AND_LOAD(5);
13583 if (astatic > 3) {
13584 DECR_AND_LOAD(4);
13589 #undef DECR_AND_LOAD
13591 tcg_gen_movi_tl(t2, framesize);
13592 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13593 tcg_temp_free(t0);
13594 tcg_temp_free(t1);
13595 tcg_temp_free(t2);
13598 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13599 int is_64_bit, int extended)
13601 TCGv t0;
13603 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13604 gen_reserved_instruction(ctx);
13605 return;
13608 t0 = tcg_temp_new();
13610 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13611 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13612 if (!is_64_bit) {
13613 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13616 tcg_temp_free(t0);
13619 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13620 int16_t offset)
13622 TCGv_i32 t0 = tcg_const_i32(op);
13623 TCGv t1 = tcg_temp_new();
13624 gen_base_offset_addr(ctx, t1, base, offset);
13625 gen_helper_cache(cpu_env, t1, t0);
13628 #if defined(TARGET_MIPS64)
13629 static void decode_i64_mips16(DisasContext *ctx,
13630 int ry, int funct, int16_t offset,
13631 int extended)
13633 switch (funct) {
13634 case I64_LDSP:
13635 check_insn(ctx, ISA_MIPS3);
13636 check_mips_64(ctx);
13637 offset = extended ? offset : offset << 3;
13638 gen_ld(ctx, OPC_LD, ry, 29, offset);
13639 break;
13640 case I64_SDSP:
13641 check_insn(ctx, ISA_MIPS3);
13642 check_mips_64(ctx);
13643 offset = extended ? offset : offset << 3;
13644 gen_st(ctx, OPC_SD, ry, 29, offset);
13645 break;
13646 case I64_SDRASP:
13647 check_insn(ctx, ISA_MIPS3);
13648 check_mips_64(ctx);
13649 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13650 gen_st(ctx, OPC_SD, 31, 29, offset);
13651 break;
13652 case I64_DADJSP:
13653 check_insn(ctx, ISA_MIPS3);
13654 check_mips_64(ctx);
13655 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13656 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13657 break;
13658 case I64_LDPC:
13659 check_insn(ctx, ISA_MIPS3);
13660 check_mips_64(ctx);
13661 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13662 gen_reserved_instruction(ctx);
13663 } else {
13664 offset = extended ? offset : offset << 3;
13665 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13667 break;
13668 case I64_DADDIU5:
13669 check_insn(ctx, ISA_MIPS3);
13670 check_mips_64(ctx);
13671 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13672 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13673 break;
13674 case I64_DADDIUPC:
13675 check_insn(ctx, ISA_MIPS3);
13676 check_mips_64(ctx);
13677 offset = extended ? offset : offset << 2;
13678 gen_addiupc(ctx, ry, offset, 1, extended);
13679 break;
13680 case I64_DADDIUSP:
13681 check_insn(ctx, ISA_MIPS3);
13682 check_mips_64(ctx);
13683 offset = extended ? offset : offset << 2;
13684 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13685 break;
13688 #endif
13690 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13692 int extend = translator_lduw(env, ctx->base.pc_next + 2);
13693 int op, rx, ry, funct, sa;
13694 int16_t imm, offset;
13696 ctx->opcode = (ctx->opcode << 16) | extend;
13697 op = (ctx->opcode >> 11) & 0x1f;
13698 sa = (ctx->opcode >> 22) & 0x1f;
13699 funct = (ctx->opcode >> 8) & 0x7;
13700 rx = xlat((ctx->opcode >> 8) & 0x7);
13701 ry = xlat((ctx->opcode >> 5) & 0x7);
13702 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13703 | ((ctx->opcode >> 21) & 0x3f) << 5
13704 | (ctx->opcode & 0x1f));
13707 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13708 * counterparts.
13710 switch (op) {
13711 case M16_OPC_ADDIUSP:
13712 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13713 break;
13714 case M16_OPC_ADDIUPC:
13715 gen_addiupc(ctx, rx, imm, 0, 1);
13716 break;
13717 case M16_OPC_B:
13718 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13719 /* No delay slot, so just process as a normal instruction */
13720 break;
13721 case M16_OPC_BEQZ:
13722 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13723 /* No delay slot, so just process as a normal instruction */
13724 break;
13725 case M16_OPC_BNEQZ:
13726 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13727 /* No delay slot, so just process as a normal instruction */
13728 break;
13729 case M16_OPC_SHIFT:
13730 switch (ctx->opcode & 0x3) {
13731 case 0x0:
13732 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13733 break;
13734 case 0x1:
13735 #if defined(TARGET_MIPS64)
13736 check_mips_64(ctx);
13737 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13738 #else
13739 gen_reserved_instruction(ctx);
13740 #endif
13741 break;
13742 case 0x2:
13743 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13744 break;
13745 case 0x3:
13746 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13747 break;
13749 break;
13750 #if defined(TARGET_MIPS64)
13751 case M16_OPC_LD:
13752 check_insn(ctx, ISA_MIPS3);
13753 check_mips_64(ctx);
13754 gen_ld(ctx, OPC_LD, ry, rx, offset);
13755 break;
13756 #endif
13757 case M16_OPC_RRIA:
13758 imm = ctx->opcode & 0xf;
13759 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13760 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13761 imm = (int16_t) (imm << 1) >> 1;
13762 if ((ctx->opcode >> 4) & 0x1) {
13763 #if defined(TARGET_MIPS64)
13764 check_mips_64(ctx);
13765 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13766 #else
13767 gen_reserved_instruction(ctx);
13768 #endif
13769 } else {
13770 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13772 break;
13773 case M16_OPC_ADDIU8:
13774 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13775 break;
13776 case M16_OPC_SLTI:
13777 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13778 break;
13779 case M16_OPC_SLTIU:
13780 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13781 break;
13782 case M16_OPC_I8:
13783 switch (funct) {
13784 case I8_BTEQZ:
13785 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13786 break;
13787 case I8_BTNEZ:
13788 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13789 break;
13790 case I8_SWRASP:
13791 gen_st(ctx, OPC_SW, 31, 29, imm);
13792 break;
13793 case I8_ADJSP:
13794 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13795 break;
13796 case I8_SVRS:
13797 check_insn(ctx, ISA_MIPS_R1);
13799 int xsregs = (ctx->opcode >> 24) & 0x7;
13800 int aregs = (ctx->opcode >> 16) & 0xf;
13801 int do_ra = (ctx->opcode >> 6) & 0x1;
13802 int do_s0 = (ctx->opcode >> 5) & 0x1;
13803 int do_s1 = (ctx->opcode >> 4) & 0x1;
13804 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13805 | (ctx->opcode & 0xf)) << 3;
13807 if (ctx->opcode & (1 << 7)) {
13808 gen_mips16_save(ctx, xsregs, aregs,
13809 do_ra, do_s0, do_s1,
13810 framesize);
13811 } else {
13812 gen_mips16_restore(ctx, xsregs, aregs,
13813 do_ra, do_s0, do_s1,
13814 framesize);
13817 break;
13818 default:
13819 gen_reserved_instruction(ctx);
13820 break;
13822 break;
13823 case M16_OPC_LI:
13824 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13825 break;
13826 case M16_OPC_CMPI:
13827 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13828 break;
13829 #if defined(TARGET_MIPS64)
13830 case M16_OPC_SD:
13831 check_insn(ctx, ISA_MIPS3);
13832 check_mips_64(ctx);
13833 gen_st(ctx, OPC_SD, ry, rx, offset);
13834 break;
13835 #endif
13836 case M16_OPC_LB:
13837 gen_ld(ctx, OPC_LB, ry, rx, offset);
13838 break;
13839 case M16_OPC_LH:
13840 gen_ld(ctx, OPC_LH, ry, rx, offset);
13841 break;
13842 case M16_OPC_LWSP:
13843 gen_ld(ctx, OPC_LW, rx, 29, offset);
13844 break;
13845 case M16_OPC_LW:
13846 gen_ld(ctx, OPC_LW, ry, rx, offset);
13847 break;
13848 case M16_OPC_LBU:
13849 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13850 break;
13851 case M16_OPC_LHU:
13852 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13853 break;
13854 case M16_OPC_LWPC:
13855 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13856 break;
13857 #if defined(TARGET_MIPS64)
13858 case M16_OPC_LWU:
13859 check_insn(ctx, ISA_MIPS3);
13860 check_mips_64(ctx);
13861 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13862 break;
13863 #endif
13864 case M16_OPC_SB:
13865 gen_st(ctx, OPC_SB, ry, rx, offset);
13866 break;
13867 case M16_OPC_SH:
13868 gen_st(ctx, OPC_SH, ry, rx, offset);
13869 break;
13870 case M16_OPC_SWSP:
13871 gen_st(ctx, OPC_SW, rx, 29, offset);
13872 break;
13873 case M16_OPC_SW:
13874 gen_st(ctx, OPC_SW, ry, rx, offset);
13875 break;
13876 #if defined(TARGET_MIPS64)
13877 case M16_OPC_I64:
13878 decode_i64_mips16(ctx, ry, funct, offset, 1);
13879 break;
13880 #endif
13881 default:
13882 gen_reserved_instruction(ctx);
13883 break;
13886 return 4;
13889 static inline bool is_uhi(int sdbbp_code)
13891 #ifdef CONFIG_USER_ONLY
13892 return false;
13893 #else
13894 return semihosting_enabled() && sdbbp_code == 1;
13895 #endif
13898 #ifdef CONFIG_USER_ONLY
13899 /* The above should dead-code away any calls to this..*/
13900 static inline void gen_helper_do_semihosting(void *env)
13902 g_assert_not_reached();
13904 #endif
13906 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13908 int rx, ry;
13909 int sa;
13910 int op, cnvt_op, op1, offset;
13911 int funct;
13912 int n_bytes;
13914 op = (ctx->opcode >> 11) & 0x1f;
13915 sa = (ctx->opcode >> 2) & 0x7;
13916 sa = sa == 0 ? 8 : sa;
13917 rx = xlat((ctx->opcode >> 8) & 0x7);
13918 cnvt_op = (ctx->opcode >> 5) & 0x7;
13919 ry = xlat((ctx->opcode >> 5) & 0x7);
13920 op1 = offset = ctx->opcode & 0x1f;
13922 n_bytes = 2;
13924 switch (op) {
13925 case M16_OPC_ADDIUSP:
13927 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13929 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13931 break;
13932 case M16_OPC_ADDIUPC:
13933 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13934 break;
13935 case M16_OPC_B:
13936 offset = (ctx->opcode & 0x7ff) << 1;
13937 offset = (int16_t)(offset << 4) >> 4;
13938 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13939 /* No delay slot, so just process as a normal instruction */
13940 break;
13941 case M16_OPC_JAL:
13942 offset = translator_lduw(env, ctx->base.pc_next + 2);
13943 offset = (((ctx->opcode & 0x1f) << 21)
13944 | ((ctx->opcode >> 5) & 0x1f) << 16
13945 | offset) << 2;
13946 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13947 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13948 n_bytes = 4;
13949 break;
13950 case M16_OPC_BEQZ:
13951 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13952 ((int8_t)ctx->opcode) << 1, 0);
13953 /* No delay slot, so just process as a normal instruction */
13954 break;
13955 case M16_OPC_BNEQZ:
13956 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13957 ((int8_t)ctx->opcode) << 1, 0);
13958 /* No delay slot, so just process as a normal instruction */
13959 break;
13960 case M16_OPC_SHIFT:
13961 switch (ctx->opcode & 0x3) {
13962 case 0x0:
13963 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13964 break;
13965 case 0x1:
13966 #if defined(TARGET_MIPS64)
13967 check_insn(ctx, ISA_MIPS3);
13968 check_mips_64(ctx);
13969 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13970 #else
13971 gen_reserved_instruction(ctx);
13972 #endif
13973 break;
13974 case 0x2:
13975 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13976 break;
13977 case 0x3:
13978 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13979 break;
13981 break;
13982 #if defined(TARGET_MIPS64)
13983 case M16_OPC_LD:
13984 check_insn(ctx, ISA_MIPS3);
13985 check_mips_64(ctx);
13986 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13987 break;
13988 #endif
13989 case M16_OPC_RRIA:
13991 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13993 if ((ctx->opcode >> 4) & 1) {
13994 #if defined(TARGET_MIPS64)
13995 check_insn(ctx, ISA_MIPS3);
13996 check_mips_64(ctx);
13997 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13998 #else
13999 gen_reserved_instruction(ctx);
14000 #endif
14001 } else {
14002 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14005 break;
14006 case M16_OPC_ADDIU8:
14008 int16_t imm = (int8_t) ctx->opcode;
14010 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14012 break;
14013 case M16_OPC_SLTI:
14015 int16_t imm = (uint8_t) ctx->opcode;
14016 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14018 break;
14019 case M16_OPC_SLTIU:
14021 int16_t imm = (uint8_t) ctx->opcode;
14022 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14024 break;
14025 case M16_OPC_I8:
14027 int reg32;
14029 funct = (ctx->opcode >> 8) & 0x7;
14030 switch (funct) {
14031 case I8_BTEQZ:
14032 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14033 ((int8_t)ctx->opcode) << 1, 0);
14034 break;
14035 case I8_BTNEZ:
14036 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14037 ((int8_t)ctx->opcode) << 1, 0);
14038 break;
14039 case I8_SWRASP:
14040 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14041 break;
14042 case I8_ADJSP:
14043 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14044 ((int8_t)ctx->opcode) << 3);
14045 break;
14046 case I8_SVRS:
14047 check_insn(ctx, ISA_MIPS_R1);
14049 int do_ra = ctx->opcode & (1 << 6);
14050 int do_s0 = ctx->opcode & (1 << 5);
14051 int do_s1 = ctx->opcode & (1 << 4);
14052 int framesize = ctx->opcode & 0xf;
14054 if (framesize == 0) {
14055 framesize = 128;
14056 } else {
14057 framesize = framesize << 3;
14060 if (ctx->opcode & (1 << 7)) {
14061 gen_mips16_save(ctx, 0, 0,
14062 do_ra, do_s0, do_s1, framesize);
14063 } else {
14064 gen_mips16_restore(ctx, 0, 0,
14065 do_ra, do_s0, do_s1, framesize);
14068 break;
14069 case I8_MOV32R:
14071 int rz = xlat(ctx->opcode & 0x7);
14073 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14074 ((ctx->opcode >> 5) & 0x7);
14075 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14077 break;
14078 case I8_MOVR32:
14079 reg32 = ctx->opcode & 0x1f;
14080 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14081 break;
14082 default:
14083 gen_reserved_instruction(ctx);
14084 break;
14087 break;
14088 case M16_OPC_LI:
14090 int16_t imm = (uint8_t) ctx->opcode;
14092 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14094 break;
14095 case M16_OPC_CMPI:
14097 int16_t imm = (uint8_t) ctx->opcode;
14098 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14100 break;
14101 #if defined(TARGET_MIPS64)
14102 case M16_OPC_SD:
14103 check_insn(ctx, ISA_MIPS3);
14104 check_mips_64(ctx);
14105 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14106 break;
14107 #endif
14108 case M16_OPC_LB:
14109 gen_ld(ctx, OPC_LB, ry, rx, offset);
14110 break;
14111 case M16_OPC_LH:
14112 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14113 break;
14114 case M16_OPC_LWSP:
14115 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14116 break;
14117 case M16_OPC_LW:
14118 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14119 break;
14120 case M16_OPC_LBU:
14121 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14122 break;
14123 case M16_OPC_LHU:
14124 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14125 break;
14126 case M16_OPC_LWPC:
14127 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14128 break;
14129 #if defined(TARGET_MIPS64)
14130 case M16_OPC_LWU:
14131 check_insn(ctx, ISA_MIPS3);
14132 check_mips_64(ctx);
14133 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14134 break;
14135 #endif
14136 case M16_OPC_SB:
14137 gen_st(ctx, OPC_SB, ry, rx, offset);
14138 break;
14139 case M16_OPC_SH:
14140 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14141 break;
14142 case M16_OPC_SWSP:
14143 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14144 break;
14145 case M16_OPC_SW:
14146 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14147 break;
14148 case M16_OPC_RRR:
14150 int rz = xlat((ctx->opcode >> 2) & 0x7);
14151 int mips32_op;
14153 switch (ctx->opcode & 0x3) {
14154 case RRR_ADDU:
14155 mips32_op = OPC_ADDU;
14156 break;
14157 case RRR_SUBU:
14158 mips32_op = OPC_SUBU;
14159 break;
14160 #if defined(TARGET_MIPS64)
14161 case RRR_DADDU:
14162 mips32_op = OPC_DADDU;
14163 check_insn(ctx, ISA_MIPS3);
14164 check_mips_64(ctx);
14165 break;
14166 case RRR_DSUBU:
14167 mips32_op = OPC_DSUBU;
14168 check_insn(ctx, ISA_MIPS3);
14169 check_mips_64(ctx);
14170 break;
14171 #endif
14172 default:
14173 gen_reserved_instruction(ctx);
14174 goto done;
14177 gen_arith(ctx, mips32_op, rz, rx, ry);
14178 done:
14181 break;
14182 case M16_OPC_RR:
14183 switch (op1) {
14184 case RR_JR:
14186 int nd = (ctx->opcode >> 7) & 0x1;
14187 int link = (ctx->opcode >> 6) & 0x1;
14188 int ra = (ctx->opcode >> 5) & 0x1;
14190 if (nd) {
14191 check_insn(ctx, ISA_MIPS_R1);
14194 if (link) {
14195 op = OPC_JALR;
14196 } else {
14197 op = OPC_JR;
14200 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14201 (nd ? 0 : 2));
14203 break;
14204 case RR_SDBBP:
14205 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14206 gen_helper_do_semihosting(cpu_env);
14207 } else {
14209 * XXX: not clear which exception should be raised
14210 * when in debug mode...
14212 check_insn(ctx, ISA_MIPS_R1);
14213 generate_exception_end(ctx, EXCP_DBp);
14215 break;
14216 case RR_SLT:
14217 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14218 break;
14219 case RR_SLTU:
14220 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14221 break;
14222 case RR_BREAK:
14223 generate_exception_end(ctx, EXCP_BREAK);
14224 break;
14225 case RR_SLLV:
14226 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14227 break;
14228 case RR_SRLV:
14229 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14230 break;
14231 case RR_SRAV:
14232 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14233 break;
14234 #if defined(TARGET_MIPS64)
14235 case RR_DSRL:
14236 check_insn(ctx, ISA_MIPS3);
14237 check_mips_64(ctx);
14238 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14239 break;
14240 #endif
14241 case RR_CMP:
14242 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14243 break;
14244 case RR_NEG:
14245 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14246 break;
14247 case RR_AND:
14248 gen_logic(ctx, OPC_AND, rx, rx, ry);
14249 break;
14250 case RR_OR:
14251 gen_logic(ctx, OPC_OR, rx, rx, ry);
14252 break;
14253 case RR_XOR:
14254 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14255 break;
14256 case RR_NOT:
14257 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14258 break;
14259 case RR_MFHI:
14260 gen_HILO(ctx, OPC_MFHI, 0, rx);
14261 break;
14262 case RR_CNVT:
14263 check_insn(ctx, ISA_MIPS_R1);
14264 switch (cnvt_op) {
14265 case RR_RY_CNVT_ZEB:
14266 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14267 break;
14268 case RR_RY_CNVT_ZEH:
14269 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14270 break;
14271 case RR_RY_CNVT_SEB:
14272 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14273 break;
14274 case RR_RY_CNVT_SEH:
14275 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14276 break;
14277 #if defined(TARGET_MIPS64)
14278 case RR_RY_CNVT_ZEW:
14279 check_insn(ctx, ISA_MIPS_R1);
14280 check_mips_64(ctx);
14281 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14282 break;
14283 case RR_RY_CNVT_SEW:
14284 check_insn(ctx, ISA_MIPS_R1);
14285 check_mips_64(ctx);
14286 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14287 break;
14288 #endif
14289 default:
14290 gen_reserved_instruction(ctx);
14291 break;
14293 break;
14294 case RR_MFLO:
14295 gen_HILO(ctx, OPC_MFLO, 0, rx);
14296 break;
14297 #if defined(TARGET_MIPS64)
14298 case RR_DSRA:
14299 check_insn(ctx, ISA_MIPS3);
14300 check_mips_64(ctx);
14301 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14302 break;
14303 case RR_DSLLV:
14304 check_insn(ctx, ISA_MIPS3);
14305 check_mips_64(ctx);
14306 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14307 break;
14308 case RR_DSRLV:
14309 check_insn(ctx, ISA_MIPS3);
14310 check_mips_64(ctx);
14311 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14312 break;
14313 case RR_DSRAV:
14314 check_insn(ctx, ISA_MIPS3);
14315 check_mips_64(ctx);
14316 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14317 break;
14318 #endif
14319 case RR_MULT:
14320 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14321 break;
14322 case RR_MULTU:
14323 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14324 break;
14325 case RR_DIV:
14326 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14327 break;
14328 case RR_DIVU:
14329 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14330 break;
14331 #if defined(TARGET_MIPS64)
14332 case RR_DMULT:
14333 check_insn(ctx, ISA_MIPS3);
14334 check_mips_64(ctx);
14335 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14336 break;
14337 case RR_DMULTU:
14338 check_insn(ctx, ISA_MIPS3);
14339 check_mips_64(ctx);
14340 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14341 break;
14342 case RR_DDIV:
14343 check_insn(ctx, ISA_MIPS3);
14344 check_mips_64(ctx);
14345 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14346 break;
14347 case RR_DDIVU:
14348 check_insn(ctx, ISA_MIPS3);
14349 check_mips_64(ctx);
14350 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14351 break;
14352 #endif
14353 default:
14354 gen_reserved_instruction(ctx);
14355 break;
14357 break;
14358 case M16_OPC_EXTEND:
14359 decode_extended_mips16_opc(env, ctx);
14360 n_bytes = 4;
14361 break;
14362 #if defined(TARGET_MIPS64)
14363 case M16_OPC_I64:
14364 funct = (ctx->opcode >> 8) & 0x7;
14365 decode_i64_mips16(ctx, ry, funct, offset, 0);
14366 break;
14367 #endif
14368 default:
14369 gen_reserved_instruction(ctx);
14370 break;
14373 return n_bytes;
14376 /* microMIPS extension to MIPS32/MIPS64 */
14379 * microMIPS32/microMIPS64 major opcodes
14381 * 1. MIPS Architecture for Programmers Volume II-B:
14382 * The microMIPS32 Instruction Set (Revision 3.05)
14384 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14386 * 2. MIPS Architecture For Programmers Volume II-A:
14387 * The MIPS64 Instruction Set (Revision 3.51)
14390 enum {
14391 POOL32A = 0x00,
14392 POOL16A = 0x01,
14393 LBU16 = 0x02,
14394 MOVE16 = 0x03,
14395 ADDI32 = 0x04,
14396 R6_LUI = 0x04,
14397 AUI = 0x04,
14398 LBU32 = 0x05,
14399 SB32 = 0x06,
14400 LB32 = 0x07,
14402 POOL32B = 0x08,
14403 POOL16B = 0x09,
14404 LHU16 = 0x0a,
14405 ANDI16 = 0x0b,
14406 ADDIU32 = 0x0c,
14407 LHU32 = 0x0d,
14408 SH32 = 0x0e,
14409 LH32 = 0x0f,
14411 POOL32I = 0x10,
14412 POOL16C = 0x11,
14413 LWSP16 = 0x12,
14414 POOL16D = 0x13,
14415 ORI32 = 0x14,
14416 POOL32F = 0x15,
14417 POOL32S = 0x16, /* MIPS64 */
14418 DADDIU32 = 0x17, /* MIPS64 */
14420 POOL32C = 0x18,
14421 LWGP16 = 0x19,
14422 LW16 = 0x1a,
14423 POOL16E = 0x1b,
14424 XORI32 = 0x1c,
14425 JALS32 = 0x1d,
14426 BOVC = 0x1d,
14427 BEQC = 0x1d,
14428 BEQZALC = 0x1d,
14429 ADDIUPC = 0x1e,
14430 PCREL = 0x1e,
14431 BNVC = 0x1f,
14432 BNEC = 0x1f,
14433 BNEZALC = 0x1f,
14435 R6_BEQZC = 0x20,
14436 JIC = 0x20,
14437 POOL16F = 0x21,
14438 SB16 = 0x22,
14439 BEQZ16 = 0x23,
14440 BEQZC16 = 0x23,
14441 SLTI32 = 0x24,
14442 BEQ32 = 0x25,
14443 BC = 0x25,
14444 SWC132 = 0x26,
14445 LWC132 = 0x27,
14447 /* 0x29 is reserved */
14448 RES_29 = 0x29,
14449 R6_BNEZC = 0x28,
14450 JIALC = 0x28,
14451 SH16 = 0x2a,
14452 BNEZ16 = 0x2b,
14453 BNEZC16 = 0x2b,
14454 SLTIU32 = 0x2c,
14455 BNE32 = 0x2d,
14456 BALC = 0x2d,
14457 SDC132 = 0x2e,
14458 LDC132 = 0x2f,
14460 /* 0x31 is reserved */
14461 RES_31 = 0x31,
14462 BLEZALC = 0x30,
14463 BGEZALC = 0x30,
14464 BGEUC = 0x30,
14465 SWSP16 = 0x32,
14466 B16 = 0x33,
14467 BC16 = 0x33,
14468 ANDI32 = 0x34,
14469 J32 = 0x35,
14470 BGTZC = 0x35,
14471 BLTZC = 0x35,
14472 BLTC = 0x35,
14473 SD32 = 0x36, /* MIPS64 */
14474 LD32 = 0x37, /* MIPS64 */
14476 /* 0x39 is reserved */
14477 RES_39 = 0x39,
14478 BGTZALC = 0x38,
14479 BLTZALC = 0x38,
14480 BLTUC = 0x38,
14481 SW16 = 0x3a,
14482 LI16 = 0x3b,
14483 JALX32 = 0x3c,
14484 JAL32 = 0x3d,
14485 BLEZC = 0x3d,
14486 BGEZC = 0x3d,
14487 BGEC = 0x3d,
14488 SW32 = 0x3e,
14489 LW32 = 0x3f
14492 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14493 enum {
14494 ADDIUPC_00 = 0x00,
14495 ADDIUPC_01 = 0x01,
14496 ADDIUPC_02 = 0x02,
14497 ADDIUPC_03 = 0x03,
14498 ADDIUPC_04 = 0x04,
14499 ADDIUPC_05 = 0x05,
14500 ADDIUPC_06 = 0x06,
14501 ADDIUPC_07 = 0x07,
14502 AUIPC = 0x1e,
14503 ALUIPC = 0x1f,
14504 LWPC_08 = 0x08,
14505 LWPC_09 = 0x09,
14506 LWPC_0A = 0x0A,
14507 LWPC_0B = 0x0B,
14508 LWPC_0C = 0x0C,
14509 LWPC_0D = 0x0D,
14510 LWPC_0E = 0x0E,
14511 LWPC_0F = 0x0F,
14514 /* POOL32A encoding of minor opcode field */
14516 enum {
14518 * These opcodes are distinguished only by bits 9..6; those bits are
14519 * what are recorded below.
14521 SLL32 = 0x0,
14522 SRL32 = 0x1,
14523 SRA = 0x2,
14524 ROTR = 0x3,
14525 SELEQZ = 0x5,
14526 SELNEZ = 0x6,
14527 R6_RDHWR = 0x7,
14529 SLLV = 0x0,
14530 SRLV = 0x1,
14531 SRAV = 0x2,
14532 ROTRV = 0x3,
14533 ADD = 0x4,
14534 ADDU32 = 0x5,
14535 SUB = 0x6,
14536 SUBU32 = 0x7,
14537 MUL = 0x8,
14538 AND = 0x9,
14539 OR32 = 0xa,
14540 NOR = 0xb,
14541 XOR32 = 0xc,
14542 SLT = 0xd,
14543 SLTU = 0xe,
14545 MOVN = 0x0,
14546 R6_MUL = 0x0,
14547 MOVZ = 0x1,
14548 MUH = 0x1,
14549 MULU = 0x2,
14550 MUHU = 0x3,
14551 LWXS = 0x4,
14552 R6_DIV = 0x4,
14553 MOD = 0x5,
14554 R6_DIVU = 0x6,
14555 MODU = 0x7,
14557 /* The following can be distinguished by their lower 6 bits. */
14558 BREAK32 = 0x07,
14559 INS = 0x0c,
14560 LSA = 0x0f,
14561 ALIGN = 0x1f,
14562 EXT = 0x2c,
14563 POOL32AXF = 0x3c,
14564 SIGRIE = 0x3f
14567 /* POOL32AXF encoding of minor opcode field extension */
14570 * 1. MIPS Architecture for Programmers Volume II-B:
14571 * The microMIPS32 Instruction Set (Revision 3.05)
14573 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14575 * 2. MIPS Architecture for Programmers VolumeIV-e:
14576 * The MIPS DSP Application-Specific Extension
14577 * to the microMIPS32 Architecture (Revision 2.34)
14579 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14582 enum {
14583 /* bits 11..6 */
14584 TEQ = 0x00,
14585 TGE = 0x08,
14586 TGEU = 0x10,
14587 TLT = 0x20,
14588 TLTU = 0x28,
14589 TNE = 0x30,
14591 MFC0 = 0x03,
14592 MTC0 = 0x0b,
14594 /* begin of microMIPS32 DSP */
14596 /* bits 13..12 for 0x01 */
14597 MFHI_ACC = 0x0,
14598 MFLO_ACC = 0x1,
14599 MTHI_ACC = 0x2,
14600 MTLO_ACC = 0x3,
14602 /* bits 13..12 for 0x2a */
14603 MADD_ACC = 0x0,
14604 MADDU_ACC = 0x1,
14605 MSUB_ACC = 0x2,
14606 MSUBU_ACC = 0x3,
14608 /* bits 13..12 for 0x32 */
14609 MULT_ACC = 0x0,
14610 MULTU_ACC = 0x1,
14612 /* end of microMIPS32 DSP */
14614 /* bits 15..12 for 0x2c */
14615 BITSWAP = 0x0,
14616 SEB = 0x2,
14617 SEH = 0x3,
14618 CLO = 0x4,
14619 CLZ = 0x5,
14620 RDHWR = 0x6,
14621 WSBH = 0x7,
14622 MULT = 0x8,
14623 MULTU = 0x9,
14624 DIV = 0xa,
14625 DIVU = 0xb,
14626 MADD = 0xc,
14627 MADDU = 0xd,
14628 MSUB = 0xe,
14629 MSUBU = 0xf,
14631 /* bits 15..12 for 0x34 */
14632 MFC2 = 0x4,
14633 MTC2 = 0x5,
14634 MFHC2 = 0x8,
14635 MTHC2 = 0x9,
14636 CFC2 = 0xc,
14637 CTC2 = 0xd,
14639 /* bits 15..12 for 0x3c */
14640 JALR = 0x0,
14641 JR = 0x0, /* alias */
14642 JALRC = 0x0,
14643 JRC = 0x0,
14644 JALR_HB = 0x1,
14645 JALRC_HB = 0x1,
14646 JALRS = 0x4,
14647 JALRS_HB = 0x5,
14649 /* bits 15..12 for 0x05 */
14650 RDPGPR = 0xe,
14651 WRPGPR = 0xf,
14653 /* bits 15..12 for 0x0d */
14654 TLBP = 0x0,
14655 TLBR = 0x1,
14656 TLBWI = 0x2,
14657 TLBWR = 0x3,
14658 TLBINV = 0x4,
14659 TLBINVF = 0x5,
14660 WAIT = 0x9,
14661 IRET = 0xd,
14662 DERET = 0xe,
14663 ERET = 0xf,
14665 /* bits 15..12 for 0x15 */
14666 DMT = 0x0,
14667 DVPE = 0x1,
14668 EMT = 0x2,
14669 EVPE = 0x3,
14671 /* bits 15..12 for 0x1d */
14672 DI = 0x4,
14673 EI = 0x5,
14675 /* bits 15..12 for 0x2d */
14676 SYNC = 0x6,
14677 SYSCALL = 0x8,
14678 SDBBP = 0xd,
14680 /* bits 15..12 for 0x35 */
14681 MFHI32 = 0x0,
14682 MFLO32 = 0x1,
14683 MTHI32 = 0x2,
14684 MTLO32 = 0x3,
14687 /* POOL32B encoding of minor opcode field (bits 15..12) */
14689 enum {
14690 LWC2 = 0x0,
14691 LWP = 0x1,
14692 LDP = 0x4,
14693 LWM32 = 0x5,
14694 CACHE = 0x6,
14695 LDM = 0x7,
14696 SWC2 = 0x8,
14697 SWP = 0x9,
14698 SDP = 0xc,
14699 SWM32 = 0xd,
14700 SDM = 0xf
14703 /* POOL32C encoding of minor opcode field (bits 15..12) */
14705 enum {
14706 LWL = 0x0,
14707 SWL = 0x8,
14708 LWR = 0x1,
14709 SWR = 0x9,
14710 PREF = 0x2,
14711 ST_EVA = 0xa,
14712 LL = 0x3,
14713 SC = 0xb,
14714 LDL = 0x4,
14715 SDL = 0xc,
14716 LDR = 0x5,
14717 SDR = 0xd,
14718 LD_EVA = 0x6,
14719 LWU = 0xe,
14720 LLD = 0x7,
14721 SCD = 0xf
14724 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14726 enum {
14727 LBUE = 0x0,
14728 LHUE = 0x1,
14729 LWLE = 0x2,
14730 LWRE = 0x3,
14731 LBE = 0x4,
14732 LHE = 0x5,
14733 LLE = 0x6,
14734 LWE = 0x7,
14737 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14739 enum {
14740 SWLE = 0x0,
14741 SWRE = 0x1,
14742 PREFE = 0x2,
14743 CACHEE = 0x3,
14744 SBE = 0x4,
14745 SHE = 0x5,
14746 SCE = 0x6,
14747 SWE = 0x7,
14750 /* POOL32F encoding of minor opcode field (bits 5..0) */
14752 enum {
14753 /* These are the bit 7..6 values */
14754 ADD_FMT = 0x0,
14756 SUB_FMT = 0x1,
14758 MUL_FMT = 0x2,
14760 DIV_FMT = 0x3,
14762 /* These are the bit 8..6 values */
14763 MOVN_FMT = 0x0,
14764 RSQRT2_FMT = 0x0,
14765 MOVF_FMT = 0x0,
14766 RINT_FMT = 0x0,
14767 SELNEZ_FMT = 0x0,
14769 MOVZ_FMT = 0x1,
14770 LWXC1 = 0x1,
14771 MOVT_FMT = 0x1,
14772 CLASS_FMT = 0x1,
14773 SELEQZ_FMT = 0x1,
14775 PLL_PS = 0x2,
14776 SWXC1 = 0x2,
14777 SEL_FMT = 0x2,
14779 PLU_PS = 0x3,
14780 LDXC1 = 0x3,
14782 MOVN_FMT_04 = 0x4,
14783 PUL_PS = 0x4,
14784 SDXC1 = 0x4,
14785 RECIP2_FMT = 0x4,
14787 MOVZ_FMT_05 = 0x05,
14788 PUU_PS = 0x5,
14789 LUXC1 = 0x5,
14791 CVT_PS_S = 0x6,
14792 SUXC1 = 0x6,
14793 ADDR_PS = 0x6,
14794 PREFX = 0x6,
14795 MADDF_FMT = 0x6,
14797 MULR_PS = 0x7,
14798 MSUBF_FMT = 0x7,
14800 MADD_S = 0x01,
14801 MADD_D = 0x09,
14802 MADD_PS = 0x11,
14803 ALNV_PS = 0x19,
14804 MSUB_S = 0x21,
14805 MSUB_D = 0x29,
14806 MSUB_PS = 0x31,
14808 NMADD_S = 0x02,
14809 NMADD_D = 0x0a,
14810 NMADD_PS = 0x12,
14811 NMSUB_S = 0x22,
14812 NMSUB_D = 0x2a,
14813 NMSUB_PS = 0x32,
14815 MIN_FMT = 0x3,
14816 MAX_FMT = 0xb,
14817 MINA_FMT = 0x23,
14818 MAXA_FMT = 0x2b,
14819 POOL32FXF = 0x3b,
14821 CABS_COND_FMT = 0x1c, /* MIPS3D */
14822 C_COND_FMT = 0x3c,
14824 CMP_CONDN_S = 0x5,
14825 CMP_CONDN_D = 0x15
14828 /* POOL32Fxf encoding of minor opcode extension field */
14830 enum {
14831 CVT_L = 0x04,
14832 RSQRT_FMT = 0x08,
14833 FLOOR_L = 0x0c,
14834 CVT_PW_PS = 0x1c,
14835 CVT_W = 0x24,
14836 SQRT_FMT = 0x28,
14837 FLOOR_W = 0x2c,
14838 CVT_PS_PW = 0x3c,
14839 CFC1 = 0x40,
14840 RECIP_FMT = 0x48,
14841 CEIL_L = 0x4c,
14842 CTC1 = 0x60,
14843 CEIL_W = 0x6c,
14844 MFC1 = 0x80,
14845 CVT_S_PL = 0x84,
14846 TRUNC_L = 0x8c,
14847 MTC1 = 0xa0,
14848 CVT_S_PU = 0xa4,
14849 TRUNC_W = 0xac,
14850 MFHC1 = 0xc0,
14851 ROUND_L = 0xcc,
14852 MTHC1 = 0xe0,
14853 ROUND_W = 0xec,
14855 MOV_FMT = 0x01,
14856 MOVF = 0x05,
14857 ABS_FMT = 0x0d,
14858 RSQRT1_FMT = 0x1d,
14859 MOVT = 0x25,
14860 NEG_FMT = 0x2d,
14861 CVT_D = 0x4d,
14862 RECIP1_FMT = 0x5d,
14863 CVT_S = 0x6d
14866 /* POOL32I encoding of minor opcode field (bits 25..21) */
14868 enum {
14869 BLTZ = 0x00,
14870 BLTZAL = 0x01,
14871 BGEZ = 0x02,
14872 BGEZAL = 0x03,
14873 BLEZ = 0x04,
14874 BNEZC = 0x05,
14875 BGTZ = 0x06,
14876 BEQZC = 0x07,
14877 TLTI = 0x08,
14878 BC1EQZC = 0x08,
14879 TGEI = 0x09,
14880 BC1NEZC = 0x09,
14881 TLTIU = 0x0a,
14882 BC2EQZC = 0x0a,
14883 TGEIU = 0x0b,
14884 BC2NEZC = 0x0a,
14885 TNEI = 0x0c,
14886 R6_SYNCI = 0x0c,
14887 LUI = 0x0d,
14888 TEQI = 0x0e,
14889 SYNCI = 0x10,
14890 BLTZALS = 0x11,
14891 BGEZALS = 0x13,
14892 BC2F = 0x14,
14893 BC2T = 0x15,
14894 BPOSGE64 = 0x1a,
14895 BPOSGE32 = 0x1b,
14896 /* These overlap and are distinguished by bit16 of the instruction */
14897 BC1F = 0x1c,
14898 BC1T = 0x1d,
14899 BC1ANY2F = 0x1c,
14900 BC1ANY2T = 0x1d,
14901 BC1ANY4F = 0x1e,
14902 BC1ANY4T = 0x1f
14905 /* POOL16A encoding of minor opcode field */
14907 enum {
14908 ADDU16 = 0x0,
14909 SUBU16 = 0x1
14912 /* POOL16B encoding of minor opcode field */
14914 enum {
14915 SLL16 = 0x0,
14916 SRL16 = 0x1
14919 /* POOL16C encoding of minor opcode field */
14921 enum {
14922 NOT16 = 0x00,
14923 XOR16 = 0x04,
14924 AND16 = 0x08,
14925 OR16 = 0x0c,
14926 LWM16 = 0x10,
14927 SWM16 = 0x14,
14928 JR16 = 0x18,
14929 JRC16 = 0x1a,
14930 JALR16 = 0x1c,
14931 JALR16S = 0x1e,
14932 MFHI16 = 0x20,
14933 MFLO16 = 0x24,
14934 BREAK16 = 0x28,
14935 SDBBP16 = 0x2c,
14936 JRADDIUSP = 0x30
14939 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14941 enum {
14942 R6_NOT16 = 0x00,
14943 R6_AND16 = 0x01,
14944 R6_LWM16 = 0x02,
14945 R6_JRC16 = 0x03,
14946 MOVEP = 0x04,
14947 MOVEP_05 = 0x05,
14948 MOVEP_06 = 0x06,
14949 MOVEP_07 = 0x07,
14950 R6_XOR16 = 0x08,
14951 R6_OR16 = 0x09,
14952 R6_SWM16 = 0x0a,
14953 JALRC16 = 0x0b,
14954 MOVEP_0C = 0x0c,
14955 MOVEP_0D = 0x0d,
14956 MOVEP_0E = 0x0e,
14957 MOVEP_0F = 0x0f,
14958 JRCADDIUSP = 0x13,
14959 R6_BREAK16 = 0x1b,
14960 R6_SDBBP16 = 0x3b
14963 /* POOL16D encoding of minor opcode field */
14965 enum {
14966 ADDIUS5 = 0x0,
14967 ADDIUSP = 0x1
14970 /* POOL16E encoding of minor opcode field */
14972 enum {
14973 ADDIUR2 = 0x0,
14974 ADDIUR1SP = 0x1
14977 static int mmreg(int r)
14979 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14981 return map[r];
14984 /* Used for 16-bit store instructions. */
14985 static int mmreg2(int r)
14987 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14989 return map[r];
14992 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14993 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14994 #define uMIPS_RS2(op) uMIPS_RS(op)
14995 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14996 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14997 #define uMIPS_RS5(op) (op & 0x1f)
14999 /* Signed immediate */
15000 #define SIMM(op, start, width) \
15001 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15002 << (32 - width)) \
15003 >> (32 - width))
15004 /* Zero-extended immediate */
15005 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
15007 static void gen_addiur1sp(DisasContext *ctx)
15009 int rd = mmreg(uMIPS_RD(ctx->opcode));
15011 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
15014 static void gen_addiur2(DisasContext *ctx)
15016 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15017 int rd = mmreg(uMIPS_RD(ctx->opcode));
15018 int rs = mmreg(uMIPS_RS(ctx->opcode));
15020 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
15023 static void gen_addiusp(DisasContext *ctx)
15025 int encoded = ZIMM(ctx->opcode, 1, 9);
15026 int decoded;
15028 if (encoded <= 1) {
15029 decoded = 256 + encoded;
15030 } else if (encoded <= 255) {
15031 decoded = encoded;
15032 } else if (encoded <= 509) {
15033 decoded = encoded - 512;
15034 } else {
15035 decoded = encoded - 768;
15038 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15041 static void gen_addius5(DisasContext *ctx)
15043 int imm = SIMM(ctx->opcode, 1, 4);
15044 int rd = (ctx->opcode >> 5) & 0x1f;
15046 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15049 static void gen_andi16(DisasContext *ctx)
15051 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15052 31, 32, 63, 64, 255, 32768, 65535 };
15053 int rd = mmreg(uMIPS_RD(ctx->opcode));
15054 int rs = mmreg(uMIPS_RS(ctx->opcode));
15055 int encoded = ZIMM(ctx->opcode, 0, 4);
15057 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15060 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15061 int base, int16_t offset)
15063 TCGv t0, t1;
15064 TCGv_i32 t2;
15066 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15067 gen_reserved_instruction(ctx);
15068 return;
15071 t0 = tcg_temp_new();
15073 gen_base_offset_addr(ctx, t0, base, offset);
15075 t1 = tcg_const_tl(reglist);
15076 t2 = tcg_const_i32(ctx->mem_idx);
15078 save_cpu_state(ctx, 1);
15079 switch (opc) {
15080 case LWM32:
15081 gen_helper_lwm(cpu_env, t0, t1, t2);
15082 break;
15083 case SWM32:
15084 gen_helper_swm(cpu_env, t0, t1, t2);
15085 break;
15086 #ifdef TARGET_MIPS64
15087 case LDM:
15088 gen_helper_ldm(cpu_env, t0, t1, t2);
15089 break;
15090 case SDM:
15091 gen_helper_sdm(cpu_env, t0, t1, t2);
15092 break;
15093 #endif
15095 tcg_temp_free(t0);
15096 tcg_temp_free(t1);
15097 tcg_temp_free_i32(t2);
15101 static void gen_pool16c_insn(DisasContext *ctx)
15103 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15104 int rs = mmreg(ctx->opcode & 0x7);
15106 switch (((ctx->opcode) >> 4) & 0x3f) {
15107 case NOT16 + 0:
15108 case NOT16 + 1:
15109 case NOT16 + 2:
15110 case NOT16 + 3:
15111 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15112 break;
15113 case XOR16 + 0:
15114 case XOR16 + 1:
15115 case XOR16 + 2:
15116 case XOR16 + 3:
15117 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15118 break;
15119 case AND16 + 0:
15120 case AND16 + 1:
15121 case AND16 + 2:
15122 case AND16 + 3:
15123 gen_logic(ctx, OPC_AND, rd, rd, rs);
15124 break;
15125 case OR16 + 0:
15126 case OR16 + 1:
15127 case OR16 + 2:
15128 case OR16 + 3:
15129 gen_logic(ctx, OPC_OR, rd, rd, rs);
15130 break;
15131 case LWM16 + 0:
15132 case LWM16 + 1:
15133 case LWM16 + 2:
15134 case LWM16 + 3:
15136 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15137 int offset = ZIMM(ctx->opcode, 0, 4);
15139 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15140 29, offset << 2);
15142 break;
15143 case SWM16 + 0:
15144 case SWM16 + 1:
15145 case SWM16 + 2:
15146 case SWM16 + 3:
15148 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15149 int offset = ZIMM(ctx->opcode, 0, 4);
15151 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15152 29, offset << 2);
15154 break;
15155 case JR16 + 0:
15156 case JR16 + 1:
15158 int reg = ctx->opcode & 0x1f;
15160 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15162 break;
15163 case JRC16 + 0:
15164 case JRC16 + 1:
15166 int reg = ctx->opcode & 0x1f;
15167 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15169 * Let normal delay slot handling in our caller take us
15170 * to the branch target.
15173 break;
15174 case JALR16 + 0:
15175 case JALR16 + 1:
15176 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15177 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15178 break;
15179 case JALR16S + 0:
15180 case JALR16S + 1:
15181 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15182 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15183 break;
15184 case MFHI16 + 0:
15185 case MFHI16 + 1:
15186 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15187 break;
15188 case MFLO16 + 0:
15189 case MFLO16 + 1:
15190 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15191 break;
15192 case BREAK16:
15193 generate_exception_end(ctx, EXCP_BREAK);
15194 break;
15195 case SDBBP16:
15196 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15197 gen_helper_do_semihosting(cpu_env);
15198 } else {
15200 * XXX: not clear which exception should be raised
15201 * when in debug mode...
15203 check_insn(ctx, ISA_MIPS_R1);
15204 generate_exception_end(ctx, EXCP_DBp);
15206 break;
15207 case JRADDIUSP + 0:
15208 case JRADDIUSP + 1:
15210 int imm = ZIMM(ctx->opcode, 0, 5);
15211 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15212 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15214 * Let normal delay slot handling in our caller take us
15215 * to the branch target.
15218 break;
15219 default:
15220 gen_reserved_instruction(ctx);
15221 break;
15225 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15226 int enc_rs)
15228 int rd, rs, re, rt;
15229 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15230 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15231 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15232 rd = rd_enc[enc_dest];
15233 re = re_enc[enc_dest];
15234 rs = rs_rt_enc[enc_rs];
15235 rt = rs_rt_enc[enc_rt];
15236 if (rs) {
15237 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15238 } else {
15239 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15241 if (rt) {
15242 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15243 } else {
15244 tcg_gen_movi_tl(cpu_gpr[re], 0);
15248 static void gen_pool16c_r6_insn(DisasContext *ctx)
15250 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15251 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15253 switch (ctx->opcode & 0xf) {
15254 case R6_NOT16:
15255 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15256 break;
15257 case R6_AND16:
15258 gen_logic(ctx, OPC_AND, rt, rt, rs);
15259 break;
15260 case R6_LWM16:
15262 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15263 int offset = extract32(ctx->opcode, 4, 4);
15264 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15266 break;
15267 case R6_JRC16: /* JRCADDIUSP */
15268 if ((ctx->opcode >> 4) & 1) {
15269 /* JRCADDIUSP */
15270 int imm = extract32(ctx->opcode, 5, 5);
15271 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15272 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15273 } else {
15274 /* JRC16 */
15275 rs = extract32(ctx->opcode, 5, 5);
15276 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15278 break;
15279 case MOVEP:
15280 case MOVEP_05:
15281 case MOVEP_06:
15282 case MOVEP_07:
15283 case MOVEP_0C:
15284 case MOVEP_0D:
15285 case MOVEP_0E:
15286 case MOVEP_0F:
15288 int enc_dest = uMIPS_RD(ctx->opcode);
15289 int enc_rt = uMIPS_RS2(ctx->opcode);
15290 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15291 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15293 break;
15294 case R6_XOR16:
15295 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15296 break;
15297 case R6_OR16:
15298 gen_logic(ctx, OPC_OR, rt, rt, rs);
15299 break;
15300 case R6_SWM16:
15302 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15303 int offset = extract32(ctx->opcode, 4, 4);
15304 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15306 break;
15307 case JALRC16: /* BREAK16, SDBBP16 */
15308 switch (ctx->opcode & 0x3f) {
15309 case JALRC16:
15310 case JALRC16 + 0x20:
15311 /* JALRC16 */
15312 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15313 31, 0, 0);
15314 break;
15315 case R6_BREAK16:
15316 /* BREAK16 */
15317 generate_exception(ctx, EXCP_BREAK);
15318 break;
15319 case R6_SDBBP16:
15320 /* SDBBP16 */
15321 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15322 gen_helper_do_semihosting(cpu_env);
15323 } else {
15324 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15325 generate_exception(ctx, EXCP_RI);
15326 } else {
15327 generate_exception(ctx, EXCP_DBp);
15330 break;
15332 break;
15333 default:
15334 generate_exception(ctx, EXCP_RI);
15335 break;
15339 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15341 TCGv t0 = tcg_temp_new();
15342 TCGv t1 = tcg_temp_new();
15344 gen_load_gpr(t0, base);
15346 if (index != 0) {
15347 gen_load_gpr(t1, index);
15348 tcg_gen_shli_tl(t1, t1, 2);
15349 gen_op_addr_add(ctx, t0, t1, t0);
15352 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15353 gen_store_gpr(t1, rd);
15355 tcg_temp_free(t0);
15356 tcg_temp_free(t1);
15359 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15360 int base, int16_t offset)
15362 TCGv t0, t1;
15364 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15365 gen_reserved_instruction(ctx);
15366 return;
15369 t0 = tcg_temp_new();
15370 t1 = tcg_temp_new();
15372 gen_base_offset_addr(ctx, t0, base, offset);
15374 switch (opc) {
15375 case LWP:
15376 if (rd == base) {
15377 gen_reserved_instruction(ctx);
15378 return;
15380 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15381 gen_store_gpr(t1, rd);
15382 tcg_gen_movi_tl(t1, 4);
15383 gen_op_addr_add(ctx, t0, t0, t1);
15384 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15385 gen_store_gpr(t1, rd + 1);
15386 break;
15387 case SWP:
15388 gen_load_gpr(t1, rd);
15389 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15390 tcg_gen_movi_tl(t1, 4);
15391 gen_op_addr_add(ctx, t0, t0, t1);
15392 gen_load_gpr(t1, rd + 1);
15393 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15394 break;
15395 #ifdef TARGET_MIPS64
15396 case LDP:
15397 if (rd == base) {
15398 gen_reserved_instruction(ctx);
15399 return;
15401 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15402 gen_store_gpr(t1, rd);
15403 tcg_gen_movi_tl(t1, 8);
15404 gen_op_addr_add(ctx, t0, t0, t1);
15405 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15406 gen_store_gpr(t1, rd + 1);
15407 break;
15408 case SDP:
15409 gen_load_gpr(t1, rd);
15410 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15411 tcg_gen_movi_tl(t1, 8);
15412 gen_op_addr_add(ctx, t0, t0, t1);
15413 gen_load_gpr(t1, rd + 1);
15414 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15415 break;
15416 #endif
15418 tcg_temp_free(t0);
15419 tcg_temp_free(t1);
15422 static void gen_sync(int stype)
15424 TCGBar tcg_mo = TCG_BAR_SC;
15426 switch (stype) {
15427 case 0x4: /* SYNC_WMB */
15428 tcg_mo |= TCG_MO_ST_ST;
15429 break;
15430 case 0x10: /* SYNC_MB */
15431 tcg_mo |= TCG_MO_ALL;
15432 break;
15433 case 0x11: /* SYNC_ACQUIRE */
15434 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15435 break;
15436 case 0x12: /* SYNC_RELEASE */
15437 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15438 break;
15439 case 0x13: /* SYNC_RMB */
15440 tcg_mo |= TCG_MO_LD_LD;
15441 break;
15442 default:
15443 tcg_mo |= TCG_MO_ALL;
15444 break;
15447 tcg_gen_mb(tcg_mo);
15450 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15452 int extension = (ctx->opcode >> 6) & 0x3f;
15453 int minor = (ctx->opcode >> 12) & 0xf;
15454 uint32_t mips32_op;
15456 switch (extension) {
15457 case TEQ:
15458 mips32_op = OPC_TEQ;
15459 goto do_trap;
15460 case TGE:
15461 mips32_op = OPC_TGE;
15462 goto do_trap;
15463 case TGEU:
15464 mips32_op = OPC_TGEU;
15465 goto do_trap;
15466 case TLT:
15467 mips32_op = OPC_TLT;
15468 goto do_trap;
15469 case TLTU:
15470 mips32_op = OPC_TLTU;
15471 goto do_trap;
15472 case TNE:
15473 mips32_op = OPC_TNE;
15474 do_trap:
15475 gen_trap(ctx, mips32_op, rs, rt, -1);
15476 break;
15477 #ifndef CONFIG_USER_ONLY
15478 case MFC0:
15479 case MFC0 + 32:
15480 check_cp0_enabled(ctx);
15481 if (rt == 0) {
15482 /* Treat as NOP. */
15483 break;
15485 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15486 break;
15487 case MTC0:
15488 case MTC0 + 32:
15489 check_cp0_enabled(ctx);
15491 TCGv t0 = tcg_temp_new();
15493 gen_load_gpr(t0, rt);
15494 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15495 tcg_temp_free(t0);
15497 break;
15498 #endif
15499 case 0x2a:
15500 switch (minor & 3) {
15501 case MADD_ACC:
15502 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15503 break;
15504 case MADDU_ACC:
15505 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15506 break;
15507 case MSUB_ACC:
15508 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15509 break;
15510 case MSUBU_ACC:
15511 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15512 break;
15513 default:
15514 goto pool32axf_invalid;
15516 break;
15517 case 0x32:
15518 switch (minor & 3) {
15519 case MULT_ACC:
15520 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15521 break;
15522 case MULTU_ACC:
15523 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15524 break;
15525 default:
15526 goto pool32axf_invalid;
15528 break;
15529 case 0x2c:
15530 switch (minor) {
15531 case BITSWAP:
15532 check_insn(ctx, ISA_MIPS_R6);
15533 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15534 break;
15535 case SEB:
15536 gen_bshfl(ctx, OPC_SEB, rs, rt);
15537 break;
15538 case SEH:
15539 gen_bshfl(ctx, OPC_SEH, rs, rt);
15540 break;
15541 case CLO:
15542 mips32_op = OPC_CLO;
15543 goto do_cl;
15544 case CLZ:
15545 mips32_op = OPC_CLZ;
15546 do_cl:
15547 check_insn(ctx, ISA_MIPS_R1);
15548 gen_cl(ctx, mips32_op, rt, rs);
15549 break;
15550 case RDHWR:
15551 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15552 gen_rdhwr(ctx, rt, rs, 0);
15553 break;
15554 case WSBH:
15555 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15556 break;
15557 case MULT:
15558 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15559 mips32_op = OPC_MULT;
15560 goto do_mul;
15561 case MULTU:
15562 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15563 mips32_op = OPC_MULTU;
15564 goto do_mul;
15565 case DIV:
15566 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15567 mips32_op = OPC_DIV;
15568 goto do_div;
15569 case DIVU:
15570 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15571 mips32_op = OPC_DIVU;
15572 goto do_div;
15573 do_div:
15574 check_insn(ctx, ISA_MIPS_R1);
15575 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15576 break;
15577 case MADD:
15578 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15579 mips32_op = OPC_MADD;
15580 goto do_mul;
15581 case MADDU:
15582 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15583 mips32_op = OPC_MADDU;
15584 goto do_mul;
15585 case MSUB:
15586 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15587 mips32_op = OPC_MSUB;
15588 goto do_mul;
15589 case MSUBU:
15590 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15591 mips32_op = OPC_MSUBU;
15592 do_mul:
15593 check_insn(ctx, ISA_MIPS_R1);
15594 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15595 break;
15596 default:
15597 goto pool32axf_invalid;
15599 break;
15600 case 0x34:
15601 switch (minor) {
15602 case MFC2:
15603 case MTC2:
15604 case MFHC2:
15605 case MTHC2:
15606 case CFC2:
15607 case CTC2:
15608 generate_exception_err(ctx, EXCP_CpU, 2);
15609 break;
15610 default:
15611 goto pool32axf_invalid;
15613 break;
15614 case 0x3c:
15615 switch (minor) {
15616 case JALR: /* JALRC */
15617 case JALR_HB: /* JALRC_HB */
15618 if (ctx->insn_flags & ISA_MIPS_R6) {
15619 /* JALRC, JALRC_HB */
15620 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15621 } else {
15622 /* JALR, JALR_HB */
15623 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15624 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15626 break;
15627 case JALRS:
15628 case JALRS_HB:
15629 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15630 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15631 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15632 break;
15633 default:
15634 goto pool32axf_invalid;
15636 break;
15637 case 0x05:
15638 switch (minor) {
15639 case RDPGPR:
15640 check_cp0_enabled(ctx);
15641 check_insn(ctx, ISA_MIPS_R2);
15642 gen_load_srsgpr(rs, rt);
15643 break;
15644 case WRPGPR:
15645 check_cp0_enabled(ctx);
15646 check_insn(ctx, ISA_MIPS_R2);
15647 gen_store_srsgpr(rs, rt);
15648 break;
15649 default:
15650 goto pool32axf_invalid;
15652 break;
15653 #ifndef CONFIG_USER_ONLY
15654 case 0x0d:
15655 switch (minor) {
15656 case TLBP:
15657 mips32_op = OPC_TLBP;
15658 goto do_cp0;
15659 case TLBR:
15660 mips32_op = OPC_TLBR;
15661 goto do_cp0;
15662 case TLBWI:
15663 mips32_op = OPC_TLBWI;
15664 goto do_cp0;
15665 case TLBWR:
15666 mips32_op = OPC_TLBWR;
15667 goto do_cp0;
15668 case TLBINV:
15669 mips32_op = OPC_TLBINV;
15670 goto do_cp0;
15671 case TLBINVF:
15672 mips32_op = OPC_TLBINVF;
15673 goto do_cp0;
15674 case WAIT:
15675 mips32_op = OPC_WAIT;
15676 goto do_cp0;
15677 case DERET:
15678 mips32_op = OPC_DERET;
15679 goto do_cp0;
15680 case ERET:
15681 mips32_op = OPC_ERET;
15682 do_cp0:
15683 gen_cp0(env, ctx, mips32_op, rt, rs);
15684 break;
15685 default:
15686 goto pool32axf_invalid;
15688 break;
15689 case 0x1d:
15690 switch (minor) {
15691 case DI:
15692 check_cp0_enabled(ctx);
15694 TCGv t0 = tcg_temp_new();
15696 save_cpu_state(ctx, 1);
15697 gen_helper_di(t0, cpu_env);
15698 gen_store_gpr(t0, rs);
15700 * Stop translation as we may have switched the execution
15701 * mode.
15703 ctx->base.is_jmp = DISAS_STOP;
15704 tcg_temp_free(t0);
15706 break;
15707 case EI:
15708 check_cp0_enabled(ctx);
15710 TCGv t0 = tcg_temp_new();
15712 save_cpu_state(ctx, 1);
15713 gen_helper_ei(t0, cpu_env);
15714 gen_store_gpr(t0, rs);
15716 * DISAS_STOP isn't sufficient, we need to ensure we break out
15717 * of translated code to check for pending interrupts.
15719 gen_save_pc(ctx->base.pc_next + 4);
15720 ctx->base.is_jmp = DISAS_EXIT;
15721 tcg_temp_free(t0);
15723 break;
15724 default:
15725 goto pool32axf_invalid;
15727 break;
15728 #endif
15729 case 0x2d:
15730 switch (minor) {
15731 case SYNC:
15732 gen_sync(extract32(ctx->opcode, 16, 5));
15733 break;
15734 case SYSCALL:
15735 generate_exception_end(ctx, EXCP_SYSCALL);
15736 break;
15737 case SDBBP:
15738 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15739 gen_helper_do_semihosting(cpu_env);
15740 } else {
15741 check_insn(ctx, ISA_MIPS_R1);
15742 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15743 gen_reserved_instruction(ctx);
15744 } else {
15745 generate_exception_end(ctx, EXCP_DBp);
15748 break;
15749 default:
15750 goto pool32axf_invalid;
15752 break;
15753 case 0x01:
15754 switch (minor & 3) {
15755 case MFHI_ACC:
15756 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15757 break;
15758 case MFLO_ACC:
15759 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15760 break;
15761 case MTHI_ACC:
15762 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15763 break;
15764 case MTLO_ACC:
15765 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15766 break;
15767 default:
15768 goto pool32axf_invalid;
15770 break;
15771 case 0x35:
15772 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15773 switch (minor) {
15774 case MFHI32:
15775 gen_HILO(ctx, OPC_MFHI, 0, rs);
15776 break;
15777 case MFLO32:
15778 gen_HILO(ctx, OPC_MFLO, 0, rs);
15779 break;
15780 case MTHI32:
15781 gen_HILO(ctx, OPC_MTHI, 0, rs);
15782 break;
15783 case MTLO32:
15784 gen_HILO(ctx, OPC_MTLO, 0, rs);
15785 break;
15786 default:
15787 goto pool32axf_invalid;
15789 break;
15790 default:
15791 pool32axf_invalid:
15792 MIPS_INVAL("pool32axf");
15793 gen_reserved_instruction(ctx);
15794 break;
15799 * Values for microMIPS fmt field. Variable-width, depending on which
15800 * formats the instruction supports.
15802 enum {
15803 FMT_SD_S = 0,
15804 FMT_SD_D = 1,
15806 FMT_SDPS_S = 0,
15807 FMT_SDPS_D = 1,
15808 FMT_SDPS_PS = 2,
15810 FMT_SWL_S = 0,
15811 FMT_SWL_W = 1,
15812 FMT_SWL_L = 2,
15814 FMT_DWL_D = 0,
15815 FMT_DWL_W = 1,
15816 FMT_DWL_L = 2
15819 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15821 int extension = (ctx->opcode >> 6) & 0x3ff;
15822 uint32_t mips32_op;
15824 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
15825 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
15826 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
15828 switch (extension) {
15829 case FLOAT_1BIT_FMT(CFC1, 0):
15830 mips32_op = OPC_CFC1;
15831 goto do_cp1;
15832 case FLOAT_1BIT_FMT(CTC1, 0):
15833 mips32_op = OPC_CTC1;
15834 goto do_cp1;
15835 case FLOAT_1BIT_FMT(MFC1, 0):
15836 mips32_op = OPC_MFC1;
15837 goto do_cp1;
15838 case FLOAT_1BIT_FMT(MTC1, 0):
15839 mips32_op = OPC_MTC1;
15840 goto do_cp1;
15841 case FLOAT_1BIT_FMT(MFHC1, 0):
15842 mips32_op = OPC_MFHC1;
15843 goto do_cp1;
15844 case FLOAT_1BIT_FMT(MTHC1, 0):
15845 mips32_op = OPC_MTHC1;
15846 do_cp1:
15847 gen_cp1(ctx, mips32_op, rt, rs);
15848 break;
15850 /* Reciprocal square root */
15851 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15852 mips32_op = OPC_RSQRT_S;
15853 goto do_unaryfp;
15854 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15855 mips32_op = OPC_RSQRT_D;
15856 goto do_unaryfp;
15858 /* Square root */
15859 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15860 mips32_op = OPC_SQRT_S;
15861 goto do_unaryfp;
15862 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15863 mips32_op = OPC_SQRT_D;
15864 goto do_unaryfp;
15866 /* Reciprocal */
15867 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15868 mips32_op = OPC_RECIP_S;
15869 goto do_unaryfp;
15870 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15871 mips32_op = OPC_RECIP_D;
15872 goto do_unaryfp;
15874 /* Floor */
15875 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15876 mips32_op = OPC_FLOOR_L_S;
15877 goto do_unaryfp;
15878 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15879 mips32_op = OPC_FLOOR_L_D;
15880 goto do_unaryfp;
15881 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15882 mips32_op = OPC_FLOOR_W_S;
15883 goto do_unaryfp;
15884 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15885 mips32_op = OPC_FLOOR_W_D;
15886 goto do_unaryfp;
15888 /* Ceiling */
15889 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15890 mips32_op = OPC_CEIL_L_S;
15891 goto do_unaryfp;
15892 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15893 mips32_op = OPC_CEIL_L_D;
15894 goto do_unaryfp;
15895 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15896 mips32_op = OPC_CEIL_W_S;
15897 goto do_unaryfp;
15898 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15899 mips32_op = OPC_CEIL_W_D;
15900 goto do_unaryfp;
15902 /* Truncation */
15903 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15904 mips32_op = OPC_TRUNC_L_S;
15905 goto do_unaryfp;
15906 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15907 mips32_op = OPC_TRUNC_L_D;
15908 goto do_unaryfp;
15909 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15910 mips32_op = OPC_TRUNC_W_S;
15911 goto do_unaryfp;
15912 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15913 mips32_op = OPC_TRUNC_W_D;
15914 goto do_unaryfp;
15916 /* Round */
15917 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15918 mips32_op = OPC_ROUND_L_S;
15919 goto do_unaryfp;
15920 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15921 mips32_op = OPC_ROUND_L_D;
15922 goto do_unaryfp;
15923 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15924 mips32_op = OPC_ROUND_W_S;
15925 goto do_unaryfp;
15926 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15927 mips32_op = OPC_ROUND_W_D;
15928 goto do_unaryfp;
15930 /* Integer to floating-point conversion */
15931 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15932 mips32_op = OPC_CVT_L_S;
15933 goto do_unaryfp;
15934 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15935 mips32_op = OPC_CVT_L_D;
15936 goto do_unaryfp;
15937 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15938 mips32_op = OPC_CVT_W_S;
15939 goto do_unaryfp;
15940 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15941 mips32_op = OPC_CVT_W_D;
15942 goto do_unaryfp;
15944 /* Paired-foo conversions */
15945 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15946 mips32_op = OPC_CVT_S_PL;
15947 goto do_unaryfp;
15948 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15949 mips32_op = OPC_CVT_S_PU;
15950 goto do_unaryfp;
15951 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15952 mips32_op = OPC_CVT_PW_PS;
15953 goto do_unaryfp;
15954 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15955 mips32_op = OPC_CVT_PS_PW;
15956 goto do_unaryfp;
15958 /* Floating-point moves */
15959 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15960 mips32_op = OPC_MOV_S;
15961 goto do_unaryfp;
15962 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15963 mips32_op = OPC_MOV_D;
15964 goto do_unaryfp;
15965 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15966 mips32_op = OPC_MOV_PS;
15967 goto do_unaryfp;
15969 /* Absolute value */
15970 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15971 mips32_op = OPC_ABS_S;
15972 goto do_unaryfp;
15973 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15974 mips32_op = OPC_ABS_D;
15975 goto do_unaryfp;
15976 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15977 mips32_op = OPC_ABS_PS;
15978 goto do_unaryfp;
15980 /* Negation */
15981 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15982 mips32_op = OPC_NEG_S;
15983 goto do_unaryfp;
15984 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15985 mips32_op = OPC_NEG_D;
15986 goto do_unaryfp;
15987 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15988 mips32_op = OPC_NEG_PS;
15989 goto do_unaryfp;
15991 /* Reciprocal square root step */
15992 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15993 mips32_op = OPC_RSQRT1_S;
15994 goto do_unaryfp;
15995 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15996 mips32_op = OPC_RSQRT1_D;
15997 goto do_unaryfp;
15998 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15999 mips32_op = OPC_RSQRT1_PS;
16000 goto do_unaryfp;
16002 /* Reciprocal step */
16003 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16004 mips32_op = OPC_RECIP1_S;
16005 goto do_unaryfp;
16006 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16007 mips32_op = OPC_RECIP1_S;
16008 goto do_unaryfp;
16009 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16010 mips32_op = OPC_RECIP1_PS;
16011 goto do_unaryfp;
16013 /* Conversions from double */
16014 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16015 mips32_op = OPC_CVT_D_S;
16016 goto do_unaryfp;
16017 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16018 mips32_op = OPC_CVT_D_W;
16019 goto do_unaryfp;
16020 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16021 mips32_op = OPC_CVT_D_L;
16022 goto do_unaryfp;
16024 /* Conversions from single */
16025 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16026 mips32_op = OPC_CVT_S_D;
16027 goto do_unaryfp;
16028 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16029 mips32_op = OPC_CVT_S_W;
16030 goto do_unaryfp;
16031 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16032 mips32_op = OPC_CVT_S_L;
16033 do_unaryfp:
16034 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16035 break;
16037 /* Conditional moves on floating-point codes */
16038 case COND_FLOAT_MOV(MOVT, 0):
16039 case COND_FLOAT_MOV(MOVT, 1):
16040 case COND_FLOAT_MOV(MOVT, 2):
16041 case COND_FLOAT_MOV(MOVT, 3):
16042 case COND_FLOAT_MOV(MOVT, 4):
16043 case COND_FLOAT_MOV(MOVT, 5):
16044 case COND_FLOAT_MOV(MOVT, 6):
16045 case COND_FLOAT_MOV(MOVT, 7):
16046 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16047 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16048 break;
16049 case COND_FLOAT_MOV(MOVF, 0):
16050 case COND_FLOAT_MOV(MOVF, 1):
16051 case COND_FLOAT_MOV(MOVF, 2):
16052 case COND_FLOAT_MOV(MOVF, 3):
16053 case COND_FLOAT_MOV(MOVF, 4):
16054 case COND_FLOAT_MOV(MOVF, 5):
16055 case COND_FLOAT_MOV(MOVF, 6):
16056 case COND_FLOAT_MOV(MOVF, 7):
16057 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16058 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16059 break;
16060 default:
16061 MIPS_INVAL("pool32fxf");
16062 gen_reserved_instruction(ctx);
16063 break;
16067 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16069 int32_t offset;
16070 uint16_t insn;
16071 int rt, rs, rd, rr;
16072 int16_t imm;
16073 uint32_t op, minor, minor2, mips32_op;
16074 uint32_t cond, fmt, cc;
16076 insn = translator_lduw(env, ctx->base.pc_next + 2);
16077 ctx->opcode = (ctx->opcode << 16) | insn;
16079 rt = (ctx->opcode >> 21) & 0x1f;
16080 rs = (ctx->opcode >> 16) & 0x1f;
16081 rd = (ctx->opcode >> 11) & 0x1f;
16082 rr = (ctx->opcode >> 6) & 0x1f;
16083 imm = (int16_t) ctx->opcode;
16085 op = (ctx->opcode >> 26) & 0x3f;
16086 switch (op) {
16087 case POOL32A:
16088 minor = ctx->opcode & 0x3f;
16089 switch (minor) {
16090 case 0x00:
16091 minor = (ctx->opcode >> 6) & 0xf;
16092 switch (minor) {
16093 case SLL32:
16094 mips32_op = OPC_SLL;
16095 goto do_shifti;
16096 case SRA:
16097 mips32_op = OPC_SRA;
16098 goto do_shifti;
16099 case SRL32:
16100 mips32_op = OPC_SRL;
16101 goto do_shifti;
16102 case ROTR:
16103 mips32_op = OPC_ROTR;
16104 do_shifti:
16105 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16106 break;
16107 case SELEQZ:
16108 check_insn(ctx, ISA_MIPS_R6);
16109 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16110 break;
16111 case SELNEZ:
16112 check_insn(ctx, ISA_MIPS_R6);
16113 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16114 break;
16115 case R6_RDHWR:
16116 check_insn(ctx, ISA_MIPS_R6);
16117 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16118 break;
16119 default:
16120 goto pool32a_invalid;
16122 break;
16123 case 0x10:
16124 minor = (ctx->opcode >> 6) & 0xf;
16125 switch (minor) {
16126 /* Arithmetic */
16127 case ADD:
16128 mips32_op = OPC_ADD;
16129 goto do_arith;
16130 case ADDU32:
16131 mips32_op = OPC_ADDU;
16132 goto do_arith;
16133 case SUB:
16134 mips32_op = OPC_SUB;
16135 goto do_arith;
16136 case SUBU32:
16137 mips32_op = OPC_SUBU;
16138 goto do_arith;
16139 case MUL:
16140 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16141 mips32_op = OPC_MUL;
16142 do_arith:
16143 gen_arith(ctx, mips32_op, rd, rs, rt);
16144 break;
16145 /* Shifts */
16146 case SLLV:
16147 mips32_op = OPC_SLLV;
16148 goto do_shift;
16149 case SRLV:
16150 mips32_op = OPC_SRLV;
16151 goto do_shift;
16152 case SRAV:
16153 mips32_op = OPC_SRAV;
16154 goto do_shift;
16155 case ROTRV:
16156 mips32_op = OPC_ROTRV;
16157 do_shift:
16158 gen_shift(ctx, mips32_op, rd, rs, rt);
16159 break;
16160 /* Logical operations */
16161 case AND:
16162 mips32_op = OPC_AND;
16163 goto do_logic;
16164 case OR32:
16165 mips32_op = OPC_OR;
16166 goto do_logic;
16167 case NOR:
16168 mips32_op = OPC_NOR;
16169 goto do_logic;
16170 case XOR32:
16171 mips32_op = OPC_XOR;
16172 do_logic:
16173 gen_logic(ctx, mips32_op, rd, rs, rt);
16174 break;
16175 /* Set less than */
16176 case SLT:
16177 mips32_op = OPC_SLT;
16178 goto do_slt;
16179 case SLTU:
16180 mips32_op = OPC_SLTU;
16181 do_slt:
16182 gen_slt(ctx, mips32_op, rd, rs, rt);
16183 break;
16184 default:
16185 goto pool32a_invalid;
16187 break;
16188 case 0x18:
16189 minor = (ctx->opcode >> 6) & 0xf;
16190 switch (minor) {
16191 /* Conditional moves */
16192 case MOVN: /* MUL */
16193 if (ctx->insn_flags & ISA_MIPS_R6) {
16194 /* MUL */
16195 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16196 } else {
16197 /* MOVN */
16198 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16200 break;
16201 case MOVZ: /* MUH */
16202 if (ctx->insn_flags & ISA_MIPS_R6) {
16203 /* MUH */
16204 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16205 } else {
16206 /* MOVZ */
16207 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16209 break;
16210 case MULU:
16211 check_insn(ctx, ISA_MIPS_R6);
16212 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16213 break;
16214 case MUHU:
16215 check_insn(ctx, ISA_MIPS_R6);
16216 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16217 break;
16218 case LWXS: /* DIV */
16219 if (ctx->insn_flags & ISA_MIPS_R6) {
16220 /* DIV */
16221 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16222 } else {
16223 /* LWXS */
16224 gen_ldxs(ctx, rs, rt, rd);
16226 break;
16227 case MOD:
16228 check_insn(ctx, ISA_MIPS_R6);
16229 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16230 break;
16231 case R6_DIVU:
16232 check_insn(ctx, ISA_MIPS_R6);
16233 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16234 break;
16235 case MODU:
16236 check_insn(ctx, ISA_MIPS_R6);
16237 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16238 break;
16239 default:
16240 goto pool32a_invalid;
16242 break;
16243 case INS:
16244 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16245 return;
16246 case LSA:
16247 check_insn(ctx, ISA_MIPS_R6);
16248 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2));
16249 break;
16250 case ALIGN:
16251 check_insn(ctx, ISA_MIPS_R6);
16252 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16253 break;
16254 case EXT:
16255 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16256 return;
16257 case POOL32AXF:
16258 gen_pool32axf(env, ctx, rt, rs);
16259 break;
16260 case BREAK32:
16261 generate_exception_end(ctx, EXCP_BREAK);
16262 break;
16263 case SIGRIE:
16264 check_insn(ctx, ISA_MIPS_R6);
16265 gen_reserved_instruction(ctx);
16266 break;
16267 default:
16268 pool32a_invalid:
16269 MIPS_INVAL("pool32a");
16270 gen_reserved_instruction(ctx);
16271 break;
16273 break;
16274 case POOL32B:
16275 minor = (ctx->opcode >> 12) & 0xf;
16276 switch (minor) {
16277 case CACHE:
16278 check_cp0_enabled(ctx);
16279 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16280 gen_cache_operation(ctx, rt, rs, imm);
16282 break;
16283 case LWC2:
16284 case SWC2:
16285 /* COP2: Not implemented. */
16286 generate_exception_err(ctx, EXCP_CpU, 2);
16287 break;
16288 #ifdef TARGET_MIPS64
16289 case LDP:
16290 case SDP:
16291 check_insn(ctx, ISA_MIPS3);
16292 check_mips_64(ctx);
16293 #endif
16294 /* fall through */
16295 case LWP:
16296 case SWP:
16297 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16298 break;
16299 #ifdef TARGET_MIPS64
16300 case LDM:
16301 case SDM:
16302 check_insn(ctx, ISA_MIPS3);
16303 check_mips_64(ctx);
16304 #endif
16305 /* fall through */
16306 case LWM32:
16307 case SWM32:
16308 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16309 break;
16310 default:
16311 MIPS_INVAL("pool32b");
16312 gen_reserved_instruction(ctx);
16313 break;
16315 break;
16316 case POOL32F:
16317 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16318 minor = ctx->opcode & 0x3f;
16319 check_cp1_enabled(ctx);
16320 switch (minor) {
16321 case ALNV_PS:
16322 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16323 mips32_op = OPC_ALNV_PS;
16324 goto do_madd;
16325 case MADD_S:
16326 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16327 mips32_op = OPC_MADD_S;
16328 goto do_madd;
16329 case MADD_D:
16330 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16331 mips32_op = OPC_MADD_D;
16332 goto do_madd;
16333 case MADD_PS:
16334 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16335 mips32_op = OPC_MADD_PS;
16336 goto do_madd;
16337 case MSUB_S:
16338 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16339 mips32_op = OPC_MSUB_S;
16340 goto do_madd;
16341 case MSUB_D:
16342 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16343 mips32_op = OPC_MSUB_D;
16344 goto do_madd;
16345 case MSUB_PS:
16346 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16347 mips32_op = OPC_MSUB_PS;
16348 goto do_madd;
16349 case NMADD_S:
16350 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16351 mips32_op = OPC_NMADD_S;
16352 goto do_madd;
16353 case NMADD_D:
16354 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16355 mips32_op = OPC_NMADD_D;
16356 goto do_madd;
16357 case NMADD_PS:
16358 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16359 mips32_op = OPC_NMADD_PS;
16360 goto do_madd;
16361 case NMSUB_S:
16362 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16363 mips32_op = OPC_NMSUB_S;
16364 goto do_madd;
16365 case NMSUB_D:
16366 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16367 mips32_op = OPC_NMSUB_D;
16368 goto do_madd;
16369 case NMSUB_PS:
16370 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16371 mips32_op = OPC_NMSUB_PS;
16372 do_madd:
16373 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16374 break;
16375 case CABS_COND_FMT:
16376 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16377 cond = (ctx->opcode >> 6) & 0xf;
16378 cc = (ctx->opcode >> 13) & 0x7;
16379 fmt = (ctx->opcode >> 10) & 0x3;
16380 switch (fmt) {
16381 case 0x0:
16382 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16383 break;
16384 case 0x1:
16385 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16386 break;
16387 case 0x2:
16388 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16389 break;
16390 default:
16391 goto pool32f_invalid;
16393 break;
16394 case C_COND_FMT:
16395 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16396 cond = (ctx->opcode >> 6) & 0xf;
16397 cc = (ctx->opcode >> 13) & 0x7;
16398 fmt = (ctx->opcode >> 10) & 0x3;
16399 switch (fmt) {
16400 case 0x0:
16401 gen_cmp_s(ctx, cond, rt, rs, cc);
16402 break;
16403 case 0x1:
16404 gen_cmp_d(ctx, cond, rt, rs, cc);
16405 break;
16406 case 0x2:
16407 gen_cmp_ps(ctx, cond, rt, rs, cc);
16408 break;
16409 default:
16410 goto pool32f_invalid;
16412 break;
16413 case CMP_CONDN_S:
16414 check_insn(ctx, ISA_MIPS_R6);
16415 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16416 break;
16417 case CMP_CONDN_D:
16418 check_insn(ctx, ISA_MIPS_R6);
16419 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16420 break;
16421 case POOL32FXF:
16422 gen_pool32fxf(ctx, rt, rs);
16423 break;
16424 case 0x00:
16425 /* PLL foo */
16426 switch ((ctx->opcode >> 6) & 0x7) {
16427 case PLL_PS:
16428 mips32_op = OPC_PLL_PS;
16429 goto do_ps;
16430 case PLU_PS:
16431 mips32_op = OPC_PLU_PS;
16432 goto do_ps;
16433 case PUL_PS:
16434 mips32_op = OPC_PUL_PS;
16435 goto do_ps;
16436 case PUU_PS:
16437 mips32_op = OPC_PUU_PS;
16438 goto do_ps;
16439 case CVT_PS_S:
16440 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16441 mips32_op = OPC_CVT_PS_S;
16442 do_ps:
16443 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16444 break;
16445 default:
16446 goto pool32f_invalid;
16448 break;
16449 case MIN_FMT:
16450 check_insn(ctx, ISA_MIPS_R6);
16451 switch ((ctx->opcode >> 9) & 0x3) {
16452 case FMT_SDPS_S:
16453 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16454 break;
16455 case FMT_SDPS_D:
16456 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16457 break;
16458 default:
16459 goto pool32f_invalid;
16461 break;
16462 case 0x08:
16463 /* [LS][WDU]XC1 */
16464 switch ((ctx->opcode >> 6) & 0x7) {
16465 case LWXC1:
16466 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16467 mips32_op = OPC_LWXC1;
16468 goto do_ldst_cp1;
16469 case SWXC1:
16470 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16471 mips32_op = OPC_SWXC1;
16472 goto do_ldst_cp1;
16473 case LDXC1:
16474 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16475 mips32_op = OPC_LDXC1;
16476 goto do_ldst_cp1;
16477 case SDXC1:
16478 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16479 mips32_op = OPC_SDXC1;
16480 goto do_ldst_cp1;
16481 case LUXC1:
16482 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16483 mips32_op = OPC_LUXC1;
16484 goto do_ldst_cp1;
16485 case SUXC1:
16486 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16487 mips32_op = OPC_SUXC1;
16488 do_ldst_cp1:
16489 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16490 break;
16491 default:
16492 goto pool32f_invalid;
16494 break;
16495 case MAX_FMT:
16496 check_insn(ctx, ISA_MIPS_R6);
16497 switch ((ctx->opcode >> 9) & 0x3) {
16498 case FMT_SDPS_S:
16499 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16500 break;
16501 case FMT_SDPS_D:
16502 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16503 break;
16504 default:
16505 goto pool32f_invalid;
16507 break;
16508 case 0x18:
16509 /* 3D insns */
16510 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16511 fmt = (ctx->opcode >> 9) & 0x3;
16512 switch ((ctx->opcode >> 6) & 0x7) {
16513 case RSQRT2_FMT:
16514 switch (fmt) {
16515 case FMT_SDPS_S:
16516 mips32_op = OPC_RSQRT2_S;
16517 goto do_3d;
16518 case FMT_SDPS_D:
16519 mips32_op = OPC_RSQRT2_D;
16520 goto do_3d;
16521 case FMT_SDPS_PS:
16522 mips32_op = OPC_RSQRT2_PS;
16523 goto do_3d;
16524 default:
16525 goto pool32f_invalid;
16527 break;
16528 case RECIP2_FMT:
16529 switch (fmt) {
16530 case FMT_SDPS_S:
16531 mips32_op = OPC_RECIP2_S;
16532 goto do_3d;
16533 case FMT_SDPS_D:
16534 mips32_op = OPC_RECIP2_D;
16535 goto do_3d;
16536 case FMT_SDPS_PS:
16537 mips32_op = OPC_RECIP2_PS;
16538 goto do_3d;
16539 default:
16540 goto pool32f_invalid;
16542 break;
16543 case ADDR_PS:
16544 mips32_op = OPC_ADDR_PS;
16545 goto do_3d;
16546 case MULR_PS:
16547 mips32_op = OPC_MULR_PS;
16548 do_3d:
16549 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16550 break;
16551 default:
16552 goto pool32f_invalid;
16554 break;
16555 case 0x20:
16556 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16557 cc = (ctx->opcode >> 13) & 0x7;
16558 fmt = (ctx->opcode >> 9) & 0x3;
16559 switch ((ctx->opcode >> 6) & 0x7) {
16560 case MOVF_FMT: /* RINT_FMT */
16561 if (ctx->insn_flags & ISA_MIPS_R6) {
16562 /* RINT_FMT */
16563 switch (fmt) {
16564 case FMT_SDPS_S:
16565 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16566 break;
16567 case FMT_SDPS_D:
16568 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16569 break;
16570 default:
16571 goto pool32f_invalid;
16573 } else {
16574 /* MOVF_FMT */
16575 switch (fmt) {
16576 case FMT_SDPS_S:
16577 gen_movcf_s(ctx, rs, rt, cc, 0);
16578 break;
16579 case FMT_SDPS_D:
16580 gen_movcf_d(ctx, rs, rt, cc, 0);
16581 break;
16582 case FMT_SDPS_PS:
16583 check_ps(ctx);
16584 gen_movcf_ps(ctx, rs, rt, cc, 0);
16585 break;
16586 default:
16587 goto pool32f_invalid;
16590 break;
16591 case MOVT_FMT: /* CLASS_FMT */
16592 if (ctx->insn_flags & ISA_MIPS_R6) {
16593 /* CLASS_FMT */
16594 switch (fmt) {
16595 case FMT_SDPS_S:
16596 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16597 break;
16598 case FMT_SDPS_D:
16599 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16600 break;
16601 default:
16602 goto pool32f_invalid;
16604 } else {
16605 /* MOVT_FMT */
16606 switch (fmt) {
16607 case FMT_SDPS_S:
16608 gen_movcf_s(ctx, rs, rt, cc, 1);
16609 break;
16610 case FMT_SDPS_D:
16611 gen_movcf_d(ctx, rs, rt, cc, 1);
16612 break;
16613 case FMT_SDPS_PS:
16614 check_ps(ctx);
16615 gen_movcf_ps(ctx, rs, rt, cc, 1);
16616 break;
16617 default:
16618 goto pool32f_invalid;
16621 break;
16622 case PREFX:
16623 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16624 break;
16625 default:
16626 goto pool32f_invalid;
16628 break;
16629 #define FINSN_3ARG_SDPS(prfx) \
16630 switch ((ctx->opcode >> 8) & 0x3) { \
16631 case FMT_SDPS_S: \
16632 mips32_op = OPC_##prfx##_S; \
16633 goto do_fpop; \
16634 case FMT_SDPS_D: \
16635 mips32_op = OPC_##prfx##_D; \
16636 goto do_fpop; \
16637 case FMT_SDPS_PS: \
16638 check_ps(ctx); \
16639 mips32_op = OPC_##prfx##_PS; \
16640 goto do_fpop; \
16641 default: \
16642 goto pool32f_invalid; \
16644 case MINA_FMT:
16645 check_insn(ctx, ISA_MIPS_R6);
16646 switch ((ctx->opcode >> 9) & 0x3) {
16647 case FMT_SDPS_S:
16648 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16649 break;
16650 case FMT_SDPS_D:
16651 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16652 break;
16653 default:
16654 goto pool32f_invalid;
16656 break;
16657 case MAXA_FMT:
16658 check_insn(ctx, ISA_MIPS_R6);
16659 switch ((ctx->opcode >> 9) & 0x3) {
16660 case FMT_SDPS_S:
16661 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16662 break;
16663 case FMT_SDPS_D:
16664 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16665 break;
16666 default:
16667 goto pool32f_invalid;
16669 break;
16670 case 0x30:
16671 /* regular FP ops */
16672 switch ((ctx->opcode >> 6) & 0x3) {
16673 case ADD_FMT:
16674 FINSN_3ARG_SDPS(ADD);
16675 break;
16676 case SUB_FMT:
16677 FINSN_3ARG_SDPS(SUB);
16678 break;
16679 case MUL_FMT:
16680 FINSN_3ARG_SDPS(MUL);
16681 break;
16682 case DIV_FMT:
16683 fmt = (ctx->opcode >> 8) & 0x3;
16684 if (fmt == 1) {
16685 mips32_op = OPC_DIV_D;
16686 } else if (fmt == 0) {
16687 mips32_op = OPC_DIV_S;
16688 } else {
16689 goto pool32f_invalid;
16691 goto do_fpop;
16692 default:
16693 goto pool32f_invalid;
16695 break;
16696 case 0x38:
16697 /* cmovs */
16698 switch ((ctx->opcode >> 6) & 0x7) {
16699 case MOVN_FMT: /* SELEQZ_FMT */
16700 if (ctx->insn_flags & ISA_MIPS_R6) {
16701 /* SELEQZ_FMT */
16702 switch ((ctx->opcode >> 9) & 0x3) {
16703 case FMT_SDPS_S:
16704 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16705 break;
16706 case FMT_SDPS_D:
16707 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16708 break;
16709 default:
16710 goto pool32f_invalid;
16712 } else {
16713 /* MOVN_FMT */
16714 FINSN_3ARG_SDPS(MOVN);
16716 break;
16717 case MOVN_FMT_04:
16718 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16719 FINSN_3ARG_SDPS(MOVN);
16720 break;
16721 case MOVZ_FMT: /* SELNEZ_FMT */
16722 if (ctx->insn_flags & ISA_MIPS_R6) {
16723 /* SELNEZ_FMT */
16724 switch ((ctx->opcode >> 9) & 0x3) {
16725 case FMT_SDPS_S:
16726 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16727 break;
16728 case FMT_SDPS_D:
16729 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16730 break;
16731 default:
16732 goto pool32f_invalid;
16734 } else {
16735 /* MOVZ_FMT */
16736 FINSN_3ARG_SDPS(MOVZ);
16738 break;
16739 case MOVZ_FMT_05:
16740 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16741 FINSN_3ARG_SDPS(MOVZ);
16742 break;
16743 case SEL_FMT:
16744 check_insn(ctx, ISA_MIPS_R6);
16745 switch ((ctx->opcode >> 9) & 0x3) {
16746 case FMT_SDPS_S:
16747 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16748 break;
16749 case FMT_SDPS_D:
16750 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16751 break;
16752 default:
16753 goto pool32f_invalid;
16755 break;
16756 case MADDF_FMT:
16757 check_insn(ctx, ISA_MIPS_R6);
16758 switch ((ctx->opcode >> 9) & 0x3) {
16759 case FMT_SDPS_S:
16760 mips32_op = OPC_MADDF_S;
16761 goto do_fpop;
16762 case FMT_SDPS_D:
16763 mips32_op = OPC_MADDF_D;
16764 goto do_fpop;
16765 default:
16766 goto pool32f_invalid;
16768 break;
16769 case MSUBF_FMT:
16770 check_insn(ctx, ISA_MIPS_R6);
16771 switch ((ctx->opcode >> 9) & 0x3) {
16772 case FMT_SDPS_S:
16773 mips32_op = OPC_MSUBF_S;
16774 goto do_fpop;
16775 case FMT_SDPS_D:
16776 mips32_op = OPC_MSUBF_D;
16777 goto do_fpop;
16778 default:
16779 goto pool32f_invalid;
16781 break;
16782 default:
16783 goto pool32f_invalid;
16785 break;
16786 do_fpop:
16787 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16788 break;
16789 default:
16790 pool32f_invalid:
16791 MIPS_INVAL("pool32f");
16792 gen_reserved_instruction(ctx);
16793 break;
16795 } else {
16796 generate_exception_err(ctx, EXCP_CpU, 1);
16798 break;
16799 case POOL32I:
16800 minor = (ctx->opcode >> 21) & 0x1f;
16801 switch (minor) {
16802 case BLTZ:
16803 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16804 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16805 break;
16806 case BLTZAL:
16807 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16808 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16809 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16810 break;
16811 case BLTZALS:
16812 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16813 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16814 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16815 break;
16816 case BGEZ:
16817 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16818 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16819 break;
16820 case BGEZAL:
16821 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16822 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16823 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16824 break;
16825 case BGEZALS:
16826 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16827 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16828 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16829 break;
16830 case BLEZ:
16831 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16832 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16833 break;
16834 case BGTZ:
16835 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16836 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16837 break;
16839 /* Traps */
16840 case TLTI: /* BC1EQZC */
16841 if (ctx->insn_flags & ISA_MIPS_R6) {
16842 /* BC1EQZC */
16843 check_cp1_enabled(ctx);
16844 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16845 } else {
16846 /* TLTI */
16847 mips32_op = OPC_TLTI;
16848 goto do_trapi;
16850 break;
16851 case TGEI: /* BC1NEZC */
16852 if (ctx->insn_flags & ISA_MIPS_R6) {
16853 /* BC1NEZC */
16854 check_cp1_enabled(ctx);
16855 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16856 } else {
16857 /* TGEI */
16858 mips32_op = OPC_TGEI;
16859 goto do_trapi;
16861 break;
16862 case TLTIU:
16863 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16864 mips32_op = OPC_TLTIU;
16865 goto do_trapi;
16866 case TGEIU:
16867 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16868 mips32_op = OPC_TGEIU;
16869 goto do_trapi;
16870 case TNEI: /* SYNCI */
16871 if (ctx->insn_flags & ISA_MIPS_R6) {
16872 /* SYNCI */
16874 * Break the TB to be able to sync copied instructions
16875 * immediately.
16877 ctx->base.is_jmp = DISAS_STOP;
16878 } else {
16879 /* TNEI */
16880 mips32_op = OPC_TNEI;
16881 goto do_trapi;
16883 break;
16884 case TEQI:
16885 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16886 mips32_op = OPC_TEQI;
16887 do_trapi:
16888 gen_trap(ctx, mips32_op, rs, -1, imm);
16889 break;
16891 case BNEZC:
16892 case BEQZC:
16893 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16894 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16895 4, rs, 0, imm << 1, 0);
16897 * Compact branches don't have a delay slot, so just let
16898 * the normal delay slot handling take us to the branch
16899 * target.
16901 break;
16902 case LUI:
16903 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16904 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16905 break;
16906 case SYNCI:
16907 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16909 * Break the TB to be able to sync copied instructions
16910 * immediately.
16912 ctx->base.is_jmp = DISAS_STOP;
16913 break;
16914 case BC2F:
16915 case BC2T:
16916 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16917 /* COP2: Not implemented. */
16918 generate_exception_err(ctx, EXCP_CpU, 2);
16919 break;
16920 case BC1F:
16921 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16922 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16923 goto do_cp1branch;
16924 case BC1T:
16925 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16926 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16927 goto do_cp1branch;
16928 case BC1ANY4F:
16929 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16930 mips32_op = OPC_BC1FANY4;
16931 goto do_cp1mips3d;
16932 case BC1ANY4T:
16933 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16934 mips32_op = OPC_BC1TANY4;
16935 do_cp1mips3d:
16936 check_cop1x(ctx);
16937 check_insn(ctx, ASE_MIPS3D);
16938 /* Fall through */
16939 do_cp1branch:
16940 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16941 check_cp1_enabled(ctx);
16942 gen_compute_branch1(ctx, mips32_op,
16943 (ctx->opcode >> 18) & 0x7, imm << 1);
16944 } else {
16945 generate_exception_err(ctx, EXCP_CpU, 1);
16947 break;
16948 case BPOSGE64:
16949 case BPOSGE32:
16950 /* MIPS DSP: not implemented */
16951 /* Fall through */
16952 default:
16953 MIPS_INVAL("pool32i");
16954 gen_reserved_instruction(ctx);
16955 break;
16957 break;
16958 case POOL32C:
16959 minor = (ctx->opcode >> 12) & 0xf;
16960 offset = sextract32(ctx->opcode, 0,
16961 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
16962 switch (minor) {
16963 case LWL:
16964 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16965 mips32_op = OPC_LWL;
16966 goto do_ld_lr;
16967 case SWL:
16968 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16969 mips32_op = OPC_SWL;
16970 goto do_st_lr;
16971 case LWR:
16972 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16973 mips32_op = OPC_LWR;
16974 goto do_ld_lr;
16975 case SWR:
16976 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16977 mips32_op = OPC_SWR;
16978 goto do_st_lr;
16979 #if defined(TARGET_MIPS64)
16980 case LDL:
16981 check_insn(ctx, ISA_MIPS3);
16982 check_mips_64(ctx);
16983 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16984 mips32_op = OPC_LDL;
16985 goto do_ld_lr;
16986 case SDL:
16987 check_insn(ctx, ISA_MIPS3);
16988 check_mips_64(ctx);
16989 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16990 mips32_op = OPC_SDL;
16991 goto do_st_lr;
16992 case LDR:
16993 check_insn(ctx, ISA_MIPS3);
16994 check_mips_64(ctx);
16995 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16996 mips32_op = OPC_LDR;
16997 goto do_ld_lr;
16998 case SDR:
16999 check_insn(ctx, ISA_MIPS3);
17000 check_mips_64(ctx);
17001 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17002 mips32_op = OPC_SDR;
17003 goto do_st_lr;
17004 case LWU:
17005 check_insn(ctx, ISA_MIPS3);
17006 check_mips_64(ctx);
17007 mips32_op = OPC_LWU;
17008 goto do_ld_lr;
17009 case LLD:
17010 check_insn(ctx, ISA_MIPS3);
17011 check_mips_64(ctx);
17012 mips32_op = OPC_LLD;
17013 goto do_ld_lr;
17014 #endif
17015 case LL:
17016 mips32_op = OPC_LL;
17017 goto do_ld_lr;
17018 do_ld_lr:
17019 gen_ld(ctx, mips32_op, rt, rs, offset);
17020 break;
17021 do_st_lr:
17022 gen_st(ctx, mips32_op, rt, rs, offset);
17023 break;
17024 case SC:
17025 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
17026 break;
17027 #if defined(TARGET_MIPS64)
17028 case SCD:
17029 check_insn(ctx, ISA_MIPS3);
17030 check_mips_64(ctx);
17031 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17032 break;
17033 #endif
17034 case LD_EVA:
17035 if (!ctx->eva) {
17036 MIPS_INVAL("pool32c ld-eva");
17037 gen_reserved_instruction(ctx);
17038 break;
17040 check_cp0_enabled(ctx);
17042 minor2 = (ctx->opcode >> 9) & 0x7;
17043 offset = sextract32(ctx->opcode, 0, 9);
17044 switch (minor2) {
17045 case LBUE:
17046 mips32_op = OPC_LBUE;
17047 goto do_ld_lr;
17048 case LHUE:
17049 mips32_op = OPC_LHUE;
17050 goto do_ld_lr;
17051 case LWLE:
17052 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17053 mips32_op = OPC_LWLE;
17054 goto do_ld_lr;
17055 case LWRE:
17056 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17057 mips32_op = OPC_LWRE;
17058 goto do_ld_lr;
17059 case LBE:
17060 mips32_op = OPC_LBE;
17061 goto do_ld_lr;
17062 case LHE:
17063 mips32_op = OPC_LHE;
17064 goto do_ld_lr;
17065 case LLE:
17066 mips32_op = OPC_LLE;
17067 goto do_ld_lr;
17068 case LWE:
17069 mips32_op = OPC_LWE;
17070 goto do_ld_lr;
17072 break;
17073 case ST_EVA:
17074 if (!ctx->eva) {
17075 MIPS_INVAL("pool32c st-eva");
17076 gen_reserved_instruction(ctx);
17077 break;
17079 check_cp0_enabled(ctx);
17081 minor2 = (ctx->opcode >> 9) & 0x7;
17082 offset = sextract32(ctx->opcode, 0, 9);
17083 switch (minor2) {
17084 case SWLE:
17085 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17086 mips32_op = OPC_SWLE;
17087 goto do_st_lr;
17088 case SWRE:
17089 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17090 mips32_op = OPC_SWRE;
17091 goto do_st_lr;
17092 case PREFE:
17093 /* Treat as no-op */
17094 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
17095 /* hint codes 24-31 are reserved and signal RI */
17096 generate_exception(ctx, EXCP_RI);
17098 break;
17099 case CACHEE:
17100 /* Treat as no-op */
17101 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17102 gen_cache_operation(ctx, rt, rs, offset);
17104 break;
17105 case SBE:
17106 mips32_op = OPC_SBE;
17107 goto do_st_lr;
17108 case SHE:
17109 mips32_op = OPC_SHE;
17110 goto do_st_lr;
17111 case SCE:
17112 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17113 break;
17114 case SWE:
17115 mips32_op = OPC_SWE;
17116 goto do_st_lr;
17118 break;
17119 case PREF:
17120 /* Treat as no-op */
17121 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
17122 /* hint codes 24-31 are reserved and signal RI */
17123 generate_exception(ctx, EXCP_RI);
17125 break;
17126 default:
17127 MIPS_INVAL("pool32c");
17128 gen_reserved_instruction(ctx);
17129 break;
17131 break;
17132 case ADDI32: /* AUI, LUI */
17133 if (ctx->insn_flags & ISA_MIPS_R6) {
17134 /* AUI, LUI */
17135 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17136 } else {
17137 /* ADDI32 */
17138 mips32_op = OPC_ADDI;
17139 goto do_addi;
17141 break;
17142 case ADDIU32:
17143 mips32_op = OPC_ADDIU;
17144 do_addi:
17145 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17146 break;
17148 /* Logical operations */
17149 case ORI32:
17150 mips32_op = OPC_ORI;
17151 goto do_logici;
17152 case XORI32:
17153 mips32_op = OPC_XORI;
17154 goto do_logici;
17155 case ANDI32:
17156 mips32_op = OPC_ANDI;
17157 do_logici:
17158 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17159 break;
17161 /* Set less than immediate */
17162 case SLTI32:
17163 mips32_op = OPC_SLTI;
17164 goto do_slti;
17165 case SLTIU32:
17166 mips32_op = OPC_SLTIU;
17167 do_slti:
17168 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17169 break;
17170 case JALX32:
17171 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17172 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17173 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17174 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17175 break;
17176 case JALS32: /* BOVC, BEQC, BEQZALC */
17177 if (ctx->insn_flags & ISA_MIPS_R6) {
17178 if (rs >= rt) {
17179 /* BOVC */
17180 mips32_op = OPC_BOVC;
17181 } else if (rs < rt && rs == 0) {
17182 /* BEQZALC */
17183 mips32_op = OPC_BEQZALC;
17184 } else {
17185 /* BEQC */
17186 mips32_op = OPC_BEQC;
17188 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17189 } else {
17190 /* JALS32 */
17191 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17192 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17193 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17195 break;
17196 case BEQ32: /* BC */
17197 if (ctx->insn_flags & ISA_MIPS_R6) {
17198 /* BC */
17199 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17200 sextract32(ctx->opcode << 1, 0, 27));
17201 } else {
17202 /* BEQ32 */
17203 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17205 break;
17206 case BNE32: /* BALC */
17207 if (ctx->insn_flags & ISA_MIPS_R6) {
17208 /* BALC */
17209 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17210 sextract32(ctx->opcode << 1, 0, 27));
17211 } else {
17212 /* BNE32 */
17213 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17215 break;
17216 case J32: /* BGTZC, BLTZC, BLTC */
17217 if (ctx->insn_flags & ISA_MIPS_R6) {
17218 if (rs == 0 && rt != 0) {
17219 /* BGTZC */
17220 mips32_op = OPC_BGTZC;
17221 } else if (rs != 0 && rt != 0 && rs == rt) {
17222 /* BLTZC */
17223 mips32_op = OPC_BLTZC;
17224 } else {
17225 /* BLTC */
17226 mips32_op = OPC_BLTC;
17228 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17229 } else {
17230 /* J32 */
17231 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17232 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17234 break;
17235 case JAL32: /* BLEZC, BGEZC, BGEC */
17236 if (ctx->insn_flags & ISA_MIPS_R6) {
17237 if (rs == 0 && rt != 0) {
17238 /* BLEZC */
17239 mips32_op = OPC_BLEZC;
17240 } else if (rs != 0 && rt != 0 && rs == rt) {
17241 /* BGEZC */
17242 mips32_op = OPC_BGEZC;
17243 } else {
17244 /* BGEC */
17245 mips32_op = OPC_BGEC;
17247 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17248 } else {
17249 /* JAL32 */
17250 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17251 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17252 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17254 break;
17255 /* Floating point (COP1) */
17256 case LWC132:
17257 mips32_op = OPC_LWC1;
17258 goto do_cop1;
17259 case LDC132:
17260 mips32_op = OPC_LDC1;
17261 goto do_cop1;
17262 case SWC132:
17263 mips32_op = OPC_SWC1;
17264 goto do_cop1;
17265 case SDC132:
17266 mips32_op = OPC_SDC1;
17267 do_cop1:
17268 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17269 break;
17270 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17271 if (ctx->insn_flags & ISA_MIPS_R6) {
17272 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17273 switch ((ctx->opcode >> 16) & 0x1f) {
17274 case ADDIUPC_00:
17275 case ADDIUPC_01:
17276 case ADDIUPC_02:
17277 case ADDIUPC_03:
17278 case ADDIUPC_04:
17279 case ADDIUPC_05:
17280 case ADDIUPC_06:
17281 case ADDIUPC_07:
17282 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17283 break;
17284 case AUIPC:
17285 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17286 break;
17287 case ALUIPC:
17288 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17289 break;
17290 case LWPC_08:
17291 case LWPC_09:
17292 case LWPC_0A:
17293 case LWPC_0B:
17294 case LWPC_0C:
17295 case LWPC_0D:
17296 case LWPC_0E:
17297 case LWPC_0F:
17298 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17299 break;
17300 default:
17301 generate_exception(ctx, EXCP_RI);
17302 break;
17304 } else {
17305 /* ADDIUPC */
17306 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17307 offset = SIMM(ctx->opcode, 0, 23) << 2;
17309 gen_addiupc(ctx, reg, offset, 0, 0);
17311 break;
17312 case BNVC: /* BNEC, BNEZALC */
17313 check_insn(ctx, ISA_MIPS_R6);
17314 if (rs >= rt) {
17315 /* BNVC */
17316 mips32_op = OPC_BNVC;
17317 } else if (rs < rt && rs == 0) {
17318 /* BNEZALC */
17319 mips32_op = OPC_BNEZALC;
17320 } else {
17321 /* BNEC */
17322 mips32_op = OPC_BNEC;
17324 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17325 break;
17326 case R6_BNEZC: /* JIALC */
17327 check_insn(ctx, ISA_MIPS_R6);
17328 if (rt != 0) {
17329 /* BNEZC */
17330 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17331 sextract32(ctx->opcode << 1, 0, 22));
17332 } else {
17333 /* JIALC */
17334 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17336 break;
17337 case R6_BEQZC: /* JIC */
17338 check_insn(ctx, ISA_MIPS_R6);
17339 if (rt != 0) {
17340 /* BEQZC */
17341 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17342 sextract32(ctx->opcode << 1, 0, 22));
17343 } else {
17344 /* JIC */
17345 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17347 break;
17348 case BLEZALC: /* BGEZALC, BGEUC */
17349 check_insn(ctx, ISA_MIPS_R6);
17350 if (rs == 0 && rt != 0) {
17351 /* BLEZALC */
17352 mips32_op = OPC_BLEZALC;
17353 } else if (rs != 0 && rt != 0 && rs == rt) {
17354 /* BGEZALC */
17355 mips32_op = OPC_BGEZALC;
17356 } else {
17357 /* BGEUC */
17358 mips32_op = OPC_BGEUC;
17360 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17361 break;
17362 case BGTZALC: /* BLTZALC, BLTUC */
17363 check_insn(ctx, ISA_MIPS_R6);
17364 if (rs == 0 && rt != 0) {
17365 /* BGTZALC */
17366 mips32_op = OPC_BGTZALC;
17367 } else if (rs != 0 && rt != 0 && rs == rt) {
17368 /* BLTZALC */
17369 mips32_op = OPC_BLTZALC;
17370 } else {
17371 /* BLTUC */
17372 mips32_op = OPC_BLTUC;
17374 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17375 break;
17376 /* Loads and stores */
17377 case LB32:
17378 mips32_op = OPC_LB;
17379 goto do_ld;
17380 case LBU32:
17381 mips32_op = OPC_LBU;
17382 goto do_ld;
17383 case LH32:
17384 mips32_op = OPC_LH;
17385 goto do_ld;
17386 case LHU32:
17387 mips32_op = OPC_LHU;
17388 goto do_ld;
17389 case LW32:
17390 mips32_op = OPC_LW;
17391 goto do_ld;
17392 #ifdef TARGET_MIPS64
17393 case LD32:
17394 check_insn(ctx, ISA_MIPS3);
17395 check_mips_64(ctx);
17396 mips32_op = OPC_LD;
17397 goto do_ld;
17398 case SD32:
17399 check_insn(ctx, ISA_MIPS3);
17400 check_mips_64(ctx);
17401 mips32_op = OPC_SD;
17402 goto do_st;
17403 #endif
17404 case SB32:
17405 mips32_op = OPC_SB;
17406 goto do_st;
17407 case SH32:
17408 mips32_op = OPC_SH;
17409 goto do_st;
17410 case SW32:
17411 mips32_op = OPC_SW;
17412 goto do_st;
17413 do_ld:
17414 gen_ld(ctx, mips32_op, rt, rs, imm);
17415 break;
17416 do_st:
17417 gen_st(ctx, mips32_op, rt, rs, imm);
17418 break;
17419 default:
17420 gen_reserved_instruction(ctx);
17421 break;
17425 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
17427 uint32_t op;
17429 /* make sure instructions are on a halfword boundary */
17430 if (ctx->base.pc_next & 0x1) {
17431 env->CP0_BadVAddr = ctx->base.pc_next;
17432 generate_exception_end(ctx, EXCP_AdEL);
17433 return 2;
17436 op = (ctx->opcode >> 10) & 0x3f;
17437 /* Enforce properly-sized instructions in a delay slot */
17438 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17439 switch (op & 0x7) { /* MSB-3..MSB-5 */
17440 case 0:
17441 /* POOL32A, POOL32B, POOL32I, POOL32C */
17442 case 4:
17443 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17444 case 5:
17445 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17446 case 6:
17447 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17448 case 7:
17449 /* LB32, LH32, LWC132, LDC132, LW32 */
17450 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17451 gen_reserved_instruction(ctx);
17452 return 2;
17454 break;
17455 case 1:
17456 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17457 case 2:
17458 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17459 case 3:
17460 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17461 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17462 gen_reserved_instruction(ctx);
17463 return 2;
17465 break;
17469 switch (op) {
17470 case POOL16A:
17472 int rd = mmreg(uMIPS_RD(ctx->opcode));
17473 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17474 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17475 uint32_t opc = 0;
17477 switch (ctx->opcode & 0x1) {
17478 case ADDU16:
17479 opc = OPC_ADDU;
17480 break;
17481 case SUBU16:
17482 opc = OPC_SUBU;
17483 break;
17485 if (ctx->insn_flags & ISA_MIPS_R6) {
17487 * In the Release 6, the register number location in
17488 * the instruction encoding has changed.
17490 gen_arith(ctx, opc, rs1, rd, rs2);
17491 } else {
17492 gen_arith(ctx, opc, rd, rs1, rs2);
17495 break;
17496 case POOL16B:
17498 int rd = mmreg(uMIPS_RD(ctx->opcode));
17499 int rs = mmreg(uMIPS_RS(ctx->opcode));
17500 int amount = (ctx->opcode >> 1) & 0x7;
17501 uint32_t opc = 0;
17502 amount = amount == 0 ? 8 : amount;
17504 switch (ctx->opcode & 0x1) {
17505 case SLL16:
17506 opc = OPC_SLL;
17507 break;
17508 case SRL16:
17509 opc = OPC_SRL;
17510 break;
17513 gen_shift_imm(ctx, opc, rd, rs, amount);
17515 break;
17516 case POOL16C:
17517 if (ctx->insn_flags & ISA_MIPS_R6) {
17518 gen_pool16c_r6_insn(ctx);
17519 } else {
17520 gen_pool16c_insn(ctx);
17522 break;
17523 case LWGP16:
17525 int rd = mmreg(uMIPS_RD(ctx->opcode));
17526 int rb = 28; /* GP */
17527 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17529 gen_ld(ctx, OPC_LW, rd, rb, offset);
17531 break;
17532 case POOL16F:
17533 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17534 if (ctx->opcode & 1) {
17535 gen_reserved_instruction(ctx);
17536 } else {
17537 /* MOVEP */
17538 int enc_dest = uMIPS_RD(ctx->opcode);
17539 int enc_rt = uMIPS_RS2(ctx->opcode);
17540 int enc_rs = uMIPS_RS1(ctx->opcode);
17541 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17543 break;
17544 case LBU16:
17546 int rd = mmreg(uMIPS_RD(ctx->opcode));
17547 int rb = mmreg(uMIPS_RS(ctx->opcode));
17548 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17549 offset = (offset == 0xf ? -1 : offset);
17551 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17553 break;
17554 case LHU16:
17556 int rd = mmreg(uMIPS_RD(ctx->opcode));
17557 int rb = mmreg(uMIPS_RS(ctx->opcode));
17558 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17560 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17562 break;
17563 case LWSP16:
17565 int rd = (ctx->opcode >> 5) & 0x1f;
17566 int rb = 29; /* SP */
17567 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17569 gen_ld(ctx, OPC_LW, rd, rb, offset);
17571 break;
17572 case LW16:
17574 int rd = mmreg(uMIPS_RD(ctx->opcode));
17575 int rb = mmreg(uMIPS_RS(ctx->opcode));
17576 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17578 gen_ld(ctx, OPC_LW, rd, rb, offset);
17580 break;
17581 case SB16:
17583 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17584 int rb = mmreg(uMIPS_RS(ctx->opcode));
17585 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17587 gen_st(ctx, OPC_SB, rd, rb, offset);
17589 break;
17590 case SH16:
17592 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17593 int rb = mmreg(uMIPS_RS(ctx->opcode));
17594 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17596 gen_st(ctx, OPC_SH, rd, rb, offset);
17598 break;
17599 case SWSP16:
17601 int rd = (ctx->opcode >> 5) & 0x1f;
17602 int rb = 29; /* SP */
17603 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17605 gen_st(ctx, OPC_SW, rd, rb, offset);
17607 break;
17608 case SW16:
17610 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17611 int rb = mmreg(uMIPS_RS(ctx->opcode));
17612 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17614 gen_st(ctx, OPC_SW, rd, rb, offset);
17616 break;
17617 case MOVE16:
17619 int rd = uMIPS_RD5(ctx->opcode);
17620 int rs = uMIPS_RS5(ctx->opcode);
17622 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17624 break;
17625 case ANDI16:
17626 gen_andi16(ctx);
17627 break;
17628 case POOL16D:
17629 switch (ctx->opcode & 0x1) {
17630 case ADDIUS5:
17631 gen_addius5(ctx);
17632 break;
17633 case ADDIUSP:
17634 gen_addiusp(ctx);
17635 break;
17637 break;
17638 case POOL16E:
17639 switch (ctx->opcode & 0x1) {
17640 case ADDIUR2:
17641 gen_addiur2(ctx);
17642 break;
17643 case ADDIUR1SP:
17644 gen_addiur1sp(ctx);
17645 break;
17647 break;
17648 case B16: /* BC16 */
17649 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17650 sextract32(ctx->opcode, 0, 10) << 1,
17651 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
17652 break;
17653 case BNEZ16: /* BNEZC16 */
17654 case BEQZ16: /* BEQZC16 */
17655 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17656 mmreg(uMIPS_RD(ctx->opcode)),
17657 0, sextract32(ctx->opcode, 0, 7) << 1,
17658 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
17660 break;
17661 case LI16:
17663 int reg = mmreg(uMIPS_RD(ctx->opcode));
17664 int imm = ZIMM(ctx->opcode, 0, 7);
17666 imm = (imm == 0x7f ? -1 : imm);
17667 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17669 break;
17670 case RES_29:
17671 case RES_31:
17672 case RES_39:
17673 gen_reserved_instruction(ctx);
17674 break;
17675 default:
17676 decode_micromips32_opc(env, ctx);
17677 return 4;
17680 return 2;
17685 * nanoMIPS opcodes
17689 /* MAJOR, P16, and P32 pools opcodes */
17690 enum {
17691 NM_P_ADDIU = 0x00,
17692 NM_ADDIUPC = 0x01,
17693 NM_MOVE_BALC = 0x02,
17694 NM_P16_MV = 0x04,
17695 NM_LW16 = 0x05,
17696 NM_BC16 = 0x06,
17697 NM_P16_SR = 0x07,
17699 NM_POOL32A = 0x08,
17700 NM_P_BAL = 0x0a,
17701 NM_P16_SHIFT = 0x0c,
17702 NM_LWSP16 = 0x0d,
17703 NM_BALC16 = 0x0e,
17704 NM_P16_4X4 = 0x0f,
17706 NM_P_GP_W = 0x10,
17707 NM_P_GP_BH = 0x11,
17708 NM_P_J = 0x12,
17709 NM_P16C = 0x14,
17710 NM_LWGP16 = 0x15,
17711 NM_P16_LB = 0x17,
17713 NM_P48I = 0x18,
17714 NM_P16_A1 = 0x1c,
17715 NM_LW4X4 = 0x1d,
17716 NM_P16_LH = 0x1f,
17718 NM_P_U12 = 0x20,
17719 NM_P_LS_U12 = 0x21,
17720 NM_P_BR1 = 0x22,
17721 NM_P16_A2 = 0x24,
17722 NM_SW16 = 0x25,
17723 NM_BEQZC16 = 0x26,
17725 NM_POOL32F = 0x28,
17726 NM_P_LS_S9 = 0x29,
17727 NM_P_BR2 = 0x2a,
17729 NM_P16_ADDU = 0x2c,
17730 NM_SWSP16 = 0x2d,
17731 NM_BNEZC16 = 0x2e,
17732 NM_MOVEP = 0x2f,
17734 NM_POOL32S = 0x30,
17735 NM_P_BRI = 0x32,
17736 NM_LI16 = 0x34,
17737 NM_SWGP16 = 0x35,
17738 NM_P16_BR = 0x36,
17740 NM_P_LUI = 0x38,
17741 NM_ANDI16 = 0x3c,
17742 NM_SW4X4 = 0x3d,
17743 NM_MOVEPREV = 0x3f,
17746 /* POOL32A instruction pool */
17747 enum {
17748 NM_POOL32A0 = 0x00,
17749 NM_SPECIAL2 = 0x01,
17750 NM_COP2_1 = 0x02,
17751 NM_UDI = 0x03,
17752 NM_POOL32A5 = 0x05,
17753 NM_POOL32A7 = 0x07,
17756 /* P.GP.W instruction pool */
17757 enum {
17758 NM_ADDIUGP_W = 0x00,
17759 NM_LWGP = 0x02,
17760 NM_SWGP = 0x03,
17763 /* P48I instruction pool */
17764 enum {
17765 NM_LI48 = 0x00,
17766 NM_ADDIU48 = 0x01,
17767 NM_ADDIUGP48 = 0x02,
17768 NM_ADDIUPC48 = 0x03,
17769 NM_LWPC48 = 0x0b,
17770 NM_SWPC48 = 0x0f,
17773 /* P.U12 instruction pool */
17774 enum {
17775 NM_ORI = 0x00,
17776 NM_XORI = 0x01,
17777 NM_ANDI = 0x02,
17778 NM_P_SR = 0x03,
17779 NM_SLTI = 0x04,
17780 NM_SLTIU = 0x05,
17781 NM_SEQI = 0x06,
17782 NM_ADDIUNEG = 0x08,
17783 NM_P_SHIFT = 0x0c,
17784 NM_P_ROTX = 0x0d,
17785 NM_P_INS = 0x0e,
17786 NM_P_EXT = 0x0f,
17789 /* POOL32F instruction pool */
17790 enum {
17791 NM_POOL32F_0 = 0x00,
17792 NM_POOL32F_3 = 0x03,
17793 NM_POOL32F_5 = 0x05,
17796 /* POOL32S instruction pool */
17797 enum {
17798 NM_POOL32S_0 = 0x00,
17799 NM_POOL32S_4 = 0x04,
17802 /* P.LUI instruction pool */
17803 enum {
17804 NM_LUI = 0x00,
17805 NM_ALUIPC = 0x01,
17808 /* P.GP.BH instruction pool */
17809 enum {
17810 NM_LBGP = 0x00,
17811 NM_SBGP = 0x01,
17812 NM_LBUGP = 0x02,
17813 NM_ADDIUGP_B = 0x03,
17814 NM_P_GP_LH = 0x04,
17815 NM_P_GP_SH = 0x05,
17816 NM_P_GP_CP1 = 0x06,
17819 /* P.LS.U12 instruction pool */
17820 enum {
17821 NM_LB = 0x00,
17822 NM_SB = 0x01,
17823 NM_LBU = 0x02,
17824 NM_P_PREFU12 = 0x03,
17825 NM_LH = 0x04,
17826 NM_SH = 0x05,
17827 NM_LHU = 0x06,
17828 NM_LWU = 0x07,
17829 NM_LW = 0x08,
17830 NM_SW = 0x09,
17831 NM_LWC1 = 0x0a,
17832 NM_SWC1 = 0x0b,
17833 NM_LDC1 = 0x0e,
17834 NM_SDC1 = 0x0f,
17837 /* P.LS.S9 instruction pool */
17838 enum {
17839 NM_P_LS_S0 = 0x00,
17840 NM_P_LS_S1 = 0x01,
17841 NM_P_LS_E0 = 0x02,
17842 NM_P_LS_WM = 0x04,
17843 NM_P_LS_UAWM = 0x05,
17846 /* P.BAL instruction pool */
17847 enum {
17848 NM_BC = 0x00,
17849 NM_BALC = 0x01,
17852 /* P.J instruction pool */
17853 enum {
17854 NM_JALRC = 0x00,
17855 NM_JALRC_HB = 0x01,
17856 NM_P_BALRSC = 0x08,
17859 /* P.BR1 instruction pool */
17860 enum {
17861 NM_BEQC = 0x00,
17862 NM_P_BR3A = 0x01,
17863 NM_BGEC = 0x02,
17864 NM_BGEUC = 0x03,
17867 /* P.BR2 instruction pool */
17868 enum {
17869 NM_BNEC = 0x00,
17870 NM_BLTC = 0x02,
17871 NM_BLTUC = 0x03,
17874 /* P.BRI instruction pool */
17875 enum {
17876 NM_BEQIC = 0x00,
17877 NM_BBEQZC = 0x01,
17878 NM_BGEIC = 0x02,
17879 NM_BGEIUC = 0x03,
17880 NM_BNEIC = 0x04,
17881 NM_BBNEZC = 0x05,
17882 NM_BLTIC = 0x06,
17883 NM_BLTIUC = 0x07,
17886 /* P16.SHIFT instruction pool */
17887 enum {
17888 NM_SLL16 = 0x00,
17889 NM_SRL16 = 0x01,
17892 /* POOL16C instruction pool */
17893 enum {
17894 NM_POOL16C_0 = 0x00,
17895 NM_LWXS16 = 0x01,
17898 /* P16.A1 instruction pool */
17899 enum {
17900 NM_ADDIUR1SP = 0x01,
17903 /* P16.A2 instruction pool */
17904 enum {
17905 NM_ADDIUR2 = 0x00,
17906 NM_P_ADDIURS5 = 0x01,
17909 /* P16.ADDU instruction pool */
17910 enum {
17911 NM_ADDU16 = 0x00,
17912 NM_SUBU16 = 0x01,
17915 /* P16.SR instruction pool */
17916 enum {
17917 NM_SAVE16 = 0x00,
17918 NM_RESTORE_JRC16 = 0x01,
17921 /* P16.4X4 instruction pool */
17922 enum {
17923 NM_ADDU4X4 = 0x00,
17924 NM_MUL4X4 = 0x01,
17927 /* P16.LB instruction pool */
17928 enum {
17929 NM_LB16 = 0x00,
17930 NM_SB16 = 0x01,
17931 NM_LBU16 = 0x02,
17934 /* P16.LH instruction pool */
17935 enum {
17936 NM_LH16 = 0x00,
17937 NM_SH16 = 0x01,
17938 NM_LHU16 = 0x02,
17941 /* P.RI instruction pool */
17942 enum {
17943 NM_SIGRIE = 0x00,
17944 NM_P_SYSCALL = 0x01,
17945 NM_BREAK = 0x02,
17946 NM_SDBBP = 0x03,
17949 /* POOL32A0 instruction pool */
17950 enum {
17951 NM_P_TRAP = 0x00,
17952 NM_SEB = 0x01,
17953 NM_SLLV = 0x02,
17954 NM_MUL = 0x03,
17955 NM_MFC0 = 0x06,
17956 NM_MFHC0 = 0x07,
17957 NM_SEH = 0x09,
17958 NM_SRLV = 0x0a,
17959 NM_MUH = 0x0b,
17960 NM_MTC0 = 0x0e,
17961 NM_MTHC0 = 0x0f,
17962 NM_SRAV = 0x12,
17963 NM_MULU = 0x13,
17964 NM_ROTRV = 0x1a,
17965 NM_MUHU = 0x1b,
17966 NM_ADD = 0x22,
17967 NM_DIV = 0x23,
17968 NM_ADDU = 0x2a,
17969 NM_MOD = 0x2b,
17970 NM_SUB = 0x32,
17971 NM_DIVU = 0x33,
17972 NM_RDHWR = 0x38,
17973 NM_SUBU = 0x3a,
17974 NM_MODU = 0x3b,
17975 NM_P_CMOVE = 0x42,
17976 NM_FORK = 0x45,
17977 NM_MFTR = 0x46,
17978 NM_MFHTR = 0x47,
17979 NM_AND = 0x4a,
17980 NM_YIELD = 0x4d,
17981 NM_MTTR = 0x4e,
17982 NM_MTHTR = 0x4f,
17983 NM_OR = 0x52,
17984 NM_D_E_MT_VPE = 0x56,
17985 NM_NOR = 0x5a,
17986 NM_XOR = 0x62,
17987 NM_SLT = 0x6a,
17988 NM_P_SLTU = 0x72,
17989 NM_SOV = 0x7a,
17992 /* CRC32 instruction pool */
17993 enum {
17994 NM_CRC32B = 0x00,
17995 NM_CRC32H = 0x01,
17996 NM_CRC32W = 0x02,
17997 NM_CRC32CB = 0x04,
17998 NM_CRC32CH = 0x05,
17999 NM_CRC32CW = 0x06,
18002 /* POOL32A5 instruction pool */
18003 enum {
18004 NM_CMP_EQ_PH = 0x00,
18005 NM_CMP_LT_PH = 0x08,
18006 NM_CMP_LE_PH = 0x10,
18007 NM_CMPGU_EQ_QB = 0x18,
18008 NM_CMPGU_LT_QB = 0x20,
18009 NM_CMPGU_LE_QB = 0x28,
18010 NM_CMPGDU_EQ_QB = 0x30,
18011 NM_CMPGDU_LT_QB = 0x38,
18012 NM_CMPGDU_LE_QB = 0x40,
18013 NM_CMPU_EQ_QB = 0x48,
18014 NM_CMPU_LT_QB = 0x50,
18015 NM_CMPU_LE_QB = 0x58,
18016 NM_ADDQ_S_W = 0x60,
18017 NM_SUBQ_S_W = 0x68,
18018 NM_ADDSC = 0x70,
18019 NM_ADDWC = 0x78,
18021 NM_ADDQ_S_PH = 0x01,
18022 NM_ADDQH_R_PH = 0x09,
18023 NM_ADDQH_R_W = 0x11,
18024 NM_ADDU_S_QB = 0x19,
18025 NM_ADDU_S_PH = 0x21,
18026 NM_ADDUH_R_QB = 0x29,
18027 NM_SHRAV_R_PH = 0x31,
18028 NM_SHRAV_R_QB = 0x39,
18029 NM_SUBQ_S_PH = 0x41,
18030 NM_SUBQH_R_PH = 0x49,
18031 NM_SUBQH_R_W = 0x51,
18032 NM_SUBU_S_QB = 0x59,
18033 NM_SUBU_S_PH = 0x61,
18034 NM_SUBUH_R_QB = 0x69,
18035 NM_SHLLV_S_PH = 0x71,
18036 NM_PRECR_SRA_R_PH_W = 0x79,
18038 NM_MULEU_S_PH_QBL = 0x12,
18039 NM_MULEU_S_PH_QBR = 0x1a,
18040 NM_MULQ_RS_PH = 0x22,
18041 NM_MULQ_S_PH = 0x2a,
18042 NM_MULQ_RS_W = 0x32,
18043 NM_MULQ_S_W = 0x3a,
18044 NM_APPEND = 0x42,
18045 NM_MODSUB = 0x52,
18046 NM_SHRAV_R_W = 0x5a,
18047 NM_SHRLV_PH = 0x62,
18048 NM_SHRLV_QB = 0x6a,
18049 NM_SHLLV_QB = 0x72,
18050 NM_SHLLV_S_W = 0x7a,
18052 NM_SHILO = 0x03,
18054 NM_MULEQ_S_W_PHL = 0x04,
18055 NM_MULEQ_S_W_PHR = 0x0c,
18057 NM_MUL_S_PH = 0x05,
18058 NM_PRECR_QB_PH = 0x0d,
18059 NM_PRECRQ_QB_PH = 0x15,
18060 NM_PRECRQ_PH_W = 0x1d,
18061 NM_PRECRQ_RS_PH_W = 0x25,
18062 NM_PRECRQU_S_QB_PH = 0x2d,
18063 NM_PACKRL_PH = 0x35,
18064 NM_PICK_QB = 0x3d,
18065 NM_PICK_PH = 0x45,
18067 NM_SHRA_R_W = 0x5e,
18068 NM_SHRA_R_PH = 0x66,
18069 NM_SHLL_S_PH = 0x76,
18070 NM_SHLL_S_W = 0x7e,
18072 NM_REPL_PH = 0x07
18075 /* POOL32A7 instruction pool */
18076 enum {
18077 NM_P_LSX = 0x00,
18078 NM_LSA = 0x01,
18079 NM_EXTW = 0x03,
18080 NM_POOL32AXF = 0x07,
18083 /* P.SR instruction pool */
18084 enum {
18085 NM_PP_SR = 0x00,
18086 NM_P_SR_F = 0x01,
18089 /* P.SHIFT instruction pool */
18090 enum {
18091 NM_P_SLL = 0x00,
18092 NM_SRL = 0x02,
18093 NM_SRA = 0x04,
18094 NM_ROTR = 0x06,
18097 /* P.ROTX instruction pool */
18098 enum {
18099 NM_ROTX = 0x00,
18102 /* P.INS instruction pool */
18103 enum {
18104 NM_INS = 0x00,
18107 /* P.EXT instruction pool */
18108 enum {
18109 NM_EXT = 0x00,
18112 /* POOL32F_0 (fmt) instruction pool */
18113 enum {
18114 NM_RINT_S = 0x04,
18115 NM_RINT_D = 0x44,
18116 NM_ADD_S = 0x06,
18117 NM_SELEQZ_S = 0x07,
18118 NM_SELEQZ_D = 0x47,
18119 NM_CLASS_S = 0x0c,
18120 NM_CLASS_D = 0x4c,
18121 NM_SUB_S = 0x0e,
18122 NM_SELNEZ_S = 0x0f,
18123 NM_SELNEZ_D = 0x4f,
18124 NM_MUL_S = 0x16,
18125 NM_SEL_S = 0x17,
18126 NM_SEL_D = 0x57,
18127 NM_DIV_S = 0x1e,
18128 NM_ADD_D = 0x26,
18129 NM_SUB_D = 0x2e,
18130 NM_MUL_D = 0x36,
18131 NM_MADDF_S = 0x37,
18132 NM_MADDF_D = 0x77,
18133 NM_DIV_D = 0x3e,
18134 NM_MSUBF_S = 0x3f,
18135 NM_MSUBF_D = 0x7f,
18138 /* POOL32F_3 instruction pool */
18139 enum {
18140 NM_MIN_FMT = 0x00,
18141 NM_MAX_FMT = 0x01,
18142 NM_MINA_FMT = 0x04,
18143 NM_MAXA_FMT = 0x05,
18144 NM_POOL32FXF = 0x07,
18147 /* POOL32F_5 instruction pool */
18148 enum {
18149 NM_CMP_CONDN_S = 0x00,
18150 NM_CMP_CONDN_D = 0x02,
18153 /* P.GP.LH instruction pool */
18154 enum {
18155 NM_LHGP = 0x00,
18156 NM_LHUGP = 0x01,
18159 /* P.GP.SH instruction pool */
18160 enum {
18161 NM_SHGP = 0x00,
18164 /* P.GP.CP1 instruction pool */
18165 enum {
18166 NM_LWC1GP = 0x00,
18167 NM_SWC1GP = 0x01,
18168 NM_LDC1GP = 0x02,
18169 NM_SDC1GP = 0x03,
18172 /* P.LS.S0 instruction pool */
18173 enum {
18174 NM_LBS9 = 0x00,
18175 NM_LHS9 = 0x04,
18176 NM_LWS9 = 0x08,
18177 NM_LDS9 = 0x0c,
18179 NM_SBS9 = 0x01,
18180 NM_SHS9 = 0x05,
18181 NM_SWS9 = 0x09,
18182 NM_SDS9 = 0x0d,
18184 NM_LBUS9 = 0x02,
18185 NM_LHUS9 = 0x06,
18186 NM_LWC1S9 = 0x0a,
18187 NM_LDC1S9 = 0x0e,
18189 NM_P_PREFS9 = 0x03,
18190 NM_LWUS9 = 0x07,
18191 NM_SWC1S9 = 0x0b,
18192 NM_SDC1S9 = 0x0f,
18195 /* P.LS.S1 instruction pool */
18196 enum {
18197 NM_ASET_ACLR = 0x02,
18198 NM_UALH = 0x04,
18199 NM_UASH = 0x05,
18200 NM_CACHE = 0x07,
18201 NM_P_LL = 0x0a,
18202 NM_P_SC = 0x0b,
18205 /* P.LS.E0 instruction pool */
18206 enum {
18207 NM_LBE = 0x00,
18208 NM_SBE = 0x01,
18209 NM_LBUE = 0x02,
18210 NM_P_PREFE = 0x03,
18211 NM_LHE = 0x04,
18212 NM_SHE = 0x05,
18213 NM_LHUE = 0x06,
18214 NM_CACHEE = 0x07,
18215 NM_LWE = 0x08,
18216 NM_SWE = 0x09,
18217 NM_P_LLE = 0x0a,
18218 NM_P_SCE = 0x0b,
18221 /* P.PREFE instruction pool */
18222 enum {
18223 NM_SYNCIE = 0x00,
18224 NM_PREFE = 0x01,
18227 /* P.LLE instruction pool */
18228 enum {
18229 NM_LLE = 0x00,
18230 NM_LLWPE = 0x01,
18233 /* P.SCE instruction pool */
18234 enum {
18235 NM_SCE = 0x00,
18236 NM_SCWPE = 0x01,
18239 /* P.LS.WM instruction pool */
18240 enum {
18241 NM_LWM = 0x00,
18242 NM_SWM = 0x01,
18245 /* P.LS.UAWM instruction pool */
18246 enum {
18247 NM_UALWM = 0x00,
18248 NM_UASWM = 0x01,
18251 /* P.BR3A instruction pool */
18252 enum {
18253 NM_BC1EQZC = 0x00,
18254 NM_BC1NEZC = 0x01,
18255 NM_BC2EQZC = 0x02,
18256 NM_BC2NEZC = 0x03,
18257 NM_BPOSGE32C = 0x04,
18260 /* P16.RI instruction pool */
18261 enum {
18262 NM_P16_SYSCALL = 0x01,
18263 NM_BREAK16 = 0x02,
18264 NM_SDBBP16 = 0x03,
18267 /* POOL16C_0 instruction pool */
18268 enum {
18269 NM_POOL16C_00 = 0x00,
18272 /* P16.JRC instruction pool */
18273 enum {
18274 NM_JRC = 0x00,
18275 NM_JALRC16 = 0x01,
18278 /* P.SYSCALL instruction pool */
18279 enum {
18280 NM_SYSCALL = 0x00,
18281 NM_HYPCALL = 0x01,
18284 /* P.TRAP instruction pool */
18285 enum {
18286 NM_TEQ = 0x00,
18287 NM_TNE = 0x01,
18290 /* P.CMOVE instruction pool */
18291 enum {
18292 NM_MOVZ = 0x00,
18293 NM_MOVN = 0x01,
18296 /* POOL32Axf instruction pool */
18297 enum {
18298 NM_POOL32AXF_1 = 0x01,
18299 NM_POOL32AXF_2 = 0x02,
18300 NM_POOL32AXF_4 = 0x04,
18301 NM_POOL32AXF_5 = 0x05,
18302 NM_POOL32AXF_7 = 0x07,
18305 /* POOL32Axf_1 instruction pool */
18306 enum {
18307 NM_POOL32AXF_1_0 = 0x00,
18308 NM_POOL32AXF_1_1 = 0x01,
18309 NM_POOL32AXF_1_3 = 0x03,
18310 NM_POOL32AXF_1_4 = 0x04,
18311 NM_POOL32AXF_1_5 = 0x05,
18312 NM_POOL32AXF_1_7 = 0x07,
18315 /* POOL32Axf_2 instruction pool */
18316 enum {
18317 NM_POOL32AXF_2_0_7 = 0x00,
18318 NM_POOL32AXF_2_8_15 = 0x01,
18319 NM_POOL32AXF_2_16_23 = 0x02,
18320 NM_POOL32AXF_2_24_31 = 0x03,
18323 /* POOL32Axf_7 instruction pool */
18324 enum {
18325 NM_SHRA_R_QB = 0x0,
18326 NM_SHRL_PH = 0x1,
18327 NM_REPL_QB = 0x2,
18330 /* POOL32Axf_1_0 instruction pool */
18331 enum {
18332 NM_MFHI = 0x0,
18333 NM_MFLO = 0x1,
18334 NM_MTHI = 0x2,
18335 NM_MTLO = 0x3,
18338 /* POOL32Axf_1_1 instruction pool */
18339 enum {
18340 NM_MTHLIP = 0x0,
18341 NM_SHILOV = 0x1,
18344 /* POOL32Axf_1_3 instruction pool */
18345 enum {
18346 NM_RDDSP = 0x0,
18347 NM_WRDSP = 0x1,
18348 NM_EXTP = 0x2,
18349 NM_EXTPDP = 0x3,
18352 /* POOL32Axf_1_4 instruction pool */
18353 enum {
18354 NM_SHLL_QB = 0x0,
18355 NM_SHRL_QB = 0x1,
18358 /* POOL32Axf_1_5 instruction pool */
18359 enum {
18360 NM_MAQ_S_W_PHR = 0x0,
18361 NM_MAQ_S_W_PHL = 0x1,
18362 NM_MAQ_SA_W_PHR = 0x2,
18363 NM_MAQ_SA_W_PHL = 0x3,
18366 /* POOL32Axf_1_7 instruction pool */
18367 enum {
18368 NM_EXTR_W = 0x0,
18369 NM_EXTR_R_W = 0x1,
18370 NM_EXTR_RS_W = 0x2,
18371 NM_EXTR_S_H = 0x3,
18374 /* POOL32Axf_2_0_7 instruction pool */
18375 enum {
18376 NM_DPA_W_PH = 0x0,
18377 NM_DPAQ_S_W_PH = 0x1,
18378 NM_DPS_W_PH = 0x2,
18379 NM_DPSQ_S_W_PH = 0x3,
18380 NM_BALIGN = 0x4,
18381 NM_MADD = 0x5,
18382 NM_MULT = 0x6,
18383 NM_EXTRV_W = 0x7,
18386 /* POOL32Axf_2_8_15 instruction pool */
18387 enum {
18388 NM_DPAX_W_PH = 0x0,
18389 NM_DPAQ_SA_L_W = 0x1,
18390 NM_DPSX_W_PH = 0x2,
18391 NM_DPSQ_SA_L_W = 0x3,
18392 NM_MADDU = 0x5,
18393 NM_MULTU = 0x6,
18394 NM_EXTRV_R_W = 0x7,
18397 /* POOL32Axf_2_16_23 instruction pool */
18398 enum {
18399 NM_DPAU_H_QBL = 0x0,
18400 NM_DPAQX_S_W_PH = 0x1,
18401 NM_DPSU_H_QBL = 0x2,
18402 NM_DPSQX_S_W_PH = 0x3,
18403 NM_EXTPV = 0x4,
18404 NM_MSUB = 0x5,
18405 NM_MULSA_W_PH = 0x6,
18406 NM_EXTRV_RS_W = 0x7,
18409 /* POOL32Axf_2_24_31 instruction pool */
18410 enum {
18411 NM_DPAU_H_QBR = 0x0,
18412 NM_DPAQX_SA_W_PH = 0x1,
18413 NM_DPSU_H_QBR = 0x2,
18414 NM_DPSQX_SA_W_PH = 0x3,
18415 NM_EXTPDPV = 0x4,
18416 NM_MSUBU = 0x5,
18417 NM_MULSAQ_S_W_PH = 0x6,
18418 NM_EXTRV_S_H = 0x7,
18421 /* POOL32Axf_{4, 5} instruction pool */
18422 enum {
18423 NM_CLO = 0x25,
18424 NM_CLZ = 0x2d,
18426 NM_TLBP = 0x01,
18427 NM_TLBR = 0x09,
18428 NM_TLBWI = 0x11,
18429 NM_TLBWR = 0x19,
18430 NM_TLBINV = 0x03,
18431 NM_TLBINVF = 0x0b,
18432 NM_DI = 0x23,
18433 NM_EI = 0x2b,
18434 NM_RDPGPR = 0x70,
18435 NM_WRPGPR = 0x78,
18436 NM_WAIT = 0x61,
18437 NM_DERET = 0x71,
18438 NM_ERETX = 0x79,
18440 /* nanoMIPS DSP instructions */
18441 NM_ABSQ_S_QB = 0x00,
18442 NM_ABSQ_S_PH = 0x08,
18443 NM_ABSQ_S_W = 0x10,
18444 NM_PRECEQ_W_PHL = 0x28,
18445 NM_PRECEQ_W_PHR = 0x30,
18446 NM_PRECEQU_PH_QBL = 0x38,
18447 NM_PRECEQU_PH_QBR = 0x48,
18448 NM_PRECEU_PH_QBL = 0x58,
18449 NM_PRECEU_PH_QBR = 0x68,
18450 NM_PRECEQU_PH_QBLA = 0x39,
18451 NM_PRECEQU_PH_QBRA = 0x49,
18452 NM_PRECEU_PH_QBLA = 0x59,
18453 NM_PRECEU_PH_QBRA = 0x69,
18454 NM_REPLV_PH = 0x01,
18455 NM_REPLV_QB = 0x09,
18456 NM_BITREV = 0x18,
18457 NM_INSV = 0x20,
18458 NM_RADDU_W_QB = 0x78,
18460 NM_BITSWAP = 0x05,
18461 NM_WSBH = 0x3d,
18464 /* PP.SR instruction pool */
18465 enum {
18466 NM_SAVE = 0x00,
18467 NM_RESTORE = 0x02,
18468 NM_RESTORE_JRC = 0x03,
18471 /* P.SR.F instruction pool */
18472 enum {
18473 NM_SAVEF = 0x00,
18474 NM_RESTOREF = 0x01,
18477 /* P16.SYSCALL instruction pool */
18478 enum {
18479 NM_SYSCALL16 = 0x00,
18480 NM_HYPCALL16 = 0x01,
18483 /* POOL16C_00 instruction pool */
18484 enum {
18485 NM_NOT16 = 0x00,
18486 NM_XOR16 = 0x01,
18487 NM_AND16 = 0x02,
18488 NM_OR16 = 0x03,
18491 /* PP.LSX and PP.LSXS instruction pool */
18492 enum {
18493 NM_LBX = 0x00,
18494 NM_LHX = 0x04,
18495 NM_LWX = 0x08,
18496 NM_LDX = 0x0c,
18498 NM_SBX = 0x01,
18499 NM_SHX = 0x05,
18500 NM_SWX = 0x09,
18501 NM_SDX = 0x0d,
18503 NM_LBUX = 0x02,
18504 NM_LHUX = 0x06,
18505 NM_LWC1X = 0x0a,
18506 NM_LDC1X = 0x0e,
18508 NM_LWUX = 0x07,
18509 NM_SWC1X = 0x0b,
18510 NM_SDC1X = 0x0f,
18512 NM_LHXS = 0x04,
18513 NM_LWXS = 0x08,
18514 NM_LDXS = 0x0c,
18516 NM_SHXS = 0x05,
18517 NM_SWXS = 0x09,
18518 NM_SDXS = 0x0d,
18520 NM_LHUXS = 0x06,
18521 NM_LWC1XS = 0x0a,
18522 NM_LDC1XS = 0x0e,
18524 NM_LWUXS = 0x07,
18525 NM_SWC1XS = 0x0b,
18526 NM_SDC1XS = 0x0f,
18529 /* ERETx instruction pool */
18530 enum {
18531 NM_ERET = 0x00,
18532 NM_ERETNC = 0x01,
18535 /* POOL32FxF_{0, 1} insturction pool */
18536 enum {
18537 NM_CFC1 = 0x40,
18538 NM_CTC1 = 0x60,
18539 NM_MFC1 = 0x80,
18540 NM_MTC1 = 0xa0,
18541 NM_MFHC1 = 0xc0,
18542 NM_MTHC1 = 0xe0,
18544 NM_CVT_S_PL = 0x84,
18545 NM_CVT_S_PU = 0xa4,
18547 NM_CVT_L_S = 0x004,
18548 NM_CVT_L_D = 0x104,
18549 NM_CVT_W_S = 0x024,
18550 NM_CVT_W_D = 0x124,
18552 NM_RSQRT_S = 0x008,
18553 NM_RSQRT_D = 0x108,
18555 NM_SQRT_S = 0x028,
18556 NM_SQRT_D = 0x128,
18558 NM_RECIP_S = 0x048,
18559 NM_RECIP_D = 0x148,
18561 NM_FLOOR_L_S = 0x00c,
18562 NM_FLOOR_L_D = 0x10c,
18564 NM_FLOOR_W_S = 0x02c,
18565 NM_FLOOR_W_D = 0x12c,
18567 NM_CEIL_L_S = 0x04c,
18568 NM_CEIL_L_D = 0x14c,
18569 NM_CEIL_W_S = 0x06c,
18570 NM_CEIL_W_D = 0x16c,
18571 NM_TRUNC_L_S = 0x08c,
18572 NM_TRUNC_L_D = 0x18c,
18573 NM_TRUNC_W_S = 0x0ac,
18574 NM_TRUNC_W_D = 0x1ac,
18575 NM_ROUND_L_S = 0x0cc,
18576 NM_ROUND_L_D = 0x1cc,
18577 NM_ROUND_W_S = 0x0ec,
18578 NM_ROUND_W_D = 0x1ec,
18580 NM_MOV_S = 0x01,
18581 NM_MOV_D = 0x81,
18582 NM_ABS_S = 0x0d,
18583 NM_ABS_D = 0x8d,
18584 NM_NEG_S = 0x2d,
18585 NM_NEG_D = 0xad,
18586 NM_CVT_D_S = 0x04d,
18587 NM_CVT_D_W = 0x0cd,
18588 NM_CVT_D_L = 0x14d,
18589 NM_CVT_S_D = 0x06d,
18590 NM_CVT_S_W = 0x0ed,
18591 NM_CVT_S_L = 0x16d,
18594 /* P.LL instruction pool */
18595 enum {
18596 NM_LL = 0x00,
18597 NM_LLWP = 0x01,
18600 /* P.SC instruction pool */
18601 enum {
18602 NM_SC = 0x00,
18603 NM_SCWP = 0x01,
18606 /* P.DVP instruction pool */
18607 enum {
18608 NM_DVP = 0x00,
18609 NM_EVP = 0x01,
18615 * nanoMIPS decoding engine
18620 /* extraction utilities */
18622 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18623 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18624 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18625 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18626 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18628 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18629 static inline int decode_gpr_gpr3(int r)
18631 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18633 return map[r & 0x7];
18636 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18637 static inline int decode_gpr_gpr3_src_store(int r)
18639 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18641 return map[r & 0x7];
18644 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18645 static inline int decode_gpr_gpr4(int r)
18647 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18648 16, 17, 18, 19, 20, 21, 22, 23 };
18650 return map[r & 0xf];
18653 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18654 static inline int decode_gpr_gpr4_zero(int r)
18656 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18657 16, 17, 18, 19, 20, 21, 22, 23 };
18659 return map[r & 0xf];
18663 static void gen_adjust_sp(DisasContext *ctx, int u)
18665 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18668 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18669 uint8_t gp, uint16_t u)
18671 int counter = 0;
18672 TCGv va = tcg_temp_new();
18673 TCGv t0 = tcg_temp_new();
18675 while (counter != count) {
18676 bool use_gp = gp && (counter == count - 1);
18677 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18678 int this_offset = -((counter + 1) << 2);
18679 gen_base_offset_addr(ctx, va, 29, this_offset);
18680 gen_load_gpr(t0, this_rt);
18681 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18682 (MO_TEUL | ctx->default_tcg_memop_mask));
18683 counter++;
18686 /* adjust stack pointer */
18687 gen_adjust_sp(ctx, -u);
18689 tcg_temp_free(t0);
18690 tcg_temp_free(va);
18693 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18694 uint8_t gp, uint16_t u)
18696 int counter = 0;
18697 TCGv va = tcg_temp_new();
18698 TCGv t0 = tcg_temp_new();
18700 while (counter != count) {
18701 bool use_gp = gp && (counter == count - 1);
18702 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18703 int this_offset = u - ((counter + 1) << 2);
18704 gen_base_offset_addr(ctx, va, 29, this_offset);
18705 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18706 ctx->default_tcg_memop_mask);
18707 tcg_gen_ext32s_tl(t0, t0);
18708 gen_store_gpr(t0, this_rt);
18709 counter++;
18712 /* adjust stack pointer */
18713 gen_adjust_sp(ctx, u);
18715 tcg_temp_free(t0);
18716 tcg_temp_free(va);
18719 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18721 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18722 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18724 switch (extract32(ctx->opcode, 2, 2)) {
18725 case NM_NOT16:
18726 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18727 break;
18728 case NM_AND16:
18729 gen_logic(ctx, OPC_AND, rt, rt, rs);
18730 break;
18731 case NM_XOR16:
18732 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18733 break;
18734 case NM_OR16:
18735 gen_logic(ctx, OPC_OR, rt, rt, rs);
18736 break;
18740 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18742 int rt = extract32(ctx->opcode, 21, 5);
18743 int rs = extract32(ctx->opcode, 16, 5);
18744 int rd = extract32(ctx->opcode, 11, 5);
18746 switch (extract32(ctx->opcode, 3, 7)) {
18747 case NM_P_TRAP:
18748 switch (extract32(ctx->opcode, 10, 1)) {
18749 case NM_TEQ:
18750 check_nms(ctx);
18751 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18752 break;
18753 case NM_TNE:
18754 check_nms(ctx);
18755 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18756 break;
18758 break;
18759 case NM_RDHWR:
18760 check_nms(ctx);
18761 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18762 break;
18763 case NM_SEB:
18764 check_nms(ctx);
18765 gen_bshfl(ctx, OPC_SEB, rs, rt);
18766 break;
18767 case NM_SEH:
18768 gen_bshfl(ctx, OPC_SEH, rs, rt);
18769 break;
18770 case NM_SLLV:
18771 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18772 break;
18773 case NM_SRLV:
18774 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18775 break;
18776 case NM_SRAV:
18777 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18778 break;
18779 case NM_ROTRV:
18780 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18781 break;
18782 case NM_ADD:
18783 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18784 break;
18785 case NM_ADDU:
18786 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18787 break;
18788 case NM_SUB:
18789 check_nms(ctx);
18790 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18791 break;
18792 case NM_SUBU:
18793 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18794 break;
18795 case NM_P_CMOVE:
18796 switch (extract32(ctx->opcode, 10, 1)) {
18797 case NM_MOVZ:
18798 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18799 break;
18800 case NM_MOVN:
18801 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18802 break;
18804 break;
18805 case NM_AND:
18806 gen_logic(ctx, OPC_AND, rd, rs, rt);
18807 break;
18808 case NM_OR:
18809 gen_logic(ctx, OPC_OR, rd, rs, rt);
18810 break;
18811 case NM_NOR:
18812 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18813 break;
18814 case NM_XOR:
18815 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18816 break;
18817 case NM_SLT:
18818 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18819 break;
18820 case NM_P_SLTU:
18821 if (rd == 0) {
18822 /* P_DVP */
18823 #ifndef CONFIG_USER_ONLY
18824 TCGv t0 = tcg_temp_new();
18825 switch (extract32(ctx->opcode, 10, 1)) {
18826 case NM_DVP:
18827 if (ctx->vp) {
18828 check_cp0_enabled(ctx);
18829 gen_helper_dvp(t0, cpu_env);
18830 gen_store_gpr(t0, rt);
18832 break;
18833 case NM_EVP:
18834 if (ctx->vp) {
18835 check_cp0_enabled(ctx);
18836 gen_helper_evp(t0, cpu_env);
18837 gen_store_gpr(t0, rt);
18839 break;
18841 tcg_temp_free(t0);
18842 #endif
18843 } else {
18844 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18846 break;
18847 case NM_SOV:
18849 TCGv t0 = tcg_temp_new();
18850 TCGv t1 = tcg_temp_new();
18851 TCGv t2 = tcg_temp_new();
18853 gen_load_gpr(t1, rs);
18854 gen_load_gpr(t2, rt);
18855 tcg_gen_add_tl(t0, t1, t2);
18856 tcg_gen_ext32s_tl(t0, t0);
18857 tcg_gen_xor_tl(t1, t1, t2);
18858 tcg_gen_xor_tl(t2, t0, t2);
18859 tcg_gen_andc_tl(t1, t2, t1);
18861 /* operands of same sign, result different sign */
18862 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18863 gen_store_gpr(t0, rd);
18865 tcg_temp_free(t0);
18866 tcg_temp_free(t1);
18867 tcg_temp_free(t2);
18869 break;
18870 case NM_MUL:
18871 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18872 break;
18873 case NM_MUH:
18874 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18875 break;
18876 case NM_MULU:
18877 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18878 break;
18879 case NM_MUHU:
18880 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18881 break;
18882 case NM_DIV:
18883 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18884 break;
18885 case NM_MOD:
18886 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18887 break;
18888 case NM_DIVU:
18889 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18890 break;
18891 case NM_MODU:
18892 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18893 break;
18894 #ifndef CONFIG_USER_ONLY
18895 case NM_MFC0:
18896 check_cp0_enabled(ctx);
18897 if (rt == 0) {
18898 /* Treat as NOP. */
18899 break;
18901 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18902 break;
18903 case NM_MTC0:
18904 check_cp0_enabled(ctx);
18906 TCGv t0 = tcg_temp_new();
18908 gen_load_gpr(t0, rt);
18909 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18910 tcg_temp_free(t0);
18912 break;
18913 case NM_D_E_MT_VPE:
18915 uint8_t sc = extract32(ctx->opcode, 10, 1);
18916 TCGv t0 = tcg_temp_new();
18918 switch (sc) {
18919 case 0:
18920 if (rs == 1) {
18921 /* DMT */
18922 check_cp0_mt(ctx);
18923 gen_helper_dmt(t0);
18924 gen_store_gpr(t0, rt);
18925 } else if (rs == 0) {
18926 /* DVPE */
18927 check_cp0_mt(ctx);
18928 gen_helper_dvpe(t0, cpu_env);
18929 gen_store_gpr(t0, rt);
18930 } else {
18931 gen_reserved_instruction(ctx);
18933 break;
18934 case 1:
18935 if (rs == 1) {
18936 /* EMT */
18937 check_cp0_mt(ctx);
18938 gen_helper_emt(t0);
18939 gen_store_gpr(t0, rt);
18940 } else if (rs == 0) {
18941 /* EVPE */
18942 check_cp0_mt(ctx);
18943 gen_helper_evpe(t0, cpu_env);
18944 gen_store_gpr(t0, rt);
18945 } else {
18946 gen_reserved_instruction(ctx);
18948 break;
18951 tcg_temp_free(t0);
18953 break;
18954 case NM_FORK:
18955 check_mt(ctx);
18957 TCGv t0 = tcg_temp_new();
18958 TCGv t1 = tcg_temp_new();
18960 gen_load_gpr(t0, rt);
18961 gen_load_gpr(t1, rs);
18962 gen_helper_fork(t0, t1);
18963 tcg_temp_free(t0);
18964 tcg_temp_free(t1);
18966 break;
18967 case NM_MFTR:
18968 case NM_MFHTR:
18969 check_cp0_enabled(ctx);
18970 if (rd == 0) {
18971 /* Treat as NOP. */
18972 return;
18974 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18975 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18976 break;
18977 case NM_MTTR:
18978 case NM_MTHTR:
18979 check_cp0_enabled(ctx);
18980 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18981 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18982 break;
18983 case NM_YIELD:
18984 check_mt(ctx);
18986 TCGv t0 = tcg_temp_new();
18988 gen_load_gpr(t0, rs);
18989 gen_helper_yield(t0, cpu_env, t0);
18990 gen_store_gpr(t0, rt);
18991 tcg_temp_free(t0);
18993 break;
18994 #endif
18995 default:
18996 gen_reserved_instruction(ctx);
18997 break;
19001 /* dsp */
19002 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19003 int ret, int v1, int v2)
19005 TCGv_i32 t0;
19006 TCGv v0_t;
19007 TCGv v1_t;
19009 t0 = tcg_temp_new_i32();
19011 v0_t = tcg_temp_new();
19012 v1_t = tcg_temp_new();
19014 tcg_gen_movi_i32(t0, v2 >> 3);
19016 gen_load_gpr(v0_t, ret);
19017 gen_load_gpr(v1_t, v1);
19019 switch (opc) {
19020 case NM_MAQ_S_W_PHR:
19021 check_dsp(ctx);
19022 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19023 break;
19024 case NM_MAQ_S_W_PHL:
19025 check_dsp(ctx);
19026 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19027 break;
19028 case NM_MAQ_SA_W_PHR:
19029 check_dsp(ctx);
19030 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19031 break;
19032 case NM_MAQ_SA_W_PHL:
19033 check_dsp(ctx);
19034 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19035 break;
19036 default:
19037 gen_reserved_instruction(ctx);
19038 break;
19041 tcg_temp_free_i32(t0);
19043 tcg_temp_free(v0_t);
19044 tcg_temp_free(v1_t);
19048 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19049 int ret, int v1, int v2)
19051 int16_t imm;
19052 TCGv t0 = tcg_temp_new();
19053 TCGv t1 = tcg_temp_new();
19054 TCGv v0_t = tcg_temp_new();
19056 gen_load_gpr(v0_t, v1);
19058 switch (opc) {
19059 case NM_POOL32AXF_1_0:
19060 check_dsp(ctx);
19061 switch (extract32(ctx->opcode, 12, 2)) {
19062 case NM_MFHI:
19063 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19064 break;
19065 case NM_MFLO:
19066 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19067 break;
19068 case NM_MTHI:
19069 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19070 break;
19071 case NM_MTLO:
19072 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19073 break;
19075 break;
19076 case NM_POOL32AXF_1_1:
19077 check_dsp(ctx);
19078 switch (extract32(ctx->opcode, 12, 2)) {
19079 case NM_MTHLIP:
19080 tcg_gen_movi_tl(t0, v2);
19081 gen_helper_mthlip(t0, v0_t, cpu_env);
19082 break;
19083 case NM_SHILOV:
19084 tcg_gen_movi_tl(t0, v2 >> 3);
19085 gen_helper_shilo(t0, v0_t, cpu_env);
19086 break;
19087 default:
19088 gen_reserved_instruction(ctx);
19089 break;
19091 break;
19092 case NM_POOL32AXF_1_3:
19093 check_dsp(ctx);
19094 imm = extract32(ctx->opcode, 14, 7);
19095 switch (extract32(ctx->opcode, 12, 2)) {
19096 case NM_RDDSP:
19097 tcg_gen_movi_tl(t0, imm);
19098 gen_helper_rddsp(t0, t0, cpu_env);
19099 gen_store_gpr(t0, ret);
19100 break;
19101 case NM_WRDSP:
19102 gen_load_gpr(t0, ret);
19103 tcg_gen_movi_tl(t1, imm);
19104 gen_helper_wrdsp(t0, t1, cpu_env);
19105 break;
19106 case NM_EXTP:
19107 tcg_gen_movi_tl(t0, v2 >> 3);
19108 tcg_gen_movi_tl(t1, v1);
19109 gen_helper_extp(t0, t0, t1, cpu_env);
19110 gen_store_gpr(t0, ret);
19111 break;
19112 case NM_EXTPDP:
19113 tcg_gen_movi_tl(t0, v2 >> 3);
19114 tcg_gen_movi_tl(t1, v1);
19115 gen_helper_extpdp(t0, t0, t1, cpu_env);
19116 gen_store_gpr(t0, ret);
19117 break;
19119 break;
19120 case NM_POOL32AXF_1_4:
19121 check_dsp(ctx);
19122 tcg_gen_movi_tl(t0, v2 >> 2);
19123 switch (extract32(ctx->opcode, 12, 1)) {
19124 case NM_SHLL_QB:
19125 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19126 gen_store_gpr(t0, ret);
19127 break;
19128 case NM_SHRL_QB:
19129 gen_helper_shrl_qb(t0, t0, v0_t);
19130 gen_store_gpr(t0, ret);
19131 break;
19133 break;
19134 case NM_POOL32AXF_1_5:
19135 opc = extract32(ctx->opcode, 12, 2);
19136 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19137 break;
19138 case NM_POOL32AXF_1_7:
19139 check_dsp(ctx);
19140 tcg_gen_movi_tl(t0, v2 >> 3);
19141 tcg_gen_movi_tl(t1, v1);
19142 switch (extract32(ctx->opcode, 12, 2)) {
19143 case NM_EXTR_W:
19144 gen_helper_extr_w(t0, t0, t1, cpu_env);
19145 gen_store_gpr(t0, ret);
19146 break;
19147 case NM_EXTR_R_W:
19148 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19149 gen_store_gpr(t0, ret);
19150 break;
19151 case NM_EXTR_RS_W:
19152 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19153 gen_store_gpr(t0, ret);
19154 break;
19155 case NM_EXTR_S_H:
19156 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19157 gen_store_gpr(t0, ret);
19158 break;
19160 break;
19161 default:
19162 gen_reserved_instruction(ctx);
19163 break;
19166 tcg_temp_free(t0);
19167 tcg_temp_free(t1);
19168 tcg_temp_free(v0_t);
19171 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19172 TCGv v0, TCGv v1, int rd)
19174 TCGv_i32 t0;
19176 t0 = tcg_temp_new_i32();
19178 tcg_gen_movi_i32(t0, rd >> 3);
19180 switch (opc) {
19181 case NM_POOL32AXF_2_0_7:
19182 switch (extract32(ctx->opcode, 9, 3)) {
19183 case NM_DPA_W_PH:
19184 check_dsp_r2(ctx);
19185 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19186 break;
19187 case NM_DPAQ_S_W_PH:
19188 check_dsp(ctx);
19189 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19190 break;
19191 case NM_DPS_W_PH:
19192 check_dsp_r2(ctx);
19193 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19194 break;
19195 case NM_DPSQ_S_W_PH:
19196 check_dsp(ctx);
19197 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19198 break;
19199 default:
19200 gen_reserved_instruction(ctx);
19201 break;
19203 break;
19204 case NM_POOL32AXF_2_8_15:
19205 switch (extract32(ctx->opcode, 9, 3)) {
19206 case NM_DPAX_W_PH:
19207 check_dsp_r2(ctx);
19208 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19209 break;
19210 case NM_DPAQ_SA_L_W:
19211 check_dsp(ctx);
19212 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19213 break;
19214 case NM_DPSX_W_PH:
19215 check_dsp_r2(ctx);
19216 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19217 break;
19218 case NM_DPSQ_SA_L_W:
19219 check_dsp(ctx);
19220 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19221 break;
19222 default:
19223 gen_reserved_instruction(ctx);
19224 break;
19226 break;
19227 case NM_POOL32AXF_2_16_23:
19228 switch (extract32(ctx->opcode, 9, 3)) {
19229 case NM_DPAU_H_QBL:
19230 check_dsp(ctx);
19231 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19232 break;
19233 case NM_DPAQX_S_W_PH:
19234 check_dsp_r2(ctx);
19235 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19236 break;
19237 case NM_DPSU_H_QBL:
19238 check_dsp(ctx);
19239 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19240 break;
19241 case NM_DPSQX_S_W_PH:
19242 check_dsp_r2(ctx);
19243 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19244 break;
19245 case NM_MULSA_W_PH:
19246 check_dsp_r2(ctx);
19247 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19248 break;
19249 default:
19250 gen_reserved_instruction(ctx);
19251 break;
19253 break;
19254 case NM_POOL32AXF_2_24_31:
19255 switch (extract32(ctx->opcode, 9, 3)) {
19256 case NM_DPAU_H_QBR:
19257 check_dsp(ctx);
19258 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19259 break;
19260 case NM_DPAQX_SA_W_PH:
19261 check_dsp_r2(ctx);
19262 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19263 break;
19264 case NM_DPSU_H_QBR:
19265 check_dsp(ctx);
19266 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19267 break;
19268 case NM_DPSQX_SA_W_PH:
19269 check_dsp_r2(ctx);
19270 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19271 break;
19272 case NM_MULSAQ_S_W_PH:
19273 check_dsp(ctx);
19274 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19275 break;
19276 default:
19277 gen_reserved_instruction(ctx);
19278 break;
19280 break;
19281 default:
19282 gen_reserved_instruction(ctx);
19283 break;
19286 tcg_temp_free_i32(t0);
19289 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19290 int rt, int rs, int rd)
19292 int ret = rt;
19293 TCGv t0 = tcg_temp_new();
19294 TCGv t1 = tcg_temp_new();
19295 TCGv v0_t = tcg_temp_new();
19296 TCGv v1_t = tcg_temp_new();
19298 gen_load_gpr(v0_t, rt);
19299 gen_load_gpr(v1_t, rs);
19301 switch (opc) {
19302 case NM_POOL32AXF_2_0_7:
19303 switch (extract32(ctx->opcode, 9, 3)) {
19304 case NM_DPA_W_PH:
19305 case NM_DPAQ_S_W_PH:
19306 case NM_DPS_W_PH:
19307 case NM_DPSQ_S_W_PH:
19308 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19309 break;
19310 case NM_BALIGN:
19311 check_dsp_r2(ctx);
19312 if (rt != 0) {
19313 gen_load_gpr(t0, rs);
19314 rd &= 3;
19315 if (rd != 0 && rd != 2) {
19316 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19317 tcg_gen_ext32u_tl(t0, t0);
19318 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19319 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19321 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19323 break;
19324 case NM_MADD:
19325 check_dsp(ctx);
19327 int acc = extract32(ctx->opcode, 14, 2);
19328 TCGv_i64 t2 = tcg_temp_new_i64();
19329 TCGv_i64 t3 = tcg_temp_new_i64();
19331 gen_load_gpr(t0, rt);
19332 gen_load_gpr(t1, rs);
19333 tcg_gen_ext_tl_i64(t2, t0);
19334 tcg_gen_ext_tl_i64(t3, t1);
19335 tcg_gen_mul_i64(t2, t2, t3);
19336 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19337 tcg_gen_add_i64(t2, t2, t3);
19338 tcg_temp_free_i64(t3);
19339 gen_move_low32(cpu_LO[acc], t2);
19340 gen_move_high32(cpu_HI[acc], t2);
19341 tcg_temp_free_i64(t2);
19343 break;
19344 case NM_MULT:
19345 check_dsp(ctx);
19347 int acc = extract32(ctx->opcode, 14, 2);
19348 TCGv_i32 t2 = tcg_temp_new_i32();
19349 TCGv_i32 t3 = tcg_temp_new_i32();
19351 gen_load_gpr(t0, rs);
19352 gen_load_gpr(t1, rt);
19353 tcg_gen_trunc_tl_i32(t2, t0);
19354 tcg_gen_trunc_tl_i32(t3, t1);
19355 tcg_gen_muls2_i32(t2, t3, t2, t3);
19356 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19357 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19358 tcg_temp_free_i32(t2);
19359 tcg_temp_free_i32(t3);
19361 break;
19362 case NM_EXTRV_W:
19363 check_dsp(ctx);
19364 gen_load_gpr(v1_t, rs);
19365 tcg_gen_movi_tl(t0, rd >> 3);
19366 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19367 gen_store_gpr(t0, ret);
19368 break;
19370 break;
19371 case NM_POOL32AXF_2_8_15:
19372 switch (extract32(ctx->opcode, 9, 3)) {
19373 case NM_DPAX_W_PH:
19374 case NM_DPAQ_SA_L_W:
19375 case NM_DPSX_W_PH:
19376 case NM_DPSQ_SA_L_W:
19377 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19378 break;
19379 case NM_MADDU:
19380 check_dsp(ctx);
19382 int acc = extract32(ctx->opcode, 14, 2);
19383 TCGv_i64 t2 = tcg_temp_new_i64();
19384 TCGv_i64 t3 = tcg_temp_new_i64();
19386 gen_load_gpr(t0, rs);
19387 gen_load_gpr(t1, rt);
19388 tcg_gen_ext32u_tl(t0, t0);
19389 tcg_gen_ext32u_tl(t1, t1);
19390 tcg_gen_extu_tl_i64(t2, t0);
19391 tcg_gen_extu_tl_i64(t3, t1);
19392 tcg_gen_mul_i64(t2, t2, t3);
19393 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19394 tcg_gen_add_i64(t2, t2, t3);
19395 tcg_temp_free_i64(t3);
19396 gen_move_low32(cpu_LO[acc], t2);
19397 gen_move_high32(cpu_HI[acc], t2);
19398 tcg_temp_free_i64(t2);
19400 break;
19401 case NM_MULTU:
19402 check_dsp(ctx);
19404 int acc = extract32(ctx->opcode, 14, 2);
19405 TCGv_i32 t2 = tcg_temp_new_i32();
19406 TCGv_i32 t3 = tcg_temp_new_i32();
19408 gen_load_gpr(t0, rs);
19409 gen_load_gpr(t1, rt);
19410 tcg_gen_trunc_tl_i32(t2, t0);
19411 tcg_gen_trunc_tl_i32(t3, t1);
19412 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19413 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19414 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19415 tcg_temp_free_i32(t2);
19416 tcg_temp_free_i32(t3);
19418 break;
19419 case NM_EXTRV_R_W:
19420 check_dsp(ctx);
19421 tcg_gen_movi_tl(t0, rd >> 3);
19422 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19423 gen_store_gpr(t0, ret);
19424 break;
19425 default:
19426 gen_reserved_instruction(ctx);
19427 break;
19429 break;
19430 case NM_POOL32AXF_2_16_23:
19431 switch (extract32(ctx->opcode, 9, 3)) {
19432 case NM_DPAU_H_QBL:
19433 case NM_DPAQX_S_W_PH:
19434 case NM_DPSU_H_QBL:
19435 case NM_DPSQX_S_W_PH:
19436 case NM_MULSA_W_PH:
19437 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19438 break;
19439 case NM_EXTPV:
19440 check_dsp(ctx);
19441 tcg_gen_movi_tl(t0, rd >> 3);
19442 gen_helper_extp(t0, t0, v1_t, cpu_env);
19443 gen_store_gpr(t0, ret);
19444 break;
19445 case NM_MSUB:
19446 check_dsp(ctx);
19448 int acc = extract32(ctx->opcode, 14, 2);
19449 TCGv_i64 t2 = tcg_temp_new_i64();
19450 TCGv_i64 t3 = tcg_temp_new_i64();
19452 gen_load_gpr(t0, rs);
19453 gen_load_gpr(t1, rt);
19454 tcg_gen_ext_tl_i64(t2, t0);
19455 tcg_gen_ext_tl_i64(t3, t1);
19456 tcg_gen_mul_i64(t2, t2, t3);
19457 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19458 tcg_gen_sub_i64(t2, t3, t2);
19459 tcg_temp_free_i64(t3);
19460 gen_move_low32(cpu_LO[acc], t2);
19461 gen_move_high32(cpu_HI[acc], t2);
19462 tcg_temp_free_i64(t2);
19464 break;
19465 case NM_EXTRV_RS_W:
19466 check_dsp(ctx);
19467 tcg_gen_movi_tl(t0, rd >> 3);
19468 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19469 gen_store_gpr(t0, ret);
19470 break;
19472 break;
19473 case NM_POOL32AXF_2_24_31:
19474 switch (extract32(ctx->opcode, 9, 3)) {
19475 case NM_DPAU_H_QBR:
19476 case NM_DPAQX_SA_W_PH:
19477 case NM_DPSU_H_QBR:
19478 case NM_DPSQX_SA_W_PH:
19479 case NM_MULSAQ_S_W_PH:
19480 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19481 break;
19482 case NM_EXTPDPV:
19483 check_dsp(ctx);
19484 tcg_gen_movi_tl(t0, rd >> 3);
19485 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19486 gen_store_gpr(t0, ret);
19487 break;
19488 case NM_MSUBU:
19489 check_dsp(ctx);
19491 int acc = extract32(ctx->opcode, 14, 2);
19492 TCGv_i64 t2 = tcg_temp_new_i64();
19493 TCGv_i64 t3 = tcg_temp_new_i64();
19495 gen_load_gpr(t0, rs);
19496 gen_load_gpr(t1, rt);
19497 tcg_gen_ext32u_tl(t0, t0);
19498 tcg_gen_ext32u_tl(t1, t1);
19499 tcg_gen_extu_tl_i64(t2, t0);
19500 tcg_gen_extu_tl_i64(t3, t1);
19501 tcg_gen_mul_i64(t2, t2, t3);
19502 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19503 tcg_gen_sub_i64(t2, t3, t2);
19504 tcg_temp_free_i64(t3);
19505 gen_move_low32(cpu_LO[acc], t2);
19506 gen_move_high32(cpu_HI[acc], t2);
19507 tcg_temp_free_i64(t2);
19509 break;
19510 case NM_EXTRV_S_H:
19511 check_dsp(ctx);
19512 tcg_gen_movi_tl(t0, rd >> 3);
19513 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19514 gen_store_gpr(t0, ret);
19515 break;
19517 break;
19518 default:
19519 gen_reserved_instruction(ctx);
19520 break;
19523 tcg_temp_free(t0);
19524 tcg_temp_free(t1);
19526 tcg_temp_free(v0_t);
19527 tcg_temp_free(v1_t);
19530 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19531 int rt, int rs)
19533 int ret = rt;
19534 TCGv t0 = tcg_temp_new();
19535 TCGv v0_t = tcg_temp_new();
19537 gen_load_gpr(v0_t, rs);
19539 switch (opc) {
19540 case NM_ABSQ_S_QB:
19541 check_dsp_r2(ctx);
19542 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19543 gen_store_gpr(v0_t, ret);
19544 break;
19545 case NM_ABSQ_S_PH:
19546 check_dsp(ctx);
19547 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19548 gen_store_gpr(v0_t, ret);
19549 break;
19550 case NM_ABSQ_S_W:
19551 check_dsp(ctx);
19552 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19553 gen_store_gpr(v0_t, ret);
19554 break;
19555 case NM_PRECEQ_W_PHL:
19556 check_dsp(ctx);
19557 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19558 tcg_gen_ext32s_tl(v0_t, v0_t);
19559 gen_store_gpr(v0_t, ret);
19560 break;
19561 case NM_PRECEQ_W_PHR:
19562 check_dsp(ctx);
19563 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19564 tcg_gen_shli_tl(v0_t, v0_t, 16);
19565 tcg_gen_ext32s_tl(v0_t, v0_t);
19566 gen_store_gpr(v0_t, ret);
19567 break;
19568 case NM_PRECEQU_PH_QBL:
19569 check_dsp(ctx);
19570 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19571 gen_store_gpr(v0_t, ret);
19572 break;
19573 case NM_PRECEQU_PH_QBR:
19574 check_dsp(ctx);
19575 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19576 gen_store_gpr(v0_t, ret);
19577 break;
19578 case NM_PRECEQU_PH_QBLA:
19579 check_dsp(ctx);
19580 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19581 gen_store_gpr(v0_t, ret);
19582 break;
19583 case NM_PRECEQU_PH_QBRA:
19584 check_dsp(ctx);
19585 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19586 gen_store_gpr(v0_t, ret);
19587 break;
19588 case NM_PRECEU_PH_QBL:
19589 check_dsp(ctx);
19590 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19591 gen_store_gpr(v0_t, ret);
19592 break;
19593 case NM_PRECEU_PH_QBR:
19594 check_dsp(ctx);
19595 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19596 gen_store_gpr(v0_t, ret);
19597 break;
19598 case NM_PRECEU_PH_QBLA:
19599 check_dsp(ctx);
19600 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19601 gen_store_gpr(v0_t, ret);
19602 break;
19603 case NM_PRECEU_PH_QBRA:
19604 check_dsp(ctx);
19605 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19606 gen_store_gpr(v0_t, ret);
19607 break;
19608 case NM_REPLV_PH:
19609 check_dsp(ctx);
19610 tcg_gen_ext16u_tl(v0_t, v0_t);
19611 tcg_gen_shli_tl(t0, v0_t, 16);
19612 tcg_gen_or_tl(v0_t, v0_t, t0);
19613 tcg_gen_ext32s_tl(v0_t, v0_t);
19614 gen_store_gpr(v0_t, ret);
19615 break;
19616 case NM_REPLV_QB:
19617 check_dsp(ctx);
19618 tcg_gen_ext8u_tl(v0_t, v0_t);
19619 tcg_gen_shli_tl(t0, v0_t, 8);
19620 tcg_gen_or_tl(v0_t, v0_t, t0);
19621 tcg_gen_shli_tl(t0, v0_t, 16);
19622 tcg_gen_or_tl(v0_t, v0_t, t0);
19623 tcg_gen_ext32s_tl(v0_t, v0_t);
19624 gen_store_gpr(v0_t, ret);
19625 break;
19626 case NM_BITREV:
19627 check_dsp(ctx);
19628 gen_helper_bitrev(v0_t, v0_t);
19629 gen_store_gpr(v0_t, ret);
19630 break;
19631 case NM_INSV:
19632 check_dsp(ctx);
19634 TCGv tv0 = tcg_temp_new();
19636 gen_load_gpr(tv0, rt);
19637 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19638 gen_store_gpr(v0_t, ret);
19639 tcg_temp_free(tv0);
19641 break;
19642 case NM_RADDU_W_QB:
19643 check_dsp(ctx);
19644 gen_helper_raddu_w_qb(v0_t, v0_t);
19645 gen_store_gpr(v0_t, ret);
19646 break;
19647 case NM_BITSWAP:
19648 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19649 break;
19650 case NM_CLO:
19651 check_nms(ctx);
19652 gen_cl(ctx, OPC_CLO, ret, rs);
19653 break;
19654 case NM_CLZ:
19655 check_nms(ctx);
19656 gen_cl(ctx, OPC_CLZ, ret, rs);
19657 break;
19658 case NM_WSBH:
19659 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19660 break;
19661 default:
19662 gen_reserved_instruction(ctx);
19663 break;
19666 tcg_temp_free(v0_t);
19667 tcg_temp_free(t0);
19670 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19671 int rt, int rs, int rd)
19673 TCGv t0 = tcg_temp_new();
19674 TCGv rs_t = tcg_temp_new();
19676 gen_load_gpr(rs_t, rs);
19678 switch (opc) {
19679 case NM_SHRA_R_QB:
19680 check_dsp_r2(ctx);
19681 tcg_gen_movi_tl(t0, rd >> 2);
19682 switch (extract32(ctx->opcode, 12, 1)) {
19683 case 0:
19684 /* NM_SHRA_QB */
19685 gen_helper_shra_qb(t0, t0, rs_t);
19686 gen_store_gpr(t0, rt);
19687 break;
19688 case 1:
19689 /* NM_SHRA_R_QB */
19690 gen_helper_shra_r_qb(t0, t0, rs_t);
19691 gen_store_gpr(t0, rt);
19692 break;
19694 break;
19695 case NM_SHRL_PH:
19696 check_dsp_r2(ctx);
19697 tcg_gen_movi_tl(t0, rd >> 1);
19698 gen_helper_shrl_ph(t0, t0, rs_t);
19699 gen_store_gpr(t0, rt);
19700 break;
19701 case NM_REPL_QB:
19702 check_dsp(ctx);
19704 int16_t imm;
19705 target_long result;
19706 imm = extract32(ctx->opcode, 13, 8);
19707 result = (uint32_t)imm << 24 |
19708 (uint32_t)imm << 16 |
19709 (uint32_t)imm << 8 |
19710 (uint32_t)imm;
19711 result = (int32_t)result;
19712 tcg_gen_movi_tl(t0, result);
19713 gen_store_gpr(t0, rt);
19715 break;
19716 default:
19717 gen_reserved_instruction(ctx);
19718 break;
19720 tcg_temp_free(t0);
19721 tcg_temp_free(rs_t);
19725 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19727 int rt = extract32(ctx->opcode, 21, 5);
19728 int rs = extract32(ctx->opcode, 16, 5);
19729 int rd = extract32(ctx->opcode, 11, 5);
19731 switch (extract32(ctx->opcode, 6, 3)) {
19732 case NM_POOL32AXF_1:
19734 int32_t op1 = extract32(ctx->opcode, 9, 3);
19735 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19737 break;
19738 case NM_POOL32AXF_2:
19740 int32_t op1 = extract32(ctx->opcode, 12, 2);
19741 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19743 break;
19744 case NM_POOL32AXF_4:
19746 int32_t op1 = extract32(ctx->opcode, 9, 7);
19747 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19749 break;
19750 case NM_POOL32AXF_5:
19751 switch (extract32(ctx->opcode, 9, 7)) {
19752 #ifndef CONFIG_USER_ONLY
19753 case NM_TLBP:
19754 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19755 break;
19756 case NM_TLBR:
19757 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19758 break;
19759 case NM_TLBWI:
19760 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19761 break;
19762 case NM_TLBWR:
19763 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19764 break;
19765 case NM_TLBINV:
19766 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19767 break;
19768 case NM_TLBINVF:
19769 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19770 break;
19771 case NM_DI:
19772 check_cp0_enabled(ctx);
19774 TCGv t0 = tcg_temp_new();
19776 save_cpu_state(ctx, 1);
19777 gen_helper_di(t0, cpu_env);
19778 gen_store_gpr(t0, rt);
19779 /* Stop translation as we may have switched the execution mode */
19780 ctx->base.is_jmp = DISAS_STOP;
19781 tcg_temp_free(t0);
19783 break;
19784 case NM_EI:
19785 check_cp0_enabled(ctx);
19787 TCGv t0 = tcg_temp_new();
19789 save_cpu_state(ctx, 1);
19790 gen_helper_ei(t0, cpu_env);
19791 gen_store_gpr(t0, rt);
19792 /* Stop translation as we may have switched the execution mode */
19793 ctx->base.is_jmp = DISAS_STOP;
19794 tcg_temp_free(t0);
19796 break;
19797 case NM_RDPGPR:
19798 gen_load_srsgpr(rs, rt);
19799 break;
19800 case NM_WRPGPR:
19801 gen_store_srsgpr(rs, rt);
19802 break;
19803 case NM_WAIT:
19804 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19805 break;
19806 case NM_DERET:
19807 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19808 break;
19809 case NM_ERETX:
19810 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19811 break;
19812 #endif
19813 default:
19814 gen_reserved_instruction(ctx);
19815 break;
19817 break;
19818 case NM_POOL32AXF_7:
19820 int32_t op1 = extract32(ctx->opcode, 9, 3);
19821 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19823 break;
19824 default:
19825 gen_reserved_instruction(ctx);
19826 break;
19830 /* Immediate Value Compact Branches */
19831 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19832 int rt, int32_t imm, int32_t offset)
19834 TCGCond cond = TCG_COND_ALWAYS;
19835 TCGv t0 = tcg_temp_new();
19836 TCGv t1 = tcg_temp_new();
19838 gen_load_gpr(t0, rt);
19839 tcg_gen_movi_tl(t1, imm);
19840 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19842 /* Load needed operands and calculate btarget */
19843 switch (opc) {
19844 case NM_BEQIC:
19845 if (rt == 0 && imm == 0) {
19846 /* Unconditional branch */
19847 } else if (rt == 0 && imm != 0) {
19848 /* Treat as NOP */
19849 goto out;
19850 } else {
19851 cond = TCG_COND_EQ;
19853 break;
19854 case NM_BBEQZC:
19855 case NM_BBNEZC:
19856 check_nms(ctx);
19857 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19858 gen_reserved_instruction(ctx);
19859 goto out;
19860 } else if (rt == 0 && opc == NM_BBEQZC) {
19861 /* Unconditional branch */
19862 } else if (rt == 0 && opc == NM_BBNEZC) {
19863 /* Treat as NOP */
19864 goto out;
19865 } else {
19866 tcg_gen_shri_tl(t0, t0, imm);
19867 tcg_gen_andi_tl(t0, t0, 1);
19868 tcg_gen_movi_tl(t1, 0);
19869 if (opc == NM_BBEQZC) {
19870 cond = TCG_COND_EQ;
19871 } else {
19872 cond = TCG_COND_NE;
19875 break;
19876 case NM_BNEIC:
19877 if (rt == 0 && imm == 0) {
19878 /* Treat as NOP */
19879 goto out;
19880 } else if (rt == 0 && imm != 0) {
19881 /* Unconditional branch */
19882 } else {
19883 cond = TCG_COND_NE;
19885 break;
19886 case NM_BGEIC:
19887 if (rt == 0 && imm == 0) {
19888 /* Unconditional branch */
19889 } else {
19890 cond = TCG_COND_GE;
19892 break;
19893 case NM_BLTIC:
19894 cond = TCG_COND_LT;
19895 break;
19896 case NM_BGEIUC:
19897 if (rt == 0 && imm == 0) {
19898 /* Unconditional branch */
19899 } else {
19900 cond = TCG_COND_GEU;
19902 break;
19903 case NM_BLTIUC:
19904 cond = TCG_COND_LTU;
19905 break;
19906 default:
19907 MIPS_INVAL("Immediate Value Compact branch");
19908 gen_reserved_instruction(ctx);
19909 goto out;
19912 /* branch completion */
19913 clear_branch_hflags(ctx);
19914 ctx->base.is_jmp = DISAS_NORETURN;
19916 if (cond == TCG_COND_ALWAYS) {
19917 /* Uncoditional compact branch */
19918 gen_goto_tb(ctx, 0, ctx->btarget);
19919 } else {
19920 /* Conditional compact branch */
19921 TCGLabel *fs = gen_new_label();
19923 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19925 gen_goto_tb(ctx, 1, ctx->btarget);
19926 gen_set_label(fs);
19928 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19931 out:
19932 tcg_temp_free(t0);
19933 tcg_temp_free(t1);
19936 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19937 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19938 int rt)
19940 TCGv t0 = tcg_temp_new();
19941 TCGv t1 = tcg_temp_new();
19943 /* load rs */
19944 gen_load_gpr(t0, rs);
19946 /* link */
19947 if (rt != 0) {
19948 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19951 /* calculate btarget */
19952 tcg_gen_shli_tl(t0, t0, 1);
19953 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19954 gen_op_addr_add(ctx, btarget, t1, t0);
19956 /* branch completion */
19957 clear_branch_hflags(ctx);
19958 ctx->base.is_jmp = DISAS_NORETURN;
19960 /* unconditional branch to register */
19961 tcg_gen_mov_tl(cpu_PC, btarget);
19962 tcg_gen_lookup_and_goto_ptr();
19964 tcg_temp_free(t0);
19965 tcg_temp_free(t1);
19968 /* nanoMIPS Branches */
19969 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19970 int rs, int rt, int32_t offset)
19972 int bcond_compute = 0;
19973 TCGv t0 = tcg_temp_new();
19974 TCGv t1 = tcg_temp_new();
19976 /* Load needed operands and calculate btarget */
19977 switch (opc) {
19978 /* compact branch */
19979 case OPC_BGEC:
19980 case OPC_BLTC:
19981 gen_load_gpr(t0, rs);
19982 gen_load_gpr(t1, rt);
19983 bcond_compute = 1;
19984 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19985 break;
19986 case OPC_BGEUC:
19987 case OPC_BLTUC:
19988 if (rs == 0 || rs == rt) {
19989 /* OPC_BLEZALC, OPC_BGEZALC */
19990 /* OPC_BGTZALC, OPC_BLTZALC */
19991 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19993 gen_load_gpr(t0, rs);
19994 gen_load_gpr(t1, rt);
19995 bcond_compute = 1;
19996 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19997 break;
19998 case OPC_BC:
19999 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20000 break;
20001 case OPC_BEQZC:
20002 if (rs != 0) {
20003 /* OPC_BEQZC, OPC_BNEZC */
20004 gen_load_gpr(t0, rs);
20005 bcond_compute = 1;
20006 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20007 } else {
20008 /* OPC_JIC, OPC_JIALC */
20009 TCGv tbase = tcg_temp_new();
20010 TCGv toffset = tcg_temp_new();
20012 gen_load_gpr(tbase, rt);
20013 tcg_gen_movi_tl(toffset, offset);
20014 gen_op_addr_add(ctx, btarget, tbase, toffset);
20015 tcg_temp_free(tbase);
20016 tcg_temp_free(toffset);
20018 break;
20019 default:
20020 MIPS_INVAL("Compact branch/jump");
20021 gen_reserved_instruction(ctx);
20022 goto out;
20025 if (bcond_compute == 0) {
20026 /* Uncoditional compact branch */
20027 switch (opc) {
20028 case OPC_BC:
20029 gen_goto_tb(ctx, 0, ctx->btarget);
20030 break;
20031 default:
20032 MIPS_INVAL("Compact branch/jump");
20033 gen_reserved_instruction(ctx);
20034 goto out;
20036 } else {
20037 /* Conditional compact branch */
20038 TCGLabel *fs = gen_new_label();
20040 switch (opc) {
20041 case OPC_BGEUC:
20042 if (rs == 0 && rt != 0) {
20043 /* OPC_BLEZALC */
20044 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20045 } else if (rs != 0 && rt != 0 && rs == rt) {
20046 /* OPC_BGEZALC */
20047 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20048 } else {
20049 /* OPC_BGEUC */
20050 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20052 break;
20053 case OPC_BLTUC:
20054 if (rs == 0 && rt != 0) {
20055 /* OPC_BGTZALC */
20056 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20057 } else if (rs != 0 && rt != 0 && rs == rt) {
20058 /* OPC_BLTZALC */
20059 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20060 } else {
20061 /* OPC_BLTUC */
20062 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20064 break;
20065 case OPC_BGEC:
20066 if (rs == 0 && rt != 0) {
20067 /* OPC_BLEZC */
20068 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20069 } else if (rs != 0 && rt != 0 && rs == rt) {
20070 /* OPC_BGEZC */
20071 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20072 } else {
20073 /* OPC_BGEC */
20074 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20076 break;
20077 case OPC_BLTC:
20078 if (rs == 0 && rt != 0) {
20079 /* OPC_BGTZC */
20080 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20081 } else if (rs != 0 && rt != 0 && rs == rt) {
20082 /* OPC_BLTZC */
20083 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20084 } else {
20085 /* OPC_BLTC */
20086 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20088 break;
20089 case OPC_BEQZC:
20090 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20091 break;
20092 default:
20093 MIPS_INVAL("Compact conditional branch/jump");
20094 gen_reserved_instruction(ctx);
20095 goto out;
20098 /* branch completion */
20099 clear_branch_hflags(ctx);
20100 ctx->base.is_jmp = DISAS_NORETURN;
20102 /* Generating branch here as compact branches don't have delay slot */
20103 gen_goto_tb(ctx, 1, ctx->btarget);
20104 gen_set_label(fs);
20106 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20109 out:
20110 tcg_temp_free(t0);
20111 tcg_temp_free(t1);
20115 /* nanoMIPS CP1 Branches */
20116 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20117 int32_t ft, int32_t offset)
20119 target_ulong btarget;
20120 TCGv_i64 t0 = tcg_temp_new_i64();
20122 gen_load_fpr64(ctx, t0, ft);
20123 tcg_gen_andi_i64(t0, t0, 1);
20125 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20127 switch (op) {
20128 case NM_BC1EQZC:
20129 tcg_gen_xori_i64(t0, t0, 1);
20130 ctx->hflags |= MIPS_HFLAG_BC;
20131 break;
20132 case NM_BC1NEZC:
20133 /* t0 already set */
20134 ctx->hflags |= MIPS_HFLAG_BC;
20135 break;
20136 default:
20137 MIPS_INVAL("cp1 cond branch");
20138 gen_reserved_instruction(ctx);
20139 goto out;
20142 tcg_gen_trunc_i64_tl(bcond, t0);
20144 ctx->btarget = btarget;
20146 out:
20147 tcg_temp_free_i64(t0);
20151 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20153 TCGv t0, t1;
20154 t0 = tcg_temp_new();
20155 t1 = tcg_temp_new();
20157 gen_load_gpr(t0, rs);
20158 gen_load_gpr(t1, rt);
20160 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20161 /* PP.LSXS instructions require shifting */
20162 switch (extract32(ctx->opcode, 7, 4)) {
20163 case NM_SHXS:
20164 check_nms(ctx);
20165 /* fall through */
20166 case NM_LHXS:
20167 case NM_LHUXS:
20168 tcg_gen_shli_tl(t0, t0, 1);
20169 break;
20170 case NM_SWXS:
20171 check_nms(ctx);
20172 /* fall through */
20173 case NM_LWXS:
20174 case NM_LWC1XS:
20175 case NM_SWC1XS:
20176 tcg_gen_shli_tl(t0, t0, 2);
20177 break;
20178 case NM_LDC1XS:
20179 case NM_SDC1XS:
20180 tcg_gen_shli_tl(t0, t0, 3);
20181 break;
20184 gen_op_addr_add(ctx, t0, t0, t1);
20186 switch (extract32(ctx->opcode, 7, 4)) {
20187 case NM_LBX:
20188 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20189 MO_SB);
20190 gen_store_gpr(t0, rd);
20191 break;
20192 case NM_LHX:
20193 /*case NM_LHXS:*/
20194 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20195 MO_TESW);
20196 gen_store_gpr(t0, rd);
20197 break;
20198 case NM_LWX:
20199 /*case NM_LWXS:*/
20200 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20201 MO_TESL);
20202 gen_store_gpr(t0, rd);
20203 break;
20204 case NM_LBUX:
20205 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20206 MO_UB);
20207 gen_store_gpr(t0, rd);
20208 break;
20209 case NM_LHUX:
20210 /*case NM_LHUXS:*/
20211 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20212 MO_TEUW);
20213 gen_store_gpr(t0, rd);
20214 break;
20215 case NM_SBX:
20216 check_nms(ctx);
20217 gen_load_gpr(t1, rd);
20218 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20219 MO_8);
20220 break;
20221 case NM_SHX:
20222 /*case NM_SHXS:*/
20223 check_nms(ctx);
20224 gen_load_gpr(t1, rd);
20225 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20226 MO_TEUW);
20227 break;
20228 case NM_SWX:
20229 /*case NM_SWXS:*/
20230 check_nms(ctx);
20231 gen_load_gpr(t1, rd);
20232 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20233 MO_TEUL);
20234 break;
20235 case NM_LWC1X:
20236 /*case NM_LWC1XS:*/
20237 case NM_LDC1X:
20238 /*case NM_LDC1XS:*/
20239 case NM_SWC1X:
20240 /*case NM_SWC1XS:*/
20241 case NM_SDC1X:
20242 /*case NM_SDC1XS:*/
20243 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20244 check_cp1_enabled(ctx);
20245 switch (extract32(ctx->opcode, 7, 4)) {
20246 case NM_LWC1X:
20247 /*case NM_LWC1XS:*/
20248 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20249 break;
20250 case NM_LDC1X:
20251 /*case NM_LDC1XS:*/
20252 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20253 break;
20254 case NM_SWC1X:
20255 /*case NM_SWC1XS:*/
20256 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20257 break;
20258 case NM_SDC1X:
20259 /*case NM_SDC1XS:*/
20260 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20261 break;
20263 } else {
20264 generate_exception_err(ctx, EXCP_CpU, 1);
20266 break;
20267 default:
20268 gen_reserved_instruction(ctx);
20269 break;
20272 tcg_temp_free(t0);
20273 tcg_temp_free(t1);
20276 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20278 int rt, rs, rd;
20280 rt = extract32(ctx->opcode, 21, 5);
20281 rs = extract32(ctx->opcode, 16, 5);
20282 rd = extract32(ctx->opcode, 11, 5);
20284 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20285 gen_reserved_instruction(ctx);
20286 return;
20288 check_cp1_enabled(ctx);
20289 switch (extract32(ctx->opcode, 0, 3)) {
20290 case NM_POOL32F_0:
20291 switch (extract32(ctx->opcode, 3, 7)) {
20292 case NM_RINT_S:
20293 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20294 break;
20295 case NM_RINT_D:
20296 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20297 break;
20298 case NM_CLASS_S:
20299 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20300 break;
20301 case NM_CLASS_D:
20302 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20303 break;
20304 case NM_ADD_S:
20305 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20306 break;
20307 case NM_ADD_D:
20308 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20309 break;
20310 case NM_SUB_S:
20311 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20312 break;
20313 case NM_SUB_D:
20314 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20315 break;
20316 case NM_MUL_S:
20317 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20318 break;
20319 case NM_MUL_D:
20320 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20321 break;
20322 case NM_DIV_S:
20323 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20324 break;
20325 case NM_DIV_D:
20326 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20327 break;
20328 case NM_SELEQZ_S:
20329 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20330 break;
20331 case NM_SELEQZ_D:
20332 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20333 break;
20334 case NM_SELNEZ_S:
20335 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20336 break;
20337 case NM_SELNEZ_D:
20338 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20339 break;
20340 case NM_SEL_S:
20341 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20342 break;
20343 case NM_SEL_D:
20344 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20345 break;
20346 case NM_MADDF_S:
20347 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20348 break;
20349 case NM_MADDF_D:
20350 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20351 break;
20352 case NM_MSUBF_S:
20353 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20354 break;
20355 case NM_MSUBF_D:
20356 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20357 break;
20358 default:
20359 gen_reserved_instruction(ctx);
20360 break;
20362 break;
20363 case NM_POOL32F_3:
20364 switch (extract32(ctx->opcode, 3, 3)) {
20365 case NM_MIN_FMT:
20366 switch (extract32(ctx->opcode, 9, 1)) {
20367 case FMT_SDPS_S:
20368 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20369 break;
20370 case FMT_SDPS_D:
20371 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20372 break;
20374 break;
20375 case NM_MAX_FMT:
20376 switch (extract32(ctx->opcode, 9, 1)) {
20377 case FMT_SDPS_S:
20378 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20379 break;
20380 case FMT_SDPS_D:
20381 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20382 break;
20384 break;
20385 case NM_MINA_FMT:
20386 switch (extract32(ctx->opcode, 9, 1)) {
20387 case FMT_SDPS_S:
20388 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20389 break;
20390 case FMT_SDPS_D:
20391 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20392 break;
20394 break;
20395 case NM_MAXA_FMT:
20396 switch (extract32(ctx->opcode, 9, 1)) {
20397 case FMT_SDPS_S:
20398 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20399 break;
20400 case FMT_SDPS_D:
20401 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20402 break;
20404 break;
20405 case NM_POOL32FXF:
20406 switch (extract32(ctx->opcode, 6, 8)) {
20407 case NM_CFC1:
20408 gen_cp1(ctx, OPC_CFC1, rt, rs);
20409 break;
20410 case NM_CTC1:
20411 gen_cp1(ctx, OPC_CTC1, rt, rs);
20412 break;
20413 case NM_MFC1:
20414 gen_cp1(ctx, OPC_MFC1, rt, rs);
20415 break;
20416 case NM_MTC1:
20417 gen_cp1(ctx, OPC_MTC1, rt, rs);
20418 break;
20419 case NM_MFHC1:
20420 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20421 break;
20422 case NM_MTHC1:
20423 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20424 break;
20425 case NM_CVT_S_PL:
20426 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20427 break;
20428 case NM_CVT_S_PU:
20429 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20430 break;
20431 default:
20432 switch (extract32(ctx->opcode, 6, 9)) {
20433 case NM_CVT_L_S:
20434 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20435 break;
20436 case NM_CVT_L_D:
20437 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20438 break;
20439 case NM_CVT_W_S:
20440 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20441 break;
20442 case NM_CVT_W_D:
20443 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20444 break;
20445 case NM_RSQRT_S:
20446 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20447 break;
20448 case NM_RSQRT_D:
20449 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20450 break;
20451 case NM_SQRT_S:
20452 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20453 break;
20454 case NM_SQRT_D:
20455 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20456 break;
20457 case NM_RECIP_S:
20458 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20459 break;
20460 case NM_RECIP_D:
20461 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20462 break;
20463 case NM_FLOOR_L_S:
20464 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20465 break;
20466 case NM_FLOOR_L_D:
20467 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20468 break;
20469 case NM_FLOOR_W_S:
20470 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20471 break;
20472 case NM_FLOOR_W_D:
20473 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20474 break;
20475 case NM_CEIL_L_S:
20476 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20477 break;
20478 case NM_CEIL_L_D:
20479 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20480 break;
20481 case NM_CEIL_W_S:
20482 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20483 break;
20484 case NM_CEIL_W_D:
20485 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20486 break;
20487 case NM_TRUNC_L_S:
20488 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20489 break;
20490 case NM_TRUNC_L_D:
20491 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20492 break;
20493 case NM_TRUNC_W_S:
20494 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20495 break;
20496 case NM_TRUNC_W_D:
20497 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20498 break;
20499 case NM_ROUND_L_S:
20500 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20501 break;
20502 case NM_ROUND_L_D:
20503 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20504 break;
20505 case NM_ROUND_W_S:
20506 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20507 break;
20508 case NM_ROUND_W_D:
20509 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20510 break;
20511 case NM_MOV_S:
20512 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20513 break;
20514 case NM_MOV_D:
20515 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20516 break;
20517 case NM_ABS_S:
20518 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20519 break;
20520 case NM_ABS_D:
20521 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20522 break;
20523 case NM_NEG_S:
20524 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20525 break;
20526 case NM_NEG_D:
20527 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20528 break;
20529 case NM_CVT_D_S:
20530 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20531 break;
20532 case NM_CVT_D_W:
20533 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20534 break;
20535 case NM_CVT_D_L:
20536 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20537 break;
20538 case NM_CVT_S_D:
20539 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20540 break;
20541 case NM_CVT_S_W:
20542 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20543 break;
20544 case NM_CVT_S_L:
20545 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20546 break;
20547 default:
20548 gen_reserved_instruction(ctx);
20549 break;
20551 break;
20553 break;
20555 break;
20556 case NM_POOL32F_5:
20557 switch (extract32(ctx->opcode, 3, 3)) {
20558 case NM_CMP_CONDN_S:
20559 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20560 break;
20561 case NM_CMP_CONDN_D:
20562 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20563 break;
20564 default:
20565 gen_reserved_instruction(ctx);
20566 break;
20568 break;
20569 default:
20570 gen_reserved_instruction(ctx);
20571 break;
20575 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20576 int rd, int rs, int rt)
20578 int ret = rd;
20579 TCGv t0 = tcg_temp_new();
20580 TCGv v1_t = tcg_temp_new();
20581 TCGv v2_t = tcg_temp_new();
20583 gen_load_gpr(v1_t, rs);
20584 gen_load_gpr(v2_t, rt);
20586 switch (opc) {
20587 case NM_CMP_EQ_PH:
20588 check_dsp(ctx);
20589 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20590 break;
20591 case NM_CMP_LT_PH:
20592 check_dsp(ctx);
20593 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20594 break;
20595 case NM_CMP_LE_PH:
20596 check_dsp(ctx);
20597 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20598 break;
20599 case NM_CMPU_EQ_QB:
20600 check_dsp(ctx);
20601 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20602 break;
20603 case NM_CMPU_LT_QB:
20604 check_dsp(ctx);
20605 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20606 break;
20607 case NM_CMPU_LE_QB:
20608 check_dsp(ctx);
20609 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20610 break;
20611 case NM_CMPGU_EQ_QB:
20612 check_dsp(ctx);
20613 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20614 gen_store_gpr(v1_t, ret);
20615 break;
20616 case NM_CMPGU_LT_QB:
20617 check_dsp(ctx);
20618 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20619 gen_store_gpr(v1_t, ret);
20620 break;
20621 case NM_CMPGU_LE_QB:
20622 check_dsp(ctx);
20623 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20624 gen_store_gpr(v1_t, ret);
20625 break;
20626 case NM_CMPGDU_EQ_QB:
20627 check_dsp_r2(ctx);
20628 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20629 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20630 gen_store_gpr(v1_t, ret);
20631 break;
20632 case NM_CMPGDU_LT_QB:
20633 check_dsp_r2(ctx);
20634 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20635 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20636 gen_store_gpr(v1_t, ret);
20637 break;
20638 case NM_CMPGDU_LE_QB:
20639 check_dsp_r2(ctx);
20640 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20641 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20642 gen_store_gpr(v1_t, ret);
20643 break;
20644 case NM_PACKRL_PH:
20645 check_dsp(ctx);
20646 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20647 gen_store_gpr(v1_t, ret);
20648 break;
20649 case NM_PICK_QB:
20650 check_dsp(ctx);
20651 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20652 gen_store_gpr(v1_t, ret);
20653 break;
20654 case NM_PICK_PH:
20655 check_dsp(ctx);
20656 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20657 gen_store_gpr(v1_t, ret);
20658 break;
20659 case NM_ADDQ_S_W:
20660 check_dsp(ctx);
20661 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20662 gen_store_gpr(v1_t, ret);
20663 break;
20664 case NM_SUBQ_S_W:
20665 check_dsp(ctx);
20666 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20667 gen_store_gpr(v1_t, ret);
20668 break;
20669 case NM_ADDSC:
20670 check_dsp(ctx);
20671 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20672 gen_store_gpr(v1_t, ret);
20673 break;
20674 case NM_ADDWC:
20675 check_dsp(ctx);
20676 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20677 gen_store_gpr(v1_t, ret);
20678 break;
20679 case NM_ADDQ_S_PH:
20680 check_dsp(ctx);
20681 switch (extract32(ctx->opcode, 10, 1)) {
20682 case 0:
20683 /* ADDQ_PH */
20684 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20685 gen_store_gpr(v1_t, ret);
20686 break;
20687 case 1:
20688 /* ADDQ_S_PH */
20689 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20690 gen_store_gpr(v1_t, ret);
20691 break;
20693 break;
20694 case NM_ADDQH_R_PH:
20695 check_dsp_r2(ctx);
20696 switch (extract32(ctx->opcode, 10, 1)) {
20697 case 0:
20698 /* ADDQH_PH */
20699 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20700 gen_store_gpr(v1_t, ret);
20701 break;
20702 case 1:
20703 /* ADDQH_R_PH */
20704 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20705 gen_store_gpr(v1_t, ret);
20706 break;
20708 break;
20709 case NM_ADDQH_R_W:
20710 check_dsp_r2(ctx);
20711 switch (extract32(ctx->opcode, 10, 1)) {
20712 case 0:
20713 /* ADDQH_W */
20714 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20715 gen_store_gpr(v1_t, ret);
20716 break;
20717 case 1:
20718 /* ADDQH_R_W */
20719 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20720 gen_store_gpr(v1_t, ret);
20721 break;
20723 break;
20724 case NM_ADDU_S_QB:
20725 check_dsp(ctx);
20726 switch (extract32(ctx->opcode, 10, 1)) {
20727 case 0:
20728 /* ADDU_QB */
20729 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20730 gen_store_gpr(v1_t, ret);
20731 break;
20732 case 1:
20733 /* ADDU_S_QB */
20734 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20735 gen_store_gpr(v1_t, ret);
20736 break;
20738 break;
20739 case NM_ADDU_S_PH:
20740 check_dsp_r2(ctx);
20741 switch (extract32(ctx->opcode, 10, 1)) {
20742 case 0:
20743 /* ADDU_PH */
20744 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20745 gen_store_gpr(v1_t, ret);
20746 break;
20747 case 1:
20748 /* ADDU_S_PH */
20749 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20750 gen_store_gpr(v1_t, ret);
20751 break;
20753 break;
20754 case NM_ADDUH_R_QB:
20755 check_dsp_r2(ctx);
20756 switch (extract32(ctx->opcode, 10, 1)) {
20757 case 0:
20758 /* ADDUH_QB */
20759 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20760 gen_store_gpr(v1_t, ret);
20761 break;
20762 case 1:
20763 /* ADDUH_R_QB */
20764 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20765 gen_store_gpr(v1_t, ret);
20766 break;
20768 break;
20769 case NM_SHRAV_R_PH:
20770 check_dsp(ctx);
20771 switch (extract32(ctx->opcode, 10, 1)) {
20772 case 0:
20773 /* SHRAV_PH */
20774 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20775 gen_store_gpr(v1_t, ret);
20776 break;
20777 case 1:
20778 /* SHRAV_R_PH */
20779 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20780 gen_store_gpr(v1_t, ret);
20781 break;
20783 break;
20784 case NM_SHRAV_R_QB:
20785 check_dsp_r2(ctx);
20786 switch (extract32(ctx->opcode, 10, 1)) {
20787 case 0:
20788 /* SHRAV_QB */
20789 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20790 gen_store_gpr(v1_t, ret);
20791 break;
20792 case 1:
20793 /* SHRAV_R_QB */
20794 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20795 gen_store_gpr(v1_t, ret);
20796 break;
20798 break;
20799 case NM_SUBQ_S_PH:
20800 check_dsp(ctx);
20801 switch (extract32(ctx->opcode, 10, 1)) {
20802 case 0:
20803 /* SUBQ_PH */
20804 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20805 gen_store_gpr(v1_t, ret);
20806 break;
20807 case 1:
20808 /* SUBQ_S_PH */
20809 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20810 gen_store_gpr(v1_t, ret);
20811 break;
20813 break;
20814 case NM_SUBQH_R_PH:
20815 check_dsp_r2(ctx);
20816 switch (extract32(ctx->opcode, 10, 1)) {
20817 case 0:
20818 /* SUBQH_PH */
20819 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20820 gen_store_gpr(v1_t, ret);
20821 break;
20822 case 1:
20823 /* SUBQH_R_PH */
20824 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20825 gen_store_gpr(v1_t, ret);
20826 break;
20828 break;
20829 case NM_SUBQH_R_W:
20830 check_dsp_r2(ctx);
20831 switch (extract32(ctx->opcode, 10, 1)) {
20832 case 0:
20833 /* SUBQH_W */
20834 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20835 gen_store_gpr(v1_t, ret);
20836 break;
20837 case 1:
20838 /* SUBQH_R_W */
20839 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20840 gen_store_gpr(v1_t, ret);
20841 break;
20843 break;
20844 case NM_SUBU_S_QB:
20845 check_dsp(ctx);
20846 switch (extract32(ctx->opcode, 10, 1)) {
20847 case 0:
20848 /* SUBU_QB */
20849 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20850 gen_store_gpr(v1_t, ret);
20851 break;
20852 case 1:
20853 /* SUBU_S_QB */
20854 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20855 gen_store_gpr(v1_t, ret);
20856 break;
20858 break;
20859 case NM_SUBU_S_PH:
20860 check_dsp_r2(ctx);
20861 switch (extract32(ctx->opcode, 10, 1)) {
20862 case 0:
20863 /* SUBU_PH */
20864 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20865 gen_store_gpr(v1_t, ret);
20866 break;
20867 case 1:
20868 /* SUBU_S_PH */
20869 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20870 gen_store_gpr(v1_t, ret);
20871 break;
20873 break;
20874 case NM_SUBUH_R_QB:
20875 check_dsp_r2(ctx);
20876 switch (extract32(ctx->opcode, 10, 1)) {
20877 case 0:
20878 /* SUBUH_QB */
20879 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20880 gen_store_gpr(v1_t, ret);
20881 break;
20882 case 1:
20883 /* SUBUH_R_QB */
20884 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20885 gen_store_gpr(v1_t, ret);
20886 break;
20888 break;
20889 case NM_SHLLV_S_PH:
20890 check_dsp(ctx);
20891 switch (extract32(ctx->opcode, 10, 1)) {
20892 case 0:
20893 /* SHLLV_PH */
20894 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20895 gen_store_gpr(v1_t, ret);
20896 break;
20897 case 1:
20898 /* SHLLV_S_PH */
20899 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20900 gen_store_gpr(v1_t, ret);
20901 break;
20903 break;
20904 case NM_PRECR_SRA_R_PH_W:
20905 check_dsp_r2(ctx);
20906 switch (extract32(ctx->opcode, 10, 1)) {
20907 case 0:
20908 /* PRECR_SRA_PH_W */
20910 TCGv_i32 sa_t = tcg_const_i32(rd);
20911 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20912 cpu_gpr[rt]);
20913 gen_store_gpr(v1_t, rt);
20914 tcg_temp_free_i32(sa_t);
20916 break;
20917 case 1:
20918 /* PRECR_SRA_R_PH_W */
20920 TCGv_i32 sa_t = tcg_const_i32(rd);
20921 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20922 cpu_gpr[rt]);
20923 gen_store_gpr(v1_t, rt);
20924 tcg_temp_free_i32(sa_t);
20926 break;
20928 break;
20929 case NM_MULEU_S_PH_QBL:
20930 check_dsp(ctx);
20931 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20932 gen_store_gpr(v1_t, ret);
20933 break;
20934 case NM_MULEU_S_PH_QBR:
20935 check_dsp(ctx);
20936 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20937 gen_store_gpr(v1_t, ret);
20938 break;
20939 case NM_MULQ_RS_PH:
20940 check_dsp(ctx);
20941 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20942 gen_store_gpr(v1_t, ret);
20943 break;
20944 case NM_MULQ_S_PH:
20945 check_dsp_r2(ctx);
20946 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20947 gen_store_gpr(v1_t, ret);
20948 break;
20949 case NM_MULQ_RS_W:
20950 check_dsp_r2(ctx);
20951 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20952 gen_store_gpr(v1_t, ret);
20953 break;
20954 case NM_MULQ_S_W:
20955 check_dsp_r2(ctx);
20956 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20957 gen_store_gpr(v1_t, ret);
20958 break;
20959 case NM_APPEND:
20960 check_dsp_r2(ctx);
20961 gen_load_gpr(t0, rs);
20962 if (rd != 0) {
20963 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20965 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20966 break;
20967 case NM_MODSUB:
20968 check_dsp(ctx);
20969 gen_helper_modsub(v1_t, v1_t, v2_t);
20970 gen_store_gpr(v1_t, ret);
20971 break;
20972 case NM_SHRAV_R_W:
20973 check_dsp(ctx);
20974 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20975 gen_store_gpr(v1_t, ret);
20976 break;
20977 case NM_SHRLV_PH:
20978 check_dsp_r2(ctx);
20979 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20980 gen_store_gpr(v1_t, ret);
20981 break;
20982 case NM_SHRLV_QB:
20983 check_dsp(ctx);
20984 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20985 gen_store_gpr(v1_t, ret);
20986 break;
20987 case NM_SHLLV_QB:
20988 check_dsp(ctx);
20989 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20990 gen_store_gpr(v1_t, ret);
20991 break;
20992 case NM_SHLLV_S_W:
20993 check_dsp(ctx);
20994 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20995 gen_store_gpr(v1_t, ret);
20996 break;
20997 case NM_SHILO:
20998 check_dsp(ctx);
21000 TCGv tv0 = tcg_temp_new();
21001 TCGv tv1 = tcg_temp_new();
21002 int16_t imm = extract32(ctx->opcode, 16, 7);
21004 tcg_gen_movi_tl(tv0, rd >> 3);
21005 tcg_gen_movi_tl(tv1, imm);
21006 gen_helper_shilo(tv0, tv1, cpu_env);
21008 break;
21009 case NM_MULEQ_S_W_PHL:
21010 check_dsp(ctx);
21011 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21012 gen_store_gpr(v1_t, ret);
21013 break;
21014 case NM_MULEQ_S_W_PHR:
21015 check_dsp(ctx);
21016 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21017 gen_store_gpr(v1_t, ret);
21018 break;
21019 case NM_MUL_S_PH:
21020 check_dsp_r2(ctx);
21021 switch (extract32(ctx->opcode, 10, 1)) {
21022 case 0:
21023 /* MUL_PH */
21024 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21025 gen_store_gpr(v1_t, ret);
21026 break;
21027 case 1:
21028 /* MUL_S_PH */
21029 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21030 gen_store_gpr(v1_t, ret);
21031 break;
21033 break;
21034 case NM_PRECR_QB_PH:
21035 check_dsp_r2(ctx);
21036 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21037 gen_store_gpr(v1_t, ret);
21038 break;
21039 case NM_PRECRQ_QB_PH:
21040 check_dsp(ctx);
21041 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21042 gen_store_gpr(v1_t, ret);
21043 break;
21044 case NM_PRECRQ_PH_W:
21045 check_dsp(ctx);
21046 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21047 gen_store_gpr(v1_t, ret);
21048 break;
21049 case NM_PRECRQ_RS_PH_W:
21050 check_dsp(ctx);
21051 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21052 gen_store_gpr(v1_t, ret);
21053 break;
21054 case NM_PRECRQU_S_QB_PH:
21055 check_dsp(ctx);
21056 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21057 gen_store_gpr(v1_t, ret);
21058 break;
21059 case NM_SHRA_R_W:
21060 check_dsp(ctx);
21061 tcg_gen_movi_tl(t0, rd);
21062 gen_helper_shra_r_w(v1_t, t0, v1_t);
21063 gen_store_gpr(v1_t, rt);
21064 break;
21065 case NM_SHRA_R_PH:
21066 check_dsp(ctx);
21067 tcg_gen_movi_tl(t0, rd >> 1);
21068 switch (extract32(ctx->opcode, 10, 1)) {
21069 case 0:
21070 /* SHRA_PH */
21071 gen_helper_shra_ph(v1_t, t0, v1_t);
21072 gen_store_gpr(v1_t, rt);
21073 break;
21074 case 1:
21075 /* SHRA_R_PH */
21076 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21077 gen_store_gpr(v1_t, rt);
21078 break;
21080 break;
21081 case NM_SHLL_S_PH:
21082 check_dsp(ctx);
21083 tcg_gen_movi_tl(t0, rd >> 1);
21084 switch (extract32(ctx->opcode, 10, 2)) {
21085 case 0:
21086 /* SHLL_PH */
21087 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21088 gen_store_gpr(v1_t, rt);
21089 break;
21090 case 2:
21091 /* SHLL_S_PH */
21092 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21093 gen_store_gpr(v1_t, rt);
21094 break;
21095 default:
21096 gen_reserved_instruction(ctx);
21097 break;
21099 break;
21100 case NM_SHLL_S_W:
21101 check_dsp(ctx);
21102 tcg_gen_movi_tl(t0, rd);
21103 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21104 gen_store_gpr(v1_t, rt);
21105 break;
21106 case NM_REPL_PH:
21107 check_dsp(ctx);
21109 int16_t imm;
21110 imm = sextract32(ctx->opcode, 11, 11);
21111 imm = (int16_t)(imm << 6) >> 6;
21112 if (rt != 0) {
21113 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21116 break;
21117 default:
21118 gen_reserved_instruction(ctx);
21119 break;
21123 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21125 uint16_t insn;
21126 uint32_t op;
21127 int rt, rs, rd;
21128 int offset;
21129 int imm;
21131 insn = translator_lduw(env, ctx->base.pc_next + 2);
21132 ctx->opcode = (ctx->opcode << 16) | insn;
21134 rt = extract32(ctx->opcode, 21, 5);
21135 rs = extract32(ctx->opcode, 16, 5);
21136 rd = extract32(ctx->opcode, 11, 5);
21138 op = extract32(ctx->opcode, 26, 6);
21139 switch (op) {
21140 case NM_P_ADDIU:
21141 if (rt == 0) {
21142 /* P.RI */
21143 switch (extract32(ctx->opcode, 19, 2)) {
21144 case NM_SIGRIE:
21145 default:
21146 gen_reserved_instruction(ctx);
21147 break;
21148 case NM_P_SYSCALL:
21149 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21150 generate_exception_end(ctx, EXCP_SYSCALL);
21151 } else {
21152 gen_reserved_instruction(ctx);
21154 break;
21155 case NM_BREAK:
21156 generate_exception_end(ctx, EXCP_BREAK);
21157 break;
21158 case NM_SDBBP:
21159 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21160 gen_helper_do_semihosting(cpu_env);
21161 } else {
21162 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21163 gen_reserved_instruction(ctx);
21164 } else {
21165 generate_exception_end(ctx, EXCP_DBp);
21168 break;
21170 } else {
21171 /* NM_ADDIU */
21172 imm = extract32(ctx->opcode, 0, 16);
21173 if (rs != 0) {
21174 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21175 } else {
21176 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21178 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21180 break;
21181 case NM_ADDIUPC:
21182 if (rt != 0) {
21183 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21184 extract32(ctx->opcode, 1, 20) << 1;
21185 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21186 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21188 break;
21189 case NM_POOL32A:
21190 switch (ctx->opcode & 0x07) {
21191 case NM_POOL32A0:
21192 gen_pool32a0_nanomips_insn(env, ctx);
21193 break;
21194 case NM_POOL32A5:
21196 int32_t op1 = extract32(ctx->opcode, 3, 7);
21197 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21199 break;
21200 case NM_POOL32A7:
21201 switch (extract32(ctx->opcode, 3, 3)) {
21202 case NM_P_LSX:
21203 gen_p_lsx(ctx, rd, rs, rt);
21204 break;
21205 case NM_LSA:
21207 * In nanoMIPS, the shift field directly encodes the shift
21208 * amount, meaning that the supported shift values are in
21209 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21211 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2) - 1);
21212 break;
21213 case NM_EXTW:
21214 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21215 break;
21216 case NM_POOL32AXF:
21217 gen_pool32axf_nanomips_insn(env, ctx);
21218 break;
21219 default:
21220 gen_reserved_instruction(ctx);
21221 break;
21223 break;
21224 default:
21225 gen_reserved_instruction(ctx);
21226 break;
21228 break;
21229 case NM_P_GP_W:
21230 switch (ctx->opcode & 0x03) {
21231 case NM_ADDIUGP_W:
21232 if (rt != 0) {
21233 offset = extract32(ctx->opcode, 0, 21);
21234 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21236 break;
21237 case NM_LWGP:
21238 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21239 break;
21240 case NM_SWGP:
21241 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21242 break;
21243 default:
21244 gen_reserved_instruction(ctx);
21245 break;
21247 break;
21248 case NM_P48I:
21250 insn = translator_lduw(env, ctx->base.pc_next + 4);
21251 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21252 switch (extract32(ctx->opcode, 16, 5)) {
21253 case NM_LI48:
21254 check_nms(ctx);
21255 if (rt != 0) {
21256 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21258 break;
21259 case NM_ADDIU48:
21260 check_nms(ctx);
21261 if (rt != 0) {
21262 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21263 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21265 break;
21266 case NM_ADDIUGP48:
21267 check_nms(ctx);
21268 if (rt != 0) {
21269 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21271 break;
21272 case NM_ADDIUPC48:
21273 check_nms(ctx);
21274 if (rt != 0) {
21275 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21276 addr_off);
21278 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21280 break;
21281 case NM_LWPC48:
21282 check_nms(ctx);
21283 if (rt != 0) {
21284 TCGv t0;
21285 t0 = tcg_temp_new();
21287 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21288 addr_off);
21290 tcg_gen_movi_tl(t0, addr);
21291 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21292 tcg_temp_free(t0);
21294 break;
21295 case NM_SWPC48:
21296 check_nms(ctx);
21298 TCGv t0, t1;
21299 t0 = tcg_temp_new();
21300 t1 = tcg_temp_new();
21302 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21303 addr_off);
21305 tcg_gen_movi_tl(t0, addr);
21306 gen_load_gpr(t1, rt);
21308 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21310 tcg_temp_free(t0);
21311 tcg_temp_free(t1);
21313 break;
21314 default:
21315 gen_reserved_instruction(ctx);
21316 break;
21318 return 6;
21320 case NM_P_U12:
21321 switch (extract32(ctx->opcode, 12, 4)) {
21322 case NM_ORI:
21323 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21324 break;
21325 case NM_XORI:
21326 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21327 break;
21328 case NM_ANDI:
21329 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21330 break;
21331 case NM_P_SR:
21332 switch (extract32(ctx->opcode, 20, 1)) {
21333 case NM_PP_SR:
21334 switch (ctx->opcode & 3) {
21335 case NM_SAVE:
21336 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21337 extract32(ctx->opcode, 2, 1),
21338 extract32(ctx->opcode, 3, 9) << 3);
21339 break;
21340 case NM_RESTORE:
21341 case NM_RESTORE_JRC:
21342 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21343 extract32(ctx->opcode, 2, 1),
21344 extract32(ctx->opcode, 3, 9) << 3);
21345 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21346 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21348 break;
21349 default:
21350 gen_reserved_instruction(ctx);
21351 break;
21353 break;
21354 case NM_P_SR_F:
21355 gen_reserved_instruction(ctx);
21356 break;
21358 break;
21359 case NM_SLTI:
21360 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21361 break;
21362 case NM_SLTIU:
21363 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21364 break;
21365 case NM_SEQI:
21367 TCGv t0 = tcg_temp_new();
21369 imm = extract32(ctx->opcode, 0, 12);
21370 gen_load_gpr(t0, rs);
21371 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21372 gen_store_gpr(t0, rt);
21374 tcg_temp_free(t0);
21376 break;
21377 case NM_ADDIUNEG:
21378 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21379 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21380 break;
21381 case NM_P_SHIFT:
21383 int shift = extract32(ctx->opcode, 0, 5);
21384 switch (extract32(ctx->opcode, 5, 4)) {
21385 case NM_P_SLL:
21386 if (rt == 0 && shift == 0) {
21387 /* NOP */
21388 } else if (rt == 0 && shift == 3) {
21389 /* EHB - treat as NOP */
21390 } else if (rt == 0 && shift == 5) {
21391 /* PAUSE - treat as NOP */
21392 } else if (rt == 0 && shift == 6) {
21393 /* SYNC */
21394 gen_sync(extract32(ctx->opcode, 16, 5));
21395 } else {
21396 /* SLL */
21397 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21398 extract32(ctx->opcode, 0, 5));
21400 break;
21401 case NM_SRL:
21402 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21403 extract32(ctx->opcode, 0, 5));
21404 break;
21405 case NM_SRA:
21406 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21407 extract32(ctx->opcode, 0, 5));
21408 break;
21409 case NM_ROTR:
21410 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21411 extract32(ctx->opcode, 0, 5));
21412 break;
21415 break;
21416 case NM_P_ROTX:
21417 check_nms(ctx);
21418 if (rt != 0) {
21419 TCGv t0 = tcg_temp_new();
21420 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21421 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21422 << 1);
21423 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21425 gen_load_gpr(t0, rs);
21426 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21427 tcg_temp_free(t0);
21429 tcg_temp_free_i32(shift);
21430 tcg_temp_free_i32(shiftx);
21431 tcg_temp_free_i32(stripe);
21433 break;
21434 case NM_P_INS:
21435 switch (((ctx->opcode >> 10) & 2) |
21436 (extract32(ctx->opcode, 5, 1))) {
21437 case NM_INS:
21438 check_nms(ctx);
21439 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21440 extract32(ctx->opcode, 6, 5));
21441 break;
21442 default:
21443 gen_reserved_instruction(ctx);
21444 break;
21446 break;
21447 case NM_P_EXT:
21448 switch (((ctx->opcode >> 10) & 2) |
21449 (extract32(ctx->opcode, 5, 1))) {
21450 case NM_EXT:
21451 check_nms(ctx);
21452 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21453 extract32(ctx->opcode, 6, 5));
21454 break;
21455 default:
21456 gen_reserved_instruction(ctx);
21457 break;
21459 break;
21460 default:
21461 gen_reserved_instruction(ctx);
21462 break;
21464 break;
21465 case NM_POOL32F:
21466 gen_pool32f_nanomips_insn(ctx);
21467 break;
21468 case NM_POOL32S:
21469 break;
21470 case NM_P_LUI:
21471 switch (extract32(ctx->opcode, 1, 1)) {
21472 case NM_LUI:
21473 if (rt != 0) {
21474 tcg_gen_movi_tl(cpu_gpr[rt],
21475 sextract32(ctx->opcode, 0, 1) << 31 |
21476 extract32(ctx->opcode, 2, 10) << 21 |
21477 extract32(ctx->opcode, 12, 9) << 12);
21479 break;
21480 case NM_ALUIPC:
21481 if (rt != 0) {
21482 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21483 extract32(ctx->opcode, 2, 10) << 21 |
21484 extract32(ctx->opcode, 12, 9) << 12;
21485 target_long addr;
21486 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21487 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21489 break;
21491 break;
21492 case NM_P_GP_BH:
21494 uint32_t u = extract32(ctx->opcode, 0, 18);
21496 switch (extract32(ctx->opcode, 18, 3)) {
21497 case NM_LBGP:
21498 gen_ld(ctx, OPC_LB, rt, 28, u);
21499 break;
21500 case NM_SBGP:
21501 gen_st(ctx, OPC_SB, rt, 28, u);
21502 break;
21503 case NM_LBUGP:
21504 gen_ld(ctx, OPC_LBU, rt, 28, u);
21505 break;
21506 case NM_ADDIUGP_B:
21507 if (rt != 0) {
21508 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21510 break;
21511 case NM_P_GP_LH:
21512 u &= ~1;
21513 switch (ctx->opcode & 1) {
21514 case NM_LHGP:
21515 gen_ld(ctx, OPC_LH, rt, 28, u);
21516 break;
21517 case NM_LHUGP:
21518 gen_ld(ctx, OPC_LHU, rt, 28, u);
21519 break;
21521 break;
21522 case NM_P_GP_SH:
21523 u &= ~1;
21524 switch (ctx->opcode & 1) {
21525 case NM_SHGP:
21526 gen_st(ctx, OPC_SH, rt, 28, u);
21527 break;
21528 default:
21529 gen_reserved_instruction(ctx);
21530 break;
21532 break;
21533 case NM_P_GP_CP1:
21534 u &= ~0x3;
21535 switch (ctx->opcode & 0x3) {
21536 case NM_LWC1GP:
21537 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21538 break;
21539 case NM_LDC1GP:
21540 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21541 break;
21542 case NM_SWC1GP:
21543 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21544 break;
21545 case NM_SDC1GP:
21546 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21547 break;
21549 break;
21550 default:
21551 gen_reserved_instruction(ctx);
21552 break;
21555 break;
21556 case NM_P_LS_U12:
21558 uint32_t u = extract32(ctx->opcode, 0, 12);
21560 switch (extract32(ctx->opcode, 12, 4)) {
21561 case NM_P_PREFU12:
21562 if (rt == 31) {
21563 /* SYNCI */
21565 * Break the TB to be able to sync copied instructions
21566 * immediately.
21568 ctx->base.is_jmp = DISAS_STOP;
21569 } else {
21570 /* PREF */
21571 /* Treat as NOP. */
21573 break;
21574 case NM_LB:
21575 gen_ld(ctx, OPC_LB, rt, rs, u);
21576 break;
21577 case NM_LH:
21578 gen_ld(ctx, OPC_LH, rt, rs, u);
21579 break;
21580 case NM_LW:
21581 gen_ld(ctx, OPC_LW, rt, rs, u);
21582 break;
21583 case NM_LBU:
21584 gen_ld(ctx, OPC_LBU, rt, rs, u);
21585 break;
21586 case NM_LHU:
21587 gen_ld(ctx, OPC_LHU, rt, rs, u);
21588 break;
21589 case NM_SB:
21590 gen_st(ctx, OPC_SB, rt, rs, u);
21591 break;
21592 case NM_SH:
21593 gen_st(ctx, OPC_SH, rt, rs, u);
21594 break;
21595 case NM_SW:
21596 gen_st(ctx, OPC_SW, rt, rs, u);
21597 break;
21598 case NM_LWC1:
21599 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21600 break;
21601 case NM_LDC1:
21602 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21603 break;
21604 case NM_SWC1:
21605 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21606 break;
21607 case NM_SDC1:
21608 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21609 break;
21610 default:
21611 gen_reserved_instruction(ctx);
21612 break;
21615 break;
21616 case NM_P_LS_S9:
21618 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21619 extract32(ctx->opcode, 0, 8);
21621 switch (extract32(ctx->opcode, 8, 3)) {
21622 case NM_P_LS_S0:
21623 switch (extract32(ctx->opcode, 11, 4)) {
21624 case NM_LBS9:
21625 gen_ld(ctx, OPC_LB, rt, rs, s);
21626 break;
21627 case NM_LHS9:
21628 gen_ld(ctx, OPC_LH, rt, rs, s);
21629 break;
21630 case NM_LWS9:
21631 gen_ld(ctx, OPC_LW, rt, rs, s);
21632 break;
21633 case NM_LBUS9:
21634 gen_ld(ctx, OPC_LBU, rt, rs, s);
21635 break;
21636 case NM_LHUS9:
21637 gen_ld(ctx, OPC_LHU, rt, rs, s);
21638 break;
21639 case NM_SBS9:
21640 gen_st(ctx, OPC_SB, rt, rs, s);
21641 break;
21642 case NM_SHS9:
21643 gen_st(ctx, OPC_SH, rt, rs, s);
21644 break;
21645 case NM_SWS9:
21646 gen_st(ctx, OPC_SW, rt, rs, s);
21647 break;
21648 case NM_LWC1S9:
21649 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21650 break;
21651 case NM_LDC1S9:
21652 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21653 break;
21654 case NM_SWC1S9:
21655 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21656 break;
21657 case NM_SDC1S9:
21658 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21659 break;
21660 case NM_P_PREFS9:
21661 if (rt == 31) {
21662 /* SYNCI */
21664 * Break the TB to be able to sync copied instructions
21665 * immediately.
21667 ctx->base.is_jmp = DISAS_STOP;
21668 } else {
21669 /* PREF */
21670 /* Treat as NOP. */
21672 break;
21673 default:
21674 gen_reserved_instruction(ctx);
21675 break;
21677 break;
21678 case NM_P_LS_S1:
21679 switch (extract32(ctx->opcode, 11, 4)) {
21680 case NM_UALH:
21681 case NM_UASH:
21682 check_nms(ctx);
21684 TCGv t0 = tcg_temp_new();
21685 TCGv t1 = tcg_temp_new();
21687 gen_base_offset_addr(ctx, t0, rs, s);
21689 switch (extract32(ctx->opcode, 11, 4)) {
21690 case NM_UALH:
21691 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21692 MO_UNALN);
21693 gen_store_gpr(t0, rt);
21694 break;
21695 case NM_UASH:
21696 gen_load_gpr(t1, rt);
21697 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21698 MO_UNALN);
21699 break;
21701 tcg_temp_free(t0);
21702 tcg_temp_free(t1);
21704 break;
21705 case NM_P_LL:
21706 switch (ctx->opcode & 0x03) {
21707 case NM_LL:
21708 gen_ld(ctx, OPC_LL, rt, rs, s);
21709 break;
21710 case NM_LLWP:
21711 check_xnp(ctx);
21712 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21713 break;
21715 break;
21716 case NM_P_SC:
21717 switch (ctx->opcode & 0x03) {
21718 case NM_SC:
21719 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21720 break;
21721 case NM_SCWP:
21722 check_xnp(ctx);
21723 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21724 false);
21725 break;
21727 break;
21728 case NM_CACHE:
21729 check_cp0_enabled(ctx);
21730 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21731 gen_cache_operation(ctx, rt, rs, s);
21733 break;
21735 break;
21736 case NM_P_LS_E0:
21737 switch (extract32(ctx->opcode, 11, 4)) {
21738 case NM_LBE:
21739 check_eva(ctx);
21740 check_cp0_enabled(ctx);
21741 gen_ld(ctx, OPC_LBE, rt, rs, s);
21742 break;
21743 case NM_SBE:
21744 check_eva(ctx);
21745 check_cp0_enabled(ctx);
21746 gen_st(ctx, OPC_SBE, rt, rs, s);
21747 break;
21748 case NM_LBUE:
21749 check_eva(ctx);
21750 check_cp0_enabled(ctx);
21751 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21752 break;
21753 case NM_P_PREFE:
21754 if (rt == 31) {
21755 /* case NM_SYNCIE */
21756 check_eva(ctx);
21757 check_cp0_enabled(ctx);
21759 * Break the TB to be able to sync copied instructions
21760 * immediately.
21762 ctx->base.is_jmp = DISAS_STOP;
21763 } else {
21764 /* case NM_PREFE */
21765 check_eva(ctx);
21766 check_cp0_enabled(ctx);
21767 /* Treat as NOP. */
21769 break;
21770 case NM_LHE:
21771 check_eva(ctx);
21772 check_cp0_enabled(ctx);
21773 gen_ld(ctx, OPC_LHE, rt, rs, s);
21774 break;
21775 case NM_SHE:
21776 check_eva(ctx);
21777 check_cp0_enabled(ctx);
21778 gen_st(ctx, OPC_SHE, rt, rs, s);
21779 break;
21780 case NM_LHUE:
21781 check_eva(ctx);
21782 check_cp0_enabled(ctx);
21783 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21784 break;
21785 case NM_CACHEE:
21786 check_nms_dl_il_sl_tl_l2c(ctx);
21787 gen_cache_operation(ctx, rt, rs, s);
21788 break;
21789 case NM_LWE:
21790 check_eva(ctx);
21791 check_cp0_enabled(ctx);
21792 gen_ld(ctx, OPC_LWE, rt, rs, s);
21793 break;
21794 case NM_SWE:
21795 check_eva(ctx);
21796 check_cp0_enabled(ctx);
21797 gen_st(ctx, OPC_SWE, rt, rs, s);
21798 break;
21799 case NM_P_LLE:
21800 switch (extract32(ctx->opcode, 2, 2)) {
21801 case NM_LLE:
21802 check_xnp(ctx);
21803 check_eva(ctx);
21804 check_cp0_enabled(ctx);
21805 gen_ld(ctx, OPC_LLE, rt, rs, s);
21806 break;
21807 case NM_LLWPE:
21808 check_xnp(ctx);
21809 check_eva(ctx);
21810 check_cp0_enabled(ctx);
21811 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21812 break;
21813 default:
21814 gen_reserved_instruction(ctx);
21815 break;
21817 break;
21818 case NM_P_SCE:
21819 switch (extract32(ctx->opcode, 2, 2)) {
21820 case NM_SCE:
21821 check_xnp(ctx);
21822 check_eva(ctx);
21823 check_cp0_enabled(ctx);
21824 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
21825 break;
21826 case NM_SCWPE:
21827 check_xnp(ctx);
21828 check_eva(ctx);
21829 check_cp0_enabled(ctx);
21830 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21831 true);
21832 break;
21833 default:
21834 gen_reserved_instruction(ctx);
21835 break;
21837 break;
21839 break;
21840 case NM_P_LS_WM:
21841 case NM_P_LS_UAWM:
21842 check_nms(ctx);
21844 int count = extract32(ctx->opcode, 12, 3);
21845 int counter = 0;
21847 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21848 extract32(ctx->opcode, 0, 8);
21849 TCGv va = tcg_temp_new();
21850 TCGv t1 = tcg_temp_new();
21851 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21852 NM_P_LS_UAWM ? MO_UNALN : 0;
21854 count = (count == 0) ? 8 : count;
21855 while (counter != count) {
21856 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21857 int this_offset = offset + (counter << 2);
21859 gen_base_offset_addr(ctx, va, rs, this_offset);
21861 switch (extract32(ctx->opcode, 11, 1)) {
21862 case NM_LWM:
21863 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21864 memop | MO_TESL);
21865 gen_store_gpr(t1, this_rt);
21866 if ((this_rt == rs) &&
21867 (counter != (count - 1))) {
21868 /* UNPREDICTABLE */
21870 break;
21871 case NM_SWM:
21872 this_rt = (rt == 0) ? 0 : this_rt;
21873 gen_load_gpr(t1, this_rt);
21874 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21875 memop | MO_TEUL);
21876 break;
21878 counter++;
21880 tcg_temp_free(va);
21881 tcg_temp_free(t1);
21883 break;
21884 default:
21885 gen_reserved_instruction(ctx);
21886 break;
21889 break;
21890 case NM_MOVE_BALC:
21891 check_nms(ctx);
21893 TCGv t0 = tcg_temp_new();
21894 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21895 extract32(ctx->opcode, 1, 20) << 1;
21896 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21897 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21898 extract32(ctx->opcode, 21, 3));
21899 gen_load_gpr(t0, rt);
21900 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21901 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21902 tcg_temp_free(t0);
21904 break;
21905 case NM_P_BAL:
21907 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21908 extract32(ctx->opcode, 1, 24) << 1;
21910 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21911 /* BC */
21912 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21913 } else {
21914 /* BALC */
21915 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21918 break;
21919 case NM_P_J:
21920 switch (extract32(ctx->opcode, 12, 4)) {
21921 case NM_JALRC:
21922 case NM_JALRC_HB:
21923 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21924 break;
21925 case NM_P_BALRSC:
21926 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21927 break;
21928 default:
21929 gen_reserved_instruction(ctx);
21930 break;
21932 break;
21933 case NM_P_BR1:
21935 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21936 extract32(ctx->opcode, 1, 13) << 1;
21937 switch (extract32(ctx->opcode, 14, 2)) {
21938 case NM_BEQC:
21939 check_nms(ctx);
21940 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21941 break;
21942 case NM_P_BR3A:
21943 s = sextract32(ctx->opcode, 0, 1) << 14 |
21944 extract32(ctx->opcode, 1, 13) << 1;
21945 check_cp1_enabled(ctx);
21946 switch (extract32(ctx->opcode, 16, 5)) {
21947 case NM_BC1EQZC:
21948 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21949 break;
21950 case NM_BC1NEZC:
21951 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21952 break;
21953 case NM_BPOSGE32C:
21954 check_dsp_r3(ctx);
21956 int32_t imm = extract32(ctx->opcode, 1, 13) |
21957 extract32(ctx->opcode, 0, 1) << 13;
21959 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21960 imm);
21962 break;
21963 default:
21964 gen_reserved_instruction(ctx);
21965 break;
21967 break;
21968 case NM_BGEC:
21969 if (rs == rt) {
21970 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21971 } else {
21972 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21974 break;
21975 case NM_BGEUC:
21976 if (rs == rt || rt == 0) {
21977 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21978 } else if (rs == 0) {
21979 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21980 } else {
21981 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21983 break;
21986 break;
21987 case NM_P_BR2:
21989 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21990 extract32(ctx->opcode, 1, 13) << 1;
21991 switch (extract32(ctx->opcode, 14, 2)) {
21992 case NM_BNEC:
21993 check_nms(ctx);
21994 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21995 break;
21996 case NM_BLTC:
21997 if (rs != 0 && rt != 0 && rs == rt) {
21998 /* NOP */
21999 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22000 } else {
22001 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22003 break;
22004 case NM_BLTUC:
22005 if (rs == 0 || rs == rt) {
22006 /* NOP */
22007 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22008 } else {
22009 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22011 break;
22012 default:
22013 gen_reserved_instruction(ctx);
22014 break;
22017 break;
22018 case NM_P_BRI:
22020 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22021 extract32(ctx->opcode, 1, 10) << 1;
22022 uint32_t u = extract32(ctx->opcode, 11, 7);
22024 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22025 rt, u, s);
22027 break;
22028 default:
22029 gen_reserved_instruction(ctx);
22030 break;
22032 return 4;
22035 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22037 uint32_t op;
22038 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22039 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22040 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22041 int offset;
22042 int imm;
22044 /* make sure instructions are on a halfword boundary */
22045 if (ctx->base.pc_next & 0x1) {
22046 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22047 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22048 tcg_temp_free(tmp);
22049 generate_exception_end(ctx, EXCP_AdEL);
22050 return 2;
22053 op = extract32(ctx->opcode, 10, 6);
22054 switch (op) {
22055 case NM_P16_MV:
22056 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22057 if (rt != 0) {
22058 /* MOVE */
22059 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22060 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22061 } else {
22062 /* P16.RI */
22063 switch (extract32(ctx->opcode, 3, 2)) {
22064 case NM_P16_SYSCALL:
22065 if (extract32(ctx->opcode, 2, 1) == 0) {
22066 generate_exception_end(ctx, EXCP_SYSCALL);
22067 } else {
22068 gen_reserved_instruction(ctx);
22070 break;
22071 case NM_BREAK16:
22072 generate_exception_end(ctx, EXCP_BREAK);
22073 break;
22074 case NM_SDBBP16:
22075 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22076 gen_helper_do_semihosting(cpu_env);
22077 } else {
22078 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22079 gen_reserved_instruction(ctx);
22080 } else {
22081 generate_exception_end(ctx, EXCP_DBp);
22084 break;
22085 default:
22086 gen_reserved_instruction(ctx);
22087 break;
22090 break;
22091 case NM_P16_SHIFT:
22093 int shift = extract32(ctx->opcode, 0, 3);
22094 uint32_t opc = 0;
22095 shift = (shift == 0) ? 8 : shift;
22097 switch (extract32(ctx->opcode, 3, 1)) {
22098 case NM_SLL16:
22099 opc = OPC_SLL;
22100 break;
22101 case NM_SRL16:
22102 opc = OPC_SRL;
22103 break;
22105 gen_shift_imm(ctx, opc, rt, rs, shift);
22107 break;
22108 case NM_P16C:
22109 switch (ctx->opcode & 1) {
22110 case NM_POOL16C_0:
22111 gen_pool16c_nanomips_insn(ctx);
22112 break;
22113 case NM_LWXS16:
22114 gen_ldxs(ctx, rt, rs, rd);
22115 break;
22117 break;
22118 case NM_P16_A1:
22119 switch (extract32(ctx->opcode, 6, 1)) {
22120 case NM_ADDIUR1SP:
22121 imm = extract32(ctx->opcode, 0, 6) << 2;
22122 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22123 break;
22124 default:
22125 gen_reserved_instruction(ctx);
22126 break;
22128 break;
22129 case NM_P16_A2:
22130 switch (extract32(ctx->opcode, 3, 1)) {
22131 case NM_ADDIUR2:
22132 imm = extract32(ctx->opcode, 0, 3) << 2;
22133 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22134 break;
22135 case NM_P_ADDIURS5:
22136 rt = extract32(ctx->opcode, 5, 5);
22137 if (rt != 0) {
22138 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22139 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22140 (extract32(ctx->opcode, 0, 3));
22141 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22143 break;
22145 break;
22146 case NM_P16_ADDU:
22147 switch (ctx->opcode & 0x1) {
22148 case NM_ADDU16:
22149 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22150 break;
22151 case NM_SUBU16:
22152 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22153 break;
22155 break;
22156 case NM_P16_4X4:
22157 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22158 extract32(ctx->opcode, 5, 3);
22159 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22160 extract32(ctx->opcode, 0, 3);
22161 rt = decode_gpr_gpr4(rt);
22162 rs = decode_gpr_gpr4(rs);
22163 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22164 (extract32(ctx->opcode, 3, 1))) {
22165 case NM_ADDU4X4:
22166 check_nms(ctx);
22167 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22168 break;
22169 case NM_MUL4X4:
22170 check_nms(ctx);
22171 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22172 break;
22173 default:
22174 gen_reserved_instruction(ctx);
22175 break;
22177 break;
22178 case NM_LI16:
22180 int imm = extract32(ctx->opcode, 0, 7);
22181 imm = (imm == 0x7f ? -1 : imm);
22182 if (rt != 0) {
22183 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22186 break;
22187 case NM_ANDI16:
22189 uint32_t u = extract32(ctx->opcode, 0, 4);
22190 u = (u == 12) ? 0xff :
22191 (u == 13) ? 0xffff : u;
22192 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22194 break;
22195 case NM_P16_LB:
22196 offset = extract32(ctx->opcode, 0, 2);
22197 switch (extract32(ctx->opcode, 2, 2)) {
22198 case NM_LB16:
22199 gen_ld(ctx, OPC_LB, rt, rs, offset);
22200 break;
22201 case NM_SB16:
22202 rt = decode_gpr_gpr3_src_store(
22203 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22204 gen_st(ctx, OPC_SB, rt, rs, offset);
22205 break;
22206 case NM_LBU16:
22207 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22208 break;
22209 default:
22210 gen_reserved_instruction(ctx);
22211 break;
22213 break;
22214 case NM_P16_LH:
22215 offset = extract32(ctx->opcode, 1, 2) << 1;
22216 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22217 case NM_LH16:
22218 gen_ld(ctx, OPC_LH, rt, rs, offset);
22219 break;
22220 case NM_SH16:
22221 rt = decode_gpr_gpr3_src_store(
22222 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22223 gen_st(ctx, OPC_SH, rt, rs, offset);
22224 break;
22225 case NM_LHU16:
22226 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22227 break;
22228 default:
22229 gen_reserved_instruction(ctx);
22230 break;
22232 break;
22233 case NM_LW16:
22234 offset = extract32(ctx->opcode, 0, 4) << 2;
22235 gen_ld(ctx, OPC_LW, rt, rs, offset);
22236 break;
22237 case NM_LWSP16:
22238 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22239 offset = extract32(ctx->opcode, 0, 5) << 2;
22240 gen_ld(ctx, OPC_LW, rt, 29, offset);
22241 break;
22242 case NM_LW4X4:
22243 check_nms(ctx);
22244 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22245 extract32(ctx->opcode, 5, 3);
22246 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22247 extract32(ctx->opcode, 0, 3);
22248 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22249 (extract32(ctx->opcode, 8, 1) << 2);
22250 rt = decode_gpr_gpr4(rt);
22251 rs = decode_gpr_gpr4(rs);
22252 gen_ld(ctx, OPC_LW, rt, rs, offset);
22253 break;
22254 case NM_SW4X4:
22255 check_nms(ctx);
22256 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22257 extract32(ctx->opcode, 5, 3);
22258 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22259 extract32(ctx->opcode, 0, 3);
22260 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22261 (extract32(ctx->opcode, 8, 1) << 2);
22262 rt = decode_gpr_gpr4_zero(rt);
22263 rs = decode_gpr_gpr4(rs);
22264 gen_st(ctx, OPC_SW, rt, rs, offset);
22265 break;
22266 case NM_LWGP16:
22267 offset = extract32(ctx->opcode, 0, 7) << 2;
22268 gen_ld(ctx, OPC_LW, rt, 28, offset);
22269 break;
22270 case NM_SWSP16:
22271 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22272 offset = extract32(ctx->opcode, 0, 5) << 2;
22273 gen_st(ctx, OPC_SW, rt, 29, offset);
22274 break;
22275 case NM_SW16:
22276 rt = decode_gpr_gpr3_src_store(
22277 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22278 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22279 offset = extract32(ctx->opcode, 0, 4) << 2;
22280 gen_st(ctx, OPC_SW, rt, rs, offset);
22281 break;
22282 case NM_SWGP16:
22283 rt = decode_gpr_gpr3_src_store(
22284 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22285 offset = extract32(ctx->opcode, 0, 7) << 2;
22286 gen_st(ctx, OPC_SW, rt, 28, offset);
22287 break;
22288 case NM_BC16:
22289 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22290 (sextract32(ctx->opcode, 0, 1) << 10) |
22291 (extract32(ctx->opcode, 1, 9) << 1));
22292 break;
22293 case NM_BALC16:
22294 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22295 (sextract32(ctx->opcode, 0, 1) << 10) |
22296 (extract32(ctx->opcode, 1, 9) << 1));
22297 break;
22298 case NM_BEQZC16:
22299 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22300 (sextract32(ctx->opcode, 0, 1) << 7) |
22301 (extract32(ctx->opcode, 1, 6) << 1));
22302 break;
22303 case NM_BNEZC16:
22304 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22305 (sextract32(ctx->opcode, 0, 1) << 7) |
22306 (extract32(ctx->opcode, 1, 6) << 1));
22307 break;
22308 case NM_P16_BR:
22309 switch (ctx->opcode & 0xf) {
22310 case 0:
22311 /* P16.JRC */
22312 switch (extract32(ctx->opcode, 4, 1)) {
22313 case NM_JRC:
22314 gen_compute_branch_nm(ctx, OPC_JR, 2,
22315 extract32(ctx->opcode, 5, 5), 0, 0);
22316 break;
22317 case NM_JALRC16:
22318 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22319 extract32(ctx->opcode, 5, 5), 31, 0);
22320 break;
22322 break;
22323 default:
22325 /* P16.BRI */
22326 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22327 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22328 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22329 extract32(ctx->opcode, 0, 4) << 1);
22331 break;
22333 break;
22334 case NM_P16_SR:
22336 int count = extract32(ctx->opcode, 0, 4);
22337 int u = extract32(ctx->opcode, 4, 4) << 4;
22339 rt = 30 + extract32(ctx->opcode, 9, 1);
22340 switch (extract32(ctx->opcode, 8, 1)) {
22341 case NM_SAVE16:
22342 gen_save(ctx, rt, count, 0, u);
22343 break;
22344 case NM_RESTORE_JRC16:
22345 gen_restore(ctx, rt, count, 0, u);
22346 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22347 break;
22350 break;
22351 case NM_MOVEP:
22352 case NM_MOVEPREV:
22353 check_nms(ctx);
22355 static const int gpr2reg1[] = {4, 5, 6, 7};
22356 static const int gpr2reg2[] = {5, 6, 7, 8};
22357 int re;
22358 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22359 extract32(ctx->opcode, 8, 1);
22360 int r1 = gpr2reg1[rd2];
22361 int r2 = gpr2reg2[rd2];
22362 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22363 extract32(ctx->opcode, 0, 3);
22364 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22365 extract32(ctx->opcode, 5, 3);
22366 TCGv t0 = tcg_temp_new();
22367 TCGv t1 = tcg_temp_new();
22368 if (op == NM_MOVEP) {
22369 rd = r1;
22370 re = r2;
22371 rs = decode_gpr_gpr4_zero(r3);
22372 rt = decode_gpr_gpr4_zero(r4);
22373 } else {
22374 rd = decode_gpr_gpr4(r3);
22375 re = decode_gpr_gpr4(r4);
22376 rs = r1;
22377 rt = r2;
22379 gen_load_gpr(t0, rs);
22380 gen_load_gpr(t1, rt);
22381 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22382 tcg_gen_mov_tl(cpu_gpr[re], t1);
22383 tcg_temp_free(t0);
22384 tcg_temp_free(t1);
22386 break;
22387 default:
22388 return decode_nanomips_32_48_opc(env, ctx);
22391 return 2;
22395 /* SmartMIPS extension to MIPS32 */
22397 #if defined(TARGET_MIPS64)
22399 /* MDMX extension to MIPS64 */
22401 #endif
22403 /* MIPSDSP functions. */
22404 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22405 int rd, int base, int offset)
22407 TCGv t0;
22409 check_dsp(ctx);
22410 t0 = tcg_temp_new();
22412 if (base == 0) {
22413 gen_load_gpr(t0, offset);
22414 } else if (offset == 0) {
22415 gen_load_gpr(t0, base);
22416 } else {
22417 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22420 switch (opc) {
22421 case OPC_LBUX:
22422 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22423 gen_store_gpr(t0, rd);
22424 break;
22425 case OPC_LHX:
22426 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22427 gen_store_gpr(t0, rd);
22428 break;
22429 case OPC_LWX:
22430 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22431 gen_store_gpr(t0, rd);
22432 break;
22433 #if defined(TARGET_MIPS64)
22434 case OPC_LDX:
22435 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22436 gen_store_gpr(t0, rd);
22437 break;
22438 #endif
22440 tcg_temp_free(t0);
22443 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22444 int ret, int v1, int v2)
22446 TCGv v1_t;
22447 TCGv v2_t;
22449 if (ret == 0) {
22450 /* Treat as NOP. */
22451 return;
22454 v1_t = tcg_temp_new();
22455 v2_t = tcg_temp_new();
22457 gen_load_gpr(v1_t, v1);
22458 gen_load_gpr(v2_t, v2);
22460 switch (op1) {
22461 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22462 case OPC_MULT_G_2E:
22463 check_dsp_r2(ctx);
22464 switch (op2) {
22465 case OPC_ADDUH_QB:
22466 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22467 break;
22468 case OPC_ADDUH_R_QB:
22469 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22470 break;
22471 case OPC_ADDQH_PH:
22472 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22473 break;
22474 case OPC_ADDQH_R_PH:
22475 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22476 break;
22477 case OPC_ADDQH_W:
22478 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22479 break;
22480 case OPC_ADDQH_R_W:
22481 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22482 break;
22483 case OPC_SUBUH_QB:
22484 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22485 break;
22486 case OPC_SUBUH_R_QB:
22487 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22488 break;
22489 case OPC_SUBQH_PH:
22490 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22491 break;
22492 case OPC_SUBQH_R_PH:
22493 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22494 break;
22495 case OPC_SUBQH_W:
22496 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22497 break;
22498 case OPC_SUBQH_R_W:
22499 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22500 break;
22502 break;
22503 case OPC_ABSQ_S_PH_DSP:
22504 switch (op2) {
22505 case OPC_ABSQ_S_QB:
22506 check_dsp_r2(ctx);
22507 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22508 break;
22509 case OPC_ABSQ_S_PH:
22510 check_dsp(ctx);
22511 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22512 break;
22513 case OPC_ABSQ_S_W:
22514 check_dsp(ctx);
22515 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22516 break;
22517 case OPC_PRECEQ_W_PHL:
22518 check_dsp(ctx);
22519 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22520 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22521 break;
22522 case OPC_PRECEQ_W_PHR:
22523 check_dsp(ctx);
22524 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22525 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22526 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22527 break;
22528 case OPC_PRECEQU_PH_QBL:
22529 check_dsp(ctx);
22530 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22531 break;
22532 case OPC_PRECEQU_PH_QBR:
22533 check_dsp(ctx);
22534 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22535 break;
22536 case OPC_PRECEQU_PH_QBLA:
22537 check_dsp(ctx);
22538 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22539 break;
22540 case OPC_PRECEQU_PH_QBRA:
22541 check_dsp(ctx);
22542 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22543 break;
22544 case OPC_PRECEU_PH_QBL:
22545 check_dsp(ctx);
22546 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22547 break;
22548 case OPC_PRECEU_PH_QBR:
22549 check_dsp(ctx);
22550 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22551 break;
22552 case OPC_PRECEU_PH_QBLA:
22553 check_dsp(ctx);
22554 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22555 break;
22556 case OPC_PRECEU_PH_QBRA:
22557 check_dsp(ctx);
22558 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22559 break;
22561 break;
22562 case OPC_ADDU_QB_DSP:
22563 switch (op2) {
22564 case OPC_ADDQ_PH:
22565 check_dsp(ctx);
22566 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22567 break;
22568 case OPC_ADDQ_S_PH:
22569 check_dsp(ctx);
22570 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22571 break;
22572 case OPC_ADDQ_S_W:
22573 check_dsp(ctx);
22574 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22575 break;
22576 case OPC_ADDU_QB:
22577 check_dsp(ctx);
22578 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22579 break;
22580 case OPC_ADDU_S_QB:
22581 check_dsp(ctx);
22582 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22583 break;
22584 case OPC_ADDU_PH:
22585 check_dsp_r2(ctx);
22586 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22587 break;
22588 case OPC_ADDU_S_PH:
22589 check_dsp_r2(ctx);
22590 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22591 break;
22592 case OPC_SUBQ_PH:
22593 check_dsp(ctx);
22594 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22595 break;
22596 case OPC_SUBQ_S_PH:
22597 check_dsp(ctx);
22598 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22599 break;
22600 case OPC_SUBQ_S_W:
22601 check_dsp(ctx);
22602 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22603 break;
22604 case OPC_SUBU_QB:
22605 check_dsp(ctx);
22606 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22607 break;
22608 case OPC_SUBU_S_QB:
22609 check_dsp(ctx);
22610 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22611 break;
22612 case OPC_SUBU_PH:
22613 check_dsp_r2(ctx);
22614 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22615 break;
22616 case OPC_SUBU_S_PH:
22617 check_dsp_r2(ctx);
22618 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22619 break;
22620 case OPC_ADDSC:
22621 check_dsp(ctx);
22622 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22623 break;
22624 case OPC_ADDWC:
22625 check_dsp(ctx);
22626 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22627 break;
22628 case OPC_MODSUB:
22629 check_dsp(ctx);
22630 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22631 break;
22632 case OPC_RADDU_W_QB:
22633 check_dsp(ctx);
22634 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22635 break;
22637 break;
22638 case OPC_CMPU_EQ_QB_DSP:
22639 switch (op2) {
22640 case OPC_PRECR_QB_PH:
22641 check_dsp_r2(ctx);
22642 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22643 break;
22644 case OPC_PRECRQ_QB_PH:
22645 check_dsp(ctx);
22646 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22647 break;
22648 case OPC_PRECR_SRA_PH_W:
22649 check_dsp_r2(ctx);
22651 TCGv_i32 sa_t = tcg_const_i32(v2);
22652 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22653 cpu_gpr[ret]);
22654 tcg_temp_free_i32(sa_t);
22655 break;
22657 case OPC_PRECR_SRA_R_PH_W:
22658 check_dsp_r2(ctx);
22660 TCGv_i32 sa_t = tcg_const_i32(v2);
22661 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22662 cpu_gpr[ret]);
22663 tcg_temp_free_i32(sa_t);
22664 break;
22666 case OPC_PRECRQ_PH_W:
22667 check_dsp(ctx);
22668 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22669 break;
22670 case OPC_PRECRQ_RS_PH_W:
22671 check_dsp(ctx);
22672 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22673 break;
22674 case OPC_PRECRQU_S_QB_PH:
22675 check_dsp(ctx);
22676 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22677 break;
22679 break;
22680 #ifdef TARGET_MIPS64
22681 case OPC_ABSQ_S_QH_DSP:
22682 switch (op2) {
22683 case OPC_PRECEQ_L_PWL:
22684 check_dsp(ctx);
22685 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22686 break;
22687 case OPC_PRECEQ_L_PWR:
22688 check_dsp(ctx);
22689 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22690 break;
22691 case OPC_PRECEQ_PW_QHL:
22692 check_dsp(ctx);
22693 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22694 break;
22695 case OPC_PRECEQ_PW_QHR:
22696 check_dsp(ctx);
22697 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22698 break;
22699 case OPC_PRECEQ_PW_QHLA:
22700 check_dsp(ctx);
22701 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22702 break;
22703 case OPC_PRECEQ_PW_QHRA:
22704 check_dsp(ctx);
22705 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22706 break;
22707 case OPC_PRECEQU_QH_OBL:
22708 check_dsp(ctx);
22709 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22710 break;
22711 case OPC_PRECEQU_QH_OBR:
22712 check_dsp(ctx);
22713 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22714 break;
22715 case OPC_PRECEQU_QH_OBLA:
22716 check_dsp(ctx);
22717 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22718 break;
22719 case OPC_PRECEQU_QH_OBRA:
22720 check_dsp(ctx);
22721 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22722 break;
22723 case OPC_PRECEU_QH_OBL:
22724 check_dsp(ctx);
22725 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22726 break;
22727 case OPC_PRECEU_QH_OBR:
22728 check_dsp(ctx);
22729 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22730 break;
22731 case OPC_PRECEU_QH_OBLA:
22732 check_dsp(ctx);
22733 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22734 break;
22735 case OPC_PRECEU_QH_OBRA:
22736 check_dsp(ctx);
22737 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22738 break;
22739 case OPC_ABSQ_S_OB:
22740 check_dsp_r2(ctx);
22741 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22742 break;
22743 case OPC_ABSQ_S_PW:
22744 check_dsp(ctx);
22745 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22746 break;
22747 case OPC_ABSQ_S_QH:
22748 check_dsp(ctx);
22749 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22750 break;
22752 break;
22753 case OPC_ADDU_OB_DSP:
22754 switch (op2) {
22755 case OPC_RADDU_L_OB:
22756 check_dsp(ctx);
22757 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22758 break;
22759 case OPC_SUBQ_PW:
22760 check_dsp(ctx);
22761 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22762 break;
22763 case OPC_SUBQ_S_PW:
22764 check_dsp(ctx);
22765 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22766 break;
22767 case OPC_SUBQ_QH:
22768 check_dsp(ctx);
22769 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22770 break;
22771 case OPC_SUBQ_S_QH:
22772 check_dsp(ctx);
22773 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22774 break;
22775 case OPC_SUBU_OB:
22776 check_dsp(ctx);
22777 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22778 break;
22779 case OPC_SUBU_S_OB:
22780 check_dsp(ctx);
22781 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22782 break;
22783 case OPC_SUBU_QH:
22784 check_dsp_r2(ctx);
22785 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22786 break;
22787 case OPC_SUBU_S_QH:
22788 check_dsp_r2(ctx);
22789 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22790 break;
22791 case OPC_SUBUH_OB:
22792 check_dsp_r2(ctx);
22793 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22794 break;
22795 case OPC_SUBUH_R_OB:
22796 check_dsp_r2(ctx);
22797 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22798 break;
22799 case OPC_ADDQ_PW:
22800 check_dsp(ctx);
22801 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22802 break;
22803 case OPC_ADDQ_S_PW:
22804 check_dsp(ctx);
22805 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22806 break;
22807 case OPC_ADDQ_QH:
22808 check_dsp(ctx);
22809 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22810 break;
22811 case OPC_ADDQ_S_QH:
22812 check_dsp(ctx);
22813 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22814 break;
22815 case OPC_ADDU_OB:
22816 check_dsp(ctx);
22817 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22818 break;
22819 case OPC_ADDU_S_OB:
22820 check_dsp(ctx);
22821 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22822 break;
22823 case OPC_ADDU_QH:
22824 check_dsp_r2(ctx);
22825 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22826 break;
22827 case OPC_ADDU_S_QH:
22828 check_dsp_r2(ctx);
22829 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22830 break;
22831 case OPC_ADDUH_OB:
22832 check_dsp_r2(ctx);
22833 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22834 break;
22835 case OPC_ADDUH_R_OB:
22836 check_dsp_r2(ctx);
22837 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22838 break;
22840 break;
22841 case OPC_CMPU_EQ_OB_DSP:
22842 switch (op2) {
22843 case OPC_PRECR_OB_QH:
22844 check_dsp_r2(ctx);
22845 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22846 break;
22847 case OPC_PRECR_SRA_QH_PW:
22848 check_dsp_r2(ctx);
22850 TCGv_i32 ret_t = tcg_const_i32(ret);
22851 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22852 tcg_temp_free_i32(ret_t);
22853 break;
22855 case OPC_PRECR_SRA_R_QH_PW:
22856 check_dsp_r2(ctx);
22858 TCGv_i32 sa_v = tcg_const_i32(ret);
22859 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22860 tcg_temp_free_i32(sa_v);
22861 break;
22863 case OPC_PRECRQ_OB_QH:
22864 check_dsp(ctx);
22865 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22866 break;
22867 case OPC_PRECRQ_PW_L:
22868 check_dsp(ctx);
22869 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22870 break;
22871 case OPC_PRECRQ_QH_PW:
22872 check_dsp(ctx);
22873 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22874 break;
22875 case OPC_PRECRQ_RS_QH_PW:
22876 check_dsp(ctx);
22877 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22878 break;
22879 case OPC_PRECRQU_S_OB_QH:
22880 check_dsp(ctx);
22881 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22882 break;
22884 break;
22885 #endif
22888 tcg_temp_free(v1_t);
22889 tcg_temp_free(v2_t);
22892 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22893 int ret, int v1, int v2)
22895 uint32_t op2;
22896 TCGv t0;
22897 TCGv v1_t;
22898 TCGv v2_t;
22900 if (ret == 0) {
22901 /* Treat as NOP. */
22902 return;
22905 t0 = tcg_temp_new();
22906 v1_t = tcg_temp_new();
22907 v2_t = tcg_temp_new();
22909 tcg_gen_movi_tl(t0, v1);
22910 gen_load_gpr(v1_t, v1);
22911 gen_load_gpr(v2_t, v2);
22913 switch (opc) {
22914 case OPC_SHLL_QB_DSP:
22916 op2 = MASK_SHLL_QB(ctx->opcode);
22917 switch (op2) {
22918 case OPC_SHLL_QB:
22919 check_dsp(ctx);
22920 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22921 break;
22922 case OPC_SHLLV_QB:
22923 check_dsp(ctx);
22924 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22925 break;
22926 case OPC_SHLL_PH:
22927 check_dsp(ctx);
22928 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22929 break;
22930 case OPC_SHLLV_PH:
22931 check_dsp(ctx);
22932 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22933 break;
22934 case OPC_SHLL_S_PH:
22935 check_dsp(ctx);
22936 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22937 break;
22938 case OPC_SHLLV_S_PH:
22939 check_dsp(ctx);
22940 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22941 break;
22942 case OPC_SHLL_S_W:
22943 check_dsp(ctx);
22944 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22945 break;
22946 case OPC_SHLLV_S_W:
22947 check_dsp(ctx);
22948 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22949 break;
22950 case OPC_SHRL_QB:
22951 check_dsp(ctx);
22952 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22953 break;
22954 case OPC_SHRLV_QB:
22955 check_dsp(ctx);
22956 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22957 break;
22958 case OPC_SHRL_PH:
22959 check_dsp_r2(ctx);
22960 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22961 break;
22962 case OPC_SHRLV_PH:
22963 check_dsp_r2(ctx);
22964 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22965 break;
22966 case OPC_SHRA_QB:
22967 check_dsp_r2(ctx);
22968 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22969 break;
22970 case OPC_SHRA_R_QB:
22971 check_dsp_r2(ctx);
22972 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22973 break;
22974 case OPC_SHRAV_QB:
22975 check_dsp_r2(ctx);
22976 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22977 break;
22978 case OPC_SHRAV_R_QB:
22979 check_dsp_r2(ctx);
22980 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22981 break;
22982 case OPC_SHRA_PH:
22983 check_dsp(ctx);
22984 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22985 break;
22986 case OPC_SHRA_R_PH:
22987 check_dsp(ctx);
22988 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22989 break;
22990 case OPC_SHRAV_PH:
22991 check_dsp(ctx);
22992 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22993 break;
22994 case OPC_SHRAV_R_PH:
22995 check_dsp(ctx);
22996 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22997 break;
22998 case OPC_SHRA_R_W:
22999 check_dsp(ctx);
23000 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23001 break;
23002 case OPC_SHRAV_R_W:
23003 check_dsp(ctx);
23004 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23005 break;
23006 default: /* Invalid */
23007 MIPS_INVAL("MASK SHLL.QB");
23008 gen_reserved_instruction(ctx);
23009 break;
23011 break;
23013 #ifdef TARGET_MIPS64
23014 case OPC_SHLL_OB_DSP:
23015 op2 = MASK_SHLL_OB(ctx->opcode);
23016 switch (op2) {
23017 case OPC_SHLL_PW:
23018 check_dsp(ctx);
23019 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23020 break;
23021 case OPC_SHLLV_PW:
23022 check_dsp(ctx);
23023 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23024 break;
23025 case OPC_SHLL_S_PW:
23026 check_dsp(ctx);
23027 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23028 break;
23029 case OPC_SHLLV_S_PW:
23030 check_dsp(ctx);
23031 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23032 break;
23033 case OPC_SHLL_OB:
23034 check_dsp(ctx);
23035 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23036 break;
23037 case OPC_SHLLV_OB:
23038 check_dsp(ctx);
23039 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23040 break;
23041 case OPC_SHLL_QH:
23042 check_dsp(ctx);
23043 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23044 break;
23045 case OPC_SHLLV_QH:
23046 check_dsp(ctx);
23047 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23048 break;
23049 case OPC_SHLL_S_QH:
23050 check_dsp(ctx);
23051 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23052 break;
23053 case OPC_SHLLV_S_QH:
23054 check_dsp(ctx);
23055 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23056 break;
23057 case OPC_SHRA_OB:
23058 check_dsp_r2(ctx);
23059 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23060 break;
23061 case OPC_SHRAV_OB:
23062 check_dsp_r2(ctx);
23063 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23064 break;
23065 case OPC_SHRA_R_OB:
23066 check_dsp_r2(ctx);
23067 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23068 break;
23069 case OPC_SHRAV_R_OB:
23070 check_dsp_r2(ctx);
23071 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23072 break;
23073 case OPC_SHRA_PW:
23074 check_dsp(ctx);
23075 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23076 break;
23077 case OPC_SHRAV_PW:
23078 check_dsp(ctx);
23079 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23080 break;
23081 case OPC_SHRA_R_PW:
23082 check_dsp(ctx);
23083 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23084 break;
23085 case OPC_SHRAV_R_PW:
23086 check_dsp(ctx);
23087 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23088 break;
23089 case OPC_SHRA_QH:
23090 check_dsp(ctx);
23091 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23092 break;
23093 case OPC_SHRAV_QH:
23094 check_dsp(ctx);
23095 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23096 break;
23097 case OPC_SHRA_R_QH:
23098 check_dsp(ctx);
23099 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23100 break;
23101 case OPC_SHRAV_R_QH:
23102 check_dsp(ctx);
23103 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23104 break;
23105 case OPC_SHRL_OB:
23106 check_dsp(ctx);
23107 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23108 break;
23109 case OPC_SHRLV_OB:
23110 check_dsp(ctx);
23111 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23112 break;
23113 case OPC_SHRL_QH:
23114 check_dsp_r2(ctx);
23115 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23116 break;
23117 case OPC_SHRLV_QH:
23118 check_dsp_r2(ctx);
23119 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23120 break;
23121 default: /* Invalid */
23122 MIPS_INVAL("MASK SHLL.OB");
23123 gen_reserved_instruction(ctx);
23124 break;
23126 break;
23127 #endif
23130 tcg_temp_free(t0);
23131 tcg_temp_free(v1_t);
23132 tcg_temp_free(v2_t);
23135 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23136 int ret, int v1, int v2, int check_ret)
23138 TCGv_i32 t0;
23139 TCGv v1_t;
23140 TCGv v2_t;
23142 if ((ret == 0) && (check_ret == 1)) {
23143 /* Treat as NOP. */
23144 return;
23147 t0 = tcg_temp_new_i32();
23148 v1_t = tcg_temp_new();
23149 v2_t = tcg_temp_new();
23151 tcg_gen_movi_i32(t0, ret);
23152 gen_load_gpr(v1_t, v1);
23153 gen_load_gpr(v2_t, v2);
23155 switch (op1) {
23157 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23158 * the same mask and op1.
23160 case OPC_MULT_G_2E:
23161 check_dsp_r2(ctx);
23162 switch (op2) {
23163 case OPC_MUL_PH:
23164 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23165 break;
23166 case OPC_MUL_S_PH:
23167 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23168 break;
23169 case OPC_MULQ_S_W:
23170 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23171 break;
23172 case OPC_MULQ_RS_W:
23173 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23174 break;
23176 break;
23177 case OPC_DPA_W_PH_DSP:
23178 switch (op2) {
23179 case OPC_DPAU_H_QBL:
23180 check_dsp(ctx);
23181 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23182 break;
23183 case OPC_DPAU_H_QBR:
23184 check_dsp(ctx);
23185 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23186 break;
23187 case OPC_DPSU_H_QBL:
23188 check_dsp(ctx);
23189 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23190 break;
23191 case OPC_DPSU_H_QBR:
23192 check_dsp(ctx);
23193 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23194 break;
23195 case OPC_DPA_W_PH:
23196 check_dsp_r2(ctx);
23197 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23198 break;
23199 case OPC_DPAX_W_PH:
23200 check_dsp_r2(ctx);
23201 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23202 break;
23203 case OPC_DPAQ_S_W_PH:
23204 check_dsp(ctx);
23205 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23206 break;
23207 case OPC_DPAQX_S_W_PH:
23208 check_dsp_r2(ctx);
23209 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23210 break;
23211 case OPC_DPAQX_SA_W_PH:
23212 check_dsp_r2(ctx);
23213 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23214 break;
23215 case OPC_DPS_W_PH:
23216 check_dsp_r2(ctx);
23217 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23218 break;
23219 case OPC_DPSX_W_PH:
23220 check_dsp_r2(ctx);
23221 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23222 break;
23223 case OPC_DPSQ_S_W_PH:
23224 check_dsp(ctx);
23225 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23226 break;
23227 case OPC_DPSQX_S_W_PH:
23228 check_dsp_r2(ctx);
23229 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23230 break;
23231 case OPC_DPSQX_SA_W_PH:
23232 check_dsp_r2(ctx);
23233 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23234 break;
23235 case OPC_MULSAQ_S_W_PH:
23236 check_dsp(ctx);
23237 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23238 break;
23239 case OPC_DPAQ_SA_L_W:
23240 check_dsp(ctx);
23241 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23242 break;
23243 case OPC_DPSQ_SA_L_W:
23244 check_dsp(ctx);
23245 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23246 break;
23247 case OPC_MAQ_S_W_PHL:
23248 check_dsp(ctx);
23249 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23250 break;
23251 case OPC_MAQ_S_W_PHR:
23252 check_dsp(ctx);
23253 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23254 break;
23255 case OPC_MAQ_SA_W_PHL:
23256 check_dsp(ctx);
23257 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23258 break;
23259 case OPC_MAQ_SA_W_PHR:
23260 check_dsp(ctx);
23261 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23262 break;
23263 case OPC_MULSA_W_PH:
23264 check_dsp_r2(ctx);
23265 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23266 break;
23268 break;
23269 #ifdef TARGET_MIPS64
23270 case OPC_DPAQ_W_QH_DSP:
23272 int ac = ret & 0x03;
23273 tcg_gen_movi_i32(t0, ac);
23275 switch (op2) {
23276 case OPC_DMADD:
23277 check_dsp(ctx);
23278 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23279 break;
23280 case OPC_DMADDU:
23281 check_dsp(ctx);
23282 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23283 break;
23284 case OPC_DMSUB:
23285 check_dsp(ctx);
23286 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23287 break;
23288 case OPC_DMSUBU:
23289 check_dsp(ctx);
23290 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23291 break;
23292 case OPC_DPA_W_QH:
23293 check_dsp_r2(ctx);
23294 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23295 break;
23296 case OPC_DPAQ_S_W_QH:
23297 check_dsp(ctx);
23298 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23299 break;
23300 case OPC_DPAQ_SA_L_PW:
23301 check_dsp(ctx);
23302 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23303 break;
23304 case OPC_DPAU_H_OBL:
23305 check_dsp(ctx);
23306 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23307 break;
23308 case OPC_DPAU_H_OBR:
23309 check_dsp(ctx);
23310 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23311 break;
23312 case OPC_DPS_W_QH:
23313 check_dsp_r2(ctx);
23314 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23315 break;
23316 case OPC_DPSQ_S_W_QH:
23317 check_dsp(ctx);
23318 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23319 break;
23320 case OPC_DPSQ_SA_L_PW:
23321 check_dsp(ctx);
23322 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23323 break;
23324 case OPC_DPSU_H_OBL:
23325 check_dsp(ctx);
23326 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23327 break;
23328 case OPC_DPSU_H_OBR:
23329 check_dsp(ctx);
23330 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23331 break;
23332 case OPC_MAQ_S_L_PWL:
23333 check_dsp(ctx);
23334 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23335 break;
23336 case OPC_MAQ_S_L_PWR:
23337 check_dsp(ctx);
23338 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23339 break;
23340 case OPC_MAQ_S_W_QHLL:
23341 check_dsp(ctx);
23342 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23343 break;
23344 case OPC_MAQ_SA_W_QHLL:
23345 check_dsp(ctx);
23346 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23347 break;
23348 case OPC_MAQ_S_W_QHLR:
23349 check_dsp(ctx);
23350 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23351 break;
23352 case OPC_MAQ_SA_W_QHLR:
23353 check_dsp(ctx);
23354 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23355 break;
23356 case OPC_MAQ_S_W_QHRL:
23357 check_dsp(ctx);
23358 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23359 break;
23360 case OPC_MAQ_SA_W_QHRL:
23361 check_dsp(ctx);
23362 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23363 break;
23364 case OPC_MAQ_S_W_QHRR:
23365 check_dsp(ctx);
23366 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23367 break;
23368 case OPC_MAQ_SA_W_QHRR:
23369 check_dsp(ctx);
23370 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23371 break;
23372 case OPC_MULSAQ_S_L_PW:
23373 check_dsp(ctx);
23374 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23375 break;
23376 case OPC_MULSAQ_S_W_QH:
23377 check_dsp(ctx);
23378 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23379 break;
23382 break;
23383 #endif
23384 case OPC_ADDU_QB_DSP:
23385 switch (op2) {
23386 case OPC_MULEU_S_PH_QBL:
23387 check_dsp(ctx);
23388 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23389 break;
23390 case OPC_MULEU_S_PH_QBR:
23391 check_dsp(ctx);
23392 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23393 break;
23394 case OPC_MULQ_RS_PH:
23395 check_dsp(ctx);
23396 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23397 break;
23398 case OPC_MULEQ_S_W_PHL:
23399 check_dsp(ctx);
23400 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23401 break;
23402 case OPC_MULEQ_S_W_PHR:
23403 check_dsp(ctx);
23404 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23405 break;
23406 case OPC_MULQ_S_PH:
23407 check_dsp_r2(ctx);
23408 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23409 break;
23411 break;
23412 #ifdef TARGET_MIPS64
23413 case OPC_ADDU_OB_DSP:
23414 switch (op2) {
23415 case OPC_MULEQ_S_PW_QHL:
23416 check_dsp(ctx);
23417 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23418 break;
23419 case OPC_MULEQ_S_PW_QHR:
23420 check_dsp(ctx);
23421 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23422 break;
23423 case OPC_MULEU_S_QH_OBL:
23424 check_dsp(ctx);
23425 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23426 break;
23427 case OPC_MULEU_S_QH_OBR:
23428 check_dsp(ctx);
23429 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23430 break;
23431 case OPC_MULQ_RS_QH:
23432 check_dsp(ctx);
23433 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23434 break;
23436 break;
23437 #endif
23440 tcg_temp_free_i32(t0);
23441 tcg_temp_free(v1_t);
23442 tcg_temp_free(v2_t);
23445 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23446 int ret, int val)
23448 int16_t imm;
23449 TCGv t0;
23450 TCGv val_t;
23452 if (ret == 0) {
23453 /* Treat as NOP. */
23454 return;
23457 t0 = tcg_temp_new();
23458 val_t = tcg_temp_new();
23459 gen_load_gpr(val_t, val);
23461 switch (op1) {
23462 case OPC_ABSQ_S_PH_DSP:
23463 switch (op2) {
23464 case OPC_BITREV:
23465 check_dsp(ctx);
23466 gen_helper_bitrev(cpu_gpr[ret], val_t);
23467 break;
23468 case OPC_REPL_QB:
23469 check_dsp(ctx);
23471 target_long result;
23472 imm = (ctx->opcode >> 16) & 0xFF;
23473 result = (uint32_t)imm << 24 |
23474 (uint32_t)imm << 16 |
23475 (uint32_t)imm << 8 |
23476 (uint32_t)imm;
23477 result = (int32_t)result;
23478 tcg_gen_movi_tl(cpu_gpr[ret], result);
23480 break;
23481 case OPC_REPLV_QB:
23482 check_dsp(ctx);
23483 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23484 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23485 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23486 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23487 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23488 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23489 break;
23490 case OPC_REPL_PH:
23491 check_dsp(ctx);
23493 imm = (ctx->opcode >> 16) & 0x03FF;
23494 imm = (int16_t)(imm << 6) >> 6;
23495 tcg_gen_movi_tl(cpu_gpr[ret], \
23496 (target_long)((int32_t)imm << 16 | \
23497 (uint16_t)imm));
23499 break;
23500 case OPC_REPLV_PH:
23501 check_dsp(ctx);
23502 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23503 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23504 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23505 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23506 break;
23508 break;
23509 #ifdef TARGET_MIPS64
23510 case OPC_ABSQ_S_QH_DSP:
23511 switch (op2) {
23512 case OPC_REPL_OB:
23513 check_dsp(ctx);
23515 target_long temp;
23517 imm = (ctx->opcode >> 16) & 0xFF;
23518 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23519 temp = (temp << 16) | temp;
23520 temp = (temp << 32) | temp;
23521 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23522 break;
23524 case OPC_REPL_PW:
23525 check_dsp(ctx);
23527 target_long temp;
23529 imm = (ctx->opcode >> 16) & 0x03FF;
23530 imm = (int16_t)(imm << 6) >> 6;
23531 temp = ((target_long)imm << 32) \
23532 | ((target_long)imm & 0xFFFFFFFF);
23533 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23534 break;
23536 case OPC_REPL_QH:
23537 check_dsp(ctx);
23539 target_long temp;
23541 imm = (ctx->opcode >> 16) & 0x03FF;
23542 imm = (int16_t)(imm << 6) >> 6;
23544 temp = ((uint64_t)(uint16_t)imm << 48) |
23545 ((uint64_t)(uint16_t)imm << 32) |
23546 ((uint64_t)(uint16_t)imm << 16) |
23547 (uint64_t)(uint16_t)imm;
23548 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23549 break;
23551 case OPC_REPLV_OB:
23552 check_dsp(ctx);
23553 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23554 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23555 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23556 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23557 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23558 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23559 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23560 break;
23561 case OPC_REPLV_PW:
23562 check_dsp(ctx);
23563 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23564 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23565 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23566 break;
23567 case OPC_REPLV_QH:
23568 check_dsp(ctx);
23569 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23570 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23571 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23572 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23573 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23574 break;
23576 break;
23577 #endif
23579 tcg_temp_free(t0);
23580 tcg_temp_free(val_t);
23583 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23584 uint32_t op1, uint32_t op2,
23585 int ret, int v1, int v2, int check_ret)
23587 TCGv t1;
23588 TCGv v1_t;
23589 TCGv v2_t;
23591 if ((ret == 0) && (check_ret == 1)) {
23592 /* Treat as NOP. */
23593 return;
23596 t1 = tcg_temp_new();
23597 v1_t = tcg_temp_new();
23598 v2_t = tcg_temp_new();
23600 gen_load_gpr(v1_t, v1);
23601 gen_load_gpr(v2_t, v2);
23603 switch (op1) {
23604 case OPC_CMPU_EQ_QB_DSP:
23605 switch (op2) {
23606 case OPC_CMPU_EQ_QB:
23607 check_dsp(ctx);
23608 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23609 break;
23610 case OPC_CMPU_LT_QB:
23611 check_dsp(ctx);
23612 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23613 break;
23614 case OPC_CMPU_LE_QB:
23615 check_dsp(ctx);
23616 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23617 break;
23618 case OPC_CMPGU_EQ_QB:
23619 check_dsp(ctx);
23620 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23621 break;
23622 case OPC_CMPGU_LT_QB:
23623 check_dsp(ctx);
23624 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23625 break;
23626 case OPC_CMPGU_LE_QB:
23627 check_dsp(ctx);
23628 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23629 break;
23630 case OPC_CMPGDU_EQ_QB:
23631 check_dsp_r2(ctx);
23632 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23633 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23634 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23635 tcg_gen_shli_tl(t1, t1, 24);
23636 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23637 break;
23638 case OPC_CMPGDU_LT_QB:
23639 check_dsp_r2(ctx);
23640 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23641 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23642 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23643 tcg_gen_shli_tl(t1, t1, 24);
23644 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23645 break;
23646 case OPC_CMPGDU_LE_QB:
23647 check_dsp_r2(ctx);
23648 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23649 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23650 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23651 tcg_gen_shli_tl(t1, t1, 24);
23652 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23653 break;
23654 case OPC_CMP_EQ_PH:
23655 check_dsp(ctx);
23656 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23657 break;
23658 case OPC_CMP_LT_PH:
23659 check_dsp(ctx);
23660 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23661 break;
23662 case OPC_CMP_LE_PH:
23663 check_dsp(ctx);
23664 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23665 break;
23666 case OPC_PICK_QB:
23667 check_dsp(ctx);
23668 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23669 break;
23670 case OPC_PICK_PH:
23671 check_dsp(ctx);
23672 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23673 break;
23674 case OPC_PACKRL_PH:
23675 check_dsp(ctx);
23676 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23677 break;
23679 break;
23680 #ifdef TARGET_MIPS64
23681 case OPC_CMPU_EQ_OB_DSP:
23682 switch (op2) {
23683 case OPC_CMP_EQ_PW:
23684 check_dsp(ctx);
23685 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23686 break;
23687 case OPC_CMP_LT_PW:
23688 check_dsp(ctx);
23689 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23690 break;
23691 case OPC_CMP_LE_PW:
23692 check_dsp(ctx);
23693 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23694 break;
23695 case OPC_CMP_EQ_QH:
23696 check_dsp(ctx);
23697 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23698 break;
23699 case OPC_CMP_LT_QH:
23700 check_dsp(ctx);
23701 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23702 break;
23703 case OPC_CMP_LE_QH:
23704 check_dsp(ctx);
23705 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23706 break;
23707 case OPC_CMPGDU_EQ_OB:
23708 check_dsp_r2(ctx);
23709 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23710 break;
23711 case OPC_CMPGDU_LT_OB:
23712 check_dsp_r2(ctx);
23713 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23714 break;
23715 case OPC_CMPGDU_LE_OB:
23716 check_dsp_r2(ctx);
23717 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23718 break;
23719 case OPC_CMPGU_EQ_OB:
23720 check_dsp(ctx);
23721 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23722 break;
23723 case OPC_CMPGU_LT_OB:
23724 check_dsp(ctx);
23725 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23726 break;
23727 case OPC_CMPGU_LE_OB:
23728 check_dsp(ctx);
23729 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23730 break;
23731 case OPC_CMPU_EQ_OB:
23732 check_dsp(ctx);
23733 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23734 break;
23735 case OPC_CMPU_LT_OB:
23736 check_dsp(ctx);
23737 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23738 break;
23739 case OPC_CMPU_LE_OB:
23740 check_dsp(ctx);
23741 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23742 break;
23743 case OPC_PACKRL_PW:
23744 check_dsp(ctx);
23745 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23746 break;
23747 case OPC_PICK_OB:
23748 check_dsp(ctx);
23749 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23750 break;
23751 case OPC_PICK_PW:
23752 check_dsp(ctx);
23753 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23754 break;
23755 case OPC_PICK_QH:
23756 check_dsp(ctx);
23757 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23758 break;
23760 break;
23761 #endif
23764 tcg_temp_free(t1);
23765 tcg_temp_free(v1_t);
23766 tcg_temp_free(v2_t);
23769 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23770 uint32_t op1, int rt, int rs, int sa)
23772 TCGv t0;
23774 check_dsp_r2(ctx);
23776 if (rt == 0) {
23777 /* Treat as NOP. */
23778 return;
23781 t0 = tcg_temp_new();
23782 gen_load_gpr(t0, rs);
23784 switch (op1) {
23785 case OPC_APPEND_DSP:
23786 switch (MASK_APPEND(ctx->opcode)) {
23787 case OPC_APPEND:
23788 if (sa != 0) {
23789 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23791 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23792 break;
23793 case OPC_PREPEND:
23794 if (sa != 0) {
23795 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23796 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23797 tcg_gen_shli_tl(t0, t0, 32 - sa);
23798 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23800 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23801 break;
23802 case OPC_BALIGN:
23803 sa &= 3;
23804 if (sa != 0 && sa != 2) {
23805 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23806 tcg_gen_ext32u_tl(t0, t0);
23807 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23808 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23810 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23811 break;
23812 default: /* Invalid */
23813 MIPS_INVAL("MASK APPEND");
23814 gen_reserved_instruction(ctx);
23815 break;
23817 break;
23818 #ifdef TARGET_MIPS64
23819 case OPC_DAPPEND_DSP:
23820 switch (MASK_DAPPEND(ctx->opcode)) {
23821 case OPC_DAPPEND:
23822 if (sa != 0) {
23823 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23825 break;
23826 case OPC_PREPENDD:
23827 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23828 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23829 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23830 break;
23831 case OPC_PREPENDW:
23832 if (sa != 0) {
23833 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23834 tcg_gen_shli_tl(t0, t0, 64 - sa);
23835 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23837 break;
23838 case OPC_DBALIGN:
23839 sa &= 7;
23840 if (sa != 0 && sa != 2 && sa != 4) {
23841 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23842 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23843 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23845 break;
23846 default: /* Invalid */
23847 MIPS_INVAL("MASK DAPPEND");
23848 gen_reserved_instruction(ctx);
23849 break;
23851 break;
23852 #endif
23854 tcg_temp_free(t0);
23857 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23858 int ret, int v1, int v2, int check_ret)
23861 TCGv t0;
23862 TCGv t1;
23863 TCGv v1_t;
23864 TCGv v2_t;
23865 int16_t imm;
23867 if ((ret == 0) && (check_ret == 1)) {
23868 /* Treat as NOP. */
23869 return;
23872 t0 = tcg_temp_new();
23873 t1 = tcg_temp_new();
23874 v1_t = tcg_temp_new();
23875 v2_t = tcg_temp_new();
23877 gen_load_gpr(v1_t, v1);
23878 gen_load_gpr(v2_t, v2);
23880 switch (op1) {
23881 case OPC_EXTR_W_DSP:
23882 check_dsp(ctx);
23883 switch (op2) {
23884 case OPC_EXTR_W:
23885 tcg_gen_movi_tl(t0, v2);
23886 tcg_gen_movi_tl(t1, v1);
23887 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23888 break;
23889 case OPC_EXTR_R_W:
23890 tcg_gen_movi_tl(t0, v2);
23891 tcg_gen_movi_tl(t1, v1);
23892 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23893 break;
23894 case OPC_EXTR_RS_W:
23895 tcg_gen_movi_tl(t0, v2);
23896 tcg_gen_movi_tl(t1, v1);
23897 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23898 break;
23899 case OPC_EXTR_S_H:
23900 tcg_gen_movi_tl(t0, v2);
23901 tcg_gen_movi_tl(t1, v1);
23902 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23903 break;
23904 case OPC_EXTRV_S_H:
23905 tcg_gen_movi_tl(t0, v2);
23906 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23907 break;
23908 case OPC_EXTRV_W:
23909 tcg_gen_movi_tl(t0, v2);
23910 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23911 break;
23912 case OPC_EXTRV_R_W:
23913 tcg_gen_movi_tl(t0, v2);
23914 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23915 break;
23916 case OPC_EXTRV_RS_W:
23917 tcg_gen_movi_tl(t0, v2);
23918 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23919 break;
23920 case OPC_EXTP:
23921 tcg_gen_movi_tl(t0, v2);
23922 tcg_gen_movi_tl(t1, v1);
23923 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23924 break;
23925 case OPC_EXTPV:
23926 tcg_gen_movi_tl(t0, v2);
23927 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23928 break;
23929 case OPC_EXTPDP:
23930 tcg_gen_movi_tl(t0, v2);
23931 tcg_gen_movi_tl(t1, v1);
23932 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23933 break;
23934 case OPC_EXTPDPV:
23935 tcg_gen_movi_tl(t0, v2);
23936 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23937 break;
23938 case OPC_SHILO:
23939 imm = (ctx->opcode >> 20) & 0x3F;
23940 tcg_gen_movi_tl(t0, ret);
23941 tcg_gen_movi_tl(t1, imm);
23942 gen_helper_shilo(t0, t1, cpu_env);
23943 break;
23944 case OPC_SHILOV:
23945 tcg_gen_movi_tl(t0, ret);
23946 gen_helper_shilo(t0, v1_t, cpu_env);
23947 break;
23948 case OPC_MTHLIP:
23949 tcg_gen_movi_tl(t0, ret);
23950 gen_helper_mthlip(t0, v1_t, cpu_env);
23951 break;
23952 case OPC_WRDSP:
23953 imm = (ctx->opcode >> 11) & 0x3FF;
23954 tcg_gen_movi_tl(t0, imm);
23955 gen_helper_wrdsp(v1_t, t0, cpu_env);
23956 break;
23957 case OPC_RDDSP:
23958 imm = (ctx->opcode >> 16) & 0x03FF;
23959 tcg_gen_movi_tl(t0, imm);
23960 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23961 break;
23963 break;
23964 #ifdef TARGET_MIPS64
23965 case OPC_DEXTR_W_DSP:
23966 check_dsp(ctx);
23967 switch (op2) {
23968 case OPC_DMTHLIP:
23969 tcg_gen_movi_tl(t0, ret);
23970 gen_helper_dmthlip(v1_t, t0, cpu_env);
23971 break;
23972 case OPC_DSHILO:
23974 int shift = (ctx->opcode >> 19) & 0x7F;
23975 int ac = (ctx->opcode >> 11) & 0x03;
23976 tcg_gen_movi_tl(t0, shift);
23977 tcg_gen_movi_tl(t1, ac);
23978 gen_helper_dshilo(t0, t1, cpu_env);
23979 break;
23981 case OPC_DSHILOV:
23983 int ac = (ctx->opcode >> 11) & 0x03;
23984 tcg_gen_movi_tl(t0, ac);
23985 gen_helper_dshilo(v1_t, t0, cpu_env);
23986 break;
23988 case OPC_DEXTP:
23989 tcg_gen_movi_tl(t0, v2);
23990 tcg_gen_movi_tl(t1, v1);
23992 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23993 break;
23994 case OPC_DEXTPV:
23995 tcg_gen_movi_tl(t0, v2);
23996 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23997 break;
23998 case OPC_DEXTPDP:
23999 tcg_gen_movi_tl(t0, v2);
24000 tcg_gen_movi_tl(t1, v1);
24001 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24002 break;
24003 case OPC_DEXTPDPV:
24004 tcg_gen_movi_tl(t0, v2);
24005 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24006 break;
24007 case OPC_DEXTR_L:
24008 tcg_gen_movi_tl(t0, v2);
24009 tcg_gen_movi_tl(t1, v1);
24010 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24011 break;
24012 case OPC_DEXTR_R_L:
24013 tcg_gen_movi_tl(t0, v2);
24014 tcg_gen_movi_tl(t1, v1);
24015 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24016 break;
24017 case OPC_DEXTR_RS_L:
24018 tcg_gen_movi_tl(t0, v2);
24019 tcg_gen_movi_tl(t1, v1);
24020 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24021 break;
24022 case OPC_DEXTR_W:
24023 tcg_gen_movi_tl(t0, v2);
24024 tcg_gen_movi_tl(t1, v1);
24025 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24026 break;
24027 case OPC_DEXTR_R_W:
24028 tcg_gen_movi_tl(t0, v2);
24029 tcg_gen_movi_tl(t1, v1);
24030 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24031 break;
24032 case OPC_DEXTR_RS_W:
24033 tcg_gen_movi_tl(t0, v2);
24034 tcg_gen_movi_tl(t1, v1);
24035 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24036 break;
24037 case OPC_DEXTR_S_H:
24038 tcg_gen_movi_tl(t0, v2);
24039 tcg_gen_movi_tl(t1, v1);
24040 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24041 break;
24042 case OPC_DEXTRV_S_H:
24043 tcg_gen_movi_tl(t0, v2);
24044 tcg_gen_movi_tl(t1, v1);
24045 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24046 break;
24047 case OPC_DEXTRV_L:
24048 tcg_gen_movi_tl(t0, v2);
24049 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24050 break;
24051 case OPC_DEXTRV_R_L:
24052 tcg_gen_movi_tl(t0, v2);
24053 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24054 break;
24055 case OPC_DEXTRV_RS_L:
24056 tcg_gen_movi_tl(t0, v2);
24057 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24058 break;
24059 case OPC_DEXTRV_W:
24060 tcg_gen_movi_tl(t0, v2);
24061 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24062 break;
24063 case OPC_DEXTRV_R_W:
24064 tcg_gen_movi_tl(t0, v2);
24065 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24066 break;
24067 case OPC_DEXTRV_RS_W:
24068 tcg_gen_movi_tl(t0, v2);
24069 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24070 break;
24072 break;
24073 #endif
24076 tcg_temp_free(t0);
24077 tcg_temp_free(t1);
24078 tcg_temp_free(v1_t);
24079 tcg_temp_free(v2_t);
24082 /* End MIPSDSP functions. */
24084 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24086 int rs, rt, rd, sa;
24087 uint32_t op1, op2;
24089 rs = (ctx->opcode >> 21) & 0x1f;
24090 rt = (ctx->opcode >> 16) & 0x1f;
24091 rd = (ctx->opcode >> 11) & 0x1f;
24092 sa = (ctx->opcode >> 6) & 0x1f;
24094 op1 = MASK_SPECIAL(ctx->opcode);
24095 switch (op1) {
24096 case OPC_MULT:
24097 case OPC_MULTU:
24098 case OPC_DIV:
24099 case OPC_DIVU:
24100 op2 = MASK_R6_MULDIV(ctx->opcode);
24101 switch (op2) {
24102 case R6_OPC_MUL:
24103 case R6_OPC_MUH:
24104 case R6_OPC_MULU:
24105 case R6_OPC_MUHU:
24106 case R6_OPC_DIV:
24107 case R6_OPC_MOD:
24108 case R6_OPC_DIVU:
24109 case R6_OPC_MODU:
24110 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24111 break;
24112 default:
24113 MIPS_INVAL("special_r6 muldiv");
24114 gen_reserved_instruction(ctx);
24115 break;
24117 break;
24118 case OPC_SELEQZ:
24119 case OPC_SELNEZ:
24120 gen_cond_move(ctx, op1, rd, rs, rt);
24121 break;
24122 case R6_OPC_CLO:
24123 case R6_OPC_CLZ:
24124 if (rt == 0 && sa == 1) {
24126 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24127 * We need additionally to check other fields.
24129 gen_cl(ctx, op1, rd, rs);
24130 } else {
24131 gen_reserved_instruction(ctx);
24133 break;
24134 case R6_OPC_SDBBP:
24135 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24136 gen_helper_do_semihosting(cpu_env);
24137 } else {
24138 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24139 gen_reserved_instruction(ctx);
24140 } else {
24141 generate_exception_end(ctx, EXCP_DBp);
24144 break;
24145 #if defined(TARGET_MIPS64)
24146 case R6_OPC_DCLO:
24147 case R6_OPC_DCLZ:
24148 if (rt == 0 && sa == 1) {
24150 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24151 * We need additionally to check other fields.
24153 check_mips_64(ctx);
24154 gen_cl(ctx, op1, rd, rs);
24155 } else {
24156 gen_reserved_instruction(ctx);
24158 break;
24159 case OPC_DMULT:
24160 case OPC_DMULTU:
24161 case OPC_DDIV:
24162 case OPC_DDIVU:
24164 op2 = MASK_R6_MULDIV(ctx->opcode);
24165 switch (op2) {
24166 case R6_OPC_DMUL:
24167 case R6_OPC_DMUH:
24168 case R6_OPC_DMULU:
24169 case R6_OPC_DMUHU:
24170 case R6_OPC_DDIV:
24171 case R6_OPC_DMOD:
24172 case R6_OPC_DDIVU:
24173 case R6_OPC_DMODU:
24174 check_mips_64(ctx);
24175 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24176 break;
24177 default:
24178 MIPS_INVAL("special_r6 muldiv");
24179 gen_reserved_instruction(ctx);
24180 break;
24182 break;
24183 #endif
24184 default: /* Invalid */
24185 MIPS_INVAL("special_r6");
24186 gen_reserved_instruction(ctx);
24187 break;
24191 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24193 int rs = extract32(ctx->opcode, 21, 5);
24194 int rt = extract32(ctx->opcode, 16, 5);
24195 int rd = extract32(ctx->opcode, 11, 5);
24196 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24198 switch (op1) {
24199 case OPC_MOVN: /* Conditional move */
24200 case OPC_MOVZ:
24201 gen_cond_move(ctx, op1, rd, rs, rt);
24202 break;
24203 case OPC_MFHI: /* Move from HI/LO */
24204 case OPC_MFLO:
24205 gen_HILO(ctx, op1, 0, rd);
24206 break;
24207 case OPC_MTHI:
24208 case OPC_MTLO: /* Move to HI/LO */
24209 gen_HILO(ctx, op1, 0, rs);
24210 break;
24211 case OPC_MULT:
24212 case OPC_MULTU:
24213 gen_mul_txx9(ctx, op1, rd, rs, rt);
24214 break;
24215 case OPC_DIV:
24216 case OPC_DIVU:
24217 gen_muldiv(ctx, op1, 0, rs, rt);
24218 break;
24219 #if defined(TARGET_MIPS64)
24220 case OPC_DMULT:
24221 case OPC_DMULTU:
24222 case OPC_DDIV:
24223 case OPC_DDIVU:
24224 check_insn_opc_user_only(ctx, INSN_R5900);
24225 gen_muldiv(ctx, op1, 0, rs, rt);
24226 break;
24227 #endif
24228 case OPC_JR:
24229 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24230 break;
24231 default: /* Invalid */
24232 MIPS_INVAL("special_tx79");
24233 gen_reserved_instruction(ctx);
24234 break;
24238 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24240 int rs, rt, rd, sa;
24241 uint32_t op1;
24243 rs = (ctx->opcode >> 21) & 0x1f;
24244 rt = (ctx->opcode >> 16) & 0x1f;
24245 rd = (ctx->opcode >> 11) & 0x1f;
24246 sa = (ctx->opcode >> 6) & 0x1f;
24248 op1 = MASK_SPECIAL(ctx->opcode);
24249 switch (op1) {
24250 case OPC_MOVN: /* Conditional move */
24251 case OPC_MOVZ:
24252 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
24253 INSN_LOONGSON2E | INSN_LOONGSON2F);
24254 gen_cond_move(ctx, op1, rd, rs, rt);
24255 break;
24256 case OPC_MFHI: /* Move from HI/LO */
24257 case OPC_MFLO:
24258 gen_HILO(ctx, op1, rs & 3, rd);
24259 break;
24260 case OPC_MTHI:
24261 case OPC_MTLO: /* Move to HI/LO */
24262 gen_HILO(ctx, op1, rd & 3, rs);
24263 break;
24264 case OPC_MOVCI:
24265 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
24266 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24267 check_cp1_enabled(ctx);
24268 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24269 (ctx->opcode >> 16) & 1);
24270 } else {
24271 generate_exception_err(ctx, EXCP_CpU, 1);
24273 break;
24274 case OPC_MULT:
24275 case OPC_MULTU:
24276 if (sa) {
24277 check_insn(ctx, INSN_VR54XX);
24278 op1 = MASK_MUL_VR54XX(ctx->opcode);
24279 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24280 } else {
24281 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24283 break;
24284 case OPC_DIV:
24285 case OPC_DIVU:
24286 gen_muldiv(ctx, op1, 0, rs, rt);
24287 break;
24288 #if defined(TARGET_MIPS64)
24289 case OPC_DMULT:
24290 case OPC_DMULTU:
24291 case OPC_DDIV:
24292 case OPC_DDIVU:
24293 check_insn(ctx, ISA_MIPS3);
24294 check_mips_64(ctx);
24295 gen_muldiv(ctx, op1, 0, rs, rt);
24296 break;
24297 #endif
24298 case OPC_JR:
24299 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24300 break;
24301 case OPC_SPIM:
24302 #ifdef MIPS_STRICT_STANDARD
24303 MIPS_INVAL("SPIM");
24304 gen_reserved_instruction(ctx);
24305 #else
24306 /* Implemented as RI exception for now. */
24307 MIPS_INVAL("spim (unofficial)");
24308 gen_reserved_instruction(ctx);
24309 #endif
24310 break;
24311 default: /* Invalid */
24312 MIPS_INVAL("special_legacy");
24313 gen_reserved_instruction(ctx);
24314 break;
24318 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24320 int rs, rt, rd, sa;
24321 uint32_t op1;
24323 rs = (ctx->opcode >> 21) & 0x1f;
24324 rt = (ctx->opcode >> 16) & 0x1f;
24325 rd = (ctx->opcode >> 11) & 0x1f;
24326 sa = (ctx->opcode >> 6) & 0x1f;
24328 op1 = MASK_SPECIAL(ctx->opcode);
24329 switch (op1) {
24330 case OPC_SLL: /* Shift with immediate */
24331 if (sa == 5 && rd == 0 &&
24332 rs == 0 && rt == 0) { /* PAUSE */
24333 if ((ctx->insn_flags & ISA_MIPS_R6) &&
24334 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24335 gen_reserved_instruction(ctx);
24336 break;
24339 /* Fallthrough */
24340 case OPC_SRA:
24341 gen_shift_imm(ctx, op1, rd, rt, sa);
24342 break;
24343 case OPC_SRL:
24344 switch ((ctx->opcode >> 21) & 0x1f) {
24345 case 1:
24346 /* rotr is decoded as srl on non-R2 CPUs */
24347 if (ctx->insn_flags & ISA_MIPS_R2) {
24348 op1 = OPC_ROTR;
24350 /* Fallthrough */
24351 case 0:
24352 gen_shift_imm(ctx, op1, rd, rt, sa);
24353 break;
24354 default:
24355 gen_reserved_instruction(ctx);
24356 break;
24358 break;
24359 case OPC_ADD:
24360 case OPC_ADDU:
24361 case OPC_SUB:
24362 case OPC_SUBU:
24363 gen_arith(ctx, op1, rd, rs, rt);
24364 break;
24365 case OPC_SLLV: /* Shifts */
24366 case OPC_SRAV:
24367 gen_shift(ctx, op1, rd, rs, rt);
24368 break;
24369 case OPC_SRLV:
24370 switch ((ctx->opcode >> 6) & 0x1f) {
24371 case 1:
24372 /* rotrv is decoded as srlv on non-R2 CPUs */
24373 if (ctx->insn_flags & ISA_MIPS_R2) {
24374 op1 = OPC_ROTRV;
24376 /* Fallthrough */
24377 case 0:
24378 gen_shift(ctx, op1, rd, rs, rt);
24379 break;
24380 default:
24381 gen_reserved_instruction(ctx);
24382 break;
24384 break;
24385 case OPC_SLT: /* Set on less than */
24386 case OPC_SLTU:
24387 gen_slt(ctx, op1, rd, rs, rt);
24388 break;
24389 case OPC_AND: /* Logic*/
24390 case OPC_OR:
24391 case OPC_NOR:
24392 case OPC_XOR:
24393 gen_logic(ctx, op1, rd, rs, rt);
24394 break;
24395 case OPC_JALR:
24396 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24397 break;
24398 case OPC_TGE: /* Traps */
24399 case OPC_TGEU:
24400 case OPC_TLT:
24401 case OPC_TLTU:
24402 case OPC_TEQ:
24403 case OPC_TNE:
24404 check_insn(ctx, ISA_MIPS2);
24405 gen_trap(ctx, op1, rs, rt, -1);
24406 break;
24407 case OPC_PMON:
24408 /* Pmon entry point, also R4010 selsl */
24409 #ifdef MIPS_STRICT_STANDARD
24410 MIPS_INVAL("PMON / selsl");
24411 gen_reserved_instruction(ctx);
24412 #else
24413 gen_helper_0e0i(pmon, sa);
24414 #endif
24415 break;
24416 case OPC_SYSCALL:
24417 generate_exception_end(ctx, EXCP_SYSCALL);
24418 break;
24419 case OPC_BREAK:
24420 generate_exception_end(ctx, EXCP_BREAK);
24421 break;
24422 case OPC_SYNC:
24423 check_insn(ctx, ISA_MIPS2);
24424 gen_sync(extract32(ctx->opcode, 6, 5));
24425 break;
24427 #if defined(TARGET_MIPS64)
24428 /* MIPS64 specific opcodes */
24429 case OPC_DSLL:
24430 case OPC_DSRA:
24431 case OPC_DSLL32:
24432 case OPC_DSRA32:
24433 check_insn(ctx, ISA_MIPS3);
24434 check_mips_64(ctx);
24435 gen_shift_imm(ctx, op1, rd, rt, sa);
24436 break;
24437 case OPC_DSRL:
24438 switch ((ctx->opcode >> 21) & 0x1f) {
24439 case 1:
24440 /* drotr is decoded as dsrl on non-R2 CPUs */
24441 if (ctx->insn_flags & ISA_MIPS_R2) {
24442 op1 = OPC_DROTR;
24444 /* Fallthrough */
24445 case 0:
24446 check_insn(ctx, ISA_MIPS3);
24447 check_mips_64(ctx);
24448 gen_shift_imm(ctx, op1, rd, rt, sa);
24449 break;
24450 default:
24451 gen_reserved_instruction(ctx);
24452 break;
24454 break;
24455 case OPC_DSRL32:
24456 switch ((ctx->opcode >> 21) & 0x1f) {
24457 case 1:
24458 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24459 if (ctx->insn_flags & ISA_MIPS_R2) {
24460 op1 = OPC_DROTR32;
24462 /* Fallthrough */
24463 case 0:
24464 check_insn(ctx, ISA_MIPS3);
24465 check_mips_64(ctx);
24466 gen_shift_imm(ctx, op1, rd, rt, sa);
24467 break;
24468 default:
24469 gen_reserved_instruction(ctx);
24470 break;
24472 break;
24473 case OPC_DADD:
24474 case OPC_DADDU:
24475 case OPC_DSUB:
24476 case OPC_DSUBU:
24477 check_insn(ctx, ISA_MIPS3);
24478 check_mips_64(ctx);
24479 gen_arith(ctx, op1, rd, rs, rt);
24480 break;
24481 case OPC_DSLLV:
24482 case OPC_DSRAV:
24483 check_insn(ctx, ISA_MIPS3);
24484 check_mips_64(ctx);
24485 gen_shift(ctx, op1, rd, rs, rt);
24486 break;
24487 case OPC_DSRLV:
24488 switch ((ctx->opcode >> 6) & 0x1f) {
24489 case 1:
24490 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24491 if (ctx->insn_flags & ISA_MIPS_R2) {
24492 op1 = OPC_DROTRV;
24494 /* Fallthrough */
24495 case 0:
24496 check_insn(ctx, ISA_MIPS3);
24497 check_mips_64(ctx);
24498 gen_shift(ctx, op1, rd, rs, rt);
24499 break;
24500 default:
24501 gen_reserved_instruction(ctx);
24502 break;
24504 break;
24505 #endif
24506 default:
24507 if (ctx->insn_flags & ISA_MIPS_R6) {
24508 decode_opc_special_r6(env, ctx);
24509 } else if (ctx->insn_flags & INSN_R5900) {
24510 decode_opc_special_tx79(env, ctx);
24511 } else {
24512 decode_opc_special_legacy(env, ctx);
24518 #if defined(TARGET_MIPS64)
24522 * MMI (MultiMedia Interface) ASE instructions
24523 * ===========================================
24527 * MMI instructions category: data communication
24528 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24530 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24531 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24532 * PCPYUD PEXEH PEXTLW PPACW
24533 * PEXEW PEXTUB
24534 * PEXTUH
24535 * PEXTUW
24539 * PCPYH rd, rt
24541 * Parallel Copy Halfword
24543 * 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
24544 * +-----------+---------+---------+---------+---------+-----------+
24545 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24546 * +-----------+---------+---------+---------+---------+-----------+
24548 static void gen_mmi_pcpyh(DisasContext *ctx)
24550 uint32_t pd, rt, rd;
24551 uint32_t opcode;
24553 opcode = ctx->opcode;
24555 pd = extract32(opcode, 21, 5);
24556 rt = extract32(opcode, 16, 5);
24557 rd = extract32(opcode, 11, 5);
24559 if (unlikely(pd != 0)) {
24560 gen_reserved_instruction(ctx);
24561 } else if (rd == 0) {
24562 /* nop */
24563 } else if (rt == 0) {
24564 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24565 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24566 } else {
24567 TCGv_i64 t0 = tcg_temp_new();
24568 TCGv_i64 t1 = tcg_temp_new();
24569 uint64_t mask = (1ULL << 16) - 1;
24571 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24572 tcg_gen_movi_i64(t1, 0);
24573 tcg_gen_or_i64(t1, t0, t1);
24574 tcg_gen_shli_i64(t0, t0, 16);
24575 tcg_gen_or_i64(t1, t0, t1);
24576 tcg_gen_shli_i64(t0, t0, 16);
24577 tcg_gen_or_i64(t1, t0, t1);
24578 tcg_gen_shli_i64(t0, t0, 16);
24579 tcg_gen_or_i64(t1, t0, t1);
24581 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24583 tcg_gen_andi_i64(t0, cpu_gpr_hi[rt], mask);
24584 tcg_gen_movi_i64(t1, 0);
24585 tcg_gen_or_i64(t1, t0, t1);
24586 tcg_gen_shli_i64(t0, t0, 16);
24587 tcg_gen_or_i64(t1, t0, t1);
24588 tcg_gen_shli_i64(t0, t0, 16);
24589 tcg_gen_or_i64(t1, t0, t1);
24590 tcg_gen_shli_i64(t0, t0, 16);
24591 tcg_gen_or_i64(t1, t0, t1);
24593 tcg_gen_mov_i64(cpu_gpr_hi[rd], t1);
24595 tcg_temp_free(t0);
24596 tcg_temp_free(t1);
24601 * PCPYLD rd, rs, rt
24603 * Parallel Copy Lower Doubleword
24605 * 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
24606 * +-----------+---------+---------+---------+---------+-----------+
24607 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24608 * +-----------+---------+---------+---------+---------+-----------+
24610 static void gen_mmi_pcpyld(DisasContext *ctx)
24612 uint32_t rs, rt, rd;
24613 uint32_t opcode;
24615 opcode = ctx->opcode;
24617 rs = extract32(opcode, 21, 5);
24618 rt = extract32(opcode, 16, 5);
24619 rd = extract32(opcode, 11, 5);
24621 if (rd == 0) {
24622 /* nop */
24623 } else {
24624 if (rs == 0) {
24625 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24626 } else {
24627 tcg_gen_mov_i64(cpu_gpr_hi[rd], cpu_gpr[rs]);
24629 if (rt == 0) {
24630 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24631 } else {
24632 if (rd != rt) {
24633 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24640 * PCPYUD rd, rs, rt
24642 * Parallel Copy Upper Doubleword
24644 * 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
24645 * +-----------+---------+---------+---------+---------+-----------+
24646 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24647 * +-----------+---------+---------+---------+---------+-----------+
24649 static void gen_mmi_pcpyud(DisasContext *ctx)
24651 uint32_t rs, rt, rd;
24652 uint32_t opcode;
24654 opcode = ctx->opcode;
24656 rs = extract32(opcode, 21, 5);
24657 rt = extract32(opcode, 16, 5);
24658 rd = extract32(opcode, 11, 5);
24660 if (rd == 0) {
24661 /* nop */
24662 } else {
24663 if (rs == 0) {
24664 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24665 } else {
24666 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr_hi[rs]);
24668 if (rt == 0) {
24669 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24670 } else {
24671 if (rd != rt) {
24672 tcg_gen_mov_i64(cpu_gpr_hi[rd], cpu_gpr_hi[rt]);
24678 #endif
24681 #if !defined(TARGET_MIPS64)
24683 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24684 #define MXU_APTN1_A 0
24685 #define MXU_APTN1_S 1
24687 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24688 #define MXU_APTN2_AA 0
24689 #define MXU_APTN2_AS 1
24690 #define MXU_APTN2_SA 2
24691 #define MXU_APTN2_SS 3
24693 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24694 #define MXU_EPTN2_AA 0
24695 #define MXU_EPTN2_AS 1
24696 #define MXU_EPTN2_SA 2
24697 #define MXU_EPTN2_SS 3
24699 /* MXU operand getting pattern 'optn2' */
24700 #define MXU_OPTN2_PTN0 0
24701 #define MXU_OPTN2_PTN1 1
24702 #define MXU_OPTN2_PTN2 2
24703 #define MXU_OPTN2_PTN3 3
24704 /* alternative naming scheme for 'optn2' */
24705 #define MXU_OPTN2_WW 0
24706 #define MXU_OPTN2_LW 1
24707 #define MXU_OPTN2_HW 2
24708 #define MXU_OPTN2_XW 3
24710 /* MXU operand getting pattern 'optn3' */
24711 #define MXU_OPTN3_PTN0 0
24712 #define MXU_OPTN3_PTN1 1
24713 #define MXU_OPTN3_PTN2 2
24714 #define MXU_OPTN3_PTN3 3
24715 #define MXU_OPTN3_PTN4 4
24716 #define MXU_OPTN3_PTN5 5
24717 #define MXU_OPTN3_PTN6 6
24718 #define MXU_OPTN3_PTN7 7
24722 * S32I2M XRa, rb - Register move from GRF to XRF
24724 static void gen_mxu_s32i2m(DisasContext *ctx)
24726 TCGv t0;
24727 uint32_t XRa, Rb;
24729 t0 = tcg_temp_new();
24731 XRa = extract32(ctx->opcode, 6, 5);
24732 Rb = extract32(ctx->opcode, 16, 5);
24734 gen_load_gpr(t0, Rb);
24735 if (XRa <= 15) {
24736 gen_store_mxu_gpr(t0, XRa);
24737 } else if (XRa == 16) {
24738 gen_store_mxu_cr(t0);
24741 tcg_temp_free(t0);
24745 * S32M2I XRa, rb - Register move from XRF to GRF
24747 static void gen_mxu_s32m2i(DisasContext *ctx)
24749 TCGv t0;
24750 uint32_t XRa, Rb;
24752 t0 = tcg_temp_new();
24754 XRa = extract32(ctx->opcode, 6, 5);
24755 Rb = extract32(ctx->opcode, 16, 5);
24757 if (XRa <= 15) {
24758 gen_load_mxu_gpr(t0, XRa);
24759 } else if (XRa == 16) {
24760 gen_load_mxu_cr(t0);
24763 gen_store_gpr(t0, Rb);
24765 tcg_temp_free(t0);
24769 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24771 static void gen_mxu_s8ldd(DisasContext *ctx)
24773 TCGv t0, t1;
24774 uint32_t XRa, Rb, s8, optn3;
24776 t0 = tcg_temp_new();
24777 t1 = tcg_temp_new();
24779 XRa = extract32(ctx->opcode, 6, 4);
24780 s8 = extract32(ctx->opcode, 10, 8);
24781 optn3 = extract32(ctx->opcode, 18, 3);
24782 Rb = extract32(ctx->opcode, 21, 5);
24784 gen_load_gpr(t0, Rb);
24785 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24787 switch (optn3) {
24788 /* XRa[7:0] = tmp8 */
24789 case MXU_OPTN3_PTN0:
24790 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24791 gen_load_mxu_gpr(t0, XRa);
24792 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24793 break;
24794 /* XRa[15:8] = tmp8 */
24795 case MXU_OPTN3_PTN1:
24796 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24797 gen_load_mxu_gpr(t0, XRa);
24798 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24799 break;
24800 /* XRa[23:16] = tmp8 */
24801 case MXU_OPTN3_PTN2:
24802 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24803 gen_load_mxu_gpr(t0, XRa);
24804 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24805 break;
24806 /* XRa[31:24] = tmp8 */
24807 case MXU_OPTN3_PTN3:
24808 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24809 gen_load_mxu_gpr(t0, XRa);
24810 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24811 break;
24812 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24813 case MXU_OPTN3_PTN4:
24814 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24815 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24816 break;
24817 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24818 case MXU_OPTN3_PTN5:
24819 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24820 tcg_gen_shli_tl(t1, t1, 8);
24821 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24822 break;
24823 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24824 case MXU_OPTN3_PTN6:
24825 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24826 tcg_gen_mov_tl(t0, t1);
24827 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24828 tcg_gen_shli_tl(t1, t1, 16);
24829 tcg_gen_or_tl(t0, t0, t1);
24830 break;
24831 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24832 case MXU_OPTN3_PTN7:
24833 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24834 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24835 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24836 break;
24839 gen_store_mxu_gpr(t0, XRa);
24841 tcg_temp_free(t0);
24842 tcg_temp_free(t1);
24846 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24848 static void gen_mxu_d16mul(DisasContext *ctx)
24850 TCGv t0, t1, t2, t3;
24851 uint32_t XRa, XRb, XRc, XRd, optn2;
24853 t0 = tcg_temp_new();
24854 t1 = tcg_temp_new();
24855 t2 = tcg_temp_new();
24856 t3 = tcg_temp_new();
24858 XRa = extract32(ctx->opcode, 6, 4);
24859 XRb = extract32(ctx->opcode, 10, 4);
24860 XRc = extract32(ctx->opcode, 14, 4);
24861 XRd = extract32(ctx->opcode, 18, 4);
24862 optn2 = extract32(ctx->opcode, 22, 2);
24864 gen_load_mxu_gpr(t1, XRb);
24865 tcg_gen_sextract_tl(t0, t1, 0, 16);
24866 tcg_gen_sextract_tl(t1, t1, 16, 16);
24867 gen_load_mxu_gpr(t3, XRc);
24868 tcg_gen_sextract_tl(t2, t3, 0, 16);
24869 tcg_gen_sextract_tl(t3, t3, 16, 16);
24871 switch (optn2) {
24872 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24873 tcg_gen_mul_tl(t3, t1, t3);
24874 tcg_gen_mul_tl(t2, t0, t2);
24875 break;
24876 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24877 tcg_gen_mul_tl(t3, t0, t3);
24878 tcg_gen_mul_tl(t2, t0, t2);
24879 break;
24880 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24881 tcg_gen_mul_tl(t3, t1, t3);
24882 tcg_gen_mul_tl(t2, t1, t2);
24883 break;
24884 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24885 tcg_gen_mul_tl(t3, t0, t3);
24886 tcg_gen_mul_tl(t2, t1, t2);
24887 break;
24889 gen_store_mxu_gpr(t3, XRa);
24890 gen_store_mxu_gpr(t2, XRd);
24892 tcg_temp_free(t0);
24893 tcg_temp_free(t1);
24894 tcg_temp_free(t2);
24895 tcg_temp_free(t3);
24899 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
24900 * and accumulate
24902 static void gen_mxu_d16mac(DisasContext *ctx)
24904 TCGv t0, t1, t2, t3;
24905 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
24907 t0 = tcg_temp_new();
24908 t1 = tcg_temp_new();
24909 t2 = tcg_temp_new();
24910 t3 = tcg_temp_new();
24912 XRa = extract32(ctx->opcode, 6, 4);
24913 XRb = extract32(ctx->opcode, 10, 4);
24914 XRc = extract32(ctx->opcode, 14, 4);
24915 XRd = extract32(ctx->opcode, 18, 4);
24916 optn2 = extract32(ctx->opcode, 22, 2);
24917 aptn2 = extract32(ctx->opcode, 24, 2);
24919 gen_load_mxu_gpr(t1, XRb);
24920 tcg_gen_sextract_tl(t0, t1, 0, 16);
24921 tcg_gen_sextract_tl(t1, t1, 16, 16);
24923 gen_load_mxu_gpr(t3, XRc);
24924 tcg_gen_sextract_tl(t2, t3, 0, 16);
24925 tcg_gen_sextract_tl(t3, t3, 16, 16);
24927 switch (optn2) {
24928 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24929 tcg_gen_mul_tl(t3, t1, t3);
24930 tcg_gen_mul_tl(t2, t0, t2);
24931 break;
24932 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24933 tcg_gen_mul_tl(t3, t0, t3);
24934 tcg_gen_mul_tl(t2, t0, t2);
24935 break;
24936 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24937 tcg_gen_mul_tl(t3, t1, t3);
24938 tcg_gen_mul_tl(t2, t1, t2);
24939 break;
24940 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24941 tcg_gen_mul_tl(t3, t0, t3);
24942 tcg_gen_mul_tl(t2, t1, t2);
24943 break;
24945 gen_load_mxu_gpr(t0, XRa);
24946 gen_load_mxu_gpr(t1, XRd);
24948 switch (aptn2) {
24949 case MXU_APTN2_AA:
24950 tcg_gen_add_tl(t3, t0, t3);
24951 tcg_gen_add_tl(t2, t1, t2);
24952 break;
24953 case MXU_APTN2_AS:
24954 tcg_gen_add_tl(t3, t0, t3);
24955 tcg_gen_sub_tl(t2, t1, t2);
24956 break;
24957 case MXU_APTN2_SA:
24958 tcg_gen_sub_tl(t3, t0, t3);
24959 tcg_gen_add_tl(t2, t1, t2);
24960 break;
24961 case MXU_APTN2_SS:
24962 tcg_gen_sub_tl(t3, t0, t3);
24963 tcg_gen_sub_tl(t2, t1, t2);
24964 break;
24966 gen_store_mxu_gpr(t3, XRa);
24967 gen_store_mxu_gpr(t2, XRd);
24969 tcg_temp_free(t0);
24970 tcg_temp_free(t1);
24971 tcg_temp_free(t2);
24972 tcg_temp_free(t3);
24976 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
24977 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
24979 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
24981 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
24982 uint32_t XRa, XRb, XRc, XRd, sel;
24984 t0 = tcg_temp_new();
24985 t1 = tcg_temp_new();
24986 t2 = tcg_temp_new();
24987 t3 = tcg_temp_new();
24988 t4 = tcg_temp_new();
24989 t5 = tcg_temp_new();
24990 t6 = tcg_temp_new();
24991 t7 = tcg_temp_new();
24993 XRa = extract32(ctx->opcode, 6, 4);
24994 XRb = extract32(ctx->opcode, 10, 4);
24995 XRc = extract32(ctx->opcode, 14, 4);
24996 XRd = extract32(ctx->opcode, 18, 4);
24997 sel = extract32(ctx->opcode, 22, 2);
24999 gen_load_mxu_gpr(t3, XRb);
25000 gen_load_mxu_gpr(t7, XRc);
25002 if (sel == 0x2) {
25003 /* Q8MULSU */
25004 tcg_gen_ext8s_tl(t0, t3);
25005 tcg_gen_shri_tl(t3, t3, 8);
25006 tcg_gen_ext8s_tl(t1, t3);
25007 tcg_gen_shri_tl(t3, t3, 8);
25008 tcg_gen_ext8s_tl(t2, t3);
25009 tcg_gen_shri_tl(t3, t3, 8);
25010 tcg_gen_ext8s_tl(t3, t3);
25011 } else {
25012 /* Q8MUL */
25013 tcg_gen_ext8u_tl(t0, t3);
25014 tcg_gen_shri_tl(t3, t3, 8);
25015 tcg_gen_ext8u_tl(t1, t3);
25016 tcg_gen_shri_tl(t3, t3, 8);
25017 tcg_gen_ext8u_tl(t2, t3);
25018 tcg_gen_shri_tl(t3, t3, 8);
25019 tcg_gen_ext8u_tl(t3, t3);
25022 tcg_gen_ext8u_tl(t4, t7);
25023 tcg_gen_shri_tl(t7, t7, 8);
25024 tcg_gen_ext8u_tl(t5, t7);
25025 tcg_gen_shri_tl(t7, t7, 8);
25026 tcg_gen_ext8u_tl(t6, t7);
25027 tcg_gen_shri_tl(t7, t7, 8);
25028 tcg_gen_ext8u_tl(t7, t7);
25030 tcg_gen_mul_tl(t0, t0, t4);
25031 tcg_gen_mul_tl(t1, t1, t5);
25032 tcg_gen_mul_tl(t2, t2, t6);
25033 tcg_gen_mul_tl(t3, t3, t7);
25035 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25036 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25037 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25038 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25040 tcg_gen_shli_tl(t1, t1, 16);
25041 tcg_gen_shli_tl(t3, t3, 16);
25043 tcg_gen_or_tl(t0, t0, t1);
25044 tcg_gen_or_tl(t1, t2, t3);
25046 gen_store_mxu_gpr(t0, XRd);
25047 gen_store_mxu_gpr(t1, XRa);
25049 tcg_temp_free(t0);
25050 tcg_temp_free(t1);
25051 tcg_temp_free(t2);
25052 tcg_temp_free(t3);
25053 tcg_temp_free(t4);
25054 tcg_temp_free(t5);
25055 tcg_temp_free(t6);
25056 tcg_temp_free(t7);
25060 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25061 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25063 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25065 TCGv t0, t1;
25066 uint32_t XRa, Rb, s12, sel;
25068 t0 = tcg_temp_new();
25069 t1 = tcg_temp_new();
25071 XRa = extract32(ctx->opcode, 6, 4);
25072 s12 = extract32(ctx->opcode, 10, 10);
25073 sel = extract32(ctx->opcode, 20, 1);
25074 Rb = extract32(ctx->opcode, 21, 5);
25076 gen_load_gpr(t0, Rb);
25078 tcg_gen_movi_tl(t1, s12);
25079 tcg_gen_shli_tl(t1, t1, 2);
25080 if (s12 & 0x200) {
25081 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25083 tcg_gen_add_tl(t1, t0, t1);
25084 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25086 if (sel == 1) {
25087 /* S32LDDR */
25088 tcg_gen_bswap32_tl(t1, t1);
25090 gen_store_mxu_gpr(t1, XRa);
25092 tcg_temp_free(t0);
25093 tcg_temp_free(t1);
25098 * MXU instruction category: logic
25099 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25101 * S32NOR S32AND S32OR S32XOR
25105 * S32NOR XRa, XRb, XRc
25106 * Update XRa with the result of logical bitwise 'nor' operation
25107 * applied to the content of XRb and XRc.
25109 static void gen_mxu_S32NOR(DisasContext *ctx)
25111 uint32_t pad, XRc, XRb, XRa;
25113 pad = extract32(ctx->opcode, 21, 5);
25114 XRc = extract32(ctx->opcode, 14, 4);
25115 XRb = extract32(ctx->opcode, 10, 4);
25116 XRa = extract32(ctx->opcode, 6, 4);
25118 if (unlikely(pad != 0)) {
25119 /* opcode padding incorrect -> do nothing */
25120 } else if (unlikely(XRa == 0)) {
25121 /* destination is zero register -> do nothing */
25122 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25123 /* both operands zero registers -> just set destination to all 1s */
25124 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25125 } else if (unlikely(XRb == 0)) {
25126 /* XRb zero register -> just set destination to the negation of XRc */
25127 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25128 } else if (unlikely(XRc == 0)) {
25129 /* XRa zero register -> just set destination to the negation of XRb */
25130 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25131 } else if (unlikely(XRb == XRc)) {
25132 /* both operands same -> just set destination to the negation of XRb */
25133 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25134 } else {
25135 /* the most general case */
25136 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25141 * S32AND XRa, XRb, XRc
25142 * Update XRa with the result of logical bitwise 'and' operation
25143 * applied to the content of XRb and XRc.
25145 static void gen_mxu_S32AND(DisasContext *ctx)
25147 uint32_t pad, XRc, XRb, XRa;
25149 pad = extract32(ctx->opcode, 21, 5);
25150 XRc = extract32(ctx->opcode, 14, 4);
25151 XRb = extract32(ctx->opcode, 10, 4);
25152 XRa = extract32(ctx->opcode, 6, 4);
25154 if (unlikely(pad != 0)) {
25155 /* opcode padding incorrect -> do nothing */
25156 } else if (unlikely(XRa == 0)) {
25157 /* destination is zero register -> do nothing */
25158 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25159 /* one of operands zero register -> just set destination to all 0s */
25160 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25161 } else if (unlikely(XRb == XRc)) {
25162 /* both operands same -> just set destination to one of them */
25163 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25164 } else {
25165 /* the most general case */
25166 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25171 * S32OR XRa, XRb, XRc
25172 * Update XRa with the result of logical bitwise 'or' operation
25173 * applied to the content of XRb and XRc.
25175 static void gen_mxu_S32OR(DisasContext *ctx)
25177 uint32_t pad, XRc, XRb, XRa;
25179 pad = extract32(ctx->opcode, 21, 5);
25180 XRc = extract32(ctx->opcode, 14, 4);
25181 XRb = extract32(ctx->opcode, 10, 4);
25182 XRa = extract32(ctx->opcode, 6, 4);
25184 if (unlikely(pad != 0)) {
25185 /* opcode padding incorrect -> do nothing */
25186 } else if (unlikely(XRa == 0)) {
25187 /* destination is zero register -> do nothing */
25188 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25189 /* both operands zero registers -> just set destination to all 0s */
25190 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25191 } else if (unlikely(XRb == 0)) {
25192 /* XRb zero register -> just set destination to the content of XRc */
25193 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25194 } else if (unlikely(XRc == 0)) {
25195 /* XRc zero register -> just set destination to the content of XRb */
25196 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25197 } else if (unlikely(XRb == XRc)) {
25198 /* both operands same -> just set destination to one of them */
25199 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25200 } else {
25201 /* the most general case */
25202 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25207 * S32XOR XRa, XRb, XRc
25208 * Update XRa with the result of logical bitwise 'xor' operation
25209 * applied to the content of XRb and XRc.
25211 static void gen_mxu_S32XOR(DisasContext *ctx)
25213 uint32_t pad, XRc, XRb, XRa;
25215 pad = extract32(ctx->opcode, 21, 5);
25216 XRc = extract32(ctx->opcode, 14, 4);
25217 XRb = extract32(ctx->opcode, 10, 4);
25218 XRa = extract32(ctx->opcode, 6, 4);
25220 if (unlikely(pad != 0)) {
25221 /* opcode padding incorrect -> do nothing */
25222 } else if (unlikely(XRa == 0)) {
25223 /* destination is zero register -> do nothing */
25224 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25225 /* both operands zero registers -> just set destination to all 0s */
25226 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25227 } else if (unlikely(XRb == 0)) {
25228 /* XRb zero register -> just set destination to the content of XRc */
25229 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25230 } else if (unlikely(XRc == 0)) {
25231 /* XRc zero register -> just set destination to the content of XRb */
25232 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25233 } else if (unlikely(XRb == XRc)) {
25234 /* both operands same -> just set destination to all 0s */
25235 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25236 } else {
25237 /* the most general case */
25238 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25244 * MXU instruction category max/min
25245 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25247 * S32MAX D16MAX Q8MAX
25248 * S32MIN D16MIN Q8MIN
25252 * S32MAX XRa, XRb, XRc
25253 * Update XRa with the maximum of signed 32-bit integers contained
25254 * in XRb and XRc.
25256 * S32MIN XRa, XRb, XRc
25257 * Update XRa with the minimum of signed 32-bit integers contained
25258 * in XRb and XRc.
25260 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25262 uint32_t pad, opc, XRc, XRb, XRa;
25264 pad = extract32(ctx->opcode, 21, 5);
25265 opc = extract32(ctx->opcode, 18, 3);
25266 XRc = extract32(ctx->opcode, 14, 4);
25267 XRb = extract32(ctx->opcode, 10, 4);
25268 XRa = extract32(ctx->opcode, 6, 4);
25270 if (unlikely(pad != 0)) {
25271 /* opcode padding incorrect -> do nothing */
25272 } else if (unlikely(XRa == 0)) {
25273 /* destination is zero register -> do nothing */
25274 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25275 /* both operands zero registers -> just set destination to zero */
25276 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25277 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25278 /* exactly one operand is zero register - find which one is not...*/
25279 uint32_t XRx = XRb ? XRb : XRc;
25280 /* ...and do max/min operation with one operand 0 */
25281 if (opc == OPC_MXU_S32MAX) {
25282 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25283 } else {
25284 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25286 } else if (unlikely(XRb == XRc)) {
25287 /* both operands same -> just set destination to one of them */
25288 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25289 } else {
25290 /* the most general case */
25291 if (opc == OPC_MXU_S32MAX) {
25292 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25293 mxu_gpr[XRc - 1]);
25294 } else {
25295 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25296 mxu_gpr[XRc - 1]);
25302 * D16MAX
25303 * Update XRa with the 16-bit-wise maximums of signed integers
25304 * contained in XRb and XRc.
25306 * D16MIN
25307 * Update XRa with the 16-bit-wise minimums of signed integers
25308 * contained in XRb and XRc.
25310 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25312 uint32_t pad, opc, XRc, XRb, XRa;
25314 pad = extract32(ctx->opcode, 21, 5);
25315 opc = extract32(ctx->opcode, 18, 3);
25316 XRc = extract32(ctx->opcode, 14, 4);
25317 XRb = extract32(ctx->opcode, 10, 4);
25318 XRa = extract32(ctx->opcode, 6, 4);
25320 if (unlikely(pad != 0)) {
25321 /* opcode padding incorrect -> do nothing */
25322 } else if (unlikely(XRc == 0)) {
25323 /* destination is zero register -> do nothing */
25324 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25325 /* both operands zero registers -> just set destination to zero */
25326 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25327 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25328 /* exactly one operand is zero register - find which one is not...*/
25329 uint32_t XRx = XRb ? XRb : XRc;
25330 /* ...and do half-word-wise max/min with one operand 0 */
25331 TCGv_i32 t0 = tcg_temp_new();
25332 TCGv_i32 t1 = tcg_const_i32(0);
25334 /* the left half-word first */
25335 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25336 if (opc == OPC_MXU_D16MAX) {
25337 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25338 } else {
25339 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25342 /* the right half-word */
25343 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25344 /* move half-words to the leftmost position */
25345 tcg_gen_shli_i32(t0, t0, 16);
25346 /* t0 will be max/min of t0 and t1 */
25347 if (opc == OPC_MXU_D16MAX) {
25348 tcg_gen_smax_i32(t0, t0, t1);
25349 } else {
25350 tcg_gen_smin_i32(t0, t0, t1);
25352 /* return resulting half-words to its original position */
25353 tcg_gen_shri_i32(t0, t0, 16);
25354 /* finally update the destination */
25355 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25357 tcg_temp_free(t1);
25358 tcg_temp_free(t0);
25359 } else if (unlikely(XRb == XRc)) {
25360 /* both operands same -> just set destination to one of them */
25361 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25362 } else {
25363 /* the most general case */
25364 TCGv_i32 t0 = tcg_temp_new();
25365 TCGv_i32 t1 = tcg_temp_new();
25367 /* the left half-word first */
25368 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25369 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25370 if (opc == OPC_MXU_D16MAX) {
25371 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25372 } else {
25373 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25376 /* the right half-word */
25377 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25378 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25379 /* move half-words to the leftmost position */
25380 tcg_gen_shli_i32(t0, t0, 16);
25381 tcg_gen_shli_i32(t1, t1, 16);
25382 /* t0 will be max/min of t0 and t1 */
25383 if (opc == OPC_MXU_D16MAX) {
25384 tcg_gen_smax_i32(t0, t0, t1);
25385 } else {
25386 tcg_gen_smin_i32(t0, t0, t1);
25388 /* return resulting half-words to its original position */
25389 tcg_gen_shri_i32(t0, t0, 16);
25390 /* finally update the destination */
25391 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25393 tcg_temp_free(t1);
25394 tcg_temp_free(t0);
25399 * Q8MAX
25400 * Update XRa with the 8-bit-wise maximums of signed integers
25401 * contained in XRb and XRc.
25403 * Q8MIN
25404 * Update XRa with the 8-bit-wise minimums of signed integers
25405 * contained in XRb and XRc.
25407 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25409 uint32_t pad, opc, XRc, XRb, XRa;
25411 pad = extract32(ctx->opcode, 21, 5);
25412 opc = extract32(ctx->opcode, 18, 3);
25413 XRc = extract32(ctx->opcode, 14, 4);
25414 XRb = extract32(ctx->opcode, 10, 4);
25415 XRa = extract32(ctx->opcode, 6, 4);
25417 if (unlikely(pad != 0)) {
25418 /* opcode padding incorrect -> do nothing */
25419 } else if (unlikely(XRa == 0)) {
25420 /* destination is zero register -> do nothing */
25421 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25422 /* both operands zero registers -> just set destination to zero */
25423 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25424 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25425 /* exactly one operand is zero register - make it be the first...*/
25426 uint32_t XRx = XRb ? XRb : XRc;
25427 /* ...and do byte-wise max/min with one operand 0 */
25428 TCGv_i32 t0 = tcg_temp_new();
25429 TCGv_i32 t1 = tcg_const_i32(0);
25430 int32_t i;
25432 /* the leftmost byte (byte 3) first */
25433 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25434 if (opc == OPC_MXU_Q8MAX) {
25435 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25436 } else {
25437 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25440 /* bytes 2, 1, 0 */
25441 for (i = 2; i >= 0; i--) {
25442 /* extract the byte */
25443 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25444 /* move the byte to the leftmost position */
25445 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25446 /* t0 will be max/min of t0 and t1 */
25447 if (opc == OPC_MXU_Q8MAX) {
25448 tcg_gen_smax_i32(t0, t0, t1);
25449 } else {
25450 tcg_gen_smin_i32(t0, t0, t1);
25452 /* return resulting byte to its original position */
25453 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25454 /* finally update the destination */
25455 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25458 tcg_temp_free(t1);
25459 tcg_temp_free(t0);
25460 } else if (unlikely(XRb == XRc)) {
25461 /* both operands same -> just set destination to one of them */
25462 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25463 } else {
25464 /* the most general case */
25465 TCGv_i32 t0 = tcg_temp_new();
25466 TCGv_i32 t1 = tcg_temp_new();
25467 int32_t i;
25469 /* the leftmost bytes (bytes 3) first */
25470 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25471 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25472 if (opc == OPC_MXU_Q8MAX) {
25473 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25474 } else {
25475 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25478 /* bytes 2, 1, 0 */
25479 for (i = 2; i >= 0; i--) {
25480 /* extract corresponding bytes */
25481 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25482 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25483 /* move the bytes to the leftmost position */
25484 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25485 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25486 /* t0 will be max/min of t0 and t1 */
25487 if (opc == OPC_MXU_Q8MAX) {
25488 tcg_gen_smax_i32(t0, t0, t1);
25489 } else {
25490 tcg_gen_smin_i32(t0, t0, t1);
25492 /* return resulting byte to its original position */
25493 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25494 /* finally update the destination */
25495 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25498 tcg_temp_free(t1);
25499 tcg_temp_free(t0);
25505 * MXU instruction category: align
25506 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25508 * S32ALN S32ALNI
25512 * S32ALNI XRc, XRb, XRa, optn3
25513 * Arrange bytes from XRb and XRc according to one of five sets of
25514 * rules determined by optn3, and place the result in XRa.
25516 static void gen_mxu_S32ALNI(DisasContext *ctx)
25518 uint32_t optn3, pad, XRc, XRb, XRa;
25520 optn3 = extract32(ctx->opcode, 23, 3);
25521 pad = extract32(ctx->opcode, 21, 2);
25522 XRc = extract32(ctx->opcode, 14, 4);
25523 XRb = extract32(ctx->opcode, 10, 4);
25524 XRa = extract32(ctx->opcode, 6, 4);
25526 if (unlikely(pad != 0)) {
25527 /* opcode padding incorrect -> do nothing */
25528 } else if (unlikely(XRa == 0)) {
25529 /* destination is zero register -> do nothing */
25530 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25531 /* both operands zero registers -> just set destination to all 0s */
25532 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25533 } else if (unlikely(XRb == 0)) {
25534 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25535 switch (optn3) {
25536 case MXU_OPTN3_PTN0:
25537 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25538 break;
25539 case MXU_OPTN3_PTN1:
25540 case MXU_OPTN3_PTN2:
25541 case MXU_OPTN3_PTN3:
25542 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25543 8 * (4 - optn3));
25544 break;
25545 case MXU_OPTN3_PTN4:
25546 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25547 break;
25549 } else if (unlikely(XRc == 0)) {
25550 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25551 switch (optn3) {
25552 case MXU_OPTN3_PTN0:
25553 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25554 break;
25555 case MXU_OPTN3_PTN1:
25556 case MXU_OPTN3_PTN2:
25557 case MXU_OPTN3_PTN3:
25558 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25559 break;
25560 case MXU_OPTN3_PTN4:
25561 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25562 break;
25564 } else if (unlikely(XRb == XRc)) {
25565 /* both operands same -> just rotation or moving from any of them */
25566 switch (optn3) {
25567 case MXU_OPTN3_PTN0:
25568 case MXU_OPTN3_PTN4:
25569 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25570 break;
25571 case MXU_OPTN3_PTN1:
25572 case MXU_OPTN3_PTN2:
25573 case MXU_OPTN3_PTN3:
25574 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25575 break;
25577 } else {
25578 /* the most general case */
25579 switch (optn3) {
25580 case MXU_OPTN3_PTN0:
25582 /* */
25583 /* XRb XRc */
25584 /* +---------------+ */
25585 /* | A B C D | E F G H */
25586 /* +-------+-------+ */
25587 /* | */
25588 /* XRa */
25589 /* */
25591 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25593 break;
25594 case MXU_OPTN3_PTN1:
25596 /* */
25597 /* XRb XRc */
25598 /* +-------------------+ */
25599 /* A | B C D E | F G H */
25600 /* +---------+---------+ */
25601 /* | */
25602 /* XRa */
25603 /* */
25605 TCGv_i32 t0 = tcg_temp_new();
25606 TCGv_i32 t1 = tcg_temp_new();
25608 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25609 tcg_gen_shli_i32(t0, t0, 8);
25611 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25612 tcg_gen_shri_i32(t1, t1, 24);
25614 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25616 tcg_temp_free(t1);
25617 tcg_temp_free(t0);
25619 break;
25620 case MXU_OPTN3_PTN2:
25622 /* */
25623 /* XRb XRc */
25624 /* +-------------------+ */
25625 /* A B | C D E F | G H */
25626 /* +---------+---------+ */
25627 /* | */
25628 /* XRa */
25629 /* */
25631 TCGv_i32 t0 = tcg_temp_new();
25632 TCGv_i32 t1 = tcg_temp_new();
25634 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25635 tcg_gen_shli_i32(t0, t0, 16);
25637 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25638 tcg_gen_shri_i32(t1, t1, 16);
25640 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25642 tcg_temp_free(t1);
25643 tcg_temp_free(t0);
25645 break;
25646 case MXU_OPTN3_PTN3:
25648 /* */
25649 /* XRb XRc */
25650 /* +-------------------+ */
25651 /* A B C | D E F G | H */
25652 /* +---------+---------+ */
25653 /* | */
25654 /* XRa */
25655 /* */
25657 TCGv_i32 t0 = tcg_temp_new();
25658 TCGv_i32 t1 = tcg_temp_new();
25660 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25661 tcg_gen_shli_i32(t0, t0, 24);
25663 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25664 tcg_gen_shri_i32(t1, t1, 8);
25666 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25668 tcg_temp_free(t1);
25669 tcg_temp_free(t0);
25671 break;
25672 case MXU_OPTN3_PTN4:
25674 /* */
25675 /* XRb XRc */
25676 /* +---------------+ */
25677 /* A B C D | E F G H | */
25678 /* +-------+-------+ */
25679 /* | */
25680 /* XRa */
25681 /* */
25683 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25685 break;
25692 * Decoding engine for MXU
25693 * =======================
25696 static void decode_opc_mxu__pool00(DisasContext *ctx)
25698 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25700 switch (opcode) {
25701 case OPC_MXU_S32MAX:
25702 case OPC_MXU_S32MIN:
25703 gen_mxu_S32MAX_S32MIN(ctx);
25704 break;
25705 case OPC_MXU_D16MAX:
25706 case OPC_MXU_D16MIN:
25707 gen_mxu_D16MAX_D16MIN(ctx);
25708 break;
25709 case OPC_MXU_Q8MAX:
25710 case OPC_MXU_Q8MIN:
25711 gen_mxu_Q8MAX_Q8MIN(ctx);
25712 break;
25713 default:
25714 MIPS_INVAL("decode_opc_mxu");
25715 gen_reserved_instruction(ctx);
25716 break;
25720 static void decode_opc_mxu__pool04(DisasContext *ctx)
25722 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25724 switch (opcode) {
25725 case OPC_MXU_S32LDD:
25726 case OPC_MXU_S32LDDR:
25727 gen_mxu_s32ldd_s32lddr(ctx);
25728 break;
25729 default:
25730 MIPS_INVAL("decode_opc_mxu");
25731 gen_reserved_instruction(ctx);
25732 break;
25736 static void decode_opc_mxu__pool16(DisasContext *ctx)
25738 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25740 switch (opcode) {
25741 case OPC_MXU_S32ALNI:
25742 gen_mxu_S32ALNI(ctx);
25743 break;
25744 case OPC_MXU_S32NOR:
25745 gen_mxu_S32NOR(ctx);
25746 break;
25747 case OPC_MXU_S32AND:
25748 gen_mxu_S32AND(ctx);
25749 break;
25750 case OPC_MXU_S32OR:
25751 gen_mxu_S32OR(ctx);
25752 break;
25753 case OPC_MXU_S32XOR:
25754 gen_mxu_S32XOR(ctx);
25755 break;
25756 default:
25757 MIPS_INVAL("decode_opc_mxu");
25758 gen_reserved_instruction(ctx);
25759 break;
25763 static void decode_opc_mxu__pool19(DisasContext *ctx)
25765 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25767 switch (opcode) {
25768 case OPC_MXU_Q8MUL:
25769 case OPC_MXU_Q8MULSU:
25770 gen_mxu_q8mul_q8mulsu(ctx);
25771 break;
25772 default:
25773 MIPS_INVAL("decode_opc_mxu");
25774 gen_reserved_instruction(ctx);
25775 break;
25780 * Main MXU decoding function
25782 static void decode_opc_mxu(DisasContext *ctx, uint32_t insn)
25784 uint32_t opcode = extract32(insn, 0, 6);
25786 if (opcode == OPC_MXU_S32M2I) {
25787 gen_mxu_s32m2i(ctx);
25788 return;
25791 if (opcode == OPC_MXU_S32I2M) {
25792 gen_mxu_s32i2m(ctx);
25793 return;
25797 TCGv t_mxu_cr = tcg_temp_new();
25798 TCGLabel *l_exit = gen_new_label();
25800 gen_load_mxu_cr(t_mxu_cr);
25801 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
25802 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
25804 switch (opcode) {
25805 case OPC_MXU__POOL00:
25806 decode_opc_mxu__pool00(ctx);
25807 break;
25808 case OPC_MXU_D16MUL:
25809 gen_mxu_d16mul(ctx);
25810 break;
25811 case OPC_MXU_D16MAC:
25812 gen_mxu_d16mac(ctx);
25813 break;
25814 case OPC_MXU__POOL04:
25815 decode_opc_mxu__pool04(ctx);
25816 break;
25817 case OPC_MXU_S8LDD:
25818 gen_mxu_s8ldd(ctx);
25819 break;
25820 case OPC_MXU__POOL16:
25821 decode_opc_mxu__pool16(ctx);
25822 break;
25823 case OPC_MXU__POOL19:
25824 decode_opc_mxu__pool19(ctx);
25825 break;
25826 default:
25827 MIPS_INVAL("decode_opc_mxu");
25828 gen_reserved_instruction(ctx);
25831 gen_set_label(l_exit);
25832 tcg_temp_free(t_mxu_cr);
25836 #endif /* !defined(TARGET_MIPS64) */
25839 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
25841 int rs, rt, rd;
25842 uint32_t op1;
25844 rs = (ctx->opcode >> 21) & 0x1f;
25845 rt = (ctx->opcode >> 16) & 0x1f;
25846 rd = (ctx->opcode >> 11) & 0x1f;
25848 op1 = MASK_SPECIAL2(ctx->opcode);
25849 switch (op1) {
25850 case OPC_MADD: /* Multiply and add/sub */
25851 case OPC_MADDU:
25852 case OPC_MSUB:
25853 case OPC_MSUBU:
25854 check_insn(ctx, ISA_MIPS_R1);
25855 gen_muldiv(ctx, op1, rd & 3, rs, rt);
25856 break;
25857 case OPC_MUL:
25858 gen_arith(ctx, op1, rd, rs, rt);
25859 break;
25860 case OPC_DIV_G_2F:
25861 case OPC_DIVU_G_2F:
25862 case OPC_MULT_G_2F:
25863 case OPC_MULTU_G_2F:
25864 case OPC_MOD_G_2F:
25865 case OPC_MODU_G_2F:
25866 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
25867 gen_loongson_integer(ctx, op1, rd, rs, rt);
25868 break;
25869 case OPC_CLO:
25870 case OPC_CLZ:
25871 check_insn(ctx, ISA_MIPS_R1);
25872 gen_cl(ctx, op1, rd, rs);
25873 break;
25874 case OPC_SDBBP:
25875 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
25876 gen_helper_do_semihosting(cpu_env);
25877 } else {
25879 * XXX: not clear which exception should be raised
25880 * when in debug mode...
25882 check_insn(ctx, ISA_MIPS_R1);
25883 generate_exception_end(ctx, EXCP_DBp);
25885 break;
25886 #if defined(TARGET_MIPS64)
25887 case OPC_DCLO:
25888 case OPC_DCLZ:
25889 check_insn(ctx, ISA_MIPS_R1);
25890 check_mips_64(ctx);
25891 gen_cl(ctx, op1, rd, rs);
25892 break;
25893 case OPC_DMULT_G_2F:
25894 case OPC_DMULTU_G_2F:
25895 case OPC_DDIV_G_2F:
25896 case OPC_DDIVU_G_2F:
25897 case OPC_DMOD_G_2F:
25898 case OPC_DMODU_G_2F:
25899 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
25900 gen_loongson_integer(ctx, op1, rd, rs, rt);
25901 break;
25902 #endif
25903 default: /* Invalid */
25904 MIPS_INVAL("special2_legacy");
25905 gen_reserved_instruction(ctx);
25906 break;
25910 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
25912 int rs, rt, rd, sa;
25913 uint32_t op1, op2;
25914 int16_t imm;
25916 rs = (ctx->opcode >> 21) & 0x1f;
25917 rt = (ctx->opcode >> 16) & 0x1f;
25918 rd = (ctx->opcode >> 11) & 0x1f;
25919 sa = (ctx->opcode >> 6) & 0x1f;
25920 imm = (int16_t)ctx->opcode >> 7;
25922 op1 = MASK_SPECIAL3(ctx->opcode);
25923 switch (op1) {
25924 case R6_OPC_PREF:
25925 if (rt >= 24) {
25926 /* hint codes 24-31 are reserved and signal RI */
25927 gen_reserved_instruction(ctx);
25929 /* Treat as NOP. */
25930 break;
25931 case R6_OPC_CACHE:
25932 check_cp0_enabled(ctx);
25933 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25934 gen_cache_operation(ctx, rt, rs, imm);
25936 break;
25937 case R6_OPC_SC:
25938 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
25939 break;
25940 case R6_OPC_LL:
25941 gen_ld(ctx, op1, rt, rs, imm);
25942 break;
25943 case OPC_BSHFL:
25945 if (rd == 0) {
25946 /* Treat as NOP. */
25947 break;
25949 op2 = MASK_BSHFL(ctx->opcode);
25950 switch (op2) {
25951 case OPC_ALIGN:
25952 case OPC_ALIGN_1:
25953 case OPC_ALIGN_2:
25954 case OPC_ALIGN_3:
25955 gen_align(ctx, 32, rd, rs, rt, sa & 3);
25956 break;
25957 case OPC_BITSWAP:
25958 gen_bitswap(ctx, op2, rd, rt);
25959 break;
25962 break;
25963 #ifndef CONFIG_USER_ONLY
25964 case OPC_GINV:
25965 if (unlikely(ctx->gi <= 1)) {
25966 gen_reserved_instruction(ctx);
25968 check_cp0_enabled(ctx);
25969 switch ((ctx->opcode >> 6) & 3) {
25970 case 0: /* GINVI */
25971 /* Treat as NOP. */
25972 break;
25973 case 2: /* GINVT */
25974 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
25975 break;
25976 default:
25977 gen_reserved_instruction(ctx);
25978 break;
25980 break;
25981 #endif
25982 #if defined(TARGET_MIPS64)
25983 case R6_OPC_SCD:
25984 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
25985 break;
25986 case R6_OPC_LLD:
25987 gen_ld(ctx, op1, rt, rs, imm);
25988 break;
25989 case OPC_DBSHFL:
25990 check_mips_64(ctx);
25992 if (rd == 0) {
25993 /* Treat as NOP. */
25994 break;
25996 op2 = MASK_DBSHFL(ctx->opcode);
25997 switch (op2) {
25998 case OPC_DALIGN:
25999 case OPC_DALIGN_1:
26000 case OPC_DALIGN_2:
26001 case OPC_DALIGN_3:
26002 case OPC_DALIGN_4:
26003 case OPC_DALIGN_5:
26004 case OPC_DALIGN_6:
26005 case OPC_DALIGN_7:
26006 gen_align(ctx, 64, rd, rs, rt, sa & 7);
26007 break;
26008 case OPC_DBITSWAP:
26009 gen_bitswap(ctx, op2, rd, rt);
26010 break;
26014 break;
26015 #endif
26016 default: /* Invalid */
26017 MIPS_INVAL("special3_r6");
26018 gen_reserved_instruction(ctx);
26019 break;
26023 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
26025 int rs, rt, rd;
26026 uint32_t op1, op2;
26028 rs = (ctx->opcode >> 21) & 0x1f;
26029 rt = (ctx->opcode >> 16) & 0x1f;
26030 rd = (ctx->opcode >> 11) & 0x1f;
26032 op1 = MASK_SPECIAL3(ctx->opcode);
26033 switch (op1) {
26034 case OPC_DIV_G_2E:
26035 case OPC_DIVU_G_2E:
26036 case OPC_MOD_G_2E:
26037 case OPC_MODU_G_2E:
26038 case OPC_MULT_G_2E:
26039 case OPC_MULTU_G_2E:
26041 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
26042 * the same mask and op1.
26044 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
26045 op2 = MASK_ADDUH_QB(ctx->opcode);
26046 switch (op2) {
26047 case OPC_ADDUH_QB:
26048 case OPC_ADDUH_R_QB:
26049 case OPC_ADDQH_PH:
26050 case OPC_ADDQH_R_PH:
26051 case OPC_ADDQH_W:
26052 case OPC_ADDQH_R_W:
26053 case OPC_SUBUH_QB:
26054 case OPC_SUBUH_R_QB:
26055 case OPC_SUBQH_PH:
26056 case OPC_SUBQH_R_PH:
26057 case OPC_SUBQH_W:
26058 case OPC_SUBQH_R_W:
26059 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26060 break;
26061 case OPC_MUL_PH:
26062 case OPC_MUL_S_PH:
26063 case OPC_MULQ_S_W:
26064 case OPC_MULQ_RS_W:
26065 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26066 break;
26067 default:
26068 MIPS_INVAL("MASK ADDUH.QB");
26069 gen_reserved_instruction(ctx);
26070 break;
26072 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
26073 gen_loongson_integer(ctx, op1, rd, rs, rt);
26074 } else {
26075 gen_reserved_instruction(ctx);
26077 break;
26078 case OPC_LX_DSP:
26079 op2 = MASK_LX(ctx->opcode);
26080 switch (op2) {
26081 #if defined(TARGET_MIPS64)
26082 case OPC_LDX:
26083 #endif
26084 case OPC_LBUX:
26085 case OPC_LHX:
26086 case OPC_LWX:
26087 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
26088 break;
26089 default: /* Invalid */
26090 MIPS_INVAL("MASK LX");
26091 gen_reserved_instruction(ctx);
26092 break;
26094 break;
26095 case OPC_ABSQ_S_PH_DSP:
26096 op2 = MASK_ABSQ_S_PH(ctx->opcode);
26097 switch (op2) {
26098 case OPC_ABSQ_S_QB:
26099 case OPC_ABSQ_S_PH:
26100 case OPC_ABSQ_S_W:
26101 case OPC_PRECEQ_W_PHL:
26102 case OPC_PRECEQ_W_PHR:
26103 case OPC_PRECEQU_PH_QBL:
26104 case OPC_PRECEQU_PH_QBR:
26105 case OPC_PRECEQU_PH_QBLA:
26106 case OPC_PRECEQU_PH_QBRA:
26107 case OPC_PRECEU_PH_QBL:
26108 case OPC_PRECEU_PH_QBR:
26109 case OPC_PRECEU_PH_QBLA:
26110 case OPC_PRECEU_PH_QBRA:
26111 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26112 break;
26113 case OPC_BITREV:
26114 case OPC_REPL_QB:
26115 case OPC_REPLV_QB:
26116 case OPC_REPL_PH:
26117 case OPC_REPLV_PH:
26118 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
26119 break;
26120 default:
26121 MIPS_INVAL("MASK ABSQ_S.PH");
26122 gen_reserved_instruction(ctx);
26123 break;
26125 break;
26126 case OPC_ADDU_QB_DSP:
26127 op2 = MASK_ADDU_QB(ctx->opcode);
26128 switch (op2) {
26129 case OPC_ADDQ_PH:
26130 case OPC_ADDQ_S_PH:
26131 case OPC_ADDQ_S_W:
26132 case OPC_ADDU_QB:
26133 case OPC_ADDU_S_QB:
26134 case OPC_ADDU_PH:
26135 case OPC_ADDU_S_PH:
26136 case OPC_SUBQ_PH:
26137 case OPC_SUBQ_S_PH:
26138 case OPC_SUBQ_S_W:
26139 case OPC_SUBU_QB:
26140 case OPC_SUBU_S_QB:
26141 case OPC_SUBU_PH:
26142 case OPC_SUBU_S_PH:
26143 case OPC_ADDSC:
26144 case OPC_ADDWC:
26145 case OPC_MODSUB:
26146 case OPC_RADDU_W_QB:
26147 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26148 break;
26149 case OPC_MULEU_S_PH_QBL:
26150 case OPC_MULEU_S_PH_QBR:
26151 case OPC_MULQ_RS_PH:
26152 case OPC_MULEQ_S_W_PHL:
26153 case OPC_MULEQ_S_W_PHR:
26154 case OPC_MULQ_S_PH:
26155 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26156 break;
26157 default: /* Invalid */
26158 MIPS_INVAL("MASK ADDU.QB");
26159 gen_reserved_instruction(ctx);
26160 break;
26163 break;
26164 case OPC_CMPU_EQ_QB_DSP:
26165 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
26166 switch (op2) {
26167 case OPC_PRECR_SRA_PH_W:
26168 case OPC_PRECR_SRA_R_PH_W:
26169 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
26170 break;
26171 case OPC_PRECR_QB_PH:
26172 case OPC_PRECRQ_QB_PH:
26173 case OPC_PRECRQ_PH_W:
26174 case OPC_PRECRQ_RS_PH_W:
26175 case OPC_PRECRQU_S_QB_PH:
26176 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26177 break;
26178 case OPC_CMPU_EQ_QB:
26179 case OPC_CMPU_LT_QB:
26180 case OPC_CMPU_LE_QB:
26181 case OPC_CMP_EQ_PH:
26182 case OPC_CMP_LT_PH:
26183 case OPC_CMP_LE_PH:
26184 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
26185 break;
26186 case OPC_CMPGU_EQ_QB:
26187 case OPC_CMPGU_LT_QB:
26188 case OPC_CMPGU_LE_QB:
26189 case OPC_CMPGDU_EQ_QB:
26190 case OPC_CMPGDU_LT_QB:
26191 case OPC_CMPGDU_LE_QB:
26192 case OPC_PICK_QB:
26193 case OPC_PICK_PH:
26194 case OPC_PACKRL_PH:
26195 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
26196 break;
26197 default: /* Invalid */
26198 MIPS_INVAL("MASK CMPU.EQ.QB");
26199 gen_reserved_instruction(ctx);
26200 break;
26202 break;
26203 case OPC_SHLL_QB_DSP:
26204 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
26205 break;
26206 case OPC_DPA_W_PH_DSP:
26207 op2 = MASK_DPA_W_PH(ctx->opcode);
26208 switch (op2) {
26209 case OPC_DPAU_H_QBL:
26210 case OPC_DPAU_H_QBR:
26211 case OPC_DPSU_H_QBL:
26212 case OPC_DPSU_H_QBR:
26213 case OPC_DPA_W_PH:
26214 case OPC_DPAX_W_PH:
26215 case OPC_DPAQ_S_W_PH:
26216 case OPC_DPAQX_S_W_PH:
26217 case OPC_DPAQX_SA_W_PH:
26218 case OPC_DPS_W_PH:
26219 case OPC_DPSX_W_PH:
26220 case OPC_DPSQ_S_W_PH:
26221 case OPC_DPSQX_S_W_PH:
26222 case OPC_DPSQX_SA_W_PH:
26223 case OPC_MULSAQ_S_W_PH:
26224 case OPC_DPAQ_SA_L_W:
26225 case OPC_DPSQ_SA_L_W:
26226 case OPC_MAQ_S_W_PHL:
26227 case OPC_MAQ_S_W_PHR:
26228 case OPC_MAQ_SA_W_PHL:
26229 case OPC_MAQ_SA_W_PHR:
26230 case OPC_MULSA_W_PH:
26231 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26232 break;
26233 default: /* Invalid */
26234 MIPS_INVAL("MASK DPAW.PH");
26235 gen_reserved_instruction(ctx);
26236 break;
26238 break;
26239 case OPC_INSV_DSP:
26240 op2 = MASK_INSV(ctx->opcode);
26241 switch (op2) {
26242 case OPC_INSV:
26243 check_dsp(ctx);
26245 TCGv t0, t1;
26247 if (rt == 0) {
26248 break;
26251 t0 = tcg_temp_new();
26252 t1 = tcg_temp_new();
26254 gen_load_gpr(t0, rt);
26255 gen_load_gpr(t1, rs);
26257 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
26259 tcg_temp_free(t0);
26260 tcg_temp_free(t1);
26261 break;
26263 default: /* Invalid */
26264 MIPS_INVAL("MASK INSV");
26265 gen_reserved_instruction(ctx);
26266 break;
26268 break;
26269 case OPC_APPEND_DSP:
26270 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
26271 break;
26272 case OPC_EXTR_W_DSP:
26273 op2 = MASK_EXTR_W(ctx->opcode);
26274 switch (op2) {
26275 case OPC_EXTR_W:
26276 case OPC_EXTR_R_W:
26277 case OPC_EXTR_RS_W:
26278 case OPC_EXTR_S_H:
26279 case OPC_EXTRV_S_H:
26280 case OPC_EXTRV_W:
26281 case OPC_EXTRV_R_W:
26282 case OPC_EXTRV_RS_W:
26283 case OPC_EXTP:
26284 case OPC_EXTPV:
26285 case OPC_EXTPDP:
26286 case OPC_EXTPDPV:
26287 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
26288 break;
26289 case OPC_RDDSP:
26290 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
26291 break;
26292 case OPC_SHILO:
26293 case OPC_SHILOV:
26294 case OPC_MTHLIP:
26295 case OPC_WRDSP:
26296 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
26297 break;
26298 default: /* Invalid */
26299 MIPS_INVAL("MASK EXTR.W");
26300 gen_reserved_instruction(ctx);
26301 break;
26303 break;
26304 #if defined(TARGET_MIPS64)
26305 case OPC_DDIV_G_2E:
26306 case OPC_DDIVU_G_2E:
26307 case OPC_DMULT_G_2E:
26308 case OPC_DMULTU_G_2E:
26309 case OPC_DMOD_G_2E:
26310 case OPC_DMODU_G_2E:
26311 check_insn(ctx, INSN_LOONGSON2E);
26312 gen_loongson_integer(ctx, op1, rd, rs, rt);
26313 break;
26314 case OPC_ABSQ_S_QH_DSP:
26315 op2 = MASK_ABSQ_S_QH(ctx->opcode);
26316 switch (op2) {
26317 case OPC_PRECEQ_L_PWL:
26318 case OPC_PRECEQ_L_PWR:
26319 case OPC_PRECEQ_PW_QHL:
26320 case OPC_PRECEQ_PW_QHR:
26321 case OPC_PRECEQ_PW_QHLA:
26322 case OPC_PRECEQ_PW_QHRA:
26323 case OPC_PRECEQU_QH_OBL:
26324 case OPC_PRECEQU_QH_OBR:
26325 case OPC_PRECEQU_QH_OBLA:
26326 case OPC_PRECEQU_QH_OBRA:
26327 case OPC_PRECEU_QH_OBL:
26328 case OPC_PRECEU_QH_OBR:
26329 case OPC_PRECEU_QH_OBLA:
26330 case OPC_PRECEU_QH_OBRA:
26331 case OPC_ABSQ_S_OB:
26332 case OPC_ABSQ_S_PW:
26333 case OPC_ABSQ_S_QH:
26334 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26335 break;
26336 case OPC_REPL_OB:
26337 case OPC_REPL_PW:
26338 case OPC_REPL_QH:
26339 case OPC_REPLV_OB:
26340 case OPC_REPLV_PW:
26341 case OPC_REPLV_QH:
26342 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
26343 break;
26344 default: /* Invalid */
26345 MIPS_INVAL("MASK ABSQ_S.QH");
26346 gen_reserved_instruction(ctx);
26347 break;
26349 break;
26350 case OPC_ADDU_OB_DSP:
26351 op2 = MASK_ADDU_OB(ctx->opcode);
26352 switch (op2) {
26353 case OPC_RADDU_L_OB:
26354 case OPC_SUBQ_PW:
26355 case OPC_SUBQ_S_PW:
26356 case OPC_SUBQ_QH:
26357 case OPC_SUBQ_S_QH:
26358 case OPC_SUBU_OB:
26359 case OPC_SUBU_S_OB:
26360 case OPC_SUBU_QH:
26361 case OPC_SUBU_S_QH:
26362 case OPC_SUBUH_OB:
26363 case OPC_SUBUH_R_OB:
26364 case OPC_ADDQ_PW:
26365 case OPC_ADDQ_S_PW:
26366 case OPC_ADDQ_QH:
26367 case OPC_ADDQ_S_QH:
26368 case OPC_ADDU_OB:
26369 case OPC_ADDU_S_OB:
26370 case OPC_ADDU_QH:
26371 case OPC_ADDU_S_QH:
26372 case OPC_ADDUH_OB:
26373 case OPC_ADDUH_R_OB:
26374 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26375 break;
26376 case OPC_MULEQ_S_PW_QHL:
26377 case OPC_MULEQ_S_PW_QHR:
26378 case OPC_MULEU_S_QH_OBL:
26379 case OPC_MULEU_S_QH_OBR:
26380 case OPC_MULQ_RS_QH:
26381 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26382 break;
26383 default: /* Invalid */
26384 MIPS_INVAL("MASK ADDU.OB");
26385 gen_reserved_instruction(ctx);
26386 break;
26388 break;
26389 case OPC_CMPU_EQ_OB_DSP:
26390 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
26391 switch (op2) {
26392 case OPC_PRECR_SRA_QH_PW:
26393 case OPC_PRECR_SRA_R_QH_PW:
26394 /* Return value is rt. */
26395 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
26396 break;
26397 case OPC_PRECR_OB_QH:
26398 case OPC_PRECRQ_OB_QH:
26399 case OPC_PRECRQ_PW_L:
26400 case OPC_PRECRQ_QH_PW:
26401 case OPC_PRECRQ_RS_QH_PW:
26402 case OPC_PRECRQU_S_OB_QH:
26403 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26404 break;
26405 case OPC_CMPU_EQ_OB:
26406 case OPC_CMPU_LT_OB:
26407 case OPC_CMPU_LE_OB:
26408 case OPC_CMP_EQ_QH:
26409 case OPC_CMP_LT_QH:
26410 case OPC_CMP_LE_QH:
26411 case OPC_CMP_EQ_PW:
26412 case OPC_CMP_LT_PW:
26413 case OPC_CMP_LE_PW:
26414 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
26415 break;
26416 case OPC_CMPGDU_EQ_OB:
26417 case OPC_CMPGDU_LT_OB:
26418 case OPC_CMPGDU_LE_OB:
26419 case OPC_CMPGU_EQ_OB:
26420 case OPC_CMPGU_LT_OB:
26421 case OPC_CMPGU_LE_OB:
26422 case OPC_PACKRL_PW:
26423 case OPC_PICK_OB:
26424 case OPC_PICK_PW:
26425 case OPC_PICK_QH:
26426 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
26427 break;
26428 default: /* Invalid */
26429 MIPS_INVAL("MASK CMPU_EQ.OB");
26430 gen_reserved_instruction(ctx);
26431 break;
26433 break;
26434 case OPC_DAPPEND_DSP:
26435 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
26436 break;
26437 case OPC_DEXTR_W_DSP:
26438 op2 = MASK_DEXTR_W(ctx->opcode);
26439 switch (op2) {
26440 case OPC_DEXTP:
26441 case OPC_DEXTPDP:
26442 case OPC_DEXTPDPV:
26443 case OPC_DEXTPV:
26444 case OPC_DEXTR_L:
26445 case OPC_DEXTR_R_L:
26446 case OPC_DEXTR_RS_L:
26447 case OPC_DEXTR_W:
26448 case OPC_DEXTR_R_W:
26449 case OPC_DEXTR_RS_W:
26450 case OPC_DEXTR_S_H:
26451 case OPC_DEXTRV_L:
26452 case OPC_DEXTRV_R_L:
26453 case OPC_DEXTRV_RS_L:
26454 case OPC_DEXTRV_S_H:
26455 case OPC_DEXTRV_W:
26456 case OPC_DEXTRV_R_W:
26457 case OPC_DEXTRV_RS_W:
26458 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
26459 break;
26460 case OPC_DMTHLIP:
26461 case OPC_DSHILO:
26462 case OPC_DSHILOV:
26463 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
26464 break;
26465 default: /* Invalid */
26466 MIPS_INVAL("MASK EXTR.W");
26467 gen_reserved_instruction(ctx);
26468 break;
26470 break;
26471 case OPC_DPAQ_W_QH_DSP:
26472 op2 = MASK_DPAQ_W_QH(ctx->opcode);
26473 switch (op2) {
26474 case OPC_DPAU_H_OBL:
26475 case OPC_DPAU_H_OBR:
26476 case OPC_DPSU_H_OBL:
26477 case OPC_DPSU_H_OBR:
26478 case OPC_DPA_W_QH:
26479 case OPC_DPAQ_S_W_QH:
26480 case OPC_DPS_W_QH:
26481 case OPC_DPSQ_S_W_QH:
26482 case OPC_MULSAQ_S_W_QH:
26483 case OPC_DPAQ_SA_L_PW:
26484 case OPC_DPSQ_SA_L_PW:
26485 case OPC_MULSAQ_S_L_PW:
26486 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26487 break;
26488 case OPC_MAQ_S_W_QHLL:
26489 case OPC_MAQ_S_W_QHLR:
26490 case OPC_MAQ_S_W_QHRL:
26491 case OPC_MAQ_S_W_QHRR:
26492 case OPC_MAQ_SA_W_QHLL:
26493 case OPC_MAQ_SA_W_QHLR:
26494 case OPC_MAQ_SA_W_QHRL:
26495 case OPC_MAQ_SA_W_QHRR:
26496 case OPC_MAQ_S_L_PWL:
26497 case OPC_MAQ_S_L_PWR:
26498 case OPC_DMADD:
26499 case OPC_DMADDU:
26500 case OPC_DMSUB:
26501 case OPC_DMSUBU:
26502 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26503 break;
26504 default: /* Invalid */
26505 MIPS_INVAL("MASK DPAQ.W.QH");
26506 gen_reserved_instruction(ctx);
26507 break;
26509 break;
26510 case OPC_DINSV_DSP:
26511 op2 = MASK_INSV(ctx->opcode);
26512 switch (op2) {
26513 case OPC_DINSV:
26515 TCGv t0, t1;
26517 if (rt == 0) {
26518 break;
26520 check_dsp(ctx);
26522 t0 = tcg_temp_new();
26523 t1 = tcg_temp_new();
26525 gen_load_gpr(t0, rt);
26526 gen_load_gpr(t1, rs);
26528 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
26530 tcg_temp_free(t0);
26531 tcg_temp_free(t1);
26532 break;
26534 default: /* Invalid */
26535 MIPS_INVAL("MASK DINSV");
26536 gen_reserved_instruction(ctx);
26537 break;
26539 break;
26540 case OPC_SHLL_OB_DSP:
26541 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
26542 break;
26543 #endif
26544 default: /* Invalid */
26545 MIPS_INVAL("special3_legacy");
26546 gen_reserved_instruction(ctx);
26547 break;
26552 #if defined(TARGET_MIPS64)
26554 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
26556 uint32_t opc = MASK_MMI0(ctx->opcode);
26558 switch (opc) {
26559 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
26560 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
26561 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
26562 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
26563 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
26564 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
26565 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
26566 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
26567 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
26568 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
26569 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
26570 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
26571 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
26572 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
26573 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
26574 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
26575 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
26576 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
26577 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
26578 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
26579 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
26580 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
26581 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
26582 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
26583 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
26584 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI0 */
26585 break;
26586 default:
26587 MIPS_INVAL("TX79 MMI class MMI0");
26588 gen_reserved_instruction(ctx);
26589 break;
26593 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
26595 uint32_t opc = MASK_MMI1(ctx->opcode);
26597 switch (opc) {
26598 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
26599 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
26600 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
26601 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
26602 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
26603 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
26604 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
26605 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
26606 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
26607 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
26608 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
26609 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
26610 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
26611 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
26612 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
26613 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
26614 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
26615 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
26616 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI1 */
26617 break;
26618 default:
26619 MIPS_INVAL("TX79 MMI class MMI1");
26620 gen_reserved_instruction(ctx);
26621 break;
26625 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
26627 uint32_t opc = MASK_MMI2(ctx->opcode);
26629 switch (opc) {
26630 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
26631 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
26632 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
26633 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
26634 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
26635 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
26636 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
26637 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
26638 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
26639 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
26640 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
26641 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
26642 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
26643 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
26644 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
26645 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
26646 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
26647 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
26648 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
26649 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
26650 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
26651 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI2 */
26652 break;
26653 case MMI_OPC_2_PCPYLD:
26654 gen_mmi_pcpyld(ctx);
26655 break;
26656 default:
26657 MIPS_INVAL("TX79 MMI class MMI2");
26658 gen_reserved_instruction(ctx);
26659 break;
26663 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
26665 uint32_t opc = MASK_MMI3(ctx->opcode);
26667 switch (opc) {
26668 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
26669 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
26670 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
26671 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
26672 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
26673 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
26674 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
26675 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
26676 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
26677 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
26678 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
26679 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI3 */
26680 break;
26681 case MMI_OPC_3_PCPYH:
26682 gen_mmi_pcpyh(ctx);
26683 break;
26684 case MMI_OPC_3_PCPYUD:
26685 gen_mmi_pcpyud(ctx);
26686 break;
26687 default:
26688 MIPS_INVAL("TX79 MMI class MMI3");
26689 gen_reserved_instruction(ctx);
26690 break;
26694 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
26696 uint32_t opc = MASK_MMI(ctx->opcode);
26697 int rs = extract32(ctx->opcode, 21, 5);
26698 int rt = extract32(ctx->opcode, 16, 5);
26699 int rd = extract32(ctx->opcode, 11, 5);
26701 switch (opc) {
26702 case MMI_OPC_CLASS_MMI0:
26703 decode_mmi0(env, ctx);
26704 break;
26705 case MMI_OPC_CLASS_MMI1:
26706 decode_mmi1(env, ctx);
26707 break;
26708 case MMI_OPC_CLASS_MMI2:
26709 decode_mmi2(env, ctx);
26710 break;
26711 case MMI_OPC_CLASS_MMI3:
26712 decode_mmi3(env, ctx);
26713 break;
26714 case MMI_OPC_MULT1:
26715 case MMI_OPC_MULTU1:
26716 case MMI_OPC_MADD:
26717 case MMI_OPC_MADDU:
26718 case MMI_OPC_MADD1:
26719 case MMI_OPC_MADDU1:
26720 gen_mul_txx9(ctx, opc, rd, rs, rt);
26721 break;
26722 case MMI_OPC_DIV1:
26723 case MMI_OPC_DIVU1:
26724 gen_div1_tx79(ctx, opc, rs, rt);
26725 break;
26726 case MMI_OPC_MTLO1:
26727 case MMI_OPC_MTHI1:
26728 gen_HILO1_tx79(ctx, opc, rs);
26729 break;
26730 case MMI_OPC_MFLO1:
26731 case MMI_OPC_MFHI1:
26732 gen_HILO1_tx79(ctx, opc, rd);
26733 break;
26734 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
26735 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
26736 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
26737 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
26738 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
26739 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
26740 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
26741 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
26742 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
26743 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI */
26744 break;
26745 default:
26746 MIPS_INVAL("TX79 MMI class");
26747 gen_reserved_instruction(ctx);
26748 break;
26752 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
26754 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_LQ */
26757 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
26759 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
26763 * The TX79-specific instruction Store Quadword
26765 * +--------+-------+-------+------------------------+
26766 * | 011111 | base | rt | offset | SQ
26767 * +--------+-------+-------+------------------------+
26768 * 6 5 5 16
26770 * has the same opcode as the Read Hardware Register instruction
26772 * +--------+-------+-------+-------+-------+--------+
26773 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
26774 * +--------+-------+-------+-------+-------+--------+
26775 * 6 5 5 5 5 6
26777 * that is required, trapped and emulated by the Linux kernel. However, all
26778 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
26779 * offset is odd. Therefore all valid SQ instructions can execute normally.
26780 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
26781 * between SQ and RDHWR, as the Linux kernel does.
26783 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
26785 int base = extract32(ctx->opcode, 21, 5);
26786 int rt = extract32(ctx->opcode, 16, 5);
26787 int offset = extract32(ctx->opcode, 0, 16);
26789 #ifdef CONFIG_USER_ONLY
26790 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
26791 uint32_t op2 = extract32(ctx->opcode, 6, 5);
26793 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
26794 int rd = extract32(ctx->opcode, 11, 5);
26796 gen_rdhwr(ctx, rt, rd, 0);
26797 return;
26799 #endif
26801 gen_mmi_sq(ctx, base, rt, offset);
26804 #endif
26806 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
26808 int rs, rt, rd, sa;
26809 uint32_t op1, op2;
26810 int16_t imm;
26812 rs = (ctx->opcode >> 21) & 0x1f;
26813 rt = (ctx->opcode >> 16) & 0x1f;
26814 rd = (ctx->opcode >> 11) & 0x1f;
26815 sa = (ctx->opcode >> 6) & 0x1f;
26816 imm = sextract32(ctx->opcode, 7, 9);
26818 op1 = MASK_SPECIAL3(ctx->opcode);
26821 * EVA loads and stores overlap Loongson 2E instructions decoded by
26822 * decode_opc_special3_legacy(), so be careful to allow their decoding when
26823 * EVA is absent.
26825 if (ctx->eva) {
26826 switch (op1) {
26827 case OPC_LWLE:
26828 case OPC_LWRE:
26829 case OPC_LBUE:
26830 case OPC_LHUE:
26831 case OPC_LBE:
26832 case OPC_LHE:
26833 case OPC_LLE:
26834 case OPC_LWE:
26835 check_cp0_enabled(ctx);
26836 gen_ld(ctx, op1, rt, rs, imm);
26837 return;
26838 case OPC_SWLE:
26839 case OPC_SWRE:
26840 case OPC_SBE:
26841 case OPC_SHE:
26842 case OPC_SWE:
26843 check_cp0_enabled(ctx);
26844 gen_st(ctx, op1, rt, rs, imm);
26845 return;
26846 case OPC_SCE:
26847 check_cp0_enabled(ctx);
26848 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
26849 return;
26850 case OPC_CACHEE:
26851 check_cp0_enabled(ctx);
26852 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26853 gen_cache_operation(ctx, rt, rs, imm);
26855 /* Treat as NOP. */
26856 return;
26857 case OPC_PREFE:
26858 check_cp0_enabled(ctx);
26859 /* Treat as NOP. */
26860 return;
26864 switch (op1) {
26865 case OPC_EXT:
26866 case OPC_INS:
26867 check_insn(ctx, ISA_MIPS_R2);
26868 gen_bitops(ctx, op1, rt, rs, sa, rd);
26869 break;
26870 case OPC_BSHFL:
26871 op2 = MASK_BSHFL(ctx->opcode);
26872 switch (op2) {
26873 case OPC_ALIGN:
26874 case OPC_ALIGN_1:
26875 case OPC_ALIGN_2:
26876 case OPC_ALIGN_3:
26877 case OPC_BITSWAP:
26878 check_insn(ctx, ISA_MIPS_R6);
26879 decode_opc_special3_r6(env, ctx);
26880 break;
26881 default:
26882 check_insn(ctx, ISA_MIPS_R2);
26883 gen_bshfl(ctx, op2, rt, rd);
26884 break;
26886 break;
26887 #if defined(TARGET_MIPS64)
26888 case OPC_DEXTM:
26889 case OPC_DEXTU:
26890 case OPC_DEXT:
26891 case OPC_DINSM:
26892 case OPC_DINSU:
26893 case OPC_DINS:
26894 check_insn(ctx, ISA_MIPS_R2);
26895 check_mips_64(ctx);
26896 gen_bitops(ctx, op1, rt, rs, sa, rd);
26897 break;
26898 case OPC_DBSHFL:
26899 op2 = MASK_DBSHFL(ctx->opcode);
26900 switch (op2) {
26901 case OPC_DALIGN:
26902 case OPC_DALIGN_1:
26903 case OPC_DALIGN_2:
26904 case OPC_DALIGN_3:
26905 case OPC_DALIGN_4:
26906 case OPC_DALIGN_5:
26907 case OPC_DALIGN_6:
26908 case OPC_DALIGN_7:
26909 case OPC_DBITSWAP:
26910 check_insn(ctx, ISA_MIPS_R6);
26911 decode_opc_special3_r6(env, ctx);
26912 break;
26913 default:
26914 check_insn(ctx, ISA_MIPS_R2);
26915 check_mips_64(ctx);
26916 op2 = MASK_DBSHFL(ctx->opcode);
26917 gen_bshfl(ctx, op2, rt, rd);
26918 break;
26920 break;
26921 #endif
26922 case OPC_RDHWR:
26923 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
26924 break;
26925 case OPC_FORK:
26926 check_mt(ctx);
26928 TCGv t0 = tcg_temp_new();
26929 TCGv t1 = tcg_temp_new();
26931 gen_load_gpr(t0, rt);
26932 gen_load_gpr(t1, rs);
26933 gen_helper_fork(t0, t1);
26934 tcg_temp_free(t0);
26935 tcg_temp_free(t1);
26937 break;
26938 case OPC_YIELD:
26939 check_mt(ctx);
26941 TCGv t0 = tcg_temp_new();
26943 gen_load_gpr(t0, rs);
26944 gen_helper_yield(t0, cpu_env, t0);
26945 gen_store_gpr(t0, rd);
26946 tcg_temp_free(t0);
26948 break;
26949 default:
26950 if (ctx->insn_flags & ISA_MIPS_R6) {
26951 decode_opc_special3_r6(env, ctx);
26952 } else {
26953 decode_opc_special3_legacy(env, ctx);
26958 static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
26960 int32_t offset;
26961 int rs, rt, rd, sa;
26962 uint32_t op, op1;
26963 int16_t imm;
26965 op = MASK_OP_MAJOR(ctx->opcode);
26966 rs = (ctx->opcode >> 21) & 0x1f;
26967 rt = (ctx->opcode >> 16) & 0x1f;
26968 rd = (ctx->opcode >> 11) & 0x1f;
26969 sa = (ctx->opcode >> 6) & 0x1f;
26970 imm = (int16_t)ctx->opcode;
26971 switch (op) {
26972 case OPC_SPECIAL:
26973 decode_opc_special(env, ctx);
26974 break;
26975 case OPC_SPECIAL2:
26976 #if defined(TARGET_MIPS64)
26977 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
26978 decode_mmi(env, ctx);
26979 break;
26981 #endif
26982 #if !defined(TARGET_MIPS64)
26983 if (ctx->insn_flags & ASE_MXU) {
26984 if (MASK_SPECIAL2(ctx->opcode) == OPC_MUL) {
26985 gen_arith(ctx, OPC_MUL, rd, rs, rt);
26986 } else {
26987 decode_opc_mxu(ctx, ctx->opcode);
26989 break;
26991 #endif
26992 decode_opc_special2_legacy(env, ctx);
26993 break;
26994 case OPC_SPECIAL3:
26995 #if defined(TARGET_MIPS64)
26996 if (ctx->insn_flags & INSN_R5900) {
26997 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
26998 } else {
26999 decode_opc_special3(env, ctx);
27001 #else
27002 decode_opc_special3(env, ctx);
27003 #endif
27004 break;
27005 case OPC_REGIMM:
27006 op1 = MASK_REGIMM(ctx->opcode);
27007 switch (op1) {
27008 case OPC_BLTZL: /* REGIMM branches */
27009 case OPC_BGEZL:
27010 case OPC_BLTZALL:
27011 case OPC_BGEZALL:
27012 check_insn(ctx, ISA_MIPS2);
27013 check_insn_opc_removed(ctx, ISA_MIPS_R6);
27014 /* Fallthrough */
27015 case OPC_BLTZ:
27016 case OPC_BGEZ:
27017 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
27018 break;
27019 case OPC_BLTZAL:
27020 case OPC_BGEZAL:
27021 if (ctx->insn_flags & ISA_MIPS_R6) {
27022 if (rs == 0) {
27023 /* OPC_NAL, OPC_BAL */
27024 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
27025 } else {
27026 gen_reserved_instruction(ctx);
27028 } else {
27029 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
27031 break;
27032 case OPC_TGEI: /* REGIMM traps */
27033 case OPC_TGEIU:
27034 case OPC_TLTI:
27035 case OPC_TLTIU:
27036 case OPC_TEQI:
27038 case OPC_TNEI:
27039 check_insn(ctx, ISA_MIPS2);
27040 check_insn_opc_removed(ctx, ISA_MIPS_R6);
27041 gen_trap(ctx, op1, rs, -1, imm);
27042 break;
27043 case OPC_SIGRIE:
27044 check_insn(ctx, ISA_MIPS_R6);
27045 gen_reserved_instruction(ctx);
27046 break;
27047 case OPC_SYNCI:
27048 check_insn(ctx, ISA_MIPS_R2);
27050 * Break the TB to be able to sync copied instructions
27051 * immediately.
27053 ctx->base.is_jmp = DISAS_STOP;
27054 break;
27055 case OPC_BPOSGE32: /* MIPS DSP branch */
27056 #if defined(TARGET_MIPS64)
27057 case OPC_BPOSGE64:
27058 #endif
27059 check_dsp(ctx);
27060 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
27061 break;
27062 #if defined(TARGET_MIPS64)
27063 case OPC_DAHI:
27064 check_insn(ctx, ISA_MIPS_R6);
27065 check_mips_64(ctx);
27066 if (rs != 0) {
27067 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
27069 break;
27070 case OPC_DATI:
27071 check_insn(ctx, ISA_MIPS_R6);
27072 check_mips_64(ctx);
27073 if (rs != 0) {
27074 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
27076 break;
27077 #endif
27078 default: /* Invalid */
27079 MIPS_INVAL("regimm");
27080 gen_reserved_instruction(ctx);
27081 break;
27083 break;
27084 case OPC_CP0:
27085 check_cp0_enabled(ctx);
27086 op1 = MASK_CP0(ctx->opcode);
27087 switch (op1) {
27088 case OPC_MFC0:
27089 case OPC_MTC0:
27090 case OPC_MFTR:
27091 case OPC_MTTR:
27092 case OPC_MFHC0:
27093 case OPC_MTHC0:
27094 #if defined(TARGET_MIPS64)
27095 case OPC_DMFC0:
27096 case OPC_DMTC0:
27097 #endif
27098 #ifndef CONFIG_USER_ONLY
27099 gen_cp0(env, ctx, op1, rt, rd);
27100 #endif /* !CONFIG_USER_ONLY */
27101 break;
27102 case OPC_C0:
27103 case OPC_C0_1:
27104 case OPC_C0_2:
27105 case OPC_C0_3:
27106 case OPC_C0_4:
27107 case OPC_C0_5:
27108 case OPC_C0_6:
27109 case OPC_C0_7:
27110 case OPC_C0_8:
27111 case OPC_C0_9:
27112 case OPC_C0_A:
27113 case OPC_C0_B:
27114 case OPC_C0_C:
27115 case OPC_C0_D:
27116 case OPC_C0_E:
27117 case OPC_C0_F:
27118 #ifndef CONFIG_USER_ONLY
27119 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
27120 #endif /* !CONFIG_USER_ONLY */
27121 break;
27122 case OPC_MFMC0:
27123 #ifndef CONFIG_USER_ONLY
27125 uint32_t op2;
27126 TCGv t0 = tcg_temp_new();
27128 op2 = MASK_MFMC0(ctx->opcode);
27129 switch (op2) {
27130 case OPC_DMT:
27131 check_cp0_mt(ctx);
27132 gen_helper_dmt(t0);
27133 gen_store_gpr(t0, rt);
27134 break;
27135 case OPC_EMT:
27136 check_cp0_mt(ctx);
27137 gen_helper_emt(t0);
27138 gen_store_gpr(t0, rt);
27139 break;
27140 case OPC_DVPE:
27141 check_cp0_mt(ctx);
27142 gen_helper_dvpe(t0, cpu_env);
27143 gen_store_gpr(t0, rt);
27144 break;
27145 case OPC_EVPE:
27146 check_cp0_mt(ctx);
27147 gen_helper_evpe(t0, cpu_env);
27148 gen_store_gpr(t0, rt);
27149 break;
27150 case OPC_DVP:
27151 check_insn(ctx, ISA_MIPS_R6);
27152 if (ctx->vp) {
27153 gen_helper_dvp(t0, cpu_env);
27154 gen_store_gpr(t0, rt);
27156 break;
27157 case OPC_EVP:
27158 check_insn(ctx, ISA_MIPS_R6);
27159 if (ctx->vp) {
27160 gen_helper_evp(t0, cpu_env);
27161 gen_store_gpr(t0, rt);
27163 break;
27164 case OPC_DI:
27165 check_insn(ctx, ISA_MIPS_R2);
27166 save_cpu_state(ctx, 1);
27167 gen_helper_di(t0, cpu_env);
27168 gen_store_gpr(t0, rt);
27170 * Stop translation as we may have switched
27171 * the execution mode.
27173 ctx->base.is_jmp = DISAS_STOP;
27174 break;
27175 case OPC_EI:
27176 check_insn(ctx, ISA_MIPS_R2);
27177 save_cpu_state(ctx, 1);
27178 gen_helper_ei(t0, cpu_env);
27179 gen_store_gpr(t0, rt);
27181 * DISAS_STOP isn't sufficient, we need to ensure we break
27182 * out of translated code to check for pending interrupts.
27184 gen_save_pc(ctx->base.pc_next + 4);
27185 ctx->base.is_jmp = DISAS_EXIT;
27186 break;
27187 default: /* Invalid */
27188 MIPS_INVAL("mfmc0");
27189 gen_reserved_instruction(ctx);
27190 break;
27192 tcg_temp_free(t0);
27194 #endif /* !CONFIG_USER_ONLY */
27195 break;
27196 case OPC_RDPGPR:
27197 check_insn(ctx, ISA_MIPS_R2);
27198 gen_load_srsgpr(rt, rd);
27199 break;
27200 case OPC_WRPGPR:
27201 check_insn(ctx, ISA_MIPS_R2);
27202 gen_store_srsgpr(rt, rd);
27203 break;
27204 default:
27205 MIPS_INVAL("cp0");
27206 gen_reserved_instruction(ctx);
27207 break;
27209 break;
27210 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
27211 if (ctx->insn_flags & ISA_MIPS_R6) {
27212 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
27213 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27214 } else {
27215 /* OPC_ADDI */
27216 /* Arithmetic with immediate opcode */
27217 gen_arith_imm(ctx, op, rt, rs, imm);
27219 break;
27220 case OPC_ADDIU:
27221 gen_arith_imm(ctx, op, rt, rs, imm);
27222 break;
27223 case OPC_SLTI: /* Set on less than with immediate opcode */
27224 case OPC_SLTIU:
27225 gen_slt_imm(ctx, op, rt, rs, imm);
27226 break;
27227 case OPC_ANDI: /* Arithmetic with immediate opcode */
27228 case OPC_LUI: /* OPC_AUI */
27229 case OPC_ORI:
27230 case OPC_XORI:
27231 gen_logic_imm(ctx, op, rt, rs, imm);
27232 break;
27233 case OPC_J: /* Jump */
27234 case OPC_JAL:
27235 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
27236 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
27237 break;
27238 /* Branch */
27239 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
27240 if (ctx->insn_flags & ISA_MIPS_R6) {
27241 if (rt == 0) {
27242 gen_reserved_instruction(ctx);
27243 break;
27245 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
27246 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27247 } else {
27248 /* OPC_BLEZL */
27249 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27251 break;
27252 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
27253 if (ctx->insn_flags & ISA_MIPS_R6) {
27254 if (rt == 0) {
27255 gen_reserved_instruction(ctx);
27256 break;
27258 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
27259 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27260 } else {
27261 /* OPC_BGTZL */
27262 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27264 break;
27265 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
27266 if (rt == 0) {
27267 /* OPC_BLEZ */
27268 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27269 } else {
27270 check_insn(ctx, ISA_MIPS_R6);
27271 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
27272 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27274 break;
27275 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
27276 if (rt == 0) {
27277 /* OPC_BGTZ */
27278 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27279 } else {
27280 check_insn(ctx, ISA_MIPS_R6);
27281 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
27282 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27284 break;
27285 case OPC_BEQL:
27286 case OPC_BNEL:
27287 check_insn(ctx, ISA_MIPS2);
27288 check_insn_opc_removed(ctx, ISA_MIPS_R6);
27289 /* Fallthrough */
27290 case OPC_BEQ:
27291 case OPC_BNE:
27292 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27293 break;
27294 case OPC_LL: /* Load and stores */
27295 check_insn(ctx, ISA_MIPS2);
27296 if (ctx->insn_flags & INSN_R5900) {
27297 check_insn_opc_user_only(ctx, INSN_R5900);
27299 /* Fallthrough */
27300 case OPC_LWL:
27301 case OPC_LWR:
27302 case OPC_LB:
27303 case OPC_LH:
27304 case OPC_LW:
27305 case OPC_LWPC:
27306 case OPC_LBU:
27307 case OPC_LHU:
27308 gen_ld(ctx, op, rt, rs, imm);
27309 break;
27310 case OPC_SWL:
27311 case OPC_SWR:
27312 case OPC_SB:
27313 case OPC_SH:
27314 case OPC_SW:
27315 gen_st(ctx, op, rt, rs, imm);
27316 break;
27317 case OPC_SC:
27318 check_insn(ctx, ISA_MIPS2);
27319 if (ctx->insn_flags & INSN_R5900) {
27320 check_insn_opc_user_only(ctx, INSN_R5900);
27322 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27323 break;
27324 case OPC_CACHE:
27325 check_cp0_enabled(ctx);
27326 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
27327 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27328 gen_cache_operation(ctx, rt, rs, imm);
27330 /* Treat as NOP. */
27331 break;
27332 case OPC_PREF:
27333 if (ctx->insn_flags & INSN_R5900) {
27334 /* Treat as NOP. */
27335 } else {
27336 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
27337 /* Treat as NOP. */
27339 break;
27341 /* Floating point (COP1). */
27342 case OPC_LWC1:
27343 case OPC_LDC1:
27344 case OPC_SWC1:
27345 case OPC_SDC1:
27346 gen_cop1_ldst(ctx, op, rt, rs, imm);
27347 break;
27349 case OPC_CP1:
27350 op1 = MASK_CP1(ctx->opcode);
27352 switch (op1) {
27353 case OPC_MFHC1:
27354 case OPC_MTHC1:
27355 check_cp1_enabled(ctx);
27356 check_insn(ctx, ISA_MIPS_R2);
27357 /* fall through */
27358 case OPC_MFC1:
27359 case OPC_CFC1:
27360 case OPC_MTC1:
27361 case OPC_CTC1:
27362 check_cp1_enabled(ctx);
27363 gen_cp1(ctx, op1, rt, rd);
27364 break;
27365 #if defined(TARGET_MIPS64)
27366 case OPC_DMFC1:
27367 case OPC_DMTC1:
27368 check_cp1_enabled(ctx);
27369 check_insn(ctx, ISA_MIPS3);
27370 check_mips_64(ctx);
27371 gen_cp1(ctx, op1, rt, rd);
27372 break;
27373 #endif
27374 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
27375 check_cp1_enabled(ctx);
27376 if (ctx->insn_flags & ISA_MIPS_R6) {
27377 /* OPC_BC1EQZ */
27378 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
27379 rt, imm << 2, 4);
27380 } else {
27381 /* OPC_BC1ANY2 */
27382 check_cop1x(ctx);
27383 check_insn(ctx, ASE_MIPS3D);
27384 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
27385 (rt >> 2) & 0x7, imm << 2);
27387 break;
27388 case OPC_BC1NEZ:
27389 check_cp1_enabled(ctx);
27390 check_insn(ctx, ISA_MIPS_R6);
27391 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
27392 rt, imm << 2, 4);
27393 break;
27394 case OPC_BC1ANY4:
27395 check_cp1_enabled(ctx);
27396 check_insn_opc_removed(ctx, ISA_MIPS_R6);
27397 check_cop1x(ctx);
27398 check_insn(ctx, ASE_MIPS3D);
27399 /* fall through */
27400 case OPC_BC1:
27401 check_cp1_enabled(ctx);
27402 check_insn_opc_removed(ctx, ISA_MIPS_R6);
27403 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
27404 (rt >> 2) & 0x7, imm << 2);
27405 break;
27406 case OPC_PS_FMT:
27407 check_ps(ctx);
27408 /* fall through */
27409 case OPC_S_FMT:
27410 case OPC_D_FMT:
27411 check_cp1_enabled(ctx);
27412 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
27413 (imm >> 8) & 0x7);
27414 break;
27415 case OPC_W_FMT:
27416 case OPC_L_FMT:
27418 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
27419 check_cp1_enabled(ctx);
27420 if (ctx->insn_flags & ISA_MIPS_R6) {
27421 switch (r6_op) {
27422 case R6_OPC_CMP_AF_S:
27423 case R6_OPC_CMP_UN_S:
27424 case R6_OPC_CMP_EQ_S:
27425 case R6_OPC_CMP_UEQ_S:
27426 case R6_OPC_CMP_LT_S:
27427 case R6_OPC_CMP_ULT_S:
27428 case R6_OPC_CMP_LE_S:
27429 case R6_OPC_CMP_ULE_S:
27430 case R6_OPC_CMP_SAF_S:
27431 case R6_OPC_CMP_SUN_S:
27432 case R6_OPC_CMP_SEQ_S:
27433 case R6_OPC_CMP_SEUQ_S:
27434 case R6_OPC_CMP_SLT_S:
27435 case R6_OPC_CMP_SULT_S:
27436 case R6_OPC_CMP_SLE_S:
27437 case R6_OPC_CMP_SULE_S:
27438 case R6_OPC_CMP_OR_S:
27439 case R6_OPC_CMP_UNE_S:
27440 case R6_OPC_CMP_NE_S:
27441 case R6_OPC_CMP_SOR_S:
27442 case R6_OPC_CMP_SUNE_S:
27443 case R6_OPC_CMP_SNE_S:
27444 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
27445 break;
27446 case R6_OPC_CMP_AF_D:
27447 case R6_OPC_CMP_UN_D:
27448 case R6_OPC_CMP_EQ_D:
27449 case R6_OPC_CMP_UEQ_D:
27450 case R6_OPC_CMP_LT_D:
27451 case R6_OPC_CMP_ULT_D:
27452 case R6_OPC_CMP_LE_D:
27453 case R6_OPC_CMP_ULE_D:
27454 case R6_OPC_CMP_SAF_D:
27455 case R6_OPC_CMP_SUN_D:
27456 case R6_OPC_CMP_SEQ_D:
27457 case R6_OPC_CMP_SEUQ_D:
27458 case R6_OPC_CMP_SLT_D:
27459 case R6_OPC_CMP_SULT_D:
27460 case R6_OPC_CMP_SLE_D:
27461 case R6_OPC_CMP_SULE_D:
27462 case R6_OPC_CMP_OR_D:
27463 case R6_OPC_CMP_UNE_D:
27464 case R6_OPC_CMP_NE_D:
27465 case R6_OPC_CMP_SOR_D:
27466 case R6_OPC_CMP_SUNE_D:
27467 case R6_OPC_CMP_SNE_D:
27468 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
27469 break;
27470 default:
27471 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
27472 rt, rd, sa, (imm >> 8) & 0x7);
27474 break;
27476 } else {
27477 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
27478 (imm >> 8) & 0x7);
27480 break;
27482 default:
27483 MIPS_INVAL("cp1");
27484 gen_reserved_instruction(ctx);
27485 break;
27487 break;
27489 /* Compact branches [R6] and COP2 [non-R6] */
27490 case OPC_BC: /* OPC_LWC2 */
27491 case OPC_BALC: /* OPC_SWC2 */
27492 if (ctx->insn_flags & ISA_MIPS_R6) {
27493 /* OPC_BC, OPC_BALC */
27494 gen_compute_compact_branch(ctx, op, 0, 0,
27495 sextract32(ctx->opcode << 2, 0, 28));
27496 } else if (ctx->insn_flags & ASE_LEXT) {
27497 gen_loongson_lswc2(ctx, rt, rs, rd);
27498 } else {
27499 /* OPC_LWC2, OPC_SWC2 */
27500 /* COP2: Not implemented. */
27501 generate_exception_err(ctx, EXCP_CpU, 2);
27503 break;
27504 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
27505 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
27506 if (ctx->insn_flags & ISA_MIPS_R6) {
27507 if (rs != 0) {
27508 /* OPC_BEQZC, OPC_BNEZC */
27509 gen_compute_compact_branch(ctx, op, rs, 0,
27510 sextract32(ctx->opcode << 2, 0, 23));
27511 } else {
27512 /* OPC_JIC, OPC_JIALC */
27513 gen_compute_compact_branch(ctx, op, 0, rt, imm);
27515 } else if (ctx->insn_flags & ASE_LEXT) {
27516 gen_loongson_lsdc2(ctx, rt, rs, rd);
27517 } else {
27518 /* OPC_LWC2, OPC_SWC2 */
27519 /* COP2: Not implemented. */
27520 generate_exception_err(ctx, EXCP_CpU, 2);
27522 break;
27523 case OPC_CP2:
27524 check_insn(ctx, ASE_LMMI);
27525 /* Note that these instructions use different fields. */
27526 gen_loongson_multimedia(ctx, sa, rd, rt);
27527 break;
27529 case OPC_CP3:
27530 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
27531 check_cp1_enabled(ctx);
27532 op1 = MASK_CP3(ctx->opcode);
27533 switch (op1) {
27534 case OPC_LUXC1:
27535 case OPC_SUXC1:
27536 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
27537 /* Fallthrough */
27538 case OPC_LWXC1:
27539 case OPC_LDXC1:
27540 case OPC_SWXC1:
27541 case OPC_SDXC1:
27542 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
27543 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
27544 break;
27545 case OPC_PREFX:
27546 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
27547 /* Treat as NOP. */
27548 break;
27549 case OPC_ALNV_PS:
27550 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
27551 /* Fallthrough */
27552 case OPC_MADD_S:
27553 case OPC_MADD_D:
27554 case OPC_MADD_PS:
27555 case OPC_MSUB_S:
27556 case OPC_MSUB_D:
27557 case OPC_MSUB_PS:
27558 case OPC_NMADD_S:
27559 case OPC_NMADD_D:
27560 case OPC_NMADD_PS:
27561 case OPC_NMSUB_S:
27562 case OPC_NMSUB_D:
27563 case OPC_NMSUB_PS:
27564 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
27565 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
27566 break;
27567 default:
27568 MIPS_INVAL("cp3");
27569 gen_reserved_instruction(ctx);
27570 break;
27572 } else {
27573 generate_exception_err(ctx, EXCP_CpU, 1);
27575 break;
27577 #if defined(TARGET_MIPS64)
27578 /* MIPS64 opcodes */
27579 case OPC_LLD:
27580 if (ctx->insn_flags & INSN_R5900) {
27581 check_insn_opc_user_only(ctx, INSN_R5900);
27583 /* fall through */
27584 case OPC_LDL:
27585 case OPC_LDR:
27586 case OPC_LWU:
27587 case OPC_LD:
27588 check_insn(ctx, ISA_MIPS3);
27589 check_mips_64(ctx);
27590 gen_ld(ctx, op, rt, rs, imm);
27591 break;
27592 case OPC_SDL:
27593 case OPC_SDR:
27594 case OPC_SD:
27595 check_insn(ctx, ISA_MIPS3);
27596 check_mips_64(ctx);
27597 gen_st(ctx, op, rt, rs, imm);
27598 break;
27599 case OPC_SCD:
27600 check_insn(ctx, ISA_MIPS3);
27601 if (ctx->insn_flags & INSN_R5900) {
27602 check_insn_opc_user_only(ctx, INSN_R5900);
27604 check_mips_64(ctx);
27605 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27606 break;
27607 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
27608 if (ctx->insn_flags & ISA_MIPS_R6) {
27609 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
27610 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27611 } else {
27612 /* OPC_DADDI */
27613 check_insn(ctx, ISA_MIPS3);
27614 check_mips_64(ctx);
27615 gen_arith_imm(ctx, op, rt, rs, imm);
27617 break;
27618 case OPC_DADDIU:
27619 check_insn(ctx, ISA_MIPS3);
27620 check_mips_64(ctx);
27621 gen_arith_imm(ctx, op, rt, rs, imm);
27622 break;
27623 #else
27624 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
27625 if (ctx->insn_flags & ISA_MIPS_R6) {
27626 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27627 } else {
27628 MIPS_INVAL("major opcode");
27629 gen_reserved_instruction(ctx);
27631 break;
27632 #endif
27633 case OPC_DAUI: /* OPC_JALX */
27634 if (ctx->insn_flags & ISA_MIPS_R6) {
27635 #if defined(TARGET_MIPS64)
27636 /* OPC_DAUI */
27637 check_mips_64(ctx);
27638 if (rs == 0) {
27639 generate_exception(ctx, EXCP_RI);
27640 } else if (rt != 0) {
27641 TCGv t0 = tcg_temp_new();
27642 gen_load_gpr(t0, rs);
27643 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
27644 tcg_temp_free(t0);
27646 #else
27647 gen_reserved_instruction(ctx);
27648 MIPS_INVAL("major opcode");
27649 #endif
27650 } else {
27651 /* OPC_JALX */
27652 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
27653 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
27654 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
27656 break;
27657 case OPC_MDMX: /* MMI_OPC_LQ */
27658 if (ctx->insn_flags & INSN_R5900) {
27659 #if defined(TARGET_MIPS64)
27660 gen_mmi_lq(env, ctx);
27661 #endif
27662 } else {
27663 /* MDMX: Not implemented. */
27665 break;
27666 case OPC_PCREL:
27667 check_insn(ctx, ISA_MIPS_R6);
27668 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
27669 break;
27670 default: /* Invalid */
27671 MIPS_INVAL("major opcode");
27672 return false;
27674 return true;
27677 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
27679 /* make sure instructions are on a word boundary */
27680 if (ctx->base.pc_next & 0x3) {
27681 env->CP0_BadVAddr = ctx->base.pc_next;
27682 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
27683 return;
27686 /* Handle blikely not taken case */
27687 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
27688 TCGLabel *l1 = gen_new_label();
27690 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
27691 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
27692 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
27693 gen_set_label(l1);
27696 /* Transition to the auto-generated decoder. */
27698 /* ISA extensions */
27699 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
27700 return;
27703 /* ISA (from latest to oldest) */
27704 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
27705 return;
27708 if (decode_opc_legacy(env, ctx)) {
27709 return;
27712 gen_reserved_instruction(ctx);
27715 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
27717 DisasContext *ctx = container_of(dcbase, DisasContext, base);
27718 CPUMIPSState *env = cs->env_ptr;
27720 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
27721 ctx->saved_pc = -1;
27722 ctx->insn_flags = env->insn_flags;
27723 ctx->CP0_Config1 = env->CP0_Config1;
27724 ctx->CP0_Config2 = env->CP0_Config2;
27725 ctx->CP0_Config3 = env->CP0_Config3;
27726 ctx->CP0_Config5 = env->CP0_Config5;
27727 ctx->btarget = 0;
27728 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
27729 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
27730 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
27731 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
27732 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
27733 ctx->PAMask = env->PAMask;
27734 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
27735 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
27736 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
27737 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
27738 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
27739 /* Restore delay slot state from the tb context. */
27740 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
27741 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
27742 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
27743 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
27744 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
27745 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
27746 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
27747 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
27748 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
27749 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
27750 restore_cpu_state(env, ctx);
27751 #ifdef CONFIG_USER_ONLY
27752 ctx->mem_idx = MIPS_HFLAG_UM;
27753 #else
27754 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
27755 #endif
27756 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
27757 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
27759 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
27760 ctx->hflags);
27763 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
27767 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
27769 DisasContext *ctx = container_of(dcbase, DisasContext, base);
27771 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
27772 ctx->btarget);
27775 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
27776 const CPUBreakpoint *bp)
27778 DisasContext *ctx = container_of(dcbase, DisasContext, base);
27780 save_cpu_state(ctx, 1);
27781 ctx->base.is_jmp = DISAS_NORETURN;
27782 gen_helper_raise_exception_debug(cpu_env);
27784 * The address covered by the breakpoint must be included in
27785 * [tb->pc, tb->pc + tb->size) in order to for it to be
27786 * properly cleared -- thus we increment the PC here so that
27787 * the logic setting tb->size below does the right thing.
27789 ctx->base.pc_next += 4;
27790 return true;
27793 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
27795 CPUMIPSState *env = cs->env_ptr;
27796 DisasContext *ctx = container_of(dcbase, DisasContext, base);
27797 int insn_bytes;
27798 int is_slot;
27800 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
27801 if (ctx->insn_flags & ISA_NANOMIPS32) {
27802 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
27803 insn_bytes = decode_nanomips_opc(env, ctx);
27804 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
27805 ctx->opcode = translator_ldl(env, ctx->base.pc_next);
27806 insn_bytes = 4;
27807 decode_opc(env, ctx);
27808 } else if (ctx->insn_flags & ASE_MICROMIPS) {
27809 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
27810 insn_bytes = decode_micromips_opc(env, ctx);
27811 } else if (ctx->insn_flags & ASE_MIPS16) {
27812 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
27813 insn_bytes = decode_mips16_opc(env, ctx);
27814 } else {
27815 gen_reserved_instruction(ctx);
27816 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
27817 return;
27820 if (ctx->hflags & MIPS_HFLAG_BMASK) {
27821 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
27822 MIPS_HFLAG_FBNSLOT))) {
27824 * Force to generate branch as there is neither delay nor
27825 * forbidden slot.
27827 is_slot = 1;
27829 if ((ctx->hflags & MIPS_HFLAG_M16) &&
27830 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
27832 * Force to generate branch as microMIPS R6 doesn't restrict
27833 * branches in the forbidden slot.
27835 is_slot = 1;
27838 if (is_slot) {
27839 gen_branch(ctx, insn_bytes);
27841 ctx->base.pc_next += insn_bytes;
27843 if (ctx->base.is_jmp != DISAS_NEXT) {
27844 return;
27847 * Execute a branch and its delay slot as a single instruction.
27848 * This is what GDB expects and is consistent with what the
27849 * hardware does (e.g. if a delay slot instruction faults, the
27850 * reported PC is the PC of the branch).
27852 if (ctx->base.singlestep_enabled &&
27853 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
27854 ctx->base.is_jmp = DISAS_TOO_MANY;
27856 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
27857 ctx->base.is_jmp = DISAS_TOO_MANY;
27861 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
27863 DisasContext *ctx = container_of(dcbase, DisasContext, base);
27865 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
27866 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
27867 gen_helper_raise_exception_debug(cpu_env);
27868 } else {
27869 switch (ctx->base.is_jmp) {
27870 case DISAS_STOP:
27871 gen_save_pc(ctx->base.pc_next);
27872 tcg_gen_lookup_and_goto_ptr();
27873 break;
27874 case DISAS_NEXT:
27875 case DISAS_TOO_MANY:
27876 save_cpu_state(ctx, 0);
27877 gen_goto_tb(ctx, 0, ctx->base.pc_next);
27878 break;
27879 case DISAS_EXIT:
27880 tcg_gen_exit_tb(NULL, 0);
27881 break;
27882 case DISAS_NORETURN:
27883 break;
27884 default:
27885 g_assert_not_reached();
27890 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
27892 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
27893 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
27896 static const TranslatorOps mips_tr_ops = {
27897 .init_disas_context = mips_tr_init_disas_context,
27898 .tb_start = mips_tr_tb_start,
27899 .insn_start = mips_tr_insn_start,
27900 .breakpoint_check = mips_tr_breakpoint_check,
27901 .translate_insn = mips_tr_translate_insn,
27902 .tb_stop = mips_tr_tb_stop,
27903 .disas_log = mips_tr_disas_log,
27906 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
27908 DisasContext ctx;
27910 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
27913 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
27915 int i;
27916 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
27918 #define printfpr(fp) \
27919 do { \
27920 if (is_fpu64) \
27921 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
27922 " fd:%13g fs:%13g psu: %13g\n", \
27923 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
27924 (double)(fp)->fd, \
27925 (double)(fp)->fs[FP_ENDIAN_IDX], \
27926 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
27927 else { \
27928 fpr_t tmp; \
27929 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
27930 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
27931 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
27932 " fd:%13g fs:%13g psu:%13g\n", \
27933 tmp.w[FP_ENDIAN_IDX], tmp.d, \
27934 (double)tmp.fd, \
27935 (double)tmp.fs[FP_ENDIAN_IDX], \
27936 (double)tmp.fs[!FP_ENDIAN_IDX]); \
27938 } while (0)
27941 qemu_fprintf(f,
27942 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
27943 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
27944 get_float_exception_flags(&env->active_fpu.fp_status));
27945 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
27946 qemu_fprintf(f, "%3s: ", fregnames[i]);
27947 printfpr(&env->active_fpu.fpr[i]);
27950 #undef printfpr
27953 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
27955 MIPSCPU *cpu = MIPS_CPU(cs);
27956 CPUMIPSState *env = &cpu->env;
27957 int i;
27959 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
27960 " LO=0x" TARGET_FMT_lx " ds %04x "
27961 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
27962 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
27963 env->hflags, env->btarget, env->bcond);
27964 for (i = 0; i < 32; i++) {
27965 if ((i & 3) == 0) {
27966 qemu_fprintf(f, "GPR%02d:", i);
27968 qemu_fprintf(f, " %s " TARGET_FMT_lx,
27969 regnames[i], env->active_tc.gpr[i]);
27970 if ((i & 3) == 3) {
27971 qemu_fprintf(f, "\n");
27975 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
27976 TARGET_FMT_lx "\n",
27977 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
27978 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
27979 PRIx64 "\n",
27980 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
27981 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
27982 env->CP0_Config2, env->CP0_Config3);
27983 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
27984 env->CP0_Config4, env->CP0_Config5);
27985 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
27986 fpu_dump_state(env, f, flags);
27990 void mips_tcg_init(void)
27992 int i;
27994 cpu_gpr[0] = NULL;
27995 for (i = 1; i < 32; i++)
27996 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
27997 offsetof(CPUMIPSState,
27998 active_tc.gpr[i]),
27999 regnames[i]);
28000 #if defined(TARGET_MIPS64)
28001 cpu_gpr_hi[0] = NULL;
28003 for (unsigned i = 1; i < 32; i++) {
28004 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
28006 cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env,
28007 offsetof(CPUMIPSState,
28008 active_tc.gpr_hi[i]),
28009 rname);
28011 #endif /* !TARGET_MIPS64 */
28012 for (i = 0; i < 32; i++) {
28013 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
28015 fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
28017 msa_translate_init();
28018 cpu_PC = tcg_global_mem_new(cpu_env,
28019 offsetof(CPUMIPSState, active_tc.PC), "PC");
28020 for (i = 0; i < MIPS_DSP_ACC; i++) {
28021 cpu_HI[i] = tcg_global_mem_new(cpu_env,
28022 offsetof(CPUMIPSState, active_tc.HI[i]),
28023 regnames_HI[i]);
28024 cpu_LO[i] = tcg_global_mem_new(cpu_env,
28025 offsetof(CPUMIPSState, active_tc.LO[i]),
28026 regnames_LO[i]);
28028 cpu_dspctrl = tcg_global_mem_new(cpu_env,
28029 offsetof(CPUMIPSState,
28030 active_tc.DSPControl),
28031 "DSPControl");
28032 bcond = tcg_global_mem_new(cpu_env,
28033 offsetof(CPUMIPSState, bcond), "bcond");
28034 btarget = tcg_global_mem_new(cpu_env,
28035 offsetof(CPUMIPSState, btarget), "btarget");
28036 hflags = tcg_global_mem_new_i32(cpu_env,
28037 offsetof(CPUMIPSState, hflags), "hflags");
28039 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
28040 offsetof(CPUMIPSState, active_fpu.fcr0),
28041 "fcr0");
28042 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
28043 offsetof(CPUMIPSState, active_fpu.fcr31),
28044 "fcr31");
28045 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
28046 "lladdr");
28047 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
28048 "llval");
28050 #if !defined(TARGET_MIPS64)
28051 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
28052 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
28053 offsetof(CPUMIPSState,
28054 active_tc.mxu_gpr[i]),
28055 mxuregnames[i]);
28058 mxu_CR = tcg_global_mem_new(cpu_env,
28059 offsetof(CPUMIPSState, active_tc.mxu_cr),
28060 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
28061 #endif /* !TARGET_MIPS64 */
28064 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
28065 target_ulong *data)
28067 env->active_tc.PC = data[0];
28068 env->hflags &= ~MIPS_HFLAG_BMASK;
28069 env->hflags |= data[1];
28070 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
28071 case MIPS_HFLAG_BR:
28072 break;
28073 case MIPS_HFLAG_BC:
28074 case MIPS_HFLAG_BL:
28075 case MIPS_HFLAG_B:
28076 env->btarget = data[2];
28077 break;