target/mips: Introduce mxu_translate_init() helper
[qemu/ar7.git] / target / mips / translate.c
bloba1a9a8500851df87d1465953c1d394a3b059c0fe
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",
2049 void mxu_translate_init(void)
2051 for (unsigned i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
2052 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
2053 offsetof(CPUMIPSState, active_tc.mxu_gpr[i]),
2054 mxuregnames[i]);
2057 mxu_CR = tcg_global_mem_new(cpu_env,
2058 offsetof(CPUMIPSState, active_tc.mxu_cr),
2059 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
2061 #endif /* !TARGET_MIPS64 */
2063 /* General purpose registers moves. */
2064 void gen_load_gpr(TCGv t, int reg)
2066 if (reg == 0) {
2067 tcg_gen_movi_tl(t, 0);
2068 } else {
2069 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2073 void gen_store_gpr(TCGv t, int reg)
2075 if (reg != 0) {
2076 tcg_gen_mov_tl(cpu_gpr[reg], t);
2080 #if defined(TARGET_MIPS64)
2081 void gen_load_gpr_hi(TCGv_i64 t, int reg)
2083 if (reg == 0) {
2084 tcg_gen_movi_i64(t, 0);
2085 } else {
2086 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
2090 void gen_store_gpr_hi(TCGv_i64 t, int reg)
2092 if (reg != 0) {
2093 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
2096 #endif /* TARGET_MIPS64 */
2098 /* Moves to/from shadow registers. */
2099 static inline void gen_load_srsgpr(int from, int to)
2101 TCGv t0 = tcg_temp_new();
2103 if (from == 0) {
2104 tcg_gen_movi_tl(t0, 0);
2105 } else {
2106 TCGv_i32 t2 = tcg_temp_new_i32();
2107 TCGv_ptr addr = tcg_temp_new_ptr();
2109 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2110 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2111 tcg_gen_andi_i32(t2, t2, 0xf);
2112 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2113 tcg_gen_ext_i32_ptr(addr, t2);
2114 tcg_gen_add_ptr(addr, cpu_env, addr);
2116 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2117 tcg_temp_free_ptr(addr);
2118 tcg_temp_free_i32(t2);
2120 gen_store_gpr(t0, to);
2121 tcg_temp_free(t0);
2124 static inline void gen_store_srsgpr(int from, int to)
2126 if (to != 0) {
2127 TCGv t0 = tcg_temp_new();
2128 TCGv_i32 t2 = tcg_temp_new_i32();
2129 TCGv_ptr addr = tcg_temp_new_ptr();
2131 gen_load_gpr(t0, from);
2132 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2133 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2134 tcg_gen_andi_i32(t2, t2, 0xf);
2135 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2136 tcg_gen_ext_i32_ptr(addr, t2);
2137 tcg_gen_add_ptr(addr, cpu_env, addr);
2139 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2140 tcg_temp_free_ptr(addr);
2141 tcg_temp_free_i32(t2);
2142 tcg_temp_free(t0);
2146 #if !defined(TARGET_MIPS64)
2147 /* MXU General purpose registers moves. */
2148 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2150 if (reg == 0) {
2151 tcg_gen_movi_tl(t, 0);
2152 } else if (reg <= 15) {
2153 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2157 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2159 if (reg > 0 && reg <= 15) {
2160 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2164 /* MXU control register moves. */
2165 static inline void gen_load_mxu_cr(TCGv t)
2167 tcg_gen_mov_tl(t, mxu_CR);
2170 static inline void gen_store_mxu_cr(TCGv t)
2172 /* TODO: Add handling of RW rules for MXU_CR. */
2173 tcg_gen_mov_tl(mxu_CR, t);
2175 #endif
2178 /* Tests */
2179 static inline void gen_save_pc(target_ulong pc)
2181 tcg_gen_movi_tl(cpu_PC, pc);
2184 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2186 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2187 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2188 gen_save_pc(ctx->base.pc_next);
2189 ctx->saved_pc = ctx->base.pc_next;
2191 if (ctx->hflags != ctx->saved_hflags) {
2192 tcg_gen_movi_i32(hflags, ctx->hflags);
2193 ctx->saved_hflags = ctx->hflags;
2194 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2195 case MIPS_HFLAG_BR:
2196 break;
2197 case MIPS_HFLAG_BC:
2198 case MIPS_HFLAG_BL:
2199 case MIPS_HFLAG_B:
2200 tcg_gen_movi_tl(btarget, ctx->btarget);
2201 break;
2206 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2208 ctx->saved_hflags = ctx->hflags;
2209 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2210 case MIPS_HFLAG_BR:
2211 break;
2212 case MIPS_HFLAG_BC:
2213 case MIPS_HFLAG_BL:
2214 case MIPS_HFLAG_B:
2215 ctx->btarget = env->btarget;
2216 break;
2220 void generate_exception_err(DisasContext *ctx, int excp, int err)
2222 TCGv_i32 texcp = tcg_const_i32(excp);
2223 TCGv_i32 terr = tcg_const_i32(err);
2224 save_cpu_state(ctx, 1);
2225 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2226 tcg_temp_free_i32(terr);
2227 tcg_temp_free_i32(texcp);
2228 ctx->base.is_jmp = DISAS_NORETURN;
2231 void generate_exception(DisasContext *ctx, int excp)
2233 gen_helper_0e0i(raise_exception, excp);
2236 void generate_exception_end(DisasContext *ctx, int excp)
2238 generate_exception_err(ctx, excp, 0);
2241 void gen_reserved_instruction(DisasContext *ctx)
2243 generate_exception_end(ctx, EXCP_RI);
2246 /* Floating point register moves. */
2247 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2249 if (ctx->hflags & MIPS_HFLAG_FRE) {
2250 generate_exception(ctx, EXCP_RI);
2252 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2255 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2257 TCGv_i64 t64;
2258 if (ctx->hflags & MIPS_HFLAG_FRE) {
2259 generate_exception(ctx, EXCP_RI);
2261 t64 = tcg_temp_new_i64();
2262 tcg_gen_extu_i32_i64(t64, t);
2263 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2264 tcg_temp_free_i64(t64);
2267 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2269 if (ctx->hflags & MIPS_HFLAG_F64) {
2270 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2271 } else {
2272 gen_load_fpr32(ctx, t, reg | 1);
2276 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2278 if (ctx->hflags & MIPS_HFLAG_F64) {
2279 TCGv_i64 t64 = tcg_temp_new_i64();
2280 tcg_gen_extu_i32_i64(t64, t);
2281 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2282 tcg_temp_free_i64(t64);
2283 } else {
2284 gen_store_fpr32(ctx, t, reg | 1);
2288 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2290 if (ctx->hflags & MIPS_HFLAG_F64) {
2291 tcg_gen_mov_i64(t, fpu_f64[reg]);
2292 } else {
2293 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2297 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2299 if (ctx->hflags & MIPS_HFLAG_F64) {
2300 tcg_gen_mov_i64(fpu_f64[reg], t);
2301 } else {
2302 TCGv_i64 t0;
2303 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2304 t0 = tcg_temp_new_i64();
2305 tcg_gen_shri_i64(t0, t, 32);
2306 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2307 tcg_temp_free_i64(t0);
2311 int get_fp_bit(int cc)
2313 if (cc) {
2314 return 24 + cc;
2315 } else {
2316 return 23;
2320 /* Addresses computation */
2321 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2323 tcg_gen_add_tl(ret, arg0, arg1);
2325 #if defined(TARGET_MIPS64)
2326 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2327 tcg_gen_ext32s_i64(ret, ret);
2329 #endif
2332 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2333 target_long ofs)
2335 tcg_gen_addi_tl(ret, base, ofs);
2337 #if defined(TARGET_MIPS64)
2338 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2339 tcg_gen_ext32s_i64(ret, ret);
2341 #endif
2344 /* Addresses computation (translation time) */
2345 static target_long addr_add(DisasContext *ctx, target_long base,
2346 target_long offset)
2348 target_long sum = base + offset;
2350 #if defined(TARGET_MIPS64)
2351 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2352 sum = (int32_t)sum;
2354 #endif
2355 return sum;
2358 /* Sign-extract the low 32-bits to a target_long. */
2359 void gen_move_low32(TCGv ret, TCGv_i64 arg)
2361 #if defined(TARGET_MIPS64)
2362 tcg_gen_ext32s_i64(ret, arg);
2363 #else
2364 tcg_gen_extrl_i64_i32(ret, arg);
2365 #endif
2368 /* Sign-extract the high 32-bits to a target_long. */
2369 void gen_move_high32(TCGv ret, TCGv_i64 arg)
2371 #if defined(TARGET_MIPS64)
2372 tcg_gen_sari_i64(ret, arg, 32);
2373 #else
2374 tcg_gen_extrh_i64_i32(ret, arg);
2375 #endif
2378 void check_cp0_enabled(DisasContext *ctx)
2380 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2381 generate_exception_end(ctx, EXCP_CpU);
2385 void check_cp1_enabled(DisasContext *ctx)
2387 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2388 generate_exception_err(ctx, EXCP_CpU, 1);
2393 * Verify that the processor is running with COP1X instructions enabled.
2394 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2395 * opcode tables.
2397 void check_cop1x(DisasContext *ctx)
2399 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2400 gen_reserved_instruction(ctx);
2405 * Verify that the processor is running with 64-bit floating-point
2406 * operations enabled.
2408 void check_cp1_64bitmode(DisasContext *ctx)
2410 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2411 gen_reserved_instruction(ctx);
2416 * Verify if floating point register is valid; an operation is not defined
2417 * if bit 0 of any register specification is set and the FR bit in the
2418 * Status register equals zero, since the register numbers specify an
2419 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2420 * in the Status register equals one, both even and odd register numbers
2421 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2423 * Multiple 64 bit wide registers can be checked by calling
2424 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2426 void check_cp1_registers(DisasContext *ctx, int regs)
2428 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
2429 gen_reserved_instruction(ctx);
2434 * Verify that the processor is running with DSP instructions enabled.
2435 * This is enabled by CP0 Status register MX(24) bit.
2437 static inline void check_dsp(DisasContext *ctx)
2439 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2440 if (ctx->insn_flags & ASE_DSP) {
2441 generate_exception_end(ctx, EXCP_DSPDIS);
2442 } else {
2443 gen_reserved_instruction(ctx);
2448 static inline void check_dsp_r2(DisasContext *ctx)
2450 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2451 if (ctx->insn_flags & ASE_DSP) {
2452 generate_exception_end(ctx, EXCP_DSPDIS);
2453 } else {
2454 gen_reserved_instruction(ctx);
2459 static inline void check_dsp_r3(DisasContext *ctx)
2461 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2462 if (ctx->insn_flags & ASE_DSP) {
2463 generate_exception_end(ctx, EXCP_DSPDIS);
2464 } else {
2465 gen_reserved_instruction(ctx);
2471 * This code generates a "reserved instruction" exception if the
2472 * CPU does not support the instruction set corresponding to flags.
2474 void check_insn(DisasContext *ctx, uint64_t flags)
2476 if (unlikely(!(ctx->insn_flags & flags))) {
2477 gen_reserved_instruction(ctx);
2482 * This code generates a "reserved instruction" exception if the
2483 * CPU has corresponding flag set which indicates that the instruction
2484 * has been removed.
2486 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2488 if (unlikely(ctx->insn_flags & flags)) {
2489 gen_reserved_instruction(ctx);
2494 * The Linux kernel traps certain reserved instruction exceptions to
2495 * emulate the corresponding instructions. QEMU is the kernel in user
2496 * mode, so those traps are emulated by accepting the instructions.
2498 * A reserved instruction exception is generated for flagged CPUs if
2499 * QEMU runs in system mode.
2501 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
2503 #ifndef CONFIG_USER_ONLY
2504 check_insn_opc_removed(ctx, flags);
2505 #endif
2509 * This code generates a "reserved instruction" exception if the
2510 * CPU does not support 64-bit paired-single (PS) floating point data type.
2512 static inline void check_ps(DisasContext *ctx)
2514 if (unlikely(!ctx->ps)) {
2515 generate_exception(ctx, EXCP_RI);
2517 check_cp1_64bitmode(ctx);
2521 * This code generates a "reserved instruction" exception if cpu is not
2522 * 64-bit or 64-bit instructions are not enabled.
2524 void check_mips_64(DisasContext *ctx)
2526 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
2527 gen_reserved_instruction(ctx);
2531 #ifndef CONFIG_USER_ONLY
2532 static inline void check_mvh(DisasContext *ctx)
2534 if (unlikely(!ctx->mvh)) {
2535 generate_exception(ctx, EXCP_RI);
2538 #endif
2541 * This code generates a "reserved instruction" exception if the
2542 * Config5 XNP bit is set.
2544 static inline void check_xnp(DisasContext *ctx)
2546 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2547 gen_reserved_instruction(ctx);
2551 #ifndef CONFIG_USER_ONLY
2553 * This code generates a "reserved instruction" exception if the
2554 * Config3 PW bit is NOT set.
2556 static inline void check_pw(DisasContext *ctx)
2558 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2559 gen_reserved_instruction(ctx);
2562 #endif
2565 * This code generates a "reserved instruction" exception if the
2566 * Config3 MT bit is NOT set.
2568 static inline void check_mt(DisasContext *ctx)
2570 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2571 gen_reserved_instruction(ctx);
2575 #ifndef CONFIG_USER_ONLY
2577 * This code generates a "coprocessor unusable" exception if CP0 is not
2578 * available, and, if that is not the case, generates a "reserved instruction"
2579 * exception if the Config5 MT bit is NOT set. This is needed for availability
2580 * control of some of MT ASE instructions.
2582 static inline void check_cp0_mt(DisasContext *ctx)
2584 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2585 generate_exception_end(ctx, EXCP_CpU);
2586 } else {
2587 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2588 gen_reserved_instruction(ctx);
2592 #endif
2595 * This code generates a "reserved instruction" exception if the
2596 * Config5 NMS bit is set.
2598 static inline void check_nms(DisasContext *ctx)
2600 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2601 gen_reserved_instruction(ctx);
2606 * This code generates a "reserved instruction" exception if the
2607 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
2608 * Config2 TL, and Config5 L2C are unset.
2610 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
2612 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
2613 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
2614 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
2615 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
2616 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
2617 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
2618 gen_reserved_instruction(ctx);
2623 * This code generates a "reserved instruction" exception if the
2624 * Config5 EVA bit is NOT set.
2626 static inline void check_eva(DisasContext *ctx)
2628 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
2629 gen_reserved_instruction(ctx);
2635 * Define small wrappers for gen_load_fpr* so that we have a uniform
2636 * calling interface for 32 and 64-bit FPRs. No sense in changing
2637 * all callers for gen_load_fpr32 when we need the CTX parameter for
2638 * this one use.
2640 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
2641 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
2642 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
2643 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
2644 int ft, int fs, int cc) \
2646 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
2647 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
2648 switch (ifmt) { \
2649 case FMT_PS: \
2650 check_ps(ctx); \
2651 break; \
2652 case FMT_D: \
2653 if (abs) { \
2654 check_cop1x(ctx); \
2656 check_cp1_registers(ctx, fs | ft); \
2657 break; \
2658 case FMT_S: \
2659 if (abs) { \
2660 check_cop1x(ctx); \
2662 break; \
2664 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
2665 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
2666 switch (n) { \
2667 case 0: \
2668 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
2669 break; \
2670 case 1: \
2671 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
2672 break; \
2673 case 2: \
2674 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
2675 break; \
2676 case 3: \
2677 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
2678 break; \
2679 case 4: \
2680 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
2681 break; \
2682 case 5: \
2683 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
2684 break; \
2685 case 6: \
2686 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
2687 break; \
2688 case 7: \
2689 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
2690 break; \
2691 case 8: \
2692 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
2693 break; \
2694 case 9: \
2695 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
2696 break; \
2697 case 10: \
2698 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
2699 break; \
2700 case 11: \
2701 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
2702 break; \
2703 case 12: \
2704 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
2705 break; \
2706 case 13: \
2707 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
2708 break; \
2709 case 14: \
2710 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
2711 break; \
2712 case 15: \
2713 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
2714 break; \
2715 default: \
2716 abort(); \
2718 tcg_temp_free_i##bits(fp0); \
2719 tcg_temp_free_i##bits(fp1); \
2722 FOP_CONDS(, 0, d, FMT_D, 64)
2723 FOP_CONDS(abs, 1, d, FMT_D, 64)
2724 FOP_CONDS(, 0, s, FMT_S, 32)
2725 FOP_CONDS(abs, 1, s, FMT_S, 32)
2726 FOP_CONDS(, 0, ps, FMT_PS, 64)
2727 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
2728 #undef FOP_CONDS
2730 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
2731 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
2732 int ft, int fs, int fd) \
2734 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
2735 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
2736 if (ifmt == FMT_D) { \
2737 check_cp1_registers(ctx, fs | ft | fd); \
2739 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
2740 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
2741 switch (n) { \
2742 case 0: \
2743 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
2744 break; \
2745 case 1: \
2746 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
2747 break; \
2748 case 2: \
2749 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
2750 break; \
2751 case 3: \
2752 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
2753 break; \
2754 case 4: \
2755 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
2756 break; \
2757 case 5: \
2758 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
2759 break; \
2760 case 6: \
2761 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
2762 break; \
2763 case 7: \
2764 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
2765 break; \
2766 case 8: \
2767 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
2768 break; \
2769 case 9: \
2770 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
2771 break; \
2772 case 10: \
2773 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2774 break; \
2775 case 11: \
2776 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2777 break; \
2778 case 12: \
2779 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2780 break; \
2781 case 13: \
2782 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2783 break; \
2784 case 14: \
2785 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
2786 break; \
2787 case 15: \
2788 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
2789 break; \
2790 case 17: \
2791 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
2792 break; \
2793 case 18: \
2794 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2795 break; \
2796 case 19: \
2797 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2798 break; \
2799 case 25: \
2800 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2801 break; \
2802 case 26: \
2803 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2804 break; \
2805 case 27: \
2806 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2807 break; \
2808 default: \
2809 abort(); \
2811 STORE; \
2812 tcg_temp_free_i ## bits(fp0); \
2813 tcg_temp_free_i ## bits(fp1); \
2816 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2817 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2818 #undef FOP_CONDNS
2819 #undef gen_ldcmp_fpr32
2820 #undef gen_ldcmp_fpr64
2822 /* load/store instructions. */
2823 #ifdef CONFIG_USER_ONLY
2824 #define OP_LD_ATOMIC(insn, fname) \
2825 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2826 DisasContext *ctx) \
2828 TCGv t0 = tcg_temp_new(); \
2829 tcg_gen_mov_tl(t0, arg1); \
2830 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2831 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2832 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2833 tcg_temp_free(t0); \
2835 #else
2836 #define OP_LD_ATOMIC(insn, fname) \
2837 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2838 DisasContext *ctx) \
2840 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2842 #endif
2843 OP_LD_ATOMIC(ll, ld32s);
2844 #if defined(TARGET_MIPS64)
2845 OP_LD_ATOMIC(lld, ld64);
2846 #endif
2847 #undef OP_LD_ATOMIC
2849 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
2851 if (base == 0) {
2852 tcg_gen_movi_tl(addr, offset);
2853 } else if (offset == 0) {
2854 gen_load_gpr(addr, base);
2855 } else {
2856 tcg_gen_movi_tl(addr, offset);
2857 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2861 static target_ulong pc_relative_pc(DisasContext *ctx)
2863 target_ulong pc = ctx->base.pc_next;
2865 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2866 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2868 pc -= branch_bytes;
2871 pc &= ~(target_ulong)3;
2872 return pc;
2875 /* Load */
2876 static void gen_ld(DisasContext *ctx, uint32_t opc,
2877 int rt, int base, int offset)
2879 TCGv t0, t1, t2;
2880 int mem_idx = ctx->mem_idx;
2882 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
2883 INSN_LOONGSON3A)) {
2885 * Loongson CPU uses a load to zero register for prefetch.
2886 * We emulate it as a NOP. On other CPU we must perform the
2887 * actual memory access.
2889 return;
2892 t0 = tcg_temp_new();
2893 gen_base_offset_addr(ctx, t0, base, offset);
2895 switch (opc) {
2896 #if defined(TARGET_MIPS64)
2897 case OPC_LWU:
2898 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
2899 ctx->default_tcg_memop_mask);
2900 gen_store_gpr(t0, rt);
2901 break;
2902 case OPC_LD:
2903 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
2904 ctx->default_tcg_memop_mask);
2905 gen_store_gpr(t0, rt);
2906 break;
2907 case OPC_LLD:
2908 case R6_OPC_LLD:
2909 op_ld_lld(t0, t0, mem_idx, ctx);
2910 gen_store_gpr(t0, rt);
2911 break;
2912 case OPC_LDL:
2913 t1 = tcg_temp_new();
2915 * Do a byte access to possibly trigger a page
2916 * fault with the unaligned address.
2918 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2919 tcg_gen_andi_tl(t1, t0, 7);
2920 #ifndef TARGET_WORDS_BIGENDIAN
2921 tcg_gen_xori_tl(t1, t1, 7);
2922 #endif
2923 tcg_gen_shli_tl(t1, t1, 3);
2924 tcg_gen_andi_tl(t0, t0, ~7);
2925 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2926 tcg_gen_shl_tl(t0, t0, t1);
2927 t2 = tcg_const_tl(-1);
2928 tcg_gen_shl_tl(t2, t2, t1);
2929 gen_load_gpr(t1, rt);
2930 tcg_gen_andc_tl(t1, t1, t2);
2931 tcg_temp_free(t2);
2932 tcg_gen_or_tl(t0, t0, t1);
2933 tcg_temp_free(t1);
2934 gen_store_gpr(t0, rt);
2935 break;
2936 case OPC_LDR:
2937 t1 = tcg_temp_new();
2939 * Do a byte access to possibly trigger a page
2940 * fault with the unaligned address.
2942 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2943 tcg_gen_andi_tl(t1, t0, 7);
2944 #ifdef TARGET_WORDS_BIGENDIAN
2945 tcg_gen_xori_tl(t1, t1, 7);
2946 #endif
2947 tcg_gen_shli_tl(t1, t1, 3);
2948 tcg_gen_andi_tl(t0, t0, ~7);
2949 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2950 tcg_gen_shr_tl(t0, t0, t1);
2951 tcg_gen_xori_tl(t1, t1, 63);
2952 t2 = tcg_const_tl(0xfffffffffffffffeull);
2953 tcg_gen_shl_tl(t2, t2, t1);
2954 gen_load_gpr(t1, rt);
2955 tcg_gen_and_tl(t1, t1, t2);
2956 tcg_temp_free(t2);
2957 tcg_gen_or_tl(t0, t0, t1);
2958 tcg_temp_free(t1);
2959 gen_store_gpr(t0, rt);
2960 break;
2961 case OPC_LDPC:
2962 t1 = tcg_const_tl(pc_relative_pc(ctx));
2963 gen_op_addr_add(ctx, t0, t0, t1);
2964 tcg_temp_free(t1);
2965 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2966 gen_store_gpr(t0, rt);
2967 break;
2968 #endif
2969 case OPC_LWPC:
2970 t1 = tcg_const_tl(pc_relative_pc(ctx));
2971 gen_op_addr_add(ctx, t0, t0, t1);
2972 tcg_temp_free(t1);
2973 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
2974 gen_store_gpr(t0, rt);
2975 break;
2976 case OPC_LWE:
2977 mem_idx = MIPS_HFLAG_UM;
2978 /* fall through */
2979 case OPC_LW:
2980 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
2981 ctx->default_tcg_memop_mask);
2982 gen_store_gpr(t0, rt);
2983 break;
2984 case OPC_LHE:
2985 mem_idx = MIPS_HFLAG_UM;
2986 /* fall through */
2987 case OPC_LH:
2988 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
2989 ctx->default_tcg_memop_mask);
2990 gen_store_gpr(t0, rt);
2991 break;
2992 case OPC_LHUE:
2993 mem_idx = MIPS_HFLAG_UM;
2994 /* fall through */
2995 case OPC_LHU:
2996 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
2997 ctx->default_tcg_memop_mask);
2998 gen_store_gpr(t0, rt);
2999 break;
3000 case OPC_LBE:
3001 mem_idx = MIPS_HFLAG_UM;
3002 /* fall through */
3003 case OPC_LB:
3004 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3005 gen_store_gpr(t0, rt);
3006 break;
3007 case OPC_LBUE:
3008 mem_idx = MIPS_HFLAG_UM;
3009 /* fall through */
3010 case OPC_LBU:
3011 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3012 gen_store_gpr(t0, rt);
3013 break;
3014 case OPC_LWLE:
3015 mem_idx = MIPS_HFLAG_UM;
3016 /* fall through */
3017 case OPC_LWL:
3018 t1 = tcg_temp_new();
3020 * Do a byte access to possibly trigger a page
3021 * fault with the unaligned address.
3023 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3024 tcg_gen_andi_tl(t1, t0, 3);
3025 #ifndef TARGET_WORDS_BIGENDIAN
3026 tcg_gen_xori_tl(t1, t1, 3);
3027 #endif
3028 tcg_gen_shli_tl(t1, t1, 3);
3029 tcg_gen_andi_tl(t0, t0, ~3);
3030 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3031 tcg_gen_shl_tl(t0, t0, t1);
3032 t2 = tcg_const_tl(-1);
3033 tcg_gen_shl_tl(t2, t2, t1);
3034 gen_load_gpr(t1, rt);
3035 tcg_gen_andc_tl(t1, t1, t2);
3036 tcg_temp_free(t2);
3037 tcg_gen_or_tl(t0, t0, t1);
3038 tcg_temp_free(t1);
3039 tcg_gen_ext32s_tl(t0, t0);
3040 gen_store_gpr(t0, rt);
3041 break;
3042 case OPC_LWRE:
3043 mem_idx = MIPS_HFLAG_UM;
3044 /* fall through */
3045 case OPC_LWR:
3046 t1 = tcg_temp_new();
3048 * Do a byte access to possibly trigger a page
3049 * fault with the unaligned address.
3051 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3052 tcg_gen_andi_tl(t1, t0, 3);
3053 #ifdef TARGET_WORDS_BIGENDIAN
3054 tcg_gen_xori_tl(t1, t1, 3);
3055 #endif
3056 tcg_gen_shli_tl(t1, t1, 3);
3057 tcg_gen_andi_tl(t0, t0, ~3);
3058 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3059 tcg_gen_shr_tl(t0, t0, t1);
3060 tcg_gen_xori_tl(t1, t1, 31);
3061 t2 = tcg_const_tl(0xfffffffeull);
3062 tcg_gen_shl_tl(t2, t2, t1);
3063 gen_load_gpr(t1, rt);
3064 tcg_gen_and_tl(t1, t1, t2);
3065 tcg_temp_free(t2);
3066 tcg_gen_or_tl(t0, t0, t1);
3067 tcg_temp_free(t1);
3068 tcg_gen_ext32s_tl(t0, t0);
3069 gen_store_gpr(t0, rt);
3070 break;
3071 case OPC_LLE:
3072 mem_idx = MIPS_HFLAG_UM;
3073 /* fall through */
3074 case OPC_LL:
3075 case R6_OPC_LL:
3076 op_ld_ll(t0, t0, mem_idx, ctx);
3077 gen_store_gpr(t0, rt);
3078 break;
3080 tcg_temp_free(t0);
3083 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3084 uint32_t reg1, uint32_t reg2)
3086 TCGv taddr = tcg_temp_new();
3087 TCGv_i64 tval = tcg_temp_new_i64();
3088 TCGv tmp1 = tcg_temp_new();
3089 TCGv tmp2 = tcg_temp_new();
3091 gen_base_offset_addr(ctx, taddr, base, offset);
3092 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3093 #ifdef TARGET_WORDS_BIGENDIAN
3094 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3095 #else
3096 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3097 #endif
3098 gen_store_gpr(tmp1, reg1);
3099 tcg_temp_free(tmp1);
3100 gen_store_gpr(tmp2, reg2);
3101 tcg_temp_free(tmp2);
3102 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3103 tcg_temp_free_i64(tval);
3104 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3105 tcg_temp_free(taddr);
3108 /* Store */
3109 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3110 int base, int offset)
3112 TCGv t0 = tcg_temp_new();
3113 TCGv t1 = tcg_temp_new();
3114 int mem_idx = ctx->mem_idx;
3116 gen_base_offset_addr(ctx, t0, base, offset);
3117 gen_load_gpr(t1, rt);
3118 switch (opc) {
3119 #if defined(TARGET_MIPS64)
3120 case OPC_SD:
3121 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3122 ctx->default_tcg_memop_mask);
3123 break;
3124 case OPC_SDL:
3125 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3126 break;
3127 case OPC_SDR:
3128 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3129 break;
3130 #endif
3131 case OPC_SWE:
3132 mem_idx = MIPS_HFLAG_UM;
3133 /* fall through */
3134 case OPC_SW:
3135 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3136 ctx->default_tcg_memop_mask);
3137 break;
3138 case OPC_SHE:
3139 mem_idx = MIPS_HFLAG_UM;
3140 /* fall through */
3141 case OPC_SH:
3142 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3143 ctx->default_tcg_memop_mask);
3144 break;
3145 case OPC_SBE:
3146 mem_idx = MIPS_HFLAG_UM;
3147 /* fall through */
3148 case OPC_SB:
3149 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3150 break;
3151 case OPC_SWLE:
3152 mem_idx = MIPS_HFLAG_UM;
3153 /* fall through */
3154 case OPC_SWL:
3155 gen_helper_0e2i(swl, t1, t0, mem_idx);
3156 break;
3157 case OPC_SWRE:
3158 mem_idx = MIPS_HFLAG_UM;
3159 /* fall through */
3160 case OPC_SWR:
3161 gen_helper_0e2i(swr, t1, t0, mem_idx);
3162 break;
3164 tcg_temp_free(t0);
3165 tcg_temp_free(t1);
3169 /* Store conditional */
3170 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3171 MemOp tcg_mo, bool eva)
3173 TCGv addr, t0, val;
3174 TCGLabel *l1 = gen_new_label();
3175 TCGLabel *done = gen_new_label();
3177 t0 = tcg_temp_new();
3178 addr = tcg_temp_new();
3179 /* compare the address against that of the preceding LL */
3180 gen_base_offset_addr(ctx, addr, base, offset);
3181 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3182 tcg_temp_free(addr);
3183 tcg_gen_movi_tl(t0, 0);
3184 gen_store_gpr(t0, rt);
3185 tcg_gen_br(done);
3187 gen_set_label(l1);
3188 /* generate cmpxchg */
3189 val = tcg_temp_new();
3190 gen_load_gpr(val, rt);
3191 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3192 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3193 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3194 gen_store_gpr(t0, rt);
3195 tcg_temp_free(val);
3197 gen_set_label(done);
3198 tcg_temp_free(t0);
3202 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3203 uint32_t reg1, uint32_t reg2, bool eva)
3205 TCGv taddr = tcg_temp_local_new();
3206 TCGv lladdr = tcg_temp_local_new();
3207 TCGv_i64 tval = tcg_temp_new_i64();
3208 TCGv_i64 llval = tcg_temp_new_i64();
3209 TCGv_i64 val = tcg_temp_new_i64();
3210 TCGv tmp1 = tcg_temp_new();
3211 TCGv tmp2 = tcg_temp_new();
3212 TCGLabel *lab_fail = gen_new_label();
3213 TCGLabel *lab_done = gen_new_label();
3215 gen_base_offset_addr(ctx, taddr, base, offset);
3217 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3218 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3220 gen_load_gpr(tmp1, reg1);
3221 gen_load_gpr(tmp2, reg2);
3223 #ifdef TARGET_WORDS_BIGENDIAN
3224 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3225 #else
3226 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3227 #endif
3229 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3230 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3231 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3232 if (reg1 != 0) {
3233 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3235 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3237 gen_set_label(lab_fail);
3239 if (reg1 != 0) {
3240 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3242 gen_set_label(lab_done);
3243 tcg_gen_movi_tl(lladdr, -1);
3244 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3247 /* Load and store */
3248 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3249 TCGv t0)
3252 * Don't do NOP if destination is zero: we must perform the actual
3253 * memory access.
3255 switch (opc) {
3256 case OPC_LWC1:
3258 TCGv_i32 fp0 = tcg_temp_new_i32();
3259 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3260 ctx->default_tcg_memop_mask);
3261 gen_store_fpr32(ctx, fp0, ft);
3262 tcg_temp_free_i32(fp0);
3264 break;
3265 case OPC_SWC1:
3267 TCGv_i32 fp0 = tcg_temp_new_i32();
3268 gen_load_fpr32(ctx, fp0, ft);
3269 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3270 ctx->default_tcg_memop_mask);
3271 tcg_temp_free_i32(fp0);
3273 break;
3274 case OPC_LDC1:
3276 TCGv_i64 fp0 = tcg_temp_new_i64();
3277 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3278 ctx->default_tcg_memop_mask);
3279 gen_store_fpr64(ctx, fp0, ft);
3280 tcg_temp_free_i64(fp0);
3282 break;
3283 case OPC_SDC1:
3285 TCGv_i64 fp0 = tcg_temp_new_i64();
3286 gen_load_fpr64(ctx, fp0, ft);
3287 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3288 ctx->default_tcg_memop_mask);
3289 tcg_temp_free_i64(fp0);
3291 break;
3292 default:
3293 MIPS_INVAL("flt_ldst");
3294 gen_reserved_instruction(ctx);
3295 break;
3299 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3300 int rs, int16_t imm)
3302 TCGv t0 = tcg_temp_new();
3304 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3305 check_cp1_enabled(ctx);
3306 switch (op) {
3307 case OPC_LDC1:
3308 case OPC_SDC1:
3309 check_insn(ctx, ISA_MIPS2);
3310 /* Fallthrough */
3311 default:
3312 gen_base_offset_addr(ctx, t0, rs, imm);
3313 gen_flt_ldst(ctx, op, rt, t0);
3315 } else {
3316 generate_exception_err(ctx, EXCP_CpU, 1);
3318 tcg_temp_free(t0);
3321 /* Arithmetic with immediate operand */
3322 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3323 int rt, int rs, int imm)
3325 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3327 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3329 * If no destination, treat it as a NOP.
3330 * For addi, we must generate the overflow exception when needed.
3332 return;
3334 switch (opc) {
3335 case OPC_ADDI:
3337 TCGv t0 = tcg_temp_local_new();
3338 TCGv t1 = tcg_temp_new();
3339 TCGv t2 = tcg_temp_new();
3340 TCGLabel *l1 = gen_new_label();
3342 gen_load_gpr(t1, rs);
3343 tcg_gen_addi_tl(t0, t1, uimm);
3344 tcg_gen_ext32s_tl(t0, t0);
3346 tcg_gen_xori_tl(t1, t1, ~uimm);
3347 tcg_gen_xori_tl(t2, t0, uimm);
3348 tcg_gen_and_tl(t1, t1, t2);
3349 tcg_temp_free(t2);
3350 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3351 tcg_temp_free(t1);
3352 /* operands of same sign, result different sign */
3353 generate_exception(ctx, EXCP_OVERFLOW);
3354 gen_set_label(l1);
3355 tcg_gen_ext32s_tl(t0, t0);
3356 gen_store_gpr(t0, rt);
3357 tcg_temp_free(t0);
3359 break;
3360 case OPC_ADDIU:
3361 if (rs != 0) {
3362 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3363 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3364 } else {
3365 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3367 break;
3368 #if defined(TARGET_MIPS64)
3369 case OPC_DADDI:
3371 TCGv t0 = tcg_temp_local_new();
3372 TCGv t1 = tcg_temp_new();
3373 TCGv t2 = tcg_temp_new();
3374 TCGLabel *l1 = gen_new_label();
3376 gen_load_gpr(t1, rs);
3377 tcg_gen_addi_tl(t0, t1, uimm);
3379 tcg_gen_xori_tl(t1, t1, ~uimm);
3380 tcg_gen_xori_tl(t2, t0, uimm);
3381 tcg_gen_and_tl(t1, t1, t2);
3382 tcg_temp_free(t2);
3383 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3384 tcg_temp_free(t1);
3385 /* operands of same sign, result different sign */
3386 generate_exception(ctx, EXCP_OVERFLOW);
3387 gen_set_label(l1);
3388 gen_store_gpr(t0, rt);
3389 tcg_temp_free(t0);
3391 break;
3392 case OPC_DADDIU:
3393 if (rs != 0) {
3394 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3395 } else {
3396 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3398 break;
3399 #endif
3403 /* Logic with immediate operand */
3404 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3405 int rt, int rs, int16_t imm)
3407 target_ulong uimm;
3409 if (rt == 0) {
3410 /* If no destination, treat it as a NOP. */
3411 return;
3413 uimm = (uint16_t)imm;
3414 switch (opc) {
3415 case OPC_ANDI:
3416 if (likely(rs != 0)) {
3417 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3418 } else {
3419 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3421 break;
3422 case OPC_ORI:
3423 if (rs != 0) {
3424 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3425 } else {
3426 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3428 break;
3429 case OPC_XORI:
3430 if (likely(rs != 0)) {
3431 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3432 } else {
3433 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3435 break;
3436 case OPC_LUI:
3437 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
3438 /* OPC_AUI */
3439 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3440 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3441 } else {
3442 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3444 break;
3446 default:
3447 break;
3451 /* Set on less than with immediate operand */
3452 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3453 int rt, int rs, int16_t imm)
3455 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3456 TCGv t0;
3458 if (rt == 0) {
3459 /* If no destination, treat it as a NOP. */
3460 return;
3462 t0 = tcg_temp_new();
3463 gen_load_gpr(t0, rs);
3464 switch (opc) {
3465 case OPC_SLTI:
3466 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3467 break;
3468 case OPC_SLTIU:
3469 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3470 break;
3472 tcg_temp_free(t0);
3475 /* Shifts with immediate operand */
3476 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3477 int rt, int rs, int16_t imm)
3479 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3480 TCGv t0;
3482 if (rt == 0) {
3483 /* If no destination, treat it as a NOP. */
3484 return;
3487 t0 = tcg_temp_new();
3488 gen_load_gpr(t0, rs);
3489 switch (opc) {
3490 case OPC_SLL:
3491 tcg_gen_shli_tl(t0, t0, uimm);
3492 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3493 break;
3494 case OPC_SRA:
3495 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3496 break;
3497 case OPC_SRL:
3498 if (uimm != 0) {
3499 tcg_gen_ext32u_tl(t0, t0);
3500 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3501 } else {
3502 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3504 break;
3505 case OPC_ROTR:
3506 if (uimm != 0) {
3507 TCGv_i32 t1 = tcg_temp_new_i32();
3509 tcg_gen_trunc_tl_i32(t1, t0);
3510 tcg_gen_rotri_i32(t1, t1, uimm);
3511 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3512 tcg_temp_free_i32(t1);
3513 } else {
3514 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3516 break;
3517 #if defined(TARGET_MIPS64)
3518 case OPC_DSLL:
3519 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3520 break;
3521 case OPC_DSRA:
3522 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3523 break;
3524 case OPC_DSRL:
3525 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3526 break;
3527 case OPC_DROTR:
3528 if (uimm != 0) {
3529 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3530 } else {
3531 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3533 break;
3534 case OPC_DSLL32:
3535 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3536 break;
3537 case OPC_DSRA32:
3538 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3539 break;
3540 case OPC_DSRL32:
3541 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3542 break;
3543 case OPC_DROTR32:
3544 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3545 break;
3546 #endif
3548 tcg_temp_free(t0);
3551 /* Arithmetic */
3552 static void gen_arith(DisasContext *ctx, uint32_t opc,
3553 int rd, int rs, int rt)
3555 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3556 && opc != OPC_DADD && opc != OPC_DSUB) {
3558 * If no destination, treat it as a NOP.
3559 * For add & sub, we must generate the overflow exception when needed.
3561 return;
3564 switch (opc) {
3565 case OPC_ADD:
3567 TCGv t0 = tcg_temp_local_new();
3568 TCGv t1 = tcg_temp_new();
3569 TCGv t2 = tcg_temp_new();
3570 TCGLabel *l1 = gen_new_label();
3572 gen_load_gpr(t1, rs);
3573 gen_load_gpr(t2, rt);
3574 tcg_gen_add_tl(t0, t1, t2);
3575 tcg_gen_ext32s_tl(t0, t0);
3576 tcg_gen_xor_tl(t1, t1, t2);
3577 tcg_gen_xor_tl(t2, t0, t2);
3578 tcg_gen_andc_tl(t1, t2, t1);
3579 tcg_temp_free(t2);
3580 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3581 tcg_temp_free(t1);
3582 /* operands of same sign, result different sign */
3583 generate_exception(ctx, EXCP_OVERFLOW);
3584 gen_set_label(l1);
3585 gen_store_gpr(t0, rd);
3586 tcg_temp_free(t0);
3588 break;
3589 case OPC_ADDU:
3590 if (rs != 0 && rt != 0) {
3591 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3592 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3593 } else if (rs == 0 && rt != 0) {
3594 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3595 } else if (rs != 0 && rt == 0) {
3596 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3597 } else {
3598 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3600 break;
3601 case OPC_SUB:
3603 TCGv t0 = tcg_temp_local_new();
3604 TCGv t1 = tcg_temp_new();
3605 TCGv t2 = tcg_temp_new();
3606 TCGLabel *l1 = gen_new_label();
3608 gen_load_gpr(t1, rs);
3609 gen_load_gpr(t2, rt);
3610 tcg_gen_sub_tl(t0, t1, t2);
3611 tcg_gen_ext32s_tl(t0, t0);
3612 tcg_gen_xor_tl(t2, t1, t2);
3613 tcg_gen_xor_tl(t1, t0, t1);
3614 tcg_gen_and_tl(t1, t1, t2);
3615 tcg_temp_free(t2);
3616 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3617 tcg_temp_free(t1);
3619 * operands of different sign, first operand and the result
3620 * of different sign
3622 generate_exception(ctx, EXCP_OVERFLOW);
3623 gen_set_label(l1);
3624 gen_store_gpr(t0, rd);
3625 tcg_temp_free(t0);
3627 break;
3628 case OPC_SUBU:
3629 if (rs != 0 && rt != 0) {
3630 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3631 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3632 } else if (rs == 0 && rt != 0) {
3633 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3634 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3635 } else if (rs != 0 && rt == 0) {
3636 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3637 } else {
3638 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3640 break;
3641 #if defined(TARGET_MIPS64)
3642 case OPC_DADD:
3644 TCGv t0 = tcg_temp_local_new();
3645 TCGv t1 = tcg_temp_new();
3646 TCGv t2 = tcg_temp_new();
3647 TCGLabel *l1 = gen_new_label();
3649 gen_load_gpr(t1, rs);
3650 gen_load_gpr(t2, rt);
3651 tcg_gen_add_tl(t0, t1, t2);
3652 tcg_gen_xor_tl(t1, t1, t2);
3653 tcg_gen_xor_tl(t2, t0, t2);
3654 tcg_gen_andc_tl(t1, t2, t1);
3655 tcg_temp_free(t2);
3656 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3657 tcg_temp_free(t1);
3658 /* operands of same sign, result different sign */
3659 generate_exception(ctx, EXCP_OVERFLOW);
3660 gen_set_label(l1);
3661 gen_store_gpr(t0, rd);
3662 tcg_temp_free(t0);
3664 break;
3665 case OPC_DADDU:
3666 if (rs != 0 && rt != 0) {
3667 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3668 } else if (rs == 0 && rt != 0) {
3669 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3670 } else if (rs != 0 && rt == 0) {
3671 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3672 } else {
3673 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3675 break;
3676 case OPC_DSUB:
3678 TCGv t0 = tcg_temp_local_new();
3679 TCGv t1 = tcg_temp_new();
3680 TCGv t2 = tcg_temp_new();
3681 TCGLabel *l1 = gen_new_label();
3683 gen_load_gpr(t1, rs);
3684 gen_load_gpr(t2, rt);
3685 tcg_gen_sub_tl(t0, t1, t2);
3686 tcg_gen_xor_tl(t2, t1, t2);
3687 tcg_gen_xor_tl(t1, t0, t1);
3688 tcg_gen_and_tl(t1, t1, t2);
3689 tcg_temp_free(t2);
3690 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3691 tcg_temp_free(t1);
3693 * Operands of different sign, first operand and result different
3694 * sign.
3696 generate_exception(ctx, EXCP_OVERFLOW);
3697 gen_set_label(l1);
3698 gen_store_gpr(t0, rd);
3699 tcg_temp_free(t0);
3701 break;
3702 case OPC_DSUBU:
3703 if (rs != 0 && rt != 0) {
3704 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3705 } else if (rs == 0 && rt != 0) {
3706 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3707 } else if (rs != 0 && rt == 0) {
3708 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3709 } else {
3710 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3712 break;
3713 #endif
3714 case OPC_MUL:
3715 if (likely(rs != 0 && rt != 0)) {
3716 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3717 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3718 } else {
3719 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3721 break;
3725 /* Conditional move */
3726 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
3727 int rd, int rs, int rt)
3729 TCGv t0, t1, t2;
3731 if (rd == 0) {
3732 /* If no destination, treat it as a NOP. */
3733 return;
3736 t0 = tcg_temp_new();
3737 gen_load_gpr(t0, rt);
3738 t1 = tcg_const_tl(0);
3739 t2 = tcg_temp_new();
3740 gen_load_gpr(t2, rs);
3741 switch (opc) {
3742 case OPC_MOVN:
3743 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3744 break;
3745 case OPC_MOVZ:
3746 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3747 break;
3748 case OPC_SELNEZ:
3749 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
3750 break;
3751 case OPC_SELEQZ:
3752 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
3753 break;
3755 tcg_temp_free(t2);
3756 tcg_temp_free(t1);
3757 tcg_temp_free(t0);
3760 /* Logic */
3761 static void gen_logic(DisasContext *ctx, uint32_t opc,
3762 int rd, int rs, int rt)
3764 if (rd == 0) {
3765 /* If no destination, treat it as a NOP. */
3766 return;
3769 switch (opc) {
3770 case OPC_AND:
3771 if (likely(rs != 0 && rt != 0)) {
3772 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3773 } else {
3774 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3776 break;
3777 case OPC_NOR:
3778 if (rs != 0 && rt != 0) {
3779 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3780 } else if (rs == 0 && rt != 0) {
3781 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
3782 } else if (rs != 0 && rt == 0) {
3783 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
3784 } else {
3785 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
3787 break;
3788 case OPC_OR:
3789 if (likely(rs != 0 && rt != 0)) {
3790 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3791 } else if (rs == 0 && rt != 0) {
3792 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3793 } else if (rs != 0 && rt == 0) {
3794 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3795 } else {
3796 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3798 break;
3799 case OPC_XOR:
3800 if (likely(rs != 0 && rt != 0)) {
3801 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3802 } else if (rs == 0 && rt != 0) {
3803 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3804 } else if (rs != 0 && rt == 0) {
3805 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3806 } else {
3807 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3809 break;
3813 /* Set on lower than */
3814 static void gen_slt(DisasContext *ctx, uint32_t opc,
3815 int rd, int rs, int rt)
3817 TCGv t0, t1;
3819 if (rd == 0) {
3820 /* If no destination, treat it as a NOP. */
3821 return;
3824 t0 = tcg_temp_new();
3825 t1 = tcg_temp_new();
3826 gen_load_gpr(t0, rs);
3827 gen_load_gpr(t1, rt);
3828 switch (opc) {
3829 case OPC_SLT:
3830 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3831 break;
3832 case OPC_SLTU:
3833 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3834 break;
3836 tcg_temp_free(t0);
3837 tcg_temp_free(t1);
3840 /* Shifts */
3841 static void gen_shift(DisasContext *ctx, uint32_t opc,
3842 int rd, int rs, int rt)
3844 TCGv t0, t1;
3846 if (rd == 0) {
3848 * If no destination, treat it as a NOP.
3849 * For add & sub, we must generate the overflow exception when needed.
3851 return;
3854 t0 = tcg_temp_new();
3855 t1 = tcg_temp_new();
3856 gen_load_gpr(t0, rs);
3857 gen_load_gpr(t1, rt);
3858 switch (opc) {
3859 case OPC_SLLV:
3860 tcg_gen_andi_tl(t0, t0, 0x1f);
3861 tcg_gen_shl_tl(t0, t1, t0);
3862 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3863 break;
3864 case OPC_SRAV:
3865 tcg_gen_andi_tl(t0, t0, 0x1f);
3866 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3867 break;
3868 case OPC_SRLV:
3869 tcg_gen_ext32u_tl(t1, t1);
3870 tcg_gen_andi_tl(t0, t0, 0x1f);
3871 tcg_gen_shr_tl(t0, t1, t0);
3872 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3873 break;
3874 case OPC_ROTRV:
3876 TCGv_i32 t2 = tcg_temp_new_i32();
3877 TCGv_i32 t3 = tcg_temp_new_i32();
3879 tcg_gen_trunc_tl_i32(t2, t0);
3880 tcg_gen_trunc_tl_i32(t3, t1);
3881 tcg_gen_andi_i32(t2, t2, 0x1f);
3882 tcg_gen_rotr_i32(t2, t3, t2);
3883 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3884 tcg_temp_free_i32(t2);
3885 tcg_temp_free_i32(t3);
3887 break;
3888 #if defined(TARGET_MIPS64)
3889 case OPC_DSLLV:
3890 tcg_gen_andi_tl(t0, t0, 0x3f);
3891 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3892 break;
3893 case OPC_DSRAV:
3894 tcg_gen_andi_tl(t0, t0, 0x3f);
3895 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3896 break;
3897 case OPC_DSRLV:
3898 tcg_gen_andi_tl(t0, t0, 0x3f);
3899 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3900 break;
3901 case OPC_DROTRV:
3902 tcg_gen_andi_tl(t0, t0, 0x3f);
3903 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3904 break;
3905 #endif
3907 tcg_temp_free(t0);
3908 tcg_temp_free(t1);
3911 #if defined(TARGET_MIPS64)
3912 /* Copy GPR to and from TX79 HI1/LO1 register. */
3913 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
3915 switch (opc) {
3916 case MMI_OPC_MFHI1:
3917 gen_store_gpr(cpu_HI[1], reg);
3918 break;
3919 case MMI_OPC_MFLO1:
3920 gen_store_gpr(cpu_LO[1], reg);
3921 break;
3922 case MMI_OPC_MTHI1:
3923 gen_load_gpr(cpu_HI[1], reg);
3924 break;
3925 case MMI_OPC_MTLO1:
3926 gen_load_gpr(cpu_LO[1], reg);
3927 break;
3928 default:
3929 MIPS_INVAL("mfthilo1 TX79");
3930 gen_reserved_instruction(ctx);
3931 break;
3934 #endif
3936 /* Arithmetic on HI/LO registers */
3937 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3939 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3940 /* Treat as NOP. */
3941 return;
3944 if (acc != 0) {
3945 check_dsp(ctx);
3948 switch (opc) {
3949 case OPC_MFHI:
3950 #if defined(TARGET_MIPS64)
3951 if (acc != 0) {
3952 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3953 } else
3954 #endif
3956 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3958 break;
3959 case OPC_MFLO:
3960 #if defined(TARGET_MIPS64)
3961 if (acc != 0) {
3962 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3963 } else
3964 #endif
3966 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3968 break;
3969 case OPC_MTHI:
3970 if (reg != 0) {
3971 #if defined(TARGET_MIPS64)
3972 if (acc != 0) {
3973 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3974 } else
3975 #endif
3977 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3979 } else {
3980 tcg_gen_movi_tl(cpu_HI[acc], 0);
3982 break;
3983 case OPC_MTLO:
3984 if (reg != 0) {
3985 #if defined(TARGET_MIPS64)
3986 if (acc != 0) {
3987 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3988 } else
3989 #endif
3991 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3993 } else {
3994 tcg_gen_movi_tl(cpu_LO[acc], 0);
3996 break;
4000 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4001 MemOp memop)
4003 TCGv t0 = tcg_const_tl(addr);
4004 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4005 gen_store_gpr(t0, reg);
4006 tcg_temp_free(t0);
4009 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4010 int rs)
4012 target_long offset;
4013 target_long addr;
4015 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4016 case OPC_ADDIUPC:
4017 if (rs != 0) {
4018 offset = sextract32(ctx->opcode << 2, 0, 21);
4019 addr = addr_add(ctx, pc, offset);
4020 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4022 break;
4023 case R6_OPC_LWPC:
4024 offset = sextract32(ctx->opcode << 2, 0, 21);
4025 addr = addr_add(ctx, pc, offset);
4026 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4027 break;
4028 #if defined(TARGET_MIPS64)
4029 case OPC_LWUPC:
4030 check_mips_64(ctx);
4031 offset = sextract32(ctx->opcode << 2, 0, 21);
4032 addr = addr_add(ctx, pc, offset);
4033 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4034 break;
4035 #endif
4036 default:
4037 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4038 case OPC_AUIPC:
4039 if (rs != 0) {
4040 offset = sextract32(ctx->opcode, 0, 16) << 16;
4041 addr = addr_add(ctx, pc, offset);
4042 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4044 break;
4045 case OPC_ALUIPC:
4046 if (rs != 0) {
4047 offset = sextract32(ctx->opcode, 0, 16) << 16;
4048 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4049 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4051 break;
4052 #if defined(TARGET_MIPS64)
4053 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4054 case R6_OPC_LDPC + (1 << 16):
4055 case R6_OPC_LDPC + (2 << 16):
4056 case R6_OPC_LDPC + (3 << 16):
4057 check_mips_64(ctx);
4058 offset = sextract32(ctx->opcode << 3, 0, 21);
4059 addr = addr_add(ctx, (pc & ~0x7), offset);
4060 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4061 break;
4062 #endif
4063 default:
4064 MIPS_INVAL("OPC_PCREL");
4065 gen_reserved_instruction(ctx);
4066 break;
4068 break;
4072 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4074 TCGv t0, t1;
4076 if (rd == 0) {
4077 /* Treat as NOP. */
4078 return;
4081 t0 = tcg_temp_new();
4082 t1 = tcg_temp_new();
4084 gen_load_gpr(t0, rs);
4085 gen_load_gpr(t1, rt);
4087 switch (opc) {
4088 case R6_OPC_DIV:
4090 TCGv t2 = tcg_temp_new();
4091 TCGv t3 = tcg_temp_new();
4092 tcg_gen_ext32s_tl(t0, t0);
4093 tcg_gen_ext32s_tl(t1, t1);
4094 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4095 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4096 tcg_gen_and_tl(t2, t2, t3);
4097 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4098 tcg_gen_or_tl(t2, t2, t3);
4099 tcg_gen_movi_tl(t3, 0);
4100 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4101 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4102 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4103 tcg_temp_free(t3);
4104 tcg_temp_free(t2);
4106 break;
4107 case R6_OPC_MOD:
4109 TCGv t2 = tcg_temp_new();
4110 TCGv t3 = tcg_temp_new();
4111 tcg_gen_ext32s_tl(t0, t0);
4112 tcg_gen_ext32s_tl(t1, t1);
4113 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4114 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4115 tcg_gen_and_tl(t2, t2, t3);
4116 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4117 tcg_gen_or_tl(t2, t2, t3);
4118 tcg_gen_movi_tl(t3, 0);
4119 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4120 tcg_gen_rem_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_DIVU:
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_divu_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_MODU:
4141 TCGv t2 = tcg_const_tl(0);
4142 TCGv t3 = tcg_const_tl(1);
4143 tcg_gen_ext32u_tl(t0, t0);
4144 tcg_gen_ext32u_tl(t1, t1);
4145 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4146 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4147 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4148 tcg_temp_free(t3);
4149 tcg_temp_free(t2);
4151 break;
4152 case R6_OPC_MUL:
4154 TCGv_i32 t2 = tcg_temp_new_i32();
4155 TCGv_i32 t3 = tcg_temp_new_i32();
4156 tcg_gen_trunc_tl_i32(t2, t0);
4157 tcg_gen_trunc_tl_i32(t3, t1);
4158 tcg_gen_mul_i32(t2, t2, t3);
4159 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4160 tcg_temp_free_i32(t2);
4161 tcg_temp_free_i32(t3);
4163 break;
4164 case R6_OPC_MUH:
4166 TCGv_i32 t2 = tcg_temp_new_i32();
4167 TCGv_i32 t3 = tcg_temp_new_i32();
4168 tcg_gen_trunc_tl_i32(t2, t0);
4169 tcg_gen_trunc_tl_i32(t3, t1);
4170 tcg_gen_muls2_i32(t2, t3, t2, t3);
4171 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4172 tcg_temp_free_i32(t2);
4173 tcg_temp_free_i32(t3);
4175 break;
4176 case R6_OPC_MULU:
4178 TCGv_i32 t2 = tcg_temp_new_i32();
4179 TCGv_i32 t3 = tcg_temp_new_i32();
4180 tcg_gen_trunc_tl_i32(t2, t0);
4181 tcg_gen_trunc_tl_i32(t3, t1);
4182 tcg_gen_mul_i32(t2, t2, t3);
4183 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4184 tcg_temp_free_i32(t2);
4185 tcg_temp_free_i32(t3);
4187 break;
4188 case R6_OPC_MUHU:
4190 TCGv_i32 t2 = tcg_temp_new_i32();
4191 TCGv_i32 t3 = tcg_temp_new_i32();
4192 tcg_gen_trunc_tl_i32(t2, t0);
4193 tcg_gen_trunc_tl_i32(t3, t1);
4194 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4195 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4196 tcg_temp_free_i32(t2);
4197 tcg_temp_free_i32(t3);
4199 break;
4200 #if defined(TARGET_MIPS64)
4201 case R6_OPC_DDIV:
4203 TCGv t2 = tcg_temp_new();
4204 TCGv t3 = tcg_temp_new();
4205 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4206 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4207 tcg_gen_and_tl(t2, t2, t3);
4208 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4209 tcg_gen_or_tl(t2, t2, t3);
4210 tcg_gen_movi_tl(t3, 0);
4211 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4212 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4213 tcg_temp_free(t3);
4214 tcg_temp_free(t2);
4216 break;
4217 case R6_OPC_DMOD:
4219 TCGv t2 = tcg_temp_new();
4220 TCGv t3 = tcg_temp_new();
4221 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4222 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4223 tcg_gen_and_tl(t2, t2, t3);
4224 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4225 tcg_gen_or_tl(t2, t2, t3);
4226 tcg_gen_movi_tl(t3, 0);
4227 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4228 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4229 tcg_temp_free(t3);
4230 tcg_temp_free(t2);
4232 break;
4233 case R6_OPC_DDIVU:
4235 TCGv t2 = tcg_const_tl(0);
4236 TCGv t3 = tcg_const_tl(1);
4237 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4238 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4239 tcg_temp_free(t3);
4240 tcg_temp_free(t2);
4242 break;
4243 case R6_OPC_DMODU:
4245 TCGv t2 = tcg_const_tl(0);
4246 TCGv t3 = tcg_const_tl(1);
4247 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4248 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4249 tcg_temp_free(t3);
4250 tcg_temp_free(t2);
4252 break;
4253 case R6_OPC_DMUL:
4254 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4255 break;
4256 case R6_OPC_DMUH:
4258 TCGv t2 = tcg_temp_new();
4259 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4260 tcg_temp_free(t2);
4262 break;
4263 case R6_OPC_DMULU:
4264 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4265 break;
4266 case R6_OPC_DMUHU:
4268 TCGv t2 = tcg_temp_new();
4269 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4270 tcg_temp_free(t2);
4272 break;
4273 #endif
4274 default:
4275 MIPS_INVAL("r6 mul/div");
4276 gen_reserved_instruction(ctx);
4277 goto out;
4279 out:
4280 tcg_temp_free(t0);
4281 tcg_temp_free(t1);
4284 #if defined(TARGET_MIPS64)
4285 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4287 TCGv t0, t1;
4289 t0 = tcg_temp_new();
4290 t1 = tcg_temp_new();
4292 gen_load_gpr(t0, rs);
4293 gen_load_gpr(t1, rt);
4295 switch (opc) {
4296 case MMI_OPC_DIV1:
4298 TCGv t2 = tcg_temp_new();
4299 TCGv t3 = tcg_temp_new();
4300 tcg_gen_ext32s_tl(t0, t0);
4301 tcg_gen_ext32s_tl(t1, t1);
4302 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4303 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4304 tcg_gen_and_tl(t2, t2, t3);
4305 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4306 tcg_gen_or_tl(t2, t2, t3);
4307 tcg_gen_movi_tl(t3, 0);
4308 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4309 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4310 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4311 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4312 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4313 tcg_temp_free(t3);
4314 tcg_temp_free(t2);
4316 break;
4317 case MMI_OPC_DIVU1:
4319 TCGv t2 = tcg_const_tl(0);
4320 TCGv t3 = tcg_const_tl(1);
4321 tcg_gen_ext32u_tl(t0, t0);
4322 tcg_gen_ext32u_tl(t1, t1);
4323 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4324 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4325 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4326 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4327 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4328 tcg_temp_free(t3);
4329 tcg_temp_free(t2);
4331 break;
4332 default:
4333 MIPS_INVAL("div1 TX79");
4334 gen_reserved_instruction(ctx);
4335 goto out;
4337 out:
4338 tcg_temp_free(t0);
4339 tcg_temp_free(t1);
4341 #endif
4343 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4344 int acc, int rs, int rt)
4346 TCGv t0, t1;
4348 t0 = tcg_temp_new();
4349 t1 = tcg_temp_new();
4351 gen_load_gpr(t0, rs);
4352 gen_load_gpr(t1, rt);
4354 if (acc != 0) {
4355 check_dsp(ctx);
4358 switch (opc) {
4359 case OPC_DIV:
4361 TCGv t2 = tcg_temp_new();
4362 TCGv t3 = tcg_temp_new();
4363 tcg_gen_ext32s_tl(t0, t0);
4364 tcg_gen_ext32s_tl(t1, t1);
4365 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4366 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4367 tcg_gen_and_tl(t2, t2, t3);
4368 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4369 tcg_gen_or_tl(t2, t2, t3);
4370 tcg_gen_movi_tl(t3, 0);
4371 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4372 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4373 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4374 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4375 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4376 tcg_temp_free(t3);
4377 tcg_temp_free(t2);
4379 break;
4380 case OPC_DIVU:
4382 TCGv t2 = tcg_const_tl(0);
4383 TCGv t3 = tcg_const_tl(1);
4384 tcg_gen_ext32u_tl(t0, t0);
4385 tcg_gen_ext32u_tl(t1, t1);
4386 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4387 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4388 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4389 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4390 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4391 tcg_temp_free(t3);
4392 tcg_temp_free(t2);
4394 break;
4395 case OPC_MULT:
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_muls2_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 case OPC_MULTU:
4410 TCGv_i32 t2 = tcg_temp_new_i32();
4411 TCGv_i32 t3 = tcg_temp_new_i32();
4412 tcg_gen_trunc_tl_i32(t2, t0);
4413 tcg_gen_trunc_tl_i32(t3, t1);
4414 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4415 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4416 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4417 tcg_temp_free_i32(t2);
4418 tcg_temp_free_i32(t3);
4420 break;
4421 #if defined(TARGET_MIPS64)
4422 case OPC_DDIV:
4424 TCGv t2 = tcg_temp_new();
4425 TCGv t3 = tcg_temp_new();
4426 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4427 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4428 tcg_gen_and_tl(t2, t2, t3);
4429 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4430 tcg_gen_or_tl(t2, t2, t3);
4431 tcg_gen_movi_tl(t3, 0);
4432 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4433 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4434 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4435 tcg_temp_free(t3);
4436 tcg_temp_free(t2);
4438 break;
4439 case OPC_DDIVU:
4441 TCGv t2 = tcg_const_tl(0);
4442 TCGv t3 = tcg_const_tl(1);
4443 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4444 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4445 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4446 tcg_temp_free(t3);
4447 tcg_temp_free(t2);
4449 break;
4450 case OPC_DMULT:
4451 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4452 break;
4453 case OPC_DMULTU:
4454 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4455 break;
4456 #endif
4457 case OPC_MADD:
4459 TCGv_i64 t2 = tcg_temp_new_i64();
4460 TCGv_i64 t3 = tcg_temp_new_i64();
4462 tcg_gen_ext_tl_i64(t2, t0);
4463 tcg_gen_ext_tl_i64(t3, t1);
4464 tcg_gen_mul_i64(t2, t2, t3);
4465 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4466 tcg_gen_add_i64(t2, t2, t3);
4467 tcg_temp_free_i64(t3);
4468 gen_move_low32(cpu_LO[acc], t2);
4469 gen_move_high32(cpu_HI[acc], t2);
4470 tcg_temp_free_i64(t2);
4472 break;
4473 case OPC_MADDU:
4475 TCGv_i64 t2 = tcg_temp_new_i64();
4476 TCGv_i64 t3 = tcg_temp_new_i64();
4478 tcg_gen_ext32u_tl(t0, t0);
4479 tcg_gen_ext32u_tl(t1, t1);
4480 tcg_gen_extu_tl_i64(t2, t0);
4481 tcg_gen_extu_tl_i64(t3, t1);
4482 tcg_gen_mul_i64(t2, t2, t3);
4483 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4484 tcg_gen_add_i64(t2, t2, t3);
4485 tcg_temp_free_i64(t3);
4486 gen_move_low32(cpu_LO[acc], t2);
4487 gen_move_high32(cpu_HI[acc], t2);
4488 tcg_temp_free_i64(t2);
4490 break;
4491 case OPC_MSUB:
4493 TCGv_i64 t2 = tcg_temp_new_i64();
4494 TCGv_i64 t3 = tcg_temp_new_i64();
4496 tcg_gen_ext_tl_i64(t2, t0);
4497 tcg_gen_ext_tl_i64(t3, t1);
4498 tcg_gen_mul_i64(t2, t2, t3);
4499 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4500 tcg_gen_sub_i64(t2, t3, t2);
4501 tcg_temp_free_i64(t3);
4502 gen_move_low32(cpu_LO[acc], t2);
4503 gen_move_high32(cpu_HI[acc], t2);
4504 tcg_temp_free_i64(t2);
4506 break;
4507 case OPC_MSUBU:
4509 TCGv_i64 t2 = tcg_temp_new_i64();
4510 TCGv_i64 t3 = tcg_temp_new_i64();
4512 tcg_gen_ext32u_tl(t0, t0);
4513 tcg_gen_ext32u_tl(t1, t1);
4514 tcg_gen_extu_tl_i64(t2, t0);
4515 tcg_gen_extu_tl_i64(t3, t1);
4516 tcg_gen_mul_i64(t2, t2, t3);
4517 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4518 tcg_gen_sub_i64(t2, t3, t2);
4519 tcg_temp_free_i64(t3);
4520 gen_move_low32(cpu_LO[acc], t2);
4521 gen_move_high32(cpu_HI[acc], t2);
4522 tcg_temp_free_i64(t2);
4524 break;
4525 default:
4526 MIPS_INVAL("mul/div");
4527 gen_reserved_instruction(ctx);
4528 goto out;
4530 out:
4531 tcg_temp_free(t0);
4532 tcg_temp_free(t1);
4536 * These MULT[U] and MADD[U] instructions implemented in for example
4537 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
4538 * architectures are special three-operand variants with the syntax
4540 * MULT[U][1] rd, rs, rt
4542 * such that
4544 * (rd, LO, HI) <- rs * rt
4546 * and
4548 * MADD[U][1] rd, rs, rt
4550 * such that
4552 * (rd, LO, HI) <- (LO, HI) + rs * rt
4554 * where the low-order 32-bits of the result is placed into both the
4555 * GPR rd and the special register LO. The high-order 32-bits of the
4556 * result is placed into the special register HI.
4558 * If the GPR rd is omitted in assembly language, it is taken to be 0,
4559 * which is the zero register that always reads as 0.
4561 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
4562 int rd, int rs, int rt)
4564 TCGv t0 = tcg_temp_new();
4565 TCGv t1 = tcg_temp_new();
4566 int acc = 0;
4568 gen_load_gpr(t0, rs);
4569 gen_load_gpr(t1, rt);
4571 switch (opc) {
4572 case MMI_OPC_MULT1:
4573 acc = 1;
4574 /* Fall through */
4575 case OPC_MULT:
4577 TCGv_i32 t2 = tcg_temp_new_i32();
4578 TCGv_i32 t3 = tcg_temp_new_i32();
4579 tcg_gen_trunc_tl_i32(t2, t0);
4580 tcg_gen_trunc_tl_i32(t3, t1);
4581 tcg_gen_muls2_i32(t2, t3, t2, t3);
4582 if (rd) {
4583 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4585 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4586 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4587 tcg_temp_free_i32(t2);
4588 tcg_temp_free_i32(t3);
4590 break;
4591 case MMI_OPC_MULTU1:
4592 acc = 1;
4593 /* Fall through */
4594 case OPC_MULTU:
4596 TCGv_i32 t2 = tcg_temp_new_i32();
4597 TCGv_i32 t3 = tcg_temp_new_i32();
4598 tcg_gen_trunc_tl_i32(t2, t0);
4599 tcg_gen_trunc_tl_i32(t3, t1);
4600 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4601 if (rd) {
4602 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4604 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4605 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4606 tcg_temp_free_i32(t2);
4607 tcg_temp_free_i32(t3);
4609 break;
4610 case MMI_OPC_MADD1:
4611 acc = 1;
4612 /* Fall through */
4613 case MMI_OPC_MADD:
4615 TCGv_i64 t2 = tcg_temp_new_i64();
4616 TCGv_i64 t3 = tcg_temp_new_i64();
4618 tcg_gen_ext_tl_i64(t2, t0);
4619 tcg_gen_ext_tl_i64(t3, t1);
4620 tcg_gen_mul_i64(t2, t2, t3);
4621 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4622 tcg_gen_add_i64(t2, t2, t3);
4623 tcg_temp_free_i64(t3);
4624 gen_move_low32(cpu_LO[acc], t2);
4625 gen_move_high32(cpu_HI[acc], t2);
4626 if (rd) {
4627 gen_move_low32(cpu_gpr[rd], t2);
4629 tcg_temp_free_i64(t2);
4631 break;
4632 case MMI_OPC_MADDU1:
4633 acc = 1;
4634 /* Fall through */
4635 case MMI_OPC_MADDU:
4637 TCGv_i64 t2 = tcg_temp_new_i64();
4638 TCGv_i64 t3 = tcg_temp_new_i64();
4640 tcg_gen_ext32u_tl(t0, t0);
4641 tcg_gen_ext32u_tl(t1, t1);
4642 tcg_gen_extu_tl_i64(t2, t0);
4643 tcg_gen_extu_tl_i64(t3, t1);
4644 tcg_gen_mul_i64(t2, t2, t3);
4645 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4646 tcg_gen_add_i64(t2, t2, t3);
4647 tcg_temp_free_i64(t3);
4648 gen_move_low32(cpu_LO[acc], t2);
4649 gen_move_high32(cpu_HI[acc], t2);
4650 if (rd) {
4651 gen_move_low32(cpu_gpr[rd], t2);
4653 tcg_temp_free_i64(t2);
4655 break;
4656 default:
4657 MIPS_INVAL("mul/madd TXx9");
4658 gen_reserved_instruction(ctx);
4659 goto out;
4662 out:
4663 tcg_temp_free(t0);
4664 tcg_temp_free(t1);
4667 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
4668 int rd, int rs, int rt)
4670 TCGv t0 = tcg_temp_new();
4671 TCGv t1 = tcg_temp_new();
4673 gen_load_gpr(t0, rs);
4674 gen_load_gpr(t1, rt);
4676 switch (opc) {
4677 case OPC_VR54XX_MULS:
4678 gen_helper_muls(t0, cpu_env, t0, t1);
4679 break;
4680 case OPC_VR54XX_MULSU:
4681 gen_helper_mulsu(t0, cpu_env, t0, t1);
4682 break;
4683 case OPC_VR54XX_MACC:
4684 gen_helper_macc(t0, cpu_env, t0, t1);
4685 break;
4686 case OPC_VR54XX_MACCU:
4687 gen_helper_maccu(t0, cpu_env, t0, t1);
4688 break;
4689 case OPC_VR54XX_MSAC:
4690 gen_helper_msac(t0, cpu_env, t0, t1);
4691 break;
4692 case OPC_VR54XX_MSACU:
4693 gen_helper_msacu(t0, cpu_env, t0, t1);
4694 break;
4695 case OPC_VR54XX_MULHI:
4696 gen_helper_mulhi(t0, cpu_env, t0, t1);
4697 break;
4698 case OPC_VR54XX_MULHIU:
4699 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4700 break;
4701 case OPC_VR54XX_MULSHI:
4702 gen_helper_mulshi(t0, cpu_env, t0, t1);
4703 break;
4704 case OPC_VR54XX_MULSHIU:
4705 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4706 break;
4707 case OPC_VR54XX_MACCHI:
4708 gen_helper_macchi(t0, cpu_env, t0, t1);
4709 break;
4710 case OPC_VR54XX_MACCHIU:
4711 gen_helper_macchiu(t0, cpu_env, t0, t1);
4712 break;
4713 case OPC_VR54XX_MSACHI:
4714 gen_helper_msachi(t0, cpu_env, t0, t1);
4715 break;
4716 case OPC_VR54XX_MSACHIU:
4717 gen_helper_msachiu(t0, cpu_env, t0, t1);
4718 break;
4719 default:
4720 MIPS_INVAL("mul vr54xx");
4721 gen_reserved_instruction(ctx);
4722 goto out;
4724 gen_store_gpr(t0, rd);
4726 out:
4727 tcg_temp_free(t0);
4728 tcg_temp_free(t1);
4731 static void gen_cl(DisasContext *ctx, uint32_t opc,
4732 int rd, int rs)
4734 TCGv t0;
4736 if (rd == 0) {
4737 /* Treat as NOP. */
4738 return;
4740 t0 = cpu_gpr[rd];
4741 gen_load_gpr(t0, rs);
4743 switch (opc) {
4744 case OPC_CLO:
4745 case R6_OPC_CLO:
4746 #if defined(TARGET_MIPS64)
4747 case OPC_DCLO:
4748 case R6_OPC_DCLO:
4749 #endif
4750 tcg_gen_not_tl(t0, t0);
4751 break;
4754 switch (opc) {
4755 case OPC_CLO:
4756 case R6_OPC_CLO:
4757 case OPC_CLZ:
4758 case R6_OPC_CLZ:
4759 tcg_gen_ext32u_tl(t0, t0);
4760 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4761 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
4762 break;
4763 #if defined(TARGET_MIPS64)
4764 case OPC_DCLO:
4765 case R6_OPC_DCLO:
4766 case OPC_DCLZ:
4767 case R6_OPC_DCLZ:
4768 tcg_gen_clzi_i64(t0, t0, 64);
4769 break;
4770 #endif
4774 /* Godson integer instructions */
4775 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
4776 int rd, int rs, int rt)
4778 TCGv t0, t1;
4780 if (rd == 0) {
4781 /* Treat as NOP. */
4782 return;
4785 switch (opc) {
4786 case OPC_MULT_G_2E:
4787 case OPC_MULT_G_2F:
4788 case OPC_MULTU_G_2E:
4789 case OPC_MULTU_G_2F:
4790 #if defined(TARGET_MIPS64)
4791 case OPC_DMULT_G_2E:
4792 case OPC_DMULT_G_2F:
4793 case OPC_DMULTU_G_2E:
4794 case OPC_DMULTU_G_2F:
4795 #endif
4796 t0 = tcg_temp_new();
4797 t1 = tcg_temp_new();
4798 break;
4799 default:
4800 t0 = tcg_temp_local_new();
4801 t1 = tcg_temp_local_new();
4802 break;
4805 gen_load_gpr(t0, rs);
4806 gen_load_gpr(t1, rt);
4808 switch (opc) {
4809 case OPC_MULT_G_2E:
4810 case OPC_MULT_G_2F:
4811 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4812 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4813 break;
4814 case OPC_MULTU_G_2E:
4815 case OPC_MULTU_G_2F:
4816 tcg_gen_ext32u_tl(t0, t0);
4817 tcg_gen_ext32u_tl(t1, t1);
4818 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4819 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4820 break;
4821 case OPC_DIV_G_2E:
4822 case OPC_DIV_G_2F:
4824 TCGLabel *l1 = gen_new_label();
4825 TCGLabel *l2 = gen_new_label();
4826 TCGLabel *l3 = gen_new_label();
4827 tcg_gen_ext32s_tl(t0, t0);
4828 tcg_gen_ext32s_tl(t1, t1);
4829 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4830 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4831 tcg_gen_br(l3);
4832 gen_set_label(l1);
4833 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4834 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4835 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4836 tcg_gen_br(l3);
4837 gen_set_label(l2);
4838 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4839 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4840 gen_set_label(l3);
4842 break;
4843 case OPC_DIVU_G_2E:
4844 case OPC_DIVU_G_2F:
4846 TCGLabel *l1 = gen_new_label();
4847 TCGLabel *l2 = gen_new_label();
4848 tcg_gen_ext32u_tl(t0, t0);
4849 tcg_gen_ext32u_tl(t1, t1);
4850 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4851 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4852 tcg_gen_br(l2);
4853 gen_set_label(l1);
4854 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4855 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4856 gen_set_label(l2);
4858 break;
4859 case OPC_MOD_G_2E:
4860 case OPC_MOD_G_2F:
4862 TCGLabel *l1 = gen_new_label();
4863 TCGLabel *l2 = gen_new_label();
4864 TCGLabel *l3 = gen_new_label();
4865 tcg_gen_ext32u_tl(t0, t0);
4866 tcg_gen_ext32u_tl(t1, t1);
4867 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4868 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4869 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4870 gen_set_label(l1);
4871 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4872 tcg_gen_br(l3);
4873 gen_set_label(l2);
4874 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4875 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4876 gen_set_label(l3);
4878 break;
4879 case OPC_MODU_G_2E:
4880 case OPC_MODU_G_2F:
4882 TCGLabel *l1 = gen_new_label();
4883 TCGLabel *l2 = gen_new_label();
4884 tcg_gen_ext32u_tl(t0, t0);
4885 tcg_gen_ext32u_tl(t1, t1);
4886 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4887 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4888 tcg_gen_br(l2);
4889 gen_set_label(l1);
4890 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4891 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4892 gen_set_label(l2);
4894 break;
4895 #if defined(TARGET_MIPS64)
4896 case OPC_DMULT_G_2E:
4897 case OPC_DMULT_G_2F:
4898 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4899 break;
4900 case OPC_DMULTU_G_2E:
4901 case OPC_DMULTU_G_2F:
4902 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4903 break;
4904 case OPC_DDIV_G_2E:
4905 case OPC_DDIV_G_2F:
4907 TCGLabel *l1 = gen_new_label();
4908 TCGLabel *l2 = gen_new_label();
4909 TCGLabel *l3 = gen_new_label();
4910 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4911 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4912 tcg_gen_br(l3);
4913 gen_set_label(l1);
4914 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4915 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4916 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4917 tcg_gen_br(l3);
4918 gen_set_label(l2);
4919 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4920 gen_set_label(l3);
4922 break;
4923 case OPC_DDIVU_G_2E:
4924 case OPC_DDIVU_G_2F:
4926 TCGLabel *l1 = gen_new_label();
4927 TCGLabel *l2 = gen_new_label();
4928 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4929 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4930 tcg_gen_br(l2);
4931 gen_set_label(l1);
4932 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4933 gen_set_label(l2);
4935 break;
4936 case OPC_DMOD_G_2E:
4937 case OPC_DMOD_G_2F:
4939 TCGLabel *l1 = gen_new_label();
4940 TCGLabel *l2 = gen_new_label();
4941 TCGLabel *l3 = gen_new_label();
4942 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4943 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4944 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4945 gen_set_label(l1);
4946 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4947 tcg_gen_br(l3);
4948 gen_set_label(l2);
4949 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4950 gen_set_label(l3);
4952 break;
4953 case OPC_DMODU_G_2E:
4954 case OPC_DMODU_G_2F:
4956 TCGLabel *l1 = gen_new_label();
4957 TCGLabel *l2 = gen_new_label();
4958 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4959 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4960 tcg_gen_br(l2);
4961 gen_set_label(l1);
4962 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4963 gen_set_label(l2);
4965 break;
4966 #endif
4969 tcg_temp_free(t0);
4970 tcg_temp_free(t1);
4973 /* Loongson multimedia instructions */
4974 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4976 uint32_t opc, shift_max;
4977 TCGv_i64 t0, t1;
4978 TCGCond cond;
4980 opc = MASK_LMMI(ctx->opcode);
4981 switch (opc) {
4982 case OPC_ADD_CP2:
4983 case OPC_SUB_CP2:
4984 case OPC_DADD_CP2:
4985 case OPC_DSUB_CP2:
4986 t0 = tcg_temp_local_new_i64();
4987 t1 = tcg_temp_local_new_i64();
4988 break;
4989 default:
4990 t0 = tcg_temp_new_i64();
4991 t1 = tcg_temp_new_i64();
4992 break;
4995 check_cp1_enabled(ctx);
4996 gen_load_fpr64(ctx, t0, rs);
4997 gen_load_fpr64(ctx, t1, rt);
4999 switch (opc) {
5000 case OPC_PADDSH:
5001 gen_helper_paddsh(t0, t0, t1);
5002 break;
5003 case OPC_PADDUSH:
5004 gen_helper_paddush(t0, t0, t1);
5005 break;
5006 case OPC_PADDH:
5007 gen_helper_paddh(t0, t0, t1);
5008 break;
5009 case OPC_PADDW:
5010 gen_helper_paddw(t0, t0, t1);
5011 break;
5012 case OPC_PADDSB:
5013 gen_helper_paddsb(t0, t0, t1);
5014 break;
5015 case OPC_PADDUSB:
5016 gen_helper_paddusb(t0, t0, t1);
5017 break;
5018 case OPC_PADDB:
5019 gen_helper_paddb(t0, t0, t1);
5020 break;
5022 case OPC_PSUBSH:
5023 gen_helper_psubsh(t0, t0, t1);
5024 break;
5025 case OPC_PSUBUSH:
5026 gen_helper_psubush(t0, t0, t1);
5027 break;
5028 case OPC_PSUBH:
5029 gen_helper_psubh(t0, t0, t1);
5030 break;
5031 case OPC_PSUBW:
5032 gen_helper_psubw(t0, t0, t1);
5033 break;
5034 case OPC_PSUBSB:
5035 gen_helper_psubsb(t0, t0, t1);
5036 break;
5037 case OPC_PSUBUSB:
5038 gen_helper_psubusb(t0, t0, t1);
5039 break;
5040 case OPC_PSUBB:
5041 gen_helper_psubb(t0, t0, t1);
5042 break;
5044 case OPC_PSHUFH:
5045 gen_helper_pshufh(t0, t0, t1);
5046 break;
5047 case OPC_PACKSSWH:
5048 gen_helper_packsswh(t0, t0, t1);
5049 break;
5050 case OPC_PACKSSHB:
5051 gen_helper_packsshb(t0, t0, t1);
5052 break;
5053 case OPC_PACKUSHB:
5054 gen_helper_packushb(t0, t0, t1);
5055 break;
5057 case OPC_PUNPCKLHW:
5058 gen_helper_punpcklhw(t0, t0, t1);
5059 break;
5060 case OPC_PUNPCKHHW:
5061 gen_helper_punpckhhw(t0, t0, t1);
5062 break;
5063 case OPC_PUNPCKLBH:
5064 gen_helper_punpcklbh(t0, t0, t1);
5065 break;
5066 case OPC_PUNPCKHBH:
5067 gen_helper_punpckhbh(t0, t0, t1);
5068 break;
5069 case OPC_PUNPCKLWD:
5070 gen_helper_punpcklwd(t0, t0, t1);
5071 break;
5072 case OPC_PUNPCKHWD:
5073 gen_helper_punpckhwd(t0, t0, t1);
5074 break;
5076 case OPC_PAVGH:
5077 gen_helper_pavgh(t0, t0, t1);
5078 break;
5079 case OPC_PAVGB:
5080 gen_helper_pavgb(t0, t0, t1);
5081 break;
5082 case OPC_PMAXSH:
5083 gen_helper_pmaxsh(t0, t0, t1);
5084 break;
5085 case OPC_PMINSH:
5086 gen_helper_pminsh(t0, t0, t1);
5087 break;
5088 case OPC_PMAXUB:
5089 gen_helper_pmaxub(t0, t0, t1);
5090 break;
5091 case OPC_PMINUB:
5092 gen_helper_pminub(t0, t0, t1);
5093 break;
5095 case OPC_PCMPEQW:
5096 gen_helper_pcmpeqw(t0, t0, t1);
5097 break;
5098 case OPC_PCMPGTW:
5099 gen_helper_pcmpgtw(t0, t0, t1);
5100 break;
5101 case OPC_PCMPEQH:
5102 gen_helper_pcmpeqh(t0, t0, t1);
5103 break;
5104 case OPC_PCMPGTH:
5105 gen_helper_pcmpgth(t0, t0, t1);
5106 break;
5107 case OPC_PCMPEQB:
5108 gen_helper_pcmpeqb(t0, t0, t1);
5109 break;
5110 case OPC_PCMPGTB:
5111 gen_helper_pcmpgtb(t0, t0, t1);
5112 break;
5114 case OPC_PSLLW:
5115 gen_helper_psllw(t0, t0, t1);
5116 break;
5117 case OPC_PSLLH:
5118 gen_helper_psllh(t0, t0, t1);
5119 break;
5120 case OPC_PSRLW:
5121 gen_helper_psrlw(t0, t0, t1);
5122 break;
5123 case OPC_PSRLH:
5124 gen_helper_psrlh(t0, t0, t1);
5125 break;
5126 case OPC_PSRAW:
5127 gen_helper_psraw(t0, t0, t1);
5128 break;
5129 case OPC_PSRAH:
5130 gen_helper_psrah(t0, t0, t1);
5131 break;
5133 case OPC_PMULLH:
5134 gen_helper_pmullh(t0, t0, t1);
5135 break;
5136 case OPC_PMULHH:
5137 gen_helper_pmulhh(t0, t0, t1);
5138 break;
5139 case OPC_PMULHUH:
5140 gen_helper_pmulhuh(t0, t0, t1);
5141 break;
5142 case OPC_PMADDHW:
5143 gen_helper_pmaddhw(t0, t0, t1);
5144 break;
5146 case OPC_PASUBUB:
5147 gen_helper_pasubub(t0, t0, t1);
5148 break;
5149 case OPC_BIADD:
5150 gen_helper_biadd(t0, t0);
5151 break;
5152 case OPC_PMOVMSKB:
5153 gen_helper_pmovmskb(t0, t0);
5154 break;
5156 case OPC_PADDD:
5157 tcg_gen_add_i64(t0, t0, t1);
5158 break;
5159 case OPC_PSUBD:
5160 tcg_gen_sub_i64(t0, t0, t1);
5161 break;
5162 case OPC_XOR_CP2:
5163 tcg_gen_xor_i64(t0, t0, t1);
5164 break;
5165 case OPC_NOR_CP2:
5166 tcg_gen_nor_i64(t0, t0, t1);
5167 break;
5168 case OPC_AND_CP2:
5169 tcg_gen_and_i64(t0, t0, t1);
5170 break;
5171 case OPC_OR_CP2:
5172 tcg_gen_or_i64(t0, t0, t1);
5173 break;
5175 case OPC_PANDN:
5176 tcg_gen_andc_i64(t0, t1, t0);
5177 break;
5179 case OPC_PINSRH_0:
5180 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5181 break;
5182 case OPC_PINSRH_1:
5183 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5184 break;
5185 case OPC_PINSRH_2:
5186 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5187 break;
5188 case OPC_PINSRH_3:
5189 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5190 break;
5192 case OPC_PEXTRH:
5193 tcg_gen_andi_i64(t1, t1, 3);
5194 tcg_gen_shli_i64(t1, t1, 4);
5195 tcg_gen_shr_i64(t0, t0, t1);
5196 tcg_gen_ext16u_i64(t0, t0);
5197 break;
5199 case OPC_ADDU_CP2:
5200 tcg_gen_add_i64(t0, t0, t1);
5201 tcg_gen_ext32s_i64(t0, t0);
5202 break;
5203 case OPC_SUBU_CP2:
5204 tcg_gen_sub_i64(t0, t0, t1);
5205 tcg_gen_ext32s_i64(t0, t0);
5206 break;
5208 case OPC_SLL_CP2:
5209 shift_max = 32;
5210 goto do_shift;
5211 case OPC_SRL_CP2:
5212 shift_max = 32;
5213 goto do_shift;
5214 case OPC_SRA_CP2:
5215 shift_max = 32;
5216 goto do_shift;
5217 case OPC_DSLL_CP2:
5218 shift_max = 64;
5219 goto do_shift;
5220 case OPC_DSRL_CP2:
5221 shift_max = 64;
5222 goto do_shift;
5223 case OPC_DSRA_CP2:
5224 shift_max = 64;
5225 goto do_shift;
5226 do_shift:
5227 /* Make sure shift count isn't TCG undefined behaviour. */
5228 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5230 switch (opc) {
5231 case OPC_SLL_CP2:
5232 case OPC_DSLL_CP2:
5233 tcg_gen_shl_i64(t0, t0, t1);
5234 break;
5235 case OPC_SRA_CP2:
5236 case OPC_DSRA_CP2:
5238 * Since SRA is UndefinedResult without sign-extended inputs,
5239 * we can treat SRA and DSRA the same.
5241 tcg_gen_sar_i64(t0, t0, t1);
5242 break;
5243 case OPC_SRL_CP2:
5244 /* We want to shift in zeros for SRL; zero-extend first. */
5245 tcg_gen_ext32u_i64(t0, t0);
5246 /* FALLTHRU */
5247 case OPC_DSRL_CP2:
5248 tcg_gen_shr_i64(t0, t0, t1);
5249 break;
5252 if (shift_max == 32) {
5253 tcg_gen_ext32s_i64(t0, t0);
5256 /* Shifts larger than MAX produce zero. */
5257 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5258 tcg_gen_neg_i64(t1, t1);
5259 tcg_gen_and_i64(t0, t0, t1);
5260 break;
5262 case OPC_ADD_CP2:
5263 case OPC_DADD_CP2:
5265 TCGv_i64 t2 = tcg_temp_new_i64();
5266 TCGLabel *lab = gen_new_label();
5268 tcg_gen_mov_i64(t2, t0);
5269 tcg_gen_add_i64(t0, t1, t2);
5270 if (opc == OPC_ADD_CP2) {
5271 tcg_gen_ext32s_i64(t0, t0);
5273 tcg_gen_xor_i64(t1, t1, t2);
5274 tcg_gen_xor_i64(t2, t2, t0);
5275 tcg_gen_andc_i64(t1, t2, t1);
5276 tcg_temp_free_i64(t2);
5277 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5278 generate_exception(ctx, EXCP_OVERFLOW);
5279 gen_set_label(lab);
5280 break;
5283 case OPC_SUB_CP2:
5284 case OPC_DSUB_CP2:
5286 TCGv_i64 t2 = tcg_temp_new_i64();
5287 TCGLabel *lab = gen_new_label();
5289 tcg_gen_mov_i64(t2, t0);
5290 tcg_gen_sub_i64(t0, t1, t2);
5291 if (opc == OPC_SUB_CP2) {
5292 tcg_gen_ext32s_i64(t0, t0);
5294 tcg_gen_xor_i64(t1, t1, t2);
5295 tcg_gen_xor_i64(t2, t2, t0);
5296 tcg_gen_and_i64(t1, t1, t2);
5297 tcg_temp_free_i64(t2);
5298 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5299 generate_exception(ctx, EXCP_OVERFLOW);
5300 gen_set_label(lab);
5301 break;
5304 case OPC_PMULUW:
5305 tcg_gen_ext32u_i64(t0, t0);
5306 tcg_gen_ext32u_i64(t1, t1);
5307 tcg_gen_mul_i64(t0, t0, t1);
5308 break;
5310 case OPC_SEQU_CP2:
5311 case OPC_SEQ_CP2:
5312 cond = TCG_COND_EQ;
5313 goto do_cc_cond;
5314 break;
5315 case OPC_SLTU_CP2:
5316 cond = TCG_COND_LTU;
5317 goto do_cc_cond;
5318 break;
5319 case OPC_SLT_CP2:
5320 cond = TCG_COND_LT;
5321 goto do_cc_cond;
5322 break;
5323 case OPC_SLEU_CP2:
5324 cond = TCG_COND_LEU;
5325 goto do_cc_cond;
5326 break;
5327 case OPC_SLE_CP2:
5328 cond = TCG_COND_LE;
5329 do_cc_cond:
5331 int cc = (ctx->opcode >> 8) & 0x7;
5332 TCGv_i64 t64 = tcg_temp_new_i64();
5333 TCGv_i32 t32 = tcg_temp_new_i32();
5335 tcg_gen_setcond_i64(cond, t64, t0, t1);
5336 tcg_gen_extrl_i64_i32(t32, t64);
5337 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
5338 get_fp_bit(cc), 1);
5340 tcg_temp_free_i32(t32);
5341 tcg_temp_free_i64(t64);
5343 goto no_rd;
5344 break;
5345 default:
5346 MIPS_INVAL("loongson_cp2");
5347 gen_reserved_instruction(ctx);
5348 return;
5351 gen_store_fpr64(ctx, t0, rd);
5353 no_rd:
5354 tcg_temp_free_i64(t0);
5355 tcg_temp_free_i64(t1);
5358 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
5359 int rs, int rd)
5361 TCGv t0, t1, t2;
5362 TCGv_i32 fp0;
5363 #if defined(TARGET_MIPS64)
5364 int lsq_rt1 = ctx->opcode & 0x1f;
5365 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
5366 #endif
5367 int shf_offset = sextract32(ctx->opcode, 6, 8);
5369 t0 = tcg_temp_new();
5371 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
5372 #if defined(TARGET_MIPS64)
5373 case OPC_GSLQ:
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_gpr(t1, rt);
5382 gen_store_gpr(t0, lsq_rt1);
5383 tcg_temp_free(t1);
5384 break;
5385 case OPC_GSLQC1:
5386 check_cp1_enabled(ctx);
5387 t1 = tcg_temp_new();
5388 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5389 tcg_gen_qemu_ld_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 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5393 ctx->default_tcg_memop_mask);
5394 gen_store_fpr64(ctx, t1, rt);
5395 gen_store_fpr64(ctx, t0, lsq_rt1);
5396 tcg_temp_free(t1);
5397 break;
5398 case OPC_GSSQ:
5399 t1 = tcg_temp_new();
5400 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5401 gen_load_gpr(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_gpr(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 case OPC_GSSQC1:
5411 check_cp1_enabled(ctx);
5412 t1 = tcg_temp_new();
5413 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5414 gen_load_fpr64(ctx, t1, rt);
5415 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5416 ctx->default_tcg_memop_mask);
5417 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5418 gen_load_fpr64(ctx, t1, lsq_rt1);
5419 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5420 ctx->default_tcg_memop_mask);
5421 tcg_temp_free(t1);
5422 break;
5423 #endif
5424 case OPC_GSSHFL:
5425 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
5426 case OPC_GSLWLC1:
5427 check_cp1_enabled(ctx);
5428 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5429 t1 = tcg_temp_new();
5430 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5431 tcg_gen_andi_tl(t1, t0, 3);
5432 #ifndef TARGET_WORDS_BIGENDIAN
5433 tcg_gen_xori_tl(t1, t1, 3);
5434 #endif
5435 tcg_gen_shli_tl(t1, t1, 3);
5436 tcg_gen_andi_tl(t0, t0, ~3);
5437 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
5438 tcg_gen_shl_tl(t0, t0, t1);
5439 t2 = tcg_const_tl(-1);
5440 tcg_gen_shl_tl(t2, t2, t1);
5441 fp0 = tcg_temp_new_i32();
5442 gen_load_fpr32(ctx, fp0, rt);
5443 tcg_gen_ext_i32_tl(t1, fp0);
5444 tcg_gen_andc_tl(t1, t1, t2);
5445 tcg_temp_free(t2);
5446 tcg_gen_or_tl(t0, t0, t1);
5447 tcg_temp_free(t1);
5448 #if defined(TARGET_MIPS64)
5449 tcg_gen_extrl_i64_i32(fp0, t0);
5450 #else
5451 tcg_gen_ext32s_tl(fp0, t0);
5452 #endif
5453 gen_store_fpr32(ctx, fp0, rt);
5454 tcg_temp_free_i32(fp0);
5455 break;
5456 case OPC_GSLWRC1:
5457 check_cp1_enabled(ctx);
5458 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5459 t1 = tcg_temp_new();
5460 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5461 tcg_gen_andi_tl(t1, t0, 3);
5462 #ifdef TARGET_WORDS_BIGENDIAN
5463 tcg_gen_xori_tl(t1, t1, 3);
5464 #endif
5465 tcg_gen_shli_tl(t1, t1, 3);
5466 tcg_gen_andi_tl(t0, t0, ~3);
5467 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
5468 tcg_gen_shr_tl(t0, t0, t1);
5469 tcg_gen_xori_tl(t1, t1, 31);
5470 t2 = tcg_const_tl(0xfffffffeull);
5471 tcg_gen_shl_tl(t2, t2, t1);
5472 fp0 = tcg_temp_new_i32();
5473 gen_load_fpr32(ctx, fp0, rt);
5474 tcg_gen_ext_i32_tl(t1, fp0);
5475 tcg_gen_and_tl(t1, t1, t2);
5476 tcg_temp_free(t2);
5477 tcg_gen_or_tl(t0, t0, t1);
5478 tcg_temp_free(t1);
5479 #if defined(TARGET_MIPS64)
5480 tcg_gen_extrl_i64_i32(fp0, t0);
5481 #else
5482 tcg_gen_ext32s_tl(fp0, t0);
5483 #endif
5484 gen_store_fpr32(ctx, fp0, rt);
5485 tcg_temp_free_i32(fp0);
5486 break;
5487 #if defined(TARGET_MIPS64)
5488 case OPC_GSLDLC1:
5489 check_cp1_enabled(ctx);
5490 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5491 t1 = tcg_temp_new();
5492 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5493 tcg_gen_andi_tl(t1, t0, 7);
5494 #ifndef TARGET_WORDS_BIGENDIAN
5495 tcg_gen_xori_tl(t1, t1, 7);
5496 #endif
5497 tcg_gen_shli_tl(t1, t1, 3);
5498 tcg_gen_andi_tl(t0, t0, ~7);
5499 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
5500 tcg_gen_shl_tl(t0, t0, t1);
5501 t2 = tcg_const_tl(-1);
5502 tcg_gen_shl_tl(t2, t2, t1);
5503 gen_load_fpr64(ctx, t1, rt);
5504 tcg_gen_andc_tl(t1, t1, t2);
5505 tcg_temp_free(t2);
5506 tcg_gen_or_tl(t0, t0, t1);
5507 tcg_temp_free(t1);
5508 gen_store_fpr64(ctx, t0, rt);
5509 break;
5510 case OPC_GSLDRC1:
5511 check_cp1_enabled(ctx);
5512 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5513 t1 = tcg_temp_new();
5514 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5515 tcg_gen_andi_tl(t1, t0, 7);
5516 #ifdef TARGET_WORDS_BIGENDIAN
5517 tcg_gen_xori_tl(t1, t1, 7);
5518 #endif
5519 tcg_gen_shli_tl(t1, t1, 3);
5520 tcg_gen_andi_tl(t0, t0, ~7);
5521 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
5522 tcg_gen_shr_tl(t0, t0, t1);
5523 tcg_gen_xori_tl(t1, t1, 63);
5524 t2 = tcg_const_tl(0xfffffffffffffffeull);
5525 tcg_gen_shl_tl(t2, t2, t1);
5526 gen_load_fpr64(ctx, t1, rt);
5527 tcg_gen_and_tl(t1, t1, t2);
5528 tcg_temp_free(t2);
5529 tcg_gen_or_tl(t0, t0, t1);
5530 tcg_temp_free(t1);
5531 gen_store_fpr64(ctx, t0, rt);
5532 break;
5533 #endif
5534 default:
5535 MIPS_INVAL("loongson_gsshfl");
5536 gen_reserved_instruction(ctx);
5537 break;
5539 break;
5540 case OPC_GSSHFS:
5541 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
5542 case OPC_GSSWLC1:
5543 check_cp1_enabled(ctx);
5544 t1 = tcg_temp_new();
5545 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5546 fp0 = tcg_temp_new_i32();
5547 gen_load_fpr32(ctx, fp0, rt);
5548 tcg_gen_ext_i32_tl(t1, fp0);
5549 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
5550 tcg_temp_free_i32(fp0);
5551 tcg_temp_free(t1);
5552 break;
5553 case OPC_GSSWRC1:
5554 check_cp1_enabled(ctx);
5555 t1 = tcg_temp_new();
5556 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5557 fp0 = tcg_temp_new_i32();
5558 gen_load_fpr32(ctx, fp0, rt);
5559 tcg_gen_ext_i32_tl(t1, fp0);
5560 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
5561 tcg_temp_free_i32(fp0);
5562 tcg_temp_free(t1);
5563 break;
5564 #if defined(TARGET_MIPS64)
5565 case OPC_GSSDLC1:
5566 check_cp1_enabled(ctx);
5567 t1 = tcg_temp_new();
5568 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5569 gen_load_fpr64(ctx, t1, rt);
5570 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
5571 tcg_temp_free(t1);
5572 break;
5573 case OPC_GSSDRC1:
5574 check_cp1_enabled(ctx);
5575 t1 = tcg_temp_new();
5576 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5577 gen_load_fpr64(ctx, t1, rt);
5578 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
5579 tcg_temp_free(t1);
5580 break;
5581 #endif
5582 default:
5583 MIPS_INVAL("loongson_gsshfs");
5584 gen_reserved_instruction(ctx);
5585 break;
5587 break;
5588 default:
5589 MIPS_INVAL("loongson_gslsq");
5590 gen_reserved_instruction(ctx);
5591 break;
5593 tcg_temp_free(t0);
5596 /* Loongson EXT LDC2/SDC2 */
5597 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
5598 int rs, int rd)
5600 int offset = sextract32(ctx->opcode, 3, 8);
5601 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
5602 TCGv t0, t1;
5603 TCGv_i32 fp0;
5605 /* Pre-conditions */
5606 switch (opc) {
5607 case OPC_GSLBX:
5608 case OPC_GSLHX:
5609 case OPC_GSLWX:
5610 case OPC_GSLDX:
5611 /* prefetch, implement as NOP */
5612 if (rt == 0) {
5613 return;
5615 break;
5616 case OPC_GSSBX:
5617 case OPC_GSSHX:
5618 case OPC_GSSWX:
5619 case OPC_GSSDX:
5620 break;
5621 case OPC_GSLWXC1:
5622 #if defined(TARGET_MIPS64)
5623 case OPC_GSLDXC1:
5624 #endif
5625 check_cp1_enabled(ctx);
5626 /* prefetch, implement as NOP */
5627 if (rt == 0) {
5628 return;
5630 break;
5631 case OPC_GSSWXC1:
5632 #if defined(TARGET_MIPS64)
5633 case OPC_GSSDXC1:
5634 #endif
5635 check_cp1_enabled(ctx);
5636 break;
5637 default:
5638 MIPS_INVAL("loongson_lsdc2");
5639 gen_reserved_instruction(ctx);
5640 return;
5641 break;
5644 t0 = tcg_temp_new();
5646 gen_base_offset_addr(ctx, t0, rs, offset);
5647 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5649 switch (opc) {
5650 case OPC_GSLBX:
5651 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
5652 gen_store_gpr(t0, rt);
5653 break;
5654 case OPC_GSLHX:
5655 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
5656 ctx->default_tcg_memop_mask);
5657 gen_store_gpr(t0, rt);
5658 break;
5659 case OPC_GSLWX:
5660 gen_base_offset_addr(ctx, t0, rs, offset);
5661 if (rd) {
5662 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5664 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
5665 ctx->default_tcg_memop_mask);
5666 gen_store_gpr(t0, rt);
5667 break;
5668 #if defined(TARGET_MIPS64)
5669 case OPC_GSLDX:
5670 gen_base_offset_addr(ctx, t0, rs, offset);
5671 if (rd) {
5672 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5674 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5675 ctx->default_tcg_memop_mask);
5676 gen_store_gpr(t0, rt);
5677 break;
5678 #endif
5679 case OPC_GSLWXC1:
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 fp0 = tcg_temp_new_i32();
5686 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
5687 ctx->default_tcg_memop_mask);
5688 gen_store_fpr32(ctx, fp0, rt);
5689 tcg_temp_free_i32(fp0);
5690 break;
5691 #if defined(TARGET_MIPS64)
5692 case OPC_GSLDXC1:
5693 check_cp1_enabled(ctx);
5694 gen_base_offset_addr(ctx, t0, rs, offset);
5695 if (rd) {
5696 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5698 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5699 ctx->default_tcg_memop_mask);
5700 gen_store_fpr64(ctx, t0, rt);
5701 break;
5702 #endif
5703 case OPC_GSSBX:
5704 t1 = tcg_temp_new();
5705 gen_load_gpr(t1, rt);
5706 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
5707 tcg_temp_free(t1);
5708 break;
5709 case OPC_GSSHX:
5710 t1 = tcg_temp_new();
5711 gen_load_gpr(t1, rt);
5712 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
5713 ctx->default_tcg_memop_mask);
5714 tcg_temp_free(t1);
5715 break;
5716 case OPC_GSSWX:
5717 t1 = tcg_temp_new();
5718 gen_load_gpr(t1, rt);
5719 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
5720 ctx->default_tcg_memop_mask);
5721 tcg_temp_free(t1);
5722 break;
5723 #if defined(TARGET_MIPS64)
5724 case OPC_GSSDX:
5725 t1 = tcg_temp_new();
5726 gen_load_gpr(t1, rt);
5727 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5728 ctx->default_tcg_memop_mask);
5729 tcg_temp_free(t1);
5730 break;
5731 #endif
5732 case OPC_GSSWXC1:
5733 fp0 = tcg_temp_new_i32();
5734 gen_load_fpr32(ctx, fp0, rt);
5735 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
5736 ctx->default_tcg_memop_mask);
5737 tcg_temp_free_i32(fp0);
5738 break;
5739 #if defined(TARGET_MIPS64)
5740 case OPC_GSSDXC1:
5741 t1 = tcg_temp_new();
5742 gen_load_fpr64(ctx, t1, rt);
5743 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
5744 ctx->default_tcg_memop_mask);
5745 tcg_temp_free(t1);
5746 break;
5747 #endif
5748 default:
5749 break;
5752 tcg_temp_free(t0);
5755 /* Traps */
5756 static void gen_trap(DisasContext *ctx, uint32_t opc,
5757 int rs, int rt, int16_t imm)
5759 int cond;
5760 TCGv t0 = tcg_temp_new();
5761 TCGv t1 = tcg_temp_new();
5763 cond = 0;
5764 /* Load needed operands */
5765 switch (opc) {
5766 case OPC_TEQ:
5767 case OPC_TGE:
5768 case OPC_TGEU:
5769 case OPC_TLT:
5770 case OPC_TLTU:
5771 case OPC_TNE:
5772 /* Compare two registers */
5773 if (rs != rt) {
5774 gen_load_gpr(t0, rs);
5775 gen_load_gpr(t1, rt);
5776 cond = 1;
5778 break;
5779 case OPC_TEQI:
5780 case OPC_TGEI:
5781 case OPC_TGEIU:
5782 case OPC_TLTI:
5783 case OPC_TLTIU:
5784 case OPC_TNEI:
5785 /* Compare register to immediate */
5786 if (rs != 0 || imm != 0) {
5787 gen_load_gpr(t0, rs);
5788 tcg_gen_movi_tl(t1, (int32_t)imm);
5789 cond = 1;
5791 break;
5793 if (cond == 0) {
5794 switch (opc) {
5795 case OPC_TEQ: /* rs == rs */
5796 case OPC_TEQI: /* r0 == 0 */
5797 case OPC_TGE: /* rs >= rs */
5798 case OPC_TGEI: /* r0 >= 0 */
5799 case OPC_TGEU: /* rs >= rs unsigned */
5800 case OPC_TGEIU: /* r0 >= 0 unsigned */
5801 /* Always trap */
5802 generate_exception_end(ctx, EXCP_TRAP);
5803 break;
5804 case OPC_TLT: /* rs < rs */
5805 case OPC_TLTI: /* r0 < 0 */
5806 case OPC_TLTU: /* rs < rs unsigned */
5807 case OPC_TLTIU: /* r0 < 0 unsigned */
5808 case OPC_TNE: /* rs != rs */
5809 case OPC_TNEI: /* r0 != 0 */
5810 /* Never trap: treat as NOP. */
5811 break;
5813 } else {
5814 TCGLabel *l1 = gen_new_label();
5816 switch (opc) {
5817 case OPC_TEQ:
5818 case OPC_TEQI:
5819 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5820 break;
5821 case OPC_TGE:
5822 case OPC_TGEI:
5823 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5824 break;
5825 case OPC_TGEU:
5826 case OPC_TGEIU:
5827 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5828 break;
5829 case OPC_TLT:
5830 case OPC_TLTI:
5831 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5832 break;
5833 case OPC_TLTU:
5834 case OPC_TLTIU:
5835 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5836 break;
5837 case OPC_TNE:
5838 case OPC_TNEI:
5839 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5840 break;
5842 generate_exception(ctx, EXCP_TRAP);
5843 gen_set_label(l1);
5845 tcg_temp_free(t0);
5846 tcg_temp_free(t1);
5849 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5851 if (unlikely(ctx->base.singlestep_enabled)) {
5852 return false;
5855 #ifndef CONFIG_USER_ONLY
5856 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5857 #else
5858 return true;
5859 #endif
5862 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5864 if (use_goto_tb(ctx, dest)) {
5865 tcg_gen_goto_tb(n);
5866 gen_save_pc(dest);
5867 tcg_gen_exit_tb(ctx->base.tb, n);
5868 } else {
5869 gen_save_pc(dest);
5870 if (ctx->base.singlestep_enabled) {
5871 save_cpu_state(ctx, 0);
5872 gen_helper_raise_exception_debug(cpu_env);
5874 tcg_gen_lookup_and_goto_ptr();
5878 /* Branches (before delay slot) */
5879 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
5880 int insn_bytes,
5881 int rs, int rt, int32_t offset,
5882 int delayslot_size)
5884 target_ulong btgt = -1;
5885 int blink = 0;
5886 int bcond_compute = 0;
5887 TCGv t0 = tcg_temp_new();
5888 TCGv t1 = tcg_temp_new();
5890 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5891 #ifdef MIPS_DEBUG_DISAS
5892 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5893 TARGET_FMT_lx "\n", ctx->base.pc_next);
5894 #endif
5895 gen_reserved_instruction(ctx);
5896 goto out;
5899 /* Load needed operands */
5900 switch (opc) {
5901 case OPC_BEQ:
5902 case OPC_BEQL:
5903 case OPC_BNE:
5904 case OPC_BNEL:
5905 /* Compare two registers */
5906 if (rs != rt) {
5907 gen_load_gpr(t0, rs);
5908 gen_load_gpr(t1, rt);
5909 bcond_compute = 1;
5911 btgt = ctx->base.pc_next + insn_bytes + offset;
5912 break;
5913 case OPC_BGEZ:
5914 case OPC_BGEZAL:
5915 case OPC_BGEZALL:
5916 case OPC_BGEZL:
5917 case OPC_BGTZ:
5918 case OPC_BGTZL:
5919 case OPC_BLEZ:
5920 case OPC_BLEZL:
5921 case OPC_BLTZ:
5922 case OPC_BLTZAL:
5923 case OPC_BLTZALL:
5924 case OPC_BLTZL:
5925 /* Compare to zero */
5926 if (rs != 0) {
5927 gen_load_gpr(t0, rs);
5928 bcond_compute = 1;
5930 btgt = ctx->base.pc_next + insn_bytes + offset;
5931 break;
5932 case OPC_BPOSGE32:
5933 #if defined(TARGET_MIPS64)
5934 case OPC_BPOSGE64:
5935 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5936 #else
5937 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5938 #endif
5939 bcond_compute = 1;
5940 btgt = ctx->base.pc_next + insn_bytes + offset;
5941 break;
5942 case OPC_J:
5943 case OPC_JAL:
5944 case OPC_JALX:
5945 /* Jump to immediate */
5946 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5947 (uint32_t)offset;
5948 break;
5949 case OPC_JR:
5950 case OPC_JALR:
5951 /* Jump to register */
5952 if (offset != 0 && offset != 16) {
5954 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5955 * others are reserved.
5957 MIPS_INVAL("jump hint");
5958 gen_reserved_instruction(ctx);
5959 goto out;
5961 gen_load_gpr(btarget, rs);
5962 break;
5963 default:
5964 MIPS_INVAL("branch/jump");
5965 gen_reserved_instruction(ctx);
5966 goto out;
5968 if (bcond_compute == 0) {
5969 /* No condition to be computed */
5970 switch (opc) {
5971 case OPC_BEQ: /* rx == rx */
5972 case OPC_BEQL: /* rx == rx likely */
5973 case OPC_BGEZ: /* 0 >= 0 */
5974 case OPC_BGEZL: /* 0 >= 0 likely */
5975 case OPC_BLEZ: /* 0 <= 0 */
5976 case OPC_BLEZL: /* 0 <= 0 likely */
5977 /* Always take */
5978 ctx->hflags |= MIPS_HFLAG_B;
5979 break;
5980 case OPC_BGEZAL: /* 0 >= 0 */
5981 case OPC_BGEZALL: /* 0 >= 0 likely */
5982 /* Always take and link */
5983 blink = 31;
5984 ctx->hflags |= MIPS_HFLAG_B;
5985 break;
5986 case OPC_BNE: /* rx != rx */
5987 case OPC_BGTZ: /* 0 > 0 */
5988 case OPC_BLTZ: /* 0 < 0 */
5989 /* Treat as NOP. */
5990 goto out;
5991 case OPC_BLTZAL: /* 0 < 0 */
5993 * Handle as an unconditional branch to get correct delay
5994 * slot checking.
5996 blink = 31;
5997 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5998 ctx->hflags |= MIPS_HFLAG_B;
5999 break;
6000 case OPC_BLTZALL: /* 0 < 0 likely */
6001 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6002 /* Skip the instruction in the delay slot */
6003 ctx->base.pc_next += 4;
6004 goto out;
6005 case OPC_BNEL: /* rx != rx likely */
6006 case OPC_BGTZL: /* 0 > 0 likely */
6007 case OPC_BLTZL: /* 0 < 0 likely */
6008 /* Skip the instruction in the delay slot */
6009 ctx->base.pc_next += 4;
6010 goto out;
6011 case OPC_J:
6012 ctx->hflags |= MIPS_HFLAG_B;
6013 break;
6014 case OPC_JALX:
6015 ctx->hflags |= MIPS_HFLAG_BX;
6016 /* Fallthrough */
6017 case OPC_JAL:
6018 blink = 31;
6019 ctx->hflags |= MIPS_HFLAG_B;
6020 break;
6021 case OPC_JR:
6022 ctx->hflags |= MIPS_HFLAG_BR;
6023 break;
6024 case OPC_JALR:
6025 blink = rt;
6026 ctx->hflags |= MIPS_HFLAG_BR;
6027 break;
6028 default:
6029 MIPS_INVAL("branch/jump");
6030 gen_reserved_instruction(ctx);
6031 goto out;
6033 } else {
6034 switch (opc) {
6035 case OPC_BEQ:
6036 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6037 goto not_likely;
6038 case OPC_BEQL:
6039 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6040 goto likely;
6041 case OPC_BNE:
6042 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6043 goto not_likely;
6044 case OPC_BNEL:
6045 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6046 goto likely;
6047 case OPC_BGEZ:
6048 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6049 goto not_likely;
6050 case OPC_BGEZL:
6051 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6052 goto likely;
6053 case OPC_BGEZAL:
6054 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6055 blink = 31;
6056 goto not_likely;
6057 case OPC_BGEZALL:
6058 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6059 blink = 31;
6060 goto likely;
6061 case OPC_BGTZ:
6062 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6063 goto not_likely;
6064 case OPC_BGTZL:
6065 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6066 goto likely;
6067 case OPC_BLEZ:
6068 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6069 goto not_likely;
6070 case OPC_BLEZL:
6071 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6072 goto likely;
6073 case OPC_BLTZ:
6074 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6075 goto not_likely;
6076 case OPC_BLTZL:
6077 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6078 goto likely;
6079 case OPC_BPOSGE32:
6080 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6081 goto not_likely;
6082 #if defined(TARGET_MIPS64)
6083 case OPC_BPOSGE64:
6084 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6085 goto not_likely;
6086 #endif
6087 case OPC_BLTZAL:
6088 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6089 blink = 31;
6090 not_likely:
6091 ctx->hflags |= MIPS_HFLAG_BC;
6092 break;
6093 case OPC_BLTZALL:
6094 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6095 blink = 31;
6096 likely:
6097 ctx->hflags |= MIPS_HFLAG_BL;
6098 break;
6099 default:
6100 MIPS_INVAL("conditional branch/jump");
6101 gen_reserved_instruction(ctx);
6102 goto out;
6106 ctx->btarget = btgt;
6108 switch (delayslot_size) {
6109 case 2:
6110 ctx->hflags |= MIPS_HFLAG_BDS16;
6111 break;
6112 case 4:
6113 ctx->hflags |= MIPS_HFLAG_BDS32;
6114 break;
6117 if (blink > 0) {
6118 int post_delay = insn_bytes + delayslot_size;
6119 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6121 tcg_gen_movi_tl(cpu_gpr[blink],
6122 ctx->base.pc_next + post_delay + lowbit);
6125 out:
6126 if (insn_bytes == 2) {
6127 ctx->hflags |= MIPS_HFLAG_B16;
6129 tcg_temp_free(t0);
6130 tcg_temp_free(t1);
6134 /* nanoMIPS Branches */
6135 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6136 int insn_bytes,
6137 int rs, int rt, int32_t offset)
6139 target_ulong btgt = -1;
6140 int bcond_compute = 0;
6141 TCGv t0 = tcg_temp_new();
6142 TCGv t1 = tcg_temp_new();
6144 /* Load needed operands */
6145 switch (opc) {
6146 case OPC_BEQ:
6147 case OPC_BNE:
6148 /* Compare two registers */
6149 if (rs != rt) {
6150 gen_load_gpr(t0, rs);
6151 gen_load_gpr(t1, rt);
6152 bcond_compute = 1;
6154 btgt = ctx->base.pc_next + insn_bytes + offset;
6155 break;
6156 case OPC_BGEZAL:
6157 /* Compare to zero */
6158 if (rs != 0) {
6159 gen_load_gpr(t0, rs);
6160 bcond_compute = 1;
6162 btgt = ctx->base.pc_next + insn_bytes + offset;
6163 break;
6164 case OPC_BPOSGE32:
6165 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6166 bcond_compute = 1;
6167 btgt = ctx->base.pc_next + insn_bytes + offset;
6168 break;
6169 case OPC_JR:
6170 case OPC_JALR:
6171 /* Jump to register */
6172 if (offset != 0 && offset != 16) {
6174 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6175 * others are reserved.
6177 MIPS_INVAL("jump hint");
6178 gen_reserved_instruction(ctx);
6179 goto out;
6181 gen_load_gpr(btarget, rs);
6182 break;
6183 default:
6184 MIPS_INVAL("branch/jump");
6185 gen_reserved_instruction(ctx);
6186 goto out;
6188 if (bcond_compute == 0) {
6189 /* No condition to be computed */
6190 switch (opc) {
6191 case OPC_BEQ: /* rx == rx */
6192 /* Always take */
6193 ctx->hflags |= MIPS_HFLAG_B;
6194 break;
6195 case OPC_BGEZAL: /* 0 >= 0 */
6196 /* Always take and link */
6197 tcg_gen_movi_tl(cpu_gpr[31],
6198 ctx->base.pc_next + insn_bytes);
6199 ctx->hflags |= MIPS_HFLAG_B;
6200 break;
6201 case OPC_BNE: /* rx != rx */
6202 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6203 /* Skip the instruction in the delay slot */
6204 ctx->base.pc_next += 4;
6205 goto out;
6206 case OPC_JR:
6207 ctx->hflags |= MIPS_HFLAG_BR;
6208 break;
6209 case OPC_JALR:
6210 if (rt > 0) {
6211 tcg_gen_movi_tl(cpu_gpr[rt],
6212 ctx->base.pc_next + insn_bytes);
6214 ctx->hflags |= MIPS_HFLAG_BR;
6215 break;
6216 default:
6217 MIPS_INVAL("branch/jump");
6218 gen_reserved_instruction(ctx);
6219 goto out;
6221 } else {
6222 switch (opc) {
6223 case OPC_BEQ:
6224 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6225 goto not_likely;
6226 case OPC_BNE:
6227 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6228 goto not_likely;
6229 case OPC_BGEZAL:
6230 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6231 tcg_gen_movi_tl(cpu_gpr[31],
6232 ctx->base.pc_next + insn_bytes);
6233 goto not_likely;
6234 case OPC_BPOSGE32:
6235 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6236 not_likely:
6237 ctx->hflags |= MIPS_HFLAG_BC;
6238 break;
6239 default:
6240 MIPS_INVAL("conditional branch/jump");
6241 gen_reserved_instruction(ctx);
6242 goto out;
6246 ctx->btarget = btgt;
6248 out:
6249 if (insn_bytes == 2) {
6250 ctx->hflags |= MIPS_HFLAG_B16;
6252 tcg_temp_free(t0);
6253 tcg_temp_free(t1);
6257 /* special3 bitfield operations */
6258 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6259 int rs, int lsb, int msb)
6261 TCGv t0 = tcg_temp_new();
6262 TCGv t1 = tcg_temp_new();
6264 gen_load_gpr(t1, rs);
6265 switch (opc) {
6266 case OPC_EXT:
6267 if (lsb + msb > 31) {
6268 goto fail;
6270 if (msb != 31) {
6271 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6272 } else {
6274 * The two checks together imply that lsb == 0,
6275 * so this is a simple sign-extension.
6277 tcg_gen_ext32s_tl(t0, t1);
6279 break;
6280 #if defined(TARGET_MIPS64)
6281 case OPC_DEXTU:
6282 lsb += 32;
6283 goto do_dext;
6284 case OPC_DEXTM:
6285 msb += 32;
6286 goto do_dext;
6287 case OPC_DEXT:
6288 do_dext:
6289 if (lsb + msb > 63) {
6290 goto fail;
6292 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6293 break;
6294 #endif
6295 case OPC_INS:
6296 if (lsb > msb) {
6297 goto fail;
6299 gen_load_gpr(t0, rt);
6300 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6301 tcg_gen_ext32s_tl(t0, t0);
6302 break;
6303 #if defined(TARGET_MIPS64)
6304 case OPC_DINSU:
6305 lsb += 32;
6306 /* FALLTHRU */
6307 case OPC_DINSM:
6308 msb += 32;
6309 /* FALLTHRU */
6310 case OPC_DINS:
6311 if (lsb > msb) {
6312 goto fail;
6314 gen_load_gpr(t0, rt);
6315 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6316 break;
6317 #endif
6318 default:
6319 fail:
6320 MIPS_INVAL("bitops");
6321 gen_reserved_instruction(ctx);
6322 tcg_temp_free(t0);
6323 tcg_temp_free(t1);
6324 return;
6326 gen_store_gpr(t0, rt);
6327 tcg_temp_free(t0);
6328 tcg_temp_free(t1);
6331 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6333 TCGv t0;
6335 if (rd == 0) {
6336 /* If no destination, treat it as a NOP. */
6337 return;
6340 t0 = tcg_temp_new();
6341 gen_load_gpr(t0, rt);
6342 switch (op2) {
6343 case OPC_WSBH:
6345 TCGv t1 = tcg_temp_new();
6346 TCGv t2 = tcg_const_tl(0x00FF00FF);
6348 tcg_gen_shri_tl(t1, t0, 8);
6349 tcg_gen_and_tl(t1, t1, t2);
6350 tcg_gen_and_tl(t0, t0, t2);
6351 tcg_gen_shli_tl(t0, t0, 8);
6352 tcg_gen_or_tl(t0, t0, t1);
6353 tcg_temp_free(t2);
6354 tcg_temp_free(t1);
6355 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6357 break;
6358 case OPC_SEB:
6359 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6360 break;
6361 case OPC_SEH:
6362 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6363 break;
6364 #if defined(TARGET_MIPS64)
6365 case OPC_DSBH:
6367 TCGv t1 = tcg_temp_new();
6368 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6370 tcg_gen_shri_tl(t1, t0, 8);
6371 tcg_gen_and_tl(t1, t1, t2);
6372 tcg_gen_and_tl(t0, t0, t2);
6373 tcg_gen_shli_tl(t0, t0, 8);
6374 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6375 tcg_temp_free(t2);
6376 tcg_temp_free(t1);
6378 break;
6379 case OPC_DSHD:
6381 TCGv t1 = tcg_temp_new();
6382 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6384 tcg_gen_shri_tl(t1, t0, 16);
6385 tcg_gen_and_tl(t1, t1, t2);
6386 tcg_gen_and_tl(t0, t0, t2);
6387 tcg_gen_shli_tl(t0, t0, 16);
6388 tcg_gen_or_tl(t0, t0, t1);
6389 tcg_gen_shri_tl(t1, t0, 32);
6390 tcg_gen_shli_tl(t0, t0, 32);
6391 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6392 tcg_temp_free(t2);
6393 tcg_temp_free(t1);
6395 break;
6396 #endif
6397 default:
6398 MIPS_INVAL("bsfhl");
6399 gen_reserved_instruction(ctx);
6400 tcg_temp_free(t0);
6401 return;
6403 tcg_temp_free(t0);
6406 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6407 int rt, int bits)
6409 TCGv t0;
6410 if (rd == 0) {
6411 /* Treat as NOP. */
6412 return;
6414 t0 = tcg_temp_new();
6415 if (bits == 0 || bits == wordsz) {
6416 if (bits == 0) {
6417 gen_load_gpr(t0, rt);
6418 } else {
6419 gen_load_gpr(t0, rs);
6421 switch (wordsz) {
6422 case 32:
6423 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6424 break;
6425 #if defined(TARGET_MIPS64)
6426 case 64:
6427 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6428 break;
6429 #endif
6431 } else {
6432 TCGv t1 = tcg_temp_new();
6433 gen_load_gpr(t0, rt);
6434 gen_load_gpr(t1, rs);
6435 switch (wordsz) {
6436 case 32:
6438 TCGv_i64 t2 = tcg_temp_new_i64();
6439 tcg_gen_concat_tl_i64(t2, t1, t0);
6440 tcg_gen_shri_i64(t2, t2, 32 - bits);
6441 gen_move_low32(cpu_gpr[rd], t2);
6442 tcg_temp_free_i64(t2);
6444 break;
6445 #if defined(TARGET_MIPS64)
6446 case 64:
6447 tcg_gen_shli_tl(t0, t0, bits);
6448 tcg_gen_shri_tl(t1, t1, 64 - bits);
6449 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6450 break;
6451 #endif
6453 tcg_temp_free(t1);
6456 tcg_temp_free(t0);
6459 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6460 int bp)
6462 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6465 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6466 int shift)
6468 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6471 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6473 TCGv t0;
6474 if (rd == 0) {
6475 /* Treat as NOP. */
6476 return;
6478 t0 = tcg_temp_new();
6479 gen_load_gpr(t0, rt);
6480 switch (opc) {
6481 case OPC_BITSWAP:
6482 gen_helper_bitswap(cpu_gpr[rd], t0);
6483 break;
6484 #if defined(TARGET_MIPS64)
6485 case OPC_DBITSWAP:
6486 gen_helper_dbitswap(cpu_gpr[rd], t0);
6487 break;
6488 #endif
6490 tcg_temp_free(t0);
6493 #ifndef CONFIG_USER_ONLY
6494 /* CP0 (MMU and control) */
6495 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6497 TCGv_i64 t0 = tcg_temp_new_i64();
6498 TCGv_i64 t1 = tcg_temp_new_i64();
6500 tcg_gen_ext_tl_i64(t0, arg);
6501 tcg_gen_ld_i64(t1, cpu_env, off);
6502 #if defined(TARGET_MIPS64)
6503 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6504 #else
6505 tcg_gen_concat32_i64(t1, t1, t0);
6506 #endif
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_mthc0_store64(TCGv arg, target_ulong off)
6514 TCGv_i64 t0 = tcg_temp_new_i64();
6515 TCGv_i64 t1 = tcg_temp_new_i64();
6517 tcg_gen_ext_tl_i64(t0, arg);
6518 tcg_gen_ld_i64(t1, cpu_env, off);
6519 tcg_gen_concat32_i64(t1, t1, t0);
6520 tcg_gen_st_i64(t1, cpu_env, off);
6521 tcg_temp_free_i64(t1);
6522 tcg_temp_free_i64(t0);
6525 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6527 TCGv_i64 t0 = tcg_temp_new_i64();
6529 tcg_gen_ld_i64(t0, cpu_env, off);
6530 #if defined(TARGET_MIPS64)
6531 tcg_gen_shri_i64(t0, t0, 30);
6532 #else
6533 tcg_gen_shri_i64(t0, t0, 32);
6534 #endif
6535 gen_move_low32(arg, t0);
6536 tcg_temp_free_i64(t0);
6539 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6541 TCGv_i64 t0 = tcg_temp_new_i64();
6543 tcg_gen_ld_i64(t0, cpu_env, off);
6544 tcg_gen_shri_i64(t0, t0, 32 + shift);
6545 gen_move_low32(arg, t0);
6546 tcg_temp_free_i64(t0);
6549 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
6551 TCGv_i32 t0 = tcg_temp_new_i32();
6553 tcg_gen_ld_i32(t0, cpu_env, off);
6554 tcg_gen_ext_i32_tl(arg, t0);
6555 tcg_temp_free_i32(t0);
6558 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
6560 tcg_gen_ld_tl(arg, cpu_env, off);
6561 tcg_gen_ext32s_tl(arg, arg);
6564 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
6566 TCGv_i32 t0 = tcg_temp_new_i32();
6568 tcg_gen_trunc_tl_i32(t0, arg);
6569 tcg_gen_st_i32(t0, cpu_env, off);
6570 tcg_temp_free_i32(t0);
6573 #define CP0_CHECK(c) \
6574 do { \
6575 if (!(c)) { \
6576 goto cp0_unimplemented; \
6578 } while (0)
6580 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6582 const char *register_name = "invalid";
6584 switch (reg) {
6585 case CP0_REGISTER_02:
6586 switch (sel) {
6587 case 0:
6588 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6589 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6590 register_name = "EntryLo0";
6591 break;
6592 default:
6593 goto cp0_unimplemented;
6595 break;
6596 case CP0_REGISTER_03:
6597 switch (sel) {
6598 case CP0_REG03__ENTRYLO1:
6599 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6600 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6601 register_name = "EntryLo1";
6602 break;
6603 default:
6604 goto cp0_unimplemented;
6606 break;
6607 case CP0_REGISTER_09:
6608 switch (sel) {
6609 case CP0_REG09__SAAR:
6610 CP0_CHECK(ctx->saar);
6611 gen_helper_mfhc0_saar(arg, cpu_env);
6612 register_name = "SAAR";
6613 break;
6614 default:
6615 goto cp0_unimplemented;
6617 break;
6618 case CP0_REGISTER_17:
6619 switch (sel) {
6620 case CP0_REG17__LLADDR:
6621 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
6622 ctx->CP0_LLAddr_shift);
6623 register_name = "LLAddr";
6624 break;
6625 case CP0_REG17__MAAR:
6626 CP0_CHECK(ctx->mrp);
6627 gen_helper_mfhc0_maar(arg, cpu_env);
6628 register_name = "MAAR";
6629 break;
6630 default:
6631 goto cp0_unimplemented;
6633 break;
6634 case CP0_REGISTER_19:
6635 switch (sel) {
6636 case CP0_REG19__WATCHHI0:
6637 case CP0_REG19__WATCHHI1:
6638 case CP0_REG19__WATCHHI2:
6639 case CP0_REG19__WATCHHI3:
6640 case CP0_REG19__WATCHHI4:
6641 case CP0_REG19__WATCHHI5:
6642 case CP0_REG19__WATCHHI6:
6643 case CP0_REG19__WATCHHI7:
6644 /* upper 32 bits are only available when Config5MI != 0 */
6645 CP0_CHECK(ctx->mi);
6646 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
6647 register_name = "WatchHi";
6648 break;
6649 default:
6650 goto cp0_unimplemented;
6652 break;
6653 case CP0_REGISTER_28:
6654 switch (sel) {
6655 case 0:
6656 case 2:
6657 case 4:
6658 case 6:
6659 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6660 register_name = "TagLo";
6661 break;
6662 default:
6663 goto cp0_unimplemented;
6665 break;
6666 default:
6667 goto cp0_unimplemented;
6669 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6670 return;
6672 cp0_unimplemented:
6673 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6674 register_name, reg, sel);
6675 tcg_gen_movi_tl(arg, 0);
6678 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6680 const char *register_name = "invalid";
6681 uint64_t mask = ctx->PAMask >> 36;
6683 switch (reg) {
6684 case CP0_REGISTER_02:
6685 switch (sel) {
6686 case 0:
6687 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6688 tcg_gen_andi_tl(arg, arg, mask);
6689 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6690 register_name = "EntryLo0";
6691 break;
6692 default:
6693 goto cp0_unimplemented;
6695 break;
6696 case CP0_REGISTER_03:
6697 switch (sel) {
6698 case CP0_REG03__ENTRYLO1:
6699 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6700 tcg_gen_andi_tl(arg, arg, mask);
6701 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6702 register_name = "EntryLo1";
6703 break;
6704 default:
6705 goto cp0_unimplemented;
6707 break;
6708 case CP0_REGISTER_09:
6709 switch (sel) {
6710 case CP0_REG09__SAAR:
6711 CP0_CHECK(ctx->saar);
6712 gen_helper_mthc0_saar(cpu_env, arg);
6713 register_name = "SAAR";
6714 break;
6715 default:
6716 goto cp0_unimplemented;
6718 break;
6719 case CP0_REGISTER_17:
6720 switch (sel) {
6721 case CP0_REG17__LLADDR:
6723 * LLAddr is read-only (the only exception is bit 0 if LLB is
6724 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6725 * relevant for modern MIPS cores supporting MTHC0, therefore
6726 * treating MTHC0 to LLAddr as NOP.
6728 register_name = "LLAddr";
6729 break;
6730 case CP0_REG17__MAAR:
6731 CP0_CHECK(ctx->mrp);
6732 gen_helper_mthc0_maar(cpu_env, arg);
6733 register_name = "MAAR";
6734 break;
6735 default:
6736 goto cp0_unimplemented;
6738 break;
6739 case CP0_REGISTER_19:
6740 switch (sel) {
6741 case CP0_REG19__WATCHHI0:
6742 case CP0_REG19__WATCHHI1:
6743 case CP0_REG19__WATCHHI2:
6744 case CP0_REG19__WATCHHI3:
6745 case CP0_REG19__WATCHHI4:
6746 case CP0_REG19__WATCHHI5:
6747 case CP0_REG19__WATCHHI6:
6748 case CP0_REG19__WATCHHI7:
6749 /* upper 32 bits are only available when Config5MI != 0 */
6750 CP0_CHECK(ctx->mi);
6751 gen_helper_0e1i(mthc0_watchhi, arg, sel);
6752 register_name = "WatchHi";
6753 break;
6754 default:
6755 goto cp0_unimplemented;
6757 break;
6758 case CP0_REGISTER_28:
6759 switch (sel) {
6760 case 0:
6761 case 2:
6762 case 4:
6763 case 6:
6764 tcg_gen_andi_tl(arg, arg, mask);
6765 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6766 register_name = "TagLo";
6767 break;
6768 default:
6769 goto cp0_unimplemented;
6771 break;
6772 default:
6773 goto cp0_unimplemented;
6775 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6777 cp0_unimplemented:
6778 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6779 register_name, reg, sel);
6782 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6784 if (ctx->insn_flags & ISA_MIPS_R6) {
6785 tcg_gen_movi_tl(arg, 0);
6786 } else {
6787 tcg_gen_movi_tl(arg, ~0);
6791 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6793 const char *register_name = "invalid";
6795 if (sel != 0) {
6796 check_insn(ctx, ISA_MIPS_R1);
6799 switch (reg) {
6800 case CP0_REGISTER_00:
6801 switch (sel) {
6802 case CP0_REG00__INDEX:
6803 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6804 register_name = "Index";
6805 break;
6806 case CP0_REG00__MVPCONTROL:
6807 CP0_CHECK(ctx->insn_flags & ASE_MT);
6808 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6809 register_name = "MVPControl";
6810 break;
6811 case CP0_REG00__MVPCONF0:
6812 CP0_CHECK(ctx->insn_flags & ASE_MT);
6813 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6814 register_name = "MVPConf0";
6815 break;
6816 case CP0_REG00__MVPCONF1:
6817 CP0_CHECK(ctx->insn_flags & ASE_MT);
6818 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6819 register_name = "MVPConf1";
6820 break;
6821 case CP0_REG00__VPCONTROL:
6822 CP0_CHECK(ctx->vp);
6823 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6824 register_name = "VPControl";
6825 break;
6826 default:
6827 goto cp0_unimplemented;
6829 break;
6830 case CP0_REGISTER_01:
6831 switch (sel) {
6832 case CP0_REG01__RANDOM:
6833 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6834 gen_helper_mfc0_random(arg, cpu_env);
6835 register_name = "Random";
6836 break;
6837 case CP0_REG01__VPECONTROL:
6838 CP0_CHECK(ctx->insn_flags & ASE_MT);
6839 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6840 register_name = "VPEControl";
6841 break;
6842 case CP0_REG01__VPECONF0:
6843 CP0_CHECK(ctx->insn_flags & ASE_MT);
6844 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6845 register_name = "VPEConf0";
6846 break;
6847 case CP0_REG01__VPECONF1:
6848 CP0_CHECK(ctx->insn_flags & ASE_MT);
6849 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6850 register_name = "VPEConf1";
6851 break;
6852 case CP0_REG01__YQMASK:
6853 CP0_CHECK(ctx->insn_flags & ASE_MT);
6854 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6855 register_name = "YQMask";
6856 break;
6857 case CP0_REG01__VPESCHEDULE:
6858 CP0_CHECK(ctx->insn_flags & ASE_MT);
6859 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6860 register_name = "VPESchedule";
6861 break;
6862 case CP0_REG01__VPESCHEFBACK:
6863 CP0_CHECK(ctx->insn_flags & ASE_MT);
6864 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6865 register_name = "VPEScheFBack";
6866 break;
6867 case CP0_REG01__VPEOPT:
6868 CP0_CHECK(ctx->insn_flags & ASE_MT);
6869 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6870 register_name = "VPEOpt";
6871 break;
6872 default:
6873 goto cp0_unimplemented;
6875 break;
6876 case CP0_REGISTER_02:
6877 switch (sel) {
6878 case CP0_REG02__ENTRYLO0:
6880 TCGv_i64 tmp = tcg_temp_new_i64();
6881 tcg_gen_ld_i64(tmp, cpu_env,
6882 offsetof(CPUMIPSState, CP0_EntryLo0));
6883 #if defined(TARGET_MIPS64)
6884 if (ctx->rxi) {
6885 /* Move RI/XI fields to bits 31:30 */
6886 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6887 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6889 #endif
6890 gen_move_low32(arg, tmp);
6891 tcg_temp_free_i64(tmp);
6893 register_name = "EntryLo0";
6894 break;
6895 case CP0_REG02__TCSTATUS:
6896 CP0_CHECK(ctx->insn_flags & ASE_MT);
6897 gen_helper_mfc0_tcstatus(arg, cpu_env);
6898 register_name = "TCStatus";
6899 break;
6900 case CP0_REG02__TCBIND:
6901 CP0_CHECK(ctx->insn_flags & ASE_MT);
6902 gen_helper_mfc0_tcbind(arg, cpu_env);
6903 register_name = "TCBind";
6904 break;
6905 case CP0_REG02__TCRESTART:
6906 CP0_CHECK(ctx->insn_flags & ASE_MT);
6907 gen_helper_mfc0_tcrestart(arg, cpu_env);
6908 register_name = "TCRestart";
6909 break;
6910 case CP0_REG02__TCHALT:
6911 CP0_CHECK(ctx->insn_flags & ASE_MT);
6912 gen_helper_mfc0_tchalt(arg, cpu_env);
6913 register_name = "TCHalt";
6914 break;
6915 case CP0_REG02__TCCONTEXT:
6916 CP0_CHECK(ctx->insn_flags & ASE_MT);
6917 gen_helper_mfc0_tccontext(arg, cpu_env);
6918 register_name = "TCContext";
6919 break;
6920 case CP0_REG02__TCSCHEDULE:
6921 CP0_CHECK(ctx->insn_flags & ASE_MT);
6922 gen_helper_mfc0_tcschedule(arg, cpu_env);
6923 register_name = "TCSchedule";
6924 break;
6925 case CP0_REG02__TCSCHEFBACK:
6926 CP0_CHECK(ctx->insn_flags & ASE_MT);
6927 gen_helper_mfc0_tcschefback(arg, cpu_env);
6928 register_name = "TCScheFBack";
6929 break;
6930 default:
6931 goto cp0_unimplemented;
6933 break;
6934 case CP0_REGISTER_03:
6935 switch (sel) {
6936 case CP0_REG03__ENTRYLO1:
6938 TCGv_i64 tmp = tcg_temp_new_i64();
6939 tcg_gen_ld_i64(tmp, cpu_env,
6940 offsetof(CPUMIPSState, CP0_EntryLo1));
6941 #if defined(TARGET_MIPS64)
6942 if (ctx->rxi) {
6943 /* Move RI/XI fields to bits 31:30 */
6944 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6945 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6947 #endif
6948 gen_move_low32(arg, tmp);
6949 tcg_temp_free_i64(tmp);
6951 register_name = "EntryLo1";
6952 break;
6953 case CP0_REG03__GLOBALNUM:
6954 CP0_CHECK(ctx->vp);
6955 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6956 register_name = "GlobalNumber";
6957 break;
6958 default:
6959 goto cp0_unimplemented;
6961 break;
6962 case CP0_REGISTER_04:
6963 switch (sel) {
6964 case CP0_REG04__CONTEXT:
6965 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6966 tcg_gen_ext32s_tl(arg, arg);
6967 register_name = "Context";
6968 break;
6969 case CP0_REG04__CONTEXTCONFIG:
6970 /* SmartMIPS ASE */
6971 /* gen_helper_mfc0_contextconfig(arg); */
6972 register_name = "ContextConfig";
6973 goto cp0_unimplemented;
6974 case CP0_REG04__USERLOCAL:
6975 CP0_CHECK(ctx->ulri);
6976 tcg_gen_ld_tl(arg, cpu_env,
6977 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6978 tcg_gen_ext32s_tl(arg, arg);
6979 register_name = "UserLocal";
6980 break;
6981 case CP0_REG04__MMID:
6982 CP0_CHECK(ctx->mi);
6983 gen_helper_mtc0_memorymapid(cpu_env, arg);
6984 register_name = "MMID";
6985 break;
6986 default:
6987 goto cp0_unimplemented;
6989 break;
6990 case CP0_REGISTER_05:
6991 switch (sel) {
6992 case CP0_REG05__PAGEMASK:
6993 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6994 register_name = "PageMask";
6995 break;
6996 case CP0_REG05__PAGEGRAIN:
6997 check_insn(ctx, ISA_MIPS_R2);
6998 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6999 register_name = "PageGrain";
7000 break;
7001 case CP0_REG05__SEGCTL0:
7002 CP0_CHECK(ctx->sc);
7003 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7004 tcg_gen_ext32s_tl(arg, arg);
7005 register_name = "SegCtl0";
7006 break;
7007 case CP0_REG05__SEGCTL1:
7008 CP0_CHECK(ctx->sc);
7009 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7010 tcg_gen_ext32s_tl(arg, arg);
7011 register_name = "SegCtl1";
7012 break;
7013 case CP0_REG05__SEGCTL2:
7014 CP0_CHECK(ctx->sc);
7015 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7016 tcg_gen_ext32s_tl(arg, arg);
7017 register_name = "SegCtl2";
7018 break;
7019 case CP0_REG05__PWBASE:
7020 check_pw(ctx);
7021 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7022 register_name = "PWBase";
7023 break;
7024 case CP0_REG05__PWFIELD:
7025 check_pw(ctx);
7026 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7027 register_name = "PWField";
7028 break;
7029 case CP0_REG05__PWSIZE:
7030 check_pw(ctx);
7031 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7032 register_name = "PWSize";
7033 break;
7034 default:
7035 goto cp0_unimplemented;
7037 break;
7038 case CP0_REGISTER_06:
7039 switch (sel) {
7040 case CP0_REG06__WIRED:
7041 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7042 register_name = "Wired";
7043 break;
7044 case CP0_REG06__SRSCONF0:
7045 check_insn(ctx, ISA_MIPS_R2);
7046 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7047 register_name = "SRSConf0";
7048 break;
7049 case CP0_REG06__SRSCONF1:
7050 check_insn(ctx, ISA_MIPS_R2);
7051 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7052 register_name = "SRSConf1";
7053 break;
7054 case CP0_REG06__SRSCONF2:
7055 check_insn(ctx, ISA_MIPS_R2);
7056 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7057 register_name = "SRSConf2";
7058 break;
7059 case CP0_REG06__SRSCONF3:
7060 check_insn(ctx, ISA_MIPS_R2);
7061 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7062 register_name = "SRSConf3";
7063 break;
7064 case CP0_REG06__SRSCONF4:
7065 check_insn(ctx, ISA_MIPS_R2);
7066 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7067 register_name = "SRSConf4";
7068 break;
7069 case CP0_REG06__PWCTL:
7070 check_pw(ctx);
7071 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7072 register_name = "PWCtl";
7073 break;
7074 default:
7075 goto cp0_unimplemented;
7077 break;
7078 case CP0_REGISTER_07:
7079 switch (sel) {
7080 case CP0_REG07__HWRENA:
7081 check_insn(ctx, ISA_MIPS_R2);
7082 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7083 register_name = "HWREna";
7084 break;
7085 default:
7086 goto cp0_unimplemented;
7088 break;
7089 case CP0_REGISTER_08:
7090 switch (sel) {
7091 case CP0_REG08__BADVADDR:
7092 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7093 tcg_gen_ext32s_tl(arg, arg);
7094 register_name = "BadVAddr";
7095 break;
7096 case CP0_REG08__BADINSTR:
7097 CP0_CHECK(ctx->bi);
7098 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7099 register_name = "BadInstr";
7100 break;
7101 case CP0_REG08__BADINSTRP:
7102 CP0_CHECK(ctx->bp);
7103 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7104 register_name = "BadInstrP";
7105 break;
7106 case CP0_REG08__BADINSTRX:
7107 CP0_CHECK(ctx->bi);
7108 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7109 tcg_gen_andi_tl(arg, arg, ~0xffff);
7110 register_name = "BadInstrX";
7111 break;
7112 default:
7113 goto cp0_unimplemented;
7115 break;
7116 case CP0_REGISTER_09:
7117 switch (sel) {
7118 case CP0_REG09__COUNT:
7119 /* Mark as an IO operation because we read the time. */
7120 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7121 gen_io_start();
7123 gen_helper_mfc0_count(arg, cpu_env);
7125 * Break the TB to be able to take timer interrupts immediately
7126 * after reading count. DISAS_STOP isn't sufficient, we need to
7127 * ensure we break completely out of translated code.
7129 gen_save_pc(ctx->base.pc_next + 4);
7130 ctx->base.is_jmp = DISAS_EXIT;
7131 register_name = "Count";
7132 break;
7133 case CP0_REG09__SAARI:
7134 CP0_CHECK(ctx->saar);
7135 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7136 register_name = "SAARI";
7137 break;
7138 case CP0_REG09__SAAR:
7139 CP0_CHECK(ctx->saar);
7140 gen_helper_mfc0_saar(arg, cpu_env);
7141 register_name = "SAAR";
7142 break;
7143 default:
7144 goto cp0_unimplemented;
7146 break;
7147 case CP0_REGISTER_10:
7148 switch (sel) {
7149 case CP0_REG10__ENTRYHI:
7150 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7151 tcg_gen_ext32s_tl(arg, arg);
7152 register_name = "EntryHi";
7153 break;
7154 default:
7155 goto cp0_unimplemented;
7157 break;
7158 case CP0_REGISTER_11:
7159 switch (sel) {
7160 case CP0_REG11__COMPARE:
7161 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7162 register_name = "Compare";
7163 break;
7164 /* 6,7 are implementation dependent */
7165 default:
7166 goto cp0_unimplemented;
7168 break;
7169 case CP0_REGISTER_12:
7170 switch (sel) {
7171 case CP0_REG12__STATUS:
7172 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7173 register_name = "Status";
7174 break;
7175 case CP0_REG12__INTCTL:
7176 check_insn(ctx, ISA_MIPS_R2);
7177 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7178 register_name = "IntCtl";
7179 break;
7180 case CP0_REG12__SRSCTL:
7181 check_insn(ctx, ISA_MIPS_R2);
7182 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7183 register_name = "SRSCtl";
7184 break;
7185 case CP0_REG12__SRSMAP:
7186 check_insn(ctx, ISA_MIPS_R2);
7187 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7188 register_name = "SRSMap";
7189 break;
7190 default:
7191 goto cp0_unimplemented;
7193 break;
7194 case CP0_REGISTER_13:
7195 switch (sel) {
7196 case CP0_REG13__CAUSE:
7197 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7198 register_name = "Cause";
7199 break;
7200 default:
7201 goto cp0_unimplemented;
7203 break;
7204 case CP0_REGISTER_14:
7205 switch (sel) {
7206 case CP0_REG14__EPC:
7207 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7208 tcg_gen_ext32s_tl(arg, arg);
7209 register_name = "EPC";
7210 break;
7211 default:
7212 goto cp0_unimplemented;
7214 break;
7215 case CP0_REGISTER_15:
7216 switch (sel) {
7217 case CP0_REG15__PRID:
7218 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7219 register_name = "PRid";
7220 break;
7221 case CP0_REG15__EBASE:
7222 check_insn(ctx, ISA_MIPS_R2);
7223 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7224 tcg_gen_ext32s_tl(arg, arg);
7225 register_name = "EBase";
7226 break;
7227 case CP0_REG15__CMGCRBASE:
7228 check_insn(ctx, ISA_MIPS_R2);
7229 CP0_CHECK(ctx->cmgcr);
7230 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7231 tcg_gen_ext32s_tl(arg, arg);
7232 register_name = "CMGCRBase";
7233 break;
7234 default:
7235 goto cp0_unimplemented;
7237 break;
7238 case CP0_REGISTER_16:
7239 switch (sel) {
7240 case CP0_REG16__CONFIG:
7241 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7242 register_name = "Config";
7243 break;
7244 case CP0_REG16__CONFIG1:
7245 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7246 register_name = "Config1";
7247 break;
7248 case CP0_REG16__CONFIG2:
7249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7250 register_name = "Config2";
7251 break;
7252 case CP0_REG16__CONFIG3:
7253 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7254 register_name = "Config3";
7255 break;
7256 case CP0_REG16__CONFIG4:
7257 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7258 register_name = "Config4";
7259 break;
7260 case CP0_REG16__CONFIG5:
7261 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7262 register_name = "Config5";
7263 break;
7264 /* 6,7 are implementation dependent */
7265 case CP0_REG16__CONFIG6:
7266 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7267 register_name = "Config6";
7268 break;
7269 case CP0_REG16__CONFIG7:
7270 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7271 register_name = "Config7";
7272 break;
7273 default:
7274 goto cp0_unimplemented;
7276 break;
7277 case CP0_REGISTER_17:
7278 switch (sel) {
7279 case CP0_REG17__LLADDR:
7280 gen_helper_mfc0_lladdr(arg, cpu_env);
7281 register_name = "LLAddr";
7282 break;
7283 case CP0_REG17__MAAR:
7284 CP0_CHECK(ctx->mrp);
7285 gen_helper_mfc0_maar(arg, cpu_env);
7286 register_name = "MAAR";
7287 break;
7288 case CP0_REG17__MAARI:
7289 CP0_CHECK(ctx->mrp);
7290 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7291 register_name = "MAARI";
7292 break;
7293 default:
7294 goto cp0_unimplemented;
7296 break;
7297 case CP0_REGISTER_18:
7298 switch (sel) {
7299 case CP0_REG18__WATCHLO0:
7300 case CP0_REG18__WATCHLO1:
7301 case CP0_REG18__WATCHLO2:
7302 case CP0_REG18__WATCHLO3:
7303 case CP0_REG18__WATCHLO4:
7304 case CP0_REG18__WATCHLO5:
7305 case CP0_REG18__WATCHLO6:
7306 case CP0_REG18__WATCHLO7:
7307 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7308 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7309 register_name = "WatchLo";
7310 break;
7311 default:
7312 goto cp0_unimplemented;
7314 break;
7315 case CP0_REGISTER_19:
7316 switch (sel) {
7317 case CP0_REG19__WATCHHI0:
7318 case CP0_REG19__WATCHHI1:
7319 case CP0_REG19__WATCHHI2:
7320 case CP0_REG19__WATCHHI3:
7321 case CP0_REG19__WATCHHI4:
7322 case CP0_REG19__WATCHHI5:
7323 case CP0_REG19__WATCHHI6:
7324 case CP0_REG19__WATCHHI7:
7325 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7326 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7327 register_name = "WatchHi";
7328 break;
7329 default:
7330 goto cp0_unimplemented;
7332 break;
7333 case CP0_REGISTER_20:
7334 switch (sel) {
7335 case CP0_REG20__XCONTEXT:
7336 #if defined(TARGET_MIPS64)
7337 check_insn(ctx, ISA_MIPS3);
7338 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7339 tcg_gen_ext32s_tl(arg, arg);
7340 register_name = "XContext";
7341 break;
7342 #endif
7343 default:
7344 goto cp0_unimplemented;
7346 break;
7347 case CP0_REGISTER_21:
7348 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7349 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7350 switch (sel) {
7351 case 0:
7352 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7353 register_name = "Framemask";
7354 break;
7355 default:
7356 goto cp0_unimplemented;
7358 break;
7359 case CP0_REGISTER_22:
7360 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7361 register_name = "'Diagnostic"; /* implementation dependent */
7362 break;
7363 case CP0_REGISTER_23:
7364 switch (sel) {
7365 case CP0_REG23__DEBUG:
7366 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7367 register_name = "Debug";
7368 break;
7369 case CP0_REG23__TRACECONTROL:
7370 /* PDtrace support */
7371 /* gen_helper_mfc0_tracecontrol(arg); */
7372 register_name = "TraceControl";
7373 goto cp0_unimplemented;
7374 case CP0_REG23__TRACECONTROL2:
7375 /* PDtrace support */
7376 /* gen_helper_mfc0_tracecontrol2(arg); */
7377 register_name = "TraceControl2";
7378 goto cp0_unimplemented;
7379 case CP0_REG23__USERTRACEDATA1:
7380 /* PDtrace support */
7381 /* gen_helper_mfc0_usertracedata1(arg);*/
7382 register_name = "UserTraceData1";
7383 goto cp0_unimplemented;
7384 case CP0_REG23__TRACEIBPC:
7385 /* PDtrace support */
7386 /* gen_helper_mfc0_traceibpc(arg); */
7387 register_name = "TraceIBPC";
7388 goto cp0_unimplemented;
7389 case CP0_REG23__TRACEDBPC:
7390 /* PDtrace support */
7391 /* gen_helper_mfc0_tracedbpc(arg); */
7392 register_name = "TraceDBPC";
7393 goto cp0_unimplemented;
7394 default:
7395 goto cp0_unimplemented;
7397 break;
7398 case CP0_REGISTER_24:
7399 switch (sel) {
7400 case CP0_REG24__DEPC:
7401 /* EJTAG support */
7402 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7403 tcg_gen_ext32s_tl(arg, arg);
7404 register_name = "DEPC";
7405 break;
7406 default:
7407 goto cp0_unimplemented;
7409 break;
7410 case CP0_REGISTER_25:
7411 switch (sel) {
7412 case CP0_REG25__PERFCTL0:
7413 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7414 register_name = "Performance0";
7415 break;
7416 case CP0_REG25__PERFCNT0:
7417 /* gen_helper_mfc0_performance1(arg); */
7418 register_name = "Performance1";
7419 goto cp0_unimplemented;
7420 case CP0_REG25__PERFCTL1:
7421 /* gen_helper_mfc0_performance2(arg); */
7422 register_name = "Performance2";
7423 goto cp0_unimplemented;
7424 case CP0_REG25__PERFCNT1:
7425 /* gen_helper_mfc0_performance3(arg); */
7426 register_name = "Performance3";
7427 goto cp0_unimplemented;
7428 case CP0_REG25__PERFCTL2:
7429 /* gen_helper_mfc0_performance4(arg); */
7430 register_name = "Performance4";
7431 goto cp0_unimplemented;
7432 case CP0_REG25__PERFCNT2:
7433 /* gen_helper_mfc0_performance5(arg); */
7434 register_name = "Performance5";
7435 goto cp0_unimplemented;
7436 case CP0_REG25__PERFCTL3:
7437 /* gen_helper_mfc0_performance6(arg); */
7438 register_name = "Performance6";
7439 goto cp0_unimplemented;
7440 case CP0_REG25__PERFCNT3:
7441 /* gen_helper_mfc0_performance7(arg); */
7442 register_name = "Performance7";
7443 goto cp0_unimplemented;
7444 default:
7445 goto cp0_unimplemented;
7447 break;
7448 case CP0_REGISTER_26:
7449 switch (sel) {
7450 case CP0_REG26__ERRCTL:
7451 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7452 register_name = "ErrCtl";
7453 break;
7454 default:
7455 goto cp0_unimplemented;
7457 break;
7458 case CP0_REGISTER_27:
7459 switch (sel) {
7460 case CP0_REG27__CACHERR:
7461 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7462 register_name = "CacheErr";
7463 break;
7464 default:
7465 goto cp0_unimplemented;
7467 break;
7468 case CP0_REGISTER_28:
7469 switch (sel) {
7470 case CP0_REG28__TAGLO:
7471 case CP0_REG28__TAGLO1:
7472 case CP0_REG28__TAGLO2:
7473 case CP0_REG28__TAGLO3:
7475 TCGv_i64 tmp = tcg_temp_new_i64();
7476 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7477 gen_move_low32(arg, tmp);
7478 tcg_temp_free_i64(tmp);
7480 register_name = "TagLo";
7481 break;
7482 case CP0_REG28__DATALO:
7483 case CP0_REG28__DATALO1:
7484 case CP0_REG28__DATALO2:
7485 case CP0_REG28__DATALO3:
7486 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7487 register_name = "DataLo";
7488 break;
7489 default:
7490 goto cp0_unimplemented;
7492 break;
7493 case CP0_REGISTER_29:
7494 switch (sel) {
7495 case CP0_REG29__TAGHI:
7496 case CP0_REG29__TAGHI1:
7497 case CP0_REG29__TAGHI2:
7498 case CP0_REG29__TAGHI3:
7499 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7500 register_name = "TagHi";
7501 break;
7502 case CP0_REG29__DATAHI:
7503 case CP0_REG29__DATAHI1:
7504 case CP0_REG29__DATAHI2:
7505 case CP0_REG29__DATAHI3:
7506 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7507 register_name = "DataHi";
7508 break;
7509 default:
7510 goto cp0_unimplemented;
7512 break;
7513 case CP0_REGISTER_30:
7514 switch (sel) {
7515 case CP0_REG30__ERROREPC:
7516 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7517 tcg_gen_ext32s_tl(arg, arg);
7518 register_name = "ErrorEPC";
7519 break;
7520 default:
7521 goto cp0_unimplemented;
7523 break;
7524 case CP0_REGISTER_31:
7525 switch (sel) {
7526 case CP0_REG31__DESAVE:
7527 /* EJTAG support */
7528 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7529 register_name = "DESAVE";
7530 break;
7531 case CP0_REG31__KSCRATCH1:
7532 case CP0_REG31__KSCRATCH2:
7533 case CP0_REG31__KSCRATCH3:
7534 case CP0_REG31__KSCRATCH4:
7535 case CP0_REG31__KSCRATCH5:
7536 case CP0_REG31__KSCRATCH6:
7537 CP0_CHECK(ctx->kscrexist & (1 << sel));
7538 tcg_gen_ld_tl(arg, cpu_env,
7539 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7540 tcg_gen_ext32s_tl(arg, arg);
7541 register_name = "KScratch";
7542 break;
7543 default:
7544 goto cp0_unimplemented;
7546 break;
7547 default:
7548 goto cp0_unimplemented;
7550 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7551 return;
7553 cp0_unimplemented:
7554 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7555 register_name, reg, sel);
7556 gen_mfc0_unimplemented(ctx, arg);
7559 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7561 const char *register_name = "invalid";
7563 if (sel != 0) {
7564 check_insn(ctx, ISA_MIPS_R1);
7567 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7568 gen_io_start();
7571 switch (reg) {
7572 case CP0_REGISTER_00:
7573 switch (sel) {
7574 case CP0_REG00__INDEX:
7575 gen_helper_mtc0_index(cpu_env, arg);
7576 register_name = "Index";
7577 break;
7578 case CP0_REG00__MVPCONTROL:
7579 CP0_CHECK(ctx->insn_flags & ASE_MT);
7580 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7581 register_name = "MVPControl";
7582 break;
7583 case CP0_REG00__MVPCONF0:
7584 CP0_CHECK(ctx->insn_flags & ASE_MT);
7585 /* ignored */
7586 register_name = "MVPConf0";
7587 break;
7588 case CP0_REG00__MVPCONF1:
7589 CP0_CHECK(ctx->insn_flags & ASE_MT);
7590 /* ignored */
7591 register_name = "MVPConf1";
7592 break;
7593 case CP0_REG00__VPCONTROL:
7594 CP0_CHECK(ctx->vp);
7595 /* ignored */
7596 register_name = "VPControl";
7597 break;
7598 default:
7599 goto cp0_unimplemented;
7601 break;
7602 case CP0_REGISTER_01:
7603 switch (sel) {
7604 case CP0_REG01__RANDOM:
7605 /* ignored */
7606 register_name = "Random";
7607 break;
7608 case CP0_REG01__VPECONTROL:
7609 CP0_CHECK(ctx->insn_flags & ASE_MT);
7610 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7611 register_name = "VPEControl";
7612 break;
7613 case CP0_REG01__VPECONF0:
7614 CP0_CHECK(ctx->insn_flags & ASE_MT);
7615 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7616 register_name = "VPEConf0";
7617 break;
7618 case CP0_REG01__VPECONF1:
7619 CP0_CHECK(ctx->insn_flags & ASE_MT);
7620 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7621 register_name = "VPEConf1";
7622 break;
7623 case CP0_REG01__YQMASK:
7624 CP0_CHECK(ctx->insn_flags & ASE_MT);
7625 gen_helper_mtc0_yqmask(cpu_env, arg);
7626 register_name = "YQMask";
7627 break;
7628 case CP0_REG01__VPESCHEDULE:
7629 CP0_CHECK(ctx->insn_flags & ASE_MT);
7630 tcg_gen_st_tl(arg, cpu_env,
7631 offsetof(CPUMIPSState, CP0_VPESchedule));
7632 register_name = "VPESchedule";
7633 break;
7634 case CP0_REG01__VPESCHEFBACK:
7635 CP0_CHECK(ctx->insn_flags & ASE_MT);
7636 tcg_gen_st_tl(arg, cpu_env,
7637 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7638 register_name = "VPEScheFBack";
7639 break;
7640 case CP0_REG01__VPEOPT:
7641 CP0_CHECK(ctx->insn_flags & ASE_MT);
7642 gen_helper_mtc0_vpeopt(cpu_env, arg);
7643 register_name = "VPEOpt";
7644 break;
7645 default:
7646 goto cp0_unimplemented;
7648 break;
7649 case CP0_REGISTER_02:
7650 switch (sel) {
7651 case CP0_REG02__ENTRYLO0:
7652 gen_helper_mtc0_entrylo0(cpu_env, arg);
7653 register_name = "EntryLo0";
7654 break;
7655 case CP0_REG02__TCSTATUS:
7656 CP0_CHECK(ctx->insn_flags & ASE_MT);
7657 gen_helper_mtc0_tcstatus(cpu_env, arg);
7658 register_name = "TCStatus";
7659 break;
7660 case CP0_REG02__TCBIND:
7661 CP0_CHECK(ctx->insn_flags & ASE_MT);
7662 gen_helper_mtc0_tcbind(cpu_env, arg);
7663 register_name = "TCBind";
7664 break;
7665 case CP0_REG02__TCRESTART:
7666 CP0_CHECK(ctx->insn_flags & ASE_MT);
7667 gen_helper_mtc0_tcrestart(cpu_env, arg);
7668 register_name = "TCRestart";
7669 break;
7670 case CP0_REG02__TCHALT:
7671 CP0_CHECK(ctx->insn_flags & ASE_MT);
7672 gen_helper_mtc0_tchalt(cpu_env, arg);
7673 register_name = "TCHalt";
7674 break;
7675 case CP0_REG02__TCCONTEXT:
7676 CP0_CHECK(ctx->insn_flags & ASE_MT);
7677 gen_helper_mtc0_tccontext(cpu_env, arg);
7678 register_name = "TCContext";
7679 break;
7680 case CP0_REG02__TCSCHEDULE:
7681 CP0_CHECK(ctx->insn_flags & ASE_MT);
7682 gen_helper_mtc0_tcschedule(cpu_env, arg);
7683 register_name = "TCSchedule";
7684 break;
7685 case CP0_REG02__TCSCHEFBACK:
7686 CP0_CHECK(ctx->insn_flags & ASE_MT);
7687 gen_helper_mtc0_tcschefback(cpu_env, arg);
7688 register_name = "TCScheFBack";
7689 break;
7690 default:
7691 goto cp0_unimplemented;
7693 break;
7694 case CP0_REGISTER_03:
7695 switch (sel) {
7696 case CP0_REG03__ENTRYLO1:
7697 gen_helper_mtc0_entrylo1(cpu_env, arg);
7698 register_name = "EntryLo1";
7699 break;
7700 case CP0_REG03__GLOBALNUM:
7701 CP0_CHECK(ctx->vp);
7702 /* ignored */
7703 register_name = "GlobalNumber";
7704 break;
7705 default:
7706 goto cp0_unimplemented;
7708 break;
7709 case CP0_REGISTER_04:
7710 switch (sel) {
7711 case CP0_REG04__CONTEXT:
7712 gen_helper_mtc0_context(cpu_env, arg);
7713 register_name = "Context";
7714 break;
7715 case CP0_REG04__CONTEXTCONFIG:
7716 /* SmartMIPS ASE */
7717 /* gen_helper_mtc0_contextconfig(arg); */
7718 register_name = "ContextConfig";
7719 goto cp0_unimplemented;
7720 case CP0_REG04__USERLOCAL:
7721 CP0_CHECK(ctx->ulri);
7722 tcg_gen_st_tl(arg, cpu_env,
7723 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7724 register_name = "UserLocal";
7725 break;
7726 case CP0_REG04__MMID:
7727 CP0_CHECK(ctx->mi);
7728 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
7729 register_name = "MMID";
7730 break;
7731 default:
7732 goto cp0_unimplemented;
7734 break;
7735 case CP0_REGISTER_05:
7736 switch (sel) {
7737 case CP0_REG05__PAGEMASK:
7738 gen_helper_mtc0_pagemask(cpu_env, arg);
7739 register_name = "PageMask";
7740 break;
7741 case CP0_REG05__PAGEGRAIN:
7742 check_insn(ctx, ISA_MIPS_R2);
7743 gen_helper_mtc0_pagegrain(cpu_env, arg);
7744 register_name = "PageGrain";
7745 ctx->base.is_jmp = DISAS_STOP;
7746 break;
7747 case CP0_REG05__SEGCTL0:
7748 CP0_CHECK(ctx->sc);
7749 gen_helper_mtc0_segctl0(cpu_env, arg);
7750 register_name = "SegCtl0";
7751 break;
7752 case CP0_REG05__SEGCTL1:
7753 CP0_CHECK(ctx->sc);
7754 gen_helper_mtc0_segctl1(cpu_env, arg);
7755 register_name = "SegCtl1";
7756 break;
7757 case CP0_REG05__SEGCTL2:
7758 CP0_CHECK(ctx->sc);
7759 gen_helper_mtc0_segctl2(cpu_env, arg);
7760 register_name = "SegCtl2";
7761 break;
7762 case CP0_REG05__PWBASE:
7763 check_pw(ctx);
7764 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7765 register_name = "PWBase";
7766 break;
7767 case CP0_REG05__PWFIELD:
7768 check_pw(ctx);
7769 gen_helper_mtc0_pwfield(cpu_env, arg);
7770 register_name = "PWField";
7771 break;
7772 case CP0_REG05__PWSIZE:
7773 check_pw(ctx);
7774 gen_helper_mtc0_pwsize(cpu_env, arg);
7775 register_name = "PWSize";
7776 break;
7777 default:
7778 goto cp0_unimplemented;
7780 break;
7781 case CP0_REGISTER_06:
7782 switch (sel) {
7783 case CP0_REG06__WIRED:
7784 gen_helper_mtc0_wired(cpu_env, arg);
7785 register_name = "Wired";
7786 break;
7787 case CP0_REG06__SRSCONF0:
7788 check_insn(ctx, ISA_MIPS_R2);
7789 gen_helper_mtc0_srsconf0(cpu_env, arg);
7790 register_name = "SRSConf0";
7791 break;
7792 case CP0_REG06__SRSCONF1:
7793 check_insn(ctx, ISA_MIPS_R2);
7794 gen_helper_mtc0_srsconf1(cpu_env, arg);
7795 register_name = "SRSConf1";
7796 break;
7797 case CP0_REG06__SRSCONF2:
7798 check_insn(ctx, ISA_MIPS_R2);
7799 gen_helper_mtc0_srsconf2(cpu_env, arg);
7800 register_name = "SRSConf2";
7801 break;
7802 case CP0_REG06__SRSCONF3:
7803 check_insn(ctx, ISA_MIPS_R2);
7804 gen_helper_mtc0_srsconf3(cpu_env, arg);
7805 register_name = "SRSConf3";
7806 break;
7807 case CP0_REG06__SRSCONF4:
7808 check_insn(ctx, ISA_MIPS_R2);
7809 gen_helper_mtc0_srsconf4(cpu_env, arg);
7810 register_name = "SRSConf4";
7811 break;
7812 case CP0_REG06__PWCTL:
7813 check_pw(ctx);
7814 gen_helper_mtc0_pwctl(cpu_env, arg);
7815 register_name = "PWCtl";
7816 break;
7817 default:
7818 goto cp0_unimplemented;
7820 break;
7821 case CP0_REGISTER_07:
7822 switch (sel) {
7823 case CP0_REG07__HWRENA:
7824 check_insn(ctx, ISA_MIPS_R2);
7825 gen_helper_mtc0_hwrena(cpu_env, arg);
7826 ctx->base.is_jmp = DISAS_STOP;
7827 register_name = "HWREna";
7828 break;
7829 default:
7830 goto cp0_unimplemented;
7832 break;
7833 case CP0_REGISTER_08:
7834 switch (sel) {
7835 case CP0_REG08__BADVADDR:
7836 /* ignored */
7837 register_name = "BadVAddr";
7838 break;
7839 case CP0_REG08__BADINSTR:
7840 /* ignored */
7841 register_name = "BadInstr";
7842 break;
7843 case CP0_REG08__BADINSTRP:
7844 /* ignored */
7845 register_name = "BadInstrP";
7846 break;
7847 case CP0_REG08__BADINSTRX:
7848 /* ignored */
7849 register_name = "BadInstrX";
7850 break;
7851 default:
7852 goto cp0_unimplemented;
7854 break;
7855 case CP0_REGISTER_09:
7856 switch (sel) {
7857 case CP0_REG09__COUNT:
7858 gen_helper_mtc0_count(cpu_env, arg);
7859 register_name = "Count";
7860 break;
7861 case CP0_REG09__SAARI:
7862 CP0_CHECK(ctx->saar);
7863 gen_helper_mtc0_saari(cpu_env, arg);
7864 register_name = "SAARI";
7865 break;
7866 case CP0_REG09__SAAR:
7867 CP0_CHECK(ctx->saar);
7868 gen_helper_mtc0_saar(cpu_env, arg);
7869 register_name = "SAAR";
7870 break;
7871 default:
7872 goto cp0_unimplemented;
7874 break;
7875 case CP0_REGISTER_10:
7876 switch (sel) {
7877 case CP0_REG10__ENTRYHI:
7878 gen_helper_mtc0_entryhi(cpu_env, arg);
7879 register_name = "EntryHi";
7880 break;
7881 default:
7882 goto cp0_unimplemented;
7884 break;
7885 case CP0_REGISTER_11:
7886 switch (sel) {
7887 case CP0_REG11__COMPARE:
7888 gen_helper_mtc0_compare(cpu_env, arg);
7889 register_name = "Compare";
7890 break;
7891 /* 6,7 are implementation dependent */
7892 default:
7893 goto cp0_unimplemented;
7895 break;
7896 case CP0_REGISTER_12:
7897 switch (sel) {
7898 case CP0_REG12__STATUS:
7899 save_cpu_state(ctx, 1);
7900 gen_helper_mtc0_status(cpu_env, arg);
7901 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7902 gen_save_pc(ctx->base.pc_next + 4);
7903 ctx->base.is_jmp = DISAS_EXIT;
7904 register_name = "Status";
7905 break;
7906 case CP0_REG12__INTCTL:
7907 check_insn(ctx, ISA_MIPS_R2);
7908 gen_helper_mtc0_intctl(cpu_env, arg);
7909 /* Stop translation as we may have switched the execution mode */
7910 ctx->base.is_jmp = DISAS_STOP;
7911 register_name = "IntCtl";
7912 break;
7913 case CP0_REG12__SRSCTL:
7914 check_insn(ctx, ISA_MIPS_R2);
7915 gen_helper_mtc0_srsctl(cpu_env, arg);
7916 /* Stop translation as we may have switched the execution mode */
7917 ctx->base.is_jmp = DISAS_STOP;
7918 register_name = "SRSCtl";
7919 break;
7920 case CP0_REG12__SRSMAP:
7921 check_insn(ctx, ISA_MIPS_R2);
7922 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7923 /* Stop translation as we may have switched the execution mode */
7924 ctx->base.is_jmp = DISAS_STOP;
7925 register_name = "SRSMap";
7926 break;
7927 default:
7928 goto cp0_unimplemented;
7930 break;
7931 case CP0_REGISTER_13:
7932 switch (sel) {
7933 case CP0_REG13__CAUSE:
7934 save_cpu_state(ctx, 1);
7935 gen_helper_mtc0_cause(cpu_env, arg);
7937 * Stop translation as we may have triggered an interrupt.
7938 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7939 * translated code to check for pending interrupts.
7941 gen_save_pc(ctx->base.pc_next + 4);
7942 ctx->base.is_jmp = DISAS_EXIT;
7943 register_name = "Cause";
7944 break;
7945 default:
7946 goto cp0_unimplemented;
7948 break;
7949 case CP0_REGISTER_14:
7950 switch (sel) {
7951 case CP0_REG14__EPC:
7952 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7953 register_name = "EPC";
7954 break;
7955 default:
7956 goto cp0_unimplemented;
7958 break;
7959 case CP0_REGISTER_15:
7960 switch (sel) {
7961 case CP0_REG15__PRID:
7962 /* ignored */
7963 register_name = "PRid";
7964 break;
7965 case CP0_REG15__EBASE:
7966 check_insn(ctx, ISA_MIPS_R2);
7967 gen_helper_mtc0_ebase(cpu_env, arg);
7968 register_name = "EBase";
7969 break;
7970 default:
7971 goto cp0_unimplemented;
7973 break;
7974 case CP0_REGISTER_16:
7975 switch (sel) {
7976 case CP0_REG16__CONFIG:
7977 gen_helper_mtc0_config0(cpu_env, arg);
7978 register_name = "Config";
7979 /* Stop translation as we may have switched the execution mode */
7980 ctx->base.is_jmp = DISAS_STOP;
7981 break;
7982 case CP0_REG16__CONFIG1:
7983 /* ignored, read only */
7984 register_name = "Config1";
7985 break;
7986 case CP0_REG16__CONFIG2:
7987 gen_helper_mtc0_config2(cpu_env, arg);
7988 register_name = "Config2";
7989 /* Stop translation as we may have switched the execution mode */
7990 ctx->base.is_jmp = DISAS_STOP;
7991 break;
7992 case CP0_REG16__CONFIG3:
7993 gen_helper_mtc0_config3(cpu_env, arg);
7994 register_name = "Config3";
7995 /* Stop translation as we may have switched the execution mode */
7996 ctx->base.is_jmp = DISAS_STOP;
7997 break;
7998 case CP0_REG16__CONFIG4:
7999 gen_helper_mtc0_config4(cpu_env, arg);
8000 register_name = "Config4";
8001 ctx->base.is_jmp = DISAS_STOP;
8002 break;
8003 case CP0_REG16__CONFIG5:
8004 gen_helper_mtc0_config5(cpu_env, arg);
8005 register_name = "Config5";
8006 /* Stop translation as we may have switched the execution mode */
8007 ctx->base.is_jmp = DISAS_STOP;
8008 break;
8009 /* 6,7 are implementation dependent */
8010 case CP0_REG16__CONFIG6:
8011 /* ignored */
8012 register_name = "Config6";
8013 break;
8014 case CP0_REG16__CONFIG7:
8015 /* ignored */
8016 register_name = "Config7";
8017 break;
8018 default:
8019 register_name = "Invalid config selector";
8020 goto cp0_unimplemented;
8022 break;
8023 case CP0_REGISTER_17:
8024 switch (sel) {
8025 case CP0_REG17__LLADDR:
8026 gen_helper_mtc0_lladdr(cpu_env, arg);
8027 register_name = "LLAddr";
8028 break;
8029 case CP0_REG17__MAAR:
8030 CP0_CHECK(ctx->mrp);
8031 gen_helper_mtc0_maar(cpu_env, arg);
8032 register_name = "MAAR";
8033 break;
8034 case CP0_REG17__MAARI:
8035 CP0_CHECK(ctx->mrp);
8036 gen_helper_mtc0_maari(cpu_env, arg);
8037 register_name = "MAARI";
8038 break;
8039 default:
8040 goto cp0_unimplemented;
8042 break;
8043 case CP0_REGISTER_18:
8044 switch (sel) {
8045 case CP0_REG18__WATCHLO0:
8046 case CP0_REG18__WATCHLO1:
8047 case CP0_REG18__WATCHLO2:
8048 case CP0_REG18__WATCHLO3:
8049 case CP0_REG18__WATCHLO4:
8050 case CP0_REG18__WATCHLO5:
8051 case CP0_REG18__WATCHLO6:
8052 case CP0_REG18__WATCHLO7:
8053 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8054 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8055 register_name = "WatchLo";
8056 break;
8057 default:
8058 goto cp0_unimplemented;
8060 break;
8061 case CP0_REGISTER_19:
8062 switch (sel) {
8063 case CP0_REG19__WATCHHI0:
8064 case CP0_REG19__WATCHHI1:
8065 case CP0_REG19__WATCHHI2:
8066 case CP0_REG19__WATCHHI3:
8067 case CP0_REG19__WATCHHI4:
8068 case CP0_REG19__WATCHHI5:
8069 case CP0_REG19__WATCHHI6:
8070 case CP0_REG19__WATCHHI7:
8071 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8072 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8073 register_name = "WatchHi";
8074 break;
8075 default:
8076 goto cp0_unimplemented;
8078 break;
8079 case CP0_REGISTER_20:
8080 switch (sel) {
8081 case CP0_REG20__XCONTEXT:
8082 #if defined(TARGET_MIPS64)
8083 check_insn(ctx, ISA_MIPS3);
8084 gen_helper_mtc0_xcontext(cpu_env, arg);
8085 register_name = "XContext";
8086 break;
8087 #endif
8088 default:
8089 goto cp0_unimplemented;
8091 break;
8092 case CP0_REGISTER_21:
8093 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8094 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8095 switch (sel) {
8096 case 0:
8097 gen_helper_mtc0_framemask(cpu_env, arg);
8098 register_name = "Framemask";
8099 break;
8100 default:
8101 goto cp0_unimplemented;
8103 break;
8104 case CP0_REGISTER_22:
8105 /* ignored */
8106 register_name = "Diagnostic"; /* implementation dependent */
8107 break;
8108 case CP0_REGISTER_23:
8109 switch (sel) {
8110 case CP0_REG23__DEBUG:
8111 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8112 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8113 gen_save_pc(ctx->base.pc_next + 4);
8114 ctx->base.is_jmp = DISAS_EXIT;
8115 register_name = "Debug";
8116 break;
8117 case CP0_REG23__TRACECONTROL:
8118 /* PDtrace support */
8119 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8120 register_name = "TraceControl";
8121 /* Stop translation as we may have switched the execution mode */
8122 ctx->base.is_jmp = DISAS_STOP;
8123 goto cp0_unimplemented;
8124 case CP0_REG23__TRACECONTROL2:
8125 /* PDtrace support */
8126 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8127 register_name = "TraceControl2";
8128 /* Stop translation as we may have switched the execution mode */
8129 ctx->base.is_jmp = DISAS_STOP;
8130 goto cp0_unimplemented;
8131 case CP0_REG23__USERTRACEDATA1:
8132 /* Stop translation as we may have switched the execution mode */
8133 ctx->base.is_jmp = DISAS_STOP;
8134 /* PDtrace support */
8135 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8136 register_name = "UserTraceData";
8137 /* Stop translation as we may have switched the execution mode */
8138 ctx->base.is_jmp = DISAS_STOP;
8139 goto cp0_unimplemented;
8140 case CP0_REG23__TRACEIBPC:
8141 /* PDtrace support */
8142 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8143 /* Stop translation as we may have switched the execution mode */
8144 ctx->base.is_jmp = DISAS_STOP;
8145 register_name = "TraceIBPC";
8146 goto cp0_unimplemented;
8147 case CP0_REG23__TRACEDBPC:
8148 /* PDtrace support */
8149 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8150 /* Stop translation as we may have switched the execution mode */
8151 ctx->base.is_jmp = DISAS_STOP;
8152 register_name = "TraceDBPC";
8153 goto cp0_unimplemented;
8154 default:
8155 goto cp0_unimplemented;
8157 break;
8158 case CP0_REGISTER_24:
8159 switch (sel) {
8160 case CP0_REG24__DEPC:
8161 /* EJTAG support */
8162 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8163 register_name = "DEPC";
8164 break;
8165 default:
8166 goto cp0_unimplemented;
8168 break;
8169 case CP0_REGISTER_25:
8170 switch (sel) {
8171 case CP0_REG25__PERFCTL0:
8172 gen_helper_mtc0_performance0(cpu_env, arg);
8173 register_name = "Performance0";
8174 break;
8175 case CP0_REG25__PERFCNT0:
8176 /* gen_helper_mtc0_performance1(arg); */
8177 register_name = "Performance1";
8178 goto cp0_unimplemented;
8179 case CP0_REG25__PERFCTL1:
8180 /* gen_helper_mtc0_performance2(arg); */
8181 register_name = "Performance2";
8182 goto cp0_unimplemented;
8183 case CP0_REG25__PERFCNT1:
8184 /* gen_helper_mtc0_performance3(arg); */
8185 register_name = "Performance3";
8186 goto cp0_unimplemented;
8187 case CP0_REG25__PERFCTL2:
8188 /* gen_helper_mtc0_performance4(arg); */
8189 register_name = "Performance4";
8190 goto cp0_unimplemented;
8191 case CP0_REG25__PERFCNT2:
8192 /* gen_helper_mtc0_performance5(arg); */
8193 register_name = "Performance5";
8194 goto cp0_unimplemented;
8195 case CP0_REG25__PERFCTL3:
8196 /* gen_helper_mtc0_performance6(arg); */
8197 register_name = "Performance6";
8198 goto cp0_unimplemented;
8199 case CP0_REG25__PERFCNT3:
8200 /* gen_helper_mtc0_performance7(arg); */
8201 register_name = "Performance7";
8202 goto cp0_unimplemented;
8203 default:
8204 goto cp0_unimplemented;
8206 break;
8207 case CP0_REGISTER_26:
8208 switch (sel) {
8209 case CP0_REG26__ERRCTL:
8210 gen_helper_mtc0_errctl(cpu_env, arg);
8211 ctx->base.is_jmp = DISAS_STOP;
8212 register_name = "ErrCtl";
8213 break;
8214 default:
8215 goto cp0_unimplemented;
8217 break;
8218 case CP0_REGISTER_27:
8219 switch (sel) {
8220 case CP0_REG27__CACHERR:
8221 /* ignored */
8222 register_name = "CacheErr";
8223 break;
8224 default:
8225 goto cp0_unimplemented;
8227 break;
8228 case CP0_REGISTER_28:
8229 switch (sel) {
8230 case CP0_REG28__TAGLO:
8231 case CP0_REG28__TAGLO1:
8232 case CP0_REG28__TAGLO2:
8233 case CP0_REG28__TAGLO3:
8234 gen_helper_mtc0_taglo(cpu_env, arg);
8235 register_name = "TagLo";
8236 break;
8237 case CP0_REG28__DATALO:
8238 case CP0_REG28__DATALO1:
8239 case CP0_REG28__DATALO2:
8240 case CP0_REG28__DATALO3:
8241 gen_helper_mtc0_datalo(cpu_env, arg);
8242 register_name = "DataLo";
8243 break;
8244 default:
8245 goto cp0_unimplemented;
8247 break;
8248 case CP0_REGISTER_29:
8249 switch (sel) {
8250 case CP0_REG29__TAGHI:
8251 case CP0_REG29__TAGHI1:
8252 case CP0_REG29__TAGHI2:
8253 case CP0_REG29__TAGHI3:
8254 gen_helper_mtc0_taghi(cpu_env, arg);
8255 register_name = "TagHi";
8256 break;
8257 case CP0_REG29__DATAHI:
8258 case CP0_REG29__DATAHI1:
8259 case CP0_REG29__DATAHI2:
8260 case CP0_REG29__DATAHI3:
8261 gen_helper_mtc0_datahi(cpu_env, arg);
8262 register_name = "DataHi";
8263 break;
8264 default:
8265 register_name = "invalid sel";
8266 goto cp0_unimplemented;
8268 break;
8269 case CP0_REGISTER_30:
8270 switch (sel) {
8271 case CP0_REG30__ERROREPC:
8272 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8273 register_name = "ErrorEPC";
8274 break;
8275 default:
8276 goto cp0_unimplemented;
8278 break;
8279 case CP0_REGISTER_31:
8280 switch (sel) {
8281 case CP0_REG31__DESAVE:
8282 /* EJTAG support */
8283 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8284 register_name = "DESAVE";
8285 break;
8286 case CP0_REG31__KSCRATCH1:
8287 case CP0_REG31__KSCRATCH2:
8288 case CP0_REG31__KSCRATCH3:
8289 case CP0_REG31__KSCRATCH4:
8290 case CP0_REG31__KSCRATCH5:
8291 case CP0_REG31__KSCRATCH6:
8292 CP0_CHECK(ctx->kscrexist & (1 << sel));
8293 tcg_gen_st_tl(arg, cpu_env,
8294 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8295 register_name = "KScratch";
8296 break;
8297 default:
8298 goto cp0_unimplemented;
8300 break;
8301 default:
8302 goto cp0_unimplemented;
8304 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8306 /* For simplicity assume that all writes can cause interrupts. */
8307 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8309 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8310 * translated code to check for pending interrupts.
8312 gen_save_pc(ctx->base.pc_next + 4);
8313 ctx->base.is_jmp = DISAS_EXIT;
8315 return;
8317 cp0_unimplemented:
8318 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8319 register_name, reg, sel);
8322 #if defined(TARGET_MIPS64)
8323 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8325 const char *register_name = "invalid";
8327 if (sel != 0) {
8328 check_insn(ctx, ISA_MIPS_R1);
8331 switch (reg) {
8332 case CP0_REGISTER_00:
8333 switch (sel) {
8334 case CP0_REG00__INDEX:
8335 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8336 register_name = "Index";
8337 break;
8338 case CP0_REG00__MVPCONTROL:
8339 CP0_CHECK(ctx->insn_flags & ASE_MT);
8340 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8341 register_name = "MVPControl";
8342 break;
8343 case CP0_REG00__MVPCONF0:
8344 CP0_CHECK(ctx->insn_flags & ASE_MT);
8345 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8346 register_name = "MVPConf0";
8347 break;
8348 case CP0_REG00__MVPCONF1:
8349 CP0_CHECK(ctx->insn_flags & ASE_MT);
8350 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8351 register_name = "MVPConf1";
8352 break;
8353 case CP0_REG00__VPCONTROL:
8354 CP0_CHECK(ctx->vp);
8355 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8356 register_name = "VPControl";
8357 break;
8358 default:
8359 goto cp0_unimplemented;
8361 break;
8362 case CP0_REGISTER_01:
8363 switch (sel) {
8364 case CP0_REG01__RANDOM:
8365 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8366 gen_helper_mfc0_random(arg, cpu_env);
8367 register_name = "Random";
8368 break;
8369 case CP0_REG01__VPECONTROL:
8370 CP0_CHECK(ctx->insn_flags & ASE_MT);
8371 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8372 register_name = "VPEControl";
8373 break;
8374 case CP0_REG01__VPECONF0:
8375 CP0_CHECK(ctx->insn_flags & ASE_MT);
8376 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8377 register_name = "VPEConf0";
8378 break;
8379 case CP0_REG01__VPECONF1:
8380 CP0_CHECK(ctx->insn_flags & ASE_MT);
8381 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8382 register_name = "VPEConf1";
8383 break;
8384 case CP0_REG01__YQMASK:
8385 CP0_CHECK(ctx->insn_flags & ASE_MT);
8386 tcg_gen_ld_tl(arg, cpu_env,
8387 offsetof(CPUMIPSState, CP0_YQMask));
8388 register_name = "YQMask";
8389 break;
8390 case CP0_REG01__VPESCHEDULE:
8391 CP0_CHECK(ctx->insn_flags & ASE_MT);
8392 tcg_gen_ld_tl(arg, cpu_env,
8393 offsetof(CPUMIPSState, CP0_VPESchedule));
8394 register_name = "VPESchedule";
8395 break;
8396 case CP0_REG01__VPESCHEFBACK:
8397 CP0_CHECK(ctx->insn_flags & ASE_MT);
8398 tcg_gen_ld_tl(arg, cpu_env,
8399 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8400 register_name = "VPEScheFBack";
8401 break;
8402 case CP0_REG01__VPEOPT:
8403 CP0_CHECK(ctx->insn_flags & ASE_MT);
8404 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8405 register_name = "VPEOpt";
8406 break;
8407 default:
8408 goto cp0_unimplemented;
8410 break;
8411 case CP0_REGISTER_02:
8412 switch (sel) {
8413 case CP0_REG02__ENTRYLO0:
8414 tcg_gen_ld_tl(arg, cpu_env,
8415 offsetof(CPUMIPSState, CP0_EntryLo0));
8416 register_name = "EntryLo0";
8417 break;
8418 case CP0_REG02__TCSTATUS:
8419 CP0_CHECK(ctx->insn_flags & ASE_MT);
8420 gen_helper_mfc0_tcstatus(arg, cpu_env);
8421 register_name = "TCStatus";
8422 break;
8423 case CP0_REG02__TCBIND:
8424 CP0_CHECK(ctx->insn_flags & ASE_MT);
8425 gen_helper_mfc0_tcbind(arg, cpu_env);
8426 register_name = "TCBind";
8427 break;
8428 case CP0_REG02__TCRESTART:
8429 CP0_CHECK(ctx->insn_flags & ASE_MT);
8430 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8431 register_name = "TCRestart";
8432 break;
8433 case CP0_REG02__TCHALT:
8434 CP0_CHECK(ctx->insn_flags & ASE_MT);
8435 gen_helper_dmfc0_tchalt(arg, cpu_env);
8436 register_name = "TCHalt";
8437 break;
8438 case CP0_REG02__TCCONTEXT:
8439 CP0_CHECK(ctx->insn_flags & ASE_MT);
8440 gen_helper_dmfc0_tccontext(arg, cpu_env);
8441 register_name = "TCContext";
8442 break;
8443 case CP0_REG02__TCSCHEDULE:
8444 CP0_CHECK(ctx->insn_flags & ASE_MT);
8445 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8446 register_name = "TCSchedule";
8447 break;
8448 case CP0_REG02__TCSCHEFBACK:
8449 CP0_CHECK(ctx->insn_flags & ASE_MT);
8450 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8451 register_name = "TCScheFBack";
8452 break;
8453 default:
8454 goto cp0_unimplemented;
8456 break;
8457 case CP0_REGISTER_03:
8458 switch (sel) {
8459 case CP0_REG03__ENTRYLO1:
8460 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8461 register_name = "EntryLo1";
8462 break;
8463 case CP0_REG03__GLOBALNUM:
8464 CP0_CHECK(ctx->vp);
8465 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8466 register_name = "GlobalNumber";
8467 break;
8468 default:
8469 goto cp0_unimplemented;
8471 break;
8472 case CP0_REGISTER_04:
8473 switch (sel) {
8474 case CP0_REG04__CONTEXT:
8475 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8476 register_name = "Context";
8477 break;
8478 case CP0_REG04__CONTEXTCONFIG:
8479 /* SmartMIPS ASE */
8480 /* gen_helper_dmfc0_contextconfig(arg); */
8481 register_name = "ContextConfig";
8482 goto cp0_unimplemented;
8483 case CP0_REG04__USERLOCAL:
8484 CP0_CHECK(ctx->ulri);
8485 tcg_gen_ld_tl(arg, cpu_env,
8486 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8487 register_name = "UserLocal";
8488 break;
8489 case CP0_REG04__MMID:
8490 CP0_CHECK(ctx->mi);
8491 gen_helper_mtc0_memorymapid(cpu_env, arg);
8492 register_name = "MMID";
8493 break;
8494 default:
8495 goto cp0_unimplemented;
8497 break;
8498 case CP0_REGISTER_05:
8499 switch (sel) {
8500 case CP0_REG05__PAGEMASK:
8501 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8502 register_name = "PageMask";
8503 break;
8504 case CP0_REG05__PAGEGRAIN:
8505 check_insn(ctx, ISA_MIPS_R2);
8506 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8507 register_name = "PageGrain";
8508 break;
8509 case CP0_REG05__SEGCTL0:
8510 CP0_CHECK(ctx->sc);
8511 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8512 register_name = "SegCtl0";
8513 break;
8514 case CP0_REG05__SEGCTL1:
8515 CP0_CHECK(ctx->sc);
8516 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8517 register_name = "SegCtl1";
8518 break;
8519 case CP0_REG05__SEGCTL2:
8520 CP0_CHECK(ctx->sc);
8521 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8522 register_name = "SegCtl2";
8523 break;
8524 case CP0_REG05__PWBASE:
8525 check_pw(ctx);
8526 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8527 register_name = "PWBase";
8528 break;
8529 case CP0_REG05__PWFIELD:
8530 check_pw(ctx);
8531 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8532 register_name = "PWField";
8533 break;
8534 case CP0_REG05__PWSIZE:
8535 check_pw(ctx);
8536 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8537 register_name = "PWSize";
8538 break;
8539 default:
8540 goto cp0_unimplemented;
8542 break;
8543 case CP0_REGISTER_06:
8544 switch (sel) {
8545 case CP0_REG06__WIRED:
8546 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8547 register_name = "Wired";
8548 break;
8549 case CP0_REG06__SRSCONF0:
8550 check_insn(ctx, ISA_MIPS_R2);
8551 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8552 register_name = "SRSConf0";
8553 break;
8554 case CP0_REG06__SRSCONF1:
8555 check_insn(ctx, ISA_MIPS_R2);
8556 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8557 register_name = "SRSConf1";
8558 break;
8559 case CP0_REG06__SRSCONF2:
8560 check_insn(ctx, ISA_MIPS_R2);
8561 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8562 register_name = "SRSConf2";
8563 break;
8564 case CP0_REG06__SRSCONF3:
8565 check_insn(ctx, ISA_MIPS_R2);
8566 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8567 register_name = "SRSConf3";
8568 break;
8569 case CP0_REG06__SRSCONF4:
8570 check_insn(ctx, ISA_MIPS_R2);
8571 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8572 register_name = "SRSConf4";
8573 break;
8574 case CP0_REG06__PWCTL:
8575 check_pw(ctx);
8576 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8577 register_name = "PWCtl";
8578 break;
8579 default:
8580 goto cp0_unimplemented;
8582 break;
8583 case CP0_REGISTER_07:
8584 switch (sel) {
8585 case CP0_REG07__HWRENA:
8586 check_insn(ctx, ISA_MIPS_R2);
8587 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8588 register_name = "HWREna";
8589 break;
8590 default:
8591 goto cp0_unimplemented;
8593 break;
8594 case CP0_REGISTER_08:
8595 switch (sel) {
8596 case CP0_REG08__BADVADDR:
8597 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8598 register_name = "BadVAddr";
8599 break;
8600 case CP0_REG08__BADINSTR:
8601 CP0_CHECK(ctx->bi);
8602 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8603 register_name = "BadInstr";
8604 break;
8605 case CP0_REG08__BADINSTRP:
8606 CP0_CHECK(ctx->bp);
8607 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8608 register_name = "BadInstrP";
8609 break;
8610 case CP0_REG08__BADINSTRX:
8611 CP0_CHECK(ctx->bi);
8612 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8613 tcg_gen_andi_tl(arg, arg, ~0xffff);
8614 register_name = "BadInstrX";
8615 break;
8616 default:
8617 goto cp0_unimplemented;
8619 break;
8620 case CP0_REGISTER_09:
8621 switch (sel) {
8622 case CP0_REG09__COUNT:
8623 /* Mark as an IO operation because we read the time. */
8624 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8625 gen_io_start();
8627 gen_helper_mfc0_count(arg, cpu_env);
8629 * Break the TB to be able to take timer interrupts immediately
8630 * after reading count. DISAS_STOP isn't sufficient, we need to
8631 * ensure we break completely out of translated code.
8633 gen_save_pc(ctx->base.pc_next + 4);
8634 ctx->base.is_jmp = DISAS_EXIT;
8635 register_name = "Count";
8636 break;
8637 case CP0_REG09__SAARI:
8638 CP0_CHECK(ctx->saar);
8639 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8640 register_name = "SAARI";
8641 break;
8642 case CP0_REG09__SAAR:
8643 CP0_CHECK(ctx->saar);
8644 gen_helper_dmfc0_saar(arg, cpu_env);
8645 register_name = "SAAR";
8646 break;
8647 default:
8648 goto cp0_unimplemented;
8650 break;
8651 case CP0_REGISTER_10:
8652 switch (sel) {
8653 case CP0_REG10__ENTRYHI:
8654 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8655 register_name = "EntryHi";
8656 break;
8657 default:
8658 goto cp0_unimplemented;
8660 break;
8661 case CP0_REGISTER_11:
8662 switch (sel) {
8663 case CP0_REG11__COMPARE:
8664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8665 register_name = "Compare";
8666 break;
8667 /* 6,7 are implementation dependent */
8668 default:
8669 goto cp0_unimplemented;
8671 break;
8672 case CP0_REGISTER_12:
8673 switch (sel) {
8674 case CP0_REG12__STATUS:
8675 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8676 register_name = "Status";
8677 break;
8678 case CP0_REG12__INTCTL:
8679 check_insn(ctx, ISA_MIPS_R2);
8680 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8681 register_name = "IntCtl";
8682 break;
8683 case CP0_REG12__SRSCTL:
8684 check_insn(ctx, ISA_MIPS_R2);
8685 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8686 register_name = "SRSCtl";
8687 break;
8688 case CP0_REG12__SRSMAP:
8689 check_insn(ctx, ISA_MIPS_R2);
8690 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8691 register_name = "SRSMap";
8692 break;
8693 default:
8694 goto cp0_unimplemented;
8696 break;
8697 case CP0_REGISTER_13:
8698 switch (sel) {
8699 case CP0_REG13__CAUSE:
8700 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8701 register_name = "Cause";
8702 break;
8703 default:
8704 goto cp0_unimplemented;
8706 break;
8707 case CP0_REGISTER_14:
8708 switch (sel) {
8709 case CP0_REG14__EPC:
8710 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8711 register_name = "EPC";
8712 break;
8713 default:
8714 goto cp0_unimplemented;
8716 break;
8717 case CP0_REGISTER_15:
8718 switch (sel) {
8719 case CP0_REG15__PRID:
8720 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8721 register_name = "PRid";
8722 break;
8723 case CP0_REG15__EBASE:
8724 check_insn(ctx, ISA_MIPS_R2);
8725 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8726 register_name = "EBase";
8727 break;
8728 case CP0_REG15__CMGCRBASE:
8729 check_insn(ctx, ISA_MIPS_R2);
8730 CP0_CHECK(ctx->cmgcr);
8731 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8732 register_name = "CMGCRBase";
8733 break;
8734 default:
8735 goto cp0_unimplemented;
8737 break;
8738 case CP0_REGISTER_16:
8739 switch (sel) {
8740 case CP0_REG16__CONFIG:
8741 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8742 register_name = "Config";
8743 break;
8744 case CP0_REG16__CONFIG1:
8745 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8746 register_name = "Config1";
8747 break;
8748 case CP0_REG16__CONFIG2:
8749 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8750 register_name = "Config2";
8751 break;
8752 case CP0_REG16__CONFIG3:
8753 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8754 register_name = "Config3";
8755 break;
8756 case CP0_REG16__CONFIG4:
8757 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8758 register_name = "Config4";
8759 break;
8760 case CP0_REG16__CONFIG5:
8761 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8762 register_name = "Config5";
8763 break;
8764 /* 6,7 are implementation dependent */
8765 case CP0_REG16__CONFIG6:
8766 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8767 register_name = "Config6";
8768 break;
8769 case CP0_REG16__CONFIG7:
8770 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8771 register_name = "Config7";
8772 break;
8773 default:
8774 goto cp0_unimplemented;
8776 break;
8777 case CP0_REGISTER_17:
8778 switch (sel) {
8779 case CP0_REG17__LLADDR:
8780 gen_helper_dmfc0_lladdr(arg, cpu_env);
8781 register_name = "LLAddr";
8782 break;
8783 case CP0_REG17__MAAR:
8784 CP0_CHECK(ctx->mrp);
8785 gen_helper_dmfc0_maar(arg, cpu_env);
8786 register_name = "MAAR";
8787 break;
8788 case CP0_REG17__MAARI:
8789 CP0_CHECK(ctx->mrp);
8790 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8791 register_name = "MAARI";
8792 break;
8793 default:
8794 goto cp0_unimplemented;
8796 break;
8797 case CP0_REGISTER_18:
8798 switch (sel) {
8799 case CP0_REG18__WATCHLO0:
8800 case CP0_REG18__WATCHLO1:
8801 case CP0_REG18__WATCHLO2:
8802 case CP0_REG18__WATCHLO3:
8803 case CP0_REG18__WATCHLO4:
8804 case CP0_REG18__WATCHLO5:
8805 case CP0_REG18__WATCHLO6:
8806 case CP0_REG18__WATCHLO7:
8807 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8808 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8809 register_name = "WatchLo";
8810 break;
8811 default:
8812 goto cp0_unimplemented;
8814 break;
8815 case CP0_REGISTER_19:
8816 switch (sel) {
8817 case CP0_REG19__WATCHHI0:
8818 case CP0_REG19__WATCHHI1:
8819 case CP0_REG19__WATCHHI2:
8820 case CP0_REG19__WATCHHI3:
8821 case CP0_REG19__WATCHHI4:
8822 case CP0_REG19__WATCHHI5:
8823 case CP0_REG19__WATCHHI6:
8824 case CP0_REG19__WATCHHI7:
8825 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8826 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
8827 register_name = "WatchHi";
8828 break;
8829 default:
8830 goto cp0_unimplemented;
8832 break;
8833 case CP0_REGISTER_20:
8834 switch (sel) {
8835 case CP0_REG20__XCONTEXT:
8836 check_insn(ctx, ISA_MIPS3);
8837 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8838 register_name = "XContext";
8839 break;
8840 default:
8841 goto cp0_unimplemented;
8843 break;
8844 case CP0_REGISTER_21:
8845 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8846 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8847 switch (sel) {
8848 case 0:
8849 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8850 register_name = "Framemask";
8851 break;
8852 default:
8853 goto cp0_unimplemented;
8855 break;
8856 case CP0_REGISTER_22:
8857 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8858 register_name = "'Diagnostic"; /* implementation dependent */
8859 break;
8860 case CP0_REGISTER_23:
8861 switch (sel) {
8862 case CP0_REG23__DEBUG:
8863 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8864 register_name = "Debug";
8865 break;
8866 case CP0_REG23__TRACECONTROL:
8867 /* PDtrace support */
8868 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
8869 register_name = "TraceControl";
8870 goto cp0_unimplemented;
8871 case CP0_REG23__TRACECONTROL2:
8872 /* PDtrace support */
8873 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
8874 register_name = "TraceControl2";
8875 goto cp0_unimplemented;
8876 case CP0_REG23__USERTRACEDATA1:
8877 /* PDtrace support */
8878 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
8879 register_name = "UserTraceData1";
8880 goto cp0_unimplemented;
8881 case CP0_REG23__TRACEIBPC:
8882 /* PDtrace support */
8883 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
8884 register_name = "TraceIBPC";
8885 goto cp0_unimplemented;
8886 case CP0_REG23__TRACEDBPC:
8887 /* PDtrace support */
8888 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
8889 register_name = "TraceDBPC";
8890 goto cp0_unimplemented;
8891 default:
8892 goto cp0_unimplemented;
8894 break;
8895 case CP0_REGISTER_24:
8896 switch (sel) {
8897 case CP0_REG24__DEPC:
8898 /* EJTAG support */
8899 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8900 register_name = "DEPC";
8901 break;
8902 default:
8903 goto cp0_unimplemented;
8905 break;
8906 case CP0_REGISTER_25:
8907 switch (sel) {
8908 case CP0_REG25__PERFCTL0:
8909 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8910 register_name = "Performance0";
8911 break;
8912 case CP0_REG25__PERFCNT0:
8913 /* gen_helper_dmfc0_performance1(arg); */
8914 register_name = "Performance1";
8915 goto cp0_unimplemented;
8916 case CP0_REG25__PERFCTL1:
8917 /* gen_helper_dmfc0_performance2(arg); */
8918 register_name = "Performance2";
8919 goto cp0_unimplemented;
8920 case CP0_REG25__PERFCNT1:
8921 /* gen_helper_dmfc0_performance3(arg); */
8922 register_name = "Performance3";
8923 goto cp0_unimplemented;
8924 case CP0_REG25__PERFCTL2:
8925 /* gen_helper_dmfc0_performance4(arg); */
8926 register_name = "Performance4";
8927 goto cp0_unimplemented;
8928 case CP0_REG25__PERFCNT2:
8929 /* gen_helper_dmfc0_performance5(arg); */
8930 register_name = "Performance5";
8931 goto cp0_unimplemented;
8932 case CP0_REG25__PERFCTL3:
8933 /* gen_helper_dmfc0_performance6(arg); */
8934 register_name = "Performance6";
8935 goto cp0_unimplemented;
8936 case CP0_REG25__PERFCNT3:
8937 /* gen_helper_dmfc0_performance7(arg); */
8938 register_name = "Performance7";
8939 goto cp0_unimplemented;
8940 default:
8941 goto cp0_unimplemented;
8943 break;
8944 case CP0_REGISTER_26:
8945 switch (sel) {
8946 case CP0_REG26__ERRCTL:
8947 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8948 register_name = "ErrCtl";
8949 break;
8950 default:
8951 goto cp0_unimplemented;
8953 break;
8954 case CP0_REGISTER_27:
8955 switch (sel) {
8956 /* ignored */
8957 case CP0_REG27__CACHERR:
8958 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8959 register_name = "CacheErr";
8960 break;
8961 default:
8962 goto cp0_unimplemented;
8964 break;
8965 case CP0_REGISTER_28:
8966 switch (sel) {
8967 case CP0_REG28__TAGLO:
8968 case CP0_REG28__TAGLO1:
8969 case CP0_REG28__TAGLO2:
8970 case CP0_REG28__TAGLO3:
8971 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8972 register_name = "TagLo";
8973 break;
8974 case CP0_REG28__DATALO:
8975 case CP0_REG28__DATALO1:
8976 case CP0_REG28__DATALO2:
8977 case CP0_REG28__DATALO3:
8978 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8979 register_name = "DataLo";
8980 break;
8981 default:
8982 goto cp0_unimplemented;
8984 break;
8985 case CP0_REGISTER_29:
8986 switch (sel) {
8987 case CP0_REG29__TAGHI:
8988 case CP0_REG29__TAGHI1:
8989 case CP0_REG29__TAGHI2:
8990 case CP0_REG29__TAGHI3:
8991 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8992 register_name = "TagHi";
8993 break;
8994 case CP0_REG29__DATAHI:
8995 case CP0_REG29__DATAHI1:
8996 case CP0_REG29__DATAHI2:
8997 case CP0_REG29__DATAHI3:
8998 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8999 register_name = "DataHi";
9000 break;
9001 default:
9002 goto cp0_unimplemented;
9004 break;
9005 case CP0_REGISTER_30:
9006 switch (sel) {
9007 case CP0_REG30__ERROREPC:
9008 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9009 register_name = "ErrorEPC";
9010 break;
9011 default:
9012 goto cp0_unimplemented;
9014 break;
9015 case CP0_REGISTER_31:
9016 switch (sel) {
9017 case CP0_REG31__DESAVE:
9018 /* EJTAG support */
9019 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9020 register_name = "DESAVE";
9021 break;
9022 case CP0_REG31__KSCRATCH1:
9023 case CP0_REG31__KSCRATCH2:
9024 case CP0_REG31__KSCRATCH3:
9025 case CP0_REG31__KSCRATCH4:
9026 case CP0_REG31__KSCRATCH5:
9027 case CP0_REG31__KSCRATCH6:
9028 CP0_CHECK(ctx->kscrexist & (1 << sel));
9029 tcg_gen_ld_tl(arg, cpu_env,
9030 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9031 register_name = "KScratch";
9032 break;
9033 default:
9034 goto cp0_unimplemented;
9036 break;
9037 default:
9038 goto cp0_unimplemented;
9040 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9041 return;
9043 cp0_unimplemented:
9044 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9045 register_name, reg, sel);
9046 gen_mfc0_unimplemented(ctx, arg);
9049 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9051 const char *register_name = "invalid";
9053 if (sel != 0) {
9054 check_insn(ctx, ISA_MIPS_R1);
9057 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9058 gen_io_start();
9061 switch (reg) {
9062 case CP0_REGISTER_00:
9063 switch (sel) {
9064 case CP0_REG00__INDEX:
9065 gen_helper_mtc0_index(cpu_env, arg);
9066 register_name = "Index";
9067 break;
9068 case CP0_REG00__MVPCONTROL:
9069 CP0_CHECK(ctx->insn_flags & ASE_MT);
9070 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9071 register_name = "MVPControl";
9072 break;
9073 case CP0_REG00__MVPCONF0:
9074 CP0_CHECK(ctx->insn_flags & ASE_MT);
9075 /* ignored */
9076 register_name = "MVPConf0";
9077 break;
9078 case CP0_REG00__MVPCONF1:
9079 CP0_CHECK(ctx->insn_flags & ASE_MT);
9080 /* ignored */
9081 register_name = "MVPConf1";
9082 break;
9083 case CP0_REG00__VPCONTROL:
9084 CP0_CHECK(ctx->vp);
9085 /* ignored */
9086 register_name = "VPControl";
9087 break;
9088 default:
9089 goto cp0_unimplemented;
9091 break;
9092 case CP0_REGISTER_01:
9093 switch (sel) {
9094 case CP0_REG01__RANDOM:
9095 /* ignored */
9096 register_name = "Random";
9097 break;
9098 case CP0_REG01__VPECONTROL:
9099 CP0_CHECK(ctx->insn_flags & ASE_MT);
9100 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9101 register_name = "VPEControl";
9102 break;
9103 case CP0_REG01__VPECONF0:
9104 CP0_CHECK(ctx->insn_flags & ASE_MT);
9105 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9106 register_name = "VPEConf0";
9107 break;
9108 case CP0_REG01__VPECONF1:
9109 CP0_CHECK(ctx->insn_flags & ASE_MT);
9110 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9111 register_name = "VPEConf1";
9112 break;
9113 case CP0_REG01__YQMASK:
9114 CP0_CHECK(ctx->insn_flags & ASE_MT);
9115 gen_helper_mtc0_yqmask(cpu_env, arg);
9116 register_name = "YQMask";
9117 break;
9118 case CP0_REG01__VPESCHEDULE:
9119 CP0_CHECK(ctx->insn_flags & ASE_MT);
9120 tcg_gen_st_tl(arg, cpu_env,
9121 offsetof(CPUMIPSState, CP0_VPESchedule));
9122 register_name = "VPESchedule";
9123 break;
9124 case CP0_REG01__VPESCHEFBACK:
9125 CP0_CHECK(ctx->insn_flags & ASE_MT);
9126 tcg_gen_st_tl(arg, cpu_env,
9127 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9128 register_name = "VPEScheFBack";
9129 break;
9130 case CP0_REG01__VPEOPT:
9131 CP0_CHECK(ctx->insn_flags & ASE_MT);
9132 gen_helper_mtc0_vpeopt(cpu_env, arg);
9133 register_name = "VPEOpt";
9134 break;
9135 default:
9136 goto cp0_unimplemented;
9138 break;
9139 case CP0_REGISTER_02:
9140 switch (sel) {
9141 case CP0_REG02__ENTRYLO0:
9142 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9143 register_name = "EntryLo0";
9144 break;
9145 case CP0_REG02__TCSTATUS:
9146 CP0_CHECK(ctx->insn_flags & ASE_MT);
9147 gen_helper_mtc0_tcstatus(cpu_env, arg);
9148 register_name = "TCStatus";
9149 break;
9150 case CP0_REG02__TCBIND:
9151 CP0_CHECK(ctx->insn_flags & ASE_MT);
9152 gen_helper_mtc0_tcbind(cpu_env, arg);
9153 register_name = "TCBind";
9154 break;
9155 case CP0_REG02__TCRESTART:
9156 CP0_CHECK(ctx->insn_flags & ASE_MT);
9157 gen_helper_mtc0_tcrestart(cpu_env, arg);
9158 register_name = "TCRestart";
9159 break;
9160 case CP0_REG02__TCHALT:
9161 CP0_CHECK(ctx->insn_flags & ASE_MT);
9162 gen_helper_mtc0_tchalt(cpu_env, arg);
9163 register_name = "TCHalt";
9164 break;
9165 case CP0_REG02__TCCONTEXT:
9166 CP0_CHECK(ctx->insn_flags & ASE_MT);
9167 gen_helper_mtc0_tccontext(cpu_env, arg);
9168 register_name = "TCContext";
9169 break;
9170 case CP0_REG02__TCSCHEDULE:
9171 CP0_CHECK(ctx->insn_flags & ASE_MT);
9172 gen_helper_mtc0_tcschedule(cpu_env, arg);
9173 register_name = "TCSchedule";
9174 break;
9175 case CP0_REG02__TCSCHEFBACK:
9176 CP0_CHECK(ctx->insn_flags & ASE_MT);
9177 gen_helper_mtc0_tcschefback(cpu_env, arg);
9178 register_name = "TCScheFBack";
9179 break;
9180 default:
9181 goto cp0_unimplemented;
9183 break;
9184 case CP0_REGISTER_03:
9185 switch (sel) {
9186 case CP0_REG03__ENTRYLO1:
9187 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9188 register_name = "EntryLo1";
9189 break;
9190 case CP0_REG03__GLOBALNUM:
9191 CP0_CHECK(ctx->vp);
9192 /* ignored */
9193 register_name = "GlobalNumber";
9194 break;
9195 default:
9196 goto cp0_unimplemented;
9198 break;
9199 case CP0_REGISTER_04:
9200 switch (sel) {
9201 case CP0_REG04__CONTEXT:
9202 gen_helper_mtc0_context(cpu_env, arg);
9203 register_name = "Context";
9204 break;
9205 case CP0_REG04__CONTEXTCONFIG:
9206 /* SmartMIPS ASE */
9207 /* gen_helper_dmtc0_contextconfig(arg); */
9208 register_name = "ContextConfig";
9209 goto cp0_unimplemented;
9210 case CP0_REG04__USERLOCAL:
9211 CP0_CHECK(ctx->ulri);
9212 tcg_gen_st_tl(arg, cpu_env,
9213 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9214 register_name = "UserLocal";
9215 break;
9216 case CP0_REG04__MMID:
9217 CP0_CHECK(ctx->mi);
9218 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
9219 register_name = "MMID";
9220 break;
9221 default:
9222 goto cp0_unimplemented;
9224 break;
9225 case CP0_REGISTER_05:
9226 switch (sel) {
9227 case CP0_REG05__PAGEMASK:
9228 gen_helper_mtc0_pagemask(cpu_env, arg);
9229 register_name = "PageMask";
9230 break;
9231 case CP0_REG05__PAGEGRAIN:
9232 check_insn(ctx, ISA_MIPS_R2);
9233 gen_helper_mtc0_pagegrain(cpu_env, arg);
9234 register_name = "PageGrain";
9235 break;
9236 case CP0_REG05__SEGCTL0:
9237 CP0_CHECK(ctx->sc);
9238 gen_helper_mtc0_segctl0(cpu_env, arg);
9239 register_name = "SegCtl0";
9240 break;
9241 case CP0_REG05__SEGCTL1:
9242 CP0_CHECK(ctx->sc);
9243 gen_helper_mtc0_segctl1(cpu_env, arg);
9244 register_name = "SegCtl1";
9245 break;
9246 case CP0_REG05__SEGCTL2:
9247 CP0_CHECK(ctx->sc);
9248 gen_helper_mtc0_segctl2(cpu_env, arg);
9249 register_name = "SegCtl2";
9250 break;
9251 case CP0_REG05__PWBASE:
9252 check_pw(ctx);
9253 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9254 register_name = "PWBase";
9255 break;
9256 case CP0_REG05__PWFIELD:
9257 check_pw(ctx);
9258 gen_helper_mtc0_pwfield(cpu_env, arg);
9259 register_name = "PWField";
9260 break;
9261 case CP0_REG05__PWSIZE:
9262 check_pw(ctx);
9263 gen_helper_mtc0_pwsize(cpu_env, arg);
9264 register_name = "PWSize";
9265 break;
9266 default:
9267 goto cp0_unimplemented;
9269 break;
9270 case CP0_REGISTER_06:
9271 switch (sel) {
9272 case CP0_REG06__WIRED:
9273 gen_helper_mtc0_wired(cpu_env, arg);
9274 register_name = "Wired";
9275 break;
9276 case CP0_REG06__SRSCONF0:
9277 check_insn(ctx, ISA_MIPS_R2);
9278 gen_helper_mtc0_srsconf0(cpu_env, arg);
9279 register_name = "SRSConf0";
9280 break;
9281 case CP0_REG06__SRSCONF1:
9282 check_insn(ctx, ISA_MIPS_R2);
9283 gen_helper_mtc0_srsconf1(cpu_env, arg);
9284 register_name = "SRSConf1";
9285 break;
9286 case CP0_REG06__SRSCONF2:
9287 check_insn(ctx, ISA_MIPS_R2);
9288 gen_helper_mtc0_srsconf2(cpu_env, arg);
9289 register_name = "SRSConf2";
9290 break;
9291 case CP0_REG06__SRSCONF3:
9292 check_insn(ctx, ISA_MIPS_R2);
9293 gen_helper_mtc0_srsconf3(cpu_env, arg);
9294 register_name = "SRSConf3";
9295 break;
9296 case CP0_REG06__SRSCONF4:
9297 check_insn(ctx, ISA_MIPS_R2);
9298 gen_helper_mtc0_srsconf4(cpu_env, arg);
9299 register_name = "SRSConf4";
9300 break;
9301 case CP0_REG06__PWCTL:
9302 check_pw(ctx);
9303 gen_helper_mtc0_pwctl(cpu_env, arg);
9304 register_name = "PWCtl";
9305 break;
9306 default:
9307 goto cp0_unimplemented;
9309 break;
9310 case CP0_REGISTER_07:
9311 switch (sel) {
9312 case CP0_REG07__HWRENA:
9313 check_insn(ctx, ISA_MIPS_R2);
9314 gen_helper_mtc0_hwrena(cpu_env, arg);
9315 ctx->base.is_jmp = DISAS_STOP;
9316 register_name = "HWREna";
9317 break;
9318 default:
9319 goto cp0_unimplemented;
9321 break;
9322 case CP0_REGISTER_08:
9323 switch (sel) {
9324 case CP0_REG08__BADVADDR:
9325 /* ignored */
9326 register_name = "BadVAddr";
9327 break;
9328 case CP0_REG08__BADINSTR:
9329 /* ignored */
9330 register_name = "BadInstr";
9331 break;
9332 case CP0_REG08__BADINSTRP:
9333 /* ignored */
9334 register_name = "BadInstrP";
9335 break;
9336 case CP0_REG08__BADINSTRX:
9337 /* ignored */
9338 register_name = "BadInstrX";
9339 break;
9340 default:
9341 goto cp0_unimplemented;
9343 break;
9344 case CP0_REGISTER_09:
9345 switch (sel) {
9346 case CP0_REG09__COUNT:
9347 gen_helper_mtc0_count(cpu_env, arg);
9348 register_name = "Count";
9349 break;
9350 case CP0_REG09__SAARI:
9351 CP0_CHECK(ctx->saar);
9352 gen_helper_mtc0_saari(cpu_env, arg);
9353 register_name = "SAARI";
9354 break;
9355 case CP0_REG09__SAAR:
9356 CP0_CHECK(ctx->saar);
9357 gen_helper_mtc0_saar(cpu_env, arg);
9358 register_name = "SAAR";
9359 break;
9360 default:
9361 goto cp0_unimplemented;
9363 /* Stop translation as we may have switched the execution mode */
9364 ctx->base.is_jmp = DISAS_STOP;
9365 break;
9366 case CP0_REGISTER_10:
9367 switch (sel) {
9368 case CP0_REG10__ENTRYHI:
9369 gen_helper_mtc0_entryhi(cpu_env, arg);
9370 register_name = "EntryHi";
9371 break;
9372 default:
9373 goto cp0_unimplemented;
9375 break;
9376 case CP0_REGISTER_11:
9377 switch (sel) {
9378 case CP0_REG11__COMPARE:
9379 gen_helper_mtc0_compare(cpu_env, arg);
9380 register_name = "Compare";
9381 break;
9382 /* 6,7 are implementation dependent */
9383 default:
9384 goto cp0_unimplemented;
9386 /* Stop translation as we may have switched the execution mode */
9387 ctx->base.is_jmp = DISAS_STOP;
9388 break;
9389 case CP0_REGISTER_12:
9390 switch (sel) {
9391 case CP0_REG12__STATUS:
9392 save_cpu_state(ctx, 1);
9393 gen_helper_mtc0_status(cpu_env, arg);
9394 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9395 gen_save_pc(ctx->base.pc_next + 4);
9396 ctx->base.is_jmp = DISAS_EXIT;
9397 register_name = "Status";
9398 break;
9399 case CP0_REG12__INTCTL:
9400 check_insn(ctx, ISA_MIPS_R2);
9401 gen_helper_mtc0_intctl(cpu_env, arg);
9402 /* Stop translation as we may have switched the execution mode */
9403 ctx->base.is_jmp = DISAS_STOP;
9404 register_name = "IntCtl";
9405 break;
9406 case CP0_REG12__SRSCTL:
9407 check_insn(ctx, ISA_MIPS_R2);
9408 gen_helper_mtc0_srsctl(cpu_env, arg);
9409 /* Stop translation as we may have switched the execution mode */
9410 ctx->base.is_jmp = DISAS_STOP;
9411 register_name = "SRSCtl";
9412 break;
9413 case CP0_REG12__SRSMAP:
9414 check_insn(ctx, ISA_MIPS_R2);
9415 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9416 /* Stop translation as we may have switched the execution mode */
9417 ctx->base.is_jmp = DISAS_STOP;
9418 register_name = "SRSMap";
9419 break;
9420 default:
9421 goto cp0_unimplemented;
9423 break;
9424 case CP0_REGISTER_13:
9425 switch (sel) {
9426 case CP0_REG13__CAUSE:
9427 save_cpu_state(ctx, 1);
9428 gen_helper_mtc0_cause(cpu_env, arg);
9430 * Stop translation as we may have triggered an interrupt.
9431 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9432 * translated code to check for pending interrupts.
9434 gen_save_pc(ctx->base.pc_next + 4);
9435 ctx->base.is_jmp = DISAS_EXIT;
9436 register_name = "Cause";
9437 break;
9438 default:
9439 goto cp0_unimplemented;
9441 break;
9442 case CP0_REGISTER_14:
9443 switch (sel) {
9444 case CP0_REG14__EPC:
9445 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9446 register_name = "EPC";
9447 break;
9448 default:
9449 goto cp0_unimplemented;
9451 break;
9452 case CP0_REGISTER_15:
9453 switch (sel) {
9454 case CP0_REG15__PRID:
9455 /* ignored */
9456 register_name = "PRid";
9457 break;
9458 case CP0_REG15__EBASE:
9459 check_insn(ctx, ISA_MIPS_R2);
9460 gen_helper_mtc0_ebase(cpu_env, arg);
9461 register_name = "EBase";
9462 break;
9463 default:
9464 goto cp0_unimplemented;
9466 break;
9467 case CP0_REGISTER_16:
9468 switch (sel) {
9469 case CP0_REG16__CONFIG:
9470 gen_helper_mtc0_config0(cpu_env, arg);
9471 register_name = "Config";
9472 /* Stop translation as we may have switched the execution mode */
9473 ctx->base.is_jmp = DISAS_STOP;
9474 break;
9475 case CP0_REG16__CONFIG1:
9476 /* ignored, read only */
9477 register_name = "Config1";
9478 break;
9479 case CP0_REG16__CONFIG2:
9480 gen_helper_mtc0_config2(cpu_env, arg);
9481 register_name = "Config2";
9482 /* Stop translation as we may have switched the execution mode */
9483 ctx->base.is_jmp = DISAS_STOP;
9484 break;
9485 case CP0_REG16__CONFIG3:
9486 gen_helper_mtc0_config3(cpu_env, arg);
9487 register_name = "Config3";
9488 /* Stop translation as we may have switched the execution mode */
9489 ctx->base.is_jmp = DISAS_STOP;
9490 break;
9491 case CP0_REG16__CONFIG4:
9492 /* currently ignored */
9493 register_name = "Config4";
9494 break;
9495 case CP0_REG16__CONFIG5:
9496 gen_helper_mtc0_config5(cpu_env, arg);
9497 register_name = "Config5";
9498 /* Stop translation as we may have switched the execution mode */
9499 ctx->base.is_jmp = DISAS_STOP;
9500 break;
9501 /* 6,7 are implementation dependent */
9502 default:
9503 register_name = "Invalid config selector";
9504 goto cp0_unimplemented;
9506 break;
9507 case CP0_REGISTER_17:
9508 switch (sel) {
9509 case CP0_REG17__LLADDR:
9510 gen_helper_mtc0_lladdr(cpu_env, arg);
9511 register_name = "LLAddr";
9512 break;
9513 case CP0_REG17__MAAR:
9514 CP0_CHECK(ctx->mrp);
9515 gen_helper_mtc0_maar(cpu_env, arg);
9516 register_name = "MAAR";
9517 break;
9518 case CP0_REG17__MAARI:
9519 CP0_CHECK(ctx->mrp);
9520 gen_helper_mtc0_maari(cpu_env, arg);
9521 register_name = "MAARI";
9522 break;
9523 default:
9524 goto cp0_unimplemented;
9526 break;
9527 case CP0_REGISTER_18:
9528 switch (sel) {
9529 case CP0_REG18__WATCHLO0:
9530 case CP0_REG18__WATCHLO1:
9531 case CP0_REG18__WATCHLO2:
9532 case CP0_REG18__WATCHLO3:
9533 case CP0_REG18__WATCHLO4:
9534 case CP0_REG18__WATCHLO5:
9535 case CP0_REG18__WATCHLO6:
9536 case CP0_REG18__WATCHLO7:
9537 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9538 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9539 register_name = "WatchLo";
9540 break;
9541 default:
9542 goto cp0_unimplemented;
9544 break;
9545 case CP0_REGISTER_19:
9546 switch (sel) {
9547 case CP0_REG19__WATCHHI0:
9548 case CP0_REG19__WATCHHI1:
9549 case CP0_REG19__WATCHHI2:
9550 case CP0_REG19__WATCHHI3:
9551 case CP0_REG19__WATCHHI4:
9552 case CP0_REG19__WATCHHI5:
9553 case CP0_REG19__WATCHHI6:
9554 case CP0_REG19__WATCHHI7:
9555 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9556 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9557 register_name = "WatchHi";
9558 break;
9559 default:
9560 goto cp0_unimplemented;
9562 break;
9563 case CP0_REGISTER_20:
9564 switch (sel) {
9565 case CP0_REG20__XCONTEXT:
9566 check_insn(ctx, ISA_MIPS3);
9567 gen_helper_mtc0_xcontext(cpu_env, arg);
9568 register_name = "XContext";
9569 break;
9570 default:
9571 goto cp0_unimplemented;
9573 break;
9574 case CP0_REGISTER_21:
9575 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9576 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9577 switch (sel) {
9578 case 0:
9579 gen_helper_mtc0_framemask(cpu_env, arg);
9580 register_name = "Framemask";
9581 break;
9582 default:
9583 goto cp0_unimplemented;
9585 break;
9586 case CP0_REGISTER_22:
9587 /* ignored */
9588 register_name = "Diagnostic"; /* implementation dependent */
9589 break;
9590 case CP0_REGISTER_23:
9591 switch (sel) {
9592 case CP0_REG23__DEBUG:
9593 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9594 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9595 gen_save_pc(ctx->base.pc_next + 4);
9596 ctx->base.is_jmp = DISAS_EXIT;
9597 register_name = "Debug";
9598 break;
9599 case CP0_REG23__TRACECONTROL:
9600 /* PDtrace support */
9601 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
9602 /* Stop translation as we may have switched the execution mode */
9603 ctx->base.is_jmp = DISAS_STOP;
9604 register_name = "TraceControl";
9605 goto cp0_unimplemented;
9606 case CP0_REG23__TRACECONTROL2:
9607 /* PDtrace support */
9608 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
9609 /* Stop translation as we may have switched the execution mode */
9610 ctx->base.is_jmp = DISAS_STOP;
9611 register_name = "TraceControl2";
9612 goto cp0_unimplemented;
9613 case CP0_REG23__USERTRACEDATA1:
9614 /* PDtrace support */
9615 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
9616 /* Stop translation as we may have switched the execution mode */
9617 ctx->base.is_jmp = DISAS_STOP;
9618 register_name = "UserTraceData1";
9619 goto cp0_unimplemented;
9620 case CP0_REG23__TRACEIBPC:
9621 /* PDtrace support */
9622 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
9623 /* Stop translation as we may have switched the execution mode */
9624 ctx->base.is_jmp = DISAS_STOP;
9625 register_name = "TraceIBPC";
9626 goto cp0_unimplemented;
9627 case CP0_REG23__TRACEDBPC:
9628 /* PDtrace support */
9629 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
9630 /* Stop translation as we may have switched the execution mode */
9631 ctx->base.is_jmp = DISAS_STOP;
9632 register_name = "TraceDBPC";
9633 goto cp0_unimplemented;
9634 default:
9635 goto cp0_unimplemented;
9637 break;
9638 case CP0_REGISTER_24:
9639 switch (sel) {
9640 case CP0_REG24__DEPC:
9641 /* EJTAG support */
9642 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9643 register_name = "DEPC";
9644 break;
9645 default:
9646 goto cp0_unimplemented;
9648 break;
9649 case CP0_REGISTER_25:
9650 switch (sel) {
9651 case CP0_REG25__PERFCTL0:
9652 gen_helper_mtc0_performance0(cpu_env, arg);
9653 register_name = "Performance0";
9654 break;
9655 case CP0_REG25__PERFCNT0:
9656 /* gen_helper_mtc0_performance1(cpu_env, arg); */
9657 register_name = "Performance1";
9658 goto cp0_unimplemented;
9659 case CP0_REG25__PERFCTL1:
9660 /* gen_helper_mtc0_performance2(cpu_env, arg); */
9661 register_name = "Performance2";
9662 goto cp0_unimplemented;
9663 case CP0_REG25__PERFCNT1:
9664 /* gen_helper_mtc0_performance3(cpu_env, arg); */
9665 register_name = "Performance3";
9666 goto cp0_unimplemented;
9667 case CP0_REG25__PERFCTL2:
9668 /* gen_helper_mtc0_performance4(cpu_env, arg); */
9669 register_name = "Performance4";
9670 goto cp0_unimplemented;
9671 case CP0_REG25__PERFCNT2:
9672 /* gen_helper_mtc0_performance5(cpu_env, arg); */
9673 register_name = "Performance5";
9674 goto cp0_unimplemented;
9675 case CP0_REG25__PERFCTL3:
9676 /* gen_helper_mtc0_performance6(cpu_env, arg); */
9677 register_name = "Performance6";
9678 goto cp0_unimplemented;
9679 case CP0_REG25__PERFCNT3:
9680 /* gen_helper_mtc0_performance7(cpu_env, arg); */
9681 register_name = "Performance7";
9682 goto cp0_unimplemented;
9683 default:
9684 goto cp0_unimplemented;
9686 break;
9687 case CP0_REGISTER_26:
9688 switch (sel) {
9689 case CP0_REG26__ERRCTL:
9690 gen_helper_mtc0_errctl(cpu_env, arg);
9691 ctx->base.is_jmp = DISAS_STOP;
9692 register_name = "ErrCtl";
9693 break;
9694 default:
9695 goto cp0_unimplemented;
9697 break;
9698 case CP0_REGISTER_27:
9699 switch (sel) {
9700 case CP0_REG27__CACHERR:
9701 /* ignored */
9702 register_name = "CacheErr";
9703 break;
9704 default:
9705 goto cp0_unimplemented;
9707 break;
9708 case CP0_REGISTER_28:
9709 switch (sel) {
9710 case CP0_REG28__TAGLO:
9711 case CP0_REG28__TAGLO1:
9712 case CP0_REG28__TAGLO2:
9713 case CP0_REG28__TAGLO3:
9714 gen_helper_mtc0_taglo(cpu_env, arg);
9715 register_name = "TagLo";
9716 break;
9717 case CP0_REG28__DATALO:
9718 case CP0_REG28__DATALO1:
9719 case CP0_REG28__DATALO2:
9720 case CP0_REG28__DATALO3:
9721 gen_helper_mtc0_datalo(cpu_env, arg);
9722 register_name = "DataLo";
9723 break;
9724 default:
9725 goto cp0_unimplemented;
9727 break;
9728 case CP0_REGISTER_29:
9729 switch (sel) {
9730 case CP0_REG29__TAGHI:
9731 case CP0_REG29__TAGHI1:
9732 case CP0_REG29__TAGHI2:
9733 case CP0_REG29__TAGHI3:
9734 gen_helper_mtc0_taghi(cpu_env, arg);
9735 register_name = "TagHi";
9736 break;
9737 case CP0_REG29__DATAHI:
9738 case CP0_REG29__DATAHI1:
9739 case CP0_REG29__DATAHI2:
9740 case CP0_REG29__DATAHI3:
9741 gen_helper_mtc0_datahi(cpu_env, arg);
9742 register_name = "DataHi";
9743 break;
9744 default:
9745 register_name = "invalid sel";
9746 goto cp0_unimplemented;
9748 break;
9749 case CP0_REGISTER_30:
9750 switch (sel) {
9751 case CP0_REG30__ERROREPC:
9752 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9753 register_name = "ErrorEPC";
9754 break;
9755 default:
9756 goto cp0_unimplemented;
9758 break;
9759 case CP0_REGISTER_31:
9760 switch (sel) {
9761 case CP0_REG31__DESAVE:
9762 /* EJTAG support */
9763 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9764 register_name = "DESAVE";
9765 break;
9766 case CP0_REG31__KSCRATCH1:
9767 case CP0_REG31__KSCRATCH2:
9768 case CP0_REG31__KSCRATCH3:
9769 case CP0_REG31__KSCRATCH4:
9770 case CP0_REG31__KSCRATCH5:
9771 case CP0_REG31__KSCRATCH6:
9772 CP0_CHECK(ctx->kscrexist & (1 << sel));
9773 tcg_gen_st_tl(arg, cpu_env,
9774 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9775 register_name = "KScratch";
9776 break;
9777 default:
9778 goto cp0_unimplemented;
9780 break;
9781 default:
9782 goto cp0_unimplemented;
9784 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9786 /* For simplicity assume that all writes can cause interrupts. */
9787 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9789 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9790 * translated code to check for pending interrupts.
9792 gen_save_pc(ctx->base.pc_next + 4);
9793 ctx->base.is_jmp = DISAS_EXIT;
9795 return;
9797 cp0_unimplemented:
9798 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9799 register_name, reg, sel);
9801 #endif /* TARGET_MIPS64 */
9803 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9804 int u, int sel, int h)
9806 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9807 TCGv t0 = tcg_temp_local_new();
9809 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9810 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9811 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9812 tcg_gen_movi_tl(t0, -1);
9813 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9814 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9815 tcg_gen_movi_tl(t0, -1);
9816 } else if (u == 0) {
9817 switch (rt) {
9818 case 1:
9819 switch (sel) {
9820 case 1:
9821 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9822 break;
9823 case 2:
9824 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9825 break;
9826 default:
9827 goto die;
9828 break;
9830 break;
9831 case 2:
9832 switch (sel) {
9833 case 1:
9834 gen_helper_mftc0_tcstatus(t0, cpu_env);
9835 break;
9836 case 2:
9837 gen_helper_mftc0_tcbind(t0, cpu_env);
9838 break;
9839 case 3:
9840 gen_helper_mftc0_tcrestart(t0, cpu_env);
9841 break;
9842 case 4:
9843 gen_helper_mftc0_tchalt(t0, cpu_env);
9844 break;
9845 case 5:
9846 gen_helper_mftc0_tccontext(t0, cpu_env);
9847 break;
9848 case 6:
9849 gen_helper_mftc0_tcschedule(t0, cpu_env);
9850 break;
9851 case 7:
9852 gen_helper_mftc0_tcschefback(t0, cpu_env);
9853 break;
9854 default:
9855 gen_mfc0(ctx, t0, rt, sel);
9856 break;
9858 break;
9859 case 10:
9860 switch (sel) {
9861 case 0:
9862 gen_helper_mftc0_entryhi(t0, cpu_env);
9863 break;
9864 default:
9865 gen_mfc0(ctx, t0, rt, sel);
9866 break;
9868 break;
9869 case 12:
9870 switch (sel) {
9871 case 0:
9872 gen_helper_mftc0_status(t0, cpu_env);
9873 break;
9874 default:
9875 gen_mfc0(ctx, t0, rt, sel);
9876 break;
9878 break;
9879 case 13:
9880 switch (sel) {
9881 case 0:
9882 gen_helper_mftc0_cause(t0, cpu_env);
9883 break;
9884 default:
9885 goto die;
9886 break;
9888 break;
9889 case 14:
9890 switch (sel) {
9891 case 0:
9892 gen_helper_mftc0_epc(t0, cpu_env);
9893 break;
9894 default:
9895 goto die;
9896 break;
9898 break;
9899 case 15:
9900 switch (sel) {
9901 case 1:
9902 gen_helper_mftc0_ebase(t0, cpu_env);
9903 break;
9904 default:
9905 goto die;
9906 break;
9908 break;
9909 case 16:
9910 switch (sel) {
9911 case 0:
9912 case 1:
9913 case 2:
9914 case 3:
9915 case 4:
9916 case 5:
9917 case 6:
9918 case 7:
9919 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9920 break;
9921 default:
9922 goto die;
9923 break;
9925 break;
9926 case 23:
9927 switch (sel) {
9928 case 0:
9929 gen_helper_mftc0_debug(t0, cpu_env);
9930 break;
9931 default:
9932 gen_mfc0(ctx, t0, rt, sel);
9933 break;
9935 break;
9936 default:
9937 gen_mfc0(ctx, t0, rt, sel);
9939 } else {
9940 switch (sel) {
9941 /* GPR registers. */
9942 case 0:
9943 gen_helper_1e0i(mftgpr, t0, rt);
9944 break;
9945 /* Auxiliary CPU registers */
9946 case 1:
9947 switch (rt) {
9948 case 0:
9949 gen_helper_1e0i(mftlo, t0, 0);
9950 break;
9951 case 1:
9952 gen_helper_1e0i(mfthi, t0, 0);
9953 break;
9954 case 2:
9955 gen_helper_1e0i(mftacx, t0, 0);
9956 break;
9957 case 4:
9958 gen_helper_1e0i(mftlo, t0, 1);
9959 break;
9960 case 5:
9961 gen_helper_1e0i(mfthi, t0, 1);
9962 break;
9963 case 6:
9964 gen_helper_1e0i(mftacx, t0, 1);
9965 break;
9966 case 8:
9967 gen_helper_1e0i(mftlo, t0, 2);
9968 break;
9969 case 9:
9970 gen_helper_1e0i(mfthi, t0, 2);
9971 break;
9972 case 10:
9973 gen_helper_1e0i(mftacx, t0, 2);
9974 break;
9975 case 12:
9976 gen_helper_1e0i(mftlo, t0, 3);
9977 break;
9978 case 13:
9979 gen_helper_1e0i(mfthi, t0, 3);
9980 break;
9981 case 14:
9982 gen_helper_1e0i(mftacx, t0, 3);
9983 break;
9984 case 16:
9985 gen_helper_mftdsp(t0, cpu_env);
9986 break;
9987 default:
9988 goto die;
9990 break;
9991 /* Floating point (COP1). */
9992 case 2:
9993 /* XXX: For now we support only a single FPU context. */
9994 if (h == 0) {
9995 TCGv_i32 fp0 = tcg_temp_new_i32();
9997 gen_load_fpr32(ctx, fp0, rt);
9998 tcg_gen_ext_i32_tl(t0, fp0);
9999 tcg_temp_free_i32(fp0);
10000 } else {
10001 TCGv_i32 fp0 = tcg_temp_new_i32();
10003 gen_load_fpr32h(ctx, fp0, rt);
10004 tcg_gen_ext_i32_tl(t0, fp0);
10005 tcg_temp_free_i32(fp0);
10007 break;
10008 case 3:
10009 /* XXX: For now we support only a single FPU context. */
10010 gen_helper_1e0i(cfc1, t0, rt);
10011 break;
10012 /* COP2: Not implemented. */
10013 case 4:
10014 case 5:
10015 /* fall through */
10016 default:
10017 goto die;
10020 trace_mips_translate_tr("mftr", rt, u, sel, h);
10021 gen_store_gpr(t0, rd);
10022 tcg_temp_free(t0);
10023 return;
10025 die:
10026 tcg_temp_free(t0);
10027 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
10028 gen_reserved_instruction(ctx);
10031 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
10032 int u, int sel, int h)
10034 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10035 TCGv t0 = tcg_temp_local_new();
10037 gen_load_gpr(t0, rt);
10038 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10039 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10040 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10041 /* NOP */
10043 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10044 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10045 /* NOP */
10047 } else if (u == 0) {
10048 switch (rd) {
10049 case 1:
10050 switch (sel) {
10051 case 1:
10052 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10053 break;
10054 case 2:
10055 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10056 break;
10057 default:
10058 goto die;
10059 break;
10061 break;
10062 case 2:
10063 switch (sel) {
10064 case 1:
10065 gen_helper_mttc0_tcstatus(cpu_env, t0);
10066 break;
10067 case 2:
10068 gen_helper_mttc0_tcbind(cpu_env, t0);
10069 break;
10070 case 3:
10071 gen_helper_mttc0_tcrestart(cpu_env, t0);
10072 break;
10073 case 4:
10074 gen_helper_mttc0_tchalt(cpu_env, t0);
10075 break;
10076 case 5:
10077 gen_helper_mttc0_tccontext(cpu_env, t0);
10078 break;
10079 case 6:
10080 gen_helper_mttc0_tcschedule(cpu_env, t0);
10081 break;
10082 case 7:
10083 gen_helper_mttc0_tcschefback(cpu_env, t0);
10084 break;
10085 default:
10086 gen_mtc0(ctx, t0, rd, sel);
10087 break;
10089 break;
10090 case 10:
10091 switch (sel) {
10092 case 0:
10093 gen_helper_mttc0_entryhi(cpu_env, t0);
10094 break;
10095 default:
10096 gen_mtc0(ctx, t0, rd, sel);
10097 break;
10099 break;
10100 case 12:
10101 switch (sel) {
10102 case 0:
10103 gen_helper_mttc0_status(cpu_env, t0);
10104 break;
10105 default:
10106 gen_mtc0(ctx, t0, rd, sel);
10107 break;
10109 break;
10110 case 13:
10111 switch (sel) {
10112 case 0:
10113 gen_helper_mttc0_cause(cpu_env, t0);
10114 break;
10115 default:
10116 goto die;
10117 break;
10119 break;
10120 case 15:
10121 switch (sel) {
10122 case 1:
10123 gen_helper_mttc0_ebase(cpu_env, t0);
10124 break;
10125 default:
10126 goto die;
10127 break;
10129 break;
10130 case 23:
10131 switch (sel) {
10132 case 0:
10133 gen_helper_mttc0_debug(cpu_env, t0);
10134 break;
10135 default:
10136 gen_mtc0(ctx, t0, rd, sel);
10137 break;
10139 break;
10140 default:
10141 gen_mtc0(ctx, t0, rd, sel);
10143 } else {
10144 switch (sel) {
10145 /* GPR registers. */
10146 case 0:
10147 gen_helper_0e1i(mttgpr, t0, rd);
10148 break;
10149 /* Auxiliary CPU registers */
10150 case 1:
10151 switch (rd) {
10152 case 0:
10153 gen_helper_0e1i(mttlo, t0, 0);
10154 break;
10155 case 1:
10156 gen_helper_0e1i(mtthi, t0, 0);
10157 break;
10158 case 2:
10159 gen_helper_0e1i(mttacx, t0, 0);
10160 break;
10161 case 4:
10162 gen_helper_0e1i(mttlo, t0, 1);
10163 break;
10164 case 5:
10165 gen_helper_0e1i(mtthi, t0, 1);
10166 break;
10167 case 6:
10168 gen_helper_0e1i(mttacx, t0, 1);
10169 break;
10170 case 8:
10171 gen_helper_0e1i(mttlo, t0, 2);
10172 break;
10173 case 9:
10174 gen_helper_0e1i(mtthi, t0, 2);
10175 break;
10176 case 10:
10177 gen_helper_0e1i(mttacx, t0, 2);
10178 break;
10179 case 12:
10180 gen_helper_0e1i(mttlo, t0, 3);
10181 break;
10182 case 13:
10183 gen_helper_0e1i(mtthi, t0, 3);
10184 break;
10185 case 14:
10186 gen_helper_0e1i(mttacx, t0, 3);
10187 break;
10188 case 16:
10189 gen_helper_mttdsp(cpu_env, t0);
10190 break;
10191 default:
10192 goto die;
10194 break;
10195 /* Floating point (COP1). */
10196 case 2:
10197 /* XXX: For now we support only a single FPU context. */
10198 if (h == 0) {
10199 TCGv_i32 fp0 = tcg_temp_new_i32();
10201 tcg_gen_trunc_tl_i32(fp0, t0);
10202 gen_store_fpr32(ctx, fp0, rd);
10203 tcg_temp_free_i32(fp0);
10204 } else {
10205 TCGv_i32 fp0 = tcg_temp_new_i32();
10207 tcg_gen_trunc_tl_i32(fp0, t0);
10208 gen_store_fpr32h(ctx, fp0, rd);
10209 tcg_temp_free_i32(fp0);
10211 break;
10212 case 3:
10213 /* XXX: For now we support only a single FPU context. */
10215 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10217 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10218 tcg_temp_free_i32(fs_tmp);
10220 /* Stop translation as we may have changed hflags */
10221 ctx->base.is_jmp = DISAS_STOP;
10222 break;
10223 /* COP2: Not implemented. */
10224 case 4:
10225 case 5:
10226 /* fall through */
10227 default:
10228 goto die;
10231 trace_mips_translate_tr("mttr", rd, u, sel, h);
10232 tcg_temp_free(t0);
10233 return;
10235 die:
10236 tcg_temp_free(t0);
10237 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10238 gen_reserved_instruction(ctx);
10241 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10242 int rt, int rd)
10244 const char *opn = "ldst";
10246 check_cp0_enabled(ctx);
10247 switch (opc) {
10248 case OPC_MFC0:
10249 if (rt == 0) {
10250 /* Treat as NOP. */
10251 return;
10253 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10254 opn = "mfc0";
10255 break;
10256 case OPC_MTC0:
10258 TCGv t0 = tcg_temp_new();
10260 gen_load_gpr(t0, rt);
10261 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10262 tcg_temp_free(t0);
10264 opn = "mtc0";
10265 break;
10266 #if defined(TARGET_MIPS64)
10267 case OPC_DMFC0:
10268 check_insn(ctx, ISA_MIPS3);
10269 if (rt == 0) {
10270 /* Treat as NOP. */
10271 return;
10273 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10274 opn = "dmfc0";
10275 break;
10276 case OPC_DMTC0:
10277 check_insn(ctx, ISA_MIPS3);
10279 TCGv t0 = tcg_temp_new();
10281 gen_load_gpr(t0, rt);
10282 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10283 tcg_temp_free(t0);
10285 opn = "dmtc0";
10286 break;
10287 #endif
10288 case OPC_MFHC0:
10289 check_mvh(ctx);
10290 if (rt == 0) {
10291 /* Treat as NOP. */
10292 return;
10294 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10295 opn = "mfhc0";
10296 break;
10297 case OPC_MTHC0:
10298 check_mvh(ctx);
10300 TCGv t0 = tcg_temp_new();
10301 gen_load_gpr(t0, rt);
10302 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10303 tcg_temp_free(t0);
10305 opn = "mthc0";
10306 break;
10307 case OPC_MFTR:
10308 check_cp0_enabled(ctx);
10309 if (rd == 0) {
10310 /* Treat as NOP. */
10311 return;
10313 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10314 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10315 opn = "mftr";
10316 break;
10317 case OPC_MTTR:
10318 check_cp0_enabled(ctx);
10319 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10320 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10321 opn = "mttr";
10322 break;
10323 case OPC_TLBWI:
10324 opn = "tlbwi";
10325 if (!env->tlb->helper_tlbwi) {
10326 goto die;
10328 gen_helper_tlbwi(cpu_env);
10329 break;
10330 case OPC_TLBINV:
10331 opn = "tlbinv";
10332 if (ctx->ie >= 2) {
10333 if (!env->tlb->helper_tlbinv) {
10334 goto die;
10336 gen_helper_tlbinv(cpu_env);
10337 } /* treat as nop if TLBINV not supported */
10338 break;
10339 case OPC_TLBINVF:
10340 opn = "tlbinvf";
10341 if (ctx->ie >= 2) {
10342 if (!env->tlb->helper_tlbinvf) {
10343 goto die;
10345 gen_helper_tlbinvf(cpu_env);
10346 } /* treat as nop if TLBINV not supported */
10347 break;
10348 case OPC_TLBWR:
10349 opn = "tlbwr";
10350 if (!env->tlb->helper_tlbwr) {
10351 goto die;
10353 gen_helper_tlbwr(cpu_env);
10354 break;
10355 case OPC_TLBP:
10356 opn = "tlbp";
10357 if (!env->tlb->helper_tlbp) {
10358 goto die;
10360 gen_helper_tlbp(cpu_env);
10361 break;
10362 case OPC_TLBR:
10363 opn = "tlbr";
10364 if (!env->tlb->helper_tlbr) {
10365 goto die;
10367 gen_helper_tlbr(cpu_env);
10368 break;
10369 case OPC_ERET: /* OPC_ERETNC */
10370 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10371 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10372 goto die;
10373 } else {
10374 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10375 if (ctx->opcode & (1 << bit_shift)) {
10376 /* OPC_ERETNC */
10377 opn = "eretnc";
10378 check_insn(ctx, ISA_MIPS_R5);
10379 gen_helper_eretnc(cpu_env);
10380 } else {
10381 /* OPC_ERET */
10382 opn = "eret";
10383 check_insn(ctx, ISA_MIPS2);
10384 gen_helper_eret(cpu_env);
10386 ctx->base.is_jmp = DISAS_EXIT;
10388 break;
10389 case OPC_DERET:
10390 opn = "deret";
10391 check_insn(ctx, ISA_MIPS_R1);
10392 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10393 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10394 goto die;
10396 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10397 MIPS_INVAL(opn);
10398 gen_reserved_instruction(ctx);
10399 } else {
10400 gen_helper_deret(cpu_env);
10401 ctx->base.is_jmp = DISAS_EXIT;
10403 break;
10404 case OPC_WAIT:
10405 opn = "wait";
10406 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
10407 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10408 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10409 goto die;
10411 /* If we get an exception, we want to restart at next instruction */
10412 ctx->base.pc_next += 4;
10413 save_cpu_state(ctx, 1);
10414 ctx->base.pc_next -= 4;
10415 gen_helper_wait(cpu_env);
10416 ctx->base.is_jmp = DISAS_NORETURN;
10417 break;
10418 default:
10419 die:
10420 MIPS_INVAL(opn);
10421 gen_reserved_instruction(ctx);
10422 return;
10424 (void)opn; /* avoid a compiler warning */
10426 #endif /* !CONFIG_USER_ONLY */
10428 /* CP1 Branches (before delay slot) */
10429 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10430 int32_t cc, int32_t offset)
10432 target_ulong btarget;
10433 TCGv_i32 t0 = tcg_temp_new_i32();
10435 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10436 gen_reserved_instruction(ctx);
10437 goto out;
10440 if (cc != 0) {
10441 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
10444 btarget = ctx->base.pc_next + 4 + offset;
10446 switch (op) {
10447 case OPC_BC1F:
10448 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10449 tcg_gen_not_i32(t0, t0);
10450 tcg_gen_andi_i32(t0, t0, 1);
10451 tcg_gen_extu_i32_tl(bcond, t0);
10452 goto not_likely;
10453 case OPC_BC1FL:
10454 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10455 tcg_gen_not_i32(t0, t0);
10456 tcg_gen_andi_i32(t0, t0, 1);
10457 tcg_gen_extu_i32_tl(bcond, t0);
10458 goto likely;
10459 case OPC_BC1T:
10460 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10461 tcg_gen_andi_i32(t0, t0, 1);
10462 tcg_gen_extu_i32_tl(bcond, t0);
10463 goto not_likely;
10464 case OPC_BC1TL:
10465 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10466 tcg_gen_andi_i32(t0, t0, 1);
10467 tcg_gen_extu_i32_tl(bcond, t0);
10468 likely:
10469 ctx->hflags |= MIPS_HFLAG_BL;
10470 break;
10471 case OPC_BC1FANY2:
10473 TCGv_i32 t1 = tcg_temp_new_i32();
10474 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10475 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10476 tcg_gen_nand_i32(t0, t0, t1);
10477 tcg_temp_free_i32(t1);
10478 tcg_gen_andi_i32(t0, t0, 1);
10479 tcg_gen_extu_i32_tl(bcond, t0);
10481 goto not_likely;
10482 case OPC_BC1TANY2:
10484 TCGv_i32 t1 = tcg_temp_new_i32();
10485 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10486 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10487 tcg_gen_or_i32(t0, t0, t1);
10488 tcg_temp_free_i32(t1);
10489 tcg_gen_andi_i32(t0, t0, 1);
10490 tcg_gen_extu_i32_tl(bcond, t0);
10492 goto not_likely;
10493 case OPC_BC1FANY4:
10495 TCGv_i32 t1 = tcg_temp_new_i32();
10496 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10497 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10498 tcg_gen_and_i32(t0, t0, t1);
10499 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10500 tcg_gen_and_i32(t0, t0, t1);
10501 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10502 tcg_gen_nand_i32(t0, t0, t1);
10503 tcg_temp_free_i32(t1);
10504 tcg_gen_andi_i32(t0, t0, 1);
10505 tcg_gen_extu_i32_tl(bcond, t0);
10507 goto not_likely;
10508 case OPC_BC1TANY4:
10510 TCGv_i32 t1 = tcg_temp_new_i32();
10511 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10512 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10513 tcg_gen_or_i32(t0, t0, t1);
10514 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10515 tcg_gen_or_i32(t0, t0, t1);
10516 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10517 tcg_gen_or_i32(t0, t0, t1);
10518 tcg_temp_free_i32(t1);
10519 tcg_gen_andi_i32(t0, t0, 1);
10520 tcg_gen_extu_i32_tl(bcond, t0);
10522 not_likely:
10523 ctx->hflags |= MIPS_HFLAG_BC;
10524 break;
10525 default:
10526 MIPS_INVAL("cp1 cond branch");
10527 gen_reserved_instruction(ctx);
10528 goto out;
10530 ctx->btarget = btarget;
10531 ctx->hflags |= MIPS_HFLAG_BDS32;
10532 out:
10533 tcg_temp_free_i32(t0);
10536 /* R6 CP1 Branches */
10537 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10538 int32_t ft, int32_t offset,
10539 int delayslot_size)
10541 target_ulong btarget;
10542 TCGv_i64 t0 = tcg_temp_new_i64();
10544 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10545 #ifdef MIPS_DEBUG_DISAS
10546 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10547 "\n", ctx->base.pc_next);
10548 #endif
10549 gen_reserved_instruction(ctx);
10550 goto out;
10553 gen_load_fpr64(ctx, t0, ft);
10554 tcg_gen_andi_i64(t0, t0, 1);
10556 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10558 switch (op) {
10559 case OPC_BC1EQZ:
10560 tcg_gen_xori_i64(t0, t0, 1);
10561 ctx->hflags |= MIPS_HFLAG_BC;
10562 break;
10563 case OPC_BC1NEZ:
10564 /* t0 already set */
10565 ctx->hflags |= MIPS_HFLAG_BC;
10566 break;
10567 default:
10568 MIPS_INVAL("cp1 cond branch");
10569 gen_reserved_instruction(ctx);
10570 goto out;
10573 tcg_gen_trunc_i64_tl(bcond, t0);
10575 ctx->btarget = btarget;
10577 switch (delayslot_size) {
10578 case 2:
10579 ctx->hflags |= MIPS_HFLAG_BDS16;
10580 break;
10581 case 4:
10582 ctx->hflags |= MIPS_HFLAG_BDS32;
10583 break;
10586 out:
10587 tcg_temp_free_i64(t0);
10590 /* Coprocessor 1 (FPU) */
10592 #define FOP(func, fmt) (((fmt) << 21) | (func))
10594 enum fopcode {
10595 OPC_ADD_S = FOP(0, FMT_S),
10596 OPC_SUB_S = FOP(1, FMT_S),
10597 OPC_MUL_S = FOP(2, FMT_S),
10598 OPC_DIV_S = FOP(3, FMT_S),
10599 OPC_SQRT_S = FOP(4, FMT_S),
10600 OPC_ABS_S = FOP(5, FMT_S),
10601 OPC_MOV_S = FOP(6, FMT_S),
10602 OPC_NEG_S = FOP(7, FMT_S),
10603 OPC_ROUND_L_S = FOP(8, FMT_S),
10604 OPC_TRUNC_L_S = FOP(9, FMT_S),
10605 OPC_CEIL_L_S = FOP(10, FMT_S),
10606 OPC_FLOOR_L_S = FOP(11, FMT_S),
10607 OPC_ROUND_W_S = FOP(12, FMT_S),
10608 OPC_TRUNC_W_S = FOP(13, FMT_S),
10609 OPC_CEIL_W_S = FOP(14, FMT_S),
10610 OPC_FLOOR_W_S = FOP(15, FMT_S),
10611 OPC_SEL_S = FOP(16, FMT_S),
10612 OPC_MOVCF_S = FOP(17, FMT_S),
10613 OPC_MOVZ_S = FOP(18, FMT_S),
10614 OPC_MOVN_S = FOP(19, FMT_S),
10615 OPC_SELEQZ_S = FOP(20, FMT_S),
10616 OPC_RECIP_S = FOP(21, FMT_S),
10617 OPC_RSQRT_S = FOP(22, FMT_S),
10618 OPC_SELNEZ_S = FOP(23, FMT_S),
10619 OPC_MADDF_S = FOP(24, FMT_S),
10620 OPC_MSUBF_S = FOP(25, FMT_S),
10621 OPC_RINT_S = FOP(26, FMT_S),
10622 OPC_CLASS_S = FOP(27, FMT_S),
10623 OPC_MIN_S = FOP(28, FMT_S),
10624 OPC_RECIP2_S = FOP(28, FMT_S),
10625 OPC_MINA_S = FOP(29, FMT_S),
10626 OPC_RECIP1_S = FOP(29, FMT_S),
10627 OPC_MAX_S = FOP(30, FMT_S),
10628 OPC_RSQRT1_S = FOP(30, FMT_S),
10629 OPC_MAXA_S = FOP(31, FMT_S),
10630 OPC_RSQRT2_S = FOP(31, FMT_S),
10631 OPC_CVT_D_S = FOP(33, FMT_S),
10632 OPC_CVT_W_S = FOP(36, FMT_S),
10633 OPC_CVT_L_S = FOP(37, FMT_S),
10634 OPC_CVT_PS_S = FOP(38, FMT_S),
10635 OPC_CMP_F_S = FOP(48, FMT_S),
10636 OPC_CMP_UN_S = FOP(49, FMT_S),
10637 OPC_CMP_EQ_S = FOP(50, FMT_S),
10638 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10639 OPC_CMP_OLT_S = FOP(52, FMT_S),
10640 OPC_CMP_ULT_S = FOP(53, FMT_S),
10641 OPC_CMP_OLE_S = FOP(54, FMT_S),
10642 OPC_CMP_ULE_S = FOP(55, FMT_S),
10643 OPC_CMP_SF_S = FOP(56, FMT_S),
10644 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10645 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10646 OPC_CMP_NGL_S = FOP(59, FMT_S),
10647 OPC_CMP_LT_S = FOP(60, FMT_S),
10648 OPC_CMP_NGE_S = FOP(61, FMT_S),
10649 OPC_CMP_LE_S = FOP(62, FMT_S),
10650 OPC_CMP_NGT_S = FOP(63, FMT_S),
10652 OPC_ADD_D = FOP(0, FMT_D),
10653 OPC_SUB_D = FOP(1, FMT_D),
10654 OPC_MUL_D = FOP(2, FMT_D),
10655 OPC_DIV_D = FOP(3, FMT_D),
10656 OPC_SQRT_D = FOP(4, FMT_D),
10657 OPC_ABS_D = FOP(5, FMT_D),
10658 OPC_MOV_D = FOP(6, FMT_D),
10659 OPC_NEG_D = FOP(7, FMT_D),
10660 OPC_ROUND_L_D = FOP(8, FMT_D),
10661 OPC_TRUNC_L_D = FOP(9, FMT_D),
10662 OPC_CEIL_L_D = FOP(10, FMT_D),
10663 OPC_FLOOR_L_D = FOP(11, FMT_D),
10664 OPC_ROUND_W_D = FOP(12, FMT_D),
10665 OPC_TRUNC_W_D = FOP(13, FMT_D),
10666 OPC_CEIL_W_D = FOP(14, FMT_D),
10667 OPC_FLOOR_W_D = FOP(15, FMT_D),
10668 OPC_SEL_D = FOP(16, FMT_D),
10669 OPC_MOVCF_D = FOP(17, FMT_D),
10670 OPC_MOVZ_D = FOP(18, FMT_D),
10671 OPC_MOVN_D = FOP(19, FMT_D),
10672 OPC_SELEQZ_D = FOP(20, FMT_D),
10673 OPC_RECIP_D = FOP(21, FMT_D),
10674 OPC_RSQRT_D = FOP(22, FMT_D),
10675 OPC_SELNEZ_D = FOP(23, FMT_D),
10676 OPC_MADDF_D = FOP(24, FMT_D),
10677 OPC_MSUBF_D = FOP(25, FMT_D),
10678 OPC_RINT_D = FOP(26, FMT_D),
10679 OPC_CLASS_D = FOP(27, FMT_D),
10680 OPC_MIN_D = FOP(28, FMT_D),
10681 OPC_RECIP2_D = FOP(28, FMT_D),
10682 OPC_MINA_D = FOP(29, FMT_D),
10683 OPC_RECIP1_D = FOP(29, FMT_D),
10684 OPC_MAX_D = FOP(30, FMT_D),
10685 OPC_RSQRT1_D = FOP(30, FMT_D),
10686 OPC_MAXA_D = FOP(31, FMT_D),
10687 OPC_RSQRT2_D = FOP(31, FMT_D),
10688 OPC_CVT_S_D = FOP(32, FMT_D),
10689 OPC_CVT_W_D = FOP(36, FMT_D),
10690 OPC_CVT_L_D = FOP(37, FMT_D),
10691 OPC_CMP_F_D = FOP(48, FMT_D),
10692 OPC_CMP_UN_D = FOP(49, FMT_D),
10693 OPC_CMP_EQ_D = FOP(50, FMT_D),
10694 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10695 OPC_CMP_OLT_D = FOP(52, FMT_D),
10696 OPC_CMP_ULT_D = FOP(53, FMT_D),
10697 OPC_CMP_OLE_D = FOP(54, FMT_D),
10698 OPC_CMP_ULE_D = FOP(55, FMT_D),
10699 OPC_CMP_SF_D = FOP(56, FMT_D),
10700 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10701 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10702 OPC_CMP_NGL_D = FOP(59, FMT_D),
10703 OPC_CMP_LT_D = FOP(60, FMT_D),
10704 OPC_CMP_NGE_D = FOP(61, FMT_D),
10705 OPC_CMP_LE_D = FOP(62, FMT_D),
10706 OPC_CMP_NGT_D = FOP(63, FMT_D),
10708 OPC_CVT_S_W = FOP(32, FMT_W),
10709 OPC_CVT_D_W = FOP(33, FMT_W),
10710 OPC_CVT_S_L = FOP(32, FMT_L),
10711 OPC_CVT_D_L = FOP(33, FMT_L),
10712 OPC_CVT_PS_PW = FOP(38, FMT_W),
10714 OPC_ADD_PS = FOP(0, FMT_PS),
10715 OPC_SUB_PS = FOP(1, FMT_PS),
10716 OPC_MUL_PS = FOP(2, FMT_PS),
10717 OPC_DIV_PS = FOP(3, FMT_PS),
10718 OPC_ABS_PS = FOP(5, FMT_PS),
10719 OPC_MOV_PS = FOP(6, FMT_PS),
10720 OPC_NEG_PS = FOP(7, FMT_PS),
10721 OPC_MOVCF_PS = FOP(17, FMT_PS),
10722 OPC_MOVZ_PS = FOP(18, FMT_PS),
10723 OPC_MOVN_PS = FOP(19, FMT_PS),
10724 OPC_ADDR_PS = FOP(24, FMT_PS),
10725 OPC_MULR_PS = FOP(26, FMT_PS),
10726 OPC_RECIP2_PS = FOP(28, FMT_PS),
10727 OPC_RECIP1_PS = FOP(29, FMT_PS),
10728 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10729 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10731 OPC_CVT_S_PU = FOP(32, FMT_PS),
10732 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10733 OPC_CVT_S_PL = FOP(40, FMT_PS),
10734 OPC_PLL_PS = FOP(44, FMT_PS),
10735 OPC_PLU_PS = FOP(45, FMT_PS),
10736 OPC_PUL_PS = FOP(46, FMT_PS),
10737 OPC_PUU_PS = FOP(47, FMT_PS),
10738 OPC_CMP_F_PS = FOP(48, FMT_PS),
10739 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10740 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10741 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10742 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10743 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10744 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10745 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10746 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10747 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10748 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10749 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10750 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10751 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10752 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10753 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
10756 enum r6_f_cmp_op {
10757 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10758 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10759 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10760 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10761 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10762 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10763 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10764 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10765 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10766 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10767 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10768 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10769 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10770 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10771 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10772 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10773 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10774 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10775 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10776 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10777 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10778 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10780 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10781 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10782 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10783 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10784 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10785 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10786 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10787 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10788 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10789 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10790 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10791 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10792 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10793 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10794 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10795 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10796 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10797 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10798 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10799 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10800 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10801 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10804 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
10806 TCGv t0 = tcg_temp_new();
10808 switch (opc) {
10809 case OPC_MFC1:
10811 TCGv_i32 fp0 = tcg_temp_new_i32();
10813 gen_load_fpr32(ctx, fp0, fs);
10814 tcg_gen_ext_i32_tl(t0, fp0);
10815 tcg_temp_free_i32(fp0);
10817 gen_store_gpr(t0, rt);
10818 break;
10819 case OPC_MTC1:
10820 gen_load_gpr(t0, rt);
10822 TCGv_i32 fp0 = tcg_temp_new_i32();
10824 tcg_gen_trunc_tl_i32(fp0, t0);
10825 gen_store_fpr32(ctx, fp0, fs);
10826 tcg_temp_free_i32(fp0);
10828 break;
10829 case OPC_CFC1:
10830 gen_helper_1e0i(cfc1, t0, fs);
10831 gen_store_gpr(t0, rt);
10832 break;
10833 case OPC_CTC1:
10834 gen_load_gpr(t0, rt);
10835 save_cpu_state(ctx, 0);
10837 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10839 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10840 tcg_temp_free_i32(fs_tmp);
10842 /* Stop translation as we may have changed hflags */
10843 ctx->base.is_jmp = DISAS_STOP;
10844 break;
10845 #if defined(TARGET_MIPS64)
10846 case OPC_DMFC1:
10847 gen_load_fpr64(ctx, t0, fs);
10848 gen_store_gpr(t0, rt);
10849 break;
10850 case OPC_DMTC1:
10851 gen_load_gpr(t0, rt);
10852 gen_store_fpr64(ctx, t0, fs);
10853 break;
10854 #endif
10855 case OPC_MFHC1:
10857 TCGv_i32 fp0 = tcg_temp_new_i32();
10859 gen_load_fpr32h(ctx, fp0, fs);
10860 tcg_gen_ext_i32_tl(t0, fp0);
10861 tcg_temp_free_i32(fp0);
10863 gen_store_gpr(t0, rt);
10864 break;
10865 case OPC_MTHC1:
10866 gen_load_gpr(t0, rt);
10868 TCGv_i32 fp0 = tcg_temp_new_i32();
10870 tcg_gen_trunc_tl_i32(fp0, t0);
10871 gen_store_fpr32h(ctx, fp0, fs);
10872 tcg_temp_free_i32(fp0);
10874 break;
10875 default:
10876 MIPS_INVAL("cp1 move");
10877 gen_reserved_instruction(ctx);
10878 goto out;
10881 out:
10882 tcg_temp_free(t0);
10885 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
10887 TCGLabel *l1;
10888 TCGCond cond;
10889 TCGv_i32 t0;
10891 if (rd == 0) {
10892 /* Treat as NOP. */
10893 return;
10896 if (tf) {
10897 cond = TCG_COND_EQ;
10898 } else {
10899 cond = TCG_COND_NE;
10902 l1 = gen_new_label();
10903 t0 = tcg_temp_new_i32();
10904 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10905 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10906 tcg_temp_free_i32(t0);
10907 if (rs == 0) {
10908 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10909 } else {
10910 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10912 gen_set_label(l1);
10915 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10916 int tf)
10918 int cond;
10919 TCGv_i32 t0 = tcg_temp_new_i32();
10920 TCGLabel *l1 = gen_new_label();
10922 if (tf) {
10923 cond = TCG_COND_EQ;
10924 } else {
10925 cond = TCG_COND_NE;
10928 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10929 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10930 gen_load_fpr32(ctx, t0, fs);
10931 gen_store_fpr32(ctx, t0, fd);
10932 gen_set_label(l1);
10933 tcg_temp_free_i32(t0);
10936 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
10937 int tf)
10939 int cond;
10940 TCGv_i32 t0 = tcg_temp_new_i32();
10941 TCGv_i64 fp0;
10942 TCGLabel *l1 = gen_new_label();
10944 if (tf) {
10945 cond = TCG_COND_EQ;
10946 } else {
10947 cond = TCG_COND_NE;
10950 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10951 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10952 tcg_temp_free_i32(t0);
10953 fp0 = tcg_temp_new_i64();
10954 gen_load_fpr64(ctx, fp0, fs);
10955 gen_store_fpr64(ctx, fp0, fd);
10956 tcg_temp_free_i64(fp0);
10957 gen_set_label(l1);
10960 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10961 int cc, int tf)
10963 int cond;
10964 TCGv_i32 t0 = tcg_temp_new_i32();
10965 TCGLabel *l1 = gen_new_label();
10966 TCGLabel *l2 = gen_new_label();
10968 if (tf) {
10969 cond = TCG_COND_EQ;
10970 } else {
10971 cond = TCG_COND_NE;
10974 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10975 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10976 gen_load_fpr32(ctx, t0, fs);
10977 gen_store_fpr32(ctx, t0, fd);
10978 gen_set_label(l1);
10980 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
10981 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10982 gen_load_fpr32h(ctx, t0, fs);
10983 gen_store_fpr32h(ctx, t0, fd);
10984 tcg_temp_free_i32(t0);
10985 gen_set_label(l2);
10988 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10989 int fs)
10991 TCGv_i32 t1 = tcg_const_i32(0);
10992 TCGv_i32 fp0 = tcg_temp_new_i32();
10993 TCGv_i32 fp1 = tcg_temp_new_i32();
10994 TCGv_i32 fp2 = tcg_temp_new_i32();
10995 gen_load_fpr32(ctx, fp0, fd);
10996 gen_load_fpr32(ctx, fp1, ft);
10997 gen_load_fpr32(ctx, fp2, fs);
10999 switch (op1) {
11000 case OPC_SEL_S:
11001 tcg_gen_andi_i32(fp0, fp0, 1);
11002 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11003 break;
11004 case OPC_SELEQZ_S:
11005 tcg_gen_andi_i32(fp1, fp1, 1);
11006 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11007 break;
11008 case OPC_SELNEZ_S:
11009 tcg_gen_andi_i32(fp1, fp1, 1);
11010 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11011 break;
11012 default:
11013 MIPS_INVAL("gen_sel_s");
11014 gen_reserved_instruction(ctx);
11015 break;
11018 gen_store_fpr32(ctx, fp0, fd);
11019 tcg_temp_free_i32(fp2);
11020 tcg_temp_free_i32(fp1);
11021 tcg_temp_free_i32(fp0);
11022 tcg_temp_free_i32(t1);
11025 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11026 int fs)
11028 TCGv_i64 t1 = tcg_const_i64(0);
11029 TCGv_i64 fp0 = tcg_temp_new_i64();
11030 TCGv_i64 fp1 = tcg_temp_new_i64();
11031 TCGv_i64 fp2 = tcg_temp_new_i64();
11032 gen_load_fpr64(ctx, fp0, fd);
11033 gen_load_fpr64(ctx, fp1, ft);
11034 gen_load_fpr64(ctx, fp2, fs);
11036 switch (op1) {
11037 case OPC_SEL_D:
11038 tcg_gen_andi_i64(fp0, fp0, 1);
11039 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11040 break;
11041 case OPC_SELEQZ_D:
11042 tcg_gen_andi_i64(fp1, fp1, 1);
11043 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11044 break;
11045 case OPC_SELNEZ_D:
11046 tcg_gen_andi_i64(fp1, fp1, 1);
11047 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11048 break;
11049 default:
11050 MIPS_INVAL("gen_sel_d");
11051 gen_reserved_instruction(ctx);
11052 break;
11055 gen_store_fpr64(ctx, fp0, fd);
11056 tcg_temp_free_i64(fp2);
11057 tcg_temp_free_i64(fp1);
11058 tcg_temp_free_i64(fp0);
11059 tcg_temp_free_i64(t1);
11062 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11063 int ft, int fs, int fd, int cc)
11065 uint32_t func = ctx->opcode & 0x3f;
11066 switch (op1) {
11067 case OPC_ADD_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_add_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_SUB_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_sub_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_MUL_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_mul_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_DIV_S:
11108 TCGv_i32 fp0 = tcg_temp_new_i32();
11109 TCGv_i32 fp1 = tcg_temp_new_i32();
11111 gen_load_fpr32(ctx, fp0, fs);
11112 gen_load_fpr32(ctx, fp1, ft);
11113 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11114 tcg_temp_free_i32(fp1);
11115 gen_store_fpr32(ctx, fp0, fd);
11116 tcg_temp_free_i32(fp0);
11118 break;
11119 case OPC_SQRT_S:
11121 TCGv_i32 fp0 = tcg_temp_new_i32();
11123 gen_load_fpr32(ctx, fp0, fs);
11124 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11125 gen_store_fpr32(ctx, fp0, fd);
11126 tcg_temp_free_i32(fp0);
11128 break;
11129 case OPC_ABS_S:
11131 TCGv_i32 fp0 = tcg_temp_new_i32();
11133 gen_load_fpr32(ctx, fp0, fs);
11134 if (ctx->abs2008) {
11135 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11136 } else {
11137 gen_helper_float_abs_s(fp0, fp0);
11139 gen_store_fpr32(ctx, fp0, fd);
11140 tcg_temp_free_i32(fp0);
11142 break;
11143 case OPC_MOV_S:
11145 TCGv_i32 fp0 = tcg_temp_new_i32();
11147 gen_load_fpr32(ctx, fp0, fs);
11148 gen_store_fpr32(ctx, fp0, fd);
11149 tcg_temp_free_i32(fp0);
11151 break;
11152 case OPC_NEG_S:
11154 TCGv_i32 fp0 = tcg_temp_new_i32();
11156 gen_load_fpr32(ctx, fp0, fs);
11157 if (ctx->abs2008) {
11158 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11159 } else {
11160 gen_helper_float_chs_s(fp0, fp0);
11162 gen_store_fpr32(ctx, fp0, fd);
11163 tcg_temp_free_i32(fp0);
11165 break;
11166 case OPC_ROUND_L_S:
11167 check_cp1_64bitmode(ctx);
11169 TCGv_i32 fp32 = tcg_temp_new_i32();
11170 TCGv_i64 fp64 = tcg_temp_new_i64();
11172 gen_load_fpr32(ctx, fp32, fs);
11173 if (ctx->nan2008) {
11174 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11175 } else {
11176 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11178 tcg_temp_free_i32(fp32);
11179 gen_store_fpr64(ctx, fp64, fd);
11180 tcg_temp_free_i64(fp64);
11182 break;
11183 case OPC_TRUNC_L_S:
11184 check_cp1_64bitmode(ctx);
11186 TCGv_i32 fp32 = tcg_temp_new_i32();
11187 TCGv_i64 fp64 = tcg_temp_new_i64();
11189 gen_load_fpr32(ctx, fp32, fs);
11190 if (ctx->nan2008) {
11191 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11192 } else {
11193 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11195 tcg_temp_free_i32(fp32);
11196 gen_store_fpr64(ctx, fp64, fd);
11197 tcg_temp_free_i64(fp64);
11199 break;
11200 case OPC_CEIL_L_S:
11201 check_cp1_64bitmode(ctx);
11203 TCGv_i32 fp32 = tcg_temp_new_i32();
11204 TCGv_i64 fp64 = tcg_temp_new_i64();
11206 gen_load_fpr32(ctx, fp32, fs);
11207 if (ctx->nan2008) {
11208 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11209 } else {
11210 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11212 tcg_temp_free_i32(fp32);
11213 gen_store_fpr64(ctx, fp64, fd);
11214 tcg_temp_free_i64(fp64);
11216 break;
11217 case OPC_FLOOR_L_S:
11218 check_cp1_64bitmode(ctx);
11220 TCGv_i32 fp32 = tcg_temp_new_i32();
11221 TCGv_i64 fp64 = tcg_temp_new_i64();
11223 gen_load_fpr32(ctx, fp32, fs);
11224 if (ctx->nan2008) {
11225 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11226 } else {
11227 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11229 tcg_temp_free_i32(fp32);
11230 gen_store_fpr64(ctx, fp64, fd);
11231 tcg_temp_free_i64(fp64);
11233 break;
11234 case OPC_ROUND_W_S:
11236 TCGv_i32 fp0 = tcg_temp_new_i32();
11238 gen_load_fpr32(ctx, fp0, fs);
11239 if (ctx->nan2008) {
11240 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11241 } else {
11242 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11244 gen_store_fpr32(ctx, fp0, fd);
11245 tcg_temp_free_i32(fp0);
11247 break;
11248 case OPC_TRUNC_W_S:
11250 TCGv_i32 fp0 = tcg_temp_new_i32();
11252 gen_load_fpr32(ctx, fp0, fs);
11253 if (ctx->nan2008) {
11254 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11255 } else {
11256 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11258 gen_store_fpr32(ctx, fp0, fd);
11259 tcg_temp_free_i32(fp0);
11261 break;
11262 case OPC_CEIL_W_S:
11264 TCGv_i32 fp0 = tcg_temp_new_i32();
11266 gen_load_fpr32(ctx, fp0, fs);
11267 if (ctx->nan2008) {
11268 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11269 } else {
11270 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11272 gen_store_fpr32(ctx, fp0, fd);
11273 tcg_temp_free_i32(fp0);
11275 break;
11276 case OPC_FLOOR_W_S:
11278 TCGv_i32 fp0 = tcg_temp_new_i32();
11280 gen_load_fpr32(ctx, fp0, fs);
11281 if (ctx->nan2008) {
11282 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11283 } else {
11284 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11286 gen_store_fpr32(ctx, fp0, fd);
11287 tcg_temp_free_i32(fp0);
11289 break;
11290 case OPC_SEL_S:
11291 check_insn(ctx, ISA_MIPS_R6);
11292 gen_sel_s(ctx, op1, fd, ft, fs);
11293 break;
11294 case OPC_SELEQZ_S:
11295 check_insn(ctx, ISA_MIPS_R6);
11296 gen_sel_s(ctx, op1, fd, ft, fs);
11297 break;
11298 case OPC_SELNEZ_S:
11299 check_insn(ctx, ISA_MIPS_R6);
11300 gen_sel_s(ctx, op1, fd, ft, fs);
11301 break;
11302 case OPC_MOVCF_S:
11303 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11304 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11305 break;
11306 case OPC_MOVZ_S:
11307 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11309 TCGLabel *l1 = gen_new_label();
11310 TCGv_i32 fp0;
11312 if (ft != 0) {
11313 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11315 fp0 = tcg_temp_new_i32();
11316 gen_load_fpr32(ctx, fp0, fs);
11317 gen_store_fpr32(ctx, fp0, fd);
11318 tcg_temp_free_i32(fp0);
11319 gen_set_label(l1);
11321 break;
11322 case OPC_MOVN_S:
11323 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11325 TCGLabel *l1 = gen_new_label();
11326 TCGv_i32 fp0;
11328 if (ft != 0) {
11329 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11330 fp0 = tcg_temp_new_i32();
11331 gen_load_fpr32(ctx, fp0, fs);
11332 gen_store_fpr32(ctx, fp0, fd);
11333 tcg_temp_free_i32(fp0);
11334 gen_set_label(l1);
11337 break;
11338 case OPC_RECIP_S:
11340 TCGv_i32 fp0 = tcg_temp_new_i32();
11342 gen_load_fpr32(ctx, fp0, fs);
11343 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11344 gen_store_fpr32(ctx, fp0, fd);
11345 tcg_temp_free_i32(fp0);
11347 break;
11348 case OPC_RSQRT_S:
11350 TCGv_i32 fp0 = tcg_temp_new_i32();
11352 gen_load_fpr32(ctx, fp0, fs);
11353 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11354 gen_store_fpr32(ctx, fp0, fd);
11355 tcg_temp_free_i32(fp0);
11357 break;
11358 case OPC_MADDF_S:
11359 check_insn(ctx, ISA_MIPS_R6);
11361 TCGv_i32 fp0 = tcg_temp_new_i32();
11362 TCGv_i32 fp1 = tcg_temp_new_i32();
11363 TCGv_i32 fp2 = tcg_temp_new_i32();
11364 gen_load_fpr32(ctx, fp0, fs);
11365 gen_load_fpr32(ctx, fp1, ft);
11366 gen_load_fpr32(ctx, fp2, fd);
11367 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11368 gen_store_fpr32(ctx, fp2, fd);
11369 tcg_temp_free_i32(fp2);
11370 tcg_temp_free_i32(fp1);
11371 tcg_temp_free_i32(fp0);
11373 break;
11374 case OPC_MSUBF_S:
11375 check_insn(ctx, ISA_MIPS_R6);
11377 TCGv_i32 fp0 = tcg_temp_new_i32();
11378 TCGv_i32 fp1 = tcg_temp_new_i32();
11379 TCGv_i32 fp2 = tcg_temp_new_i32();
11380 gen_load_fpr32(ctx, fp0, fs);
11381 gen_load_fpr32(ctx, fp1, ft);
11382 gen_load_fpr32(ctx, fp2, fd);
11383 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11384 gen_store_fpr32(ctx, fp2, fd);
11385 tcg_temp_free_i32(fp2);
11386 tcg_temp_free_i32(fp1);
11387 tcg_temp_free_i32(fp0);
11389 break;
11390 case OPC_RINT_S:
11391 check_insn(ctx, ISA_MIPS_R6);
11393 TCGv_i32 fp0 = tcg_temp_new_i32();
11394 gen_load_fpr32(ctx, fp0, fs);
11395 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11396 gen_store_fpr32(ctx, fp0, fd);
11397 tcg_temp_free_i32(fp0);
11399 break;
11400 case OPC_CLASS_S:
11401 check_insn(ctx, ISA_MIPS_R6);
11403 TCGv_i32 fp0 = tcg_temp_new_i32();
11404 gen_load_fpr32(ctx, fp0, fs);
11405 gen_helper_float_class_s(fp0, cpu_env, fp0);
11406 gen_store_fpr32(ctx, fp0, fd);
11407 tcg_temp_free_i32(fp0);
11409 break;
11410 case OPC_MIN_S: /* OPC_RECIP2_S */
11411 if (ctx->insn_flags & ISA_MIPS_R6) {
11412 /* OPC_MIN_S */
11413 TCGv_i32 fp0 = tcg_temp_new_i32();
11414 TCGv_i32 fp1 = tcg_temp_new_i32();
11415 TCGv_i32 fp2 = tcg_temp_new_i32();
11416 gen_load_fpr32(ctx, fp0, fs);
11417 gen_load_fpr32(ctx, fp1, ft);
11418 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11419 gen_store_fpr32(ctx, fp2, fd);
11420 tcg_temp_free_i32(fp2);
11421 tcg_temp_free_i32(fp1);
11422 tcg_temp_free_i32(fp0);
11423 } else {
11424 /* OPC_RECIP2_S */
11425 check_cp1_64bitmode(ctx);
11427 TCGv_i32 fp0 = tcg_temp_new_i32();
11428 TCGv_i32 fp1 = tcg_temp_new_i32();
11430 gen_load_fpr32(ctx, fp0, fs);
11431 gen_load_fpr32(ctx, fp1, ft);
11432 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11433 tcg_temp_free_i32(fp1);
11434 gen_store_fpr32(ctx, fp0, fd);
11435 tcg_temp_free_i32(fp0);
11438 break;
11439 case OPC_MINA_S: /* OPC_RECIP1_S */
11440 if (ctx->insn_flags & ISA_MIPS_R6) {
11441 /* OPC_MINA_S */
11442 TCGv_i32 fp0 = tcg_temp_new_i32();
11443 TCGv_i32 fp1 = tcg_temp_new_i32();
11444 TCGv_i32 fp2 = tcg_temp_new_i32();
11445 gen_load_fpr32(ctx, fp0, fs);
11446 gen_load_fpr32(ctx, fp1, ft);
11447 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11448 gen_store_fpr32(ctx, fp2, fd);
11449 tcg_temp_free_i32(fp2);
11450 tcg_temp_free_i32(fp1);
11451 tcg_temp_free_i32(fp0);
11452 } else {
11453 /* OPC_RECIP1_S */
11454 check_cp1_64bitmode(ctx);
11456 TCGv_i32 fp0 = tcg_temp_new_i32();
11458 gen_load_fpr32(ctx, fp0, fs);
11459 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11460 gen_store_fpr32(ctx, fp0, fd);
11461 tcg_temp_free_i32(fp0);
11464 break;
11465 case OPC_MAX_S: /* OPC_RSQRT1_S */
11466 if (ctx->insn_flags & ISA_MIPS_R6) {
11467 /* OPC_MAX_S */
11468 TCGv_i32 fp0 = tcg_temp_new_i32();
11469 TCGv_i32 fp1 = tcg_temp_new_i32();
11470 gen_load_fpr32(ctx, fp0, fs);
11471 gen_load_fpr32(ctx, fp1, ft);
11472 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11473 gen_store_fpr32(ctx, fp1, fd);
11474 tcg_temp_free_i32(fp1);
11475 tcg_temp_free_i32(fp0);
11476 } else {
11477 /* OPC_RSQRT1_S */
11478 check_cp1_64bitmode(ctx);
11480 TCGv_i32 fp0 = tcg_temp_new_i32();
11482 gen_load_fpr32(ctx, fp0, fs);
11483 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11484 gen_store_fpr32(ctx, fp0, fd);
11485 tcg_temp_free_i32(fp0);
11488 break;
11489 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11490 if (ctx->insn_flags & ISA_MIPS_R6) {
11491 /* OPC_MAXA_S */
11492 TCGv_i32 fp0 = tcg_temp_new_i32();
11493 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_maxa_s(fp1, cpu_env, fp0, fp1);
11497 gen_store_fpr32(ctx, fp1, fd);
11498 tcg_temp_free_i32(fp1);
11499 tcg_temp_free_i32(fp0);
11500 } else {
11501 /* OPC_RSQRT2_S */
11502 check_cp1_64bitmode(ctx);
11504 TCGv_i32 fp0 = tcg_temp_new_i32();
11505 TCGv_i32 fp1 = tcg_temp_new_i32();
11507 gen_load_fpr32(ctx, fp0, fs);
11508 gen_load_fpr32(ctx, fp1, ft);
11509 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11510 tcg_temp_free_i32(fp1);
11511 gen_store_fpr32(ctx, fp0, fd);
11512 tcg_temp_free_i32(fp0);
11515 break;
11516 case OPC_CVT_D_S:
11517 check_cp1_registers(ctx, fd);
11519 TCGv_i32 fp32 = tcg_temp_new_i32();
11520 TCGv_i64 fp64 = tcg_temp_new_i64();
11522 gen_load_fpr32(ctx, fp32, fs);
11523 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11524 tcg_temp_free_i32(fp32);
11525 gen_store_fpr64(ctx, fp64, fd);
11526 tcg_temp_free_i64(fp64);
11528 break;
11529 case OPC_CVT_W_S:
11531 TCGv_i32 fp0 = tcg_temp_new_i32();
11533 gen_load_fpr32(ctx, fp0, fs);
11534 if (ctx->nan2008) {
11535 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11536 } else {
11537 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11539 gen_store_fpr32(ctx, fp0, fd);
11540 tcg_temp_free_i32(fp0);
11542 break;
11543 case OPC_CVT_L_S:
11544 check_cp1_64bitmode(ctx);
11546 TCGv_i32 fp32 = tcg_temp_new_i32();
11547 TCGv_i64 fp64 = tcg_temp_new_i64();
11549 gen_load_fpr32(ctx, fp32, fs);
11550 if (ctx->nan2008) {
11551 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11552 } else {
11553 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11555 tcg_temp_free_i32(fp32);
11556 gen_store_fpr64(ctx, fp64, fd);
11557 tcg_temp_free_i64(fp64);
11559 break;
11560 case OPC_CVT_PS_S:
11561 check_ps(ctx);
11563 TCGv_i64 fp64 = tcg_temp_new_i64();
11564 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11565 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11567 gen_load_fpr32(ctx, fp32_0, fs);
11568 gen_load_fpr32(ctx, fp32_1, ft);
11569 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11570 tcg_temp_free_i32(fp32_1);
11571 tcg_temp_free_i32(fp32_0);
11572 gen_store_fpr64(ctx, fp64, fd);
11573 tcg_temp_free_i64(fp64);
11575 break;
11576 case OPC_CMP_F_S:
11577 case OPC_CMP_UN_S:
11578 case OPC_CMP_EQ_S:
11579 case OPC_CMP_UEQ_S:
11580 case OPC_CMP_OLT_S:
11581 case OPC_CMP_ULT_S:
11582 case OPC_CMP_OLE_S:
11583 case OPC_CMP_ULE_S:
11584 case OPC_CMP_SF_S:
11585 case OPC_CMP_NGLE_S:
11586 case OPC_CMP_SEQ_S:
11587 case OPC_CMP_NGL_S:
11588 case OPC_CMP_LT_S:
11589 case OPC_CMP_NGE_S:
11590 case OPC_CMP_LE_S:
11591 case OPC_CMP_NGT_S:
11592 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11593 if (ctx->opcode & (1 << 6)) {
11594 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
11595 } else {
11596 gen_cmp_s(ctx, func - 48, ft, fs, cc);
11598 break;
11599 case OPC_ADD_D:
11600 check_cp1_registers(ctx, fs | ft | fd);
11602 TCGv_i64 fp0 = tcg_temp_new_i64();
11603 TCGv_i64 fp1 = tcg_temp_new_i64();
11605 gen_load_fpr64(ctx, fp0, fs);
11606 gen_load_fpr64(ctx, fp1, ft);
11607 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11608 tcg_temp_free_i64(fp1);
11609 gen_store_fpr64(ctx, fp0, fd);
11610 tcg_temp_free_i64(fp0);
11612 break;
11613 case OPC_SUB_D:
11614 check_cp1_registers(ctx, fs | ft | fd);
11616 TCGv_i64 fp0 = tcg_temp_new_i64();
11617 TCGv_i64 fp1 = tcg_temp_new_i64();
11619 gen_load_fpr64(ctx, fp0, fs);
11620 gen_load_fpr64(ctx, fp1, ft);
11621 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11622 tcg_temp_free_i64(fp1);
11623 gen_store_fpr64(ctx, fp0, fd);
11624 tcg_temp_free_i64(fp0);
11626 break;
11627 case OPC_MUL_D:
11628 check_cp1_registers(ctx, fs | ft | fd);
11630 TCGv_i64 fp0 = tcg_temp_new_i64();
11631 TCGv_i64 fp1 = tcg_temp_new_i64();
11633 gen_load_fpr64(ctx, fp0, fs);
11634 gen_load_fpr64(ctx, fp1, ft);
11635 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11636 tcg_temp_free_i64(fp1);
11637 gen_store_fpr64(ctx, fp0, fd);
11638 tcg_temp_free_i64(fp0);
11640 break;
11641 case OPC_DIV_D:
11642 check_cp1_registers(ctx, fs | ft | fd);
11644 TCGv_i64 fp0 = tcg_temp_new_i64();
11645 TCGv_i64 fp1 = tcg_temp_new_i64();
11647 gen_load_fpr64(ctx, fp0, fs);
11648 gen_load_fpr64(ctx, fp1, ft);
11649 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11650 tcg_temp_free_i64(fp1);
11651 gen_store_fpr64(ctx, fp0, fd);
11652 tcg_temp_free_i64(fp0);
11654 break;
11655 case OPC_SQRT_D:
11656 check_cp1_registers(ctx, fs | fd);
11658 TCGv_i64 fp0 = tcg_temp_new_i64();
11660 gen_load_fpr64(ctx, fp0, fs);
11661 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11662 gen_store_fpr64(ctx, fp0, fd);
11663 tcg_temp_free_i64(fp0);
11665 break;
11666 case OPC_ABS_D:
11667 check_cp1_registers(ctx, fs | fd);
11669 TCGv_i64 fp0 = tcg_temp_new_i64();
11671 gen_load_fpr64(ctx, fp0, fs);
11672 if (ctx->abs2008) {
11673 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11674 } else {
11675 gen_helper_float_abs_d(fp0, fp0);
11677 gen_store_fpr64(ctx, fp0, fd);
11678 tcg_temp_free_i64(fp0);
11680 break;
11681 case OPC_MOV_D:
11682 check_cp1_registers(ctx, fs | fd);
11684 TCGv_i64 fp0 = tcg_temp_new_i64();
11686 gen_load_fpr64(ctx, fp0, fs);
11687 gen_store_fpr64(ctx, fp0, fd);
11688 tcg_temp_free_i64(fp0);
11690 break;
11691 case OPC_NEG_D:
11692 check_cp1_registers(ctx, fs | fd);
11694 TCGv_i64 fp0 = tcg_temp_new_i64();
11696 gen_load_fpr64(ctx, fp0, fs);
11697 if (ctx->abs2008) {
11698 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11699 } else {
11700 gen_helper_float_chs_d(fp0, fp0);
11702 gen_store_fpr64(ctx, fp0, fd);
11703 tcg_temp_free_i64(fp0);
11705 break;
11706 case OPC_ROUND_L_D:
11707 check_cp1_64bitmode(ctx);
11709 TCGv_i64 fp0 = tcg_temp_new_i64();
11711 gen_load_fpr64(ctx, fp0, fs);
11712 if (ctx->nan2008) {
11713 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11714 } else {
11715 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11717 gen_store_fpr64(ctx, fp0, fd);
11718 tcg_temp_free_i64(fp0);
11720 break;
11721 case OPC_TRUNC_L_D:
11722 check_cp1_64bitmode(ctx);
11724 TCGv_i64 fp0 = tcg_temp_new_i64();
11726 gen_load_fpr64(ctx, fp0, fs);
11727 if (ctx->nan2008) {
11728 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11729 } else {
11730 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11732 gen_store_fpr64(ctx, fp0, fd);
11733 tcg_temp_free_i64(fp0);
11735 break;
11736 case OPC_CEIL_L_D:
11737 check_cp1_64bitmode(ctx);
11739 TCGv_i64 fp0 = tcg_temp_new_i64();
11741 gen_load_fpr64(ctx, fp0, fs);
11742 if (ctx->nan2008) {
11743 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11744 } else {
11745 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11747 gen_store_fpr64(ctx, fp0, fd);
11748 tcg_temp_free_i64(fp0);
11750 break;
11751 case OPC_FLOOR_L_D:
11752 check_cp1_64bitmode(ctx);
11754 TCGv_i64 fp0 = tcg_temp_new_i64();
11756 gen_load_fpr64(ctx, fp0, fs);
11757 if (ctx->nan2008) {
11758 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11759 } else {
11760 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11762 gen_store_fpr64(ctx, fp0, fd);
11763 tcg_temp_free_i64(fp0);
11765 break;
11766 case OPC_ROUND_W_D:
11767 check_cp1_registers(ctx, fs);
11769 TCGv_i32 fp32 = tcg_temp_new_i32();
11770 TCGv_i64 fp64 = tcg_temp_new_i64();
11772 gen_load_fpr64(ctx, fp64, fs);
11773 if (ctx->nan2008) {
11774 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11775 } else {
11776 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11778 tcg_temp_free_i64(fp64);
11779 gen_store_fpr32(ctx, fp32, fd);
11780 tcg_temp_free_i32(fp32);
11782 break;
11783 case OPC_TRUNC_W_D:
11784 check_cp1_registers(ctx, fs);
11786 TCGv_i32 fp32 = tcg_temp_new_i32();
11787 TCGv_i64 fp64 = tcg_temp_new_i64();
11789 gen_load_fpr64(ctx, fp64, fs);
11790 if (ctx->nan2008) {
11791 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11792 } else {
11793 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11795 tcg_temp_free_i64(fp64);
11796 gen_store_fpr32(ctx, fp32, fd);
11797 tcg_temp_free_i32(fp32);
11799 break;
11800 case OPC_CEIL_W_D:
11801 check_cp1_registers(ctx, fs);
11803 TCGv_i32 fp32 = tcg_temp_new_i32();
11804 TCGv_i64 fp64 = tcg_temp_new_i64();
11806 gen_load_fpr64(ctx, fp64, fs);
11807 if (ctx->nan2008) {
11808 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11809 } else {
11810 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11812 tcg_temp_free_i64(fp64);
11813 gen_store_fpr32(ctx, fp32, fd);
11814 tcg_temp_free_i32(fp32);
11816 break;
11817 case OPC_FLOOR_W_D:
11818 check_cp1_registers(ctx, fs);
11820 TCGv_i32 fp32 = tcg_temp_new_i32();
11821 TCGv_i64 fp64 = tcg_temp_new_i64();
11823 gen_load_fpr64(ctx, fp64, fs);
11824 if (ctx->nan2008) {
11825 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11826 } else {
11827 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11829 tcg_temp_free_i64(fp64);
11830 gen_store_fpr32(ctx, fp32, fd);
11831 tcg_temp_free_i32(fp32);
11833 break;
11834 case OPC_SEL_D:
11835 check_insn(ctx, ISA_MIPS_R6);
11836 gen_sel_d(ctx, op1, fd, ft, fs);
11837 break;
11838 case OPC_SELEQZ_D:
11839 check_insn(ctx, ISA_MIPS_R6);
11840 gen_sel_d(ctx, op1, fd, ft, fs);
11841 break;
11842 case OPC_SELNEZ_D:
11843 check_insn(ctx, ISA_MIPS_R6);
11844 gen_sel_d(ctx, op1, fd, ft, fs);
11845 break;
11846 case OPC_MOVCF_D:
11847 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11848 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11849 break;
11850 case OPC_MOVZ_D:
11851 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11853 TCGLabel *l1 = gen_new_label();
11854 TCGv_i64 fp0;
11856 if (ft != 0) {
11857 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11859 fp0 = tcg_temp_new_i64();
11860 gen_load_fpr64(ctx, fp0, fs);
11861 gen_store_fpr64(ctx, fp0, fd);
11862 tcg_temp_free_i64(fp0);
11863 gen_set_label(l1);
11865 break;
11866 case OPC_MOVN_D:
11867 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11869 TCGLabel *l1 = gen_new_label();
11870 TCGv_i64 fp0;
11872 if (ft != 0) {
11873 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11874 fp0 = tcg_temp_new_i64();
11875 gen_load_fpr64(ctx, fp0, fs);
11876 gen_store_fpr64(ctx, fp0, fd);
11877 tcg_temp_free_i64(fp0);
11878 gen_set_label(l1);
11881 break;
11882 case OPC_RECIP_D:
11883 check_cp1_registers(ctx, fs | fd);
11885 TCGv_i64 fp0 = tcg_temp_new_i64();
11887 gen_load_fpr64(ctx, fp0, fs);
11888 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11889 gen_store_fpr64(ctx, fp0, fd);
11890 tcg_temp_free_i64(fp0);
11892 break;
11893 case OPC_RSQRT_D:
11894 check_cp1_registers(ctx, fs | fd);
11896 TCGv_i64 fp0 = tcg_temp_new_i64();
11898 gen_load_fpr64(ctx, fp0, fs);
11899 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11900 gen_store_fpr64(ctx, fp0, fd);
11901 tcg_temp_free_i64(fp0);
11903 break;
11904 case OPC_MADDF_D:
11905 check_insn(ctx, ISA_MIPS_R6);
11907 TCGv_i64 fp0 = tcg_temp_new_i64();
11908 TCGv_i64 fp1 = tcg_temp_new_i64();
11909 TCGv_i64 fp2 = tcg_temp_new_i64();
11910 gen_load_fpr64(ctx, fp0, fs);
11911 gen_load_fpr64(ctx, fp1, ft);
11912 gen_load_fpr64(ctx, fp2, fd);
11913 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11914 gen_store_fpr64(ctx, fp2, fd);
11915 tcg_temp_free_i64(fp2);
11916 tcg_temp_free_i64(fp1);
11917 tcg_temp_free_i64(fp0);
11919 break;
11920 case OPC_MSUBF_D:
11921 check_insn(ctx, ISA_MIPS_R6);
11923 TCGv_i64 fp0 = tcg_temp_new_i64();
11924 TCGv_i64 fp1 = tcg_temp_new_i64();
11925 TCGv_i64 fp2 = tcg_temp_new_i64();
11926 gen_load_fpr64(ctx, fp0, fs);
11927 gen_load_fpr64(ctx, fp1, ft);
11928 gen_load_fpr64(ctx, fp2, fd);
11929 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11930 gen_store_fpr64(ctx, fp2, fd);
11931 tcg_temp_free_i64(fp2);
11932 tcg_temp_free_i64(fp1);
11933 tcg_temp_free_i64(fp0);
11935 break;
11936 case OPC_RINT_D:
11937 check_insn(ctx, ISA_MIPS_R6);
11939 TCGv_i64 fp0 = tcg_temp_new_i64();
11940 gen_load_fpr64(ctx, fp0, fs);
11941 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11942 gen_store_fpr64(ctx, fp0, fd);
11943 tcg_temp_free_i64(fp0);
11945 break;
11946 case OPC_CLASS_D:
11947 check_insn(ctx, ISA_MIPS_R6);
11949 TCGv_i64 fp0 = tcg_temp_new_i64();
11950 gen_load_fpr64(ctx, fp0, fs);
11951 gen_helper_float_class_d(fp0, cpu_env, fp0);
11952 gen_store_fpr64(ctx, fp0, fd);
11953 tcg_temp_free_i64(fp0);
11955 break;
11956 case OPC_MIN_D: /* OPC_RECIP2_D */
11957 if (ctx->insn_flags & ISA_MIPS_R6) {
11958 /* OPC_MIN_D */
11959 TCGv_i64 fp0 = tcg_temp_new_i64();
11960 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_min_d(fp1, cpu_env, fp0, fp1);
11964 gen_store_fpr64(ctx, fp1, fd);
11965 tcg_temp_free_i64(fp1);
11966 tcg_temp_free_i64(fp0);
11967 } else {
11968 /* OPC_RECIP2_D */
11969 check_cp1_64bitmode(ctx);
11971 TCGv_i64 fp0 = tcg_temp_new_i64();
11972 TCGv_i64 fp1 = tcg_temp_new_i64();
11974 gen_load_fpr64(ctx, fp0, fs);
11975 gen_load_fpr64(ctx, fp1, ft);
11976 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11977 tcg_temp_free_i64(fp1);
11978 gen_store_fpr64(ctx, fp0, fd);
11979 tcg_temp_free_i64(fp0);
11982 break;
11983 case OPC_MINA_D: /* OPC_RECIP1_D */
11984 if (ctx->insn_flags & ISA_MIPS_R6) {
11985 /* OPC_MINA_D */
11986 TCGv_i64 fp0 = tcg_temp_new_i64();
11987 TCGv_i64 fp1 = tcg_temp_new_i64();
11988 gen_load_fpr64(ctx, fp0, fs);
11989 gen_load_fpr64(ctx, fp1, ft);
11990 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11991 gen_store_fpr64(ctx, fp1, fd);
11992 tcg_temp_free_i64(fp1);
11993 tcg_temp_free_i64(fp0);
11994 } else {
11995 /* OPC_RECIP1_D */
11996 check_cp1_64bitmode(ctx);
11998 TCGv_i64 fp0 = tcg_temp_new_i64();
12000 gen_load_fpr64(ctx, fp0, fs);
12001 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12002 gen_store_fpr64(ctx, fp0, fd);
12003 tcg_temp_free_i64(fp0);
12006 break;
12007 case OPC_MAX_D: /* OPC_RSQRT1_D */
12008 if (ctx->insn_flags & ISA_MIPS_R6) {
12009 /* OPC_MAX_D */
12010 TCGv_i64 fp0 = tcg_temp_new_i64();
12011 TCGv_i64 fp1 = tcg_temp_new_i64();
12012 gen_load_fpr64(ctx, fp0, fs);
12013 gen_load_fpr64(ctx, fp1, ft);
12014 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12015 gen_store_fpr64(ctx, fp1, fd);
12016 tcg_temp_free_i64(fp1);
12017 tcg_temp_free_i64(fp0);
12018 } else {
12019 /* OPC_RSQRT1_D */
12020 check_cp1_64bitmode(ctx);
12022 TCGv_i64 fp0 = tcg_temp_new_i64();
12024 gen_load_fpr64(ctx, fp0, fs);
12025 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12026 gen_store_fpr64(ctx, fp0, fd);
12027 tcg_temp_free_i64(fp0);
12030 break;
12031 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12032 if (ctx->insn_flags & ISA_MIPS_R6) {
12033 /* OPC_MAXA_D */
12034 TCGv_i64 fp0 = tcg_temp_new_i64();
12035 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_maxa_d(fp1, cpu_env, fp0, fp1);
12039 gen_store_fpr64(ctx, fp1, fd);
12040 tcg_temp_free_i64(fp1);
12041 tcg_temp_free_i64(fp0);
12042 } else {
12043 /* OPC_RSQRT2_D */
12044 check_cp1_64bitmode(ctx);
12046 TCGv_i64 fp0 = tcg_temp_new_i64();
12047 TCGv_i64 fp1 = tcg_temp_new_i64();
12049 gen_load_fpr64(ctx, fp0, fs);
12050 gen_load_fpr64(ctx, fp1, ft);
12051 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12052 tcg_temp_free_i64(fp1);
12053 gen_store_fpr64(ctx, fp0, fd);
12054 tcg_temp_free_i64(fp0);
12057 break;
12058 case OPC_CMP_F_D:
12059 case OPC_CMP_UN_D:
12060 case OPC_CMP_EQ_D:
12061 case OPC_CMP_UEQ_D:
12062 case OPC_CMP_OLT_D:
12063 case OPC_CMP_ULT_D:
12064 case OPC_CMP_OLE_D:
12065 case OPC_CMP_ULE_D:
12066 case OPC_CMP_SF_D:
12067 case OPC_CMP_NGLE_D:
12068 case OPC_CMP_SEQ_D:
12069 case OPC_CMP_NGL_D:
12070 case OPC_CMP_LT_D:
12071 case OPC_CMP_NGE_D:
12072 case OPC_CMP_LE_D:
12073 case OPC_CMP_NGT_D:
12074 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12075 if (ctx->opcode & (1 << 6)) {
12076 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12077 } else {
12078 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12080 break;
12081 case OPC_CVT_S_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 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12089 tcg_temp_free_i64(fp64);
12090 gen_store_fpr32(ctx, fp32, fd);
12091 tcg_temp_free_i32(fp32);
12093 break;
12094 case OPC_CVT_W_D:
12095 check_cp1_registers(ctx, fs);
12097 TCGv_i32 fp32 = tcg_temp_new_i32();
12098 TCGv_i64 fp64 = tcg_temp_new_i64();
12100 gen_load_fpr64(ctx, fp64, fs);
12101 if (ctx->nan2008) {
12102 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12103 } else {
12104 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12106 tcg_temp_free_i64(fp64);
12107 gen_store_fpr32(ctx, fp32, fd);
12108 tcg_temp_free_i32(fp32);
12110 break;
12111 case OPC_CVT_L_D:
12112 check_cp1_64bitmode(ctx);
12114 TCGv_i64 fp0 = tcg_temp_new_i64();
12116 gen_load_fpr64(ctx, fp0, fs);
12117 if (ctx->nan2008) {
12118 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12119 } else {
12120 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12122 gen_store_fpr64(ctx, fp0, fd);
12123 tcg_temp_free_i64(fp0);
12125 break;
12126 case OPC_CVT_S_W:
12128 TCGv_i32 fp0 = tcg_temp_new_i32();
12130 gen_load_fpr32(ctx, fp0, fs);
12131 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12132 gen_store_fpr32(ctx, fp0, fd);
12133 tcg_temp_free_i32(fp0);
12135 break;
12136 case OPC_CVT_D_W:
12137 check_cp1_registers(ctx, fd);
12139 TCGv_i32 fp32 = tcg_temp_new_i32();
12140 TCGv_i64 fp64 = tcg_temp_new_i64();
12142 gen_load_fpr32(ctx, fp32, fs);
12143 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12144 tcg_temp_free_i32(fp32);
12145 gen_store_fpr64(ctx, fp64, fd);
12146 tcg_temp_free_i64(fp64);
12148 break;
12149 case OPC_CVT_S_L:
12150 check_cp1_64bitmode(ctx);
12152 TCGv_i32 fp32 = tcg_temp_new_i32();
12153 TCGv_i64 fp64 = tcg_temp_new_i64();
12155 gen_load_fpr64(ctx, fp64, fs);
12156 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12157 tcg_temp_free_i64(fp64);
12158 gen_store_fpr32(ctx, fp32, fd);
12159 tcg_temp_free_i32(fp32);
12161 break;
12162 case OPC_CVT_D_L:
12163 check_cp1_64bitmode(ctx);
12165 TCGv_i64 fp0 = tcg_temp_new_i64();
12167 gen_load_fpr64(ctx, fp0, fs);
12168 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12169 gen_store_fpr64(ctx, fp0, fd);
12170 tcg_temp_free_i64(fp0);
12172 break;
12173 case OPC_CVT_PS_PW:
12174 check_ps(ctx);
12176 TCGv_i64 fp0 = tcg_temp_new_i64();
12178 gen_load_fpr64(ctx, fp0, fs);
12179 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12180 gen_store_fpr64(ctx, fp0, fd);
12181 tcg_temp_free_i64(fp0);
12183 break;
12184 case OPC_ADD_PS:
12185 check_ps(ctx);
12187 TCGv_i64 fp0 = tcg_temp_new_i64();
12188 TCGv_i64 fp1 = tcg_temp_new_i64();
12190 gen_load_fpr64(ctx, fp0, fs);
12191 gen_load_fpr64(ctx, fp1, ft);
12192 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12193 tcg_temp_free_i64(fp1);
12194 gen_store_fpr64(ctx, fp0, fd);
12195 tcg_temp_free_i64(fp0);
12197 break;
12198 case OPC_SUB_PS:
12199 check_ps(ctx);
12201 TCGv_i64 fp0 = tcg_temp_new_i64();
12202 TCGv_i64 fp1 = tcg_temp_new_i64();
12204 gen_load_fpr64(ctx, fp0, fs);
12205 gen_load_fpr64(ctx, fp1, ft);
12206 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12207 tcg_temp_free_i64(fp1);
12208 gen_store_fpr64(ctx, fp0, fd);
12209 tcg_temp_free_i64(fp0);
12211 break;
12212 case OPC_MUL_PS:
12213 check_ps(ctx);
12215 TCGv_i64 fp0 = tcg_temp_new_i64();
12216 TCGv_i64 fp1 = tcg_temp_new_i64();
12218 gen_load_fpr64(ctx, fp0, fs);
12219 gen_load_fpr64(ctx, fp1, ft);
12220 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12221 tcg_temp_free_i64(fp1);
12222 gen_store_fpr64(ctx, fp0, fd);
12223 tcg_temp_free_i64(fp0);
12225 break;
12226 case OPC_ABS_PS:
12227 check_ps(ctx);
12229 TCGv_i64 fp0 = tcg_temp_new_i64();
12231 gen_load_fpr64(ctx, fp0, fs);
12232 gen_helper_float_abs_ps(fp0, fp0);
12233 gen_store_fpr64(ctx, fp0, fd);
12234 tcg_temp_free_i64(fp0);
12236 break;
12237 case OPC_MOV_PS:
12238 check_ps(ctx);
12240 TCGv_i64 fp0 = tcg_temp_new_i64();
12242 gen_load_fpr64(ctx, fp0, fs);
12243 gen_store_fpr64(ctx, fp0, fd);
12244 tcg_temp_free_i64(fp0);
12246 break;
12247 case OPC_NEG_PS:
12248 check_ps(ctx);
12250 TCGv_i64 fp0 = tcg_temp_new_i64();
12252 gen_load_fpr64(ctx, fp0, fs);
12253 gen_helper_float_chs_ps(fp0, fp0);
12254 gen_store_fpr64(ctx, fp0, fd);
12255 tcg_temp_free_i64(fp0);
12257 break;
12258 case OPC_MOVCF_PS:
12259 check_ps(ctx);
12260 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12261 break;
12262 case OPC_MOVZ_PS:
12263 check_ps(ctx);
12265 TCGLabel *l1 = gen_new_label();
12266 TCGv_i64 fp0;
12268 if (ft != 0) {
12269 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12271 fp0 = tcg_temp_new_i64();
12272 gen_load_fpr64(ctx, fp0, fs);
12273 gen_store_fpr64(ctx, fp0, fd);
12274 tcg_temp_free_i64(fp0);
12275 gen_set_label(l1);
12277 break;
12278 case OPC_MOVN_PS:
12279 check_ps(ctx);
12281 TCGLabel *l1 = gen_new_label();
12282 TCGv_i64 fp0;
12284 if (ft != 0) {
12285 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12286 fp0 = tcg_temp_new_i64();
12287 gen_load_fpr64(ctx, fp0, fs);
12288 gen_store_fpr64(ctx, fp0, fd);
12289 tcg_temp_free_i64(fp0);
12290 gen_set_label(l1);
12293 break;
12294 case OPC_ADDR_PS:
12295 check_ps(ctx);
12297 TCGv_i64 fp0 = tcg_temp_new_i64();
12298 TCGv_i64 fp1 = tcg_temp_new_i64();
12300 gen_load_fpr64(ctx, fp0, ft);
12301 gen_load_fpr64(ctx, fp1, fs);
12302 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12303 tcg_temp_free_i64(fp1);
12304 gen_store_fpr64(ctx, fp0, fd);
12305 tcg_temp_free_i64(fp0);
12307 break;
12308 case OPC_MULR_PS:
12309 check_ps(ctx);
12311 TCGv_i64 fp0 = tcg_temp_new_i64();
12312 TCGv_i64 fp1 = tcg_temp_new_i64();
12314 gen_load_fpr64(ctx, fp0, ft);
12315 gen_load_fpr64(ctx, fp1, fs);
12316 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12317 tcg_temp_free_i64(fp1);
12318 gen_store_fpr64(ctx, fp0, fd);
12319 tcg_temp_free_i64(fp0);
12321 break;
12322 case OPC_RECIP2_PS:
12323 check_ps(ctx);
12325 TCGv_i64 fp0 = tcg_temp_new_i64();
12326 TCGv_i64 fp1 = tcg_temp_new_i64();
12328 gen_load_fpr64(ctx, fp0, fs);
12329 gen_load_fpr64(ctx, fp1, ft);
12330 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12331 tcg_temp_free_i64(fp1);
12332 gen_store_fpr64(ctx, fp0, fd);
12333 tcg_temp_free_i64(fp0);
12335 break;
12336 case OPC_RECIP1_PS:
12337 check_ps(ctx);
12339 TCGv_i64 fp0 = tcg_temp_new_i64();
12341 gen_load_fpr64(ctx, fp0, fs);
12342 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12343 gen_store_fpr64(ctx, fp0, fd);
12344 tcg_temp_free_i64(fp0);
12346 break;
12347 case OPC_RSQRT1_PS:
12348 check_ps(ctx);
12350 TCGv_i64 fp0 = tcg_temp_new_i64();
12352 gen_load_fpr64(ctx, fp0, fs);
12353 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12354 gen_store_fpr64(ctx, fp0, fd);
12355 tcg_temp_free_i64(fp0);
12357 break;
12358 case OPC_RSQRT2_PS:
12359 check_ps(ctx);
12361 TCGv_i64 fp0 = tcg_temp_new_i64();
12362 TCGv_i64 fp1 = tcg_temp_new_i64();
12364 gen_load_fpr64(ctx, fp0, fs);
12365 gen_load_fpr64(ctx, fp1, ft);
12366 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12367 tcg_temp_free_i64(fp1);
12368 gen_store_fpr64(ctx, fp0, fd);
12369 tcg_temp_free_i64(fp0);
12371 break;
12372 case OPC_CVT_S_PU:
12373 check_cp1_64bitmode(ctx);
12375 TCGv_i32 fp0 = tcg_temp_new_i32();
12377 gen_load_fpr32h(ctx, fp0, fs);
12378 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12379 gen_store_fpr32(ctx, fp0, fd);
12380 tcg_temp_free_i32(fp0);
12382 break;
12383 case OPC_CVT_PW_PS:
12384 check_ps(ctx);
12386 TCGv_i64 fp0 = tcg_temp_new_i64();
12388 gen_load_fpr64(ctx, fp0, fs);
12389 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12390 gen_store_fpr64(ctx, fp0, fd);
12391 tcg_temp_free_i64(fp0);
12393 break;
12394 case OPC_CVT_S_PL:
12395 check_cp1_64bitmode(ctx);
12397 TCGv_i32 fp0 = tcg_temp_new_i32();
12399 gen_load_fpr32(ctx, fp0, fs);
12400 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12401 gen_store_fpr32(ctx, fp0, fd);
12402 tcg_temp_free_i32(fp0);
12404 break;
12405 case OPC_PLL_PS:
12406 check_ps(ctx);
12408 TCGv_i32 fp0 = tcg_temp_new_i32();
12409 TCGv_i32 fp1 = tcg_temp_new_i32();
12411 gen_load_fpr32(ctx, fp0, fs);
12412 gen_load_fpr32(ctx, fp1, ft);
12413 gen_store_fpr32h(ctx, fp0, fd);
12414 gen_store_fpr32(ctx, fp1, fd);
12415 tcg_temp_free_i32(fp0);
12416 tcg_temp_free_i32(fp1);
12418 break;
12419 case OPC_PLU_PS:
12420 check_ps(ctx);
12422 TCGv_i32 fp0 = tcg_temp_new_i32();
12423 TCGv_i32 fp1 = tcg_temp_new_i32();
12425 gen_load_fpr32(ctx, fp0, fs);
12426 gen_load_fpr32h(ctx, fp1, ft);
12427 gen_store_fpr32(ctx, fp1, fd);
12428 gen_store_fpr32h(ctx, fp0, fd);
12429 tcg_temp_free_i32(fp0);
12430 tcg_temp_free_i32(fp1);
12432 break;
12433 case OPC_PUL_PS:
12434 check_ps(ctx);
12436 TCGv_i32 fp0 = tcg_temp_new_i32();
12437 TCGv_i32 fp1 = tcg_temp_new_i32();
12439 gen_load_fpr32h(ctx, fp0, fs);
12440 gen_load_fpr32(ctx, fp1, ft);
12441 gen_store_fpr32(ctx, fp1, fd);
12442 gen_store_fpr32h(ctx, fp0, fd);
12443 tcg_temp_free_i32(fp0);
12444 tcg_temp_free_i32(fp1);
12446 break;
12447 case OPC_PUU_PS:
12448 check_ps(ctx);
12450 TCGv_i32 fp0 = tcg_temp_new_i32();
12451 TCGv_i32 fp1 = tcg_temp_new_i32();
12453 gen_load_fpr32h(ctx, fp0, fs);
12454 gen_load_fpr32h(ctx, fp1, ft);
12455 gen_store_fpr32(ctx, fp1, fd);
12456 gen_store_fpr32h(ctx, fp0, fd);
12457 tcg_temp_free_i32(fp0);
12458 tcg_temp_free_i32(fp1);
12460 break;
12461 case OPC_CMP_F_PS:
12462 case OPC_CMP_UN_PS:
12463 case OPC_CMP_EQ_PS:
12464 case OPC_CMP_UEQ_PS:
12465 case OPC_CMP_OLT_PS:
12466 case OPC_CMP_ULT_PS:
12467 case OPC_CMP_OLE_PS:
12468 case OPC_CMP_ULE_PS:
12469 case OPC_CMP_SF_PS:
12470 case OPC_CMP_NGLE_PS:
12471 case OPC_CMP_SEQ_PS:
12472 case OPC_CMP_NGL_PS:
12473 case OPC_CMP_LT_PS:
12474 case OPC_CMP_NGE_PS:
12475 case OPC_CMP_LE_PS:
12476 case OPC_CMP_NGT_PS:
12477 if (ctx->opcode & (1 << 6)) {
12478 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
12479 } else {
12480 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
12482 break;
12483 default:
12484 MIPS_INVAL("farith");
12485 gen_reserved_instruction(ctx);
12486 return;
12490 /* Coprocessor 3 (FPU) */
12491 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12492 int fd, int fs, int base, int index)
12494 TCGv t0 = tcg_temp_new();
12496 if (base == 0) {
12497 gen_load_gpr(t0, index);
12498 } else if (index == 0) {
12499 gen_load_gpr(t0, base);
12500 } else {
12501 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12504 * Don't do NOP if destination is zero: we must perform the actual
12505 * memory access.
12507 switch (opc) {
12508 case OPC_LWXC1:
12509 check_cop1x(ctx);
12511 TCGv_i32 fp0 = tcg_temp_new_i32();
12513 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12514 tcg_gen_trunc_tl_i32(fp0, t0);
12515 gen_store_fpr32(ctx, fp0, fd);
12516 tcg_temp_free_i32(fp0);
12518 break;
12519 case OPC_LDXC1:
12520 check_cop1x(ctx);
12521 check_cp1_registers(ctx, fd);
12523 TCGv_i64 fp0 = tcg_temp_new_i64();
12524 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12525 gen_store_fpr64(ctx, fp0, fd);
12526 tcg_temp_free_i64(fp0);
12528 break;
12529 case OPC_LUXC1:
12530 check_cp1_64bitmode(ctx);
12531 tcg_gen_andi_tl(t0, t0, ~0x7);
12533 TCGv_i64 fp0 = tcg_temp_new_i64();
12535 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12536 gen_store_fpr64(ctx, fp0, fd);
12537 tcg_temp_free_i64(fp0);
12539 break;
12540 case OPC_SWXC1:
12541 check_cop1x(ctx);
12543 TCGv_i32 fp0 = tcg_temp_new_i32();
12544 gen_load_fpr32(ctx, fp0, fs);
12545 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12546 tcg_temp_free_i32(fp0);
12548 break;
12549 case OPC_SDXC1:
12550 check_cop1x(ctx);
12551 check_cp1_registers(ctx, fs);
12553 TCGv_i64 fp0 = tcg_temp_new_i64();
12554 gen_load_fpr64(ctx, fp0, fs);
12555 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12556 tcg_temp_free_i64(fp0);
12558 break;
12559 case OPC_SUXC1:
12560 check_cp1_64bitmode(ctx);
12561 tcg_gen_andi_tl(t0, t0, ~0x7);
12563 TCGv_i64 fp0 = tcg_temp_new_i64();
12564 gen_load_fpr64(ctx, fp0, fs);
12565 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12566 tcg_temp_free_i64(fp0);
12568 break;
12570 tcg_temp_free(t0);
12573 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12574 int fd, int fr, int fs, int ft)
12576 switch (opc) {
12577 case OPC_ALNV_PS:
12578 check_ps(ctx);
12580 TCGv t0 = tcg_temp_local_new();
12581 TCGv_i32 fp = tcg_temp_new_i32();
12582 TCGv_i32 fph = tcg_temp_new_i32();
12583 TCGLabel *l1 = gen_new_label();
12584 TCGLabel *l2 = gen_new_label();
12586 gen_load_gpr(t0, fr);
12587 tcg_gen_andi_tl(t0, t0, 0x7);
12589 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12590 gen_load_fpr32(ctx, fp, fs);
12591 gen_load_fpr32h(ctx, fph, fs);
12592 gen_store_fpr32(ctx, fp, fd);
12593 gen_store_fpr32h(ctx, fph, fd);
12594 tcg_gen_br(l2);
12595 gen_set_label(l1);
12596 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12597 tcg_temp_free(t0);
12598 #ifdef TARGET_WORDS_BIGENDIAN
12599 gen_load_fpr32(ctx, fp, fs);
12600 gen_load_fpr32h(ctx, fph, ft);
12601 gen_store_fpr32h(ctx, fp, fd);
12602 gen_store_fpr32(ctx, fph, fd);
12603 #else
12604 gen_load_fpr32h(ctx, fph, fs);
12605 gen_load_fpr32(ctx, fp, ft);
12606 gen_store_fpr32(ctx, fph, fd);
12607 gen_store_fpr32h(ctx, fp, fd);
12608 #endif
12609 gen_set_label(l2);
12610 tcg_temp_free_i32(fp);
12611 tcg_temp_free_i32(fph);
12613 break;
12614 case OPC_MADD_S:
12615 check_cop1x(ctx);
12617 TCGv_i32 fp0 = tcg_temp_new_i32();
12618 TCGv_i32 fp1 = tcg_temp_new_i32();
12619 TCGv_i32 fp2 = tcg_temp_new_i32();
12621 gen_load_fpr32(ctx, fp0, fs);
12622 gen_load_fpr32(ctx, fp1, ft);
12623 gen_load_fpr32(ctx, fp2, fr);
12624 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12625 tcg_temp_free_i32(fp0);
12626 tcg_temp_free_i32(fp1);
12627 gen_store_fpr32(ctx, fp2, fd);
12628 tcg_temp_free_i32(fp2);
12630 break;
12631 case OPC_MADD_D:
12632 check_cop1x(ctx);
12633 check_cp1_registers(ctx, fd | fs | ft | fr);
12635 TCGv_i64 fp0 = tcg_temp_new_i64();
12636 TCGv_i64 fp1 = tcg_temp_new_i64();
12637 TCGv_i64 fp2 = tcg_temp_new_i64();
12639 gen_load_fpr64(ctx, fp0, fs);
12640 gen_load_fpr64(ctx, fp1, ft);
12641 gen_load_fpr64(ctx, fp2, fr);
12642 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12643 tcg_temp_free_i64(fp0);
12644 tcg_temp_free_i64(fp1);
12645 gen_store_fpr64(ctx, fp2, fd);
12646 tcg_temp_free_i64(fp2);
12648 break;
12649 case OPC_MADD_PS:
12650 check_ps(ctx);
12652 TCGv_i64 fp0 = tcg_temp_new_i64();
12653 TCGv_i64 fp1 = tcg_temp_new_i64();
12654 TCGv_i64 fp2 = tcg_temp_new_i64();
12656 gen_load_fpr64(ctx, fp0, fs);
12657 gen_load_fpr64(ctx, fp1, ft);
12658 gen_load_fpr64(ctx, fp2, fr);
12659 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12660 tcg_temp_free_i64(fp0);
12661 tcg_temp_free_i64(fp1);
12662 gen_store_fpr64(ctx, fp2, fd);
12663 tcg_temp_free_i64(fp2);
12665 break;
12666 case OPC_MSUB_S:
12667 check_cop1x(ctx);
12669 TCGv_i32 fp0 = tcg_temp_new_i32();
12670 TCGv_i32 fp1 = tcg_temp_new_i32();
12671 TCGv_i32 fp2 = tcg_temp_new_i32();
12673 gen_load_fpr32(ctx, fp0, fs);
12674 gen_load_fpr32(ctx, fp1, ft);
12675 gen_load_fpr32(ctx, fp2, fr);
12676 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12677 tcg_temp_free_i32(fp0);
12678 tcg_temp_free_i32(fp1);
12679 gen_store_fpr32(ctx, fp2, fd);
12680 tcg_temp_free_i32(fp2);
12682 break;
12683 case OPC_MSUB_D:
12684 check_cop1x(ctx);
12685 check_cp1_registers(ctx, fd | fs | ft | fr);
12687 TCGv_i64 fp0 = tcg_temp_new_i64();
12688 TCGv_i64 fp1 = tcg_temp_new_i64();
12689 TCGv_i64 fp2 = tcg_temp_new_i64();
12691 gen_load_fpr64(ctx, fp0, fs);
12692 gen_load_fpr64(ctx, fp1, ft);
12693 gen_load_fpr64(ctx, fp2, fr);
12694 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12695 tcg_temp_free_i64(fp0);
12696 tcg_temp_free_i64(fp1);
12697 gen_store_fpr64(ctx, fp2, fd);
12698 tcg_temp_free_i64(fp2);
12700 break;
12701 case OPC_MSUB_PS:
12702 check_ps(ctx);
12704 TCGv_i64 fp0 = tcg_temp_new_i64();
12705 TCGv_i64 fp1 = tcg_temp_new_i64();
12706 TCGv_i64 fp2 = tcg_temp_new_i64();
12708 gen_load_fpr64(ctx, fp0, fs);
12709 gen_load_fpr64(ctx, fp1, ft);
12710 gen_load_fpr64(ctx, fp2, fr);
12711 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12712 tcg_temp_free_i64(fp0);
12713 tcg_temp_free_i64(fp1);
12714 gen_store_fpr64(ctx, fp2, fd);
12715 tcg_temp_free_i64(fp2);
12717 break;
12718 case OPC_NMADD_S:
12719 check_cop1x(ctx);
12721 TCGv_i32 fp0 = tcg_temp_new_i32();
12722 TCGv_i32 fp1 = tcg_temp_new_i32();
12723 TCGv_i32 fp2 = tcg_temp_new_i32();
12725 gen_load_fpr32(ctx, fp0, fs);
12726 gen_load_fpr32(ctx, fp1, ft);
12727 gen_load_fpr32(ctx, fp2, fr);
12728 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12729 tcg_temp_free_i32(fp0);
12730 tcg_temp_free_i32(fp1);
12731 gen_store_fpr32(ctx, fp2, fd);
12732 tcg_temp_free_i32(fp2);
12734 break;
12735 case OPC_NMADD_D:
12736 check_cop1x(ctx);
12737 check_cp1_registers(ctx, fd | fs | ft | fr);
12739 TCGv_i64 fp0 = tcg_temp_new_i64();
12740 TCGv_i64 fp1 = tcg_temp_new_i64();
12741 TCGv_i64 fp2 = tcg_temp_new_i64();
12743 gen_load_fpr64(ctx, fp0, fs);
12744 gen_load_fpr64(ctx, fp1, ft);
12745 gen_load_fpr64(ctx, fp2, fr);
12746 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12747 tcg_temp_free_i64(fp0);
12748 tcg_temp_free_i64(fp1);
12749 gen_store_fpr64(ctx, fp2, fd);
12750 tcg_temp_free_i64(fp2);
12752 break;
12753 case OPC_NMADD_PS:
12754 check_ps(ctx);
12756 TCGv_i64 fp0 = tcg_temp_new_i64();
12757 TCGv_i64 fp1 = tcg_temp_new_i64();
12758 TCGv_i64 fp2 = tcg_temp_new_i64();
12760 gen_load_fpr64(ctx, fp0, fs);
12761 gen_load_fpr64(ctx, fp1, ft);
12762 gen_load_fpr64(ctx, fp2, fr);
12763 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12764 tcg_temp_free_i64(fp0);
12765 tcg_temp_free_i64(fp1);
12766 gen_store_fpr64(ctx, fp2, fd);
12767 tcg_temp_free_i64(fp2);
12769 break;
12770 case OPC_NMSUB_S:
12771 check_cop1x(ctx);
12773 TCGv_i32 fp0 = tcg_temp_new_i32();
12774 TCGv_i32 fp1 = tcg_temp_new_i32();
12775 TCGv_i32 fp2 = tcg_temp_new_i32();
12777 gen_load_fpr32(ctx, fp0, fs);
12778 gen_load_fpr32(ctx, fp1, ft);
12779 gen_load_fpr32(ctx, fp2, fr);
12780 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12781 tcg_temp_free_i32(fp0);
12782 tcg_temp_free_i32(fp1);
12783 gen_store_fpr32(ctx, fp2, fd);
12784 tcg_temp_free_i32(fp2);
12786 break;
12787 case OPC_NMSUB_D:
12788 check_cop1x(ctx);
12789 check_cp1_registers(ctx, fd | fs | ft | fr);
12791 TCGv_i64 fp0 = tcg_temp_new_i64();
12792 TCGv_i64 fp1 = tcg_temp_new_i64();
12793 TCGv_i64 fp2 = tcg_temp_new_i64();
12795 gen_load_fpr64(ctx, fp0, fs);
12796 gen_load_fpr64(ctx, fp1, ft);
12797 gen_load_fpr64(ctx, fp2, fr);
12798 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12799 tcg_temp_free_i64(fp0);
12800 tcg_temp_free_i64(fp1);
12801 gen_store_fpr64(ctx, fp2, fd);
12802 tcg_temp_free_i64(fp2);
12804 break;
12805 case OPC_NMSUB_PS:
12806 check_ps(ctx);
12808 TCGv_i64 fp0 = tcg_temp_new_i64();
12809 TCGv_i64 fp1 = tcg_temp_new_i64();
12810 TCGv_i64 fp2 = tcg_temp_new_i64();
12812 gen_load_fpr64(ctx, fp0, fs);
12813 gen_load_fpr64(ctx, fp1, ft);
12814 gen_load_fpr64(ctx, fp2, fr);
12815 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12816 tcg_temp_free_i64(fp0);
12817 tcg_temp_free_i64(fp1);
12818 gen_store_fpr64(ctx, fp2, fd);
12819 tcg_temp_free_i64(fp2);
12821 break;
12822 default:
12823 MIPS_INVAL("flt3_arith");
12824 gen_reserved_instruction(ctx);
12825 return;
12829 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12831 TCGv t0;
12833 #if !defined(CONFIG_USER_ONLY)
12835 * The Linux kernel will emulate rdhwr if it's not supported natively.
12836 * Therefore only check the ISA in system mode.
12838 check_insn(ctx, ISA_MIPS_R2);
12839 #endif
12840 t0 = tcg_temp_new();
12842 switch (rd) {
12843 case 0:
12844 gen_helper_rdhwr_cpunum(t0, cpu_env);
12845 gen_store_gpr(t0, rt);
12846 break;
12847 case 1:
12848 gen_helper_rdhwr_synci_step(t0, cpu_env);
12849 gen_store_gpr(t0, rt);
12850 break;
12851 case 2:
12852 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12853 gen_io_start();
12855 gen_helper_rdhwr_cc(t0, cpu_env);
12856 gen_store_gpr(t0, rt);
12858 * Break the TB to be able to take timer interrupts immediately
12859 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12860 * we break completely out of translated code.
12862 gen_save_pc(ctx->base.pc_next + 4);
12863 ctx->base.is_jmp = DISAS_EXIT;
12864 break;
12865 case 3:
12866 gen_helper_rdhwr_ccres(t0, cpu_env);
12867 gen_store_gpr(t0, rt);
12868 break;
12869 case 4:
12870 check_insn(ctx, ISA_MIPS_R6);
12871 if (sel != 0) {
12873 * Performance counter registers are not implemented other than
12874 * control register 0.
12876 generate_exception(ctx, EXCP_RI);
12878 gen_helper_rdhwr_performance(t0, cpu_env);
12879 gen_store_gpr(t0, rt);
12880 break;
12881 case 5:
12882 check_insn(ctx, ISA_MIPS_R6);
12883 gen_helper_rdhwr_xnp(t0, cpu_env);
12884 gen_store_gpr(t0, rt);
12885 break;
12886 case 29:
12887 #if defined(CONFIG_USER_ONLY)
12888 tcg_gen_ld_tl(t0, cpu_env,
12889 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12890 gen_store_gpr(t0, rt);
12891 break;
12892 #else
12893 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12894 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12895 tcg_gen_ld_tl(t0, cpu_env,
12896 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12897 gen_store_gpr(t0, rt);
12898 } else {
12899 gen_reserved_instruction(ctx);
12901 break;
12902 #endif
12903 default: /* Invalid */
12904 MIPS_INVAL("rdhwr");
12905 gen_reserved_instruction(ctx);
12906 break;
12908 tcg_temp_free(t0);
12911 static inline void clear_branch_hflags(DisasContext *ctx)
12913 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12914 if (ctx->base.is_jmp == DISAS_NEXT) {
12915 save_cpu_state(ctx, 0);
12916 } else {
12918 * It is not safe to save ctx->hflags as hflags may be changed
12919 * in execution time by the instruction in delay / forbidden slot.
12921 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12925 static void gen_branch(DisasContext *ctx, int insn_bytes)
12927 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12928 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12929 /* Branches completion */
12930 clear_branch_hflags(ctx);
12931 ctx->base.is_jmp = DISAS_NORETURN;
12932 /* FIXME: Need to clear can_do_io. */
12933 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12934 case MIPS_HFLAG_FBNSLOT:
12935 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12936 break;
12937 case MIPS_HFLAG_B:
12938 /* unconditional branch */
12939 if (proc_hflags & MIPS_HFLAG_BX) {
12940 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12942 gen_goto_tb(ctx, 0, ctx->btarget);
12943 break;
12944 case MIPS_HFLAG_BL:
12945 /* blikely taken case */
12946 gen_goto_tb(ctx, 0, ctx->btarget);
12947 break;
12948 case MIPS_HFLAG_BC:
12949 /* Conditional branch */
12951 TCGLabel *l1 = gen_new_label();
12953 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12954 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12955 gen_set_label(l1);
12956 gen_goto_tb(ctx, 0, ctx->btarget);
12958 break;
12959 case MIPS_HFLAG_BR:
12960 /* unconditional branch to register */
12961 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12962 TCGv t0 = tcg_temp_new();
12963 TCGv_i32 t1 = tcg_temp_new_i32();
12965 tcg_gen_andi_tl(t0, btarget, 0x1);
12966 tcg_gen_trunc_tl_i32(t1, t0);
12967 tcg_temp_free(t0);
12968 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12969 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12970 tcg_gen_or_i32(hflags, hflags, t1);
12971 tcg_temp_free_i32(t1);
12973 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12974 } else {
12975 tcg_gen_mov_tl(cpu_PC, btarget);
12977 if (ctx->base.singlestep_enabled) {
12978 save_cpu_state(ctx, 0);
12979 gen_helper_raise_exception_debug(cpu_env);
12981 tcg_gen_lookup_and_goto_ptr();
12982 break;
12983 default:
12984 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12985 abort();
12990 /* Compact Branches */
12991 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12992 int rs, int rt, int32_t offset)
12994 int bcond_compute = 0;
12995 TCGv t0 = tcg_temp_new();
12996 TCGv t1 = tcg_temp_new();
12997 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12999 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13000 #ifdef MIPS_DEBUG_DISAS
13001 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
13002 "\n", ctx->base.pc_next);
13003 #endif
13004 gen_reserved_instruction(ctx);
13005 goto out;
13008 /* Load needed operands and calculate btarget */
13009 switch (opc) {
13010 /* compact branch */
13011 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13012 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13013 gen_load_gpr(t0, rs);
13014 gen_load_gpr(t1, rt);
13015 bcond_compute = 1;
13016 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13017 if (rs <= rt && rs == 0) {
13018 /* OPC_BEQZALC, OPC_BNEZALC */
13019 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13021 break;
13022 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13023 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13024 gen_load_gpr(t0, rs);
13025 gen_load_gpr(t1, rt);
13026 bcond_compute = 1;
13027 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13028 break;
13029 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13030 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13031 if (rs == 0 || rs == rt) {
13032 /* OPC_BLEZALC, OPC_BGEZALC */
13033 /* OPC_BGTZALC, OPC_BLTZALC */
13034 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13036 gen_load_gpr(t0, rs);
13037 gen_load_gpr(t1, rt);
13038 bcond_compute = 1;
13039 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13040 break;
13041 case OPC_BC:
13042 case OPC_BALC:
13043 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13044 break;
13045 case OPC_BEQZC:
13046 case OPC_BNEZC:
13047 if (rs != 0) {
13048 /* OPC_BEQZC, OPC_BNEZC */
13049 gen_load_gpr(t0, rs);
13050 bcond_compute = 1;
13051 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13052 } else {
13053 /* OPC_JIC, OPC_JIALC */
13054 TCGv tbase = tcg_temp_new();
13055 TCGv toffset = tcg_temp_new();
13057 gen_load_gpr(tbase, rt);
13058 tcg_gen_movi_tl(toffset, offset);
13059 gen_op_addr_add(ctx, btarget, tbase, toffset);
13060 tcg_temp_free(tbase);
13061 tcg_temp_free(toffset);
13063 break;
13064 default:
13065 MIPS_INVAL("Compact branch/jump");
13066 gen_reserved_instruction(ctx);
13067 goto out;
13070 if (bcond_compute == 0) {
13071 /* Uncoditional compact branch */
13072 switch (opc) {
13073 case OPC_JIALC:
13074 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13075 /* Fallthrough */
13076 case OPC_JIC:
13077 ctx->hflags |= MIPS_HFLAG_BR;
13078 break;
13079 case OPC_BALC:
13080 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13081 /* Fallthrough */
13082 case OPC_BC:
13083 ctx->hflags |= MIPS_HFLAG_B;
13084 break;
13085 default:
13086 MIPS_INVAL("Compact branch/jump");
13087 gen_reserved_instruction(ctx);
13088 goto out;
13091 /* Generating branch here as compact branches don't have delay slot */
13092 gen_branch(ctx, 4);
13093 } else {
13094 /* Conditional compact branch */
13095 TCGLabel *fs = gen_new_label();
13096 save_cpu_state(ctx, 0);
13098 switch (opc) {
13099 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13100 if (rs == 0 && rt != 0) {
13101 /* OPC_BLEZALC */
13102 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13103 } else if (rs != 0 && rt != 0 && rs == rt) {
13104 /* OPC_BGEZALC */
13105 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13106 } else {
13107 /* OPC_BGEUC */
13108 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13110 break;
13111 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13112 if (rs == 0 && rt != 0) {
13113 /* OPC_BGTZALC */
13114 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13115 } else if (rs != 0 && rt != 0 && rs == rt) {
13116 /* OPC_BLTZALC */
13117 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13118 } else {
13119 /* OPC_BLTUC */
13120 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13122 break;
13123 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13124 if (rs == 0 && rt != 0) {
13125 /* OPC_BLEZC */
13126 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13127 } else if (rs != 0 && rt != 0 && rs == rt) {
13128 /* OPC_BGEZC */
13129 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13130 } else {
13131 /* OPC_BGEC */
13132 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13134 break;
13135 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13136 if (rs == 0 && rt != 0) {
13137 /* OPC_BGTZC */
13138 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13139 } else if (rs != 0 && rt != 0 && rs == rt) {
13140 /* OPC_BLTZC */
13141 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13142 } else {
13143 /* OPC_BLTC */
13144 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13146 break;
13147 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13148 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13149 if (rs >= rt) {
13150 /* OPC_BOVC, OPC_BNVC */
13151 TCGv t2 = tcg_temp_new();
13152 TCGv t3 = tcg_temp_new();
13153 TCGv t4 = tcg_temp_new();
13154 TCGv input_overflow = tcg_temp_new();
13156 gen_load_gpr(t0, rs);
13157 gen_load_gpr(t1, rt);
13158 tcg_gen_ext32s_tl(t2, t0);
13159 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13160 tcg_gen_ext32s_tl(t3, t1);
13161 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13162 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13164 tcg_gen_add_tl(t4, t2, t3);
13165 tcg_gen_ext32s_tl(t4, t4);
13166 tcg_gen_xor_tl(t2, t2, t3);
13167 tcg_gen_xor_tl(t3, t4, t3);
13168 tcg_gen_andc_tl(t2, t3, t2);
13169 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13170 tcg_gen_or_tl(t4, t4, input_overflow);
13171 if (opc == OPC_BOVC) {
13172 /* OPC_BOVC */
13173 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13174 } else {
13175 /* OPC_BNVC */
13176 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13178 tcg_temp_free(input_overflow);
13179 tcg_temp_free(t4);
13180 tcg_temp_free(t3);
13181 tcg_temp_free(t2);
13182 } else if (rs < rt && rs == 0) {
13183 /* OPC_BEQZALC, OPC_BNEZALC */
13184 if (opc == OPC_BEQZALC) {
13185 /* OPC_BEQZALC */
13186 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13187 } else {
13188 /* OPC_BNEZALC */
13189 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13191 } else {
13192 /* OPC_BEQC, OPC_BNEC */
13193 if (opc == OPC_BEQC) {
13194 /* OPC_BEQC */
13195 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13196 } else {
13197 /* OPC_BNEC */
13198 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13201 break;
13202 case OPC_BEQZC:
13203 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13204 break;
13205 case OPC_BNEZC:
13206 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13207 break;
13208 default:
13209 MIPS_INVAL("Compact conditional branch/jump");
13210 gen_reserved_instruction(ctx);
13211 goto out;
13214 /* Generating branch here as compact branches don't have delay slot */
13215 gen_goto_tb(ctx, 1, ctx->btarget);
13216 gen_set_label(fs);
13218 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13221 out:
13222 tcg_temp_free(t0);
13223 tcg_temp_free(t1);
13226 /* ISA extensions (ASEs) */
13227 /* MIPS16 extension to MIPS32 */
13229 /* MIPS16 major opcodes */
13230 enum {
13231 M16_OPC_ADDIUSP = 0x00,
13232 M16_OPC_ADDIUPC = 0x01,
13233 M16_OPC_B = 0x02,
13234 M16_OPC_JAL = 0x03,
13235 M16_OPC_BEQZ = 0x04,
13236 M16_OPC_BNEQZ = 0x05,
13237 M16_OPC_SHIFT = 0x06,
13238 M16_OPC_LD = 0x07,
13239 M16_OPC_RRIA = 0x08,
13240 M16_OPC_ADDIU8 = 0x09,
13241 M16_OPC_SLTI = 0x0a,
13242 M16_OPC_SLTIU = 0x0b,
13243 M16_OPC_I8 = 0x0c,
13244 M16_OPC_LI = 0x0d,
13245 M16_OPC_CMPI = 0x0e,
13246 M16_OPC_SD = 0x0f,
13247 M16_OPC_LB = 0x10,
13248 M16_OPC_LH = 0x11,
13249 M16_OPC_LWSP = 0x12,
13250 M16_OPC_LW = 0x13,
13251 M16_OPC_LBU = 0x14,
13252 M16_OPC_LHU = 0x15,
13253 M16_OPC_LWPC = 0x16,
13254 M16_OPC_LWU = 0x17,
13255 M16_OPC_SB = 0x18,
13256 M16_OPC_SH = 0x19,
13257 M16_OPC_SWSP = 0x1a,
13258 M16_OPC_SW = 0x1b,
13259 M16_OPC_RRR = 0x1c,
13260 M16_OPC_RR = 0x1d,
13261 M16_OPC_EXTEND = 0x1e,
13262 M16_OPC_I64 = 0x1f
13265 /* I8 funct field */
13266 enum {
13267 I8_BTEQZ = 0x0,
13268 I8_BTNEZ = 0x1,
13269 I8_SWRASP = 0x2,
13270 I8_ADJSP = 0x3,
13271 I8_SVRS = 0x4,
13272 I8_MOV32R = 0x5,
13273 I8_MOVR32 = 0x7
13276 /* RRR f field */
13277 enum {
13278 RRR_DADDU = 0x0,
13279 RRR_ADDU = 0x1,
13280 RRR_DSUBU = 0x2,
13281 RRR_SUBU = 0x3
13284 /* RR funct field */
13285 enum {
13286 RR_JR = 0x00,
13287 RR_SDBBP = 0x01,
13288 RR_SLT = 0x02,
13289 RR_SLTU = 0x03,
13290 RR_SLLV = 0x04,
13291 RR_BREAK = 0x05,
13292 RR_SRLV = 0x06,
13293 RR_SRAV = 0x07,
13294 RR_DSRL = 0x08,
13295 RR_CMP = 0x0a,
13296 RR_NEG = 0x0b,
13297 RR_AND = 0x0c,
13298 RR_OR = 0x0d,
13299 RR_XOR = 0x0e,
13300 RR_NOT = 0x0f,
13301 RR_MFHI = 0x10,
13302 RR_CNVT = 0x11,
13303 RR_MFLO = 0x12,
13304 RR_DSRA = 0x13,
13305 RR_DSLLV = 0x14,
13306 RR_DSRLV = 0x16,
13307 RR_DSRAV = 0x17,
13308 RR_MULT = 0x18,
13309 RR_MULTU = 0x19,
13310 RR_DIV = 0x1a,
13311 RR_DIVU = 0x1b,
13312 RR_DMULT = 0x1c,
13313 RR_DMULTU = 0x1d,
13314 RR_DDIV = 0x1e,
13315 RR_DDIVU = 0x1f
13318 /* I64 funct field */
13319 enum {
13320 I64_LDSP = 0x0,
13321 I64_SDSP = 0x1,
13322 I64_SDRASP = 0x2,
13323 I64_DADJSP = 0x3,
13324 I64_LDPC = 0x4,
13325 I64_DADDIU5 = 0x5,
13326 I64_DADDIUPC = 0x6,
13327 I64_DADDIUSP = 0x7
13330 /* RR ry field for CNVT */
13331 enum {
13332 RR_RY_CNVT_ZEB = 0x0,
13333 RR_RY_CNVT_ZEH = 0x1,
13334 RR_RY_CNVT_ZEW = 0x2,
13335 RR_RY_CNVT_SEB = 0x4,
13336 RR_RY_CNVT_SEH = 0x5,
13337 RR_RY_CNVT_SEW = 0x6,
13340 static int xlat(int r)
13342 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13344 return map[r];
13347 static void gen_mips16_save(DisasContext *ctx,
13348 int xsregs, int aregs,
13349 int do_ra, int do_s0, int do_s1,
13350 int framesize)
13352 TCGv t0 = tcg_temp_new();
13353 TCGv t1 = tcg_temp_new();
13354 TCGv t2 = tcg_temp_new();
13355 int args, astatic;
13357 switch (aregs) {
13358 case 0:
13359 case 1:
13360 case 2:
13361 case 3:
13362 case 11:
13363 args = 0;
13364 break;
13365 case 4:
13366 case 5:
13367 case 6:
13368 case 7:
13369 args = 1;
13370 break;
13371 case 8:
13372 case 9:
13373 case 10:
13374 args = 2;
13375 break;
13376 case 12:
13377 case 13:
13378 args = 3;
13379 break;
13380 case 14:
13381 args = 4;
13382 break;
13383 default:
13384 gen_reserved_instruction(ctx);
13385 return;
13388 switch (args) {
13389 case 4:
13390 gen_base_offset_addr(ctx, t0, 29, 12);
13391 gen_load_gpr(t1, 7);
13392 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13393 /* Fall through */
13394 case 3:
13395 gen_base_offset_addr(ctx, t0, 29, 8);
13396 gen_load_gpr(t1, 6);
13397 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13398 /* Fall through */
13399 case 2:
13400 gen_base_offset_addr(ctx, t0, 29, 4);
13401 gen_load_gpr(t1, 5);
13402 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13403 /* Fall through */
13404 case 1:
13405 gen_base_offset_addr(ctx, t0, 29, 0);
13406 gen_load_gpr(t1, 4);
13407 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13410 gen_load_gpr(t0, 29);
13412 #define DECR_AND_STORE(reg) do { \
13413 tcg_gen_movi_tl(t2, -4); \
13414 gen_op_addr_add(ctx, t0, t0, t2); \
13415 gen_load_gpr(t1, reg); \
13416 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13417 } while (0)
13419 if (do_ra) {
13420 DECR_AND_STORE(31);
13423 switch (xsregs) {
13424 case 7:
13425 DECR_AND_STORE(30);
13426 /* Fall through */
13427 case 6:
13428 DECR_AND_STORE(23);
13429 /* Fall through */
13430 case 5:
13431 DECR_AND_STORE(22);
13432 /* Fall through */
13433 case 4:
13434 DECR_AND_STORE(21);
13435 /* Fall through */
13436 case 3:
13437 DECR_AND_STORE(20);
13438 /* Fall through */
13439 case 2:
13440 DECR_AND_STORE(19);
13441 /* Fall through */
13442 case 1:
13443 DECR_AND_STORE(18);
13446 if (do_s1) {
13447 DECR_AND_STORE(17);
13449 if (do_s0) {
13450 DECR_AND_STORE(16);
13453 switch (aregs) {
13454 case 0:
13455 case 4:
13456 case 8:
13457 case 12:
13458 case 14:
13459 astatic = 0;
13460 break;
13461 case 1:
13462 case 5:
13463 case 9:
13464 case 13:
13465 astatic = 1;
13466 break;
13467 case 2:
13468 case 6:
13469 case 10:
13470 astatic = 2;
13471 break;
13472 case 3:
13473 case 7:
13474 astatic = 3;
13475 break;
13476 case 11:
13477 astatic = 4;
13478 break;
13479 default:
13480 gen_reserved_instruction(ctx);
13481 return;
13484 if (astatic > 0) {
13485 DECR_AND_STORE(7);
13486 if (astatic > 1) {
13487 DECR_AND_STORE(6);
13488 if (astatic > 2) {
13489 DECR_AND_STORE(5);
13490 if (astatic > 3) {
13491 DECR_AND_STORE(4);
13496 #undef DECR_AND_STORE
13498 tcg_gen_movi_tl(t2, -framesize);
13499 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13500 tcg_temp_free(t0);
13501 tcg_temp_free(t1);
13502 tcg_temp_free(t2);
13505 static void gen_mips16_restore(DisasContext *ctx,
13506 int xsregs, int aregs,
13507 int do_ra, int do_s0, int do_s1,
13508 int framesize)
13510 int astatic;
13511 TCGv t0 = tcg_temp_new();
13512 TCGv t1 = tcg_temp_new();
13513 TCGv t2 = tcg_temp_new();
13515 tcg_gen_movi_tl(t2, framesize);
13516 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13518 #define DECR_AND_LOAD(reg) do { \
13519 tcg_gen_movi_tl(t2, -4); \
13520 gen_op_addr_add(ctx, t0, t0, t2); \
13521 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13522 gen_store_gpr(t1, reg); \
13523 } while (0)
13525 if (do_ra) {
13526 DECR_AND_LOAD(31);
13529 switch (xsregs) {
13530 case 7:
13531 DECR_AND_LOAD(30);
13532 /* Fall through */
13533 case 6:
13534 DECR_AND_LOAD(23);
13535 /* Fall through */
13536 case 5:
13537 DECR_AND_LOAD(22);
13538 /* Fall through */
13539 case 4:
13540 DECR_AND_LOAD(21);
13541 /* Fall through */
13542 case 3:
13543 DECR_AND_LOAD(20);
13544 /* Fall through */
13545 case 2:
13546 DECR_AND_LOAD(19);
13547 /* Fall through */
13548 case 1:
13549 DECR_AND_LOAD(18);
13552 if (do_s1) {
13553 DECR_AND_LOAD(17);
13555 if (do_s0) {
13556 DECR_AND_LOAD(16);
13559 switch (aregs) {
13560 case 0:
13561 case 4:
13562 case 8:
13563 case 12:
13564 case 14:
13565 astatic = 0;
13566 break;
13567 case 1:
13568 case 5:
13569 case 9:
13570 case 13:
13571 astatic = 1;
13572 break;
13573 case 2:
13574 case 6:
13575 case 10:
13576 astatic = 2;
13577 break;
13578 case 3:
13579 case 7:
13580 astatic = 3;
13581 break;
13582 case 11:
13583 astatic = 4;
13584 break;
13585 default:
13586 gen_reserved_instruction(ctx);
13587 return;
13590 if (astatic > 0) {
13591 DECR_AND_LOAD(7);
13592 if (astatic > 1) {
13593 DECR_AND_LOAD(6);
13594 if (astatic > 2) {
13595 DECR_AND_LOAD(5);
13596 if (astatic > 3) {
13597 DECR_AND_LOAD(4);
13602 #undef DECR_AND_LOAD
13604 tcg_gen_movi_tl(t2, framesize);
13605 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13606 tcg_temp_free(t0);
13607 tcg_temp_free(t1);
13608 tcg_temp_free(t2);
13611 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13612 int is_64_bit, int extended)
13614 TCGv t0;
13616 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13617 gen_reserved_instruction(ctx);
13618 return;
13621 t0 = tcg_temp_new();
13623 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13624 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13625 if (!is_64_bit) {
13626 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13629 tcg_temp_free(t0);
13632 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13633 int16_t offset)
13635 TCGv_i32 t0 = tcg_const_i32(op);
13636 TCGv t1 = tcg_temp_new();
13637 gen_base_offset_addr(ctx, t1, base, offset);
13638 gen_helper_cache(cpu_env, t1, t0);
13641 #if defined(TARGET_MIPS64)
13642 static void decode_i64_mips16(DisasContext *ctx,
13643 int ry, int funct, int16_t offset,
13644 int extended)
13646 switch (funct) {
13647 case I64_LDSP:
13648 check_insn(ctx, ISA_MIPS3);
13649 check_mips_64(ctx);
13650 offset = extended ? offset : offset << 3;
13651 gen_ld(ctx, OPC_LD, ry, 29, offset);
13652 break;
13653 case I64_SDSP:
13654 check_insn(ctx, ISA_MIPS3);
13655 check_mips_64(ctx);
13656 offset = extended ? offset : offset << 3;
13657 gen_st(ctx, OPC_SD, ry, 29, offset);
13658 break;
13659 case I64_SDRASP:
13660 check_insn(ctx, ISA_MIPS3);
13661 check_mips_64(ctx);
13662 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13663 gen_st(ctx, OPC_SD, 31, 29, offset);
13664 break;
13665 case I64_DADJSP:
13666 check_insn(ctx, ISA_MIPS3);
13667 check_mips_64(ctx);
13668 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13669 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13670 break;
13671 case I64_LDPC:
13672 check_insn(ctx, ISA_MIPS3);
13673 check_mips_64(ctx);
13674 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13675 gen_reserved_instruction(ctx);
13676 } else {
13677 offset = extended ? offset : offset << 3;
13678 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13680 break;
13681 case I64_DADDIU5:
13682 check_insn(ctx, ISA_MIPS3);
13683 check_mips_64(ctx);
13684 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13685 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13686 break;
13687 case I64_DADDIUPC:
13688 check_insn(ctx, ISA_MIPS3);
13689 check_mips_64(ctx);
13690 offset = extended ? offset : offset << 2;
13691 gen_addiupc(ctx, ry, offset, 1, extended);
13692 break;
13693 case I64_DADDIUSP:
13694 check_insn(ctx, ISA_MIPS3);
13695 check_mips_64(ctx);
13696 offset = extended ? offset : offset << 2;
13697 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13698 break;
13701 #endif
13703 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13705 int extend = translator_lduw(env, ctx->base.pc_next + 2);
13706 int op, rx, ry, funct, sa;
13707 int16_t imm, offset;
13709 ctx->opcode = (ctx->opcode << 16) | extend;
13710 op = (ctx->opcode >> 11) & 0x1f;
13711 sa = (ctx->opcode >> 22) & 0x1f;
13712 funct = (ctx->opcode >> 8) & 0x7;
13713 rx = xlat((ctx->opcode >> 8) & 0x7);
13714 ry = xlat((ctx->opcode >> 5) & 0x7);
13715 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13716 | ((ctx->opcode >> 21) & 0x3f) << 5
13717 | (ctx->opcode & 0x1f));
13720 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13721 * counterparts.
13723 switch (op) {
13724 case M16_OPC_ADDIUSP:
13725 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13726 break;
13727 case M16_OPC_ADDIUPC:
13728 gen_addiupc(ctx, rx, imm, 0, 1);
13729 break;
13730 case M16_OPC_B:
13731 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13732 /* No delay slot, so just process as a normal instruction */
13733 break;
13734 case M16_OPC_BEQZ:
13735 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13736 /* No delay slot, so just process as a normal instruction */
13737 break;
13738 case M16_OPC_BNEQZ:
13739 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13740 /* No delay slot, so just process as a normal instruction */
13741 break;
13742 case M16_OPC_SHIFT:
13743 switch (ctx->opcode & 0x3) {
13744 case 0x0:
13745 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13746 break;
13747 case 0x1:
13748 #if defined(TARGET_MIPS64)
13749 check_mips_64(ctx);
13750 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13751 #else
13752 gen_reserved_instruction(ctx);
13753 #endif
13754 break;
13755 case 0x2:
13756 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13757 break;
13758 case 0x3:
13759 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13760 break;
13762 break;
13763 #if defined(TARGET_MIPS64)
13764 case M16_OPC_LD:
13765 check_insn(ctx, ISA_MIPS3);
13766 check_mips_64(ctx);
13767 gen_ld(ctx, OPC_LD, ry, rx, offset);
13768 break;
13769 #endif
13770 case M16_OPC_RRIA:
13771 imm = ctx->opcode & 0xf;
13772 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13773 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13774 imm = (int16_t) (imm << 1) >> 1;
13775 if ((ctx->opcode >> 4) & 0x1) {
13776 #if defined(TARGET_MIPS64)
13777 check_mips_64(ctx);
13778 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13779 #else
13780 gen_reserved_instruction(ctx);
13781 #endif
13782 } else {
13783 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13785 break;
13786 case M16_OPC_ADDIU8:
13787 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13788 break;
13789 case M16_OPC_SLTI:
13790 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13791 break;
13792 case M16_OPC_SLTIU:
13793 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13794 break;
13795 case M16_OPC_I8:
13796 switch (funct) {
13797 case I8_BTEQZ:
13798 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13799 break;
13800 case I8_BTNEZ:
13801 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13802 break;
13803 case I8_SWRASP:
13804 gen_st(ctx, OPC_SW, 31, 29, imm);
13805 break;
13806 case I8_ADJSP:
13807 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13808 break;
13809 case I8_SVRS:
13810 check_insn(ctx, ISA_MIPS_R1);
13812 int xsregs = (ctx->opcode >> 24) & 0x7;
13813 int aregs = (ctx->opcode >> 16) & 0xf;
13814 int do_ra = (ctx->opcode >> 6) & 0x1;
13815 int do_s0 = (ctx->opcode >> 5) & 0x1;
13816 int do_s1 = (ctx->opcode >> 4) & 0x1;
13817 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13818 | (ctx->opcode & 0xf)) << 3;
13820 if (ctx->opcode & (1 << 7)) {
13821 gen_mips16_save(ctx, xsregs, aregs,
13822 do_ra, do_s0, do_s1,
13823 framesize);
13824 } else {
13825 gen_mips16_restore(ctx, xsregs, aregs,
13826 do_ra, do_s0, do_s1,
13827 framesize);
13830 break;
13831 default:
13832 gen_reserved_instruction(ctx);
13833 break;
13835 break;
13836 case M16_OPC_LI:
13837 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13838 break;
13839 case M16_OPC_CMPI:
13840 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13841 break;
13842 #if defined(TARGET_MIPS64)
13843 case M16_OPC_SD:
13844 check_insn(ctx, ISA_MIPS3);
13845 check_mips_64(ctx);
13846 gen_st(ctx, OPC_SD, ry, rx, offset);
13847 break;
13848 #endif
13849 case M16_OPC_LB:
13850 gen_ld(ctx, OPC_LB, ry, rx, offset);
13851 break;
13852 case M16_OPC_LH:
13853 gen_ld(ctx, OPC_LH, ry, rx, offset);
13854 break;
13855 case M16_OPC_LWSP:
13856 gen_ld(ctx, OPC_LW, rx, 29, offset);
13857 break;
13858 case M16_OPC_LW:
13859 gen_ld(ctx, OPC_LW, ry, rx, offset);
13860 break;
13861 case M16_OPC_LBU:
13862 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13863 break;
13864 case M16_OPC_LHU:
13865 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13866 break;
13867 case M16_OPC_LWPC:
13868 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13869 break;
13870 #if defined(TARGET_MIPS64)
13871 case M16_OPC_LWU:
13872 check_insn(ctx, ISA_MIPS3);
13873 check_mips_64(ctx);
13874 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13875 break;
13876 #endif
13877 case M16_OPC_SB:
13878 gen_st(ctx, OPC_SB, ry, rx, offset);
13879 break;
13880 case M16_OPC_SH:
13881 gen_st(ctx, OPC_SH, ry, rx, offset);
13882 break;
13883 case M16_OPC_SWSP:
13884 gen_st(ctx, OPC_SW, rx, 29, offset);
13885 break;
13886 case M16_OPC_SW:
13887 gen_st(ctx, OPC_SW, ry, rx, offset);
13888 break;
13889 #if defined(TARGET_MIPS64)
13890 case M16_OPC_I64:
13891 decode_i64_mips16(ctx, ry, funct, offset, 1);
13892 break;
13893 #endif
13894 default:
13895 gen_reserved_instruction(ctx);
13896 break;
13899 return 4;
13902 static inline bool is_uhi(int sdbbp_code)
13904 #ifdef CONFIG_USER_ONLY
13905 return false;
13906 #else
13907 return semihosting_enabled() && sdbbp_code == 1;
13908 #endif
13911 #ifdef CONFIG_USER_ONLY
13912 /* The above should dead-code away any calls to this..*/
13913 static inline void gen_helper_do_semihosting(void *env)
13915 g_assert_not_reached();
13917 #endif
13919 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13921 int rx, ry;
13922 int sa;
13923 int op, cnvt_op, op1, offset;
13924 int funct;
13925 int n_bytes;
13927 op = (ctx->opcode >> 11) & 0x1f;
13928 sa = (ctx->opcode >> 2) & 0x7;
13929 sa = sa == 0 ? 8 : sa;
13930 rx = xlat((ctx->opcode >> 8) & 0x7);
13931 cnvt_op = (ctx->opcode >> 5) & 0x7;
13932 ry = xlat((ctx->opcode >> 5) & 0x7);
13933 op1 = offset = ctx->opcode & 0x1f;
13935 n_bytes = 2;
13937 switch (op) {
13938 case M16_OPC_ADDIUSP:
13940 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13942 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13944 break;
13945 case M16_OPC_ADDIUPC:
13946 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13947 break;
13948 case M16_OPC_B:
13949 offset = (ctx->opcode & 0x7ff) << 1;
13950 offset = (int16_t)(offset << 4) >> 4;
13951 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13952 /* No delay slot, so just process as a normal instruction */
13953 break;
13954 case M16_OPC_JAL:
13955 offset = translator_lduw(env, ctx->base.pc_next + 2);
13956 offset = (((ctx->opcode & 0x1f) << 21)
13957 | ((ctx->opcode >> 5) & 0x1f) << 16
13958 | offset) << 2;
13959 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13960 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13961 n_bytes = 4;
13962 break;
13963 case M16_OPC_BEQZ:
13964 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13965 ((int8_t)ctx->opcode) << 1, 0);
13966 /* No delay slot, so just process as a normal instruction */
13967 break;
13968 case M16_OPC_BNEQZ:
13969 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13970 ((int8_t)ctx->opcode) << 1, 0);
13971 /* No delay slot, so just process as a normal instruction */
13972 break;
13973 case M16_OPC_SHIFT:
13974 switch (ctx->opcode & 0x3) {
13975 case 0x0:
13976 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13977 break;
13978 case 0x1:
13979 #if defined(TARGET_MIPS64)
13980 check_insn(ctx, ISA_MIPS3);
13981 check_mips_64(ctx);
13982 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13983 #else
13984 gen_reserved_instruction(ctx);
13985 #endif
13986 break;
13987 case 0x2:
13988 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13989 break;
13990 case 0x3:
13991 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13992 break;
13994 break;
13995 #if defined(TARGET_MIPS64)
13996 case M16_OPC_LD:
13997 check_insn(ctx, ISA_MIPS3);
13998 check_mips_64(ctx);
13999 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
14000 break;
14001 #endif
14002 case M16_OPC_RRIA:
14004 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14006 if ((ctx->opcode >> 4) & 1) {
14007 #if defined(TARGET_MIPS64)
14008 check_insn(ctx, ISA_MIPS3);
14009 check_mips_64(ctx);
14010 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14011 #else
14012 gen_reserved_instruction(ctx);
14013 #endif
14014 } else {
14015 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14018 break;
14019 case M16_OPC_ADDIU8:
14021 int16_t imm = (int8_t) ctx->opcode;
14023 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14025 break;
14026 case M16_OPC_SLTI:
14028 int16_t imm = (uint8_t) ctx->opcode;
14029 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14031 break;
14032 case M16_OPC_SLTIU:
14034 int16_t imm = (uint8_t) ctx->opcode;
14035 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14037 break;
14038 case M16_OPC_I8:
14040 int reg32;
14042 funct = (ctx->opcode >> 8) & 0x7;
14043 switch (funct) {
14044 case I8_BTEQZ:
14045 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14046 ((int8_t)ctx->opcode) << 1, 0);
14047 break;
14048 case I8_BTNEZ:
14049 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14050 ((int8_t)ctx->opcode) << 1, 0);
14051 break;
14052 case I8_SWRASP:
14053 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14054 break;
14055 case I8_ADJSP:
14056 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14057 ((int8_t)ctx->opcode) << 3);
14058 break;
14059 case I8_SVRS:
14060 check_insn(ctx, ISA_MIPS_R1);
14062 int do_ra = ctx->opcode & (1 << 6);
14063 int do_s0 = ctx->opcode & (1 << 5);
14064 int do_s1 = ctx->opcode & (1 << 4);
14065 int framesize = ctx->opcode & 0xf;
14067 if (framesize == 0) {
14068 framesize = 128;
14069 } else {
14070 framesize = framesize << 3;
14073 if (ctx->opcode & (1 << 7)) {
14074 gen_mips16_save(ctx, 0, 0,
14075 do_ra, do_s0, do_s1, framesize);
14076 } else {
14077 gen_mips16_restore(ctx, 0, 0,
14078 do_ra, do_s0, do_s1, framesize);
14081 break;
14082 case I8_MOV32R:
14084 int rz = xlat(ctx->opcode & 0x7);
14086 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14087 ((ctx->opcode >> 5) & 0x7);
14088 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14090 break;
14091 case I8_MOVR32:
14092 reg32 = ctx->opcode & 0x1f;
14093 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14094 break;
14095 default:
14096 gen_reserved_instruction(ctx);
14097 break;
14100 break;
14101 case M16_OPC_LI:
14103 int16_t imm = (uint8_t) ctx->opcode;
14105 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14107 break;
14108 case M16_OPC_CMPI:
14110 int16_t imm = (uint8_t) ctx->opcode;
14111 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14113 break;
14114 #if defined(TARGET_MIPS64)
14115 case M16_OPC_SD:
14116 check_insn(ctx, ISA_MIPS3);
14117 check_mips_64(ctx);
14118 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14119 break;
14120 #endif
14121 case M16_OPC_LB:
14122 gen_ld(ctx, OPC_LB, ry, rx, offset);
14123 break;
14124 case M16_OPC_LH:
14125 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14126 break;
14127 case M16_OPC_LWSP:
14128 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14129 break;
14130 case M16_OPC_LW:
14131 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14132 break;
14133 case M16_OPC_LBU:
14134 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14135 break;
14136 case M16_OPC_LHU:
14137 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14138 break;
14139 case M16_OPC_LWPC:
14140 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14141 break;
14142 #if defined(TARGET_MIPS64)
14143 case M16_OPC_LWU:
14144 check_insn(ctx, ISA_MIPS3);
14145 check_mips_64(ctx);
14146 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14147 break;
14148 #endif
14149 case M16_OPC_SB:
14150 gen_st(ctx, OPC_SB, ry, rx, offset);
14151 break;
14152 case M16_OPC_SH:
14153 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14154 break;
14155 case M16_OPC_SWSP:
14156 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14157 break;
14158 case M16_OPC_SW:
14159 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14160 break;
14161 case M16_OPC_RRR:
14163 int rz = xlat((ctx->opcode >> 2) & 0x7);
14164 int mips32_op;
14166 switch (ctx->opcode & 0x3) {
14167 case RRR_ADDU:
14168 mips32_op = OPC_ADDU;
14169 break;
14170 case RRR_SUBU:
14171 mips32_op = OPC_SUBU;
14172 break;
14173 #if defined(TARGET_MIPS64)
14174 case RRR_DADDU:
14175 mips32_op = OPC_DADDU;
14176 check_insn(ctx, ISA_MIPS3);
14177 check_mips_64(ctx);
14178 break;
14179 case RRR_DSUBU:
14180 mips32_op = OPC_DSUBU;
14181 check_insn(ctx, ISA_MIPS3);
14182 check_mips_64(ctx);
14183 break;
14184 #endif
14185 default:
14186 gen_reserved_instruction(ctx);
14187 goto done;
14190 gen_arith(ctx, mips32_op, rz, rx, ry);
14191 done:
14194 break;
14195 case M16_OPC_RR:
14196 switch (op1) {
14197 case RR_JR:
14199 int nd = (ctx->opcode >> 7) & 0x1;
14200 int link = (ctx->opcode >> 6) & 0x1;
14201 int ra = (ctx->opcode >> 5) & 0x1;
14203 if (nd) {
14204 check_insn(ctx, ISA_MIPS_R1);
14207 if (link) {
14208 op = OPC_JALR;
14209 } else {
14210 op = OPC_JR;
14213 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14214 (nd ? 0 : 2));
14216 break;
14217 case RR_SDBBP:
14218 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14219 gen_helper_do_semihosting(cpu_env);
14220 } else {
14222 * XXX: not clear which exception should be raised
14223 * when in debug mode...
14225 check_insn(ctx, ISA_MIPS_R1);
14226 generate_exception_end(ctx, EXCP_DBp);
14228 break;
14229 case RR_SLT:
14230 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14231 break;
14232 case RR_SLTU:
14233 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14234 break;
14235 case RR_BREAK:
14236 generate_exception_end(ctx, EXCP_BREAK);
14237 break;
14238 case RR_SLLV:
14239 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14240 break;
14241 case RR_SRLV:
14242 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14243 break;
14244 case RR_SRAV:
14245 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14246 break;
14247 #if defined(TARGET_MIPS64)
14248 case RR_DSRL:
14249 check_insn(ctx, ISA_MIPS3);
14250 check_mips_64(ctx);
14251 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14252 break;
14253 #endif
14254 case RR_CMP:
14255 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14256 break;
14257 case RR_NEG:
14258 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14259 break;
14260 case RR_AND:
14261 gen_logic(ctx, OPC_AND, rx, rx, ry);
14262 break;
14263 case RR_OR:
14264 gen_logic(ctx, OPC_OR, rx, rx, ry);
14265 break;
14266 case RR_XOR:
14267 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14268 break;
14269 case RR_NOT:
14270 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14271 break;
14272 case RR_MFHI:
14273 gen_HILO(ctx, OPC_MFHI, 0, rx);
14274 break;
14275 case RR_CNVT:
14276 check_insn(ctx, ISA_MIPS_R1);
14277 switch (cnvt_op) {
14278 case RR_RY_CNVT_ZEB:
14279 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14280 break;
14281 case RR_RY_CNVT_ZEH:
14282 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14283 break;
14284 case RR_RY_CNVT_SEB:
14285 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14286 break;
14287 case RR_RY_CNVT_SEH:
14288 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14289 break;
14290 #if defined(TARGET_MIPS64)
14291 case RR_RY_CNVT_ZEW:
14292 check_insn(ctx, ISA_MIPS_R1);
14293 check_mips_64(ctx);
14294 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14295 break;
14296 case RR_RY_CNVT_SEW:
14297 check_insn(ctx, ISA_MIPS_R1);
14298 check_mips_64(ctx);
14299 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14300 break;
14301 #endif
14302 default:
14303 gen_reserved_instruction(ctx);
14304 break;
14306 break;
14307 case RR_MFLO:
14308 gen_HILO(ctx, OPC_MFLO, 0, rx);
14309 break;
14310 #if defined(TARGET_MIPS64)
14311 case RR_DSRA:
14312 check_insn(ctx, ISA_MIPS3);
14313 check_mips_64(ctx);
14314 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14315 break;
14316 case RR_DSLLV:
14317 check_insn(ctx, ISA_MIPS3);
14318 check_mips_64(ctx);
14319 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14320 break;
14321 case RR_DSRLV:
14322 check_insn(ctx, ISA_MIPS3);
14323 check_mips_64(ctx);
14324 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14325 break;
14326 case RR_DSRAV:
14327 check_insn(ctx, ISA_MIPS3);
14328 check_mips_64(ctx);
14329 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14330 break;
14331 #endif
14332 case RR_MULT:
14333 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14334 break;
14335 case RR_MULTU:
14336 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14337 break;
14338 case RR_DIV:
14339 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14340 break;
14341 case RR_DIVU:
14342 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14343 break;
14344 #if defined(TARGET_MIPS64)
14345 case RR_DMULT:
14346 check_insn(ctx, ISA_MIPS3);
14347 check_mips_64(ctx);
14348 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14349 break;
14350 case RR_DMULTU:
14351 check_insn(ctx, ISA_MIPS3);
14352 check_mips_64(ctx);
14353 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14354 break;
14355 case RR_DDIV:
14356 check_insn(ctx, ISA_MIPS3);
14357 check_mips_64(ctx);
14358 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14359 break;
14360 case RR_DDIVU:
14361 check_insn(ctx, ISA_MIPS3);
14362 check_mips_64(ctx);
14363 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14364 break;
14365 #endif
14366 default:
14367 gen_reserved_instruction(ctx);
14368 break;
14370 break;
14371 case M16_OPC_EXTEND:
14372 decode_extended_mips16_opc(env, ctx);
14373 n_bytes = 4;
14374 break;
14375 #if defined(TARGET_MIPS64)
14376 case M16_OPC_I64:
14377 funct = (ctx->opcode >> 8) & 0x7;
14378 decode_i64_mips16(ctx, ry, funct, offset, 0);
14379 break;
14380 #endif
14381 default:
14382 gen_reserved_instruction(ctx);
14383 break;
14386 return n_bytes;
14389 /* microMIPS extension to MIPS32/MIPS64 */
14392 * microMIPS32/microMIPS64 major opcodes
14394 * 1. MIPS Architecture for Programmers Volume II-B:
14395 * The microMIPS32 Instruction Set (Revision 3.05)
14397 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14399 * 2. MIPS Architecture For Programmers Volume II-A:
14400 * The MIPS64 Instruction Set (Revision 3.51)
14403 enum {
14404 POOL32A = 0x00,
14405 POOL16A = 0x01,
14406 LBU16 = 0x02,
14407 MOVE16 = 0x03,
14408 ADDI32 = 0x04,
14409 R6_LUI = 0x04,
14410 AUI = 0x04,
14411 LBU32 = 0x05,
14412 SB32 = 0x06,
14413 LB32 = 0x07,
14415 POOL32B = 0x08,
14416 POOL16B = 0x09,
14417 LHU16 = 0x0a,
14418 ANDI16 = 0x0b,
14419 ADDIU32 = 0x0c,
14420 LHU32 = 0x0d,
14421 SH32 = 0x0e,
14422 LH32 = 0x0f,
14424 POOL32I = 0x10,
14425 POOL16C = 0x11,
14426 LWSP16 = 0x12,
14427 POOL16D = 0x13,
14428 ORI32 = 0x14,
14429 POOL32F = 0x15,
14430 POOL32S = 0x16, /* MIPS64 */
14431 DADDIU32 = 0x17, /* MIPS64 */
14433 POOL32C = 0x18,
14434 LWGP16 = 0x19,
14435 LW16 = 0x1a,
14436 POOL16E = 0x1b,
14437 XORI32 = 0x1c,
14438 JALS32 = 0x1d,
14439 BOVC = 0x1d,
14440 BEQC = 0x1d,
14441 BEQZALC = 0x1d,
14442 ADDIUPC = 0x1e,
14443 PCREL = 0x1e,
14444 BNVC = 0x1f,
14445 BNEC = 0x1f,
14446 BNEZALC = 0x1f,
14448 R6_BEQZC = 0x20,
14449 JIC = 0x20,
14450 POOL16F = 0x21,
14451 SB16 = 0x22,
14452 BEQZ16 = 0x23,
14453 BEQZC16 = 0x23,
14454 SLTI32 = 0x24,
14455 BEQ32 = 0x25,
14456 BC = 0x25,
14457 SWC132 = 0x26,
14458 LWC132 = 0x27,
14460 /* 0x29 is reserved */
14461 RES_29 = 0x29,
14462 R6_BNEZC = 0x28,
14463 JIALC = 0x28,
14464 SH16 = 0x2a,
14465 BNEZ16 = 0x2b,
14466 BNEZC16 = 0x2b,
14467 SLTIU32 = 0x2c,
14468 BNE32 = 0x2d,
14469 BALC = 0x2d,
14470 SDC132 = 0x2e,
14471 LDC132 = 0x2f,
14473 /* 0x31 is reserved */
14474 RES_31 = 0x31,
14475 BLEZALC = 0x30,
14476 BGEZALC = 0x30,
14477 BGEUC = 0x30,
14478 SWSP16 = 0x32,
14479 B16 = 0x33,
14480 BC16 = 0x33,
14481 ANDI32 = 0x34,
14482 J32 = 0x35,
14483 BGTZC = 0x35,
14484 BLTZC = 0x35,
14485 BLTC = 0x35,
14486 SD32 = 0x36, /* MIPS64 */
14487 LD32 = 0x37, /* MIPS64 */
14489 /* 0x39 is reserved */
14490 RES_39 = 0x39,
14491 BGTZALC = 0x38,
14492 BLTZALC = 0x38,
14493 BLTUC = 0x38,
14494 SW16 = 0x3a,
14495 LI16 = 0x3b,
14496 JALX32 = 0x3c,
14497 JAL32 = 0x3d,
14498 BLEZC = 0x3d,
14499 BGEZC = 0x3d,
14500 BGEC = 0x3d,
14501 SW32 = 0x3e,
14502 LW32 = 0x3f
14505 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14506 enum {
14507 ADDIUPC_00 = 0x00,
14508 ADDIUPC_01 = 0x01,
14509 ADDIUPC_02 = 0x02,
14510 ADDIUPC_03 = 0x03,
14511 ADDIUPC_04 = 0x04,
14512 ADDIUPC_05 = 0x05,
14513 ADDIUPC_06 = 0x06,
14514 ADDIUPC_07 = 0x07,
14515 AUIPC = 0x1e,
14516 ALUIPC = 0x1f,
14517 LWPC_08 = 0x08,
14518 LWPC_09 = 0x09,
14519 LWPC_0A = 0x0A,
14520 LWPC_0B = 0x0B,
14521 LWPC_0C = 0x0C,
14522 LWPC_0D = 0x0D,
14523 LWPC_0E = 0x0E,
14524 LWPC_0F = 0x0F,
14527 /* POOL32A encoding of minor opcode field */
14529 enum {
14531 * These opcodes are distinguished only by bits 9..6; those bits are
14532 * what are recorded below.
14534 SLL32 = 0x0,
14535 SRL32 = 0x1,
14536 SRA = 0x2,
14537 ROTR = 0x3,
14538 SELEQZ = 0x5,
14539 SELNEZ = 0x6,
14540 R6_RDHWR = 0x7,
14542 SLLV = 0x0,
14543 SRLV = 0x1,
14544 SRAV = 0x2,
14545 ROTRV = 0x3,
14546 ADD = 0x4,
14547 ADDU32 = 0x5,
14548 SUB = 0x6,
14549 SUBU32 = 0x7,
14550 MUL = 0x8,
14551 AND = 0x9,
14552 OR32 = 0xa,
14553 NOR = 0xb,
14554 XOR32 = 0xc,
14555 SLT = 0xd,
14556 SLTU = 0xe,
14558 MOVN = 0x0,
14559 R6_MUL = 0x0,
14560 MOVZ = 0x1,
14561 MUH = 0x1,
14562 MULU = 0x2,
14563 MUHU = 0x3,
14564 LWXS = 0x4,
14565 R6_DIV = 0x4,
14566 MOD = 0x5,
14567 R6_DIVU = 0x6,
14568 MODU = 0x7,
14570 /* The following can be distinguished by their lower 6 bits. */
14571 BREAK32 = 0x07,
14572 INS = 0x0c,
14573 LSA = 0x0f,
14574 ALIGN = 0x1f,
14575 EXT = 0x2c,
14576 POOL32AXF = 0x3c,
14577 SIGRIE = 0x3f
14580 /* POOL32AXF encoding of minor opcode field extension */
14583 * 1. MIPS Architecture for Programmers Volume II-B:
14584 * The microMIPS32 Instruction Set (Revision 3.05)
14586 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14588 * 2. MIPS Architecture for Programmers VolumeIV-e:
14589 * The MIPS DSP Application-Specific Extension
14590 * to the microMIPS32 Architecture (Revision 2.34)
14592 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14595 enum {
14596 /* bits 11..6 */
14597 TEQ = 0x00,
14598 TGE = 0x08,
14599 TGEU = 0x10,
14600 TLT = 0x20,
14601 TLTU = 0x28,
14602 TNE = 0x30,
14604 MFC0 = 0x03,
14605 MTC0 = 0x0b,
14607 /* begin of microMIPS32 DSP */
14609 /* bits 13..12 for 0x01 */
14610 MFHI_ACC = 0x0,
14611 MFLO_ACC = 0x1,
14612 MTHI_ACC = 0x2,
14613 MTLO_ACC = 0x3,
14615 /* bits 13..12 for 0x2a */
14616 MADD_ACC = 0x0,
14617 MADDU_ACC = 0x1,
14618 MSUB_ACC = 0x2,
14619 MSUBU_ACC = 0x3,
14621 /* bits 13..12 for 0x32 */
14622 MULT_ACC = 0x0,
14623 MULTU_ACC = 0x1,
14625 /* end of microMIPS32 DSP */
14627 /* bits 15..12 for 0x2c */
14628 BITSWAP = 0x0,
14629 SEB = 0x2,
14630 SEH = 0x3,
14631 CLO = 0x4,
14632 CLZ = 0x5,
14633 RDHWR = 0x6,
14634 WSBH = 0x7,
14635 MULT = 0x8,
14636 MULTU = 0x9,
14637 DIV = 0xa,
14638 DIVU = 0xb,
14639 MADD = 0xc,
14640 MADDU = 0xd,
14641 MSUB = 0xe,
14642 MSUBU = 0xf,
14644 /* bits 15..12 for 0x34 */
14645 MFC2 = 0x4,
14646 MTC2 = 0x5,
14647 MFHC2 = 0x8,
14648 MTHC2 = 0x9,
14649 CFC2 = 0xc,
14650 CTC2 = 0xd,
14652 /* bits 15..12 for 0x3c */
14653 JALR = 0x0,
14654 JR = 0x0, /* alias */
14655 JALRC = 0x0,
14656 JRC = 0x0,
14657 JALR_HB = 0x1,
14658 JALRC_HB = 0x1,
14659 JALRS = 0x4,
14660 JALRS_HB = 0x5,
14662 /* bits 15..12 for 0x05 */
14663 RDPGPR = 0xe,
14664 WRPGPR = 0xf,
14666 /* bits 15..12 for 0x0d */
14667 TLBP = 0x0,
14668 TLBR = 0x1,
14669 TLBWI = 0x2,
14670 TLBWR = 0x3,
14671 TLBINV = 0x4,
14672 TLBINVF = 0x5,
14673 WAIT = 0x9,
14674 IRET = 0xd,
14675 DERET = 0xe,
14676 ERET = 0xf,
14678 /* bits 15..12 for 0x15 */
14679 DMT = 0x0,
14680 DVPE = 0x1,
14681 EMT = 0x2,
14682 EVPE = 0x3,
14684 /* bits 15..12 for 0x1d */
14685 DI = 0x4,
14686 EI = 0x5,
14688 /* bits 15..12 for 0x2d */
14689 SYNC = 0x6,
14690 SYSCALL = 0x8,
14691 SDBBP = 0xd,
14693 /* bits 15..12 for 0x35 */
14694 MFHI32 = 0x0,
14695 MFLO32 = 0x1,
14696 MTHI32 = 0x2,
14697 MTLO32 = 0x3,
14700 /* POOL32B encoding of minor opcode field (bits 15..12) */
14702 enum {
14703 LWC2 = 0x0,
14704 LWP = 0x1,
14705 LDP = 0x4,
14706 LWM32 = 0x5,
14707 CACHE = 0x6,
14708 LDM = 0x7,
14709 SWC2 = 0x8,
14710 SWP = 0x9,
14711 SDP = 0xc,
14712 SWM32 = 0xd,
14713 SDM = 0xf
14716 /* POOL32C encoding of minor opcode field (bits 15..12) */
14718 enum {
14719 LWL = 0x0,
14720 SWL = 0x8,
14721 LWR = 0x1,
14722 SWR = 0x9,
14723 PREF = 0x2,
14724 ST_EVA = 0xa,
14725 LL = 0x3,
14726 SC = 0xb,
14727 LDL = 0x4,
14728 SDL = 0xc,
14729 LDR = 0x5,
14730 SDR = 0xd,
14731 LD_EVA = 0x6,
14732 LWU = 0xe,
14733 LLD = 0x7,
14734 SCD = 0xf
14737 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14739 enum {
14740 LBUE = 0x0,
14741 LHUE = 0x1,
14742 LWLE = 0x2,
14743 LWRE = 0x3,
14744 LBE = 0x4,
14745 LHE = 0x5,
14746 LLE = 0x6,
14747 LWE = 0x7,
14750 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14752 enum {
14753 SWLE = 0x0,
14754 SWRE = 0x1,
14755 PREFE = 0x2,
14756 CACHEE = 0x3,
14757 SBE = 0x4,
14758 SHE = 0x5,
14759 SCE = 0x6,
14760 SWE = 0x7,
14763 /* POOL32F encoding of minor opcode field (bits 5..0) */
14765 enum {
14766 /* These are the bit 7..6 values */
14767 ADD_FMT = 0x0,
14769 SUB_FMT = 0x1,
14771 MUL_FMT = 0x2,
14773 DIV_FMT = 0x3,
14775 /* These are the bit 8..6 values */
14776 MOVN_FMT = 0x0,
14777 RSQRT2_FMT = 0x0,
14778 MOVF_FMT = 0x0,
14779 RINT_FMT = 0x0,
14780 SELNEZ_FMT = 0x0,
14782 MOVZ_FMT = 0x1,
14783 LWXC1 = 0x1,
14784 MOVT_FMT = 0x1,
14785 CLASS_FMT = 0x1,
14786 SELEQZ_FMT = 0x1,
14788 PLL_PS = 0x2,
14789 SWXC1 = 0x2,
14790 SEL_FMT = 0x2,
14792 PLU_PS = 0x3,
14793 LDXC1 = 0x3,
14795 MOVN_FMT_04 = 0x4,
14796 PUL_PS = 0x4,
14797 SDXC1 = 0x4,
14798 RECIP2_FMT = 0x4,
14800 MOVZ_FMT_05 = 0x05,
14801 PUU_PS = 0x5,
14802 LUXC1 = 0x5,
14804 CVT_PS_S = 0x6,
14805 SUXC1 = 0x6,
14806 ADDR_PS = 0x6,
14807 PREFX = 0x6,
14808 MADDF_FMT = 0x6,
14810 MULR_PS = 0x7,
14811 MSUBF_FMT = 0x7,
14813 MADD_S = 0x01,
14814 MADD_D = 0x09,
14815 MADD_PS = 0x11,
14816 ALNV_PS = 0x19,
14817 MSUB_S = 0x21,
14818 MSUB_D = 0x29,
14819 MSUB_PS = 0x31,
14821 NMADD_S = 0x02,
14822 NMADD_D = 0x0a,
14823 NMADD_PS = 0x12,
14824 NMSUB_S = 0x22,
14825 NMSUB_D = 0x2a,
14826 NMSUB_PS = 0x32,
14828 MIN_FMT = 0x3,
14829 MAX_FMT = 0xb,
14830 MINA_FMT = 0x23,
14831 MAXA_FMT = 0x2b,
14832 POOL32FXF = 0x3b,
14834 CABS_COND_FMT = 0x1c, /* MIPS3D */
14835 C_COND_FMT = 0x3c,
14837 CMP_CONDN_S = 0x5,
14838 CMP_CONDN_D = 0x15
14841 /* POOL32Fxf encoding of minor opcode extension field */
14843 enum {
14844 CVT_L = 0x04,
14845 RSQRT_FMT = 0x08,
14846 FLOOR_L = 0x0c,
14847 CVT_PW_PS = 0x1c,
14848 CVT_W = 0x24,
14849 SQRT_FMT = 0x28,
14850 FLOOR_W = 0x2c,
14851 CVT_PS_PW = 0x3c,
14852 CFC1 = 0x40,
14853 RECIP_FMT = 0x48,
14854 CEIL_L = 0x4c,
14855 CTC1 = 0x60,
14856 CEIL_W = 0x6c,
14857 MFC1 = 0x80,
14858 CVT_S_PL = 0x84,
14859 TRUNC_L = 0x8c,
14860 MTC1 = 0xa0,
14861 CVT_S_PU = 0xa4,
14862 TRUNC_W = 0xac,
14863 MFHC1 = 0xc0,
14864 ROUND_L = 0xcc,
14865 MTHC1 = 0xe0,
14866 ROUND_W = 0xec,
14868 MOV_FMT = 0x01,
14869 MOVF = 0x05,
14870 ABS_FMT = 0x0d,
14871 RSQRT1_FMT = 0x1d,
14872 MOVT = 0x25,
14873 NEG_FMT = 0x2d,
14874 CVT_D = 0x4d,
14875 RECIP1_FMT = 0x5d,
14876 CVT_S = 0x6d
14879 /* POOL32I encoding of minor opcode field (bits 25..21) */
14881 enum {
14882 BLTZ = 0x00,
14883 BLTZAL = 0x01,
14884 BGEZ = 0x02,
14885 BGEZAL = 0x03,
14886 BLEZ = 0x04,
14887 BNEZC = 0x05,
14888 BGTZ = 0x06,
14889 BEQZC = 0x07,
14890 TLTI = 0x08,
14891 BC1EQZC = 0x08,
14892 TGEI = 0x09,
14893 BC1NEZC = 0x09,
14894 TLTIU = 0x0a,
14895 BC2EQZC = 0x0a,
14896 TGEIU = 0x0b,
14897 BC2NEZC = 0x0a,
14898 TNEI = 0x0c,
14899 R6_SYNCI = 0x0c,
14900 LUI = 0x0d,
14901 TEQI = 0x0e,
14902 SYNCI = 0x10,
14903 BLTZALS = 0x11,
14904 BGEZALS = 0x13,
14905 BC2F = 0x14,
14906 BC2T = 0x15,
14907 BPOSGE64 = 0x1a,
14908 BPOSGE32 = 0x1b,
14909 /* These overlap and are distinguished by bit16 of the instruction */
14910 BC1F = 0x1c,
14911 BC1T = 0x1d,
14912 BC1ANY2F = 0x1c,
14913 BC1ANY2T = 0x1d,
14914 BC1ANY4F = 0x1e,
14915 BC1ANY4T = 0x1f
14918 /* POOL16A encoding of minor opcode field */
14920 enum {
14921 ADDU16 = 0x0,
14922 SUBU16 = 0x1
14925 /* POOL16B encoding of minor opcode field */
14927 enum {
14928 SLL16 = 0x0,
14929 SRL16 = 0x1
14932 /* POOL16C encoding of minor opcode field */
14934 enum {
14935 NOT16 = 0x00,
14936 XOR16 = 0x04,
14937 AND16 = 0x08,
14938 OR16 = 0x0c,
14939 LWM16 = 0x10,
14940 SWM16 = 0x14,
14941 JR16 = 0x18,
14942 JRC16 = 0x1a,
14943 JALR16 = 0x1c,
14944 JALR16S = 0x1e,
14945 MFHI16 = 0x20,
14946 MFLO16 = 0x24,
14947 BREAK16 = 0x28,
14948 SDBBP16 = 0x2c,
14949 JRADDIUSP = 0x30
14952 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14954 enum {
14955 R6_NOT16 = 0x00,
14956 R6_AND16 = 0x01,
14957 R6_LWM16 = 0x02,
14958 R6_JRC16 = 0x03,
14959 MOVEP = 0x04,
14960 MOVEP_05 = 0x05,
14961 MOVEP_06 = 0x06,
14962 MOVEP_07 = 0x07,
14963 R6_XOR16 = 0x08,
14964 R6_OR16 = 0x09,
14965 R6_SWM16 = 0x0a,
14966 JALRC16 = 0x0b,
14967 MOVEP_0C = 0x0c,
14968 MOVEP_0D = 0x0d,
14969 MOVEP_0E = 0x0e,
14970 MOVEP_0F = 0x0f,
14971 JRCADDIUSP = 0x13,
14972 R6_BREAK16 = 0x1b,
14973 R6_SDBBP16 = 0x3b
14976 /* POOL16D encoding of minor opcode field */
14978 enum {
14979 ADDIUS5 = 0x0,
14980 ADDIUSP = 0x1
14983 /* POOL16E encoding of minor opcode field */
14985 enum {
14986 ADDIUR2 = 0x0,
14987 ADDIUR1SP = 0x1
14990 static int mmreg(int r)
14992 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14994 return map[r];
14997 /* Used for 16-bit store instructions. */
14998 static int mmreg2(int r)
15000 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15002 return map[r];
15005 #define uMIPS_RD(op) ((op >> 7) & 0x7)
15006 #define uMIPS_RS(op) ((op >> 4) & 0x7)
15007 #define uMIPS_RS2(op) uMIPS_RS(op)
15008 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
15009 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15010 #define uMIPS_RS5(op) (op & 0x1f)
15012 /* Signed immediate */
15013 #define SIMM(op, start, width) \
15014 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15015 << (32 - width)) \
15016 >> (32 - width))
15017 /* Zero-extended immediate */
15018 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
15020 static void gen_addiur1sp(DisasContext *ctx)
15022 int rd = mmreg(uMIPS_RD(ctx->opcode));
15024 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
15027 static void gen_addiur2(DisasContext *ctx)
15029 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15030 int rd = mmreg(uMIPS_RD(ctx->opcode));
15031 int rs = mmreg(uMIPS_RS(ctx->opcode));
15033 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
15036 static void gen_addiusp(DisasContext *ctx)
15038 int encoded = ZIMM(ctx->opcode, 1, 9);
15039 int decoded;
15041 if (encoded <= 1) {
15042 decoded = 256 + encoded;
15043 } else if (encoded <= 255) {
15044 decoded = encoded;
15045 } else if (encoded <= 509) {
15046 decoded = encoded - 512;
15047 } else {
15048 decoded = encoded - 768;
15051 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15054 static void gen_addius5(DisasContext *ctx)
15056 int imm = SIMM(ctx->opcode, 1, 4);
15057 int rd = (ctx->opcode >> 5) & 0x1f;
15059 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15062 static void gen_andi16(DisasContext *ctx)
15064 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15065 31, 32, 63, 64, 255, 32768, 65535 };
15066 int rd = mmreg(uMIPS_RD(ctx->opcode));
15067 int rs = mmreg(uMIPS_RS(ctx->opcode));
15068 int encoded = ZIMM(ctx->opcode, 0, 4);
15070 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15073 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15074 int base, int16_t offset)
15076 TCGv t0, t1;
15077 TCGv_i32 t2;
15079 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15080 gen_reserved_instruction(ctx);
15081 return;
15084 t0 = tcg_temp_new();
15086 gen_base_offset_addr(ctx, t0, base, offset);
15088 t1 = tcg_const_tl(reglist);
15089 t2 = tcg_const_i32(ctx->mem_idx);
15091 save_cpu_state(ctx, 1);
15092 switch (opc) {
15093 case LWM32:
15094 gen_helper_lwm(cpu_env, t0, t1, t2);
15095 break;
15096 case SWM32:
15097 gen_helper_swm(cpu_env, t0, t1, t2);
15098 break;
15099 #ifdef TARGET_MIPS64
15100 case LDM:
15101 gen_helper_ldm(cpu_env, t0, t1, t2);
15102 break;
15103 case SDM:
15104 gen_helper_sdm(cpu_env, t0, t1, t2);
15105 break;
15106 #endif
15108 tcg_temp_free(t0);
15109 tcg_temp_free(t1);
15110 tcg_temp_free_i32(t2);
15114 static void gen_pool16c_insn(DisasContext *ctx)
15116 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15117 int rs = mmreg(ctx->opcode & 0x7);
15119 switch (((ctx->opcode) >> 4) & 0x3f) {
15120 case NOT16 + 0:
15121 case NOT16 + 1:
15122 case NOT16 + 2:
15123 case NOT16 + 3:
15124 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15125 break;
15126 case XOR16 + 0:
15127 case XOR16 + 1:
15128 case XOR16 + 2:
15129 case XOR16 + 3:
15130 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15131 break;
15132 case AND16 + 0:
15133 case AND16 + 1:
15134 case AND16 + 2:
15135 case AND16 + 3:
15136 gen_logic(ctx, OPC_AND, rd, rd, rs);
15137 break;
15138 case OR16 + 0:
15139 case OR16 + 1:
15140 case OR16 + 2:
15141 case OR16 + 3:
15142 gen_logic(ctx, OPC_OR, rd, rd, rs);
15143 break;
15144 case LWM16 + 0:
15145 case LWM16 + 1:
15146 case LWM16 + 2:
15147 case LWM16 + 3:
15149 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15150 int offset = ZIMM(ctx->opcode, 0, 4);
15152 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15153 29, offset << 2);
15155 break;
15156 case SWM16 + 0:
15157 case SWM16 + 1:
15158 case SWM16 + 2:
15159 case SWM16 + 3:
15161 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15162 int offset = ZIMM(ctx->opcode, 0, 4);
15164 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15165 29, offset << 2);
15167 break;
15168 case JR16 + 0:
15169 case JR16 + 1:
15171 int reg = ctx->opcode & 0x1f;
15173 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15175 break;
15176 case JRC16 + 0:
15177 case JRC16 + 1:
15179 int reg = ctx->opcode & 0x1f;
15180 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15182 * Let normal delay slot handling in our caller take us
15183 * to the branch target.
15186 break;
15187 case JALR16 + 0:
15188 case JALR16 + 1:
15189 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15190 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15191 break;
15192 case JALR16S + 0:
15193 case JALR16S + 1:
15194 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15195 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15196 break;
15197 case MFHI16 + 0:
15198 case MFHI16 + 1:
15199 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15200 break;
15201 case MFLO16 + 0:
15202 case MFLO16 + 1:
15203 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15204 break;
15205 case BREAK16:
15206 generate_exception_end(ctx, EXCP_BREAK);
15207 break;
15208 case SDBBP16:
15209 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15210 gen_helper_do_semihosting(cpu_env);
15211 } else {
15213 * XXX: not clear which exception should be raised
15214 * when in debug mode...
15216 check_insn(ctx, ISA_MIPS_R1);
15217 generate_exception_end(ctx, EXCP_DBp);
15219 break;
15220 case JRADDIUSP + 0:
15221 case JRADDIUSP + 1:
15223 int imm = ZIMM(ctx->opcode, 0, 5);
15224 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15225 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15227 * Let normal delay slot handling in our caller take us
15228 * to the branch target.
15231 break;
15232 default:
15233 gen_reserved_instruction(ctx);
15234 break;
15238 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15239 int enc_rs)
15241 int rd, rs, re, rt;
15242 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15243 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15244 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15245 rd = rd_enc[enc_dest];
15246 re = re_enc[enc_dest];
15247 rs = rs_rt_enc[enc_rs];
15248 rt = rs_rt_enc[enc_rt];
15249 if (rs) {
15250 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15251 } else {
15252 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15254 if (rt) {
15255 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15256 } else {
15257 tcg_gen_movi_tl(cpu_gpr[re], 0);
15261 static void gen_pool16c_r6_insn(DisasContext *ctx)
15263 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15264 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15266 switch (ctx->opcode & 0xf) {
15267 case R6_NOT16:
15268 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15269 break;
15270 case R6_AND16:
15271 gen_logic(ctx, OPC_AND, rt, rt, rs);
15272 break;
15273 case R6_LWM16:
15275 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15276 int offset = extract32(ctx->opcode, 4, 4);
15277 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15279 break;
15280 case R6_JRC16: /* JRCADDIUSP */
15281 if ((ctx->opcode >> 4) & 1) {
15282 /* JRCADDIUSP */
15283 int imm = extract32(ctx->opcode, 5, 5);
15284 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15285 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15286 } else {
15287 /* JRC16 */
15288 rs = extract32(ctx->opcode, 5, 5);
15289 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15291 break;
15292 case MOVEP:
15293 case MOVEP_05:
15294 case MOVEP_06:
15295 case MOVEP_07:
15296 case MOVEP_0C:
15297 case MOVEP_0D:
15298 case MOVEP_0E:
15299 case MOVEP_0F:
15301 int enc_dest = uMIPS_RD(ctx->opcode);
15302 int enc_rt = uMIPS_RS2(ctx->opcode);
15303 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15304 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15306 break;
15307 case R6_XOR16:
15308 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15309 break;
15310 case R6_OR16:
15311 gen_logic(ctx, OPC_OR, rt, rt, rs);
15312 break;
15313 case R6_SWM16:
15315 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15316 int offset = extract32(ctx->opcode, 4, 4);
15317 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15319 break;
15320 case JALRC16: /* BREAK16, SDBBP16 */
15321 switch (ctx->opcode & 0x3f) {
15322 case JALRC16:
15323 case JALRC16 + 0x20:
15324 /* JALRC16 */
15325 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15326 31, 0, 0);
15327 break;
15328 case R6_BREAK16:
15329 /* BREAK16 */
15330 generate_exception(ctx, EXCP_BREAK);
15331 break;
15332 case R6_SDBBP16:
15333 /* SDBBP16 */
15334 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15335 gen_helper_do_semihosting(cpu_env);
15336 } else {
15337 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15338 generate_exception(ctx, EXCP_RI);
15339 } else {
15340 generate_exception(ctx, EXCP_DBp);
15343 break;
15345 break;
15346 default:
15347 generate_exception(ctx, EXCP_RI);
15348 break;
15352 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15354 TCGv t0 = tcg_temp_new();
15355 TCGv t1 = tcg_temp_new();
15357 gen_load_gpr(t0, base);
15359 if (index != 0) {
15360 gen_load_gpr(t1, index);
15361 tcg_gen_shli_tl(t1, t1, 2);
15362 gen_op_addr_add(ctx, t0, t1, t0);
15365 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15366 gen_store_gpr(t1, rd);
15368 tcg_temp_free(t0);
15369 tcg_temp_free(t1);
15372 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15373 int base, int16_t offset)
15375 TCGv t0, t1;
15377 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15378 gen_reserved_instruction(ctx);
15379 return;
15382 t0 = tcg_temp_new();
15383 t1 = tcg_temp_new();
15385 gen_base_offset_addr(ctx, t0, base, offset);
15387 switch (opc) {
15388 case LWP:
15389 if (rd == base) {
15390 gen_reserved_instruction(ctx);
15391 return;
15393 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15394 gen_store_gpr(t1, rd);
15395 tcg_gen_movi_tl(t1, 4);
15396 gen_op_addr_add(ctx, t0, t0, t1);
15397 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15398 gen_store_gpr(t1, rd + 1);
15399 break;
15400 case SWP:
15401 gen_load_gpr(t1, rd);
15402 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15403 tcg_gen_movi_tl(t1, 4);
15404 gen_op_addr_add(ctx, t0, t0, t1);
15405 gen_load_gpr(t1, rd + 1);
15406 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15407 break;
15408 #ifdef TARGET_MIPS64
15409 case LDP:
15410 if (rd == base) {
15411 gen_reserved_instruction(ctx);
15412 return;
15414 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15415 gen_store_gpr(t1, rd);
15416 tcg_gen_movi_tl(t1, 8);
15417 gen_op_addr_add(ctx, t0, t0, t1);
15418 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15419 gen_store_gpr(t1, rd + 1);
15420 break;
15421 case SDP:
15422 gen_load_gpr(t1, rd);
15423 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15424 tcg_gen_movi_tl(t1, 8);
15425 gen_op_addr_add(ctx, t0, t0, t1);
15426 gen_load_gpr(t1, rd + 1);
15427 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15428 break;
15429 #endif
15431 tcg_temp_free(t0);
15432 tcg_temp_free(t1);
15435 static void gen_sync(int stype)
15437 TCGBar tcg_mo = TCG_BAR_SC;
15439 switch (stype) {
15440 case 0x4: /* SYNC_WMB */
15441 tcg_mo |= TCG_MO_ST_ST;
15442 break;
15443 case 0x10: /* SYNC_MB */
15444 tcg_mo |= TCG_MO_ALL;
15445 break;
15446 case 0x11: /* SYNC_ACQUIRE */
15447 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15448 break;
15449 case 0x12: /* SYNC_RELEASE */
15450 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15451 break;
15452 case 0x13: /* SYNC_RMB */
15453 tcg_mo |= TCG_MO_LD_LD;
15454 break;
15455 default:
15456 tcg_mo |= TCG_MO_ALL;
15457 break;
15460 tcg_gen_mb(tcg_mo);
15463 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15465 int extension = (ctx->opcode >> 6) & 0x3f;
15466 int minor = (ctx->opcode >> 12) & 0xf;
15467 uint32_t mips32_op;
15469 switch (extension) {
15470 case TEQ:
15471 mips32_op = OPC_TEQ;
15472 goto do_trap;
15473 case TGE:
15474 mips32_op = OPC_TGE;
15475 goto do_trap;
15476 case TGEU:
15477 mips32_op = OPC_TGEU;
15478 goto do_trap;
15479 case TLT:
15480 mips32_op = OPC_TLT;
15481 goto do_trap;
15482 case TLTU:
15483 mips32_op = OPC_TLTU;
15484 goto do_trap;
15485 case TNE:
15486 mips32_op = OPC_TNE;
15487 do_trap:
15488 gen_trap(ctx, mips32_op, rs, rt, -1);
15489 break;
15490 #ifndef CONFIG_USER_ONLY
15491 case MFC0:
15492 case MFC0 + 32:
15493 check_cp0_enabled(ctx);
15494 if (rt == 0) {
15495 /* Treat as NOP. */
15496 break;
15498 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15499 break;
15500 case MTC0:
15501 case MTC0 + 32:
15502 check_cp0_enabled(ctx);
15504 TCGv t0 = tcg_temp_new();
15506 gen_load_gpr(t0, rt);
15507 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15508 tcg_temp_free(t0);
15510 break;
15511 #endif
15512 case 0x2a:
15513 switch (minor & 3) {
15514 case MADD_ACC:
15515 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15516 break;
15517 case MADDU_ACC:
15518 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15519 break;
15520 case MSUB_ACC:
15521 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15522 break;
15523 case MSUBU_ACC:
15524 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15525 break;
15526 default:
15527 goto pool32axf_invalid;
15529 break;
15530 case 0x32:
15531 switch (minor & 3) {
15532 case MULT_ACC:
15533 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15534 break;
15535 case MULTU_ACC:
15536 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15537 break;
15538 default:
15539 goto pool32axf_invalid;
15541 break;
15542 case 0x2c:
15543 switch (minor) {
15544 case BITSWAP:
15545 check_insn(ctx, ISA_MIPS_R6);
15546 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15547 break;
15548 case SEB:
15549 gen_bshfl(ctx, OPC_SEB, rs, rt);
15550 break;
15551 case SEH:
15552 gen_bshfl(ctx, OPC_SEH, rs, rt);
15553 break;
15554 case CLO:
15555 mips32_op = OPC_CLO;
15556 goto do_cl;
15557 case CLZ:
15558 mips32_op = OPC_CLZ;
15559 do_cl:
15560 check_insn(ctx, ISA_MIPS_R1);
15561 gen_cl(ctx, mips32_op, rt, rs);
15562 break;
15563 case RDHWR:
15564 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15565 gen_rdhwr(ctx, rt, rs, 0);
15566 break;
15567 case WSBH:
15568 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15569 break;
15570 case MULT:
15571 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15572 mips32_op = OPC_MULT;
15573 goto do_mul;
15574 case MULTU:
15575 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15576 mips32_op = OPC_MULTU;
15577 goto do_mul;
15578 case DIV:
15579 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15580 mips32_op = OPC_DIV;
15581 goto do_div;
15582 case DIVU:
15583 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15584 mips32_op = OPC_DIVU;
15585 goto do_div;
15586 do_div:
15587 check_insn(ctx, ISA_MIPS_R1);
15588 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15589 break;
15590 case MADD:
15591 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15592 mips32_op = OPC_MADD;
15593 goto do_mul;
15594 case MADDU:
15595 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15596 mips32_op = OPC_MADDU;
15597 goto do_mul;
15598 case MSUB:
15599 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15600 mips32_op = OPC_MSUB;
15601 goto do_mul;
15602 case MSUBU:
15603 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15604 mips32_op = OPC_MSUBU;
15605 do_mul:
15606 check_insn(ctx, ISA_MIPS_R1);
15607 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15608 break;
15609 default:
15610 goto pool32axf_invalid;
15612 break;
15613 case 0x34:
15614 switch (minor) {
15615 case MFC2:
15616 case MTC2:
15617 case MFHC2:
15618 case MTHC2:
15619 case CFC2:
15620 case CTC2:
15621 generate_exception_err(ctx, EXCP_CpU, 2);
15622 break;
15623 default:
15624 goto pool32axf_invalid;
15626 break;
15627 case 0x3c:
15628 switch (minor) {
15629 case JALR: /* JALRC */
15630 case JALR_HB: /* JALRC_HB */
15631 if (ctx->insn_flags & ISA_MIPS_R6) {
15632 /* JALRC, JALRC_HB */
15633 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15634 } else {
15635 /* JALR, JALR_HB */
15636 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15637 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15639 break;
15640 case JALRS:
15641 case JALRS_HB:
15642 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15643 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15644 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15645 break;
15646 default:
15647 goto pool32axf_invalid;
15649 break;
15650 case 0x05:
15651 switch (minor) {
15652 case RDPGPR:
15653 check_cp0_enabled(ctx);
15654 check_insn(ctx, ISA_MIPS_R2);
15655 gen_load_srsgpr(rs, rt);
15656 break;
15657 case WRPGPR:
15658 check_cp0_enabled(ctx);
15659 check_insn(ctx, ISA_MIPS_R2);
15660 gen_store_srsgpr(rs, rt);
15661 break;
15662 default:
15663 goto pool32axf_invalid;
15665 break;
15666 #ifndef CONFIG_USER_ONLY
15667 case 0x0d:
15668 switch (minor) {
15669 case TLBP:
15670 mips32_op = OPC_TLBP;
15671 goto do_cp0;
15672 case TLBR:
15673 mips32_op = OPC_TLBR;
15674 goto do_cp0;
15675 case TLBWI:
15676 mips32_op = OPC_TLBWI;
15677 goto do_cp0;
15678 case TLBWR:
15679 mips32_op = OPC_TLBWR;
15680 goto do_cp0;
15681 case TLBINV:
15682 mips32_op = OPC_TLBINV;
15683 goto do_cp0;
15684 case TLBINVF:
15685 mips32_op = OPC_TLBINVF;
15686 goto do_cp0;
15687 case WAIT:
15688 mips32_op = OPC_WAIT;
15689 goto do_cp0;
15690 case DERET:
15691 mips32_op = OPC_DERET;
15692 goto do_cp0;
15693 case ERET:
15694 mips32_op = OPC_ERET;
15695 do_cp0:
15696 gen_cp0(env, ctx, mips32_op, rt, rs);
15697 break;
15698 default:
15699 goto pool32axf_invalid;
15701 break;
15702 case 0x1d:
15703 switch (minor) {
15704 case DI:
15705 check_cp0_enabled(ctx);
15707 TCGv t0 = tcg_temp_new();
15709 save_cpu_state(ctx, 1);
15710 gen_helper_di(t0, cpu_env);
15711 gen_store_gpr(t0, rs);
15713 * Stop translation as we may have switched the execution
15714 * mode.
15716 ctx->base.is_jmp = DISAS_STOP;
15717 tcg_temp_free(t0);
15719 break;
15720 case EI:
15721 check_cp0_enabled(ctx);
15723 TCGv t0 = tcg_temp_new();
15725 save_cpu_state(ctx, 1);
15726 gen_helper_ei(t0, cpu_env);
15727 gen_store_gpr(t0, rs);
15729 * DISAS_STOP isn't sufficient, we need to ensure we break out
15730 * of translated code to check for pending interrupts.
15732 gen_save_pc(ctx->base.pc_next + 4);
15733 ctx->base.is_jmp = DISAS_EXIT;
15734 tcg_temp_free(t0);
15736 break;
15737 default:
15738 goto pool32axf_invalid;
15740 break;
15741 #endif
15742 case 0x2d:
15743 switch (minor) {
15744 case SYNC:
15745 gen_sync(extract32(ctx->opcode, 16, 5));
15746 break;
15747 case SYSCALL:
15748 generate_exception_end(ctx, EXCP_SYSCALL);
15749 break;
15750 case SDBBP:
15751 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15752 gen_helper_do_semihosting(cpu_env);
15753 } else {
15754 check_insn(ctx, ISA_MIPS_R1);
15755 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15756 gen_reserved_instruction(ctx);
15757 } else {
15758 generate_exception_end(ctx, EXCP_DBp);
15761 break;
15762 default:
15763 goto pool32axf_invalid;
15765 break;
15766 case 0x01:
15767 switch (minor & 3) {
15768 case MFHI_ACC:
15769 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15770 break;
15771 case MFLO_ACC:
15772 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15773 break;
15774 case MTHI_ACC:
15775 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15776 break;
15777 case MTLO_ACC:
15778 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15779 break;
15780 default:
15781 goto pool32axf_invalid;
15783 break;
15784 case 0x35:
15785 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15786 switch (minor) {
15787 case MFHI32:
15788 gen_HILO(ctx, OPC_MFHI, 0, rs);
15789 break;
15790 case MFLO32:
15791 gen_HILO(ctx, OPC_MFLO, 0, rs);
15792 break;
15793 case MTHI32:
15794 gen_HILO(ctx, OPC_MTHI, 0, rs);
15795 break;
15796 case MTLO32:
15797 gen_HILO(ctx, OPC_MTLO, 0, rs);
15798 break;
15799 default:
15800 goto pool32axf_invalid;
15802 break;
15803 default:
15804 pool32axf_invalid:
15805 MIPS_INVAL("pool32axf");
15806 gen_reserved_instruction(ctx);
15807 break;
15812 * Values for microMIPS fmt field. Variable-width, depending on which
15813 * formats the instruction supports.
15815 enum {
15816 FMT_SD_S = 0,
15817 FMT_SD_D = 1,
15819 FMT_SDPS_S = 0,
15820 FMT_SDPS_D = 1,
15821 FMT_SDPS_PS = 2,
15823 FMT_SWL_S = 0,
15824 FMT_SWL_W = 1,
15825 FMT_SWL_L = 2,
15827 FMT_DWL_D = 0,
15828 FMT_DWL_W = 1,
15829 FMT_DWL_L = 2
15832 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15834 int extension = (ctx->opcode >> 6) & 0x3ff;
15835 uint32_t mips32_op;
15837 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
15838 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
15839 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
15841 switch (extension) {
15842 case FLOAT_1BIT_FMT(CFC1, 0):
15843 mips32_op = OPC_CFC1;
15844 goto do_cp1;
15845 case FLOAT_1BIT_FMT(CTC1, 0):
15846 mips32_op = OPC_CTC1;
15847 goto do_cp1;
15848 case FLOAT_1BIT_FMT(MFC1, 0):
15849 mips32_op = OPC_MFC1;
15850 goto do_cp1;
15851 case FLOAT_1BIT_FMT(MTC1, 0):
15852 mips32_op = OPC_MTC1;
15853 goto do_cp1;
15854 case FLOAT_1BIT_FMT(MFHC1, 0):
15855 mips32_op = OPC_MFHC1;
15856 goto do_cp1;
15857 case FLOAT_1BIT_FMT(MTHC1, 0):
15858 mips32_op = OPC_MTHC1;
15859 do_cp1:
15860 gen_cp1(ctx, mips32_op, rt, rs);
15861 break;
15863 /* Reciprocal square root */
15864 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15865 mips32_op = OPC_RSQRT_S;
15866 goto do_unaryfp;
15867 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15868 mips32_op = OPC_RSQRT_D;
15869 goto do_unaryfp;
15871 /* Square root */
15872 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15873 mips32_op = OPC_SQRT_S;
15874 goto do_unaryfp;
15875 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15876 mips32_op = OPC_SQRT_D;
15877 goto do_unaryfp;
15879 /* Reciprocal */
15880 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15881 mips32_op = OPC_RECIP_S;
15882 goto do_unaryfp;
15883 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15884 mips32_op = OPC_RECIP_D;
15885 goto do_unaryfp;
15887 /* Floor */
15888 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15889 mips32_op = OPC_FLOOR_L_S;
15890 goto do_unaryfp;
15891 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15892 mips32_op = OPC_FLOOR_L_D;
15893 goto do_unaryfp;
15894 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15895 mips32_op = OPC_FLOOR_W_S;
15896 goto do_unaryfp;
15897 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15898 mips32_op = OPC_FLOOR_W_D;
15899 goto do_unaryfp;
15901 /* Ceiling */
15902 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15903 mips32_op = OPC_CEIL_L_S;
15904 goto do_unaryfp;
15905 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15906 mips32_op = OPC_CEIL_L_D;
15907 goto do_unaryfp;
15908 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15909 mips32_op = OPC_CEIL_W_S;
15910 goto do_unaryfp;
15911 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15912 mips32_op = OPC_CEIL_W_D;
15913 goto do_unaryfp;
15915 /* Truncation */
15916 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15917 mips32_op = OPC_TRUNC_L_S;
15918 goto do_unaryfp;
15919 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15920 mips32_op = OPC_TRUNC_L_D;
15921 goto do_unaryfp;
15922 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15923 mips32_op = OPC_TRUNC_W_S;
15924 goto do_unaryfp;
15925 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15926 mips32_op = OPC_TRUNC_W_D;
15927 goto do_unaryfp;
15929 /* Round */
15930 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15931 mips32_op = OPC_ROUND_L_S;
15932 goto do_unaryfp;
15933 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15934 mips32_op = OPC_ROUND_L_D;
15935 goto do_unaryfp;
15936 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15937 mips32_op = OPC_ROUND_W_S;
15938 goto do_unaryfp;
15939 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15940 mips32_op = OPC_ROUND_W_D;
15941 goto do_unaryfp;
15943 /* Integer to floating-point conversion */
15944 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15945 mips32_op = OPC_CVT_L_S;
15946 goto do_unaryfp;
15947 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15948 mips32_op = OPC_CVT_L_D;
15949 goto do_unaryfp;
15950 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15951 mips32_op = OPC_CVT_W_S;
15952 goto do_unaryfp;
15953 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15954 mips32_op = OPC_CVT_W_D;
15955 goto do_unaryfp;
15957 /* Paired-foo conversions */
15958 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15959 mips32_op = OPC_CVT_S_PL;
15960 goto do_unaryfp;
15961 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15962 mips32_op = OPC_CVT_S_PU;
15963 goto do_unaryfp;
15964 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15965 mips32_op = OPC_CVT_PW_PS;
15966 goto do_unaryfp;
15967 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15968 mips32_op = OPC_CVT_PS_PW;
15969 goto do_unaryfp;
15971 /* Floating-point moves */
15972 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15973 mips32_op = OPC_MOV_S;
15974 goto do_unaryfp;
15975 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15976 mips32_op = OPC_MOV_D;
15977 goto do_unaryfp;
15978 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15979 mips32_op = OPC_MOV_PS;
15980 goto do_unaryfp;
15982 /* Absolute value */
15983 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15984 mips32_op = OPC_ABS_S;
15985 goto do_unaryfp;
15986 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15987 mips32_op = OPC_ABS_D;
15988 goto do_unaryfp;
15989 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15990 mips32_op = OPC_ABS_PS;
15991 goto do_unaryfp;
15993 /* Negation */
15994 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15995 mips32_op = OPC_NEG_S;
15996 goto do_unaryfp;
15997 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15998 mips32_op = OPC_NEG_D;
15999 goto do_unaryfp;
16000 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16001 mips32_op = OPC_NEG_PS;
16002 goto do_unaryfp;
16004 /* Reciprocal square root step */
16005 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16006 mips32_op = OPC_RSQRT1_S;
16007 goto do_unaryfp;
16008 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16009 mips32_op = OPC_RSQRT1_D;
16010 goto do_unaryfp;
16011 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16012 mips32_op = OPC_RSQRT1_PS;
16013 goto do_unaryfp;
16015 /* Reciprocal step */
16016 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16017 mips32_op = OPC_RECIP1_S;
16018 goto do_unaryfp;
16019 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16020 mips32_op = OPC_RECIP1_S;
16021 goto do_unaryfp;
16022 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16023 mips32_op = OPC_RECIP1_PS;
16024 goto do_unaryfp;
16026 /* Conversions from double */
16027 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16028 mips32_op = OPC_CVT_D_S;
16029 goto do_unaryfp;
16030 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16031 mips32_op = OPC_CVT_D_W;
16032 goto do_unaryfp;
16033 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16034 mips32_op = OPC_CVT_D_L;
16035 goto do_unaryfp;
16037 /* Conversions from single */
16038 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16039 mips32_op = OPC_CVT_S_D;
16040 goto do_unaryfp;
16041 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16042 mips32_op = OPC_CVT_S_W;
16043 goto do_unaryfp;
16044 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16045 mips32_op = OPC_CVT_S_L;
16046 do_unaryfp:
16047 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16048 break;
16050 /* Conditional moves on floating-point codes */
16051 case COND_FLOAT_MOV(MOVT, 0):
16052 case COND_FLOAT_MOV(MOVT, 1):
16053 case COND_FLOAT_MOV(MOVT, 2):
16054 case COND_FLOAT_MOV(MOVT, 3):
16055 case COND_FLOAT_MOV(MOVT, 4):
16056 case COND_FLOAT_MOV(MOVT, 5):
16057 case COND_FLOAT_MOV(MOVT, 6):
16058 case COND_FLOAT_MOV(MOVT, 7):
16059 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16060 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16061 break;
16062 case COND_FLOAT_MOV(MOVF, 0):
16063 case COND_FLOAT_MOV(MOVF, 1):
16064 case COND_FLOAT_MOV(MOVF, 2):
16065 case COND_FLOAT_MOV(MOVF, 3):
16066 case COND_FLOAT_MOV(MOVF, 4):
16067 case COND_FLOAT_MOV(MOVF, 5):
16068 case COND_FLOAT_MOV(MOVF, 6):
16069 case COND_FLOAT_MOV(MOVF, 7):
16070 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16071 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16072 break;
16073 default:
16074 MIPS_INVAL("pool32fxf");
16075 gen_reserved_instruction(ctx);
16076 break;
16080 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16082 int32_t offset;
16083 uint16_t insn;
16084 int rt, rs, rd, rr;
16085 int16_t imm;
16086 uint32_t op, minor, minor2, mips32_op;
16087 uint32_t cond, fmt, cc;
16089 insn = translator_lduw(env, ctx->base.pc_next + 2);
16090 ctx->opcode = (ctx->opcode << 16) | insn;
16092 rt = (ctx->opcode >> 21) & 0x1f;
16093 rs = (ctx->opcode >> 16) & 0x1f;
16094 rd = (ctx->opcode >> 11) & 0x1f;
16095 rr = (ctx->opcode >> 6) & 0x1f;
16096 imm = (int16_t) ctx->opcode;
16098 op = (ctx->opcode >> 26) & 0x3f;
16099 switch (op) {
16100 case POOL32A:
16101 minor = ctx->opcode & 0x3f;
16102 switch (minor) {
16103 case 0x00:
16104 minor = (ctx->opcode >> 6) & 0xf;
16105 switch (minor) {
16106 case SLL32:
16107 mips32_op = OPC_SLL;
16108 goto do_shifti;
16109 case SRA:
16110 mips32_op = OPC_SRA;
16111 goto do_shifti;
16112 case SRL32:
16113 mips32_op = OPC_SRL;
16114 goto do_shifti;
16115 case ROTR:
16116 mips32_op = OPC_ROTR;
16117 do_shifti:
16118 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16119 break;
16120 case SELEQZ:
16121 check_insn(ctx, ISA_MIPS_R6);
16122 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16123 break;
16124 case SELNEZ:
16125 check_insn(ctx, ISA_MIPS_R6);
16126 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16127 break;
16128 case R6_RDHWR:
16129 check_insn(ctx, ISA_MIPS_R6);
16130 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16131 break;
16132 default:
16133 goto pool32a_invalid;
16135 break;
16136 case 0x10:
16137 minor = (ctx->opcode >> 6) & 0xf;
16138 switch (minor) {
16139 /* Arithmetic */
16140 case ADD:
16141 mips32_op = OPC_ADD;
16142 goto do_arith;
16143 case ADDU32:
16144 mips32_op = OPC_ADDU;
16145 goto do_arith;
16146 case SUB:
16147 mips32_op = OPC_SUB;
16148 goto do_arith;
16149 case SUBU32:
16150 mips32_op = OPC_SUBU;
16151 goto do_arith;
16152 case MUL:
16153 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16154 mips32_op = OPC_MUL;
16155 do_arith:
16156 gen_arith(ctx, mips32_op, rd, rs, rt);
16157 break;
16158 /* Shifts */
16159 case SLLV:
16160 mips32_op = OPC_SLLV;
16161 goto do_shift;
16162 case SRLV:
16163 mips32_op = OPC_SRLV;
16164 goto do_shift;
16165 case SRAV:
16166 mips32_op = OPC_SRAV;
16167 goto do_shift;
16168 case ROTRV:
16169 mips32_op = OPC_ROTRV;
16170 do_shift:
16171 gen_shift(ctx, mips32_op, rd, rs, rt);
16172 break;
16173 /* Logical operations */
16174 case AND:
16175 mips32_op = OPC_AND;
16176 goto do_logic;
16177 case OR32:
16178 mips32_op = OPC_OR;
16179 goto do_logic;
16180 case NOR:
16181 mips32_op = OPC_NOR;
16182 goto do_logic;
16183 case XOR32:
16184 mips32_op = OPC_XOR;
16185 do_logic:
16186 gen_logic(ctx, mips32_op, rd, rs, rt);
16187 break;
16188 /* Set less than */
16189 case SLT:
16190 mips32_op = OPC_SLT;
16191 goto do_slt;
16192 case SLTU:
16193 mips32_op = OPC_SLTU;
16194 do_slt:
16195 gen_slt(ctx, mips32_op, rd, rs, rt);
16196 break;
16197 default:
16198 goto pool32a_invalid;
16200 break;
16201 case 0x18:
16202 minor = (ctx->opcode >> 6) & 0xf;
16203 switch (minor) {
16204 /* Conditional moves */
16205 case MOVN: /* MUL */
16206 if (ctx->insn_flags & ISA_MIPS_R6) {
16207 /* MUL */
16208 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16209 } else {
16210 /* MOVN */
16211 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16213 break;
16214 case MOVZ: /* MUH */
16215 if (ctx->insn_flags & ISA_MIPS_R6) {
16216 /* MUH */
16217 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16218 } else {
16219 /* MOVZ */
16220 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16222 break;
16223 case MULU:
16224 check_insn(ctx, ISA_MIPS_R6);
16225 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16226 break;
16227 case MUHU:
16228 check_insn(ctx, ISA_MIPS_R6);
16229 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16230 break;
16231 case LWXS: /* DIV */
16232 if (ctx->insn_flags & ISA_MIPS_R6) {
16233 /* DIV */
16234 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16235 } else {
16236 /* LWXS */
16237 gen_ldxs(ctx, rs, rt, rd);
16239 break;
16240 case MOD:
16241 check_insn(ctx, ISA_MIPS_R6);
16242 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16243 break;
16244 case R6_DIVU:
16245 check_insn(ctx, ISA_MIPS_R6);
16246 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16247 break;
16248 case MODU:
16249 check_insn(ctx, ISA_MIPS_R6);
16250 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16251 break;
16252 default:
16253 goto pool32a_invalid;
16255 break;
16256 case INS:
16257 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16258 return;
16259 case LSA:
16260 check_insn(ctx, ISA_MIPS_R6);
16261 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2));
16262 break;
16263 case ALIGN:
16264 check_insn(ctx, ISA_MIPS_R6);
16265 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16266 break;
16267 case EXT:
16268 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16269 return;
16270 case POOL32AXF:
16271 gen_pool32axf(env, ctx, rt, rs);
16272 break;
16273 case BREAK32:
16274 generate_exception_end(ctx, EXCP_BREAK);
16275 break;
16276 case SIGRIE:
16277 check_insn(ctx, ISA_MIPS_R6);
16278 gen_reserved_instruction(ctx);
16279 break;
16280 default:
16281 pool32a_invalid:
16282 MIPS_INVAL("pool32a");
16283 gen_reserved_instruction(ctx);
16284 break;
16286 break;
16287 case POOL32B:
16288 minor = (ctx->opcode >> 12) & 0xf;
16289 switch (minor) {
16290 case CACHE:
16291 check_cp0_enabled(ctx);
16292 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16293 gen_cache_operation(ctx, rt, rs, imm);
16295 break;
16296 case LWC2:
16297 case SWC2:
16298 /* COP2: Not implemented. */
16299 generate_exception_err(ctx, EXCP_CpU, 2);
16300 break;
16301 #ifdef TARGET_MIPS64
16302 case LDP:
16303 case SDP:
16304 check_insn(ctx, ISA_MIPS3);
16305 check_mips_64(ctx);
16306 #endif
16307 /* fall through */
16308 case LWP:
16309 case SWP:
16310 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16311 break;
16312 #ifdef TARGET_MIPS64
16313 case LDM:
16314 case SDM:
16315 check_insn(ctx, ISA_MIPS3);
16316 check_mips_64(ctx);
16317 #endif
16318 /* fall through */
16319 case LWM32:
16320 case SWM32:
16321 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16322 break;
16323 default:
16324 MIPS_INVAL("pool32b");
16325 gen_reserved_instruction(ctx);
16326 break;
16328 break;
16329 case POOL32F:
16330 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16331 minor = ctx->opcode & 0x3f;
16332 check_cp1_enabled(ctx);
16333 switch (minor) {
16334 case ALNV_PS:
16335 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16336 mips32_op = OPC_ALNV_PS;
16337 goto do_madd;
16338 case MADD_S:
16339 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16340 mips32_op = OPC_MADD_S;
16341 goto do_madd;
16342 case MADD_D:
16343 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16344 mips32_op = OPC_MADD_D;
16345 goto do_madd;
16346 case MADD_PS:
16347 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16348 mips32_op = OPC_MADD_PS;
16349 goto do_madd;
16350 case MSUB_S:
16351 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16352 mips32_op = OPC_MSUB_S;
16353 goto do_madd;
16354 case MSUB_D:
16355 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16356 mips32_op = OPC_MSUB_D;
16357 goto do_madd;
16358 case MSUB_PS:
16359 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16360 mips32_op = OPC_MSUB_PS;
16361 goto do_madd;
16362 case NMADD_S:
16363 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16364 mips32_op = OPC_NMADD_S;
16365 goto do_madd;
16366 case NMADD_D:
16367 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16368 mips32_op = OPC_NMADD_D;
16369 goto do_madd;
16370 case NMADD_PS:
16371 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16372 mips32_op = OPC_NMADD_PS;
16373 goto do_madd;
16374 case NMSUB_S:
16375 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16376 mips32_op = OPC_NMSUB_S;
16377 goto do_madd;
16378 case NMSUB_D:
16379 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16380 mips32_op = OPC_NMSUB_D;
16381 goto do_madd;
16382 case NMSUB_PS:
16383 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16384 mips32_op = OPC_NMSUB_PS;
16385 do_madd:
16386 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16387 break;
16388 case CABS_COND_FMT:
16389 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16390 cond = (ctx->opcode >> 6) & 0xf;
16391 cc = (ctx->opcode >> 13) & 0x7;
16392 fmt = (ctx->opcode >> 10) & 0x3;
16393 switch (fmt) {
16394 case 0x0:
16395 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16396 break;
16397 case 0x1:
16398 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16399 break;
16400 case 0x2:
16401 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16402 break;
16403 default:
16404 goto pool32f_invalid;
16406 break;
16407 case C_COND_FMT:
16408 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16409 cond = (ctx->opcode >> 6) & 0xf;
16410 cc = (ctx->opcode >> 13) & 0x7;
16411 fmt = (ctx->opcode >> 10) & 0x3;
16412 switch (fmt) {
16413 case 0x0:
16414 gen_cmp_s(ctx, cond, rt, rs, cc);
16415 break;
16416 case 0x1:
16417 gen_cmp_d(ctx, cond, rt, rs, cc);
16418 break;
16419 case 0x2:
16420 gen_cmp_ps(ctx, cond, rt, rs, cc);
16421 break;
16422 default:
16423 goto pool32f_invalid;
16425 break;
16426 case CMP_CONDN_S:
16427 check_insn(ctx, ISA_MIPS_R6);
16428 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16429 break;
16430 case CMP_CONDN_D:
16431 check_insn(ctx, ISA_MIPS_R6);
16432 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16433 break;
16434 case POOL32FXF:
16435 gen_pool32fxf(ctx, rt, rs);
16436 break;
16437 case 0x00:
16438 /* PLL foo */
16439 switch ((ctx->opcode >> 6) & 0x7) {
16440 case PLL_PS:
16441 mips32_op = OPC_PLL_PS;
16442 goto do_ps;
16443 case PLU_PS:
16444 mips32_op = OPC_PLU_PS;
16445 goto do_ps;
16446 case PUL_PS:
16447 mips32_op = OPC_PUL_PS;
16448 goto do_ps;
16449 case PUU_PS:
16450 mips32_op = OPC_PUU_PS;
16451 goto do_ps;
16452 case CVT_PS_S:
16453 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16454 mips32_op = OPC_CVT_PS_S;
16455 do_ps:
16456 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16457 break;
16458 default:
16459 goto pool32f_invalid;
16461 break;
16462 case MIN_FMT:
16463 check_insn(ctx, ISA_MIPS_R6);
16464 switch ((ctx->opcode >> 9) & 0x3) {
16465 case FMT_SDPS_S:
16466 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16467 break;
16468 case FMT_SDPS_D:
16469 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16470 break;
16471 default:
16472 goto pool32f_invalid;
16474 break;
16475 case 0x08:
16476 /* [LS][WDU]XC1 */
16477 switch ((ctx->opcode >> 6) & 0x7) {
16478 case LWXC1:
16479 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16480 mips32_op = OPC_LWXC1;
16481 goto do_ldst_cp1;
16482 case SWXC1:
16483 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16484 mips32_op = OPC_SWXC1;
16485 goto do_ldst_cp1;
16486 case LDXC1:
16487 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16488 mips32_op = OPC_LDXC1;
16489 goto do_ldst_cp1;
16490 case SDXC1:
16491 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16492 mips32_op = OPC_SDXC1;
16493 goto do_ldst_cp1;
16494 case LUXC1:
16495 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16496 mips32_op = OPC_LUXC1;
16497 goto do_ldst_cp1;
16498 case SUXC1:
16499 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16500 mips32_op = OPC_SUXC1;
16501 do_ldst_cp1:
16502 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16503 break;
16504 default:
16505 goto pool32f_invalid;
16507 break;
16508 case MAX_FMT:
16509 check_insn(ctx, ISA_MIPS_R6);
16510 switch ((ctx->opcode >> 9) & 0x3) {
16511 case FMT_SDPS_S:
16512 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16513 break;
16514 case FMT_SDPS_D:
16515 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16516 break;
16517 default:
16518 goto pool32f_invalid;
16520 break;
16521 case 0x18:
16522 /* 3D insns */
16523 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16524 fmt = (ctx->opcode >> 9) & 0x3;
16525 switch ((ctx->opcode >> 6) & 0x7) {
16526 case RSQRT2_FMT:
16527 switch (fmt) {
16528 case FMT_SDPS_S:
16529 mips32_op = OPC_RSQRT2_S;
16530 goto do_3d;
16531 case FMT_SDPS_D:
16532 mips32_op = OPC_RSQRT2_D;
16533 goto do_3d;
16534 case FMT_SDPS_PS:
16535 mips32_op = OPC_RSQRT2_PS;
16536 goto do_3d;
16537 default:
16538 goto pool32f_invalid;
16540 break;
16541 case RECIP2_FMT:
16542 switch (fmt) {
16543 case FMT_SDPS_S:
16544 mips32_op = OPC_RECIP2_S;
16545 goto do_3d;
16546 case FMT_SDPS_D:
16547 mips32_op = OPC_RECIP2_D;
16548 goto do_3d;
16549 case FMT_SDPS_PS:
16550 mips32_op = OPC_RECIP2_PS;
16551 goto do_3d;
16552 default:
16553 goto pool32f_invalid;
16555 break;
16556 case ADDR_PS:
16557 mips32_op = OPC_ADDR_PS;
16558 goto do_3d;
16559 case MULR_PS:
16560 mips32_op = OPC_MULR_PS;
16561 do_3d:
16562 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16563 break;
16564 default:
16565 goto pool32f_invalid;
16567 break;
16568 case 0x20:
16569 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16570 cc = (ctx->opcode >> 13) & 0x7;
16571 fmt = (ctx->opcode >> 9) & 0x3;
16572 switch ((ctx->opcode >> 6) & 0x7) {
16573 case MOVF_FMT: /* RINT_FMT */
16574 if (ctx->insn_flags & ISA_MIPS_R6) {
16575 /* RINT_FMT */
16576 switch (fmt) {
16577 case FMT_SDPS_S:
16578 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16579 break;
16580 case FMT_SDPS_D:
16581 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16582 break;
16583 default:
16584 goto pool32f_invalid;
16586 } else {
16587 /* MOVF_FMT */
16588 switch (fmt) {
16589 case FMT_SDPS_S:
16590 gen_movcf_s(ctx, rs, rt, cc, 0);
16591 break;
16592 case FMT_SDPS_D:
16593 gen_movcf_d(ctx, rs, rt, cc, 0);
16594 break;
16595 case FMT_SDPS_PS:
16596 check_ps(ctx);
16597 gen_movcf_ps(ctx, rs, rt, cc, 0);
16598 break;
16599 default:
16600 goto pool32f_invalid;
16603 break;
16604 case MOVT_FMT: /* CLASS_FMT */
16605 if (ctx->insn_flags & ISA_MIPS_R6) {
16606 /* CLASS_FMT */
16607 switch (fmt) {
16608 case FMT_SDPS_S:
16609 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16610 break;
16611 case FMT_SDPS_D:
16612 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16613 break;
16614 default:
16615 goto pool32f_invalid;
16617 } else {
16618 /* MOVT_FMT */
16619 switch (fmt) {
16620 case FMT_SDPS_S:
16621 gen_movcf_s(ctx, rs, rt, cc, 1);
16622 break;
16623 case FMT_SDPS_D:
16624 gen_movcf_d(ctx, rs, rt, cc, 1);
16625 break;
16626 case FMT_SDPS_PS:
16627 check_ps(ctx);
16628 gen_movcf_ps(ctx, rs, rt, cc, 1);
16629 break;
16630 default:
16631 goto pool32f_invalid;
16634 break;
16635 case PREFX:
16636 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16637 break;
16638 default:
16639 goto pool32f_invalid;
16641 break;
16642 #define FINSN_3ARG_SDPS(prfx) \
16643 switch ((ctx->opcode >> 8) & 0x3) { \
16644 case FMT_SDPS_S: \
16645 mips32_op = OPC_##prfx##_S; \
16646 goto do_fpop; \
16647 case FMT_SDPS_D: \
16648 mips32_op = OPC_##prfx##_D; \
16649 goto do_fpop; \
16650 case FMT_SDPS_PS: \
16651 check_ps(ctx); \
16652 mips32_op = OPC_##prfx##_PS; \
16653 goto do_fpop; \
16654 default: \
16655 goto pool32f_invalid; \
16657 case MINA_FMT:
16658 check_insn(ctx, ISA_MIPS_R6);
16659 switch ((ctx->opcode >> 9) & 0x3) {
16660 case FMT_SDPS_S:
16661 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16662 break;
16663 case FMT_SDPS_D:
16664 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16665 break;
16666 default:
16667 goto pool32f_invalid;
16669 break;
16670 case MAXA_FMT:
16671 check_insn(ctx, ISA_MIPS_R6);
16672 switch ((ctx->opcode >> 9) & 0x3) {
16673 case FMT_SDPS_S:
16674 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16675 break;
16676 case FMT_SDPS_D:
16677 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16678 break;
16679 default:
16680 goto pool32f_invalid;
16682 break;
16683 case 0x30:
16684 /* regular FP ops */
16685 switch ((ctx->opcode >> 6) & 0x3) {
16686 case ADD_FMT:
16687 FINSN_3ARG_SDPS(ADD);
16688 break;
16689 case SUB_FMT:
16690 FINSN_3ARG_SDPS(SUB);
16691 break;
16692 case MUL_FMT:
16693 FINSN_3ARG_SDPS(MUL);
16694 break;
16695 case DIV_FMT:
16696 fmt = (ctx->opcode >> 8) & 0x3;
16697 if (fmt == 1) {
16698 mips32_op = OPC_DIV_D;
16699 } else if (fmt == 0) {
16700 mips32_op = OPC_DIV_S;
16701 } else {
16702 goto pool32f_invalid;
16704 goto do_fpop;
16705 default:
16706 goto pool32f_invalid;
16708 break;
16709 case 0x38:
16710 /* cmovs */
16711 switch ((ctx->opcode >> 6) & 0x7) {
16712 case MOVN_FMT: /* SELEQZ_FMT */
16713 if (ctx->insn_flags & ISA_MIPS_R6) {
16714 /* SELEQZ_FMT */
16715 switch ((ctx->opcode >> 9) & 0x3) {
16716 case FMT_SDPS_S:
16717 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16718 break;
16719 case FMT_SDPS_D:
16720 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16721 break;
16722 default:
16723 goto pool32f_invalid;
16725 } else {
16726 /* MOVN_FMT */
16727 FINSN_3ARG_SDPS(MOVN);
16729 break;
16730 case MOVN_FMT_04:
16731 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16732 FINSN_3ARG_SDPS(MOVN);
16733 break;
16734 case MOVZ_FMT: /* SELNEZ_FMT */
16735 if (ctx->insn_flags & ISA_MIPS_R6) {
16736 /* SELNEZ_FMT */
16737 switch ((ctx->opcode >> 9) & 0x3) {
16738 case FMT_SDPS_S:
16739 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16740 break;
16741 case FMT_SDPS_D:
16742 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16743 break;
16744 default:
16745 goto pool32f_invalid;
16747 } else {
16748 /* MOVZ_FMT */
16749 FINSN_3ARG_SDPS(MOVZ);
16751 break;
16752 case MOVZ_FMT_05:
16753 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16754 FINSN_3ARG_SDPS(MOVZ);
16755 break;
16756 case SEL_FMT:
16757 check_insn(ctx, ISA_MIPS_R6);
16758 switch ((ctx->opcode >> 9) & 0x3) {
16759 case FMT_SDPS_S:
16760 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16761 break;
16762 case FMT_SDPS_D:
16763 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16764 break;
16765 default:
16766 goto pool32f_invalid;
16768 break;
16769 case MADDF_FMT:
16770 check_insn(ctx, ISA_MIPS_R6);
16771 switch ((ctx->opcode >> 9) & 0x3) {
16772 case FMT_SDPS_S:
16773 mips32_op = OPC_MADDF_S;
16774 goto do_fpop;
16775 case FMT_SDPS_D:
16776 mips32_op = OPC_MADDF_D;
16777 goto do_fpop;
16778 default:
16779 goto pool32f_invalid;
16781 break;
16782 case MSUBF_FMT:
16783 check_insn(ctx, ISA_MIPS_R6);
16784 switch ((ctx->opcode >> 9) & 0x3) {
16785 case FMT_SDPS_S:
16786 mips32_op = OPC_MSUBF_S;
16787 goto do_fpop;
16788 case FMT_SDPS_D:
16789 mips32_op = OPC_MSUBF_D;
16790 goto do_fpop;
16791 default:
16792 goto pool32f_invalid;
16794 break;
16795 default:
16796 goto pool32f_invalid;
16798 break;
16799 do_fpop:
16800 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16801 break;
16802 default:
16803 pool32f_invalid:
16804 MIPS_INVAL("pool32f");
16805 gen_reserved_instruction(ctx);
16806 break;
16808 } else {
16809 generate_exception_err(ctx, EXCP_CpU, 1);
16811 break;
16812 case POOL32I:
16813 minor = (ctx->opcode >> 21) & 0x1f;
16814 switch (minor) {
16815 case BLTZ:
16816 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16817 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16818 break;
16819 case BLTZAL:
16820 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16821 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16822 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16823 break;
16824 case BLTZALS:
16825 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16826 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16827 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16828 break;
16829 case BGEZ:
16830 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16831 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16832 break;
16833 case BGEZAL:
16834 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16835 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16836 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16837 break;
16838 case BGEZALS:
16839 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16840 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16841 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16842 break;
16843 case BLEZ:
16844 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16845 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16846 break;
16847 case BGTZ:
16848 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16849 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16850 break;
16852 /* Traps */
16853 case TLTI: /* BC1EQZC */
16854 if (ctx->insn_flags & ISA_MIPS_R6) {
16855 /* BC1EQZC */
16856 check_cp1_enabled(ctx);
16857 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16858 } else {
16859 /* TLTI */
16860 mips32_op = OPC_TLTI;
16861 goto do_trapi;
16863 break;
16864 case TGEI: /* BC1NEZC */
16865 if (ctx->insn_flags & ISA_MIPS_R6) {
16866 /* BC1NEZC */
16867 check_cp1_enabled(ctx);
16868 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16869 } else {
16870 /* TGEI */
16871 mips32_op = OPC_TGEI;
16872 goto do_trapi;
16874 break;
16875 case TLTIU:
16876 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16877 mips32_op = OPC_TLTIU;
16878 goto do_trapi;
16879 case TGEIU:
16880 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16881 mips32_op = OPC_TGEIU;
16882 goto do_trapi;
16883 case TNEI: /* SYNCI */
16884 if (ctx->insn_flags & ISA_MIPS_R6) {
16885 /* SYNCI */
16887 * Break the TB to be able to sync copied instructions
16888 * immediately.
16890 ctx->base.is_jmp = DISAS_STOP;
16891 } else {
16892 /* TNEI */
16893 mips32_op = OPC_TNEI;
16894 goto do_trapi;
16896 break;
16897 case TEQI:
16898 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16899 mips32_op = OPC_TEQI;
16900 do_trapi:
16901 gen_trap(ctx, mips32_op, rs, -1, imm);
16902 break;
16904 case BNEZC:
16905 case BEQZC:
16906 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16907 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16908 4, rs, 0, imm << 1, 0);
16910 * Compact branches don't have a delay slot, so just let
16911 * the normal delay slot handling take us to the branch
16912 * target.
16914 break;
16915 case LUI:
16916 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16917 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16918 break;
16919 case SYNCI:
16920 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16922 * Break the TB to be able to sync copied instructions
16923 * immediately.
16925 ctx->base.is_jmp = DISAS_STOP;
16926 break;
16927 case BC2F:
16928 case BC2T:
16929 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16930 /* COP2: Not implemented. */
16931 generate_exception_err(ctx, EXCP_CpU, 2);
16932 break;
16933 case BC1F:
16934 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16935 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16936 goto do_cp1branch;
16937 case BC1T:
16938 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16939 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16940 goto do_cp1branch;
16941 case BC1ANY4F:
16942 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16943 mips32_op = OPC_BC1FANY4;
16944 goto do_cp1mips3d;
16945 case BC1ANY4T:
16946 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16947 mips32_op = OPC_BC1TANY4;
16948 do_cp1mips3d:
16949 check_cop1x(ctx);
16950 check_insn(ctx, ASE_MIPS3D);
16951 /* Fall through */
16952 do_cp1branch:
16953 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16954 check_cp1_enabled(ctx);
16955 gen_compute_branch1(ctx, mips32_op,
16956 (ctx->opcode >> 18) & 0x7, imm << 1);
16957 } else {
16958 generate_exception_err(ctx, EXCP_CpU, 1);
16960 break;
16961 case BPOSGE64:
16962 case BPOSGE32:
16963 /* MIPS DSP: not implemented */
16964 /* Fall through */
16965 default:
16966 MIPS_INVAL("pool32i");
16967 gen_reserved_instruction(ctx);
16968 break;
16970 break;
16971 case POOL32C:
16972 minor = (ctx->opcode >> 12) & 0xf;
16973 offset = sextract32(ctx->opcode, 0,
16974 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
16975 switch (minor) {
16976 case LWL:
16977 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16978 mips32_op = OPC_LWL;
16979 goto do_ld_lr;
16980 case SWL:
16981 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16982 mips32_op = OPC_SWL;
16983 goto do_st_lr;
16984 case LWR:
16985 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16986 mips32_op = OPC_LWR;
16987 goto do_ld_lr;
16988 case SWR:
16989 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16990 mips32_op = OPC_SWR;
16991 goto do_st_lr;
16992 #if defined(TARGET_MIPS64)
16993 case LDL:
16994 check_insn(ctx, ISA_MIPS3);
16995 check_mips_64(ctx);
16996 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16997 mips32_op = OPC_LDL;
16998 goto do_ld_lr;
16999 case SDL:
17000 check_insn(ctx, ISA_MIPS3);
17001 check_mips_64(ctx);
17002 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17003 mips32_op = OPC_SDL;
17004 goto do_st_lr;
17005 case LDR:
17006 check_insn(ctx, ISA_MIPS3);
17007 check_mips_64(ctx);
17008 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17009 mips32_op = OPC_LDR;
17010 goto do_ld_lr;
17011 case SDR:
17012 check_insn(ctx, ISA_MIPS3);
17013 check_mips_64(ctx);
17014 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17015 mips32_op = OPC_SDR;
17016 goto do_st_lr;
17017 case LWU:
17018 check_insn(ctx, ISA_MIPS3);
17019 check_mips_64(ctx);
17020 mips32_op = OPC_LWU;
17021 goto do_ld_lr;
17022 case LLD:
17023 check_insn(ctx, ISA_MIPS3);
17024 check_mips_64(ctx);
17025 mips32_op = OPC_LLD;
17026 goto do_ld_lr;
17027 #endif
17028 case LL:
17029 mips32_op = OPC_LL;
17030 goto do_ld_lr;
17031 do_ld_lr:
17032 gen_ld(ctx, mips32_op, rt, rs, offset);
17033 break;
17034 do_st_lr:
17035 gen_st(ctx, mips32_op, rt, rs, offset);
17036 break;
17037 case SC:
17038 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
17039 break;
17040 #if defined(TARGET_MIPS64)
17041 case SCD:
17042 check_insn(ctx, ISA_MIPS3);
17043 check_mips_64(ctx);
17044 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17045 break;
17046 #endif
17047 case LD_EVA:
17048 if (!ctx->eva) {
17049 MIPS_INVAL("pool32c ld-eva");
17050 gen_reserved_instruction(ctx);
17051 break;
17053 check_cp0_enabled(ctx);
17055 minor2 = (ctx->opcode >> 9) & 0x7;
17056 offset = sextract32(ctx->opcode, 0, 9);
17057 switch (minor2) {
17058 case LBUE:
17059 mips32_op = OPC_LBUE;
17060 goto do_ld_lr;
17061 case LHUE:
17062 mips32_op = OPC_LHUE;
17063 goto do_ld_lr;
17064 case LWLE:
17065 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17066 mips32_op = OPC_LWLE;
17067 goto do_ld_lr;
17068 case LWRE:
17069 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17070 mips32_op = OPC_LWRE;
17071 goto do_ld_lr;
17072 case LBE:
17073 mips32_op = OPC_LBE;
17074 goto do_ld_lr;
17075 case LHE:
17076 mips32_op = OPC_LHE;
17077 goto do_ld_lr;
17078 case LLE:
17079 mips32_op = OPC_LLE;
17080 goto do_ld_lr;
17081 case LWE:
17082 mips32_op = OPC_LWE;
17083 goto do_ld_lr;
17085 break;
17086 case ST_EVA:
17087 if (!ctx->eva) {
17088 MIPS_INVAL("pool32c st-eva");
17089 gen_reserved_instruction(ctx);
17090 break;
17092 check_cp0_enabled(ctx);
17094 minor2 = (ctx->opcode >> 9) & 0x7;
17095 offset = sextract32(ctx->opcode, 0, 9);
17096 switch (minor2) {
17097 case SWLE:
17098 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17099 mips32_op = OPC_SWLE;
17100 goto do_st_lr;
17101 case SWRE:
17102 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17103 mips32_op = OPC_SWRE;
17104 goto do_st_lr;
17105 case PREFE:
17106 /* Treat as no-op */
17107 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
17108 /* hint codes 24-31 are reserved and signal RI */
17109 generate_exception(ctx, EXCP_RI);
17111 break;
17112 case CACHEE:
17113 /* Treat as no-op */
17114 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17115 gen_cache_operation(ctx, rt, rs, offset);
17117 break;
17118 case SBE:
17119 mips32_op = OPC_SBE;
17120 goto do_st_lr;
17121 case SHE:
17122 mips32_op = OPC_SHE;
17123 goto do_st_lr;
17124 case SCE:
17125 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17126 break;
17127 case SWE:
17128 mips32_op = OPC_SWE;
17129 goto do_st_lr;
17131 break;
17132 case PREF:
17133 /* Treat as no-op */
17134 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
17135 /* hint codes 24-31 are reserved and signal RI */
17136 generate_exception(ctx, EXCP_RI);
17138 break;
17139 default:
17140 MIPS_INVAL("pool32c");
17141 gen_reserved_instruction(ctx);
17142 break;
17144 break;
17145 case ADDI32: /* AUI, LUI */
17146 if (ctx->insn_flags & ISA_MIPS_R6) {
17147 /* AUI, LUI */
17148 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17149 } else {
17150 /* ADDI32 */
17151 mips32_op = OPC_ADDI;
17152 goto do_addi;
17154 break;
17155 case ADDIU32:
17156 mips32_op = OPC_ADDIU;
17157 do_addi:
17158 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17159 break;
17161 /* Logical operations */
17162 case ORI32:
17163 mips32_op = OPC_ORI;
17164 goto do_logici;
17165 case XORI32:
17166 mips32_op = OPC_XORI;
17167 goto do_logici;
17168 case ANDI32:
17169 mips32_op = OPC_ANDI;
17170 do_logici:
17171 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17172 break;
17174 /* Set less than immediate */
17175 case SLTI32:
17176 mips32_op = OPC_SLTI;
17177 goto do_slti;
17178 case SLTIU32:
17179 mips32_op = OPC_SLTIU;
17180 do_slti:
17181 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17182 break;
17183 case JALX32:
17184 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17185 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17186 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17187 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17188 break;
17189 case JALS32: /* BOVC, BEQC, BEQZALC */
17190 if (ctx->insn_flags & ISA_MIPS_R6) {
17191 if (rs >= rt) {
17192 /* BOVC */
17193 mips32_op = OPC_BOVC;
17194 } else if (rs < rt && rs == 0) {
17195 /* BEQZALC */
17196 mips32_op = OPC_BEQZALC;
17197 } else {
17198 /* BEQC */
17199 mips32_op = OPC_BEQC;
17201 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17202 } else {
17203 /* JALS32 */
17204 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17205 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17206 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17208 break;
17209 case BEQ32: /* BC */
17210 if (ctx->insn_flags & ISA_MIPS_R6) {
17211 /* BC */
17212 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17213 sextract32(ctx->opcode << 1, 0, 27));
17214 } else {
17215 /* BEQ32 */
17216 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17218 break;
17219 case BNE32: /* BALC */
17220 if (ctx->insn_flags & ISA_MIPS_R6) {
17221 /* BALC */
17222 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17223 sextract32(ctx->opcode << 1, 0, 27));
17224 } else {
17225 /* BNE32 */
17226 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17228 break;
17229 case J32: /* BGTZC, BLTZC, BLTC */
17230 if (ctx->insn_flags & ISA_MIPS_R6) {
17231 if (rs == 0 && rt != 0) {
17232 /* BGTZC */
17233 mips32_op = OPC_BGTZC;
17234 } else if (rs != 0 && rt != 0 && rs == rt) {
17235 /* BLTZC */
17236 mips32_op = OPC_BLTZC;
17237 } else {
17238 /* BLTC */
17239 mips32_op = OPC_BLTC;
17241 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17242 } else {
17243 /* J32 */
17244 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17245 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17247 break;
17248 case JAL32: /* BLEZC, BGEZC, BGEC */
17249 if (ctx->insn_flags & ISA_MIPS_R6) {
17250 if (rs == 0 && rt != 0) {
17251 /* BLEZC */
17252 mips32_op = OPC_BLEZC;
17253 } else if (rs != 0 && rt != 0 && rs == rt) {
17254 /* BGEZC */
17255 mips32_op = OPC_BGEZC;
17256 } else {
17257 /* BGEC */
17258 mips32_op = OPC_BGEC;
17260 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17261 } else {
17262 /* JAL32 */
17263 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17264 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17265 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17267 break;
17268 /* Floating point (COP1) */
17269 case LWC132:
17270 mips32_op = OPC_LWC1;
17271 goto do_cop1;
17272 case LDC132:
17273 mips32_op = OPC_LDC1;
17274 goto do_cop1;
17275 case SWC132:
17276 mips32_op = OPC_SWC1;
17277 goto do_cop1;
17278 case SDC132:
17279 mips32_op = OPC_SDC1;
17280 do_cop1:
17281 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17282 break;
17283 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17284 if (ctx->insn_flags & ISA_MIPS_R6) {
17285 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17286 switch ((ctx->opcode >> 16) & 0x1f) {
17287 case ADDIUPC_00:
17288 case ADDIUPC_01:
17289 case ADDIUPC_02:
17290 case ADDIUPC_03:
17291 case ADDIUPC_04:
17292 case ADDIUPC_05:
17293 case ADDIUPC_06:
17294 case ADDIUPC_07:
17295 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17296 break;
17297 case AUIPC:
17298 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17299 break;
17300 case ALUIPC:
17301 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17302 break;
17303 case LWPC_08:
17304 case LWPC_09:
17305 case LWPC_0A:
17306 case LWPC_0B:
17307 case LWPC_0C:
17308 case LWPC_0D:
17309 case LWPC_0E:
17310 case LWPC_0F:
17311 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17312 break;
17313 default:
17314 generate_exception(ctx, EXCP_RI);
17315 break;
17317 } else {
17318 /* ADDIUPC */
17319 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17320 offset = SIMM(ctx->opcode, 0, 23) << 2;
17322 gen_addiupc(ctx, reg, offset, 0, 0);
17324 break;
17325 case BNVC: /* BNEC, BNEZALC */
17326 check_insn(ctx, ISA_MIPS_R6);
17327 if (rs >= rt) {
17328 /* BNVC */
17329 mips32_op = OPC_BNVC;
17330 } else if (rs < rt && rs == 0) {
17331 /* BNEZALC */
17332 mips32_op = OPC_BNEZALC;
17333 } else {
17334 /* BNEC */
17335 mips32_op = OPC_BNEC;
17337 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17338 break;
17339 case R6_BNEZC: /* JIALC */
17340 check_insn(ctx, ISA_MIPS_R6);
17341 if (rt != 0) {
17342 /* BNEZC */
17343 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17344 sextract32(ctx->opcode << 1, 0, 22));
17345 } else {
17346 /* JIALC */
17347 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17349 break;
17350 case R6_BEQZC: /* JIC */
17351 check_insn(ctx, ISA_MIPS_R6);
17352 if (rt != 0) {
17353 /* BEQZC */
17354 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17355 sextract32(ctx->opcode << 1, 0, 22));
17356 } else {
17357 /* JIC */
17358 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17360 break;
17361 case BLEZALC: /* BGEZALC, BGEUC */
17362 check_insn(ctx, ISA_MIPS_R6);
17363 if (rs == 0 && rt != 0) {
17364 /* BLEZALC */
17365 mips32_op = OPC_BLEZALC;
17366 } else if (rs != 0 && rt != 0 && rs == rt) {
17367 /* BGEZALC */
17368 mips32_op = OPC_BGEZALC;
17369 } else {
17370 /* BGEUC */
17371 mips32_op = OPC_BGEUC;
17373 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17374 break;
17375 case BGTZALC: /* BLTZALC, BLTUC */
17376 check_insn(ctx, ISA_MIPS_R6);
17377 if (rs == 0 && rt != 0) {
17378 /* BGTZALC */
17379 mips32_op = OPC_BGTZALC;
17380 } else if (rs != 0 && rt != 0 && rs == rt) {
17381 /* BLTZALC */
17382 mips32_op = OPC_BLTZALC;
17383 } else {
17384 /* BLTUC */
17385 mips32_op = OPC_BLTUC;
17387 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17388 break;
17389 /* Loads and stores */
17390 case LB32:
17391 mips32_op = OPC_LB;
17392 goto do_ld;
17393 case LBU32:
17394 mips32_op = OPC_LBU;
17395 goto do_ld;
17396 case LH32:
17397 mips32_op = OPC_LH;
17398 goto do_ld;
17399 case LHU32:
17400 mips32_op = OPC_LHU;
17401 goto do_ld;
17402 case LW32:
17403 mips32_op = OPC_LW;
17404 goto do_ld;
17405 #ifdef TARGET_MIPS64
17406 case LD32:
17407 check_insn(ctx, ISA_MIPS3);
17408 check_mips_64(ctx);
17409 mips32_op = OPC_LD;
17410 goto do_ld;
17411 case SD32:
17412 check_insn(ctx, ISA_MIPS3);
17413 check_mips_64(ctx);
17414 mips32_op = OPC_SD;
17415 goto do_st;
17416 #endif
17417 case SB32:
17418 mips32_op = OPC_SB;
17419 goto do_st;
17420 case SH32:
17421 mips32_op = OPC_SH;
17422 goto do_st;
17423 case SW32:
17424 mips32_op = OPC_SW;
17425 goto do_st;
17426 do_ld:
17427 gen_ld(ctx, mips32_op, rt, rs, imm);
17428 break;
17429 do_st:
17430 gen_st(ctx, mips32_op, rt, rs, imm);
17431 break;
17432 default:
17433 gen_reserved_instruction(ctx);
17434 break;
17438 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
17440 uint32_t op;
17442 /* make sure instructions are on a halfword boundary */
17443 if (ctx->base.pc_next & 0x1) {
17444 env->CP0_BadVAddr = ctx->base.pc_next;
17445 generate_exception_end(ctx, EXCP_AdEL);
17446 return 2;
17449 op = (ctx->opcode >> 10) & 0x3f;
17450 /* Enforce properly-sized instructions in a delay slot */
17451 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17452 switch (op & 0x7) { /* MSB-3..MSB-5 */
17453 case 0:
17454 /* POOL32A, POOL32B, POOL32I, POOL32C */
17455 case 4:
17456 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17457 case 5:
17458 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17459 case 6:
17460 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17461 case 7:
17462 /* LB32, LH32, LWC132, LDC132, LW32 */
17463 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17464 gen_reserved_instruction(ctx);
17465 return 2;
17467 break;
17468 case 1:
17469 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17470 case 2:
17471 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17472 case 3:
17473 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17474 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17475 gen_reserved_instruction(ctx);
17476 return 2;
17478 break;
17482 switch (op) {
17483 case POOL16A:
17485 int rd = mmreg(uMIPS_RD(ctx->opcode));
17486 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17487 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17488 uint32_t opc = 0;
17490 switch (ctx->opcode & 0x1) {
17491 case ADDU16:
17492 opc = OPC_ADDU;
17493 break;
17494 case SUBU16:
17495 opc = OPC_SUBU;
17496 break;
17498 if (ctx->insn_flags & ISA_MIPS_R6) {
17500 * In the Release 6, the register number location in
17501 * the instruction encoding has changed.
17503 gen_arith(ctx, opc, rs1, rd, rs2);
17504 } else {
17505 gen_arith(ctx, opc, rd, rs1, rs2);
17508 break;
17509 case POOL16B:
17511 int rd = mmreg(uMIPS_RD(ctx->opcode));
17512 int rs = mmreg(uMIPS_RS(ctx->opcode));
17513 int amount = (ctx->opcode >> 1) & 0x7;
17514 uint32_t opc = 0;
17515 amount = amount == 0 ? 8 : amount;
17517 switch (ctx->opcode & 0x1) {
17518 case SLL16:
17519 opc = OPC_SLL;
17520 break;
17521 case SRL16:
17522 opc = OPC_SRL;
17523 break;
17526 gen_shift_imm(ctx, opc, rd, rs, amount);
17528 break;
17529 case POOL16C:
17530 if (ctx->insn_flags & ISA_MIPS_R6) {
17531 gen_pool16c_r6_insn(ctx);
17532 } else {
17533 gen_pool16c_insn(ctx);
17535 break;
17536 case LWGP16:
17538 int rd = mmreg(uMIPS_RD(ctx->opcode));
17539 int rb = 28; /* GP */
17540 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17542 gen_ld(ctx, OPC_LW, rd, rb, offset);
17544 break;
17545 case POOL16F:
17546 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17547 if (ctx->opcode & 1) {
17548 gen_reserved_instruction(ctx);
17549 } else {
17550 /* MOVEP */
17551 int enc_dest = uMIPS_RD(ctx->opcode);
17552 int enc_rt = uMIPS_RS2(ctx->opcode);
17553 int enc_rs = uMIPS_RS1(ctx->opcode);
17554 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17556 break;
17557 case LBU16:
17559 int rd = mmreg(uMIPS_RD(ctx->opcode));
17560 int rb = mmreg(uMIPS_RS(ctx->opcode));
17561 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17562 offset = (offset == 0xf ? -1 : offset);
17564 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17566 break;
17567 case LHU16:
17569 int rd = mmreg(uMIPS_RD(ctx->opcode));
17570 int rb = mmreg(uMIPS_RS(ctx->opcode));
17571 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17573 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17575 break;
17576 case LWSP16:
17578 int rd = (ctx->opcode >> 5) & 0x1f;
17579 int rb = 29; /* SP */
17580 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17582 gen_ld(ctx, OPC_LW, rd, rb, offset);
17584 break;
17585 case LW16:
17587 int rd = mmreg(uMIPS_RD(ctx->opcode));
17588 int rb = mmreg(uMIPS_RS(ctx->opcode));
17589 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17591 gen_ld(ctx, OPC_LW, rd, rb, offset);
17593 break;
17594 case SB16:
17596 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17597 int rb = mmreg(uMIPS_RS(ctx->opcode));
17598 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17600 gen_st(ctx, OPC_SB, rd, rb, offset);
17602 break;
17603 case SH16:
17605 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17606 int rb = mmreg(uMIPS_RS(ctx->opcode));
17607 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17609 gen_st(ctx, OPC_SH, rd, rb, offset);
17611 break;
17612 case SWSP16:
17614 int rd = (ctx->opcode >> 5) & 0x1f;
17615 int rb = 29; /* SP */
17616 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17618 gen_st(ctx, OPC_SW, rd, rb, offset);
17620 break;
17621 case SW16:
17623 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17624 int rb = mmreg(uMIPS_RS(ctx->opcode));
17625 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17627 gen_st(ctx, OPC_SW, rd, rb, offset);
17629 break;
17630 case MOVE16:
17632 int rd = uMIPS_RD5(ctx->opcode);
17633 int rs = uMIPS_RS5(ctx->opcode);
17635 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17637 break;
17638 case ANDI16:
17639 gen_andi16(ctx);
17640 break;
17641 case POOL16D:
17642 switch (ctx->opcode & 0x1) {
17643 case ADDIUS5:
17644 gen_addius5(ctx);
17645 break;
17646 case ADDIUSP:
17647 gen_addiusp(ctx);
17648 break;
17650 break;
17651 case POOL16E:
17652 switch (ctx->opcode & 0x1) {
17653 case ADDIUR2:
17654 gen_addiur2(ctx);
17655 break;
17656 case ADDIUR1SP:
17657 gen_addiur1sp(ctx);
17658 break;
17660 break;
17661 case B16: /* BC16 */
17662 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17663 sextract32(ctx->opcode, 0, 10) << 1,
17664 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
17665 break;
17666 case BNEZ16: /* BNEZC16 */
17667 case BEQZ16: /* BEQZC16 */
17668 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17669 mmreg(uMIPS_RD(ctx->opcode)),
17670 0, sextract32(ctx->opcode, 0, 7) << 1,
17671 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
17673 break;
17674 case LI16:
17676 int reg = mmreg(uMIPS_RD(ctx->opcode));
17677 int imm = ZIMM(ctx->opcode, 0, 7);
17679 imm = (imm == 0x7f ? -1 : imm);
17680 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17682 break;
17683 case RES_29:
17684 case RES_31:
17685 case RES_39:
17686 gen_reserved_instruction(ctx);
17687 break;
17688 default:
17689 decode_micromips32_opc(env, ctx);
17690 return 4;
17693 return 2;
17698 * nanoMIPS opcodes
17702 /* MAJOR, P16, and P32 pools opcodes */
17703 enum {
17704 NM_P_ADDIU = 0x00,
17705 NM_ADDIUPC = 0x01,
17706 NM_MOVE_BALC = 0x02,
17707 NM_P16_MV = 0x04,
17708 NM_LW16 = 0x05,
17709 NM_BC16 = 0x06,
17710 NM_P16_SR = 0x07,
17712 NM_POOL32A = 0x08,
17713 NM_P_BAL = 0x0a,
17714 NM_P16_SHIFT = 0x0c,
17715 NM_LWSP16 = 0x0d,
17716 NM_BALC16 = 0x0e,
17717 NM_P16_4X4 = 0x0f,
17719 NM_P_GP_W = 0x10,
17720 NM_P_GP_BH = 0x11,
17721 NM_P_J = 0x12,
17722 NM_P16C = 0x14,
17723 NM_LWGP16 = 0x15,
17724 NM_P16_LB = 0x17,
17726 NM_P48I = 0x18,
17727 NM_P16_A1 = 0x1c,
17728 NM_LW4X4 = 0x1d,
17729 NM_P16_LH = 0x1f,
17731 NM_P_U12 = 0x20,
17732 NM_P_LS_U12 = 0x21,
17733 NM_P_BR1 = 0x22,
17734 NM_P16_A2 = 0x24,
17735 NM_SW16 = 0x25,
17736 NM_BEQZC16 = 0x26,
17738 NM_POOL32F = 0x28,
17739 NM_P_LS_S9 = 0x29,
17740 NM_P_BR2 = 0x2a,
17742 NM_P16_ADDU = 0x2c,
17743 NM_SWSP16 = 0x2d,
17744 NM_BNEZC16 = 0x2e,
17745 NM_MOVEP = 0x2f,
17747 NM_POOL32S = 0x30,
17748 NM_P_BRI = 0x32,
17749 NM_LI16 = 0x34,
17750 NM_SWGP16 = 0x35,
17751 NM_P16_BR = 0x36,
17753 NM_P_LUI = 0x38,
17754 NM_ANDI16 = 0x3c,
17755 NM_SW4X4 = 0x3d,
17756 NM_MOVEPREV = 0x3f,
17759 /* POOL32A instruction pool */
17760 enum {
17761 NM_POOL32A0 = 0x00,
17762 NM_SPECIAL2 = 0x01,
17763 NM_COP2_1 = 0x02,
17764 NM_UDI = 0x03,
17765 NM_POOL32A5 = 0x05,
17766 NM_POOL32A7 = 0x07,
17769 /* P.GP.W instruction pool */
17770 enum {
17771 NM_ADDIUGP_W = 0x00,
17772 NM_LWGP = 0x02,
17773 NM_SWGP = 0x03,
17776 /* P48I instruction pool */
17777 enum {
17778 NM_LI48 = 0x00,
17779 NM_ADDIU48 = 0x01,
17780 NM_ADDIUGP48 = 0x02,
17781 NM_ADDIUPC48 = 0x03,
17782 NM_LWPC48 = 0x0b,
17783 NM_SWPC48 = 0x0f,
17786 /* P.U12 instruction pool */
17787 enum {
17788 NM_ORI = 0x00,
17789 NM_XORI = 0x01,
17790 NM_ANDI = 0x02,
17791 NM_P_SR = 0x03,
17792 NM_SLTI = 0x04,
17793 NM_SLTIU = 0x05,
17794 NM_SEQI = 0x06,
17795 NM_ADDIUNEG = 0x08,
17796 NM_P_SHIFT = 0x0c,
17797 NM_P_ROTX = 0x0d,
17798 NM_P_INS = 0x0e,
17799 NM_P_EXT = 0x0f,
17802 /* POOL32F instruction pool */
17803 enum {
17804 NM_POOL32F_0 = 0x00,
17805 NM_POOL32F_3 = 0x03,
17806 NM_POOL32F_5 = 0x05,
17809 /* POOL32S instruction pool */
17810 enum {
17811 NM_POOL32S_0 = 0x00,
17812 NM_POOL32S_4 = 0x04,
17815 /* P.LUI instruction pool */
17816 enum {
17817 NM_LUI = 0x00,
17818 NM_ALUIPC = 0x01,
17821 /* P.GP.BH instruction pool */
17822 enum {
17823 NM_LBGP = 0x00,
17824 NM_SBGP = 0x01,
17825 NM_LBUGP = 0x02,
17826 NM_ADDIUGP_B = 0x03,
17827 NM_P_GP_LH = 0x04,
17828 NM_P_GP_SH = 0x05,
17829 NM_P_GP_CP1 = 0x06,
17832 /* P.LS.U12 instruction pool */
17833 enum {
17834 NM_LB = 0x00,
17835 NM_SB = 0x01,
17836 NM_LBU = 0x02,
17837 NM_P_PREFU12 = 0x03,
17838 NM_LH = 0x04,
17839 NM_SH = 0x05,
17840 NM_LHU = 0x06,
17841 NM_LWU = 0x07,
17842 NM_LW = 0x08,
17843 NM_SW = 0x09,
17844 NM_LWC1 = 0x0a,
17845 NM_SWC1 = 0x0b,
17846 NM_LDC1 = 0x0e,
17847 NM_SDC1 = 0x0f,
17850 /* P.LS.S9 instruction pool */
17851 enum {
17852 NM_P_LS_S0 = 0x00,
17853 NM_P_LS_S1 = 0x01,
17854 NM_P_LS_E0 = 0x02,
17855 NM_P_LS_WM = 0x04,
17856 NM_P_LS_UAWM = 0x05,
17859 /* P.BAL instruction pool */
17860 enum {
17861 NM_BC = 0x00,
17862 NM_BALC = 0x01,
17865 /* P.J instruction pool */
17866 enum {
17867 NM_JALRC = 0x00,
17868 NM_JALRC_HB = 0x01,
17869 NM_P_BALRSC = 0x08,
17872 /* P.BR1 instruction pool */
17873 enum {
17874 NM_BEQC = 0x00,
17875 NM_P_BR3A = 0x01,
17876 NM_BGEC = 0x02,
17877 NM_BGEUC = 0x03,
17880 /* P.BR2 instruction pool */
17881 enum {
17882 NM_BNEC = 0x00,
17883 NM_BLTC = 0x02,
17884 NM_BLTUC = 0x03,
17887 /* P.BRI instruction pool */
17888 enum {
17889 NM_BEQIC = 0x00,
17890 NM_BBEQZC = 0x01,
17891 NM_BGEIC = 0x02,
17892 NM_BGEIUC = 0x03,
17893 NM_BNEIC = 0x04,
17894 NM_BBNEZC = 0x05,
17895 NM_BLTIC = 0x06,
17896 NM_BLTIUC = 0x07,
17899 /* P16.SHIFT instruction pool */
17900 enum {
17901 NM_SLL16 = 0x00,
17902 NM_SRL16 = 0x01,
17905 /* POOL16C instruction pool */
17906 enum {
17907 NM_POOL16C_0 = 0x00,
17908 NM_LWXS16 = 0x01,
17911 /* P16.A1 instruction pool */
17912 enum {
17913 NM_ADDIUR1SP = 0x01,
17916 /* P16.A2 instruction pool */
17917 enum {
17918 NM_ADDIUR2 = 0x00,
17919 NM_P_ADDIURS5 = 0x01,
17922 /* P16.ADDU instruction pool */
17923 enum {
17924 NM_ADDU16 = 0x00,
17925 NM_SUBU16 = 0x01,
17928 /* P16.SR instruction pool */
17929 enum {
17930 NM_SAVE16 = 0x00,
17931 NM_RESTORE_JRC16 = 0x01,
17934 /* P16.4X4 instruction pool */
17935 enum {
17936 NM_ADDU4X4 = 0x00,
17937 NM_MUL4X4 = 0x01,
17940 /* P16.LB instruction pool */
17941 enum {
17942 NM_LB16 = 0x00,
17943 NM_SB16 = 0x01,
17944 NM_LBU16 = 0x02,
17947 /* P16.LH instruction pool */
17948 enum {
17949 NM_LH16 = 0x00,
17950 NM_SH16 = 0x01,
17951 NM_LHU16 = 0x02,
17954 /* P.RI instruction pool */
17955 enum {
17956 NM_SIGRIE = 0x00,
17957 NM_P_SYSCALL = 0x01,
17958 NM_BREAK = 0x02,
17959 NM_SDBBP = 0x03,
17962 /* POOL32A0 instruction pool */
17963 enum {
17964 NM_P_TRAP = 0x00,
17965 NM_SEB = 0x01,
17966 NM_SLLV = 0x02,
17967 NM_MUL = 0x03,
17968 NM_MFC0 = 0x06,
17969 NM_MFHC0 = 0x07,
17970 NM_SEH = 0x09,
17971 NM_SRLV = 0x0a,
17972 NM_MUH = 0x0b,
17973 NM_MTC0 = 0x0e,
17974 NM_MTHC0 = 0x0f,
17975 NM_SRAV = 0x12,
17976 NM_MULU = 0x13,
17977 NM_ROTRV = 0x1a,
17978 NM_MUHU = 0x1b,
17979 NM_ADD = 0x22,
17980 NM_DIV = 0x23,
17981 NM_ADDU = 0x2a,
17982 NM_MOD = 0x2b,
17983 NM_SUB = 0x32,
17984 NM_DIVU = 0x33,
17985 NM_RDHWR = 0x38,
17986 NM_SUBU = 0x3a,
17987 NM_MODU = 0x3b,
17988 NM_P_CMOVE = 0x42,
17989 NM_FORK = 0x45,
17990 NM_MFTR = 0x46,
17991 NM_MFHTR = 0x47,
17992 NM_AND = 0x4a,
17993 NM_YIELD = 0x4d,
17994 NM_MTTR = 0x4e,
17995 NM_MTHTR = 0x4f,
17996 NM_OR = 0x52,
17997 NM_D_E_MT_VPE = 0x56,
17998 NM_NOR = 0x5a,
17999 NM_XOR = 0x62,
18000 NM_SLT = 0x6a,
18001 NM_P_SLTU = 0x72,
18002 NM_SOV = 0x7a,
18005 /* CRC32 instruction pool */
18006 enum {
18007 NM_CRC32B = 0x00,
18008 NM_CRC32H = 0x01,
18009 NM_CRC32W = 0x02,
18010 NM_CRC32CB = 0x04,
18011 NM_CRC32CH = 0x05,
18012 NM_CRC32CW = 0x06,
18015 /* POOL32A5 instruction pool */
18016 enum {
18017 NM_CMP_EQ_PH = 0x00,
18018 NM_CMP_LT_PH = 0x08,
18019 NM_CMP_LE_PH = 0x10,
18020 NM_CMPGU_EQ_QB = 0x18,
18021 NM_CMPGU_LT_QB = 0x20,
18022 NM_CMPGU_LE_QB = 0x28,
18023 NM_CMPGDU_EQ_QB = 0x30,
18024 NM_CMPGDU_LT_QB = 0x38,
18025 NM_CMPGDU_LE_QB = 0x40,
18026 NM_CMPU_EQ_QB = 0x48,
18027 NM_CMPU_LT_QB = 0x50,
18028 NM_CMPU_LE_QB = 0x58,
18029 NM_ADDQ_S_W = 0x60,
18030 NM_SUBQ_S_W = 0x68,
18031 NM_ADDSC = 0x70,
18032 NM_ADDWC = 0x78,
18034 NM_ADDQ_S_PH = 0x01,
18035 NM_ADDQH_R_PH = 0x09,
18036 NM_ADDQH_R_W = 0x11,
18037 NM_ADDU_S_QB = 0x19,
18038 NM_ADDU_S_PH = 0x21,
18039 NM_ADDUH_R_QB = 0x29,
18040 NM_SHRAV_R_PH = 0x31,
18041 NM_SHRAV_R_QB = 0x39,
18042 NM_SUBQ_S_PH = 0x41,
18043 NM_SUBQH_R_PH = 0x49,
18044 NM_SUBQH_R_W = 0x51,
18045 NM_SUBU_S_QB = 0x59,
18046 NM_SUBU_S_PH = 0x61,
18047 NM_SUBUH_R_QB = 0x69,
18048 NM_SHLLV_S_PH = 0x71,
18049 NM_PRECR_SRA_R_PH_W = 0x79,
18051 NM_MULEU_S_PH_QBL = 0x12,
18052 NM_MULEU_S_PH_QBR = 0x1a,
18053 NM_MULQ_RS_PH = 0x22,
18054 NM_MULQ_S_PH = 0x2a,
18055 NM_MULQ_RS_W = 0x32,
18056 NM_MULQ_S_W = 0x3a,
18057 NM_APPEND = 0x42,
18058 NM_MODSUB = 0x52,
18059 NM_SHRAV_R_W = 0x5a,
18060 NM_SHRLV_PH = 0x62,
18061 NM_SHRLV_QB = 0x6a,
18062 NM_SHLLV_QB = 0x72,
18063 NM_SHLLV_S_W = 0x7a,
18065 NM_SHILO = 0x03,
18067 NM_MULEQ_S_W_PHL = 0x04,
18068 NM_MULEQ_S_W_PHR = 0x0c,
18070 NM_MUL_S_PH = 0x05,
18071 NM_PRECR_QB_PH = 0x0d,
18072 NM_PRECRQ_QB_PH = 0x15,
18073 NM_PRECRQ_PH_W = 0x1d,
18074 NM_PRECRQ_RS_PH_W = 0x25,
18075 NM_PRECRQU_S_QB_PH = 0x2d,
18076 NM_PACKRL_PH = 0x35,
18077 NM_PICK_QB = 0x3d,
18078 NM_PICK_PH = 0x45,
18080 NM_SHRA_R_W = 0x5e,
18081 NM_SHRA_R_PH = 0x66,
18082 NM_SHLL_S_PH = 0x76,
18083 NM_SHLL_S_W = 0x7e,
18085 NM_REPL_PH = 0x07
18088 /* POOL32A7 instruction pool */
18089 enum {
18090 NM_P_LSX = 0x00,
18091 NM_LSA = 0x01,
18092 NM_EXTW = 0x03,
18093 NM_POOL32AXF = 0x07,
18096 /* P.SR instruction pool */
18097 enum {
18098 NM_PP_SR = 0x00,
18099 NM_P_SR_F = 0x01,
18102 /* P.SHIFT instruction pool */
18103 enum {
18104 NM_P_SLL = 0x00,
18105 NM_SRL = 0x02,
18106 NM_SRA = 0x04,
18107 NM_ROTR = 0x06,
18110 /* P.ROTX instruction pool */
18111 enum {
18112 NM_ROTX = 0x00,
18115 /* P.INS instruction pool */
18116 enum {
18117 NM_INS = 0x00,
18120 /* P.EXT instruction pool */
18121 enum {
18122 NM_EXT = 0x00,
18125 /* POOL32F_0 (fmt) instruction pool */
18126 enum {
18127 NM_RINT_S = 0x04,
18128 NM_RINT_D = 0x44,
18129 NM_ADD_S = 0x06,
18130 NM_SELEQZ_S = 0x07,
18131 NM_SELEQZ_D = 0x47,
18132 NM_CLASS_S = 0x0c,
18133 NM_CLASS_D = 0x4c,
18134 NM_SUB_S = 0x0e,
18135 NM_SELNEZ_S = 0x0f,
18136 NM_SELNEZ_D = 0x4f,
18137 NM_MUL_S = 0x16,
18138 NM_SEL_S = 0x17,
18139 NM_SEL_D = 0x57,
18140 NM_DIV_S = 0x1e,
18141 NM_ADD_D = 0x26,
18142 NM_SUB_D = 0x2e,
18143 NM_MUL_D = 0x36,
18144 NM_MADDF_S = 0x37,
18145 NM_MADDF_D = 0x77,
18146 NM_DIV_D = 0x3e,
18147 NM_MSUBF_S = 0x3f,
18148 NM_MSUBF_D = 0x7f,
18151 /* POOL32F_3 instruction pool */
18152 enum {
18153 NM_MIN_FMT = 0x00,
18154 NM_MAX_FMT = 0x01,
18155 NM_MINA_FMT = 0x04,
18156 NM_MAXA_FMT = 0x05,
18157 NM_POOL32FXF = 0x07,
18160 /* POOL32F_5 instruction pool */
18161 enum {
18162 NM_CMP_CONDN_S = 0x00,
18163 NM_CMP_CONDN_D = 0x02,
18166 /* P.GP.LH instruction pool */
18167 enum {
18168 NM_LHGP = 0x00,
18169 NM_LHUGP = 0x01,
18172 /* P.GP.SH instruction pool */
18173 enum {
18174 NM_SHGP = 0x00,
18177 /* P.GP.CP1 instruction pool */
18178 enum {
18179 NM_LWC1GP = 0x00,
18180 NM_SWC1GP = 0x01,
18181 NM_LDC1GP = 0x02,
18182 NM_SDC1GP = 0x03,
18185 /* P.LS.S0 instruction pool */
18186 enum {
18187 NM_LBS9 = 0x00,
18188 NM_LHS9 = 0x04,
18189 NM_LWS9 = 0x08,
18190 NM_LDS9 = 0x0c,
18192 NM_SBS9 = 0x01,
18193 NM_SHS9 = 0x05,
18194 NM_SWS9 = 0x09,
18195 NM_SDS9 = 0x0d,
18197 NM_LBUS9 = 0x02,
18198 NM_LHUS9 = 0x06,
18199 NM_LWC1S9 = 0x0a,
18200 NM_LDC1S9 = 0x0e,
18202 NM_P_PREFS9 = 0x03,
18203 NM_LWUS9 = 0x07,
18204 NM_SWC1S9 = 0x0b,
18205 NM_SDC1S9 = 0x0f,
18208 /* P.LS.S1 instruction pool */
18209 enum {
18210 NM_ASET_ACLR = 0x02,
18211 NM_UALH = 0x04,
18212 NM_UASH = 0x05,
18213 NM_CACHE = 0x07,
18214 NM_P_LL = 0x0a,
18215 NM_P_SC = 0x0b,
18218 /* P.LS.E0 instruction pool */
18219 enum {
18220 NM_LBE = 0x00,
18221 NM_SBE = 0x01,
18222 NM_LBUE = 0x02,
18223 NM_P_PREFE = 0x03,
18224 NM_LHE = 0x04,
18225 NM_SHE = 0x05,
18226 NM_LHUE = 0x06,
18227 NM_CACHEE = 0x07,
18228 NM_LWE = 0x08,
18229 NM_SWE = 0x09,
18230 NM_P_LLE = 0x0a,
18231 NM_P_SCE = 0x0b,
18234 /* P.PREFE instruction pool */
18235 enum {
18236 NM_SYNCIE = 0x00,
18237 NM_PREFE = 0x01,
18240 /* P.LLE instruction pool */
18241 enum {
18242 NM_LLE = 0x00,
18243 NM_LLWPE = 0x01,
18246 /* P.SCE instruction pool */
18247 enum {
18248 NM_SCE = 0x00,
18249 NM_SCWPE = 0x01,
18252 /* P.LS.WM instruction pool */
18253 enum {
18254 NM_LWM = 0x00,
18255 NM_SWM = 0x01,
18258 /* P.LS.UAWM instruction pool */
18259 enum {
18260 NM_UALWM = 0x00,
18261 NM_UASWM = 0x01,
18264 /* P.BR3A instruction pool */
18265 enum {
18266 NM_BC1EQZC = 0x00,
18267 NM_BC1NEZC = 0x01,
18268 NM_BC2EQZC = 0x02,
18269 NM_BC2NEZC = 0x03,
18270 NM_BPOSGE32C = 0x04,
18273 /* P16.RI instruction pool */
18274 enum {
18275 NM_P16_SYSCALL = 0x01,
18276 NM_BREAK16 = 0x02,
18277 NM_SDBBP16 = 0x03,
18280 /* POOL16C_0 instruction pool */
18281 enum {
18282 NM_POOL16C_00 = 0x00,
18285 /* P16.JRC instruction pool */
18286 enum {
18287 NM_JRC = 0x00,
18288 NM_JALRC16 = 0x01,
18291 /* P.SYSCALL instruction pool */
18292 enum {
18293 NM_SYSCALL = 0x00,
18294 NM_HYPCALL = 0x01,
18297 /* P.TRAP instruction pool */
18298 enum {
18299 NM_TEQ = 0x00,
18300 NM_TNE = 0x01,
18303 /* P.CMOVE instruction pool */
18304 enum {
18305 NM_MOVZ = 0x00,
18306 NM_MOVN = 0x01,
18309 /* POOL32Axf instruction pool */
18310 enum {
18311 NM_POOL32AXF_1 = 0x01,
18312 NM_POOL32AXF_2 = 0x02,
18313 NM_POOL32AXF_4 = 0x04,
18314 NM_POOL32AXF_5 = 0x05,
18315 NM_POOL32AXF_7 = 0x07,
18318 /* POOL32Axf_1 instruction pool */
18319 enum {
18320 NM_POOL32AXF_1_0 = 0x00,
18321 NM_POOL32AXF_1_1 = 0x01,
18322 NM_POOL32AXF_1_3 = 0x03,
18323 NM_POOL32AXF_1_4 = 0x04,
18324 NM_POOL32AXF_1_5 = 0x05,
18325 NM_POOL32AXF_1_7 = 0x07,
18328 /* POOL32Axf_2 instruction pool */
18329 enum {
18330 NM_POOL32AXF_2_0_7 = 0x00,
18331 NM_POOL32AXF_2_8_15 = 0x01,
18332 NM_POOL32AXF_2_16_23 = 0x02,
18333 NM_POOL32AXF_2_24_31 = 0x03,
18336 /* POOL32Axf_7 instruction pool */
18337 enum {
18338 NM_SHRA_R_QB = 0x0,
18339 NM_SHRL_PH = 0x1,
18340 NM_REPL_QB = 0x2,
18343 /* POOL32Axf_1_0 instruction pool */
18344 enum {
18345 NM_MFHI = 0x0,
18346 NM_MFLO = 0x1,
18347 NM_MTHI = 0x2,
18348 NM_MTLO = 0x3,
18351 /* POOL32Axf_1_1 instruction pool */
18352 enum {
18353 NM_MTHLIP = 0x0,
18354 NM_SHILOV = 0x1,
18357 /* POOL32Axf_1_3 instruction pool */
18358 enum {
18359 NM_RDDSP = 0x0,
18360 NM_WRDSP = 0x1,
18361 NM_EXTP = 0x2,
18362 NM_EXTPDP = 0x3,
18365 /* POOL32Axf_1_4 instruction pool */
18366 enum {
18367 NM_SHLL_QB = 0x0,
18368 NM_SHRL_QB = 0x1,
18371 /* POOL32Axf_1_5 instruction pool */
18372 enum {
18373 NM_MAQ_S_W_PHR = 0x0,
18374 NM_MAQ_S_W_PHL = 0x1,
18375 NM_MAQ_SA_W_PHR = 0x2,
18376 NM_MAQ_SA_W_PHL = 0x3,
18379 /* POOL32Axf_1_7 instruction pool */
18380 enum {
18381 NM_EXTR_W = 0x0,
18382 NM_EXTR_R_W = 0x1,
18383 NM_EXTR_RS_W = 0x2,
18384 NM_EXTR_S_H = 0x3,
18387 /* POOL32Axf_2_0_7 instruction pool */
18388 enum {
18389 NM_DPA_W_PH = 0x0,
18390 NM_DPAQ_S_W_PH = 0x1,
18391 NM_DPS_W_PH = 0x2,
18392 NM_DPSQ_S_W_PH = 0x3,
18393 NM_BALIGN = 0x4,
18394 NM_MADD = 0x5,
18395 NM_MULT = 0x6,
18396 NM_EXTRV_W = 0x7,
18399 /* POOL32Axf_2_8_15 instruction pool */
18400 enum {
18401 NM_DPAX_W_PH = 0x0,
18402 NM_DPAQ_SA_L_W = 0x1,
18403 NM_DPSX_W_PH = 0x2,
18404 NM_DPSQ_SA_L_W = 0x3,
18405 NM_MADDU = 0x5,
18406 NM_MULTU = 0x6,
18407 NM_EXTRV_R_W = 0x7,
18410 /* POOL32Axf_2_16_23 instruction pool */
18411 enum {
18412 NM_DPAU_H_QBL = 0x0,
18413 NM_DPAQX_S_W_PH = 0x1,
18414 NM_DPSU_H_QBL = 0x2,
18415 NM_DPSQX_S_W_PH = 0x3,
18416 NM_EXTPV = 0x4,
18417 NM_MSUB = 0x5,
18418 NM_MULSA_W_PH = 0x6,
18419 NM_EXTRV_RS_W = 0x7,
18422 /* POOL32Axf_2_24_31 instruction pool */
18423 enum {
18424 NM_DPAU_H_QBR = 0x0,
18425 NM_DPAQX_SA_W_PH = 0x1,
18426 NM_DPSU_H_QBR = 0x2,
18427 NM_DPSQX_SA_W_PH = 0x3,
18428 NM_EXTPDPV = 0x4,
18429 NM_MSUBU = 0x5,
18430 NM_MULSAQ_S_W_PH = 0x6,
18431 NM_EXTRV_S_H = 0x7,
18434 /* POOL32Axf_{4, 5} instruction pool */
18435 enum {
18436 NM_CLO = 0x25,
18437 NM_CLZ = 0x2d,
18439 NM_TLBP = 0x01,
18440 NM_TLBR = 0x09,
18441 NM_TLBWI = 0x11,
18442 NM_TLBWR = 0x19,
18443 NM_TLBINV = 0x03,
18444 NM_TLBINVF = 0x0b,
18445 NM_DI = 0x23,
18446 NM_EI = 0x2b,
18447 NM_RDPGPR = 0x70,
18448 NM_WRPGPR = 0x78,
18449 NM_WAIT = 0x61,
18450 NM_DERET = 0x71,
18451 NM_ERETX = 0x79,
18453 /* nanoMIPS DSP instructions */
18454 NM_ABSQ_S_QB = 0x00,
18455 NM_ABSQ_S_PH = 0x08,
18456 NM_ABSQ_S_W = 0x10,
18457 NM_PRECEQ_W_PHL = 0x28,
18458 NM_PRECEQ_W_PHR = 0x30,
18459 NM_PRECEQU_PH_QBL = 0x38,
18460 NM_PRECEQU_PH_QBR = 0x48,
18461 NM_PRECEU_PH_QBL = 0x58,
18462 NM_PRECEU_PH_QBR = 0x68,
18463 NM_PRECEQU_PH_QBLA = 0x39,
18464 NM_PRECEQU_PH_QBRA = 0x49,
18465 NM_PRECEU_PH_QBLA = 0x59,
18466 NM_PRECEU_PH_QBRA = 0x69,
18467 NM_REPLV_PH = 0x01,
18468 NM_REPLV_QB = 0x09,
18469 NM_BITREV = 0x18,
18470 NM_INSV = 0x20,
18471 NM_RADDU_W_QB = 0x78,
18473 NM_BITSWAP = 0x05,
18474 NM_WSBH = 0x3d,
18477 /* PP.SR instruction pool */
18478 enum {
18479 NM_SAVE = 0x00,
18480 NM_RESTORE = 0x02,
18481 NM_RESTORE_JRC = 0x03,
18484 /* P.SR.F instruction pool */
18485 enum {
18486 NM_SAVEF = 0x00,
18487 NM_RESTOREF = 0x01,
18490 /* P16.SYSCALL instruction pool */
18491 enum {
18492 NM_SYSCALL16 = 0x00,
18493 NM_HYPCALL16 = 0x01,
18496 /* POOL16C_00 instruction pool */
18497 enum {
18498 NM_NOT16 = 0x00,
18499 NM_XOR16 = 0x01,
18500 NM_AND16 = 0x02,
18501 NM_OR16 = 0x03,
18504 /* PP.LSX and PP.LSXS instruction pool */
18505 enum {
18506 NM_LBX = 0x00,
18507 NM_LHX = 0x04,
18508 NM_LWX = 0x08,
18509 NM_LDX = 0x0c,
18511 NM_SBX = 0x01,
18512 NM_SHX = 0x05,
18513 NM_SWX = 0x09,
18514 NM_SDX = 0x0d,
18516 NM_LBUX = 0x02,
18517 NM_LHUX = 0x06,
18518 NM_LWC1X = 0x0a,
18519 NM_LDC1X = 0x0e,
18521 NM_LWUX = 0x07,
18522 NM_SWC1X = 0x0b,
18523 NM_SDC1X = 0x0f,
18525 NM_LHXS = 0x04,
18526 NM_LWXS = 0x08,
18527 NM_LDXS = 0x0c,
18529 NM_SHXS = 0x05,
18530 NM_SWXS = 0x09,
18531 NM_SDXS = 0x0d,
18533 NM_LHUXS = 0x06,
18534 NM_LWC1XS = 0x0a,
18535 NM_LDC1XS = 0x0e,
18537 NM_LWUXS = 0x07,
18538 NM_SWC1XS = 0x0b,
18539 NM_SDC1XS = 0x0f,
18542 /* ERETx instruction pool */
18543 enum {
18544 NM_ERET = 0x00,
18545 NM_ERETNC = 0x01,
18548 /* POOL32FxF_{0, 1} insturction pool */
18549 enum {
18550 NM_CFC1 = 0x40,
18551 NM_CTC1 = 0x60,
18552 NM_MFC1 = 0x80,
18553 NM_MTC1 = 0xa0,
18554 NM_MFHC1 = 0xc0,
18555 NM_MTHC1 = 0xe0,
18557 NM_CVT_S_PL = 0x84,
18558 NM_CVT_S_PU = 0xa4,
18560 NM_CVT_L_S = 0x004,
18561 NM_CVT_L_D = 0x104,
18562 NM_CVT_W_S = 0x024,
18563 NM_CVT_W_D = 0x124,
18565 NM_RSQRT_S = 0x008,
18566 NM_RSQRT_D = 0x108,
18568 NM_SQRT_S = 0x028,
18569 NM_SQRT_D = 0x128,
18571 NM_RECIP_S = 0x048,
18572 NM_RECIP_D = 0x148,
18574 NM_FLOOR_L_S = 0x00c,
18575 NM_FLOOR_L_D = 0x10c,
18577 NM_FLOOR_W_S = 0x02c,
18578 NM_FLOOR_W_D = 0x12c,
18580 NM_CEIL_L_S = 0x04c,
18581 NM_CEIL_L_D = 0x14c,
18582 NM_CEIL_W_S = 0x06c,
18583 NM_CEIL_W_D = 0x16c,
18584 NM_TRUNC_L_S = 0x08c,
18585 NM_TRUNC_L_D = 0x18c,
18586 NM_TRUNC_W_S = 0x0ac,
18587 NM_TRUNC_W_D = 0x1ac,
18588 NM_ROUND_L_S = 0x0cc,
18589 NM_ROUND_L_D = 0x1cc,
18590 NM_ROUND_W_S = 0x0ec,
18591 NM_ROUND_W_D = 0x1ec,
18593 NM_MOV_S = 0x01,
18594 NM_MOV_D = 0x81,
18595 NM_ABS_S = 0x0d,
18596 NM_ABS_D = 0x8d,
18597 NM_NEG_S = 0x2d,
18598 NM_NEG_D = 0xad,
18599 NM_CVT_D_S = 0x04d,
18600 NM_CVT_D_W = 0x0cd,
18601 NM_CVT_D_L = 0x14d,
18602 NM_CVT_S_D = 0x06d,
18603 NM_CVT_S_W = 0x0ed,
18604 NM_CVT_S_L = 0x16d,
18607 /* P.LL instruction pool */
18608 enum {
18609 NM_LL = 0x00,
18610 NM_LLWP = 0x01,
18613 /* P.SC instruction pool */
18614 enum {
18615 NM_SC = 0x00,
18616 NM_SCWP = 0x01,
18619 /* P.DVP instruction pool */
18620 enum {
18621 NM_DVP = 0x00,
18622 NM_EVP = 0x01,
18628 * nanoMIPS decoding engine
18633 /* extraction utilities */
18635 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18636 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18637 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18638 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18639 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18641 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18642 static inline int decode_gpr_gpr3(int r)
18644 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18646 return map[r & 0x7];
18649 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18650 static inline int decode_gpr_gpr3_src_store(int r)
18652 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18654 return map[r & 0x7];
18657 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18658 static inline int decode_gpr_gpr4(int r)
18660 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18661 16, 17, 18, 19, 20, 21, 22, 23 };
18663 return map[r & 0xf];
18666 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18667 static inline int decode_gpr_gpr4_zero(int r)
18669 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18670 16, 17, 18, 19, 20, 21, 22, 23 };
18672 return map[r & 0xf];
18676 static void gen_adjust_sp(DisasContext *ctx, int u)
18678 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18681 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18682 uint8_t gp, uint16_t u)
18684 int counter = 0;
18685 TCGv va = tcg_temp_new();
18686 TCGv t0 = tcg_temp_new();
18688 while (counter != count) {
18689 bool use_gp = gp && (counter == count - 1);
18690 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18691 int this_offset = -((counter + 1) << 2);
18692 gen_base_offset_addr(ctx, va, 29, this_offset);
18693 gen_load_gpr(t0, this_rt);
18694 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18695 (MO_TEUL | ctx->default_tcg_memop_mask));
18696 counter++;
18699 /* adjust stack pointer */
18700 gen_adjust_sp(ctx, -u);
18702 tcg_temp_free(t0);
18703 tcg_temp_free(va);
18706 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18707 uint8_t gp, uint16_t u)
18709 int counter = 0;
18710 TCGv va = tcg_temp_new();
18711 TCGv t0 = tcg_temp_new();
18713 while (counter != count) {
18714 bool use_gp = gp && (counter == count - 1);
18715 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18716 int this_offset = u - ((counter + 1) << 2);
18717 gen_base_offset_addr(ctx, va, 29, this_offset);
18718 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18719 ctx->default_tcg_memop_mask);
18720 tcg_gen_ext32s_tl(t0, t0);
18721 gen_store_gpr(t0, this_rt);
18722 counter++;
18725 /* adjust stack pointer */
18726 gen_adjust_sp(ctx, u);
18728 tcg_temp_free(t0);
18729 tcg_temp_free(va);
18732 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18734 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18735 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18737 switch (extract32(ctx->opcode, 2, 2)) {
18738 case NM_NOT16:
18739 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18740 break;
18741 case NM_AND16:
18742 gen_logic(ctx, OPC_AND, rt, rt, rs);
18743 break;
18744 case NM_XOR16:
18745 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18746 break;
18747 case NM_OR16:
18748 gen_logic(ctx, OPC_OR, rt, rt, rs);
18749 break;
18753 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18755 int rt = extract32(ctx->opcode, 21, 5);
18756 int rs = extract32(ctx->opcode, 16, 5);
18757 int rd = extract32(ctx->opcode, 11, 5);
18759 switch (extract32(ctx->opcode, 3, 7)) {
18760 case NM_P_TRAP:
18761 switch (extract32(ctx->opcode, 10, 1)) {
18762 case NM_TEQ:
18763 check_nms(ctx);
18764 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18765 break;
18766 case NM_TNE:
18767 check_nms(ctx);
18768 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18769 break;
18771 break;
18772 case NM_RDHWR:
18773 check_nms(ctx);
18774 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18775 break;
18776 case NM_SEB:
18777 check_nms(ctx);
18778 gen_bshfl(ctx, OPC_SEB, rs, rt);
18779 break;
18780 case NM_SEH:
18781 gen_bshfl(ctx, OPC_SEH, rs, rt);
18782 break;
18783 case NM_SLLV:
18784 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18785 break;
18786 case NM_SRLV:
18787 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18788 break;
18789 case NM_SRAV:
18790 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18791 break;
18792 case NM_ROTRV:
18793 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18794 break;
18795 case NM_ADD:
18796 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18797 break;
18798 case NM_ADDU:
18799 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18800 break;
18801 case NM_SUB:
18802 check_nms(ctx);
18803 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18804 break;
18805 case NM_SUBU:
18806 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18807 break;
18808 case NM_P_CMOVE:
18809 switch (extract32(ctx->opcode, 10, 1)) {
18810 case NM_MOVZ:
18811 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18812 break;
18813 case NM_MOVN:
18814 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18815 break;
18817 break;
18818 case NM_AND:
18819 gen_logic(ctx, OPC_AND, rd, rs, rt);
18820 break;
18821 case NM_OR:
18822 gen_logic(ctx, OPC_OR, rd, rs, rt);
18823 break;
18824 case NM_NOR:
18825 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18826 break;
18827 case NM_XOR:
18828 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18829 break;
18830 case NM_SLT:
18831 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18832 break;
18833 case NM_P_SLTU:
18834 if (rd == 0) {
18835 /* P_DVP */
18836 #ifndef CONFIG_USER_ONLY
18837 TCGv t0 = tcg_temp_new();
18838 switch (extract32(ctx->opcode, 10, 1)) {
18839 case NM_DVP:
18840 if (ctx->vp) {
18841 check_cp0_enabled(ctx);
18842 gen_helper_dvp(t0, cpu_env);
18843 gen_store_gpr(t0, rt);
18845 break;
18846 case NM_EVP:
18847 if (ctx->vp) {
18848 check_cp0_enabled(ctx);
18849 gen_helper_evp(t0, cpu_env);
18850 gen_store_gpr(t0, rt);
18852 break;
18854 tcg_temp_free(t0);
18855 #endif
18856 } else {
18857 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18859 break;
18860 case NM_SOV:
18862 TCGv t0 = tcg_temp_new();
18863 TCGv t1 = tcg_temp_new();
18864 TCGv t2 = tcg_temp_new();
18866 gen_load_gpr(t1, rs);
18867 gen_load_gpr(t2, rt);
18868 tcg_gen_add_tl(t0, t1, t2);
18869 tcg_gen_ext32s_tl(t0, t0);
18870 tcg_gen_xor_tl(t1, t1, t2);
18871 tcg_gen_xor_tl(t2, t0, t2);
18872 tcg_gen_andc_tl(t1, t2, t1);
18874 /* operands of same sign, result different sign */
18875 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18876 gen_store_gpr(t0, rd);
18878 tcg_temp_free(t0);
18879 tcg_temp_free(t1);
18880 tcg_temp_free(t2);
18882 break;
18883 case NM_MUL:
18884 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18885 break;
18886 case NM_MUH:
18887 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18888 break;
18889 case NM_MULU:
18890 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18891 break;
18892 case NM_MUHU:
18893 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18894 break;
18895 case NM_DIV:
18896 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18897 break;
18898 case NM_MOD:
18899 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18900 break;
18901 case NM_DIVU:
18902 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18903 break;
18904 case NM_MODU:
18905 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18906 break;
18907 #ifndef CONFIG_USER_ONLY
18908 case NM_MFC0:
18909 check_cp0_enabled(ctx);
18910 if (rt == 0) {
18911 /* Treat as NOP. */
18912 break;
18914 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18915 break;
18916 case NM_MTC0:
18917 check_cp0_enabled(ctx);
18919 TCGv t0 = tcg_temp_new();
18921 gen_load_gpr(t0, rt);
18922 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18923 tcg_temp_free(t0);
18925 break;
18926 case NM_D_E_MT_VPE:
18928 uint8_t sc = extract32(ctx->opcode, 10, 1);
18929 TCGv t0 = tcg_temp_new();
18931 switch (sc) {
18932 case 0:
18933 if (rs == 1) {
18934 /* DMT */
18935 check_cp0_mt(ctx);
18936 gen_helper_dmt(t0);
18937 gen_store_gpr(t0, rt);
18938 } else if (rs == 0) {
18939 /* DVPE */
18940 check_cp0_mt(ctx);
18941 gen_helper_dvpe(t0, cpu_env);
18942 gen_store_gpr(t0, rt);
18943 } else {
18944 gen_reserved_instruction(ctx);
18946 break;
18947 case 1:
18948 if (rs == 1) {
18949 /* EMT */
18950 check_cp0_mt(ctx);
18951 gen_helper_emt(t0);
18952 gen_store_gpr(t0, rt);
18953 } else if (rs == 0) {
18954 /* EVPE */
18955 check_cp0_mt(ctx);
18956 gen_helper_evpe(t0, cpu_env);
18957 gen_store_gpr(t0, rt);
18958 } else {
18959 gen_reserved_instruction(ctx);
18961 break;
18964 tcg_temp_free(t0);
18966 break;
18967 case NM_FORK:
18968 check_mt(ctx);
18970 TCGv t0 = tcg_temp_new();
18971 TCGv t1 = tcg_temp_new();
18973 gen_load_gpr(t0, rt);
18974 gen_load_gpr(t1, rs);
18975 gen_helper_fork(t0, t1);
18976 tcg_temp_free(t0);
18977 tcg_temp_free(t1);
18979 break;
18980 case NM_MFTR:
18981 case NM_MFHTR:
18982 check_cp0_enabled(ctx);
18983 if (rd == 0) {
18984 /* Treat as NOP. */
18985 return;
18987 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18988 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18989 break;
18990 case NM_MTTR:
18991 case NM_MTHTR:
18992 check_cp0_enabled(ctx);
18993 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18994 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18995 break;
18996 case NM_YIELD:
18997 check_mt(ctx);
18999 TCGv t0 = tcg_temp_new();
19001 gen_load_gpr(t0, rs);
19002 gen_helper_yield(t0, cpu_env, t0);
19003 gen_store_gpr(t0, rt);
19004 tcg_temp_free(t0);
19006 break;
19007 #endif
19008 default:
19009 gen_reserved_instruction(ctx);
19010 break;
19014 /* dsp */
19015 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19016 int ret, int v1, int v2)
19018 TCGv_i32 t0;
19019 TCGv v0_t;
19020 TCGv v1_t;
19022 t0 = tcg_temp_new_i32();
19024 v0_t = tcg_temp_new();
19025 v1_t = tcg_temp_new();
19027 tcg_gen_movi_i32(t0, v2 >> 3);
19029 gen_load_gpr(v0_t, ret);
19030 gen_load_gpr(v1_t, v1);
19032 switch (opc) {
19033 case NM_MAQ_S_W_PHR:
19034 check_dsp(ctx);
19035 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19036 break;
19037 case NM_MAQ_S_W_PHL:
19038 check_dsp(ctx);
19039 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19040 break;
19041 case NM_MAQ_SA_W_PHR:
19042 check_dsp(ctx);
19043 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19044 break;
19045 case NM_MAQ_SA_W_PHL:
19046 check_dsp(ctx);
19047 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19048 break;
19049 default:
19050 gen_reserved_instruction(ctx);
19051 break;
19054 tcg_temp_free_i32(t0);
19056 tcg_temp_free(v0_t);
19057 tcg_temp_free(v1_t);
19061 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19062 int ret, int v1, int v2)
19064 int16_t imm;
19065 TCGv t0 = tcg_temp_new();
19066 TCGv t1 = tcg_temp_new();
19067 TCGv v0_t = tcg_temp_new();
19069 gen_load_gpr(v0_t, v1);
19071 switch (opc) {
19072 case NM_POOL32AXF_1_0:
19073 check_dsp(ctx);
19074 switch (extract32(ctx->opcode, 12, 2)) {
19075 case NM_MFHI:
19076 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19077 break;
19078 case NM_MFLO:
19079 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19080 break;
19081 case NM_MTHI:
19082 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19083 break;
19084 case NM_MTLO:
19085 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19086 break;
19088 break;
19089 case NM_POOL32AXF_1_1:
19090 check_dsp(ctx);
19091 switch (extract32(ctx->opcode, 12, 2)) {
19092 case NM_MTHLIP:
19093 tcg_gen_movi_tl(t0, v2);
19094 gen_helper_mthlip(t0, v0_t, cpu_env);
19095 break;
19096 case NM_SHILOV:
19097 tcg_gen_movi_tl(t0, v2 >> 3);
19098 gen_helper_shilo(t0, v0_t, cpu_env);
19099 break;
19100 default:
19101 gen_reserved_instruction(ctx);
19102 break;
19104 break;
19105 case NM_POOL32AXF_1_3:
19106 check_dsp(ctx);
19107 imm = extract32(ctx->opcode, 14, 7);
19108 switch (extract32(ctx->opcode, 12, 2)) {
19109 case NM_RDDSP:
19110 tcg_gen_movi_tl(t0, imm);
19111 gen_helper_rddsp(t0, t0, cpu_env);
19112 gen_store_gpr(t0, ret);
19113 break;
19114 case NM_WRDSP:
19115 gen_load_gpr(t0, ret);
19116 tcg_gen_movi_tl(t1, imm);
19117 gen_helper_wrdsp(t0, t1, cpu_env);
19118 break;
19119 case NM_EXTP:
19120 tcg_gen_movi_tl(t0, v2 >> 3);
19121 tcg_gen_movi_tl(t1, v1);
19122 gen_helper_extp(t0, t0, t1, cpu_env);
19123 gen_store_gpr(t0, ret);
19124 break;
19125 case NM_EXTPDP:
19126 tcg_gen_movi_tl(t0, v2 >> 3);
19127 tcg_gen_movi_tl(t1, v1);
19128 gen_helper_extpdp(t0, t0, t1, cpu_env);
19129 gen_store_gpr(t0, ret);
19130 break;
19132 break;
19133 case NM_POOL32AXF_1_4:
19134 check_dsp(ctx);
19135 tcg_gen_movi_tl(t0, v2 >> 2);
19136 switch (extract32(ctx->opcode, 12, 1)) {
19137 case NM_SHLL_QB:
19138 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19139 gen_store_gpr(t0, ret);
19140 break;
19141 case NM_SHRL_QB:
19142 gen_helper_shrl_qb(t0, t0, v0_t);
19143 gen_store_gpr(t0, ret);
19144 break;
19146 break;
19147 case NM_POOL32AXF_1_5:
19148 opc = extract32(ctx->opcode, 12, 2);
19149 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19150 break;
19151 case NM_POOL32AXF_1_7:
19152 check_dsp(ctx);
19153 tcg_gen_movi_tl(t0, v2 >> 3);
19154 tcg_gen_movi_tl(t1, v1);
19155 switch (extract32(ctx->opcode, 12, 2)) {
19156 case NM_EXTR_W:
19157 gen_helper_extr_w(t0, t0, t1, cpu_env);
19158 gen_store_gpr(t0, ret);
19159 break;
19160 case NM_EXTR_R_W:
19161 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19162 gen_store_gpr(t0, ret);
19163 break;
19164 case NM_EXTR_RS_W:
19165 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19166 gen_store_gpr(t0, ret);
19167 break;
19168 case NM_EXTR_S_H:
19169 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19170 gen_store_gpr(t0, ret);
19171 break;
19173 break;
19174 default:
19175 gen_reserved_instruction(ctx);
19176 break;
19179 tcg_temp_free(t0);
19180 tcg_temp_free(t1);
19181 tcg_temp_free(v0_t);
19184 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19185 TCGv v0, TCGv v1, int rd)
19187 TCGv_i32 t0;
19189 t0 = tcg_temp_new_i32();
19191 tcg_gen_movi_i32(t0, rd >> 3);
19193 switch (opc) {
19194 case NM_POOL32AXF_2_0_7:
19195 switch (extract32(ctx->opcode, 9, 3)) {
19196 case NM_DPA_W_PH:
19197 check_dsp_r2(ctx);
19198 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19199 break;
19200 case NM_DPAQ_S_W_PH:
19201 check_dsp(ctx);
19202 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19203 break;
19204 case NM_DPS_W_PH:
19205 check_dsp_r2(ctx);
19206 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19207 break;
19208 case NM_DPSQ_S_W_PH:
19209 check_dsp(ctx);
19210 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19211 break;
19212 default:
19213 gen_reserved_instruction(ctx);
19214 break;
19216 break;
19217 case NM_POOL32AXF_2_8_15:
19218 switch (extract32(ctx->opcode, 9, 3)) {
19219 case NM_DPAX_W_PH:
19220 check_dsp_r2(ctx);
19221 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19222 break;
19223 case NM_DPAQ_SA_L_W:
19224 check_dsp(ctx);
19225 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19226 break;
19227 case NM_DPSX_W_PH:
19228 check_dsp_r2(ctx);
19229 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19230 break;
19231 case NM_DPSQ_SA_L_W:
19232 check_dsp(ctx);
19233 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19234 break;
19235 default:
19236 gen_reserved_instruction(ctx);
19237 break;
19239 break;
19240 case NM_POOL32AXF_2_16_23:
19241 switch (extract32(ctx->opcode, 9, 3)) {
19242 case NM_DPAU_H_QBL:
19243 check_dsp(ctx);
19244 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19245 break;
19246 case NM_DPAQX_S_W_PH:
19247 check_dsp_r2(ctx);
19248 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19249 break;
19250 case NM_DPSU_H_QBL:
19251 check_dsp(ctx);
19252 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19253 break;
19254 case NM_DPSQX_S_W_PH:
19255 check_dsp_r2(ctx);
19256 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19257 break;
19258 case NM_MULSA_W_PH:
19259 check_dsp_r2(ctx);
19260 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19261 break;
19262 default:
19263 gen_reserved_instruction(ctx);
19264 break;
19266 break;
19267 case NM_POOL32AXF_2_24_31:
19268 switch (extract32(ctx->opcode, 9, 3)) {
19269 case NM_DPAU_H_QBR:
19270 check_dsp(ctx);
19271 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19272 break;
19273 case NM_DPAQX_SA_W_PH:
19274 check_dsp_r2(ctx);
19275 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19276 break;
19277 case NM_DPSU_H_QBR:
19278 check_dsp(ctx);
19279 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19280 break;
19281 case NM_DPSQX_SA_W_PH:
19282 check_dsp_r2(ctx);
19283 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19284 break;
19285 case NM_MULSAQ_S_W_PH:
19286 check_dsp(ctx);
19287 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19288 break;
19289 default:
19290 gen_reserved_instruction(ctx);
19291 break;
19293 break;
19294 default:
19295 gen_reserved_instruction(ctx);
19296 break;
19299 tcg_temp_free_i32(t0);
19302 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19303 int rt, int rs, int rd)
19305 int ret = rt;
19306 TCGv t0 = tcg_temp_new();
19307 TCGv t1 = tcg_temp_new();
19308 TCGv v0_t = tcg_temp_new();
19309 TCGv v1_t = tcg_temp_new();
19311 gen_load_gpr(v0_t, rt);
19312 gen_load_gpr(v1_t, rs);
19314 switch (opc) {
19315 case NM_POOL32AXF_2_0_7:
19316 switch (extract32(ctx->opcode, 9, 3)) {
19317 case NM_DPA_W_PH:
19318 case NM_DPAQ_S_W_PH:
19319 case NM_DPS_W_PH:
19320 case NM_DPSQ_S_W_PH:
19321 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19322 break;
19323 case NM_BALIGN:
19324 check_dsp_r2(ctx);
19325 if (rt != 0) {
19326 gen_load_gpr(t0, rs);
19327 rd &= 3;
19328 if (rd != 0 && rd != 2) {
19329 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19330 tcg_gen_ext32u_tl(t0, t0);
19331 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19332 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19334 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19336 break;
19337 case NM_MADD:
19338 check_dsp(ctx);
19340 int acc = extract32(ctx->opcode, 14, 2);
19341 TCGv_i64 t2 = tcg_temp_new_i64();
19342 TCGv_i64 t3 = tcg_temp_new_i64();
19344 gen_load_gpr(t0, rt);
19345 gen_load_gpr(t1, rs);
19346 tcg_gen_ext_tl_i64(t2, t0);
19347 tcg_gen_ext_tl_i64(t3, t1);
19348 tcg_gen_mul_i64(t2, t2, t3);
19349 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19350 tcg_gen_add_i64(t2, t2, t3);
19351 tcg_temp_free_i64(t3);
19352 gen_move_low32(cpu_LO[acc], t2);
19353 gen_move_high32(cpu_HI[acc], t2);
19354 tcg_temp_free_i64(t2);
19356 break;
19357 case NM_MULT:
19358 check_dsp(ctx);
19360 int acc = extract32(ctx->opcode, 14, 2);
19361 TCGv_i32 t2 = tcg_temp_new_i32();
19362 TCGv_i32 t3 = tcg_temp_new_i32();
19364 gen_load_gpr(t0, rs);
19365 gen_load_gpr(t1, rt);
19366 tcg_gen_trunc_tl_i32(t2, t0);
19367 tcg_gen_trunc_tl_i32(t3, t1);
19368 tcg_gen_muls2_i32(t2, t3, t2, t3);
19369 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19370 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19371 tcg_temp_free_i32(t2);
19372 tcg_temp_free_i32(t3);
19374 break;
19375 case NM_EXTRV_W:
19376 check_dsp(ctx);
19377 gen_load_gpr(v1_t, rs);
19378 tcg_gen_movi_tl(t0, rd >> 3);
19379 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19380 gen_store_gpr(t0, ret);
19381 break;
19383 break;
19384 case NM_POOL32AXF_2_8_15:
19385 switch (extract32(ctx->opcode, 9, 3)) {
19386 case NM_DPAX_W_PH:
19387 case NM_DPAQ_SA_L_W:
19388 case NM_DPSX_W_PH:
19389 case NM_DPSQ_SA_L_W:
19390 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19391 break;
19392 case NM_MADDU:
19393 check_dsp(ctx);
19395 int acc = extract32(ctx->opcode, 14, 2);
19396 TCGv_i64 t2 = tcg_temp_new_i64();
19397 TCGv_i64 t3 = tcg_temp_new_i64();
19399 gen_load_gpr(t0, rs);
19400 gen_load_gpr(t1, rt);
19401 tcg_gen_ext32u_tl(t0, t0);
19402 tcg_gen_ext32u_tl(t1, t1);
19403 tcg_gen_extu_tl_i64(t2, t0);
19404 tcg_gen_extu_tl_i64(t3, t1);
19405 tcg_gen_mul_i64(t2, t2, t3);
19406 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19407 tcg_gen_add_i64(t2, t2, t3);
19408 tcg_temp_free_i64(t3);
19409 gen_move_low32(cpu_LO[acc], t2);
19410 gen_move_high32(cpu_HI[acc], t2);
19411 tcg_temp_free_i64(t2);
19413 break;
19414 case NM_MULTU:
19415 check_dsp(ctx);
19417 int acc = extract32(ctx->opcode, 14, 2);
19418 TCGv_i32 t2 = tcg_temp_new_i32();
19419 TCGv_i32 t3 = tcg_temp_new_i32();
19421 gen_load_gpr(t0, rs);
19422 gen_load_gpr(t1, rt);
19423 tcg_gen_trunc_tl_i32(t2, t0);
19424 tcg_gen_trunc_tl_i32(t3, t1);
19425 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19426 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19427 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19428 tcg_temp_free_i32(t2);
19429 tcg_temp_free_i32(t3);
19431 break;
19432 case NM_EXTRV_R_W:
19433 check_dsp(ctx);
19434 tcg_gen_movi_tl(t0, rd >> 3);
19435 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19436 gen_store_gpr(t0, ret);
19437 break;
19438 default:
19439 gen_reserved_instruction(ctx);
19440 break;
19442 break;
19443 case NM_POOL32AXF_2_16_23:
19444 switch (extract32(ctx->opcode, 9, 3)) {
19445 case NM_DPAU_H_QBL:
19446 case NM_DPAQX_S_W_PH:
19447 case NM_DPSU_H_QBL:
19448 case NM_DPSQX_S_W_PH:
19449 case NM_MULSA_W_PH:
19450 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19451 break;
19452 case NM_EXTPV:
19453 check_dsp(ctx);
19454 tcg_gen_movi_tl(t0, rd >> 3);
19455 gen_helper_extp(t0, t0, v1_t, cpu_env);
19456 gen_store_gpr(t0, ret);
19457 break;
19458 case NM_MSUB:
19459 check_dsp(ctx);
19461 int acc = extract32(ctx->opcode, 14, 2);
19462 TCGv_i64 t2 = tcg_temp_new_i64();
19463 TCGv_i64 t3 = tcg_temp_new_i64();
19465 gen_load_gpr(t0, rs);
19466 gen_load_gpr(t1, rt);
19467 tcg_gen_ext_tl_i64(t2, t0);
19468 tcg_gen_ext_tl_i64(t3, t1);
19469 tcg_gen_mul_i64(t2, t2, t3);
19470 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19471 tcg_gen_sub_i64(t2, t3, t2);
19472 tcg_temp_free_i64(t3);
19473 gen_move_low32(cpu_LO[acc], t2);
19474 gen_move_high32(cpu_HI[acc], t2);
19475 tcg_temp_free_i64(t2);
19477 break;
19478 case NM_EXTRV_RS_W:
19479 check_dsp(ctx);
19480 tcg_gen_movi_tl(t0, rd >> 3);
19481 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19482 gen_store_gpr(t0, ret);
19483 break;
19485 break;
19486 case NM_POOL32AXF_2_24_31:
19487 switch (extract32(ctx->opcode, 9, 3)) {
19488 case NM_DPAU_H_QBR:
19489 case NM_DPAQX_SA_W_PH:
19490 case NM_DPSU_H_QBR:
19491 case NM_DPSQX_SA_W_PH:
19492 case NM_MULSAQ_S_W_PH:
19493 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19494 break;
19495 case NM_EXTPDPV:
19496 check_dsp(ctx);
19497 tcg_gen_movi_tl(t0, rd >> 3);
19498 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19499 gen_store_gpr(t0, ret);
19500 break;
19501 case NM_MSUBU:
19502 check_dsp(ctx);
19504 int acc = extract32(ctx->opcode, 14, 2);
19505 TCGv_i64 t2 = tcg_temp_new_i64();
19506 TCGv_i64 t3 = tcg_temp_new_i64();
19508 gen_load_gpr(t0, rs);
19509 gen_load_gpr(t1, rt);
19510 tcg_gen_ext32u_tl(t0, t0);
19511 tcg_gen_ext32u_tl(t1, t1);
19512 tcg_gen_extu_tl_i64(t2, t0);
19513 tcg_gen_extu_tl_i64(t3, t1);
19514 tcg_gen_mul_i64(t2, t2, t3);
19515 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19516 tcg_gen_sub_i64(t2, t3, t2);
19517 tcg_temp_free_i64(t3);
19518 gen_move_low32(cpu_LO[acc], t2);
19519 gen_move_high32(cpu_HI[acc], t2);
19520 tcg_temp_free_i64(t2);
19522 break;
19523 case NM_EXTRV_S_H:
19524 check_dsp(ctx);
19525 tcg_gen_movi_tl(t0, rd >> 3);
19526 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19527 gen_store_gpr(t0, ret);
19528 break;
19530 break;
19531 default:
19532 gen_reserved_instruction(ctx);
19533 break;
19536 tcg_temp_free(t0);
19537 tcg_temp_free(t1);
19539 tcg_temp_free(v0_t);
19540 tcg_temp_free(v1_t);
19543 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19544 int rt, int rs)
19546 int ret = rt;
19547 TCGv t0 = tcg_temp_new();
19548 TCGv v0_t = tcg_temp_new();
19550 gen_load_gpr(v0_t, rs);
19552 switch (opc) {
19553 case NM_ABSQ_S_QB:
19554 check_dsp_r2(ctx);
19555 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19556 gen_store_gpr(v0_t, ret);
19557 break;
19558 case NM_ABSQ_S_PH:
19559 check_dsp(ctx);
19560 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19561 gen_store_gpr(v0_t, ret);
19562 break;
19563 case NM_ABSQ_S_W:
19564 check_dsp(ctx);
19565 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19566 gen_store_gpr(v0_t, ret);
19567 break;
19568 case NM_PRECEQ_W_PHL:
19569 check_dsp(ctx);
19570 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19571 tcg_gen_ext32s_tl(v0_t, v0_t);
19572 gen_store_gpr(v0_t, ret);
19573 break;
19574 case NM_PRECEQ_W_PHR:
19575 check_dsp(ctx);
19576 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19577 tcg_gen_shli_tl(v0_t, v0_t, 16);
19578 tcg_gen_ext32s_tl(v0_t, v0_t);
19579 gen_store_gpr(v0_t, ret);
19580 break;
19581 case NM_PRECEQU_PH_QBL:
19582 check_dsp(ctx);
19583 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19584 gen_store_gpr(v0_t, ret);
19585 break;
19586 case NM_PRECEQU_PH_QBR:
19587 check_dsp(ctx);
19588 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19589 gen_store_gpr(v0_t, ret);
19590 break;
19591 case NM_PRECEQU_PH_QBLA:
19592 check_dsp(ctx);
19593 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19594 gen_store_gpr(v0_t, ret);
19595 break;
19596 case NM_PRECEQU_PH_QBRA:
19597 check_dsp(ctx);
19598 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19599 gen_store_gpr(v0_t, ret);
19600 break;
19601 case NM_PRECEU_PH_QBL:
19602 check_dsp(ctx);
19603 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19604 gen_store_gpr(v0_t, ret);
19605 break;
19606 case NM_PRECEU_PH_QBR:
19607 check_dsp(ctx);
19608 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19609 gen_store_gpr(v0_t, ret);
19610 break;
19611 case NM_PRECEU_PH_QBLA:
19612 check_dsp(ctx);
19613 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19614 gen_store_gpr(v0_t, ret);
19615 break;
19616 case NM_PRECEU_PH_QBRA:
19617 check_dsp(ctx);
19618 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19619 gen_store_gpr(v0_t, ret);
19620 break;
19621 case NM_REPLV_PH:
19622 check_dsp(ctx);
19623 tcg_gen_ext16u_tl(v0_t, v0_t);
19624 tcg_gen_shli_tl(t0, v0_t, 16);
19625 tcg_gen_or_tl(v0_t, v0_t, t0);
19626 tcg_gen_ext32s_tl(v0_t, v0_t);
19627 gen_store_gpr(v0_t, ret);
19628 break;
19629 case NM_REPLV_QB:
19630 check_dsp(ctx);
19631 tcg_gen_ext8u_tl(v0_t, v0_t);
19632 tcg_gen_shli_tl(t0, v0_t, 8);
19633 tcg_gen_or_tl(v0_t, v0_t, t0);
19634 tcg_gen_shli_tl(t0, v0_t, 16);
19635 tcg_gen_or_tl(v0_t, v0_t, t0);
19636 tcg_gen_ext32s_tl(v0_t, v0_t);
19637 gen_store_gpr(v0_t, ret);
19638 break;
19639 case NM_BITREV:
19640 check_dsp(ctx);
19641 gen_helper_bitrev(v0_t, v0_t);
19642 gen_store_gpr(v0_t, ret);
19643 break;
19644 case NM_INSV:
19645 check_dsp(ctx);
19647 TCGv tv0 = tcg_temp_new();
19649 gen_load_gpr(tv0, rt);
19650 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19651 gen_store_gpr(v0_t, ret);
19652 tcg_temp_free(tv0);
19654 break;
19655 case NM_RADDU_W_QB:
19656 check_dsp(ctx);
19657 gen_helper_raddu_w_qb(v0_t, v0_t);
19658 gen_store_gpr(v0_t, ret);
19659 break;
19660 case NM_BITSWAP:
19661 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19662 break;
19663 case NM_CLO:
19664 check_nms(ctx);
19665 gen_cl(ctx, OPC_CLO, ret, rs);
19666 break;
19667 case NM_CLZ:
19668 check_nms(ctx);
19669 gen_cl(ctx, OPC_CLZ, ret, rs);
19670 break;
19671 case NM_WSBH:
19672 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19673 break;
19674 default:
19675 gen_reserved_instruction(ctx);
19676 break;
19679 tcg_temp_free(v0_t);
19680 tcg_temp_free(t0);
19683 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19684 int rt, int rs, int rd)
19686 TCGv t0 = tcg_temp_new();
19687 TCGv rs_t = tcg_temp_new();
19689 gen_load_gpr(rs_t, rs);
19691 switch (opc) {
19692 case NM_SHRA_R_QB:
19693 check_dsp_r2(ctx);
19694 tcg_gen_movi_tl(t0, rd >> 2);
19695 switch (extract32(ctx->opcode, 12, 1)) {
19696 case 0:
19697 /* NM_SHRA_QB */
19698 gen_helper_shra_qb(t0, t0, rs_t);
19699 gen_store_gpr(t0, rt);
19700 break;
19701 case 1:
19702 /* NM_SHRA_R_QB */
19703 gen_helper_shra_r_qb(t0, t0, rs_t);
19704 gen_store_gpr(t0, rt);
19705 break;
19707 break;
19708 case NM_SHRL_PH:
19709 check_dsp_r2(ctx);
19710 tcg_gen_movi_tl(t0, rd >> 1);
19711 gen_helper_shrl_ph(t0, t0, rs_t);
19712 gen_store_gpr(t0, rt);
19713 break;
19714 case NM_REPL_QB:
19715 check_dsp(ctx);
19717 int16_t imm;
19718 target_long result;
19719 imm = extract32(ctx->opcode, 13, 8);
19720 result = (uint32_t)imm << 24 |
19721 (uint32_t)imm << 16 |
19722 (uint32_t)imm << 8 |
19723 (uint32_t)imm;
19724 result = (int32_t)result;
19725 tcg_gen_movi_tl(t0, result);
19726 gen_store_gpr(t0, rt);
19728 break;
19729 default:
19730 gen_reserved_instruction(ctx);
19731 break;
19733 tcg_temp_free(t0);
19734 tcg_temp_free(rs_t);
19738 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19740 int rt = extract32(ctx->opcode, 21, 5);
19741 int rs = extract32(ctx->opcode, 16, 5);
19742 int rd = extract32(ctx->opcode, 11, 5);
19744 switch (extract32(ctx->opcode, 6, 3)) {
19745 case NM_POOL32AXF_1:
19747 int32_t op1 = extract32(ctx->opcode, 9, 3);
19748 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19750 break;
19751 case NM_POOL32AXF_2:
19753 int32_t op1 = extract32(ctx->opcode, 12, 2);
19754 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19756 break;
19757 case NM_POOL32AXF_4:
19759 int32_t op1 = extract32(ctx->opcode, 9, 7);
19760 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19762 break;
19763 case NM_POOL32AXF_5:
19764 switch (extract32(ctx->opcode, 9, 7)) {
19765 #ifndef CONFIG_USER_ONLY
19766 case NM_TLBP:
19767 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19768 break;
19769 case NM_TLBR:
19770 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19771 break;
19772 case NM_TLBWI:
19773 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19774 break;
19775 case NM_TLBWR:
19776 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19777 break;
19778 case NM_TLBINV:
19779 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19780 break;
19781 case NM_TLBINVF:
19782 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19783 break;
19784 case NM_DI:
19785 check_cp0_enabled(ctx);
19787 TCGv t0 = tcg_temp_new();
19789 save_cpu_state(ctx, 1);
19790 gen_helper_di(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_EI:
19798 check_cp0_enabled(ctx);
19800 TCGv t0 = tcg_temp_new();
19802 save_cpu_state(ctx, 1);
19803 gen_helper_ei(t0, cpu_env);
19804 gen_store_gpr(t0, rt);
19805 /* Stop translation as we may have switched the execution mode */
19806 ctx->base.is_jmp = DISAS_STOP;
19807 tcg_temp_free(t0);
19809 break;
19810 case NM_RDPGPR:
19811 gen_load_srsgpr(rs, rt);
19812 break;
19813 case NM_WRPGPR:
19814 gen_store_srsgpr(rs, rt);
19815 break;
19816 case NM_WAIT:
19817 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19818 break;
19819 case NM_DERET:
19820 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19821 break;
19822 case NM_ERETX:
19823 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19824 break;
19825 #endif
19826 default:
19827 gen_reserved_instruction(ctx);
19828 break;
19830 break;
19831 case NM_POOL32AXF_7:
19833 int32_t op1 = extract32(ctx->opcode, 9, 3);
19834 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19836 break;
19837 default:
19838 gen_reserved_instruction(ctx);
19839 break;
19843 /* Immediate Value Compact Branches */
19844 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19845 int rt, int32_t imm, int32_t offset)
19847 TCGCond cond = TCG_COND_ALWAYS;
19848 TCGv t0 = tcg_temp_new();
19849 TCGv t1 = tcg_temp_new();
19851 gen_load_gpr(t0, rt);
19852 tcg_gen_movi_tl(t1, imm);
19853 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19855 /* Load needed operands and calculate btarget */
19856 switch (opc) {
19857 case NM_BEQIC:
19858 if (rt == 0 && imm == 0) {
19859 /* Unconditional branch */
19860 } else if (rt == 0 && imm != 0) {
19861 /* Treat as NOP */
19862 goto out;
19863 } else {
19864 cond = TCG_COND_EQ;
19866 break;
19867 case NM_BBEQZC:
19868 case NM_BBNEZC:
19869 check_nms(ctx);
19870 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19871 gen_reserved_instruction(ctx);
19872 goto out;
19873 } else if (rt == 0 && opc == NM_BBEQZC) {
19874 /* Unconditional branch */
19875 } else if (rt == 0 && opc == NM_BBNEZC) {
19876 /* Treat as NOP */
19877 goto out;
19878 } else {
19879 tcg_gen_shri_tl(t0, t0, imm);
19880 tcg_gen_andi_tl(t0, t0, 1);
19881 tcg_gen_movi_tl(t1, 0);
19882 if (opc == NM_BBEQZC) {
19883 cond = TCG_COND_EQ;
19884 } else {
19885 cond = TCG_COND_NE;
19888 break;
19889 case NM_BNEIC:
19890 if (rt == 0 && imm == 0) {
19891 /* Treat as NOP */
19892 goto out;
19893 } else if (rt == 0 && imm != 0) {
19894 /* Unconditional branch */
19895 } else {
19896 cond = TCG_COND_NE;
19898 break;
19899 case NM_BGEIC:
19900 if (rt == 0 && imm == 0) {
19901 /* Unconditional branch */
19902 } else {
19903 cond = TCG_COND_GE;
19905 break;
19906 case NM_BLTIC:
19907 cond = TCG_COND_LT;
19908 break;
19909 case NM_BGEIUC:
19910 if (rt == 0 && imm == 0) {
19911 /* Unconditional branch */
19912 } else {
19913 cond = TCG_COND_GEU;
19915 break;
19916 case NM_BLTIUC:
19917 cond = TCG_COND_LTU;
19918 break;
19919 default:
19920 MIPS_INVAL("Immediate Value Compact branch");
19921 gen_reserved_instruction(ctx);
19922 goto out;
19925 /* branch completion */
19926 clear_branch_hflags(ctx);
19927 ctx->base.is_jmp = DISAS_NORETURN;
19929 if (cond == TCG_COND_ALWAYS) {
19930 /* Uncoditional compact branch */
19931 gen_goto_tb(ctx, 0, ctx->btarget);
19932 } else {
19933 /* Conditional compact branch */
19934 TCGLabel *fs = gen_new_label();
19936 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19938 gen_goto_tb(ctx, 1, ctx->btarget);
19939 gen_set_label(fs);
19941 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19944 out:
19945 tcg_temp_free(t0);
19946 tcg_temp_free(t1);
19949 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19950 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19951 int rt)
19953 TCGv t0 = tcg_temp_new();
19954 TCGv t1 = tcg_temp_new();
19956 /* load rs */
19957 gen_load_gpr(t0, rs);
19959 /* link */
19960 if (rt != 0) {
19961 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19964 /* calculate btarget */
19965 tcg_gen_shli_tl(t0, t0, 1);
19966 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19967 gen_op_addr_add(ctx, btarget, t1, t0);
19969 /* branch completion */
19970 clear_branch_hflags(ctx);
19971 ctx->base.is_jmp = DISAS_NORETURN;
19973 /* unconditional branch to register */
19974 tcg_gen_mov_tl(cpu_PC, btarget);
19975 tcg_gen_lookup_and_goto_ptr();
19977 tcg_temp_free(t0);
19978 tcg_temp_free(t1);
19981 /* nanoMIPS Branches */
19982 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19983 int rs, int rt, int32_t offset)
19985 int bcond_compute = 0;
19986 TCGv t0 = tcg_temp_new();
19987 TCGv t1 = tcg_temp_new();
19989 /* Load needed operands and calculate btarget */
19990 switch (opc) {
19991 /* compact branch */
19992 case OPC_BGEC:
19993 case OPC_BLTC:
19994 gen_load_gpr(t0, rs);
19995 gen_load_gpr(t1, rt);
19996 bcond_compute = 1;
19997 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19998 break;
19999 case OPC_BGEUC:
20000 case OPC_BLTUC:
20001 if (rs == 0 || rs == rt) {
20002 /* OPC_BLEZALC, OPC_BGEZALC */
20003 /* OPC_BGTZALC, OPC_BLTZALC */
20004 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20006 gen_load_gpr(t0, rs);
20007 gen_load_gpr(t1, rt);
20008 bcond_compute = 1;
20009 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20010 break;
20011 case OPC_BC:
20012 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20013 break;
20014 case OPC_BEQZC:
20015 if (rs != 0) {
20016 /* OPC_BEQZC, OPC_BNEZC */
20017 gen_load_gpr(t0, rs);
20018 bcond_compute = 1;
20019 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20020 } else {
20021 /* OPC_JIC, OPC_JIALC */
20022 TCGv tbase = tcg_temp_new();
20023 TCGv toffset = tcg_temp_new();
20025 gen_load_gpr(tbase, rt);
20026 tcg_gen_movi_tl(toffset, offset);
20027 gen_op_addr_add(ctx, btarget, tbase, toffset);
20028 tcg_temp_free(tbase);
20029 tcg_temp_free(toffset);
20031 break;
20032 default:
20033 MIPS_INVAL("Compact branch/jump");
20034 gen_reserved_instruction(ctx);
20035 goto out;
20038 if (bcond_compute == 0) {
20039 /* Uncoditional compact branch */
20040 switch (opc) {
20041 case OPC_BC:
20042 gen_goto_tb(ctx, 0, ctx->btarget);
20043 break;
20044 default:
20045 MIPS_INVAL("Compact branch/jump");
20046 gen_reserved_instruction(ctx);
20047 goto out;
20049 } else {
20050 /* Conditional compact branch */
20051 TCGLabel *fs = gen_new_label();
20053 switch (opc) {
20054 case OPC_BGEUC:
20055 if (rs == 0 && rt != 0) {
20056 /* OPC_BLEZALC */
20057 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20058 } else if (rs != 0 && rt != 0 && rs == rt) {
20059 /* OPC_BGEZALC */
20060 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20061 } else {
20062 /* OPC_BGEUC */
20063 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20065 break;
20066 case OPC_BLTUC:
20067 if (rs == 0 && rt != 0) {
20068 /* OPC_BGTZALC */
20069 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20070 } else if (rs != 0 && rt != 0 && rs == rt) {
20071 /* OPC_BLTZALC */
20072 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20073 } else {
20074 /* OPC_BLTUC */
20075 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20077 break;
20078 case OPC_BGEC:
20079 if (rs == 0 && rt != 0) {
20080 /* OPC_BLEZC */
20081 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20082 } else if (rs != 0 && rt != 0 && rs == rt) {
20083 /* OPC_BGEZC */
20084 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20085 } else {
20086 /* OPC_BGEC */
20087 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20089 break;
20090 case OPC_BLTC:
20091 if (rs == 0 && rt != 0) {
20092 /* OPC_BGTZC */
20093 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20094 } else if (rs != 0 && rt != 0 && rs == rt) {
20095 /* OPC_BLTZC */
20096 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20097 } else {
20098 /* OPC_BLTC */
20099 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20101 break;
20102 case OPC_BEQZC:
20103 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20104 break;
20105 default:
20106 MIPS_INVAL("Compact conditional branch/jump");
20107 gen_reserved_instruction(ctx);
20108 goto out;
20111 /* branch completion */
20112 clear_branch_hflags(ctx);
20113 ctx->base.is_jmp = DISAS_NORETURN;
20115 /* Generating branch here as compact branches don't have delay slot */
20116 gen_goto_tb(ctx, 1, ctx->btarget);
20117 gen_set_label(fs);
20119 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20122 out:
20123 tcg_temp_free(t0);
20124 tcg_temp_free(t1);
20128 /* nanoMIPS CP1 Branches */
20129 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20130 int32_t ft, int32_t offset)
20132 target_ulong btarget;
20133 TCGv_i64 t0 = tcg_temp_new_i64();
20135 gen_load_fpr64(ctx, t0, ft);
20136 tcg_gen_andi_i64(t0, t0, 1);
20138 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20140 switch (op) {
20141 case NM_BC1EQZC:
20142 tcg_gen_xori_i64(t0, t0, 1);
20143 ctx->hflags |= MIPS_HFLAG_BC;
20144 break;
20145 case NM_BC1NEZC:
20146 /* t0 already set */
20147 ctx->hflags |= MIPS_HFLAG_BC;
20148 break;
20149 default:
20150 MIPS_INVAL("cp1 cond branch");
20151 gen_reserved_instruction(ctx);
20152 goto out;
20155 tcg_gen_trunc_i64_tl(bcond, t0);
20157 ctx->btarget = btarget;
20159 out:
20160 tcg_temp_free_i64(t0);
20164 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20166 TCGv t0, t1;
20167 t0 = tcg_temp_new();
20168 t1 = tcg_temp_new();
20170 gen_load_gpr(t0, rs);
20171 gen_load_gpr(t1, rt);
20173 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20174 /* PP.LSXS instructions require shifting */
20175 switch (extract32(ctx->opcode, 7, 4)) {
20176 case NM_SHXS:
20177 check_nms(ctx);
20178 /* fall through */
20179 case NM_LHXS:
20180 case NM_LHUXS:
20181 tcg_gen_shli_tl(t0, t0, 1);
20182 break;
20183 case NM_SWXS:
20184 check_nms(ctx);
20185 /* fall through */
20186 case NM_LWXS:
20187 case NM_LWC1XS:
20188 case NM_SWC1XS:
20189 tcg_gen_shli_tl(t0, t0, 2);
20190 break;
20191 case NM_LDC1XS:
20192 case NM_SDC1XS:
20193 tcg_gen_shli_tl(t0, t0, 3);
20194 break;
20197 gen_op_addr_add(ctx, t0, t0, t1);
20199 switch (extract32(ctx->opcode, 7, 4)) {
20200 case NM_LBX:
20201 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20202 MO_SB);
20203 gen_store_gpr(t0, rd);
20204 break;
20205 case NM_LHX:
20206 /*case NM_LHXS:*/
20207 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20208 MO_TESW);
20209 gen_store_gpr(t0, rd);
20210 break;
20211 case NM_LWX:
20212 /*case NM_LWXS:*/
20213 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20214 MO_TESL);
20215 gen_store_gpr(t0, rd);
20216 break;
20217 case NM_LBUX:
20218 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20219 MO_UB);
20220 gen_store_gpr(t0, rd);
20221 break;
20222 case NM_LHUX:
20223 /*case NM_LHUXS:*/
20224 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20225 MO_TEUW);
20226 gen_store_gpr(t0, rd);
20227 break;
20228 case NM_SBX:
20229 check_nms(ctx);
20230 gen_load_gpr(t1, rd);
20231 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20232 MO_8);
20233 break;
20234 case NM_SHX:
20235 /*case NM_SHXS:*/
20236 check_nms(ctx);
20237 gen_load_gpr(t1, rd);
20238 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20239 MO_TEUW);
20240 break;
20241 case NM_SWX:
20242 /*case NM_SWXS:*/
20243 check_nms(ctx);
20244 gen_load_gpr(t1, rd);
20245 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20246 MO_TEUL);
20247 break;
20248 case NM_LWC1X:
20249 /*case NM_LWC1XS:*/
20250 case NM_LDC1X:
20251 /*case NM_LDC1XS:*/
20252 case NM_SWC1X:
20253 /*case NM_SWC1XS:*/
20254 case NM_SDC1X:
20255 /*case NM_SDC1XS:*/
20256 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20257 check_cp1_enabled(ctx);
20258 switch (extract32(ctx->opcode, 7, 4)) {
20259 case NM_LWC1X:
20260 /*case NM_LWC1XS:*/
20261 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20262 break;
20263 case NM_LDC1X:
20264 /*case NM_LDC1XS:*/
20265 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20266 break;
20267 case NM_SWC1X:
20268 /*case NM_SWC1XS:*/
20269 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20270 break;
20271 case NM_SDC1X:
20272 /*case NM_SDC1XS:*/
20273 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20274 break;
20276 } else {
20277 generate_exception_err(ctx, EXCP_CpU, 1);
20279 break;
20280 default:
20281 gen_reserved_instruction(ctx);
20282 break;
20285 tcg_temp_free(t0);
20286 tcg_temp_free(t1);
20289 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20291 int rt, rs, rd;
20293 rt = extract32(ctx->opcode, 21, 5);
20294 rs = extract32(ctx->opcode, 16, 5);
20295 rd = extract32(ctx->opcode, 11, 5);
20297 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20298 gen_reserved_instruction(ctx);
20299 return;
20301 check_cp1_enabled(ctx);
20302 switch (extract32(ctx->opcode, 0, 3)) {
20303 case NM_POOL32F_0:
20304 switch (extract32(ctx->opcode, 3, 7)) {
20305 case NM_RINT_S:
20306 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20307 break;
20308 case NM_RINT_D:
20309 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20310 break;
20311 case NM_CLASS_S:
20312 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20313 break;
20314 case NM_CLASS_D:
20315 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20316 break;
20317 case NM_ADD_S:
20318 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20319 break;
20320 case NM_ADD_D:
20321 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20322 break;
20323 case NM_SUB_S:
20324 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20325 break;
20326 case NM_SUB_D:
20327 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20328 break;
20329 case NM_MUL_S:
20330 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20331 break;
20332 case NM_MUL_D:
20333 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20334 break;
20335 case NM_DIV_S:
20336 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20337 break;
20338 case NM_DIV_D:
20339 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20340 break;
20341 case NM_SELEQZ_S:
20342 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20343 break;
20344 case NM_SELEQZ_D:
20345 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20346 break;
20347 case NM_SELNEZ_S:
20348 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20349 break;
20350 case NM_SELNEZ_D:
20351 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20352 break;
20353 case NM_SEL_S:
20354 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20355 break;
20356 case NM_SEL_D:
20357 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20358 break;
20359 case NM_MADDF_S:
20360 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20361 break;
20362 case NM_MADDF_D:
20363 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20364 break;
20365 case NM_MSUBF_S:
20366 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20367 break;
20368 case NM_MSUBF_D:
20369 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20370 break;
20371 default:
20372 gen_reserved_instruction(ctx);
20373 break;
20375 break;
20376 case NM_POOL32F_3:
20377 switch (extract32(ctx->opcode, 3, 3)) {
20378 case NM_MIN_FMT:
20379 switch (extract32(ctx->opcode, 9, 1)) {
20380 case FMT_SDPS_S:
20381 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20382 break;
20383 case FMT_SDPS_D:
20384 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20385 break;
20387 break;
20388 case NM_MAX_FMT:
20389 switch (extract32(ctx->opcode, 9, 1)) {
20390 case FMT_SDPS_S:
20391 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20392 break;
20393 case FMT_SDPS_D:
20394 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20395 break;
20397 break;
20398 case NM_MINA_FMT:
20399 switch (extract32(ctx->opcode, 9, 1)) {
20400 case FMT_SDPS_S:
20401 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20402 break;
20403 case FMT_SDPS_D:
20404 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20405 break;
20407 break;
20408 case NM_MAXA_FMT:
20409 switch (extract32(ctx->opcode, 9, 1)) {
20410 case FMT_SDPS_S:
20411 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20412 break;
20413 case FMT_SDPS_D:
20414 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20415 break;
20417 break;
20418 case NM_POOL32FXF:
20419 switch (extract32(ctx->opcode, 6, 8)) {
20420 case NM_CFC1:
20421 gen_cp1(ctx, OPC_CFC1, rt, rs);
20422 break;
20423 case NM_CTC1:
20424 gen_cp1(ctx, OPC_CTC1, rt, rs);
20425 break;
20426 case NM_MFC1:
20427 gen_cp1(ctx, OPC_MFC1, rt, rs);
20428 break;
20429 case NM_MTC1:
20430 gen_cp1(ctx, OPC_MTC1, rt, rs);
20431 break;
20432 case NM_MFHC1:
20433 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20434 break;
20435 case NM_MTHC1:
20436 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20437 break;
20438 case NM_CVT_S_PL:
20439 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20440 break;
20441 case NM_CVT_S_PU:
20442 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20443 break;
20444 default:
20445 switch (extract32(ctx->opcode, 6, 9)) {
20446 case NM_CVT_L_S:
20447 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20448 break;
20449 case NM_CVT_L_D:
20450 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20451 break;
20452 case NM_CVT_W_S:
20453 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20454 break;
20455 case NM_CVT_W_D:
20456 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20457 break;
20458 case NM_RSQRT_S:
20459 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20460 break;
20461 case NM_RSQRT_D:
20462 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20463 break;
20464 case NM_SQRT_S:
20465 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20466 break;
20467 case NM_SQRT_D:
20468 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20469 break;
20470 case NM_RECIP_S:
20471 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20472 break;
20473 case NM_RECIP_D:
20474 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20475 break;
20476 case NM_FLOOR_L_S:
20477 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20478 break;
20479 case NM_FLOOR_L_D:
20480 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20481 break;
20482 case NM_FLOOR_W_S:
20483 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20484 break;
20485 case NM_FLOOR_W_D:
20486 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20487 break;
20488 case NM_CEIL_L_S:
20489 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20490 break;
20491 case NM_CEIL_L_D:
20492 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20493 break;
20494 case NM_CEIL_W_S:
20495 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20496 break;
20497 case NM_CEIL_W_D:
20498 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20499 break;
20500 case NM_TRUNC_L_S:
20501 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20502 break;
20503 case NM_TRUNC_L_D:
20504 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20505 break;
20506 case NM_TRUNC_W_S:
20507 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20508 break;
20509 case NM_TRUNC_W_D:
20510 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20511 break;
20512 case NM_ROUND_L_S:
20513 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20514 break;
20515 case NM_ROUND_L_D:
20516 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20517 break;
20518 case NM_ROUND_W_S:
20519 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20520 break;
20521 case NM_ROUND_W_D:
20522 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20523 break;
20524 case NM_MOV_S:
20525 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20526 break;
20527 case NM_MOV_D:
20528 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20529 break;
20530 case NM_ABS_S:
20531 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20532 break;
20533 case NM_ABS_D:
20534 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20535 break;
20536 case NM_NEG_S:
20537 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20538 break;
20539 case NM_NEG_D:
20540 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20541 break;
20542 case NM_CVT_D_S:
20543 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20544 break;
20545 case NM_CVT_D_W:
20546 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20547 break;
20548 case NM_CVT_D_L:
20549 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20550 break;
20551 case NM_CVT_S_D:
20552 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20553 break;
20554 case NM_CVT_S_W:
20555 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20556 break;
20557 case NM_CVT_S_L:
20558 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20559 break;
20560 default:
20561 gen_reserved_instruction(ctx);
20562 break;
20564 break;
20566 break;
20568 break;
20569 case NM_POOL32F_5:
20570 switch (extract32(ctx->opcode, 3, 3)) {
20571 case NM_CMP_CONDN_S:
20572 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20573 break;
20574 case NM_CMP_CONDN_D:
20575 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20576 break;
20577 default:
20578 gen_reserved_instruction(ctx);
20579 break;
20581 break;
20582 default:
20583 gen_reserved_instruction(ctx);
20584 break;
20588 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20589 int rd, int rs, int rt)
20591 int ret = rd;
20592 TCGv t0 = tcg_temp_new();
20593 TCGv v1_t = tcg_temp_new();
20594 TCGv v2_t = tcg_temp_new();
20596 gen_load_gpr(v1_t, rs);
20597 gen_load_gpr(v2_t, rt);
20599 switch (opc) {
20600 case NM_CMP_EQ_PH:
20601 check_dsp(ctx);
20602 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20603 break;
20604 case NM_CMP_LT_PH:
20605 check_dsp(ctx);
20606 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20607 break;
20608 case NM_CMP_LE_PH:
20609 check_dsp(ctx);
20610 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20611 break;
20612 case NM_CMPU_EQ_QB:
20613 check_dsp(ctx);
20614 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20615 break;
20616 case NM_CMPU_LT_QB:
20617 check_dsp(ctx);
20618 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20619 break;
20620 case NM_CMPU_LE_QB:
20621 check_dsp(ctx);
20622 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20623 break;
20624 case NM_CMPGU_EQ_QB:
20625 check_dsp(ctx);
20626 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20627 gen_store_gpr(v1_t, ret);
20628 break;
20629 case NM_CMPGU_LT_QB:
20630 check_dsp(ctx);
20631 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20632 gen_store_gpr(v1_t, ret);
20633 break;
20634 case NM_CMPGU_LE_QB:
20635 check_dsp(ctx);
20636 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20637 gen_store_gpr(v1_t, ret);
20638 break;
20639 case NM_CMPGDU_EQ_QB:
20640 check_dsp_r2(ctx);
20641 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20642 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20643 gen_store_gpr(v1_t, ret);
20644 break;
20645 case NM_CMPGDU_LT_QB:
20646 check_dsp_r2(ctx);
20647 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20648 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20649 gen_store_gpr(v1_t, ret);
20650 break;
20651 case NM_CMPGDU_LE_QB:
20652 check_dsp_r2(ctx);
20653 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20654 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20655 gen_store_gpr(v1_t, ret);
20656 break;
20657 case NM_PACKRL_PH:
20658 check_dsp(ctx);
20659 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20660 gen_store_gpr(v1_t, ret);
20661 break;
20662 case NM_PICK_QB:
20663 check_dsp(ctx);
20664 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20665 gen_store_gpr(v1_t, ret);
20666 break;
20667 case NM_PICK_PH:
20668 check_dsp(ctx);
20669 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20670 gen_store_gpr(v1_t, ret);
20671 break;
20672 case NM_ADDQ_S_W:
20673 check_dsp(ctx);
20674 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20675 gen_store_gpr(v1_t, ret);
20676 break;
20677 case NM_SUBQ_S_W:
20678 check_dsp(ctx);
20679 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20680 gen_store_gpr(v1_t, ret);
20681 break;
20682 case NM_ADDSC:
20683 check_dsp(ctx);
20684 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20685 gen_store_gpr(v1_t, ret);
20686 break;
20687 case NM_ADDWC:
20688 check_dsp(ctx);
20689 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20690 gen_store_gpr(v1_t, ret);
20691 break;
20692 case NM_ADDQ_S_PH:
20693 check_dsp(ctx);
20694 switch (extract32(ctx->opcode, 10, 1)) {
20695 case 0:
20696 /* ADDQ_PH */
20697 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20698 gen_store_gpr(v1_t, ret);
20699 break;
20700 case 1:
20701 /* ADDQ_S_PH */
20702 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20703 gen_store_gpr(v1_t, ret);
20704 break;
20706 break;
20707 case NM_ADDQH_R_PH:
20708 check_dsp_r2(ctx);
20709 switch (extract32(ctx->opcode, 10, 1)) {
20710 case 0:
20711 /* ADDQH_PH */
20712 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20713 gen_store_gpr(v1_t, ret);
20714 break;
20715 case 1:
20716 /* ADDQH_R_PH */
20717 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20718 gen_store_gpr(v1_t, ret);
20719 break;
20721 break;
20722 case NM_ADDQH_R_W:
20723 check_dsp_r2(ctx);
20724 switch (extract32(ctx->opcode, 10, 1)) {
20725 case 0:
20726 /* ADDQH_W */
20727 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20728 gen_store_gpr(v1_t, ret);
20729 break;
20730 case 1:
20731 /* ADDQH_R_W */
20732 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20733 gen_store_gpr(v1_t, ret);
20734 break;
20736 break;
20737 case NM_ADDU_S_QB:
20738 check_dsp(ctx);
20739 switch (extract32(ctx->opcode, 10, 1)) {
20740 case 0:
20741 /* ADDU_QB */
20742 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20743 gen_store_gpr(v1_t, ret);
20744 break;
20745 case 1:
20746 /* ADDU_S_QB */
20747 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20748 gen_store_gpr(v1_t, ret);
20749 break;
20751 break;
20752 case NM_ADDU_S_PH:
20753 check_dsp_r2(ctx);
20754 switch (extract32(ctx->opcode, 10, 1)) {
20755 case 0:
20756 /* ADDU_PH */
20757 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20758 gen_store_gpr(v1_t, ret);
20759 break;
20760 case 1:
20761 /* ADDU_S_PH */
20762 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20763 gen_store_gpr(v1_t, ret);
20764 break;
20766 break;
20767 case NM_ADDUH_R_QB:
20768 check_dsp_r2(ctx);
20769 switch (extract32(ctx->opcode, 10, 1)) {
20770 case 0:
20771 /* ADDUH_QB */
20772 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20773 gen_store_gpr(v1_t, ret);
20774 break;
20775 case 1:
20776 /* ADDUH_R_QB */
20777 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20778 gen_store_gpr(v1_t, ret);
20779 break;
20781 break;
20782 case NM_SHRAV_R_PH:
20783 check_dsp(ctx);
20784 switch (extract32(ctx->opcode, 10, 1)) {
20785 case 0:
20786 /* SHRAV_PH */
20787 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20788 gen_store_gpr(v1_t, ret);
20789 break;
20790 case 1:
20791 /* SHRAV_R_PH */
20792 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20793 gen_store_gpr(v1_t, ret);
20794 break;
20796 break;
20797 case NM_SHRAV_R_QB:
20798 check_dsp_r2(ctx);
20799 switch (extract32(ctx->opcode, 10, 1)) {
20800 case 0:
20801 /* SHRAV_QB */
20802 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20803 gen_store_gpr(v1_t, ret);
20804 break;
20805 case 1:
20806 /* SHRAV_R_QB */
20807 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20808 gen_store_gpr(v1_t, ret);
20809 break;
20811 break;
20812 case NM_SUBQ_S_PH:
20813 check_dsp(ctx);
20814 switch (extract32(ctx->opcode, 10, 1)) {
20815 case 0:
20816 /* SUBQ_PH */
20817 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20818 gen_store_gpr(v1_t, ret);
20819 break;
20820 case 1:
20821 /* SUBQ_S_PH */
20822 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20823 gen_store_gpr(v1_t, ret);
20824 break;
20826 break;
20827 case NM_SUBQH_R_PH:
20828 check_dsp_r2(ctx);
20829 switch (extract32(ctx->opcode, 10, 1)) {
20830 case 0:
20831 /* SUBQH_PH */
20832 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20833 gen_store_gpr(v1_t, ret);
20834 break;
20835 case 1:
20836 /* SUBQH_R_PH */
20837 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20838 gen_store_gpr(v1_t, ret);
20839 break;
20841 break;
20842 case NM_SUBQH_R_W:
20843 check_dsp_r2(ctx);
20844 switch (extract32(ctx->opcode, 10, 1)) {
20845 case 0:
20846 /* SUBQH_W */
20847 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20848 gen_store_gpr(v1_t, ret);
20849 break;
20850 case 1:
20851 /* SUBQH_R_W */
20852 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20853 gen_store_gpr(v1_t, ret);
20854 break;
20856 break;
20857 case NM_SUBU_S_QB:
20858 check_dsp(ctx);
20859 switch (extract32(ctx->opcode, 10, 1)) {
20860 case 0:
20861 /* SUBU_QB */
20862 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20863 gen_store_gpr(v1_t, ret);
20864 break;
20865 case 1:
20866 /* SUBU_S_QB */
20867 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20868 gen_store_gpr(v1_t, ret);
20869 break;
20871 break;
20872 case NM_SUBU_S_PH:
20873 check_dsp_r2(ctx);
20874 switch (extract32(ctx->opcode, 10, 1)) {
20875 case 0:
20876 /* SUBU_PH */
20877 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20878 gen_store_gpr(v1_t, ret);
20879 break;
20880 case 1:
20881 /* SUBU_S_PH */
20882 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20883 gen_store_gpr(v1_t, ret);
20884 break;
20886 break;
20887 case NM_SUBUH_R_QB:
20888 check_dsp_r2(ctx);
20889 switch (extract32(ctx->opcode, 10, 1)) {
20890 case 0:
20891 /* SUBUH_QB */
20892 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20893 gen_store_gpr(v1_t, ret);
20894 break;
20895 case 1:
20896 /* SUBUH_R_QB */
20897 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20898 gen_store_gpr(v1_t, ret);
20899 break;
20901 break;
20902 case NM_SHLLV_S_PH:
20903 check_dsp(ctx);
20904 switch (extract32(ctx->opcode, 10, 1)) {
20905 case 0:
20906 /* SHLLV_PH */
20907 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20908 gen_store_gpr(v1_t, ret);
20909 break;
20910 case 1:
20911 /* SHLLV_S_PH */
20912 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20913 gen_store_gpr(v1_t, ret);
20914 break;
20916 break;
20917 case NM_PRECR_SRA_R_PH_W:
20918 check_dsp_r2(ctx);
20919 switch (extract32(ctx->opcode, 10, 1)) {
20920 case 0:
20921 /* PRECR_SRA_PH_W */
20923 TCGv_i32 sa_t = tcg_const_i32(rd);
20924 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20925 cpu_gpr[rt]);
20926 gen_store_gpr(v1_t, rt);
20927 tcg_temp_free_i32(sa_t);
20929 break;
20930 case 1:
20931 /* PRECR_SRA_R_PH_W */
20933 TCGv_i32 sa_t = tcg_const_i32(rd);
20934 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20935 cpu_gpr[rt]);
20936 gen_store_gpr(v1_t, rt);
20937 tcg_temp_free_i32(sa_t);
20939 break;
20941 break;
20942 case NM_MULEU_S_PH_QBL:
20943 check_dsp(ctx);
20944 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20945 gen_store_gpr(v1_t, ret);
20946 break;
20947 case NM_MULEU_S_PH_QBR:
20948 check_dsp(ctx);
20949 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20950 gen_store_gpr(v1_t, ret);
20951 break;
20952 case NM_MULQ_RS_PH:
20953 check_dsp(ctx);
20954 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20955 gen_store_gpr(v1_t, ret);
20956 break;
20957 case NM_MULQ_S_PH:
20958 check_dsp_r2(ctx);
20959 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20960 gen_store_gpr(v1_t, ret);
20961 break;
20962 case NM_MULQ_RS_W:
20963 check_dsp_r2(ctx);
20964 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20965 gen_store_gpr(v1_t, ret);
20966 break;
20967 case NM_MULQ_S_W:
20968 check_dsp_r2(ctx);
20969 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20970 gen_store_gpr(v1_t, ret);
20971 break;
20972 case NM_APPEND:
20973 check_dsp_r2(ctx);
20974 gen_load_gpr(t0, rs);
20975 if (rd != 0) {
20976 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20978 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20979 break;
20980 case NM_MODSUB:
20981 check_dsp(ctx);
20982 gen_helper_modsub(v1_t, v1_t, v2_t);
20983 gen_store_gpr(v1_t, ret);
20984 break;
20985 case NM_SHRAV_R_W:
20986 check_dsp(ctx);
20987 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20988 gen_store_gpr(v1_t, ret);
20989 break;
20990 case NM_SHRLV_PH:
20991 check_dsp_r2(ctx);
20992 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20993 gen_store_gpr(v1_t, ret);
20994 break;
20995 case NM_SHRLV_QB:
20996 check_dsp(ctx);
20997 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20998 gen_store_gpr(v1_t, ret);
20999 break;
21000 case NM_SHLLV_QB:
21001 check_dsp(ctx);
21002 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21003 gen_store_gpr(v1_t, ret);
21004 break;
21005 case NM_SHLLV_S_W:
21006 check_dsp(ctx);
21007 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21008 gen_store_gpr(v1_t, ret);
21009 break;
21010 case NM_SHILO:
21011 check_dsp(ctx);
21013 TCGv tv0 = tcg_temp_new();
21014 TCGv tv1 = tcg_temp_new();
21015 int16_t imm = extract32(ctx->opcode, 16, 7);
21017 tcg_gen_movi_tl(tv0, rd >> 3);
21018 tcg_gen_movi_tl(tv1, imm);
21019 gen_helper_shilo(tv0, tv1, cpu_env);
21021 break;
21022 case NM_MULEQ_S_W_PHL:
21023 check_dsp(ctx);
21024 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21025 gen_store_gpr(v1_t, ret);
21026 break;
21027 case NM_MULEQ_S_W_PHR:
21028 check_dsp(ctx);
21029 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21030 gen_store_gpr(v1_t, ret);
21031 break;
21032 case NM_MUL_S_PH:
21033 check_dsp_r2(ctx);
21034 switch (extract32(ctx->opcode, 10, 1)) {
21035 case 0:
21036 /* MUL_PH */
21037 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21038 gen_store_gpr(v1_t, ret);
21039 break;
21040 case 1:
21041 /* MUL_S_PH */
21042 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21043 gen_store_gpr(v1_t, ret);
21044 break;
21046 break;
21047 case NM_PRECR_QB_PH:
21048 check_dsp_r2(ctx);
21049 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21050 gen_store_gpr(v1_t, ret);
21051 break;
21052 case NM_PRECRQ_QB_PH:
21053 check_dsp(ctx);
21054 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21055 gen_store_gpr(v1_t, ret);
21056 break;
21057 case NM_PRECRQ_PH_W:
21058 check_dsp(ctx);
21059 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21060 gen_store_gpr(v1_t, ret);
21061 break;
21062 case NM_PRECRQ_RS_PH_W:
21063 check_dsp(ctx);
21064 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21065 gen_store_gpr(v1_t, ret);
21066 break;
21067 case NM_PRECRQU_S_QB_PH:
21068 check_dsp(ctx);
21069 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21070 gen_store_gpr(v1_t, ret);
21071 break;
21072 case NM_SHRA_R_W:
21073 check_dsp(ctx);
21074 tcg_gen_movi_tl(t0, rd);
21075 gen_helper_shra_r_w(v1_t, t0, v1_t);
21076 gen_store_gpr(v1_t, rt);
21077 break;
21078 case NM_SHRA_R_PH:
21079 check_dsp(ctx);
21080 tcg_gen_movi_tl(t0, rd >> 1);
21081 switch (extract32(ctx->opcode, 10, 1)) {
21082 case 0:
21083 /* SHRA_PH */
21084 gen_helper_shra_ph(v1_t, t0, v1_t);
21085 gen_store_gpr(v1_t, rt);
21086 break;
21087 case 1:
21088 /* SHRA_R_PH */
21089 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21090 gen_store_gpr(v1_t, rt);
21091 break;
21093 break;
21094 case NM_SHLL_S_PH:
21095 check_dsp(ctx);
21096 tcg_gen_movi_tl(t0, rd >> 1);
21097 switch (extract32(ctx->opcode, 10, 2)) {
21098 case 0:
21099 /* SHLL_PH */
21100 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21101 gen_store_gpr(v1_t, rt);
21102 break;
21103 case 2:
21104 /* SHLL_S_PH */
21105 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21106 gen_store_gpr(v1_t, rt);
21107 break;
21108 default:
21109 gen_reserved_instruction(ctx);
21110 break;
21112 break;
21113 case NM_SHLL_S_W:
21114 check_dsp(ctx);
21115 tcg_gen_movi_tl(t0, rd);
21116 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21117 gen_store_gpr(v1_t, rt);
21118 break;
21119 case NM_REPL_PH:
21120 check_dsp(ctx);
21122 int16_t imm;
21123 imm = sextract32(ctx->opcode, 11, 11);
21124 imm = (int16_t)(imm << 6) >> 6;
21125 if (rt != 0) {
21126 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21129 break;
21130 default:
21131 gen_reserved_instruction(ctx);
21132 break;
21136 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21138 uint16_t insn;
21139 uint32_t op;
21140 int rt, rs, rd;
21141 int offset;
21142 int imm;
21144 insn = translator_lduw(env, ctx->base.pc_next + 2);
21145 ctx->opcode = (ctx->opcode << 16) | insn;
21147 rt = extract32(ctx->opcode, 21, 5);
21148 rs = extract32(ctx->opcode, 16, 5);
21149 rd = extract32(ctx->opcode, 11, 5);
21151 op = extract32(ctx->opcode, 26, 6);
21152 switch (op) {
21153 case NM_P_ADDIU:
21154 if (rt == 0) {
21155 /* P.RI */
21156 switch (extract32(ctx->opcode, 19, 2)) {
21157 case NM_SIGRIE:
21158 default:
21159 gen_reserved_instruction(ctx);
21160 break;
21161 case NM_P_SYSCALL:
21162 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21163 generate_exception_end(ctx, EXCP_SYSCALL);
21164 } else {
21165 gen_reserved_instruction(ctx);
21167 break;
21168 case NM_BREAK:
21169 generate_exception_end(ctx, EXCP_BREAK);
21170 break;
21171 case NM_SDBBP:
21172 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21173 gen_helper_do_semihosting(cpu_env);
21174 } else {
21175 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21176 gen_reserved_instruction(ctx);
21177 } else {
21178 generate_exception_end(ctx, EXCP_DBp);
21181 break;
21183 } else {
21184 /* NM_ADDIU */
21185 imm = extract32(ctx->opcode, 0, 16);
21186 if (rs != 0) {
21187 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21188 } else {
21189 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21191 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21193 break;
21194 case NM_ADDIUPC:
21195 if (rt != 0) {
21196 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21197 extract32(ctx->opcode, 1, 20) << 1;
21198 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21199 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21201 break;
21202 case NM_POOL32A:
21203 switch (ctx->opcode & 0x07) {
21204 case NM_POOL32A0:
21205 gen_pool32a0_nanomips_insn(env, ctx);
21206 break;
21207 case NM_POOL32A5:
21209 int32_t op1 = extract32(ctx->opcode, 3, 7);
21210 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21212 break;
21213 case NM_POOL32A7:
21214 switch (extract32(ctx->opcode, 3, 3)) {
21215 case NM_P_LSX:
21216 gen_p_lsx(ctx, rd, rs, rt);
21217 break;
21218 case NM_LSA:
21220 * In nanoMIPS, the shift field directly encodes the shift
21221 * amount, meaning that the supported shift values are in
21222 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21224 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2) - 1);
21225 break;
21226 case NM_EXTW:
21227 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21228 break;
21229 case NM_POOL32AXF:
21230 gen_pool32axf_nanomips_insn(env, ctx);
21231 break;
21232 default:
21233 gen_reserved_instruction(ctx);
21234 break;
21236 break;
21237 default:
21238 gen_reserved_instruction(ctx);
21239 break;
21241 break;
21242 case NM_P_GP_W:
21243 switch (ctx->opcode & 0x03) {
21244 case NM_ADDIUGP_W:
21245 if (rt != 0) {
21246 offset = extract32(ctx->opcode, 0, 21);
21247 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21249 break;
21250 case NM_LWGP:
21251 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21252 break;
21253 case NM_SWGP:
21254 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21255 break;
21256 default:
21257 gen_reserved_instruction(ctx);
21258 break;
21260 break;
21261 case NM_P48I:
21263 insn = translator_lduw(env, ctx->base.pc_next + 4);
21264 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21265 switch (extract32(ctx->opcode, 16, 5)) {
21266 case NM_LI48:
21267 check_nms(ctx);
21268 if (rt != 0) {
21269 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21271 break;
21272 case NM_ADDIU48:
21273 check_nms(ctx);
21274 if (rt != 0) {
21275 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21276 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21278 break;
21279 case NM_ADDIUGP48:
21280 check_nms(ctx);
21281 if (rt != 0) {
21282 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21284 break;
21285 case NM_ADDIUPC48:
21286 check_nms(ctx);
21287 if (rt != 0) {
21288 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21289 addr_off);
21291 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21293 break;
21294 case NM_LWPC48:
21295 check_nms(ctx);
21296 if (rt != 0) {
21297 TCGv t0;
21298 t0 = tcg_temp_new();
21300 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21301 addr_off);
21303 tcg_gen_movi_tl(t0, addr);
21304 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21305 tcg_temp_free(t0);
21307 break;
21308 case NM_SWPC48:
21309 check_nms(ctx);
21311 TCGv t0, t1;
21312 t0 = tcg_temp_new();
21313 t1 = tcg_temp_new();
21315 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21316 addr_off);
21318 tcg_gen_movi_tl(t0, addr);
21319 gen_load_gpr(t1, rt);
21321 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21323 tcg_temp_free(t0);
21324 tcg_temp_free(t1);
21326 break;
21327 default:
21328 gen_reserved_instruction(ctx);
21329 break;
21331 return 6;
21333 case NM_P_U12:
21334 switch (extract32(ctx->opcode, 12, 4)) {
21335 case NM_ORI:
21336 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21337 break;
21338 case NM_XORI:
21339 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21340 break;
21341 case NM_ANDI:
21342 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21343 break;
21344 case NM_P_SR:
21345 switch (extract32(ctx->opcode, 20, 1)) {
21346 case NM_PP_SR:
21347 switch (ctx->opcode & 3) {
21348 case NM_SAVE:
21349 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21350 extract32(ctx->opcode, 2, 1),
21351 extract32(ctx->opcode, 3, 9) << 3);
21352 break;
21353 case NM_RESTORE:
21354 case NM_RESTORE_JRC:
21355 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21356 extract32(ctx->opcode, 2, 1),
21357 extract32(ctx->opcode, 3, 9) << 3);
21358 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21359 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21361 break;
21362 default:
21363 gen_reserved_instruction(ctx);
21364 break;
21366 break;
21367 case NM_P_SR_F:
21368 gen_reserved_instruction(ctx);
21369 break;
21371 break;
21372 case NM_SLTI:
21373 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21374 break;
21375 case NM_SLTIU:
21376 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21377 break;
21378 case NM_SEQI:
21380 TCGv t0 = tcg_temp_new();
21382 imm = extract32(ctx->opcode, 0, 12);
21383 gen_load_gpr(t0, rs);
21384 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21385 gen_store_gpr(t0, rt);
21387 tcg_temp_free(t0);
21389 break;
21390 case NM_ADDIUNEG:
21391 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21392 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21393 break;
21394 case NM_P_SHIFT:
21396 int shift = extract32(ctx->opcode, 0, 5);
21397 switch (extract32(ctx->opcode, 5, 4)) {
21398 case NM_P_SLL:
21399 if (rt == 0 && shift == 0) {
21400 /* NOP */
21401 } else if (rt == 0 && shift == 3) {
21402 /* EHB - treat as NOP */
21403 } else if (rt == 0 && shift == 5) {
21404 /* PAUSE - treat as NOP */
21405 } else if (rt == 0 && shift == 6) {
21406 /* SYNC */
21407 gen_sync(extract32(ctx->opcode, 16, 5));
21408 } else {
21409 /* SLL */
21410 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21411 extract32(ctx->opcode, 0, 5));
21413 break;
21414 case NM_SRL:
21415 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21416 extract32(ctx->opcode, 0, 5));
21417 break;
21418 case NM_SRA:
21419 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21420 extract32(ctx->opcode, 0, 5));
21421 break;
21422 case NM_ROTR:
21423 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21424 extract32(ctx->opcode, 0, 5));
21425 break;
21428 break;
21429 case NM_P_ROTX:
21430 check_nms(ctx);
21431 if (rt != 0) {
21432 TCGv t0 = tcg_temp_new();
21433 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21434 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21435 << 1);
21436 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21438 gen_load_gpr(t0, rs);
21439 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21440 tcg_temp_free(t0);
21442 tcg_temp_free_i32(shift);
21443 tcg_temp_free_i32(shiftx);
21444 tcg_temp_free_i32(stripe);
21446 break;
21447 case NM_P_INS:
21448 switch (((ctx->opcode >> 10) & 2) |
21449 (extract32(ctx->opcode, 5, 1))) {
21450 case NM_INS:
21451 check_nms(ctx);
21452 gen_bitops(ctx, OPC_INS, 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 case NM_P_EXT:
21461 switch (((ctx->opcode >> 10) & 2) |
21462 (extract32(ctx->opcode, 5, 1))) {
21463 case NM_EXT:
21464 check_nms(ctx);
21465 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21466 extract32(ctx->opcode, 6, 5));
21467 break;
21468 default:
21469 gen_reserved_instruction(ctx);
21470 break;
21472 break;
21473 default:
21474 gen_reserved_instruction(ctx);
21475 break;
21477 break;
21478 case NM_POOL32F:
21479 gen_pool32f_nanomips_insn(ctx);
21480 break;
21481 case NM_POOL32S:
21482 break;
21483 case NM_P_LUI:
21484 switch (extract32(ctx->opcode, 1, 1)) {
21485 case NM_LUI:
21486 if (rt != 0) {
21487 tcg_gen_movi_tl(cpu_gpr[rt],
21488 sextract32(ctx->opcode, 0, 1) << 31 |
21489 extract32(ctx->opcode, 2, 10) << 21 |
21490 extract32(ctx->opcode, 12, 9) << 12);
21492 break;
21493 case NM_ALUIPC:
21494 if (rt != 0) {
21495 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21496 extract32(ctx->opcode, 2, 10) << 21 |
21497 extract32(ctx->opcode, 12, 9) << 12;
21498 target_long addr;
21499 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21500 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21502 break;
21504 break;
21505 case NM_P_GP_BH:
21507 uint32_t u = extract32(ctx->opcode, 0, 18);
21509 switch (extract32(ctx->opcode, 18, 3)) {
21510 case NM_LBGP:
21511 gen_ld(ctx, OPC_LB, rt, 28, u);
21512 break;
21513 case NM_SBGP:
21514 gen_st(ctx, OPC_SB, rt, 28, u);
21515 break;
21516 case NM_LBUGP:
21517 gen_ld(ctx, OPC_LBU, rt, 28, u);
21518 break;
21519 case NM_ADDIUGP_B:
21520 if (rt != 0) {
21521 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21523 break;
21524 case NM_P_GP_LH:
21525 u &= ~1;
21526 switch (ctx->opcode & 1) {
21527 case NM_LHGP:
21528 gen_ld(ctx, OPC_LH, rt, 28, u);
21529 break;
21530 case NM_LHUGP:
21531 gen_ld(ctx, OPC_LHU, rt, 28, u);
21532 break;
21534 break;
21535 case NM_P_GP_SH:
21536 u &= ~1;
21537 switch (ctx->opcode & 1) {
21538 case NM_SHGP:
21539 gen_st(ctx, OPC_SH, rt, 28, u);
21540 break;
21541 default:
21542 gen_reserved_instruction(ctx);
21543 break;
21545 break;
21546 case NM_P_GP_CP1:
21547 u &= ~0x3;
21548 switch (ctx->opcode & 0x3) {
21549 case NM_LWC1GP:
21550 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21551 break;
21552 case NM_LDC1GP:
21553 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21554 break;
21555 case NM_SWC1GP:
21556 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21557 break;
21558 case NM_SDC1GP:
21559 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21560 break;
21562 break;
21563 default:
21564 gen_reserved_instruction(ctx);
21565 break;
21568 break;
21569 case NM_P_LS_U12:
21571 uint32_t u = extract32(ctx->opcode, 0, 12);
21573 switch (extract32(ctx->opcode, 12, 4)) {
21574 case NM_P_PREFU12:
21575 if (rt == 31) {
21576 /* SYNCI */
21578 * Break the TB to be able to sync copied instructions
21579 * immediately.
21581 ctx->base.is_jmp = DISAS_STOP;
21582 } else {
21583 /* PREF */
21584 /* Treat as NOP. */
21586 break;
21587 case NM_LB:
21588 gen_ld(ctx, OPC_LB, rt, rs, u);
21589 break;
21590 case NM_LH:
21591 gen_ld(ctx, OPC_LH, rt, rs, u);
21592 break;
21593 case NM_LW:
21594 gen_ld(ctx, OPC_LW, rt, rs, u);
21595 break;
21596 case NM_LBU:
21597 gen_ld(ctx, OPC_LBU, rt, rs, u);
21598 break;
21599 case NM_LHU:
21600 gen_ld(ctx, OPC_LHU, rt, rs, u);
21601 break;
21602 case NM_SB:
21603 gen_st(ctx, OPC_SB, rt, rs, u);
21604 break;
21605 case NM_SH:
21606 gen_st(ctx, OPC_SH, rt, rs, u);
21607 break;
21608 case NM_SW:
21609 gen_st(ctx, OPC_SW, rt, rs, u);
21610 break;
21611 case NM_LWC1:
21612 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21613 break;
21614 case NM_LDC1:
21615 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21616 break;
21617 case NM_SWC1:
21618 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21619 break;
21620 case NM_SDC1:
21621 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21622 break;
21623 default:
21624 gen_reserved_instruction(ctx);
21625 break;
21628 break;
21629 case NM_P_LS_S9:
21631 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21632 extract32(ctx->opcode, 0, 8);
21634 switch (extract32(ctx->opcode, 8, 3)) {
21635 case NM_P_LS_S0:
21636 switch (extract32(ctx->opcode, 11, 4)) {
21637 case NM_LBS9:
21638 gen_ld(ctx, OPC_LB, rt, rs, s);
21639 break;
21640 case NM_LHS9:
21641 gen_ld(ctx, OPC_LH, rt, rs, s);
21642 break;
21643 case NM_LWS9:
21644 gen_ld(ctx, OPC_LW, rt, rs, s);
21645 break;
21646 case NM_LBUS9:
21647 gen_ld(ctx, OPC_LBU, rt, rs, s);
21648 break;
21649 case NM_LHUS9:
21650 gen_ld(ctx, OPC_LHU, rt, rs, s);
21651 break;
21652 case NM_SBS9:
21653 gen_st(ctx, OPC_SB, rt, rs, s);
21654 break;
21655 case NM_SHS9:
21656 gen_st(ctx, OPC_SH, rt, rs, s);
21657 break;
21658 case NM_SWS9:
21659 gen_st(ctx, OPC_SW, rt, rs, s);
21660 break;
21661 case NM_LWC1S9:
21662 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21663 break;
21664 case NM_LDC1S9:
21665 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21666 break;
21667 case NM_SWC1S9:
21668 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21669 break;
21670 case NM_SDC1S9:
21671 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21672 break;
21673 case NM_P_PREFS9:
21674 if (rt == 31) {
21675 /* SYNCI */
21677 * Break the TB to be able to sync copied instructions
21678 * immediately.
21680 ctx->base.is_jmp = DISAS_STOP;
21681 } else {
21682 /* PREF */
21683 /* Treat as NOP. */
21685 break;
21686 default:
21687 gen_reserved_instruction(ctx);
21688 break;
21690 break;
21691 case NM_P_LS_S1:
21692 switch (extract32(ctx->opcode, 11, 4)) {
21693 case NM_UALH:
21694 case NM_UASH:
21695 check_nms(ctx);
21697 TCGv t0 = tcg_temp_new();
21698 TCGv t1 = tcg_temp_new();
21700 gen_base_offset_addr(ctx, t0, rs, s);
21702 switch (extract32(ctx->opcode, 11, 4)) {
21703 case NM_UALH:
21704 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21705 MO_UNALN);
21706 gen_store_gpr(t0, rt);
21707 break;
21708 case NM_UASH:
21709 gen_load_gpr(t1, rt);
21710 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21711 MO_UNALN);
21712 break;
21714 tcg_temp_free(t0);
21715 tcg_temp_free(t1);
21717 break;
21718 case NM_P_LL:
21719 switch (ctx->opcode & 0x03) {
21720 case NM_LL:
21721 gen_ld(ctx, OPC_LL, rt, rs, s);
21722 break;
21723 case NM_LLWP:
21724 check_xnp(ctx);
21725 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21726 break;
21728 break;
21729 case NM_P_SC:
21730 switch (ctx->opcode & 0x03) {
21731 case NM_SC:
21732 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21733 break;
21734 case NM_SCWP:
21735 check_xnp(ctx);
21736 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21737 false);
21738 break;
21740 break;
21741 case NM_CACHE:
21742 check_cp0_enabled(ctx);
21743 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21744 gen_cache_operation(ctx, rt, rs, s);
21746 break;
21748 break;
21749 case NM_P_LS_E0:
21750 switch (extract32(ctx->opcode, 11, 4)) {
21751 case NM_LBE:
21752 check_eva(ctx);
21753 check_cp0_enabled(ctx);
21754 gen_ld(ctx, OPC_LBE, rt, rs, s);
21755 break;
21756 case NM_SBE:
21757 check_eva(ctx);
21758 check_cp0_enabled(ctx);
21759 gen_st(ctx, OPC_SBE, rt, rs, s);
21760 break;
21761 case NM_LBUE:
21762 check_eva(ctx);
21763 check_cp0_enabled(ctx);
21764 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21765 break;
21766 case NM_P_PREFE:
21767 if (rt == 31) {
21768 /* case NM_SYNCIE */
21769 check_eva(ctx);
21770 check_cp0_enabled(ctx);
21772 * Break the TB to be able to sync copied instructions
21773 * immediately.
21775 ctx->base.is_jmp = DISAS_STOP;
21776 } else {
21777 /* case NM_PREFE */
21778 check_eva(ctx);
21779 check_cp0_enabled(ctx);
21780 /* Treat as NOP. */
21782 break;
21783 case NM_LHE:
21784 check_eva(ctx);
21785 check_cp0_enabled(ctx);
21786 gen_ld(ctx, OPC_LHE, rt, rs, s);
21787 break;
21788 case NM_SHE:
21789 check_eva(ctx);
21790 check_cp0_enabled(ctx);
21791 gen_st(ctx, OPC_SHE, rt, rs, s);
21792 break;
21793 case NM_LHUE:
21794 check_eva(ctx);
21795 check_cp0_enabled(ctx);
21796 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21797 break;
21798 case NM_CACHEE:
21799 check_nms_dl_il_sl_tl_l2c(ctx);
21800 gen_cache_operation(ctx, rt, rs, s);
21801 break;
21802 case NM_LWE:
21803 check_eva(ctx);
21804 check_cp0_enabled(ctx);
21805 gen_ld(ctx, OPC_LWE, rt, rs, s);
21806 break;
21807 case NM_SWE:
21808 check_eva(ctx);
21809 check_cp0_enabled(ctx);
21810 gen_st(ctx, OPC_SWE, rt, rs, s);
21811 break;
21812 case NM_P_LLE:
21813 switch (extract32(ctx->opcode, 2, 2)) {
21814 case NM_LLE:
21815 check_xnp(ctx);
21816 check_eva(ctx);
21817 check_cp0_enabled(ctx);
21818 gen_ld(ctx, OPC_LLE, rt, rs, s);
21819 break;
21820 case NM_LLWPE:
21821 check_xnp(ctx);
21822 check_eva(ctx);
21823 check_cp0_enabled(ctx);
21824 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21825 break;
21826 default:
21827 gen_reserved_instruction(ctx);
21828 break;
21830 break;
21831 case NM_P_SCE:
21832 switch (extract32(ctx->opcode, 2, 2)) {
21833 case NM_SCE:
21834 check_xnp(ctx);
21835 check_eva(ctx);
21836 check_cp0_enabled(ctx);
21837 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
21838 break;
21839 case NM_SCWPE:
21840 check_xnp(ctx);
21841 check_eva(ctx);
21842 check_cp0_enabled(ctx);
21843 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21844 true);
21845 break;
21846 default:
21847 gen_reserved_instruction(ctx);
21848 break;
21850 break;
21852 break;
21853 case NM_P_LS_WM:
21854 case NM_P_LS_UAWM:
21855 check_nms(ctx);
21857 int count = extract32(ctx->opcode, 12, 3);
21858 int counter = 0;
21860 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21861 extract32(ctx->opcode, 0, 8);
21862 TCGv va = tcg_temp_new();
21863 TCGv t1 = tcg_temp_new();
21864 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21865 NM_P_LS_UAWM ? MO_UNALN : 0;
21867 count = (count == 0) ? 8 : count;
21868 while (counter != count) {
21869 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21870 int this_offset = offset + (counter << 2);
21872 gen_base_offset_addr(ctx, va, rs, this_offset);
21874 switch (extract32(ctx->opcode, 11, 1)) {
21875 case NM_LWM:
21876 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21877 memop | MO_TESL);
21878 gen_store_gpr(t1, this_rt);
21879 if ((this_rt == rs) &&
21880 (counter != (count - 1))) {
21881 /* UNPREDICTABLE */
21883 break;
21884 case NM_SWM:
21885 this_rt = (rt == 0) ? 0 : this_rt;
21886 gen_load_gpr(t1, this_rt);
21887 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21888 memop | MO_TEUL);
21889 break;
21891 counter++;
21893 tcg_temp_free(va);
21894 tcg_temp_free(t1);
21896 break;
21897 default:
21898 gen_reserved_instruction(ctx);
21899 break;
21902 break;
21903 case NM_MOVE_BALC:
21904 check_nms(ctx);
21906 TCGv t0 = tcg_temp_new();
21907 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21908 extract32(ctx->opcode, 1, 20) << 1;
21909 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21910 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21911 extract32(ctx->opcode, 21, 3));
21912 gen_load_gpr(t0, rt);
21913 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21914 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21915 tcg_temp_free(t0);
21917 break;
21918 case NM_P_BAL:
21920 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21921 extract32(ctx->opcode, 1, 24) << 1;
21923 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21924 /* BC */
21925 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21926 } else {
21927 /* BALC */
21928 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21931 break;
21932 case NM_P_J:
21933 switch (extract32(ctx->opcode, 12, 4)) {
21934 case NM_JALRC:
21935 case NM_JALRC_HB:
21936 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21937 break;
21938 case NM_P_BALRSC:
21939 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21940 break;
21941 default:
21942 gen_reserved_instruction(ctx);
21943 break;
21945 break;
21946 case NM_P_BR1:
21948 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21949 extract32(ctx->opcode, 1, 13) << 1;
21950 switch (extract32(ctx->opcode, 14, 2)) {
21951 case NM_BEQC:
21952 check_nms(ctx);
21953 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21954 break;
21955 case NM_P_BR3A:
21956 s = sextract32(ctx->opcode, 0, 1) << 14 |
21957 extract32(ctx->opcode, 1, 13) << 1;
21958 check_cp1_enabled(ctx);
21959 switch (extract32(ctx->opcode, 16, 5)) {
21960 case NM_BC1EQZC:
21961 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21962 break;
21963 case NM_BC1NEZC:
21964 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21965 break;
21966 case NM_BPOSGE32C:
21967 check_dsp_r3(ctx);
21969 int32_t imm = extract32(ctx->opcode, 1, 13) |
21970 extract32(ctx->opcode, 0, 1) << 13;
21972 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21973 imm);
21975 break;
21976 default:
21977 gen_reserved_instruction(ctx);
21978 break;
21980 break;
21981 case NM_BGEC:
21982 if (rs == rt) {
21983 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21984 } else {
21985 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21987 break;
21988 case NM_BGEUC:
21989 if (rs == rt || rt == 0) {
21990 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21991 } else if (rs == 0) {
21992 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21993 } else {
21994 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21996 break;
21999 break;
22000 case NM_P_BR2:
22002 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22003 extract32(ctx->opcode, 1, 13) << 1;
22004 switch (extract32(ctx->opcode, 14, 2)) {
22005 case NM_BNEC:
22006 check_nms(ctx);
22007 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22008 break;
22009 case NM_BLTC:
22010 if (rs != 0 && rt != 0 && rs == rt) {
22011 /* NOP */
22012 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22013 } else {
22014 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22016 break;
22017 case NM_BLTUC:
22018 if (rs == 0 || rs == rt) {
22019 /* NOP */
22020 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22021 } else {
22022 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22024 break;
22025 default:
22026 gen_reserved_instruction(ctx);
22027 break;
22030 break;
22031 case NM_P_BRI:
22033 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22034 extract32(ctx->opcode, 1, 10) << 1;
22035 uint32_t u = extract32(ctx->opcode, 11, 7);
22037 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22038 rt, u, s);
22040 break;
22041 default:
22042 gen_reserved_instruction(ctx);
22043 break;
22045 return 4;
22048 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22050 uint32_t op;
22051 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22052 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22053 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22054 int offset;
22055 int imm;
22057 /* make sure instructions are on a halfword boundary */
22058 if (ctx->base.pc_next & 0x1) {
22059 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22060 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22061 tcg_temp_free(tmp);
22062 generate_exception_end(ctx, EXCP_AdEL);
22063 return 2;
22066 op = extract32(ctx->opcode, 10, 6);
22067 switch (op) {
22068 case NM_P16_MV:
22069 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22070 if (rt != 0) {
22071 /* MOVE */
22072 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22073 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22074 } else {
22075 /* P16.RI */
22076 switch (extract32(ctx->opcode, 3, 2)) {
22077 case NM_P16_SYSCALL:
22078 if (extract32(ctx->opcode, 2, 1) == 0) {
22079 generate_exception_end(ctx, EXCP_SYSCALL);
22080 } else {
22081 gen_reserved_instruction(ctx);
22083 break;
22084 case NM_BREAK16:
22085 generate_exception_end(ctx, EXCP_BREAK);
22086 break;
22087 case NM_SDBBP16:
22088 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22089 gen_helper_do_semihosting(cpu_env);
22090 } else {
22091 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22092 gen_reserved_instruction(ctx);
22093 } else {
22094 generate_exception_end(ctx, EXCP_DBp);
22097 break;
22098 default:
22099 gen_reserved_instruction(ctx);
22100 break;
22103 break;
22104 case NM_P16_SHIFT:
22106 int shift = extract32(ctx->opcode, 0, 3);
22107 uint32_t opc = 0;
22108 shift = (shift == 0) ? 8 : shift;
22110 switch (extract32(ctx->opcode, 3, 1)) {
22111 case NM_SLL16:
22112 opc = OPC_SLL;
22113 break;
22114 case NM_SRL16:
22115 opc = OPC_SRL;
22116 break;
22118 gen_shift_imm(ctx, opc, rt, rs, shift);
22120 break;
22121 case NM_P16C:
22122 switch (ctx->opcode & 1) {
22123 case NM_POOL16C_0:
22124 gen_pool16c_nanomips_insn(ctx);
22125 break;
22126 case NM_LWXS16:
22127 gen_ldxs(ctx, rt, rs, rd);
22128 break;
22130 break;
22131 case NM_P16_A1:
22132 switch (extract32(ctx->opcode, 6, 1)) {
22133 case NM_ADDIUR1SP:
22134 imm = extract32(ctx->opcode, 0, 6) << 2;
22135 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22136 break;
22137 default:
22138 gen_reserved_instruction(ctx);
22139 break;
22141 break;
22142 case NM_P16_A2:
22143 switch (extract32(ctx->opcode, 3, 1)) {
22144 case NM_ADDIUR2:
22145 imm = extract32(ctx->opcode, 0, 3) << 2;
22146 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22147 break;
22148 case NM_P_ADDIURS5:
22149 rt = extract32(ctx->opcode, 5, 5);
22150 if (rt != 0) {
22151 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22152 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22153 (extract32(ctx->opcode, 0, 3));
22154 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22156 break;
22158 break;
22159 case NM_P16_ADDU:
22160 switch (ctx->opcode & 0x1) {
22161 case NM_ADDU16:
22162 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22163 break;
22164 case NM_SUBU16:
22165 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22166 break;
22168 break;
22169 case NM_P16_4X4:
22170 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22171 extract32(ctx->opcode, 5, 3);
22172 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22173 extract32(ctx->opcode, 0, 3);
22174 rt = decode_gpr_gpr4(rt);
22175 rs = decode_gpr_gpr4(rs);
22176 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22177 (extract32(ctx->opcode, 3, 1))) {
22178 case NM_ADDU4X4:
22179 check_nms(ctx);
22180 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22181 break;
22182 case NM_MUL4X4:
22183 check_nms(ctx);
22184 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22185 break;
22186 default:
22187 gen_reserved_instruction(ctx);
22188 break;
22190 break;
22191 case NM_LI16:
22193 int imm = extract32(ctx->opcode, 0, 7);
22194 imm = (imm == 0x7f ? -1 : imm);
22195 if (rt != 0) {
22196 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22199 break;
22200 case NM_ANDI16:
22202 uint32_t u = extract32(ctx->opcode, 0, 4);
22203 u = (u == 12) ? 0xff :
22204 (u == 13) ? 0xffff : u;
22205 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22207 break;
22208 case NM_P16_LB:
22209 offset = extract32(ctx->opcode, 0, 2);
22210 switch (extract32(ctx->opcode, 2, 2)) {
22211 case NM_LB16:
22212 gen_ld(ctx, OPC_LB, rt, rs, offset);
22213 break;
22214 case NM_SB16:
22215 rt = decode_gpr_gpr3_src_store(
22216 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22217 gen_st(ctx, OPC_SB, rt, rs, offset);
22218 break;
22219 case NM_LBU16:
22220 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22221 break;
22222 default:
22223 gen_reserved_instruction(ctx);
22224 break;
22226 break;
22227 case NM_P16_LH:
22228 offset = extract32(ctx->opcode, 1, 2) << 1;
22229 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22230 case NM_LH16:
22231 gen_ld(ctx, OPC_LH, rt, rs, offset);
22232 break;
22233 case NM_SH16:
22234 rt = decode_gpr_gpr3_src_store(
22235 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22236 gen_st(ctx, OPC_SH, rt, rs, offset);
22237 break;
22238 case NM_LHU16:
22239 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22240 break;
22241 default:
22242 gen_reserved_instruction(ctx);
22243 break;
22245 break;
22246 case NM_LW16:
22247 offset = extract32(ctx->opcode, 0, 4) << 2;
22248 gen_ld(ctx, OPC_LW, rt, rs, offset);
22249 break;
22250 case NM_LWSP16:
22251 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22252 offset = extract32(ctx->opcode, 0, 5) << 2;
22253 gen_ld(ctx, OPC_LW, rt, 29, offset);
22254 break;
22255 case NM_LW4X4:
22256 check_nms(ctx);
22257 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22258 extract32(ctx->opcode, 5, 3);
22259 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22260 extract32(ctx->opcode, 0, 3);
22261 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22262 (extract32(ctx->opcode, 8, 1) << 2);
22263 rt = decode_gpr_gpr4(rt);
22264 rs = decode_gpr_gpr4(rs);
22265 gen_ld(ctx, OPC_LW, rt, rs, offset);
22266 break;
22267 case NM_SW4X4:
22268 check_nms(ctx);
22269 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22270 extract32(ctx->opcode, 5, 3);
22271 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22272 extract32(ctx->opcode, 0, 3);
22273 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22274 (extract32(ctx->opcode, 8, 1) << 2);
22275 rt = decode_gpr_gpr4_zero(rt);
22276 rs = decode_gpr_gpr4(rs);
22277 gen_st(ctx, OPC_SW, rt, rs, offset);
22278 break;
22279 case NM_LWGP16:
22280 offset = extract32(ctx->opcode, 0, 7) << 2;
22281 gen_ld(ctx, OPC_LW, rt, 28, offset);
22282 break;
22283 case NM_SWSP16:
22284 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22285 offset = extract32(ctx->opcode, 0, 5) << 2;
22286 gen_st(ctx, OPC_SW, rt, 29, offset);
22287 break;
22288 case NM_SW16:
22289 rt = decode_gpr_gpr3_src_store(
22290 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22291 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22292 offset = extract32(ctx->opcode, 0, 4) << 2;
22293 gen_st(ctx, OPC_SW, rt, rs, offset);
22294 break;
22295 case NM_SWGP16:
22296 rt = decode_gpr_gpr3_src_store(
22297 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22298 offset = extract32(ctx->opcode, 0, 7) << 2;
22299 gen_st(ctx, OPC_SW, rt, 28, offset);
22300 break;
22301 case NM_BC16:
22302 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22303 (sextract32(ctx->opcode, 0, 1) << 10) |
22304 (extract32(ctx->opcode, 1, 9) << 1));
22305 break;
22306 case NM_BALC16:
22307 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22308 (sextract32(ctx->opcode, 0, 1) << 10) |
22309 (extract32(ctx->opcode, 1, 9) << 1));
22310 break;
22311 case NM_BEQZC16:
22312 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22313 (sextract32(ctx->opcode, 0, 1) << 7) |
22314 (extract32(ctx->opcode, 1, 6) << 1));
22315 break;
22316 case NM_BNEZC16:
22317 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22318 (sextract32(ctx->opcode, 0, 1) << 7) |
22319 (extract32(ctx->opcode, 1, 6) << 1));
22320 break;
22321 case NM_P16_BR:
22322 switch (ctx->opcode & 0xf) {
22323 case 0:
22324 /* P16.JRC */
22325 switch (extract32(ctx->opcode, 4, 1)) {
22326 case NM_JRC:
22327 gen_compute_branch_nm(ctx, OPC_JR, 2,
22328 extract32(ctx->opcode, 5, 5), 0, 0);
22329 break;
22330 case NM_JALRC16:
22331 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22332 extract32(ctx->opcode, 5, 5), 31, 0);
22333 break;
22335 break;
22336 default:
22338 /* P16.BRI */
22339 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22340 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22341 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22342 extract32(ctx->opcode, 0, 4) << 1);
22344 break;
22346 break;
22347 case NM_P16_SR:
22349 int count = extract32(ctx->opcode, 0, 4);
22350 int u = extract32(ctx->opcode, 4, 4) << 4;
22352 rt = 30 + extract32(ctx->opcode, 9, 1);
22353 switch (extract32(ctx->opcode, 8, 1)) {
22354 case NM_SAVE16:
22355 gen_save(ctx, rt, count, 0, u);
22356 break;
22357 case NM_RESTORE_JRC16:
22358 gen_restore(ctx, rt, count, 0, u);
22359 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22360 break;
22363 break;
22364 case NM_MOVEP:
22365 case NM_MOVEPREV:
22366 check_nms(ctx);
22368 static const int gpr2reg1[] = {4, 5, 6, 7};
22369 static const int gpr2reg2[] = {5, 6, 7, 8};
22370 int re;
22371 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22372 extract32(ctx->opcode, 8, 1);
22373 int r1 = gpr2reg1[rd2];
22374 int r2 = gpr2reg2[rd2];
22375 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22376 extract32(ctx->opcode, 0, 3);
22377 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22378 extract32(ctx->opcode, 5, 3);
22379 TCGv t0 = tcg_temp_new();
22380 TCGv t1 = tcg_temp_new();
22381 if (op == NM_MOVEP) {
22382 rd = r1;
22383 re = r2;
22384 rs = decode_gpr_gpr4_zero(r3);
22385 rt = decode_gpr_gpr4_zero(r4);
22386 } else {
22387 rd = decode_gpr_gpr4(r3);
22388 re = decode_gpr_gpr4(r4);
22389 rs = r1;
22390 rt = r2;
22392 gen_load_gpr(t0, rs);
22393 gen_load_gpr(t1, rt);
22394 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22395 tcg_gen_mov_tl(cpu_gpr[re], t1);
22396 tcg_temp_free(t0);
22397 tcg_temp_free(t1);
22399 break;
22400 default:
22401 return decode_nanomips_32_48_opc(env, ctx);
22404 return 2;
22408 /* SmartMIPS extension to MIPS32 */
22410 #if defined(TARGET_MIPS64)
22412 /* MDMX extension to MIPS64 */
22414 #endif
22416 /* MIPSDSP functions. */
22417 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22418 int rd, int base, int offset)
22420 TCGv t0;
22422 check_dsp(ctx);
22423 t0 = tcg_temp_new();
22425 if (base == 0) {
22426 gen_load_gpr(t0, offset);
22427 } else if (offset == 0) {
22428 gen_load_gpr(t0, base);
22429 } else {
22430 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22433 switch (opc) {
22434 case OPC_LBUX:
22435 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22436 gen_store_gpr(t0, rd);
22437 break;
22438 case OPC_LHX:
22439 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22440 gen_store_gpr(t0, rd);
22441 break;
22442 case OPC_LWX:
22443 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22444 gen_store_gpr(t0, rd);
22445 break;
22446 #if defined(TARGET_MIPS64)
22447 case OPC_LDX:
22448 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22449 gen_store_gpr(t0, rd);
22450 break;
22451 #endif
22453 tcg_temp_free(t0);
22456 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22457 int ret, int v1, int v2)
22459 TCGv v1_t;
22460 TCGv v2_t;
22462 if (ret == 0) {
22463 /* Treat as NOP. */
22464 return;
22467 v1_t = tcg_temp_new();
22468 v2_t = tcg_temp_new();
22470 gen_load_gpr(v1_t, v1);
22471 gen_load_gpr(v2_t, v2);
22473 switch (op1) {
22474 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22475 case OPC_MULT_G_2E:
22476 check_dsp_r2(ctx);
22477 switch (op2) {
22478 case OPC_ADDUH_QB:
22479 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22480 break;
22481 case OPC_ADDUH_R_QB:
22482 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22483 break;
22484 case OPC_ADDQH_PH:
22485 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22486 break;
22487 case OPC_ADDQH_R_PH:
22488 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22489 break;
22490 case OPC_ADDQH_W:
22491 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22492 break;
22493 case OPC_ADDQH_R_W:
22494 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22495 break;
22496 case OPC_SUBUH_QB:
22497 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22498 break;
22499 case OPC_SUBUH_R_QB:
22500 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22501 break;
22502 case OPC_SUBQH_PH:
22503 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22504 break;
22505 case OPC_SUBQH_R_PH:
22506 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22507 break;
22508 case OPC_SUBQH_W:
22509 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22510 break;
22511 case OPC_SUBQH_R_W:
22512 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22513 break;
22515 break;
22516 case OPC_ABSQ_S_PH_DSP:
22517 switch (op2) {
22518 case OPC_ABSQ_S_QB:
22519 check_dsp_r2(ctx);
22520 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22521 break;
22522 case OPC_ABSQ_S_PH:
22523 check_dsp(ctx);
22524 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22525 break;
22526 case OPC_ABSQ_S_W:
22527 check_dsp(ctx);
22528 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22529 break;
22530 case OPC_PRECEQ_W_PHL:
22531 check_dsp(ctx);
22532 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22533 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22534 break;
22535 case OPC_PRECEQ_W_PHR:
22536 check_dsp(ctx);
22537 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22538 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22539 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22540 break;
22541 case OPC_PRECEQU_PH_QBL:
22542 check_dsp(ctx);
22543 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22544 break;
22545 case OPC_PRECEQU_PH_QBR:
22546 check_dsp(ctx);
22547 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22548 break;
22549 case OPC_PRECEQU_PH_QBLA:
22550 check_dsp(ctx);
22551 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22552 break;
22553 case OPC_PRECEQU_PH_QBRA:
22554 check_dsp(ctx);
22555 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22556 break;
22557 case OPC_PRECEU_PH_QBL:
22558 check_dsp(ctx);
22559 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22560 break;
22561 case OPC_PRECEU_PH_QBR:
22562 check_dsp(ctx);
22563 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22564 break;
22565 case OPC_PRECEU_PH_QBLA:
22566 check_dsp(ctx);
22567 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22568 break;
22569 case OPC_PRECEU_PH_QBRA:
22570 check_dsp(ctx);
22571 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22572 break;
22574 break;
22575 case OPC_ADDU_QB_DSP:
22576 switch (op2) {
22577 case OPC_ADDQ_PH:
22578 check_dsp(ctx);
22579 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22580 break;
22581 case OPC_ADDQ_S_PH:
22582 check_dsp(ctx);
22583 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22584 break;
22585 case OPC_ADDQ_S_W:
22586 check_dsp(ctx);
22587 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22588 break;
22589 case OPC_ADDU_QB:
22590 check_dsp(ctx);
22591 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22592 break;
22593 case OPC_ADDU_S_QB:
22594 check_dsp(ctx);
22595 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22596 break;
22597 case OPC_ADDU_PH:
22598 check_dsp_r2(ctx);
22599 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22600 break;
22601 case OPC_ADDU_S_PH:
22602 check_dsp_r2(ctx);
22603 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22604 break;
22605 case OPC_SUBQ_PH:
22606 check_dsp(ctx);
22607 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22608 break;
22609 case OPC_SUBQ_S_PH:
22610 check_dsp(ctx);
22611 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22612 break;
22613 case OPC_SUBQ_S_W:
22614 check_dsp(ctx);
22615 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22616 break;
22617 case OPC_SUBU_QB:
22618 check_dsp(ctx);
22619 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22620 break;
22621 case OPC_SUBU_S_QB:
22622 check_dsp(ctx);
22623 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22624 break;
22625 case OPC_SUBU_PH:
22626 check_dsp_r2(ctx);
22627 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22628 break;
22629 case OPC_SUBU_S_PH:
22630 check_dsp_r2(ctx);
22631 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22632 break;
22633 case OPC_ADDSC:
22634 check_dsp(ctx);
22635 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22636 break;
22637 case OPC_ADDWC:
22638 check_dsp(ctx);
22639 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22640 break;
22641 case OPC_MODSUB:
22642 check_dsp(ctx);
22643 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22644 break;
22645 case OPC_RADDU_W_QB:
22646 check_dsp(ctx);
22647 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22648 break;
22650 break;
22651 case OPC_CMPU_EQ_QB_DSP:
22652 switch (op2) {
22653 case OPC_PRECR_QB_PH:
22654 check_dsp_r2(ctx);
22655 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22656 break;
22657 case OPC_PRECRQ_QB_PH:
22658 check_dsp(ctx);
22659 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22660 break;
22661 case OPC_PRECR_SRA_PH_W:
22662 check_dsp_r2(ctx);
22664 TCGv_i32 sa_t = tcg_const_i32(v2);
22665 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22666 cpu_gpr[ret]);
22667 tcg_temp_free_i32(sa_t);
22668 break;
22670 case OPC_PRECR_SRA_R_PH_W:
22671 check_dsp_r2(ctx);
22673 TCGv_i32 sa_t = tcg_const_i32(v2);
22674 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22675 cpu_gpr[ret]);
22676 tcg_temp_free_i32(sa_t);
22677 break;
22679 case OPC_PRECRQ_PH_W:
22680 check_dsp(ctx);
22681 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22682 break;
22683 case OPC_PRECRQ_RS_PH_W:
22684 check_dsp(ctx);
22685 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22686 break;
22687 case OPC_PRECRQU_S_QB_PH:
22688 check_dsp(ctx);
22689 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22690 break;
22692 break;
22693 #ifdef TARGET_MIPS64
22694 case OPC_ABSQ_S_QH_DSP:
22695 switch (op2) {
22696 case OPC_PRECEQ_L_PWL:
22697 check_dsp(ctx);
22698 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22699 break;
22700 case OPC_PRECEQ_L_PWR:
22701 check_dsp(ctx);
22702 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22703 break;
22704 case OPC_PRECEQ_PW_QHL:
22705 check_dsp(ctx);
22706 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22707 break;
22708 case OPC_PRECEQ_PW_QHR:
22709 check_dsp(ctx);
22710 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22711 break;
22712 case OPC_PRECEQ_PW_QHLA:
22713 check_dsp(ctx);
22714 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22715 break;
22716 case OPC_PRECEQ_PW_QHRA:
22717 check_dsp(ctx);
22718 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22719 break;
22720 case OPC_PRECEQU_QH_OBL:
22721 check_dsp(ctx);
22722 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22723 break;
22724 case OPC_PRECEQU_QH_OBR:
22725 check_dsp(ctx);
22726 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22727 break;
22728 case OPC_PRECEQU_QH_OBLA:
22729 check_dsp(ctx);
22730 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22731 break;
22732 case OPC_PRECEQU_QH_OBRA:
22733 check_dsp(ctx);
22734 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22735 break;
22736 case OPC_PRECEU_QH_OBL:
22737 check_dsp(ctx);
22738 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22739 break;
22740 case OPC_PRECEU_QH_OBR:
22741 check_dsp(ctx);
22742 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22743 break;
22744 case OPC_PRECEU_QH_OBLA:
22745 check_dsp(ctx);
22746 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22747 break;
22748 case OPC_PRECEU_QH_OBRA:
22749 check_dsp(ctx);
22750 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22751 break;
22752 case OPC_ABSQ_S_OB:
22753 check_dsp_r2(ctx);
22754 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22755 break;
22756 case OPC_ABSQ_S_PW:
22757 check_dsp(ctx);
22758 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22759 break;
22760 case OPC_ABSQ_S_QH:
22761 check_dsp(ctx);
22762 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22763 break;
22765 break;
22766 case OPC_ADDU_OB_DSP:
22767 switch (op2) {
22768 case OPC_RADDU_L_OB:
22769 check_dsp(ctx);
22770 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22771 break;
22772 case OPC_SUBQ_PW:
22773 check_dsp(ctx);
22774 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22775 break;
22776 case OPC_SUBQ_S_PW:
22777 check_dsp(ctx);
22778 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22779 break;
22780 case OPC_SUBQ_QH:
22781 check_dsp(ctx);
22782 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22783 break;
22784 case OPC_SUBQ_S_QH:
22785 check_dsp(ctx);
22786 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22787 break;
22788 case OPC_SUBU_OB:
22789 check_dsp(ctx);
22790 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22791 break;
22792 case OPC_SUBU_S_OB:
22793 check_dsp(ctx);
22794 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22795 break;
22796 case OPC_SUBU_QH:
22797 check_dsp_r2(ctx);
22798 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22799 break;
22800 case OPC_SUBU_S_QH:
22801 check_dsp_r2(ctx);
22802 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22803 break;
22804 case OPC_SUBUH_OB:
22805 check_dsp_r2(ctx);
22806 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22807 break;
22808 case OPC_SUBUH_R_OB:
22809 check_dsp_r2(ctx);
22810 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22811 break;
22812 case OPC_ADDQ_PW:
22813 check_dsp(ctx);
22814 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22815 break;
22816 case OPC_ADDQ_S_PW:
22817 check_dsp(ctx);
22818 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22819 break;
22820 case OPC_ADDQ_QH:
22821 check_dsp(ctx);
22822 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22823 break;
22824 case OPC_ADDQ_S_QH:
22825 check_dsp(ctx);
22826 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22827 break;
22828 case OPC_ADDU_OB:
22829 check_dsp(ctx);
22830 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22831 break;
22832 case OPC_ADDU_S_OB:
22833 check_dsp(ctx);
22834 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22835 break;
22836 case OPC_ADDU_QH:
22837 check_dsp_r2(ctx);
22838 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22839 break;
22840 case OPC_ADDU_S_QH:
22841 check_dsp_r2(ctx);
22842 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22843 break;
22844 case OPC_ADDUH_OB:
22845 check_dsp_r2(ctx);
22846 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22847 break;
22848 case OPC_ADDUH_R_OB:
22849 check_dsp_r2(ctx);
22850 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22851 break;
22853 break;
22854 case OPC_CMPU_EQ_OB_DSP:
22855 switch (op2) {
22856 case OPC_PRECR_OB_QH:
22857 check_dsp_r2(ctx);
22858 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22859 break;
22860 case OPC_PRECR_SRA_QH_PW:
22861 check_dsp_r2(ctx);
22863 TCGv_i32 ret_t = tcg_const_i32(ret);
22864 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22865 tcg_temp_free_i32(ret_t);
22866 break;
22868 case OPC_PRECR_SRA_R_QH_PW:
22869 check_dsp_r2(ctx);
22871 TCGv_i32 sa_v = tcg_const_i32(ret);
22872 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22873 tcg_temp_free_i32(sa_v);
22874 break;
22876 case OPC_PRECRQ_OB_QH:
22877 check_dsp(ctx);
22878 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22879 break;
22880 case OPC_PRECRQ_PW_L:
22881 check_dsp(ctx);
22882 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22883 break;
22884 case OPC_PRECRQ_QH_PW:
22885 check_dsp(ctx);
22886 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22887 break;
22888 case OPC_PRECRQ_RS_QH_PW:
22889 check_dsp(ctx);
22890 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22891 break;
22892 case OPC_PRECRQU_S_OB_QH:
22893 check_dsp(ctx);
22894 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22895 break;
22897 break;
22898 #endif
22901 tcg_temp_free(v1_t);
22902 tcg_temp_free(v2_t);
22905 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22906 int ret, int v1, int v2)
22908 uint32_t op2;
22909 TCGv t0;
22910 TCGv v1_t;
22911 TCGv v2_t;
22913 if (ret == 0) {
22914 /* Treat as NOP. */
22915 return;
22918 t0 = tcg_temp_new();
22919 v1_t = tcg_temp_new();
22920 v2_t = tcg_temp_new();
22922 tcg_gen_movi_tl(t0, v1);
22923 gen_load_gpr(v1_t, v1);
22924 gen_load_gpr(v2_t, v2);
22926 switch (opc) {
22927 case OPC_SHLL_QB_DSP:
22929 op2 = MASK_SHLL_QB(ctx->opcode);
22930 switch (op2) {
22931 case OPC_SHLL_QB:
22932 check_dsp(ctx);
22933 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22934 break;
22935 case OPC_SHLLV_QB:
22936 check_dsp(ctx);
22937 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22938 break;
22939 case OPC_SHLL_PH:
22940 check_dsp(ctx);
22941 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22942 break;
22943 case OPC_SHLLV_PH:
22944 check_dsp(ctx);
22945 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22946 break;
22947 case OPC_SHLL_S_PH:
22948 check_dsp(ctx);
22949 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22950 break;
22951 case OPC_SHLLV_S_PH:
22952 check_dsp(ctx);
22953 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22954 break;
22955 case OPC_SHLL_S_W:
22956 check_dsp(ctx);
22957 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22958 break;
22959 case OPC_SHLLV_S_W:
22960 check_dsp(ctx);
22961 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22962 break;
22963 case OPC_SHRL_QB:
22964 check_dsp(ctx);
22965 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22966 break;
22967 case OPC_SHRLV_QB:
22968 check_dsp(ctx);
22969 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22970 break;
22971 case OPC_SHRL_PH:
22972 check_dsp_r2(ctx);
22973 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22974 break;
22975 case OPC_SHRLV_PH:
22976 check_dsp_r2(ctx);
22977 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22978 break;
22979 case OPC_SHRA_QB:
22980 check_dsp_r2(ctx);
22981 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22982 break;
22983 case OPC_SHRA_R_QB:
22984 check_dsp_r2(ctx);
22985 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22986 break;
22987 case OPC_SHRAV_QB:
22988 check_dsp_r2(ctx);
22989 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22990 break;
22991 case OPC_SHRAV_R_QB:
22992 check_dsp_r2(ctx);
22993 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22994 break;
22995 case OPC_SHRA_PH:
22996 check_dsp(ctx);
22997 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22998 break;
22999 case OPC_SHRA_R_PH:
23000 check_dsp(ctx);
23001 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23002 break;
23003 case OPC_SHRAV_PH:
23004 check_dsp(ctx);
23005 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23006 break;
23007 case OPC_SHRAV_R_PH:
23008 check_dsp(ctx);
23009 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23010 break;
23011 case OPC_SHRA_R_W:
23012 check_dsp(ctx);
23013 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23014 break;
23015 case OPC_SHRAV_R_W:
23016 check_dsp(ctx);
23017 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23018 break;
23019 default: /* Invalid */
23020 MIPS_INVAL("MASK SHLL.QB");
23021 gen_reserved_instruction(ctx);
23022 break;
23024 break;
23026 #ifdef TARGET_MIPS64
23027 case OPC_SHLL_OB_DSP:
23028 op2 = MASK_SHLL_OB(ctx->opcode);
23029 switch (op2) {
23030 case OPC_SHLL_PW:
23031 check_dsp(ctx);
23032 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23033 break;
23034 case OPC_SHLLV_PW:
23035 check_dsp(ctx);
23036 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23037 break;
23038 case OPC_SHLL_S_PW:
23039 check_dsp(ctx);
23040 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23041 break;
23042 case OPC_SHLLV_S_PW:
23043 check_dsp(ctx);
23044 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23045 break;
23046 case OPC_SHLL_OB:
23047 check_dsp(ctx);
23048 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23049 break;
23050 case OPC_SHLLV_OB:
23051 check_dsp(ctx);
23052 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23053 break;
23054 case OPC_SHLL_QH:
23055 check_dsp(ctx);
23056 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23057 break;
23058 case OPC_SHLLV_QH:
23059 check_dsp(ctx);
23060 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23061 break;
23062 case OPC_SHLL_S_QH:
23063 check_dsp(ctx);
23064 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23065 break;
23066 case OPC_SHLLV_S_QH:
23067 check_dsp(ctx);
23068 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23069 break;
23070 case OPC_SHRA_OB:
23071 check_dsp_r2(ctx);
23072 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23073 break;
23074 case OPC_SHRAV_OB:
23075 check_dsp_r2(ctx);
23076 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23077 break;
23078 case OPC_SHRA_R_OB:
23079 check_dsp_r2(ctx);
23080 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23081 break;
23082 case OPC_SHRAV_R_OB:
23083 check_dsp_r2(ctx);
23084 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23085 break;
23086 case OPC_SHRA_PW:
23087 check_dsp(ctx);
23088 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23089 break;
23090 case OPC_SHRAV_PW:
23091 check_dsp(ctx);
23092 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23093 break;
23094 case OPC_SHRA_R_PW:
23095 check_dsp(ctx);
23096 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23097 break;
23098 case OPC_SHRAV_R_PW:
23099 check_dsp(ctx);
23100 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23101 break;
23102 case OPC_SHRA_QH:
23103 check_dsp(ctx);
23104 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23105 break;
23106 case OPC_SHRAV_QH:
23107 check_dsp(ctx);
23108 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23109 break;
23110 case OPC_SHRA_R_QH:
23111 check_dsp(ctx);
23112 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23113 break;
23114 case OPC_SHRAV_R_QH:
23115 check_dsp(ctx);
23116 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23117 break;
23118 case OPC_SHRL_OB:
23119 check_dsp(ctx);
23120 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23121 break;
23122 case OPC_SHRLV_OB:
23123 check_dsp(ctx);
23124 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23125 break;
23126 case OPC_SHRL_QH:
23127 check_dsp_r2(ctx);
23128 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23129 break;
23130 case OPC_SHRLV_QH:
23131 check_dsp_r2(ctx);
23132 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23133 break;
23134 default: /* Invalid */
23135 MIPS_INVAL("MASK SHLL.OB");
23136 gen_reserved_instruction(ctx);
23137 break;
23139 break;
23140 #endif
23143 tcg_temp_free(t0);
23144 tcg_temp_free(v1_t);
23145 tcg_temp_free(v2_t);
23148 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23149 int ret, int v1, int v2, int check_ret)
23151 TCGv_i32 t0;
23152 TCGv v1_t;
23153 TCGv v2_t;
23155 if ((ret == 0) && (check_ret == 1)) {
23156 /* Treat as NOP. */
23157 return;
23160 t0 = tcg_temp_new_i32();
23161 v1_t = tcg_temp_new();
23162 v2_t = tcg_temp_new();
23164 tcg_gen_movi_i32(t0, ret);
23165 gen_load_gpr(v1_t, v1);
23166 gen_load_gpr(v2_t, v2);
23168 switch (op1) {
23170 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23171 * the same mask and op1.
23173 case OPC_MULT_G_2E:
23174 check_dsp_r2(ctx);
23175 switch (op2) {
23176 case OPC_MUL_PH:
23177 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23178 break;
23179 case OPC_MUL_S_PH:
23180 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23181 break;
23182 case OPC_MULQ_S_W:
23183 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23184 break;
23185 case OPC_MULQ_RS_W:
23186 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23187 break;
23189 break;
23190 case OPC_DPA_W_PH_DSP:
23191 switch (op2) {
23192 case OPC_DPAU_H_QBL:
23193 check_dsp(ctx);
23194 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23195 break;
23196 case OPC_DPAU_H_QBR:
23197 check_dsp(ctx);
23198 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23199 break;
23200 case OPC_DPSU_H_QBL:
23201 check_dsp(ctx);
23202 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23203 break;
23204 case OPC_DPSU_H_QBR:
23205 check_dsp(ctx);
23206 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23207 break;
23208 case OPC_DPA_W_PH:
23209 check_dsp_r2(ctx);
23210 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23211 break;
23212 case OPC_DPAX_W_PH:
23213 check_dsp_r2(ctx);
23214 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23215 break;
23216 case OPC_DPAQ_S_W_PH:
23217 check_dsp(ctx);
23218 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23219 break;
23220 case OPC_DPAQX_S_W_PH:
23221 check_dsp_r2(ctx);
23222 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23223 break;
23224 case OPC_DPAQX_SA_W_PH:
23225 check_dsp_r2(ctx);
23226 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23227 break;
23228 case OPC_DPS_W_PH:
23229 check_dsp_r2(ctx);
23230 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23231 break;
23232 case OPC_DPSX_W_PH:
23233 check_dsp_r2(ctx);
23234 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23235 break;
23236 case OPC_DPSQ_S_W_PH:
23237 check_dsp(ctx);
23238 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23239 break;
23240 case OPC_DPSQX_S_W_PH:
23241 check_dsp_r2(ctx);
23242 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23243 break;
23244 case OPC_DPSQX_SA_W_PH:
23245 check_dsp_r2(ctx);
23246 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23247 break;
23248 case OPC_MULSAQ_S_W_PH:
23249 check_dsp(ctx);
23250 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23251 break;
23252 case OPC_DPAQ_SA_L_W:
23253 check_dsp(ctx);
23254 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23255 break;
23256 case OPC_DPSQ_SA_L_W:
23257 check_dsp(ctx);
23258 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23259 break;
23260 case OPC_MAQ_S_W_PHL:
23261 check_dsp(ctx);
23262 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23263 break;
23264 case OPC_MAQ_S_W_PHR:
23265 check_dsp(ctx);
23266 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23267 break;
23268 case OPC_MAQ_SA_W_PHL:
23269 check_dsp(ctx);
23270 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23271 break;
23272 case OPC_MAQ_SA_W_PHR:
23273 check_dsp(ctx);
23274 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23275 break;
23276 case OPC_MULSA_W_PH:
23277 check_dsp_r2(ctx);
23278 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23279 break;
23281 break;
23282 #ifdef TARGET_MIPS64
23283 case OPC_DPAQ_W_QH_DSP:
23285 int ac = ret & 0x03;
23286 tcg_gen_movi_i32(t0, ac);
23288 switch (op2) {
23289 case OPC_DMADD:
23290 check_dsp(ctx);
23291 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23292 break;
23293 case OPC_DMADDU:
23294 check_dsp(ctx);
23295 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23296 break;
23297 case OPC_DMSUB:
23298 check_dsp(ctx);
23299 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23300 break;
23301 case OPC_DMSUBU:
23302 check_dsp(ctx);
23303 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23304 break;
23305 case OPC_DPA_W_QH:
23306 check_dsp_r2(ctx);
23307 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23308 break;
23309 case OPC_DPAQ_S_W_QH:
23310 check_dsp(ctx);
23311 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23312 break;
23313 case OPC_DPAQ_SA_L_PW:
23314 check_dsp(ctx);
23315 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23316 break;
23317 case OPC_DPAU_H_OBL:
23318 check_dsp(ctx);
23319 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23320 break;
23321 case OPC_DPAU_H_OBR:
23322 check_dsp(ctx);
23323 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23324 break;
23325 case OPC_DPS_W_QH:
23326 check_dsp_r2(ctx);
23327 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23328 break;
23329 case OPC_DPSQ_S_W_QH:
23330 check_dsp(ctx);
23331 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23332 break;
23333 case OPC_DPSQ_SA_L_PW:
23334 check_dsp(ctx);
23335 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23336 break;
23337 case OPC_DPSU_H_OBL:
23338 check_dsp(ctx);
23339 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23340 break;
23341 case OPC_DPSU_H_OBR:
23342 check_dsp(ctx);
23343 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23344 break;
23345 case OPC_MAQ_S_L_PWL:
23346 check_dsp(ctx);
23347 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23348 break;
23349 case OPC_MAQ_S_L_PWR:
23350 check_dsp(ctx);
23351 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23352 break;
23353 case OPC_MAQ_S_W_QHLL:
23354 check_dsp(ctx);
23355 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23356 break;
23357 case OPC_MAQ_SA_W_QHLL:
23358 check_dsp(ctx);
23359 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23360 break;
23361 case OPC_MAQ_S_W_QHLR:
23362 check_dsp(ctx);
23363 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23364 break;
23365 case OPC_MAQ_SA_W_QHLR:
23366 check_dsp(ctx);
23367 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23368 break;
23369 case OPC_MAQ_S_W_QHRL:
23370 check_dsp(ctx);
23371 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23372 break;
23373 case OPC_MAQ_SA_W_QHRL:
23374 check_dsp(ctx);
23375 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23376 break;
23377 case OPC_MAQ_S_W_QHRR:
23378 check_dsp(ctx);
23379 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23380 break;
23381 case OPC_MAQ_SA_W_QHRR:
23382 check_dsp(ctx);
23383 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23384 break;
23385 case OPC_MULSAQ_S_L_PW:
23386 check_dsp(ctx);
23387 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23388 break;
23389 case OPC_MULSAQ_S_W_QH:
23390 check_dsp(ctx);
23391 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23392 break;
23395 break;
23396 #endif
23397 case OPC_ADDU_QB_DSP:
23398 switch (op2) {
23399 case OPC_MULEU_S_PH_QBL:
23400 check_dsp(ctx);
23401 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23402 break;
23403 case OPC_MULEU_S_PH_QBR:
23404 check_dsp(ctx);
23405 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23406 break;
23407 case OPC_MULQ_RS_PH:
23408 check_dsp(ctx);
23409 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23410 break;
23411 case OPC_MULEQ_S_W_PHL:
23412 check_dsp(ctx);
23413 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23414 break;
23415 case OPC_MULEQ_S_W_PHR:
23416 check_dsp(ctx);
23417 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23418 break;
23419 case OPC_MULQ_S_PH:
23420 check_dsp_r2(ctx);
23421 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23422 break;
23424 break;
23425 #ifdef TARGET_MIPS64
23426 case OPC_ADDU_OB_DSP:
23427 switch (op2) {
23428 case OPC_MULEQ_S_PW_QHL:
23429 check_dsp(ctx);
23430 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23431 break;
23432 case OPC_MULEQ_S_PW_QHR:
23433 check_dsp(ctx);
23434 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23435 break;
23436 case OPC_MULEU_S_QH_OBL:
23437 check_dsp(ctx);
23438 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23439 break;
23440 case OPC_MULEU_S_QH_OBR:
23441 check_dsp(ctx);
23442 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23443 break;
23444 case OPC_MULQ_RS_QH:
23445 check_dsp(ctx);
23446 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23447 break;
23449 break;
23450 #endif
23453 tcg_temp_free_i32(t0);
23454 tcg_temp_free(v1_t);
23455 tcg_temp_free(v2_t);
23458 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23459 int ret, int val)
23461 int16_t imm;
23462 TCGv t0;
23463 TCGv val_t;
23465 if (ret == 0) {
23466 /* Treat as NOP. */
23467 return;
23470 t0 = tcg_temp_new();
23471 val_t = tcg_temp_new();
23472 gen_load_gpr(val_t, val);
23474 switch (op1) {
23475 case OPC_ABSQ_S_PH_DSP:
23476 switch (op2) {
23477 case OPC_BITREV:
23478 check_dsp(ctx);
23479 gen_helper_bitrev(cpu_gpr[ret], val_t);
23480 break;
23481 case OPC_REPL_QB:
23482 check_dsp(ctx);
23484 target_long result;
23485 imm = (ctx->opcode >> 16) & 0xFF;
23486 result = (uint32_t)imm << 24 |
23487 (uint32_t)imm << 16 |
23488 (uint32_t)imm << 8 |
23489 (uint32_t)imm;
23490 result = (int32_t)result;
23491 tcg_gen_movi_tl(cpu_gpr[ret], result);
23493 break;
23494 case OPC_REPLV_QB:
23495 check_dsp(ctx);
23496 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23497 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23498 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23499 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23500 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23501 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23502 break;
23503 case OPC_REPL_PH:
23504 check_dsp(ctx);
23506 imm = (ctx->opcode >> 16) & 0x03FF;
23507 imm = (int16_t)(imm << 6) >> 6;
23508 tcg_gen_movi_tl(cpu_gpr[ret], \
23509 (target_long)((int32_t)imm << 16 | \
23510 (uint16_t)imm));
23512 break;
23513 case OPC_REPLV_PH:
23514 check_dsp(ctx);
23515 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23516 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23517 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23518 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23519 break;
23521 break;
23522 #ifdef TARGET_MIPS64
23523 case OPC_ABSQ_S_QH_DSP:
23524 switch (op2) {
23525 case OPC_REPL_OB:
23526 check_dsp(ctx);
23528 target_long temp;
23530 imm = (ctx->opcode >> 16) & 0xFF;
23531 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23532 temp = (temp << 16) | temp;
23533 temp = (temp << 32) | temp;
23534 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23535 break;
23537 case OPC_REPL_PW:
23538 check_dsp(ctx);
23540 target_long temp;
23542 imm = (ctx->opcode >> 16) & 0x03FF;
23543 imm = (int16_t)(imm << 6) >> 6;
23544 temp = ((target_long)imm << 32) \
23545 | ((target_long)imm & 0xFFFFFFFF);
23546 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23547 break;
23549 case OPC_REPL_QH:
23550 check_dsp(ctx);
23552 target_long temp;
23554 imm = (ctx->opcode >> 16) & 0x03FF;
23555 imm = (int16_t)(imm << 6) >> 6;
23557 temp = ((uint64_t)(uint16_t)imm << 48) |
23558 ((uint64_t)(uint16_t)imm << 32) |
23559 ((uint64_t)(uint16_t)imm << 16) |
23560 (uint64_t)(uint16_t)imm;
23561 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23562 break;
23564 case OPC_REPLV_OB:
23565 check_dsp(ctx);
23566 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23567 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23568 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23569 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23570 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23571 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23572 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23573 break;
23574 case OPC_REPLV_PW:
23575 check_dsp(ctx);
23576 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23577 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23578 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23579 break;
23580 case OPC_REPLV_QH:
23581 check_dsp(ctx);
23582 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23583 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23584 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23585 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23586 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23587 break;
23589 break;
23590 #endif
23592 tcg_temp_free(t0);
23593 tcg_temp_free(val_t);
23596 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23597 uint32_t op1, uint32_t op2,
23598 int ret, int v1, int v2, int check_ret)
23600 TCGv t1;
23601 TCGv v1_t;
23602 TCGv v2_t;
23604 if ((ret == 0) && (check_ret == 1)) {
23605 /* Treat as NOP. */
23606 return;
23609 t1 = tcg_temp_new();
23610 v1_t = tcg_temp_new();
23611 v2_t = tcg_temp_new();
23613 gen_load_gpr(v1_t, v1);
23614 gen_load_gpr(v2_t, v2);
23616 switch (op1) {
23617 case OPC_CMPU_EQ_QB_DSP:
23618 switch (op2) {
23619 case OPC_CMPU_EQ_QB:
23620 check_dsp(ctx);
23621 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23622 break;
23623 case OPC_CMPU_LT_QB:
23624 check_dsp(ctx);
23625 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23626 break;
23627 case OPC_CMPU_LE_QB:
23628 check_dsp(ctx);
23629 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23630 break;
23631 case OPC_CMPGU_EQ_QB:
23632 check_dsp(ctx);
23633 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23634 break;
23635 case OPC_CMPGU_LT_QB:
23636 check_dsp(ctx);
23637 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23638 break;
23639 case OPC_CMPGU_LE_QB:
23640 check_dsp(ctx);
23641 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23642 break;
23643 case OPC_CMPGDU_EQ_QB:
23644 check_dsp_r2(ctx);
23645 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23646 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23647 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23648 tcg_gen_shli_tl(t1, t1, 24);
23649 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23650 break;
23651 case OPC_CMPGDU_LT_QB:
23652 check_dsp_r2(ctx);
23653 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23654 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23655 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23656 tcg_gen_shli_tl(t1, t1, 24);
23657 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23658 break;
23659 case OPC_CMPGDU_LE_QB:
23660 check_dsp_r2(ctx);
23661 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23662 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23663 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23664 tcg_gen_shli_tl(t1, t1, 24);
23665 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23666 break;
23667 case OPC_CMP_EQ_PH:
23668 check_dsp(ctx);
23669 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23670 break;
23671 case OPC_CMP_LT_PH:
23672 check_dsp(ctx);
23673 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23674 break;
23675 case OPC_CMP_LE_PH:
23676 check_dsp(ctx);
23677 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23678 break;
23679 case OPC_PICK_QB:
23680 check_dsp(ctx);
23681 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23682 break;
23683 case OPC_PICK_PH:
23684 check_dsp(ctx);
23685 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23686 break;
23687 case OPC_PACKRL_PH:
23688 check_dsp(ctx);
23689 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23690 break;
23692 break;
23693 #ifdef TARGET_MIPS64
23694 case OPC_CMPU_EQ_OB_DSP:
23695 switch (op2) {
23696 case OPC_CMP_EQ_PW:
23697 check_dsp(ctx);
23698 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23699 break;
23700 case OPC_CMP_LT_PW:
23701 check_dsp(ctx);
23702 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23703 break;
23704 case OPC_CMP_LE_PW:
23705 check_dsp(ctx);
23706 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23707 break;
23708 case OPC_CMP_EQ_QH:
23709 check_dsp(ctx);
23710 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23711 break;
23712 case OPC_CMP_LT_QH:
23713 check_dsp(ctx);
23714 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23715 break;
23716 case OPC_CMP_LE_QH:
23717 check_dsp(ctx);
23718 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23719 break;
23720 case OPC_CMPGDU_EQ_OB:
23721 check_dsp_r2(ctx);
23722 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23723 break;
23724 case OPC_CMPGDU_LT_OB:
23725 check_dsp_r2(ctx);
23726 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23727 break;
23728 case OPC_CMPGDU_LE_OB:
23729 check_dsp_r2(ctx);
23730 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23731 break;
23732 case OPC_CMPGU_EQ_OB:
23733 check_dsp(ctx);
23734 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23735 break;
23736 case OPC_CMPGU_LT_OB:
23737 check_dsp(ctx);
23738 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23739 break;
23740 case OPC_CMPGU_LE_OB:
23741 check_dsp(ctx);
23742 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23743 break;
23744 case OPC_CMPU_EQ_OB:
23745 check_dsp(ctx);
23746 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23747 break;
23748 case OPC_CMPU_LT_OB:
23749 check_dsp(ctx);
23750 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23751 break;
23752 case OPC_CMPU_LE_OB:
23753 check_dsp(ctx);
23754 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23755 break;
23756 case OPC_PACKRL_PW:
23757 check_dsp(ctx);
23758 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23759 break;
23760 case OPC_PICK_OB:
23761 check_dsp(ctx);
23762 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23763 break;
23764 case OPC_PICK_PW:
23765 check_dsp(ctx);
23766 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23767 break;
23768 case OPC_PICK_QH:
23769 check_dsp(ctx);
23770 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23771 break;
23773 break;
23774 #endif
23777 tcg_temp_free(t1);
23778 tcg_temp_free(v1_t);
23779 tcg_temp_free(v2_t);
23782 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23783 uint32_t op1, int rt, int rs, int sa)
23785 TCGv t0;
23787 check_dsp_r2(ctx);
23789 if (rt == 0) {
23790 /* Treat as NOP. */
23791 return;
23794 t0 = tcg_temp_new();
23795 gen_load_gpr(t0, rs);
23797 switch (op1) {
23798 case OPC_APPEND_DSP:
23799 switch (MASK_APPEND(ctx->opcode)) {
23800 case OPC_APPEND:
23801 if (sa != 0) {
23802 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23804 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23805 break;
23806 case OPC_PREPEND:
23807 if (sa != 0) {
23808 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23809 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23810 tcg_gen_shli_tl(t0, t0, 32 - sa);
23811 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23813 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23814 break;
23815 case OPC_BALIGN:
23816 sa &= 3;
23817 if (sa != 0 && sa != 2) {
23818 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23819 tcg_gen_ext32u_tl(t0, t0);
23820 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23821 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23823 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23824 break;
23825 default: /* Invalid */
23826 MIPS_INVAL("MASK APPEND");
23827 gen_reserved_instruction(ctx);
23828 break;
23830 break;
23831 #ifdef TARGET_MIPS64
23832 case OPC_DAPPEND_DSP:
23833 switch (MASK_DAPPEND(ctx->opcode)) {
23834 case OPC_DAPPEND:
23835 if (sa != 0) {
23836 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23838 break;
23839 case OPC_PREPENDD:
23840 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23841 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23842 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23843 break;
23844 case OPC_PREPENDW:
23845 if (sa != 0) {
23846 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23847 tcg_gen_shli_tl(t0, t0, 64 - sa);
23848 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23850 break;
23851 case OPC_DBALIGN:
23852 sa &= 7;
23853 if (sa != 0 && sa != 2 && sa != 4) {
23854 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23855 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23856 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23858 break;
23859 default: /* Invalid */
23860 MIPS_INVAL("MASK DAPPEND");
23861 gen_reserved_instruction(ctx);
23862 break;
23864 break;
23865 #endif
23867 tcg_temp_free(t0);
23870 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23871 int ret, int v1, int v2, int check_ret)
23874 TCGv t0;
23875 TCGv t1;
23876 TCGv v1_t;
23877 TCGv v2_t;
23878 int16_t imm;
23880 if ((ret == 0) && (check_ret == 1)) {
23881 /* Treat as NOP. */
23882 return;
23885 t0 = tcg_temp_new();
23886 t1 = tcg_temp_new();
23887 v1_t = tcg_temp_new();
23888 v2_t = tcg_temp_new();
23890 gen_load_gpr(v1_t, v1);
23891 gen_load_gpr(v2_t, v2);
23893 switch (op1) {
23894 case OPC_EXTR_W_DSP:
23895 check_dsp(ctx);
23896 switch (op2) {
23897 case OPC_EXTR_W:
23898 tcg_gen_movi_tl(t0, v2);
23899 tcg_gen_movi_tl(t1, v1);
23900 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23901 break;
23902 case OPC_EXTR_R_W:
23903 tcg_gen_movi_tl(t0, v2);
23904 tcg_gen_movi_tl(t1, v1);
23905 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23906 break;
23907 case OPC_EXTR_RS_W:
23908 tcg_gen_movi_tl(t0, v2);
23909 tcg_gen_movi_tl(t1, v1);
23910 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23911 break;
23912 case OPC_EXTR_S_H:
23913 tcg_gen_movi_tl(t0, v2);
23914 tcg_gen_movi_tl(t1, v1);
23915 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23916 break;
23917 case OPC_EXTRV_S_H:
23918 tcg_gen_movi_tl(t0, v2);
23919 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23920 break;
23921 case OPC_EXTRV_W:
23922 tcg_gen_movi_tl(t0, v2);
23923 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23924 break;
23925 case OPC_EXTRV_R_W:
23926 tcg_gen_movi_tl(t0, v2);
23927 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23928 break;
23929 case OPC_EXTRV_RS_W:
23930 tcg_gen_movi_tl(t0, v2);
23931 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23932 break;
23933 case OPC_EXTP:
23934 tcg_gen_movi_tl(t0, v2);
23935 tcg_gen_movi_tl(t1, v1);
23936 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23937 break;
23938 case OPC_EXTPV:
23939 tcg_gen_movi_tl(t0, v2);
23940 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23941 break;
23942 case OPC_EXTPDP:
23943 tcg_gen_movi_tl(t0, v2);
23944 tcg_gen_movi_tl(t1, v1);
23945 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23946 break;
23947 case OPC_EXTPDPV:
23948 tcg_gen_movi_tl(t0, v2);
23949 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23950 break;
23951 case OPC_SHILO:
23952 imm = (ctx->opcode >> 20) & 0x3F;
23953 tcg_gen_movi_tl(t0, ret);
23954 tcg_gen_movi_tl(t1, imm);
23955 gen_helper_shilo(t0, t1, cpu_env);
23956 break;
23957 case OPC_SHILOV:
23958 tcg_gen_movi_tl(t0, ret);
23959 gen_helper_shilo(t0, v1_t, cpu_env);
23960 break;
23961 case OPC_MTHLIP:
23962 tcg_gen_movi_tl(t0, ret);
23963 gen_helper_mthlip(t0, v1_t, cpu_env);
23964 break;
23965 case OPC_WRDSP:
23966 imm = (ctx->opcode >> 11) & 0x3FF;
23967 tcg_gen_movi_tl(t0, imm);
23968 gen_helper_wrdsp(v1_t, t0, cpu_env);
23969 break;
23970 case OPC_RDDSP:
23971 imm = (ctx->opcode >> 16) & 0x03FF;
23972 tcg_gen_movi_tl(t0, imm);
23973 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23974 break;
23976 break;
23977 #ifdef TARGET_MIPS64
23978 case OPC_DEXTR_W_DSP:
23979 check_dsp(ctx);
23980 switch (op2) {
23981 case OPC_DMTHLIP:
23982 tcg_gen_movi_tl(t0, ret);
23983 gen_helper_dmthlip(v1_t, t0, cpu_env);
23984 break;
23985 case OPC_DSHILO:
23987 int shift = (ctx->opcode >> 19) & 0x7F;
23988 int ac = (ctx->opcode >> 11) & 0x03;
23989 tcg_gen_movi_tl(t0, shift);
23990 tcg_gen_movi_tl(t1, ac);
23991 gen_helper_dshilo(t0, t1, cpu_env);
23992 break;
23994 case OPC_DSHILOV:
23996 int ac = (ctx->opcode >> 11) & 0x03;
23997 tcg_gen_movi_tl(t0, ac);
23998 gen_helper_dshilo(v1_t, t0, cpu_env);
23999 break;
24001 case OPC_DEXTP:
24002 tcg_gen_movi_tl(t0, v2);
24003 tcg_gen_movi_tl(t1, v1);
24005 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24006 break;
24007 case OPC_DEXTPV:
24008 tcg_gen_movi_tl(t0, v2);
24009 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24010 break;
24011 case OPC_DEXTPDP:
24012 tcg_gen_movi_tl(t0, v2);
24013 tcg_gen_movi_tl(t1, v1);
24014 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24015 break;
24016 case OPC_DEXTPDPV:
24017 tcg_gen_movi_tl(t0, v2);
24018 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24019 break;
24020 case OPC_DEXTR_L:
24021 tcg_gen_movi_tl(t0, v2);
24022 tcg_gen_movi_tl(t1, v1);
24023 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24024 break;
24025 case OPC_DEXTR_R_L:
24026 tcg_gen_movi_tl(t0, v2);
24027 tcg_gen_movi_tl(t1, v1);
24028 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24029 break;
24030 case OPC_DEXTR_RS_L:
24031 tcg_gen_movi_tl(t0, v2);
24032 tcg_gen_movi_tl(t1, v1);
24033 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24034 break;
24035 case OPC_DEXTR_W:
24036 tcg_gen_movi_tl(t0, v2);
24037 tcg_gen_movi_tl(t1, v1);
24038 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24039 break;
24040 case OPC_DEXTR_R_W:
24041 tcg_gen_movi_tl(t0, v2);
24042 tcg_gen_movi_tl(t1, v1);
24043 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24044 break;
24045 case OPC_DEXTR_RS_W:
24046 tcg_gen_movi_tl(t0, v2);
24047 tcg_gen_movi_tl(t1, v1);
24048 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24049 break;
24050 case OPC_DEXTR_S_H:
24051 tcg_gen_movi_tl(t0, v2);
24052 tcg_gen_movi_tl(t1, v1);
24053 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24054 break;
24055 case OPC_DEXTRV_S_H:
24056 tcg_gen_movi_tl(t0, v2);
24057 tcg_gen_movi_tl(t1, v1);
24058 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24059 break;
24060 case OPC_DEXTRV_L:
24061 tcg_gen_movi_tl(t0, v2);
24062 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24063 break;
24064 case OPC_DEXTRV_R_L:
24065 tcg_gen_movi_tl(t0, v2);
24066 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24067 break;
24068 case OPC_DEXTRV_RS_L:
24069 tcg_gen_movi_tl(t0, v2);
24070 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24071 break;
24072 case OPC_DEXTRV_W:
24073 tcg_gen_movi_tl(t0, v2);
24074 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24075 break;
24076 case OPC_DEXTRV_R_W:
24077 tcg_gen_movi_tl(t0, v2);
24078 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24079 break;
24080 case OPC_DEXTRV_RS_W:
24081 tcg_gen_movi_tl(t0, v2);
24082 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24083 break;
24085 break;
24086 #endif
24089 tcg_temp_free(t0);
24090 tcg_temp_free(t1);
24091 tcg_temp_free(v1_t);
24092 tcg_temp_free(v2_t);
24095 /* End MIPSDSP functions. */
24097 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24099 int rs, rt, rd, sa;
24100 uint32_t op1, op2;
24102 rs = (ctx->opcode >> 21) & 0x1f;
24103 rt = (ctx->opcode >> 16) & 0x1f;
24104 rd = (ctx->opcode >> 11) & 0x1f;
24105 sa = (ctx->opcode >> 6) & 0x1f;
24107 op1 = MASK_SPECIAL(ctx->opcode);
24108 switch (op1) {
24109 case OPC_MULT:
24110 case OPC_MULTU:
24111 case OPC_DIV:
24112 case OPC_DIVU:
24113 op2 = MASK_R6_MULDIV(ctx->opcode);
24114 switch (op2) {
24115 case R6_OPC_MUL:
24116 case R6_OPC_MUH:
24117 case R6_OPC_MULU:
24118 case R6_OPC_MUHU:
24119 case R6_OPC_DIV:
24120 case R6_OPC_MOD:
24121 case R6_OPC_DIVU:
24122 case R6_OPC_MODU:
24123 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24124 break;
24125 default:
24126 MIPS_INVAL("special_r6 muldiv");
24127 gen_reserved_instruction(ctx);
24128 break;
24130 break;
24131 case OPC_SELEQZ:
24132 case OPC_SELNEZ:
24133 gen_cond_move(ctx, op1, rd, rs, rt);
24134 break;
24135 case R6_OPC_CLO:
24136 case R6_OPC_CLZ:
24137 if (rt == 0 && sa == 1) {
24139 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24140 * We need additionally to check other fields.
24142 gen_cl(ctx, op1, rd, rs);
24143 } else {
24144 gen_reserved_instruction(ctx);
24146 break;
24147 case R6_OPC_SDBBP:
24148 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24149 gen_helper_do_semihosting(cpu_env);
24150 } else {
24151 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24152 gen_reserved_instruction(ctx);
24153 } else {
24154 generate_exception_end(ctx, EXCP_DBp);
24157 break;
24158 #if defined(TARGET_MIPS64)
24159 case R6_OPC_DCLO:
24160 case R6_OPC_DCLZ:
24161 if (rt == 0 && sa == 1) {
24163 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24164 * We need additionally to check other fields.
24166 check_mips_64(ctx);
24167 gen_cl(ctx, op1, rd, rs);
24168 } else {
24169 gen_reserved_instruction(ctx);
24171 break;
24172 case OPC_DMULT:
24173 case OPC_DMULTU:
24174 case OPC_DDIV:
24175 case OPC_DDIVU:
24177 op2 = MASK_R6_MULDIV(ctx->opcode);
24178 switch (op2) {
24179 case R6_OPC_DMUL:
24180 case R6_OPC_DMUH:
24181 case R6_OPC_DMULU:
24182 case R6_OPC_DMUHU:
24183 case R6_OPC_DDIV:
24184 case R6_OPC_DMOD:
24185 case R6_OPC_DDIVU:
24186 case R6_OPC_DMODU:
24187 check_mips_64(ctx);
24188 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24189 break;
24190 default:
24191 MIPS_INVAL("special_r6 muldiv");
24192 gen_reserved_instruction(ctx);
24193 break;
24195 break;
24196 #endif
24197 default: /* Invalid */
24198 MIPS_INVAL("special_r6");
24199 gen_reserved_instruction(ctx);
24200 break;
24204 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24206 int rs = extract32(ctx->opcode, 21, 5);
24207 int rt = extract32(ctx->opcode, 16, 5);
24208 int rd = extract32(ctx->opcode, 11, 5);
24209 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24211 switch (op1) {
24212 case OPC_MOVN: /* Conditional move */
24213 case OPC_MOVZ:
24214 gen_cond_move(ctx, op1, rd, rs, rt);
24215 break;
24216 case OPC_MFHI: /* Move from HI/LO */
24217 case OPC_MFLO:
24218 gen_HILO(ctx, op1, 0, rd);
24219 break;
24220 case OPC_MTHI:
24221 case OPC_MTLO: /* Move to HI/LO */
24222 gen_HILO(ctx, op1, 0, rs);
24223 break;
24224 case OPC_MULT:
24225 case OPC_MULTU:
24226 gen_mul_txx9(ctx, op1, rd, rs, rt);
24227 break;
24228 case OPC_DIV:
24229 case OPC_DIVU:
24230 gen_muldiv(ctx, op1, 0, rs, rt);
24231 break;
24232 #if defined(TARGET_MIPS64)
24233 case OPC_DMULT:
24234 case OPC_DMULTU:
24235 case OPC_DDIV:
24236 case OPC_DDIVU:
24237 check_insn_opc_user_only(ctx, INSN_R5900);
24238 gen_muldiv(ctx, op1, 0, rs, rt);
24239 break;
24240 #endif
24241 case OPC_JR:
24242 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24243 break;
24244 default: /* Invalid */
24245 MIPS_INVAL("special_tx79");
24246 gen_reserved_instruction(ctx);
24247 break;
24251 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24253 int rs, rt, rd, sa;
24254 uint32_t op1;
24256 rs = (ctx->opcode >> 21) & 0x1f;
24257 rt = (ctx->opcode >> 16) & 0x1f;
24258 rd = (ctx->opcode >> 11) & 0x1f;
24259 sa = (ctx->opcode >> 6) & 0x1f;
24261 op1 = MASK_SPECIAL(ctx->opcode);
24262 switch (op1) {
24263 case OPC_MOVN: /* Conditional move */
24264 case OPC_MOVZ:
24265 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
24266 INSN_LOONGSON2E | INSN_LOONGSON2F);
24267 gen_cond_move(ctx, op1, rd, rs, rt);
24268 break;
24269 case OPC_MFHI: /* Move from HI/LO */
24270 case OPC_MFLO:
24271 gen_HILO(ctx, op1, rs & 3, rd);
24272 break;
24273 case OPC_MTHI:
24274 case OPC_MTLO: /* Move to HI/LO */
24275 gen_HILO(ctx, op1, rd & 3, rs);
24276 break;
24277 case OPC_MOVCI:
24278 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
24279 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24280 check_cp1_enabled(ctx);
24281 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24282 (ctx->opcode >> 16) & 1);
24283 } else {
24284 generate_exception_err(ctx, EXCP_CpU, 1);
24286 break;
24287 case OPC_MULT:
24288 case OPC_MULTU:
24289 if (sa) {
24290 check_insn(ctx, INSN_VR54XX);
24291 op1 = MASK_MUL_VR54XX(ctx->opcode);
24292 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24293 } else {
24294 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24296 break;
24297 case OPC_DIV:
24298 case OPC_DIVU:
24299 gen_muldiv(ctx, op1, 0, rs, rt);
24300 break;
24301 #if defined(TARGET_MIPS64)
24302 case OPC_DMULT:
24303 case OPC_DMULTU:
24304 case OPC_DDIV:
24305 case OPC_DDIVU:
24306 check_insn(ctx, ISA_MIPS3);
24307 check_mips_64(ctx);
24308 gen_muldiv(ctx, op1, 0, rs, rt);
24309 break;
24310 #endif
24311 case OPC_JR:
24312 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24313 break;
24314 case OPC_SPIM:
24315 #ifdef MIPS_STRICT_STANDARD
24316 MIPS_INVAL("SPIM");
24317 gen_reserved_instruction(ctx);
24318 #else
24319 /* Implemented as RI exception for now. */
24320 MIPS_INVAL("spim (unofficial)");
24321 gen_reserved_instruction(ctx);
24322 #endif
24323 break;
24324 default: /* Invalid */
24325 MIPS_INVAL("special_legacy");
24326 gen_reserved_instruction(ctx);
24327 break;
24331 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24333 int rs, rt, rd, sa;
24334 uint32_t op1;
24336 rs = (ctx->opcode >> 21) & 0x1f;
24337 rt = (ctx->opcode >> 16) & 0x1f;
24338 rd = (ctx->opcode >> 11) & 0x1f;
24339 sa = (ctx->opcode >> 6) & 0x1f;
24341 op1 = MASK_SPECIAL(ctx->opcode);
24342 switch (op1) {
24343 case OPC_SLL: /* Shift with immediate */
24344 if (sa == 5 && rd == 0 &&
24345 rs == 0 && rt == 0) { /* PAUSE */
24346 if ((ctx->insn_flags & ISA_MIPS_R6) &&
24347 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24348 gen_reserved_instruction(ctx);
24349 break;
24352 /* Fallthrough */
24353 case OPC_SRA:
24354 gen_shift_imm(ctx, op1, rd, rt, sa);
24355 break;
24356 case OPC_SRL:
24357 switch ((ctx->opcode >> 21) & 0x1f) {
24358 case 1:
24359 /* rotr is decoded as srl on non-R2 CPUs */
24360 if (ctx->insn_flags & ISA_MIPS_R2) {
24361 op1 = OPC_ROTR;
24363 /* Fallthrough */
24364 case 0:
24365 gen_shift_imm(ctx, op1, rd, rt, sa);
24366 break;
24367 default:
24368 gen_reserved_instruction(ctx);
24369 break;
24371 break;
24372 case OPC_ADD:
24373 case OPC_ADDU:
24374 case OPC_SUB:
24375 case OPC_SUBU:
24376 gen_arith(ctx, op1, rd, rs, rt);
24377 break;
24378 case OPC_SLLV: /* Shifts */
24379 case OPC_SRAV:
24380 gen_shift(ctx, op1, rd, rs, rt);
24381 break;
24382 case OPC_SRLV:
24383 switch ((ctx->opcode >> 6) & 0x1f) {
24384 case 1:
24385 /* rotrv is decoded as srlv on non-R2 CPUs */
24386 if (ctx->insn_flags & ISA_MIPS_R2) {
24387 op1 = OPC_ROTRV;
24389 /* Fallthrough */
24390 case 0:
24391 gen_shift(ctx, op1, rd, rs, rt);
24392 break;
24393 default:
24394 gen_reserved_instruction(ctx);
24395 break;
24397 break;
24398 case OPC_SLT: /* Set on less than */
24399 case OPC_SLTU:
24400 gen_slt(ctx, op1, rd, rs, rt);
24401 break;
24402 case OPC_AND: /* Logic*/
24403 case OPC_OR:
24404 case OPC_NOR:
24405 case OPC_XOR:
24406 gen_logic(ctx, op1, rd, rs, rt);
24407 break;
24408 case OPC_JALR:
24409 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24410 break;
24411 case OPC_TGE: /* Traps */
24412 case OPC_TGEU:
24413 case OPC_TLT:
24414 case OPC_TLTU:
24415 case OPC_TEQ:
24416 case OPC_TNE:
24417 check_insn(ctx, ISA_MIPS2);
24418 gen_trap(ctx, op1, rs, rt, -1);
24419 break;
24420 case OPC_PMON:
24421 /* Pmon entry point, also R4010 selsl */
24422 #ifdef MIPS_STRICT_STANDARD
24423 MIPS_INVAL("PMON / selsl");
24424 gen_reserved_instruction(ctx);
24425 #else
24426 gen_helper_0e0i(pmon, sa);
24427 #endif
24428 break;
24429 case OPC_SYSCALL:
24430 generate_exception_end(ctx, EXCP_SYSCALL);
24431 break;
24432 case OPC_BREAK:
24433 generate_exception_end(ctx, EXCP_BREAK);
24434 break;
24435 case OPC_SYNC:
24436 check_insn(ctx, ISA_MIPS2);
24437 gen_sync(extract32(ctx->opcode, 6, 5));
24438 break;
24440 #if defined(TARGET_MIPS64)
24441 /* MIPS64 specific opcodes */
24442 case OPC_DSLL:
24443 case OPC_DSRA:
24444 case OPC_DSLL32:
24445 case OPC_DSRA32:
24446 check_insn(ctx, ISA_MIPS3);
24447 check_mips_64(ctx);
24448 gen_shift_imm(ctx, op1, rd, rt, sa);
24449 break;
24450 case OPC_DSRL:
24451 switch ((ctx->opcode >> 21) & 0x1f) {
24452 case 1:
24453 /* drotr is decoded as dsrl on non-R2 CPUs */
24454 if (ctx->insn_flags & ISA_MIPS_R2) {
24455 op1 = OPC_DROTR;
24457 /* Fallthrough */
24458 case 0:
24459 check_insn(ctx, ISA_MIPS3);
24460 check_mips_64(ctx);
24461 gen_shift_imm(ctx, op1, rd, rt, sa);
24462 break;
24463 default:
24464 gen_reserved_instruction(ctx);
24465 break;
24467 break;
24468 case OPC_DSRL32:
24469 switch ((ctx->opcode >> 21) & 0x1f) {
24470 case 1:
24471 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24472 if (ctx->insn_flags & ISA_MIPS_R2) {
24473 op1 = OPC_DROTR32;
24475 /* Fallthrough */
24476 case 0:
24477 check_insn(ctx, ISA_MIPS3);
24478 check_mips_64(ctx);
24479 gen_shift_imm(ctx, op1, rd, rt, sa);
24480 break;
24481 default:
24482 gen_reserved_instruction(ctx);
24483 break;
24485 break;
24486 case OPC_DADD:
24487 case OPC_DADDU:
24488 case OPC_DSUB:
24489 case OPC_DSUBU:
24490 check_insn(ctx, ISA_MIPS3);
24491 check_mips_64(ctx);
24492 gen_arith(ctx, op1, rd, rs, rt);
24493 break;
24494 case OPC_DSLLV:
24495 case OPC_DSRAV:
24496 check_insn(ctx, ISA_MIPS3);
24497 check_mips_64(ctx);
24498 gen_shift(ctx, op1, rd, rs, rt);
24499 break;
24500 case OPC_DSRLV:
24501 switch ((ctx->opcode >> 6) & 0x1f) {
24502 case 1:
24503 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24504 if (ctx->insn_flags & ISA_MIPS_R2) {
24505 op1 = OPC_DROTRV;
24507 /* Fallthrough */
24508 case 0:
24509 check_insn(ctx, ISA_MIPS3);
24510 check_mips_64(ctx);
24511 gen_shift(ctx, op1, rd, rs, rt);
24512 break;
24513 default:
24514 gen_reserved_instruction(ctx);
24515 break;
24517 break;
24518 #endif
24519 default:
24520 if (ctx->insn_flags & ISA_MIPS_R6) {
24521 decode_opc_special_r6(env, ctx);
24522 } else if (ctx->insn_flags & INSN_R5900) {
24523 decode_opc_special_tx79(env, ctx);
24524 } else {
24525 decode_opc_special_legacy(env, ctx);
24531 #if defined(TARGET_MIPS64)
24535 * MMI (MultiMedia Interface) ASE instructions
24536 * ===========================================
24540 * MMI instructions category: data communication
24541 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24543 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24544 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24545 * PCPYUD PEXEH PEXTLW PPACW
24546 * PEXEW PEXTUB
24547 * PEXTUH
24548 * PEXTUW
24552 * PCPYH rd, rt
24554 * Parallel Copy Halfword
24556 * 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
24557 * +-----------+---------+---------+---------+---------+-----------+
24558 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24559 * +-----------+---------+---------+---------+---------+-----------+
24561 static void gen_mmi_pcpyh(DisasContext *ctx)
24563 uint32_t pd, rt, rd;
24564 uint32_t opcode;
24566 opcode = ctx->opcode;
24568 pd = extract32(opcode, 21, 5);
24569 rt = extract32(opcode, 16, 5);
24570 rd = extract32(opcode, 11, 5);
24572 if (unlikely(pd != 0)) {
24573 gen_reserved_instruction(ctx);
24574 } else if (rd == 0) {
24575 /* nop */
24576 } else if (rt == 0) {
24577 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24578 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24579 } else {
24580 TCGv_i64 t0 = tcg_temp_new();
24581 TCGv_i64 t1 = tcg_temp_new();
24582 uint64_t mask = (1ULL << 16) - 1;
24584 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24585 tcg_gen_movi_i64(t1, 0);
24586 tcg_gen_or_i64(t1, t0, t1);
24587 tcg_gen_shli_i64(t0, t0, 16);
24588 tcg_gen_or_i64(t1, t0, t1);
24589 tcg_gen_shli_i64(t0, t0, 16);
24590 tcg_gen_or_i64(t1, t0, t1);
24591 tcg_gen_shli_i64(t0, t0, 16);
24592 tcg_gen_or_i64(t1, t0, t1);
24594 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24596 tcg_gen_andi_i64(t0, cpu_gpr_hi[rt], mask);
24597 tcg_gen_movi_i64(t1, 0);
24598 tcg_gen_or_i64(t1, t0, t1);
24599 tcg_gen_shli_i64(t0, t0, 16);
24600 tcg_gen_or_i64(t1, t0, t1);
24601 tcg_gen_shli_i64(t0, t0, 16);
24602 tcg_gen_or_i64(t1, t0, t1);
24603 tcg_gen_shli_i64(t0, t0, 16);
24604 tcg_gen_or_i64(t1, t0, t1);
24606 tcg_gen_mov_i64(cpu_gpr_hi[rd], t1);
24608 tcg_temp_free(t0);
24609 tcg_temp_free(t1);
24614 * PCPYLD rd, rs, rt
24616 * Parallel Copy Lower Doubleword
24618 * 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
24619 * +-----------+---------+---------+---------+---------+-----------+
24620 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24621 * +-----------+---------+---------+---------+---------+-----------+
24623 static void gen_mmi_pcpyld(DisasContext *ctx)
24625 uint32_t rs, rt, rd;
24626 uint32_t opcode;
24628 opcode = ctx->opcode;
24630 rs = extract32(opcode, 21, 5);
24631 rt = extract32(opcode, 16, 5);
24632 rd = extract32(opcode, 11, 5);
24634 if (rd == 0) {
24635 /* nop */
24636 } else {
24637 if (rs == 0) {
24638 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24639 } else {
24640 tcg_gen_mov_i64(cpu_gpr_hi[rd], cpu_gpr[rs]);
24642 if (rt == 0) {
24643 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24644 } else {
24645 if (rd != rt) {
24646 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24653 * PCPYUD rd, rs, rt
24655 * Parallel Copy Upper Doubleword
24657 * 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
24658 * +-----------+---------+---------+---------+---------+-----------+
24659 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24660 * +-----------+---------+---------+---------+---------+-----------+
24662 static void gen_mmi_pcpyud(DisasContext *ctx)
24664 uint32_t rs, rt, rd;
24665 uint32_t opcode;
24667 opcode = ctx->opcode;
24669 rs = extract32(opcode, 21, 5);
24670 rt = extract32(opcode, 16, 5);
24671 rd = extract32(opcode, 11, 5);
24673 if (rd == 0) {
24674 /* nop */
24675 } else {
24676 if (rs == 0) {
24677 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24678 } else {
24679 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr_hi[rs]);
24681 if (rt == 0) {
24682 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24683 } else {
24684 if (rd != rt) {
24685 tcg_gen_mov_i64(cpu_gpr_hi[rd], cpu_gpr_hi[rt]);
24691 #endif
24694 #if !defined(TARGET_MIPS64)
24696 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24697 #define MXU_APTN1_A 0
24698 #define MXU_APTN1_S 1
24700 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24701 #define MXU_APTN2_AA 0
24702 #define MXU_APTN2_AS 1
24703 #define MXU_APTN2_SA 2
24704 #define MXU_APTN2_SS 3
24706 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24707 #define MXU_EPTN2_AA 0
24708 #define MXU_EPTN2_AS 1
24709 #define MXU_EPTN2_SA 2
24710 #define MXU_EPTN2_SS 3
24712 /* MXU operand getting pattern 'optn2' */
24713 #define MXU_OPTN2_PTN0 0
24714 #define MXU_OPTN2_PTN1 1
24715 #define MXU_OPTN2_PTN2 2
24716 #define MXU_OPTN2_PTN3 3
24717 /* alternative naming scheme for 'optn2' */
24718 #define MXU_OPTN2_WW 0
24719 #define MXU_OPTN2_LW 1
24720 #define MXU_OPTN2_HW 2
24721 #define MXU_OPTN2_XW 3
24723 /* MXU operand getting pattern 'optn3' */
24724 #define MXU_OPTN3_PTN0 0
24725 #define MXU_OPTN3_PTN1 1
24726 #define MXU_OPTN3_PTN2 2
24727 #define MXU_OPTN3_PTN3 3
24728 #define MXU_OPTN3_PTN4 4
24729 #define MXU_OPTN3_PTN5 5
24730 #define MXU_OPTN3_PTN6 6
24731 #define MXU_OPTN3_PTN7 7
24735 * S32I2M XRa, rb - Register move from GRF to XRF
24737 static void gen_mxu_s32i2m(DisasContext *ctx)
24739 TCGv t0;
24740 uint32_t XRa, Rb;
24742 t0 = tcg_temp_new();
24744 XRa = extract32(ctx->opcode, 6, 5);
24745 Rb = extract32(ctx->opcode, 16, 5);
24747 gen_load_gpr(t0, Rb);
24748 if (XRa <= 15) {
24749 gen_store_mxu_gpr(t0, XRa);
24750 } else if (XRa == 16) {
24751 gen_store_mxu_cr(t0);
24754 tcg_temp_free(t0);
24758 * S32M2I XRa, rb - Register move from XRF to GRF
24760 static void gen_mxu_s32m2i(DisasContext *ctx)
24762 TCGv t0;
24763 uint32_t XRa, Rb;
24765 t0 = tcg_temp_new();
24767 XRa = extract32(ctx->opcode, 6, 5);
24768 Rb = extract32(ctx->opcode, 16, 5);
24770 if (XRa <= 15) {
24771 gen_load_mxu_gpr(t0, XRa);
24772 } else if (XRa == 16) {
24773 gen_load_mxu_cr(t0);
24776 gen_store_gpr(t0, Rb);
24778 tcg_temp_free(t0);
24782 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24784 static void gen_mxu_s8ldd(DisasContext *ctx)
24786 TCGv t0, t1;
24787 uint32_t XRa, Rb, s8, optn3;
24789 t0 = tcg_temp_new();
24790 t1 = tcg_temp_new();
24792 XRa = extract32(ctx->opcode, 6, 4);
24793 s8 = extract32(ctx->opcode, 10, 8);
24794 optn3 = extract32(ctx->opcode, 18, 3);
24795 Rb = extract32(ctx->opcode, 21, 5);
24797 gen_load_gpr(t0, Rb);
24798 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24800 switch (optn3) {
24801 /* XRa[7:0] = tmp8 */
24802 case MXU_OPTN3_PTN0:
24803 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24804 gen_load_mxu_gpr(t0, XRa);
24805 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24806 break;
24807 /* XRa[15:8] = tmp8 */
24808 case MXU_OPTN3_PTN1:
24809 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24810 gen_load_mxu_gpr(t0, XRa);
24811 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24812 break;
24813 /* XRa[23:16] = tmp8 */
24814 case MXU_OPTN3_PTN2:
24815 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24816 gen_load_mxu_gpr(t0, XRa);
24817 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24818 break;
24819 /* XRa[31:24] = tmp8 */
24820 case MXU_OPTN3_PTN3:
24821 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24822 gen_load_mxu_gpr(t0, XRa);
24823 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24824 break;
24825 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24826 case MXU_OPTN3_PTN4:
24827 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24828 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24829 break;
24830 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24831 case MXU_OPTN3_PTN5:
24832 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24833 tcg_gen_shli_tl(t1, t1, 8);
24834 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24835 break;
24836 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24837 case MXU_OPTN3_PTN6:
24838 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24839 tcg_gen_mov_tl(t0, t1);
24840 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24841 tcg_gen_shli_tl(t1, t1, 16);
24842 tcg_gen_or_tl(t0, t0, t1);
24843 break;
24844 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24845 case MXU_OPTN3_PTN7:
24846 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24847 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24848 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24849 break;
24852 gen_store_mxu_gpr(t0, XRa);
24854 tcg_temp_free(t0);
24855 tcg_temp_free(t1);
24859 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24861 static void gen_mxu_d16mul(DisasContext *ctx)
24863 TCGv t0, t1, t2, t3;
24864 uint32_t XRa, XRb, XRc, XRd, optn2;
24866 t0 = tcg_temp_new();
24867 t1 = tcg_temp_new();
24868 t2 = tcg_temp_new();
24869 t3 = tcg_temp_new();
24871 XRa = extract32(ctx->opcode, 6, 4);
24872 XRb = extract32(ctx->opcode, 10, 4);
24873 XRc = extract32(ctx->opcode, 14, 4);
24874 XRd = extract32(ctx->opcode, 18, 4);
24875 optn2 = extract32(ctx->opcode, 22, 2);
24877 gen_load_mxu_gpr(t1, XRb);
24878 tcg_gen_sextract_tl(t0, t1, 0, 16);
24879 tcg_gen_sextract_tl(t1, t1, 16, 16);
24880 gen_load_mxu_gpr(t3, XRc);
24881 tcg_gen_sextract_tl(t2, t3, 0, 16);
24882 tcg_gen_sextract_tl(t3, t3, 16, 16);
24884 switch (optn2) {
24885 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24886 tcg_gen_mul_tl(t3, t1, t3);
24887 tcg_gen_mul_tl(t2, t0, t2);
24888 break;
24889 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24890 tcg_gen_mul_tl(t3, t0, t3);
24891 tcg_gen_mul_tl(t2, t0, t2);
24892 break;
24893 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24894 tcg_gen_mul_tl(t3, t1, t3);
24895 tcg_gen_mul_tl(t2, t1, t2);
24896 break;
24897 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24898 tcg_gen_mul_tl(t3, t0, t3);
24899 tcg_gen_mul_tl(t2, t1, t2);
24900 break;
24902 gen_store_mxu_gpr(t3, XRa);
24903 gen_store_mxu_gpr(t2, XRd);
24905 tcg_temp_free(t0);
24906 tcg_temp_free(t1);
24907 tcg_temp_free(t2);
24908 tcg_temp_free(t3);
24912 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
24913 * and accumulate
24915 static void gen_mxu_d16mac(DisasContext *ctx)
24917 TCGv t0, t1, t2, t3;
24918 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
24920 t0 = tcg_temp_new();
24921 t1 = tcg_temp_new();
24922 t2 = tcg_temp_new();
24923 t3 = tcg_temp_new();
24925 XRa = extract32(ctx->opcode, 6, 4);
24926 XRb = extract32(ctx->opcode, 10, 4);
24927 XRc = extract32(ctx->opcode, 14, 4);
24928 XRd = extract32(ctx->opcode, 18, 4);
24929 optn2 = extract32(ctx->opcode, 22, 2);
24930 aptn2 = extract32(ctx->opcode, 24, 2);
24932 gen_load_mxu_gpr(t1, XRb);
24933 tcg_gen_sextract_tl(t0, t1, 0, 16);
24934 tcg_gen_sextract_tl(t1, t1, 16, 16);
24936 gen_load_mxu_gpr(t3, XRc);
24937 tcg_gen_sextract_tl(t2, t3, 0, 16);
24938 tcg_gen_sextract_tl(t3, t3, 16, 16);
24940 switch (optn2) {
24941 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24942 tcg_gen_mul_tl(t3, t1, t3);
24943 tcg_gen_mul_tl(t2, t0, t2);
24944 break;
24945 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24946 tcg_gen_mul_tl(t3, t0, t3);
24947 tcg_gen_mul_tl(t2, t0, t2);
24948 break;
24949 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24950 tcg_gen_mul_tl(t3, t1, t3);
24951 tcg_gen_mul_tl(t2, t1, t2);
24952 break;
24953 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24954 tcg_gen_mul_tl(t3, t0, t3);
24955 tcg_gen_mul_tl(t2, t1, t2);
24956 break;
24958 gen_load_mxu_gpr(t0, XRa);
24959 gen_load_mxu_gpr(t1, XRd);
24961 switch (aptn2) {
24962 case MXU_APTN2_AA:
24963 tcg_gen_add_tl(t3, t0, t3);
24964 tcg_gen_add_tl(t2, t1, t2);
24965 break;
24966 case MXU_APTN2_AS:
24967 tcg_gen_add_tl(t3, t0, t3);
24968 tcg_gen_sub_tl(t2, t1, t2);
24969 break;
24970 case MXU_APTN2_SA:
24971 tcg_gen_sub_tl(t3, t0, t3);
24972 tcg_gen_add_tl(t2, t1, t2);
24973 break;
24974 case MXU_APTN2_SS:
24975 tcg_gen_sub_tl(t3, t0, t3);
24976 tcg_gen_sub_tl(t2, t1, t2);
24977 break;
24979 gen_store_mxu_gpr(t3, XRa);
24980 gen_store_mxu_gpr(t2, XRd);
24982 tcg_temp_free(t0);
24983 tcg_temp_free(t1);
24984 tcg_temp_free(t2);
24985 tcg_temp_free(t3);
24989 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
24990 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
24992 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
24994 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
24995 uint32_t XRa, XRb, XRc, XRd, sel;
24997 t0 = tcg_temp_new();
24998 t1 = tcg_temp_new();
24999 t2 = tcg_temp_new();
25000 t3 = tcg_temp_new();
25001 t4 = tcg_temp_new();
25002 t5 = tcg_temp_new();
25003 t6 = tcg_temp_new();
25004 t7 = tcg_temp_new();
25006 XRa = extract32(ctx->opcode, 6, 4);
25007 XRb = extract32(ctx->opcode, 10, 4);
25008 XRc = extract32(ctx->opcode, 14, 4);
25009 XRd = extract32(ctx->opcode, 18, 4);
25010 sel = extract32(ctx->opcode, 22, 2);
25012 gen_load_mxu_gpr(t3, XRb);
25013 gen_load_mxu_gpr(t7, XRc);
25015 if (sel == 0x2) {
25016 /* Q8MULSU */
25017 tcg_gen_ext8s_tl(t0, t3);
25018 tcg_gen_shri_tl(t3, t3, 8);
25019 tcg_gen_ext8s_tl(t1, t3);
25020 tcg_gen_shri_tl(t3, t3, 8);
25021 tcg_gen_ext8s_tl(t2, t3);
25022 tcg_gen_shri_tl(t3, t3, 8);
25023 tcg_gen_ext8s_tl(t3, t3);
25024 } else {
25025 /* Q8MUL */
25026 tcg_gen_ext8u_tl(t0, t3);
25027 tcg_gen_shri_tl(t3, t3, 8);
25028 tcg_gen_ext8u_tl(t1, t3);
25029 tcg_gen_shri_tl(t3, t3, 8);
25030 tcg_gen_ext8u_tl(t2, t3);
25031 tcg_gen_shri_tl(t3, t3, 8);
25032 tcg_gen_ext8u_tl(t3, t3);
25035 tcg_gen_ext8u_tl(t4, t7);
25036 tcg_gen_shri_tl(t7, t7, 8);
25037 tcg_gen_ext8u_tl(t5, t7);
25038 tcg_gen_shri_tl(t7, t7, 8);
25039 tcg_gen_ext8u_tl(t6, t7);
25040 tcg_gen_shri_tl(t7, t7, 8);
25041 tcg_gen_ext8u_tl(t7, t7);
25043 tcg_gen_mul_tl(t0, t0, t4);
25044 tcg_gen_mul_tl(t1, t1, t5);
25045 tcg_gen_mul_tl(t2, t2, t6);
25046 tcg_gen_mul_tl(t3, t3, t7);
25048 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25049 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25050 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25051 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25053 tcg_gen_shli_tl(t1, t1, 16);
25054 tcg_gen_shli_tl(t3, t3, 16);
25056 tcg_gen_or_tl(t0, t0, t1);
25057 tcg_gen_or_tl(t1, t2, t3);
25059 gen_store_mxu_gpr(t0, XRd);
25060 gen_store_mxu_gpr(t1, XRa);
25062 tcg_temp_free(t0);
25063 tcg_temp_free(t1);
25064 tcg_temp_free(t2);
25065 tcg_temp_free(t3);
25066 tcg_temp_free(t4);
25067 tcg_temp_free(t5);
25068 tcg_temp_free(t6);
25069 tcg_temp_free(t7);
25073 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25074 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25076 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25078 TCGv t0, t1;
25079 uint32_t XRa, Rb, s12, sel;
25081 t0 = tcg_temp_new();
25082 t1 = tcg_temp_new();
25084 XRa = extract32(ctx->opcode, 6, 4);
25085 s12 = extract32(ctx->opcode, 10, 10);
25086 sel = extract32(ctx->opcode, 20, 1);
25087 Rb = extract32(ctx->opcode, 21, 5);
25089 gen_load_gpr(t0, Rb);
25091 tcg_gen_movi_tl(t1, s12);
25092 tcg_gen_shli_tl(t1, t1, 2);
25093 if (s12 & 0x200) {
25094 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25096 tcg_gen_add_tl(t1, t0, t1);
25097 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25099 if (sel == 1) {
25100 /* S32LDDR */
25101 tcg_gen_bswap32_tl(t1, t1);
25103 gen_store_mxu_gpr(t1, XRa);
25105 tcg_temp_free(t0);
25106 tcg_temp_free(t1);
25111 * MXU instruction category: logic
25112 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25114 * S32NOR S32AND S32OR S32XOR
25118 * S32NOR XRa, XRb, XRc
25119 * Update XRa with the result of logical bitwise 'nor' operation
25120 * applied to the content of XRb and XRc.
25122 static void gen_mxu_S32NOR(DisasContext *ctx)
25124 uint32_t pad, XRc, XRb, XRa;
25126 pad = extract32(ctx->opcode, 21, 5);
25127 XRc = extract32(ctx->opcode, 14, 4);
25128 XRb = extract32(ctx->opcode, 10, 4);
25129 XRa = extract32(ctx->opcode, 6, 4);
25131 if (unlikely(pad != 0)) {
25132 /* opcode padding incorrect -> do nothing */
25133 } else if (unlikely(XRa == 0)) {
25134 /* destination is zero register -> do nothing */
25135 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25136 /* both operands zero registers -> just set destination to all 1s */
25137 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25138 } else if (unlikely(XRb == 0)) {
25139 /* XRb zero register -> just set destination to the negation of XRc */
25140 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25141 } else if (unlikely(XRc == 0)) {
25142 /* XRa zero register -> just set destination to the negation of XRb */
25143 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25144 } else if (unlikely(XRb == XRc)) {
25145 /* both operands same -> just set destination to the negation of XRb */
25146 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25147 } else {
25148 /* the most general case */
25149 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25154 * S32AND XRa, XRb, XRc
25155 * Update XRa with the result of logical bitwise 'and' operation
25156 * applied to the content of XRb and XRc.
25158 static void gen_mxu_S32AND(DisasContext *ctx)
25160 uint32_t pad, XRc, XRb, XRa;
25162 pad = extract32(ctx->opcode, 21, 5);
25163 XRc = extract32(ctx->opcode, 14, 4);
25164 XRb = extract32(ctx->opcode, 10, 4);
25165 XRa = extract32(ctx->opcode, 6, 4);
25167 if (unlikely(pad != 0)) {
25168 /* opcode padding incorrect -> do nothing */
25169 } else if (unlikely(XRa == 0)) {
25170 /* destination is zero register -> do nothing */
25171 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25172 /* one of operands zero register -> just set destination to all 0s */
25173 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25174 } else if (unlikely(XRb == XRc)) {
25175 /* both operands same -> just set destination to one of them */
25176 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25177 } else {
25178 /* the most general case */
25179 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25184 * S32OR XRa, XRb, XRc
25185 * Update XRa with the result of logical bitwise 'or' operation
25186 * applied to the content of XRb and XRc.
25188 static void gen_mxu_S32OR(DisasContext *ctx)
25190 uint32_t pad, XRc, XRb, XRa;
25192 pad = extract32(ctx->opcode, 21, 5);
25193 XRc = extract32(ctx->opcode, 14, 4);
25194 XRb = extract32(ctx->opcode, 10, 4);
25195 XRa = extract32(ctx->opcode, 6, 4);
25197 if (unlikely(pad != 0)) {
25198 /* opcode padding incorrect -> do nothing */
25199 } else if (unlikely(XRa == 0)) {
25200 /* destination is zero register -> do nothing */
25201 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25202 /* both operands zero registers -> just set destination to all 0s */
25203 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25204 } else if (unlikely(XRb == 0)) {
25205 /* XRb zero register -> just set destination to the content of XRc */
25206 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25207 } else if (unlikely(XRc == 0)) {
25208 /* XRc zero register -> just set destination to the content of XRb */
25209 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25210 } else if (unlikely(XRb == XRc)) {
25211 /* both operands same -> just set destination to one of them */
25212 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25213 } else {
25214 /* the most general case */
25215 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25220 * S32XOR XRa, XRb, XRc
25221 * Update XRa with the result of logical bitwise 'xor' operation
25222 * applied to the content of XRb and XRc.
25224 static void gen_mxu_S32XOR(DisasContext *ctx)
25226 uint32_t pad, XRc, XRb, XRa;
25228 pad = extract32(ctx->opcode, 21, 5);
25229 XRc = extract32(ctx->opcode, 14, 4);
25230 XRb = extract32(ctx->opcode, 10, 4);
25231 XRa = extract32(ctx->opcode, 6, 4);
25233 if (unlikely(pad != 0)) {
25234 /* opcode padding incorrect -> do nothing */
25235 } else if (unlikely(XRa == 0)) {
25236 /* destination is zero register -> do nothing */
25237 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25238 /* both operands zero registers -> just set destination to all 0s */
25239 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25240 } else if (unlikely(XRb == 0)) {
25241 /* XRb zero register -> just set destination to the content of XRc */
25242 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25243 } else if (unlikely(XRc == 0)) {
25244 /* XRc zero register -> just set destination to the content of XRb */
25245 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25246 } else if (unlikely(XRb == XRc)) {
25247 /* both operands same -> just set destination to all 0s */
25248 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25249 } else {
25250 /* the most general case */
25251 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25257 * MXU instruction category max/min
25258 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25260 * S32MAX D16MAX Q8MAX
25261 * S32MIN D16MIN Q8MIN
25265 * S32MAX XRa, XRb, XRc
25266 * Update XRa with the maximum of signed 32-bit integers contained
25267 * in XRb and XRc.
25269 * S32MIN XRa, XRb, XRc
25270 * Update XRa with the minimum of signed 32-bit integers contained
25271 * in XRb and XRc.
25273 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25275 uint32_t pad, opc, XRc, XRb, XRa;
25277 pad = extract32(ctx->opcode, 21, 5);
25278 opc = extract32(ctx->opcode, 18, 3);
25279 XRc = extract32(ctx->opcode, 14, 4);
25280 XRb = extract32(ctx->opcode, 10, 4);
25281 XRa = extract32(ctx->opcode, 6, 4);
25283 if (unlikely(pad != 0)) {
25284 /* opcode padding incorrect -> do nothing */
25285 } else if (unlikely(XRa == 0)) {
25286 /* destination is zero register -> do nothing */
25287 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25288 /* both operands zero registers -> just set destination to zero */
25289 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25290 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25291 /* exactly one operand is zero register - find which one is not...*/
25292 uint32_t XRx = XRb ? XRb : XRc;
25293 /* ...and do max/min operation with one operand 0 */
25294 if (opc == OPC_MXU_S32MAX) {
25295 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25296 } else {
25297 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25299 } else if (unlikely(XRb == XRc)) {
25300 /* both operands same -> just set destination to one of them */
25301 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25302 } else {
25303 /* the most general case */
25304 if (opc == OPC_MXU_S32MAX) {
25305 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25306 mxu_gpr[XRc - 1]);
25307 } else {
25308 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25309 mxu_gpr[XRc - 1]);
25315 * D16MAX
25316 * Update XRa with the 16-bit-wise maximums of signed integers
25317 * contained in XRb and XRc.
25319 * D16MIN
25320 * Update XRa with the 16-bit-wise minimums of signed integers
25321 * contained in XRb and XRc.
25323 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25325 uint32_t pad, opc, XRc, XRb, XRa;
25327 pad = extract32(ctx->opcode, 21, 5);
25328 opc = extract32(ctx->opcode, 18, 3);
25329 XRc = extract32(ctx->opcode, 14, 4);
25330 XRb = extract32(ctx->opcode, 10, 4);
25331 XRa = extract32(ctx->opcode, 6, 4);
25333 if (unlikely(pad != 0)) {
25334 /* opcode padding incorrect -> do nothing */
25335 } else if (unlikely(XRc == 0)) {
25336 /* destination is zero register -> do nothing */
25337 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25338 /* both operands zero registers -> just set destination to zero */
25339 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25340 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25341 /* exactly one operand is zero register - find which one is not...*/
25342 uint32_t XRx = XRb ? XRb : XRc;
25343 /* ...and do half-word-wise max/min with one operand 0 */
25344 TCGv_i32 t0 = tcg_temp_new();
25345 TCGv_i32 t1 = tcg_const_i32(0);
25347 /* the left half-word first */
25348 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25349 if (opc == OPC_MXU_D16MAX) {
25350 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25351 } else {
25352 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25355 /* the right half-word */
25356 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25357 /* move half-words to the leftmost position */
25358 tcg_gen_shli_i32(t0, t0, 16);
25359 /* t0 will be max/min of t0 and t1 */
25360 if (opc == OPC_MXU_D16MAX) {
25361 tcg_gen_smax_i32(t0, t0, t1);
25362 } else {
25363 tcg_gen_smin_i32(t0, t0, t1);
25365 /* return resulting half-words to its original position */
25366 tcg_gen_shri_i32(t0, t0, 16);
25367 /* finally update the destination */
25368 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25370 tcg_temp_free(t1);
25371 tcg_temp_free(t0);
25372 } else if (unlikely(XRb == XRc)) {
25373 /* both operands same -> just set destination to one of them */
25374 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25375 } else {
25376 /* the most general case */
25377 TCGv_i32 t0 = tcg_temp_new();
25378 TCGv_i32 t1 = tcg_temp_new();
25380 /* the left half-word first */
25381 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25382 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25383 if (opc == OPC_MXU_D16MAX) {
25384 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25385 } else {
25386 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25389 /* the right half-word */
25390 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25391 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25392 /* move half-words to the leftmost position */
25393 tcg_gen_shli_i32(t0, t0, 16);
25394 tcg_gen_shli_i32(t1, t1, 16);
25395 /* t0 will be max/min of t0 and t1 */
25396 if (opc == OPC_MXU_D16MAX) {
25397 tcg_gen_smax_i32(t0, t0, t1);
25398 } else {
25399 tcg_gen_smin_i32(t0, t0, t1);
25401 /* return resulting half-words to its original position */
25402 tcg_gen_shri_i32(t0, t0, 16);
25403 /* finally update the destination */
25404 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25406 tcg_temp_free(t1);
25407 tcg_temp_free(t0);
25412 * Q8MAX
25413 * Update XRa with the 8-bit-wise maximums of signed integers
25414 * contained in XRb and XRc.
25416 * Q8MIN
25417 * Update XRa with the 8-bit-wise minimums of signed integers
25418 * contained in XRb and XRc.
25420 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25422 uint32_t pad, opc, XRc, XRb, XRa;
25424 pad = extract32(ctx->opcode, 21, 5);
25425 opc = extract32(ctx->opcode, 18, 3);
25426 XRc = extract32(ctx->opcode, 14, 4);
25427 XRb = extract32(ctx->opcode, 10, 4);
25428 XRa = extract32(ctx->opcode, 6, 4);
25430 if (unlikely(pad != 0)) {
25431 /* opcode padding incorrect -> do nothing */
25432 } else if (unlikely(XRa == 0)) {
25433 /* destination is zero register -> do nothing */
25434 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25435 /* both operands zero registers -> just set destination to zero */
25436 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25437 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25438 /* exactly one operand is zero register - make it be the first...*/
25439 uint32_t XRx = XRb ? XRb : XRc;
25440 /* ...and do byte-wise max/min with one operand 0 */
25441 TCGv_i32 t0 = tcg_temp_new();
25442 TCGv_i32 t1 = tcg_const_i32(0);
25443 int32_t i;
25445 /* the leftmost byte (byte 3) first */
25446 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25447 if (opc == OPC_MXU_Q8MAX) {
25448 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25449 } else {
25450 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25453 /* bytes 2, 1, 0 */
25454 for (i = 2; i >= 0; i--) {
25455 /* extract the byte */
25456 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25457 /* move the byte to the leftmost position */
25458 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25459 /* t0 will be max/min of t0 and t1 */
25460 if (opc == OPC_MXU_Q8MAX) {
25461 tcg_gen_smax_i32(t0, t0, t1);
25462 } else {
25463 tcg_gen_smin_i32(t0, t0, t1);
25465 /* return resulting byte to its original position */
25466 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25467 /* finally update the destination */
25468 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25471 tcg_temp_free(t1);
25472 tcg_temp_free(t0);
25473 } else if (unlikely(XRb == XRc)) {
25474 /* both operands same -> just set destination to one of them */
25475 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25476 } else {
25477 /* the most general case */
25478 TCGv_i32 t0 = tcg_temp_new();
25479 TCGv_i32 t1 = tcg_temp_new();
25480 int32_t i;
25482 /* the leftmost bytes (bytes 3) first */
25483 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25484 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25485 if (opc == OPC_MXU_Q8MAX) {
25486 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25487 } else {
25488 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25491 /* bytes 2, 1, 0 */
25492 for (i = 2; i >= 0; i--) {
25493 /* extract corresponding bytes */
25494 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25495 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25496 /* move the bytes to the leftmost position */
25497 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25498 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25499 /* t0 will be max/min of t0 and t1 */
25500 if (opc == OPC_MXU_Q8MAX) {
25501 tcg_gen_smax_i32(t0, t0, t1);
25502 } else {
25503 tcg_gen_smin_i32(t0, t0, t1);
25505 /* return resulting byte to its original position */
25506 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25507 /* finally update the destination */
25508 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25511 tcg_temp_free(t1);
25512 tcg_temp_free(t0);
25518 * MXU instruction category: align
25519 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25521 * S32ALN S32ALNI
25525 * S32ALNI XRc, XRb, XRa, optn3
25526 * Arrange bytes from XRb and XRc according to one of five sets of
25527 * rules determined by optn3, and place the result in XRa.
25529 static void gen_mxu_S32ALNI(DisasContext *ctx)
25531 uint32_t optn3, pad, XRc, XRb, XRa;
25533 optn3 = extract32(ctx->opcode, 23, 3);
25534 pad = extract32(ctx->opcode, 21, 2);
25535 XRc = extract32(ctx->opcode, 14, 4);
25536 XRb = extract32(ctx->opcode, 10, 4);
25537 XRa = extract32(ctx->opcode, 6, 4);
25539 if (unlikely(pad != 0)) {
25540 /* opcode padding incorrect -> do nothing */
25541 } else if (unlikely(XRa == 0)) {
25542 /* destination is zero register -> do nothing */
25543 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25544 /* both operands zero registers -> just set destination to all 0s */
25545 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25546 } else if (unlikely(XRb == 0)) {
25547 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25548 switch (optn3) {
25549 case MXU_OPTN3_PTN0:
25550 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25551 break;
25552 case MXU_OPTN3_PTN1:
25553 case MXU_OPTN3_PTN2:
25554 case MXU_OPTN3_PTN3:
25555 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25556 8 * (4 - optn3));
25557 break;
25558 case MXU_OPTN3_PTN4:
25559 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25560 break;
25562 } else if (unlikely(XRc == 0)) {
25563 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25564 switch (optn3) {
25565 case MXU_OPTN3_PTN0:
25566 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25567 break;
25568 case MXU_OPTN3_PTN1:
25569 case MXU_OPTN3_PTN2:
25570 case MXU_OPTN3_PTN3:
25571 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25572 break;
25573 case MXU_OPTN3_PTN4:
25574 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25575 break;
25577 } else if (unlikely(XRb == XRc)) {
25578 /* both operands same -> just rotation or moving from any of them */
25579 switch (optn3) {
25580 case MXU_OPTN3_PTN0:
25581 case MXU_OPTN3_PTN4:
25582 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25583 break;
25584 case MXU_OPTN3_PTN1:
25585 case MXU_OPTN3_PTN2:
25586 case MXU_OPTN3_PTN3:
25587 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25588 break;
25590 } else {
25591 /* the most general case */
25592 switch (optn3) {
25593 case MXU_OPTN3_PTN0:
25595 /* */
25596 /* XRb XRc */
25597 /* +---------------+ */
25598 /* | A B C D | E F G H */
25599 /* +-------+-------+ */
25600 /* | */
25601 /* XRa */
25602 /* */
25604 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25606 break;
25607 case MXU_OPTN3_PTN1:
25609 /* */
25610 /* XRb XRc */
25611 /* +-------------------+ */
25612 /* A | B C D E | F G H */
25613 /* +---------+---------+ */
25614 /* | */
25615 /* XRa */
25616 /* */
25618 TCGv_i32 t0 = tcg_temp_new();
25619 TCGv_i32 t1 = tcg_temp_new();
25621 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25622 tcg_gen_shli_i32(t0, t0, 8);
25624 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25625 tcg_gen_shri_i32(t1, t1, 24);
25627 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25629 tcg_temp_free(t1);
25630 tcg_temp_free(t0);
25632 break;
25633 case MXU_OPTN3_PTN2:
25635 /* */
25636 /* XRb XRc */
25637 /* +-------------------+ */
25638 /* A B | C D E F | G H */
25639 /* +---------+---------+ */
25640 /* | */
25641 /* XRa */
25642 /* */
25644 TCGv_i32 t0 = tcg_temp_new();
25645 TCGv_i32 t1 = tcg_temp_new();
25647 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25648 tcg_gen_shli_i32(t0, t0, 16);
25650 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25651 tcg_gen_shri_i32(t1, t1, 16);
25653 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25655 tcg_temp_free(t1);
25656 tcg_temp_free(t0);
25658 break;
25659 case MXU_OPTN3_PTN3:
25661 /* */
25662 /* XRb XRc */
25663 /* +-------------------+ */
25664 /* A B C | D E F G | H */
25665 /* +---------+---------+ */
25666 /* | */
25667 /* XRa */
25668 /* */
25670 TCGv_i32 t0 = tcg_temp_new();
25671 TCGv_i32 t1 = tcg_temp_new();
25673 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25674 tcg_gen_shli_i32(t0, t0, 24);
25676 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25677 tcg_gen_shri_i32(t1, t1, 8);
25679 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25681 tcg_temp_free(t1);
25682 tcg_temp_free(t0);
25684 break;
25685 case MXU_OPTN3_PTN4:
25687 /* */
25688 /* XRb XRc */
25689 /* +---------------+ */
25690 /* A B C D | E F G H | */
25691 /* +-------+-------+ */
25692 /* | */
25693 /* XRa */
25694 /* */
25696 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25698 break;
25705 * Decoding engine for MXU
25706 * =======================
25709 static void decode_opc_mxu__pool00(DisasContext *ctx)
25711 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25713 switch (opcode) {
25714 case OPC_MXU_S32MAX:
25715 case OPC_MXU_S32MIN:
25716 gen_mxu_S32MAX_S32MIN(ctx);
25717 break;
25718 case OPC_MXU_D16MAX:
25719 case OPC_MXU_D16MIN:
25720 gen_mxu_D16MAX_D16MIN(ctx);
25721 break;
25722 case OPC_MXU_Q8MAX:
25723 case OPC_MXU_Q8MIN:
25724 gen_mxu_Q8MAX_Q8MIN(ctx);
25725 break;
25726 default:
25727 MIPS_INVAL("decode_opc_mxu");
25728 gen_reserved_instruction(ctx);
25729 break;
25733 static void decode_opc_mxu__pool04(DisasContext *ctx)
25735 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25737 switch (opcode) {
25738 case OPC_MXU_S32LDD:
25739 case OPC_MXU_S32LDDR:
25740 gen_mxu_s32ldd_s32lddr(ctx);
25741 break;
25742 default:
25743 MIPS_INVAL("decode_opc_mxu");
25744 gen_reserved_instruction(ctx);
25745 break;
25749 static void decode_opc_mxu__pool16(DisasContext *ctx)
25751 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25753 switch (opcode) {
25754 case OPC_MXU_S32ALNI:
25755 gen_mxu_S32ALNI(ctx);
25756 break;
25757 case OPC_MXU_S32NOR:
25758 gen_mxu_S32NOR(ctx);
25759 break;
25760 case OPC_MXU_S32AND:
25761 gen_mxu_S32AND(ctx);
25762 break;
25763 case OPC_MXU_S32OR:
25764 gen_mxu_S32OR(ctx);
25765 break;
25766 case OPC_MXU_S32XOR:
25767 gen_mxu_S32XOR(ctx);
25768 break;
25769 default:
25770 MIPS_INVAL("decode_opc_mxu");
25771 gen_reserved_instruction(ctx);
25772 break;
25776 static void decode_opc_mxu__pool19(DisasContext *ctx)
25778 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25780 switch (opcode) {
25781 case OPC_MXU_Q8MUL:
25782 case OPC_MXU_Q8MULSU:
25783 gen_mxu_q8mul_q8mulsu(ctx);
25784 break;
25785 default:
25786 MIPS_INVAL("decode_opc_mxu");
25787 gen_reserved_instruction(ctx);
25788 break;
25793 * Main MXU decoding function
25795 bool decode_ase_mxu(DisasContext *ctx, uint32_t insn)
25797 uint32_t opcode = extract32(insn, 0, 6);
25799 if (opcode == OPC_MXU_S32M2I) {
25800 gen_mxu_s32m2i(ctx);
25801 return true;
25804 if (opcode == OPC_MXU_S32I2M) {
25805 gen_mxu_s32i2m(ctx);
25806 return true;
25810 TCGv t_mxu_cr = tcg_temp_new();
25811 TCGLabel *l_exit = gen_new_label();
25813 gen_load_mxu_cr(t_mxu_cr);
25814 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
25815 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
25817 switch (opcode) {
25818 case OPC_MXU__POOL00:
25819 decode_opc_mxu__pool00(ctx);
25820 break;
25821 case OPC_MXU_D16MUL:
25822 gen_mxu_d16mul(ctx);
25823 break;
25824 case OPC_MXU_D16MAC:
25825 gen_mxu_d16mac(ctx);
25826 break;
25827 case OPC_MXU__POOL04:
25828 decode_opc_mxu__pool04(ctx);
25829 break;
25830 case OPC_MXU_S8LDD:
25831 gen_mxu_s8ldd(ctx);
25832 break;
25833 case OPC_MXU__POOL16:
25834 decode_opc_mxu__pool16(ctx);
25835 break;
25836 case OPC_MXU__POOL19:
25837 decode_opc_mxu__pool19(ctx);
25838 break;
25839 default:
25840 MIPS_INVAL("decode_opc_mxu");
25841 gen_reserved_instruction(ctx);
25844 gen_set_label(l_exit);
25845 tcg_temp_free(t_mxu_cr);
25848 return true;
25851 #endif /* !defined(TARGET_MIPS64) */
25854 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
25856 int rs, rt, rd;
25857 uint32_t op1;
25859 rs = (ctx->opcode >> 21) & 0x1f;
25860 rt = (ctx->opcode >> 16) & 0x1f;
25861 rd = (ctx->opcode >> 11) & 0x1f;
25863 op1 = MASK_SPECIAL2(ctx->opcode);
25864 switch (op1) {
25865 case OPC_MADD: /* Multiply and add/sub */
25866 case OPC_MADDU:
25867 case OPC_MSUB:
25868 case OPC_MSUBU:
25869 check_insn(ctx, ISA_MIPS_R1);
25870 gen_muldiv(ctx, op1, rd & 3, rs, rt);
25871 break;
25872 case OPC_MUL:
25873 gen_arith(ctx, op1, rd, rs, rt);
25874 break;
25875 case OPC_DIV_G_2F:
25876 case OPC_DIVU_G_2F:
25877 case OPC_MULT_G_2F:
25878 case OPC_MULTU_G_2F:
25879 case OPC_MOD_G_2F:
25880 case OPC_MODU_G_2F:
25881 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
25882 gen_loongson_integer(ctx, op1, rd, rs, rt);
25883 break;
25884 case OPC_CLO:
25885 case OPC_CLZ:
25886 check_insn(ctx, ISA_MIPS_R1);
25887 gen_cl(ctx, op1, rd, rs);
25888 break;
25889 case OPC_SDBBP:
25890 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
25891 gen_helper_do_semihosting(cpu_env);
25892 } else {
25894 * XXX: not clear which exception should be raised
25895 * when in debug mode...
25897 check_insn(ctx, ISA_MIPS_R1);
25898 generate_exception_end(ctx, EXCP_DBp);
25900 break;
25901 #if defined(TARGET_MIPS64)
25902 case OPC_DCLO:
25903 case OPC_DCLZ:
25904 check_insn(ctx, ISA_MIPS_R1);
25905 check_mips_64(ctx);
25906 gen_cl(ctx, op1, rd, rs);
25907 break;
25908 case OPC_DMULT_G_2F:
25909 case OPC_DMULTU_G_2F:
25910 case OPC_DDIV_G_2F:
25911 case OPC_DDIVU_G_2F:
25912 case OPC_DMOD_G_2F:
25913 case OPC_DMODU_G_2F:
25914 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
25915 gen_loongson_integer(ctx, op1, rd, rs, rt);
25916 break;
25917 #endif
25918 default: /* Invalid */
25919 MIPS_INVAL("special2_legacy");
25920 gen_reserved_instruction(ctx);
25921 break;
25925 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
25927 int rs, rt, rd, sa;
25928 uint32_t op1, op2;
25929 int16_t imm;
25931 rs = (ctx->opcode >> 21) & 0x1f;
25932 rt = (ctx->opcode >> 16) & 0x1f;
25933 rd = (ctx->opcode >> 11) & 0x1f;
25934 sa = (ctx->opcode >> 6) & 0x1f;
25935 imm = (int16_t)ctx->opcode >> 7;
25937 op1 = MASK_SPECIAL3(ctx->opcode);
25938 switch (op1) {
25939 case R6_OPC_PREF:
25940 if (rt >= 24) {
25941 /* hint codes 24-31 are reserved and signal RI */
25942 gen_reserved_instruction(ctx);
25944 /* Treat as NOP. */
25945 break;
25946 case R6_OPC_CACHE:
25947 check_cp0_enabled(ctx);
25948 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25949 gen_cache_operation(ctx, rt, rs, imm);
25951 break;
25952 case R6_OPC_SC:
25953 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
25954 break;
25955 case R6_OPC_LL:
25956 gen_ld(ctx, op1, rt, rs, imm);
25957 break;
25958 case OPC_BSHFL:
25960 if (rd == 0) {
25961 /* Treat as NOP. */
25962 break;
25964 op2 = MASK_BSHFL(ctx->opcode);
25965 switch (op2) {
25966 case OPC_ALIGN:
25967 case OPC_ALIGN_1:
25968 case OPC_ALIGN_2:
25969 case OPC_ALIGN_3:
25970 gen_align(ctx, 32, rd, rs, rt, sa & 3);
25971 break;
25972 case OPC_BITSWAP:
25973 gen_bitswap(ctx, op2, rd, rt);
25974 break;
25977 break;
25978 #ifndef CONFIG_USER_ONLY
25979 case OPC_GINV:
25980 if (unlikely(ctx->gi <= 1)) {
25981 gen_reserved_instruction(ctx);
25983 check_cp0_enabled(ctx);
25984 switch ((ctx->opcode >> 6) & 3) {
25985 case 0: /* GINVI */
25986 /* Treat as NOP. */
25987 break;
25988 case 2: /* GINVT */
25989 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
25990 break;
25991 default:
25992 gen_reserved_instruction(ctx);
25993 break;
25995 break;
25996 #endif
25997 #if defined(TARGET_MIPS64)
25998 case R6_OPC_SCD:
25999 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
26000 break;
26001 case R6_OPC_LLD:
26002 gen_ld(ctx, op1, rt, rs, imm);
26003 break;
26004 case OPC_DBSHFL:
26005 check_mips_64(ctx);
26007 if (rd == 0) {
26008 /* Treat as NOP. */
26009 break;
26011 op2 = MASK_DBSHFL(ctx->opcode);
26012 switch (op2) {
26013 case OPC_DALIGN:
26014 case OPC_DALIGN_1:
26015 case OPC_DALIGN_2:
26016 case OPC_DALIGN_3:
26017 case OPC_DALIGN_4:
26018 case OPC_DALIGN_5:
26019 case OPC_DALIGN_6:
26020 case OPC_DALIGN_7:
26021 gen_align(ctx, 64, rd, rs, rt, sa & 7);
26022 break;
26023 case OPC_DBITSWAP:
26024 gen_bitswap(ctx, op2, rd, rt);
26025 break;
26029 break;
26030 #endif
26031 default: /* Invalid */
26032 MIPS_INVAL("special3_r6");
26033 gen_reserved_instruction(ctx);
26034 break;
26038 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
26040 int rs, rt, rd;
26041 uint32_t op1, op2;
26043 rs = (ctx->opcode >> 21) & 0x1f;
26044 rt = (ctx->opcode >> 16) & 0x1f;
26045 rd = (ctx->opcode >> 11) & 0x1f;
26047 op1 = MASK_SPECIAL3(ctx->opcode);
26048 switch (op1) {
26049 case OPC_DIV_G_2E:
26050 case OPC_DIVU_G_2E:
26051 case OPC_MOD_G_2E:
26052 case OPC_MODU_G_2E:
26053 case OPC_MULT_G_2E:
26054 case OPC_MULTU_G_2E:
26056 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
26057 * the same mask and op1.
26059 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
26060 op2 = MASK_ADDUH_QB(ctx->opcode);
26061 switch (op2) {
26062 case OPC_ADDUH_QB:
26063 case OPC_ADDUH_R_QB:
26064 case OPC_ADDQH_PH:
26065 case OPC_ADDQH_R_PH:
26066 case OPC_ADDQH_W:
26067 case OPC_ADDQH_R_W:
26068 case OPC_SUBUH_QB:
26069 case OPC_SUBUH_R_QB:
26070 case OPC_SUBQH_PH:
26071 case OPC_SUBQH_R_PH:
26072 case OPC_SUBQH_W:
26073 case OPC_SUBQH_R_W:
26074 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26075 break;
26076 case OPC_MUL_PH:
26077 case OPC_MUL_S_PH:
26078 case OPC_MULQ_S_W:
26079 case OPC_MULQ_RS_W:
26080 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26081 break;
26082 default:
26083 MIPS_INVAL("MASK ADDUH.QB");
26084 gen_reserved_instruction(ctx);
26085 break;
26087 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
26088 gen_loongson_integer(ctx, op1, rd, rs, rt);
26089 } else {
26090 gen_reserved_instruction(ctx);
26092 break;
26093 case OPC_LX_DSP:
26094 op2 = MASK_LX(ctx->opcode);
26095 switch (op2) {
26096 #if defined(TARGET_MIPS64)
26097 case OPC_LDX:
26098 #endif
26099 case OPC_LBUX:
26100 case OPC_LHX:
26101 case OPC_LWX:
26102 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
26103 break;
26104 default: /* Invalid */
26105 MIPS_INVAL("MASK LX");
26106 gen_reserved_instruction(ctx);
26107 break;
26109 break;
26110 case OPC_ABSQ_S_PH_DSP:
26111 op2 = MASK_ABSQ_S_PH(ctx->opcode);
26112 switch (op2) {
26113 case OPC_ABSQ_S_QB:
26114 case OPC_ABSQ_S_PH:
26115 case OPC_ABSQ_S_W:
26116 case OPC_PRECEQ_W_PHL:
26117 case OPC_PRECEQ_W_PHR:
26118 case OPC_PRECEQU_PH_QBL:
26119 case OPC_PRECEQU_PH_QBR:
26120 case OPC_PRECEQU_PH_QBLA:
26121 case OPC_PRECEQU_PH_QBRA:
26122 case OPC_PRECEU_PH_QBL:
26123 case OPC_PRECEU_PH_QBR:
26124 case OPC_PRECEU_PH_QBLA:
26125 case OPC_PRECEU_PH_QBRA:
26126 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26127 break;
26128 case OPC_BITREV:
26129 case OPC_REPL_QB:
26130 case OPC_REPLV_QB:
26131 case OPC_REPL_PH:
26132 case OPC_REPLV_PH:
26133 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
26134 break;
26135 default:
26136 MIPS_INVAL("MASK ABSQ_S.PH");
26137 gen_reserved_instruction(ctx);
26138 break;
26140 break;
26141 case OPC_ADDU_QB_DSP:
26142 op2 = MASK_ADDU_QB(ctx->opcode);
26143 switch (op2) {
26144 case OPC_ADDQ_PH:
26145 case OPC_ADDQ_S_PH:
26146 case OPC_ADDQ_S_W:
26147 case OPC_ADDU_QB:
26148 case OPC_ADDU_S_QB:
26149 case OPC_ADDU_PH:
26150 case OPC_ADDU_S_PH:
26151 case OPC_SUBQ_PH:
26152 case OPC_SUBQ_S_PH:
26153 case OPC_SUBQ_S_W:
26154 case OPC_SUBU_QB:
26155 case OPC_SUBU_S_QB:
26156 case OPC_SUBU_PH:
26157 case OPC_SUBU_S_PH:
26158 case OPC_ADDSC:
26159 case OPC_ADDWC:
26160 case OPC_MODSUB:
26161 case OPC_RADDU_W_QB:
26162 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26163 break;
26164 case OPC_MULEU_S_PH_QBL:
26165 case OPC_MULEU_S_PH_QBR:
26166 case OPC_MULQ_RS_PH:
26167 case OPC_MULEQ_S_W_PHL:
26168 case OPC_MULEQ_S_W_PHR:
26169 case OPC_MULQ_S_PH:
26170 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26171 break;
26172 default: /* Invalid */
26173 MIPS_INVAL("MASK ADDU.QB");
26174 gen_reserved_instruction(ctx);
26175 break;
26178 break;
26179 case OPC_CMPU_EQ_QB_DSP:
26180 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
26181 switch (op2) {
26182 case OPC_PRECR_SRA_PH_W:
26183 case OPC_PRECR_SRA_R_PH_W:
26184 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
26185 break;
26186 case OPC_PRECR_QB_PH:
26187 case OPC_PRECRQ_QB_PH:
26188 case OPC_PRECRQ_PH_W:
26189 case OPC_PRECRQ_RS_PH_W:
26190 case OPC_PRECRQU_S_QB_PH:
26191 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26192 break;
26193 case OPC_CMPU_EQ_QB:
26194 case OPC_CMPU_LT_QB:
26195 case OPC_CMPU_LE_QB:
26196 case OPC_CMP_EQ_PH:
26197 case OPC_CMP_LT_PH:
26198 case OPC_CMP_LE_PH:
26199 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
26200 break;
26201 case OPC_CMPGU_EQ_QB:
26202 case OPC_CMPGU_LT_QB:
26203 case OPC_CMPGU_LE_QB:
26204 case OPC_CMPGDU_EQ_QB:
26205 case OPC_CMPGDU_LT_QB:
26206 case OPC_CMPGDU_LE_QB:
26207 case OPC_PICK_QB:
26208 case OPC_PICK_PH:
26209 case OPC_PACKRL_PH:
26210 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
26211 break;
26212 default: /* Invalid */
26213 MIPS_INVAL("MASK CMPU.EQ.QB");
26214 gen_reserved_instruction(ctx);
26215 break;
26217 break;
26218 case OPC_SHLL_QB_DSP:
26219 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
26220 break;
26221 case OPC_DPA_W_PH_DSP:
26222 op2 = MASK_DPA_W_PH(ctx->opcode);
26223 switch (op2) {
26224 case OPC_DPAU_H_QBL:
26225 case OPC_DPAU_H_QBR:
26226 case OPC_DPSU_H_QBL:
26227 case OPC_DPSU_H_QBR:
26228 case OPC_DPA_W_PH:
26229 case OPC_DPAX_W_PH:
26230 case OPC_DPAQ_S_W_PH:
26231 case OPC_DPAQX_S_W_PH:
26232 case OPC_DPAQX_SA_W_PH:
26233 case OPC_DPS_W_PH:
26234 case OPC_DPSX_W_PH:
26235 case OPC_DPSQ_S_W_PH:
26236 case OPC_DPSQX_S_W_PH:
26237 case OPC_DPSQX_SA_W_PH:
26238 case OPC_MULSAQ_S_W_PH:
26239 case OPC_DPAQ_SA_L_W:
26240 case OPC_DPSQ_SA_L_W:
26241 case OPC_MAQ_S_W_PHL:
26242 case OPC_MAQ_S_W_PHR:
26243 case OPC_MAQ_SA_W_PHL:
26244 case OPC_MAQ_SA_W_PHR:
26245 case OPC_MULSA_W_PH:
26246 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26247 break;
26248 default: /* Invalid */
26249 MIPS_INVAL("MASK DPAW.PH");
26250 gen_reserved_instruction(ctx);
26251 break;
26253 break;
26254 case OPC_INSV_DSP:
26255 op2 = MASK_INSV(ctx->opcode);
26256 switch (op2) {
26257 case OPC_INSV:
26258 check_dsp(ctx);
26260 TCGv t0, t1;
26262 if (rt == 0) {
26263 break;
26266 t0 = tcg_temp_new();
26267 t1 = tcg_temp_new();
26269 gen_load_gpr(t0, rt);
26270 gen_load_gpr(t1, rs);
26272 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
26274 tcg_temp_free(t0);
26275 tcg_temp_free(t1);
26276 break;
26278 default: /* Invalid */
26279 MIPS_INVAL("MASK INSV");
26280 gen_reserved_instruction(ctx);
26281 break;
26283 break;
26284 case OPC_APPEND_DSP:
26285 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
26286 break;
26287 case OPC_EXTR_W_DSP:
26288 op2 = MASK_EXTR_W(ctx->opcode);
26289 switch (op2) {
26290 case OPC_EXTR_W:
26291 case OPC_EXTR_R_W:
26292 case OPC_EXTR_RS_W:
26293 case OPC_EXTR_S_H:
26294 case OPC_EXTRV_S_H:
26295 case OPC_EXTRV_W:
26296 case OPC_EXTRV_R_W:
26297 case OPC_EXTRV_RS_W:
26298 case OPC_EXTP:
26299 case OPC_EXTPV:
26300 case OPC_EXTPDP:
26301 case OPC_EXTPDPV:
26302 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
26303 break;
26304 case OPC_RDDSP:
26305 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
26306 break;
26307 case OPC_SHILO:
26308 case OPC_SHILOV:
26309 case OPC_MTHLIP:
26310 case OPC_WRDSP:
26311 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
26312 break;
26313 default: /* Invalid */
26314 MIPS_INVAL("MASK EXTR.W");
26315 gen_reserved_instruction(ctx);
26316 break;
26318 break;
26319 #if defined(TARGET_MIPS64)
26320 case OPC_DDIV_G_2E:
26321 case OPC_DDIVU_G_2E:
26322 case OPC_DMULT_G_2E:
26323 case OPC_DMULTU_G_2E:
26324 case OPC_DMOD_G_2E:
26325 case OPC_DMODU_G_2E:
26326 check_insn(ctx, INSN_LOONGSON2E);
26327 gen_loongson_integer(ctx, op1, rd, rs, rt);
26328 break;
26329 case OPC_ABSQ_S_QH_DSP:
26330 op2 = MASK_ABSQ_S_QH(ctx->opcode);
26331 switch (op2) {
26332 case OPC_PRECEQ_L_PWL:
26333 case OPC_PRECEQ_L_PWR:
26334 case OPC_PRECEQ_PW_QHL:
26335 case OPC_PRECEQ_PW_QHR:
26336 case OPC_PRECEQ_PW_QHLA:
26337 case OPC_PRECEQ_PW_QHRA:
26338 case OPC_PRECEQU_QH_OBL:
26339 case OPC_PRECEQU_QH_OBR:
26340 case OPC_PRECEQU_QH_OBLA:
26341 case OPC_PRECEQU_QH_OBRA:
26342 case OPC_PRECEU_QH_OBL:
26343 case OPC_PRECEU_QH_OBR:
26344 case OPC_PRECEU_QH_OBLA:
26345 case OPC_PRECEU_QH_OBRA:
26346 case OPC_ABSQ_S_OB:
26347 case OPC_ABSQ_S_PW:
26348 case OPC_ABSQ_S_QH:
26349 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26350 break;
26351 case OPC_REPL_OB:
26352 case OPC_REPL_PW:
26353 case OPC_REPL_QH:
26354 case OPC_REPLV_OB:
26355 case OPC_REPLV_PW:
26356 case OPC_REPLV_QH:
26357 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
26358 break;
26359 default: /* Invalid */
26360 MIPS_INVAL("MASK ABSQ_S.QH");
26361 gen_reserved_instruction(ctx);
26362 break;
26364 break;
26365 case OPC_ADDU_OB_DSP:
26366 op2 = MASK_ADDU_OB(ctx->opcode);
26367 switch (op2) {
26368 case OPC_RADDU_L_OB:
26369 case OPC_SUBQ_PW:
26370 case OPC_SUBQ_S_PW:
26371 case OPC_SUBQ_QH:
26372 case OPC_SUBQ_S_QH:
26373 case OPC_SUBU_OB:
26374 case OPC_SUBU_S_OB:
26375 case OPC_SUBU_QH:
26376 case OPC_SUBU_S_QH:
26377 case OPC_SUBUH_OB:
26378 case OPC_SUBUH_R_OB:
26379 case OPC_ADDQ_PW:
26380 case OPC_ADDQ_S_PW:
26381 case OPC_ADDQ_QH:
26382 case OPC_ADDQ_S_QH:
26383 case OPC_ADDU_OB:
26384 case OPC_ADDU_S_OB:
26385 case OPC_ADDU_QH:
26386 case OPC_ADDU_S_QH:
26387 case OPC_ADDUH_OB:
26388 case OPC_ADDUH_R_OB:
26389 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26390 break;
26391 case OPC_MULEQ_S_PW_QHL:
26392 case OPC_MULEQ_S_PW_QHR:
26393 case OPC_MULEU_S_QH_OBL:
26394 case OPC_MULEU_S_QH_OBR:
26395 case OPC_MULQ_RS_QH:
26396 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26397 break;
26398 default: /* Invalid */
26399 MIPS_INVAL("MASK ADDU.OB");
26400 gen_reserved_instruction(ctx);
26401 break;
26403 break;
26404 case OPC_CMPU_EQ_OB_DSP:
26405 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
26406 switch (op2) {
26407 case OPC_PRECR_SRA_QH_PW:
26408 case OPC_PRECR_SRA_R_QH_PW:
26409 /* Return value is rt. */
26410 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
26411 break;
26412 case OPC_PRECR_OB_QH:
26413 case OPC_PRECRQ_OB_QH:
26414 case OPC_PRECRQ_PW_L:
26415 case OPC_PRECRQ_QH_PW:
26416 case OPC_PRECRQ_RS_QH_PW:
26417 case OPC_PRECRQU_S_OB_QH:
26418 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26419 break;
26420 case OPC_CMPU_EQ_OB:
26421 case OPC_CMPU_LT_OB:
26422 case OPC_CMPU_LE_OB:
26423 case OPC_CMP_EQ_QH:
26424 case OPC_CMP_LT_QH:
26425 case OPC_CMP_LE_QH:
26426 case OPC_CMP_EQ_PW:
26427 case OPC_CMP_LT_PW:
26428 case OPC_CMP_LE_PW:
26429 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
26430 break;
26431 case OPC_CMPGDU_EQ_OB:
26432 case OPC_CMPGDU_LT_OB:
26433 case OPC_CMPGDU_LE_OB:
26434 case OPC_CMPGU_EQ_OB:
26435 case OPC_CMPGU_LT_OB:
26436 case OPC_CMPGU_LE_OB:
26437 case OPC_PACKRL_PW:
26438 case OPC_PICK_OB:
26439 case OPC_PICK_PW:
26440 case OPC_PICK_QH:
26441 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
26442 break;
26443 default: /* Invalid */
26444 MIPS_INVAL("MASK CMPU_EQ.OB");
26445 gen_reserved_instruction(ctx);
26446 break;
26448 break;
26449 case OPC_DAPPEND_DSP:
26450 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
26451 break;
26452 case OPC_DEXTR_W_DSP:
26453 op2 = MASK_DEXTR_W(ctx->opcode);
26454 switch (op2) {
26455 case OPC_DEXTP:
26456 case OPC_DEXTPDP:
26457 case OPC_DEXTPDPV:
26458 case OPC_DEXTPV:
26459 case OPC_DEXTR_L:
26460 case OPC_DEXTR_R_L:
26461 case OPC_DEXTR_RS_L:
26462 case OPC_DEXTR_W:
26463 case OPC_DEXTR_R_W:
26464 case OPC_DEXTR_RS_W:
26465 case OPC_DEXTR_S_H:
26466 case OPC_DEXTRV_L:
26467 case OPC_DEXTRV_R_L:
26468 case OPC_DEXTRV_RS_L:
26469 case OPC_DEXTRV_S_H:
26470 case OPC_DEXTRV_W:
26471 case OPC_DEXTRV_R_W:
26472 case OPC_DEXTRV_RS_W:
26473 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
26474 break;
26475 case OPC_DMTHLIP:
26476 case OPC_DSHILO:
26477 case OPC_DSHILOV:
26478 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
26479 break;
26480 default: /* Invalid */
26481 MIPS_INVAL("MASK EXTR.W");
26482 gen_reserved_instruction(ctx);
26483 break;
26485 break;
26486 case OPC_DPAQ_W_QH_DSP:
26487 op2 = MASK_DPAQ_W_QH(ctx->opcode);
26488 switch (op2) {
26489 case OPC_DPAU_H_OBL:
26490 case OPC_DPAU_H_OBR:
26491 case OPC_DPSU_H_OBL:
26492 case OPC_DPSU_H_OBR:
26493 case OPC_DPA_W_QH:
26494 case OPC_DPAQ_S_W_QH:
26495 case OPC_DPS_W_QH:
26496 case OPC_DPSQ_S_W_QH:
26497 case OPC_MULSAQ_S_W_QH:
26498 case OPC_DPAQ_SA_L_PW:
26499 case OPC_DPSQ_SA_L_PW:
26500 case OPC_MULSAQ_S_L_PW:
26501 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26502 break;
26503 case OPC_MAQ_S_W_QHLL:
26504 case OPC_MAQ_S_W_QHLR:
26505 case OPC_MAQ_S_W_QHRL:
26506 case OPC_MAQ_S_W_QHRR:
26507 case OPC_MAQ_SA_W_QHLL:
26508 case OPC_MAQ_SA_W_QHLR:
26509 case OPC_MAQ_SA_W_QHRL:
26510 case OPC_MAQ_SA_W_QHRR:
26511 case OPC_MAQ_S_L_PWL:
26512 case OPC_MAQ_S_L_PWR:
26513 case OPC_DMADD:
26514 case OPC_DMADDU:
26515 case OPC_DMSUB:
26516 case OPC_DMSUBU:
26517 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26518 break;
26519 default: /* Invalid */
26520 MIPS_INVAL("MASK DPAQ.W.QH");
26521 gen_reserved_instruction(ctx);
26522 break;
26524 break;
26525 case OPC_DINSV_DSP:
26526 op2 = MASK_INSV(ctx->opcode);
26527 switch (op2) {
26528 case OPC_DINSV:
26530 TCGv t0, t1;
26532 if (rt == 0) {
26533 break;
26535 check_dsp(ctx);
26537 t0 = tcg_temp_new();
26538 t1 = tcg_temp_new();
26540 gen_load_gpr(t0, rt);
26541 gen_load_gpr(t1, rs);
26543 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
26545 tcg_temp_free(t0);
26546 tcg_temp_free(t1);
26547 break;
26549 default: /* Invalid */
26550 MIPS_INVAL("MASK DINSV");
26551 gen_reserved_instruction(ctx);
26552 break;
26554 break;
26555 case OPC_SHLL_OB_DSP:
26556 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
26557 break;
26558 #endif
26559 default: /* Invalid */
26560 MIPS_INVAL("special3_legacy");
26561 gen_reserved_instruction(ctx);
26562 break;
26567 #if defined(TARGET_MIPS64)
26569 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
26571 uint32_t opc = MASK_MMI0(ctx->opcode);
26573 switch (opc) {
26574 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
26575 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
26576 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
26577 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
26578 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
26579 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
26580 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
26581 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
26582 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
26583 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
26584 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
26585 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
26586 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
26587 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
26588 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
26589 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
26590 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
26591 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
26592 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
26593 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
26594 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
26595 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
26596 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
26597 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
26598 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
26599 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI0 */
26600 break;
26601 default:
26602 MIPS_INVAL("TX79 MMI class MMI0");
26603 gen_reserved_instruction(ctx);
26604 break;
26608 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
26610 uint32_t opc = MASK_MMI1(ctx->opcode);
26612 switch (opc) {
26613 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
26614 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
26615 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
26616 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
26617 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
26618 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
26619 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
26620 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
26621 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
26622 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
26623 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
26624 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
26625 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
26626 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
26627 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
26628 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
26629 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
26630 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
26631 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI1 */
26632 break;
26633 default:
26634 MIPS_INVAL("TX79 MMI class MMI1");
26635 gen_reserved_instruction(ctx);
26636 break;
26640 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
26642 uint32_t opc = MASK_MMI2(ctx->opcode);
26644 switch (opc) {
26645 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
26646 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
26647 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
26648 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
26649 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
26650 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
26651 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
26652 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
26653 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
26654 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
26655 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
26656 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
26657 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
26658 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
26659 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
26660 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
26661 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
26662 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
26663 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
26664 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
26665 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
26666 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI2 */
26667 break;
26668 case MMI_OPC_2_PCPYLD:
26669 gen_mmi_pcpyld(ctx);
26670 break;
26671 default:
26672 MIPS_INVAL("TX79 MMI class MMI2");
26673 gen_reserved_instruction(ctx);
26674 break;
26678 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
26680 uint32_t opc = MASK_MMI3(ctx->opcode);
26682 switch (opc) {
26683 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
26684 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
26685 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
26686 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
26687 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
26688 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
26689 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
26690 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
26691 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
26692 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
26693 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
26694 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI3 */
26695 break;
26696 case MMI_OPC_3_PCPYH:
26697 gen_mmi_pcpyh(ctx);
26698 break;
26699 case MMI_OPC_3_PCPYUD:
26700 gen_mmi_pcpyud(ctx);
26701 break;
26702 default:
26703 MIPS_INVAL("TX79 MMI class MMI3");
26704 gen_reserved_instruction(ctx);
26705 break;
26709 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
26711 uint32_t opc = MASK_MMI(ctx->opcode);
26712 int rs = extract32(ctx->opcode, 21, 5);
26713 int rt = extract32(ctx->opcode, 16, 5);
26714 int rd = extract32(ctx->opcode, 11, 5);
26716 switch (opc) {
26717 case MMI_OPC_CLASS_MMI0:
26718 decode_mmi0(env, ctx);
26719 break;
26720 case MMI_OPC_CLASS_MMI1:
26721 decode_mmi1(env, ctx);
26722 break;
26723 case MMI_OPC_CLASS_MMI2:
26724 decode_mmi2(env, ctx);
26725 break;
26726 case MMI_OPC_CLASS_MMI3:
26727 decode_mmi3(env, ctx);
26728 break;
26729 case MMI_OPC_MULT1:
26730 case MMI_OPC_MULTU1:
26731 case MMI_OPC_MADD:
26732 case MMI_OPC_MADDU:
26733 case MMI_OPC_MADD1:
26734 case MMI_OPC_MADDU1:
26735 gen_mul_txx9(ctx, opc, rd, rs, rt);
26736 break;
26737 case MMI_OPC_DIV1:
26738 case MMI_OPC_DIVU1:
26739 gen_div1_tx79(ctx, opc, rs, rt);
26740 break;
26741 case MMI_OPC_MTLO1:
26742 case MMI_OPC_MTHI1:
26743 gen_HILO1_tx79(ctx, opc, rs);
26744 break;
26745 case MMI_OPC_MFLO1:
26746 case MMI_OPC_MFHI1:
26747 gen_HILO1_tx79(ctx, opc, rd);
26748 break;
26749 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
26750 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
26751 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
26752 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
26753 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
26754 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
26755 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
26756 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
26757 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
26758 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI */
26759 break;
26760 default:
26761 MIPS_INVAL("TX79 MMI class");
26762 gen_reserved_instruction(ctx);
26763 break;
26767 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
26769 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_LQ */
26772 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
26774 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
26778 * The TX79-specific instruction Store Quadword
26780 * +--------+-------+-------+------------------------+
26781 * | 011111 | base | rt | offset | SQ
26782 * +--------+-------+-------+------------------------+
26783 * 6 5 5 16
26785 * has the same opcode as the Read Hardware Register instruction
26787 * +--------+-------+-------+-------+-------+--------+
26788 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
26789 * +--------+-------+-------+-------+-------+--------+
26790 * 6 5 5 5 5 6
26792 * that is required, trapped and emulated by the Linux kernel. However, all
26793 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
26794 * offset is odd. Therefore all valid SQ instructions can execute normally.
26795 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
26796 * between SQ and RDHWR, as the Linux kernel does.
26798 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
26800 int base = extract32(ctx->opcode, 21, 5);
26801 int rt = extract32(ctx->opcode, 16, 5);
26802 int offset = extract32(ctx->opcode, 0, 16);
26804 #ifdef CONFIG_USER_ONLY
26805 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
26806 uint32_t op2 = extract32(ctx->opcode, 6, 5);
26808 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
26809 int rd = extract32(ctx->opcode, 11, 5);
26811 gen_rdhwr(ctx, rt, rd, 0);
26812 return;
26814 #endif
26816 gen_mmi_sq(ctx, base, rt, offset);
26819 #endif
26821 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
26823 int rs, rt, rd, sa;
26824 uint32_t op1, op2;
26825 int16_t imm;
26827 rs = (ctx->opcode >> 21) & 0x1f;
26828 rt = (ctx->opcode >> 16) & 0x1f;
26829 rd = (ctx->opcode >> 11) & 0x1f;
26830 sa = (ctx->opcode >> 6) & 0x1f;
26831 imm = sextract32(ctx->opcode, 7, 9);
26833 op1 = MASK_SPECIAL3(ctx->opcode);
26836 * EVA loads and stores overlap Loongson 2E instructions decoded by
26837 * decode_opc_special3_legacy(), so be careful to allow their decoding when
26838 * EVA is absent.
26840 if (ctx->eva) {
26841 switch (op1) {
26842 case OPC_LWLE:
26843 case OPC_LWRE:
26844 case OPC_LBUE:
26845 case OPC_LHUE:
26846 case OPC_LBE:
26847 case OPC_LHE:
26848 case OPC_LLE:
26849 case OPC_LWE:
26850 check_cp0_enabled(ctx);
26851 gen_ld(ctx, op1, rt, rs, imm);
26852 return;
26853 case OPC_SWLE:
26854 case OPC_SWRE:
26855 case OPC_SBE:
26856 case OPC_SHE:
26857 case OPC_SWE:
26858 check_cp0_enabled(ctx);
26859 gen_st(ctx, op1, rt, rs, imm);
26860 return;
26861 case OPC_SCE:
26862 check_cp0_enabled(ctx);
26863 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
26864 return;
26865 case OPC_CACHEE:
26866 check_cp0_enabled(ctx);
26867 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26868 gen_cache_operation(ctx, rt, rs, imm);
26870 /* Treat as NOP. */
26871 return;
26872 case OPC_PREFE:
26873 check_cp0_enabled(ctx);
26874 /* Treat as NOP. */
26875 return;
26879 switch (op1) {
26880 case OPC_EXT:
26881 case OPC_INS:
26882 check_insn(ctx, ISA_MIPS_R2);
26883 gen_bitops(ctx, op1, rt, rs, sa, rd);
26884 break;
26885 case OPC_BSHFL:
26886 op2 = MASK_BSHFL(ctx->opcode);
26887 switch (op2) {
26888 case OPC_ALIGN:
26889 case OPC_ALIGN_1:
26890 case OPC_ALIGN_2:
26891 case OPC_ALIGN_3:
26892 case OPC_BITSWAP:
26893 check_insn(ctx, ISA_MIPS_R6);
26894 decode_opc_special3_r6(env, ctx);
26895 break;
26896 default:
26897 check_insn(ctx, ISA_MIPS_R2);
26898 gen_bshfl(ctx, op2, rt, rd);
26899 break;
26901 break;
26902 #if defined(TARGET_MIPS64)
26903 case OPC_DEXTM:
26904 case OPC_DEXTU:
26905 case OPC_DEXT:
26906 case OPC_DINSM:
26907 case OPC_DINSU:
26908 case OPC_DINS:
26909 check_insn(ctx, ISA_MIPS_R2);
26910 check_mips_64(ctx);
26911 gen_bitops(ctx, op1, rt, rs, sa, rd);
26912 break;
26913 case OPC_DBSHFL:
26914 op2 = MASK_DBSHFL(ctx->opcode);
26915 switch (op2) {
26916 case OPC_DALIGN:
26917 case OPC_DALIGN_1:
26918 case OPC_DALIGN_2:
26919 case OPC_DALIGN_3:
26920 case OPC_DALIGN_4:
26921 case OPC_DALIGN_5:
26922 case OPC_DALIGN_6:
26923 case OPC_DALIGN_7:
26924 case OPC_DBITSWAP:
26925 check_insn(ctx, ISA_MIPS_R6);
26926 decode_opc_special3_r6(env, ctx);
26927 break;
26928 default:
26929 check_insn(ctx, ISA_MIPS_R2);
26930 check_mips_64(ctx);
26931 op2 = MASK_DBSHFL(ctx->opcode);
26932 gen_bshfl(ctx, op2, rt, rd);
26933 break;
26935 break;
26936 #endif
26937 case OPC_RDHWR:
26938 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
26939 break;
26940 case OPC_FORK:
26941 check_mt(ctx);
26943 TCGv t0 = tcg_temp_new();
26944 TCGv t1 = tcg_temp_new();
26946 gen_load_gpr(t0, rt);
26947 gen_load_gpr(t1, rs);
26948 gen_helper_fork(t0, t1);
26949 tcg_temp_free(t0);
26950 tcg_temp_free(t1);
26952 break;
26953 case OPC_YIELD:
26954 check_mt(ctx);
26956 TCGv t0 = tcg_temp_new();
26958 gen_load_gpr(t0, rs);
26959 gen_helper_yield(t0, cpu_env, t0);
26960 gen_store_gpr(t0, rd);
26961 tcg_temp_free(t0);
26963 break;
26964 default:
26965 if (ctx->insn_flags & ISA_MIPS_R6) {
26966 decode_opc_special3_r6(env, ctx);
26967 } else {
26968 decode_opc_special3_legacy(env, ctx);
26973 static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
26975 int32_t offset;
26976 int rs, rt, rd, sa;
26977 uint32_t op, op1;
26978 int16_t imm;
26980 op = MASK_OP_MAJOR(ctx->opcode);
26981 rs = (ctx->opcode >> 21) & 0x1f;
26982 rt = (ctx->opcode >> 16) & 0x1f;
26983 rd = (ctx->opcode >> 11) & 0x1f;
26984 sa = (ctx->opcode >> 6) & 0x1f;
26985 imm = (int16_t)ctx->opcode;
26986 switch (op) {
26987 case OPC_SPECIAL:
26988 decode_opc_special(env, ctx);
26989 break;
26990 case OPC_SPECIAL2:
26991 #if defined(TARGET_MIPS64)
26992 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
26993 decode_mmi(env, ctx);
26994 break;
26996 #endif
26997 if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) {
26998 if (MASK_SPECIAL2(ctx->opcode) == OPC_MUL) {
26999 gen_arith(ctx, OPC_MUL, rd, rs, rt);
27000 } else {
27001 decode_ase_mxu(ctx, ctx->opcode);
27003 break;
27005 decode_opc_special2_legacy(env, ctx);
27006 break;
27007 case OPC_SPECIAL3:
27008 #if defined(TARGET_MIPS64)
27009 if (ctx->insn_flags & INSN_R5900) {
27010 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
27011 } else {
27012 decode_opc_special3(env, ctx);
27014 #else
27015 decode_opc_special3(env, ctx);
27016 #endif
27017 break;
27018 case OPC_REGIMM:
27019 op1 = MASK_REGIMM(ctx->opcode);
27020 switch (op1) {
27021 case OPC_BLTZL: /* REGIMM branches */
27022 case OPC_BGEZL:
27023 case OPC_BLTZALL:
27024 case OPC_BGEZALL:
27025 check_insn(ctx, ISA_MIPS2);
27026 check_insn_opc_removed(ctx, ISA_MIPS_R6);
27027 /* Fallthrough */
27028 case OPC_BLTZ:
27029 case OPC_BGEZ:
27030 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
27031 break;
27032 case OPC_BLTZAL:
27033 case OPC_BGEZAL:
27034 if (ctx->insn_flags & ISA_MIPS_R6) {
27035 if (rs == 0) {
27036 /* OPC_NAL, OPC_BAL */
27037 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
27038 } else {
27039 gen_reserved_instruction(ctx);
27041 } else {
27042 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
27044 break;
27045 case OPC_TGEI: /* REGIMM traps */
27046 case OPC_TGEIU:
27047 case OPC_TLTI:
27048 case OPC_TLTIU:
27049 case OPC_TEQI:
27051 case OPC_TNEI:
27052 check_insn(ctx, ISA_MIPS2);
27053 check_insn_opc_removed(ctx, ISA_MIPS_R6);
27054 gen_trap(ctx, op1, rs, -1, imm);
27055 break;
27056 case OPC_SIGRIE:
27057 check_insn(ctx, ISA_MIPS_R6);
27058 gen_reserved_instruction(ctx);
27059 break;
27060 case OPC_SYNCI:
27061 check_insn(ctx, ISA_MIPS_R2);
27063 * Break the TB to be able to sync copied instructions
27064 * immediately.
27066 ctx->base.is_jmp = DISAS_STOP;
27067 break;
27068 case OPC_BPOSGE32: /* MIPS DSP branch */
27069 #if defined(TARGET_MIPS64)
27070 case OPC_BPOSGE64:
27071 #endif
27072 check_dsp(ctx);
27073 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
27074 break;
27075 #if defined(TARGET_MIPS64)
27076 case OPC_DAHI:
27077 check_insn(ctx, ISA_MIPS_R6);
27078 check_mips_64(ctx);
27079 if (rs != 0) {
27080 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
27082 break;
27083 case OPC_DATI:
27084 check_insn(ctx, ISA_MIPS_R6);
27085 check_mips_64(ctx);
27086 if (rs != 0) {
27087 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
27089 break;
27090 #endif
27091 default: /* Invalid */
27092 MIPS_INVAL("regimm");
27093 gen_reserved_instruction(ctx);
27094 break;
27096 break;
27097 case OPC_CP0:
27098 check_cp0_enabled(ctx);
27099 op1 = MASK_CP0(ctx->opcode);
27100 switch (op1) {
27101 case OPC_MFC0:
27102 case OPC_MTC0:
27103 case OPC_MFTR:
27104 case OPC_MTTR:
27105 case OPC_MFHC0:
27106 case OPC_MTHC0:
27107 #if defined(TARGET_MIPS64)
27108 case OPC_DMFC0:
27109 case OPC_DMTC0:
27110 #endif
27111 #ifndef CONFIG_USER_ONLY
27112 gen_cp0(env, ctx, op1, rt, rd);
27113 #endif /* !CONFIG_USER_ONLY */
27114 break;
27115 case OPC_C0:
27116 case OPC_C0_1:
27117 case OPC_C0_2:
27118 case OPC_C0_3:
27119 case OPC_C0_4:
27120 case OPC_C0_5:
27121 case OPC_C0_6:
27122 case OPC_C0_7:
27123 case OPC_C0_8:
27124 case OPC_C0_9:
27125 case OPC_C0_A:
27126 case OPC_C0_B:
27127 case OPC_C0_C:
27128 case OPC_C0_D:
27129 case OPC_C0_E:
27130 case OPC_C0_F:
27131 #ifndef CONFIG_USER_ONLY
27132 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
27133 #endif /* !CONFIG_USER_ONLY */
27134 break;
27135 case OPC_MFMC0:
27136 #ifndef CONFIG_USER_ONLY
27138 uint32_t op2;
27139 TCGv t0 = tcg_temp_new();
27141 op2 = MASK_MFMC0(ctx->opcode);
27142 switch (op2) {
27143 case OPC_DMT:
27144 check_cp0_mt(ctx);
27145 gen_helper_dmt(t0);
27146 gen_store_gpr(t0, rt);
27147 break;
27148 case OPC_EMT:
27149 check_cp0_mt(ctx);
27150 gen_helper_emt(t0);
27151 gen_store_gpr(t0, rt);
27152 break;
27153 case OPC_DVPE:
27154 check_cp0_mt(ctx);
27155 gen_helper_dvpe(t0, cpu_env);
27156 gen_store_gpr(t0, rt);
27157 break;
27158 case OPC_EVPE:
27159 check_cp0_mt(ctx);
27160 gen_helper_evpe(t0, cpu_env);
27161 gen_store_gpr(t0, rt);
27162 break;
27163 case OPC_DVP:
27164 check_insn(ctx, ISA_MIPS_R6);
27165 if (ctx->vp) {
27166 gen_helper_dvp(t0, cpu_env);
27167 gen_store_gpr(t0, rt);
27169 break;
27170 case OPC_EVP:
27171 check_insn(ctx, ISA_MIPS_R6);
27172 if (ctx->vp) {
27173 gen_helper_evp(t0, cpu_env);
27174 gen_store_gpr(t0, rt);
27176 break;
27177 case OPC_DI:
27178 check_insn(ctx, ISA_MIPS_R2);
27179 save_cpu_state(ctx, 1);
27180 gen_helper_di(t0, cpu_env);
27181 gen_store_gpr(t0, rt);
27183 * Stop translation as we may have switched
27184 * the execution mode.
27186 ctx->base.is_jmp = DISAS_STOP;
27187 break;
27188 case OPC_EI:
27189 check_insn(ctx, ISA_MIPS_R2);
27190 save_cpu_state(ctx, 1);
27191 gen_helper_ei(t0, cpu_env);
27192 gen_store_gpr(t0, rt);
27194 * DISAS_STOP isn't sufficient, we need to ensure we break
27195 * out of translated code to check for pending interrupts.
27197 gen_save_pc(ctx->base.pc_next + 4);
27198 ctx->base.is_jmp = DISAS_EXIT;
27199 break;
27200 default: /* Invalid */
27201 MIPS_INVAL("mfmc0");
27202 gen_reserved_instruction(ctx);
27203 break;
27205 tcg_temp_free(t0);
27207 #endif /* !CONFIG_USER_ONLY */
27208 break;
27209 case OPC_RDPGPR:
27210 check_insn(ctx, ISA_MIPS_R2);
27211 gen_load_srsgpr(rt, rd);
27212 break;
27213 case OPC_WRPGPR:
27214 check_insn(ctx, ISA_MIPS_R2);
27215 gen_store_srsgpr(rt, rd);
27216 break;
27217 default:
27218 MIPS_INVAL("cp0");
27219 gen_reserved_instruction(ctx);
27220 break;
27222 break;
27223 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
27224 if (ctx->insn_flags & ISA_MIPS_R6) {
27225 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
27226 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27227 } else {
27228 /* OPC_ADDI */
27229 /* Arithmetic with immediate opcode */
27230 gen_arith_imm(ctx, op, rt, rs, imm);
27232 break;
27233 case OPC_ADDIU:
27234 gen_arith_imm(ctx, op, rt, rs, imm);
27235 break;
27236 case OPC_SLTI: /* Set on less than with immediate opcode */
27237 case OPC_SLTIU:
27238 gen_slt_imm(ctx, op, rt, rs, imm);
27239 break;
27240 case OPC_ANDI: /* Arithmetic with immediate opcode */
27241 case OPC_LUI: /* OPC_AUI */
27242 case OPC_ORI:
27243 case OPC_XORI:
27244 gen_logic_imm(ctx, op, rt, rs, imm);
27245 break;
27246 case OPC_J: /* Jump */
27247 case OPC_JAL:
27248 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
27249 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
27250 break;
27251 /* Branch */
27252 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
27253 if (ctx->insn_flags & ISA_MIPS_R6) {
27254 if (rt == 0) {
27255 gen_reserved_instruction(ctx);
27256 break;
27258 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
27259 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27260 } else {
27261 /* OPC_BLEZL */
27262 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27264 break;
27265 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
27266 if (ctx->insn_flags & ISA_MIPS_R6) {
27267 if (rt == 0) {
27268 gen_reserved_instruction(ctx);
27269 break;
27271 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
27272 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27273 } else {
27274 /* OPC_BGTZL */
27275 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27277 break;
27278 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
27279 if (rt == 0) {
27280 /* OPC_BLEZ */
27281 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27282 } else {
27283 check_insn(ctx, ISA_MIPS_R6);
27284 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
27285 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27287 break;
27288 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
27289 if (rt == 0) {
27290 /* OPC_BGTZ */
27291 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27292 } else {
27293 check_insn(ctx, ISA_MIPS_R6);
27294 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
27295 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27297 break;
27298 case OPC_BEQL:
27299 case OPC_BNEL:
27300 check_insn(ctx, ISA_MIPS2);
27301 check_insn_opc_removed(ctx, ISA_MIPS_R6);
27302 /* Fallthrough */
27303 case OPC_BEQ:
27304 case OPC_BNE:
27305 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27306 break;
27307 case OPC_LL: /* Load and stores */
27308 check_insn(ctx, ISA_MIPS2);
27309 if (ctx->insn_flags & INSN_R5900) {
27310 check_insn_opc_user_only(ctx, INSN_R5900);
27312 /* Fallthrough */
27313 case OPC_LWL:
27314 case OPC_LWR:
27315 case OPC_LB:
27316 case OPC_LH:
27317 case OPC_LW:
27318 case OPC_LWPC:
27319 case OPC_LBU:
27320 case OPC_LHU:
27321 gen_ld(ctx, op, rt, rs, imm);
27322 break;
27323 case OPC_SWL:
27324 case OPC_SWR:
27325 case OPC_SB:
27326 case OPC_SH:
27327 case OPC_SW:
27328 gen_st(ctx, op, rt, rs, imm);
27329 break;
27330 case OPC_SC:
27331 check_insn(ctx, ISA_MIPS2);
27332 if (ctx->insn_flags & INSN_R5900) {
27333 check_insn_opc_user_only(ctx, INSN_R5900);
27335 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27336 break;
27337 case OPC_CACHE:
27338 check_cp0_enabled(ctx);
27339 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
27340 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27341 gen_cache_operation(ctx, rt, rs, imm);
27343 /* Treat as NOP. */
27344 break;
27345 case OPC_PREF:
27346 if (ctx->insn_flags & INSN_R5900) {
27347 /* Treat as NOP. */
27348 } else {
27349 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
27350 /* Treat as NOP. */
27352 break;
27354 /* Floating point (COP1). */
27355 case OPC_LWC1:
27356 case OPC_LDC1:
27357 case OPC_SWC1:
27358 case OPC_SDC1:
27359 gen_cop1_ldst(ctx, op, rt, rs, imm);
27360 break;
27362 case OPC_CP1:
27363 op1 = MASK_CP1(ctx->opcode);
27365 switch (op1) {
27366 case OPC_MFHC1:
27367 case OPC_MTHC1:
27368 check_cp1_enabled(ctx);
27369 check_insn(ctx, ISA_MIPS_R2);
27370 /* fall through */
27371 case OPC_MFC1:
27372 case OPC_CFC1:
27373 case OPC_MTC1:
27374 case OPC_CTC1:
27375 check_cp1_enabled(ctx);
27376 gen_cp1(ctx, op1, rt, rd);
27377 break;
27378 #if defined(TARGET_MIPS64)
27379 case OPC_DMFC1:
27380 case OPC_DMTC1:
27381 check_cp1_enabled(ctx);
27382 check_insn(ctx, ISA_MIPS3);
27383 check_mips_64(ctx);
27384 gen_cp1(ctx, op1, rt, rd);
27385 break;
27386 #endif
27387 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
27388 check_cp1_enabled(ctx);
27389 if (ctx->insn_flags & ISA_MIPS_R6) {
27390 /* OPC_BC1EQZ */
27391 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
27392 rt, imm << 2, 4);
27393 } else {
27394 /* OPC_BC1ANY2 */
27395 check_cop1x(ctx);
27396 check_insn(ctx, ASE_MIPS3D);
27397 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
27398 (rt >> 2) & 0x7, imm << 2);
27400 break;
27401 case OPC_BC1NEZ:
27402 check_cp1_enabled(ctx);
27403 check_insn(ctx, ISA_MIPS_R6);
27404 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
27405 rt, imm << 2, 4);
27406 break;
27407 case OPC_BC1ANY4:
27408 check_cp1_enabled(ctx);
27409 check_insn_opc_removed(ctx, ISA_MIPS_R6);
27410 check_cop1x(ctx);
27411 check_insn(ctx, ASE_MIPS3D);
27412 /* fall through */
27413 case OPC_BC1:
27414 check_cp1_enabled(ctx);
27415 check_insn_opc_removed(ctx, ISA_MIPS_R6);
27416 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
27417 (rt >> 2) & 0x7, imm << 2);
27418 break;
27419 case OPC_PS_FMT:
27420 check_ps(ctx);
27421 /* fall through */
27422 case OPC_S_FMT:
27423 case OPC_D_FMT:
27424 check_cp1_enabled(ctx);
27425 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
27426 (imm >> 8) & 0x7);
27427 break;
27428 case OPC_W_FMT:
27429 case OPC_L_FMT:
27431 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
27432 check_cp1_enabled(ctx);
27433 if (ctx->insn_flags & ISA_MIPS_R6) {
27434 switch (r6_op) {
27435 case R6_OPC_CMP_AF_S:
27436 case R6_OPC_CMP_UN_S:
27437 case R6_OPC_CMP_EQ_S:
27438 case R6_OPC_CMP_UEQ_S:
27439 case R6_OPC_CMP_LT_S:
27440 case R6_OPC_CMP_ULT_S:
27441 case R6_OPC_CMP_LE_S:
27442 case R6_OPC_CMP_ULE_S:
27443 case R6_OPC_CMP_SAF_S:
27444 case R6_OPC_CMP_SUN_S:
27445 case R6_OPC_CMP_SEQ_S:
27446 case R6_OPC_CMP_SEUQ_S:
27447 case R6_OPC_CMP_SLT_S:
27448 case R6_OPC_CMP_SULT_S:
27449 case R6_OPC_CMP_SLE_S:
27450 case R6_OPC_CMP_SULE_S:
27451 case R6_OPC_CMP_OR_S:
27452 case R6_OPC_CMP_UNE_S:
27453 case R6_OPC_CMP_NE_S:
27454 case R6_OPC_CMP_SOR_S:
27455 case R6_OPC_CMP_SUNE_S:
27456 case R6_OPC_CMP_SNE_S:
27457 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
27458 break;
27459 case R6_OPC_CMP_AF_D:
27460 case R6_OPC_CMP_UN_D:
27461 case R6_OPC_CMP_EQ_D:
27462 case R6_OPC_CMP_UEQ_D:
27463 case R6_OPC_CMP_LT_D:
27464 case R6_OPC_CMP_ULT_D:
27465 case R6_OPC_CMP_LE_D:
27466 case R6_OPC_CMP_ULE_D:
27467 case R6_OPC_CMP_SAF_D:
27468 case R6_OPC_CMP_SUN_D:
27469 case R6_OPC_CMP_SEQ_D:
27470 case R6_OPC_CMP_SEUQ_D:
27471 case R6_OPC_CMP_SLT_D:
27472 case R6_OPC_CMP_SULT_D:
27473 case R6_OPC_CMP_SLE_D:
27474 case R6_OPC_CMP_SULE_D:
27475 case R6_OPC_CMP_OR_D:
27476 case R6_OPC_CMP_UNE_D:
27477 case R6_OPC_CMP_NE_D:
27478 case R6_OPC_CMP_SOR_D:
27479 case R6_OPC_CMP_SUNE_D:
27480 case R6_OPC_CMP_SNE_D:
27481 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
27482 break;
27483 default:
27484 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
27485 rt, rd, sa, (imm >> 8) & 0x7);
27487 break;
27489 } else {
27490 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
27491 (imm >> 8) & 0x7);
27493 break;
27495 default:
27496 MIPS_INVAL("cp1");
27497 gen_reserved_instruction(ctx);
27498 break;
27500 break;
27502 /* Compact branches [R6] and COP2 [non-R6] */
27503 case OPC_BC: /* OPC_LWC2 */
27504 case OPC_BALC: /* OPC_SWC2 */
27505 if (ctx->insn_flags & ISA_MIPS_R6) {
27506 /* OPC_BC, OPC_BALC */
27507 gen_compute_compact_branch(ctx, op, 0, 0,
27508 sextract32(ctx->opcode << 2, 0, 28));
27509 } else if (ctx->insn_flags & ASE_LEXT) {
27510 gen_loongson_lswc2(ctx, rt, rs, rd);
27511 } else {
27512 /* OPC_LWC2, OPC_SWC2 */
27513 /* COP2: Not implemented. */
27514 generate_exception_err(ctx, EXCP_CpU, 2);
27516 break;
27517 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
27518 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
27519 if (ctx->insn_flags & ISA_MIPS_R6) {
27520 if (rs != 0) {
27521 /* OPC_BEQZC, OPC_BNEZC */
27522 gen_compute_compact_branch(ctx, op, rs, 0,
27523 sextract32(ctx->opcode << 2, 0, 23));
27524 } else {
27525 /* OPC_JIC, OPC_JIALC */
27526 gen_compute_compact_branch(ctx, op, 0, rt, imm);
27528 } else if (ctx->insn_flags & ASE_LEXT) {
27529 gen_loongson_lsdc2(ctx, rt, rs, rd);
27530 } else {
27531 /* OPC_LWC2, OPC_SWC2 */
27532 /* COP2: Not implemented. */
27533 generate_exception_err(ctx, EXCP_CpU, 2);
27535 break;
27536 case OPC_CP2:
27537 check_insn(ctx, ASE_LMMI);
27538 /* Note that these instructions use different fields. */
27539 gen_loongson_multimedia(ctx, sa, rd, rt);
27540 break;
27542 case OPC_CP3:
27543 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
27544 check_cp1_enabled(ctx);
27545 op1 = MASK_CP3(ctx->opcode);
27546 switch (op1) {
27547 case OPC_LUXC1:
27548 case OPC_SUXC1:
27549 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
27550 /* Fallthrough */
27551 case OPC_LWXC1:
27552 case OPC_LDXC1:
27553 case OPC_SWXC1:
27554 case OPC_SDXC1:
27555 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
27556 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
27557 break;
27558 case OPC_PREFX:
27559 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
27560 /* Treat as NOP. */
27561 break;
27562 case OPC_ALNV_PS:
27563 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
27564 /* Fallthrough */
27565 case OPC_MADD_S:
27566 case OPC_MADD_D:
27567 case OPC_MADD_PS:
27568 case OPC_MSUB_S:
27569 case OPC_MSUB_D:
27570 case OPC_MSUB_PS:
27571 case OPC_NMADD_S:
27572 case OPC_NMADD_D:
27573 case OPC_NMADD_PS:
27574 case OPC_NMSUB_S:
27575 case OPC_NMSUB_D:
27576 case OPC_NMSUB_PS:
27577 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
27578 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
27579 break;
27580 default:
27581 MIPS_INVAL("cp3");
27582 gen_reserved_instruction(ctx);
27583 break;
27585 } else {
27586 generate_exception_err(ctx, EXCP_CpU, 1);
27588 break;
27590 #if defined(TARGET_MIPS64)
27591 /* MIPS64 opcodes */
27592 case OPC_LLD:
27593 if (ctx->insn_flags & INSN_R5900) {
27594 check_insn_opc_user_only(ctx, INSN_R5900);
27596 /* fall through */
27597 case OPC_LDL:
27598 case OPC_LDR:
27599 case OPC_LWU:
27600 case OPC_LD:
27601 check_insn(ctx, ISA_MIPS3);
27602 check_mips_64(ctx);
27603 gen_ld(ctx, op, rt, rs, imm);
27604 break;
27605 case OPC_SDL:
27606 case OPC_SDR:
27607 case OPC_SD:
27608 check_insn(ctx, ISA_MIPS3);
27609 check_mips_64(ctx);
27610 gen_st(ctx, op, rt, rs, imm);
27611 break;
27612 case OPC_SCD:
27613 check_insn(ctx, ISA_MIPS3);
27614 if (ctx->insn_flags & INSN_R5900) {
27615 check_insn_opc_user_only(ctx, INSN_R5900);
27617 check_mips_64(ctx);
27618 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27619 break;
27620 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
27621 if (ctx->insn_flags & ISA_MIPS_R6) {
27622 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
27623 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27624 } else {
27625 /* OPC_DADDI */
27626 check_insn(ctx, ISA_MIPS3);
27627 check_mips_64(ctx);
27628 gen_arith_imm(ctx, op, rt, rs, imm);
27630 break;
27631 case OPC_DADDIU:
27632 check_insn(ctx, ISA_MIPS3);
27633 check_mips_64(ctx);
27634 gen_arith_imm(ctx, op, rt, rs, imm);
27635 break;
27636 #else
27637 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
27638 if (ctx->insn_flags & ISA_MIPS_R6) {
27639 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27640 } else {
27641 MIPS_INVAL("major opcode");
27642 gen_reserved_instruction(ctx);
27644 break;
27645 #endif
27646 case OPC_DAUI: /* OPC_JALX */
27647 if (ctx->insn_flags & ISA_MIPS_R6) {
27648 #if defined(TARGET_MIPS64)
27649 /* OPC_DAUI */
27650 check_mips_64(ctx);
27651 if (rs == 0) {
27652 generate_exception(ctx, EXCP_RI);
27653 } else if (rt != 0) {
27654 TCGv t0 = tcg_temp_new();
27655 gen_load_gpr(t0, rs);
27656 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
27657 tcg_temp_free(t0);
27659 #else
27660 gen_reserved_instruction(ctx);
27661 MIPS_INVAL("major opcode");
27662 #endif
27663 } else {
27664 /* OPC_JALX */
27665 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
27666 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
27667 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
27669 break;
27670 case OPC_MDMX: /* MMI_OPC_LQ */
27671 if (ctx->insn_flags & INSN_R5900) {
27672 #if defined(TARGET_MIPS64)
27673 gen_mmi_lq(env, ctx);
27674 #endif
27675 } else {
27676 /* MDMX: Not implemented. */
27678 break;
27679 case OPC_PCREL:
27680 check_insn(ctx, ISA_MIPS_R6);
27681 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
27682 break;
27683 default: /* Invalid */
27684 MIPS_INVAL("major opcode");
27685 return false;
27687 return true;
27690 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
27692 /* make sure instructions are on a word boundary */
27693 if (ctx->base.pc_next & 0x3) {
27694 env->CP0_BadVAddr = ctx->base.pc_next;
27695 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
27696 return;
27699 /* Handle blikely not taken case */
27700 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
27701 TCGLabel *l1 = gen_new_label();
27703 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
27704 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
27705 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
27706 gen_set_label(l1);
27709 /* Transition to the auto-generated decoder. */
27711 /* ISA extensions */
27712 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
27713 return;
27716 /* ISA (from latest to oldest) */
27717 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
27718 return;
27721 if (decode_opc_legacy(env, ctx)) {
27722 return;
27725 gen_reserved_instruction(ctx);
27728 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
27730 DisasContext *ctx = container_of(dcbase, DisasContext, base);
27731 CPUMIPSState *env = cs->env_ptr;
27733 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
27734 ctx->saved_pc = -1;
27735 ctx->insn_flags = env->insn_flags;
27736 ctx->CP0_Config1 = env->CP0_Config1;
27737 ctx->CP0_Config2 = env->CP0_Config2;
27738 ctx->CP0_Config3 = env->CP0_Config3;
27739 ctx->CP0_Config5 = env->CP0_Config5;
27740 ctx->btarget = 0;
27741 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
27742 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
27743 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
27744 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
27745 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
27746 ctx->PAMask = env->PAMask;
27747 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
27748 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
27749 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
27750 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
27751 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
27752 /* Restore delay slot state from the tb context. */
27753 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
27754 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
27755 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
27756 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
27757 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
27758 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
27759 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
27760 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
27761 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
27762 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
27763 restore_cpu_state(env, ctx);
27764 #ifdef CONFIG_USER_ONLY
27765 ctx->mem_idx = MIPS_HFLAG_UM;
27766 #else
27767 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
27768 #endif
27769 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
27770 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
27772 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
27773 ctx->hflags);
27776 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
27780 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
27782 DisasContext *ctx = container_of(dcbase, DisasContext, base);
27784 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
27785 ctx->btarget);
27788 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
27789 const CPUBreakpoint *bp)
27791 DisasContext *ctx = container_of(dcbase, DisasContext, base);
27793 save_cpu_state(ctx, 1);
27794 ctx->base.is_jmp = DISAS_NORETURN;
27795 gen_helper_raise_exception_debug(cpu_env);
27797 * The address covered by the breakpoint must be included in
27798 * [tb->pc, tb->pc + tb->size) in order to for it to be
27799 * properly cleared -- thus we increment the PC here so that
27800 * the logic setting tb->size below does the right thing.
27802 ctx->base.pc_next += 4;
27803 return true;
27806 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
27808 CPUMIPSState *env = cs->env_ptr;
27809 DisasContext *ctx = container_of(dcbase, DisasContext, base);
27810 int insn_bytes;
27811 int is_slot;
27813 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
27814 if (ctx->insn_flags & ISA_NANOMIPS32) {
27815 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
27816 insn_bytes = decode_nanomips_opc(env, ctx);
27817 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
27818 ctx->opcode = translator_ldl(env, ctx->base.pc_next);
27819 insn_bytes = 4;
27820 decode_opc(env, ctx);
27821 } else if (ctx->insn_flags & ASE_MICROMIPS) {
27822 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
27823 insn_bytes = decode_micromips_opc(env, ctx);
27824 } else if (ctx->insn_flags & ASE_MIPS16) {
27825 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
27826 insn_bytes = decode_mips16_opc(env, ctx);
27827 } else {
27828 gen_reserved_instruction(ctx);
27829 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
27830 return;
27833 if (ctx->hflags & MIPS_HFLAG_BMASK) {
27834 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
27835 MIPS_HFLAG_FBNSLOT))) {
27837 * Force to generate branch as there is neither delay nor
27838 * forbidden slot.
27840 is_slot = 1;
27842 if ((ctx->hflags & MIPS_HFLAG_M16) &&
27843 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
27845 * Force to generate branch as microMIPS R6 doesn't restrict
27846 * branches in the forbidden slot.
27848 is_slot = 1;
27851 if (is_slot) {
27852 gen_branch(ctx, insn_bytes);
27854 ctx->base.pc_next += insn_bytes;
27856 if (ctx->base.is_jmp != DISAS_NEXT) {
27857 return;
27860 * Execute a branch and its delay slot as a single instruction.
27861 * This is what GDB expects and is consistent with what the
27862 * hardware does (e.g. if a delay slot instruction faults, the
27863 * reported PC is the PC of the branch).
27865 if (ctx->base.singlestep_enabled &&
27866 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
27867 ctx->base.is_jmp = DISAS_TOO_MANY;
27869 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
27870 ctx->base.is_jmp = DISAS_TOO_MANY;
27874 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
27876 DisasContext *ctx = container_of(dcbase, DisasContext, base);
27878 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
27879 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
27880 gen_helper_raise_exception_debug(cpu_env);
27881 } else {
27882 switch (ctx->base.is_jmp) {
27883 case DISAS_STOP:
27884 gen_save_pc(ctx->base.pc_next);
27885 tcg_gen_lookup_and_goto_ptr();
27886 break;
27887 case DISAS_NEXT:
27888 case DISAS_TOO_MANY:
27889 save_cpu_state(ctx, 0);
27890 gen_goto_tb(ctx, 0, ctx->base.pc_next);
27891 break;
27892 case DISAS_EXIT:
27893 tcg_gen_exit_tb(NULL, 0);
27894 break;
27895 case DISAS_NORETURN:
27896 break;
27897 default:
27898 g_assert_not_reached();
27903 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
27905 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
27906 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
27909 static const TranslatorOps mips_tr_ops = {
27910 .init_disas_context = mips_tr_init_disas_context,
27911 .tb_start = mips_tr_tb_start,
27912 .insn_start = mips_tr_insn_start,
27913 .breakpoint_check = mips_tr_breakpoint_check,
27914 .translate_insn = mips_tr_translate_insn,
27915 .tb_stop = mips_tr_tb_stop,
27916 .disas_log = mips_tr_disas_log,
27919 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
27921 DisasContext ctx;
27923 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
27926 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
27928 int i;
27929 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
27931 #define printfpr(fp) \
27932 do { \
27933 if (is_fpu64) \
27934 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
27935 " fd:%13g fs:%13g psu: %13g\n", \
27936 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
27937 (double)(fp)->fd, \
27938 (double)(fp)->fs[FP_ENDIAN_IDX], \
27939 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
27940 else { \
27941 fpr_t tmp; \
27942 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
27943 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
27944 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
27945 " fd:%13g fs:%13g psu:%13g\n", \
27946 tmp.w[FP_ENDIAN_IDX], tmp.d, \
27947 (double)tmp.fd, \
27948 (double)tmp.fs[FP_ENDIAN_IDX], \
27949 (double)tmp.fs[!FP_ENDIAN_IDX]); \
27951 } while (0)
27954 qemu_fprintf(f,
27955 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
27956 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
27957 get_float_exception_flags(&env->active_fpu.fp_status));
27958 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
27959 qemu_fprintf(f, "%3s: ", fregnames[i]);
27960 printfpr(&env->active_fpu.fpr[i]);
27963 #undef printfpr
27966 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
27968 MIPSCPU *cpu = MIPS_CPU(cs);
27969 CPUMIPSState *env = &cpu->env;
27970 int i;
27972 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
27973 " LO=0x" TARGET_FMT_lx " ds %04x "
27974 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
27975 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
27976 env->hflags, env->btarget, env->bcond);
27977 for (i = 0; i < 32; i++) {
27978 if ((i & 3) == 0) {
27979 qemu_fprintf(f, "GPR%02d:", i);
27981 qemu_fprintf(f, " %s " TARGET_FMT_lx,
27982 regnames[i], env->active_tc.gpr[i]);
27983 if ((i & 3) == 3) {
27984 qemu_fprintf(f, "\n");
27988 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
27989 TARGET_FMT_lx "\n",
27990 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
27991 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
27992 PRIx64 "\n",
27993 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
27994 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
27995 env->CP0_Config2, env->CP0_Config3);
27996 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
27997 env->CP0_Config4, env->CP0_Config5);
27998 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
27999 fpu_dump_state(env, f, flags);
28003 void mips_tcg_init(void)
28005 int i;
28007 cpu_gpr[0] = NULL;
28008 for (i = 1; i < 32; i++)
28009 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
28010 offsetof(CPUMIPSState,
28011 active_tc.gpr[i]),
28012 regnames[i]);
28013 #if defined(TARGET_MIPS64)
28014 cpu_gpr_hi[0] = NULL;
28016 for (unsigned i = 1; i < 32; i++) {
28017 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
28019 cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env,
28020 offsetof(CPUMIPSState,
28021 active_tc.gpr_hi[i]),
28022 rname);
28024 #endif /* !TARGET_MIPS64 */
28025 for (i = 0; i < 32; i++) {
28026 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
28028 fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
28030 msa_translate_init();
28031 cpu_PC = tcg_global_mem_new(cpu_env,
28032 offsetof(CPUMIPSState, active_tc.PC), "PC");
28033 for (i = 0; i < MIPS_DSP_ACC; i++) {
28034 cpu_HI[i] = tcg_global_mem_new(cpu_env,
28035 offsetof(CPUMIPSState, active_tc.HI[i]),
28036 regnames_HI[i]);
28037 cpu_LO[i] = tcg_global_mem_new(cpu_env,
28038 offsetof(CPUMIPSState, active_tc.LO[i]),
28039 regnames_LO[i]);
28041 cpu_dspctrl = tcg_global_mem_new(cpu_env,
28042 offsetof(CPUMIPSState,
28043 active_tc.DSPControl),
28044 "DSPControl");
28045 bcond = tcg_global_mem_new(cpu_env,
28046 offsetof(CPUMIPSState, bcond), "bcond");
28047 btarget = tcg_global_mem_new(cpu_env,
28048 offsetof(CPUMIPSState, btarget), "btarget");
28049 hflags = tcg_global_mem_new_i32(cpu_env,
28050 offsetof(CPUMIPSState, hflags), "hflags");
28052 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
28053 offsetof(CPUMIPSState, active_fpu.fcr0),
28054 "fcr0");
28055 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
28056 offsetof(CPUMIPSState, active_fpu.fcr31),
28057 "fcr31");
28058 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
28059 "lladdr");
28060 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
28061 "llval");
28063 if (TARGET_LONG_BITS == 32) {
28064 mxu_translate_init();
28068 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
28069 target_ulong *data)
28071 env->active_tc.PC = data[0];
28072 env->hflags &= ~MIPS_HFLAG_BMASK;
28073 env->hflags |= data[1];
28074 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
28075 case MIPS_HFLAG_BR:
28076 break;
28077 case MIPS_HFLAG_BC:
28078 case MIPS_HFLAG_BL:
28079 case MIPS_HFLAG_B:
28080 env->btarget = data[2];
28081 break;