target/mips: Restrict mips_cpu_dump_state() to cpu.c
[qemu/kevin.git] / target / mips / translate.c
blobf0ae3716022a4e37077f8da215598d91b2a187d5
1 /*
2 * MIPS emulation for QEMU - main translation routines
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
9 * Copyright (c) 2020 Philippe Mathieu-Daudé
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 #include "qemu/osdep.h"
26 #include "cpu.h"
27 #include "internal.h"
28 #include "tcg/tcg-op.h"
29 #include "exec/translator.h"
30 #include "exec/helper-proto.h"
31 #include "exec/helper-gen.h"
32 #include "semihosting/semihost.h"
34 #include "target/mips/trace.h"
35 #include "trace-tcg.h"
36 #include "exec/translator.h"
37 #include "exec/log.h"
38 #include "qemu/qemu-print.h"
39 #include "fpu_helper.h"
40 #include "translate.h"
42 enum {
43 /* indirect opcode tables */
44 OPC_SPECIAL = (0x00 << 26),
45 OPC_REGIMM = (0x01 << 26),
46 OPC_CP0 = (0x10 << 26),
47 OPC_CP2 = (0x12 << 26),
48 OPC_CP3 = (0x13 << 26),
49 OPC_SPECIAL2 = (0x1C << 26),
50 OPC_SPECIAL3 = (0x1F << 26),
51 /* arithmetic with immediate */
52 OPC_ADDI = (0x08 << 26),
53 OPC_ADDIU = (0x09 << 26),
54 OPC_SLTI = (0x0A << 26),
55 OPC_SLTIU = (0x0B << 26),
56 /* logic with immediate */
57 OPC_ANDI = (0x0C << 26),
58 OPC_ORI = (0x0D << 26),
59 OPC_XORI = (0x0E << 26),
60 OPC_LUI = (0x0F << 26),
61 /* arithmetic with immediate */
62 OPC_DADDI = (0x18 << 26),
63 OPC_DADDIU = (0x19 << 26),
64 /* Jump and branches */
65 OPC_J = (0x02 << 26),
66 OPC_JAL = (0x03 << 26),
67 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
68 OPC_BEQL = (0x14 << 26),
69 OPC_BNE = (0x05 << 26),
70 OPC_BNEL = (0x15 << 26),
71 OPC_BLEZ = (0x06 << 26),
72 OPC_BLEZL = (0x16 << 26),
73 OPC_BGTZ = (0x07 << 26),
74 OPC_BGTZL = (0x17 << 26),
75 OPC_JALX = (0x1D << 26),
76 OPC_DAUI = (0x1D << 26),
77 /* Load and stores */
78 OPC_LDL = (0x1A << 26),
79 OPC_LDR = (0x1B << 26),
80 OPC_LB = (0x20 << 26),
81 OPC_LH = (0x21 << 26),
82 OPC_LWL = (0x22 << 26),
83 OPC_LW = (0x23 << 26),
84 OPC_LWPC = OPC_LW | 0x5,
85 OPC_LBU = (0x24 << 26),
86 OPC_LHU = (0x25 << 26),
87 OPC_LWR = (0x26 << 26),
88 OPC_LWU = (0x27 << 26),
89 OPC_SB = (0x28 << 26),
90 OPC_SH = (0x29 << 26),
91 OPC_SWL = (0x2A << 26),
92 OPC_SW = (0x2B << 26),
93 OPC_SDL = (0x2C << 26),
94 OPC_SDR = (0x2D << 26),
95 OPC_SWR = (0x2E << 26),
96 OPC_LL = (0x30 << 26),
97 OPC_LLD = (0x34 << 26),
98 OPC_LD = (0x37 << 26),
99 OPC_LDPC = OPC_LD | 0x5,
100 OPC_SC = (0x38 << 26),
101 OPC_SCD = (0x3C << 26),
102 OPC_SD = (0x3F << 26),
103 /* Floating point load/store */
104 OPC_LWC1 = (0x31 << 26),
105 OPC_LWC2 = (0x32 << 26),
106 OPC_LDC1 = (0x35 << 26),
107 OPC_LDC2 = (0x36 << 26),
108 OPC_SWC1 = (0x39 << 26),
109 OPC_SWC2 = (0x3A << 26),
110 OPC_SDC1 = (0x3D << 26),
111 OPC_SDC2 = (0x3E << 26),
112 /* Compact Branches */
113 OPC_BLEZALC = (0x06 << 26),
114 OPC_BGEZALC = (0x06 << 26),
115 OPC_BGEUC = (0x06 << 26),
116 OPC_BGTZALC = (0x07 << 26),
117 OPC_BLTZALC = (0x07 << 26),
118 OPC_BLTUC = (0x07 << 26),
119 OPC_BOVC = (0x08 << 26),
120 OPC_BEQZALC = (0x08 << 26),
121 OPC_BEQC = (0x08 << 26),
122 OPC_BLEZC = (0x16 << 26),
123 OPC_BGEZC = (0x16 << 26),
124 OPC_BGEC = (0x16 << 26),
125 OPC_BGTZC = (0x17 << 26),
126 OPC_BLTZC = (0x17 << 26),
127 OPC_BLTC = (0x17 << 26),
128 OPC_BNVC = (0x18 << 26),
129 OPC_BNEZALC = (0x18 << 26),
130 OPC_BNEC = (0x18 << 26),
131 OPC_BC = (0x32 << 26),
132 OPC_BEQZC = (0x36 << 26),
133 OPC_JIC = (0x36 << 26),
134 OPC_BALC = (0x3A << 26),
135 OPC_BNEZC = (0x3E << 26),
136 OPC_JIALC = (0x3E << 26),
137 /* MDMX ASE specific */
138 OPC_MDMX = (0x1E << 26),
139 /* Cache and prefetch */
140 OPC_CACHE = (0x2F << 26),
141 OPC_PREF = (0x33 << 26),
142 /* PC-relative address computation / loads */
143 OPC_PCREL = (0x3B << 26),
146 /* PC-relative address computation / loads */
147 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
148 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
149 enum {
150 /* Instructions determined by bits 19 and 20 */
151 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
152 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
153 OPC_LWUPC = OPC_PCREL | (2 << 19),
155 /* Instructions determined by bits 16 ... 20 */
156 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
157 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
159 /* Other */
160 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
163 /* MIPS special opcodes */
164 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
166 enum {
167 /* Shifts */
168 OPC_SLL = 0x00 | OPC_SPECIAL,
169 /* NOP is SLL r0, r0, 0 */
170 /* SSNOP is SLL r0, r0, 1 */
171 /* EHB is SLL r0, r0, 3 */
172 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
173 OPC_ROTR = OPC_SRL | (1 << 21),
174 OPC_SRA = 0x03 | OPC_SPECIAL,
175 OPC_SLLV = 0x04 | OPC_SPECIAL,
176 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
177 OPC_ROTRV = OPC_SRLV | (1 << 6),
178 OPC_SRAV = 0x07 | OPC_SPECIAL,
179 OPC_DSLLV = 0x14 | OPC_SPECIAL,
180 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
181 OPC_DROTRV = OPC_DSRLV | (1 << 6),
182 OPC_DSRAV = 0x17 | OPC_SPECIAL,
183 OPC_DSLL = 0x38 | OPC_SPECIAL,
184 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
185 OPC_DROTR = OPC_DSRL | (1 << 21),
186 OPC_DSRA = 0x3B | OPC_SPECIAL,
187 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
188 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
189 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
190 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
191 /* Multiplication / division */
192 OPC_MULT = 0x18 | OPC_SPECIAL,
193 OPC_MULTU = 0x19 | OPC_SPECIAL,
194 OPC_DIV = 0x1A | OPC_SPECIAL,
195 OPC_DIVU = 0x1B | OPC_SPECIAL,
196 OPC_DMULT = 0x1C | OPC_SPECIAL,
197 OPC_DMULTU = 0x1D | OPC_SPECIAL,
198 OPC_DDIV = 0x1E | OPC_SPECIAL,
199 OPC_DDIVU = 0x1F | OPC_SPECIAL,
201 /* 2 registers arithmetic / logic */
202 OPC_ADD = 0x20 | OPC_SPECIAL,
203 OPC_ADDU = 0x21 | OPC_SPECIAL,
204 OPC_SUB = 0x22 | OPC_SPECIAL,
205 OPC_SUBU = 0x23 | OPC_SPECIAL,
206 OPC_AND = 0x24 | OPC_SPECIAL,
207 OPC_OR = 0x25 | OPC_SPECIAL,
208 OPC_XOR = 0x26 | OPC_SPECIAL,
209 OPC_NOR = 0x27 | OPC_SPECIAL,
210 OPC_SLT = 0x2A | OPC_SPECIAL,
211 OPC_SLTU = 0x2B | OPC_SPECIAL,
212 OPC_DADD = 0x2C | OPC_SPECIAL,
213 OPC_DADDU = 0x2D | OPC_SPECIAL,
214 OPC_DSUB = 0x2E | OPC_SPECIAL,
215 OPC_DSUBU = 0x2F | OPC_SPECIAL,
216 /* Jumps */
217 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
218 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
219 /* Traps */
220 OPC_TGE = 0x30 | OPC_SPECIAL,
221 OPC_TGEU = 0x31 | OPC_SPECIAL,
222 OPC_TLT = 0x32 | OPC_SPECIAL,
223 OPC_TLTU = 0x33 | OPC_SPECIAL,
224 OPC_TEQ = 0x34 | OPC_SPECIAL,
225 OPC_TNE = 0x36 | OPC_SPECIAL,
226 /* HI / LO registers load & stores */
227 OPC_MFHI = 0x10 | OPC_SPECIAL,
228 OPC_MTHI = 0x11 | OPC_SPECIAL,
229 OPC_MFLO = 0x12 | OPC_SPECIAL,
230 OPC_MTLO = 0x13 | OPC_SPECIAL,
231 /* Conditional moves */
232 OPC_MOVZ = 0x0A | OPC_SPECIAL,
233 OPC_MOVN = 0x0B | OPC_SPECIAL,
235 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
236 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
238 OPC_MOVCI = 0x01 | OPC_SPECIAL,
240 /* Special */
241 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
242 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
243 OPC_BREAK = 0x0D | OPC_SPECIAL,
244 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
245 OPC_SYNC = 0x0F | OPC_SPECIAL,
247 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
248 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
249 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
250 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
254 * R6 Multiply and Divide instructions have the same opcode
255 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
257 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
259 enum {
260 R6_OPC_MUL = OPC_MULT | (2 << 6),
261 R6_OPC_MUH = OPC_MULT | (3 << 6),
262 R6_OPC_MULU = OPC_MULTU | (2 << 6),
263 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
264 R6_OPC_DIV = OPC_DIV | (2 << 6),
265 R6_OPC_MOD = OPC_DIV | (3 << 6),
266 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
267 R6_OPC_MODU = OPC_DIVU | (3 << 6),
269 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
270 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
271 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
272 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
273 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
274 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
275 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
276 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
278 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
279 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
280 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
281 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
282 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
285 /* Multiplication variants of the vr54xx. */
286 #define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
288 enum {
289 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
290 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
291 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
292 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
293 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
294 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
295 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
296 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
297 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
298 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
299 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
300 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
301 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
302 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
305 /* REGIMM (rt field) opcodes */
306 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
308 enum {
309 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
310 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
311 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
312 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
313 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
314 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
315 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
316 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
317 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
318 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
319 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
320 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
321 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
322 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
323 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
324 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
326 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
327 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
330 /* Special2 opcodes */
331 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
333 enum {
334 /* Multiply & xxx operations */
335 OPC_MADD = 0x00 | OPC_SPECIAL2,
336 OPC_MADDU = 0x01 | OPC_SPECIAL2,
337 OPC_MUL = 0x02 | OPC_SPECIAL2,
338 OPC_MSUB = 0x04 | OPC_SPECIAL2,
339 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
340 /* Loongson 2F */
341 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
342 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
343 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
344 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
345 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
346 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
347 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
348 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
349 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
350 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
351 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
352 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
353 /* Misc */
354 OPC_CLZ = 0x20 | OPC_SPECIAL2,
355 OPC_CLO = 0x21 | OPC_SPECIAL2,
356 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
357 OPC_DCLO = 0x25 | OPC_SPECIAL2,
358 /* Special */
359 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
362 /* Special3 opcodes */
363 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
365 enum {
366 OPC_EXT = 0x00 | OPC_SPECIAL3,
367 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
368 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
369 OPC_DEXT = 0x03 | OPC_SPECIAL3,
370 OPC_INS = 0x04 | OPC_SPECIAL3,
371 OPC_DINSM = 0x05 | OPC_SPECIAL3,
372 OPC_DINSU = 0x06 | OPC_SPECIAL3,
373 OPC_DINS = 0x07 | OPC_SPECIAL3,
374 OPC_FORK = 0x08 | OPC_SPECIAL3,
375 OPC_YIELD = 0x09 | OPC_SPECIAL3,
376 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
377 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
378 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
379 OPC_GINV = 0x3D | OPC_SPECIAL3,
381 /* Loongson 2E */
382 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
383 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
384 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
385 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
386 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
387 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
388 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
389 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
390 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
391 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
392 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
393 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
395 /* MIPS DSP Load */
396 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
397 /* MIPS DSP Arithmetic */
398 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
399 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
400 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
401 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
402 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
403 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
404 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
405 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
406 /* MIPS DSP GPR-Based Shift Sub-class */
407 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
408 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
409 /* MIPS DSP Multiply Sub-class insns */
410 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
411 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
413 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
414 /* DSP Bit/Manipulation Sub-class */
415 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
416 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
417 /* MIPS DSP Append Sub-class */
418 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
419 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
420 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
421 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
422 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
424 /* EVA */
425 OPC_LWLE = 0x19 | OPC_SPECIAL3,
426 OPC_LWRE = 0x1A | OPC_SPECIAL3,
427 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
428 OPC_SBE = 0x1C | OPC_SPECIAL3,
429 OPC_SHE = 0x1D | OPC_SPECIAL3,
430 OPC_SCE = 0x1E | OPC_SPECIAL3,
431 OPC_SWE = 0x1F | OPC_SPECIAL3,
432 OPC_SWLE = 0x21 | OPC_SPECIAL3,
433 OPC_SWRE = 0x22 | OPC_SPECIAL3,
434 OPC_PREFE = 0x23 | OPC_SPECIAL3,
435 OPC_LBUE = 0x28 | OPC_SPECIAL3,
436 OPC_LHUE = 0x29 | OPC_SPECIAL3,
437 OPC_LBE = 0x2C | OPC_SPECIAL3,
438 OPC_LHE = 0x2D | OPC_SPECIAL3,
439 OPC_LLE = 0x2E | OPC_SPECIAL3,
440 OPC_LWE = 0x2F | OPC_SPECIAL3,
442 /* R6 */
443 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
444 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
445 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
446 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
447 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
448 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
451 /* Loongson EXT load/store quad word opcodes */
452 #define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
453 enum {
454 OPC_GSLQ = 0x0020 | OPC_LWC2,
455 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
456 OPC_GSSHFL = OPC_LWC2,
457 OPC_GSSQ = 0x0020 | OPC_SWC2,
458 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
459 OPC_GSSHFS = OPC_SWC2,
462 /* Loongson EXT shifted load/store opcodes */
463 #define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
464 enum {
465 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
466 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
467 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
468 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
469 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
470 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
471 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
472 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
475 /* Loongson EXT LDC2/SDC2 opcodes */
476 #define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
478 enum {
479 OPC_GSLBX = 0x0 | OPC_LDC2,
480 OPC_GSLHX = 0x1 | OPC_LDC2,
481 OPC_GSLWX = 0x2 | OPC_LDC2,
482 OPC_GSLDX = 0x3 | OPC_LDC2,
483 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
484 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
485 OPC_GSSBX = 0x0 | OPC_SDC2,
486 OPC_GSSHX = 0x1 | OPC_SDC2,
487 OPC_GSSWX = 0x2 | OPC_SDC2,
488 OPC_GSSDX = 0x3 | OPC_SDC2,
489 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
490 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
493 /* BSHFL opcodes */
494 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
496 enum {
497 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
498 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
499 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
500 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
501 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
502 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
503 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
504 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
507 /* DBSHFL opcodes */
508 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
510 enum {
511 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
512 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
513 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
514 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
515 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
516 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
517 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
518 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
519 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
520 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
521 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
524 /* MIPS DSP REGIMM opcodes */
525 enum {
526 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
527 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
530 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
531 /* MIPS DSP Load */
532 enum {
533 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
534 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
535 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
536 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
539 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
540 enum {
541 /* MIPS DSP Arithmetic Sub-class */
542 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
543 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
544 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
545 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
546 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
547 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
548 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
549 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
550 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
551 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
552 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
553 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
554 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
555 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
556 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
557 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
558 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
559 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
560 /* MIPS DSP Multiply Sub-class insns */
561 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
562 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
563 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
564 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
565 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
566 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
569 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
570 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
571 enum {
572 /* MIPS DSP Arithmetic Sub-class */
573 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
574 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
575 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
576 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
577 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
578 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
579 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
580 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
581 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
582 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
583 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
584 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
585 /* MIPS DSP Multiply Sub-class insns */
586 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
587 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
588 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
589 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
592 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
593 enum {
594 /* MIPS DSP Arithmetic Sub-class */
595 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
596 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
597 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
598 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
599 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
600 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
601 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
602 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
603 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
604 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
605 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
606 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
607 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
608 /* DSP Bit/Manipulation Sub-class */
609 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
610 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
611 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
612 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
613 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
616 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
617 enum {
618 /* MIPS DSP Arithmetic Sub-class */
619 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
620 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
621 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
622 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
623 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
624 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
625 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
626 /* DSP Compare-Pick Sub-class */
627 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
628 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
629 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
630 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
631 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
632 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
634 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
635 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
636 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
637 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
638 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
639 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
640 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
641 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
644 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
645 enum {
646 /* MIPS DSP GPR-Based Shift Sub-class */
647 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
648 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
649 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
650 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
651 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
652 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
653 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
654 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
655 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
656 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
657 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
658 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
659 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
660 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
661 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
662 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
663 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
664 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
665 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
666 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
667 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
668 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
671 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
672 enum {
673 /* MIPS DSP Multiply Sub-class insns */
674 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
675 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
676 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
677 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
678 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
679 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
680 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
681 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
682 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
683 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
684 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
685 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
686 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
687 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
688 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
689 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
690 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
691 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
692 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
693 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
694 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
695 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
698 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
699 enum {
700 /* DSP Bit/Manipulation Sub-class */
701 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
704 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
705 enum {
706 /* MIPS DSP Append Sub-class */
707 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
708 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
709 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
712 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
713 enum {
714 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
715 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
716 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
717 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
718 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
719 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
720 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
721 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
722 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
723 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
724 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
725 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
726 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
727 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
728 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
729 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
730 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
731 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
734 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
735 enum {
736 /* MIPS DSP Arithmetic Sub-class */
737 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
738 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
739 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
740 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
741 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
742 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
743 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
744 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
745 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
746 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
747 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
748 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
749 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
750 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
753 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
754 /* DSP Bit/Manipulation Sub-class */
755 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
756 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
757 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
758 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
759 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
760 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
763 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
764 enum {
765 /* MIPS DSP Multiply Sub-class insns */
766 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
767 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
768 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
769 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
770 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
771 /* MIPS DSP Arithmetic Sub-class */
772 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
773 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
774 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
775 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
776 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
777 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
778 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
779 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
780 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
781 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
782 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
783 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
784 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
785 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
786 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
787 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
788 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
789 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
790 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
791 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
792 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
795 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796 enum {
797 /* DSP Compare-Pick Sub-class */
798 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
799 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
800 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
801 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
802 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
803 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
804 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
805 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
806 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
807 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
808 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
809 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
810 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
811 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
817 /* MIPS DSP Arithmetic Sub-class */
818 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
819 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
820 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
821 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
822 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
823 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
824 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
825 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
828 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
829 enum {
830 /* DSP Append Sub-class */
831 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
832 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
833 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
834 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
837 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
838 enum {
839 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
840 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
841 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
842 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
843 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
844 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
845 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
846 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
847 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
848 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
849 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
850 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
851 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
852 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
853 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
854 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
855 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
856 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
857 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
858 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
859 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
860 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
863 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
864 enum {
865 /* DSP Bit/Manipulation Sub-class */
866 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
869 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
870 enum {
871 /* MIPS DSP Multiply Sub-class insns */
872 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
873 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
874 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
875 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
876 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
877 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
878 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
879 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
880 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
881 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
882 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
883 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
884 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
885 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
890 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
891 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
892 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
893 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
894 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
895 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
896 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
897 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
900 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
901 enum {
902 /* MIPS DSP GPR-Based Shift Sub-class */
903 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
904 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
905 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
906 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
907 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
908 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
909 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
910 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
911 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
912 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
913 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
914 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
915 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
916 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
921 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
922 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
923 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
924 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
925 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
926 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
927 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
928 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
931 /* Coprocessor 0 (rs field) */
932 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
934 enum {
935 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
936 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
937 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
938 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
939 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
940 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
941 OPC_MFTR = (0x08 << 21) | OPC_CP0,
942 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
943 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
944 OPC_MTTR = (0x0C << 21) | OPC_CP0,
945 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
946 OPC_C0 = (0x10 << 21) | OPC_CP0,
947 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
948 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
949 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
950 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
951 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
952 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
953 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
954 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
955 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
956 OPC_C0_A = (0x1A << 21) | OPC_CP0,
957 OPC_C0_B = (0x1B << 21) | OPC_CP0,
958 OPC_C0_C = (0x1C << 21) | OPC_CP0,
959 OPC_C0_D = (0x1D << 21) | OPC_CP0,
960 OPC_C0_E = (0x1E << 21) | OPC_CP0,
961 OPC_C0_F = (0x1F << 21) | OPC_CP0,
964 /* MFMC0 opcodes */
965 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
967 enum {
968 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
969 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
970 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
971 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
972 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
973 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
974 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
975 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
978 /* Coprocessor 0 (with rs == C0) */
979 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
981 enum {
982 OPC_TLBR = 0x01 | OPC_C0,
983 OPC_TLBWI = 0x02 | OPC_C0,
984 OPC_TLBINV = 0x03 | OPC_C0,
985 OPC_TLBINVF = 0x04 | OPC_C0,
986 OPC_TLBWR = 0x06 | OPC_C0,
987 OPC_TLBP = 0x08 | OPC_C0,
988 OPC_RFE = 0x10 | OPC_C0,
989 OPC_ERET = 0x18 | OPC_C0,
990 OPC_DERET = 0x1F | OPC_C0,
991 OPC_WAIT = 0x20 | OPC_C0,
994 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
996 enum {
997 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
998 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
999 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1000 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1001 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1002 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1003 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1004 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1005 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1006 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1007 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1010 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1012 enum {
1013 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1014 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1015 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1016 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1017 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1018 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1019 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1020 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1022 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1023 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1024 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1025 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1026 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1027 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1028 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1029 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1031 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1032 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1033 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1034 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1035 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1036 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1037 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1038 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1040 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1041 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1042 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1043 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1044 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1045 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1046 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1047 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1049 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1050 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1051 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1052 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1053 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1054 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1056 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1057 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1058 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1059 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1060 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1061 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1063 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1064 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1065 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1066 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1067 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1068 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1070 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1071 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1072 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1073 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1074 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1075 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1077 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1078 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1079 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1080 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1081 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1082 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1084 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1085 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1086 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1087 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1088 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1089 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1091 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1092 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1093 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1094 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1095 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1096 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1098 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1099 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1100 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1101 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1102 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1103 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1107 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1109 enum {
1110 OPC_LWXC1 = 0x00 | OPC_CP3,
1111 OPC_LDXC1 = 0x01 | OPC_CP3,
1112 OPC_LUXC1 = 0x05 | OPC_CP3,
1113 OPC_SWXC1 = 0x08 | OPC_CP3,
1114 OPC_SDXC1 = 0x09 | OPC_CP3,
1115 OPC_SUXC1 = 0x0D | OPC_CP3,
1116 OPC_PREFX = 0x0F | OPC_CP3,
1117 OPC_ALNV_PS = 0x1E | OPC_CP3,
1118 OPC_MADD_S = 0x20 | OPC_CP3,
1119 OPC_MADD_D = 0x21 | OPC_CP3,
1120 OPC_MADD_PS = 0x26 | OPC_CP3,
1121 OPC_MSUB_S = 0x28 | OPC_CP3,
1122 OPC_MSUB_D = 0x29 | OPC_CP3,
1123 OPC_MSUB_PS = 0x2E | OPC_CP3,
1124 OPC_NMADD_S = 0x30 | OPC_CP3,
1125 OPC_NMADD_D = 0x31 | OPC_CP3,
1126 OPC_NMADD_PS = 0x36 | OPC_CP3,
1127 OPC_NMSUB_S = 0x38 | OPC_CP3,
1128 OPC_NMSUB_D = 0x39 | OPC_CP3,
1129 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1133 * MMI (MultiMedia Instruction) encodings
1134 * ======================================
1136 * MMI instructions encoding table keys:
1138 * * This code is reserved for future use. An attempt to execute it
1139 * causes a Reserved Instruction exception.
1140 * % This code indicates an instruction class. The instruction word
1141 * must be further decoded by examining additional tables that show
1142 * the values for other instruction fields.
1143 * # This code is reserved for the unsupported instructions DMULT,
1144 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
1145 * to execute it causes a Reserved Instruction exception.
1147 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
1149 * 31 26 0
1150 * +--------+----------------------------------------+
1151 * | opcode | |
1152 * +--------+----------------------------------------+
1154 * opcode bits 28..26
1155 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1156 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1157 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1158 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
1159 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
1160 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
1161 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
1162 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
1163 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
1164 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
1165 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
1168 enum {
1169 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
1170 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
1171 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
1175 * MMI instructions with opcode field = MMI:
1177 * 31 26 5 0
1178 * +--------+-------------------------------+--------+
1179 * | MMI | |function|
1180 * +--------+-------------------------------+--------+
1182 * function bits 2..0
1183 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1184 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1185 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1186 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
1187 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
1188 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
1189 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
1190 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
1191 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
1192 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
1193 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
1196 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
1197 enum {
1198 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
1199 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
1200 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
1201 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
1202 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
1203 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
1204 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
1205 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
1208 /* global register indices */
1209 TCGv cpu_gpr[32], cpu_PC;
1211 * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[])
1212 * and the upper halves in cpu_gpr_hi[].
1214 TCGv_i64 cpu_gpr_hi[32];
1215 TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1216 static TCGv cpu_dspctrl, btarget;
1217 TCGv bcond;
1218 static TCGv cpu_lladdr, cpu_llval;
1219 static TCGv_i32 hflags;
1220 TCGv_i32 fpu_fcr0, fpu_fcr31;
1221 TCGv_i64 fpu_f64[32];
1223 #include "exec/gen-icount.h"
1225 #define gen_helper_0e0i(name, arg) do { \
1226 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1227 gen_helper_##name(cpu_env, helper_tmp); \
1228 tcg_temp_free_i32(helper_tmp); \
1229 } while (0)
1231 #define gen_helper_0e1i(name, arg1, arg2) do { \
1232 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1233 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1234 tcg_temp_free_i32(helper_tmp); \
1235 } while (0)
1237 #define gen_helper_1e0i(name, ret, arg1) do { \
1238 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1239 gen_helper_##name(ret, cpu_env, helper_tmp); \
1240 tcg_temp_free_i32(helper_tmp); \
1241 } while (0)
1243 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1244 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1245 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1246 tcg_temp_free_i32(helper_tmp); \
1247 } while (0)
1249 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1250 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1251 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1252 tcg_temp_free_i32(helper_tmp); \
1253 } while (0)
1255 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1256 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1257 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1258 tcg_temp_free_i32(helper_tmp); \
1259 } while (0)
1261 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1262 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1263 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1264 tcg_temp_free_i32(helper_tmp); \
1265 } while (0)
1267 #define DISAS_STOP DISAS_TARGET_0
1268 #define DISAS_EXIT DISAS_TARGET_1
1270 static const char * const regnames_HI[] = {
1271 "HI0", "HI1", "HI2", "HI3",
1274 static const char * const regnames_LO[] = {
1275 "LO0", "LO1", "LO2", "LO3",
1278 /* General purpose registers moves. */
1279 void gen_load_gpr(TCGv t, int reg)
1281 if (reg == 0) {
1282 tcg_gen_movi_tl(t, 0);
1283 } else {
1284 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1288 void gen_store_gpr(TCGv t, int reg)
1290 if (reg != 0) {
1291 tcg_gen_mov_tl(cpu_gpr[reg], t);
1295 #if defined(TARGET_MIPS64)
1296 void gen_load_gpr_hi(TCGv_i64 t, int reg)
1298 if (reg == 0) {
1299 tcg_gen_movi_i64(t, 0);
1300 } else {
1301 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
1305 void gen_store_gpr_hi(TCGv_i64 t, int reg)
1307 if (reg != 0) {
1308 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
1311 #endif /* TARGET_MIPS64 */
1313 /* Moves to/from shadow registers. */
1314 static inline void gen_load_srsgpr(int from, int to)
1316 TCGv t0 = tcg_temp_new();
1318 if (from == 0) {
1319 tcg_gen_movi_tl(t0, 0);
1320 } else {
1321 TCGv_i32 t2 = tcg_temp_new_i32();
1322 TCGv_ptr addr = tcg_temp_new_ptr();
1324 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1325 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1326 tcg_gen_andi_i32(t2, t2, 0xf);
1327 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1328 tcg_gen_ext_i32_ptr(addr, t2);
1329 tcg_gen_add_ptr(addr, cpu_env, addr);
1331 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1332 tcg_temp_free_ptr(addr);
1333 tcg_temp_free_i32(t2);
1335 gen_store_gpr(t0, to);
1336 tcg_temp_free(t0);
1339 static inline void gen_store_srsgpr(int from, int to)
1341 if (to != 0) {
1342 TCGv t0 = tcg_temp_new();
1343 TCGv_i32 t2 = tcg_temp_new_i32();
1344 TCGv_ptr addr = tcg_temp_new_ptr();
1346 gen_load_gpr(t0, from);
1347 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1348 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1349 tcg_gen_andi_i32(t2, t2, 0xf);
1350 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1351 tcg_gen_ext_i32_ptr(addr, t2);
1352 tcg_gen_add_ptr(addr, cpu_env, addr);
1354 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1355 tcg_temp_free_ptr(addr);
1356 tcg_temp_free_i32(t2);
1357 tcg_temp_free(t0);
1361 /* Tests */
1362 static inline void gen_save_pc(target_ulong pc)
1364 tcg_gen_movi_tl(cpu_PC, pc);
1367 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1369 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1370 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1371 gen_save_pc(ctx->base.pc_next);
1372 ctx->saved_pc = ctx->base.pc_next;
1374 if (ctx->hflags != ctx->saved_hflags) {
1375 tcg_gen_movi_i32(hflags, ctx->hflags);
1376 ctx->saved_hflags = ctx->hflags;
1377 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1378 case MIPS_HFLAG_BR:
1379 break;
1380 case MIPS_HFLAG_BC:
1381 case MIPS_HFLAG_BL:
1382 case MIPS_HFLAG_B:
1383 tcg_gen_movi_tl(btarget, ctx->btarget);
1384 break;
1389 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1391 ctx->saved_hflags = ctx->hflags;
1392 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1393 case MIPS_HFLAG_BR:
1394 break;
1395 case MIPS_HFLAG_BC:
1396 case MIPS_HFLAG_BL:
1397 case MIPS_HFLAG_B:
1398 ctx->btarget = env->btarget;
1399 break;
1403 void generate_exception_err(DisasContext *ctx, int excp, int err)
1405 TCGv_i32 texcp = tcg_const_i32(excp);
1406 TCGv_i32 terr = tcg_const_i32(err);
1407 save_cpu_state(ctx, 1);
1408 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1409 tcg_temp_free_i32(terr);
1410 tcg_temp_free_i32(texcp);
1411 ctx->base.is_jmp = DISAS_NORETURN;
1414 void generate_exception(DisasContext *ctx, int excp)
1416 gen_helper_0e0i(raise_exception, excp);
1419 void generate_exception_end(DisasContext *ctx, int excp)
1421 generate_exception_err(ctx, excp, 0);
1424 void gen_reserved_instruction(DisasContext *ctx)
1426 generate_exception_end(ctx, EXCP_RI);
1429 /* Floating point register moves. */
1430 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1432 if (ctx->hflags & MIPS_HFLAG_FRE) {
1433 generate_exception(ctx, EXCP_RI);
1435 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1438 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1440 TCGv_i64 t64;
1441 if (ctx->hflags & MIPS_HFLAG_FRE) {
1442 generate_exception(ctx, EXCP_RI);
1444 t64 = tcg_temp_new_i64();
1445 tcg_gen_extu_i32_i64(t64, t);
1446 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1447 tcg_temp_free_i64(t64);
1450 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1452 if (ctx->hflags & MIPS_HFLAG_F64) {
1453 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1454 } else {
1455 gen_load_fpr32(ctx, t, reg | 1);
1459 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1461 if (ctx->hflags & MIPS_HFLAG_F64) {
1462 TCGv_i64 t64 = tcg_temp_new_i64();
1463 tcg_gen_extu_i32_i64(t64, t);
1464 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1465 tcg_temp_free_i64(t64);
1466 } else {
1467 gen_store_fpr32(ctx, t, reg | 1);
1471 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1473 if (ctx->hflags & MIPS_HFLAG_F64) {
1474 tcg_gen_mov_i64(t, fpu_f64[reg]);
1475 } else {
1476 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1480 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1482 if (ctx->hflags & MIPS_HFLAG_F64) {
1483 tcg_gen_mov_i64(fpu_f64[reg], t);
1484 } else {
1485 TCGv_i64 t0;
1486 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1487 t0 = tcg_temp_new_i64();
1488 tcg_gen_shri_i64(t0, t, 32);
1489 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1490 tcg_temp_free_i64(t0);
1494 int get_fp_bit(int cc)
1496 if (cc) {
1497 return 24 + cc;
1498 } else {
1499 return 23;
1503 /* Addresses computation */
1504 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1506 tcg_gen_add_tl(ret, arg0, arg1);
1508 #if defined(TARGET_MIPS64)
1509 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1510 tcg_gen_ext32s_i64(ret, ret);
1512 #endif
1515 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
1516 target_long ofs)
1518 tcg_gen_addi_tl(ret, base, ofs);
1520 #if defined(TARGET_MIPS64)
1521 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1522 tcg_gen_ext32s_i64(ret, ret);
1524 #endif
1527 /* Addresses computation (translation time) */
1528 static target_long addr_add(DisasContext *ctx, target_long base,
1529 target_long offset)
1531 target_long sum = base + offset;
1533 #if defined(TARGET_MIPS64)
1534 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1535 sum = (int32_t)sum;
1537 #endif
1538 return sum;
1541 /* Sign-extract the low 32-bits to a target_long. */
1542 void gen_move_low32(TCGv ret, TCGv_i64 arg)
1544 #if defined(TARGET_MIPS64)
1545 tcg_gen_ext32s_i64(ret, arg);
1546 #else
1547 tcg_gen_extrl_i64_i32(ret, arg);
1548 #endif
1551 /* Sign-extract the high 32-bits to a target_long. */
1552 void gen_move_high32(TCGv ret, TCGv_i64 arg)
1554 #if defined(TARGET_MIPS64)
1555 tcg_gen_sari_i64(ret, arg, 32);
1556 #else
1557 tcg_gen_extrh_i64_i32(ret, arg);
1558 #endif
1561 bool check_cp0_enabled(DisasContext *ctx)
1563 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1564 generate_exception_end(ctx, EXCP_CpU);
1565 return false;
1567 return true;
1570 void check_cp1_enabled(DisasContext *ctx)
1572 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
1573 generate_exception_err(ctx, EXCP_CpU, 1);
1578 * Verify that the processor is running with COP1X instructions enabled.
1579 * This is associated with the nabla symbol in the MIPS32 and MIPS64
1580 * opcode tables.
1582 void check_cop1x(DisasContext *ctx)
1584 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
1585 gen_reserved_instruction(ctx);
1590 * Verify that the processor is running with 64-bit floating-point
1591 * operations enabled.
1593 void check_cp1_64bitmode(DisasContext *ctx)
1595 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
1596 gen_reserved_instruction(ctx);
1601 * Verify if floating point register is valid; an operation is not defined
1602 * if bit 0 of any register specification is set and the FR bit in the
1603 * Status register equals zero, since the register numbers specify an
1604 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1605 * in the Status register equals one, both even and odd register numbers
1606 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1608 * Multiple 64 bit wide registers can be checked by calling
1609 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1611 void check_cp1_registers(DisasContext *ctx, int regs)
1613 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
1614 gen_reserved_instruction(ctx);
1619 * Verify that the processor is running with DSP instructions enabled.
1620 * This is enabled by CP0 Status register MX(24) bit.
1622 static inline void check_dsp(DisasContext *ctx)
1624 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1625 if (ctx->insn_flags & ASE_DSP) {
1626 generate_exception_end(ctx, EXCP_DSPDIS);
1627 } else {
1628 gen_reserved_instruction(ctx);
1633 static inline void check_dsp_r2(DisasContext *ctx)
1635 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
1636 if (ctx->insn_flags & ASE_DSP) {
1637 generate_exception_end(ctx, EXCP_DSPDIS);
1638 } else {
1639 gen_reserved_instruction(ctx);
1644 static inline void check_dsp_r3(DisasContext *ctx)
1646 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
1647 if (ctx->insn_flags & ASE_DSP) {
1648 generate_exception_end(ctx, EXCP_DSPDIS);
1649 } else {
1650 gen_reserved_instruction(ctx);
1656 * This code generates a "reserved instruction" exception if the
1657 * CPU does not support the instruction set corresponding to flags.
1659 void check_insn(DisasContext *ctx, uint64_t flags)
1661 if (unlikely(!(ctx->insn_flags & flags))) {
1662 gen_reserved_instruction(ctx);
1667 * This code generates a "reserved instruction" exception if the
1668 * CPU has corresponding flag set which indicates that the instruction
1669 * has been removed.
1671 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
1673 if (unlikely(ctx->insn_flags & flags)) {
1674 gen_reserved_instruction(ctx);
1679 * The Linux kernel traps certain reserved instruction exceptions to
1680 * emulate the corresponding instructions. QEMU is the kernel in user
1681 * mode, so those traps are emulated by accepting the instructions.
1683 * A reserved instruction exception is generated for flagged CPUs if
1684 * QEMU runs in system mode.
1686 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
1688 #ifndef CONFIG_USER_ONLY
1689 check_insn_opc_removed(ctx, flags);
1690 #endif
1694 * This code generates a "reserved instruction" exception if the
1695 * CPU does not support 64-bit paired-single (PS) floating point data type.
1697 static inline void check_ps(DisasContext *ctx)
1699 if (unlikely(!ctx->ps)) {
1700 generate_exception(ctx, EXCP_RI);
1702 check_cp1_64bitmode(ctx);
1706 * This code generates a "reserved instruction" exception if cpu is not
1707 * 64-bit or 64-bit instructions are not enabled.
1709 void check_mips_64(DisasContext *ctx)
1711 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
1712 gen_reserved_instruction(ctx);
1716 #ifndef CONFIG_USER_ONLY
1717 static inline void check_mvh(DisasContext *ctx)
1719 if (unlikely(!ctx->mvh)) {
1720 generate_exception(ctx, EXCP_RI);
1723 #endif
1726 * This code generates a "reserved instruction" exception if the
1727 * Config5 XNP bit is set.
1729 static inline void check_xnp(DisasContext *ctx)
1731 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
1732 gen_reserved_instruction(ctx);
1736 #ifndef CONFIG_USER_ONLY
1738 * This code generates a "reserved instruction" exception if the
1739 * Config3 PW bit is NOT set.
1741 static inline void check_pw(DisasContext *ctx)
1743 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
1744 gen_reserved_instruction(ctx);
1747 #endif
1750 * This code generates a "reserved instruction" exception if the
1751 * Config3 MT bit is NOT set.
1753 static inline void check_mt(DisasContext *ctx)
1755 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1756 gen_reserved_instruction(ctx);
1760 #ifndef CONFIG_USER_ONLY
1762 * This code generates a "coprocessor unusable" exception if CP0 is not
1763 * available, and, if that is not the case, generates a "reserved instruction"
1764 * exception if the Config5 MT bit is NOT set. This is needed for availability
1765 * control of some of MT ASE instructions.
1767 static inline void check_cp0_mt(DisasContext *ctx)
1769 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1770 generate_exception_end(ctx, EXCP_CpU);
1771 } else {
1772 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1773 gen_reserved_instruction(ctx);
1777 #endif
1780 * This code generates a "reserved instruction" exception if the
1781 * Config5 NMS bit is set.
1783 static inline void check_nms(DisasContext *ctx)
1785 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
1786 gen_reserved_instruction(ctx);
1791 * This code generates a "reserved instruction" exception if the
1792 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
1793 * Config2 TL, and Config5 L2C are unset.
1795 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
1797 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
1798 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
1799 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
1800 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
1801 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
1802 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
1803 gen_reserved_instruction(ctx);
1808 * This code generates a "reserved instruction" exception if the
1809 * Config5 EVA bit is NOT set.
1811 static inline void check_eva(DisasContext *ctx)
1813 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
1814 gen_reserved_instruction(ctx);
1820 * Define small wrappers for gen_load_fpr* so that we have a uniform
1821 * calling interface for 32 and 64-bit FPRs. No sense in changing
1822 * all callers for gen_load_fpr32 when we need the CTX parameter for
1823 * this one use.
1825 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1826 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1827 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1828 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1829 int ft, int fs, int cc) \
1831 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
1832 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
1833 switch (ifmt) { \
1834 case FMT_PS: \
1835 check_ps(ctx); \
1836 break; \
1837 case FMT_D: \
1838 if (abs) { \
1839 check_cop1x(ctx); \
1841 check_cp1_registers(ctx, fs | ft); \
1842 break; \
1843 case FMT_S: \
1844 if (abs) { \
1845 check_cop1x(ctx); \
1847 break; \
1849 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
1850 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
1851 switch (n) { \
1852 case 0: \
1853 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
1854 break; \
1855 case 1: \
1856 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
1857 break; \
1858 case 2: \
1859 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
1860 break; \
1861 case 3: \
1862 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
1863 break; \
1864 case 4: \
1865 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
1866 break; \
1867 case 5: \
1868 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
1869 break; \
1870 case 6: \
1871 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
1872 break; \
1873 case 7: \
1874 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
1875 break; \
1876 case 8: \
1877 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
1878 break; \
1879 case 9: \
1880 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
1881 break; \
1882 case 10: \
1883 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
1884 break; \
1885 case 11: \
1886 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
1887 break; \
1888 case 12: \
1889 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
1890 break; \
1891 case 13: \
1892 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
1893 break; \
1894 case 14: \
1895 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
1896 break; \
1897 case 15: \
1898 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
1899 break; \
1900 default: \
1901 abort(); \
1903 tcg_temp_free_i##bits(fp0); \
1904 tcg_temp_free_i##bits(fp1); \
1907 FOP_CONDS(, 0, d, FMT_D, 64)
1908 FOP_CONDS(abs, 1, d, FMT_D, 64)
1909 FOP_CONDS(, 0, s, FMT_S, 32)
1910 FOP_CONDS(abs, 1, s, FMT_S, 32)
1911 FOP_CONDS(, 0, ps, FMT_PS, 64)
1912 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1913 #undef FOP_CONDS
1915 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1916 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
1917 int ft, int fs, int fd) \
1919 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1920 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1921 if (ifmt == FMT_D) { \
1922 check_cp1_registers(ctx, fs | ft | fd); \
1924 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1925 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1926 switch (n) { \
1927 case 0: \
1928 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1929 break; \
1930 case 1: \
1931 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1932 break; \
1933 case 2: \
1934 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1935 break; \
1936 case 3: \
1937 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1938 break; \
1939 case 4: \
1940 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1941 break; \
1942 case 5: \
1943 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1944 break; \
1945 case 6: \
1946 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1947 break; \
1948 case 7: \
1949 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1950 break; \
1951 case 8: \
1952 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1953 break; \
1954 case 9: \
1955 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1956 break; \
1957 case 10: \
1958 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1959 break; \
1960 case 11: \
1961 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1962 break; \
1963 case 12: \
1964 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1965 break; \
1966 case 13: \
1967 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1968 break; \
1969 case 14: \
1970 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1971 break; \
1972 case 15: \
1973 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1974 break; \
1975 case 17: \
1976 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1977 break; \
1978 case 18: \
1979 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1980 break; \
1981 case 19: \
1982 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1983 break; \
1984 case 25: \
1985 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1986 break; \
1987 case 26: \
1988 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
1989 break; \
1990 case 27: \
1991 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
1992 break; \
1993 default: \
1994 abort(); \
1996 STORE; \
1997 tcg_temp_free_i ## bits(fp0); \
1998 tcg_temp_free_i ## bits(fp1); \
2001 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2002 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2003 #undef FOP_CONDNS
2004 #undef gen_ldcmp_fpr32
2005 #undef gen_ldcmp_fpr64
2007 /* load/store instructions. */
2008 #ifdef CONFIG_USER_ONLY
2009 #define OP_LD_ATOMIC(insn, fname) \
2010 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2011 DisasContext *ctx) \
2013 TCGv t0 = tcg_temp_new(); \
2014 tcg_gen_mov_tl(t0, arg1); \
2015 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2016 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2017 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2018 tcg_temp_free(t0); \
2020 #else
2021 #define OP_LD_ATOMIC(insn, fname) \
2022 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2023 DisasContext *ctx) \
2025 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2027 #endif
2028 OP_LD_ATOMIC(ll, ld32s);
2029 #if defined(TARGET_MIPS64)
2030 OP_LD_ATOMIC(lld, ld64);
2031 #endif
2032 #undef OP_LD_ATOMIC
2034 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
2036 if (base == 0) {
2037 tcg_gen_movi_tl(addr, offset);
2038 } else if (offset == 0) {
2039 gen_load_gpr(addr, base);
2040 } else {
2041 tcg_gen_movi_tl(addr, offset);
2042 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2046 static target_ulong pc_relative_pc(DisasContext *ctx)
2048 target_ulong pc = ctx->base.pc_next;
2050 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2051 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2053 pc -= branch_bytes;
2056 pc &= ~(target_ulong)3;
2057 return pc;
2060 /* Load */
2061 static void gen_ld(DisasContext *ctx, uint32_t opc,
2062 int rt, int base, int offset)
2064 TCGv t0, t1, t2;
2065 int mem_idx = ctx->mem_idx;
2067 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
2068 INSN_LOONGSON3A)) {
2070 * Loongson CPU uses a load to zero register for prefetch.
2071 * We emulate it as a NOP. On other CPU we must perform the
2072 * actual memory access.
2074 return;
2077 t0 = tcg_temp_new();
2078 gen_base_offset_addr(ctx, t0, base, offset);
2080 switch (opc) {
2081 #if defined(TARGET_MIPS64)
2082 case OPC_LWU:
2083 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
2084 ctx->default_tcg_memop_mask);
2085 gen_store_gpr(t0, rt);
2086 break;
2087 case OPC_LD:
2088 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
2089 ctx->default_tcg_memop_mask);
2090 gen_store_gpr(t0, rt);
2091 break;
2092 case OPC_LLD:
2093 case R6_OPC_LLD:
2094 op_ld_lld(t0, t0, mem_idx, ctx);
2095 gen_store_gpr(t0, rt);
2096 break;
2097 case OPC_LDL:
2098 t1 = tcg_temp_new();
2100 * Do a byte access to possibly trigger a page
2101 * fault with the unaligned address.
2103 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2104 tcg_gen_andi_tl(t1, t0, 7);
2105 #ifndef TARGET_WORDS_BIGENDIAN
2106 tcg_gen_xori_tl(t1, t1, 7);
2107 #endif
2108 tcg_gen_shli_tl(t1, t1, 3);
2109 tcg_gen_andi_tl(t0, t0, ~7);
2110 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2111 tcg_gen_shl_tl(t0, t0, t1);
2112 t2 = tcg_const_tl(-1);
2113 tcg_gen_shl_tl(t2, t2, t1);
2114 gen_load_gpr(t1, rt);
2115 tcg_gen_andc_tl(t1, t1, t2);
2116 tcg_temp_free(t2);
2117 tcg_gen_or_tl(t0, t0, t1);
2118 tcg_temp_free(t1);
2119 gen_store_gpr(t0, rt);
2120 break;
2121 case OPC_LDR:
2122 t1 = tcg_temp_new();
2124 * Do a byte access to possibly trigger a page
2125 * fault with the unaligned address.
2127 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2128 tcg_gen_andi_tl(t1, t0, 7);
2129 #ifdef TARGET_WORDS_BIGENDIAN
2130 tcg_gen_xori_tl(t1, t1, 7);
2131 #endif
2132 tcg_gen_shli_tl(t1, t1, 3);
2133 tcg_gen_andi_tl(t0, t0, ~7);
2134 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2135 tcg_gen_shr_tl(t0, t0, t1);
2136 tcg_gen_xori_tl(t1, t1, 63);
2137 t2 = tcg_const_tl(0xfffffffffffffffeull);
2138 tcg_gen_shl_tl(t2, t2, t1);
2139 gen_load_gpr(t1, rt);
2140 tcg_gen_and_tl(t1, t1, t2);
2141 tcg_temp_free(t2);
2142 tcg_gen_or_tl(t0, t0, t1);
2143 tcg_temp_free(t1);
2144 gen_store_gpr(t0, rt);
2145 break;
2146 case OPC_LDPC:
2147 t1 = tcg_const_tl(pc_relative_pc(ctx));
2148 gen_op_addr_add(ctx, t0, t0, t1);
2149 tcg_temp_free(t1);
2150 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2151 gen_store_gpr(t0, rt);
2152 break;
2153 #endif
2154 case OPC_LWPC:
2155 t1 = tcg_const_tl(pc_relative_pc(ctx));
2156 gen_op_addr_add(ctx, t0, t0, t1);
2157 tcg_temp_free(t1);
2158 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
2159 gen_store_gpr(t0, rt);
2160 break;
2161 case OPC_LWE:
2162 mem_idx = MIPS_HFLAG_UM;
2163 /* fall through */
2164 case OPC_LW:
2165 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
2166 ctx->default_tcg_memop_mask);
2167 gen_store_gpr(t0, rt);
2168 break;
2169 case OPC_LHE:
2170 mem_idx = MIPS_HFLAG_UM;
2171 /* fall through */
2172 case OPC_LH:
2173 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
2174 ctx->default_tcg_memop_mask);
2175 gen_store_gpr(t0, rt);
2176 break;
2177 case OPC_LHUE:
2178 mem_idx = MIPS_HFLAG_UM;
2179 /* fall through */
2180 case OPC_LHU:
2181 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
2182 ctx->default_tcg_memop_mask);
2183 gen_store_gpr(t0, rt);
2184 break;
2185 case OPC_LBE:
2186 mem_idx = MIPS_HFLAG_UM;
2187 /* fall through */
2188 case OPC_LB:
2189 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2190 gen_store_gpr(t0, rt);
2191 break;
2192 case OPC_LBUE:
2193 mem_idx = MIPS_HFLAG_UM;
2194 /* fall through */
2195 case OPC_LBU:
2196 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2197 gen_store_gpr(t0, rt);
2198 break;
2199 case OPC_LWLE:
2200 mem_idx = MIPS_HFLAG_UM;
2201 /* fall through */
2202 case OPC_LWL:
2203 t1 = tcg_temp_new();
2205 * Do a byte access to possibly trigger a page
2206 * fault with the unaligned address.
2208 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2209 tcg_gen_andi_tl(t1, t0, 3);
2210 #ifndef TARGET_WORDS_BIGENDIAN
2211 tcg_gen_xori_tl(t1, t1, 3);
2212 #endif
2213 tcg_gen_shli_tl(t1, t1, 3);
2214 tcg_gen_andi_tl(t0, t0, ~3);
2215 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2216 tcg_gen_shl_tl(t0, t0, t1);
2217 t2 = tcg_const_tl(-1);
2218 tcg_gen_shl_tl(t2, t2, t1);
2219 gen_load_gpr(t1, rt);
2220 tcg_gen_andc_tl(t1, t1, t2);
2221 tcg_temp_free(t2);
2222 tcg_gen_or_tl(t0, t0, t1);
2223 tcg_temp_free(t1);
2224 tcg_gen_ext32s_tl(t0, t0);
2225 gen_store_gpr(t0, rt);
2226 break;
2227 case OPC_LWRE:
2228 mem_idx = MIPS_HFLAG_UM;
2229 /* fall through */
2230 case OPC_LWR:
2231 t1 = tcg_temp_new();
2233 * Do a byte access to possibly trigger a page
2234 * fault with the unaligned address.
2236 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2237 tcg_gen_andi_tl(t1, t0, 3);
2238 #ifdef TARGET_WORDS_BIGENDIAN
2239 tcg_gen_xori_tl(t1, t1, 3);
2240 #endif
2241 tcg_gen_shli_tl(t1, t1, 3);
2242 tcg_gen_andi_tl(t0, t0, ~3);
2243 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2244 tcg_gen_shr_tl(t0, t0, t1);
2245 tcg_gen_xori_tl(t1, t1, 31);
2246 t2 = tcg_const_tl(0xfffffffeull);
2247 tcg_gen_shl_tl(t2, t2, t1);
2248 gen_load_gpr(t1, rt);
2249 tcg_gen_and_tl(t1, t1, t2);
2250 tcg_temp_free(t2);
2251 tcg_gen_or_tl(t0, t0, t1);
2252 tcg_temp_free(t1);
2253 tcg_gen_ext32s_tl(t0, t0);
2254 gen_store_gpr(t0, rt);
2255 break;
2256 case OPC_LLE:
2257 mem_idx = MIPS_HFLAG_UM;
2258 /* fall through */
2259 case OPC_LL:
2260 case R6_OPC_LL:
2261 op_ld_ll(t0, t0, mem_idx, ctx);
2262 gen_store_gpr(t0, rt);
2263 break;
2265 tcg_temp_free(t0);
2268 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
2269 uint32_t reg1, uint32_t reg2)
2271 TCGv taddr = tcg_temp_new();
2272 TCGv_i64 tval = tcg_temp_new_i64();
2273 TCGv tmp1 = tcg_temp_new();
2274 TCGv tmp2 = tcg_temp_new();
2276 gen_base_offset_addr(ctx, taddr, base, offset);
2277 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
2278 #ifdef TARGET_WORDS_BIGENDIAN
2279 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
2280 #else
2281 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
2282 #endif
2283 gen_store_gpr(tmp1, reg1);
2284 tcg_temp_free(tmp1);
2285 gen_store_gpr(tmp2, reg2);
2286 tcg_temp_free(tmp2);
2287 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2288 tcg_temp_free_i64(tval);
2289 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
2290 tcg_temp_free(taddr);
2293 /* Store */
2294 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
2295 int base, int offset)
2297 TCGv t0 = tcg_temp_new();
2298 TCGv t1 = tcg_temp_new();
2299 int mem_idx = ctx->mem_idx;
2301 gen_base_offset_addr(ctx, t0, base, offset);
2302 gen_load_gpr(t1, rt);
2303 switch (opc) {
2304 #if defined(TARGET_MIPS64)
2305 case OPC_SD:
2306 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
2307 ctx->default_tcg_memop_mask);
2308 break;
2309 case OPC_SDL:
2310 gen_helper_0e2i(sdl, t1, t0, mem_idx);
2311 break;
2312 case OPC_SDR:
2313 gen_helper_0e2i(sdr, t1, t0, mem_idx);
2314 break;
2315 #endif
2316 case OPC_SWE:
2317 mem_idx = MIPS_HFLAG_UM;
2318 /* fall through */
2319 case OPC_SW:
2320 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
2321 ctx->default_tcg_memop_mask);
2322 break;
2323 case OPC_SHE:
2324 mem_idx = MIPS_HFLAG_UM;
2325 /* fall through */
2326 case OPC_SH:
2327 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
2328 ctx->default_tcg_memop_mask);
2329 break;
2330 case OPC_SBE:
2331 mem_idx = MIPS_HFLAG_UM;
2332 /* fall through */
2333 case OPC_SB:
2334 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
2335 break;
2336 case OPC_SWLE:
2337 mem_idx = MIPS_HFLAG_UM;
2338 /* fall through */
2339 case OPC_SWL:
2340 gen_helper_0e2i(swl, t1, t0, mem_idx);
2341 break;
2342 case OPC_SWRE:
2343 mem_idx = MIPS_HFLAG_UM;
2344 /* fall through */
2345 case OPC_SWR:
2346 gen_helper_0e2i(swr, t1, t0, mem_idx);
2347 break;
2349 tcg_temp_free(t0);
2350 tcg_temp_free(t1);
2354 /* Store conditional */
2355 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
2356 MemOp tcg_mo, bool eva)
2358 TCGv addr, t0, val;
2359 TCGLabel *l1 = gen_new_label();
2360 TCGLabel *done = gen_new_label();
2362 t0 = tcg_temp_new();
2363 addr = tcg_temp_new();
2364 /* compare the address against that of the preceding LL */
2365 gen_base_offset_addr(ctx, addr, base, offset);
2366 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
2367 tcg_temp_free(addr);
2368 tcg_gen_movi_tl(t0, 0);
2369 gen_store_gpr(t0, rt);
2370 tcg_gen_br(done);
2372 gen_set_label(l1);
2373 /* generate cmpxchg */
2374 val = tcg_temp_new();
2375 gen_load_gpr(val, rt);
2376 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
2377 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
2378 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
2379 gen_store_gpr(t0, rt);
2380 tcg_temp_free(val);
2382 gen_set_label(done);
2383 tcg_temp_free(t0);
2387 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
2388 uint32_t reg1, uint32_t reg2, bool eva)
2390 TCGv taddr = tcg_temp_local_new();
2391 TCGv lladdr = tcg_temp_local_new();
2392 TCGv_i64 tval = tcg_temp_new_i64();
2393 TCGv_i64 llval = tcg_temp_new_i64();
2394 TCGv_i64 val = tcg_temp_new_i64();
2395 TCGv tmp1 = tcg_temp_new();
2396 TCGv tmp2 = tcg_temp_new();
2397 TCGLabel *lab_fail = gen_new_label();
2398 TCGLabel *lab_done = gen_new_label();
2400 gen_base_offset_addr(ctx, taddr, base, offset);
2402 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2403 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
2405 gen_load_gpr(tmp1, reg1);
2406 gen_load_gpr(tmp2, reg2);
2408 #ifdef TARGET_WORDS_BIGENDIAN
2409 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
2410 #else
2411 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
2412 #endif
2414 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2415 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
2416 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
2417 if (reg1 != 0) {
2418 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
2420 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
2422 gen_set_label(lab_fail);
2424 if (reg1 != 0) {
2425 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
2427 gen_set_label(lab_done);
2428 tcg_gen_movi_tl(lladdr, -1);
2429 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2432 /* Load and store */
2433 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
2434 TCGv t0)
2437 * Don't do NOP if destination is zero: we must perform the actual
2438 * memory access.
2440 switch (opc) {
2441 case OPC_LWC1:
2443 TCGv_i32 fp0 = tcg_temp_new_i32();
2444 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2445 ctx->default_tcg_memop_mask);
2446 gen_store_fpr32(ctx, fp0, ft);
2447 tcg_temp_free_i32(fp0);
2449 break;
2450 case OPC_SWC1:
2452 TCGv_i32 fp0 = tcg_temp_new_i32();
2453 gen_load_fpr32(ctx, fp0, ft);
2454 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2455 ctx->default_tcg_memop_mask);
2456 tcg_temp_free_i32(fp0);
2458 break;
2459 case OPC_LDC1:
2461 TCGv_i64 fp0 = tcg_temp_new_i64();
2462 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2463 ctx->default_tcg_memop_mask);
2464 gen_store_fpr64(ctx, fp0, ft);
2465 tcg_temp_free_i64(fp0);
2467 break;
2468 case OPC_SDC1:
2470 TCGv_i64 fp0 = tcg_temp_new_i64();
2471 gen_load_fpr64(ctx, fp0, ft);
2472 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2473 ctx->default_tcg_memop_mask);
2474 tcg_temp_free_i64(fp0);
2476 break;
2477 default:
2478 MIPS_INVAL("flt_ldst");
2479 gen_reserved_instruction(ctx);
2480 break;
2484 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2485 int rs, int16_t imm)
2487 TCGv t0 = tcg_temp_new();
2489 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2490 check_cp1_enabled(ctx);
2491 switch (op) {
2492 case OPC_LDC1:
2493 case OPC_SDC1:
2494 check_insn(ctx, ISA_MIPS2);
2495 /* Fallthrough */
2496 default:
2497 gen_base_offset_addr(ctx, t0, rs, imm);
2498 gen_flt_ldst(ctx, op, rt, t0);
2500 } else {
2501 generate_exception_err(ctx, EXCP_CpU, 1);
2503 tcg_temp_free(t0);
2506 /* Arithmetic with immediate operand */
2507 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2508 int rt, int rs, int imm)
2510 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2512 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2514 * If no destination, treat it as a NOP.
2515 * For addi, we must generate the overflow exception when needed.
2517 return;
2519 switch (opc) {
2520 case OPC_ADDI:
2522 TCGv t0 = tcg_temp_local_new();
2523 TCGv t1 = tcg_temp_new();
2524 TCGv t2 = tcg_temp_new();
2525 TCGLabel *l1 = gen_new_label();
2527 gen_load_gpr(t1, rs);
2528 tcg_gen_addi_tl(t0, t1, uimm);
2529 tcg_gen_ext32s_tl(t0, t0);
2531 tcg_gen_xori_tl(t1, t1, ~uimm);
2532 tcg_gen_xori_tl(t2, t0, uimm);
2533 tcg_gen_and_tl(t1, t1, t2);
2534 tcg_temp_free(t2);
2535 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2536 tcg_temp_free(t1);
2537 /* operands of same sign, result different sign */
2538 generate_exception(ctx, EXCP_OVERFLOW);
2539 gen_set_label(l1);
2540 tcg_gen_ext32s_tl(t0, t0);
2541 gen_store_gpr(t0, rt);
2542 tcg_temp_free(t0);
2544 break;
2545 case OPC_ADDIU:
2546 if (rs != 0) {
2547 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2548 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2549 } else {
2550 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2552 break;
2553 #if defined(TARGET_MIPS64)
2554 case OPC_DADDI:
2556 TCGv t0 = tcg_temp_local_new();
2557 TCGv t1 = tcg_temp_new();
2558 TCGv t2 = tcg_temp_new();
2559 TCGLabel *l1 = gen_new_label();
2561 gen_load_gpr(t1, rs);
2562 tcg_gen_addi_tl(t0, t1, uimm);
2564 tcg_gen_xori_tl(t1, t1, ~uimm);
2565 tcg_gen_xori_tl(t2, t0, uimm);
2566 tcg_gen_and_tl(t1, t1, t2);
2567 tcg_temp_free(t2);
2568 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2569 tcg_temp_free(t1);
2570 /* operands of same sign, result different sign */
2571 generate_exception(ctx, EXCP_OVERFLOW);
2572 gen_set_label(l1);
2573 gen_store_gpr(t0, rt);
2574 tcg_temp_free(t0);
2576 break;
2577 case OPC_DADDIU:
2578 if (rs != 0) {
2579 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2580 } else {
2581 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2583 break;
2584 #endif
2588 /* Logic with immediate operand */
2589 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2590 int rt, int rs, int16_t imm)
2592 target_ulong uimm;
2594 if (rt == 0) {
2595 /* If no destination, treat it as a NOP. */
2596 return;
2598 uimm = (uint16_t)imm;
2599 switch (opc) {
2600 case OPC_ANDI:
2601 if (likely(rs != 0)) {
2602 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2603 } else {
2604 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2606 break;
2607 case OPC_ORI:
2608 if (rs != 0) {
2609 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2610 } else {
2611 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2613 break;
2614 case OPC_XORI:
2615 if (likely(rs != 0)) {
2616 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2617 } else {
2618 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2620 break;
2621 case OPC_LUI:
2622 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
2623 /* OPC_AUI */
2624 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2625 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2626 } else {
2627 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2629 break;
2631 default:
2632 break;
2636 /* Set on less than with immediate operand */
2637 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2638 int rt, int rs, int16_t imm)
2640 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2641 TCGv t0;
2643 if (rt == 0) {
2644 /* If no destination, treat it as a NOP. */
2645 return;
2647 t0 = tcg_temp_new();
2648 gen_load_gpr(t0, rs);
2649 switch (opc) {
2650 case OPC_SLTI:
2651 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2652 break;
2653 case OPC_SLTIU:
2654 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2655 break;
2657 tcg_temp_free(t0);
2660 /* Shifts with immediate operand */
2661 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2662 int rt, int rs, int16_t imm)
2664 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2665 TCGv t0;
2667 if (rt == 0) {
2668 /* If no destination, treat it as a NOP. */
2669 return;
2672 t0 = tcg_temp_new();
2673 gen_load_gpr(t0, rs);
2674 switch (opc) {
2675 case OPC_SLL:
2676 tcg_gen_shli_tl(t0, t0, uimm);
2677 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2678 break;
2679 case OPC_SRA:
2680 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2681 break;
2682 case OPC_SRL:
2683 if (uimm != 0) {
2684 tcg_gen_ext32u_tl(t0, t0);
2685 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2686 } else {
2687 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2689 break;
2690 case OPC_ROTR:
2691 if (uimm != 0) {
2692 TCGv_i32 t1 = tcg_temp_new_i32();
2694 tcg_gen_trunc_tl_i32(t1, t0);
2695 tcg_gen_rotri_i32(t1, t1, uimm);
2696 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2697 tcg_temp_free_i32(t1);
2698 } else {
2699 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2701 break;
2702 #if defined(TARGET_MIPS64)
2703 case OPC_DSLL:
2704 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2705 break;
2706 case OPC_DSRA:
2707 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2708 break;
2709 case OPC_DSRL:
2710 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2711 break;
2712 case OPC_DROTR:
2713 if (uimm != 0) {
2714 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2715 } else {
2716 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2718 break;
2719 case OPC_DSLL32:
2720 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2721 break;
2722 case OPC_DSRA32:
2723 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2724 break;
2725 case OPC_DSRL32:
2726 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2727 break;
2728 case OPC_DROTR32:
2729 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2730 break;
2731 #endif
2733 tcg_temp_free(t0);
2736 /* Arithmetic */
2737 static void gen_arith(DisasContext *ctx, uint32_t opc,
2738 int rd, int rs, int rt)
2740 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2741 && opc != OPC_DADD && opc != OPC_DSUB) {
2743 * If no destination, treat it as a NOP.
2744 * For add & sub, we must generate the overflow exception when needed.
2746 return;
2749 switch (opc) {
2750 case OPC_ADD:
2752 TCGv t0 = tcg_temp_local_new();
2753 TCGv t1 = tcg_temp_new();
2754 TCGv t2 = tcg_temp_new();
2755 TCGLabel *l1 = gen_new_label();
2757 gen_load_gpr(t1, rs);
2758 gen_load_gpr(t2, rt);
2759 tcg_gen_add_tl(t0, t1, t2);
2760 tcg_gen_ext32s_tl(t0, t0);
2761 tcg_gen_xor_tl(t1, t1, t2);
2762 tcg_gen_xor_tl(t2, t0, t2);
2763 tcg_gen_andc_tl(t1, t2, t1);
2764 tcg_temp_free(t2);
2765 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2766 tcg_temp_free(t1);
2767 /* operands of same sign, result different sign */
2768 generate_exception(ctx, EXCP_OVERFLOW);
2769 gen_set_label(l1);
2770 gen_store_gpr(t0, rd);
2771 tcg_temp_free(t0);
2773 break;
2774 case OPC_ADDU:
2775 if (rs != 0 && rt != 0) {
2776 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2777 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2778 } else if (rs == 0 && rt != 0) {
2779 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2780 } else if (rs != 0 && rt == 0) {
2781 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2782 } else {
2783 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2785 break;
2786 case OPC_SUB:
2788 TCGv t0 = tcg_temp_local_new();
2789 TCGv t1 = tcg_temp_new();
2790 TCGv t2 = tcg_temp_new();
2791 TCGLabel *l1 = gen_new_label();
2793 gen_load_gpr(t1, rs);
2794 gen_load_gpr(t2, rt);
2795 tcg_gen_sub_tl(t0, t1, t2);
2796 tcg_gen_ext32s_tl(t0, t0);
2797 tcg_gen_xor_tl(t2, t1, t2);
2798 tcg_gen_xor_tl(t1, t0, t1);
2799 tcg_gen_and_tl(t1, t1, t2);
2800 tcg_temp_free(t2);
2801 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2802 tcg_temp_free(t1);
2804 * operands of different sign, first operand and the result
2805 * of different sign
2807 generate_exception(ctx, EXCP_OVERFLOW);
2808 gen_set_label(l1);
2809 gen_store_gpr(t0, rd);
2810 tcg_temp_free(t0);
2812 break;
2813 case OPC_SUBU:
2814 if (rs != 0 && rt != 0) {
2815 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2816 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2817 } else if (rs == 0 && rt != 0) {
2818 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2819 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2820 } else if (rs != 0 && rt == 0) {
2821 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2822 } else {
2823 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2825 break;
2826 #if defined(TARGET_MIPS64)
2827 case OPC_DADD:
2829 TCGv t0 = tcg_temp_local_new();
2830 TCGv t1 = tcg_temp_new();
2831 TCGv t2 = tcg_temp_new();
2832 TCGLabel *l1 = gen_new_label();
2834 gen_load_gpr(t1, rs);
2835 gen_load_gpr(t2, rt);
2836 tcg_gen_add_tl(t0, t1, t2);
2837 tcg_gen_xor_tl(t1, t1, t2);
2838 tcg_gen_xor_tl(t2, t0, t2);
2839 tcg_gen_andc_tl(t1, t2, t1);
2840 tcg_temp_free(t2);
2841 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2842 tcg_temp_free(t1);
2843 /* operands of same sign, result different sign */
2844 generate_exception(ctx, EXCP_OVERFLOW);
2845 gen_set_label(l1);
2846 gen_store_gpr(t0, rd);
2847 tcg_temp_free(t0);
2849 break;
2850 case OPC_DADDU:
2851 if (rs != 0 && rt != 0) {
2852 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2853 } else if (rs == 0 && rt != 0) {
2854 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2855 } else if (rs != 0 && rt == 0) {
2856 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2857 } else {
2858 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2860 break;
2861 case OPC_DSUB:
2863 TCGv t0 = tcg_temp_local_new();
2864 TCGv t1 = tcg_temp_new();
2865 TCGv t2 = tcg_temp_new();
2866 TCGLabel *l1 = gen_new_label();
2868 gen_load_gpr(t1, rs);
2869 gen_load_gpr(t2, rt);
2870 tcg_gen_sub_tl(t0, t1, t2);
2871 tcg_gen_xor_tl(t2, t1, t2);
2872 tcg_gen_xor_tl(t1, t0, t1);
2873 tcg_gen_and_tl(t1, t1, t2);
2874 tcg_temp_free(t2);
2875 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2876 tcg_temp_free(t1);
2878 * Operands of different sign, first operand and result different
2879 * sign.
2881 generate_exception(ctx, EXCP_OVERFLOW);
2882 gen_set_label(l1);
2883 gen_store_gpr(t0, rd);
2884 tcg_temp_free(t0);
2886 break;
2887 case OPC_DSUBU:
2888 if (rs != 0 && rt != 0) {
2889 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2890 } else if (rs == 0 && rt != 0) {
2891 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2892 } else if (rs != 0 && rt == 0) {
2893 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2894 } else {
2895 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2897 break;
2898 #endif
2899 case OPC_MUL:
2900 if (likely(rs != 0 && rt != 0)) {
2901 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2902 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2903 } else {
2904 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2906 break;
2910 /* Conditional move */
2911 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2912 int rd, int rs, int rt)
2914 TCGv t0, t1, t2;
2916 if (rd == 0) {
2917 /* If no destination, treat it as a NOP. */
2918 return;
2921 t0 = tcg_temp_new();
2922 gen_load_gpr(t0, rt);
2923 t1 = tcg_const_tl(0);
2924 t2 = tcg_temp_new();
2925 gen_load_gpr(t2, rs);
2926 switch (opc) {
2927 case OPC_MOVN:
2928 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2929 break;
2930 case OPC_MOVZ:
2931 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2932 break;
2933 case OPC_SELNEZ:
2934 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2935 break;
2936 case OPC_SELEQZ:
2937 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2938 break;
2940 tcg_temp_free(t2);
2941 tcg_temp_free(t1);
2942 tcg_temp_free(t0);
2945 /* Logic */
2946 static void gen_logic(DisasContext *ctx, uint32_t opc,
2947 int rd, int rs, int rt)
2949 if (rd == 0) {
2950 /* If no destination, treat it as a NOP. */
2951 return;
2954 switch (opc) {
2955 case OPC_AND:
2956 if (likely(rs != 0 && rt != 0)) {
2957 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2958 } else {
2959 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2961 break;
2962 case OPC_NOR:
2963 if (rs != 0 && rt != 0) {
2964 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2965 } else if (rs == 0 && rt != 0) {
2966 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2967 } else if (rs != 0 && rt == 0) {
2968 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2969 } else {
2970 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2972 break;
2973 case OPC_OR:
2974 if (likely(rs != 0 && rt != 0)) {
2975 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2976 } else if (rs == 0 && rt != 0) {
2977 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2978 } else if (rs != 0 && rt == 0) {
2979 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2980 } else {
2981 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2983 break;
2984 case OPC_XOR:
2985 if (likely(rs != 0 && rt != 0)) {
2986 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2987 } else if (rs == 0 && rt != 0) {
2988 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2989 } else if (rs != 0 && rt == 0) {
2990 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2991 } else {
2992 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2994 break;
2998 /* Set on lower than */
2999 static void gen_slt(DisasContext *ctx, uint32_t opc,
3000 int rd, int rs, int rt)
3002 TCGv t0, t1;
3004 if (rd == 0) {
3005 /* If no destination, treat it as a NOP. */
3006 return;
3009 t0 = tcg_temp_new();
3010 t1 = tcg_temp_new();
3011 gen_load_gpr(t0, rs);
3012 gen_load_gpr(t1, rt);
3013 switch (opc) {
3014 case OPC_SLT:
3015 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3016 break;
3017 case OPC_SLTU:
3018 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3019 break;
3021 tcg_temp_free(t0);
3022 tcg_temp_free(t1);
3025 /* Shifts */
3026 static void gen_shift(DisasContext *ctx, uint32_t opc,
3027 int rd, int rs, int rt)
3029 TCGv t0, t1;
3031 if (rd == 0) {
3033 * If no destination, treat it as a NOP.
3034 * For add & sub, we must generate the overflow exception when needed.
3036 return;
3039 t0 = tcg_temp_new();
3040 t1 = tcg_temp_new();
3041 gen_load_gpr(t0, rs);
3042 gen_load_gpr(t1, rt);
3043 switch (opc) {
3044 case OPC_SLLV:
3045 tcg_gen_andi_tl(t0, t0, 0x1f);
3046 tcg_gen_shl_tl(t0, t1, t0);
3047 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3048 break;
3049 case OPC_SRAV:
3050 tcg_gen_andi_tl(t0, t0, 0x1f);
3051 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3052 break;
3053 case OPC_SRLV:
3054 tcg_gen_ext32u_tl(t1, t1);
3055 tcg_gen_andi_tl(t0, t0, 0x1f);
3056 tcg_gen_shr_tl(t0, t1, t0);
3057 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3058 break;
3059 case OPC_ROTRV:
3061 TCGv_i32 t2 = tcg_temp_new_i32();
3062 TCGv_i32 t3 = tcg_temp_new_i32();
3064 tcg_gen_trunc_tl_i32(t2, t0);
3065 tcg_gen_trunc_tl_i32(t3, t1);
3066 tcg_gen_andi_i32(t2, t2, 0x1f);
3067 tcg_gen_rotr_i32(t2, t3, t2);
3068 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3069 tcg_temp_free_i32(t2);
3070 tcg_temp_free_i32(t3);
3072 break;
3073 #if defined(TARGET_MIPS64)
3074 case OPC_DSLLV:
3075 tcg_gen_andi_tl(t0, t0, 0x3f);
3076 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3077 break;
3078 case OPC_DSRAV:
3079 tcg_gen_andi_tl(t0, t0, 0x3f);
3080 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3081 break;
3082 case OPC_DSRLV:
3083 tcg_gen_andi_tl(t0, t0, 0x3f);
3084 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3085 break;
3086 case OPC_DROTRV:
3087 tcg_gen_andi_tl(t0, t0, 0x3f);
3088 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3089 break;
3090 #endif
3092 tcg_temp_free(t0);
3093 tcg_temp_free(t1);
3096 /* Arithmetic on HI/LO registers */
3097 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3099 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3100 /* Treat as NOP. */
3101 return;
3104 if (acc != 0) {
3105 check_dsp(ctx);
3108 switch (opc) {
3109 case OPC_MFHI:
3110 #if defined(TARGET_MIPS64)
3111 if (acc != 0) {
3112 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3113 } else
3114 #endif
3116 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3118 break;
3119 case OPC_MFLO:
3120 #if defined(TARGET_MIPS64)
3121 if (acc != 0) {
3122 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3123 } else
3124 #endif
3126 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3128 break;
3129 case OPC_MTHI:
3130 if (reg != 0) {
3131 #if defined(TARGET_MIPS64)
3132 if (acc != 0) {
3133 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3134 } else
3135 #endif
3137 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3139 } else {
3140 tcg_gen_movi_tl(cpu_HI[acc], 0);
3142 break;
3143 case OPC_MTLO:
3144 if (reg != 0) {
3145 #if defined(TARGET_MIPS64)
3146 if (acc != 0) {
3147 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3148 } else
3149 #endif
3151 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3153 } else {
3154 tcg_gen_movi_tl(cpu_LO[acc], 0);
3156 break;
3160 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3161 MemOp memop)
3163 TCGv t0 = tcg_const_tl(addr);
3164 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3165 gen_store_gpr(t0, reg);
3166 tcg_temp_free(t0);
3169 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3170 int rs)
3172 target_long offset;
3173 target_long addr;
3175 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3176 case OPC_ADDIUPC:
3177 if (rs != 0) {
3178 offset = sextract32(ctx->opcode << 2, 0, 21);
3179 addr = addr_add(ctx, pc, offset);
3180 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3182 break;
3183 case R6_OPC_LWPC:
3184 offset = sextract32(ctx->opcode << 2, 0, 21);
3185 addr = addr_add(ctx, pc, offset);
3186 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3187 break;
3188 #if defined(TARGET_MIPS64)
3189 case OPC_LWUPC:
3190 check_mips_64(ctx);
3191 offset = sextract32(ctx->opcode << 2, 0, 21);
3192 addr = addr_add(ctx, pc, offset);
3193 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3194 break;
3195 #endif
3196 default:
3197 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3198 case OPC_AUIPC:
3199 if (rs != 0) {
3200 offset = sextract32(ctx->opcode, 0, 16) << 16;
3201 addr = addr_add(ctx, pc, offset);
3202 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3204 break;
3205 case OPC_ALUIPC:
3206 if (rs != 0) {
3207 offset = sextract32(ctx->opcode, 0, 16) << 16;
3208 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3209 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3211 break;
3212 #if defined(TARGET_MIPS64)
3213 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3214 case R6_OPC_LDPC + (1 << 16):
3215 case R6_OPC_LDPC + (2 << 16):
3216 case R6_OPC_LDPC + (3 << 16):
3217 check_mips_64(ctx);
3218 offset = sextract32(ctx->opcode << 3, 0, 21);
3219 addr = addr_add(ctx, (pc & ~0x7), offset);
3220 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3221 break;
3222 #endif
3223 default:
3224 MIPS_INVAL("OPC_PCREL");
3225 gen_reserved_instruction(ctx);
3226 break;
3228 break;
3232 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3234 TCGv t0, t1;
3236 if (rd == 0) {
3237 /* Treat as NOP. */
3238 return;
3241 t0 = tcg_temp_new();
3242 t1 = tcg_temp_new();
3244 gen_load_gpr(t0, rs);
3245 gen_load_gpr(t1, rt);
3247 switch (opc) {
3248 case R6_OPC_DIV:
3250 TCGv t2 = tcg_temp_new();
3251 TCGv t3 = tcg_temp_new();
3252 tcg_gen_ext32s_tl(t0, t0);
3253 tcg_gen_ext32s_tl(t1, t1);
3254 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3255 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3256 tcg_gen_and_tl(t2, t2, t3);
3257 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3258 tcg_gen_or_tl(t2, t2, t3);
3259 tcg_gen_movi_tl(t3, 0);
3260 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3261 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3262 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3263 tcg_temp_free(t3);
3264 tcg_temp_free(t2);
3266 break;
3267 case R6_OPC_MOD:
3269 TCGv t2 = tcg_temp_new();
3270 TCGv t3 = tcg_temp_new();
3271 tcg_gen_ext32s_tl(t0, t0);
3272 tcg_gen_ext32s_tl(t1, t1);
3273 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3274 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3275 tcg_gen_and_tl(t2, t2, t3);
3276 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3277 tcg_gen_or_tl(t2, t2, t3);
3278 tcg_gen_movi_tl(t3, 0);
3279 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3280 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3281 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3282 tcg_temp_free(t3);
3283 tcg_temp_free(t2);
3285 break;
3286 case R6_OPC_DIVU:
3288 TCGv t2 = tcg_const_tl(0);
3289 TCGv t3 = tcg_const_tl(1);
3290 tcg_gen_ext32u_tl(t0, t0);
3291 tcg_gen_ext32u_tl(t1, t1);
3292 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3293 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3294 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3295 tcg_temp_free(t3);
3296 tcg_temp_free(t2);
3298 break;
3299 case R6_OPC_MODU:
3301 TCGv t2 = tcg_const_tl(0);
3302 TCGv t3 = tcg_const_tl(1);
3303 tcg_gen_ext32u_tl(t0, t0);
3304 tcg_gen_ext32u_tl(t1, t1);
3305 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3306 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3307 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3308 tcg_temp_free(t3);
3309 tcg_temp_free(t2);
3311 break;
3312 case R6_OPC_MUL:
3314 TCGv_i32 t2 = tcg_temp_new_i32();
3315 TCGv_i32 t3 = tcg_temp_new_i32();
3316 tcg_gen_trunc_tl_i32(t2, t0);
3317 tcg_gen_trunc_tl_i32(t3, t1);
3318 tcg_gen_mul_i32(t2, t2, t3);
3319 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3320 tcg_temp_free_i32(t2);
3321 tcg_temp_free_i32(t3);
3323 break;
3324 case R6_OPC_MUH:
3326 TCGv_i32 t2 = tcg_temp_new_i32();
3327 TCGv_i32 t3 = tcg_temp_new_i32();
3328 tcg_gen_trunc_tl_i32(t2, t0);
3329 tcg_gen_trunc_tl_i32(t3, t1);
3330 tcg_gen_muls2_i32(t2, t3, t2, t3);
3331 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3332 tcg_temp_free_i32(t2);
3333 tcg_temp_free_i32(t3);
3335 break;
3336 case R6_OPC_MULU:
3338 TCGv_i32 t2 = tcg_temp_new_i32();
3339 TCGv_i32 t3 = tcg_temp_new_i32();
3340 tcg_gen_trunc_tl_i32(t2, t0);
3341 tcg_gen_trunc_tl_i32(t3, t1);
3342 tcg_gen_mul_i32(t2, t2, t3);
3343 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3344 tcg_temp_free_i32(t2);
3345 tcg_temp_free_i32(t3);
3347 break;
3348 case R6_OPC_MUHU:
3350 TCGv_i32 t2 = tcg_temp_new_i32();
3351 TCGv_i32 t3 = tcg_temp_new_i32();
3352 tcg_gen_trunc_tl_i32(t2, t0);
3353 tcg_gen_trunc_tl_i32(t3, t1);
3354 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3355 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3356 tcg_temp_free_i32(t2);
3357 tcg_temp_free_i32(t3);
3359 break;
3360 #if defined(TARGET_MIPS64)
3361 case R6_OPC_DDIV:
3363 TCGv t2 = tcg_temp_new();
3364 TCGv t3 = tcg_temp_new();
3365 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3366 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3367 tcg_gen_and_tl(t2, t2, t3);
3368 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3369 tcg_gen_or_tl(t2, t2, t3);
3370 tcg_gen_movi_tl(t3, 0);
3371 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3372 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3373 tcg_temp_free(t3);
3374 tcg_temp_free(t2);
3376 break;
3377 case R6_OPC_DMOD:
3379 TCGv t2 = tcg_temp_new();
3380 TCGv t3 = tcg_temp_new();
3381 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3382 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3383 tcg_gen_and_tl(t2, t2, t3);
3384 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3385 tcg_gen_or_tl(t2, t2, t3);
3386 tcg_gen_movi_tl(t3, 0);
3387 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3388 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3389 tcg_temp_free(t3);
3390 tcg_temp_free(t2);
3392 break;
3393 case R6_OPC_DDIVU:
3395 TCGv t2 = tcg_const_tl(0);
3396 TCGv t3 = tcg_const_tl(1);
3397 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3398 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3399 tcg_temp_free(t3);
3400 tcg_temp_free(t2);
3402 break;
3403 case R6_OPC_DMODU:
3405 TCGv t2 = tcg_const_tl(0);
3406 TCGv t3 = tcg_const_tl(1);
3407 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3408 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3409 tcg_temp_free(t3);
3410 tcg_temp_free(t2);
3412 break;
3413 case R6_OPC_DMUL:
3414 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3415 break;
3416 case R6_OPC_DMUH:
3418 TCGv t2 = tcg_temp_new();
3419 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3420 tcg_temp_free(t2);
3422 break;
3423 case R6_OPC_DMULU:
3424 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3425 break;
3426 case R6_OPC_DMUHU:
3428 TCGv t2 = tcg_temp_new();
3429 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3430 tcg_temp_free(t2);
3432 break;
3433 #endif
3434 default:
3435 MIPS_INVAL("r6 mul/div");
3436 gen_reserved_instruction(ctx);
3437 goto out;
3439 out:
3440 tcg_temp_free(t0);
3441 tcg_temp_free(t1);
3444 #if defined(TARGET_MIPS64)
3445 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
3447 TCGv t0, t1;
3449 t0 = tcg_temp_new();
3450 t1 = tcg_temp_new();
3452 gen_load_gpr(t0, rs);
3453 gen_load_gpr(t1, rt);
3455 switch (opc) {
3456 case MMI_OPC_DIV1:
3458 TCGv t2 = tcg_temp_new();
3459 TCGv t3 = tcg_temp_new();
3460 tcg_gen_ext32s_tl(t0, t0);
3461 tcg_gen_ext32s_tl(t1, t1);
3462 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3463 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3464 tcg_gen_and_tl(t2, t2, t3);
3465 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3466 tcg_gen_or_tl(t2, t2, t3);
3467 tcg_gen_movi_tl(t3, 0);
3468 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3469 tcg_gen_div_tl(cpu_LO[1], t0, t1);
3470 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
3471 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3472 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3473 tcg_temp_free(t3);
3474 tcg_temp_free(t2);
3476 break;
3477 case MMI_OPC_DIVU1:
3479 TCGv t2 = tcg_const_tl(0);
3480 TCGv t3 = tcg_const_tl(1);
3481 tcg_gen_ext32u_tl(t0, t0);
3482 tcg_gen_ext32u_tl(t1, t1);
3483 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3484 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
3485 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
3486 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3487 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3488 tcg_temp_free(t3);
3489 tcg_temp_free(t2);
3491 break;
3492 default:
3493 MIPS_INVAL("div1 TX79");
3494 gen_reserved_instruction(ctx);
3495 goto out;
3497 out:
3498 tcg_temp_free(t0);
3499 tcg_temp_free(t1);
3501 #endif
3503 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3504 int acc, int rs, int rt)
3506 TCGv t0, t1;
3508 t0 = tcg_temp_new();
3509 t1 = tcg_temp_new();
3511 gen_load_gpr(t0, rs);
3512 gen_load_gpr(t1, rt);
3514 if (acc != 0) {
3515 check_dsp(ctx);
3518 switch (opc) {
3519 case OPC_DIV:
3521 TCGv t2 = tcg_temp_new();
3522 TCGv t3 = tcg_temp_new();
3523 tcg_gen_ext32s_tl(t0, t0);
3524 tcg_gen_ext32s_tl(t1, t1);
3525 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3526 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3527 tcg_gen_and_tl(t2, t2, t3);
3528 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3529 tcg_gen_or_tl(t2, t2, t3);
3530 tcg_gen_movi_tl(t3, 0);
3531 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3532 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3533 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3534 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3535 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3536 tcg_temp_free(t3);
3537 tcg_temp_free(t2);
3539 break;
3540 case OPC_DIVU:
3542 TCGv t2 = tcg_const_tl(0);
3543 TCGv t3 = tcg_const_tl(1);
3544 tcg_gen_ext32u_tl(t0, t0);
3545 tcg_gen_ext32u_tl(t1, t1);
3546 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3547 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3548 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3549 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3550 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3551 tcg_temp_free(t3);
3552 tcg_temp_free(t2);
3554 break;
3555 case OPC_MULT:
3557 TCGv_i32 t2 = tcg_temp_new_i32();
3558 TCGv_i32 t3 = tcg_temp_new_i32();
3559 tcg_gen_trunc_tl_i32(t2, t0);
3560 tcg_gen_trunc_tl_i32(t3, t1);
3561 tcg_gen_muls2_i32(t2, t3, t2, t3);
3562 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3563 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3564 tcg_temp_free_i32(t2);
3565 tcg_temp_free_i32(t3);
3567 break;
3568 case OPC_MULTU:
3570 TCGv_i32 t2 = tcg_temp_new_i32();
3571 TCGv_i32 t3 = tcg_temp_new_i32();
3572 tcg_gen_trunc_tl_i32(t2, t0);
3573 tcg_gen_trunc_tl_i32(t3, t1);
3574 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3575 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3576 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3577 tcg_temp_free_i32(t2);
3578 tcg_temp_free_i32(t3);
3580 break;
3581 #if defined(TARGET_MIPS64)
3582 case OPC_DDIV:
3584 TCGv t2 = tcg_temp_new();
3585 TCGv t3 = tcg_temp_new();
3586 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3587 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3588 tcg_gen_and_tl(t2, t2, t3);
3589 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3590 tcg_gen_or_tl(t2, t2, t3);
3591 tcg_gen_movi_tl(t3, 0);
3592 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3593 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3594 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3595 tcg_temp_free(t3);
3596 tcg_temp_free(t2);
3598 break;
3599 case OPC_DDIVU:
3601 TCGv t2 = tcg_const_tl(0);
3602 TCGv t3 = tcg_const_tl(1);
3603 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3604 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3605 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3606 tcg_temp_free(t3);
3607 tcg_temp_free(t2);
3609 break;
3610 case OPC_DMULT:
3611 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3612 break;
3613 case OPC_DMULTU:
3614 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3615 break;
3616 #endif
3617 case OPC_MADD:
3619 TCGv_i64 t2 = tcg_temp_new_i64();
3620 TCGv_i64 t3 = tcg_temp_new_i64();
3622 tcg_gen_ext_tl_i64(t2, t0);
3623 tcg_gen_ext_tl_i64(t3, t1);
3624 tcg_gen_mul_i64(t2, t2, t3);
3625 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3626 tcg_gen_add_i64(t2, t2, t3);
3627 tcg_temp_free_i64(t3);
3628 gen_move_low32(cpu_LO[acc], t2);
3629 gen_move_high32(cpu_HI[acc], t2);
3630 tcg_temp_free_i64(t2);
3632 break;
3633 case OPC_MADDU:
3635 TCGv_i64 t2 = tcg_temp_new_i64();
3636 TCGv_i64 t3 = tcg_temp_new_i64();
3638 tcg_gen_ext32u_tl(t0, t0);
3639 tcg_gen_ext32u_tl(t1, t1);
3640 tcg_gen_extu_tl_i64(t2, t0);
3641 tcg_gen_extu_tl_i64(t3, t1);
3642 tcg_gen_mul_i64(t2, t2, t3);
3643 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3644 tcg_gen_add_i64(t2, t2, t3);
3645 tcg_temp_free_i64(t3);
3646 gen_move_low32(cpu_LO[acc], t2);
3647 gen_move_high32(cpu_HI[acc], t2);
3648 tcg_temp_free_i64(t2);
3650 break;
3651 case OPC_MSUB:
3653 TCGv_i64 t2 = tcg_temp_new_i64();
3654 TCGv_i64 t3 = tcg_temp_new_i64();
3656 tcg_gen_ext_tl_i64(t2, t0);
3657 tcg_gen_ext_tl_i64(t3, t1);
3658 tcg_gen_mul_i64(t2, t2, t3);
3659 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3660 tcg_gen_sub_i64(t2, t3, t2);
3661 tcg_temp_free_i64(t3);
3662 gen_move_low32(cpu_LO[acc], t2);
3663 gen_move_high32(cpu_HI[acc], t2);
3664 tcg_temp_free_i64(t2);
3666 break;
3667 case OPC_MSUBU:
3669 TCGv_i64 t2 = tcg_temp_new_i64();
3670 TCGv_i64 t3 = tcg_temp_new_i64();
3672 tcg_gen_ext32u_tl(t0, t0);
3673 tcg_gen_ext32u_tl(t1, t1);
3674 tcg_gen_extu_tl_i64(t2, t0);
3675 tcg_gen_extu_tl_i64(t3, t1);
3676 tcg_gen_mul_i64(t2, t2, t3);
3677 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3678 tcg_gen_sub_i64(t2, t3, t2);
3679 tcg_temp_free_i64(t3);
3680 gen_move_low32(cpu_LO[acc], t2);
3681 gen_move_high32(cpu_HI[acc], t2);
3682 tcg_temp_free_i64(t2);
3684 break;
3685 default:
3686 MIPS_INVAL("mul/div");
3687 gen_reserved_instruction(ctx);
3688 goto out;
3690 out:
3691 tcg_temp_free(t0);
3692 tcg_temp_free(t1);
3696 * These MULT[U] and MADD[U] instructions implemented in for example
3697 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
3698 * architectures are special three-operand variants with the syntax
3700 * MULT[U][1] rd, rs, rt
3702 * such that
3704 * (rd, LO, HI) <- rs * rt
3706 * and
3708 * MADD[U][1] rd, rs, rt
3710 * such that
3712 * (rd, LO, HI) <- (LO, HI) + rs * rt
3714 * where the low-order 32-bits of the result is placed into both the
3715 * GPR rd and the special register LO. The high-order 32-bits of the
3716 * result is placed into the special register HI.
3718 * If the GPR rd is omitted in assembly language, it is taken to be 0,
3719 * which is the zero register that always reads as 0.
3721 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
3722 int rd, int rs, int rt)
3724 TCGv t0 = tcg_temp_new();
3725 TCGv t1 = tcg_temp_new();
3726 int acc = 0;
3728 gen_load_gpr(t0, rs);
3729 gen_load_gpr(t1, rt);
3731 switch (opc) {
3732 case MMI_OPC_MULT1:
3733 acc = 1;
3734 /* Fall through */
3735 case OPC_MULT:
3737 TCGv_i32 t2 = tcg_temp_new_i32();
3738 TCGv_i32 t3 = tcg_temp_new_i32();
3739 tcg_gen_trunc_tl_i32(t2, t0);
3740 tcg_gen_trunc_tl_i32(t3, t1);
3741 tcg_gen_muls2_i32(t2, t3, t2, t3);
3742 if (rd) {
3743 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3745 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3746 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3747 tcg_temp_free_i32(t2);
3748 tcg_temp_free_i32(t3);
3750 break;
3751 case MMI_OPC_MULTU1:
3752 acc = 1;
3753 /* Fall through */
3754 case OPC_MULTU:
3756 TCGv_i32 t2 = tcg_temp_new_i32();
3757 TCGv_i32 t3 = tcg_temp_new_i32();
3758 tcg_gen_trunc_tl_i32(t2, t0);
3759 tcg_gen_trunc_tl_i32(t3, t1);
3760 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3761 if (rd) {
3762 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3764 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3765 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3766 tcg_temp_free_i32(t2);
3767 tcg_temp_free_i32(t3);
3769 break;
3770 case MMI_OPC_MADD1:
3771 acc = 1;
3772 /* Fall through */
3773 case MMI_OPC_MADD:
3775 TCGv_i64 t2 = tcg_temp_new_i64();
3776 TCGv_i64 t3 = tcg_temp_new_i64();
3778 tcg_gen_ext_tl_i64(t2, t0);
3779 tcg_gen_ext_tl_i64(t3, t1);
3780 tcg_gen_mul_i64(t2, t2, t3);
3781 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3782 tcg_gen_add_i64(t2, t2, t3);
3783 tcg_temp_free_i64(t3);
3784 gen_move_low32(cpu_LO[acc], t2);
3785 gen_move_high32(cpu_HI[acc], t2);
3786 if (rd) {
3787 gen_move_low32(cpu_gpr[rd], t2);
3789 tcg_temp_free_i64(t2);
3791 break;
3792 case MMI_OPC_MADDU1:
3793 acc = 1;
3794 /* Fall through */
3795 case MMI_OPC_MADDU:
3797 TCGv_i64 t2 = tcg_temp_new_i64();
3798 TCGv_i64 t3 = tcg_temp_new_i64();
3800 tcg_gen_ext32u_tl(t0, t0);
3801 tcg_gen_ext32u_tl(t1, t1);
3802 tcg_gen_extu_tl_i64(t2, t0);
3803 tcg_gen_extu_tl_i64(t3, t1);
3804 tcg_gen_mul_i64(t2, t2, t3);
3805 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3806 tcg_gen_add_i64(t2, t2, t3);
3807 tcg_temp_free_i64(t3);
3808 gen_move_low32(cpu_LO[acc], t2);
3809 gen_move_high32(cpu_HI[acc], t2);
3810 if (rd) {
3811 gen_move_low32(cpu_gpr[rd], t2);
3813 tcg_temp_free_i64(t2);
3815 break;
3816 default:
3817 MIPS_INVAL("mul/madd TXx9");
3818 gen_reserved_instruction(ctx);
3819 goto out;
3822 out:
3823 tcg_temp_free(t0);
3824 tcg_temp_free(t1);
3827 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
3828 int rd, int rs, int rt)
3830 TCGv t0 = tcg_temp_new();
3831 TCGv t1 = tcg_temp_new();
3833 gen_load_gpr(t0, rs);
3834 gen_load_gpr(t1, rt);
3836 switch (opc) {
3837 case OPC_VR54XX_MULS:
3838 gen_helper_muls(t0, cpu_env, t0, t1);
3839 break;
3840 case OPC_VR54XX_MULSU:
3841 gen_helper_mulsu(t0, cpu_env, t0, t1);
3842 break;
3843 case OPC_VR54XX_MACC:
3844 gen_helper_macc(t0, cpu_env, t0, t1);
3845 break;
3846 case OPC_VR54XX_MACCU:
3847 gen_helper_maccu(t0, cpu_env, t0, t1);
3848 break;
3849 case OPC_VR54XX_MSAC:
3850 gen_helper_msac(t0, cpu_env, t0, t1);
3851 break;
3852 case OPC_VR54XX_MSACU:
3853 gen_helper_msacu(t0, cpu_env, t0, t1);
3854 break;
3855 case OPC_VR54XX_MULHI:
3856 gen_helper_mulhi(t0, cpu_env, t0, t1);
3857 break;
3858 case OPC_VR54XX_MULHIU:
3859 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3860 break;
3861 case OPC_VR54XX_MULSHI:
3862 gen_helper_mulshi(t0, cpu_env, t0, t1);
3863 break;
3864 case OPC_VR54XX_MULSHIU:
3865 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3866 break;
3867 case OPC_VR54XX_MACCHI:
3868 gen_helper_macchi(t0, cpu_env, t0, t1);
3869 break;
3870 case OPC_VR54XX_MACCHIU:
3871 gen_helper_macchiu(t0, cpu_env, t0, t1);
3872 break;
3873 case OPC_VR54XX_MSACHI:
3874 gen_helper_msachi(t0, cpu_env, t0, t1);
3875 break;
3876 case OPC_VR54XX_MSACHIU:
3877 gen_helper_msachiu(t0, cpu_env, t0, t1);
3878 break;
3879 default:
3880 MIPS_INVAL("mul vr54xx");
3881 gen_reserved_instruction(ctx);
3882 goto out;
3884 gen_store_gpr(t0, rd);
3886 out:
3887 tcg_temp_free(t0);
3888 tcg_temp_free(t1);
3891 static void gen_cl(DisasContext *ctx, uint32_t opc,
3892 int rd, int rs)
3894 TCGv t0;
3896 if (rd == 0) {
3897 /* Treat as NOP. */
3898 return;
3900 t0 = cpu_gpr[rd];
3901 gen_load_gpr(t0, rs);
3903 switch (opc) {
3904 case OPC_CLO:
3905 case R6_OPC_CLO:
3906 #if defined(TARGET_MIPS64)
3907 case OPC_DCLO:
3908 case R6_OPC_DCLO:
3909 #endif
3910 tcg_gen_not_tl(t0, t0);
3911 break;
3914 switch (opc) {
3915 case OPC_CLO:
3916 case R6_OPC_CLO:
3917 case OPC_CLZ:
3918 case R6_OPC_CLZ:
3919 tcg_gen_ext32u_tl(t0, t0);
3920 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3921 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
3922 break;
3923 #if defined(TARGET_MIPS64)
3924 case OPC_DCLO:
3925 case R6_OPC_DCLO:
3926 case OPC_DCLZ:
3927 case R6_OPC_DCLZ:
3928 tcg_gen_clzi_i64(t0, t0, 64);
3929 break;
3930 #endif
3934 /* Godson integer instructions */
3935 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3936 int rd, int rs, int rt)
3938 TCGv t0, t1;
3940 if (rd == 0) {
3941 /* Treat as NOP. */
3942 return;
3945 switch (opc) {
3946 case OPC_MULT_G_2E:
3947 case OPC_MULT_G_2F:
3948 case OPC_MULTU_G_2E:
3949 case OPC_MULTU_G_2F:
3950 #if defined(TARGET_MIPS64)
3951 case OPC_DMULT_G_2E:
3952 case OPC_DMULT_G_2F:
3953 case OPC_DMULTU_G_2E:
3954 case OPC_DMULTU_G_2F:
3955 #endif
3956 t0 = tcg_temp_new();
3957 t1 = tcg_temp_new();
3958 break;
3959 default:
3960 t0 = tcg_temp_local_new();
3961 t1 = tcg_temp_local_new();
3962 break;
3965 gen_load_gpr(t0, rs);
3966 gen_load_gpr(t1, rt);
3968 switch (opc) {
3969 case OPC_MULT_G_2E:
3970 case OPC_MULT_G_2F:
3971 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3972 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3973 break;
3974 case OPC_MULTU_G_2E:
3975 case OPC_MULTU_G_2F:
3976 tcg_gen_ext32u_tl(t0, t0);
3977 tcg_gen_ext32u_tl(t1, t1);
3978 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3979 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3980 break;
3981 case OPC_DIV_G_2E:
3982 case OPC_DIV_G_2F:
3984 TCGLabel *l1 = gen_new_label();
3985 TCGLabel *l2 = gen_new_label();
3986 TCGLabel *l3 = gen_new_label();
3987 tcg_gen_ext32s_tl(t0, t0);
3988 tcg_gen_ext32s_tl(t1, t1);
3989 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3990 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3991 tcg_gen_br(l3);
3992 gen_set_label(l1);
3993 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3994 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3995 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3996 tcg_gen_br(l3);
3997 gen_set_label(l2);
3998 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3999 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4000 gen_set_label(l3);
4002 break;
4003 case OPC_DIVU_G_2E:
4004 case OPC_DIVU_G_2F:
4006 TCGLabel *l1 = gen_new_label();
4007 TCGLabel *l2 = gen_new_label();
4008 tcg_gen_ext32u_tl(t0, t0);
4009 tcg_gen_ext32u_tl(t1, t1);
4010 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4011 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4012 tcg_gen_br(l2);
4013 gen_set_label(l1);
4014 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4015 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4016 gen_set_label(l2);
4018 break;
4019 case OPC_MOD_G_2E:
4020 case OPC_MOD_G_2F:
4022 TCGLabel *l1 = gen_new_label();
4023 TCGLabel *l2 = gen_new_label();
4024 TCGLabel *l3 = gen_new_label();
4025 tcg_gen_ext32u_tl(t0, t0);
4026 tcg_gen_ext32u_tl(t1, t1);
4027 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4028 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4029 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4030 gen_set_label(l1);
4031 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4032 tcg_gen_br(l3);
4033 gen_set_label(l2);
4034 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4035 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4036 gen_set_label(l3);
4038 break;
4039 case OPC_MODU_G_2E:
4040 case OPC_MODU_G_2F:
4042 TCGLabel *l1 = gen_new_label();
4043 TCGLabel *l2 = gen_new_label();
4044 tcg_gen_ext32u_tl(t0, t0);
4045 tcg_gen_ext32u_tl(t1, t1);
4046 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4047 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4048 tcg_gen_br(l2);
4049 gen_set_label(l1);
4050 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4051 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4052 gen_set_label(l2);
4054 break;
4055 #if defined(TARGET_MIPS64)
4056 case OPC_DMULT_G_2E:
4057 case OPC_DMULT_G_2F:
4058 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4059 break;
4060 case OPC_DMULTU_G_2E:
4061 case OPC_DMULTU_G_2F:
4062 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4063 break;
4064 case OPC_DDIV_G_2E:
4065 case OPC_DDIV_G_2F:
4067 TCGLabel *l1 = gen_new_label();
4068 TCGLabel *l2 = gen_new_label();
4069 TCGLabel *l3 = gen_new_label();
4070 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4071 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4072 tcg_gen_br(l3);
4073 gen_set_label(l1);
4074 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4075 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4076 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4077 tcg_gen_br(l3);
4078 gen_set_label(l2);
4079 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4080 gen_set_label(l3);
4082 break;
4083 case OPC_DDIVU_G_2E:
4084 case OPC_DDIVU_G_2F:
4086 TCGLabel *l1 = gen_new_label();
4087 TCGLabel *l2 = gen_new_label();
4088 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4089 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4090 tcg_gen_br(l2);
4091 gen_set_label(l1);
4092 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4093 gen_set_label(l2);
4095 break;
4096 case OPC_DMOD_G_2E:
4097 case OPC_DMOD_G_2F:
4099 TCGLabel *l1 = gen_new_label();
4100 TCGLabel *l2 = gen_new_label();
4101 TCGLabel *l3 = gen_new_label();
4102 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4103 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4104 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4105 gen_set_label(l1);
4106 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4107 tcg_gen_br(l3);
4108 gen_set_label(l2);
4109 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4110 gen_set_label(l3);
4112 break;
4113 case OPC_DMODU_G_2E:
4114 case OPC_DMODU_G_2F:
4116 TCGLabel *l1 = gen_new_label();
4117 TCGLabel *l2 = gen_new_label();
4118 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4119 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4120 tcg_gen_br(l2);
4121 gen_set_label(l1);
4122 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4123 gen_set_label(l2);
4125 break;
4126 #endif
4129 tcg_temp_free(t0);
4130 tcg_temp_free(t1);
4133 /* Loongson multimedia instructions */
4134 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4136 uint32_t opc, shift_max;
4137 TCGv_i64 t0, t1;
4138 TCGCond cond;
4140 opc = MASK_LMMI(ctx->opcode);
4141 switch (opc) {
4142 case OPC_ADD_CP2:
4143 case OPC_SUB_CP2:
4144 case OPC_DADD_CP2:
4145 case OPC_DSUB_CP2:
4146 t0 = tcg_temp_local_new_i64();
4147 t1 = tcg_temp_local_new_i64();
4148 break;
4149 default:
4150 t0 = tcg_temp_new_i64();
4151 t1 = tcg_temp_new_i64();
4152 break;
4155 check_cp1_enabled(ctx);
4156 gen_load_fpr64(ctx, t0, rs);
4157 gen_load_fpr64(ctx, t1, rt);
4159 switch (opc) {
4160 case OPC_PADDSH:
4161 gen_helper_paddsh(t0, t0, t1);
4162 break;
4163 case OPC_PADDUSH:
4164 gen_helper_paddush(t0, t0, t1);
4165 break;
4166 case OPC_PADDH:
4167 gen_helper_paddh(t0, t0, t1);
4168 break;
4169 case OPC_PADDW:
4170 gen_helper_paddw(t0, t0, t1);
4171 break;
4172 case OPC_PADDSB:
4173 gen_helper_paddsb(t0, t0, t1);
4174 break;
4175 case OPC_PADDUSB:
4176 gen_helper_paddusb(t0, t0, t1);
4177 break;
4178 case OPC_PADDB:
4179 gen_helper_paddb(t0, t0, t1);
4180 break;
4182 case OPC_PSUBSH:
4183 gen_helper_psubsh(t0, t0, t1);
4184 break;
4185 case OPC_PSUBUSH:
4186 gen_helper_psubush(t0, t0, t1);
4187 break;
4188 case OPC_PSUBH:
4189 gen_helper_psubh(t0, t0, t1);
4190 break;
4191 case OPC_PSUBW:
4192 gen_helper_psubw(t0, t0, t1);
4193 break;
4194 case OPC_PSUBSB:
4195 gen_helper_psubsb(t0, t0, t1);
4196 break;
4197 case OPC_PSUBUSB:
4198 gen_helper_psubusb(t0, t0, t1);
4199 break;
4200 case OPC_PSUBB:
4201 gen_helper_psubb(t0, t0, t1);
4202 break;
4204 case OPC_PSHUFH:
4205 gen_helper_pshufh(t0, t0, t1);
4206 break;
4207 case OPC_PACKSSWH:
4208 gen_helper_packsswh(t0, t0, t1);
4209 break;
4210 case OPC_PACKSSHB:
4211 gen_helper_packsshb(t0, t0, t1);
4212 break;
4213 case OPC_PACKUSHB:
4214 gen_helper_packushb(t0, t0, t1);
4215 break;
4217 case OPC_PUNPCKLHW:
4218 gen_helper_punpcklhw(t0, t0, t1);
4219 break;
4220 case OPC_PUNPCKHHW:
4221 gen_helper_punpckhhw(t0, t0, t1);
4222 break;
4223 case OPC_PUNPCKLBH:
4224 gen_helper_punpcklbh(t0, t0, t1);
4225 break;
4226 case OPC_PUNPCKHBH:
4227 gen_helper_punpckhbh(t0, t0, t1);
4228 break;
4229 case OPC_PUNPCKLWD:
4230 gen_helper_punpcklwd(t0, t0, t1);
4231 break;
4232 case OPC_PUNPCKHWD:
4233 gen_helper_punpckhwd(t0, t0, t1);
4234 break;
4236 case OPC_PAVGH:
4237 gen_helper_pavgh(t0, t0, t1);
4238 break;
4239 case OPC_PAVGB:
4240 gen_helper_pavgb(t0, t0, t1);
4241 break;
4242 case OPC_PMAXSH:
4243 gen_helper_pmaxsh(t0, t0, t1);
4244 break;
4245 case OPC_PMINSH:
4246 gen_helper_pminsh(t0, t0, t1);
4247 break;
4248 case OPC_PMAXUB:
4249 gen_helper_pmaxub(t0, t0, t1);
4250 break;
4251 case OPC_PMINUB:
4252 gen_helper_pminub(t0, t0, t1);
4253 break;
4255 case OPC_PCMPEQW:
4256 gen_helper_pcmpeqw(t0, t0, t1);
4257 break;
4258 case OPC_PCMPGTW:
4259 gen_helper_pcmpgtw(t0, t0, t1);
4260 break;
4261 case OPC_PCMPEQH:
4262 gen_helper_pcmpeqh(t0, t0, t1);
4263 break;
4264 case OPC_PCMPGTH:
4265 gen_helper_pcmpgth(t0, t0, t1);
4266 break;
4267 case OPC_PCMPEQB:
4268 gen_helper_pcmpeqb(t0, t0, t1);
4269 break;
4270 case OPC_PCMPGTB:
4271 gen_helper_pcmpgtb(t0, t0, t1);
4272 break;
4274 case OPC_PSLLW:
4275 gen_helper_psllw(t0, t0, t1);
4276 break;
4277 case OPC_PSLLH:
4278 gen_helper_psllh(t0, t0, t1);
4279 break;
4280 case OPC_PSRLW:
4281 gen_helper_psrlw(t0, t0, t1);
4282 break;
4283 case OPC_PSRLH:
4284 gen_helper_psrlh(t0, t0, t1);
4285 break;
4286 case OPC_PSRAW:
4287 gen_helper_psraw(t0, t0, t1);
4288 break;
4289 case OPC_PSRAH:
4290 gen_helper_psrah(t0, t0, t1);
4291 break;
4293 case OPC_PMULLH:
4294 gen_helper_pmullh(t0, t0, t1);
4295 break;
4296 case OPC_PMULHH:
4297 gen_helper_pmulhh(t0, t0, t1);
4298 break;
4299 case OPC_PMULHUH:
4300 gen_helper_pmulhuh(t0, t0, t1);
4301 break;
4302 case OPC_PMADDHW:
4303 gen_helper_pmaddhw(t0, t0, t1);
4304 break;
4306 case OPC_PASUBUB:
4307 gen_helper_pasubub(t0, t0, t1);
4308 break;
4309 case OPC_BIADD:
4310 gen_helper_biadd(t0, t0);
4311 break;
4312 case OPC_PMOVMSKB:
4313 gen_helper_pmovmskb(t0, t0);
4314 break;
4316 case OPC_PADDD:
4317 tcg_gen_add_i64(t0, t0, t1);
4318 break;
4319 case OPC_PSUBD:
4320 tcg_gen_sub_i64(t0, t0, t1);
4321 break;
4322 case OPC_XOR_CP2:
4323 tcg_gen_xor_i64(t0, t0, t1);
4324 break;
4325 case OPC_NOR_CP2:
4326 tcg_gen_nor_i64(t0, t0, t1);
4327 break;
4328 case OPC_AND_CP2:
4329 tcg_gen_and_i64(t0, t0, t1);
4330 break;
4331 case OPC_OR_CP2:
4332 tcg_gen_or_i64(t0, t0, t1);
4333 break;
4335 case OPC_PANDN:
4336 tcg_gen_andc_i64(t0, t1, t0);
4337 break;
4339 case OPC_PINSRH_0:
4340 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4341 break;
4342 case OPC_PINSRH_1:
4343 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4344 break;
4345 case OPC_PINSRH_2:
4346 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4347 break;
4348 case OPC_PINSRH_3:
4349 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4350 break;
4352 case OPC_PEXTRH:
4353 tcg_gen_andi_i64(t1, t1, 3);
4354 tcg_gen_shli_i64(t1, t1, 4);
4355 tcg_gen_shr_i64(t0, t0, t1);
4356 tcg_gen_ext16u_i64(t0, t0);
4357 break;
4359 case OPC_ADDU_CP2:
4360 tcg_gen_add_i64(t0, t0, t1);
4361 tcg_gen_ext32s_i64(t0, t0);
4362 break;
4363 case OPC_SUBU_CP2:
4364 tcg_gen_sub_i64(t0, t0, t1);
4365 tcg_gen_ext32s_i64(t0, t0);
4366 break;
4368 case OPC_SLL_CP2:
4369 shift_max = 32;
4370 goto do_shift;
4371 case OPC_SRL_CP2:
4372 shift_max = 32;
4373 goto do_shift;
4374 case OPC_SRA_CP2:
4375 shift_max = 32;
4376 goto do_shift;
4377 case OPC_DSLL_CP2:
4378 shift_max = 64;
4379 goto do_shift;
4380 case OPC_DSRL_CP2:
4381 shift_max = 64;
4382 goto do_shift;
4383 case OPC_DSRA_CP2:
4384 shift_max = 64;
4385 goto do_shift;
4386 do_shift:
4387 /* Make sure shift count isn't TCG undefined behaviour. */
4388 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4390 switch (opc) {
4391 case OPC_SLL_CP2:
4392 case OPC_DSLL_CP2:
4393 tcg_gen_shl_i64(t0, t0, t1);
4394 break;
4395 case OPC_SRA_CP2:
4396 case OPC_DSRA_CP2:
4398 * Since SRA is UndefinedResult without sign-extended inputs,
4399 * we can treat SRA and DSRA the same.
4401 tcg_gen_sar_i64(t0, t0, t1);
4402 break;
4403 case OPC_SRL_CP2:
4404 /* We want to shift in zeros for SRL; zero-extend first. */
4405 tcg_gen_ext32u_i64(t0, t0);
4406 /* FALLTHRU */
4407 case OPC_DSRL_CP2:
4408 tcg_gen_shr_i64(t0, t0, t1);
4409 break;
4412 if (shift_max == 32) {
4413 tcg_gen_ext32s_i64(t0, t0);
4416 /* Shifts larger than MAX produce zero. */
4417 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4418 tcg_gen_neg_i64(t1, t1);
4419 tcg_gen_and_i64(t0, t0, t1);
4420 break;
4422 case OPC_ADD_CP2:
4423 case OPC_DADD_CP2:
4425 TCGv_i64 t2 = tcg_temp_new_i64();
4426 TCGLabel *lab = gen_new_label();
4428 tcg_gen_mov_i64(t2, t0);
4429 tcg_gen_add_i64(t0, t1, t2);
4430 if (opc == OPC_ADD_CP2) {
4431 tcg_gen_ext32s_i64(t0, t0);
4433 tcg_gen_xor_i64(t1, t1, t2);
4434 tcg_gen_xor_i64(t2, t2, t0);
4435 tcg_gen_andc_i64(t1, t2, t1);
4436 tcg_temp_free_i64(t2);
4437 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4438 generate_exception(ctx, EXCP_OVERFLOW);
4439 gen_set_label(lab);
4440 break;
4443 case OPC_SUB_CP2:
4444 case OPC_DSUB_CP2:
4446 TCGv_i64 t2 = tcg_temp_new_i64();
4447 TCGLabel *lab = gen_new_label();
4449 tcg_gen_mov_i64(t2, t0);
4450 tcg_gen_sub_i64(t0, t1, t2);
4451 if (opc == OPC_SUB_CP2) {
4452 tcg_gen_ext32s_i64(t0, t0);
4454 tcg_gen_xor_i64(t1, t1, t2);
4455 tcg_gen_xor_i64(t2, t2, t0);
4456 tcg_gen_and_i64(t1, t1, t2);
4457 tcg_temp_free_i64(t2);
4458 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4459 generate_exception(ctx, EXCP_OVERFLOW);
4460 gen_set_label(lab);
4461 break;
4464 case OPC_PMULUW:
4465 tcg_gen_ext32u_i64(t0, t0);
4466 tcg_gen_ext32u_i64(t1, t1);
4467 tcg_gen_mul_i64(t0, t0, t1);
4468 break;
4470 case OPC_SEQU_CP2:
4471 case OPC_SEQ_CP2:
4472 cond = TCG_COND_EQ;
4473 goto do_cc_cond;
4474 break;
4475 case OPC_SLTU_CP2:
4476 cond = TCG_COND_LTU;
4477 goto do_cc_cond;
4478 break;
4479 case OPC_SLT_CP2:
4480 cond = TCG_COND_LT;
4481 goto do_cc_cond;
4482 break;
4483 case OPC_SLEU_CP2:
4484 cond = TCG_COND_LEU;
4485 goto do_cc_cond;
4486 break;
4487 case OPC_SLE_CP2:
4488 cond = TCG_COND_LE;
4489 do_cc_cond:
4491 int cc = (ctx->opcode >> 8) & 0x7;
4492 TCGv_i64 t64 = tcg_temp_new_i64();
4493 TCGv_i32 t32 = tcg_temp_new_i32();
4495 tcg_gen_setcond_i64(cond, t64, t0, t1);
4496 tcg_gen_extrl_i64_i32(t32, t64);
4497 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
4498 get_fp_bit(cc), 1);
4500 tcg_temp_free_i32(t32);
4501 tcg_temp_free_i64(t64);
4503 goto no_rd;
4504 break;
4505 default:
4506 MIPS_INVAL("loongson_cp2");
4507 gen_reserved_instruction(ctx);
4508 return;
4511 gen_store_fpr64(ctx, t0, rd);
4513 no_rd:
4514 tcg_temp_free_i64(t0);
4515 tcg_temp_free_i64(t1);
4518 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
4519 int rs, int rd)
4521 TCGv t0, t1, t2;
4522 TCGv_i32 fp0;
4523 #if defined(TARGET_MIPS64)
4524 int lsq_rt1 = ctx->opcode & 0x1f;
4525 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
4526 #endif
4527 int shf_offset = sextract32(ctx->opcode, 6, 8);
4529 t0 = tcg_temp_new();
4531 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
4532 #if defined(TARGET_MIPS64)
4533 case OPC_GSLQ:
4534 t1 = tcg_temp_new();
4535 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4536 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4537 ctx->default_tcg_memop_mask);
4538 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4539 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4540 ctx->default_tcg_memop_mask);
4541 gen_store_gpr(t1, rt);
4542 gen_store_gpr(t0, lsq_rt1);
4543 tcg_temp_free(t1);
4544 break;
4545 case OPC_GSLQC1:
4546 check_cp1_enabled(ctx);
4547 t1 = tcg_temp_new();
4548 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4549 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4550 ctx->default_tcg_memop_mask);
4551 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4552 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4553 ctx->default_tcg_memop_mask);
4554 gen_store_fpr64(ctx, t1, rt);
4555 gen_store_fpr64(ctx, t0, lsq_rt1);
4556 tcg_temp_free(t1);
4557 break;
4558 case OPC_GSSQ:
4559 t1 = tcg_temp_new();
4560 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4561 gen_load_gpr(t1, rt);
4562 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4563 ctx->default_tcg_memop_mask);
4564 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4565 gen_load_gpr(t1, lsq_rt1);
4566 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4567 ctx->default_tcg_memop_mask);
4568 tcg_temp_free(t1);
4569 break;
4570 case OPC_GSSQC1:
4571 check_cp1_enabled(ctx);
4572 t1 = tcg_temp_new();
4573 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4574 gen_load_fpr64(ctx, t1, rt);
4575 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4576 ctx->default_tcg_memop_mask);
4577 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4578 gen_load_fpr64(ctx, t1, lsq_rt1);
4579 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4580 ctx->default_tcg_memop_mask);
4581 tcg_temp_free(t1);
4582 break;
4583 #endif
4584 case OPC_GSSHFL:
4585 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4586 case OPC_GSLWLC1:
4587 check_cp1_enabled(ctx);
4588 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4589 t1 = tcg_temp_new();
4590 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4591 tcg_gen_andi_tl(t1, t0, 3);
4592 #ifndef TARGET_WORDS_BIGENDIAN
4593 tcg_gen_xori_tl(t1, t1, 3);
4594 #endif
4595 tcg_gen_shli_tl(t1, t1, 3);
4596 tcg_gen_andi_tl(t0, t0, ~3);
4597 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4598 tcg_gen_shl_tl(t0, t0, t1);
4599 t2 = tcg_const_tl(-1);
4600 tcg_gen_shl_tl(t2, t2, t1);
4601 fp0 = tcg_temp_new_i32();
4602 gen_load_fpr32(ctx, fp0, rt);
4603 tcg_gen_ext_i32_tl(t1, fp0);
4604 tcg_gen_andc_tl(t1, t1, t2);
4605 tcg_temp_free(t2);
4606 tcg_gen_or_tl(t0, t0, t1);
4607 tcg_temp_free(t1);
4608 #if defined(TARGET_MIPS64)
4609 tcg_gen_extrl_i64_i32(fp0, t0);
4610 #else
4611 tcg_gen_ext32s_tl(fp0, t0);
4612 #endif
4613 gen_store_fpr32(ctx, fp0, rt);
4614 tcg_temp_free_i32(fp0);
4615 break;
4616 case OPC_GSLWRC1:
4617 check_cp1_enabled(ctx);
4618 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4619 t1 = tcg_temp_new();
4620 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4621 tcg_gen_andi_tl(t1, t0, 3);
4622 #ifdef TARGET_WORDS_BIGENDIAN
4623 tcg_gen_xori_tl(t1, t1, 3);
4624 #endif
4625 tcg_gen_shli_tl(t1, t1, 3);
4626 tcg_gen_andi_tl(t0, t0, ~3);
4627 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4628 tcg_gen_shr_tl(t0, t0, t1);
4629 tcg_gen_xori_tl(t1, t1, 31);
4630 t2 = tcg_const_tl(0xfffffffeull);
4631 tcg_gen_shl_tl(t2, t2, t1);
4632 fp0 = tcg_temp_new_i32();
4633 gen_load_fpr32(ctx, fp0, rt);
4634 tcg_gen_ext_i32_tl(t1, fp0);
4635 tcg_gen_and_tl(t1, t1, t2);
4636 tcg_temp_free(t2);
4637 tcg_gen_or_tl(t0, t0, t1);
4638 tcg_temp_free(t1);
4639 #if defined(TARGET_MIPS64)
4640 tcg_gen_extrl_i64_i32(fp0, t0);
4641 #else
4642 tcg_gen_ext32s_tl(fp0, t0);
4643 #endif
4644 gen_store_fpr32(ctx, fp0, rt);
4645 tcg_temp_free_i32(fp0);
4646 break;
4647 #if defined(TARGET_MIPS64)
4648 case OPC_GSLDLC1:
4649 check_cp1_enabled(ctx);
4650 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4651 t1 = tcg_temp_new();
4652 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4653 tcg_gen_andi_tl(t1, t0, 7);
4654 #ifndef TARGET_WORDS_BIGENDIAN
4655 tcg_gen_xori_tl(t1, t1, 7);
4656 #endif
4657 tcg_gen_shli_tl(t1, t1, 3);
4658 tcg_gen_andi_tl(t0, t0, ~7);
4659 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4660 tcg_gen_shl_tl(t0, t0, t1);
4661 t2 = tcg_const_tl(-1);
4662 tcg_gen_shl_tl(t2, t2, t1);
4663 gen_load_fpr64(ctx, t1, rt);
4664 tcg_gen_andc_tl(t1, t1, t2);
4665 tcg_temp_free(t2);
4666 tcg_gen_or_tl(t0, t0, t1);
4667 tcg_temp_free(t1);
4668 gen_store_fpr64(ctx, t0, rt);
4669 break;
4670 case OPC_GSLDRC1:
4671 check_cp1_enabled(ctx);
4672 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4673 t1 = tcg_temp_new();
4674 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4675 tcg_gen_andi_tl(t1, t0, 7);
4676 #ifdef TARGET_WORDS_BIGENDIAN
4677 tcg_gen_xori_tl(t1, t1, 7);
4678 #endif
4679 tcg_gen_shli_tl(t1, t1, 3);
4680 tcg_gen_andi_tl(t0, t0, ~7);
4681 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4682 tcg_gen_shr_tl(t0, t0, t1);
4683 tcg_gen_xori_tl(t1, t1, 63);
4684 t2 = tcg_const_tl(0xfffffffffffffffeull);
4685 tcg_gen_shl_tl(t2, t2, t1);
4686 gen_load_fpr64(ctx, t1, rt);
4687 tcg_gen_and_tl(t1, t1, t2);
4688 tcg_temp_free(t2);
4689 tcg_gen_or_tl(t0, t0, t1);
4690 tcg_temp_free(t1);
4691 gen_store_fpr64(ctx, t0, rt);
4692 break;
4693 #endif
4694 default:
4695 MIPS_INVAL("loongson_gsshfl");
4696 gen_reserved_instruction(ctx);
4697 break;
4699 break;
4700 case OPC_GSSHFS:
4701 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4702 case OPC_GSSWLC1:
4703 check_cp1_enabled(ctx);
4704 t1 = tcg_temp_new();
4705 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4706 fp0 = tcg_temp_new_i32();
4707 gen_load_fpr32(ctx, fp0, rt);
4708 tcg_gen_ext_i32_tl(t1, fp0);
4709 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
4710 tcg_temp_free_i32(fp0);
4711 tcg_temp_free(t1);
4712 break;
4713 case OPC_GSSWRC1:
4714 check_cp1_enabled(ctx);
4715 t1 = tcg_temp_new();
4716 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4717 fp0 = tcg_temp_new_i32();
4718 gen_load_fpr32(ctx, fp0, rt);
4719 tcg_gen_ext_i32_tl(t1, fp0);
4720 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
4721 tcg_temp_free_i32(fp0);
4722 tcg_temp_free(t1);
4723 break;
4724 #if defined(TARGET_MIPS64)
4725 case OPC_GSSDLC1:
4726 check_cp1_enabled(ctx);
4727 t1 = tcg_temp_new();
4728 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4729 gen_load_fpr64(ctx, t1, rt);
4730 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
4731 tcg_temp_free(t1);
4732 break;
4733 case OPC_GSSDRC1:
4734 check_cp1_enabled(ctx);
4735 t1 = tcg_temp_new();
4736 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4737 gen_load_fpr64(ctx, t1, rt);
4738 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
4739 tcg_temp_free(t1);
4740 break;
4741 #endif
4742 default:
4743 MIPS_INVAL("loongson_gsshfs");
4744 gen_reserved_instruction(ctx);
4745 break;
4747 break;
4748 default:
4749 MIPS_INVAL("loongson_gslsq");
4750 gen_reserved_instruction(ctx);
4751 break;
4753 tcg_temp_free(t0);
4756 /* Loongson EXT LDC2/SDC2 */
4757 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
4758 int rs, int rd)
4760 int offset = sextract32(ctx->opcode, 3, 8);
4761 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
4762 TCGv t0, t1;
4763 TCGv_i32 fp0;
4765 /* Pre-conditions */
4766 switch (opc) {
4767 case OPC_GSLBX:
4768 case OPC_GSLHX:
4769 case OPC_GSLWX:
4770 case OPC_GSLDX:
4771 /* prefetch, implement as NOP */
4772 if (rt == 0) {
4773 return;
4775 break;
4776 case OPC_GSSBX:
4777 case OPC_GSSHX:
4778 case OPC_GSSWX:
4779 case OPC_GSSDX:
4780 break;
4781 case OPC_GSLWXC1:
4782 #if defined(TARGET_MIPS64)
4783 case OPC_GSLDXC1:
4784 #endif
4785 check_cp1_enabled(ctx);
4786 /* prefetch, implement as NOP */
4787 if (rt == 0) {
4788 return;
4790 break;
4791 case OPC_GSSWXC1:
4792 #if defined(TARGET_MIPS64)
4793 case OPC_GSSDXC1:
4794 #endif
4795 check_cp1_enabled(ctx);
4796 break;
4797 default:
4798 MIPS_INVAL("loongson_lsdc2");
4799 gen_reserved_instruction(ctx);
4800 return;
4801 break;
4804 t0 = tcg_temp_new();
4806 gen_base_offset_addr(ctx, t0, rs, offset);
4807 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4809 switch (opc) {
4810 case OPC_GSLBX:
4811 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
4812 gen_store_gpr(t0, rt);
4813 break;
4814 case OPC_GSLHX:
4815 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
4816 ctx->default_tcg_memop_mask);
4817 gen_store_gpr(t0, rt);
4818 break;
4819 case OPC_GSLWX:
4820 gen_base_offset_addr(ctx, t0, rs, offset);
4821 if (rd) {
4822 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4824 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
4825 ctx->default_tcg_memop_mask);
4826 gen_store_gpr(t0, rt);
4827 break;
4828 #if defined(TARGET_MIPS64)
4829 case OPC_GSLDX:
4830 gen_base_offset_addr(ctx, t0, rs, offset);
4831 if (rd) {
4832 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4834 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4835 ctx->default_tcg_memop_mask);
4836 gen_store_gpr(t0, rt);
4837 break;
4838 #endif
4839 case OPC_GSLWXC1:
4840 check_cp1_enabled(ctx);
4841 gen_base_offset_addr(ctx, t0, rs, offset);
4842 if (rd) {
4843 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4845 fp0 = tcg_temp_new_i32();
4846 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
4847 ctx->default_tcg_memop_mask);
4848 gen_store_fpr32(ctx, fp0, rt);
4849 tcg_temp_free_i32(fp0);
4850 break;
4851 #if defined(TARGET_MIPS64)
4852 case OPC_GSLDXC1:
4853 check_cp1_enabled(ctx);
4854 gen_base_offset_addr(ctx, t0, rs, offset);
4855 if (rd) {
4856 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4858 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4859 ctx->default_tcg_memop_mask);
4860 gen_store_fpr64(ctx, t0, rt);
4861 break;
4862 #endif
4863 case OPC_GSSBX:
4864 t1 = tcg_temp_new();
4865 gen_load_gpr(t1, rt);
4866 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
4867 tcg_temp_free(t1);
4868 break;
4869 case OPC_GSSHX:
4870 t1 = tcg_temp_new();
4871 gen_load_gpr(t1, rt);
4872 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
4873 ctx->default_tcg_memop_mask);
4874 tcg_temp_free(t1);
4875 break;
4876 case OPC_GSSWX:
4877 t1 = tcg_temp_new();
4878 gen_load_gpr(t1, rt);
4879 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
4880 ctx->default_tcg_memop_mask);
4881 tcg_temp_free(t1);
4882 break;
4883 #if defined(TARGET_MIPS64)
4884 case OPC_GSSDX:
4885 t1 = tcg_temp_new();
4886 gen_load_gpr(t1, rt);
4887 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4888 ctx->default_tcg_memop_mask);
4889 tcg_temp_free(t1);
4890 break;
4891 #endif
4892 case OPC_GSSWXC1:
4893 fp0 = tcg_temp_new_i32();
4894 gen_load_fpr32(ctx, fp0, rt);
4895 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
4896 ctx->default_tcg_memop_mask);
4897 tcg_temp_free_i32(fp0);
4898 break;
4899 #if defined(TARGET_MIPS64)
4900 case OPC_GSSDXC1:
4901 t1 = tcg_temp_new();
4902 gen_load_fpr64(ctx, t1, rt);
4903 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
4904 ctx->default_tcg_memop_mask);
4905 tcg_temp_free(t1);
4906 break;
4907 #endif
4908 default:
4909 break;
4912 tcg_temp_free(t0);
4915 /* Traps */
4916 static void gen_trap(DisasContext *ctx, uint32_t opc,
4917 int rs, int rt, int16_t imm)
4919 int cond;
4920 TCGv t0 = tcg_temp_new();
4921 TCGv t1 = tcg_temp_new();
4923 cond = 0;
4924 /* Load needed operands */
4925 switch (opc) {
4926 case OPC_TEQ:
4927 case OPC_TGE:
4928 case OPC_TGEU:
4929 case OPC_TLT:
4930 case OPC_TLTU:
4931 case OPC_TNE:
4932 /* Compare two registers */
4933 if (rs != rt) {
4934 gen_load_gpr(t0, rs);
4935 gen_load_gpr(t1, rt);
4936 cond = 1;
4938 break;
4939 case OPC_TEQI:
4940 case OPC_TGEI:
4941 case OPC_TGEIU:
4942 case OPC_TLTI:
4943 case OPC_TLTIU:
4944 case OPC_TNEI:
4945 /* Compare register to immediate */
4946 if (rs != 0 || imm != 0) {
4947 gen_load_gpr(t0, rs);
4948 tcg_gen_movi_tl(t1, (int32_t)imm);
4949 cond = 1;
4951 break;
4953 if (cond == 0) {
4954 switch (opc) {
4955 case OPC_TEQ: /* rs == rs */
4956 case OPC_TEQI: /* r0 == 0 */
4957 case OPC_TGE: /* rs >= rs */
4958 case OPC_TGEI: /* r0 >= 0 */
4959 case OPC_TGEU: /* rs >= rs unsigned */
4960 case OPC_TGEIU: /* r0 >= 0 unsigned */
4961 /* Always trap */
4962 generate_exception_end(ctx, EXCP_TRAP);
4963 break;
4964 case OPC_TLT: /* rs < rs */
4965 case OPC_TLTI: /* r0 < 0 */
4966 case OPC_TLTU: /* rs < rs unsigned */
4967 case OPC_TLTIU: /* r0 < 0 unsigned */
4968 case OPC_TNE: /* rs != rs */
4969 case OPC_TNEI: /* r0 != 0 */
4970 /* Never trap: treat as NOP. */
4971 break;
4973 } else {
4974 TCGLabel *l1 = gen_new_label();
4976 switch (opc) {
4977 case OPC_TEQ:
4978 case OPC_TEQI:
4979 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4980 break;
4981 case OPC_TGE:
4982 case OPC_TGEI:
4983 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4984 break;
4985 case OPC_TGEU:
4986 case OPC_TGEIU:
4987 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4988 break;
4989 case OPC_TLT:
4990 case OPC_TLTI:
4991 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4992 break;
4993 case OPC_TLTU:
4994 case OPC_TLTIU:
4995 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4996 break;
4997 case OPC_TNE:
4998 case OPC_TNEI:
4999 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5000 break;
5002 generate_exception(ctx, EXCP_TRAP);
5003 gen_set_label(l1);
5005 tcg_temp_free(t0);
5006 tcg_temp_free(t1);
5009 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5011 if (unlikely(ctx->base.singlestep_enabled)) {
5012 return false;
5015 #ifndef CONFIG_USER_ONLY
5016 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5017 #else
5018 return true;
5019 #endif
5022 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5024 if (use_goto_tb(ctx, dest)) {
5025 tcg_gen_goto_tb(n);
5026 gen_save_pc(dest);
5027 tcg_gen_exit_tb(ctx->base.tb, n);
5028 } else {
5029 gen_save_pc(dest);
5030 if (ctx->base.singlestep_enabled) {
5031 save_cpu_state(ctx, 0);
5032 gen_helper_raise_exception_debug(cpu_env);
5034 tcg_gen_lookup_and_goto_ptr();
5038 /* Branches (before delay slot) */
5039 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
5040 int insn_bytes,
5041 int rs, int rt, int32_t offset,
5042 int delayslot_size)
5044 target_ulong btgt = -1;
5045 int blink = 0;
5046 int bcond_compute = 0;
5047 TCGv t0 = tcg_temp_new();
5048 TCGv t1 = tcg_temp_new();
5050 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5051 #ifdef MIPS_DEBUG_DISAS
5052 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5053 TARGET_FMT_lx "\n", ctx->base.pc_next);
5054 #endif
5055 gen_reserved_instruction(ctx);
5056 goto out;
5059 /* Load needed operands */
5060 switch (opc) {
5061 case OPC_BEQ:
5062 case OPC_BEQL:
5063 case OPC_BNE:
5064 case OPC_BNEL:
5065 /* Compare two registers */
5066 if (rs != rt) {
5067 gen_load_gpr(t0, rs);
5068 gen_load_gpr(t1, rt);
5069 bcond_compute = 1;
5071 btgt = ctx->base.pc_next + insn_bytes + offset;
5072 break;
5073 case OPC_BGEZ:
5074 case OPC_BGEZAL:
5075 case OPC_BGEZALL:
5076 case OPC_BGEZL:
5077 case OPC_BGTZ:
5078 case OPC_BGTZL:
5079 case OPC_BLEZ:
5080 case OPC_BLEZL:
5081 case OPC_BLTZ:
5082 case OPC_BLTZAL:
5083 case OPC_BLTZALL:
5084 case OPC_BLTZL:
5085 /* Compare to zero */
5086 if (rs != 0) {
5087 gen_load_gpr(t0, rs);
5088 bcond_compute = 1;
5090 btgt = ctx->base.pc_next + insn_bytes + offset;
5091 break;
5092 case OPC_BPOSGE32:
5093 #if defined(TARGET_MIPS64)
5094 case OPC_BPOSGE64:
5095 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5096 #else
5097 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5098 #endif
5099 bcond_compute = 1;
5100 btgt = ctx->base.pc_next + insn_bytes + offset;
5101 break;
5102 case OPC_J:
5103 case OPC_JAL:
5104 case OPC_JALX:
5105 /* Jump to immediate */
5106 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5107 (uint32_t)offset;
5108 break;
5109 case OPC_JR:
5110 case OPC_JALR:
5111 /* Jump to register */
5112 if (offset != 0 && offset != 16) {
5114 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5115 * others are reserved.
5117 MIPS_INVAL("jump hint");
5118 gen_reserved_instruction(ctx);
5119 goto out;
5121 gen_load_gpr(btarget, rs);
5122 break;
5123 default:
5124 MIPS_INVAL("branch/jump");
5125 gen_reserved_instruction(ctx);
5126 goto out;
5128 if (bcond_compute == 0) {
5129 /* No condition to be computed */
5130 switch (opc) {
5131 case OPC_BEQ: /* rx == rx */
5132 case OPC_BEQL: /* rx == rx likely */
5133 case OPC_BGEZ: /* 0 >= 0 */
5134 case OPC_BGEZL: /* 0 >= 0 likely */
5135 case OPC_BLEZ: /* 0 <= 0 */
5136 case OPC_BLEZL: /* 0 <= 0 likely */
5137 /* Always take */
5138 ctx->hflags |= MIPS_HFLAG_B;
5139 break;
5140 case OPC_BGEZAL: /* 0 >= 0 */
5141 case OPC_BGEZALL: /* 0 >= 0 likely */
5142 /* Always take and link */
5143 blink = 31;
5144 ctx->hflags |= MIPS_HFLAG_B;
5145 break;
5146 case OPC_BNE: /* rx != rx */
5147 case OPC_BGTZ: /* 0 > 0 */
5148 case OPC_BLTZ: /* 0 < 0 */
5149 /* Treat as NOP. */
5150 goto out;
5151 case OPC_BLTZAL: /* 0 < 0 */
5153 * Handle as an unconditional branch to get correct delay
5154 * slot checking.
5156 blink = 31;
5157 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5158 ctx->hflags |= MIPS_HFLAG_B;
5159 break;
5160 case OPC_BLTZALL: /* 0 < 0 likely */
5161 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5162 /* Skip the instruction in the delay slot */
5163 ctx->base.pc_next += 4;
5164 goto out;
5165 case OPC_BNEL: /* rx != rx likely */
5166 case OPC_BGTZL: /* 0 > 0 likely */
5167 case OPC_BLTZL: /* 0 < 0 likely */
5168 /* Skip the instruction in the delay slot */
5169 ctx->base.pc_next += 4;
5170 goto out;
5171 case OPC_J:
5172 ctx->hflags |= MIPS_HFLAG_B;
5173 break;
5174 case OPC_JALX:
5175 ctx->hflags |= MIPS_HFLAG_BX;
5176 /* Fallthrough */
5177 case OPC_JAL:
5178 blink = 31;
5179 ctx->hflags |= MIPS_HFLAG_B;
5180 break;
5181 case OPC_JR:
5182 ctx->hflags |= MIPS_HFLAG_BR;
5183 break;
5184 case OPC_JALR:
5185 blink = rt;
5186 ctx->hflags |= MIPS_HFLAG_BR;
5187 break;
5188 default:
5189 MIPS_INVAL("branch/jump");
5190 gen_reserved_instruction(ctx);
5191 goto out;
5193 } else {
5194 switch (opc) {
5195 case OPC_BEQ:
5196 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5197 goto not_likely;
5198 case OPC_BEQL:
5199 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5200 goto likely;
5201 case OPC_BNE:
5202 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5203 goto not_likely;
5204 case OPC_BNEL:
5205 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5206 goto likely;
5207 case OPC_BGEZ:
5208 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5209 goto not_likely;
5210 case OPC_BGEZL:
5211 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5212 goto likely;
5213 case OPC_BGEZAL:
5214 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5215 blink = 31;
5216 goto not_likely;
5217 case OPC_BGEZALL:
5218 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5219 blink = 31;
5220 goto likely;
5221 case OPC_BGTZ:
5222 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5223 goto not_likely;
5224 case OPC_BGTZL:
5225 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5226 goto likely;
5227 case OPC_BLEZ:
5228 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5229 goto not_likely;
5230 case OPC_BLEZL:
5231 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5232 goto likely;
5233 case OPC_BLTZ:
5234 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5235 goto not_likely;
5236 case OPC_BLTZL:
5237 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5238 goto likely;
5239 case OPC_BPOSGE32:
5240 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5241 goto not_likely;
5242 #if defined(TARGET_MIPS64)
5243 case OPC_BPOSGE64:
5244 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5245 goto not_likely;
5246 #endif
5247 case OPC_BLTZAL:
5248 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5249 blink = 31;
5250 not_likely:
5251 ctx->hflags |= MIPS_HFLAG_BC;
5252 break;
5253 case OPC_BLTZALL:
5254 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5255 blink = 31;
5256 likely:
5257 ctx->hflags |= MIPS_HFLAG_BL;
5258 break;
5259 default:
5260 MIPS_INVAL("conditional branch/jump");
5261 gen_reserved_instruction(ctx);
5262 goto out;
5266 ctx->btarget = btgt;
5268 switch (delayslot_size) {
5269 case 2:
5270 ctx->hflags |= MIPS_HFLAG_BDS16;
5271 break;
5272 case 4:
5273 ctx->hflags |= MIPS_HFLAG_BDS32;
5274 break;
5277 if (blink > 0) {
5278 int post_delay = insn_bytes + delayslot_size;
5279 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5281 tcg_gen_movi_tl(cpu_gpr[blink],
5282 ctx->base.pc_next + post_delay + lowbit);
5285 out:
5286 if (insn_bytes == 2) {
5287 ctx->hflags |= MIPS_HFLAG_B16;
5289 tcg_temp_free(t0);
5290 tcg_temp_free(t1);
5294 /* nanoMIPS Branches */
5295 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5296 int insn_bytes,
5297 int rs, int rt, int32_t offset)
5299 target_ulong btgt = -1;
5300 int bcond_compute = 0;
5301 TCGv t0 = tcg_temp_new();
5302 TCGv t1 = tcg_temp_new();
5304 /* Load needed operands */
5305 switch (opc) {
5306 case OPC_BEQ:
5307 case OPC_BNE:
5308 /* Compare two registers */
5309 if (rs != rt) {
5310 gen_load_gpr(t0, rs);
5311 gen_load_gpr(t1, rt);
5312 bcond_compute = 1;
5314 btgt = ctx->base.pc_next + insn_bytes + offset;
5315 break;
5316 case OPC_BGEZAL:
5317 /* Compare to zero */
5318 if (rs != 0) {
5319 gen_load_gpr(t0, rs);
5320 bcond_compute = 1;
5322 btgt = ctx->base.pc_next + insn_bytes + offset;
5323 break;
5324 case OPC_BPOSGE32:
5325 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5326 bcond_compute = 1;
5327 btgt = ctx->base.pc_next + insn_bytes + offset;
5328 break;
5329 case OPC_JR:
5330 case OPC_JALR:
5331 /* Jump to register */
5332 if (offset != 0 && offset != 16) {
5334 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5335 * others are reserved.
5337 MIPS_INVAL("jump hint");
5338 gen_reserved_instruction(ctx);
5339 goto out;
5341 gen_load_gpr(btarget, rs);
5342 break;
5343 default:
5344 MIPS_INVAL("branch/jump");
5345 gen_reserved_instruction(ctx);
5346 goto out;
5348 if (bcond_compute == 0) {
5349 /* No condition to be computed */
5350 switch (opc) {
5351 case OPC_BEQ: /* rx == rx */
5352 /* Always take */
5353 ctx->hflags |= MIPS_HFLAG_B;
5354 break;
5355 case OPC_BGEZAL: /* 0 >= 0 */
5356 /* Always take and link */
5357 tcg_gen_movi_tl(cpu_gpr[31],
5358 ctx->base.pc_next + insn_bytes);
5359 ctx->hflags |= MIPS_HFLAG_B;
5360 break;
5361 case OPC_BNE: /* rx != rx */
5362 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5363 /* Skip the instruction in the delay slot */
5364 ctx->base.pc_next += 4;
5365 goto out;
5366 case OPC_JR:
5367 ctx->hflags |= MIPS_HFLAG_BR;
5368 break;
5369 case OPC_JALR:
5370 if (rt > 0) {
5371 tcg_gen_movi_tl(cpu_gpr[rt],
5372 ctx->base.pc_next + insn_bytes);
5374 ctx->hflags |= MIPS_HFLAG_BR;
5375 break;
5376 default:
5377 MIPS_INVAL("branch/jump");
5378 gen_reserved_instruction(ctx);
5379 goto out;
5381 } else {
5382 switch (opc) {
5383 case OPC_BEQ:
5384 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5385 goto not_likely;
5386 case OPC_BNE:
5387 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5388 goto not_likely;
5389 case OPC_BGEZAL:
5390 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5391 tcg_gen_movi_tl(cpu_gpr[31],
5392 ctx->base.pc_next + insn_bytes);
5393 goto not_likely;
5394 case OPC_BPOSGE32:
5395 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5396 not_likely:
5397 ctx->hflags |= MIPS_HFLAG_BC;
5398 break;
5399 default:
5400 MIPS_INVAL("conditional branch/jump");
5401 gen_reserved_instruction(ctx);
5402 goto out;
5406 ctx->btarget = btgt;
5408 out:
5409 if (insn_bytes == 2) {
5410 ctx->hflags |= MIPS_HFLAG_B16;
5412 tcg_temp_free(t0);
5413 tcg_temp_free(t1);
5417 /* special3 bitfield operations */
5418 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
5419 int rs, int lsb, int msb)
5421 TCGv t0 = tcg_temp_new();
5422 TCGv t1 = tcg_temp_new();
5424 gen_load_gpr(t1, rs);
5425 switch (opc) {
5426 case OPC_EXT:
5427 if (lsb + msb > 31) {
5428 goto fail;
5430 if (msb != 31) {
5431 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5432 } else {
5434 * The two checks together imply that lsb == 0,
5435 * so this is a simple sign-extension.
5437 tcg_gen_ext32s_tl(t0, t1);
5439 break;
5440 #if defined(TARGET_MIPS64)
5441 case OPC_DEXTU:
5442 lsb += 32;
5443 goto do_dext;
5444 case OPC_DEXTM:
5445 msb += 32;
5446 goto do_dext;
5447 case OPC_DEXT:
5448 do_dext:
5449 if (lsb + msb > 63) {
5450 goto fail;
5452 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5453 break;
5454 #endif
5455 case OPC_INS:
5456 if (lsb > msb) {
5457 goto fail;
5459 gen_load_gpr(t0, rt);
5460 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5461 tcg_gen_ext32s_tl(t0, t0);
5462 break;
5463 #if defined(TARGET_MIPS64)
5464 case OPC_DINSU:
5465 lsb += 32;
5466 /* FALLTHRU */
5467 case OPC_DINSM:
5468 msb += 32;
5469 /* FALLTHRU */
5470 case OPC_DINS:
5471 if (lsb > msb) {
5472 goto fail;
5474 gen_load_gpr(t0, rt);
5475 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5476 break;
5477 #endif
5478 default:
5479 fail:
5480 MIPS_INVAL("bitops");
5481 gen_reserved_instruction(ctx);
5482 tcg_temp_free(t0);
5483 tcg_temp_free(t1);
5484 return;
5486 gen_store_gpr(t0, rt);
5487 tcg_temp_free(t0);
5488 tcg_temp_free(t1);
5491 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
5493 TCGv t0;
5495 if (rd == 0) {
5496 /* If no destination, treat it as a NOP. */
5497 return;
5500 t0 = tcg_temp_new();
5501 gen_load_gpr(t0, rt);
5502 switch (op2) {
5503 case OPC_WSBH:
5505 TCGv t1 = tcg_temp_new();
5506 TCGv t2 = tcg_const_tl(0x00FF00FF);
5508 tcg_gen_shri_tl(t1, t0, 8);
5509 tcg_gen_and_tl(t1, t1, t2);
5510 tcg_gen_and_tl(t0, t0, t2);
5511 tcg_gen_shli_tl(t0, t0, 8);
5512 tcg_gen_or_tl(t0, t0, t1);
5513 tcg_temp_free(t2);
5514 tcg_temp_free(t1);
5515 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5517 break;
5518 case OPC_SEB:
5519 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
5520 break;
5521 case OPC_SEH:
5522 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
5523 break;
5524 #if defined(TARGET_MIPS64)
5525 case OPC_DSBH:
5527 TCGv t1 = tcg_temp_new();
5528 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
5530 tcg_gen_shri_tl(t1, t0, 8);
5531 tcg_gen_and_tl(t1, t1, t2);
5532 tcg_gen_and_tl(t0, t0, t2);
5533 tcg_gen_shli_tl(t0, t0, 8);
5534 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5535 tcg_temp_free(t2);
5536 tcg_temp_free(t1);
5538 break;
5539 case OPC_DSHD:
5541 TCGv t1 = tcg_temp_new();
5542 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
5544 tcg_gen_shri_tl(t1, t0, 16);
5545 tcg_gen_and_tl(t1, t1, t2);
5546 tcg_gen_and_tl(t0, t0, t2);
5547 tcg_gen_shli_tl(t0, t0, 16);
5548 tcg_gen_or_tl(t0, t0, t1);
5549 tcg_gen_shri_tl(t1, t0, 32);
5550 tcg_gen_shli_tl(t0, t0, 32);
5551 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5552 tcg_temp_free(t2);
5553 tcg_temp_free(t1);
5555 break;
5556 #endif
5557 default:
5558 MIPS_INVAL("bsfhl");
5559 gen_reserved_instruction(ctx);
5560 tcg_temp_free(t0);
5561 return;
5563 tcg_temp_free(t0);
5566 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
5567 int rt, int bits)
5569 TCGv t0;
5570 if (rd == 0) {
5571 /* Treat as NOP. */
5572 return;
5574 t0 = tcg_temp_new();
5575 if (bits == 0 || bits == wordsz) {
5576 if (bits == 0) {
5577 gen_load_gpr(t0, rt);
5578 } else {
5579 gen_load_gpr(t0, rs);
5581 switch (wordsz) {
5582 case 32:
5583 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5584 break;
5585 #if defined(TARGET_MIPS64)
5586 case 64:
5587 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5588 break;
5589 #endif
5591 } else {
5592 TCGv t1 = tcg_temp_new();
5593 gen_load_gpr(t0, rt);
5594 gen_load_gpr(t1, rs);
5595 switch (wordsz) {
5596 case 32:
5598 TCGv_i64 t2 = tcg_temp_new_i64();
5599 tcg_gen_concat_tl_i64(t2, t1, t0);
5600 tcg_gen_shri_i64(t2, t2, 32 - bits);
5601 gen_move_low32(cpu_gpr[rd], t2);
5602 tcg_temp_free_i64(t2);
5604 break;
5605 #if defined(TARGET_MIPS64)
5606 case 64:
5607 tcg_gen_shli_tl(t0, t0, bits);
5608 tcg_gen_shri_tl(t1, t1, 64 - bits);
5609 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5610 break;
5611 #endif
5613 tcg_temp_free(t1);
5616 tcg_temp_free(t0);
5619 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5620 int bp)
5622 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5625 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5626 int shift)
5628 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5631 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5633 TCGv t0;
5634 if (rd == 0) {
5635 /* Treat as NOP. */
5636 return;
5638 t0 = tcg_temp_new();
5639 gen_load_gpr(t0, rt);
5640 switch (opc) {
5641 case OPC_BITSWAP:
5642 gen_helper_bitswap(cpu_gpr[rd], t0);
5643 break;
5644 #if defined(TARGET_MIPS64)
5645 case OPC_DBITSWAP:
5646 gen_helper_dbitswap(cpu_gpr[rd], t0);
5647 break;
5648 #endif
5650 tcg_temp_free(t0);
5653 #ifndef CONFIG_USER_ONLY
5654 /* CP0 (MMU and control) */
5655 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5657 TCGv_i64 t0 = tcg_temp_new_i64();
5658 TCGv_i64 t1 = tcg_temp_new_i64();
5660 tcg_gen_ext_tl_i64(t0, arg);
5661 tcg_gen_ld_i64(t1, cpu_env, off);
5662 #if defined(TARGET_MIPS64)
5663 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5664 #else
5665 tcg_gen_concat32_i64(t1, t1, t0);
5666 #endif
5667 tcg_gen_st_i64(t1, cpu_env, off);
5668 tcg_temp_free_i64(t1);
5669 tcg_temp_free_i64(t0);
5672 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5674 TCGv_i64 t0 = tcg_temp_new_i64();
5675 TCGv_i64 t1 = tcg_temp_new_i64();
5677 tcg_gen_ext_tl_i64(t0, arg);
5678 tcg_gen_ld_i64(t1, cpu_env, off);
5679 tcg_gen_concat32_i64(t1, t1, t0);
5680 tcg_gen_st_i64(t1, cpu_env, off);
5681 tcg_temp_free_i64(t1);
5682 tcg_temp_free_i64(t0);
5685 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5687 TCGv_i64 t0 = tcg_temp_new_i64();
5689 tcg_gen_ld_i64(t0, cpu_env, off);
5690 #if defined(TARGET_MIPS64)
5691 tcg_gen_shri_i64(t0, t0, 30);
5692 #else
5693 tcg_gen_shri_i64(t0, t0, 32);
5694 #endif
5695 gen_move_low32(arg, t0);
5696 tcg_temp_free_i64(t0);
5699 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5701 TCGv_i64 t0 = tcg_temp_new_i64();
5703 tcg_gen_ld_i64(t0, cpu_env, off);
5704 tcg_gen_shri_i64(t0, t0, 32 + shift);
5705 gen_move_low32(arg, t0);
5706 tcg_temp_free_i64(t0);
5709 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
5711 TCGv_i32 t0 = tcg_temp_new_i32();
5713 tcg_gen_ld_i32(t0, cpu_env, off);
5714 tcg_gen_ext_i32_tl(arg, t0);
5715 tcg_temp_free_i32(t0);
5718 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
5720 tcg_gen_ld_tl(arg, cpu_env, off);
5721 tcg_gen_ext32s_tl(arg, arg);
5724 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
5726 TCGv_i32 t0 = tcg_temp_new_i32();
5728 tcg_gen_trunc_tl_i32(t0, arg);
5729 tcg_gen_st_i32(t0, cpu_env, off);
5730 tcg_temp_free_i32(t0);
5733 #define CP0_CHECK(c) \
5734 do { \
5735 if (!(c)) { \
5736 goto cp0_unimplemented; \
5738 } while (0)
5740 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5742 const char *register_name = "invalid";
5744 switch (reg) {
5745 case CP0_REGISTER_02:
5746 switch (sel) {
5747 case 0:
5748 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5749 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5750 register_name = "EntryLo0";
5751 break;
5752 default:
5753 goto cp0_unimplemented;
5755 break;
5756 case CP0_REGISTER_03:
5757 switch (sel) {
5758 case CP0_REG03__ENTRYLO1:
5759 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5760 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5761 register_name = "EntryLo1";
5762 break;
5763 default:
5764 goto cp0_unimplemented;
5766 break;
5767 case CP0_REGISTER_09:
5768 switch (sel) {
5769 case CP0_REG09__SAAR:
5770 CP0_CHECK(ctx->saar);
5771 gen_helper_mfhc0_saar(arg, cpu_env);
5772 register_name = "SAAR";
5773 break;
5774 default:
5775 goto cp0_unimplemented;
5777 break;
5778 case CP0_REGISTER_17:
5779 switch (sel) {
5780 case CP0_REG17__LLADDR:
5781 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
5782 ctx->CP0_LLAddr_shift);
5783 register_name = "LLAddr";
5784 break;
5785 case CP0_REG17__MAAR:
5786 CP0_CHECK(ctx->mrp);
5787 gen_helper_mfhc0_maar(arg, cpu_env);
5788 register_name = "MAAR";
5789 break;
5790 default:
5791 goto cp0_unimplemented;
5793 break;
5794 case CP0_REGISTER_19:
5795 switch (sel) {
5796 case CP0_REG19__WATCHHI0:
5797 case CP0_REG19__WATCHHI1:
5798 case CP0_REG19__WATCHHI2:
5799 case CP0_REG19__WATCHHI3:
5800 case CP0_REG19__WATCHHI4:
5801 case CP0_REG19__WATCHHI5:
5802 case CP0_REG19__WATCHHI6:
5803 case CP0_REG19__WATCHHI7:
5804 /* upper 32 bits are only available when Config5MI != 0 */
5805 CP0_CHECK(ctx->mi);
5806 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
5807 register_name = "WatchHi";
5808 break;
5809 default:
5810 goto cp0_unimplemented;
5812 break;
5813 case CP0_REGISTER_28:
5814 switch (sel) {
5815 case 0:
5816 case 2:
5817 case 4:
5818 case 6:
5819 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5820 register_name = "TagLo";
5821 break;
5822 default:
5823 goto cp0_unimplemented;
5825 break;
5826 default:
5827 goto cp0_unimplemented;
5829 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
5830 return;
5832 cp0_unimplemented:
5833 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
5834 register_name, reg, sel);
5835 tcg_gen_movi_tl(arg, 0);
5838 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5840 const char *register_name = "invalid";
5841 uint64_t mask = ctx->PAMask >> 36;
5843 switch (reg) {
5844 case CP0_REGISTER_02:
5845 switch (sel) {
5846 case 0:
5847 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5848 tcg_gen_andi_tl(arg, arg, mask);
5849 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5850 register_name = "EntryLo0";
5851 break;
5852 default:
5853 goto cp0_unimplemented;
5855 break;
5856 case CP0_REGISTER_03:
5857 switch (sel) {
5858 case CP0_REG03__ENTRYLO1:
5859 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5860 tcg_gen_andi_tl(arg, arg, mask);
5861 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5862 register_name = "EntryLo1";
5863 break;
5864 default:
5865 goto cp0_unimplemented;
5867 break;
5868 case CP0_REGISTER_09:
5869 switch (sel) {
5870 case CP0_REG09__SAAR:
5871 CP0_CHECK(ctx->saar);
5872 gen_helper_mthc0_saar(cpu_env, arg);
5873 register_name = "SAAR";
5874 break;
5875 default:
5876 goto cp0_unimplemented;
5878 break;
5879 case CP0_REGISTER_17:
5880 switch (sel) {
5881 case CP0_REG17__LLADDR:
5883 * LLAddr is read-only (the only exception is bit 0 if LLB is
5884 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
5885 * relevant for modern MIPS cores supporting MTHC0, therefore
5886 * treating MTHC0 to LLAddr as NOP.
5888 register_name = "LLAddr";
5889 break;
5890 case CP0_REG17__MAAR:
5891 CP0_CHECK(ctx->mrp);
5892 gen_helper_mthc0_maar(cpu_env, arg);
5893 register_name = "MAAR";
5894 break;
5895 default:
5896 goto cp0_unimplemented;
5898 break;
5899 case CP0_REGISTER_19:
5900 switch (sel) {
5901 case CP0_REG19__WATCHHI0:
5902 case CP0_REG19__WATCHHI1:
5903 case CP0_REG19__WATCHHI2:
5904 case CP0_REG19__WATCHHI3:
5905 case CP0_REG19__WATCHHI4:
5906 case CP0_REG19__WATCHHI5:
5907 case CP0_REG19__WATCHHI6:
5908 case CP0_REG19__WATCHHI7:
5909 /* upper 32 bits are only available when Config5MI != 0 */
5910 CP0_CHECK(ctx->mi);
5911 gen_helper_0e1i(mthc0_watchhi, arg, sel);
5912 register_name = "WatchHi";
5913 break;
5914 default:
5915 goto cp0_unimplemented;
5917 break;
5918 case CP0_REGISTER_28:
5919 switch (sel) {
5920 case 0:
5921 case 2:
5922 case 4:
5923 case 6:
5924 tcg_gen_andi_tl(arg, arg, mask);
5925 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5926 register_name = "TagLo";
5927 break;
5928 default:
5929 goto cp0_unimplemented;
5931 break;
5932 default:
5933 goto cp0_unimplemented;
5935 trace_mips_translate_c0("mthc0", register_name, reg, sel);
5936 return;
5938 cp0_unimplemented:
5939 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
5940 register_name, reg, sel);
5943 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5945 if (ctx->insn_flags & ISA_MIPS_R6) {
5946 tcg_gen_movi_tl(arg, 0);
5947 } else {
5948 tcg_gen_movi_tl(arg, ~0);
5952 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5954 const char *register_name = "invalid";
5956 if (sel != 0) {
5957 check_insn(ctx, ISA_MIPS_R1);
5960 switch (reg) {
5961 case CP0_REGISTER_00:
5962 switch (sel) {
5963 case CP0_REG00__INDEX:
5964 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5965 register_name = "Index";
5966 break;
5967 case CP0_REG00__MVPCONTROL:
5968 CP0_CHECK(ctx->insn_flags & ASE_MT);
5969 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5970 register_name = "MVPControl";
5971 break;
5972 case CP0_REG00__MVPCONF0:
5973 CP0_CHECK(ctx->insn_flags & ASE_MT);
5974 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5975 register_name = "MVPConf0";
5976 break;
5977 case CP0_REG00__MVPCONF1:
5978 CP0_CHECK(ctx->insn_flags & ASE_MT);
5979 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5980 register_name = "MVPConf1";
5981 break;
5982 case CP0_REG00__VPCONTROL:
5983 CP0_CHECK(ctx->vp);
5984 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
5985 register_name = "VPControl";
5986 break;
5987 default:
5988 goto cp0_unimplemented;
5990 break;
5991 case CP0_REGISTER_01:
5992 switch (sel) {
5993 case CP0_REG01__RANDOM:
5994 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
5995 gen_helper_mfc0_random(arg, cpu_env);
5996 register_name = "Random";
5997 break;
5998 case CP0_REG01__VPECONTROL:
5999 CP0_CHECK(ctx->insn_flags & ASE_MT);
6000 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6001 register_name = "VPEControl";
6002 break;
6003 case CP0_REG01__VPECONF0:
6004 CP0_CHECK(ctx->insn_flags & ASE_MT);
6005 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6006 register_name = "VPEConf0";
6007 break;
6008 case CP0_REG01__VPECONF1:
6009 CP0_CHECK(ctx->insn_flags & ASE_MT);
6010 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6011 register_name = "VPEConf1";
6012 break;
6013 case CP0_REG01__YQMASK:
6014 CP0_CHECK(ctx->insn_flags & ASE_MT);
6015 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6016 register_name = "YQMask";
6017 break;
6018 case CP0_REG01__VPESCHEDULE:
6019 CP0_CHECK(ctx->insn_flags & ASE_MT);
6020 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6021 register_name = "VPESchedule";
6022 break;
6023 case CP0_REG01__VPESCHEFBACK:
6024 CP0_CHECK(ctx->insn_flags & ASE_MT);
6025 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6026 register_name = "VPEScheFBack";
6027 break;
6028 case CP0_REG01__VPEOPT:
6029 CP0_CHECK(ctx->insn_flags & ASE_MT);
6030 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6031 register_name = "VPEOpt";
6032 break;
6033 default:
6034 goto cp0_unimplemented;
6036 break;
6037 case CP0_REGISTER_02:
6038 switch (sel) {
6039 case CP0_REG02__ENTRYLO0:
6041 TCGv_i64 tmp = tcg_temp_new_i64();
6042 tcg_gen_ld_i64(tmp, cpu_env,
6043 offsetof(CPUMIPSState, CP0_EntryLo0));
6044 #if defined(TARGET_MIPS64)
6045 if (ctx->rxi) {
6046 /* Move RI/XI fields to bits 31:30 */
6047 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6048 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6050 #endif
6051 gen_move_low32(arg, tmp);
6052 tcg_temp_free_i64(tmp);
6054 register_name = "EntryLo0";
6055 break;
6056 case CP0_REG02__TCSTATUS:
6057 CP0_CHECK(ctx->insn_flags & ASE_MT);
6058 gen_helper_mfc0_tcstatus(arg, cpu_env);
6059 register_name = "TCStatus";
6060 break;
6061 case CP0_REG02__TCBIND:
6062 CP0_CHECK(ctx->insn_flags & ASE_MT);
6063 gen_helper_mfc0_tcbind(arg, cpu_env);
6064 register_name = "TCBind";
6065 break;
6066 case CP0_REG02__TCRESTART:
6067 CP0_CHECK(ctx->insn_flags & ASE_MT);
6068 gen_helper_mfc0_tcrestart(arg, cpu_env);
6069 register_name = "TCRestart";
6070 break;
6071 case CP0_REG02__TCHALT:
6072 CP0_CHECK(ctx->insn_flags & ASE_MT);
6073 gen_helper_mfc0_tchalt(arg, cpu_env);
6074 register_name = "TCHalt";
6075 break;
6076 case CP0_REG02__TCCONTEXT:
6077 CP0_CHECK(ctx->insn_flags & ASE_MT);
6078 gen_helper_mfc0_tccontext(arg, cpu_env);
6079 register_name = "TCContext";
6080 break;
6081 case CP0_REG02__TCSCHEDULE:
6082 CP0_CHECK(ctx->insn_flags & ASE_MT);
6083 gen_helper_mfc0_tcschedule(arg, cpu_env);
6084 register_name = "TCSchedule";
6085 break;
6086 case CP0_REG02__TCSCHEFBACK:
6087 CP0_CHECK(ctx->insn_flags & ASE_MT);
6088 gen_helper_mfc0_tcschefback(arg, cpu_env);
6089 register_name = "TCScheFBack";
6090 break;
6091 default:
6092 goto cp0_unimplemented;
6094 break;
6095 case CP0_REGISTER_03:
6096 switch (sel) {
6097 case CP0_REG03__ENTRYLO1:
6099 TCGv_i64 tmp = tcg_temp_new_i64();
6100 tcg_gen_ld_i64(tmp, cpu_env,
6101 offsetof(CPUMIPSState, CP0_EntryLo1));
6102 #if defined(TARGET_MIPS64)
6103 if (ctx->rxi) {
6104 /* Move RI/XI fields to bits 31:30 */
6105 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6106 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6108 #endif
6109 gen_move_low32(arg, tmp);
6110 tcg_temp_free_i64(tmp);
6112 register_name = "EntryLo1";
6113 break;
6114 case CP0_REG03__GLOBALNUM:
6115 CP0_CHECK(ctx->vp);
6116 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6117 register_name = "GlobalNumber";
6118 break;
6119 default:
6120 goto cp0_unimplemented;
6122 break;
6123 case CP0_REGISTER_04:
6124 switch (sel) {
6125 case CP0_REG04__CONTEXT:
6126 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6127 tcg_gen_ext32s_tl(arg, arg);
6128 register_name = "Context";
6129 break;
6130 case CP0_REG04__CONTEXTCONFIG:
6131 /* SmartMIPS ASE */
6132 /* gen_helper_mfc0_contextconfig(arg); */
6133 register_name = "ContextConfig";
6134 goto cp0_unimplemented;
6135 case CP0_REG04__USERLOCAL:
6136 CP0_CHECK(ctx->ulri);
6137 tcg_gen_ld_tl(arg, cpu_env,
6138 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6139 tcg_gen_ext32s_tl(arg, arg);
6140 register_name = "UserLocal";
6141 break;
6142 case CP0_REG04__MMID:
6143 CP0_CHECK(ctx->mi);
6144 gen_helper_mtc0_memorymapid(cpu_env, arg);
6145 register_name = "MMID";
6146 break;
6147 default:
6148 goto cp0_unimplemented;
6150 break;
6151 case CP0_REGISTER_05:
6152 switch (sel) {
6153 case CP0_REG05__PAGEMASK:
6154 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6155 register_name = "PageMask";
6156 break;
6157 case CP0_REG05__PAGEGRAIN:
6158 check_insn(ctx, ISA_MIPS_R2);
6159 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6160 register_name = "PageGrain";
6161 break;
6162 case CP0_REG05__SEGCTL0:
6163 CP0_CHECK(ctx->sc);
6164 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6165 tcg_gen_ext32s_tl(arg, arg);
6166 register_name = "SegCtl0";
6167 break;
6168 case CP0_REG05__SEGCTL1:
6169 CP0_CHECK(ctx->sc);
6170 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6171 tcg_gen_ext32s_tl(arg, arg);
6172 register_name = "SegCtl1";
6173 break;
6174 case CP0_REG05__SEGCTL2:
6175 CP0_CHECK(ctx->sc);
6176 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6177 tcg_gen_ext32s_tl(arg, arg);
6178 register_name = "SegCtl2";
6179 break;
6180 case CP0_REG05__PWBASE:
6181 check_pw(ctx);
6182 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6183 register_name = "PWBase";
6184 break;
6185 case CP0_REG05__PWFIELD:
6186 check_pw(ctx);
6187 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6188 register_name = "PWField";
6189 break;
6190 case CP0_REG05__PWSIZE:
6191 check_pw(ctx);
6192 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6193 register_name = "PWSize";
6194 break;
6195 default:
6196 goto cp0_unimplemented;
6198 break;
6199 case CP0_REGISTER_06:
6200 switch (sel) {
6201 case CP0_REG06__WIRED:
6202 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6203 register_name = "Wired";
6204 break;
6205 case CP0_REG06__SRSCONF0:
6206 check_insn(ctx, ISA_MIPS_R2);
6207 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6208 register_name = "SRSConf0";
6209 break;
6210 case CP0_REG06__SRSCONF1:
6211 check_insn(ctx, ISA_MIPS_R2);
6212 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6213 register_name = "SRSConf1";
6214 break;
6215 case CP0_REG06__SRSCONF2:
6216 check_insn(ctx, ISA_MIPS_R2);
6217 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6218 register_name = "SRSConf2";
6219 break;
6220 case CP0_REG06__SRSCONF3:
6221 check_insn(ctx, ISA_MIPS_R2);
6222 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6223 register_name = "SRSConf3";
6224 break;
6225 case CP0_REG06__SRSCONF4:
6226 check_insn(ctx, ISA_MIPS_R2);
6227 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6228 register_name = "SRSConf4";
6229 break;
6230 case CP0_REG06__PWCTL:
6231 check_pw(ctx);
6232 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6233 register_name = "PWCtl";
6234 break;
6235 default:
6236 goto cp0_unimplemented;
6238 break;
6239 case CP0_REGISTER_07:
6240 switch (sel) {
6241 case CP0_REG07__HWRENA:
6242 check_insn(ctx, ISA_MIPS_R2);
6243 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6244 register_name = "HWREna";
6245 break;
6246 default:
6247 goto cp0_unimplemented;
6249 break;
6250 case CP0_REGISTER_08:
6251 switch (sel) {
6252 case CP0_REG08__BADVADDR:
6253 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6254 tcg_gen_ext32s_tl(arg, arg);
6255 register_name = "BadVAddr";
6256 break;
6257 case CP0_REG08__BADINSTR:
6258 CP0_CHECK(ctx->bi);
6259 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6260 register_name = "BadInstr";
6261 break;
6262 case CP0_REG08__BADINSTRP:
6263 CP0_CHECK(ctx->bp);
6264 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6265 register_name = "BadInstrP";
6266 break;
6267 case CP0_REG08__BADINSTRX:
6268 CP0_CHECK(ctx->bi);
6269 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6270 tcg_gen_andi_tl(arg, arg, ~0xffff);
6271 register_name = "BadInstrX";
6272 break;
6273 default:
6274 goto cp0_unimplemented;
6276 break;
6277 case CP0_REGISTER_09:
6278 switch (sel) {
6279 case CP0_REG09__COUNT:
6280 /* Mark as an IO operation because we read the time. */
6281 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6282 gen_io_start();
6284 gen_helper_mfc0_count(arg, cpu_env);
6286 * Break the TB to be able to take timer interrupts immediately
6287 * after reading count. DISAS_STOP isn't sufficient, we need to
6288 * ensure we break completely out of translated code.
6290 gen_save_pc(ctx->base.pc_next + 4);
6291 ctx->base.is_jmp = DISAS_EXIT;
6292 register_name = "Count";
6293 break;
6294 case CP0_REG09__SAARI:
6295 CP0_CHECK(ctx->saar);
6296 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
6297 register_name = "SAARI";
6298 break;
6299 case CP0_REG09__SAAR:
6300 CP0_CHECK(ctx->saar);
6301 gen_helper_mfc0_saar(arg, cpu_env);
6302 register_name = "SAAR";
6303 break;
6304 default:
6305 goto cp0_unimplemented;
6307 break;
6308 case CP0_REGISTER_10:
6309 switch (sel) {
6310 case CP0_REG10__ENTRYHI:
6311 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6312 tcg_gen_ext32s_tl(arg, arg);
6313 register_name = "EntryHi";
6314 break;
6315 default:
6316 goto cp0_unimplemented;
6318 break;
6319 case CP0_REGISTER_11:
6320 switch (sel) {
6321 case CP0_REG11__COMPARE:
6322 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6323 register_name = "Compare";
6324 break;
6325 /* 6,7 are implementation dependent */
6326 default:
6327 goto cp0_unimplemented;
6329 break;
6330 case CP0_REGISTER_12:
6331 switch (sel) {
6332 case CP0_REG12__STATUS:
6333 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6334 register_name = "Status";
6335 break;
6336 case CP0_REG12__INTCTL:
6337 check_insn(ctx, ISA_MIPS_R2);
6338 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6339 register_name = "IntCtl";
6340 break;
6341 case CP0_REG12__SRSCTL:
6342 check_insn(ctx, ISA_MIPS_R2);
6343 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6344 register_name = "SRSCtl";
6345 break;
6346 case CP0_REG12__SRSMAP:
6347 check_insn(ctx, ISA_MIPS_R2);
6348 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6349 register_name = "SRSMap";
6350 break;
6351 default:
6352 goto cp0_unimplemented;
6354 break;
6355 case CP0_REGISTER_13:
6356 switch (sel) {
6357 case CP0_REG13__CAUSE:
6358 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6359 register_name = "Cause";
6360 break;
6361 default:
6362 goto cp0_unimplemented;
6364 break;
6365 case CP0_REGISTER_14:
6366 switch (sel) {
6367 case CP0_REG14__EPC:
6368 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6369 tcg_gen_ext32s_tl(arg, arg);
6370 register_name = "EPC";
6371 break;
6372 default:
6373 goto cp0_unimplemented;
6375 break;
6376 case CP0_REGISTER_15:
6377 switch (sel) {
6378 case CP0_REG15__PRID:
6379 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6380 register_name = "PRid";
6381 break;
6382 case CP0_REG15__EBASE:
6383 check_insn(ctx, ISA_MIPS_R2);
6384 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6385 tcg_gen_ext32s_tl(arg, arg);
6386 register_name = "EBase";
6387 break;
6388 case CP0_REG15__CMGCRBASE:
6389 check_insn(ctx, ISA_MIPS_R2);
6390 CP0_CHECK(ctx->cmgcr);
6391 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6392 tcg_gen_ext32s_tl(arg, arg);
6393 register_name = "CMGCRBase";
6394 break;
6395 default:
6396 goto cp0_unimplemented;
6398 break;
6399 case CP0_REGISTER_16:
6400 switch (sel) {
6401 case CP0_REG16__CONFIG:
6402 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6403 register_name = "Config";
6404 break;
6405 case CP0_REG16__CONFIG1:
6406 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6407 register_name = "Config1";
6408 break;
6409 case CP0_REG16__CONFIG2:
6410 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6411 register_name = "Config2";
6412 break;
6413 case CP0_REG16__CONFIG3:
6414 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6415 register_name = "Config3";
6416 break;
6417 case CP0_REG16__CONFIG4:
6418 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6419 register_name = "Config4";
6420 break;
6421 case CP0_REG16__CONFIG5:
6422 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6423 register_name = "Config5";
6424 break;
6425 /* 6,7 are implementation dependent */
6426 case CP0_REG16__CONFIG6:
6427 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6428 register_name = "Config6";
6429 break;
6430 case CP0_REG16__CONFIG7:
6431 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6432 register_name = "Config7";
6433 break;
6434 default:
6435 goto cp0_unimplemented;
6437 break;
6438 case CP0_REGISTER_17:
6439 switch (sel) {
6440 case CP0_REG17__LLADDR:
6441 gen_helper_mfc0_lladdr(arg, cpu_env);
6442 register_name = "LLAddr";
6443 break;
6444 case CP0_REG17__MAAR:
6445 CP0_CHECK(ctx->mrp);
6446 gen_helper_mfc0_maar(arg, cpu_env);
6447 register_name = "MAAR";
6448 break;
6449 case CP0_REG17__MAARI:
6450 CP0_CHECK(ctx->mrp);
6451 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6452 register_name = "MAARI";
6453 break;
6454 default:
6455 goto cp0_unimplemented;
6457 break;
6458 case CP0_REGISTER_18:
6459 switch (sel) {
6460 case CP0_REG18__WATCHLO0:
6461 case CP0_REG18__WATCHLO1:
6462 case CP0_REG18__WATCHLO2:
6463 case CP0_REG18__WATCHLO3:
6464 case CP0_REG18__WATCHLO4:
6465 case CP0_REG18__WATCHLO5:
6466 case CP0_REG18__WATCHLO6:
6467 case CP0_REG18__WATCHLO7:
6468 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6469 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6470 register_name = "WatchLo";
6471 break;
6472 default:
6473 goto cp0_unimplemented;
6475 break;
6476 case CP0_REGISTER_19:
6477 switch (sel) {
6478 case CP0_REG19__WATCHHI0:
6479 case CP0_REG19__WATCHHI1:
6480 case CP0_REG19__WATCHHI2:
6481 case CP0_REG19__WATCHHI3:
6482 case CP0_REG19__WATCHHI4:
6483 case CP0_REG19__WATCHHI5:
6484 case CP0_REG19__WATCHHI6:
6485 case CP0_REG19__WATCHHI7:
6486 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6487 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6488 register_name = "WatchHi";
6489 break;
6490 default:
6491 goto cp0_unimplemented;
6493 break;
6494 case CP0_REGISTER_20:
6495 switch (sel) {
6496 case CP0_REG20__XCONTEXT:
6497 #if defined(TARGET_MIPS64)
6498 check_insn(ctx, ISA_MIPS3);
6499 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6500 tcg_gen_ext32s_tl(arg, arg);
6501 register_name = "XContext";
6502 break;
6503 #endif
6504 default:
6505 goto cp0_unimplemented;
6507 break;
6508 case CP0_REGISTER_21:
6509 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6510 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6511 switch (sel) {
6512 case 0:
6513 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6514 register_name = "Framemask";
6515 break;
6516 default:
6517 goto cp0_unimplemented;
6519 break;
6520 case CP0_REGISTER_22:
6521 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6522 register_name = "'Diagnostic"; /* implementation dependent */
6523 break;
6524 case CP0_REGISTER_23:
6525 switch (sel) {
6526 case CP0_REG23__DEBUG:
6527 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6528 register_name = "Debug";
6529 break;
6530 case CP0_REG23__TRACECONTROL:
6531 /* PDtrace support */
6532 /* gen_helper_mfc0_tracecontrol(arg); */
6533 register_name = "TraceControl";
6534 goto cp0_unimplemented;
6535 case CP0_REG23__TRACECONTROL2:
6536 /* PDtrace support */
6537 /* gen_helper_mfc0_tracecontrol2(arg); */
6538 register_name = "TraceControl2";
6539 goto cp0_unimplemented;
6540 case CP0_REG23__USERTRACEDATA1:
6541 /* PDtrace support */
6542 /* gen_helper_mfc0_usertracedata1(arg);*/
6543 register_name = "UserTraceData1";
6544 goto cp0_unimplemented;
6545 case CP0_REG23__TRACEIBPC:
6546 /* PDtrace support */
6547 /* gen_helper_mfc0_traceibpc(arg); */
6548 register_name = "TraceIBPC";
6549 goto cp0_unimplemented;
6550 case CP0_REG23__TRACEDBPC:
6551 /* PDtrace support */
6552 /* gen_helper_mfc0_tracedbpc(arg); */
6553 register_name = "TraceDBPC";
6554 goto cp0_unimplemented;
6555 default:
6556 goto cp0_unimplemented;
6558 break;
6559 case CP0_REGISTER_24:
6560 switch (sel) {
6561 case CP0_REG24__DEPC:
6562 /* EJTAG support */
6563 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6564 tcg_gen_ext32s_tl(arg, arg);
6565 register_name = "DEPC";
6566 break;
6567 default:
6568 goto cp0_unimplemented;
6570 break;
6571 case CP0_REGISTER_25:
6572 switch (sel) {
6573 case CP0_REG25__PERFCTL0:
6574 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6575 register_name = "Performance0";
6576 break;
6577 case CP0_REG25__PERFCNT0:
6578 /* gen_helper_mfc0_performance1(arg); */
6579 register_name = "Performance1";
6580 goto cp0_unimplemented;
6581 case CP0_REG25__PERFCTL1:
6582 /* gen_helper_mfc0_performance2(arg); */
6583 register_name = "Performance2";
6584 goto cp0_unimplemented;
6585 case CP0_REG25__PERFCNT1:
6586 /* gen_helper_mfc0_performance3(arg); */
6587 register_name = "Performance3";
6588 goto cp0_unimplemented;
6589 case CP0_REG25__PERFCTL2:
6590 /* gen_helper_mfc0_performance4(arg); */
6591 register_name = "Performance4";
6592 goto cp0_unimplemented;
6593 case CP0_REG25__PERFCNT2:
6594 /* gen_helper_mfc0_performance5(arg); */
6595 register_name = "Performance5";
6596 goto cp0_unimplemented;
6597 case CP0_REG25__PERFCTL3:
6598 /* gen_helper_mfc0_performance6(arg); */
6599 register_name = "Performance6";
6600 goto cp0_unimplemented;
6601 case CP0_REG25__PERFCNT3:
6602 /* gen_helper_mfc0_performance7(arg); */
6603 register_name = "Performance7";
6604 goto cp0_unimplemented;
6605 default:
6606 goto cp0_unimplemented;
6608 break;
6609 case CP0_REGISTER_26:
6610 switch (sel) {
6611 case CP0_REG26__ERRCTL:
6612 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6613 register_name = "ErrCtl";
6614 break;
6615 default:
6616 goto cp0_unimplemented;
6618 break;
6619 case CP0_REGISTER_27:
6620 switch (sel) {
6621 case CP0_REG27__CACHERR:
6622 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6623 register_name = "CacheErr";
6624 break;
6625 default:
6626 goto cp0_unimplemented;
6628 break;
6629 case CP0_REGISTER_28:
6630 switch (sel) {
6631 case CP0_REG28__TAGLO:
6632 case CP0_REG28__TAGLO1:
6633 case CP0_REG28__TAGLO2:
6634 case CP0_REG28__TAGLO3:
6636 TCGv_i64 tmp = tcg_temp_new_i64();
6637 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
6638 gen_move_low32(arg, tmp);
6639 tcg_temp_free_i64(tmp);
6641 register_name = "TagLo";
6642 break;
6643 case CP0_REG28__DATALO:
6644 case CP0_REG28__DATALO1:
6645 case CP0_REG28__DATALO2:
6646 case CP0_REG28__DATALO3:
6647 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6648 register_name = "DataLo";
6649 break;
6650 default:
6651 goto cp0_unimplemented;
6653 break;
6654 case CP0_REGISTER_29:
6655 switch (sel) {
6656 case CP0_REG29__TAGHI:
6657 case CP0_REG29__TAGHI1:
6658 case CP0_REG29__TAGHI2:
6659 case CP0_REG29__TAGHI3:
6660 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6661 register_name = "TagHi";
6662 break;
6663 case CP0_REG29__DATAHI:
6664 case CP0_REG29__DATAHI1:
6665 case CP0_REG29__DATAHI2:
6666 case CP0_REG29__DATAHI3:
6667 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6668 register_name = "DataHi";
6669 break;
6670 default:
6671 goto cp0_unimplemented;
6673 break;
6674 case CP0_REGISTER_30:
6675 switch (sel) {
6676 case CP0_REG30__ERROREPC:
6677 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6678 tcg_gen_ext32s_tl(arg, arg);
6679 register_name = "ErrorEPC";
6680 break;
6681 default:
6682 goto cp0_unimplemented;
6684 break;
6685 case CP0_REGISTER_31:
6686 switch (sel) {
6687 case CP0_REG31__DESAVE:
6688 /* EJTAG support */
6689 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6690 register_name = "DESAVE";
6691 break;
6692 case CP0_REG31__KSCRATCH1:
6693 case CP0_REG31__KSCRATCH2:
6694 case CP0_REG31__KSCRATCH3:
6695 case CP0_REG31__KSCRATCH4:
6696 case CP0_REG31__KSCRATCH5:
6697 case CP0_REG31__KSCRATCH6:
6698 CP0_CHECK(ctx->kscrexist & (1 << sel));
6699 tcg_gen_ld_tl(arg, cpu_env,
6700 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
6701 tcg_gen_ext32s_tl(arg, arg);
6702 register_name = "KScratch";
6703 break;
6704 default:
6705 goto cp0_unimplemented;
6707 break;
6708 default:
6709 goto cp0_unimplemented;
6711 trace_mips_translate_c0("mfc0", register_name, reg, sel);
6712 return;
6714 cp0_unimplemented:
6715 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
6716 register_name, reg, sel);
6717 gen_mfc0_unimplemented(ctx, arg);
6720 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6722 const char *register_name = "invalid";
6724 if (sel != 0) {
6725 check_insn(ctx, ISA_MIPS_R1);
6728 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6729 gen_io_start();
6732 switch (reg) {
6733 case CP0_REGISTER_00:
6734 switch (sel) {
6735 case CP0_REG00__INDEX:
6736 gen_helper_mtc0_index(cpu_env, arg);
6737 register_name = "Index";
6738 break;
6739 case CP0_REG00__MVPCONTROL:
6740 CP0_CHECK(ctx->insn_flags & ASE_MT);
6741 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6742 register_name = "MVPControl";
6743 break;
6744 case CP0_REG00__MVPCONF0:
6745 CP0_CHECK(ctx->insn_flags & ASE_MT);
6746 /* ignored */
6747 register_name = "MVPConf0";
6748 break;
6749 case CP0_REG00__MVPCONF1:
6750 CP0_CHECK(ctx->insn_flags & ASE_MT);
6751 /* ignored */
6752 register_name = "MVPConf1";
6753 break;
6754 case CP0_REG00__VPCONTROL:
6755 CP0_CHECK(ctx->vp);
6756 /* ignored */
6757 register_name = "VPControl";
6758 break;
6759 default:
6760 goto cp0_unimplemented;
6762 break;
6763 case CP0_REGISTER_01:
6764 switch (sel) {
6765 case CP0_REG01__RANDOM:
6766 /* ignored */
6767 register_name = "Random";
6768 break;
6769 case CP0_REG01__VPECONTROL:
6770 CP0_CHECK(ctx->insn_flags & ASE_MT);
6771 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6772 register_name = "VPEControl";
6773 break;
6774 case CP0_REG01__VPECONF0:
6775 CP0_CHECK(ctx->insn_flags & ASE_MT);
6776 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6777 register_name = "VPEConf0";
6778 break;
6779 case CP0_REG01__VPECONF1:
6780 CP0_CHECK(ctx->insn_flags & ASE_MT);
6781 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6782 register_name = "VPEConf1";
6783 break;
6784 case CP0_REG01__YQMASK:
6785 CP0_CHECK(ctx->insn_flags & ASE_MT);
6786 gen_helper_mtc0_yqmask(cpu_env, arg);
6787 register_name = "YQMask";
6788 break;
6789 case CP0_REG01__VPESCHEDULE:
6790 CP0_CHECK(ctx->insn_flags & ASE_MT);
6791 tcg_gen_st_tl(arg, cpu_env,
6792 offsetof(CPUMIPSState, CP0_VPESchedule));
6793 register_name = "VPESchedule";
6794 break;
6795 case CP0_REG01__VPESCHEFBACK:
6796 CP0_CHECK(ctx->insn_flags & ASE_MT);
6797 tcg_gen_st_tl(arg, cpu_env,
6798 offsetof(CPUMIPSState, CP0_VPEScheFBack));
6799 register_name = "VPEScheFBack";
6800 break;
6801 case CP0_REG01__VPEOPT:
6802 CP0_CHECK(ctx->insn_flags & ASE_MT);
6803 gen_helper_mtc0_vpeopt(cpu_env, arg);
6804 register_name = "VPEOpt";
6805 break;
6806 default:
6807 goto cp0_unimplemented;
6809 break;
6810 case CP0_REGISTER_02:
6811 switch (sel) {
6812 case CP0_REG02__ENTRYLO0:
6813 gen_helper_mtc0_entrylo0(cpu_env, arg);
6814 register_name = "EntryLo0";
6815 break;
6816 case CP0_REG02__TCSTATUS:
6817 CP0_CHECK(ctx->insn_flags & ASE_MT);
6818 gen_helper_mtc0_tcstatus(cpu_env, arg);
6819 register_name = "TCStatus";
6820 break;
6821 case CP0_REG02__TCBIND:
6822 CP0_CHECK(ctx->insn_flags & ASE_MT);
6823 gen_helper_mtc0_tcbind(cpu_env, arg);
6824 register_name = "TCBind";
6825 break;
6826 case CP0_REG02__TCRESTART:
6827 CP0_CHECK(ctx->insn_flags & ASE_MT);
6828 gen_helper_mtc0_tcrestart(cpu_env, arg);
6829 register_name = "TCRestart";
6830 break;
6831 case CP0_REG02__TCHALT:
6832 CP0_CHECK(ctx->insn_flags & ASE_MT);
6833 gen_helper_mtc0_tchalt(cpu_env, arg);
6834 register_name = "TCHalt";
6835 break;
6836 case CP0_REG02__TCCONTEXT:
6837 CP0_CHECK(ctx->insn_flags & ASE_MT);
6838 gen_helper_mtc0_tccontext(cpu_env, arg);
6839 register_name = "TCContext";
6840 break;
6841 case CP0_REG02__TCSCHEDULE:
6842 CP0_CHECK(ctx->insn_flags & ASE_MT);
6843 gen_helper_mtc0_tcschedule(cpu_env, arg);
6844 register_name = "TCSchedule";
6845 break;
6846 case CP0_REG02__TCSCHEFBACK:
6847 CP0_CHECK(ctx->insn_flags & ASE_MT);
6848 gen_helper_mtc0_tcschefback(cpu_env, arg);
6849 register_name = "TCScheFBack";
6850 break;
6851 default:
6852 goto cp0_unimplemented;
6854 break;
6855 case CP0_REGISTER_03:
6856 switch (sel) {
6857 case CP0_REG03__ENTRYLO1:
6858 gen_helper_mtc0_entrylo1(cpu_env, arg);
6859 register_name = "EntryLo1";
6860 break;
6861 case CP0_REG03__GLOBALNUM:
6862 CP0_CHECK(ctx->vp);
6863 /* ignored */
6864 register_name = "GlobalNumber";
6865 break;
6866 default:
6867 goto cp0_unimplemented;
6869 break;
6870 case CP0_REGISTER_04:
6871 switch (sel) {
6872 case CP0_REG04__CONTEXT:
6873 gen_helper_mtc0_context(cpu_env, arg);
6874 register_name = "Context";
6875 break;
6876 case CP0_REG04__CONTEXTCONFIG:
6877 /* SmartMIPS ASE */
6878 /* gen_helper_mtc0_contextconfig(arg); */
6879 register_name = "ContextConfig";
6880 goto cp0_unimplemented;
6881 case CP0_REG04__USERLOCAL:
6882 CP0_CHECK(ctx->ulri);
6883 tcg_gen_st_tl(arg, cpu_env,
6884 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6885 register_name = "UserLocal";
6886 break;
6887 case CP0_REG04__MMID:
6888 CP0_CHECK(ctx->mi);
6889 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
6890 register_name = "MMID";
6891 break;
6892 default:
6893 goto cp0_unimplemented;
6895 break;
6896 case CP0_REGISTER_05:
6897 switch (sel) {
6898 case CP0_REG05__PAGEMASK:
6899 gen_helper_mtc0_pagemask(cpu_env, arg);
6900 register_name = "PageMask";
6901 break;
6902 case CP0_REG05__PAGEGRAIN:
6903 check_insn(ctx, ISA_MIPS_R2);
6904 gen_helper_mtc0_pagegrain(cpu_env, arg);
6905 register_name = "PageGrain";
6906 ctx->base.is_jmp = DISAS_STOP;
6907 break;
6908 case CP0_REG05__SEGCTL0:
6909 CP0_CHECK(ctx->sc);
6910 gen_helper_mtc0_segctl0(cpu_env, arg);
6911 register_name = "SegCtl0";
6912 break;
6913 case CP0_REG05__SEGCTL1:
6914 CP0_CHECK(ctx->sc);
6915 gen_helper_mtc0_segctl1(cpu_env, arg);
6916 register_name = "SegCtl1";
6917 break;
6918 case CP0_REG05__SEGCTL2:
6919 CP0_CHECK(ctx->sc);
6920 gen_helper_mtc0_segctl2(cpu_env, arg);
6921 register_name = "SegCtl2";
6922 break;
6923 case CP0_REG05__PWBASE:
6924 check_pw(ctx);
6925 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6926 register_name = "PWBase";
6927 break;
6928 case CP0_REG05__PWFIELD:
6929 check_pw(ctx);
6930 gen_helper_mtc0_pwfield(cpu_env, arg);
6931 register_name = "PWField";
6932 break;
6933 case CP0_REG05__PWSIZE:
6934 check_pw(ctx);
6935 gen_helper_mtc0_pwsize(cpu_env, arg);
6936 register_name = "PWSize";
6937 break;
6938 default:
6939 goto cp0_unimplemented;
6941 break;
6942 case CP0_REGISTER_06:
6943 switch (sel) {
6944 case CP0_REG06__WIRED:
6945 gen_helper_mtc0_wired(cpu_env, arg);
6946 register_name = "Wired";
6947 break;
6948 case CP0_REG06__SRSCONF0:
6949 check_insn(ctx, ISA_MIPS_R2);
6950 gen_helper_mtc0_srsconf0(cpu_env, arg);
6951 register_name = "SRSConf0";
6952 break;
6953 case CP0_REG06__SRSCONF1:
6954 check_insn(ctx, ISA_MIPS_R2);
6955 gen_helper_mtc0_srsconf1(cpu_env, arg);
6956 register_name = "SRSConf1";
6957 break;
6958 case CP0_REG06__SRSCONF2:
6959 check_insn(ctx, ISA_MIPS_R2);
6960 gen_helper_mtc0_srsconf2(cpu_env, arg);
6961 register_name = "SRSConf2";
6962 break;
6963 case CP0_REG06__SRSCONF3:
6964 check_insn(ctx, ISA_MIPS_R2);
6965 gen_helper_mtc0_srsconf3(cpu_env, arg);
6966 register_name = "SRSConf3";
6967 break;
6968 case CP0_REG06__SRSCONF4:
6969 check_insn(ctx, ISA_MIPS_R2);
6970 gen_helper_mtc0_srsconf4(cpu_env, arg);
6971 register_name = "SRSConf4";
6972 break;
6973 case CP0_REG06__PWCTL:
6974 check_pw(ctx);
6975 gen_helper_mtc0_pwctl(cpu_env, arg);
6976 register_name = "PWCtl";
6977 break;
6978 default:
6979 goto cp0_unimplemented;
6981 break;
6982 case CP0_REGISTER_07:
6983 switch (sel) {
6984 case CP0_REG07__HWRENA:
6985 check_insn(ctx, ISA_MIPS_R2);
6986 gen_helper_mtc0_hwrena(cpu_env, arg);
6987 ctx->base.is_jmp = DISAS_STOP;
6988 register_name = "HWREna";
6989 break;
6990 default:
6991 goto cp0_unimplemented;
6993 break;
6994 case CP0_REGISTER_08:
6995 switch (sel) {
6996 case CP0_REG08__BADVADDR:
6997 /* ignored */
6998 register_name = "BadVAddr";
6999 break;
7000 case CP0_REG08__BADINSTR:
7001 /* ignored */
7002 register_name = "BadInstr";
7003 break;
7004 case CP0_REG08__BADINSTRP:
7005 /* ignored */
7006 register_name = "BadInstrP";
7007 break;
7008 case CP0_REG08__BADINSTRX:
7009 /* ignored */
7010 register_name = "BadInstrX";
7011 break;
7012 default:
7013 goto cp0_unimplemented;
7015 break;
7016 case CP0_REGISTER_09:
7017 switch (sel) {
7018 case CP0_REG09__COUNT:
7019 gen_helper_mtc0_count(cpu_env, arg);
7020 register_name = "Count";
7021 break;
7022 case CP0_REG09__SAARI:
7023 CP0_CHECK(ctx->saar);
7024 gen_helper_mtc0_saari(cpu_env, arg);
7025 register_name = "SAARI";
7026 break;
7027 case CP0_REG09__SAAR:
7028 CP0_CHECK(ctx->saar);
7029 gen_helper_mtc0_saar(cpu_env, arg);
7030 register_name = "SAAR";
7031 break;
7032 default:
7033 goto cp0_unimplemented;
7035 break;
7036 case CP0_REGISTER_10:
7037 switch (sel) {
7038 case CP0_REG10__ENTRYHI:
7039 gen_helper_mtc0_entryhi(cpu_env, arg);
7040 register_name = "EntryHi";
7041 break;
7042 default:
7043 goto cp0_unimplemented;
7045 break;
7046 case CP0_REGISTER_11:
7047 switch (sel) {
7048 case CP0_REG11__COMPARE:
7049 gen_helper_mtc0_compare(cpu_env, arg);
7050 register_name = "Compare";
7051 break;
7052 /* 6,7 are implementation dependent */
7053 default:
7054 goto cp0_unimplemented;
7056 break;
7057 case CP0_REGISTER_12:
7058 switch (sel) {
7059 case CP0_REG12__STATUS:
7060 save_cpu_state(ctx, 1);
7061 gen_helper_mtc0_status(cpu_env, arg);
7062 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7063 gen_save_pc(ctx->base.pc_next + 4);
7064 ctx->base.is_jmp = DISAS_EXIT;
7065 register_name = "Status";
7066 break;
7067 case CP0_REG12__INTCTL:
7068 check_insn(ctx, ISA_MIPS_R2);
7069 gen_helper_mtc0_intctl(cpu_env, arg);
7070 /* Stop translation as we may have switched the execution mode */
7071 ctx->base.is_jmp = DISAS_STOP;
7072 register_name = "IntCtl";
7073 break;
7074 case CP0_REG12__SRSCTL:
7075 check_insn(ctx, ISA_MIPS_R2);
7076 gen_helper_mtc0_srsctl(cpu_env, arg);
7077 /* Stop translation as we may have switched the execution mode */
7078 ctx->base.is_jmp = DISAS_STOP;
7079 register_name = "SRSCtl";
7080 break;
7081 case CP0_REG12__SRSMAP:
7082 check_insn(ctx, ISA_MIPS_R2);
7083 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7084 /* Stop translation as we may have switched the execution mode */
7085 ctx->base.is_jmp = DISAS_STOP;
7086 register_name = "SRSMap";
7087 break;
7088 default:
7089 goto cp0_unimplemented;
7091 break;
7092 case CP0_REGISTER_13:
7093 switch (sel) {
7094 case CP0_REG13__CAUSE:
7095 save_cpu_state(ctx, 1);
7096 gen_helper_mtc0_cause(cpu_env, arg);
7098 * Stop translation as we may have triggered an interrupt.
7099 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7100 * translated code to check for pending interrupts.
7102 gen_save_pc(ctx->base.pc_next + 4);
7103 ctx->base.is_jmp = DISAS_EXIT;
7104 register_name = "Cause";
7105 break;
7106 default:
7107 goto cp0_unimplemented;
7109 break;
7110 case CP0_REGISTER_14:
7111 switch (sel) {
7112 case CP0_REG14__EPC:
7113 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7114 register_name = "EPC";
7115 break;
7116 default:
7117 goto cp0_unimplemented;
7119 break;
7120 case CP0_REGISTER_15:
7121 switch (sel) {
7122 case CP0_REG15__PRID:
7123 /* ignored */
7124 register_name = "PRid";
7125 break;
7126 case CP0_REG15__EBASE:
7127 check_insn(ctx, ISA_MIPS_R2);
7128 gen_helper_mtc0_ebase(cpu_env, arg);
7129 register_name = "EBase";
7130 break;
7131 default:
7132 goto cp0_unimplemented;
7134 break;
7135 case CP0_REGISTER_16:
7136 switch (sel) {
7137 case CP0_REG16__CONFIG:
7138 gen_helper_mtc0_config0(cpu_env, arg);
7139 register_name = "Config";
7140 /* Stop translation as we may have switched the execution mode */
7141 ctx->base.is_jmp = DISAS_STOP;
7142 break;
7143 case CP0_REG16__CONFIG1:
7144 /* ignored, read only */
7145 register_name = "Config1";
7146 break;
7147 case CP0_REG16__CONFIG2:
7148 gen_helper_mtc0_config2(cpu_env, arg);
7149 register_name = "Config2";
7150 /* Stop translation as we may have switched the execution mode */
7151 ctx->base.is_jmp = DISAS_STOP;
7152 break;
7153 case CP0_REG16__CONFIG3:
7154 gen_helper_mtc0_config3(cpu_env, arg);
7155 register_name = "Config3";
7156 /* Stop translation as we may have switched the execution mode */
7157 ctx->base.is_jmp = DISAS_STOP;
7158 break;
7159 case CP0_REG16__CONFIG4:
7160 gen_helper_mtc0_config4(cpu_env, arg);
7161 register_name = "Config4";
7162 ctx->base.is_jmp = DISAS_STOP;
7163 break;
7164 case CP0_REG16__CONFIG5:
7165 gen_helper_mtc0_config5(cpu_env, arg);
7166 register_name = "Config5";
7167 /* Stop translation as we may have switched the execution mode */
7168 ctx->base.is_jmp = DISAS_STOP;
7169 break;
7170 /* 6,7 are implementation dependent */
7171 case CP0_REG16__CONFIG6:
7172 /* ignored */
7173 register_name = "Config6";
7174 break;
7175 case CP0_REG16__CONFIG7:
7176 /* ignored */
7177 register_name = "Config7";
7178 break;
7179 default:
7180 register_name = "Invalid config selector";
7181 goto cp0_unimplemented;
7183 break;
7184 case CP0_REGISTER_17:
7185 switch (sel) {
7186 case CP0_REG17__LLADDR:
7187 gen_helper_mtc0_lladdr(cpu_env, arg);
7188 register_name = "LLAddr";
7189 break;
7190 case CP0_REG17__MAAR:
7191 CP0_CHECK(ctx->mrp);
7192 gen_helper_mtc0_maar(cpu_env, arg);
7193 register_name = "MAAR";
7194 break;
7195 case CP0_REG17__MAARI:
7196 CP0_CHECK(ctx->mrp);
7197 gen_helper_mtc0_maari(cpu_env, arg);
7198 register_name = "MAARI";
7199 break;
7200 default:
7201 goto cp0_unimplemented;
7203 break;
7204 case CP0_REGISTER_18:
7205 switch (sel) {
7206 case CP0_REG18__WATCHLO0:
7207 case CP0_REG18__WATCHLO1:
7208 case CP0_REG18__WATCHLO2:
7209 case CP0_REG18__WATCHLO3:
7210 case CP0_REG18__WATCHLO4:
7211 case CP0_REG18__WATCHLO5:
7212 case CP0_REG18__WATCHLO6:
7213 case CP0_REG18__WATCHLO7:
7214 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7215 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7216 register_name = "WatchLo";
7217 break;
7218 default:
7219 goto cp0_unimplemented;
7221 break;
7222 case CP0_REGISTER_19:
7223 switch (sel) {
7224 case CP0_REG19__WATCHHI0:
7225 case CP0_REG19__WATCHHI1:
7226 case CP0_REG19__WATCHHI2:
7227 case CP0_REG19__WATCHHI3:
7228 case CP0_REG19__WATCHHI4:
7229 case CP0_REG19__WATCHHI5:
7230 case CP0_REG19__WATCHHI6:
7231 case CP0_REG19__WATCHHI7:
7232 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7233 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7234 register_name = "WatchHi";
7235 break;
7236 default:
7237 goto cp0_unimplemented;
7239 break;
7240 case CP0_REGISTER_20:
7241 switch (sel) {
7242 case CP0_REG20__XCONTEXT:
7243 #if defined(TARGET_MIPS64)
7244 check_insn(ctx, ISA_MIPS3);
7245 gen_helper_mtc0_xcontext(cpu_env, arg);
7246 register_name = "XContext";
7247 break;
7248 #endif
7249 default:
7250 goto cp0_unimplemented;
7252 break;
7253 case CP0_REGISTER_21:
7254 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7255 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7256 switch (sel) {
7257 case 0:
7258 gen_helper_mtc0_framemask(cpu_env, arg);
7259 register_name = "Framemask";
7260 break;
7261 default:
7262 goto cp0_unimplemented;
7264 break;
7265 case CP0_REGISTER_22:
7266 /* ignored */
7267 register_name = "Diagnostic"; /* implementation dependent */
7268 break;
7269 case CP0_REGISTER_23:
7270 switch (sel) {
7271 case CP0_REG23__DEBUG:
7272 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7273 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7274 gen_save_pc(ctx->base.pc_next + 4);
7275 ctx->base.is_jmp = DISAS_EXIT;
7276 register_name = "Debug";
7277 break;
7278 case CP0_REG23__TRACECONTROL:
7279 /* PDtrace support */
7280 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
7281 register_name = "TraceControl";
7282 /* Stop translation as we may have switched the execution mode */
7283 ctx->base.is_jmp = DISAS_STOP;
7284 goto cp0_unimplemented;
7285 case CP0_REG23__TRACECONTROL2:
7286 /* PDtrace support */
7287 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
7288 register_name = "TraceControl2";
7289 /* Stop translation as we may have switched the execution mode */
7290 ctx->base.is_jmp = DISAS_STOP;
7291 goto cp0_unimplemented;
7292 case CP0_REG23__USERTRACEDATA1:
7293 /* Stop translation as we may have switched the execution mode */
7294 ctx->base.is_jmp = DISAS_STOP;
7295 /* PDtrace support */
7296 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
7297 register_name = "UserTraceData";
7298 /* Stop translation as we may have switched the execution mode */
7299 ctx->base.is_jmp = DISAS_STOP;
7300 goto cp0_unimplemented;
7301 case CP0_REG23__TRACEIBPC:
7302 /* PDtrace support */
7303 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
7304 /* Stop translation as we may have switched the execution mode */
7305 ctx->base.is_jmp = DISAS_STOP;
7306 register_name = "TraceIBPC";
7307 goto cp0_unimplemented;
7308 case CP0_REG23__TRACEDBPC:
7309 /* PDtrace support */
7310 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
7311 /* Stop translation as we may have switched the execution mode */
7312 ctx->base.is_jmp = DISAS_STOP;
7313 register_name = "TraceDBPC";
7314 goto cp0_unimplemented;
7315 default:
7316 goto cp0_unimplemented;
7318 break;
7319 case CP0_REGISTER_24:
7320 switch (sel) {
7321 case CP0_REG24__DEPC:
7322 /* EJTAG support */
7323 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7324 register_name = "DEPC";
7325 break;
7326 default:
7327 goto cp0_unimplemented;
7329 break;
7330 case CP0_REGISTER_25:
7331 switch (sel) {
7332 case CP0_REG25__PERFCTL0:
7333 gen_helper_mtc0_performance0(cpu_env, arg);
7334 register_name = "Performance0";
7335 break;
7336 case CP0_REG25__PERFCNT0:
7337 /* gen_helper_mtc0_performance1(arg); */
7338 register_name = "Performance1";
7339 goto cp0_unimplemented;
7340 case CP0_REG25__PERFCTL1:
7341 /* gen_helper_mtc0_performance2(arg); */
7342 register_name = "Performance2";
7343 goto cp0_unimplemented;
7344 case CP0_REG25__PERFCNT1:
7345 /* gen_helper_mtc0_performance3(arg); */
7346 register_name = "Performance3";
7347 goto cp0_unimplemented;
7348 case CP0_REG25__PERFCTL2:
7349 /* gen_helper_mtc0_performance4(arg); */
7350 register_name = "Performance4";
7351 goto cp0_unimplemented;
7352 case CP0_REG25__PERFCNT2:
7353 /* gen_helper_mtc0_performance5(arg); */
7354 register_name = "Performance5";
7355 goto cp0_unimplemented;
7356 case CP0_REG25__PERFCTL3:
7357 /* gen_helper_mtc0_performance6(arg); */
7358 register_name = "Performance6";
7359 goto cp0_unimplemented;
7360 case CP0_REG25__PERFCNT3:
7361 /* gen_helper_mtc0_performance7(arg); */
7362 register_name = "Performance7";
7363 goto cp0_unimplemented;
7364 default:
7365 goto cp0_unimplemented;
7367 break;
7368 case CP0_REGISTER_26:
7369 switch (sel) {
7370 case CP0_REG26__ERRCTL:
7371 gen_helper_mtc0_errctl(cpu_env, arg);
7372 ctx->base.is_jmp = DISAS_STOP;
7373 register_name = "ErrCtl";
7374 break;
7375 default:
7376 goto cp0_unimplemented;
7378 break;
7379 case CP0_REGISTER_27:
7380 switch (sel) {
7381 case CP0_REG27__CACHERR:
7382 /* ignored */
7383 register_name = "CacheErr";
7384 break;
7385 default:
7386 goto cp0_unimplemented;
7388 break;
7389 case CP0_REGISTER_28:
7390 switch (sel) {
7391 case CP0_REG28__TAGLO:
7392 case CP0_REG28__TAGLO1:
7393 case CP0_REG28__TAGLO2:
7394 case CP0_REG28__TAGLO3:
7395 gen_helper_mtc0_taglo(cpu_env, arg);
7396 register_name = "TagLo";
7397 break;
7398 case CP0_REG28__DATALO:
7399 case CP0_REG28__DATALO1:
7400 case CP0_REG28__DATALO2:
7401 case CP0_REG28__DATALO3:
7402 gen_helper_mtc0_datalo(cpu_env, arg);
7403 register_name = "DataLo";
7404 break;
7405 default:
7406 goto cp0_unimplemented;
7408 break;
7409 case CP0_REGISTER_29:
7410 switch (sel) {
7411 case CP0_REG29__TAGHI:
7412 case CP0_REG29__TAGHI1:
7413 case CP0_REG29__TAGHI2:
7414 case CP0_REG29__TAGHI3:
7415 gen_helper_mtc0_taghi(cpu_env, arg);
7416 register_name = "TagHi";
7417 break;
7418 case CP0_REG29__DATAHI:
7419 case CP0_REG29__DATAHI1:
7420 case CP0_REG29__DATAHI2:
7421 case CP0_REG29__DATAHI3:
7422 gen_helper_mtc0_datahi(cpu_env, arg);
7423 register_name = "DataHi";
7424 break;
7425 default:
7426 register_name = "invalid sel";
7427 goto cp0_unimplemented;
7429 break;
7430 case CP0_REGISTER_30:
7431 switch (sel) {
7432 case CP0_REG30__ERROREPC:
7433 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7434 register_name = "ErrorEPC";
7435 break;
7436 default:
7437 goto cp0_unimplemented;
7439 break;
7440 case CP0_REGISTER_31:
7441 switch (sel) {
7442 case CP0_REG31__DESAVE:
7443 /* EJTAG support */
7444 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7445 register_name = "DESAVE";
7446 break;
7447 case CP0_REG31__KSCRATCH1:
7448 case CP0_REG31__KSCRATCH2:
7449 case CP0_REG31__KSCRATCH3:
7450 case CP0_REG31__KSCRATCH4:
7451 case CP0_REG31__KSCRATCH5:
7452 case CP0_REG31__KSCRATCH6:
7453 CP0_CHECK(ctx->kscrexist & (1 << sel));
7454 tcg_gen_st_tl(arg, cpu_env,
7455 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7456 register_name = "KScratch";
7457 break;
7458 default:
7459 goto cp0_unimplemented;
7461 break;
7462 default:
7463 goto cp0_unimplemented;
7465 trace_mips_translate_c0("mtc0", register_name, reg, sel);
7467 /* For simplicity assume that all writes can cause interrupts. */
7468 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7470 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7471 * translated code to check for pending interrupts.
7473 gen_save_pc(ctx->base.pc_next + 4);
7474 ctx->base.is_jmp = DISAS_EXIT;
7476 return;
7478 cp0_unimplemented:
7479 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
7480 register_name, reg, sel);
7483 #if defined(TARGET_MIPS64)
7484 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7486 const char *register_name = "invalid";
7488 if (sel != 0) {
7489 check_insn(ctx, ISA_MIPS_R1);
7492 switch (reg) {
7493 case CP0_REGISTER_00:
7494 switch (sel) {
7495 case CP0_REG00__INDEX:
7496 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7497 register_name = "Index";
7498 break;
7499 case CP0_REG00__MVPCONTROL:
7500 CP0_CHECK(ctx->insn_flags & ASE_MT);
7501 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7502 register_name = "MVPControl";
7503 break;
7504 case CP0_REG00__MVPCONF0:
7505 CP0_CHECK(ctx->insn_flags & ASE_MT);
7506 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7507 register_name = "MVPConf0";
7508 break;
7509 case CP0_REG00__MVPCONF1:
7510 CP0_CHECK(ctx->insn_flags & ASE_MT);
7511 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7512 register_name = "MVPConf1";
7513 break;
7514 case CP0_REG00__VPCONTROL:
7515 CP0_CHECK(ctx->vp);
7516 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7517 register_name = "VPControl";
7518 break;
7519 default:
7520 goto cp0_unimplemented;
7522 break;
7523 case CP0_REGISTER_01:
7524 switch (sel) {
7525 case CP0_REG01__RANDOM:
7526 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7527 gen_helper_mfc0_random(arg, cpu_env);
7528 register_name = "Random";
7529 break;
7530 case CP0_REG01__VPECONTROL:
7531 CP0_CHECK(ctx->insn_flags & ASE_MT);
7532 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7533 register_name = "VPEControl";
7534 break;
7535 case CP0_REG01__VPECONF0:
7536 CP0_CHECK(ctx->insn_flags & ASE_MT);
7537 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7538 register_name = "VPEConf0";
7539 break;
7540 case CP0_REG01__VPECONF1:
7541 CP0_CHECK(ctx->insn_flags & ASE_MT);
7542 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7543 register_name = "VPEConf1";
7544 break;
7545 case CP0_REG01__YQMASK:
7546 CP0_CHECK(ctx->insn_flags & ASE_MT);
7547 tcg_gen_ld_tl(arg, cpu_env,
7548 offsetof(CPUMIPSState, CP0_YQMask));
7549 register_name = "YQMask";
7550 break;
7551 case CP0_REG01__VPESCHEDULE:
7552 CP0_CHECK(ctx->insn_flags & ASE_MT);
7553 tcg_gen_ld_tl(arg, cpu_env,
7554 offsetof(CPUMIPSState, CP0_VPESchedule));
7555 register_name = "VPESchedule";
7556 break;
7557 case CP0_REG01__VPESCHEFBACK:
7558 CP0_CHECK(ctx->insn_flags & ASE_MT);
7559 tcg_gen_ld_tl(arg, cpu_env,
7560 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7561 register_name = "VPEScheFBack";
7562 break;
7563 case CP0_REG01__VPEOPT:
7564 CP0_CHECK(ctx->insn_flags & ASE_MT);
7565 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7566 register_name = "VPEOpt";
7567 break;
7568 default:
7569 goto cp0_unimplemented;
7571 break;
7572 case CP0_REGISTER_02:
7573 switch (sel) {
7574 case CP0_REG02__ENTRYLO0:
7575 tcg_gen_ld_tl(arg, cpu_env,
7576 offsetof(CPUMIPSState, CP0_EntryLo0));
7577 register_name = "EntryLo0";
7578 break;
7579 case CP0_REG02__TCSTATUS:
7580 CP0_CHECK(ctx->insn_flags & ASE_MT);
7581 gen_helper_mfc0_tcstatus(arg, cpu_env);
7582 register_name = "TCStatus";
7583 break;
7584 case CP0_REG02__TCBIND:
7585 CP0_CHECK(ctx->insn_flags & ASE_MT);
7586 gen_helper_mfc0_tcbind(arg, cpu_env);
7587 register_name = "TCBind";
7588 break;
7589 case CP0_REG02__TCRESTART:
7590 CP0_CHECK(ctx->insn_flags & ASE_MT);
7591 gen_helper_dmfc0_tcrestart(arg, cpu_env);
7592 register_name = "TCRestart";
7593 break;
7594 case CP0_REG02__TCHALT:
7595 CP0_CHECK(ctx->insn_flags & ASE_MT);
7596 gen_helper_dmfc0_tchalt(arg, cpu_env);
7597 register_name = "TCHalt";
7598 break;
7599 case CP0_REG02__TCCONTEXT:
7600 CP0_CHECK(ctx->insn_flags & ASE_MT);
7601 gen_helper_dmfc0_tccontext(arg, cpu_env);
7602 register_name = "TCContext";
7603 break;
7604 case CP0_REG02__TCSCHEDULE:
7605 CP0_CHECK(ctx->insn_flags & ASE_MT);
7606 gen_helper_dmfc0_tcschedule(arg, cpu_env);
7607 register_name = "TCSchedule";
7608 break;
7609 case CP0_REG02__TCSCHEFBACK:
7610 CP0_CHECK(ctx->insn_flags & ASE_MT);
7611 gen_helper_dmfc0_tcschefback(arg, cpu_env);
7612 register_name = "TCScheFBack";
7613 break;
7614 default:
7615 goto cp0_unimplemented;
7617 break;
7618 case CP0_REGISTER_03:
7619 switch (sel) {
7620 case CP0_REG03__ENTRYLO1:
7621 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
7622 register_name = "EntryLo1";
7623 break;
7624 case CP0_REG03__GLOBALNUM:
7625 CP0_CHECK(ctx->vp);
7626 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7627 register_name = "GlobalNumber";
7628 break;
7629 default:
7630 goto cp0_unimplemented;
7632 break;
7633 case CP0_REGISTER_04:
7634 switch (sel) {
7635 case CP0_REG04__CONTEXT:
7636 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7637 register_name = "Context";
7638 break;
7639 case CP0_REG04__CONTEXTCONFIG:
7640 /* SmartMIPS ASE */
7641 /* gen_helper_dmfc0_contextconfig(arg); */
7642 register_name = "ContextConfig";
7643 goto cp0_unimplemented;
7644 case CP0_REG04__USERLOCAL:
7645 CP0_CHECK(ctx->ulri);
7646 tcg_gen_ld_tl(arg, cpu_env,
7647 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7648 register_name = "UserLocal";
7649 break;
7650 case CP0_REG04__MMID:
7651 CP0_CHECK(ctx->mi);
7652 gen_helper_mtc0_memorymapid(cpu_env, arg);
7653 register_name = "MMID";
7654 break;
7655 default:
7656 goto cp0_unimplemented;
7658 break;
7659 case CP0_REGISTER_05:
7660 switch (sel) {
7661 case CP0_REG05__PAGEMASK:
7662 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7663 register_name = "PageMask";
7664 break;
7665 case CP0_REG05__PAGEGRAIN:
7666 check_insn(ctx, ISA_MIPS_R2);
7667 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7668 register_name = "PageGrain";
7669 break;
7670 case CP0_REG05__SEGCTL0:
7671 CP0_CHECK(ctx->sc);
7672 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7673 register_name = "SegCtl0";
7674 break;
7675 case CP0_REG05__SEGCTL1:
7676 CP0_CHECK(ctx->sc);
7677 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7678 register_name = "SegCtl1";
7679 break;
7680 case CP0_REG05__SEGCTL2:
7681 CP0_CHECK(ctx->sc);
7682 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7683 register_name = "SegCtl2";
7684 break;
7685 case CP0_REG05__PWBASE:
7686 check_pw(ctx);
7687 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
7688 register_name = "PWBase";
7689 break;
7690 case CP0_REG05__PWFIELD:
7691 check_pw(ctx);
7692 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
7693 register_name = "PWField";
7694 break;
7695 case CP0_REG05__PWSIZE:
7696 check_pw(ctx);
7697 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
7698 register_name = "PWSize";
7699 break;
7700 default:
7701 goto cp0_unimplemented;
7703 break;
7704 case CP0_REGISTER_06:
7705 switch (sel) {
7706 case CP0_REG06__WIRED:
7707 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7708 register_name = "Wired";
7709 break;
7710 case CP0_REG06__SRSCONF0:
7711 check_insn(ctx, ISA_MIPS_R2);
7712 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7713 register_name = "SRSConf0";
7714 break;
7715 case CP0_REG06__SRSCONF1:
7716 check_insn(ctx, ISA_MIPS_R2);
7717 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7718 register_name = "SRSConf1";
7719 break;
7720 case CP0_REG06__SRSCONF2:
7721 check_insn(ctx, ISA_MIPS_R2);
7722 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7723 register_name = "SRSConf2";
7724 break;
7725 case CP0_REG06__SRSCONF3:
7726 check_insn(ctx, ISA_MIPS_R2);
7727 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7728 register_name = "SRSConf3";
7729 break;
7730 case CP0_REG06__SRSCONF4:
7731 check_insn(ctx, ISA_MIPS_R2);
7732 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7733 register_name = "SRSConf4";
7734 break;
7735 case CP0_REG06__PWCTL:
7736 check_pw(ctx);
7737 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7738 register_name = "PWCtl";
7739 break;
7740 default:
7741 goto cp0_unimplemented;
7743 break;
7744 case CP0_REGISTER_07:
7745 switch (sel) {
7746 case CP0_REG07__HWRENA:
7747 check_insn(ctx, ISA_MIPS_R2);
7748 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7749 register_name = "HWREna";
7750 break;
7751 default:
7752 goto cp0_unimplemented;
7754 break;
7755 case CP0_REGISTER_08:
7756 switch (sel) {
7757 case CP0_REG08__BADVADDR:
7758 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7759 register_name = "BadVAddr";
7760 break;
7761 case CP0_REG08__BADINSTR:
7762 CP0_CHECK(ctx->bi);
7763 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7764 register_name = "BadInstr";
7765 break;
7766 case CP0_REG08__BADINSTRP:
7767 CP0_CHECK(ctx->bp);
7768 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7769 register_name = "BadInstrP";
7770 break;
7771 case CP0_REG08__BADINSTRX:
7772 CP0_CHECK(ctx->bi);
7773 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7774 tcg_gen_andi_tl(arg, arg, ~0xffff);
7775 register_name = "BadInstrX";
7776 break;
7777 default:
7778 goto cp0_unimplemented;
7780 break;
7781 case CP0_REGISTER_09:
7782 switch (sel) {
7783 case CP0_REG09__COUNT:
7784 /* Mark as an IO operation because we read the time. */
7785 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7786 gen_io_start();
7788 gen_helper_mfc0_count(arg, cpu_env);
7790 * Break the TB to be able to take timer interrupts immediately
7791 * after reading count. DISAS_STOP isn't sufficient, we need to
7792 * ensure we break completely out of translated code.
7794 gen_save_pc(ctx->base.pc_next + 4);
7795 ctx->base.is_jmp = DISAS_EXIT;
7796 register_name = "Count";
7797 break;
7798 case CP0_REG09__SAARI:
7799 CP0_CHECK(ctx->saar);
7800 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7801 register_name = "SAARI";
7802 break;
7803 case CP0_REG09__SAAR:
7804 CP0_CHECK(ctx->saar);
7805 gen_helper_dmfc0_saar(arg, cpu_env);
7806 register_name = "SAAR";
7807 break;
7808 default:
7809 goto cp0_unimplemented;
7811 break;
7812 case CP0_REGISTER_10:
7813 switch (sel) {
7814 case CP0_REG10__ENTRYHI:
7815 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7816 register_name = "EntryHi";
7817 break;
7818 default:
7819 goto cp0_unimplemented;
7821 break;
7822 case CP0_REGISTER_11:
7823 switch (sel) {
7824 case CP0_REG11__COMPARE:
7825 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7826 register_name = "Compare";
7827 break;
7828 /* 6,7 are implementation dependent */
7829 default:
7830 goto cp0_unimplemented;
7832 break;
7833 case CP0_REGISTER_12:
7834 switch (sel) {
7835 case CP0_REG12__STATUS:
7836 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7837 register_name = "Status";
7838 break;
7839 case CP0_REG12__INTCTL:
7840 check_insn(ctx, ISA_MIPS_R2);
7841 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7842 register_name = "IntCtl";
7843 break;
7844 case CP0_REG12__SRSCTL:
7845 check_insn(ctx, ISA_MIPS_R2);
7846 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7847 register_name = "SRSCtl";
7848 break;
7849 case CP0_REG12__SRSMAP:
7850 check_insn(ctx, ISA_MIPS_R2);
7851 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7852 register_name = "SRSMap";
7853 break;
7854 default:
7855 goto cp0_unimplemented;
7857 break;
7858 case CP0_REGISTER_13:
7859 switch (sel) {
7860 case CP0_REG13__CAUSE:
7861 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7862 register_name = "Cause";
7863 break;
7864 default:
7865 goto cp0_unimplemented;
7867 break;
7868 case CP0_REGISTER_14:
7869 switch (sel) {
7870 case CP0_REG14__EPC:
7871 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7872 register_name = "EPC";
7873 break;
7874 default:
7875 goto cp0_unimplemented;
7877 break;
7878 case CP0_REGISTER_15:
7879 switch (sel) {
7880 case CP0_REG15__PRID:
7881 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7882 register_name = "PRid";
7883 break;
7884 case CP0_REG15__EBASE:
7885 check_insn(ctx, ISA_MIPS_R2);
7886 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7887 register_name = "EBase";
7888 break;
7889 case CP0_REG15__CMGCRBASE:
7890 check_insn(ctx, ISA_MIPS_R2);
7891 CP0_CHECK(ctx->cmgcr);
7892 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7893 register_name = "CMGCRBase";
7894 break;
7895 default:
7896 goto cp0_unimplemented;
7898 break;
7899 case CP0_REGISTER_16:
7900 switch (sel) {
7901 case CP0_REG16__CONFIG:
7902 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7903 register_name = "Config";
7904 break;
7905 case CP0_REG16__CONFIG1:
7906 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7907 register_name = "Config1";
7908 break;
7909 case CP0_REG16__CONFIG2:
7910 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7911 register_name = "Config2";
7912 break;
7913 case CP0_REG16__CONFIG3:
7914 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7915 register_name = "Config3";
7916 break;
7917 case CP0_REG16__CONFIG4:
7918 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7919 register_name = "Config4";
7920 break;
7921 case CP0_REG16__CONFIG5:
7922 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7923 register_name = "Config5";
7924 break;
7925 /* 6,7 are implementation dependent */
7926 case CP0_REG16__CONFIG6:
7927 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7928 register_name = "Config6";
7929 break;
7930 case CP0_REG16__CONFIG7:
7931 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7932 register_name = "Config7";
7933 break;
7934 default:
7935 goto cp0_unimplemented;
7937 break;
7938 case CP0_REGISTER_17:
7939 switch (sel) {
7940 case CP0_REG17__LLADDR:
7941 gen_helper_dmfc0_lladdr(arg, cpu_env);
7942 register_name = "LLAddr";
7943 break;
7944 case CP0_REG17__MAAR:
7945 CP0_CHECK(ctx->mrp);
7946 gen_helper_dmfc0_maar(arg, cpu_env);
7947 register_name = "MAAR";
7948 break;
7949 case CP0_REG17__MAARI:
7950 CP0_CHECK(ctx->mrp);
7951 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7952 register_name = "MAARI";
7953 break;
7954 default:
7955 goto cp0_unimplemented;
7957 break;
7958 case CP0_REGISTER_18:
7959 switch (sel) {
7960 case CP0_REG18__WATCHLO0:
7961 case CP0_REG18__WATCHLO1:
7962 case CP0_REG18__WATCHLO2:
7963 case CP0_REG18__WATCHLO3:
7964 case CP0_REG18__WATCHLO4:
7965 case CP0_REG18__WATCHLO5:
7966 case CP0_REG18__WATCHLO6:
7967 case CP0_REG18__WATCHLO7:
7968 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7969 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
7970 register_name = "WatchLo";
7971 break;
7972 default:
7973 goto cp0_unimplemented;
7975 break;
7976 case CP0_REGISTER_19:
7977 switch (sel) {
7978 case CP0_REG19__WATCHHI0:
7979 case CP0_REG19__WATCHHI1:
7980 case CP0_REG19__WATCHHI2:
7981 case CP0_REG19__WATCHHI3:
7982 case CP0_REG19__WATCHHI4:
7983 case CP0_REG19__WATCHHI5:
7984 case CP0_REG19__WATCHHI6:
7985 case CP0_REG19__WATCHHI7:
7986 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7987 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
7988 register_name = "WatchHi";
7989 break;
7990 default:
7991 goto cp0_unimplemented;
7993 break;
7994 case CP0_REGISTER_20:
7995 switch (sel) {
7996 case CP0_REG20__XCONTEXT:
7997 check_insn(ctx, ISA_MIPS3);
7998 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7999 register_name = "XContext";
8000 break;
8001 default:
8002 goto cp0_unimplemented;
8004 break;
8005 case CP0_REGISTER_21:
8006 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8007 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8008 switch (sel) {
8009 case 0:
8010 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8011 register_name = "Framemask";
8012 break;
8013 default:
8014 goto cp0_unimplemented;
8016 break;
8017 case CP0_REGISTER_22:
8018 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8019 register_name = "'Diagnostic"; /* implementation dependent */
8020 break;
8021 case CP0_REGISTER_23:
8022 switch (sel) {
8023 case CP0_REG23__DEBUG:
8024 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8025 register_name = "Debug";
8026 break;
8027 case CP0_REG23__TRACECONTROL:
8028 /* PDtrace support */
8029 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
8030 register_name = "TraceControl";
8031 goto cp0_unimplemented;
8032 case CP0_REG23__TRACECONTROL2:
8033 /* PDtrace support */
8034 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
8035 register_name = "TraceControl2";
8036 goto cp0_unimplemented;
8037 case CP0_REG23__USERTRACEDATA1:
8038 /* PDtrace support */
8039 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
8040 register_name = "UserTraceData1";
8041 goto cp0_unimplemented;
8042 case CP0_REG23__TRACEIBPC:
8043 /* PDtrace support */
8044 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
8045 register_name = "TraceIBPC";
8046 goto cp0_unimplemented;
8047 case CP0_REG23__TRACEDBPC:
8048 /* PDtrace support */
8049 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
8050 register_name = "TraceDBPC";
8051 goto cp0_unimplemented;
8052 default:
8053 goto cp0_unimplemented;
8055 break;
8056 case CP0_REGISTER_24:
8057 switch (sel) {
8058 case CP0_REG24__DEPC:
8059 /* EJTAG support */
8060 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8061 register_name = "DEPC";
8062 break;
8063 default:
8064 goto cp0_unimplemented;
8066 break;
8067 case CP0_REGISTER_25:
8068 switch (sel) {
8069 case CP0_REG25__PERFCTL0:
8070 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8071 register_name = "Performance0";
8072 break;
8073 case CP0_REG25__PERFCNT0:
8074 /* gen_helper_dmfc0_performance1(arg); */
8075 register_name = "Performance1";
8076 goto cp0_unimplemented;
8077 case CP0_REG25__PERFCTL1:
8078 /* gen_helper_dmfc0_performance2(arg); */
8079 register_name = "Performance2";
8080 goto cp0_unimplemented;
8081 case CP0_REG25__PERFCNT1:
8082 /* gen_helper_dmfc0_performance3(arg); */
8083 register_name = "Performance3";
8084 goto cp0_unimplemented;
8085 case CP0_REG25__PERFCTL2:
8086 /* gen_helper_dmfc0_performance4(arg); */
8087 register_name = "Performance4";
8088 goto cp0_unimplemented;
8089 case CP0_REG25__PERFCNT2:
8090 /* gen_helper_dmfc0_performance5(arg); */
8091 register_name = "Performance5";
8092 goto cp0_unimplemented;
8093 case CP0_REG25__PERFCTL3:
8094 /* gen_helper_dmfc0_performance6(arg); */
8095 register_name = "Performance6";
8096 goto cp0_unimplemented;
8097 case CP0_REG25__PERFCNT3:
8098 /* gen_helper_dmfc0_performance7(arg); */
8099 register_name = "Performance7";
8100 goto cp0_unimplemented;
8101 default:
8102 goto cp0_unimplemented;
8104 break;
8105 case CP0_REGISTER_26:
8106 switch (sel) {
8107 case CP0_REG26__ERRCTL:
8108 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8109 register_name = "ErrCtl";
8110 break;
8111 default:
8112 goto cp0_unimplemented;
8114 break;
8115 case CP0_REGISTER_27:
8116 switch (sel) {
8117 /* ignored */
8118 case CP0_REG27__CACHERR:
8119 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8120 register_name = "CacheErr";
8121 break;
8122 default:
8123 goto cp0_unimplemented;
8125 break;
8126 case CP0_REGISTER_28:
8127 switch (sel) {
8128 case CP0_REG28__TAGLO:
8129 case CP0_REG28__TAGLO1:
8130 case CP0_REG28__TAGLO2:
8131 case CP0_REG28__TAGLO3:
8132 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8133 register_name = "TagLo";
8134 break;
8135 case CP0_REG28__DATALO:
8136 case CP0_REG28__DATALO1:
8137 case CP0_REG28__DATALO2:
8138 case CP0_REG28__DATALO3:
8139 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8140 register_name = "DataLo";
8141 break;
8142 default:
8143 goto cp0_unimplemented;
8145 break;
8146 case CP0_REGISTER_29:
8147 switch (sel) {
8148 case CP0_REG29__TAGHI:
8149 case CP0_REG29__TAGHI1:
8150 case CP0_REG29__TAGHI2:
8151 case CP0_REG29__TAGHI3:
8152 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8153 register_name = "TagHi";
8154 break;
8155 case CP0_REG29__DATAHI:
8156 case CP0_REG29__DATAHI1:
8157 case CP0_REG29__DATAHI2:
8158 case CP0_REG29__DATAHI3:
8159 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8160 register_name = "DataHi";
8161 break;
8162 default:
8163 goto cp0_unimplemented;
8165 break;
8166 case CP0_REGISTER_30:
8167 switch (sel) {
8168 case CP0_REG30__ERROREPC:
8169 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8170 register_name = "ErrorEPC";
8171 break;
8172 default:
8173 goto cp0_unimplemented;
8175 break;
8176 case CP0_REGISTER_31:
8177 switch (sel) {
8178 case CP0_REG31__DESAVE:
8179 /* EJTAG support */
8180 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8181 register_name = "DESAVE";
8182 break;
8183 case CP0_REG31__KSCRATCH1:
8184 case CP0_REG31__KSCRATCH2:
8185 case CP0_REG31__KSCRATCH3:
8186 case CP0_REG31__KSCRATCH4:
8187 case CP0_REG31__KSCRATCH5:
8188 case CP0_REG31__KSCRATCH6:
8189 CP0_CHECK(ctx->kscrexist & (1 << sel));
8190 tcg_gen_ld_tl(arg, cpu_env,
8191 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8192 register_name = "KScratch";
8193 break;
8194 default:
8195 goto cp0_unimplemented;
8197 break;
8198 default:
8199 goto cp0_unimplemented;
8201 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
8202 return;
8204 cp0_unimplemented:
8205 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
8206 register_name, reg, sel);
8207 gen_mfc0_unimplemented(ctx, arg);
8210 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8212 const char *register_name = "invalid";
8214 if (sel != 0) {
8215 check_insn(ctx, ISA_MIPS_R1);
8218 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8219 gen_io_start();
8222 switch (reg) {
8223 case CP0_REGISTER_00:
8224 switch (sel) {
8225 case CP0_REG00__INDEX:
8226 gen_helper_mtc0_index(cpu_env, arg);
8227 register_name = "Index";
8228 break;
8229 case CP0_REG00__MVPCONTROL:
8230 CP0_CHECK(ctx->insn_flags & ASE_MT);
8231 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8232 register_name = "MVPControl";
8233 break;
8234 case CP0_REG00__MVPCONF0:
8235 CP0_CHECK(ctx->insn_flags & ASE_MT);
8236 /* ignored */
8237 register_name = "MVPConf0";
8238 break;
8239 case CP0_REG00__MVPCONF1:
8240 CP0_CHECK(ctx->insn_flags & ASE_MT);
8241 /* ignored */
8242 register_name = "MVPConf1";
8243 break;
8244 case CP0_REG00__VPCONTROL:
8245 CP0_CHECK(ctx->vp);
8246 /* ignored */
8247 register_name = "VPControl";
8248 break;
8249 default:
8250 goto cp0_unimplemented;
8252 break;
8253 case CP0_REGISTER_01:
8254 switch (sel) {
8255 case CP0_REG01__RANDOM:
8256 /* ignored */
8257 register_name = "Random";
8258 break;
8259 case CP0_REG01__VPECONTROL:
8260 CP0_CHECK(ctx->insn_flags & ASE_MT);
8261 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8262 register_name = "VPEControl";
8263 break;
8264 case CP0_REG01__VPECONF0:
8265 CP0_CHECK(ctx->insn_flags & ASE_MT);
8266 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8267 register_name = "VPEConf0";
8268 break;
8269 case CP0_REG01__VPECONF1:
8270 CP0_CHECK(ctx->insn_flags & ASE_MT);
8271 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8272 register_name = "VPEConf1";
8273 break;
8274 case CP0_REG01__YQMASK:
8275 CP0_CHECK(ctx->insn_flags & ASE_MT);
8276 gen_helper_mtc0_yqmask(cpu_env, arg);
8277 register_name = "YQMask";
8278 break;
8279 case CP0_REG01__VPESCHEDULE:
8280 CP0_CHECK(ctx->insn_flags & ASE_MT);
8281 tcg_gen_st_tl(arg, cpu_env,
8282 offsetof(CPUMIPSState, CP0_VPESchedule));
8283 register_name = "VPESchedule";
8284 break;
8285 case CP0_REG01__VPESCHEFBACK:
8286 CP0_CHECK(ctx->insn_flags & ASE_MT);
8287 tcg_gen_st_tl(arg, cpu_env,
8288 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8289 register_name = "VPEScheFBack";
8290 break;
8291 case CP0_REG01__VPEOPT:
8292 CP0_CHECK(ctx->insn_flags & ASE_MT);
8293 gen_helper_mtc0_vpeopt(cpu_env, arg);
8294 register_name = "VPEOpt";
8295 break;
8296 default:
8297 goto cp0_unimplemented;
8299 break;
8300 case CP0_REGISTER_02:
8301 switch (sel) {
8302 case CP0_REG02__ENTRYLO0:
8303 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8304 register_name = "EntryLo0";
8305 break;
8306 case CP0_REG02__TCSTATUS:
8307 CP0_CHECK(ctx->insn_flags & ASE_MT);
8308 gen_helper_mtc0_tcstatus(cpu_env, arg);
8309 register_name = "TCStatus";
8310 break;
8311 case CP0_REG02__TCBIND:
8312 CP0_CHECK(ctx->insn_flags & ASE_MT);
8313 gen_helper_mtc0_tcbind(cpu_env, arg);
8314 register_name = "TCBind";
8315 break;
8316 case CP0_REG02__TCRESTART:
8317 CP0_CHECK(ctx->insn_flags & ASE_MT);
8318 gen_helper_mtc0_tcrestart(cpu_env, arg);
8319 register_name = "TCRestart";
8320 break;
8321 case CP0_REG02__TCHALT:
8322 CP0_CHECK(ctx->insn_flags & ASE_MT);
8323 gen_helper_mtc0_tchalt(cpu_env, arg);
8324 register_name = "TCHalt";
8325 break;
8326 case CP0_REG02__TCCONTEXT:
8327 CP0_CHECK(ctx->insn_flags & ASE_MT);
8328 gen_helper_mtc0_tccontext(cpu_env, arg);
8329 register_name = "TCContext";
8330 break;
8331 case CP0_REG02__TCSCHEDULE:
8332 CP0_CHECK(ctx->insn_flags & ASE_MT);
8333 gen_helper_mtc0_tcschedule(cpu_env, arg);
8334 register_name = "TCSchedule";
8335 break;
8336 case CP0_REG02__TCSCHEFBACK:
8337 CP0_CHECK(ctx->insn_flags & ASE_MT);
8338 gen_helper_mtc0_tcschefback(cpu_env, arg);
8339 register_name = "TCScheFBack";
8340 break;
8341 default:
8342 goto cp0_unimplemented;
8344 break;
8345 case CP0_REGISTER_03:
8346 switch (sel) {
8347 case CP0_REG03__ENTRYLO1:
8348 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8349 register_name = "EntryLo1";
8350 break;
8351 case CP0_REG03__GLOBALNUM:
8352 CP0_CHECK(ctx->vp);
8353 /* ignored */
8354 register_name = "GlobalNumber";
8355 break;
8356 default:
8357 goto cp0_unimplemented;
8359 break;
8360 case CP0_REGISTER_04:
8361 switch (sel) {
8362 case CP0_REG04__CONTEXT:
8363 gen_helper_mtc0_context(cpu_env, arg);
8364 register_name = "Context";
8365 break;
8366 case CP0_REG04__CONTEXTCONFIG:
8367 /* SmartMIPS ASE */
8368 /* gen_helper_dmtc0_contextconfig(arg); */
8369 register_name = "ContextConfig";
8370 goto cp0_unimplemented;
8371 case CP0_REG04__USERLOCAL:
8372 CP0_CHECK(ctx->ulri);
8373 tcg_gen_st_tl(arg, cpu_env,
8374 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8375 register_name = "UserLocal";
8376 break;
8377 case CP0_REG04__MMID:
8378 CP0_CHECK(ctx->mi);
8379 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8380 register_name = "MMID";
8381 break;
8382 default:
8383 goto cp0_unimplemented;
8385 break;
8386 case CP0_REGISTER_05:
8387 switch (sel) {
8388 case CP0_REG05__PAGEMASK:
8389 gen_helper_mtc0_pagemask(cpu_env, arg);
8390 register_name = "PageMask";
8391 break;
8392 case CP0_REG05__PAGEGRAIN:
8393 check_insn(ctx, ISA_MIPS_R2);
8394 gen_helper_mtc0_pagegrain(cpu_env, arg);
8395 register_name = "PageGrain";
8396 break;
8397 case CP0_REG05__SEGCTL0:
8398 CP0_CHECK(ctx->sc);
8399 gen_helper_mtc0_segctl0(cpu_env, arg);
8400 register_name = "SegCtl0";
8401 break;
8402 case CP0_REG05__SEGCTL1:
8403 CP0_CHECK(ctx->sc);
8404 gen_helper_mtc0_segctl1(cpu_env, arg);
8405 register_name = "SegCtl1";
8406 break;
8407 case CP0_REG05__SEGCTL2:
8408 CP0_CHECK(ctx->sc);
8409 gen_helper_mtc0_segctl2(cpu_env, arg);
8410 register_name = "SegCtl2";
8411 break;
8412 case CP0_REG05__PWBASE:
8413 check_pw(ctx);
8414 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8415 register_name = "PWBase";
8416 break;
8417 case CP0_REG05__PWFIELD:
8418 check_pw(ctx);
8419 gen_helper_mtc0_pwfield(cpu_env, arg);
8420 register_name = "PWField";
8421 break;
8422 case CP0_REG05__PWSIZE:
8423 check_pw(ctx);
8424 gen_helper_mtc0_pwsize(cpu_env, arg);
8425 register_name = "PWSize";
8426 break;
8427 default:
8428 goto cp0_unimplemented;
8430 break;
8431 case CP0_REGISTER_06:
8432 switch (sel) {
8433 case CP0_REG06__WIRED:
8434 gen_helper_mtc0_wired(cpu_env, arg);
8435 register_name = "Wired";
8436 break;
8437 case CP0_REG06__SRSCONF0:
8438 check_insn(ctx, ISA_MIPS_R2);
8439 gen_helper_mtc0_srsconf0(cpu_env, arg);
8440 register_name = "SRSConf0";
8441 break;
8442 case CP0_REG06__SRSCONF1:
8443 check_insn(ctx, ISA_MIPS_R2);
8444 gen_helper_mtc0_srsconf1(cpu_env, arg);
8445 register_name = "SRSConf1";
8446 break;
8447 case CP0_REG06__SRSCONF2:
8448 check_insn(ctx, ISA_MIPS_R2);
8449 gen_helper_mtc0_srsconf2(cpu_env, arg);
8450 register_name = "SRSConf2";
8451 break;
8452 case CP0_REG06__SRSCONF3:
8453 check_insn(ctx, ISA_MIPS_R2);
8454 gen_helper_mtc0_srsconf3(cpu_env, arg);
8455 register_name = "SRSConf3";
8456 break;
8457 case CP0_REG06__SRSCONF4:
8458 check_insn(ctx, ISA_MIPS_R2);
8459 gen_helper_mtc0_srsconf4(cpu_env, arg);
8460 register_name = "SRSConf4";
8461 break;
8462 case CP0_REG06__PWCTL:
8463 check_pw(ctx);
8464 gen_helper_mtc0_pwctl(cpu_env, arg);
8465 register_name = "PWCtl";
8466 break;
8467 default:
8468 goto cp0_unimplemented;
8470 break;
8471 case CP0_REGISTER_07:
8472 switch (sel) {
8473 case CP0_REG07__HWRENA:
8474 check_insn(ctx, ISA_MIPS_R2);
8475 gen_helper_mtc0_hwrena(cpu_env, arg);
8476 ctx->base.is_jmp = DISAS_STOP;
8477 register_name = "HWREna";
8478 break;
8479 default:
8480 goto cp0_unimplemented;
8482 break;
8483 case CP0_REGISTER_08:
8484 switch (sel) {
8485 case CP0_REG08__BADVADDR:
8486 /* ignored */
8487 register_name = "BadVAddr";
8488 break;
8489 case CP0_REG08__BADINSTR:
8490 /* ignored */
8491 register_name = "BadInstr";
8492 break;
8493 case CP0_REG08__BADINSTRP:
8494 /* ignored */
8495 register_name = "BadInstrP";
8496 break;
8497 case CP0_REG08__BADINSTRX:
8498 /* ignored */
8499 register_name = "BadInstrX";
8500 break;
8501 default:
8502 goto cp0_unimplemented;
8504 break;
8505 case CP0_REGISTER_09:
8506 switch (sel) {
8507 case CP0_REG09__COUNT:
8508 gen_helper_mtc0_count(cpu_env, arg);
8509 register_name = "Count";
8510 break;
8511 case CP0_REG09__SAARI:
8512 CP0_CHECK(ctx->saar);
8513 gen_helper_mtc0_saari(cpu_env, arg);
8514 register_name = "SAARI";
8515 break;
8516 case CP0_REG09__SAAR:
8517 CP0_CHECK(ctx->saar);
8518 gen_helper_mtc0_saar(cpu_env, arg);
8519 register_name = "SAAR";
8520 break;
8521 default:
8522 goto cp0_unimplemented;
8524 /* Stop translation as we may have switched the execution mode */
8525 ctx->base.is_jmp = DISAS_STOP;
8526 break;
8527 case CP0_REGISTER_10:
8528 switch (sel) {
8529 case CP0_REG10__ENTRYHI:
8530 gen_helper_mtc0_entryhi(cpu_env, arg);
8531 register_name = "EntryHi";
8532 break;
8533 default:
8534 goto cp0_unimplemented;
8536 break;
8537 case CP0_REGISTER_11:
8538 switch (sel) {
8539 case CP0_REG11__COMPARE:
8540 gen_helper_mtc0_compare(cpu_env, arg);
8541 register_name = "Compare";
8542 break;
8543 /* 6,7 are implementation dependent */
8544 default:
8545 goto cp0_unimplemented;
8547 /* Stop translation as we may have switched the execution mode */
8548 ctx->base.is_jmp = DISAS_STOP;
8549 break;
8550 case CP0_REGISTER_12:
8551 switch (sel) {
8552 case CP0_REG12__STATUS:
8553 save_cpu_state(ctx, 1);
8554 gen_helper_mtc0_status(cpu_env, arg);
8555 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8556 gen_save_pc(ctx->base.pc_next + 4);
8557 ctx->base.is_jmp = DISAS_EXIT;
8558 register_name = "Status";
8559 break;
8560 case CP0_REG12__INTCTL:
8561 check_insn(ctx, ISA_MIPS_R2);
8562 gen_helper_mtc0_intctl(cpu_env, arg);
8563 /* Stop translation as we may have switched the execution mode */
8564 ctx->base.is_jmp = DISAS_STOP;
8565 register_name = "IntCtl";
8566 break;
8567 case CP0_REG12__SRSCTL:
8568 check_insn(ctx, ISA_MIPS_R2);
8569 gen_helper_mtc0_srsctl(cpu_env, arg);
8570 /* Stop translation as we may have switched the execution mode */
8571 ctx->base.is_jmp = DISAS_STOP;
8572 register_name = "SRSCtl";
8573 break;
8574 case CP0_REG12__SRSMAP:
8575 check_insn(ctx, ISA_MIPS_R2);
8576 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8577 /* Stop translation as we may have switched the execution mode */
8578 ctx->base.is_jmp = DISAS_STOP;
8579 register_name = "SRSMap";
8580 break;
8581 default:
8582 goto cp0_unimplemented;
8584 break;
8585 case CP0_REGISTER_13:
8586 switch (sel) {
8587 case CP0_REG13__CAUSE:
8588 save_cpu_state(ctx, 1);
8589 gen_helper_mtc0_cause(cpu_env, arg);
8591 * Stop translation as we may have triggered an interrupt.
8592 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8593 * translated code to check for pending interrupts.
8595 gen_save_pc(ctx->base.pc_next + 4);
8596 ctx->base.is_jmp = DISAS_EXIT;
8597 register_name = "Cause";
8598 break;
8599 default:
8600 goto cp0_unimplemented;
8602 break;
8603 case CP0_REGISTER_14:
8604 switch (sel) {
8605 case CP0_REG14__EPC:
8606 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8607 register_name = "EPC";
8608 break;
8609 default:
8610 goto cp0_unimplemented;
8612 break;
8613 case CP0_REGISTER_15:
8614 switch (sel) {
8615 case CP0_REG15__PRID:
8616 /* ignored */
8617 register_name = "PRid";
8618 break;
8619 case CP0_REG15__EBASE:
8620 check_insn(ctx, ISA_MIPS_R2);
8621 gen_helper_mtc0_ebase(cpu_env, arg);
8622 register_name = "EBase";
8623 break;
8624 default:
8625 goto cp0_unimplemented;
8627 break;
8628 case CP0_REGISTER_16:
8629 switch (sel) {
8630 case CP0_REG16__CONFIG:
8631 gen_helper_mtc0_config0(cpu_env, arg);
8632 register_name = "Config";
8633 /* Stop translation as we may have switched the execution mode */
8634 ctx->base.is_jmp = DISAS_STOP;
8635 break;
8636 case CP0_REG16__CONFIG1:
8637 /* ignored, read only */
8638 register_name = "Config1";
8639 break;
8640 case CP0_REG16__CONFIG2:
8641 gen_helper_mtc0_config2(cpu_env, arg);
8642 register_name = "Config2";
8643 /* Stop translation as we may have switched the execution mode */
8644 ctx->base.is_jmp = DISAS_STOP;
8645 break;
8646 case CP0_REG16__CONFIG3:
8647 gen_helper_mtc0_config3(cpu_env, arg);
8648 register_name = "Config3";
8649 /* Stop translation as we may have switched the execution mode */
8650 ctx->base.is_jmp = DISAS_STOP;
8651 break;
8652 case CP0_REG16__CONFIG4:
8653 /* currently ignored */
8654 register_name = "Config4";
8655 break;
8656 case CP0_REG16__CONFIG5:
8657 gen_helper_mtc0_config5(cpu_env, arg);
8658 register_name = "Config5";
8659 /* Stop translation as we may have switched the execution mode */
8660 ctx->base.is_jmp = DISAS_STOP;
8661 break;
8662 /* 6,7 are implementation dependent */
8663 default:
8664 register_name = "Invalid config selector";
8665 goto cp0_unimplemented;
8667 break;
8668 case CP0_REGISTER_17:
8669 switch (sel) {
8670 case CP0_REG17__LLADDR:
8671 gen_helper_mtc0_lladdr(cpu_env, arg);
8672 register_name = "LLAddr";
8673 break;
8674 case CP0_REG17__MAAR:
8675 CP0_CHECK(ctx->mrp);
8676 gen_helper_mtc0_maar(cpu_env, arg);
8677 register_name = "MAAR";
8678 break;
8679 case CP0_REG17__MAARI:
8680 CP0_CHECK(ctx->mrp);
8681 gen_helper_mtc0_maari(cpu_env, arg);
8682 register_name = "MAARI";
8683 break;
8684 default:
8685 goto cp0_unimplemented;
8687 break;
8688 case CP0_REGISTER_18:
8689 switch (sel) {
8690 case CP0_REG18__WATCHLO0:
8691 case CP0_REG18__WATCHLO1:
8692 case CP0_REG18__WATCHLO2:
8693 case CP0_REG18__WATCHLO3:
8694 case CP0_REG18__WATCHLO4:
8695 case CP0_REG18__WATCHLO5:
8696 case CP0_REG18__WATCHLO6:
8697 case CP0_REG18__WATCHLO7:
8698 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8699 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8700 register_name = "WatchLo";
8701 break;
8702 default:
8703 goto cp0_unimplemented;
8705 break;
8706 case CP0_REGISTER_19:
8707 switch (sel) {
8708 case CP0_REG19__WATCHHI0:
8709 case CP0_REG19__WATCHHI1:
8710 case CP0_REG19__WATCHHI2:
8711 case CP0_REG19__WATCHHI3:
8712 case CP0_REG19__WATCHHI4:
8713 case CP0_REG19__WATCHHI5:
8714 case CP0_REG19__WATCHHI6:
8715 case CP0_REG19__WATCHHI7:
8716 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8717 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8718 register_name = "WatchHi";
8719 break;
8720 default:
8721 goto cp0_unimplemented;
8723 break;
8724 case CP0_REGISTER_20:
8725 switch (sel) {
8726 case CP0_REG20__XCONTEXT:
8727 check_insn(ctx, ISA_MIPS3);
8728 gen_helper_mtc0_xcontext(cpu_env, arg);
8729 register_name = "XContext";
8730 break;
8731 default:
8732 goto cp0_unimplemented;
8734 break;
8735 case CP0_REGISTER_21:
8736 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8737 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8738 switch (sel) {
8739 case 0:
8740 gen_helper_mtc0_framemask(cpu_env, arg);
8741 register_name = "Framemask";
8742 break;
8743 default:
8744 goto cp0_unimplemented;
8746 break;
8747 case CP0_REGISTER_22:
8748 /* ignored */
8749 register_name = "Diagnostic"; /* implementation dependent */
8750 break;
8751 case CP0_REGISTER_23:
8752 switch (sel) {
8753 case CP0_REG23__DEBUG:
8754 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8755 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8756 gen_save_pc(ctx->base.pc_next + 4);
8757 ctx->base.is_jmp = DISAS_EXIT;
8758 register_name = "Debug";
8759 break;
8760 case CP0_REG23__TRACECONTROL:
8761 /* PDtrace support */
8762 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8763 /* Stop translation as we may have switched the execution mode */
8764 ctx->base.is_jmp = DISAS_STOP;
8765 register_name = "TraceControl";
8766 goto cp0_unimplemented;
8767 case CP0_REG23__TRACECONTROL2:
8768 /* PDtrace support */
8769 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8770 /* Stop translation as we may have switched the execution mode */
8771 ctx->base.is_jmp = DISAS_STOP;
8772 register_name = "TraceControl2";
8773 goto cp0_unimplemented;
8774 case CP0_REG23__USERTRACEDATA1:
8775 /* PDtrace support */
8776 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8777 /* Stop translation as we may have switched the execution mode */
8778 ctx->base.is_jmp = DISAS_STOP;
8779 register_name = "UserTraceData1";
8780 goto cp0_unimplemented;
8781 case CP0_REG23__TRACEIBPC:
8782 /* PDtrace support */
8783 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8784 /* Stop translation as we may have switched the execution mode */
8785 ctx->base.is_jmp = DISAS_STOP;
8786 register_name = "TraceIBPC";
8787 goto cp0_unimplemented;
8788 case CP0_REG23__TRACEDBPC:
8789 /* PDtrace support */
8790 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8791 /* Stop translation as we may have switched the execution mode */
8792 ctx->base.is_jmp = DISAS_STOP;
8793 register_name = "TraceDBPC";
8794 goto cp0_unimplemented;
8795 default:
8796 goto cp0_unimplemented;
8798 break;
8799 case CP0_REGISTER_24:
8800 switch (sel) {
8801 case CP0_REG24__DEPC:
8802 /* EJTAG support */
8803 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8804 register_name = "DEPC";
8805 break;
8806 default:
8807 goto cp0_unimplemented;
8809 break;
8810 case CP0_REGISTER_25:
8811 switch (sel) {
8812 case CP0_REG25__PERFCTL0:
8813 gen_helper_mtc0_performance0(cpu_env, arg);
8814 register_name = "Performance0";
8815 break;
8816 case CP0_REG25__PERFCNT0:
8817 /* gen_helper_mtc0_performance1(cpu_env, arg); */
8818 register_name = "Performance1";
8819 goto cp0_unimplemented;
8820 case CP0_REG25__PERFCTL1:
8821 /* gen_helper_mtc0_performance2(cpu_env, arg); */
8822 register_name = "Performance2";
8823 goto cp0_unimplemented;
8824 case CP0_REG25__PERFCNT1:
8825 /* gen_helper_mtc0_performance3(cpu_env, arg); */
8826 register_name = "Performance3";
8827 goto cp0_unimplemented;
8828 case CP0_REG25__PERFCTL2:
8829 /* gen_helper_mtc0_performance4(cpu_env, arg); */
8830 register_name = "Performance4";
8831 goto cp0_unimplemented;
8832 case CP0_REG25__PERFCNT2:
8833 /* gen_helper_mtc0_performance5(cpu_env, arg); */
8834 register_name = "Performance5";
8835 goto cp0_unimplemented;
8836 case CP0_REG25__PERFCTL3:
8837 /* gen_helper_mtc0_performance6(cpu_env, arg); */
8838 register_name = "Performance6";
8839 goto cp0_unimplemented;
8840 case CP0_REG25__PERFCNT3:
8841 /* gen_helper_mtc0_performance7(cpu_env, arg); */
8842 register_name = "Performance7";
8843 goto cp0_unimplemented;
8844 default:
8845 goto cp0_unimplemented;
8847 break;
8848 case CP0_REGISTER_26:
8849 switch (sel) {
8850 case CP0_REG26__ERRCTL:
8851 gen_helper_mtc0_errctl(cpu_env, arg);
8852 ctx->base.is_jmp = DISAS_STOP;
8853 register_name = "ErrCtl";
8854 break;
8855 default:
8856 goto cp0_unimplemented;
8858 break;
8859 case CP0_REGISTER_27:
8860 switch (sel) {
8861 case CP0_REG27__CACHERR:
8862 /* ignored */
8863 register_name = "CacheErr";
8864 break;
8865 default:
8866 goto cp0_unimplemented;
8868 break;
8869 case CP0_REGISTER_28:
8870 switch (sel) {
8871 case CP0_REG28__TAGLO:
8872 case CP0_REG28__TAGLO1:
8873 case CP0_REG28__TAGLO2:
8874 case CP0_REG28__TAGLO3:
8875 gen_helper_mtc0_taglo(cpu_env, arg);
8876 register_name = "TagLo";
8877 break;
8878 case CP0_REG28__DATALO:
8879 case CP0_REG28__DATALO1:
8880 case CP0_REG28__DATALO2:
8881 case CP0_REG28__DATALO3:
8882 gen_helper_mtc0_datalo(cpu_env, arg);
8883 register_name = "DataLo";
8884 break;
8885 default:
8886 goto cp0_unimplemented;
8888 break;
8889 case CP0_REGISTER_29:
8890 switch (sel) {
8891 case CP0_REG29__TAGHI:
8892 case CP0_REG29__TAGHI1:
8893 case CP0_REG29__TAGHI2:
8894 case CP0_REG29__TAGHI3:
8895 gen_helper_mtc0_taghi(cpu_env, arg);
8896 register_name = "TagHi";
8897 break;
8898 case CP0_REG29__DATAHI:
8899 case CP0_REG29__DATAHI1:
8900 case CP0_REG29__DATAHI2:
8901 case CP0_REG29__DATAHI3:
8902 gen_helper_mtc0_datahi(cpu_env, arg);
8903 register_name = "DataHi";
8904 break;
8905 default:
8906 register_name = "invalid sel";
8907 goto cp0_unimplemented;
8909 break;
8910 case CP0_REGISTER_30:
8911 switch (sel) {
8912 case CP0_REG30__ERROREPC:
8913 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8914 register_name = "ErrorEPC";
8915 break;
8916 default:
8917 goto cp0_unimplemented;
8919 break;
8920 case CP0_REGISTER_31:
8921 switch (sel) {
8922 case CP0_REG31__DESAVE:
8923 /* EJTAG support */
8924 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8925 register_name = "DESAVE";
8926 break;
8927 case CP0_REG31__KSCRATCH1:
8928 case CP0_REG31__KSCRATCH2:
8929 case CP0_REG31__KSCRATCH3:
8930 case CP0_REG31__KSCRATCH4:
8931 case CP0_REG31__KSCRATCH5:
8932 case CP0_REG31__KSCRATCH6:
8933 CP0_CHECK(ctx->kscrexist & (1 << sel));
8934 tcg_gen_st_tl(arg, cpu_env,
8935 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8936 register_name = "KScratch";
8937 break;
8938 default:
8939 goto cp0_unimplemented;
8941 break;
8942 default:
8943 goto cp0_unimplemented;
8945 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
8947 /* For simplicity assume that all writes can cause interrupts. */
8948 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8950 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8951 * translated code to check for pending interrupts.
8953 gen_save_pc(ctx->base.pc_next + 4);
8954 ctx->base.is_jmp = DISAS_EXIT;
8956 return;
8958 cp0_unimplemented:
8959 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
8960 register_name, reg, sel);
8962 #endif /* TARGET_MIPS64 */
8964 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
8965 int u, int sel, int h)
8967 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8968 TCGv t0 = tcg_temp_local_new();
8970 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8971 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8972 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
8973 tcg_gen_movi_tl(t0, -1);
8974 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8975 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
8976 tcg_gen_movi_tl(t0, -1);
8977 } else if (u == 0) {
8978 switch (rt) {
8979 case 1:
8980 switch (sel) {
8981 case 1:
8982 gen_helper_mftc0_vpecontrol(t0, cpu_env);
8983 break;
8984 case 2:
8985 gen_helper_mftc0_vpeconf0(t0, cpu_env);
8986 break;
8987 default:
8988 goto die;
8989 break;
8991 break;
8992 case 2:
8993 switch (sel) {
8994 case 1:
8995 gen_helper_mftc0_tcstatus(t0, cpu_env);
8996 break;
8997 case 2:
8998 gen_helper_mftc0_tcbind(t0, cpu_env);
8999 break;
9000 case 3:
9001 gen_helper_mftc0_tcrestart(t0, cpu_env);
9002 break;
9003 case 4:
9004 gen_helper_mftc0_tchalt(t0, cpu_env);
9005 break;
9006 case 5:
9007 gen_helper_mftc0_tccontext(t0, cpu_env);
9008 break;
9009 case 6:
9010 gen_helper_mftc0_tcschedule(t0, cpu_env);
9011 break;
9012 case 7:
9013 gen_helper_mftc0_tcschefback(t0, cpu_env);
9014 break;
9015 default:
9016 gen_mfc0(ctx, t0, rt, sel);
9017 break;
9019 break;
9020 case 10:
9021 switch (sel) {
9022 case 0:
9023 gen_helper_mftc0_entryhi(t0, cpu_env);
9024 break;
9025 default:
9026 gen_mfc0(ctx, t0, rt, sel);
9027 break;
9029 break;
9030 case 12:
9031 switch (sel) {
9032 case 0:
9033 gen_helper_mftc0_status(t0, cpu_env);
9034 break;
9035 default:
9036 gen_mfc0(ctx, t0, rt, sel);
9037 break;
9039 break;
9040 case 13:
9041 switch (sel) {
9042 case 0:
9043 gen_helper_mftc0_cause(t0, cpu_env);
9044 break;
9045 default:
9046 goto die;
9047 break;
9049 break;
9050 case 14:
9051 switch (sel) {
9052 case 0:
9053 gen_helper_mftc0_epc(t0, cpu_env);
9054 break;
9055 default:
9056 goto die;
9057 break;
9059 break;
9060 case 15:
9061 switch (sel) {
9062 case 1:
9063 gen_helper_mftc0_ebase(t0, cpu_env);
9064 break;
9065 default:
9066 goto die;
9067 break;
9069 break;
9070 case 16:
9071 switch (sel) {
9072 case 0:
9073 case 1:
9074 case 2:
9075 case 3:
9076 case 4:
9077 case 5:
9078 case 6:
9079 case 7:
9080 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9081 break;
9082 default:
9083 goto die;
9084 break;
9086 break;
9087 case 23:
9088 switch (sel) {
9089 case 0:
9090 gen_helper_mftc0_debug(t0, cpu_env);
9091 break;
9092 default:
9093 gen_mfc0(ctx, t0, rt, sel);
9094 break;
9096 break;
9097 default:
9098 gen_mfc0(ctx, t0, rt, sel);
9100 } else {
9101 switch (sel) {
9102 /* GPR registers. */
9103 case 0:
9104 gen_helper_1e0i(mftgpr, t0, rt);
9105 break;
9106 /* Auxiliary CPU registers */
9107 case 1:
9108 switch (rt) {
9109 case 0:
9110 gen_helper_1e0i(mftlo, t0, 0);
9111 break;
9112 case 1:
9113 gen_helper_1e0i(mfthi, t0, 0);
9114 break;
9115 case 2:
9116 gen_helper_1e0i(mftacx, t0, 0);
9117 break;
9118 case 4:
9119 gen_helper_1e0i(mftlo, t0, 1);
9120 break;
9121 case 5:
9122 gen_helper_1e0i(mfthi, t0, 1);
9123 break;
9124 case 6:
9125 gen_helper_1e0i(mftacx, t0, 1);
9126 break;
9127 case 8:
9128 gen_helper_1e0i(mftlo, t0, 2);
9129 break;
9130 case 9:
9131 gen_helper_1e0i(mfthi, t0, 2);
9132 break;
9133 case 10:
9134 gen_helper_1e0i(mftacx, t0, 2);
9135 break;
9136 case 12:
9137 gen_helper_1e0i(mftlo, t0, 3);
9138 break;
9139 case 13:
9140 gen_helper_1e0i(mfthi, t0, 3);
9141 break;
9142 case 14:
9143 gen_helper_1e0i(mftacx, t0, 3);
9144 break;
9145 case 16:
9146 gen_helper_mftdsp(t0, cpu_env);
9147 break;
9148 default:
9149 goto die;
9151 break;
9152 /* Floating point (COP1). */
9153 case 2:
9154 /* XXX: For now we support only a single FPU context. */
9155 if (h == 0) {
9156 TCGv_i32 fp0 = tcg_temp_new_i32();
9158 gen_load_fpr32(ctx, fp0, rt);
9159 tcg_gen_ext_i32_tl(t0, fp0);
9160 tcg_temp_free_i32(fp0);
9161 } else {
9162 TCGv_i32 fp0 = tcg_temp_new_i32();
9164 gen_load_fpr32h(ctx, fp0, rt);
9165 tcg_gen_ext_i32_tl(t0, fp0);
9166 tcg_temp_free_i32(fp0);
9168 break;
9169 case 3:
9170 /* XXX: For now we support only a single FPU context. */
9171 gen_helper_1e0i(cfc1, t0, rt);
9172 break;
9173 /* COP2: Not implemented. */
9174 case 4:
9175 case 5:
9176 /* fall through */
9177 default:
9178 goto die;
9181 trace_mips_translate_tr("mftr", rt, u, sel, h);
9182 gen_store_gpr(t0, rd);
9183 tcg_temp_free(t0);
9184 return;
9186 die:
9187 tcg_temp_free(t0);
9188 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9189 gen_reserved_instruction(ctx);
9192 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9193 int u, int sel, int h)
9195 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9196 TCGv t0 = tcg_temp_local_new();
9198 gen_load_gpr(t0, rt);
9199 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9200 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9201 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9202 /* NOP */
9204 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9205 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9206 /* NOP */
9208 } else if (u == 0) {
9209 switch (rd) {
9210 case 1:
9211 switch (sel) {
9212 case 1:
9213 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9214 break;
9215 case 2:
9216 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9217 break;
9218 default:
9219 goto die;
9220 break;
9222 break;
9223 case 2:
9224 switch (sel) {
9225 case 1:
9226 gen_helper_mttc0_tcstatus(cpu_env, t0);
9227 break;
9228 case 2:
9229 gen_helper_mttc0_tcbind(cpu_env, t0);
9230 break;
9231 case 3:
9232 gen_helper_mttc0_tcrestart(cpu_env, t0);
9233 break;
9234 case 4:
9235 gen_helper_mttc0_tchalt(cpu_env, t0);
9236 break;
9237 case 5:
9238 gen_helper_mttc0_tccontext(cpu_env, t0);
9239 break;
9240 case 6:
9241 gen_helper_mttc0_tcschedule(cpu_env, t0);
9242 break;
9243 case 7:
9244 gen_helper_mttc0_tcschefback(cpu_env, t0);
9245 break;
9246 default:
9247 gen_mtc0(ctx, t0, rd, sel);
9248 break;
9250 break;
9251 case 10:
9252 switch (sel) {
9253 case 0:
9254 gen_helper_mttc0_entryhi(cpu_env, t0);
9255 break;
9256 default:
9257 gen_mtc0(ctx, t0, rd, sel);
9258 break;
9260 break;
9261 case 12:
9262 switch (sel) {
9263 case 0:
9264 gen_helper_mttc0_status(cpu_env, t0);
9265 break;
9266 default:
9267 gen_mtc0(ctx, t0, rd, sel);
9268 break;
9270 break;
9271 case 13:
9272 switch (sel) {
9273 case 0:
9274 gen_helper_mttc0_cause(cpu_env, t0);
9275 break;
9276 default:
9277 goto die;
9278 break;
9280 break;
9281 case 15:
9282 switch (sel) {
9283 case 1:
9284 gen_helper_mttc0_ebase(cpu_env, t0);
9285 break;
9286 default:
9287 goto die;
9288 break;
9290 break;
9291 case 23:
9292 switch (sel) {
9293 case 0:
9294 gen_helper_mttc0_debug(cpu_env, t0);
9295 break;
9296 default:
9297 gen_mtc0(ctx, t0, rd, sel);
9298 break;
9300 break;
9301 default:
9302 gen_mtc0(ctx, t0, rd, sel);
9304 } else {
9305 switch (sel) {
9306 /* GPR registers. */
9307 case 0:
9308 gen_helper_0e1i(mttgpr, t0, rd);
9309 break;
9310 /* Auxiliary CPU registers */
9311 case 1:
9312 switch (rd) {
9313 case 0:
9314 gen_helper_0e1i(mttlo, t0, 0);
9315 break;
9316 case 1:
9317 gen_helper_0e1i(mtthi, t0, 0);
9318 break;
9319 case 2:
9320 gen_helper_0e1i(mttacx, t0, 0);
9321 break;
9322 case 4:
9323 gen_helper_0e1i(mttlo, t0, 1);
9324 break;
9325 case 5:
9326 gen_helper_0e1i(mtthi, t0, 1);
9327 break;
9328 case 6:
9329 gen_helper_0e1i(mttacx, t0, 1);
9330 break;
9331 case 8:
9332 gen_helper_0e1i(mttlo, t0, 2);
9333 break;
9334 case 9:
9335 gen_helper_0e1i(mtthi, t0, 2);
9336 break;
9337 case 10:
9338 gen_helper_0e1i(mttacx, t0, 2);
9339 break;
9340 case 12:
9341 gen_helper_0e1i(mttlo, t0, 3);
9342 break;
9343 case 13:
9344 gen_helper_0e1i(mtthi, t0, 3);
9345 break;
9346 case 14:
9347 gen_helper_0e1i(mttacx, t0, 3);
9348 break;
9349 case 16:
9350 gen_helper_mttdsp(cpu_env, t0);
9351 break;
9352 default:
9353 goto die;
9355 break;
9356 /* Floating point (COP1). */
9357 case 2:
9358 /* XXX: For now we support only a single FPU context. */
9359 if (h == 0) {
9360 TCGv_i32 fp0 = tcg_temp_new_i32();
9362 tcg_gen_trunc_tl_i32(fp0, t0);
9363 gen_store_fpr32(ctx, fp0, rd);
9364 tcg_temp_free_i32(fp0);
9365 } else {
9366 TCGv_i32 fp0 = tcg_temp_new_i32();
9368 tcg_gen_trunc_tl_i32(fp0, t0);
9369 gen_store_fpr32h(ctx, fp0, rd);
9370 tcg_temp_free_i32(fp0);
9372 break;
9373 case 3:
9374 /* XXX: For now we support only a single FPU context. */
9376 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9378 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9379 tcg_temp_free_i32(fs_tmp);
9381 /* Stop translation as we may have changed hflags */
9382 ctx->base.is_jmp = DISAS_STOP;
9383 break;
9384 /* COP2: Not implemented. */
9385 case 4:
9386 case 5:
9387 /* fall through */
9388 default:
9389 goto die;
9392 trace_mips_translate_tr("mttr", rd, u, sel, h);
9393 tcg_temp_free(t0);
9394 return;
9396 die:
9397 tcg_temp_free(t0);
9398 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9399 gen_reserved_instruction(ctx);
9402 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
9403 int rt, int rd)
9405 const char *opn = "ldst";
9407 check_cp0_enabled(ctx);
9408 switch (opc) {
9409 case OPC_MFC0:
9410 if (rt == 0) {
9411 /* Treat as NOP. */
9412 return;
9414 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9415 opn = "mfc0";
9416 break;
9417 case OPC_MTC0:
9419 TCGv t0 = tcg_temp_new();
9421 gen_load_gpr(t0, rt);
9422 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9423 tcg_temp_free(t0);
9425 opn = "mtc0";
9426 break;
9427 #if defined(TARGET_MIPS64)
9428 case OPC_DMFC0:
9429 check_insn(ctx, ISA_MIPS3);
9430 if (rt == 0) {
9431 /* Treat as NOP. */
9432 return;
9434 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9435 opn = "dmfc0";
9436 break;
9437 case OPC_DMTC0:
9438 check_insn(ctx, ISA_MIPS3);
9440 TCGv t0 = tcg_temp_new();
9442 gen_load_gpr(t0, rt);
9443 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9444 tcg_temp_free(t0);
9446 opn = "dmtc0";
9447 break;
9448 #endif
9449 case OPC_MFHC0:
9450 check_mvh(ctx);
9451 if (rt == 0) {
9452 /* Treat as NOP. */
9453 return;
9455 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9456 opn = "mfhc0";
9457 break;
9458 case OPC_MTHC0:
9459 check_mvh(ctx);
9461 TCGv t0 = tcg_temp_new();
9462 gen_load_gpr(t0, rt);
9463 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9464 tcg_temp_free(t0);
9466 opn = "mthc0";
9467 break;
9468 case OPC_MFTR:
9469 check_cp0_enabled(ctx);
9470 if (rd == 0) {
9471 /* Treat as NOP. */
9472 return;
9474 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9475 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9476 opn = "mftr";
9477 break;
9478 case OPC_MTTR:
9479 check_cp0_enabled(ctx);
9480 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9481 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9482 opn = "mttr";
9483 break;
9484 case OPC_TLBWI:
9485 opn = "tlbwi";
9486 if (!env->tlb->helper_tlbwi) {
9487 goto die;
9489 gen_helper_tlbwi(cpu_env);
9490 break;
9491 case OPC_TLBINV:
9492 opn = "tlbinv";
9493 if (ctx->ie >= 2) {
9494 if (!env->tlb->helper_tlbinv) {
9495 goto die;
9497 gen_helper_tlbinv(cpu_env);
9498 } /* treat as nop if TLBINV not supported */
9499 break;
9500 case OPC_TLBINVF:
9501 opn = "tlbinvf";
9502 if (ctx->ie >= 2) {
9503 if (!env->tlb->helper_tlbinvf) {
9504 goto die;
9506 gen_helper_tlbinvf(cpu_env);
9507 } /* treat as nop if TLBINV not supported */
9508 break;
9509 case OPC_TLBWR:
9510 opn = "tlbwr";
9511 if (!env->tlb->helper_tlbwr) {
9512 goto die;
9514 gen_helper_tlbwr(cpu_env);
9515 break;
9516 case OPC_TLBP:
9517 opn = "tlbp";
9518 if (!env->tlb->helper_tlbp) {
9519 goto die;
9521 gen_helper_tlbp(cpu_env);
9522 break;
9523 case OPC_TLBR:
9524 opn = "tlbr";
9525 if (!env->tlb->helper_tlbr) {
9526 goto die;
9528 gen_helper_tlbr(cpu_env);
9529 break;
9530 case OPC_ERET: /* OPC_ERETNC */
9531 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9532 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9533 goto die;
9534 } else {
9535 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9536 if (ctx->opcode & (1 << bit_shift)) {
9537 /* OPC_ERETNC */
9538 opn = "eretnc";
9539 check_insn(ctx, ISA_MIPS_R5);
9540 gen_helper_eretnc(cpu_env);
9541 } else {
9542 /* OPC_ERET */
9543 opn = "eret";
9544 check_insn(ctx, ISA_MIPS2);
9545 gen_helper_eret(cpu_env);
9547 ctx->base.is_jmp = DISAS_EXIT;
9549 break;
9550 case OPC_DERET:
9551 opn = "deret";
9552 check_insn(ctx, ISA_MIPS_R1);
9553 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9554 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9555 goto die;
9557 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9558 MIPS_INVAL(opn);
9559 gen_reserved_instruction(ctx);
9560 } else {
9561 gen_helper_deret(cpu_env);
9562 ctx->base.is_jmp = DISAS_EXIT;
9564 break;
9565 case OPC_WAIT:
9566 opn = "wait";
9567 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
9568 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9569 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9570 goto die;
9572 /* If we get an exception, we want to restart at next instruction */
9573 ctx->base.pc_next += 4;
9574 save_cpu_state(ctx, 1);
9575 ctx->base.pc_next -= 4;
9576 gen_helper_wait(cpu_env);
9577 ctx->base.is_jmp = DISAS_NORETURN;
9578 break;
9579 default:
9580 die:
9581 MIPS_INVAL(opn);
9582 gen_reserved_instruction(ctx);
9583 return;
9585 (void)opn; /* avoid a compiler warning */
9587 #endif /* !CONFIG_USER_ONLY */
9589 /* CP1 Branches (before delay slot) */
9590 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9591 int32_t cc, int32_t offset)
9593 target_ulong btarget;
9594 TCGv_i32 t0 = tcg_temp_new_i32();
9596 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9597 gen_reserved_instruction(ctx);
9598 goto out;
9601 if (cc != 0) {
9602 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
9605 btarget = ctx->base.pc_next + 4 + offset;
9607 switch (op) {
9608 case OPC_BC1F:
9609 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9610 tcg_gen_not_i32(t0, t0);
9611 tcg_gen_andi_i32(t0, t0, 1);
9612 tcg_gen_extu_i32_tl(bcond, t0);
9613 goto not_likely;
9614 case OPC_BC1FL:
9615 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9616 tcg_gen_not_i32(t0, t0);
9617 tcg_gen_andi_i32(t0, t0, 1);
9618 tcg_gen_extu_i32_tl(bcond, t0);
9619 goto likely;
9620 case OPC_BC1T:
9621 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9622 tcg_gen_andi_i32(t0, t0, 1);
9623 tcg_gen_extu_i32_tl(bcond, t0);
9624 goto not_likely;
9625 case OPC_BC1TL:
9626 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9627 tcg_gen_andi_i32(t0, t0, 1);
9628 tcg_gen_extu_i32_tl(bcond, t0);
9629 likely:
9630 ctx->hflags |= MIPS_HFLAG_BL;
9631 break;
9632 case OPC_BC1FANY2:
9634 TCGv_i32 t1 = tcg_temp_new_i32();
9635 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9636 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9637 tcg_gen_nand_i32(t0, t0, t1);
9638 tcg_temp_free_i32(t1);
9639 tcg_gen_andi_i32(t0, t0, 1);
9640 tcg_gen_extu_i32_tl(bcond, t0);
9642 goto not_likely;
9643 case OPC_BC1TANY2:
9645 TCGv_i32 t1 = tcg_temp_new_i32();
9646 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9647 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9648 tcg_gen_or_i32(t0, t0, t1);
9649 tcg_temp_free_i32(t1);
9650 tcg_gen_andi_i32(t0, t0, 1);
9651 tcg_gen_extu_i32_tl(bcond, t0);
9653 goto not_likely;
9654 case OPC_BC1FANY4:
9656 TCGv_i32 t1 = tcg_temp_new_i32();
9657 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9658 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9659 tcg_gen_and_i32(t0, t0, t1);
9660 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
9661 tcg_gen_and_i32(t0, t0, t1);
9662 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
9663 tcg_gen_nand_i32(t0, t0, t1);
9664 tcg_temp_free_i32(t1);
9665 tcg_gen_andi_i32(t0, t0, 1);
9666 tcg_gen_extu_i32_tl(bcond, t0);
9668 goto not_likely;
9669 case OPC_BC1TANY4:
9671 TCGv_i32 t1 = tcg_temp_new_i32();
9672 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9673 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9674 tcg_gen_or_i32(t0, t0, t1);
9675 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
9676 tcg_gen_or_i32(t0, t0, t1);
9677 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
9678 tcg_gen_or_i32(t0, t0, t1);
9679 tcg_temp_free_i32(t1);
9680 tcg_gen_andi_i32(t0, t0, 1);
9681 tcg_gen_extu_i32_tl(bcond, t0);
9683 not_likely:
9684 ctx->hflags |= MIPS_HFLAG_BC;
9685 break;
9686 default:
9687 MIPS_INVAL("cp1 cond branch");
9688 gen_reserved_instruction(ctx);
9689 goto out;
9691 ctx->btarget = btarget;
9692 ctx->hflags |= MIPS_HFLAG_BDS32;
9693 out:
9694 tcg_temp_free_i32(t0);
9697 /* R6 CP1 Branches */
9698 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
9699 int32_t ft, int32_t offset,
9700 int delayslot_size)
9702 target_ulong btarget;
9703 TCGv_i64 t0 = tcg_temp_new_i64();
9705 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9706 #ifdef MIPS_DEBUG_DISAS
9707 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
9708 "\n", ctx->base.pc_next);
9709 #endif
9710 gen_reserved_instruction(ctx);
9711 goto out;
9714 gen_load_fpr64(ctx, t0, ft);
9715 tcg_gen_andi_i64(t0, t0, 1);
9717 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
9719 switch (op) {
9720 case OPC_BC1EQZ:
9721 tcg_gen_xori_i64(t0, t0, 1);
9722 ctx->hflags |= MIPS_HFLAG_BC;
9723 break;
9724 case OPC_BC1NEZ:
9725 /* t0 already set */
9726 ctx->hflags |= MIPS_HFLAG_BC;
9727 break;
9728 default:
9729 MIPS_INVAL("cp1 cond branch");
9730 gen_reserved_instruction(ctx);
9731 goto out;
9734 tcg_gen_trunc_i64_tl(bcond, t0);
9736 ctx->btarget = btarget;
9738 switch (delayslot_size) {
9739 case 2:
9740 ctx->hflags |= MIPS_HFLAG_BDS16;
9741 break;
9742 case 4:
9743 ctx->hflags |= MIPS_HFLAG_BDS32;
9744 break;
9747 out:
9748 tcg_temp_free_i64(t0);
9751 /* Coprocessor 1 (FPU) */
9753 #define FOP(func, fmt) (((fmt) << 21) | (func))
9755 enum fopcode {
9756 OPC_ADD_S = FOP(0, FMT_S),
9757 OPC_SUB_S = FOP(1, FMT_S),
9758 OPC_MUL_S = FOP(2, FMT_S),
9759 OPC_DIV_S = FOP(3, FMT_S),
9760 OPC_SQRT_S = FOP(4, FMT_S),
9761 OPC_ABS_S = FOP(5, FMT_S),
9762 OPC_MOV_S = FOP(6, FMT_S),
9763 OPC_NEG_S = FOP(7, FMT_S),
9764 OPC_ROUND_L_S = FOP(8, FMT_S),
9765 OPC_TRUNC_L_S = FOP(9, FMT_S),
9766 OPC_CEIL_L_S = FOP(10, FMT_S),
9767 OPC_FLOOR_L_S = FOP(11, FMT_S),
9768 OPC_ROUND_W_S = FOP(12, FMT_S),
9769 OPC_TRUNC_W_S = FOP(13, FMT_S),
9770 OPC_CEIL_W_S = FOP(14, FMT_S),
9771 OPC_FLOOR_W_S = FOP(15, FMT_S),
9772 OPC_SEL_S = FOP(16, FMT_S),
9773 OPC_MOVCF_S = FOP(17, FMT_S),
9774 OPC_MOVZ_S = FOP(18, FMT_S),
9775 OPC_MOVN_S = FOP(19, FMT_S),
9776 OPC_SELEQZ_S = FOP(20, FMT_S),
9777 OPC_RECIP_S = FOP(21, FMT_S),
9778 OPC_RSQRT_S = FOP(22, FMT_S),
9779 OPC_SELNEZ_S = FOP(23, FMT_S),
9780 OPC_MADDF_S = FOP(24, FMT_S),
9781 OPC_MSUBF_S = FOP(25, FMT_S),
9782 OPC_RINT_S = FOP(26, FMT_S),
9783 OPC_CLASS_S = FOP(27, FMT_S),
9784 OPC_MIN_S = FOP(28, FMT_S),
9785 OPC_RECIP2_S = FOP(28, FMT_S),
9786 OPC_MINA_S = FOP(29, FMT_S),
9787 OPC_RECIP1_S = FOP(29, FMT_S),
9788 OPC_MAX_S = FOP(30, FMT_S),
9789 OPC_RSQRT1_S = FOP(30, FMT_S),
9790 OPC_MAXA_S = FOP(31, FMT_S),
9791 OPC_RSQRT2_S = FOP(31, FMT_S),
9792 OPC_CVT_D_S = FOP(33, FMT_S),
9793 OPC_CVT_W_S = FOP(36, FMT_S),
9794 OPC_CVT_L_S = FOP(37, FMT_S),
9795 OPC_CVT_PS_S = FOP(38, FMT_S),
9796 OPC_CMP_F_S = FOP(48, FMT_S),
9797 OPC_CMP_UN_S = FOP(49, FMT_S),
9798 OPC_CMP_EQ_S = FOP(50, FMT_S),
9799 OPC_CMP_UEQ_S = FOP(51, FMT_S),
9800 OPC_CMP_OLT_S = FOP(52, FMT_S),
9801 OPC_CMP_ULT_S = FOP(53, FMT_S),
9802 OPC_CMP_OLE_S = FOP(54, FMT_S),
9803 OPC_CMP_ULE_S = FOP(55, FMT_S),
9804 OPC_CMP_SF_S = FOP(56, FMT_S),
9805 OPC_CMP_NGLE_S = FOP(57, FMT_S),
9806 OPC_CMP_SEQ_S = FOP(58, FMT_S),
9807 OPC_CMP_NGL_S = FOP(59, FMT_S),
9808 OPC_CMP_LT_S = FOP(60, FMT_S),
9809 OPC_CMP_NGE_S = FOP(61, FMT_S),
9810 OPC_CMP_LE_S = FOP(62, FMT_S),
9811 OPC_CMP_NGT_S = FOP(63, FMT_S),
9813 OPC_ADD_D = FOP(0, FMT_D),
9814 OPC_SUB_D = FOP(1, FMT_D),
9815 OPC_MUL_D = FOP(2, FMT_D),
9816 OPC_DIV_D = FOP(3, FMT_D),
9817 OPC_SQRT_D = FOP(4, FMT_D),
9818 OPC_ABS_D = FOP(5, FMT_D),
9819 OPC_MOV_D = FOP(6, FMT_D),
9820 OPC_NEG_D = FOP(7, FMT_D),
9821 OPC_ROUND_L_D = FOP(8, FMT_D),
9822 OPC_TRUNC_L_D = FOP(9, FMT_D),
9823 OPC_CEIL_L_D = FOP(10, FMT_D),
9824 OPC_FLOOR_L_D = FOP(11, FMT_D),
9825 OPC_ROUND_W_D = FOP(12, FMT_D),
9826 OPC_TRUNC_W_D = FOP(13, FMT_D),
9827 OPC_CEIL_W_D = FOP(14, FMT_D),
9828 OPC_FLOOR_W_D = FOP(15, FMT_D),
9829 OPC_SEL_D = FOP(16, FMT_D),
9830 OPC_MOVCF_D = FOP(17, FMT_D),
9831 OPC_MOVZ_D = FOP(18, FMT_D),
9832 OPC_MOVN_D = FOP(19, FMT_D),
9833 OPC_SELEQZ_D = FOP(20, FMT_D),
9834 OPC_RECIP_D = FOP(21, FMT_D),
9835 OPC_RSQRT_D = FOP(22, FMT_D),
9836 OPC_SELNEZ_D = FOP(23, FMT_D),
9837 OPC_MADDF_D = FOP(24, FMT_D),
9838 OPC_MSUBF_D = FOP(25, FMT_D),
9839 OPC_RINT_D = FOP(26, FMT_D),
9840 OPC_CLASS_D = FOP(27, FMT_D),
9841 OPC_MIN_D = FOP(28, FMT_D),
9842 OPC_RECIP2_D = FOP(28, FMT_D),
9843 OPC_MINA_D = FOP(29, FMT_D),
9844 OPC_RECIP1_D = FOP(29, FMT_D),
9845 OPC_MAX_D = FOP(30, FMT_D),
9846 OPC_RSQRT1_D = FOP(30, FMT_D),
9847 OPC_MAXA_D = FOP(31, FMT_D),
9848 OPC_RSQRT2_D = FOP(31, FMT_D),
9849 OPC_CVT_S_D = FOP(32, FMT_D),
9850 OPC_CVT_W_D = FOP(36, FMT_D),
9851 OPC_CVT_L_D = FOP(37, FMT_D),
9852 OPC_CMP_F_D = FOP(48, FMT_D),
9853 OPC_CMP_UN_D = FOP(49, FMT_D),
9854 OPC_CMP_EQ_D = FOP(50, FMT_D),
9855 OPC_CMP_UEQ_D = FOP(51, FMT_D),
9856 OPC_CMP_OLT_D = FOP(52, FMT_D),
9857 OPC_CMP_ULT_D = FOP(53, FMT_D),
9858 OPC_CMP_OLE_D = FOP(54, FMT_D),
9859 OPC_CMP_ULE_D = FOP(55, FMT_D),
9860 OPC_CMP_SF_D = FOP(56, FMT_D),
9861 OPC_CMP_NGLE_D = FOP(57, FMT_D),
9862 OPC_CMP_SEQ_D = FOP(58, FMT_D),
9863 OPC_CMP_NGL_D = FOP(59, FMT_D),
9864 OPC_CMP_LT_D = FOP(60, FMT_D),
9865 OPC_CMP_NGE_D = FOP(61, FMT_D),
9866 OPC_CMP_LE_D = FOP(62, FMT_D),
9867 OPC_CMP_NGT_D = FOP(63, FMT_D),
9869 OPC_CVT_S_W = FOP(32, FMT_W),
9870 OPC_CVT_D_W = FOP(33, FMT_W),
9871 OPC_CVT_S_L = FOP(32, FMT_L),
9872 OPC_CVT_D_L = FOP(33, FMT_L),
9873 OPC_CVT_PS_PW = FOP(38, FMT_W),
9875 OPC_ADD_PS = FOP(0, FMT_PS),
9876 OPC_SUB_PS = FOP(1, FMT_PS),
9877 OPC_MUL_PS = FOP(2, FMT_PS),
9878 OPC_DIV_PS = FOP(3, FMT_PS),
9879 OPC_ABS_PS = FOP(5, FMT_PS),
9880 OPC_MOV_PS = FOP(6, FMT_PS),
9881 OPC_NEG_PS = FOP(7, FMT_PS),
9882 OPC_MOVCF_PS = FOP(17, FMT_PS),
9883 OPC_MOVZ_PS = FOP(18, FMT_PS),
9884 OPC_MOVN_PS = FOP(19, FMT_PS),
9885 OPC_ADDR_PS = FOP(24, FMT_PS),
9886 OPC_MULR_PS = FOP(26, FMT_PS),
9887 OPC_RECIP2_PS = FOP(28, FMT_PS),
9888 OPC_RECIP1_PS = FOP(29, FMT_PS),
9889 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9890 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9892 OPC_CVT_S_PU = FOP(32, FMT_PS),
9893 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9894 OPC_CVT_S_PL = FOP(40, FMT_PS),
9895 OPC_PLL_PS = FOP(44, FMT_PS),
9896 OPC_PLU_PS = FOP(45, FMT_PS),
9897 OPC_PUL_PS = FOP(46, FMT_PS),
9898 OPC_PUU_PS = FOP(47, FMT_PS),
9899 OPC_CMP_F_PS = FOP(48, FMT_PS),
9900 OPC_CMP_UN_PS = FOP(49, FMT_PS),
9901 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
9902 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
9903 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
9904 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
9905 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
9906 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
9907 OPC_CMP_SF_PS = FOP(56, FMT_PS),
9908 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
9909 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
9910 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
9911 OPC_CMP_LT_PS = FOP(60, FMT_PS),
9912 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
9913 OPC_CMP_LE_PS = FOP(62, FMT_PS),
9914 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
9917 enum r6_f_cmp_op {
9918 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9919 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9920 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9921 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9922 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9923 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9924 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9925 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9926 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9927 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9928 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9929 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9930 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9931 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9932 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9933 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9934 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9935 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9936 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9937 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9938 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9939 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9941 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9942 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9943 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9944 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9945 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9946 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9947 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9948 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9949 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9950 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9951 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9952 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9953 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9954 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9955 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9956 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9957 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9958 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9959 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9960 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9961 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9962 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9965 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
9967 TCGv t0 = tcg_temp_new();
9969 switch (opc) {
9970 case OPC_MFC1:
9972 TCGv_i32 fp0 = tcg_temp_new_i32();
9974 gen_load_fpr32(ctx, fp0, fs);
9975 tcg_gen_ext_i32_tl(t0, fp0);
9976 tcg_temp_free_i32(fp0);
9978 gen_store_gpr(t0, rt);
9979 break;
9980 case OPC_MTC1:
9981 gen_load_gpr(t0, rt);
9983 TCGv_i32 fp0 = tcg_temp_new_i32();
9985 tcg_gen_trunc_tl_i32(fp0, t0);
9986 gen_store_fpr32(ctx, fp0, fs);
9987 tcg_temp_free_i32(fp0);
9989 break;
9990 case OPC_CFC1:
9991 gen_helper_1e0i(cfc1, t0, fs);
9992 gen_store_gpr(t0, rt);
9993 break;
9994 case OPC_CTC1:
9995 gen_load_gpr(t0, rt);
9996 save_cpu_state(ctx, 0);
9998 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10000 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10001 tcg_temp_free_i32(fs_tmp);
10003 /* Stop translation as we may have changed hflags */
10004 ctx->base.is_jmp = DISAS_STOP;
10005 break;
10006 #if defined(TARGET_MIPS64)
10007 case OPC_DMFC1:
10008 gen_load_fpr64(ctx, t0, fs);
10009 gen_store_gpr(t0, rt);
10010 break;
10011 case OPC_DMTC1:
10012 gen_load_gpr(t0, rt);
10013 gen_store_fpr64(ctx, t0, fs);
10014 break;
10015 #endif
10016 case OPC_MFHC1:
10018 TCGv_i32 fp0 = tcg_temp_new_i32();
10020 gen_load_fpr32h(ctx, fp0, fs);
10021 tcg_gen_ext_i32_tl(t0, fp0);
10022 tcg_temp_free_i32(fp0);
10024 gen_store_gpr(t0, rt);
10025 break;
10026 case OPC_MTHC1:
10027 gen_load_gpr(t0, rt);
10029 TCGv_i32 fp0 = tcg_temp_new_i32();
10031 tcg_gen_trunc_tl_i32(fp0, t0);
10032 gen_store_fpr32h(ctx, fp0, fs);
10033 tcg_temp_free_i32(fp0);
10035 break;
10036 default:
10037 MIPS_INVAL("cp1 move");
10038 gen_reserved_instruction(ctx);
10039 goto out;
10042 out:
10043 tcg_temp_free(t0);
10046 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
10048 TCGLabel *l1;
10049 TCGCond cond;
10050 TCGv_i32 t0;
10052 if (rd == 0) {
10053 /* Treat as NOP. */
10054 return;
10057 if (tf) {
10058 cond = TCG_COND_EQ;
10059 } else {
10060 cond = TCG_COND_NE;
10063 l1 = gen_new_label();
10064 t0 = tcg_temp_new_i32();
10065 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10066 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10067 tcg_temp_free_i32(t0);
10068 gen_load_gpr(cpu_gpr[rd], rs);
10069 gen_set_label(l1);
10072 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10073 int tf)
10075 int cond;
10076 TCGv_i32 t0 = tcg_temp_new_i32();
10077 TCGLabel *l1 = gen_new_label();
10079 if (tf) {
10080 cond = TCG_COND_EQ;
10081 } else {
10082 cond = TCG_COND_NE;
10085 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10086 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10087 gen_load_fpr32(ctx, t0, fs);
10088 gen_store_fpr32(ctx, t0, fd);
10089 gen_set_label(l1);
10090 tcg_temp_free_i32(t0);
10093 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
10094 int tf)
10096 int cond;
10097 TCGv_i32 t0 = tcg_temp_new_i32();
10098 TCGv_i64 fp0;
10099 TCGLabel *l1 = gen_new_label();
10101 if (tf) {
10102 cond = TCG_COND_EQ;
10103 } else {
10104 cond = TCG_COND_NE;
10107 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10108 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10109 tcg_temp_free_i32(t0);
10110 fp0 = tcg_temp_new_i64();
10111 gen_load_fpr64(ctx, fp0, fs);
10112 gen_store_fpr64(ctx, fp0, fd);
10113 tcg_temp_free_i64(fp0);
10114 gen_set_label(l1);
10117 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10118 int cc, int tf)
10120 int cond;
10121 TCGv_i32 t0 = tcg_temp_new_i32();
10122 TCGLabel *l1 = gen_new_label();
10123 TCGLabel *l2 = gen_new_label();
10125 if (tf) {
10126 cond = TCG_COND_EQ;
10127 } else {
10128 cond = TCG_COND_NE;
10131 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10132 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10133 gen_load_fpr32(ctx, t0, fs);
10134 gen_store_fpr32(ctx, t0, fd);
10135 gen_set_label(l1);
10137 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
10138 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10139 gen_load_fpr32h(ctx, t0, fs);
10140 gen_store_fpr32h(ctx, t0, fd);
10141 tcg_temp_free_i32(t0);
10142 gen_set_label(l2);
10145 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10146 int fs)
10148 TCGv_i32 t1 = tcg_const_i32(0);
10149 TCGv_i32 fp0 = tcg_temp_new_i32();
10150 TCGv_i32 fp1 = tcg_temp_new_i32();
10151 TCGv_i32 fp2 = tcg_temp_new_i32();
10152 gen_load_fpr32(ctx, fp0, fd);
10153 gen_load_fpr32(ctx, fp1, ft);
10154 gen_load_fpr32(ctx, fp2, fs);
10156 switch (op1) {
10157 case OPC_SEL_S:
10158 tcg_gen_andi_i32(fp0, fp0, 1);
10159 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10160 break;
10161 case OPC_SELEQZ_S:
10162 tcg_gen_andi_i32(fp1, fp1, 1);
10163 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10164 break;
10165 case OPC_SELNEZ_S:
10166 tcg_gen_andi_i32(fp1, fp1, 1);
10167 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10168 break;
10169 default:
10170 MIPS_INVAL("gen_sel_s");
10171 gen_reserved_instruction(ctx);
10172 break;
10175 gen_store_fpr32(ctx, fp0, fd);
10176 tcg_temp_free_i32(fp2);
10177 tcg_temp_free_i32(fp1);
10178 tcg_temp_free_i32(fp0);
10179 tcg_temp_free_i32(t1);
10182 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10183 int fs)
10185 TCGv_i64 t1 = tcg_const_i64(0);
10186 TCGv_i64 fp0 = tcg_temp_new_i64();
10187 TCGv_i64 fp1 = tcg_temp_new_i64();
10188 TCGv_i64 fp2 = tcg_temp_new_i64();
10189 gen_load_fpr64(ctx, fp0, fd);
10190 gen_load_fpr64(ctx, fp1, ft);
10191 gen_load_fpr64(ctx, fp2, fs);
10193 switch (op1) {
10194 case OPC_SEL_D:
10195 tcg_gen_andi_i64(fp0, fp0, 1);
10196 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10197 break;
10198 case OPC_SELEQZ_D:
10199 tcg_gen_andi_i64(fp1, fp1, 1);
10200 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10201 break;
10202 case OPC_SELNEZ_D:
10203 tcg_gen_andi_i64(fp1, fp1, 1);
10204 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10205 break;
10206 default:
10207 MIPS_INVAL("gen_sel_d");
10208 gen_reserved_instruction(ctx);
10209 break;
10212 gen_store_fpr64(ctx, fp0, fd);
10213 tcg_temp_free_i64(fp2);
10214 tcg_temp_free_i64(fp1);
10215 tcg_temp_free_i64(fp0);
10216 tcg_temp_free_i64(t1);
10219 static void gen_farith(DisasContext *ctx, enum fopcode op1,
10220 int ft, int fs, int fd, int cc)
10222 uint32_t func = ctx->opcode & 0x3f;
10223 switch (op1) {
10224 case OPC_ADD_S:
10226 TCGv_i32 fp0 = tcg_temp_new_i32();
10227 TCGv_i32 fp1 = tcg_temp_new_i32();
10229 gen_load_fpr32(ctx, fp0, fs);
10230 gen_load_fpr32(ctx, fp1, ft);
10231 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10232 tcg_temp_free_i32(fp1);
10233 gen_store_fpr32(ctx, fp0, fd);
10234 tcg_temp_free_i32(fp0);
10236 break;
10237 case OPC_SUB_S:
10239 TCGv_i32 fp0 = tcg_temp_new_i32();
10240 TCGv_i32 fp1 = tcg_temp_new_i32();
10242 gen_load_fpr32(ctx, fp0, fs);
10243 gen_load_fpr32(ctx, fp1, ft);
10244 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10245 tcg_temp_free_i32(fp1);
10246 gen_store_fpr32(ctx, fp0, fd);
10247 tcg_temp_free_i32(fp0);
10249 break;
10250 case OPC_MUL_S:
10252 TCGv_i32 fp0 = tcg_temp_new_i32();
10253 TCGv_i32 fp1 = tcg_temp_new_i32();
10255 gen_load_fpr32(ctx, fp0, fs);
10256 gen_load_fpr32(ctx, fp1, ft);
10257 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10258 tcg_temp_free_i32(fp1);
10259 gen_store_fpr32(ctx, fp0, fd);
10260 tcg_temp_free_i32(fp0);
10262 break;
10263 case OPC_DIV_S:
10265 TCGv_i32 fp0 = tcg_temp_new_i32();
10266 TCGv_i32 fp1 = tcg_temp_new_i32();
10268 gen_load_fpr32(ctx, fp0, fs);
10269 gen_load_fpr32(ctx, fp1, ft);
10270 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10271 tcg_temp_free_i32(fp1);
10272 gen_store_fpr32(ctx, fp0, fd);
10273 tcg_temp_free_i32(fp0);
10275 break;
10276 case OPC_SQRT_S:
10278 TCGv_i32 fp0 = tcg_temp_new_i32();
10280 gen_load_fpr32(ctx, fp0, fs);
10281 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10282 gen_store_fpr32(ctx, fp0, fd);
10283 tcg_temp_free_i32(fp0);
10285 break;
10286 case OPC_ABS_S:
10288 TCGv_i32 fp0 = tcg_temp_new_i32();
10290 gen_load_fpr32(ctx, fp0, fs);
10291 if (ctx->abs2008) {
10292 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10293 } else {
10294 gen_helper_float_abs_s(fp0, fp0);
10296 gen_store_fpr32(ctx, fp0, fd);
10297 tcg_temp_free_i32(fp0);
10299 break;
10300 case OPC_MOV_S:
10302 TCGv_i32 fp0 = tcg_temp_new_i32();
10304 gen_load_fpr32(ctx, fp0, fs);
10305 gen_store_fpr32(ctx, fp0, fd);
10306 tcg_temp_free_i32(fp0);
10308 break;
10309 case OPC_NEG_S:
10311 TCGv_i32 fp0 = tcg_temp_new_i32();
10313 gen_load_fpr32(ctx, fp0, fs);
10314 if (ctx->abs2008) {
10315 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10316 } else {
10317 gen_helper_float_chs_s(fp0, fp0);
10319 gen_store_fpr32(ctx, fp0, fd);
10320 tcg_temp_free_i32(fp0);
10322 break;
10323 case OPC_ROUND_L_S:
10324 check_cp1_64bitmode(ctx);
10326 TCGv_i32 fp32 = tcg_temp_new_i32();
10327 TCGv_i64 fp64 = tcg_temp_new_i64();
10329 gen_load_fpr32(ctx, fp32, fs);
10330 if (ctx->nan2008) {
10331 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10332 } else {
10333 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10335 tcg_temp_free_i32(fp32);
10336 gen_store_fpr64(ctx, fp64, fd);
10337 tcg_temp_free_i64(fp64);
10339 break;
10340 case OPC_TRUNC_L_S:
10341 check_cp1_64bitmode(ctx);
10343 TCGv_i32 fp32 = tcg_temp_new_i32();
10344 TCGv_i64 fp64 = tcg_temp_new_i64();
10346 gen_load_fpr32(ctx, fp32, fs);
10347 if (ctx->nan2008) {
10348 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10349 } else {
10350 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10352 tcg_temp_free_i32(fp32);
10353 gen_store_fpr64(ctx, fp64, fd);
10354 tcg_temp_free_i64(fp64);
10356 break;
10357 case OPC_CEIL_L_S:
10358 check_cp1_64bitmode(ctx);
10360 TCGv_i32 fp32 = tcg_temp_new_i32();
10361 TCGv_i64 fp64 = tcg_temp_new_i64();
10363 gen_load_fpr32(ctx, fp32, fs);
10364 if (ctx->nan2008) {
10365 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10366 } else {
10367 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10369 tcg_temp_free_i32(fp32);
10370 gen_store_fpr64(ctx, fp64, fd);
10371 tcg_temp_free_i64(fp64);
10373 break;
10374 case OPC_FLOOR_L_S:
10375 check_cp1_64bitmode(ctx);
10377 TCGv_i32 fp32 = tcg_temp_new_i32();
10378 TCGv_i64 fp64 = tcg_temp_new_i64();
10380 gen_load_fpr32(ctx, fp32, fs);
10381 if (ctx->nan2008) {
10382 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10383 } else {
10384 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10386 tcg_temp_free_i32(fp32);
10387 gen_store_fpr64(ctx, fp64, fd);
10388 tcg_temp_free_i64(fp64);
10390 break;
10391 case OPC_ROUND_W_S:
10393 TCGv_i32 fp0 = tcg_temp_new_i32();
10395 gen_load_fpr32(ctx, fp0, fs);
10396 if (ctx->nan2008) {
10397 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10398 } else {
10399 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10401 gen_store_fpr32(ctx, fp0, fd);
10402 tcg_temp_free_i32(fp0);
10404 break;
10405 case OPC_TRUNC_W_S:
10407 TCGv_i32 fp0 = tcg_temp_new_i32();
10409 gen_load_fpr32(ctx, fp0, fs);
10410 if (ctx->nan2008) {
10411 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10412 } else {
10413 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10415 gen_store_fpr32(ctx, fp0, fd);
10416 tcg_temp_free_i32(fp0);
10418 break;
10419 case OPC_CEIL_W_S:
10421 TCGv_i32 fp0 = tcg_temp_new_i32();
10423 gen_load_fpr32(ctx, fp0, fs);
10424 if (ctx->nan2008) {
10425 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10426 } else {
10427 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10429 gen_store_fpr32(ctx, fp0, fd);
10430 tcg_temp_free_i32(fp0);
10432 break;
10433 case OPC_FLOOR_W_S:
10435 TCGv_i32 fp0 = tcg_temp_new_i32();
10437 gen_load_fpr32(ctx, fp0, fs);
10438 if (ctx->nan2008) {
10439 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10440 } else {
10441 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10443 gen_store_fpr32(ctx, fp0, fd);
10444 tcg_temp_free_i32(fp0);
10446 break;
10447 case OPC_SEL_S:
10448 check_insn(ctx, ISA_MIPS_R6);
10449 gen_sel_s(ctx, op1, fd, ft, fs);
10450 break;
10451 case OPC_SELEQZ_S:
10452 check_insn(ctx, ISA_MIPS_R6);
10453 gen_sel_s(ctx, op1, fd, ft, fs);
10454 break;
10455 case OPC_SELNEZ_S:
10456 check_insn(ctx, ISA_MIPS_R6);
10457 gen_sel_s(ctx, op1, fd, ft, fs);
10458 break;
10459 case OPC_MOVCF_S:
10460 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10461 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10462 break;
10463 case OPC_MOVZ_S:
10464 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10466 TCGLabel *l1 = gen_new_label();
10467 TCGv_i32 fp0;
10469 if (ft != 0) {
10470 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10472 fp0 = tcg_temp_new_i32();
10473 gen_load_fpr32(ctx, fp0, fs);
10474 gen_store_fpr32(ctx, fp0, fd);
10475 tcg_temp_free_i32(fp0);
10476 gen_set_label(l1);
10478 break;
10479 case OPC_MOVN_S:
10480 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10482 TCGLabel *l1 = gen_new_label();
10483 TCGv_i32 fp0;
10485 if (ft != 0) {
10486 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10487 fp0 = tcg_temp_new_i32();
10488 gen_load_fpr32(ctx, fp0, fs);
10489 gen_store_fpr32(ctx, fp0, fd);
10490 tcg_temp_free_i32(fp0);
10491 gen_set_label(l1);
10494 break;
10495 case OPC_RECIP_S:
10497 TCGv_i32 fp0 = tcg_temp_new_i32();
10499 gen_load_fpr32(ctx, fp0, fs);
10500 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10501 gen_store_fpr32(ctx, fp0, fd);
10502 tcg_temp_free_i32(fp0);
10504 break;
10505 case OPC_RSQRT_S:
10507 TCGv_i32 fp0 = tcg_temp_new_i32();
10509 gen_load_fpr32(ctx, fp0, fs);
10510 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10511 gen_store_fpr32(ctx, fp0, fd);
10512 tcg_temp_free_i32(fp0);
10514 break;
10515 case OPC_MADDF_S:
10516 check_insn(ctx, ISA_MIPS_R6);
10518 TCGv_i32 fp0 = tcg_temp_new_i32();
10519 TCGv_i32 fp1 = tcg_temp_new_i32();
10520 TCGv_i32 fp2 = tcg_temp_new_i32();
10521 gen_load_fpr32(ctx, fp0, fs);
10522 gen_load_fpr32(ctx, fp1, ft);
10523 gen_load_fpr32(ctx, fp2, fd);
10524 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10525 gen_store_fpr32(ctx, fp2, fd);
10526 tcg_temp_free_i32(fp2);
10527 tcg_temp_free_i32(fp1);
10528 tcg_temp_free_i32(fp0);
10530 break;
10531 case OPC_MSUBF_S:
10532 check_insn(ctx, ISA_MIPS_R6);
10534 TCGv_i32 fp0 = tcg_temp_new_i32();
10535 TCGv_i32 fp1 = tcg_temp_new_i32();
10536 TCGv_i32 fp2 = tcg_temp_new_i32();
10537 gen_load_fpr32(ctx, fp0, fs);
10538 gen_load_fpr32(ctx, fp1, ft);
10539 gen_load_fpr32(ctx, fp2, fd);
10540 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10541 gen_store_fpr32(ctx, fp2, fd);
10542 tcg_temp_free_i32(fp2);
10543 tcg_temp_free_i32(fp1);
10544 tcg_temp_free_i32(fp0);
10546 break;
10547 case OPC_RINT_S:
10548 check_insn(ctx, ISA_MIPS_R6);
10550 TCGv_i32 fp0 = tcg_temp_new_i32();
10551 gen_load_fpr32(ctx, fp0, fs);
10552 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10553 gen_store_fpr32(ctx, fp0, fd);
10554 tcg_temp_free_i32(fp0);
10556 break;
10557 case OPC_CLASS_S:
10558 check_insn(ctx, ISA_MIPS_R6);
10560 TCGv_i32 fp0 = tcg_temp_new_i32();
10561 gen_load_fpr32(ctx, fp0, fs);
10562 gen_helper_float_class_s(fp0, cpu_env, fp0);
10563 gen_store_fpr32(ctx, fp0, fd);
10564 tcg_temp_free_i32(fp0);
10566 break;
10567 case OPC_MIN_S: /* OPC_RECIP2_S */
10568 if (ctx->insn_flags & ISA_MIPS_R6) {
10569 /* OPC_MIN_S */
10570 TCGv_i32 fp0 = tcg_temp_new_i32();
10571 TCGv_i32 fp1 = tcg_temp_new_i32();
10572 TCGv_i32 fp2 = tcg_temp_new_i32();
10573 gen_load_fpr32(ctx, fp0, fs);
10574 gen_load_fpr32(ctx, fp1, ft);
10575 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10576 gen_store_fpr32(ctx, fp2, fd);
10577 tcg_temp_free_i32(fp2);
10578 tcg_temp_free_i32(fp1);
10579 tcg_temp_free_i32(fp0);
10580 } else {
10581 /* OPC_RECIP2_S */
10582 check_cp1_64bitmode(ctx);
10584 TCGv_i32 fp0 = tcg_temp_new_i32();
10585 TCGv_i32 fp1 = tcg_temp_new_i32();
10587 gen_load_fpr32(ctx, fp0, fs);
10588 gen_load_fpr32(ctx, fp1, ft);
10589 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10590 tcg_temp_free_i32(fp1);
10591 gen_store_fpr32(ctx, fp0, fd);
10592 tcg_temp_free_i32(fp0);
10595 break;
10596 case OPC_MINA_S: /* OPC_RECIP1_S */
10597 if (ctx->insn_flags & ISA_MIPS_R6) {
10598 /* OPC_MINA_S */
10599 TCGv_i32 fp0 = tcg_temp_new_i32();
10600 TCGv_i32 fp1 = tcg_temp_new_i32();
10601 TCGv_i32 fp2 = tcg_temp_new_i32();
10602 gen_load_fpr32(ctx, fp0, fs);
10603 gen_load_fpr32(ctx, fp1, ft);
10604 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10605 gen_store_fpr32(ctx, fp2, fd);
10606 tcg_temp_free_i32(fp2);
10607 tcg_temp_free_i32(fp1);
10608 tcg_temp_free_i32(fp0);
10609 } else {
10610 /* OPC_RECIP1_S */
10611 check_cp1_64bitmode(ctx);
10613 TCGv_i32 fp0 = tcg_temp_new_i32();
10615 gen_load_fpr32(ctx, fp0, fs);
10616 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10617 gen_store_fpr32(ctx, fp0, fd);
10618 tcg_temp_free_i32(fp0);
10621 break;
10622 case OPC_MAX_S: /* OPC_RSQRT1_S */
10623 if (ctx->insn_flags & ISA_MIPS_R6) {
10624 /* OPC_MAX_S */
10625 TCGv_i32 fp0 = tcg_temp_new_i32();
10626 TCGv_i32 fp1 = tcg_temp_new_i32();
10627 gen_load_fpr32(ctx, fp0, fs);
10628 gen_load_fpr32(ctx, fp1, ft);
10629 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10630 gen_store_fpr32(ctx, fp1, fd);
10631 tcg_temp_free_i32(fp1);
10632 tcg_temp_free_i32(fp0);
10633 } else {
10634 /* OPC_RSQRT1_S */
10635 check_cp1_64bitmode(ctx);
10637 TCGv_i32 fp0 = tcg_temp_new_i32();
10639 gen_load_fpr32(ctx, fp0, fs);
10640 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
10641 gen_store_fpr32(ctx, fp0, fd);
10642 tcg_temp_free_i32(fp0);
10645 break;
10646 case OPC_MAXA_S: /* OPC_RSQRT2_S */
10647 if (ctx->insn_flags & ISA_MIPS_R6) {
10648 /* OPC_MAXA_S */
10649 TCGv_i32 fp0 = tcg_temp_new_i32();
10650 TCGv_i32 fp1 = tcg_temp_new_i32();
10651 gen_load_fpr32(ctx, fp0, fs);
10652 gen_load_fpr32(ctx, fp1, ft);
10653 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
10654 gen_store_fpr32(ctx, fp1, fd);
10655 tcg_temp_free_i32(fp1);
10656 tcg_temp_free_i32(fp0);
10657 } else {
10658 /* OPC_RSQRT2_S */
10659 check_cp1_64bitmode(ctx);
10661 TCGv_i32 fp0 = tcg_temp_new_i32();
10662 TCGv_i32 fp1 = tcg_temp_new_i32();
10664 gen_load_fpr32(ctx, fp0, fs);
10665 gen_load_fpr32(ctx, fp1, ft);
10666 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10667 tcg_temp_free_i32(fp1);
10668 gen_store_fpr32(ctx, fp0, fd);
10669 tcg_temp_free_i32(fp0);
10672 break;
10673 case OPC_CVT_D_S:
10674 check_cp1_registers(ctx, fd);
10676 TCGv_i32 fp32 = tcg_temp_new_i32();
10677 TCGv_i64 fp64 = tcg_temp_new_i64();
10679 gen_load_fpr32(ctx, fp32, fs);
10680 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
10681 tcg_temp_free_i32(fp32);
10682 gen_store_fpr64(ctx, fp64, fd);
10683 tcg_temp_free_i64(fp64);
10685 break;
10686 case OPC_CVT_W_S:
10688 TCGv_i32 fp0 = tcg_temp_new_i32();
10690 gen_load_fpr32(ctx, fp0, fs);
10691 if (ctx->nan2008) {
10692 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
10693 } else {
10694 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
10696 gen_store_fpr32(ctx, fp0, fd);
10697 tcg_temp_free_i32(fp0);
10699 break;
10700 case OPC_CVT_L_S:
10701 check_cp1_64bitmode(ctx);
10703 TCGv_i32 fp32 = tcg_temp_new_i32();
10704 TCGv_i64 fp64 = tcg_temp_new_i64();
10706 gen_load_fpr32(ctx, fp32, fs);
10707 if (ctx->nan2008) {
10708 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
10709 } else {
10710 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
10712 tcg_temp_free_i32(fp32);
10713 gen_store_fpr64(ctx, fp64, fd);
10714 tcg_temp_free_i64(fp64);
10716 break;
10717 case OPC_CVT_PS_S:
10718 check_ps(ctx);
10720 TCGv_i64 fp64 = tcg_temp_new_i64();
10721 TCGv_i32 fp32_0 = tcg_temp_new_i32();
10722 TCGv_i32 fp32_1 = tcg_temp_new_i32();
10724 gen_load_fpr32(ctx, fp32_0, fs);
10725 gen_load_fpr32(ctx, fp32_1, ft);
10726 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
10727 tcg_temp_free_i32(fp32_1);
10728 tcg_temp_free_i32(fp32_0);
10729 gen_store_fpr64(ctx, fp64, fd);
10730 tcg_temp_free_i64(fp64);
10732 break;
10733 case OPC_CMP_F_S:
10734 case OPC_CMP_UN_S:
10735 case OPC_CMP_EQ_S:
10736 case OPC_CMP_UEQ_S:
10737 case OPC_CMP_OLT_S:
10738 case OPC_CMP_ULT_S:
10739 case OPC_CMP_OLE_S:
10740 case OPC_CMP_ULE_S:
10741 case OPC_CMP_SF_S:
10742 case OPC_CMP_NGLE_S:
10743 case OPC_CMP_SEQ_S:
10744 case OPC_CMP_NGL_S:
10745 case OPC_CMP_LT_S:
10746 case OPC_CMP_NGE_S:
10747 case OPC_CMP_LE_S:
10748 case OPC_CMP_NGT_S:
10749 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10750 if (ctx->opcode & (1 << 6)) {
10751 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
10752 } else {
10753 gen_cmp_s(ctx, func - 48, ft, fs, cc);
10755 break;
10756 case OPC_ADD_D:
10757 check_cp1_registers(ctx, fs | ft | fd);
10759 TCGv_i64 fp0 = tcg_temp_new_i64();
10760 TCGv_i64 fp1 = tcg_temp_new_i64();
10762 gen_load_fpr64(ctx, fp0, fs);
10763 gen_load_fpr64(ctx, fp1, ft);
10764 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
10765 tcg_temp_free_i64(fp1);
10766 gen_store_fpr64(ctx, fp0, fd);
10767 tcg_temp_free_i64(fp0);
10769 break;
10770 case OPC_SUB_D:
10771 check_cp1_registers(ctx, fs | ft | fd);
10773 TCGv_i64 fp0 = tcg_temp_new_i64();
10774 TCGv_i64 fp1 = tcg_temp_new_i64();
10776 gen_load_fpr64(ctx, fp0, fs);
10777 gen_load_fpr64(ctx, fp1, ft);
10778 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
10779 tcg_temp_free_i64(fp1);
10780 gen_store_fpr64(ctx, fp0, fd);
10781 tcg_temp_free_i64(fp0);
10783 break;
10784 case OPC_MUL_D:
10785 check_cp1_registers(ctx, fs | ft | fd);
10787 TCGv_i64 fp0 = tcg_temp_new_i64();
10788 TCGv_i64 fp1 = tcg_temp_new_i64();
10790 gen_load_fpr64(ctx, fp0, fs);
10791 gen_load_fpr64(ctx, fp1, ft);
10792 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
10793 tcg_temp_free_i64(fp1);
10794 gen_store_fpr64(ctx, fp0, fd);
10795 tcg_temp_free_i64(fp0);
10797 break;
10798 case OPC_DIV_D:
10799 check_cp1_registers(ctx, fs | ft | fd);
10801 TCGv_i64 fp0 = tcg_temp_new_i64();
10802 TCGv_i64 fp1 = tcg_temp_new_i64();
10804 gen_load_fpr64(ctx, fp0, fs);
10805 gen_load_fpr64(ctx, fp1, ft);
10806 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
10807 tcg_temp_free_i64(fp1);
10808 gen_store_fpr64(ctx, fp0, fd);
10809 tcg_temp_free_i64(fp0);
10811 break;
10812 case OPC_SQRT_D:
10813 check_cp1_registers(ctx, fs | fd);
10815 TCGv_i64 fp0 = tcg_temp_new_i64();
10817 gen_load_fpr64(ctx, fp0, fs);
10818 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
10819 gen_store_fpr64(ctx, fp0, fd);
10820 tcg_temp_free_i64(fp0);
10822 break;
10823 case OPC_ABS_D:
10824 check_cp1_registers(ctx, fs | fd);
10826 TCGv_i64 fp0 = tcg_temp_new_i64();
10828 gen_load_fpr64(ctx, fp0, fs);
10829 if (ctx->abs2008) {
10830 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
10831 } else {
10832 gen_helper_float_abs_d(fp0, fp0);
10834 gen_store_fpr64(ctx, fp0, fd);
10835 tcg_temp_free_i64(fp0);
10837 break;
10838 case OPC_MOV_D:
10839 check_cp1_registers(ctx, fs | fd);
10841 TCGv_i64 fp0 = tcg_temp_new_i64();
10843 gen_load_fpr64(ctx, fp0, fs);
10844 gen_store_fpr64(ctx, fp0, fd);
10845 tcg_temp_free_i64(fp0);
10847 break;
10848 case OPC_NEG_D:
10849 check_cp1_registers(ctx, fs | fd);
10851 TCGv_i64 fp0 = tcg_temp_new_i64();
10853 gen_load_fpr64(ctx, fp0, fs);
10854 if (ctx->abs2008) {
10855 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10856 } else {
10857 gen_helper_float_chs_d(fp0, fp0);
10859 gen_store_fpr64(ctx, fp0, fd);
10860 tcg_temp_free_i64(fp0);
10862 break;
10863 case OPC_ROUND_L_D:
10864 check_cp1_64bitmode(ctx);
10866 TCGv_i64 fp0 = tcg_temp_new_i64();
10868 gen_load_fpr64(ctx, fp0, fs);
10869 if (ctx->nan2008) {
10870 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
10871 } else {
10872 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
10874 gen_store_fpr64(ctx, fp0, fd);
10875 tcg_temp_free_i64(fp0);
10877 break;
10878 case OPC_TRUNC_L_D:
10879 check_cp1_64bitmode(ctx);
10881 TCGv_i64 fp0 = tcg_temp_new_i64();
10883 gen_load_fpr64(ctx, fp0, fs);
10884 if (ctx->nan2008) {
10885 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10886 } else {
10887 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10889 gen_store_fpr64(ctx, fp0, fd);
10890 tcg_temp_free_i64(fp0);
10892 break;
10893 case OPC_CEIL_L_D:
10894 check_cp1_64bitmode(ctx);
10896 TCGv_i64 fp0 = tcg_temp_new_i64();
10898 gen_load_fpr64(ctx, fp0, fs);
10899 if (ctx->nan2008) {
10900 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10901 } else {
10902 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10904 gen_store_fpr64(ctx, fp0, fd);
10905 tcg_temp_free_i64(fp0);
10907 break;
10908 case OPC_FLOOR_L_D:
10909 check_cp1_64bitmode(ctx);
10911 TCGv_i64 fp0 = tcg_temp_new_i64();
10913 gen_load_fpr64(ctx, fp0, fs);
10914 if (ctx->nan2008) {
10915 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10916 } else {
10917 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10919 gen_store_fpr64(ctx, fp0, fd);
10920 tcg_temp_free_i64(fp0);
10922 break;
10923 case OPC_ROUND_W_D:
10924 check_cp1_registers(ctx, fs);
10926 TCGv_i32 fp32 = tcg_temp_new_i32();
10927 TCGv_i64 fp64 = tcg_temp_new_i64();
10929 gen_load_fpr64(ctx, fp64, fs);
10930 if (ctx->nan2008) {
10931 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10932 } else {
10933 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10935 tcg_temp_free_i64(fp64);
10936 gen_store_fpr32(ctx, fp32, fd);
10937 tcg_temp_free_i32(fp32);
10939 break;
10940 case OPC_TRUNC_W_D:
10941 check_cp1_registers(ctx, fs);
10943 TCGv_i32 fp32 = tcg_temp_new_i32();
10944 TCGv_i64 fp64 = tcg_temp_new_i64();
10946 gen_load_fpr64(ctx, fp64, fs);
10947 if (ctx->nan2008) {
10948 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
10949 } else {
10950 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
10952 tcg_temp_free_i64(fp64);
10953 gen_store_fpr32(ctx, fp32, fd);
10954 tcg_temp_free_i32(fp32);
10956 break;
10957 case OPC_CEIL_W_D:
10958 check_cp1_registers(ctx, fs);
10960 TCGv_i32 fp32 = tcg_temp_new_i32();
10961 TCGv_i64 fp64 = tcg_temp_new_i64();
10963 gen_load_fpr64(ctx, fp64, fs);
10964 if (ctx->nan2008) {
10965 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
10966 } else {
10967 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
10969 tcg_temp_free_i64(fp64);
10970 gen_store_fpr32(ctx, fp32, fd);
10971 tcg_temp_free_i32(fp32);
10973 break;
10974 case OPC_FLOOR_W_D:
10975 check_cp1_registers(ctx, fs);
10977 TCGv_i32 fp32 = tcg_temp_new_i32();
10978 TCGv_i64 fp64 = tcg_temp_new_i64();
10980 gen_load_fpr64(ctx, fp64, fs);
10981 if (ctx->nan2008) {
10982 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
10983 } else {
10984 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
10986 tcg_temp_free_i64(fp64);
10987 gen_store_fpr32(ctx, fp32, fd);
10988 tcg_temp_free_i32(fp32);
10990 break;
10991 case OPC_SEL_D:
10992 check_insn(ctx, ISA_MIPS_R6);
10993 gen_sel_d(ctx, op1, fd, ft, fs);
10994 break;
10995 case OPC_SELEQZ_D:
10996 check_insn(ctx, ISA_MIPS_R6);
10997 gen_sel_d(ctx, op1, fd, ft, fs);
10998 break;
10999 case OPC_SELNEZ_D:
11000 check_insn(ctx, ISA_MIPS_R6);
11001 gen_sel_d(ctx, op1, fd, ft, fs);
11002 break;
11003 case OPC_MOVCF_D:
11004 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11005 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11006 break;
11007 case OPC_MOVZ_D:
11008 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11010 TCGLabel *l1 = gen_new_label();
11011 TCGv_i64 fp0;
11013 if (ft != 0) {
11014 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11016 fp0 = tcg_temp_new_i64();
11017 gen_load_fpr64(ctx, fp0, fs);
11018 gen_store_fpr64(ctx, fp0, fd);
11019 tcg_temp_free_i64(fp0);
11020 gen_set_label(l1);
11022 break;
11023 case OPC_MOVN_D:
11024 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11026 TCGLabel *l1 = gen_new_label();
11027 TCGv_i64 fp0;
11029 if (ft != 0) {
11030 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11031 fp0 = tcg_temp_new_i64();
11032 gen_load_fpr64(ctx, fp0, fs);
11033 gen_store_fpr64(ctx, fp0, fd);
11034 tcg_temp_free_i64(fp0);
11035 gen_set_label(l1);
11038 break;
11039 case OPC_RECIP_D:
11040 check_cp1_registers(ctx, fs | fd);
11042 TCGv_i64 fp0 = tcg_temp_new_i64();
11044 gen_load_fpr64(ctx, fp0, fs);
11045 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11046 gen_store_fpr64(ctx, fp0, fd);
11047 tcg_temp_free_i64(fp0);
11049 break;
11050 case OPC_RSQRT_D:
11051 check_cp1_registers(ctx, fs | fd);
11053 TCGv_i64 fp0 = tcg_temp_new_i64();
11055 gen_load_fpr64(ctx, fp0, fs);
11056 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11057 gen_store_fpr64(ctx, fp0, fd);
11058 tcg_temp_free_i64(fp0);
11060 break;
11061 case OPC_MADDF_D:
11062 check_insn(ctx, ISA_MIPS_R6);
11064 TCGv_i64 fp0 = tcg_temp_new_i64();
11065 TCGv_i64 fp1 = tcg_temp_new_i64();
11066 TCGv_i64 fp2 = tcg_temp_new_i64();
11067 gen_load_fpr64(ctx, fp0, fs);
11068 gen_load_fpr64(ctx, fp1, ft);
11069 gen_load_fpr64(ctx, fp2, fd);
11070 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11071 gen_store_fpr64(ctx, fp2, fd);
11072 tcg_temp_free_i64(fp2);
11073 tcg_temp_free_i64(fp1);
11074 tcg_temp_free_i64(fp0);
11076 break;
11077 case OPC_MSUBF_D:
11078 check_insn(ctx, ISA_MIPS_R6);
11080 TCGv_i64 fp0 = tcg_temp_new_i64();
11081 TCGv_i64 fp1 = tcg_temp_new_i64();
11082 TCGv_i64 fp2 = tcg_temp_new_i64();
11083 gen_load_fpr64(ctx, fp0, fs);
11084 gen_load_fpr64(ctx, fp1, ft);
11085 gen_load_fpr64(ctx, fp2, fd);
11086 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11087 gen_store_fpr64(ctx, fp2, fd);
11088 tcg_temp_free_i64(fp2);
11089 tcg_temp_free_i64(fp1);
11090 tcg_temp_free_i64(fp0);
11092 break;
11093 case OPC_RINT_D:
11094 check_insn(ctx, ISA_MIPS_R6);
11096 TCGv_i64 fp0 = tcg_temp_new_i64();
11097 gen_load_fpr64(ctx, fp0, fs);
11098 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11099 gen_store_fpr64(ctx, fp0, fd);
11100 tcg_temp_free_i64(fp0);
11102 break;
11103 case OPC_CLASS_D:
11104 check_insn(ctx, ISA_MIPS_R6);
11106 TCGv_i64 fp0 = tcg_temp_new_i64();
11107 gen_load_fpr64(ctx, fp0, fs);
11108 gen_helper_float_class_d(fp0, cpu_env, fp0);
11109 gen_store_fpr64(ctx, fp0, fd);
11110 tcg_temp_free_i64(fp0);
11112 break;
11113 case OPC_MIN_D: /* OPC_RECIP2_D */
11114 if (ctx->insn_flags & ISA_MIPS_R6) {
11115 /* OPC_MIN_D */
11116 TCGv_i64 fp0 = tcg_temp_new_i64();
11117 TCGv_i64 fp1 = tcg_temp_new_i64();
11118 gen_load_fpr64(ctx, fp0, fs);
11119 gen_load_fpr64(ctx, fp1, ft);
11120 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11121 gen_store_fpr64(ctx, fp1, fd);
11122 tcg_temp_free_i64(fp1);
11123 tcg_temp_free_i64(fp0);
11124 } else {
11125 /* OPC_RECIP2_D */
11126 check_cp1_64bitmode(ctx);
11128 TCGv_i64 fp0 = tcg_temp_new_i64();
11129 TCGv_i64 fp1 = tcg_temp_new_i64();
11131 gen_load_fpr64(ctx, fp0, fs);
11132 gen_load_fpr64(ctx, fp1, ft);
11133 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11134 tcg_temp_free_i64(fp1);
11135 gen_store_fpr64(ctx, fp0, fd);
11136 tcg_temp_free_i64(fp0);
11139 break;
11140 case OPC_MINA_D: /* OPC_RECIP1_D */
11141 if (ctx->insn_flags & ISA_MIPS_R6) {
11142 /* OPC_MINA_D */
11143 TCGv_i64 fp0 = tcg_temp_new_i64();
11144 TCGv_i64 fp1 = tcg_temp_new_i64();
11145 gen_load_fpr64(ctx, fp0, fs);
11146 gen_load_fpr64(ctx, fp1, ft);
11147 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11148 gen_store_fpr64(ctx, fp1, fd);
11149 tcg_temp_free_i64(fp1);
11150 tcg_temp_free_i64(fp0);
11151 } else {
11152 /* OPC_RECIP1_D */
11153 check_cp1_64bitmode(ctx);
11155 TCGv_i64 fp0 = tcg_temp_new_i64();
11157 gen_load_fpr64(ctx, fp0, fs);
11158 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11159 gen_store_fpr64(ctx, fp0, fd);
11160 tcg_temp_free_i64(fp0);
11163 break;
11164 case OPC_MAX_D: /* OPC_RSQRT1_D */
11165 if (ctx->insn_flags & ISA_MIPS_R6) {
11166 /* OPC_MAX_D */
11167 TCGv_i64 fp0 = tcg_temp_new_i64();
11168 TCGv_i64 fp1 = tcg_temp_new_i64();
11169 gen_load_fpr64(ctx, fp0, fs);
11170 gen_load_fpr64(ctx, fp1, ft);
11171 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11172 gen_store_fpr64(ctx, fp1, fd);
11173 tcg_temp_free_i64(fp1);
11174 tcg_temp_free_i64(fp0);
11175 } else {
11176 /* OPC_RSQRT1_D */
11177 check_cp1_64bitmode(ctx);
11179 TCGv_i64 fp0 = tcg_temp_new_i64();
11181 gen_load_fpr64(ctx, fp0, fs);
11182 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11183 gen_store_fpr64(ctx, fp0, fd);
11184 tcg_temp_free_i64(fp0);
11187 break;
11188 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11189 if (ctx->insn_flags & ISA_MIPS_R6) {
11190 /* OPC_MAXA_D */
11191 TCGv_i64 fp0 = tcg_temp_new_i64();
11192 TCGv_i64 fp1 = tcg_temp_new_i64();
11193 gen_load_fpr64(ctx, fp0, fs);
11194 gen_load_fpr64(ctx, fp1, ft);
11195 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11196 gen_store_fpr64(ctx, fp1, fd);
11197 tcg_temp_free_i64(fp1);
11198 tcg_temp_free_i64(fp0);
11199 } else {
11200 /* OPC_RSQRT2_D */
11201 check_cp1_64bitmode(ctx);
11203 TCGv_i64 fp0 = tcg_temp_new_i64();
11204 TCGv_i64 fp1 = tcg_temp_new_i64();
11206 gen_load_fpr64(ctx, fp0, fs);
11207 gen_load_fpr64(ctx, fp1, ft);
11208 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11209 tcg_temp_free_i64(fp1);
11210 gen_store_fpr64(ctx, fp0, fd);
11211 tcg_temp_free_i64(fp0);
11214 break;
11215 case OPC_CMP_F_D:
11216 case OPC_CMP_UN_D:
11217 case OPC_CMP_EQ_D:
11218 case OPC_CMP_UEQ_D:
11219 case OPC_CMP_OLT_D:
11220 case OPC_CMP_ULT_D:
11221 case OPC_CMP_OLE_D:
11222 case OPC_CMP_ULE_D:
11223 case OPC_CMP_SF_D:
11224 case OPC_CMP_NGLE_D:
11225 case OPC_CMP_SEQ_D:
11226 case OPC_CMP_NGL_D:
11227 case OPC_CMP_LT_D:
11228 case OPC_CMP_NGE_D:
11229 case OPC_CMP_LE_D:
11230 case OPC_CMP_NGT_D:
11231 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11232 if (ctx->opcode & (1 << 6)) {
11233 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
11234 } else {
11235 gen_cmp_d(ctx, func - 48, ft, fs, cc);
11237 break;
11238 case OPC_CVT_S_D:
11239 check_cp1_registers(ctx, fs);
11241 TCGv_i32 fp32 = tcg_temp_new_i32();
11242 TCGv_i64 fp64 = tcg_temp_new_i64();
11244 gen_load_fpr64(ctx, fp64, fs);
11245 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11246 tcg_temp_free_i64(fp64);
11247 gen_store_fpr32(ctx, fp32, fd);
11248 tcg_temp_free_i32(fp32);
11250 break;
11251 case OPC_CVT_W_D:
11252 check_cp1_registers(ctx, fs);
11254 TCGv_i32 fp32 = tcg_temp_new_i32();
11255 TCGv_i64 fp64 = tcg_temp_new_i64();
11257 gen_load_fpr64(ctx, fp64, fs);
11258 if (ctx->nan2008) {
11259 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11260 } else {
11261 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11263 tcg_temp_free_i64(fp64);
11264 gen_store_fpr32(ctx, fp32, fd);
11265 tcg_temp_free_i32(fp32);
11267 break;
11268 case OPC_CVT_L_D:
11269 check_cp1_64bitmode(ctx);
11271 TCGv_i64 fp0 = tcg_temp_new_i64();
11273 gen_load_fpr64(ctx, fp0, fs);
11274 if (ctx->nan2008) {
11275 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11276 } else {
11277 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11279 gen_store_fpr64(ctx, fp0, fd);
11280 tcg_temp_free_i64(fp0);
11282 break;
11283 case OPC_CVT_S_W:
11285 TCGv_i32 fp0 = tcg_temp_new_i32();
11287 gen_load_fpr32(ctx, fp0, fs);
11288 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11289 gen_store_fpr32(ctx, fp0, fd);
11290 tcg_temp_free_i32(fp0);
11292 break;
11293 case OPC_CVT_D_W:
11294 check_cp1_registers(ctx, fd);
11296 TCGv_i32 fp32 = tcg_temp_new_i32();
11297 TCGv_i64 fp64 = tcg_temp_new_i64();
11299 gen_load_fpr32(ctx, fp32, fs);
11300 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11301 tcg_temp_free_i32(fp32);
11302 gen_store_fpr64(ctx, fp64, fd);
11303 tcg_temp_free_i64(fp64);
11305 break;
11306 case OPC_CVT_S_L:
11307 check_cp1_64bitmode(ctx);
11309 TCGv_i32 fp32 = tcg_temp_new_i32();
11310 TCGv_i64 fp64 = tcg_temp_new_i64();
11312 gen_load_fpr64(ctx, fp64, fs);
11313 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11314 tcg_temp_free_i64(fp64);
11315 gen_store_fpr32(ctx, fp32, fd);
11316 tcg_temp_free_i32(fp32);
11318 break;
11319 case OPC_CVT_D_L:
11320 check_cp1_64bitmode(ctx);
11322 TCGv_i64 fp0 = tcg_temp_new_i64();
11324 gen_load_fpr64(ctx, fp0, fs);
11325 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11326 gen_store_fpr64(ctx, fp0, fd);
11327 tcg_temp_free_i64(fp0);
11329 break;
11330 case OPC_CVT_PS_PW:
11331 check_ps(ctx);
11333 TCGv_i64 fp0 = tcg_temp_new_i64();
11335 gen_load_fpr64(ctx, fp0, fs);
11336 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11337 gen_store_fpr64(ctx, fp0, fd);
11338 tcg_temp_free_i64(fp0);
11340 break;
11341 case OPC_ADD_PS:
11342 check_ps(ctx);
11344 TCGv_i64 fp0 = tcg_temp_new_i64();
11345 TCGv_i64 fp1 = tcg_temp_new_i64();
11347 gen_load_fpr64(ctx, fp0, fs);
11348 gen_load_fpr64(ctx, fp1, ft);
11349 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11350 tcg_temp_free_i64(fp1);
11351 gen_store_fpr64(ctx, fp0, fd);
11352 tcg_temp_free_i64(fp0);
11354 break;
11355 case OPC_SUB_PS:
11356 check_ps(ctx);
11358 TCGv_i64 fp0 = tcg_temp_new_i64();
11359 TCGv_i64 fp1 = tcg_temp_new_i64();
11361 gen_load_fpr64(ctx, fp0, fs);
11362 gen_load_fpr64(ctx, fp1, ft);
11363 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11364 tcg_temp_free_i64(fp1);
11365 gen_store_fpr64(ctx, fp0, fd);
11366 tcg_temp_free_i64(fp0);
11368 break;
11369 case OPC_MUL_PS:
11370 check_ps(ctx);
11372 TCGv_i64 fp0 = tcg_temp_new_i64();
11373 TCGv_i64 fp1 = tcg_temp_new_i64();
11375 gen_load_fpr64(ctx, fp0, fs);
11376 gen_load_fpr64(ctx, fp1, ft);
11377 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11378 tcg_temp_free_i64(fp1);
11379 gen_store_fpr64(ctx, fp0, fd);
11380 tcg_temp_free_i64(fp0);
11382 break;
11383 case OPC_ABS_PS:
11384 check_ps(ctx);
11386 TCGv_i64 fp0 = tcg_temp_new_i64();
11388 gen_load_fpr64(ctx, fp0, fs);
11389 gen_helper_float_abs_ps(fp0, fp0);
11390 gen_store_fpr64(ctx, fp0, fd);
11391 tcg_temp_free_i64(fp0);
11393 break;
11394 case OPC_MOV_PS:
11395 check_ps(ctx);
11397 TCGv_i64 fp0 = tcg_temp_new_i64();
11399 gen_load_fpr64(ctx, fp0, fs);
11400 gen_store_fpr64(ctx, fp0, fd);
11401 tcg_temp_free_i64(fp0);
11403 break;
11404 case OPC_NEG_PS:
11405 check_ps(ctx);
11407 TCGv_i64 fp0 = tcg_temp_new_i64();
11409 gen_load_fpr64(ctx, fp0, fs);
11410 gen_helper_float_chs_ps(fp0, fp0);
11411 gen_store_fpr64(ctx, fp0, fd);
11412 tcg_temp_free_i64(fp0);
11414 break;
11415 case OPC_MOVCF_PS:
11416 check_ps(ctx);
11417 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11418 break;
11419 case OPC_MOVZ_PS:
11420 check_ps(ctx);
11422 TCGLabel *l1 = gen_new_label();
11423 TCGv_i64 fp0;
11425 if (ft != 0) {
11426 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11428 fp0 = tcg_temp_new_i64();
11429 gen_load_fpr64(ctx, fp0, fs);
11430 gen_store_fpr64(ctx, fp0, fd);
11431 tcg_temp_free_i64(fp0);
11432 gen_set_label(l1);
11434 break;
11435 case OPC_MOVN_PS:
11436 check_ps(ctx);
11438 TCGLabel *l1 = gen_new_label();
11439 TCGv_i64 fp0;
11441 if (ft != 0) {
11442 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11443 fp0 = tcg_temp_new_i64();
11444 gen_load_fpr64(ctx, fp0, fs);
11445 gen_store_fpr64(ctx, fp0, fd);
11446 tcg_temp_free_i64(fp0);
11447 gen_set_label(l1);
11450 break;
11451 case OPC_ADDR_PS:
11452 check_ps(ctx);
11454 TCGv_i64 fp0 = tcg_temp_new_i64();
11455 TCGv_i64 fp1 = tcg_temp_new_i64();
11457 gen_load_fpr64(ctx, fp0, ft);
11458 gen_load_fpr64(ctx, fp1, fs);
11459 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11460 tcg_temp_free_i64(fp1);
11461 gen_store_fpr64(ctx, fp0, fd);
11462 tcg_temp_free_i64(fp0);
11464 break;
11465 case OPC_MULR_PS:
11466 check_ps(ctx);
11468 TCGv_i64 fp0 = tcg_temp_new_i64();
11469 TCGv_i64 fp1 = tcg_temp_new_i64();
11471 gen_load_fpr64(ctx, fp0, ft);
11472 gen_load_fpr64(ctx, fp1, fs);
11473 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11474 tcg_temp_free_i64(fp1);
11475 gen_store_fpr64(ctx, fp0, fd);
11476 tcg_temp_free_i64(fp0);
11478 break;
11479 case OPC_RECIP2_PS:
11480 check_ps(ctx);
11482 TCGv_i64 fp0 = tcg_temp_new_i64();
11483 TCGv_i64 fp1 = tcg_temp_new_i64();
11485 gen_load_fpr64(ctx, fp0, fs);
11486 gen_load_fpr64(ctx, fp1, ft);
11487 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11488 tcg_temp_free_i64(fp1);
11489 gen_store_fpr64(ctx, fp0, fd);
11490 tcg_temp_free_i64(fp0);
11492 break;
11493 case OPC_RECIP1_PS:
11494 check_ps(ctx);
11496 TCGv_i64 fp0 = tcg_temp_new_i64();
11498 gen_load_fpr64(ctx, fp0, fs);
11499 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11500 gen_store_fpr64(ctx, fp0, fd);
11501 tcg_temp_free_i64(fp0);
11503 break;
11504 case OPC_RSQRT1_PS:
11505 check_ps(ctx);
11507 TCGv_i64 fp0 = tcg_temp_new_i64();
11509 gen_load_fpr64(ctx, fp0, fs);
11510 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11511 gen_store_fpr64(ctx, fp0, fd);
11512 tcg_temp_free_i64(fp0);
11514 break;
11515 case OPC_RSQRT2_PS:
11516 check_ps(ctx);
11518 TCGv_i64 fp0 = tcg_temp_new_i64();
11519 TCGv_i64 fp1 = tcg_temp_new_i64();
11521 gen_load_fpr64(ctx, fp0, fs);
11522 gen_load_fpr64(ctx, fp1, ft);
11523 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11524 tcg_temp_free_i64(fp1);
11525 gen_store_fpr64(ctx, fp0, fd);
11526 tcg_temp_free_i64(fp0);
11528 break;
11529 case OPC_CVT_S_PU:
11530 check_cp1_64bitmode(ctx);
11532 TCGv_i32 fp0 = tcg_temp_new_i32();
11534 gen_load_fpr32h(ctx, fp0, fs);
11535 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11536 gen_store_fpr32(ctx, fp0, fd);
11537 tcg_temp_free_i32(fp0);
11539 break;
11540 case OPC_CVT_PW_PS:
11541 check_ps(ctx);
11543 TCGv_i64 fp0 = tcg_temp_new_i64();
11545 gen_load_fpr64(ctx, fp0, fs);
11546 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11547 gen_store_fpr64(ctx, fp0, fd);
11548 tcg_temp_free_i64(fp0);
11550 break;
11551 case OPC_CVT_S_PL:
11552 check_cp1_64bitmode(ctx);
11554 TCGv_i32 fp0 = tcg_temp_new_i32();
11556 gen_load_fpr32(ctx, fp0, fs);
11557 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11558 gen_store_fpr32(ctx, fp0, fd);
11559 tcg_temp_free_i32(fp0);
11561 break;
11562 case OPC_PLL_PS:
11563 check_ps(ctx);
11565 TCGv_i32 fp0 = tcg_temp_new_i32();
11566 TCGv_i32 fp1 = tcg_temp_new_i32();
11568 gen_load_fpr32(ctx, fp0, fs);
11569 gen_load_fpr32(ctx, fp1, ft);
11570 gen_store_fpr32h(ctx, fp0, fd);
11571 gen_store_fpr32(ctx, fp1, fd);
11572 tcg_temp_free_i32(fp0);
11573 tcg_temp_free_i32(fp1);
11575 break;
11576 case OPC_PLU_PS:
11577 check_ps(ctx);
11579 TCGv_i32 fp0 = tcg_temp_new_i32();
11580 TCGv_i32 fp1 = tcg_temp_new_i32();
11582 gen_load_fpr32(ctx, fp0, fs);
11583 gen_load_fpr32h(ctx, fp1, ft);
11584 gen_store_fpr32(ctx, fp1, fd);
11585 gen_store_fpr32h(ctx, fp0, fd);
11586 tcg_temp_free_i32(fp0);
11587 tcg_temp_free_i32(fp1);
11589 break;
11590 case OPC_PUL_PS:
11591 check_ps(ctx);
11593 TCGv_i32 fp0 = tcg_temp_new_i32();
11594 TCGv_i32 fp1 = tcg_temp_new_i32();
11596 gen_load_fpr32h(ctx, fp0, fs);
11597 gen_load_fpr32(ctx, fp1, ft);
11598 gen_store_fpr32(ctx, fp1, fd);
11599 gen_store_fpr32h(ctx, fp0, fd);
11600 tcg_temp_free_i32(fp0);
11601 tcg_temp_free_i32(fp1);
11603 break;
11604 case OPC_PUU_PS:
11605 check_ps(ctx);
11607 TCGv_i32 fp0 = tcg_temp_new_i32();
11608 TCGv_i32 fp1 = tcg_temp_new_i32();
11610 gen_load_fpr32h(ctx, fp0, fs);
11611 gen_load_fpr32h(ctx, fp1, ft);
11612 gen_store_fpr32(ctx, fp1, fd);
11613 gen_store_fpr32h(ctx, fp0, fd);
11614 tcg_temp_free_i32(fp0);
11615 tcg_temp_free_i32(fp1);
11617 break;
11618 case OPC_CMP_F_PS:
11619 case OPC_CMP_UN_PS:
11620 case OPC_CMP_EQ_PS:
11621 case OPC_CMP_UEQ_PS:
11622 case OPC_CMP_OLT_PS:
11623 case OPC_CMP_ULT_PS:
11624 case OPC_CMP_OLE_PS:
11625 case OPC_CMP_ULE_PS:
11626 case OPC_CMP_SF_PS:
11627 case OPC_CMP_NGLE_PS:
11628 case OPC_CMP_SEQ_PS:
11629 case OPC_CMP_NGL_PS:
11630 case OPC_CMP_LT_PS:
11631 case OPC_CMP_NGE_PS:
11632 case OPC_CMP_LE_PS:
11633 case OPC_CMP_NGT_PS:
11634 if (ctx->opcode & (1 << 6)) {
11635 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
11636 } else {
11637 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
11639 break;
11640 default:
11641 MIPS_INVAL("farith");
11642 gen_reserved_instruction(ctx);
11643 return;
11647 /* Coprocessor 3 (FPU) */
11648 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
11649 int fd, int fs, int base, int index)
11651 TCGv t0 = tcg_temp_new();
11653 if (base == 0) {
11654 gen_load_gpr(t0, index);
11655 } else if (index == 0) {
11656 gen_load_gpr(t0, base);
11657 } else {
11658 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
11661 * Don't do NOP if destination is zero: we must perform the actual
11662 * memory access.
11664 switch (opc) {
11665 case OPC_LWXC1:
11666 check_cop1x(ctx);
11668 TCGv_i32 fp0 = tcg_temp_new_i32();
11670 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
11671 tcg_gen_trunc_tl_i32(fp0, t0);
11672 gen_store_fpr32(ctx, fp0, fd);
11673 tcg_temp_free_i32(fp0);
11675 break;
11676 case OPC_LDXC1:
11677 check_cop1x(ctx);
11678 check_cp1_registers(ctx, fd);
11680 TCGv_i64 fp0 = tcg_temp_new_i64();
11681 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11682 gen_store_fpr64(ctx, fp0, fd);
11683 tcg_temp_free_i64(fp0);
11685 break;
11686 case OPC_LUXC1:
11687 check_cp1_64bitmode(ctx);
11688 tcg_gen_andi_tl(t0, t0, ~0x7);
11690 TCGv_i64 fp0 = tcg_temp_new_i64();
11692 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11693 gen_store_fpr64(ctx, fp0, fd);
11694 tcg_temp_free_i64(fp0);
11696 break;
11697 case OPC_SWXC1:
11698 check_cop1x(ctx);
11700 TCGv_i32 fp0 = tcg_temp_new_i32();
11701 gen_load_fpr32(ctx, fp0, fs);
11702 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
11703 tcg_temp_free_i32(fp0);
11705 break;
11706 case OPC_SDXC1:
11707 check_cop1x(ctx);
11708 check_cp1_registers(ctx, fs);
11710 TCGv_i64 fp0 = tcg_temp_new_i64();
11711 gen_load_fpr64(ctx, fp0, fs);
11712 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11713 tcg_temp_free_i64(fp0);
11715 break;
11716 case OPC_SUXC1:
11717 check_cp1_64bitmode(ctx);
11718 tcg_gen_andi_tl(t0, t0, ~0x7);
11720 TCGv_i64 fp0 = tcg_temp_new_i64();
11721 gen_load_fpr64(ctx, fp0, fs);
11722 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11723 tcg_temp_free_i64(fp0);
11725 break;
11727 tcg_temp_free(t0);
11730 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
11731 int fd, int fr, int fs, int ft)
11733 switch (opc) {
11734 case OPC_ALNV_PS:
11735 check_ps(ctx);
11737 TCGv t0 = tcg_temp_local_new();
11738 TCGv_i32 fp = tcg_temp_new_i32();
11739 TCGv_i32 fph = tcg_temp_new_i32();
11740 TCGLabel *l1 = gen_new_label();
11741 TCGLabel *l2 = gen_new_label();
11743 gen_load_gpr(t0, fr);
11744 tcg_gen_andi_tl(t0, t0, 0x7);
11746 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
11747 gen_load_fpr32(ctx, fp, fs);
11748 gen_load_fpr32h(ctx, fph, fs);
11749 gen_store_fpr32(ctx, fp, fd);
11750 gen_store_fpr32h(ctx, fph, fd);
11751 tcg_gen_br(l2);
11752 gen_set_label(l1);
11753 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
11754 tcg_temp_free(t0);
11755 #ifdef TARGET_WORDS_BIGENDIAN
11756 gen_load_fpr32(ctx, fp, fs);
11757 gen_load_fpr32h(ctx, fph, ft);
11758 gen_store_fpr32h(ctx, fp, fd);
11759 gen_store_fpr32(ctx, fph, fd);
11760 #else
11761 gen_load_fpr32h(ctx, fph, fs);
11762 gen_load_fpr32(ctx, fp, ft);
11763 gen_store_fpr32(ctx, fph, fd);
11764 gen_store_fpr32h(ctx, fp, fd);
11765 #endif
11766 gen_set_label(l2);
11767 tcg_temp_free_i32(fp);
11768 tcg_temp_free_i32(fph);
11770 break;
11771 case OPC_MADD_S:
11772 check_cop1x(ctx);
11774 TCGv_i32 fp0 = tcg_temp_new_i32();
11775 TCGv_i32 fp1 = tcg_temp_new_i32();
11776 TCGv_i32 fp2 = tcg_temp_new_i32();
11778 gen_load_fpr32(ctx, fp0, fs);
11779 gen_load_fpr32(ctx, fp1, ft);
11780 gen_load_fpr32(ctx, fp2, fr);
11781 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
11782 tcg_temp_free_i32(fp0);
11783 tcg_temp_free_i32(fp1);
11784 gen_store_fpr32(ctx, fp2, fd);
11785 tcg_temp_free_i32(fp2);
11787 break;
11788 case OPC_MADD_D:
11789 check_cop1x(ctx);
11790 check_cp1_registers(ctx, fd | fs | ft | fr);
11792 TCGv_i64 fp0 = tcg_temp_new_i64();
11793 TCGv_i64 fp1 = tcg_temp_new_i64();
11794 TCGv_i64 fp2 = tcg_temp_new_i64();
11796 gen_load_fpr64(ctx, fp0, fs);
11797 gen_load_fpr64(ctx, fp1, ft);
11798 gen_load_fpr64(ctx, fp2, fr);
11799 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
11800 tcg_temp_free_i64(fp0);
11801 tcg_temp_free_i64(fp1);
11802 gen_store_fpr64(ctx, fp2, fd);
11803 tcg_temp_free_i64(fp2);
11805 break;
11806 case OPC_MADD_PS:
11807 check_ps(ctx);
11809 TCGv_i64 fp0 = tcg_temp_new_i64();
11810 TCGv_i64 fp1 = tcg_temp_new_i64();
11811 TCGv_i64 fp2 = tcg_temp_new_i64();
11813 gen_load_fpr64(ctx, fp0, fs);
11814 gen_load_fpr64(ctx, fp1, ft);
11815 gen_load_fpr64(ctx, fp2, fr);
11816 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
11817 tcg_temp_free_i64(fp0);
11818 tcg_temp_free_i64(fp1);
11819 gen_store_fpr64(ctx, fp2, fd);
11820 tcg_temp_free_i64(fp2);
11822 break;
11823 case OPC_MSUB_S:
11824 check_cop1x(ctx);
11826 TCGv_i32 fp0 = tcg_temp_new_i32();
11827 TCGv_i32 fp1 = tcg_temp_new_i32();
11828 TCGv_i32 fp2 = tcg_temp_new_i32();
11830 gen_load_fpr32(ctx, fp0, fs);
11831 gen_load_fpr32(ctx, fp1, ft);
11832 gen_load_fpr32(ctx, fp2, fr);
11833 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
11834 tcg_temp_free_i32(fp0);
11835 tcg_temp_free_i32(fp1);
11836 gen_store_fpr32(ctx, fp2, fd);
11837 tcg_temp_free_i32(fp2);
11839 break;
11840 case OPC_MSUB_D:
11841 check_cop1x(ctx);
11842 check_cp1_registers(ctx, fd | fs | ft | fr);
11844 TCGv_i64 fp0 = tcg_temp_new_i64();
11845 TCGv_i64 fp1 = tcg_temp_new_i64();
11846 TCGv_i64 fp2 = tcg_temp_new_i64();
11848 gen_load_fpr64(ctx, fp0, fs);
11849 gen_load_fpr64(ctx, fp1, ft);
11850 gen_load_fpr64(ctx, fp2, fr);
11851 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
11852 tcg_temp_free_i64(fp0);
11853 tcg_temp_free_i64(fp1);
11854 gen_store_fpr64(ctx, fp2, fd);
11855 tcg_temp_free_i64(fp2);
11857 break;
11858 case OPC_MSUB_PS:
11859 check_ps(ctx);
11861 TCGv_i64 fp0 = tcg_temp_new_i64();
11862 TCGv_i64 fp1 = tcg_temp_new_i64();
11863 TCGv_i64 fp2 = tcg_temp_new_i64();
11865 gen_load_fpr64(ctx, fp0, fs);
11866 gen_load_fpr64(ctx, fp1, ft);
11867 gen_load_fpr64(ctx, fp2, fr);
11868 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
11869 tcg_temp_free_i64(fp0);
11870 tcg_temp_free_i64(fp1);
11871 gen_store_fpr64(ctx, fp2, fd);
11872 tcg_temp_free_i64(fp2);
11874 break;
11875 case OPC_NMADD_S:
11876 check_cop1x(ctx);
11878 TCGv_i32 fp0 = tcg_temp_new_i32();
11879 TCGv_i32 fp1 = tcg_temp_new_i32();
11880 TCGv_i32 fp2 = tcg_temp_new_i32();
11882 gen_load_fpr32(ctx, fp0, fs);
11883 gen_load_fpr32(ctx, fp1, ft);
11884 gen_load_fpr32(ctx, fp2, fr);
11885 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
11886 tcg_temp_free_i32(fp0);
11887 tcg_temp_free_i32(fp1);
11888 gen_store_fpr32(ctx, fp2, fd);
11889 tcg_temp_free_i32(fp2);
11891 break;
11892 case OPC_NMADD_D:
11893 check_cop1x(ctx);
11894 check_cp1_registers(ctx, fd | fs | ft | fr);
11896 TCGv_i64 fp0 = tcg_temp_new_i64();
11897 TCGv_i64 fp1 = tcg_temp_new_i64();
11898 TCGv_i64 fp2 = tcg_temp_new_i64();
11900 gen_load_fpr64(ctx, fp0, fs);
11901 gen_load_fpr64(ctx, fp1, ft);
11902 gen_load_fpr64(ctx, fp2, fr);
11903 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
11904 tcg_temp_free_i64(fp0);
11905 tcg_temp_free_i64(fp1);
11906 gen_store_fpr64(ctx, fp2, fd);
11907 tcg_temp_free_i64(fp2);
11909 break;
11910 case OPC_NMADD_PS:
11911 check_ps(ctx);
11913 TCGv_i64 fp0 = tcg_temp_new_i64();
11914 TCGv_i64 fp1 = tcg_temp_new_i64();
11915 TCGv_i64 fp2 = tcg_temp_new_i64();
11917 gen_load_fpr64(ctx, fp0, fs);
11918 gen_load_fpr64(ctx, fp1, ft);
11919 gen_load_fpr64(ctx, fp2, fr);
11920 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
11921 tcg_temp_free_i64(fp0);
11922 tcg_temp_free_i64(fp1);
11923 gen_store_fpr64(ctx, fp2, fd);
11924 tcg_temp_free_i64(fp2);
11926 break;
11927 case OPC_NMSUB_S:
11928 check_cop1x(ctx);
11930 TCGv_i32 fp0 = tcg_temp_new_i32();
11931 TCGv_i32 fp1 = tcg_temp_new_i32();
11932 TCGv_i32 fp2 = tcg_temp_new_i32();
11934 gen_load_fpr32(ctx, fp0, fs);
11935 gen_load_fpr32(ctx, fp1, ft);
11936 gen_load_fpr32(ctx, fp2, fr);
11937 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
11938 tcg_temp_free_i32(fp0);
11939 tcg_temp_free_i32(fp1);
11940 gen_store_fpr32(ctx, fp2, fd);
11941 tcg_temp_free_i32(fp2);
11943 break;
11944 case OPC_NMSUB_D:
11945 check_cop1x(ctx);
11946 check_cp1_registers(ctx, fd | fs | ft | fr);
11948 TCGv_i64 fp0 = tcg_temp_new_i64();
11949 TCGv_i64 fp1 = tcg_temp_new_i64();
11950 TCGv_i64 fp2 = tcg_temp_new_i64();
11952 gen_load_fpr64(ctx, fp0, fs);
11953 gen_load_fpr64(ctx, fp1, ft);
11954 gen_load_fpr64(ctx, fp2, fr);
11955 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
11956 tcg_temp_free_i64(fp0);
11957 tcg_temp_free_i64(fp1);
11958 gen_store_fpr64(ctx, fp2, fd);
11959 tcg_temp_free_i64(fp2);
11961 break;
11962 case OPC_NMSUB_PS:
11963 check_ps(ctx);
11965 TCGv_i64 fp0 = tcg_temp_new_i64();
11966 TCGv_i64 fp1 = tcg_temp_new_i64();
11967 TCGv_i64 fp2 = tcg_temp_new_i64();
11969 gen_load_fpr64(ctx, fp0, fs);
11970 gen_load_fpr64(ctx, fp1, ft);
11971 gen_load_fpr64(ctx, fp2, fr);
11972 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
11973 tcg_temp_free_i64(fp0);
11974 tcg_temp_free_i64(fp1);
11975 gen_store_fpr64(ctx, fp2, fd);
11976 tcg_temp_free_i64(fp2);
11978 break;
11979 default:
11980 MIPS_INVAL("flt3_arith");
11981 gen_reserved_instruction(ctx);
11982 return;
11986 void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
11988 TCGv t0;
11990 #if !defined(CONFIG_USER_ONLY)
11992 * The Linux kernel will emulate rdhwr if it's not supported natively.
11993 * Therefore only check the ISA in system mode.
11995 check_insn(ctx, ISA_MIPS_R2);
11996 #endif
11997 t0 = tcg_temp_new();
11999 switch (rd) {
12000 case 0:
12001 gen_helper_rdhwr_cpunum(t0, cpu_env);
12002 gen_store_gpr(t0, rt);
12003 break;
12004 case 1:
12005 gen_helper_rdhwr_synci_step(t0, cpu_env);
12006 gen_store_gpr(t0, rt);
12007 break;
12008 case 2:
12009 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12010 gen_io_start();
12012 gen_helper_rdhwr_cc(t0, cpu_env);
12013 gen_store_gpr(t0, rt);
12015 * Break the TB to be able to take timer interrupts immediately
12016 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12017 * we break completely out of translated code.
12019 gen_save_pc(ctx->base.pc_next + 4);
12020 ctx->base.is_jmp = DISAS_EXIT;
12021 break;
12022 case 3:
12023 gen_helper_rdhwr_ccres(t0, cpu_env);
12024 gen_store_gpr(t0, rt);
12025 break;
12026 case 4:
12027 check_insn(ctx, ISA_MIPS_R6);
12028 if (sel != 0) {
12030 * Performance counter registers are not implemented other than
12031 * control register 0.
12033 generate_exception(ctx, EXCP_RI);
12035 gen_helper_rdhwr_performance(t0, cpu_env);
12036 gen_store_gpr(t0, rt);
12037 break;
12038 case 5:
12039 check_insn(ctx, ISA_MIPS_R6);
12040 gen_helper_rdhwr_xnp(t0, cpu_env);
12041 gen_store_gpr(t0, rt);
12042 break;
12043 case 29:
12044 #if defined(CONFIG_USER_ONLY)
12045 tcg_gen_ld_tl(t0, cpu_env,
12046 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12047 gen_store_gpr(t0, rt);
12048 break;
12049 #else
12050 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12051 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12052 tcg_gen_ld_tl(t0, cpu_env,
12053 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12054 gen_store_gpr(t0, rt);
12055 } else {
12056 gen_reserved_instruction(ctx);
12058 break;
12059 #endif
12060 default: /* Invalid */
12061 MIPS_INVAL("rdhwr");
12062 gen_reserved_instruction(ctx);
12063 break;
12065 tcg_temp_free(t0);
12068 static inline void clear_branch_hflags(DisasContext *ctx)
12070 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12071 if (ctx->base.is_jmp == DISAS_NEXT) {
12072 save_cpu_state(ctx, 0);
12073 } else {
12075 * It is not safe to save ctx->hflags as hflags may be changed
12076 * in execution time by the instruction in delay / forbidden slot.
12078 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12082 static void gen_branch(DisasContext *ctx, int insn_bytes)
12084 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12085 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12086 /* Branches completion */
12087 clear_branch_hflags(ctx);
12088 ctx->base.is_jmp = DISAS_NORETURN;
12089 /* FIXME: Need to clear can_do_io. */
12090 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12091 case MIPS_HFLAG_FBNSLOT:
12092 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12093 break;
12094 case MIPS_HFLAG_B:
12095 /* unconditional branch */
12096 if (proc_hflags & MIPS_HFLAG_BX) {
12097 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12099 gen_goto_tb(ctx, 0, ctx->btarget);
12100 break;
12101 case MIPS_HFLAG_BL:
12102 /* blikely taken case */
12103 gen_goto_tb(ctx, 0, ctx->btarget);
12104 break;
12105 case MIPS_HFLAG_BC:
12106 /* Conditional branch */
12108 TCGLabel *l1 = gen_new_label();
12110 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12111 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12112 gen_set_label(l1);
12113 gen_goto_tb(ctx, 0, ctx->btarget);
12115 break;
12116 case MIPS_HFLAG_BR:
12117 /* unconditional branch to register */
12118 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12119 TCGv t0 = tcg_temp_new();
12120 TCGv_i32 t1 = tcg_temp_new_i32();
12122 tcg_gen_andi_tl(t0, btarget, 0x1);
12123 tcg_gen_trunc_tl_i32(t1, t0);
12124 tcg_temp_free(t0);
12125 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12126 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12127 tcg_gen_or_i32(hflags, hflags, t1);
12128 tcg_temp_free_i32(t1);
12130 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12131 } else {
12132 tcg_gen_mov_tl(cpu_PC, btarget);
12134 if (ctx->base.singlestep_enabled) {
12135 save_cpu_state(ctx, 0);
12136 gen_helper_raise_exception_debug(cpu_env);
12138 tcg_gen_lookup_and_goto_ptr();
12139 break;
12140 default:
12141 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12142 abort();
12147 /* Compact Branches */
12148 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12149 int rs, int rt, int32_t offset)
12151 int bcond_compute = 0;
12152 TCGv t0 = tcg_temp_new();
12153 TCGv t1 = tcg_temp_new();
12154 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12156 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12157 #ifdef MIPS_DEBUG_DISAS
12158 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12159 "\n", ctx->base.pc_next);
12160 #endif
12161 gen_reserved_instruction(ctx);
12162 goto out;
12165 /* Load needed operands and calculate btarget */
12166 switch (opc) {
12167 /* compact branch */
12168 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12169 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12170 gen_load_gpr(t0, rs);
12171 gen_load_gpr(t1, rt);
12172 bcond_compute = 1;
12173 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12174 if (rs <= rt && rs == 0) {
12175 /* OPC_BEQZALC, OPC_BNEZALC */
12176 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12178 break;
12179 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12180 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12181 gen_load_gpr(t0, rs);
12182 gen_load_gpr(t1, rt);
12183 bcond_compute = 1;
12184 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12185 break;
12186 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12187 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12188 if (rs == 0 || rs == rt) {
12189 /* OPC_BLEZALC, OPC_BGEZALC */
12190 /* OPC_BGTZALC, OPC_BLTZALC */
12191 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12193 gen_load_gpr(t0, rs);
12194 gen_load_gpr(t1, rt);
12195 bcond_compute = 1;
12196 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12197 break;
12198 case OPC_BC:
12199 case OPC_BALC:
12200 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12201 break;
12202 case OPC_BEQZC:
12203 case OPC_BNEZC:
12204 if (rs != 0) {
12205 /* OPC_BEQZC, OPC_BNEZC */
12206 gen_load_gpr(t0, rs);
12207 bcond_compute = 1;
12208 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12209 } else {
12210 /* OPC_JIC, OPC_JIALC */
12211 TCGv tbase = tcg_temp_new();
12212 TCGv toffset = tcg_temp_new();
12214 gen_load_gpr(tbase, rt);
12215 tcg_gen_movi_tl(toffset, offset);
12216 gen_op_addr_add(ctx, btarget, tbase, toffset);
12217 tcg_temp_free(tbase);
12218 tcg_temp_free(toffset);
12220 break;
12221 default:
12222 MIPS_INVAL("Compact branch/jump");
12223 gen_reserved_instruction(ctx);
12224 goto out;
12227 if (bcond_compute == 0) {
12228 /* Uncoditional compact branch */
12229 switch (opc) {
12230 case OPC_JIALC:
12231 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12232 /* Fallthrough */
12233 case OPC_JIC:
12234 ctx->hflags |= MIPS_HFLAG_BR;
12235 break;
12236 case OPC_BALC:
12237 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12238 /* Fallthrough */
12239 case OPC_BC:
12240 ctx->hflags |= MIPS_HFLAG_B;
12241 break;
12242 default:
12243 MIPS_INVAL("Compact branch/jump");
12244 gen_reserved_instruction(ctx);
12245 goto out;
12248 /* Generating branch here as compact branches don't have delay slot */
12249 gen_branch(ctx, 4);
12250 } else {
12251 /* Conditional compact branch */
12252 TCGLabel *fs = gen_new_label();
12253 save_cpu_state(ctx, 0);
12255 switch (opc) {
12256 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12257 if (rs == 0 && rt != 0) {
12258 /* OPC_BLEZALC */
12259 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12260 } else if (rs != 0 && rt != 0 && rs == rt) {
12261 /* OPC_BGEZALC */
12262 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12263 } else {
12264 /* OPC_BGEUC */
12265 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12267 break;
12268 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12269 if (rs == 0 && rt != 0) {
12270 /* OPC_BGTZALC */
12271 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12272 } else if (rs != 0 && rt != 0 && rs == rt) {
12273 /* OPC_BLTZALC */
12274 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12275 } else {
12276 /* OPC_BLTUC */
12277 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12279 break;
12280 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12281 if (rs == 0 && rt != 0) {
12282 /* OPC_BLEZC */
12283 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12284 } else if (rs != 0 && rt != 0 && rs == rt) {
12285 /* OPC_BGEZC */
12286 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12287 } else {
12288 /* OPC_BGEC */
12289 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12291 break;
12292 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12293 if (rs == 0 && rt != 0) {
12294 /* OPC_BGTZC */
12295 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12296 } else if (rs != 0 && rt != 0 && rs == rt) {
12297 /* OPC_BLTZC */
12298 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12299 } else {
12300 /* OPC_BLTC */
12301 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12303 break;
12304 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12305 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12306 if (rs >= rt) {
12307 /* OPC_BOVC, OPC_BNVC */
12308 TCGv t2 = tcg_temp_new();
12309 TCGv t3 = tcg_temp_new();
12310 TCGv t4 = tcg_temp_new();
12311 TCGv input_overflow = tcg_temp_new();
12313 gen_load_gpr(t0, rs);
12314 gen_load_gpr(t1, rt);
12315 tcg_gen_ext32s_tl(t2, t0);
12316 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12317 tcg_gen_ext32s_tl(t3, t1);
12318 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12319 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12321 tcg_gen_add_tl(t4, t2, t3);
12322 tcg_gen_ext32s_tl(t4, t4);
12323 tcg_gen_xor_tl(t2, t2, t3);
12324 tcg_gen_xor_tl(t3, t4, t3);
12325 tcg_gen_andc_tl(t2, t3, t2);
12326 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12327 tcg_gen_or_tl(t4, t4, input_overflow);
12328 if (opc == OPC_BOVC) {
12329 /* OPC_BOVC */
12330 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12331 } else {
12332 /* OPC_BNVC */
12333 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12335 tcg_temp_free(input_overflow);
12336 tcg_temp_free(t4);
12337 tcg_temp_free(t3);
12338 tcg_temp_free(t2);
12339 } else if (rs < rt && rs == 0) {
12340 /* OPC_BEQZALC, OPC_BNEZALC */
12341 if (opc == OPC_BEQZALC) {
12342 /* OPC_BEQZALC */
12343 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12344 } else {
12345 /* OPC_BNEZALC */
12346 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12348 } else {
12349 /* OPC_BEQC, OPC_BNEC */
12350 if (opc == OPC_BEQC) {
12351 /* OPC_BEQC */
12352 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12353 } else {
12354 /* OPC_BNEC */
12355 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12358 break;
12359 case OPC_BEQZC:
12360 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12361 break;
12362 case OPC_BNEZC:
12363 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12364 break;
12365 default:
12366 MIPS_INVAL("Compact conditional branch/jump");
12367 gen_reserved_instruction(ctx);
12368 goto out;
12371 /* Generating branch here as compact branches don't have delay slot */
12372 gen_goto_tb(ctx, 1, ctx->btarget);
12373 gen_set_label(fs);
12375 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12378 out:
12379 tcg_temp_free(t0);
12380 tcg_temp_free(t1);
12383 /* ISA extensions (ASEs) */
12384 /* MIPS16 extension to MIPS32 */
12386 /* MIPS16 major opcodes */
12387 enum {
12388 M16_OPC_ADDIUSP = 0x00,
12389 M16_OPC_ADDIUPC = 0x01,
12390 M16_OPC_B = 0x02,
12391 M16_OPC_JAL = 0x03,
12392 M16_OPC_BEQZ = 0x04,
12393 M16_OPC_BNEQZ = 0x05,
12394 M16_OPC_SHIFT = 0x06,
12395 M16_OPC_LD = 0x07,
12396 M16_OPC_RRIA = 0x08,
12397 M16_OPC_ADDIU8 = 0x09,
12398 M16_OPC_SLTI = 0x0a,
12399 M16_OPC_SLTIU = 0x0b,
12400 M16_OPC_I8 = 0x0c,
12401 M16_OPC_LI = 0x0d,
12402 M16_OPC_CMPI = 0x0e,
12403 M16_OPC_SD = 0x0f,
12404 M16_OPC_LB = 0x10,
12405 M16_OPC_LH = 0x11,
12406 M16_OPC_LWSP = 0x12,
12407 M16_OPC_LW = 0x13,
12408 M16_OPC_LBU = 0x14,
12409 M16_OPC_LHU = 0x15,
12410 M16_OPC_LWPC = 0x16,
12411 M16_OPC_LWU = 0x17,
12412 M16_OPC_SB = 0x18,
12413 M16_OPC_SH = 0x19,
12414 M16_OPC_SWSP = 0x1a,
12415 M16_OPC_SW = 0x1b,
12416 M16_OPC_RRR = 0x1c,
12417 M16_OPC_RR = 0x1d,
12418 M16_OPC_EXTEND = 0x1e,
12419 M16_OPC_I64 = 0x1f
12422 /* I8 funct field */
12423 enum {
12424 I8_BTEQZ = 0x0,
12425 I8_BTNEZ = 0x1,
12426 I8_SWRASP = 0x2,
12427 I8_ADJSP = 0x3,
12428 I8_SVRS = 0x4,
12429 I8_MOV32R = 0x5,
12430 I8_MOVR32 = 0x7
12433 /* RRR f field */
12434 enum {
12435 RRR_DADDU = 0x0,
12436 RRR_ADDU = 0x1,
12437 RRR_DSUBU = 0x2,
12438 RRR_SUBU = 0x3
12441 /* RR funct field */
12442 enum {
12443 RR_JR = 0x00,
12444 RR_SDBBP = 0x01,
12445 RR_SLT = 0x02,
12446 RR_SLTU = 0x03,
12447 RR_SLLV = 0x04,
12448 RR_BREAK = 0x05,
12449 RR_SRLV = 0x06,
12450 RR_SRAV = 0x07,
12451 RR_DSRL = 0x08,
12452 RR_CMP = 0x0a,
12453 RR_NEG = 0x0b,
12454 RR_AND = 0x0c,
12455 RR_OR = 0x0d,
12456 RR_XOR = 0x0e,
12457 RR_NOT = 0x0f,
12458 RR_MFHI = 0x10,
12459 RR_CNVT = 0x11,
12460 RR_MFLO = 0x12,
12461 RR_DSRA = 0x13,
12462 RR_DSLLV = 0x14,
12463 RR_DSRLV = 0x16,
12464 RR_DSRAV = 0x17,
12465 RR_MULT = 0x18,
12466 RR_MULTU = 0x19,
12467 RR_DIV = 0x1a,
12468 RR_DIVU = 0x1b,
12469 RR_DMULT = 0x1c,
12470 RR_DMULTU = 0x1d,
12471 RR_DDIV = 0x1e,
12472 RR_DDIVU = 0x1f
12475 /* I64 funct field */
12476 enum {
12477 I64_LDSP = 0x0,
12478 I64_SDSP = 0x1,
12479 I64_SDRASP = 0x2,
12480 I64_DADJSP = 0x3,
12481 I64_LDPC = 0x4,
12482 I64_DADDIU5 = 0x5,
12483 I64_DADDIUPC = 0x6,
12484 I64_DADDIUSP = 0x7
12487 /* RR ry field for CNVT */
12488 enum {
12489 RR_RY_CNVT_ZEB = 0x0,
12490 RR_RY_CNVT_ZEH = 0x1,
12491 RR_RY_CNVT_ZEW = 0x2,
12492 RR_RY_CNVT_SEB = 0x4,
12493 RR_RY_CNVT_SEH = 0x5,
12494 RR_RY_CNVT_SEW = 0x6,
12497 static int xlat(int r)
12499 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12501 return map[r];
12504 static void gen_mips16_save(DisasContext *ctx,
12505 int xsregs, int aregs,
12506 int do_ra, int do_s0, int do_s1,
12507 int framesize)
12509 TCGv t0 = tcg_temp_new();
12510 TCGv t1 = tcg_temp_new();
12511 TCGv t2 = tcg_temp_new();
12512 int args, astatic;
12514 switch (aregs) {
12515 case 0:
12516 case 1:
12517 case 2:
12518 case 3:
12519 case 11:
12520 args = 0;
12521 break;
12522 case 4:
12523 case 5:
12524 case 6:
12525 case 7:
12526 args = 1;
12527 break;
12528 case 8:
12529 case 9:
12530 case 10:
12531 args = 2;
12532 break;
12533 case 12:
12534 case 13:
12535 args = 3;
12536 break;
12537 case 14:
12538 args = 4;
12539 break;
12540 default:
12541 gen_reserved_instruction(ctx);
12542 return;
12545 switch (args) {
12546 case 4:
12547 gen_base_offset_addr(ctx, t0, 29, 12);
12548 gen_load_gpr(t1, 7);
12549 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12550 /* Fall through */
12551 case 3:
12552 gen_base_offset_addr(ctx, t0, 29, 8);
12553 gen_load_gpr(t1, 6);
12554 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12555 /* Fall through */
12556 case 2:
12557 gen_base_offset_addr(ctx, t0, 29, 4);
12558 gen_load_gpr(t1, 5);
12559 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12560 /* Fall through */
12561 case 1:
12562 gen_base_offset_addr(ctx, t0, 29, 0);
12563 gen_load_gpr(t1, 4);
12564 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12567 gen_load_gpr(t0, 29);
12569 #define DECR_AND_STORE(reg) do { \
12570 tcg_gen_movi_tl(t2, -4); \
12571 gen_op_addr_add(ctx, t0, t0, t2); \
12572 gen_load_gpr(t1, reg); \
12573 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12574 } while (0)
12576 if (do_ra) {
12577 DECR_AND_STORE(31);
12580 switch (xsregs) {
12581 case 7:
12582 DECR_AND_STORE(30);
12583 /* Fall through */
12584 case 6:
12585 DECR_AND_STORE(23);
12586 /* Fall through */
12587 case 5:
12588 DECR_AND_STORE(22);
12589 /* Fall through */
12590 case 4:
12591 DECR_AND_STORE(21);
12592 /* Fall through */
12593 case 3:
12594 DECR_AND_STORE(20);
12595 /* Fall through */
12596 case 2:
12597 DECR_AND_STORE(19);
12598 /* Fall through */
12599 case 1:
12600 DECR_AND_STORE(18);
12603 if (do_s1) {
12604 DECR_AND_STORE(17);
12606 if (do_s0) {
12607 DECR_AND_STORE(16);
12610 switch (aregs) {
12611 case 0:
12612 case 4:
12613 case 8:
12614 case 12:
12615 case 14:
12616 astatic = 0;
12617 break;
12618 case 1:
12619 case 5:
12620 case 9:
12621 case 13:
12622 astatic = 1;
12623 break;
12624 case 2:
12625 case 6:
12626 case 10:
12627 astatic = 2;
12628 break;
12629 case 3:
12630 case 7:
12631 astatic = 3;
12632 break;
12633 case 11:
12634 astatic = 4;
12635 break;
12636 default:
12637 gen_reserved_instruction(ctx);
12638 return;
12641 if (astatic > 0) {
12642 DECR_AND_STORE(7);
12643 if (astatic > 1) {
12644 DECR_AND_STORE(6);
12645 if (astatic > 2) {
12646 DECR_AND_STORE(5);
12647 if (astatic > 3) {
12648 DECR_AND_STORE(4);
12653 #undef DECR_AND_STORE
12655 tcg_gen_movi_tl(t2, -framesize);
12656 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12657 tcg_temp_free(t0);
12658 tcg_temp_free(t1);
12659 tcg_temp_free(t2);
12662 static void gen_mips16_restore(DisasContext *ctx,
12663 int xsregs, int aregs,
12664 int do_ra, int do_s0, int do_s1,
12665 int framesize)
12667 int astatic;
12668 TCGv t0 = tcg_temp_new();
12669 TCGv t1 = tcg_temp_new();
12670 TCGv t2 = tcg_temp_new();
12672 tcg_gen_movi_tl(t2, framesize);
12673 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
12675 #define DECR_AND_LOAD(reg) do { \
12676 tcg_gen_movi_tl(t2, -4); \
12677 gen_op_addr_add(ctx, t0, t0, t2); \
12678 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
12679 gen_store_gpr(t1, reg); \
12680 } while (0)
12682 if (do_ra) {
12683 DECR_AND_LOAD(31);
12686 switch (xsregs) {
12687 case 7:
12688 DECR_AND_LOAD(30);
12689 /* Fall through */
12690 case 6:
12691 DECR_AND_LOAD(23);
12692 /* Fall through */
12693 case 5:
12694 DECR_AND_LOAD(22);
12695 /* Fall through */
12696 case 4:
12697 DECR_AND_LOAD(21);
12698 /* Fall through */
12699 case 3:
12700 DECR_AND_LOAD(20);
12701 /* Fall through */
12702 case 2:
12703 DECR_AND_LOAD(19);
12704 /* Fall through */
12705 case 1:
12706 DECR_AND_LOAD(18);
12709 if (do_s1) {
12710 DECR_AND_LOAD(17);
12712 if (do_s0) {
12713 DECR_AND_LOAD(16);
12716 switch (aregs) {
12717 case 0:
12718 case 4:
12719 case 8:
12720 case 12:
12721 case 14:
12722 astatic = 0;
12723 break;
12724 case 1:
12725 case 5:
12726 case 9:
12727 case 13:
12728 astatic = 1;
12729 break;
12730 case 2:
12731 case 6:
12732 case 10:
12733 astatic = 2;
12734 break;
12735 case 3:
12736 case 7:
12737 astatic = 3;
12738 break;
12739 case 11:
12740 astatic = 4;
12741 break;
12742 default:
12743 gen_reserved_instruction(ctx);
12744 return;
12747 if (astatic > 0) {
12748 DECR_AND_LOAD(7);
12749 if (astatic > 1) {
12750 DECR_AND_LOAD(6);
12751 if (astatic > 2) {
12752 DECR_AND_LOAD(5);
12753 if (astatic > 3) {
12754 DECR_AND_LOAD(4);
12759 #undef DECR_AND_LOAD
12761 tcg_gen_movi_tl(t2, framesize);
12762 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12763 tcg_temp_free(t0);
12764 tcg_temp_free(t1);
12765 tcg_temp_free(t2);
12768 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
12769 int is_64_bit, int extended)
12771 TCGv t0;
12773 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12774 gen_reserved_instruction(ctx);
12775 return;
12778 t0 = tcg_temp_new();
12780 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
12781 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
12782 if (!is_64_bit) {
12783 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12786 tcg_temp_free(t0);
12789 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
12790 int16_t offset)
12792 TCGv_i32 t0 = tcg_const_i32(op);
12793 TCGv t1 = tcg_temp_new();
12794 gen_base_offset_addr(ctx, t1, base, offset);
12795 gen_helper_cache(cpu_env, t1, t0);
12796 tcg_temp_free(t1);
12797 tcg_temp_free_i32(t0);
12800 #if defined(TARGET_MIPS64)
12801 static void decode_i64_mips16(DisasContext *ctx,
12802 int ry, int funct, int16_t offset,
12803 int extended)
12805 switch (funct) {
12806 case I64_LDSP:
12807 check_insn(ctx, ISA_MIPS3);
12808 check_mips_64(ctx);
12809 offset = extended ? offset : offset << 3;
12810 gen_ld(ctx, OPC_LD, ry, 29, offset);
12811 break;
12812 case I64_SDSP:
12813 check_insn(ctx, ISA_MIPS3);
12814 check_mips_64(ctx);
12815 offset = extended ? offset : offset << 3;
12816 gen_st(ctx, OPC_SD, ry, 29, offset);
12817 break;
12818 case I64_SDRASP:
12819 check_insn(ctx, ISA_MIPS3);
12820 check_mips_64(ctx);
12821 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
12822 gen_st(ctx, OPC_SD, 31, 29, offset);
12823 break;
12824 case I64_DADJSP:
12825 check_insn(ctx, ISA_MIPS3);
12826 check_mips_64(ctx);
12827 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
12828 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
12829 break;
12830 case I64_LDPC:
12831 check_insn(ctx, ISA_MIPS3);
12832 check_mips_64(ctx);
12833 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12834 gen_reserved_instruction(ctx);
12835 } else {
12836 offset = extended ? offset : offset << 3;
12837 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
12839 break;
12840 case I64_DADDIU5:
12841 check_insn(ctx, ISA_MIPS3);
12842 check_mips_64(ctx);
12843 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
12844 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
12845 break;
12846 case I64_DADDIUPC:
12847 check_insn(ctx, ISA_MIPS3);
12848 check_mips_64(ctx);
12849 offset = extended ? offset : offset << 2;
12850 gen_addiupc(ctx, ry, offset, 1, extended);
12851 break;
12852 case I64_DADDIUSP:
12853 check_insn(ctx, ISA_MIPS3);
12854 check_mips_64(ctx);
12855 offset = extended ? offset : offset << 2;
12856 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
12857 break;
12860 #endif
12862 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
12864 int extend = translator_lduw(env, ctx->base.pc_next + 2);
12865 int op, rx, ry, funct, sa;
12866 int16_t imm, offset;
12868 ctx->opcode = (ctx->opcode << 16) | extend;
12869 op = (ctx->opcode >> 11) & 0x1f;
12870 sa = (ctx->opcode >> 22) & 0x1f;
12871 funct = (ctx->opcode >> 8) & 0x7;
12872 rx = xlat((ctx->opcode >> 8) & 0x7);
12873 ry = xlat((ctx->opcode >> 5) & 0x7);
12874 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
12875 | ((ctx->opcode >> 21) & 0x3f) << 5
12876 | (ctx->opcode & 0x1f));
12879 * The extended opcodes cleverly reuse the opcodes from their 16-bit
12880 * counterparts.
12882 switch (op) {
12883 case M16_OPC_ADDIUSP:
12884 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
12885 break;
12886 case M16_OPC_ADDIUPC:
12887 gen_addiupc(ctx, rx, imm, 0, 1);
12888 break;
12889 case M16_OPC_B:
12890 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
12891 /* No delay slot, so just process as a normal instruction */
12892 break;
12893 case M16_OPC_BEQZ:
12894 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
12895 /* No delay slot, so just process as a normal instruction */
12896 break;
12897 case M16_OPC_BNEQZ:
12898 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
12899 /* No delay slot, so just process as a normal instruction */
12900 break;
12901 case M16_OPC_SHIFT:
12902 switch (ctx->opcode & 0x3) {
12903 case 0x0:
12904 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
12905 break;
12906 case 0x1:
12907 #if defined(TARGET_MIPS64)
12908 check_mips_64(ctx);
12909 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
12910 #else
12911 gen_reserved_instruction(ctx);
12912 #endif
12913 break;
12914 case 0x2:
12915 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
12916 break;
12917 case 0x3:
12918 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
12919 break;
12921 break;
12922 #if defined(TARGET_MIPS64)
12923 case M16_OPC_LD:
12924 check_insn(ctx, ISA_MIPS3);
12925 check_mips_64(ctx);
12926 gen_ld(ctx, OPC_LD, ry, rx, offset);
12927 break;
12928 #endif
12929 case M16_OPC_RRIA:
12930 imm = ctx->opcode & 0xf;
12931 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
12932 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
12933 imm = (int16_t) (imm << 1) >> 1;
12934 if ((ctx->opcode >> 4) & 0x1) {
12935 #if defined(TARGET_MIPS64)
12936 check_mips_64(ctx);
12937 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12938 #else
12939 gen_reserved_instruction(ctx);
12940 #endif
12941 } else {
12942 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12944 break;
12945 case M16_OPC_ADDIU8:
12946 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12947 break;
12948 case M16_OPC_SLTI:
12949 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12950 break;
12951 case M16_OPC_SLTIU:
12952 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12953 break;
12954 case M16_OPC_I8:
12955 switch (funct) {
12956 case I8_BTEQZ:
12957 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
12958 break;
12959 case I8_BTNEZ:
12960 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
12961 break;
12962 case I8_SWRASP:
12963 gen_st(ctx, OPC_SW, 31, 29, imm);
12964 break;
12965 case I8_ADJSP:
12966 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
12967 break;
12968 case I8_SVRS:
12969 check_insn(ctx, ISA_MIPS_R1);
12971 int xsregs = (ctx->opcode >> 24) & 0x7;
12972 int aregs = (ctx->opcode >> 16) & 0xf;
12973 int do_ra = (ctx->opcode >> 6) & 0x1;
12974 int do_s0 = (ctx->opcode >> 5) & 0x1;
12975 int do_s1 = (ctx->opcode >> 4) & 0x1;
12976 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
12977 | (ctx->opcode & 0xf)) << 3;
12979 if (ctx->opcode & (1 << 7)) {
12980 gen_mips16_save(ctx, xsregs, aregs,
12981 do_ra, do_s0, do_s1,
12982 framesize);
12983 } else {
12984 gen_mips16_restore(ctx, xsregs, aregs,
12985 do_ra, do_s0, do_s1,
12986 framesize);
12989 break;
12990 default:
12991 gen_reserved_instruction(ctx);
12992 break;
12994 break;
12995 case M16_OPC_LI:
12996 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
12997 break;
12998 case M16_OPC_CMPI:
12999 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13000 break;
13001 #if defined(TARGET_MIPS64)
13002 case M16_OPC_SD:
13003 check_insn(ctx, ISA_MIPS3);
13004 check_mips_64(ctx);
13005 gen_st(ctx, OPC_SD, ry, rx, offset);
13006 break;
13007 #endif
13008 case M16_OPC_LB:
13009 gen_ld(ctx, OPC_LB, ry, rx, offset);
13010 break;
13011 case M16_OPC_LH:
13012 gen_ld(ctx, OPC_LH, ry, rx, offset);
13013 break;
13014 case M16_OPC_LWSP:
13015 gen_ld(ctx, OPC_LW, rx, 29, offset);
13016 break;
13017 case M16_OPC_LW:
13018 gen_ld(ctx, OPC_LW, ry, rx, offset);
13019 break;
13020 case M16_OPC_LBU:
13021 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13022 break;
13023 case M16_OPC_LHU:
13024 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13025 break;
13026 case M16_OPC_LWPC:
13027 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13028 break;
13029 #if defined(TARGET_MIPS64)
13030 case M16_OPC_LWU:
13031 check_insn(ctx, ISA_MIPS3);
13032 check_mips_64(ctx);
13033 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13034 break;
13035 #endif
13036 case M16_OPC_SB:
13037 gen_st(ctx, OPC_SB, ry, rx, offset);
13038 break;
13039 case M16_OPC_SH:
13040 gen_st(ctx, OPC_SH, ry, rx, offset);
13041 break;
13042 case M16_OPC_SWSP:
13043 gen_st(ctx, OPC_SW, rx, 29, offset);
13044 break;
13045 case M16_OPC_SW:
13046 gen_st(ctx, OPC_SW, ry, rx, offset);
13047 break;
13048 #if defined(TARGET_MIPS64)
13049 case M16_OPC_I64:
13050 decode_i64_mips16(ctx, ry, funct, offset, 1);
13051 break;
13052 #endif
13053 default:
13054 gen_reserved_instruction(ctx);
13055 break;
13058 return 4;
13061 static inline bool is_uhi(int sdbbp_code)
13063 #ifdef CONFIG_USER_ONLY
13064 return false;
13065 #else
13066 return semihosting_enabled() && sdbbp_code == 1;
13067 #endif
13070 #ifdef CONFIG_USER_ONLY
13071 /* The above should dead-code away any calls to this..*/
13072 static inline void gen_helper_do_semihosting(void *env)
13074 g_assert_not_reached();
13076 #endif
13078 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13080 int rx, ry;
13081 int sa;
13082 int op, cnvt_op, op1, offset;
13083 int funct;
13084 int n_bytes;
13086 op = (ctx->opcode >> 11) & 0x1f;
13087 sa = (ctx->opcode >> 2) & 0x7;
13088 sa = sa == 0 ? 8 : sa;
13089 rx = xlat((ctx->opcode >> 8) & 0x7);
13090 cnvt_op = (ctx->opcode >> 5) & 0x7;
13091 ry = xlat((ctx->opcode >> 5) & 0x7);
13092 op1 = offset = ctx->opcode & 0x1f;
13094 n_bytes = 2;
13096 switch (op) {
13097 case M16_OPC_ADDIUSP:
13099 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13101 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13103 break;
13104 case M16_OPC_ADDIUPC:
13105 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13106 break;
13107 case M16_OPC_B:
13108 offset = (ctx->opcode & 0x7ff) << 1;
13109 offset = (int16_t)(offset << 4) >> 4;
13110 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13111 /* No delay slot, so just process as a normal instruction */
13112 break;
13113 case M16_OPC_JAL:
13114 offset = translator_lduw(env, ctx->base.pc_next + 2);
13115 offset = (((ctx->opcode & 0x1f) << 21)
13116 | ((ctx->opcode >> 5) & 0x1f) << 16
13117 | offset) << 2;
13118 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13119 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13120 n_bytes = 4;
13121 break;
13122 case M16_OPC_BEQZ:
13123 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13124 ((int8_t)ctx->opcode) << 1, 0);
13125 /* No delay slot, so just process as a normal instruction */
13126 break;
13127 case M16_OPC_BNEQZ:
13128 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13129 ((int8_t)ctx->opcode) << 1, 0);
13130 /* No delay slot, so just process as a normal instruction */
13131 break;
13132 case M16_OPC_SHIFT:
13133 switch (ctx->opcode & 0x3) {
13134 case 0x0:
13135 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13136 break;
13137 case 0x1:
13138 #if defined(TARGET_MIPS64)
13139 check_insn(ctx, ISA_MIPS3);
13140 check_mips_64(ctx);
13141 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13142 #else
13143 gen_reserved_instruction(ctx);
13144 #endif
13145 break;
13146 case 0x2:
13147 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13148 break;
13149 case 0x3:
13150 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13151 break;
13153 break;
13154 #if defined(TARGET_MIPS64)
13155 case M16_OPC_LD:
13156 check_insn(ctx, ISA_MIPS3);
13157 check_mips_64(ctx);
13158 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13159 break;
13160 #endif
13161 case M16_OPC_RRIA:
13163 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13165 if ((ctx->opcode >> 4) & 1) {
13166 #if defined(TARGET_MIPS64)
13167 check_insn(ctx, ISA_MIPS3);
13168 check_mips_64(ctx);
13169 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13170 #else
13171 gen_reserved_instruction(ctx);
13172 #endif
13173 } else {
13174 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13177 break;
13178 case M16_OPC_ADDIU8:
13180 int16_t imm = (int8_t) ctx->opcode;
13182 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13184 break;
13185 case M16_OPC_SLTI:
13187 int16_t imm = (uint8_t) ctx->opcode;
13188 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13190 break;
13191 case M16_OPC_SLTIU:
13193 int16_t imm = (uint8_t) ctx->opcode;
13194 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13196 break;
13197 case M16_OPC_I8:
13199 int reg32;
13201 funct = (ctx->opcode >> 8) & 0x7;
13202 switch (funct) {
13203 case I8_BTEQZ:
13204 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13205 ((int8_t)ctx->opcode) << 1, 0);
13206 break;
13207 case I8_BTNEZ:
13208 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13209 ((int8_t)ctx->opcode) << 1, 0);
13210 break;
13211 case I8_SWRASP:
13212 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13213 break;
13214 case I8_ADJSP:
13215 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13216 ((int8_t)ctx->opcode) << 3);
13217 break;
13218 case I8_SVRS:
13219 check_insn(ctx, ISA_MIPS_R1);
13221 int do_ra = ctx->opcode & (1 << 6);
13222 int do_s0 = ctx->opcode & (1 << 5);
13223 int do_s1 = ctx->opcode & (1 << 4);
13224 int framesize = ctx->opcode & 0xf;
13226 if (framesize == 0) {
13227 framesize = 128;
13228 } else {
13229 framesize = framesize << 3;
13232 if (ctx->opcode & (1 << 7)) {
13233 gen_mips16_save(ctx, 0, 0,
13234 do_ra, do_s0, do_s1, framesize);
13235 } else {
13236 gen_mips16_restore(ctx, 0, 0,
13237 do_ra, do_s0, do_s1, framesize);
13240 break;
13241 case I8_MOV32R:
13243 int rz = xlat(ctx->opcode & 0x7);
13245 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13246 ((ctx->opcode >> 5) & 0x7);
13247 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13249 break;
13250 case I8_MOVR32:
13251 reg32 = ctx->opcode & 0x1f;
13252 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13253 break;
13254 default:
13255 gen_reserved_instruction(ctx);
13256 break;
13259 break;
13260 case M16_OPC_LI:
13262 int16_t imm = (uint8_t) ctx->opcode;
13264 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13266 break;
13267 case M16_OPC_CMPI:
13269 int16_t imm = (uint8_t) ctx->opcode;
13270 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13272 break;
13273 #if defined(TARGET_MIPS64)
13274 case M16_OPC_SD:
13275 check_insn(ctx, ISA_MIPS3);
13276 check_mips_64(ctx);
13277 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13278 break;
13279 #endif
13280 case M16_OPC_LB:
13281 gen_ld(ctx, OPC_LB, ry, rx, offset);
13282 break;
13283 case M16_OPC_LH:
13284 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13285 break;
13286 case M16_OPC_LWSP:
13287 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13288 break;
13289 case M16_OPC_LW:
13290 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13291 break;
13292 case M16_OPC_LBU:
13293 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13294 break;
13295 case M16_OPC_LHU:
13296 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13297 break;
13298 case M16_OPC_LWPC:
13299 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13300 break;
13301 #if defined(TARGET_MIPS64)
13302 case M16_OPC_LWU:
13303 check_insn(ctx, ISA_MIPS3);
13304 check_mips_64(ctx);
13305 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13306 break;
13307 #endif
13308 case M16_OPC_SB:
13309 gen_st(ctx, OPC_SB, ry, rx, offset);
13310 break;
13311 case M16_OPC_SH:
13312 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13313 break;
13314 case M16_OPC_SWSP:
13315 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13316 break;
13317 case M16_OPC_SW:
13318 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13319 break;
13320 case M16_OPC_RRR:
13322 int rz = xlat((ctx->opcode >> 2) & 0x7);
13323 int mips32_op;
13325 switch (ctx->opcode & 0x3) {
13326 case RRR_ADDU:
13327 mips32_op = OPC_ADDU;
13328 break;
13329 case RRR_SUBU:
13330 mips32_op = OPC_SUBU;
13331 break;
13332 #if defined(TARGET_MIPS64)
13333 case RRR_DADDU:
13334 mips32_op = OPC_DADDU;
13335 check_insn(ctx, ISA_MIPS3);
13336 check_mips_64(ctx);
13337 break;
13338 case RRR_DSUBU:
13339 mips32_op = OPC_DSUBU;
13340 check_insn(ctx, ISA_MIPS3);
13341 check_mips_64(ctx);
13342 break;
13343 #endif
13344 default:
13345 gen_reserved_instruction(ctx);
13346 goto done;
13349 gen_arith(ctx, mips32_op, rz, rx, ry);
13350 done:
13353 break;
13354 case M16_OPC_RR:
13355 switch (op1) {
13356 case RR_JR:
13358 int nd = (ctx->opcode >> 7) & 0x1;
13359 int link = (ctx->opcode >> 6) & 0x1;
13360 int ra = (ctx->opcode >> 5) & 0x1;
13362 if (nd) {
13363 check_insn(ctx, ISA_MIPS_R1);
13366 if (link) {
13367 op = OPC_JALR;
13368 } else {
13369 op = OPC_JR;
13372 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13373 (nd ? 0 : 2));
13375 break;
13376 case RR_SDBBP:
13377 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13378 gen_helper_do_semihosting(cpu_env);
13379 } else {
13381 * XXX: not clear which exception should be raised
13382 * when in debug mode...
13384 check_insn(ctx, ISA_MIPS_R1);
13385 generate_exception_end(ctx, EXCP_DBp);
13387 break;
13388 case RR_SLT:
13389 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13390 break;
13391 case RR_SLTU:
13392 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13393 break;
13394 case RR_BREAK:
13395 generate_exception_end(ctx, EXCP_BREAK);
13396 break;
13397 case RR_SLLV:
13398 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13399 break;
13400 case RR_SRLV:
13401 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13402 break;
13403 case RR_SRAV:
13404 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13405 break;
13406 #if defined(TARGET_MIPS64)
13407 case RR_DSRL:
13408 check_insn(ctx, ISA_MIPS3);
13409 check_mips_64(ctx);
13410 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13411 break;
13412 #endif
13413 case RR_CMP:
13414 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13415 break;
13416 case RR_NEG:
13417 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13418 break;
13419 case RR_AND:
13420 gen_logic(ctx, OPC_AND, rx, rx, ry);
13421 break;
13422 case RR_OR:
13423 gen_logic(ctx, OPC_OR, rx, rx, ry);
13424 break;
13425 case RR_XOR:
13426 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13427 break;
13428 case RR_NOT:
13429 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13430 break;
13431 case RR_MFHI:
13432 gen_HILO(ctx, OPC_MFHI, 0, rx);
13433 break;
13434 case RR_CNVT:
13435 check_insn(ctx, ISA_MIPS_R1);
13436 switch (cnvt_op) {
13437 case RR_RY_CNVT_ZEB:
13438 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13439 break;
13440 case RR_RY_CNVT_ZEH:
13441 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13442 break;
13443 case RR_RY_CNVT_SEB:
13444 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13445 break;
13446 case RR_RY_CNVT_SEH:
13447 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13448 break;
13449 #if defined(TARGET_MIPS64)
13450 case RR_RY_CNVT_ZEW:
13451 check_insn(ctx, ISA_MIPS_R1);
13452 check_mips_64(ctx);
13453 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13454 break;
13455 case RR_RY_CNVT_SEW:
13456 check_insn(ctx, ISA_MIPS_R1);
13457 check_mips_64(ctx);
13458 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13459 break;
13460 #endif
13461 default:
13462 gen_reserved_instruction(ctx);
13463 break;
13465 break;
13466 case RR_MFLO:
13467 gen_HILO(ctx, OPC_MFLO, 0, rx);
13468 break;
13469 #if defined(TARGET_MIPS64)
13470 case RR_DSRA:
13471 check_insn(ctx, ISA_MIPS3);
13472 check_mips_64(ctx);
13473 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13474 break;
13475 case RR_DSLLV:
13476 check_insn(ctx, ISA_MIPS3);
13477 check_mips_64(ctx);
13478 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13479 break;
13480 case RR_DSRLV:
13481 check_insn(ctx, ISA_MIPS3);
13482 check_mips_64(ctx);
13483 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13484 break;
13485 case RR_DSRAV:
13486 check_insn(ctx, ISA_MIPS3);
13487 check_mips_64(ctx);
13488 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13489 break;
13490 #endif
13491 case RR_MULT:
13492 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13493 break;
13494 case RR_MULTU:
13495 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13496 break;
13497 case RR_DIV:
13498 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13499 break;
13500 case RR_DIVU:
13501 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13502 break;
13503 #if defined(TARGET_MIPS64)
13504 case RR_DMULT:
13505 check_insn(ctx, ISA_MIPS3);
13506 check_mips_64(ctx);
13507 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13508 break;
13509 case RR_DMULTU:
13510 check_insn(ctx, ISA_MIPS3);
13511 check_mips_64(ctx);
13512 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13513 break;
13514 case RR_DDIV:
13515 check_insn(ctx, ISA_MIPS3);
13516 check_mips_64(ctx);
13517 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13518 break;
13519 case RR_DDIVU:
13520 check_insn(ctx, ISA_MIPS3);
13521 check_mips_64(ctx);
13522 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13523 break;
13524 #endif
13525 default:
13526 gen_reserved_instruction(ctx);
13527 break;
13529 break;
13530 case M16_OPC_EXTEND:
13531 decode_extended_mips16_opc(env, ctx);
13532 n_bytes = 4;
13533 break;
13534 #if defined(TARGET_MIPS64)
13535 case M16_OPC_I64:
13536 funct = (ctx->opcode >> 8) & 0x7;
13537 decode_i64_mips16(ctx, ry, funct, offset, 0);
13538 break;
13539 #endif
13540 default:
13541 gen_reserved_instruction(ctx);
13542 break;
13545 return n_bytes;
13548 /* microMIPS extension to MIPS32/MIPS64 */
13551 * microMIPS32/microMIPS64 major opcodes
13553 * 1. MIPS Architecture for Programmers Volume II-B:
13554 * The microMIPS32 Instruction Set (Revision 3.05)
13556 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13558 * 2. MIPS Architecture For Programmers Volume II-A:
13559 * The MIPS64 Instruction Set (Revision 3.51)
13562 enum {
13563 POOL32A = 0x00,
13564 POOL16A = 0x01,
13565 LBU16 = 0x02,
13566 MOVE16 = 0x03,
13567 ADDI32 = 0x04,
13568 R6_LUI = 0x04,
13569 AUI = 0x04,
13570 LBU32 = 0x05,
13571 SB32 = 0x06,
13572 LB32 = 0x07,
13574 POOL32B = 0x08,
13575 POOL16B = 0x09,
13576 LHU16 = 0x0a,
13577 ANDI16 = 0x0b,
13578 ADDIU32 = 0x0c,
13579 LHU32 = 0x0d,
13580 SH32 = 0x0e,
13581 LH32 = 0x0f,
13583 POOL32I = 0x10,
13584 POOL16C = 0x11,
13585 LWSP16 = 0x12,
13586 POOL16D = 0x13,
13587 ORI32 = 0x14,
13588 POOL32F = 0x15,
13589 POOL32S = 0x16, /* MIPS64 */
13590 DADDIU32 = 0x17, /* MIPS64 */
13592 POOL32C = 0x18,
13593 LWGP16 = 0x19,
13594 LW16 = 0x1a,
13595 POOL16E = 0x1b,
13596 XORI32 = 0x1c,
13597 JALS32 = 0x1d,
13598 BOVC = 0x1d,
13599 BEQC = 0x1d,
13600 BEQZALC = 0x1d,
13601 ADDIUPC = 0x1e,
13602 PCREL = 0x1e,
13603 BNVC = 0x1f,
13604 BNEC = 0x1f,
13605 BNEZALC = 0x1f,
13607 R6_BEQZC = 0x20,
13608 JIC = 0x20,
13609 POOL16F = 0x21,
13610 SB16 = 0x22,
13611 BEQZ16 = 0x23,
13612 BEQZC16 = 0x23,
13613 SLTI32 = 0x24,
13614 BEQ32 = 0x25,
13615 BC = 0x25,
13616 SWC132 = 0x26,
13617 LWC132 = 0x27,
13619 /* 0x29 is reserved */
13620 RES_29 = 0x29,
13621 R6_BNEZC = 0x28,
13622 JIALC = 0x28,
13623 SH16 = 0x2a,
13624 BNEZ16 = 0x2b,
13625 BNEZC16 = 0x2b,
13626 SLTIU32 = 0x2c,
13627 BNE32 = 0x2d,
13628 BALC = 0x2d,
13629 SDC132 = 0x2e,
13630 LDC132 = 0x2f,
13632 /* 0x31 is reserved */
13633 RES_31 = 0x31,
13634 BLEZALC = 0x30,
13635 BGEZALC = 0x30,
13636 BGEUC = 0x30,
13637 SWSP16 = 0x32,
13638 B16 = 0x33,
13639 BC16 = 0x33,
13640 ANDI32 = 0x34,
13641 J32 = 0x35,
13642 BGTZC = 0x35,
13643 BLTZC = 0x35,
13644 BLTC = 0x35,
13645 SD32 = 0x36, /* MIPS64 */
13646 LD32 = 0x37, /* MIPS64 */
13648 /* 0x39 is reserved */
13649 RES_39 = 0x39,
13650 BGTZALC = 0x38,
13651 BLTZALC = 0x38,
13652 BLTUC = 0x38,
13653 SW16 = 0x3a,
13654 LI16 = 0x3b,
13655 JALX32 = 0x3c,
13656 JAL32 = 0x3d,
13657 BLEZC = 0x3d,
13658 BGEZC = 0x3d,
13659 BGEC = 0x3d,
13660 SW32 = 0x3e,
13661 LW32 = 0x3f
13664 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
13665 enum {
13666 ADDIUPC_00 = 0x00,
13667 ADDIUPC_01 = 0x01,
13668 ADDIUPC_02 = 0x02,
13669 ADDIUPC_03 = 0x03,
13670 ADDIUPC_04 = 0x04,
13671 ADDIUPC_05 = 0x05,
13672 ADDIUPC_06 = 0x06,
13673 ADDIUPC_07 = 0x07,
13674 AUIPC = 0x1e,
13675 ALUIPC = 0x1f,
13676 LWPC_08 = 0x08,
13677 LWPC_09 = 0x09,
13678 LWPC_0A = 0x0A,
13679 LWPC_0B = 0x0B,
13680 LWPC_0C = 0x0C,
13681 LWPC_0D = 0x0D,
13682 LWPC_0E = 0x0E,
13683 LWPC_0F = 0x0F,
13686 /* POOL32A encoding of minor opcode field */
13688 enum {
13690 * These opcodes are distinguished only by bits 9..6; those bits are
13691 * what are recorded below.
13693 SLL32 = 0x0,
13694 SRL32 = 0x1,
13695 SRA = 0x2,
13696 ROTR = 0x3,
13697 SELEQZ = 0x5,
13698 SELNEZ = 0x6,
13699 R6_RDHWR = 0x7,
13701 SLLV = 0x0,
13702 SRLV = 0x1,
13703 SRAV = 0x2,
13704 ROTRV = 0x3,
13705 ADD = 0x4,
13706 ADDU32 = 0x5,
13707 SUB = 0x6,
13708 SUBU32 = 0x7,
13709 MUL = 0x8,
13710 AND = 0x9,
13711 OR32 = 0xa,
13712 NOR = 0xb,
13713 XOR32 = 0xc,
13714 SLT = 0xd,
13715 SLTU = 0xe,
13717 MOVN = 0x0,
13718 R6_MUL = 0x0,
13719 MOVZ = 0x1,
13720 MUH = 0x1,
13721 MULU = 0x2,
13722 MUHU = 0x3,
13723 LWXS = 0x4,
13724 R6_DIV = 0x4,
13725 MOD = 0x5,
13726 R6_DIVU = 0x6,
13727 MODU = 0x7,
13729 /* The following can be distinguished by their lower 6 bits. */
13730 BREAK32 = 0x07,
13731 INS = 0x0c,
13732 LSA = 0x0f,
13733 ALIGN = 0x1f,
13734 EXT = 0x2c,
13735 POOL32AXF = 0x3c,
13736 SIGRIE = 0x3f
13739 /* POOL32AXF encoding of minor opcode field extension */
13742 * 1. MIPS Architecture for Programmers Volume II-B:
13743 * The microMIPS32 Instruction Set (Revision 3.05)
13745 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
13747 * 2. MIPS Architecture for Programmers VolumeIV-e:
13748 * The MIPS DSP Application-Specific Extension
13749 * to the microMIPS32 Architecture (Revision 2.34)
13751 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
13754 enum {
13755 /* bits 11..6 */
13756 TEQ = 0x00,
13757 TGE = 0x08,
13758 TGEU = 0x10,
13759 TLT = 0x20,
13760 TLTU = 0x28,
13761 TNE = 0x30,
13763 MFC0 = 0x03,
13764 MTC0 = 0x0b,
13766 /* begin of microMIPS32 DSP */
13768 /* bits 13..12 for 0x01 */
13769 MFHI_ACC = 0x0,
13770 MFLO_ACC = 0x1,
13771 MTHI_ACC = 0x2,
13772 MTLO_ACC = 0x3,
13774 /* bits 13..12 for 0x2a */
13775 MADD_ACC = 0x0,
13776 MADDU_ACC = 0x1,
13777 MSUB_ACC = 0x2,
13778 MSUBU_ACC = 0x3,
13780 /* bits 13..12 for 0x32 */
13781 MULT_ACC = 0x0,
13782 MULTU_ACC = 0x1,
13784 /* end of microMIPS32 DSP */
13786 /* bits 15..12 for 0x2c */
13787 BITSWAP = 0x0,
13788 SEB = 0x2,
13789 SEH = 0x3,
13790 CLO = 0x4,
13791 CLZ = 0x5,
13792 RDHWR = 0x6,
13793 WSBH = 0x7,
13794 MULT = 0x8,
13795 MULTU = 0x9,
13796 DIV = 0xa,
13797 DIVU = 0xb,
13798 MADD = 0xc,
13799 MADDU = 0xd,
13800 MSUB = 0xe,
13801 MSUBU = 0xf,
13803 /* bits 15..12 for 0x34 */
13804 MFC2 = 0x4,
13805 MTC2 = 0x5,
13806 MFHC2 = 0x8,
13807 MTHC2 = 0x9,
13808 CFC2 = 0xc,
13809 CTC2 = 0xd,
13811 /* bits 15..12 for 0x3c */
13812 JALR = 0x0,
13813 JR = 0x0, /* alias */
13814 JALRC = 0x0,
13815 JRC = 0x0,
13816 JALR_HB = 0x1,
13817 JALRC_HB = 0x1,
13818 JALRS = 0x4,
13819 JALRS_HB = 0x5,
13821 /* bits 15..12 for 0x05 */
13822 RDPGPR = 0xe,
13823 WRPGPR = 0xf,
13825 /* bits 15..12 for 0x0d */
13826 TLBP = 0x0,
13827 TLBR = 0x1,
13828 TLBWI = 0x2,
13829 TLBWR = 0x3,
13830 TLBINV = 0x4,
13831 TLBINVF = 0x5,
13832 WAIT = 0x9,
13833 IRET = 0xd,
13834 DERET = 0xe,
13835 ERET = 0xf,
13837 /* bits 15..12 for 0x15 */
13838 DMT = 0x0,
13839 DVPE = 0x1,
13840 EMT = 0x2,
13841 EVPE = 0x3,
13843 /* bits 15..12 for 0x1d */
13844 DI = 0x4,
13845 EI = 0x5,
13847 /* bits 15..12 for 0x2d */
13848 SYNC = 0x6,
13849 SYSCALL = 0x8,
13850 SDBBP = 0xd,
13852 /* bits 15..12 for 0x35 */
13853 MFHI32 = 0x0,
13854 MFLO32 = 0x1,
13855 MTHI32 = 0x2,
13856 MTLO32 = 0x3,
13859 /* POOL32B encoding of minor opcode field (bits 15..12) */
13861 enum {
13862 LWC2 = 0x0,
13863 LWP = 0x1,
13864 LDP = 0x4,
13865 LWM32 = 0x5,
13866 CACHE = 0x6,
13867 LDM = 0x7,
13868 SWC2 = 0x8,
13869 SWP = 0x9,
13870 SDP = 0xc,
13871 SWM32 = 0xd,
13872 SDM = 0xf
13875 /* POOL32C encoding of minor opcode field (bits 15..12) */
13877 enum {
13878 LWL = 0x0,
13879 SWL = 0x8,
13880 LWR = 0x1,
13881 SWR = 0x9,
13882 PREF = 0x2,
13883 ST_EVA = 0xa,
13884 LL = 0x3,
13885 SC = 0xb,
13886 LDL = 0x4,
13887 SDL = 0xc,
13888 LDR = 0x5,
13889 SDR = 0xd,
13890 LD_EVA = 0x6,
13891 LWU = 0xe,
13892 LLD = 0x7,
13893 SCD = 0xf
13896 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
13898 enum {
13899 LBUE = 0x0,
13900 LHUE = 0x1,
13901 LWLE = 0x2,
13902 LWRE = 0x3,
13903 LBE = 0x4,
13904 LHE = 0x5,
13905 LLE = 0x6,
13906 LWE = 0x7,
13909 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
13911 enum {
13912 SWLE = 0x0,
13913 SWRE = 0x1,
13914 PREFE = 0x2,
13915 CACHEE = 0x3,
13916 SBE = 0x4,
13917 SHE = 0x5,
13918 SCE = 0x6,
13919 SWE = 0x7,
13922 /* POOL32F encoding of minor opcode field (bits 5..0) */
13924 enum {
13925 /* These are the bit 7..6 values */
13926 ADD_FMT = 0x0,
13928 SUB_FMT = 0x1,
13930 MUL_FMT = 0x2,
13932 DIV_FMT = 0x3,
13934 /* These are the bit 8..6 values */
13935 MOVN_FMT = 0x0,
13936 RSQRT2_FMT = 0x0,
13937 MOVF_FMT = 0x0,
13938 RINT_FMT = 0x0,
13939 SELNEZ_FMT = 0x0,
13941 MOVZ_FMT = 0x1,
13942 LWXC1 = 0x1,
13943 MOVT_FMT = 0x1,
13944 CLASS_FMT = 0x1,
13945 SELEQZ_FMT = 0x1,
13947 PLL_PS = 0x2,
13948 SWXC1 = 0x2,
13949 SEL_FMT = 0x2,
13951 PLU_PS = 0x3,
13952 LDXC1 = 0x3,
13954 MOVN_FMT_04 = 0x4,
13955 PUL_PS = 0x4,
13956 SDXC1 = 0x4,
13957 RECIP2_FMT = 0x4,
13959 MOVZ_FMT_05 = 0x05,
13960 PUU_PS = 0x5,
13961 LUXC1 = 0x5,
13963 CVT_PS_S = 0x6,
13964 SUXC1 = 0x6,
13965 ADDR_PS = 0x6,
13966 PREFX = 0x6,
13967 MADDF_FMT = 0x6,
13969 MULR_PS = 0x7,
13970 MSUBF_FMT = 0x7,
13972 MADD_S = 0x01,
13973 MADD_D = 0x09,
13974 MADD_PS = 0x11,
13975 ALNV_PS = 0x19,
13976 MSUB_S = 0x21,
13977 MSUB_D = 0x29,
13978 MSUB_PS = 0x31,
13980 NMADD_S = 0x02,
13981 NMADD_D = 0x0a,
13982 NMADD_PS = 0x12,
13983 NMSUB_S = 0x22,
13984 NMSUB_D = 0x2a,
13985 NMSUB_PS = 0x32,
13987 MIN_FMT = 0x3,
13988 MAX_FMT = 0xb,
13989 MINA_FMT = 0x23,
13990 MAXA_FMT = 0x2b,
13991 POOL32FXF = 0x3b,
13993 CABS_COND_FMT = 0x1c, /* MIPS3D */
13994 C_COND_FMT = 0x3c,
13996 CMP_CONDN_S = 0x5,
13997 CMP_CONDN_D = 0x15
14000 /* POOL32Fxf encoding of minor opcode extension field */
14002 enum {
14003 CVT_L = 0x04,
14004 RSQRT_FMT = 0x08,
14005 FLOOR_L = 0x0c,
14006 CVT_PW_PS = 0x1c,
14007 CVT_W = 0x24,
14008 SQRT_FMT = 0x28,
14009 FLOOR_W = 0x2c,
14010 CVT_PS_PW = 0x3c,
14011 CFC1 = 0x40,
14012 RECIP_FMT = 0x48,
14013 CEIL_L = 0x4c,
14014 CTC1 = 0x60,
14015 CEIL_W = 0x6c,
14016 MFC1 = 0x80,
14017 CVT_S_PL = 0x84,
14018 TRUNC_L = 0x8c,
14019 MTC1 = 0xa0,
14020 CVT_S_PU = 0xa4,
14021 TRUNC_W = 0xac,
14022 MFHC1 = 0xc0,
14023 ROUND_L = 0xcc,
14024 MTHC1 = 0xe0,
14025 ROUND_W = 0xec,
14027 MOV_FMT = 0x01,
14028 MOVF = 0x05,
14029 ABS_FMT = 0x0d,
14030 RSQRT1_FMT = 0x1d,
14031 MOVT = 0x25,
14032 NEG_FMT = 0x2d,
14033 CVT_D = 0x4d,
14034 RECIP1_FMT = 0x5d,
14035 CVT_S = 0x6d
14038 /* POOL32I encoding of minor opcode field (bits 25..21) */
14040 enum {
14041 BLTZ = 0x00,
14042 BLTZAL = 0x01,
14043 BGEZ = 0x02,
14044 BGEZAL = 0x03,
14045 BLEZ = 0x04,
14046 BNEZC = 0x05,
14047 BGTZ = 0x06,
14048 BEQZC = 0x07,
14049 TLTI = 0x08,
14050 BC1EQZC = 0x08,
14051 TGEI = 0x09,
14052 BC1NEZC = 0x09,
14053 TLTIU = 0x0a,
14054 BC2EQZC = 0x0a,
14055 TGEIU = 0x0b,
14056 BC2NEZC = 0x0a,
14057 TNEI = 0x0c,
14058 R6_SYNCI = 0x0c,
14059 LUI = 0x0d,
14060 TEQI = 0x0e,
14061 SYNCI = 0x10,
14062 BLTZALS = 0x11,
14063 BGEZALS = 0x13,
14064 BC2F = 0x14,
14065 BC2T = 0x15,
14066 BPOSGE64 = 0x1a,
14067 BPOSGE32 = 0x1b,
14068 /* These overlap and are distinguished by bit16 of the instruction */
14069 BC1F = 0x1c,
14070 BC1T = 0x1d,
14071 BC1ANY2F = 0x1c,
14072 BC1ANY2T = 0x1d,
14073 BC1ANY4F = 0x1e,
14074 BC1ANY4T = 0x1f
14077 /* POOL16A encoding of minor opcode field */
14079 enum {
14080 ADDU16 = 0x0,
14081 SUBU16 = 0x1
14084 /* POOL16B encoding of minor opcode field */
14086 enum {
14087 SLL16 = 0x0,
14088 SRL16 = 0x1
14091 /* POOL16C encoding of minor opcode field */
14093 enum {
14094 NOT16 = 0x00,
14095 XOR16 = 0x04,
14096 AND16 = 0x08,
14097 OR16 = 0x0c,
14098 LWM16 = 0x10,
14099 SWM16 = 0x14,
14100 JR16 = 0x18,
14101 JRC16 = 0x1a,
14102 JALR16 = 0x1c,
14103 JALR16S = 0x1e,
14104 MFHI16 = 0x20,
14105 MFLO16 = 0x24,
14106 BREAK16 = 0x28,
14107 SDBBP16 = 0x2c,
14108 JRADDIUSP = 0x30
14111 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14113 enum {
14114 R6_NOT16 = 0x00,
14115 R6_AND16 = 0x01,
14116 R6_LWM16 = 0x02,
14117 R6_JRC16 = 0x03,
14118 MOVEP = 0x04,
14119 MOVEP_05 = 0x05,
14120 MOVEP_06 = 0x06,
14121 MOVEP_07 = 0x07,
14122 R6_XOR16 = 0x08,
14123 R6_OR16 = 0x09,
14124 R6_SWM16 = 0x0a,
14125 JALRC16 = 0x0b,
14126 MOVEP_0C = 0x0c,
14127 MOVEP_0D = 0x0d,
14128 MOVEP_0E = 0x0e,
14129 MOVEP_0F = 0x0f,
14130 JRCADDIUSP = 0x13,
14131 R6_BREAK16 = 0x1b,
14132 R6_SDBBP16 = 0x3b
14135 /* POOL16D encoding of minor opcode field */
14137 enum {
14138 ADDIUS5 = 0x0,
14139 ADDIUSP = 0x1
14142 /* POOL16E encoding of minor opcode field */
14144 enum {
14145 ADDIUR2 = 0x0,
14146 ADDIUR1SP = 0x1
14149 static int mmreg(int r)
14151 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14153 return map[r];
14156 /* Used for 16-bit store instructions. */
14157 static int mmreg2(int r)
14159 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14161 return map[r];
14164 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14165 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14166 #define uMIPS_RS2(op) uMIPS_RS(op)
14167 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14168 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14169 #define uMIPS_RS5(op) (op & 0x1f)
14171 /* Signed immediate */
14172 #define SIMM(op, start, width) \
14173 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
14174 << (32 - width)) \
14175 >> (32 - width))
14176 /* Zero-extended immediate */
14177 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
14179 static void gen_addiur1sp(DisasContext *ctx)
14181 int rd = mmreg(uMIPS_RD(ctx->opcode));
14183 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14186 static void gen_addiur2(DisasContext *ctx)
14188 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14189 int rd = mmreg(uMIPS_RD(ctx->opcode));
14190 int rs = mmreg(uMIPS_RS(ctx->opcode));
14192 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14195 static void gen_addiusp(DisasContext *ctx)
14197 int encoded = ZIMM(ctx->opcode, 1, 9);
14198 int decoded;
14200 if (encoded <= 1) {
14201 decoded = 256 + encoded;
14202 } else if (encoded <= 255) {
14203 decoded = encoded;
14204 } else if (encoded <= 509) {
14205 decoded = encoded - 512;
14206 } else {
14207 decoded = encoded - 768;
14210 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14213 static void gen_addius5(DisasContext *ctx)
14215 int imm = SIMM(ctx->opcode, 1, 4);
14216 int rd = (ctx->opcode >> 5) & 0x1f;
14218 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14221 static void gen_andi16(DisasContext *ctx)
14223 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14224 31, 32, 63, 64, 255, 32768, 65535 };
14225 int rd = mmreg(uMIPS_RD(ctx->opcode));
14226 int rs = mmreg(uMIPS_RS(ctx->opcode));
14227 int encoded = ZIMM(ctx->opcode, 0, 4);
14229 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14232 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
14233 int base, int16_t offset)
14235 TCGv t0, t1;
14236 TCGv_i32 t2;
14238 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14239 gen_reserved_instruction(ctx);
14240 return;
14243 t0 = tcg_temp_new();
14245 gen_base_offset_addr(ctx, t0, base, offset);
14247 t1 = tcg_const_tl(reglist);
14248 t2 = tcg_const_i32(ctx->mem_idx);
14250 save_cpu_state(ctx, 1);
14251 switch (opc) {
14252 case LWM32:
14253 gen_helper_lwm(cpu_env, t0, t1, t2);
14254 break;
14255 case SWM32:
14256 gen_helper_swm(cpu_env, t0, t1, t2);
14257 break;
14258 #ifdef TARGET_MIPS64
14259 case LDM:
14260 gen_helper_ldm(cpu_env, t0, t1, t2);
14261 break;
14262 case SDM:
14263 gen_helper_sdm(cpu_env, t0, t1, t2);
14264 break;
14265 #endif
14267 tcg_temp_free(t0);
14268 tcg_temp_free(t1);
14269 tcg_temp_free_i32(t2);
14273 static void gen_pool16c_insn(DisasContext *ctx)
14275 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14276 int rs = mmreg(ctx->opcode & 0x7);
14278 switch (((ctx->opcode) >> 4) & 0x3f) {
14279 case NOT16 + 0:
14280 case NOT16 + 1:
14281 case NOT16 + 2:
14282 case NOT16 + 3:
14283 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14284 break;
14285 case XOR16 + 0:
14286 case XOR16 + 1:
14287 case XOR16 + 2:
14288 case XOR16 + 3:
14289 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14290 break;
14291 case AND16 + 0:
14292 case AND16 + 1:
14293 case AND16 + 2:
14294 case AND16 + 3:
14295 gen_logic(ctx, OPC_AND, rd, rd, rs);
14296 break;
14297 case OR16 + 0:
14298 case OR16 + 1:
14299 case OR16 + 2:
14300 case OR16 + 3:
14301 gen_logic(ctx, OPC_OR, rd, rd, rs);
14302 break;
14303 case LWM16 + 0:
14304 case LWM16 + 1:
14305 case LWM16 + 2:
14306 case LWM16 + 3:
14308 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14309 int offset = ZIMM(ctx->opcode, 0, 4);
14311 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14312 29, offset << 2);
14314 break;
14315 case SWM16 + 0:
14316 case SWM16 + 1:
14317 case SWM16 + 2:
14318 case SWM16 + 3:
14320 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14321 int offset = ZIMM(ctx->opcode, 0, 4);
14323 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14324 29, offset << 2);
14326 break;
14327 case JR16 + 0:
14328 case JR16 + 1:
14330 int reg = ctx->opcode & 0x1f;
14332 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14334 break;
14335 case JRC16 + 0:
14336 case JRC16 + 1:
14338 int reg = ctx->opcode & 0x1f;
14339 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14341 * Let normal delay slot handling in our caller take us
14342 * to the branch target.
14345 break;
14346 case JALR16 + 0:
14347 case JALR16 + 1:
14348 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14349 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14350 break;
14351 case JALR16S + 0:
14352 case JALR16S + 1:
14353 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14354 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14355 break;
14356 case MFHI16 + 0:
14357 case MFHI16 + 1:
14358 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14359 break;
14360 case MFLO16 + 0:
14361 case MFLO16 + 1:
14362 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14363 break;
14364 case BREAK16:
14365 generate_exception_end(ctx, EXCP_BREAK);
14366 break;
14367 case SDBBP16:
14368 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14369 gen_helper_do_semihosting(cpu_env);
14370 } else {
14372 * XXX: not clear which exception should be raised
14373 * when in debug mode...
14375 check_insn(ctx, ISA_MIPS_R1);
14376 generate_exception_end(ctx, EXCP_DBp);
14378 break;
14379 case JRADDIUSP + 0:
14380 case JRADDIUSP + 1:
14382 int imm = ZIMM(ctx->opcode, 0, 5);
14383 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14384 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14386 * Let normal delay slot handling in our caller take us
14387 * to the branch target.
14390 break;
14391 default:
14392 gen_reserved_instruction(ctx);
14393 break;
14397 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14398 int enc_rs)
14400 int rd, re;
14401 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14402 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14403 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14405 rd = rd_enc[enc_dest];
14406 re = re_enc[enc_dest];
14407 gen_load_gpr(cpu_gpr[rd], rs_rt_enc[enc_rs]);
14408 gen_load_gpr(cpu_gpr[re], rs_rt_enc[enc_rt]);
14411 static void gen_pool16c_r6_insn(DisasContext *ctx)
14413 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14414 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14416 switch (ctx->opcode & 0xf) {
14417 case R6_NOT16:
14418 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14419 break;
14420 case R6_AND16:
14421 gen_logic(ctx, OPC_AND, rt, rt, rs);
14422 break;
14423 case R6_LWM16:
14425 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14426 int offset = extract32(ctx->opcode, 4, 4);
14427 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14429 break;
14430 case R6_JRC16: /* JRCADDIUSP */
14431 if ((ctx->opcode >> 4) & 1) {
14432 /* JRCADDIUSP */
14433 int imm = extract32(ctx->opcode, 5, 5);
14434 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14435 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14436 } else {
14437 /* JRC16 */
14438 rs = extract32(ctx->opcode, 5, 5);
14439 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14441 break;
14442 case MOVEP:
14443 case MOVEP_05:
14444 case MOVEP_06:
14445 case MOVEP_07:
14446 case MOVEP_0C:
14447 case MOVEP_0D:
14448 case MOVEP_0E:
14449 case MOVEP_0F:
14451 int enc_dest = uMIPS_RD(ctx->opcode);
14452 int enc_rt = uMIPS_RS2(ctx->opcode);
14453 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14454 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14456 break;
14457 case R6_XOR16:
14458 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14459 break;
14460 case R6_OR16:
14461 gen_logic(ctx, OPC_OR, rt, rt, rs);
14462 break;
14463 case R6_SWM16:
14465 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14466 int offset = extract32(ctx->opcode, 4, 4);
14467 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14469 break;
14470 case JALRC16: /* BREAK16, SDBBP16 */
14471 switch (ctx->opcode & 0x3f) {
14472 case JALRC16:
14473 case JALRC16 + 0x20:
14474 /* JALRC16 */
14475 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14476 31, 0, 0);
14477 break;
14478 case R6_BREAK16:
14479 /* BREAK16 */
14480 generate_exception(ctx, EXCP_BREAK);
14481 break;
14482 case R6_SDBBP16:
14483 /* SDBBP16 */
14484 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14485 gen_helper_do_semihosting(cpu_env);
14486 } else {
14487 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14488 generate_exception(ctx, EXCP_RI);
14489 } else {
14490 generate_exception(ctx, EXCP_DBp);
14493 break;
14495 break;
14496 default:
14497 generate_exception(ctx, EXCP_RI);
14498 break;
14502 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
14504 TCGv t0 = tcg_temp_new();
14505 TCGv t1 = tcg_temp_new();
14507 gen_load_gpr(t0, base);
14509 if (index != 0) {
14510 gen_load_gpr(t1, index);
14511 tcg_gen_shli_tl(t1, t1, 2);
14512 gen_op_addr_add(ctx, t0, t1, t0);
14515 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14516 gen_store_gpr(t1, rd);
14518 tcg_temp_free(t0);
14519 tcg_temp_free(t1);
14522 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
14523 int base, int16_t offset)
14525 TCGv t0, t1;
14527 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14528 gen_reserved_instruction(ctx);
14529 return;
14532 t0 = tcg_temp_new();
14533 t1 = tcg_temp_new();
14535 gen_base_offset_addr(ctx, t0, base, offset);
14537 switch (opc) {
14538 case LWP:
14539 if (rd == base) {
14540 gen_reserved_instruction(ctx);
14541 return;
14543 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14544 gen_store_gpr(t1, rd);
14545 tcg_gen_movi_tl(t1, 4);
14546 gen_op_addr_add(ctx, t0, t0, t1);
14547 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14548 gen_store_gpr(t1, rd + 1);
14549 break;
14550 case SWP:
14551 gen_load_gpr(t1, rd);
14552 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14553 tcg_gen_movi_tl(t1, 4);
14554 gen_op_addr_add(ctx, t0, t0, t1);
14555 gen_load_gpr(t1, rd + 1);
14556 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14557 break;
14558 #ifdef TARGET_MIPS64
14559 case LDP:
14560 if (rd == base) {
14561 gen_reserved_instruction(ctx);
14562 return;
14564 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14565 gen_store_gpr(t1, rd);
14566 tcg_gen_movi_tl(t1, 8);
14567 gen_op_addr_add(ctx, t0, t0, t1);
14568 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14569 gen_store_gpr(t1, rd + 1);
14570 break;
14571 case SDP:
14572 gen_load_gpr(t1, rd);
14573 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14574 tcg_gen_movi_tl(t1, 8);
14575 gen_op_addr_add(ctx, t0, t0, t1);
14576 gen_load_gpr(t1, rd + 1);
14577 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14578 break;
14579 #endif
14581 tcg_temp_free(t0);
14582 tcg_temp_free(t1);
14585 static void gen_sync(int stype)
14587 TCGBar tcg_mo = TCG_BAR_SC;
14589 switch (stype) {
14590 case 0x4: /* SYNC_WMB */
14591 tcg_mo |= TCG_MO_ST_ST;
14592 break;
14593 case 0x10: /* SYNC_MB */
14594 tcg_mo |= TCG_MO_ALL;
14595 break;
14596 case 0x11: /* SYNC_ACQUIRE */
14597 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14598 break;
14599 case 0x12: /* SYNC_RELEASE */
14600 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14601 break;
14602 case 0x13: /* SYNC_RMB */
14603 tcg_mo |= TCG_MO_LD_LD;
14604 break;
14605 default:
14606 tcg_mo |= TCG_MO_ALL;
14607 break;
14610 tcg_gen_mb(tcg_mo);
14613 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14615 int extension = (ctx->opcode >> 6) & 0x3f;
14616 int minor = (ctx->opcode >> 12) & 0xf;
14617 uint32_t mips32_op;
14619 switch (extension) {
14620 case TEQ:
14621 mips32_op = OPC_TEQ;
14622 goto do_trap;
14623 case TGE:
14624 mips32_op = OPC_TGE;
14625 goto do_trap;
14626 case TGEU:
14627 mips32_op = OPC_TGEU;
14628 goto do_trap;
14629 case TLT:
14630 mips32_op = OPC_TLT;
14631 goto do_trap;
14632 case TLTU:
14633 mips32_op = OPC_TLTU;
14634 goto do_trap;
14635 case TNE:
14636 mips32_op = OPC_TNE;
14637 do_trap:
14638 gen_trap(ctx, mips32_op, rs, rt, -1);
14639 break;
14640 #ifndef CONFIG_USER_ONLY
14641 case MFC0:
14642 case MFC0 + 32:
14643 check_cp0_enabled(ctx);
14644 if (rt == 0) {
14645 /* Treat as NOP. */
14646 break;
14648 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
14649 break;
14650 case MTC0:
14651 case MTC0 + 32:
14652 check_cp0_enabled(ctx);
14654 TCGv t0 = tcg_temp_new();
14656 gen_load_gpr(t0, rt);
14657 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
14658 tcg_temp_free(t0);
14660 break;
14661 #endif
14662 case 0x2a:
14663 switch (minor & 3) {
14664 case MADD_ACC:
14665 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
14666 break;
14667 case MADDU_ACC:
14668 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
14669 break;
14670 case MSUB_ACC:
14671 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
14672 break;
14673 case MSUBU_ACC:
14674 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
14675 break;
14676 default:
14677 goto pool32axf_invalid;
14679 break;
14680 case 0x32:
14681 switch (minor & 3) {
14682 case MULT_ACC:
14683 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
14684 break;
14685 case MULTU_ACC:
14686 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
14687 break;
14688 default:
14689 goto pool32axf_invalid;
14691 break;
14692 case 0x2c:
14693 switch (minor) {
14694 case BITSWAP:
14695 check_insn(ctx, ISA_MIPS_R6);
14696 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
14697 break;
14698 case SEB:
14699 gen_bshfl(ctx, OPC_SEB, rs, rt);
14700 break;
14701 case SEH:
14702 gen_bshfl(ctx, OPC_SEH, rs, rt);
14703 break;
14704 case CLO:
14705 mips32_op = OPC_CLO;
14706 goto do_cl;
14707 case CLZ:
14708 mips32_op = OPC_CLZ;
14709 do_cl:
14710 check_insn(ctx, ISA_MIPS_R1);
14711 gen_cl(ctx, mips32_op, rt, rs);
14712 break;
14713 case RDHWR:
14714 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14715 gen_rdhwr(ctx, rt, rs, 0);
14716 break;
14717 case WSBH:
14718 gen_bshfl(ctx, OPC_WSBH, rs, rt);
14719 break;
14720 case MULT:
14721 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14722 mips32_op = OPC_MULT;
14723 goto do_mul;
14724 case MULTU:
14725 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14726 mips32_op = OPC_MULTU;
14727 goto do_mul;
14728 case DIV:
14729 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14730 mips32_op = OPC_DIV;
14731 goto do_div;
14732 case DIVU:
14733 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14734 mips32_op = OPC_DIVU;
14735 goto do_div;
14736 do_div:
14737 check_insn(ctx, ISA_MIPS_R1);
14738 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14739 break;
14740 case MADD:
14741 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14742 mips32_op = OPC_MADD;
14743 goto do_mul;
14744 case MADDU:
14745 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14746 mips32_op = OPC_MADDU;
14747 goto do_mul;
14748 case MSUB:
14749 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14750 mips32_op = OPC_MSUB;
14751 goto do_mul;
14752 case MSUBU:
14753 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14754 mips32_op = OPC_MSUBU;
14755 do_mul:
14756 check_insn(ctx, ISA_MIPS_R1);
14757 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14758 break;
14759 default:
14760 goto pool32axf_invalid;
14762 break;
14763 case 0x34:
14764 switch (minor) {
14765 case MFC2:
14766 case MTC2:
14767 case MFHC2:
14768 case MTHC2:
14769 case CFC2:
14770 case CTC2:
14771 generate_exception_err(ctx, EXCP_CpU, 2);
14772 break;
14773 default:
14774 goto pool32axf_invalid;
14776 break;
14777 case 0x3c:
14778 switch (minor) {
14779 case JALR: /* JALRC */
14780 case JALR_HB: /* JALRC_HB */
14781 if (ctx->insn_flags & ISA_MIPS_R6) {
14782 /* JALRC, JALRC_HB */
14783 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
14784 } else {
14785 /* JALR, JALR_HB */
14786 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
14787 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14789 break;
14790 case JALRS:
14791 case JALRS_HB:
14792 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14793 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
14794 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14795 break;
14796 default:
14797 goto pool32axf_invalid;
14799 break;
14800 case 0x05:
14801 switch (minor) {
14802 case RDPGPR:
14803 check_cp0_enabled(ctx);
14804 check_insn(ctx, ISA_MIPS_R2);
14805 gen_load_srsgpr(rs, rt);
14806 break;
14807 case WRPGPR:
14808 check_cp0_enabled(ctx);
14809 check_insn(ctx, ISA_MIPS_R2);
14810 gen_store_srsgpr(rs, rt);
14811 break;
14812 default:
14813 goto pool32axf_invalid;
14815 break;
14816 #ifndef CONFIG_USER_ONLY
14817 case 0x0d:
14818 switch (minor) {
14819 case TLBP:
14820 mips32_op = OPC_TLBP;
14821 goto do_cp0;
14822 case TLBR:
14823 mips32_op = OPC_TLBR;
14824 goto do_cp0;
14825 case TLBWI:
14826 mips32_op = OPC_TLBWI;
14827 goto do_cp0;
14828 case TLBWR:
14829 mips32_op = OPC_TLBWR;
14830 goto do_cp0;
14831 case TLBINV:
14832 mips32_op = OPC_TLBINV;
14833 goto do_cp0;
14834 case TLBINVF:
14835 mips32_op = OPC_TLBINVF;
14836 goto do_cp0;
14837 case WAIT:
14838 mips32_op = OPC_WAIT;
14839 goto do_cp0;
14840 case DERET:
14841 mips32_op = OPC_DERET;
14842 goto do_cp0;
14843 case ERET:
14844 mips32_op = OPC_ERET;
14845 do_cp0:
14846 gen_cp0(env, ctx, mips32_op, rt, rs);
14847 break;
14848 default:
14849 goto pool32axf_invalid;
14851 break;
14852 case 0x1d:
14853 switch (minor) {
14854 case DI:
14855 check_cp0_enabled(ctx);
14857 TCGv t0 = tcg_temp_new();
14859 save_cpu_state(ctx, 1);
14860 gen_helper_di(t0, cpu_env);
14861 gen_store_gpr(t0, rs);
14863 * Stop translation as we may have switched the execution
14864 * mode.
14866 ctx->base.is_jmp = DISAS_STOP;
14867 tcg_temp_free(t0);
14869 break;
14870 case EI:
14871 check_cp0_enabled(ctx);
14873 TCGv t0 = tcg_temp_new();
14875 save_cpu_state(ctx, 1);
14876 gen_helper_ei(t0, cpu_env);
14877 gen_store_gpr(t0, rs);
14879 * DISAS_STOP isn't sufficient, we need to ensure we break out
14880 * of translated code to check for pending interrupts.
14882 gen_save_pc(ctx->base.pc_next + 4);
14883 ctx->base.is_jmp = DISAS_EXIT;
14884 tcg_temp_free(t0);
14886 break;
14887 default:
14888 goto pool32axf_invalid;
14890 break;
14891 #endif
14892 case 0x2d:
14893 switch (minor) {
14894 case SYNC:
14895 gen_sync(extract32(ctx->opcode, 16, 5));
14896 break;
14897 case SYSCALL:
14898 generate_exception_end(ctx, EXCP_SYSCALL);
14899 break;
14900 case SDBBP:
14901 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
14902 gen_helper_do_semihosting(cpu_env);
14903 } else {
14904 check_insn(ctx, ISA_MIPS_R1);
14905 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14906 gen_reserved_instruction(ctx);
14907 } else {
14908 generate_exception_end(ctx, EXCP_DBp);
14911 break;
14912 default:
14913 goto pool32axf_invalid;
14915 break;
14916 case 0x01:
14917 switch (minor & 3) {
14918 case MFHI_ACC:
14919 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
14920 break;
14921 case MFLO_ACC:
14922 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
14923 break;
14924 case MTHI_ACC:
14925 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
14926 break;
14927 case MTLO_ACC:
14928 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
14929 break;
14930 default:
14931 goto pool32axf_invalid;
14933 break;
14934 case 0x35:
14935 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14936 switch (minor) {
14937 case MFHI32:
14938 gen_HILO(ctx, OPC_MFHI, 0, rs);
14939 break;
14940 case MFLO32:
14941 gen_HILO(ctx, OPC_MFLO, 0, rs);
14942 break;
14943 case MTHI32:
14944 gen_HILO(ctx, OPC_MTHI, 0, rs);
14945 break;
14946 case MTLO32:
14947 gen_HILO(ctx, OPC_MTLO, 0, rs);
14948 break;
14949 default:
14950 goto pool32axf_invalid;
14952 break;
14953 default:
14954 pool32axf_invalid:
14955 MIPS_INVAL("pool32axf");
14956 gen_reserved_instruction(ctx);
14957 break;
14962 * Values for microMIPS fmt field. Variable-width, depending on which
14963 * formats the instruction supports.
14965 enum {
14966 FMT_SD_S = 0,
14967 FMT_SD_D = 1,
14969 FMT_SDPS_S = 0,
14970 FMT_SDPS_D = 1,
14971 FMT_SDPS_PS = 2,
14973 FMT_SWL_S = 0,
14974 FMT_SWL_W = 1,
14975 FMT_SWL_L = 2,
14977 FMT_DWL_D = 0,
14978 FMT_DWL_W = 1,
14979 FMT_DWL_L = 2
14982 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
14984 int extension = (ctx->opcode >> 6) & 0x3ff;
14985 uint32_t mips32_op;
14987 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
14988 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
14989 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
14991 switch (extension) {
14992 case FLOAT_1BIT_FMT(CFC1, 0):
14993 mips32_op = OPC_CFC1;
14994 goto do_cp1;
14995 case FLOAT_1BIT_FMT(CTC1, 0):
14996 mips32_op = OPC_CTC1;
14997 goto do_cp1;
14998 case FLOAT_1BIT_FMT(MFC1, 0):
14999 mips32_op = OPC_MFC1;
15000 goto do_cp1;
15001 case FLOAT_1BIT_FMT(MTC1, 0):
15002 mips32_op = OPC_MTC1;
15003 goto do_cp1;
15004 case FLOAT_1BIT_FMT(MFHC1, 0):
15005 mips32_op = OPC_MFHC1;
15006 goto do_cp1;
15007 case FLOAT_1BIT_FMT(MTHC1, 0):
15008 mips32_op = OPC_MTHC1;
15009 do_cp1:
15010 gen_cp1(ctx, mips32_op, rt, rs);
15011 break;
15013 /* Reciprocal square root */
15014 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15015 mips32_op = OPC_RSQRT_S;
15016 goto do_unaryfp;
15017 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15018 mips32_op = OPC_RSQRT_D;
15019 goto do_unaryfp;
15021 /* Square root */
15022 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15023 mips32_op = OPC_SQRT_S;
15024 goto do_unaryfp;
15025 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15026 mips32_op = OPC_SQRT_D;
15027 goto do_unaryfp;
15029 /* Reciprocal */
15030 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15031 mips32_op = OPC_RECIP_S;
15032 goto do_unaryfp;
15033 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15034 mips32_op = OPC_RECIP_D;
15035 goto do_unaryfp;
15037 /* Floor */
15038 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15039 mips32_op = OPC_FLOOR_L_S;
15040 goto do_unaryfp;
15041 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15042 mips32_op = OPC_FLOOR_L_D;
15043 goto do_unaryfp;
15044 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15045 mips32_op = OPC_FLOOR_W_S;
15046 goto do_unaryfp;
15047 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15048 mips32_op = OPC_FLOOR_W_D;
15049 goto do_unaryfp;
15051 /* Ceiling */
15052 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15053 mips32_op = OPC_CEIL_L_S;
15054 goto do_unaryfp;
15055 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15056 mips32_op = OPC_CEIL_L_D;
15057 goto do_unaryfp;
15058 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15059 mips32_op = OPC_CEIL_W_S;
15060 goto do_unaryfp;
15061 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15062 mips32_op = OPC_CEIL_W_D;
15063 goto do_unaryfp;
15065 /* Truncation */
15066 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15067 mips32_op = OPC_TRUNC_L_S;
15068 goto do_unaryfp;
15069 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15070 mips32_op = OPC_TRUNC_L_D;
15071 goto do_unaryfp;
15072 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15073 mips32_op = OPC_TRUNC_W_S;
15074 goto do_unaryfp;
15075 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15076 mips32_op = OPC_TRUNC_W_D;
15077 goto do_unaryfp;
15079 /* Round */
15080 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15081 mips32_op = OPC_ROUND_L_S;
15082 goto do_unaryfp;
15083 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15084 mips32_op = OPC_ROUND_L_D;
15085 goto do_unaryfp;
15086 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15087 mips32_op = OPC_ROUND_W_S;
15088 goto do_unaryfp;
15089 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15090 mips32_op = OPC_ROUND_W_D;
15091 goto do_unaryfp;
15093 /* Integer to floating-point conversion */
15094 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15095 mips32_op = OPC_CVT_L_S;
15096 goto do_unaryfp;
15097 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15098 mips32_op = OPC_CVT_L_D;
15099 goto do_unaryfp;
15100 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15101 mips32_op = OPC_CVT_W_S;
15102 goto do_unaryfp;
15103 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15104 mips32_op = OPC_CVT_W_D;
15105 goto do_unaryfp;
15107 /* Paired-foo conversions */
15108 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15109 mips32_op = OPC_CVT_S_PL;
15110 goto do_unaryfp;
15111 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15112 mips32_op = OPC_CVT_S_PU;
15113 goto do_unaryfp;
15114 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15115 mips32_op = OPC_CVT_PW_PS;
15116 goto do_unaryfp;
15117 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15118 mips32_op = OPC_CVT_PS_PW;
15119 goto do_unaryfp;
15121 /* Floating-point moves */
15122 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15123 mips32_op = OPC_MOV_S;
15124 goto do_unaryfp;
15125 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15126 mips32_op = OPC_MOV_D;
15127 goto do_unaryfp;
15128 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15129 mips32_op = OPC_MOV_PS;
15130 goto do_unaryfp;
15132 /* Absolute value */
15133 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15134 mips32_op = OPC_ABS_S;
15135 goto do_unaryfp;
15136 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15137 mips32_op = OPC_ABS_D;
15138 goto do_unaryfp;
15139 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15140 mips32_op = OPC_ABS_PS;
15141 goto do_unaryfp;
15143 /* Negation */
15144 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15145 mips32_op = OPC_NEG_S;
15146 goto do_unaryfp;
15147 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15148 mips32_op = OPC_NEG_D;
15149 goto do_unaryfp;
15150 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15151 mips32_op = OPC_NEG_PS;
15152 goto do_unaryfp;
15154 /* Reciprocal square root step */
15155 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15156 mips32_op = OPC_RSQRT1_S;
15157 goto do_unaryfp;
15158 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15159 mips32_op = OPC_RSQRT1_D;
15160 goto do_unaryfp;
15161 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15162 mips32_op = OPC_RSQRT1_PS;
15163 goto do_unaryfp;
15165 /* Reciprocal step */
15166 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15167 mips32_op = OPC_RECIP1_S;
15168 goto do_unaryfp;
15169 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15170 mips32_op = OPC_RECIP1_S;
15171 goto do_unaryfp;
15172 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15173 mips32_op = OPC_RECIP1_PS;
15174 goto do_unaryfp;
15176 /* Conversions from double */
15177 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15178 mips32_op = OPC_CVT_D_S;
15179 goto do_unaryfp;
15180 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15181 mips32_op = OPC_CVT_D_W;
15182 goto do_unaryfp;
15183 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15184 mips32_op = OPC_CVT_D_L;
15185 goto do_unaryfp;
15187 /* Conversions from single */
15188 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15189 mips32_op = OPC_CVT_S_D;
15190 goto do_unaryfp;
15191 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15192 mips32_op = OPC_CVT_S_W;
15193 goto do_unaryfp;
15194 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15195 mips32_op = OPC_CVT_S_L;
15196 do_unaryfp:
15197 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15198 break;
15200 /* Conditional moves on floating-point codes */
15201 case COND_FLOAT_MOV(MOVT, 0):
15202 case COND_FLOAT_MOV(MOVT, 1):
15203 case COND_FLOAT_MOV(MOVT, 2):
15204 case COND_FLOAT_MOV(MOVT, 3):
15205 case COND_FLOAT_MOV(MOVT, 4):
15206 case COND_FLOAT_MOV(MOVT, 5):
15207 case COND_FLOAT_MOV(MOVT, 6):
15208 case COND_FLOAT_MOV(MOVT, 7):
15209 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15210 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15211 break;
15212 case COND_FLOAT_MOV(MOVF, 0):
15213 case COND_FLOAT_MOV(MOVF, 1):
15214 case COND_FLOAT_MOV(MOVF, 2):
15215 case COND_FLOAT_MOV(MOVF, 3):
15216 case COND_FLOAT_MOV(MOVF, 4):
15217 case COND_FLOAT_MOV(MOVF, 5):
15218 case COND_FLOAT_MOV(MOVF, 6):
15219 case COND_FLOAT_MOV(MOVF, 7):
15220 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15221 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15222 break;
15223 default:
15224 MIPS_INVAL("pool32fxf");
15225 gen_reserved_instruction(ctx);
15226 break;
15230 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15232 int32_t offset;
15233 uint16_t insn;
15234 int rt, rs, rd, rr;
15235 int16_t imm;
15236 uint32_t op, minor, minor2, mips32_op;
15237 uint32_t cond, fmt, cc;
15239 insn = translator_lduw(env, ctx->base.pc_next + 2);
15240 ctx->opcode = (ctx->opcode << 16) | insn;
15242 rt = (ctx->opcode >> 21) & 0x1f;
15243 rs = (ctx->opcode >> 16) & 0x1f;
15244 rd = (ctx->opcode >> 11) & 0x1f;
15245 rr = (ctx->opcode >> 6) & 0x1f;
15246 imm = (int16_t) ctx->opcode;
15248 op = (ctx->opcode >> 26) & 0x3f;
15249 switch (op) {
15250 case POOL32A:
15251 minor = ctx->opcode & 0x3f;
15252 switch (minor) {
15253 case 0x00:
15254 minor = (ctx->opcode >> 6) & 0xf;
15255 switch (minor) {
15256 case SLL32:
15257 mips32_op = OPC_SLL;
15258 goto do_shifti;
15259 case SRA:
15260 mips32_op = OPC_SRA;
15261 goto do_shifti;
15262 case SRL32:
15263 mips32_op = OPC_SRL;
15264 goto do_shifti;
15265 case ROTR:
15266 mips32_op = OPC_ROTR;
15267 do_shifti:
15268 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15269 break;
15270 case SELEQZ:
15271 check_insn(ctx, ISA_MIPS_R6);
15272 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15273 break;
15274 case SELNEZ:
15275 check_insn(ctx, ISA_MIPS_R6);
15276 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15277 break;
15278 case R6_RDHWR:
15279 check_insn(ctx, ISA_MIPS_R6);
15280 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15281 break;
15282 default:
15283 goto pool32a_invalid;
15285 break;
15286 case 0x10:
15287 minor = (ctx->opcode >> 6) & 0xf;
15288 switch (minor) {
15289 /* Arithmetic */
15290 case ADD:
15291 mips32_op = OPC_ADD;
15292 goto do_arith;
15293 case ADDU32:
15294 mips32_op = OPC_ADDU;
15295 goto do_arith;
15296 case SUB:
15297 mips32_op = OPC_SUB;
15298 goto do_arith;
15299 case SUBU32:
15300 mips32_op = OPC_SUBU;
15301 goto do_arith;
15302 case MUL:
15303 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15304 mips32_op = OPC_MUL;
15305 do_arith:
15306 gen_arith(ctx, mips32_op, rd, rs, rt);
15307 break;
15308 /* Shifts */
15309 case SLLV:
15310 mips32_op = OPC_SLLV;
15311 goto do_shift;
15312 case SRLV:
15313 mips32_op = OPC_SRLV;
15314 goto do_shift;
15315 case SRAV:
15316 mips32_op = OPC_SRAV;
15317 goto do_shift;
15318 case ROTRV:
15319 mips32_op = OPC_ROTRV;
15320 do_shift:
15321 gen_shift(ctx, mips32_op, rd, rs, rt);
15322 break;
15323 /* Logical operations */
15324 case AND:
15325 mips32_op = OPC_AND;
15326 goto do_logic;
15327 case OR32:
15328 mips32_op = OPC_OR;
15329 goto do_logic;
15330 case NOR:
15331 mips32_op = OPC_NOR;
15332 goto do_logic;
15333 case XOR32:
15334 mips32_op = OPC_XOR;
15335 do_logic:
15336 gen_logic(ctx, mips32_op, rd, rs, rt);
15337 break;
15338 /* Set less than */
15339 case SLT:
15340 mips32_op = OPC_SLT;
15341 goto do_slt;
15342 case SLTU:
15343 mips32_op = OPC_SLTU;
15344 do_slt:
15345 gen_slt(ctx, mips32_op, rd, rs, rt);
15346 break;
15347 default:
15348 goto pool32a_invalid;
15350 break;
15351 case 0x18:
15352 minor = (ctx->opcode >> 6) & 0xf;
15353 switch (minor) {
15354 /* Conditional moves */
15355 case MOVN: /* MUL */
15356 if (ctx->insn_flags & ISA_MIPS_R6) {
15357 /* MUL */
15358 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15359 } else {
15360 /* MOVN */
15361 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15363 break;
15364 case MOVZ: /* MUH */
15365 if (ctx->insn_flags & ISA_MIPS_R6) {
15366 /* MUH */
15367 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15368 } else {
15369 /* MOVZ */
15370 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15372 break;
15373 case MULU:
15374 check_insn(ctx, ISA_MIPS_R6);
15375 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15376 break;
15377 case MUHU:
15378 check_insn(ctx, ISA_MIPS_R6);
15379 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15380 break;
15381 case LWXS: /* DIV */
15382 if (ctx->insn_flags & ISA_MIPS_R6) {
15383 /* DIV */
15384 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15385 } else {
15386 /* LWXS */
15387 gen_ldxs(ctx, rs, rt, rd);
15389 break;
15390 case MOD:
15391 check_insn(ctx, ISA_MIPS_R6);
15392 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15393 break;
15394 case R6_DIVU:
15395 check_insn(ctx, ISA_MIPS_R6);
15396 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15397 break;
15398 case MODU:
15399 check_insn(ctx, ISA_MIPS_R6);
15400 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15401 break;
15402 default:
15403 goto pool32a_invalid;
15405 break;
15406 case INS:
15407 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15408 return;
15409 case LSA:
15410 check_insn(ctx, ISA_MIPS_R6);
15411 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2));
15412 break;
15413 case ALIGN:
15414 check_insn(ctx, ISA_MIPS_R6);
15415 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15416 break;
15417 case EXT:
15418 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15419 return;
15420 case POOL32AXF:
15421 gen_pool32axf(env, ctx, rt, rs);
15422 break;
15423 case BREAK32:
15424 generate_exception_end(ctx, EXCP_BREAK);
15425 break;
15426 case SIGRIE:
15427 check_insn(ctx, ISA_MIPS_R6);
15428 gen_reserved_instruction(ctx);
15429 break;
15430 default:
15431 pool32a_invalid:
15432 MIPS_INVAL("pool32a");
15433 gen_reserved_instruction(ctx);
15434 break;
15436 break;
15437 case POOL32B:
15438 minor = (ctx->opcode >> 12) & 0xf;
15439 switch (minor) {
15440 case CACHE:
15441 check_cp0_enabled(ctx);
15442 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15443 gen_cache_operation(ctx, rt, rs, imm);
15445 break;
15446 case LWC2:
15447 case SWC2:
15448 /* COP2: Not implemented. */
15449 generate_exception_err(ctx, EXCP_CpU, 2);
15450 break;
15451 #ifdef TARGET_MIPS64
15452 case LDP:
15453 case SDP:
15454 check_insn(ctx, ISA_MIPS3);
15455 check_mips_64(ctx);
15456 #endif
15457 /* fall through */
15458 case LWP:
15459 case SWP:
15460 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15461 break;
15462 #ifdef TARGET_MIPS64
15463 case LDM:
15464 case SDM:
15465 check_insn(ctx, ISA_MIPS3);
15466 check_mips_64(ctx);
15467 #endif
15468 /* fall through */
15469 case LWM32:
15470 case SWM32:
15471 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15472 break;
15473 default:
15474 MIPS_INVAL("pool32b");
15475 gen_reserved_instruction(ctx);
15476 break;
15478 break;
15479 case POOL32F:
15480 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15481 minor = ctx->opcode & 0x3f;
15482 check_cp1_enabled(ctx);
15483 switch (minor) {
15484 case ALNV_PS:
15485 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15486 mips32_op = OPC_ALNV_PS;
15487 goto do_madd;
15488 case MADD_S:
15489 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15490 mips32_op = OPC_MADD_S;
15491 goto do_madd;
15492 case MADD_D:
15493 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15494 mips32_op = OPC_MADD_D;
15495 goto do_madd;
15496 case MADD_PS:
15497 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15498 mips32_op = OPC_MADD_PS;
15499 goto do_madd;
15500 case MSUB_S:
15501 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15502 mips32_op = OPC_MSUB_S;
15503 goto do_madd;
15504 case MSUB_D:
15505 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15506 mips32_op = OPC_MSUB_D;
15507 goto do_madd;
15508 case MSUB_PS:
15509 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15510 mips32_op = OPC_MSUB_PS;
15511 goto do_madd;
15512 case NMADD_S:
15513 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15514 mips32_op = OPC_NMADD_S;
15515 goto do_madd;
15516 case NMADD_D:
15517 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15518 mips32_op = OPC_NMADD_D;
15519 goto do_madd;
15520 case NMADD_PS:
15521 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15522 mips32_op = OPC_NMADD_PS;
15523 goto do_madd;
15524 case NMSUB_S:
15525 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15526 mips32_op = OPC_NMSUB_S;
15527 goto do_madd;
15528 case NMSUB_D:
15529 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15530 mips32_op = OPC_NMSUB_D;
15531 goto do_madd;
15532 case NMSUB_PS:
15533 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15534 mips32_op = OPC_NMSUB_PS;
15535 do_madd:
15536 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15537 break;
15538 case CABS_COND_FMT:
15539 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15540 cond = (ctx->opcode >> 6) & 0xf;
15541 cc = (ctx->opcode >> 13) & 0x7;
15542 fmt = (ctx->opcode >> 10) & 0x3;
15543 switch (fmt) {
15544 case 0x0:
15545 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15546 break;
15547 case 0x1:
15548 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15549 break;
15550 case 0x2:
15551 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15552 break;
15553 default:
15554 goto pool32f_invalid;
15556 break;
15557 case C_COND_FMT:
15558 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15559 cond = (ctx->opcode >> 6) & 0xf;
15560 cc = (ctx->opcode >> 13) & 0x7;
15561 fmt = (ctx->opcode >> 10) & 0x3;
15562 switch (fmt) {
15563 case 0x0:
15564 gen_cmp_s(ctx, cond, rt, rs, cc);
15565 break;
15566 case 0x1:
15567 gen_cmp_d(ctx, cond, rt, rs, cc);
15568 break;
15569 case 0x2:
15570 gen_cmp_ps(ctx, cond, rt, rs, cc);
15571 break;
15572 default:
15573 goto pool32f_invalid;
15575 break;
15576 case CMP_CONDN_S:
15577 check_insn(ctx, ISA_MIPS_R6);
15578 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15579 break;
15580 case CMP_CONDN_D:
15581 check_insn(ctx, ISA_MIPS_R6);
15582 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15583 break;
15584 case POOL32FXF:
15585 gen_pool32fxf(ctx, rt, rs);
15586 break;
15587 case 0x00:
15588 /* PLL foo */
15589 switch ((ctx->opcode >> 6) & 0x7) {
15590 case PLL_PS:
15591 mips32_op = OPC_PLL_PS;
15592 goto do_ps;
15593 case PLU_PS:
15594 mips32_op = OPC_PLU_PS;
15595 goto do_ps;
15596 case PUL_PS:
15597 mips32_op = OPC_PUL_PS;
15598 goto do_ps;
15599 case PUU_PS:
15600 mips32_op = OPC_PUU_PS;
15601 goto do_ps;
15602 case CVT_PS_S:
15603 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15604 mips32_op = OPC_CVT_PS_S;
15605 do_ps:
15606 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15607 break;
15608 default:
15609 goto pool32f_invalid;
15611 break;
15612 case MIN_FMT:
15613 check_insn(ctx, ISA_MIPS_R6);
15614 switch ((ctx->opcode >> 9) & 0x3) {
15615 case FMT_SDPS_S:
15616 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15617 break;
15618 case FMT_SDPS_D:
15619 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15620 break;
15621 default:
15622 goto pool32f_invalid;
15624 break;
15625 case 0x08:
15626 /* [LS][WDU]XC1 */
15627 switch ((ctx->opcode >> 6) & 0x7) {
15628 case LWXC1:
15629 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15630 mips32_op = OPC_LWXC1;
15631 goto do_ldst_cp1;
15632 case SWXC1:
15633 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15634 mips32_op = OPC_SWXC1;
15635 goto do_ldst_cp1;
15636 case LDXC1:
15637 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15638 mips32_op = OPC_LDXC1;
15639 goto do_ldst_cp1;
15640 case SDXC1:
15641 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15642 mips32_op = OPC_SDXC1;
15643 goto do_ldst_cp1;
15644 case LUXC1:
15645 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15646 mips32_op = OPC_LUXC1;
15647 goto do_ldst_cp1;
15648 case SUXC1:
15649 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15650 mips32_op = OPC_SUXC1;
15651 do_ldst_cp1:
15652 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15653 break;
15654 default:
15655 goto pool32f_invalid;
15657 break;
15658 case MAX_FMT:
15659 check_insn(ctx, ISA_MIPS_R6);
15660 switch ((ctx->opcode >> 9) & 0x3) {
15661 case FMT_SDPS_S:
15662 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
15663 break;
15664 case FMT_SDPS_D:
15665 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
15666 break;
15667 default:
15668 goto pool32f_invalid;
15670 break;
15671 case 0x18:
15672 /* 3D insns */
15673 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15674 fmt = (ctx->opcode >> 9) & 0x3;
15675 switch ((ctx->opcode >> 6) & 0x7) {
15676 case RSQRT2_FMT:
15677 switch (fmt) {
15678 case FMT_SDPS_S:
15679 mips32_op = OPC_RSQRT2_S;
15680 goto do_3d;
15681 case FMT_SDPS_D:
15682 mips32_op = OPC_RSQRT2_D;
15683 goto do_3d;
15684 case FMT_SDPS_PS:
15685 mips32_op = OPC_RSQRT2_PS;
15686 goto do_3d;
15687 default:
15688 goto pool32f_invalid;
15690 break;
15691 case RECIP2_FMT:
15692 switch (fmt) {
15693 case FMT_SDPS_S:
15694 mips32_op = OPC_RECIP2_S;
15695 goto do_3d;
15696 case FMT_SDPS_D:
15697 mips32_op = OPC_RECIP2_D;
15698 goto do_3d;
15699 case FMT_SDPS_PS:
15700 mips32_op = OPC_RECIP2_PS;
15701 goto do_3d;
15702 default:
15703 goto pool32f_invalid;
15705 break;
15706 case ADDR_PS:
15707 mips32_op = OPC_ADDR_PS;
15708 goto do_3d;
15709 case MULR_PS:
15710 mips32_op = OPC_MULR_PS;
15711 do_3d:
15712 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15713 break;
15714 default:
15715 goto pool32f_invalid;
15717 break;
15718 case 0x20:
15719 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
15720 cc = (ctx->opcode >> 13) & 0x7;
15721 fmt = (ctx->opcode >> 9) & 0x3;
15722 switch ((ctx->opcode >> 6) & 0x7) {
15723 case MOVF_FMT: /* RINT_FMT */
15724 if (ctx->insn_flags & ISA_MIPS_R6) {
15725 /* RINT_FMT */
15726 switch (fmt) {
15727 case FMT_SDPS_S:
15728 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
15729 break;
15730 case FMT_SDPS_D:
15731 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
15732 break;
15733 default:
15734 goto pool32f_invalid;
15736 } else {
15737 /* MOVF_FMT */
15738 switch (fmt) {
15739 case FMT_SDPS_S:
15740 gen_movcf_s(ctx, rs, rt, cc, 0);
15741 break;
15742 case FMT_SDPS_D:
15743 gen_movcf_d(ctx, rs, rt, cc, 0);
15744 break;
15745 case FMT_SDPS_PS:
15746 check_ps(ctx);
15747 gen_movcf_ps(ctx, rs, rt, cc, 0);
15748 break;
15749 default:
15750 goto pool32f_invalid;
15753 break;
15754 case MOVT_FMT: /* CLASS_FMT */
15755 if (ctx->insn_flags & ISA_MIPS_R6) {
15756 /* CLASS_FMT */
15757 switch (fmt) {
15758 case FMT_SDPS_S:
15759 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
15760 break;
15761 case FMT_SDPS_D:
15762 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
15763 break;
15764 default:
15765 goto pool32f_invalid;
15767 } else {
15768 /* MOVT_FMT */
15769 switch (fmt) {
15770 case FMT_SDPS_S:
15771 gen_movcf_s(ctx, rs, rt, cc, 1);
15772 break;
15773 case FMT_SDPS_D:
15774 gen_movcf_d(ctx, rs, rt, cc, 1);
15775 break;
15776 case FMT_SDPS_PS:
15777 check_ps(ctx);
15778 gen_movcf_ps(ctx, rs, rt, cc, 1);
15779 break;
15780 default:
15781 goto pool32f_invalid;
15784 break;
15785 case PREFX:
15786 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15787 break;
15788 default:
15789 goto pool32f_invalid;
15791 break;
15792 #define FINSN_3ARG_SDPS(prfx) \
15793 switch ((ctx->opcode >> 8) & 0x3) { \
15794 case FMT_SDPS_S: \
15795 mips32_op = OPC_##prfx##_S; \
15796 goto do_fpop; \
15797 case FMT_SDPS_D: \
15798 mips32_op = OPC_##prfx##_D; \
15799 goto do_fpop; \
15800 case FMT_SDPS_PS: \
15801 check_ps(ctx); \
15802 mips32_op = OPC_##prfx##_PS; \
15803 goto do_fpop; \
15804 default: \
15805 goto pool32f_invalid; \
15807 case MINA_FMT:
15808 check_insn(ctx, ISA_MIPS_R6);
15809 switch ((ctx->opcode >> 9) & 0x3) {
15810 case FMT_SDPS_S:
15811 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
15812 break;
15813 case FMT_SDPS_D:
15814 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
15815 break;
15816 default:
15817 goto pool32f_invalid;
15819 break;
15820 case MAXA_FMT:
15821 check_insn(ctx, ISA_MIPS_R6);
15822 switch ((ctx->opcode >> 9) & 0x3) {
15823 case FMT_SDPS_S:
15824 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
15825 break;
15826 case FMT_SDPS_D:
15827 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
15828 break;
15829 default:
15830 goto pool32f_invalid;
15832 break;
15833 case 0x30:
15834 /* regular FP ops */
15835 switch ((ctx->opcode >> 6) & 0x3) {
15836 case ADD_FMT:
15837 FINSN_3ARG_SDPS(ADD);
15838 break;
15839 case SUB_FMT:
15840 FINSN_3ARG_SDPS(SUB);
15841 break;
15842 case MUL_FMT:
15843 FINSN_3ARG_SDPS(MUL);
15844 break;
15845 case DIV_FMT:
15846 fmt = (ctx->opcode >> 8) & 0x3;
15847 if (fmt == 1) {
15848 mips32_op = OPC_DIV_D;
15849 } else if (fmt == 0) {
15850 mips32_op = OPC_DIV_S;
15851 } else {
15852 goto pool32f_invalid;
15854 goto do_fpop;
15855 default:
15856 goto pool32f_invalid;
15858 break;
15859 case 0x38:
15860 /* cmovs */
15861 switch ((ctx->opcode >> 6) & 0x7) {
15862 case MOVN_FMT: /* SELEQZ_FMT */
15863 if (ctx->insn_flags & ISA_MIPS_R6) {
15864 /* SELEQZ_FMT */
15865 switch ((ctx->opcode >> 9) & 0x3) {
15866 case FMT_SDPS_S:
15867 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
15868 break;
15869 case FMT_SDPS_D:
15870 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
15871 break;
15872 default:
15873 goto pool32f_invalid;
15875 } else {
15876 /* MOVN_FMT */
15877 FINSN_3ARG_SDPS(MOVN);
15879 break;
15880 case MOVN_FMT_04:
15881 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15882 FINSN_3ARG_SDPS(MOVN);
15883 break;
15884 case MOVZ_FMT: /* SELNEZ_FMT */
15885 if (ctx->insn_flags & ISA_MIPS_R6) {
15886 /* SELNEZ_FMT */
15887 switch ((ctx->opcode >> 9) & 0x3) {
15888 case FMT_SDPS_S:
15889 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
15890 break;
15891 case FMT_SDPS_D:
15892 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
15893 break;
15894 default:
15895 goto pool32f_invalid;
15897 } else {
15898 /* MOVZ_FMT */
15899 FINSN_3ARG_SDPS(MOVZ);
15901 break;
15902 case MOVZ_FMT_05:
15903 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15904 FINSN_3ARG_SDPS(MOVZ);
15905 break;
15906 case SEL_FMT:
15907 check_insn(ctx, ISA_MIPS_R6);
15908 switch ((ctx->opcode >> 9) & 0x3) {
15909 case FMT_SDPS_S:
15910 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
15911 break;
15912 case FMT_SDPS_D:
15913 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
15914 break;
15915 default:
15916 goto pool32f_invalid;
15918 break;
15919 case MADDF_FMT:
15920 check_insn(ctx, ISA_MIPS_R6);
15921 switch ((ctx->opcode >> 9) & 0x3) {
15922 case FMT_SDPS_S:
15923 mips32_op = OPC_MADDF_S;
15924 goto do_fpop;
15925 case FMT_SDPS_D:
15926 mips32_op = OPC_MADDF_D;
15927 goto do_fpop;
15928 default:
15929 goto pool32f_invalid;
15931 break;
15932 case MSUBF_FMT:
15933 check_insn(ctx, ISA_MIPS_R6);
15934 switch ((ctx->opcode >> 9) & 0x3) {
15935 case FMT_SDPS_S:
15936 mips32_op = OPC_MSUBF_S;
15937 goto do_fpop;
15938 case FMT_SDPS_D:
15939 mips32_op = OPC_MSUBF_D;
15940 goto do_fpop;
15941 default:
15942 goto pool32f_invalid;
15944 break;
15945 default:
15946 goto pool32f_invalid;
15948 break;
15949 do_fpop:
15950 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15951 break;
15952 default:
15953 pool32f_invalid:
15954 MIPS_INVAL("pool32f");
15955 gen_reserved_instruction(ctx);
15956 break;
15958 } else {
15959 generate_exception_err(ctx, EXCP_CpU, 1);
15961 break;
15962 case POOL32I:
15963 minor = (ctx->opcode >> 21) & 0x1f;
15964 switch (minor) {
15965 case BLTZ:
15966 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15967 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
15968 break;
15969 case BLTZAL:
15970 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15971 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
15972 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15973 break;
15974 case BLTZALS:
15975 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15976 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
15977 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15978 break;
15979 case BGEZ:
15980 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15981 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
15982 break;
15983 case BGEZAL:
15984 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15985 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
15986 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15987 break;
15988 case BGEZALS:
15989 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15990 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
15991 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15992 break;
15993 case BLEZ:
15994 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15995 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
15996 break;
15997 case BGTZ:
15998 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15999 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16000 break;
16002 /* Traps */
16003 case TLTI: /* BC1EQZC */
16004 if (ctx->insn_flags & ISA_MIPS_R6) {
16005 /* BC1EQZC */
16006 check_cp1_enabled(ctx);
16007 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16008 } else {
16009 /* TLTI */
16010 mips32_op = OPC_TLTI;
16011 goto do_trapi;
16013 break;
16014 case TGEI: /* BC1NEZC */
16015 if (ctx->insn_flags & ISA_MIPS_R6) {
16016 /* BC1NEZC */
16017 check_cp1_enabled(ctx);
16018 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16019 } else {
16020 /* TGEI */
16021 mips32_op = OPC_TGEI;
16022 goto do_trapi;
16024 break;
16025 case TLTIU:
16026 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16027 mips32_op = OPC_TLTIU;
16028 goto do_trapi;
16029 case TGEIU:
16030 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16031 mips32_op = OPC_TGEIU;
16032 goto do_trapi;
16033 case TNEI: /* SYNCI */
16034 if (ctx->insn_flags & ISA_MIPS_R6) {
16035 /* SYNCI */
16037 * Break the TB to be able to sync copied instructions
16038 * immediately.
16040 ctx->base.is_jmp = DISAS_STOP;
16041 } else {
16042 /* TNEI */
16043 mips32_op = OPC_TNEI;
16044 goto do_trapi;
16046 break;
16047 case TEQI:
16048 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16049 mips32_op = OPC_TEQI;
16050 do_trapi:
16051 gen_trap(ctx, mips32_op, rs, -1, imm);
16052 break;
16054 case BNEZC:
16055 case BEQZC:
16056 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16057 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16058 4, rs, 0, imm << 1, 0);
16060 * Compact branches don't have a delay slot, so just let
16061 * the normal delay slot handling take us to the branch
16062 * target.
16064 break;
16065 case LUI:
16066 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16067 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16068 break;
16069 case SYNCI:
16070 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16072 * Break the TB to be able to sync copied instructions
16073 * immediately.
16075 ctx->base.is_jmp = DISAS_STOP;
16076 break;
16077 case BC2F:
16078 case BC2T:
16079 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16080 /* COP2: Not implemented. */
16081 generate_exception_err(ctx, EXCP_CpU, 2);
16082 break;
16083 case BC1F:
16084 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16085 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16086 goto do_cp1branch;
16087 case BC1T:
16088 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16089 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16090 goto do_cp1branch;
16091 case BC1ANY4F:
16092 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16093 mips32_op = OPC_BC1FANY4;
16094 goto do_cp1mips3d;
16095 case BC1ANY4T:
16096 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16097 mips32_op = OPC_BC1TANY4;
16098 do_cp1mips3d:
16099 check_cop1x(ctx);
16100 check_insn(ctx, ASE_MIPS3D);
16101 /* Fall through */
16102 do_cp1branch:
16103 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16104 check_cp1_enabled(ctx);
16105 gen_compute_branch1(ctx, mips32_op,
16106 (ctx->opcode >> 18) & 0x7, imm << 1);
16107 } else {
16108 generate_exception_err(ctx, EXCP_CpU, 1);
16110 break;
16111 case BPOSGE64:
16112 case BPOSGE32:
16113 /* MIPS DSP: not implemented */
16114 /* Fall through */
16115 default:
16116 MIPS_INVAL("pool32i");
16117 gen_reserved_instruction(ctx);
16118 break;
16120 break;
16121 case POOL32C:
16122 minor = (ctx->opcode >> 12) & 0xf;
16123 offset = sextract32(ctx->opcode, 0,
16124 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
16125 switch (minor) {
16126 case LWL:
16127 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16128 mips32_op = OPC_LWL;
16129 goto do_ld_lr;
16130 case SWL:
16131 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16132 mips32_op = OPC_SWL;
16133 goto do_st_lr;
16134 case LWR:
16135 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16136 mips32_op = OPC_LWR;
16137 goto do_ld_lr;
16138 case SWR:
16139 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16140 mips32_op = OPC_SWR;
16141 goto do_st_lr;
16142 #if defined(TARGET_MIPS64)
16143 case LDL:
16144 check_insn(ctx, ISA_MIPS3);
16145 check_mips_64(ctx);
16146 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16147 mips32_op = OPC_LDL;
16148 goto do_ld_lr;
16149 case SDL:
16150 check_insn(ctx, ISA_MIPS3);
16151 check_mips_64(ctx);
16152 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16153 mips32_op = OPC_SDL;
16154 goto do_st_lr;
16155 case LDR:
16156 check_insn(ctx, ISA_MIPS3);
16157 check_mips_64(ctx);
16158 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16159 mips32_op = OPC_LDR;
16160 goto do_ld_lr;
16161 case SDR:
16162 check_insn(ctx, ISA_MIPS3);
16163 check_mips_64(ctx);
16164 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16165 mips32_op = OPC_SDR;
16166 goto do_st_lr;
16167 case LWU:
16168 check_insn(ctx, ISA_MIPS3);
16169 check_mips_64(ctx);
16170 mips32_op = OPC_LWU;
16171 goto do_ld_lr;
16172 case LLD:
16173 check_insn(ctx, ISA_MIPS3);
16174 check_mips_64(ctx);
16175 mips32_op = OPC_LLD;
16176 goto do_ld_lr;
16177 #endif
16178 case LL:
16179 mips32_op = OPC_LL;
16180 goto do_ld_lr;
16181 do_ld_lr:
16182 gen_ld(ctx, mips32_op, rt, rs, offset);
16183 break;
16184 do_st_lr:
16185 gen_st(ctx, mips32_op, rt, rs, offset);
16186 break;
16187 case SC:
16188 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
16189 break;
16190 #if defined(TARGET_MIPS64)
16191 case SCD:
16192 check_insn(ctx, ISA_MIPS3);
16193 check_mips_64(ctx);
16194 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
16195 break;
16196 #endif
16197 case LD_EVA:
16198 if (!ctx->eva) {
16199 MIPS_INVAL("pool32c ld-eva");
16200 gen_reserved_instruction(ctx);
16201 break;
16203 check_cp0_enabled(ctx);
16205 minor2 = (ctx->opcode >> 9) & 0x7;
16206 offset = sextract32(ctx->opcode, 0, 9);
16207 switch (minor2) {
16208 case LBUE:
16209 mips32_op = OPC_LBUE;
16210 goto do_ld_lr;
16211 case LHUE:
16212 mips32_op = OPC_LHUE;
16213 goto do_ld_lr;
16214 case LWLE:
16215 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16216 mips32_op = OPC_LWLE;
16217 goto do_ld_lr;
16218 case LWRE:
16219 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16220 mips32_op = OPC_LWRE;
16221 goto do_ld_lr;
16222 case LBE:
16223 mips32_op = OPC_LBE;
16224 goto do_ld_lr;
16225 case LHE:
16226 mips32_op = OPC_LHE;
16227 goto do_ld_lr;
16228 case LLE:
16229 mips32_op = OPC_LLE;
16230 goto do_ld_lr;
16231 case LWE:
16232 mips32_op = OPC_LWE;
16233 goto do_ld_lr;
16235 break;
16236 case ST_EVA:
16237 if (!ctx->eva) {
16238 MIPS_INVAL("pool32c st-eva");
16239 gen_reserved_instruction(ctx);
16240 break;
16242 check_cp0_enabled(ctx);
16244 minor2 = (ctx->opcode >> 9) & 0x7;
16245 offset = sextract32(ctx->opcode, 0, 9);
16246 switch (minor2) {
16247 case SWLE:
16248 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16249 mips32_op = OPC_SWLE;
16250 goto do_st_lr;
16251 case SWRE:
16252 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16253 mips32_op = OPC_SWRE;
16254 goto do_st_lr;
16255 case PREFE:
16256 /* Treat as no-op */
16257 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
16258 /* hint codes 24-31 are reserved and signal RI */
16259 generate_exception(ctx, EXCP_RI);
16261 break;
16262 case CACHEE:
16263 /* Treat as no-op */
16264 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16265 gen_cache_operation(ctx, rt, rs, offset);
16267 break;
16268 case SBE:
16269 mips32_op = OPC_SBE;
16270 goto do_st_lr;
16271 case SHE:
16272 mips32_op = OPC_SHE;
16273 goto do_st_lr;
16274 case SCE:
16275 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
16276 break;
16277 case SWE:
16278 mips32_op = OPC_SWE;
16279 goto do_st_lr;
16281 break;
16282 case PREF:
16283 /* Treat as no-op */
16284 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
16285 /* hint codes 24-31 are reserved and signal RI */
16286 generate_exception(ctx, EXCP_RI);
16288 break;
16289 default:
16290 MIPS_INVAL("pool32c");
16291 gen_reserved_instruction(ctx);
16292 break;
16294 break;
16295 case ADDI32: /* AUI, LUI */
16296 if (ctx->insn_flags & ISA_MIPS_R6) {
16297 /* AUI, LUI */
16298 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16299 } else {
16300 /* ADDI32 */
16301 mips32_op = OPC_ADDI;
16302 goto do_addi;
16304 break;
16305 case ADDIU32:
16306 mips32_op = OPC_ADDIU;
16307 do_addi:
16308 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16309 break;
16311 /* Logical operations */
16312 case ORI32:
16313 mips32_op = OPC_ORI;
16314 goto do_logici;
16315 case XORI32:
16316 mips32_op = OPC_XORI;
16317 goto do_logici;
16318 case ANDI32:
16319 mips32_op = OPC_ANDI;
16320 do_logici:
16321 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16322 break;
16324 /* Set less than immediate */
16325 case SLTI32:
16326 mips32_op = OPC_SLTI;
16327 goto do_slti;
16328 case SLTIU32:
16329 mips32_op = OPC_SLTIU;
16330 do_slti:
16331 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16332 break;
16333 case JALX32:
16334 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16335 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16336 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16337 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16338 break;
16339 case JALS32: /* BOVC, BEQC, BEQZALC */
16340 if (ctx->insn_flags & ISA_MIPS_R6) {
16341 if (rs >= rt) {
16342 /* BOVC */
16343 mips32_op = OPC_BOVC;
16344 } else if (rs < rt && rs == 0) {
16345 /* BEQZALC */
16346 mips32_op = OPC_BEQZALC;
16347 } else {
16348 /* BEQC */
16349 mips32_op = OPC_BEQC;
16351 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16352 } else {
16353 /* JALS32 */
16354 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16355 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16356 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16358 break;
16359 case BEQ32: /* BC */
16360 if (ctx->insn_flags & ISA_MIPS_R6) {
16361 /* BC */
16362 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16363 sextract32(ctx->opcode << 1, 0, 27));
16364 } else {
16365 /* BEQ32 */
16366 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16368 break;
16369 case BNE32: /* BALC */
16370 if (ctx->insn_flags & ISA_MIPS_R6) {
16371 /* BALC */
16372 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16373 sextract32(ctx->opcode << 1, 0, 27));
16374 } else {
16375 /* BNE32 */
16376 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16378 break;
16379 case J32: /* BGTZC, BLTZC, BLTC */
16380 if (ctx->insn_flags & ISA_MIPS_R6) {
16381 if (rs == 0 && rt != 0) {
16382 /* BGTZC */
16383 mips32_op = OPC_BGTZC;
16384 } else if (rs != 0 && rt != 0 && rs == rt) {
16385 /* BLTZC */
16386 mips32_op = OPC_BLTZC;
16387 } else {
16388 /* BLTC */
16389 mips32_op = OPC_BLTC;
16391 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16392 } else {
16393 /* J32 */
16394 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16395 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16397 break;
16398 case JAL32: /* BLEZC, BGEZC, BGEC */
16399 if (ctx->insn_flags & ISA_MIPS_R6) {
16400 if (rs == 0 && rt != 0) {
16401 /* BLEZC */
16402 mips32_op = OPC_BLEZC;
16403 } else if (rs != 0 && rt != 0 && rs == rt) {
16404 /* BGEZC */
16405 mips32_op = OPC_BGEZC;
16406 } else {
16407 /* BGEC */
16408 mips32_op = OPC_BGEC;
16410 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16411 } else {
16412 /* JAL32 */
16413 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16414 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16415 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16417 break;
16418 /* Floating point (COP1) */
16419 case LWC132:
16420 mips32_op = OPC_LWC1;
16421 goto do_cop1;
16422 case LDC132:
16423 mips32_op = OPC_LDC1;
16424 goto do_cop1;
16425 case SWC132:
16426 mips32_op = OPC_SWC1;
16427 goto do_cop1;
16428 case SDC132:
16429 mips32_op = OPC_SDC1;
16430 do_cop1:
16431 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16432 break;
16433 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16434 if (ctx->insn_flags & ISA_MIPS_R6) {
16435 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16436 switch ((ctx->opcode >> 16) & 0x1f) {
16437 case ADDIUPC_00:
16438 case ADDIUPC_01:
16439 case ADDIUPC_02:
16440 case ADDIUPC_03:
16441 case ADDIUPC_04:
16442 case ADDIUPC_05:
16443 case ADDIUPC_06:
16444 case ADDIUPC_07:
16445 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16446 break;
16447 case AUIPC:
16448 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16449 break;
16450 case ALUIPC:
16451 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16452 break;
16453 case LWPC_08:
16454 case LWPC_09:
16455 case LWPC_0A:
16456 case LWPC_0B:
16457 case LWPC_0C:
16458 case LWPC_0D:
16459 case LWPC_0E:
16460 case LWPC_0F:
16461 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16462 break;
16463 default:
16464 generate_exception(ctx, EXCP_RI);
16465 break;
16467 } else {
16468 /* ADDIUPC */
16469 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16470 offset = SIMM(ctx->opcode, 0, 23) << 2;
16472 gen_addiupc(ctx, reg, offset, 0, 0);
16474 break;
16475 case BNVC: /* BNEC, BNEZALC */
16476 check_insn(ctx, ISA_MIPS_R6);
16477 if (rs >= rt) {
16478 /* BNVC */
16479 mips32_op = OPC_BNVC;
16480 } else if (rs < rt && rs == 0) {
16481 /* BNEZALC */
16482 mips32_op = OPC_BNEZALC;
16483 } else {
16484 /* BNEC */
16485 mips32_op = OPC_BNEC;
16487 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16488 break;
16489 case R6_BNEZC: /* JIALC */
16490 check_insn(ctx, ISA_MIPS_R6);
16491 if (rt != 0) {
16492 /* BNEZC */
16493 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16494 sextract32(ctx->opcode << 1, 0, 22));
16495 } else {
16496 /* JIALC */
16497 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16499 break;
16500 case R6_BEQZC: /* JIC */
16501 check_insn(ctx, ISA_MIPS_R6);
16502 if (rt != 0) {
16503 /* BEQZC */
16504 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16505 sextract32(ctx->opcode << 1, 0, 22));
16506 } else {
16507 /* JIC */
16508 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16510 break;
16511 case BLEZALC: /* BGEZALC, BGEUC */
16512 check_insn(ctx, ISA_MIPS_R6);
16513 if (rs == 0 && rt != 0) {
16514 /* BLEZALC */
16515 mips32_op = OPC_BLEZALC;
16516 } else if (rs != 0 && rt != 0 && rs == rt) {
16517 /* BGEZALC */
16518 mips32_op = OPC_BGEZALC;
16519 } else {
16520 /* BGEUC */
16521 mips32_op = OPC_BGEUC;
16523 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16524 break;
16525 case BGTZALC: /* BLTZALC, BLTUC */
16526 check_insn(ctx, ISA_MIPS_R6);
16527 if (rs == 0 && rt != 0) {
16528 /* BGTZALC */
16529 mips32_op = OPC_BGTZALC;
16530 } else if (rs != 0 && rt != 0 && rs == rt) {
16531 /* BLTZALC */
16532 mips32_op = OPC_BLTZALC;
16533 } else {
16534 /* BLTUC */
16535 mips32_op = OPC_BLTUC;
16537 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16538 break;
16539 /* Loads and stores */
16540 case LB32:
16541 mips32_op = OPC_LB;
16542 goto do_ld;
16543 case LBU32:
16544 mips32_op = OPC_LBU;
16545 goto do_ld;
16546 case LH32:
16547 mips32_op = OPC_LH;
16548 goto do_ld;
16549 case LHU32:
16550 mips32_op = OPC_LHU;
16551 goto do_ld;
16552 case LW32:
16553 mips32_op = OPC_LW;
16554 goto do_ld;
16555 #ifdef TARGET_MIPS64
16556 case LD32:
16557 check_insn(ctx, ISA_MIPS3);
16558 check_mips_64(ctx);
16559 mips32_op = OPC_LD;
16560 goto do_ld;
16561 case SD32:
16562 check_insn(ctx, ISA_MIPS3);
16563 check_mips_64(ctx);
16564 mips32_op = OPC_SD;
16565 goto do_st;
16566 #endif
16567 case SB32:
16568 mips32_op = OPC_SB;
16569 goto do_st;
16570 case SH32:
16571 mips32_op = OPC_SH;
16572 goto do_st;
16573 case SW32:
16574 mips32_op = OPC_SW;
16575 goto do_st;
16576 do_ld:
16577 gen_ld(ctx, mips32_op, rt, rs, imm);
16578 break;
16579 do_st:
16580 gen_st(ctx, mips32_op, rt, rs, imm);
16581 break;
16582 default:
16583 gen_reserved_instruction(ctx);
16584 break;
16588 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
16590 uint32_t op;
16592 /* make sure instructions are on a halfword boundary */
16593 if (ctx->base.pc_next & 0x1) {
16594 env->CP0_BadVAddr = ctx->base.pc_next;
16595 generate_exception_end(ctx, EXCP_AdEL);
16596 return 2;
16599 op = (ctx->opcode >> 10) & 0x3f;
16600 /* Enforce properly-sized instructions in a delay slot */
16601 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16602 switch (op & 0x7) { /* MSB-3..MSB-5 */
16603 case 0:
16604 /* POOL32A, POOL32B, POOL32I, POOL32C */
16605 case 4:
16606 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16607 case 5:
16608 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16609 case 6:
16610 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16611 case 7:
16612 /* LB32, LH32, LWC132, LDC132, LW32 */
16613 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16614 gen_reserved_instruction(ctx);
16615 return 2;
16617 break;
16618 case 1:
16619 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16620 case 2:
16621 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16622 case 3:
16623 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16624 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16625 gen_reserved_instruction(ctx);
16626 return 2;
16628 break;
16632 switch (op) {
16633 case POOL16A:
16635 int rd = mmreg(uMIPS_RD(ctx->opcode));
16636 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16637 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16638 uint32_t opc = 0;
16640 switch (ctx->opcode & 0x1) {
16641 case ADDU16:
16642 opc = OPC_ADDU;
16643 break;
16644 case SUBU16:
16645 opc = OPC_SUBU;
16646 break;
16648 if (ctx->insn_flags & ISA_MIPS_R6) {
16650 * In the Release 6, the register number location in
16651 * the instruction encoding has changed.
16653 gen_arith(ctx, opc, rs1, rd, rs2);
16654 } else {
16655 gen_arith(ctx, opc, rd, rs1, rs2);
16658 break;
16659 case POOL16B:
16661 int rd = mmreg(uMIPS_RD(ctx->opcode));
16662 int rs = mmreg(uMIPS_RS(ctx->opcode));
16663 int amount = (ctx->opcode >> 1) & 0x7;
16664 uint32_t opc = 0;
16665 amount = amount == 0 ? 8 : amount;
16667 switch (ctx->opcode & 0x1) {
16668 case SLL16:
16669 opc = OPC_SLL;
16670 break;
16671 case SRL16:
16672 opc = OPC_SRL;
16673 break;
16676 gen_shift_imm(ctx, opc, rd, rs, amount);
16678 break;
16679 case POOL16C:
16680 if (ctx->insn_flags & ISA_MIPS_R6) {
16681 gen_pool16c_r6_insn(ctx);
16682 } else {
16683 gen_pool16c_insn(ctx);
16685 break;
16686 case LWGP16:
16688 int rd = mmreg(uMIPS_RD(ctx->opcode));
16689 int rb = 28; /* GP */
16690 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
16692 gen_ld(ctx, OPC_LW, rd, rb, offset);
16694 break;
16695 case POOL16F:
16696 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16697 if (ctx->opcode & 1) {
16698 gen_reserved_instruction(ctx);
16699 } else {
16700 /* MOVEP */
16701 int enc_dest = uMIPS_RD(ctx->opcode);
16702 int enc_rt = uMIPS_RS2(ctx->opcode);
16703 int enc_rs = uMIPS_RS1(ctx->opcode);
16704 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
16706 break;
16707 case LBU16:
16709 int rd = mmreg(uMIPS_RD(ctx->opcode));
16710 int rb = mmreg(uMIPS_RS(ctx->opcode));
16711 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16712 offset = (offset == 0xf ? -1 : offset);
16714 gen_ld(ctx, OPC_LBU, rd, rb, offset);
16716 break;
16717 case LHU16:
16719 int rd = mmreg(uMIPS_RD(ctx->opcode));
16720 int rb = mmreg(uMIPS_RS(ctx->opcode));
16721 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16723 gen_ld(ctx, OPC_LHU, rd, rb, offset);
16725 break;
16726 case LWSP16:
16728 int rd = (ctx->opcode >> 5) & 0x1f;
16729 int rb = 29; /* SP */
16730 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16732 gen_ld(ctx, OPC_LW, rd, rb, offset);
16734 break;
16735 case LW16:
16737 int rd = mmreg(uMIPS_RD(ctx->opcode));
16738 int rb = mmreg(uMIPS_RS(ctx->opcode));
16739 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16741 gen_ld(ctx, OPC_LW, rd, rb, offset);
16743 break;
16744 case SB16:
16746 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16747 int rb = mmreg(uMIPS_RS(ctx->opcode));
16748 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16750 gen_st(ctx, OPC_SB, rd, rb, offset);
16752 break;
16753 case SH16:
16755 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16756 int rb = mmreg(uMIPS_RS(ctx->opcode));
16757 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16759 gen_st(ctx, OPC_SH, rd, rb, offset);
16761 break;
16762 case SWSP16:
16764 int rd = (ctx->opcode >> 5) & 0x1f;
16765 int rb = 29; /* SP */
16766 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16768 gen_st(ctx, OPC_SW, rd, rb, offset);
16770 break;
16771 case SW16:
16773 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16774 int rb = mmreg(uMIPS_RS(ctx->opcode));
16775 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16777 gen_st(ctx, OPC_SW, rd, rb, offset);
16779 break;
16780 case MOVE16:
16782 int rd = uMIPS_RD5(ctx->opcode);
16783 int rs = uMIPS_RS5(ctx->opcode);
16785 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
16787 break;
16788 case ANDI16:
16789 gen_andi16(ctx);
16790 break;
16791 case POOL16D:
16792 switch (ctx->opcode & 0x1) {
16793 case ADDIUS5:
16794 gen_addius5(ctx);
16795 break;
16796 case ADDIUSP:
16797 gen_addiusp(ctx);
16798 break;
16800 break;
16801 case POOL16E:
16802 switch (ctx->opcode & 0x1) {
16803 case ADDIUR2:
16804 gen_addiur2(ctx);
16805 break;
16806 case ADDIUR1SP:
16807 gen_addiur1sp(ctx);
16808 break;
16810 break;
16811 case B16: /* BC16 */
16812 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
16813 sextract32(ctx->opcode, 0, 10) << 1,
16814 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
16815 break;
16816 case BNEZ16: /* BNEZC16 */
16817 case BEQZ16: /* BEQZC16 */
16818 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
16819 mmreg(uMIPS_RD(ctx->opcode)),
16820 0, sextract32(ctx->opcode, 0, 7) << 1,
16821 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
16823 break;
16824 case LI16:
16826 int reg = mmreg(uMIPS_RD(ctx->opcode));
16827 int imm = ZIMM(ctx->opcode, 0, 7);
16829 imm = (imm == 0x7f ? -1 : imm);
16830 tcg_gen_movi_tl(cpu_gpr[reg], imm);
16832 break;
16833 case RES_29:
16834 case RES_31:
16835 case RES_39:
16836 gen_reserved_instruction(ctx);
16837 break;
16838 default:
16839 decode_micromips32_opc(env, ctx);
16840 return 4;
16843 return 2;
16848 * nanoMIPS opcodes
16852 /* MAJOR, P16, and P32 pools opcodes */
16853 enum {
16854 NM_P_ADDIU = 0x00,
16855 NM_ADDIUPC = 0x01,
16856 NM_MOVE_BALC = 0x02,
16857 NM_P16_MV = 0x04,
16858 NM_LW16 = 0x05,
16859 NM_BC16 = 0x06,
16860 NM_P16_SR = 0x07,
16862 NM_POOL32A = 0x08,
16863 NM_P_BAL = 0x0a,
16864 NM_P16_SHIFT = 0x0c,
16865 NM_LWSP16 = 0x0d,
16866 NM_BALC16 = 0x0e,
16867 NM_P16_4X4 = 0x0f,
16869 NM_P_GP_W = 0x10,
16870 NM_P_GP_BH = 0x11,
16871 NM_P_J = 0x12,
16872 NM_P16C = 0x14,
16873 NM_LWGP16 = 0x15,
16874 NM_P16_LB = 0x17,
16876 NM_P48I = 0x18,
16877 NM_P16_A1 = 0x1c,
16878 NM_LW4X4 = 0x1d,
16879 NM_P16_LH = 0x1f,
16881 NM_P_U12 = 0x20,
16882 NM_P_LS_U12 = 0x21,
16883 NM_P_BR1 = 0x22,
16884 NM_P16_A2 = 0x24,
16885 NM_SW16 = 0x25,
16886 NM_BEQZC16 = 0x26,
16888 NM_POOL32F = 0x28,
16889 NM_P_LS_S9 = 0x29,
16890 NM_P_BR2 = 0x2a,
16892 NM_P16_ADDU = 0x2c,
16893 NM_SWSP16 = 0x2d,
16894 NM_BNEZC16 = 0x2e,
16895 NM_MOVEP = 0x2f,
16897 NM_POOL32S = 0x30,
16898 NM_P_BRI = 0x32,
16899 NM_LI16 = 0x34,
16900 NM_SWGP16 = 0x35,
16901 NM_P16_BR = 0x36,
16903 NM_P_LUI = 0x38,
16904 NM_ANDI16 = 0x3c,
16905 NM_SW4X4 = 0x3d,
16906 NM_MOVEPREV = 0x3f,
16909 /* POOL32A instruction pool */
16910 enum {
16911 NM_POOL32A0 = 0x00,
16912 NM_SPECIAL2 = 0x01,
16913 NM_COP2_1 = 0x02,
16914 NM_UDI = 0x03,
16915 NM_POOL32A5 = 0x05,
16916 NM_POOL32A7 = 0x07,
16919 /* P.GP.W instruction pool */
16920 enum {
16921 NM_ADDIUGP_W = 0x00,
16922 NM_LWGP = 0x02,
16923 NM_SWGP = 0x03,
16926 /* P48I instruction pool */
16927 enum {
16928 NM_LI48 = 0x00,
16929 NM_ADDIU48 = 0x01,
16930 NM_ADDIUGP48 = 0x02,
16931 NM_ADDIUPC48 = 0x03,
16932 NM_LWPC48 = 0x0b,
16933 NM_SWPC48 = 0x0f,
16936 /* P.U12 instruction pool */
16937 enum {
16938 NM_ORI = 0x00,
16939 NM_XORI = 0x01,
16940 NM_ANDI = 0x02,
16941 NM_P_SR = 0x03,
16942 NM_SLTI = 0x04,
16943 NM_SLTIU = 0x05,
16944 NM_SEQI = 0x06,
16945 NM_ADDIUNEG = 0x08,
16946 NM_P_SHIFT = 0x0c,
16947 NM_P_ROTX = 0x0d,
16948 NM_P_INS = 0x0e,
16949 NM_P_EXT = 0x0f,
16952 /* POOL32F instruction pool */
16953 enum {
16954 NM_POOL32F_0 = 0x00,
16955 NM_POOL32F_3 = 0x03,
16956 NM_POOL32F_5 = 0x05,
16959 /* POOL32S instruction pool */
16960 enum {
16961 NM_POOL32S_0 = 0x00,
16962 NM_POOL32S_4 = 0x04,
16965 /* P.LUI instruction pool */
16966 enum {
16967 NM_LUI = 0x00,
16968 NM_ALUIPC = 0x01,
16971 /* P.GP.BH instruction pool */
16972 enum {
16973 NM_LBGP = 0x00,
16974 NM_SBGP = 0x01,
16975 NM_LBUGP = 0x02,
16976 NM_ADDIUGP_B = 0x03,
16977 NM_P_GP_LH = 0x04,
16978 NM_P_GP_SH = 0x05,
16979 NM_P_GP_CP1 = 0x06,
16982 /* P.LS.U12 instruction pool */
16983 enum {
16984 NM_LB = 0x00,
16985 NM_SB = 0x01,
16986 NM_LBU = 0x02,
16987 NM_P_PREFU12 = 0x03,
16988 NM_LH = 0x04,
16989 NM_SH = 0x05,
16990 NM_LHU = 0x06,
16991 NM_LWU = 0x07,
16992 NM_LW = 0x08,
16993 NM_SW = 0x09,
16994 NM_LWC1 = 0x0a,
16995 NM_SWC1 = 0x0b,
16996 NM_LDC1 = 0x0e,
16997 NM_SDC1 = 0x0f,
17000 /* P.LS.S9 instruction pool */
17001 enum {
17002 NM_P_LS_S0 = 0x00,
17003 NM_P_LS_S1 = 0x01,
17004 NM_P_LS_E0 = 0x02,
17005 NM_P_LS_WM = 0x04,
17006 NM_P_LS_UAWM = 0x05,
17009 /* P.BAL instruction pool */
17010 enum {
17011 NM_BC = 0x00,
17012 NM_BALC = 0x01,
17015 /* P.J instruction pool */
17016 enum {
17017 NM_JALRC = 0x00,
17018 NM_JALRC_HB = 0x01,
17019 NM_P_BALRSC = 0x08,
17022 /* P.BR1 instruction pool */
17023 enum {
17024 NM_BEQC = 0x00,
17025 NM_P_BR3A = 0x01,
17026 NM_BGEC = 0x02,
17027 NM_BGEUC = 0x03,
17030 /* P.BR2 instruction pool */
17031 enum {
17032 NM_BNEC = 0x00,
17033 NM_BLTC = 0x02,
17034 NM_BLTUC = 0x03,
17037 /* P.BRI instruction pool */
17038 enum {
17039 NM_BEQIC = 0x00,
17040 NM_BBEQZC = 0x01,
17041 NM_BGEIC = 0x02,
17042 NM_BGEIUC = 0x03,
17043 NM_BNEIC = 0x04,
17044 NM_BBNEZC = 0x05,
17045 NM_BLTIC = 0x06,
17046 NM_BLTIUC = 0x07,
17049 /* P16.SHIFT instruction pool */
17050 enum {
17051 NM_SLL16 = 0x00,
17052 NM_SRL16 = 0x01,
17055 /* POOL16C instruction pool */
17056 enum {
17057 NM_POOL16C_0 = 0x00,
17058 NM_LWXS16 = 0x01,
17061 /* P16.A1 instruction pool */
17062 enum {
17063 NM_ADDIUR1SP = 0x01,
17066 /* P16.A2 instruction pool */
17067 enum {
17068 NM_ADDIUR2 = 0x00,
17069 NM_P_ADDIURS5 = 0x01,
17072 /* P16.ADDU instruction pool */
17073 enum {
17074 NM_ADDU16 = 0x00,
17075 NM_SUBU16 = 0x01,
17078 /* P16.SR instruction pool */
17079 enum {
17080 NM_SAVE16 = 0x00,
17081 NM_RESTORE_JRC16 = 0x01,
17084 /* P16.4X4 instruction pool */
17085 enum {
17086 NM_ADDU4X4 = 0x00,
17087 NM_MUL4X4 = 0x01,
17090 /* P16.LB instruction pool */
17091 enum {
17092 NM_LB16 = 0x00,
17093 NM_SB16 = 0x01,
17094 NM_LBU16 = 0x02,
17097 /* P16.LH instruction pool */
17098 enum {
17099 NM_LH16 = 0x00,
17100 NM_SH16 = 0x01,
17101 NM_LHU16 = 0x02,
17104 /* P.RI instruction pool */
17105 enum {
17106 NM_SIGRIE = 0x00,
17107 NM_P_SYSCALL = 0x01,
17108 NM_BREAK = 0x02,
17109 NM_SDBBP = 0x03,
17112 /* POOL32A0 instruction pool */
17113 enum {
17114 NM_P_TRAP = 0x00,
17115 NM_SEB = 0x01,
17116 NM_SLLV = 0x02,
17117 NM_MUL = 0x03,
17118 NM_MFC0 = 0x06,
17119 NM_MFHC0 = 0x07,
17120 NM_SEH = 0x09,
17121 NM_SRLV = 0x0a,
17122 NM_MUH = 0x0b,
17123 NM_MTC0 = 0x0e,
17124 NM_MTHC0 = 0x0f,
17125 NM_SRAV = 0x12,
17126 NM_MULU = 0x13,
17127 NM_ROTRV = 0x1a,
17128 NM_MUHU = 0x1b,
17129 NM_ADD = 0x22,
17130 NM_DIV = 0x23,
17131 NM_ADDU = 0x2a,
17132 NM_MOD = 0x2b,
17133 NM_SUB = 0x32,
17134 NM_DIVU = 0x33,
17135 NM_RDHWR = 0x38,
17136 NM_SUBU = 0x3a,
17137 NM_MODU = 0x3b,
17138 NM_P_CMOVE = 0x42,
17139 NM_FORK = 0x45,
17140 NM_MFTR = 0x46,
17141 NM_MFHTR = 0x47,
17142 NM_AND = 0x4a,
17143 NM_YIELD = 0x4d,
17144 NM_MTTR = 0x4e,
17145 NM_MTHTR = 0x4f,
17146 NM_OR = 0x52,
17147 NM_D_E_MT_VPE = 0x56,
17148 NM_NOR = 0x5a,
17149 NM_XOR = 0x62,
17150 NM_SLT = 0x6a,
17151 NM_P_SLTU = 0x72,
17152 NM_SOV = 0x7a,
17155 /* CRC32 instruction pool */
17156 enum {
17157 NM_CRC32B = 0x00,
17158 NM_CRC32H = 0x01,
17159 NM_CRC32W = 0x02,
17160 NM_CRC32CB = 0x04,
17161 NM_CRC32CH = 0x05,
17162 NM_CRC32CW = 0x06,
17165 /* POOL32A5 instruction pool */
17166 enum {
17167 NM_CMP_EQ_PH = 0x00,
17168 NM_CMP_LT_PH = 0x08,
17169 NM_CMP_LE_PH = 0x10,
17170 NM_CMPGU_EQ_QB = 0x18,
17171 NM_CMPGU_LT_QB = 0x20,
17172 NM_CMPGU_LE_QB = 0x28,
17173 NM_CMPGDU_EQ_QB = 0x30,
17174 NM_CMPGDU_LT_QB = 0x38,
17175 NM_CMPGDU_LE_QB = 0x40,
17176 NM_CMPU_EQ_QB = 0x48,
17177 NM_CMPU_LT_QB = 0x50,
17178 NM_CMPU_LE_QB = 0x58,
17179 NM_ADDQ_S_W = 0x60,
17180 NM_SUBQ_S_W = 0x68,
17181 NM_ADDSC = 0x70,
17182 NM_ADDWC = 0x78,
17184 NM_ADDQ_S_PH = 0x01,
17185 NM_ADDQH_R_PH = 0x09,
17186 NM_ADDQH_R_W = 0x11,
17187 NM_ADDU_S_QB = 0x19,
17188 NM_ADDU_S_PH = 0x21,
17189 NM_ADDUH_R_QB = 0x29,
17190 NM_SHRAV_R_PH = 0x31,
17191 NM_SHRAV_R_QB = 0x39,
17192 NM_SUBQ_S_PH = 0x41,
17193 NM_SUBQH_R_PH = 0x49,
17194 NM_SUBQH_R_W = 0x51,
17195 NM_SUBU_S_QB = 0x59,
17196 NM_SUBU_S_PH = 0x61,
17197 NM_SUBUH_R_QB = 0x69,
17198 NM_SHLLV_S_PH = 0x71,
17199 NM_PRECR_SRA_R_PH_W = 0x79,
17201 NM_MULEU_S_PH_QBL = 0x12,
17202 NM_MULEU_S_PH_QBR = 0x1a,
17203 NM_MULQ_RS_PH = 0x22,
17204 NM_MULQ_S_PH = 0x2a,
17205 NM_MULQ_RS_W = 0x32,
17206 NM_MULQ_S_W = 0x3a,
17207 NM_APPEND = 0x42,
17208 NM_MODSUB = 0x52,
17209 NM_SHRAV_R_W = 0x5a,
17210 NM_SHRLV_PH = 0x62,
17211 NM_SHRLV_QB = 0x6a,
17212 NM_SHLLV_QB = 0x72,
17213 NM_SHLLV_S_W = 0x7a,
17215 NM_SHILO = 0x03,
17217 NM_MULEQ_S_W_PHL = 0x04,
17218 NM_MULEQ_S_W_PHR = 0x0c,
17220 NM_MUL_S_PH = 0x05,
17221 NM_PRECR_QB_PH = 0x0d,
17222 NM_PRECRQ_QB_PH = 0x15,
17223 NM_PRECRQ_PH_W = 0x1d,
17224 NM_PRECRQ_RS_PH_W = 0x25,
17225 NM_PRECRQU_S_QB_PH = 0x2d,
17226 NM_PACKRL_PH = 0x35,
17227 NM_PICK_QB = 0x3d,
17228 NM_PICK_PH = 0x45,
17230 NM_SHRA_R_W = 0x5e,
17231 NM_SHRA_R_PH = 0x66,
17232 NM_SHLL_S_PH = 0x76,
17233 NM_SHLL_S_W = 0x7e,
17235 NM_REPL_PH = 0x07
17238 /* POOL32A7 instruction pool */
17239 enum {
17240 NM_P_LSX = 0x00,
17241 NM_LSA = 0x01,
17242 NM_EXTW = 0x03,
17243 NM_POOL32AXF = 0x07,
17246 /* P.SR instruction pool */
17247 enum {
17248 NM_PP_SR = 0x00,
17249 NM_P_SR_F = 0x01,
17252 /* P.SHIFT instruction pool */
17253 enum {
17254 NM_P_SLL = 0x00,
17255 NM_SRL = 0x02,
17256 NM_SRA = 0x04,
17257 NM_ROTR = 0x06,
17260 /* P.ROTX instruction pool */
17261 enum {
17262 NM_ROTX = 0x00,
17265 /* P.INS instruction pool */
17266 enum {
17267 NM_INS = 0x00,
17270 /* P.EXT instruction pool */
17271 enum {
17272 NM_EXT = 0x00,
17275 /* POOL32F_0 (fmt) instruction pool */
17276 enum {
17277 NM_RINT_S = 0x04,
17278 NM_RINT_D = 0x44,
17279 NM_ADD_S = 0x06,
17280 NM_SELEQZ_S = 0x07,
17281 NM_SELEQZ_D = 0x47,
17282 NM_CLASS_S = 0x0c,
17283 NM_CLASS_D = 0x4c,
17284 NM_SUB_S = 0x0e,
17285 NM_SELNEZ_S = 0x0f,
17286 NM_SELNEZ_D = 0x4f,
17287 NM_MUL_S = 0x16,
17288 NM_SEL_S = 0x17,
17289 NM_SEL_D = 0x57,
17290 NM_DIV_S = 0x1e,
17291 NM_ADD_D = 0x26,
17292 NM_SUB_D = 0x2e,
17293 NM_MUL_D = 0x36,
17294 NM_MADDF_S = 0x37,
17295 NM_MADDF_D = 0x77,
17296 NM_DIV_D = 0x3e,
17297 NM_MSUBF_S = 0x3f,
17298 NM_MSUBF_D = 0x7f,
17301 /* POOL32F_3 instruction pool */
17302 enum {
17303 NM_MIN_FMT = 0x00,
17304 NM_MAX_FMT = 0x01,
17305 NM_MINA_FMT = 0x04,
17306 NM_MAXA_FMT = 0x05,
17307 NM_POOL32FXF = 0x07,
17310 /* POOL32F_5 instruction pool */
17311 enum {
17312 NM_CMP_CONDN_S = 0x00,
17313 NM_CMP_CONDN_D = 0x02,
17316 /* P.GP.LH instruction pool */
17317 enum {
17318 NM_LHGP = 0x00,
17319 NM_LHUGP = 0x01,
17322 /* P.GP.SH instruction pool */
17323 enum {
17324 NM_SHGP = 0x00,
17327 /* P.GP.CP1 instruction pool */
17328 enum {
17329 NM_LWC1GP = 0x00,
17330 NM_SWC1GP = 0x01,
17331 NM_LDC1GP = 0x02,
17332 NM_SDC1GP = 0x03,
17335 /* P.LS.S0 instruction pool */
17336 enum {
17337 NM_LBS9 = 0x00,
17338 NM_LHS9 = 0x04,
17339 NM_LWS9 = 0x08,
17340 NM_LDS9 = 0x0c,
17342 NM_SBS9 = 0x01,
17343 NM_SHS9 = 0x05,
17344 NM_SWS9 = 0x09,
17345 NM_SDS9 = 0x0d,
17347 NM_LBUS9 = 0x02,
17348 NM_LHUS9 = 0x06,
17349 NM_LWC1S9 = 0x0a,
17350 NM_LDC1S9 = 0x0e,
17352 NM_P_PREFS9 = 0x03,
17353 NM_LWUS9 = 0x07,
17354 NM_SWC1S9 = 0x0b,
17355 NM_SDC1S9 = 0x0f,
17358 /* P.LS.S1 instruction pool */
17359 enum {
17360 NM_ASET_ACLR = 0x02,
17361 NM_UALH = 0x04,
17362 NM_UASH = 0x05,
17363 NM_CACHE = 0x07,
17364 NM_P_LL = 0x0a,
17365 NM_P_SC = 0x0b,
17368 /* P.LS.E0 instruction pool */
17369 enum {
17370 NM_LBE = 0x00,
17371 NM_SBE = 0x01,
17372 NM_LBUE = 0x02,
17373 NM_P_PREFE = 0x03,
17374 NM_LHE = 0x04,
17375 NM_SHE = 0x05,
17376 NM_LHUE = 0x06,
17377 NM_CACHEE = 0x07,
17378 NM_LWE = 0x08,
17379 NM_SWE = 0x09,
17380 NM_P_LLE = 0x0a,
17381 NM_P_SCE = 0x0b,
17384 /* P.PREFE instruction pool */
17385 enum {
17386 NM_SYNCIE = 0x00,
17387 NM_PREFE = 0x01,
17390 /* P.LLE instruction pool */
17391 enum {
17392 NM_LLE = 0x00,
17393 NM_LLWPE = 0x01,
17396 /* P.SCE instruction pool */
17397 enum {
17398 NM_SCE = 0x00,
17399 NM_SCWPE = 0x01,
17402 /* P.LS.WM instruction pool */
17403 enum {
17404 NM_LWM = 0x00,
17405 NM_SWM = 0x01,
17408 /* P.LS.UAWM instruction pool */
17409 enum {
17410 NM_UALWM = 0x00,
17411 NM_UASWM = 0x01,
17414 /* P.BR3A instruction pool */
17415 enum {
17416 NM_BC1EQZC = 0x00,
17417 NM_BC1NEZC = 0x01,
17418 NM_BC2EQZC = 0x02,
17419 NM_BC2NEZC = 0x03,
17420 NM_BPOSGE32C = 0x04,
17423 /* P16.RI instruction pool */
17424 enum {
17425 NM_P16_SYSCALL = 0x01,
17426 NM_BREAK16 = 0x02,
17427 NM_SDBBP16 = 0x03,
17430 /* POOL16C_0 instruction pool */
17431 enum {
17432 NM_POOL16C_00 = 0x00,
17435 /* P16.JRC instruction pool */
17436 enum {
17437 NM_JRC = 0x00,
17438 NM_JALRC16 = 0x01,
17441 /* P.SYSCALL instruction pool */
17442 enum {
17443 NM_SYSCALL = 0x00,
17444 NM_HYPCALL = 0x01,
17447 /* P.TRAP instruction pool */
17448 enum {
17449 NM_TEQ = 0x00,
17450 NM_TNE = 0x01,
17453 /* P.CMOVE instruction pool */
17454 enum {
17455 NM_MOVZ = 0x00,
17456 NM_MOVN = 0x01,
17459 /* POOL32Axf instruction pool */
17460 enum {
17461 NM_POOL32AXF_1 = 0x01,
17462 NM_POOL32AXF_2 = 0x02,
17463 NM_POOL32AXF_4 = 0x04,
17464 NM_POOL32AXF_5 = 0x05,
17465 NM_POOL32AXF_7 = 0x07,
17468 /* POOL32Axf_1 instruction pool */
17469 enum {
17470 NM_POOL32AXF_1_0 = 0x00,
17471 NM_POOL32AXF_1_1 = 0x01,
17472 NM_POOL32AXF_1_3 = 0x03,
17473 NM_POOL32AXF_1_4 = 0x04,
17474 NM_POOL32AXF_1_5 = 0x05,
17475 NM_POOL32AXF_1_7 = 0x07,
17478 /* POOL32Axf_2 instruction pool */
17479 enum {
17480 NM_POOL32AXF_2_0_7 = 0x00,
17481 NM_POOL32AXF_2_8_15 = 0x01,
17482 NM_POOL32AXF_2_16_23 = 0x02,
17483 NM_POOL32AXF_2_24_31 = 0x03,
17486 /* POOL32Axf_7 instruction pool */
17487 enum {
17488 NM_SHRA_R_QB = 0x0,
17489 NM_SHRL_PH = 0x1,
17490 NM_REPL_QB = 0x2,
17493 /* POOL32Axf_1_0 instruction pool */
17494 enum {
17495 NM_MFHI = 0x0,
17496 NM_MFLO = 0x1,
17497 NM_MTHI = 0x2,
17498 NM_MTLO = 0x3,
17501 /* POOL32Axf_1_1 instruction pool */
17502 enum {
17503 NM_MTHLIP = 0x0,
17504 NM_SHILOV = 0x1,
17507 /* POOL32Axf_1_3 instruction pool */
17508 enum {
17509 NM_RDDSP = 0x0,
17510 NM_WRDSP = 0x1,
17511 NM_EXTP = 0x2,
17512 NM_EXTPDP = 0x3,
17515 /* POOL32Axf_1_4 instruction pool */
17516 enum {
17517 NM_SHLL_QB = 0x0,
17518 NM_SHRL_QB = 0x1,
17521 /* POOL32Axf_1_5 instruction pool */
17522 enum {
17523 NM_MAQ_S_W_PHR = 0x0,
17524 NM_MAQ_S_W_PHL = 0x1,
17525 NM_MAQ_SA_W_PHR = 0x2,
17526 NM_MAQ_SA_W_PHL = 0x3,
17529 /* POOL32Axf_1_7 instruction pool */
17530 enum {
17531 NM_EXTR_W = 0x0,
17532 NM_EXTR_R_W = 0x1,
17533 NM_EXTR_RS_W = 0x2,
17534 NM_EXTR_S_H = 0x3,
17537 /* POOL32Axf_2_0_7 instruction pool */
17538 enum {
17539 NM_DPA_W_PH = 0x0,
17540 NM_DPAQ_S_W_PH = 0x1,
17541 NM_DPS_W_PH = 0x2,
17542 NM_DPSQ_S_W_PH = 0x3,
17543 NM_BALIGN = 0x4,
17544 NM_MADD = 0x5,
17545 NM_MULT = 0x6,
17546 NM_EXTRV_W = 0x7,
17549 /* POOL32Axf_2_8_15 instruction pool */
17550 enum {
17551 NM_DPAX_W_PH = 0x0,
17552 NM_DPAQ_SA_L_W = 0x1,
17553 NM_DPSX_W_PH = 0x2,
17554 NM_DPSQ_SA_L_W = 0x3,
17555 NM_MADDU = 0x5,
17556 NM_MULTU = 0x6,
17557 NM_EXTRV_R_W = 0x7,
17560 /* POOL32Axf_2_16_23 instruction pool */
17561 enum {
17562 NM_DPAU_H_QBL = 0x0,
17563 NM_DPAQX_S_W_PH = 0x1,
17564 NM_DPSU_H_QBL = 0x2,
17565 NM_DPSQX_S_W_PH = 0x3,
17566 NM_EXTPV = 0x4,
17567 NM_MSUB = 0x5,
17568 NM_MULSA_W_PH = 0x6,
17569 NM_EXTRV_RS_W = 0x7,
17572 /* POOL32Axf_2_24_31 instruction pool */
17573 enum {
17574 NM_DPAU_H_QBR = 0x0,
17575 NM_DPAQX_SA_W_PH = 0x1,
17576 NM_DPSU_H_QBR = 0x2,
17577 NM_DPSQX_SA_W_PH = 0x3,
17578 NM_EXTPDPV = 0x4,
17579 NM_MSUBU = 0x5,
17580 NM_MULSAQ_S_W_PH = 0x6,
17581 NM_EXTRV_S_H = 0x7,
17584 /* POOL32Axf_{4, 5} instruction pool */
17585 enum {
17586 NM_CLO = 0x25,
17587 NM_CLZ = 0x2d,
17589 NM_TLBP = 0x01,
17590 NM_TLBR = 0x09,
17591 NM_TLBWI = 0x11,
17592 NM_TLBWR = 0x19,
17593 NM_TLBINV = 0x03,
17594 NM_TLBINVF = 0x0b,
17595 NM_DI = 0x23,
17596 NM_EI = 0x2b,
17597 NM_RDPGPR = 0x70,
17598 NM_WRPGPR = 0x78,
17599 NM_WAIT = 0x61,
17600 NM_DERET = 0x71,
17601 NM_ERETX = 0x79,
17603 /* nanoMIPS DSP instructions */
17604 NM_ABSQ_S_QB = 0x00,
17605 NM_ABSQ_S_PH = 0x08,
17606 NM_ABSQ_S_W = 0x10,
17607 NM_PRECEQ_W_PHL = 0x28,
17608 NM_PRECEQ_W_PHR = 0x30,
17609 NM_PRECEQU_PH_QBL = 0x38,
17610 NM_PRECEQU_PH_QBR = 0x48,
17611 NM_PRECEU_PH_QBL = 0x58,
17612 NM_PRECEU_PH_QBR = 0x68,
17613 NM_PRECEQU_PH_QBLA = 0x39,
17614 NM_PRECEQU_PH_QBRA = 0x49,
17615 NM_PRECEU_PH_QBLA = 0x59,
17616 NM_PRECEU_PH_QBRA = 0x69,
17617 NM_REPLV_PH = 0x01,
17618 NM_REPLV_QB = 0x09,
17619 NM_BITREV = 0x18,
17620 NM_INSV = 0x20,
17621 NM_RADDU_W_QB = 0x78,
17623 NM_BITSWAP = 0x05,
17624 NM_WSBH = 0x3d,
17627 /* PP.SR instruction pool */
17628 enum {
17629 NM_SAVE = 0x00,
17630 NM_RESTORE = 0x02,
17631 NM_RESTORE_JRC = 0x03,
17634 /* P.SR.F instruction pool */
17635 enum {
17636 NM_SAVEF = 0x00,
17637 NM_RESTOREF = 0x01,
17640 /* P16.SYSCALL instruction pool */
17641 enum {
17642 NM_SYSCALL16 = 0x00,
17643 NM_HYPCALL16 = 0x01,
17646 /* POOL16C_00 instruction pool */
17647 enum {
17648 NM_NOT16 = 0x00,
17649 NM_XOR16 = 0x01,
17650 NM_AND16 = 0x02,
17651 NM_OR16 = 0x03,
17654 /* PP.LSX and PP.LSXS instruction pool */
17655 enum {
17656 NM_LBX = 0x00,
17657 NM_LHX = 0x04,
17658 NM_LWX = 0x08,
17659 NM_LDX = 0x0c,
17661 NM_SBX = 0x01,
17662 NM_SHX = 0x05,
17663 NM_SWX = 0x09,
17664 NM_SDX = 0x0d,
17666 NM_LBUX = 0x02,
17667 NM_LHUX = 0x06,
17668 NM_LWC1X = 0x0a,
17669 NM_LDC1X = 0x0e,
17671 NM_LWUX = 0x07,
17672 NM_SWC1X = 0x0b,
17673 NM_SDC1X = 0x0f,
17675 NM_LHXS = 0x04,
17676 NM_LWXS = 0x08,
17677 NM_LDXS = 0x0c,
17679 NM_SHXS = 0x05,
17680 NM_SWXS = 0x09,
17681 NM_SDXS = 0x0d,
17683 NM_LHUXS = 0x06,
17684 NM_LWC1XS = 0x0a,
17685 NM_LDC1XS = 0x0e,
17687 NM_LWUXS = 0x07,
17688 NM_SWC1XS = 0x0b,
17689 NM_SDC1XS = 0x0f,
17692 /* ERETx instruction pool */
17693 enum {
17694 NM_ERET = 0x00,
17695 NM_ERETNC = 0x01,
17698 /* POOL32FxF_{0, 1} insturction pool */
17699 enum {
17700 NM_CFC1 = 0x40,
17701 NM_CTC1 = 0x60,
17702 NM_MFC1 = 0x80,
17703 NM_MTC1 = 0xa0,
17704 NM_MFHC1 = 0xc0,
17705 NM_MTHC1 = 0xe0,
17707 NM_CVT_S_PL = 0x84,
17708 NM_CVT_S_PU = 0xa4,
17710 NM_CVT_L_S = 0x004,
17711 NM_CVT_L_D = 0x104,
17712 NM_CVT_W_S = 0x024,
17713 NM_CVT_W_D = 0x124,
17715 NM_RSQRT_S = 0x008,
17716 NM_RSQRT_D = 0x108,
17718 NM_SQRT_S = 0x028,
17719 NM_SQRT_D = 0x128,
17721 NM_RECIP_S = 0x048,
17722 NM_RECIP_D = 0x148,
17724 NM_FLOOR_L_S = 0x00c,
17725 NM_FLOOR_L_D = 0x10c,
17727 NM_FLOOR_W_S = 0x02c,
17728 NM_FLOOR_W_D = 0x12c,
17730 NM_CEIL_L_S = 0x04c,
17731 NM_CEIL_L_D = 0x14c,
17732 NM_CEIL_W_S = 0x06c,
17733 NM_CEIL_W_D = 0x16c,
17734 NM_TRUNC_L_S = 0x08c,
17735 NM_TRUNC_L_D = 0x18c,
17736 NM_TRUNC_W_S = 0x0ac,
17737 NM_TRUNC_W_D = 0x1ac,
17738 NM_ROUND_L_S = 0x0cc,
17739 NM_ROUND_L_D = 0x1cc,
17740 NM_ROUND_W_S = 0x0ec,
17741 NM_ROUND_W_D = 0x1ec,
17743 NM_MOV_S = 0x01,
17744 NM_MOV_D = 0x81,
17745 NM_ABS_S = 0x0d,
17746 NM_ABS_D = 0x8d,
17747 NM_NEG_S = 0x2d,
17748 NM_NEG_D = 0xad,
17749 NM_CVT_D_S = 0x04d,
17750 NM_CVT_D_W = 0x0cd,
17751 NM_CVT_D_L = 0x14d,
17752 NM_CVT_S_D = 0x06d,
17753 NM_CVT_S_W = 0x0ed,
17754 NM_CVT_S_L = 0x16d,
17757 /* P.LL instruction pool */
17758 enum {
17759 NM_LL = 0x00,
17760 NM_LLWP = 0x01,
17763 /* P.SC instruction pool */
17764 enum {
17765 NM_SC = 0x00,
17766 NM_SCWP = 0x01,
17769 /* P.DVP instruction pool */
17770 enum {
17771 NM_DVP = 0x00,
17772 NM_EVP = 0x01,
17778 * nanoMIPS decoding engine
17783 /* extraction utilities */
17785 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
17786 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
17787 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
17788 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17789 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17791 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
17792 static inline int decode_gpr_gpr3(int r)
17794 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
17796 return map[r & 0x7];
17799 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
17800 static inline int decode_gpr_gpr3_src_store(int r)
17802 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
17804 return map[r & 0x7];
17807 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
17808 static inline int decode_gpr_gpr4(int r)
17810 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
17811 16, 17, 18, 19, 20, 21, 22, 23 };
17813 return map[r & 0xf];
17816 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
17817 static inline int decode_gpr_gpr4_zero(int r)
17819 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
17820 16, 17, 18, 19, 20, 21, 22, 23 };
17822 return map[r & 0xf];
17826 static void gen_adjust_sp(DisasContext *ctx, int u)
17828 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
17831 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
17832 uint8_t gp, uint16_t u)
17834 int counter = 0;
17835 TCGv va = tcg_temp_new();
17836 TCGv t0 = tcg_temp_new();
17838 while (counter != count) {
17839 bool use_gp = gp && (counter == count - 1);
17840 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17841 int this_offset = -((counter + 1) << 2);
17842 gen_base_offset_addr(ctx, va, 29, this_offset);
17843 gen_load_gpr(t0, this_rt);
17844 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
17845 (MO_TEUL | ctx->default_tcg_memop_mask));
17846 counter++;
17849 /* adjust stack pointer */
17850 gen_adjust_sp(ctx, -u);
17852 tcg_temp_free(t0);
17853 tcg_temp_free(va);
17856 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
17857 uint8_t gp, uint16_t u)
17859 int counter = 0;
17860 TCGv va = tcg_temp_new();
17861 TCGv t0 = tcg_temp_new();
17863 while (counter != count) {
17864 bool use_gp = gp && (counter == count - 1);
17865 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17866 int this_offset = u - ((counter + 1) << 2);
17867 gen_base_offset_addr(ctx, va, 29, this_offset);
17868 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
17869 ctx->default_tcg_memop_mask);
17870 tcg_gen_ext32s_tl(t0, t0);
17871 gen_store_gpr(t0, this_rt);
17872 counter++;
17875 /* adjust stack pointer */
17876 gen_adjust_sp(ctx, u);
17878 tcg_temp_free(t0);
17879 tcg_temp_free(va);
17882 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
17884 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
17885 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
17887 switch (extract32(ctx->opcode, 2, 2)) {
17888 case NM_NOT16:
17889 gen_logic(ctx, OPC_NOR, rt, rs, 0);
17890 break;
17891 case NM_AND16:
17892 gen_logic(ctx, OPC_AND, rt, rt, rs);
17893 break;
17894 case NM_XOR16:
17895 gen_logic(ctx, OPC_XOR, rt, rt, rs);
17896 break;
17897 case NM_OR16:
17898 gen_logic(ctx, OPC_OR, rt, rt, rs);
17899 break;
17903 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
17905 int rt = extract32(ctx->opcode, 21, 5);
17906 int rs = extract32(ctx->opcode, 16, 5);
17907 int rd = extract32(ctx->opcode, 11, 5);
17909 switch (extract32(ctx->opcode, 3, 7)) {
17910 case NM_P_TRAP:
17911 switch (extract32(ctx->opcode, 10, 1)) {
17912 case NM_TEQ:
17913 check_nms(ctx);
17914 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
17915 break;
17916 case NM_TNE:
17917 check_nms(ctx);
17918 gen_trap(ctx, OPC_TNE, rs, rt, -1);
17919 break;
17921 break;
17922 case NM_RDHWR:
17923 check_nms(ctx);
17924 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
17925 break;
17926 case NM_SEB:
17927 check_nms(ctx);
17928 gen_bshfl(ctx, OPC_SEB, rs, rt);
17929 break;
17930 case NM_SEH:
17931 gen_bshfl(ctx, OPC_SEH, rs, rt);
17932 break;
17933 case NM_SLLV:
17934 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
17935 break;
17936 case NM_SRLV:
17937 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
17938 break;
17939 case NM_SRAV:
17940 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
17941 break;
17942 case NM_ROTRV:
17943 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
17944 break;
17945 case NM_ADD:
17946 gen_arith(ctx, OPC_ADD, rd, rs, rt);
17947 break;
17948 case NM_ADDU:
17949 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
17950 break;
17951 case NM_SUB:
17952 check_nms(ctx);
17953 gen_arith(ctx, OPC_SUB, rd, rs, rt);
17954 break;
17955 case NM_SUBU:
17956 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
17957 break;
17958 case NM_P_CMOVE:
17959 switch (extract32(ctx->opcode, 10, 1)) {
17960 case NM_MOVZ:
17961 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
17962 break;
17963 case NM_MOVN:
17964 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
17965 break;
17967 break;
17968 case NM_AND:
17969 gen_logic(ctx, OPC_AND, rd, rs, rt);
17970 break;
17971 case NM_OR:
17972 gen_logic(ctx, OPC_OR, rd, rs, rt);
17973 break;
17974 case NM_NOR:
17975 gen_logic(ctx, OPC_NOR, rd, rs, rt);
17976 break;
17977 case NM_XOR:
17978 gen_logic(ctx, OPC_XOR, rd, rs, rt);
17979 break;
17980 case NM_SLT:
17981 gen_slt(ctx, OPC_SLT, rd, rs, rt);
17982 break;
17983 case NM_P_SLTU:
17984 if (rd == 0) {
17985 /* P_DVP */
17986 #ifndef CONFIG_USER_ONLY
17987 TCGv t0 = tcg_temp_new();
17988 switch (extract32(ctx->opcode, 10, 1)) {
17989 case NM_DVP:
17990 if (ctx->vp) {
17991 check_cp0_enabled(ctx);
17992 gen_helper_dvp(t0, cpu_env);
17993 gen_store_gpr(t0, rt);
17995 break;
17996 case NM_EVP:
17997 if (ctx->vp) {
17998 check_cp0_enabled(ctx);
17999 gen_helper_evp(t0, cpu_env);
18000 gen_store_gpr(t0, rt);
18002 break;
18004 tcg_temp_free(t0);
18005 #endif
18006 } else {
18007 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18009 break;
18010 case NM_SOV:
18012 TCGv t0 = tcg_temp_new();
18013 TCGv t1 = tcg_temp_new();
18014 TCGv t2 = tcg_temp_new();
18016 gen_load_gpr(t1, rs);
18017 gen_load_gpr(t2, rt);
18018 tcg_gen_add_tl(t0, t1, t2);
18019 tcg_gen_ext32s_tl(t0, t0);
18020 tcg_gen_xor_tl(t1, t1, t2);
18021 tcg_gen_xor_tl(t2, t0, t2);
18022 tcg_gen_andc_tl(t1, t2, t1);
18024 /* operands of same sign, result different sign */
18025 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18026 gen_store_gpr(t0, rd);
18028 tcg_temp_free(t0);
18029 tcg_temp_free(t1);
18030 tcg_temp_free(t2);
18032 break;
18033 case NM_MUL:
18034 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18035 break;
18036 case NM_MUH:
18037 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18038 break;
18039 case NM_MULU:
18040 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18041 break;
18042 case NM_MUHU:
18043 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18044 break;
18045 case NM_DIV:
18046 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18047 break;
18048 case NM_MOD:
18049 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18050 break;
18051 case NM_DIVU:
18052 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18053 break;
18054 case NM_MODU:
18055 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18056 break;
18057 #ifndef CONFIG_USER_ONLY
18058 case NM_MFC0:
18059 check_cp0_enabled(ctx);
18060 if (rt == 0) {
18061 /* Treat as NOP. */
18062 break;
18064 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18065 break;
18066 case NM_MTC0:
18067 check_cp0_enabled(ctx);
18069 TCGv t0 = tcg_temp_new();
18071 gen_load_gpr(t0, rt);
18072 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18073 tcg_temp_free(t0);
18075 break;
18076 case NM_D_E_MT_VPE:
18078 uint8_t sc = extract32(ctx->opcode, 10, 1);
18079 TCGv t0 = tcg_temp_new();
18081 switch (sc) {
18082 case 0:
18083 if (rs == 1) {
18084 /* DMT */
18085 check_cp0_mt(ctx);
18086 gen_helper_dmt(t0);
18087 gen_store_gpr(t0, rt);
18088 } else if (rs == 0) {
18089 /* DVPE */
18090 check_cp0_mt(ctx);
18091 gen_helper_dvpe(t0, cpu_env);
18092 gen_store_gpr(t0, rt);
18093 } else {
18094 gen_reserved_instruction(ctx);
18096 break;
18097 case 1:
18098 if (rs == 1) {
18099 /* EMT */
18100 check_cp0_mt(ctx);
18101 gen_helper_emt(t0);
18102 gen_store_gpr(t0, rt);
18103 } else if (rs == 0) {
18104 /* EVPE */
18105 check_cp0_mt(ctx);
18106 gen_helper_evpe(t0, cpu_env);
18107 gen_store_gpr(t0, rt);
18108 } else {
18109 gen_reserved_instruction(ctx);
18111 break;
18114 tcg_temp_free(t0);
18116 break;
18117 case NM_FORK:
18118 check_mt(ctx);
18120 TCGv t0 = tcg_temp_new();
18121 TCGv t1 = tcg_temp_new();
18123 gen_load_gpr(t0, rt);
18124 gen_load_gpr(t1, rs);
18125 gen_helper_fork(t0, t1);
18126 tcg_temp_free(t0);
18127 tcg_temp_free(t1);
18129 break;
18130 case NM_MFTR:
18131 case NM_MFHTR:
18132 check_cp0_enabled(ctx);
18133 if (rd == 0) {
18134 /* Treat as NOP. */
18135 return;
18137 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18138 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18139 break;
18140 case NM_MTTR:
18141 case NM_MTHTR:
18142 check_cp0_enabled(ctx);
18143 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18144 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18145 break;
18146 case NM_YIELD:
18147 check_mt(ctx);
18149 TCGv t0 = tcg_temp_new();
18151 gen_load_gpr(t0, rs);
18152 gen_helper_yield(t0, cpu_env, t0);
18153 gen_store_gpr(t0, rt);
18154 tcg_temp_free(t0);
18156 break;
18157 #endif
18158 default:
18159 gen_reserved_instruction(ctx);
18160 break;
18164 /* dsp */
18165 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18166 int ret, int v1, int v2)
18168 TCGv_i32 t0;
18169 TCGv v0_t;
18170 TCGv v1_t;
18172 t0 = tcg_temp_new_i32();
18174 v0_t = tcg_temp_new();
18175 v1_t = tcg_temp_new();
18177 tcg_gen_movi_i32(t0, v2 >> 3);
18179 gen_load_gpr(v0_t, ret);
18180 gen_load_gpr(v1_t, v1);
18182 switch (opc) {
18183 case NM_MAQ_S_W_PHR:
18184 check_dsp(ctx);
18185 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18186 break;
18187 case NM_MAQ_S_W_PHL:
18188 check_dsp(ctx);
18189 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18190 break;
18191 case NM_MAQ_SA_W_PHR:
18192 check_dsp(ctx);
18193 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18194 break;
18195 case NM_MAQ_SA_W_PHL:
18196 check_dsp(ctx);
18197 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18198 break;
18199 default:
18200 gen_reserved_instruction(ctx);
18201 break;
18204 tcg_temp_free_i32(t0);
18206 tcg_temp_free(v0_t);
18207 tcg_temp_free(v1_t);
18211 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18212 int ret, int v1, int v2)
18214 int16_t imm;
18215 TCGv t0 = tcg_temp_new();
18216 TCGv t1 = tcg_temp_new();
18217 TCGv v0_t = tcg_temp_new();
18219 gen_load_gpr(v0_t, v1);
18221 switch (opc) {
18222 case NM_POOL32AXF_1_0:
18223 check_dsp(ctx);
18224 switch (extract32(ctx->opcode, 12, 2)) {
18225 case NM_MFHI:
18226 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18227 break;
18228 case NM_MFLO:
18229 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18230 break;
18231 case NM_MTHI:
18232 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18233 break;
18234 case NM_MTLO:
18235 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18236 break;
18238 break;
18239 case NM_POOL32AXF_1_1:
18240 check_dsp(ctx);
18241 switch (extract32(ctx->opcode, 12, 2)) {
18242 case NM_MTHLIP:
18243 tcg_gen_movi_tl(t0, v2);
18244 gen_helper_mthlip(t0, v0_t, cpu_env);
18245 break;
18246 case NM_SHILOV:
18247 tcg_gen_movi_tl(t0, v2 >> 3);
18248 gen_helper_shilo(t0, v0_t, cpu_env);
18249 break;
18250 default:
18251 gen_reserved_instruction(ctx);
18252 break;
18254 break;
18255 case NM_POOL32AXF_1_3:
18256 check_dsp(ctx);
18257 imm = extract32(ctx->opcode, 14, 7);
18258 switch (extract32(ctx->opcode, 12, 2)) {
18259 case NM_RDDSP:
18260 tcg_gen_movi_tl(t0, imm);
18261 gen_helper_rddsp(t0, t0, cpu_env);
18262 gen_store_gpr(t0, ret);
18263 break;
18264 case NM_WRDSP:
18265 gen_load_gpr(t0, ret);
18266 tcg_gen_movi_tl(t1, imm);
18267 gen_helper_wrdsp(t0, t1, cpu_env);
18268 break;
18269 case NM_EXTP:
18270 tcg_gen_movi_tl(t0, v2 >> 3);
18271 tcg_gen_movi_tl(t1, v1);
18272 gen_helper_extp(t0, t0, t1, cpu_env);
18273 gen_store_gpr(t0, ret);
18274 break;
18275 case NM_EXTPDP:
18276 tcg_gen_movi_tl(t0, v2 >> 3);
18277 tcg_gen_movi_tl(t1, v1);
18278 gen_helper_extpdp(t0, t0, t1, cpu_env);
18279 gen_store_gpr(t0, ret);
18280 break;
18282 break;
18283 case NM_POOL32AXF_1_4:
18284 check_dsp(ctx);
18285 tcg_gen_movi_tl(t0, v2 >> 2);
18286 switch (extract32(ctx->opcode, 12, 1)) {
18287 case NM_SHLL_QB:
18288 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18289 gen_store_gpr(t0, ret);
18290 break;
18291 case NM_SHRL_QB:
18292 gen_helper_shrl_qb(t0, t0, v0_t);
18293 gen_store_gpr(t0, ret);
18294 break;
18296 break;
18297 case NM_POOL32AXF_1_5:
18298 opc = extract32(ctx->opcode, 12, 2);
18299 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18300 break;
18301 case NM_POOL32AXF_1_7:
18302 check_dsp(ctx);
18303 tcg_gen_movi_tl(t0, v2 >> 3);
18304 tcg_gen_movi_tl(t1, v1);
18305 switch (extract32(ctx->opcode, 12, 2)) {
18306 case NM_EXTR_W:
18307 gen_helper_extr_w(t0, t0, t1, cpu_env);
18308 gen_store_gpr(t0, ret);
18309 break;
18310 case NM_EXTR_R_W:
18311 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18312 gen_store_gpr(t0, ret);
18313 break;
18314 case NM_EXTR_RS_W:
18315 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18316 gen_store_gpr(t0, ret);
18317 break;
18318 case NM_EXTR_S_H:
18319 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18320 gen_store_gpr(t0, ret);
18321 break;
18323 break;
18324 default:
18325 gen_reserved_instruction(ctx);
18326 break;
18329 tcg_temp_free(t0);
18330 tcg_temp_free(t1);
18331 tcg_temp_free(v0_t);
18334 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18335 TCGv v0, TCGv v1, int rd)
18337 TCGv_i32 t0;
18339 t0 = tcg_temp_new_i32();
18341 tcg_gen_movi_i32(t0, rd >> 3);
18343 switch (opc) {
18344 case NM_POOL32AXF_2_0_7:
18345 switch (extract32(ctx->opcode, 9, 3)) {
18346 case NM_DPA_W_PH:
18347 check_dsp_r2(ctx);
18348 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18349 break;
18350 case NM_DPAQ_S_W_PH:
18351 check_dsp(ctx);
18352 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18353 break;
18354 case NM_DPS_W_PH:
18355 check_dsp_r2(ctx);
18356 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18357 break;
18358 case NM_DPSQ_S_W_PH:
18359 check_dsp(ctx);
18360 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18361 break;
18362 default:
18363 gen_reserved_instruction(ctx);
18364 break;
18366 break;
18367 case NM_POOL32AXF_2_8_15:
18368 switch (extract32(ctx->opcode, 9, 3)) {
18369 case NM_DPAX_W_PH:
18370 check_dsp_r2(ctx);
18371 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18372 break;
18373 case NM_DPAQ_SA_L_W:
18374 check_dsp(ctx);
18375 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18376 break;
18377 case NM_DPSX_W_PH:
18378 check_dsp_r2(ctx);
18379 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18380 break;
18381 case NM_DPSQ_SA_L_W:
18382 check_dsp(ctx);
18383 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18384 break;
18385 default:
18386 gen_reserved_instruction(ctx);
18387 break;
18389 break;
18390 case NM_POOL32AXF_2_16_23:
18391 switch (extract32(ctx->opcode, 9, 3)) {
18392 case NM_DPAU_H_QBL:
18393 check_dsp(ctx);
18394 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18395 break;
18396 case NM_DPAQX_S_W_PH:
18397 check_dsp_r2(ctx);
18398 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18399 break;
18400 case NM_DPSU_H_QBL:
18401 check_dsp(ctx);
18402 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18403 break;
18404 case NM_DPSQX_S_W_PH:
18405 check_dsp_r2(ctx);
18406 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18407 break;
18408 case NM_MULSA_W_PH:
18409 check_dsp_r2(ctx);
18410 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18411 break;
18412 default:
18413 gen_reserved_instruction(ctx);
18414 break;
18416 break;
18417 case NM_POOL32AXF_2_24_31:
18418 switch (extract32(ctx->opcode, 9, 3)) {
18419 case NM_DPAU_H_QBR:
18420 check_dsp(ctx);
18421 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18422 break;
18423 case NM_DPAQX_SA_W_PH:
18424 check_dsp_r2(ctx);
18425 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18426 break;
18427 case NM_DPSU_H_QBR:
18428 check_dsp(ctx);
18429 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18430 break;
18431 case NM_DPSQX_SA_W_PH:
18432 check_dsp_r2(ctx);
18433 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18434 break;
18435 case NM_MULSAQ_S_W_PH:
18436 check_dsp(ctx);
18437 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18438 break;
18439 default:
18440 gen_reserved_instruction(ctx);
18441 break;
18443 break;
18444 default:
18445 gen_reserved_instruction(ctx);
18446 break;
18449 tcg_temp_free_i32(t0);
18452 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18453 int rt, int rs, int rd)
18455 int ret = rt;
18456 TCGv t0 = tcg_temp_new();
18457 TCGv t1 = tcg_temp_new();
18458 TCGv v0_t = tcg_temp_new();
18459 TCGv v1_t = tcg_temp_new();
18461 gen_load_gpr(v0_t, rt);
18462 gen_load_gpr(v1_t, rs);
18464 switch (opc) {
18465 case NM_POOL32AXF_2_0_7:
18466 switch (extract32(ctx->opcode, 9, 3)) {
18467 case NM_DPA_W_PH:
18468 case NM_DPAQ_S_W_PH:
18469 case NM_DPS_W_PH:
18470 case NM_DPSQ_S_W_PH:
18471 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18472 break;
18473 case NM_BALIGN:
18474 check_dsp_r2(ctx);
18475 if (rt != 0) {
18476 gen_load_gpr(t0, rs);
18477 rd &= 3;
18478 if (rd != 0 && rd != 2) {
18479 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18480 tcg_gen_ext32u_tl(t0, t0);
18481 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18482 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18484 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18486 break;
18487 case NM_MADD:
18488 check_dsp(ctx);
18490 int acc = extract32(ctx->opcode, 14, 2);
18491 TCGv_i64 t2 = tcg_temp_new_i64();
18492 TCGv_i64 t3 = tcg_temp_new_i64();
18494 gen_load_gpr(t0, rt);
18495 gen_load_gpr(t1, rs);
18496 tcg_gen_ext_tl_i64(t2, t0);
18497 tcg_gen_ext_tl_i64(t3, t1);
18498 tcg_gen_mul_i64(t2, t2, t3);
18499 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18500 tcg_gen_add_i64(t2, t2, t3);
18501 tcg_temp_free_i64(t3);
18502 gen_move_low32(cpu_LO[acc], t2);
18503 gen_move_high32(cpu_HI[acc], t2);
18504 tcg_temp_free_i64(t2);
18506 break;
18507 case NM_MULT:
18508 check_dsp(ctx);
18510 int acc = extract32(ctx->opcode, 14, 2);
18511 TCGv_i32 t2 = tcg_temp_new_i32();
18512 TCGv_i32 t3 = tcg_temp_new_i32();
18514 gen_load_gpr(t0, rs);
18515 gen_load_gpr(t1, rt);
18516 tcg_gen_trunc_tl_i32(t2, t0);
18517 tcg_gen_trunc_tl_i32(t3, t1);
18518 tcg_gen_muls2_i32(t2, t3, t2, t3);
18519 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18520 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18521 tcg_temp_free_i32(t2);
18522 tcg_temp_free_i32(t3);
18524 break;
18525 case NM_EXTRV_W:
18526 check_dsp(ctx);
18527 gen_load_gpr(v1_t, rs);
18528 tcg_gen_movi_tl(t0, rd >> 3);
18529 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18530 gen_store_gpr(t0, ret);
18531 break;
18533 break;
18534 case NM_POOL32AXF_2_8_15:
18535 switch (extract32(ctx->opcode, 9, 3)) {
18536 case NM_DPAX_W_PH:
18537 case NM_DPAQ_SA_L_W:
18538 case NM_DPSX_W_PH:
18539 case NM_DPSQ_SA_L_W:
18540 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18541 break;
18542 case NM_MADDU:
18543 check_dsp(ctx);
18545 int acc = extract32(ctx->opcode, 14, 2);
18546 TCGv_i64 t2 = tcg_temp_new_i64();
18547 TCGv_i64 t3 = tcg_temp_new_i64();
18549 gen_load_gpr(t0, rs);
18550 gen_load_gpr(t1, rt);
18551 tcg_gen_ext32u_tl(t0, t0);
18552 tcg_gen_ext32u_tl(t1, t1);
18553 tcg_gen_extu_tl_i64(t2, t0);
18554 tcg_gen_extu_tl_i64(t3, t1);
18555 tcg_gen_mul_i64(t2, t2, t3);
18556 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18557 tcg_gen_add_i64(t2, t2, t3);
18558 tcg_temp_free_i64(t3);
18559 gen_move_low32(cpu_LO[acc], t2);
18560 gen_move_high32(cpu_HI[acc], t2);
18561 tcg_temp_free_i64(t2);
18563 break;
18564 case NM_MULTU:
18565 check_dsp(ctx);
18567 int acc = extract32(ctx->opcode, 14, 2);
18568 TCGv_i32 t2 = tcg_temp_new_i32();
18569 TCGv_i32 t3 = tcg_temp_new_i32();
18571 gen_load_gpr(t0, rs);
18572 gen_load_gpr(t1, rt);
18573 tcg_gen_trunc_tl_i32(t2, t0);
18574 tcg_gen_trunc_tl_i32(t3, t1);
18575 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18576 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18577 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18578 tcg_temp_free_i32(t2);
18579 tcg_temp_free_i32(t3);
18581 break;
18582 case NM_EXTRV_R_W:
18583 check_dsp(ctx);
18584 tcg_gen_movi_tl(t0, rd >> 3);
18585 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18586 gen_store_gpr(t0, ret);
18587 break;
18588 default:
18589 gen_reserved_instruction(ctx);
18590 break;
18592 break;
18593 case NM_POOL32AXF_2_16_23:
18594 switch (extract32(ctx->opcode, 9, 3)) {
18595 case NM_DPAU_H_QBL:
18596 case NM_DPAQX_S_W_PH:
18597 case NM_DPSU_H_QBL:
18598 case NM_DPSQX_S_W_PH:
18599 case NM_MULSA_W_PH:
18600 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18601 break;
18602 case NM_EXTPV:
18603 check_dsp(ctx);
18604 tcg_gen_movi_tl(t0, rd >> 3);
18605 gen_helper_extp(t0, t0, v1_t, cpu_env);
18606 gen_store_gpr(t0, ret);
18607 break;
18608 case NM_MSUB:
18609 check_dsp(ctx);
18611 int acc = extract32(ctx->opcode, 14, 2);
18612 TCGv_i64 t2 = tcg_temp_new_i64();
18613 TCGv_i64 t3 = tcg_temp_new_i64();
18615 gen_load_gpr(t0, rs);
18616 gen_load_gpr(t1, rt);
18617 tcg_gen_ext_tl_i64(t2, t0);
18618 tcg_gen_ext_tl_i64(t3, t1);
18619 tcg_gen_mul_i64(t2, t2, t3);
18620 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18621 tcg_gen_sub_i64(t2, t3, t2);
18622 tcg_temp_free_i64(t3);
18623 gen_move_low32(cpu_LO[acc], t2);
18624 gen_move_high32(cpu_HI[acc], t2);
18625 tcg_temp_free_i64(t2);
18627 break;
18628 case NM_EXTRV_RS_W:
18629 check_dsp(ctx);
18630 tcg_gen_movi_tl(t0, rd >> 3);
18631 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18632 gen_store_gpr(t0, ret);
18633 break;
18635 break;
18636 case NM_POOL32AXF_2_24_31:
18637 switch (extract32(ctx->opcode, 9, 3)) {
18638 case NM_DPAU_H_QBR:
18639 case NM_DPAQX_SA_W_PH:
18640 case NM_DPSU_H_QBR:
18641 case NM_DPSQX_SA_W_PH:
18642 case NM_MULSAQ_S_W_PH:
18643 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18644 break;
18645 case NM_EXTPDPV:
18646 check_dsp(ctx);
18647 tcg_gen_movi_tl(t0, rd >> 3);
18648 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18649 gen_store_gpr(t0, ret);
18650 break;
18651 case NM_MSUBU:
18652 check_dsp(ctx);
18654 int acc = extract32(ctx->opcode, 14, 2);
18655 TCGv_i64 t2 = tcg_temp_new_i64();
18656 TCGv_i64 t3 = tcg_temp_new_i64();
18658 gen_load_gpr(t0, rs);
18659 gen_load_gpr(t1, rt);
18660 tcg_gen_ext32u_tl(t0, t0);
18661 tcg_gen_ext32u_tl(t1, t1);
18662 tcg_gen_extu_tl_i64(t2, t0);
18663 tcg_gen_extu_tl_i64(t3, t1);
18664 tcg_gen_mul_i64(t2, t2, t3);
18665 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18666 tcg_gen_sub_i64(t2, t3, t2);
18667 tcg_temp_free_i64(t3);
18668 gen_move_low32(cpu_LO[acc], t2);
18669 gen_move_high32(cpu_HI[acc], t2);
18670 tcg_temp_free_i64(t2);
18672 break;
18673 case NM_EXTRV_S_H:
18674 check_dsp(ctx);
18675 tcg_gen_movi_tl(t0, rd >> 3);
18676 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
18677 gen_store_gpr(t0, ret);
18678 break;
18680 break;
18681 default:
18682 gen_reserved_instruction(ctx);
18683 break;
18686 tcg_temp_free(t0);
18687 tcg_temp_free(t1);
18689 tcg_temp_free(v0_t);
18690 tcg_temp_free(v1_t);
18693 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
18694 int rt, int rs)
18696 int ret = rt;
18697 TCGv t0 = tcg_temp_new();
18698 TCGv v0_t = tcg_temp_new();
18700 gen_load_gpr(v0_t, rs);
18702 switch (opc) {
18703 case NM_ABSQ_S_QB:
18704 check_dsp_r2(ctx);
18705 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
18706 gen_store_gpr(v0_t, ret);
18707 break;
18708 case NM_ABSQ_S_PH:
18709 check_dsp(ctx);
18710 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
18711 gen_store_gpr(v0_t, ret);
18712 break;
18713 case NM_ABSQ_S_W:
18714 check_dsp(ctx);
18715 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
18716 gen_store_gpr(v0_t, ret);
18717 break;
18718 case NM_PRECEQ_W_PHL:
18719 check_dsp(ctx);
18720 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
18721 tcg_gen_ext32s_tl(v0_t, v0_t);
18722 gen_store_gpr(v0_t, ret);
18723 break;
18724 case NM_PRECEQ_W_PHR:
18725 check_dsp(ctx);
18726 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
18727 tcg_gen_shli_tl(v0_t, v0_t, 16);
18728 tcg_gen_ext32s_tl(v0_t, v0_t);
18729 gen_store_gpr(v0_t, ret);
18730 break;
18731 case NM_PRECEQU_PH_QBL:
18732 check_dsp(ctx);
18733 gen_helper_precequ_ph_qbl(v0_t, v0_t);
18734 gen_store_gpr(v0_t, ret);
18735 break;
18736 case NM_PRECEQU_PH_QBR:
18737 check_dsp(ctx);
18738 gen_helper_precequ_ph_qbr(v0_t, v0_t);
18739 gen_store_gpr(v0_t, ret);
18740 break;
18741 case NM_PRECEQU_PH_QBLA:
18742 check_dsp(ctx);
18743 gen_helper_precequ_ph_qbla(v0_t, v0_t);
18744 gen_store_gpr(v0_t, ret);
18745 break;
18746 case NM_PRECEQU_PH_QBRA:
18747 check_dsp(ctx);
18748 gen_helper_precequ_ph_qbra(v0_t, v0_t);
18749 gen_store_gpr(v0_t, ret);
18750 break;
18751 case NM_PRECEU_PH_QBL:
18752 check_dsp(ctx);
18753 gen_helper_preceu_ph_qbl(v0_t, v0_t);
18754 gen_store_gpr(v0_t, ret);
18755 break;
18756 case NM_PRECEU_PH_QBR:
18757 check_dsp(ctx);
18758 gen_helper_preceu_ph_qbr(v0_t, v0_t);
18759 gen_store_gpr(v0_t, ret);
18760 break;
18761 case NM_PRECEU_PH_QBLA:
18762 check_dsp(ctx);
18763 gen_helper_preceu_ph_qbla(v0_t, v0_t);
18764 gen_store_gpr(v0_t, ret);
18765 break;
18766 case NM_PRECEU_PH_QBRA:
18767 check_dsp(ctx);
18768 gen_helper_preceu_ph_qbra(v0_t, v0_t);
18769 gen_store_gpr(v0_t, ret);
18770 break;
18771 case NM_REPLV_PH:
18772 check_dsp(ctx);
18773 tcg_gen_ext16u_tl(v0_t, v0_t);
18774 tcg_gen_shli_tl(t0, v0_t, 16);
18775 tcg_gen_or_tl(v0_t, v0_t, t0);
18776 tcg_gen_ext32s_tl(v0_t, v0_t);
18777 gen_store_gpr(v0_t, ret);
18778 break;
18779 case NM_REPLV_QB:
18780 check_dsp(ctx);
18781 tcg_gen_ext8u_tl(v0_t, v0_t);
18782 tcg_gen_shli_tl(t0, v0_t, 8);
18783 tcg_gen_or_tl(v0_t, v0_t, t0);
18784 tcg_gen_shli_tl(t0, v0_t, 16);
18785 tcg_gen_or_tl(v0_t, v0_t, t0);
18786 tcg_gen_ext32s_tl(v0_t, v0_t);
18787 gen_store_gpr(v0_t, ret);
18788 break;
18789 case NM_BITREV:
18790 check_dsp(ctx);
18791 gen_helper_bitrev(v0_t, v0_t);
18792 gen_store_gpr(v0_t, ret);
18793 break;
18794 case NM_INSV:
18795 check_dsp(ctx);
18797 TCGv tv0 = tcg_temp_new();
18799 gen_load_gpr(tv0, rt);
18800 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
18801 gen_store_gpr(v0_t, ret);
18802 tcg_temp_free(tv0);
18804 break;
18805 case NM_RADDU_W_QB:
18806 check_dsp(ctx);
18807 gen_helper_raddu_w_qb(v0_t, v0_t);
18808 gen_store_gpr(v0_t, ret);
18809 break;
18810 case NM_BITSWAP:
18811 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
18812 break;
18813 case NM_CLO:
18814 check_nms(ctx);
18815 gen_cl(ctx, OPC_CLO, ret, rs);
18816 break;
18817 case NM_CLZ:
18818 check_nms(ctx);
18819 gen_cl(ctx, OPC_CLZ, ret, rs);
18820 break;
18821 case NM_WSBH:
18822 gen_bshfl(ctx, OPC_WSBH, ret, rs);
18823 break;
18824 default:
18825 gen_reserved_instruction(ctx);
18826 break;
18829 tcg_temp_free(v0_t);
18830 tcg_temp_free(t0);
18833 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
18834 int rt, int rs, int rd)
18836 TCGv t0 = tcg_temp_new();
18837 TCGv rs_t = tcg_temp_new();
18839 gen_load_gpr(rs_t, rs);
18841 switch (opc) {
18842 case NM_SHRA_R_QB:
18843 check_dsp_r2(ctx);
18844 tcg_gen_movi_tl(t0, rd >> 2);
18845 switch (extract32(ctx->opcode, 12, 1)) {
18846 case 0:
18847 /* NM_SHRA_QB */
18848 gen_helper_shra_qb(t0, t0, rs_t);
18849 gen_store_gpr(t0, rt);
18850 break;
18851 case 1:
18852 /* NM_SHRA_R_QB */
18853 gen_helper_shra_r_qb(t0, t0, rs_t);
18854 gen_store_gpr(t0, rt);
18855 break;
18857 break;
18858 case NM_SHRL_PH:
18859 check_dsp_r2(ctx);
18860 tcg_gen_movi_tl(t0, rd >> 1);
18861 gen_helper_shrl_ph(t0, t0, rs_t);
18862 gen_store_gpr(t0, rt);
18863 break;
18864 case NM_REPL_QB:
18865 check_dsp(ctx);
18867 int16_t imm;
18868 target_long result;
18869 imm = extract32(ctx->opcode, 13, 8);
18870 result = (uint32_t)imm << 24 |
18871 (uint32_t)imm << 16 |
18872 (uint32_t)imm << 8 |
18873 (uint32_t)imm;
18874 result = (int32_t)result;
18875 tcg_gen_movi_tl(t0, result);
18876 gen_store_gpr(t0, rt);
18878 break;
18879 default:
18880 gen_reserved_instruction(ctx);
18881 break;
18883 tcg_temp_free(t0);
18884 tcg_temp_free(rs_t);
18888 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18890 int rt = extract32(ctx->opcode, 21, 5);
18891 int rs = extract32(ctx->opcode, 16, 5);
18892 int rd = extract32(ctx->opcode, 11, 5);
18894 switch (extract32(ctx->opcode, 6, 3)) {
18895 case NM_POOL32AXF_1:
18897 int32_t op1 = extract32(ctx->opcode, 9, 3);
18898 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
18900 break;
18901 case NM_POOL32AXF_2:
18903 int32_t op1 = extract32(ctx->opcode, 12, 2);
18904 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
18906 break;
18907 case NM_POOL32AXF_4:
18909 int32_t op1 = extract32(ctx->opcode, 9, 7);
18910 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
18912 break;
18913 case NM_POOL32AXF_5:
18914 switch (extract32(ctx->opcode, 9, 7)) {
18915 #ifndef CONFIG_USER_ONLY
18916 case NM_TLBP:
18917 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
18918 break;
18919 case NM_TLBR:
18920 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
18921 break;
18922 case NM_TLBWI:
18923 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
18924 break;
18925 case NM_TLBWR:
18926 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
18927 break;
18928 case NM_TLBINV:
18929 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
18930 break;
18931 case NM_TLBINVF:
18932 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
18933 break;
18934 case NM_DI:
18935 check_cp0_enabled(ctx);
18937 TCGv t0 = tcg_temp_new();
18939 save_cpu_state(ctx, 1);
18940 gen_helper_di(t0, cpu_env);
18941 gen_store_gpr(t0, rt);
18942 /* Stop translation as we may have switched the execution mode */
18943 ctx->base.is_jmp = DISAS_STOP;
18944 tcg_temp_free(t0);
18946 break;
18947 case NM_EI:
18948 check_cp0_enabled(ctx);
18950 TCGv t0 = tcg_temp_new();
18952 save_cpu_state(ctx, 1);
18953 gen_helper_ei(t0, cpu_env);
18954 gen_store_gpr(t0, rt);
18955 /* Stop translation as we may have switched the execution mode */
18956 ctx->base.is_jmp = DISAS_STOP;
18957 tcg_temp_free(t0);
18959 break;
18960 case NM_RDPGPR:
18961 check_cp0_enabled(ctx);
18962 gen_load_srsgpr(rs, rt);
18963 break;
18964 case NM_WRPGPR:
18965 check_cp0_enabled(ctx);
18966 gen_store_srsgpr(rs, rt);
18967 break;
18968 case NM_WAIT:
18969 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
18970 break;
18971 case NM_DERET:
18972 gen_cp0(env, ctx, OPC_DERET, 0, 0);
18973 break;
18974 case NM_ERETX:
18975 gen_cp0(env, ctx, OPC_ERET, 0, 0);
18976 break;
18977 #endif
18978 default:
18979 gen_reserved_instruction(ctx);
18980 break;
18982 break;
18983 case NM_POOL32AXF_7:
18985 int32_t op1 = extract32(ctx->opcode, 9, 3);
18986 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
18988 break;
18989 default:
18990 gen_reserved_instruction(ctx);
18991 break;
18995 /* Immediate Value Compact Branches */
18996 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
18997 int rt, int32_t imm, int32_t offset)
18999 TCGCond cond = TCG_COND_ALWAYS;
19000 TCGv t0 = tcg_temp_new();
19001 TCGv t1 = tcg_temp_new();
19003 gen_load_gpr(t0, rt);
19004 tcg_gen_movi_tl(t1, imm);
19005 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19007 /* Load needed operands and calculate btarget */
19008 switch (opc) {
19009 case NM_BEQIC:
19010 if (rt == 0 && imm == 0) {
19011 /* Unconditional branch */
19012 } else if (rt == 0 && imm != 0) {
19013 /* Treat as NOP */
19014 goto out;
19015 } else {
19016 cond = TCG_COND_EQ;
19018 break;
19019 case NM_BBEQZC:
19020 case NM_BBNEZC:
19021 check_nms(ctx);
19022 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19023 gen_reserved_instruction(ctx);
19024 goto out;
19025 } else if (rt == 0 && opc == NM_BBEQZC) {
19026 /* Unconditional branch */
19027 } else if (rt == 0 && opc == NM_BBNEZC) {
19028 /* Treat as NOP */
19029 goto out;
19030 } else {
19031 tcg_gen_shri_tl(t0, t0, imm);
19032 tcg_gen_andi_tl(t0, t0, 1);
19033 tcg_gen_movi_tl(t1, 0);
19034 if (opc == NM_BBEQZC) {
19035 cond = TCG_COND_EQ;
19036 } else {
19037 cond = TCG_COND_NE;
19040 break;
19041 case NM_BNEIC:
19042 if (rt == 0 && imm == 0) {
19043 /* Treat as NOP */
19044 goto out;
19045 } else if (rt == 0 && imm != 0) {
19046 /* Unconditional branch */
19047 } else {
19048 cond = TCG_COND_NE;
19050 break;
19051 case NM_BGEIC:
19052 if (rt == 0 && imm == 0) {
19053 /* Unconditional branch */
19054 } else {
19055 cond = TCG_COND_GE;
19057 break;
19058 case NM_BLTIC:
19059 cond = TCG_COND_LT;
19060 break;
19061 case NM_BGEIUC:
19062 if (rt == 0 && imm == 0) {
19063 /* Unconditional branch */
19064 } else {
19065 cond = TCG_COND_GEU;
19067 break;
19068 case NM_BLTIUC:
19069 cond = TCG_COND_LTU;
19070 break;
19071 default:
19072 MIPS_INVAL("Immediate Value Compact branch");
19073 gen_reserved_instruction(ctx);
19074 goto out;
19077 /* branch completion */
19078 clear_branch_hflags(ctx);
19079 ctx->base.is_jmp = DISAS_NORETURN;
19081 if (cond == TCG_COND_ALWAYS) {
19082 /* Uncoditional compact branch */
19083 gen_goto_tb(ctx, 0, ctx->btarget);
19084 } else {
19085 /* Conditional compact branch */
19086 TCGLabel *fs = gen_new_label();
19088 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19090 gen_goto_tb(ctx, 1, ctx->btarget);
19091 gen_set_label(fs);
19093 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19096 out:
19097 tcg_temp_free(t0);
19098 tcg_temp_free(t1);
19101 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19102 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19103 int rt)
19105 TCGv t0 = tcg_temp_new();
19106 TCGv t1 = tcg_temp_new();
19108 /* load rs */
19109 gen_load_gpr(t0, rs);
19111 /* link */
19112 if (rt != 0) {
19113 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19116 /* calculate btarget */
19117 tcg_gen_shli_tl(t0, t0, 1);
19118 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19119 gen_op_addr_add(ctx, btarget, t1, t0);
19121 /* branch completion */
19122 clear_branch_hflags(ctx);
19123 ctx->base.is_jmp = DISAS_NORETURN;
19125 /* unconditional branch to register */
19126 tcg_gen_mov_tl(cpu_PC, btarget);
19127 tcg_gen_lookup_and_goto_ptr();
19129 tcg_temp_free(t0);
19130 tcg_temp_free(t1);
19133 /* nanoMIPS Branches */
19134 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19135 int rs, int rt, int32_t offset)
19137 int bcond_compute = 0;
19138 TCGv t0 = tcg_temp_new();
19139 TCGv t1 = tcg_temp_new();
19141 /* Load needed operands and calculate btarget */
19142 switch (opc) {
19143 /* compact branch */
19144 case OPC_BGEC:
19145 case OPC_BLTC:
19146 gen_load_gpr(t0, rs);
19147 gen_load_gpr(t1, rt);
19148 bcond_compute = 1;
19149 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19150 break;
19151 case OPC_BGEUC:
19152 case OPC_BLTUC:
19153 if (rs == 0 || rs == rt) {
19154 /* OPC_BLEZALC, OPC_BGEZALC */
19155 /* OPC_BGTZALC, OPC_BLTZALC */
19156 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19158 gen_load_gpr(t0, rs);
19159 gen_load_gpr(t1, rt);
19160 bcond_compute = 1;
19161 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19162 break;
19163 case OPC_BC:
19164 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19165 break;
19166 case OPC_BEQZC:
19167 if (rs != 0) {
19168 /* OPC_BEQZC, OPC_BNEZC */
19169 gen_load_gpr(t0, rs);
19170 bcond_compute = 1;
19171 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19172 } else {
19173 /* OPC_JIC, OPC_JIALC */
19174 TCGv tbase = tcg_temp_new();
19175 TCGv toffset = tcg_temp_new();
19177 gen_load_gpr(tbase, rt);
19178 tcg_gen_movi_tl(toffset, offset);
19179 gen_op_addr_add(ctx, btarget, tbase, toffset);
19180 tcg_temp_free(tbase);
19181 tcg_temp_free(toffset);
19183 break;
19184 default:
19185 MIPS_INVAL("Compact branch/jump");
19186 gen_reserved_instruction(ctx);
19187 goto out;
19190 if (bcond_compute == 0) {
19191 /* Uncoditional compact branch */
19192 switch (opc) {
19193 case OPC_BC:
19194 gen_goto_tb(ctx, 0, ctx->btarget);
19195 break;
19196 default:
19197 MIPS_INVAL("Compact branch/jump");
19198 gen_reserved_instruction(ctx);
19199 goto out;
19201 } else {
19202 /* Conditional compact branch */
19203 TCGLabel *fs = gen_new_label();
19205 switch (opc) {
19206 case OPC_BGEUC:
19207 if (rs == 0 && rt != 0) {
19208 /* OPC_BLEZALC */
19209 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19210 } else if (rs != 0 && rt != 0 && rs == rt) {
19211 /* OPC_BGEZALC */
19212 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19213 } else {
19214 /* OPC_BGEUC */
19215 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19217 break;
19218 case OPC_BLTUC:
19219 if (rs == 0 && rt != 0) {
19220 /* OPC_BGTZALC */
19221 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19222 } else if (rs != 0 && rt != 0 && rs == rt) {
19223 /* OPC_BLTZALC */
19224 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19225 } else {
19226 /* OPC_BLTUC */
19227 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19229 break;
19230 case OPC_BGEC:
19231 if (rs == 0 && rt != 0) {
19232 /* OPC_BLEZC */
19233 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19234 } else if (rs != 0 && rt != 0 && rs == rt) {
19235 /* OPC_BGEZC */
19236 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19237 } else {
19238 /* OPC_BGEC */
19239 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19241 break;
19242 case OPC_BLTC:
19243 if (rs == 0 && rt != 0) {
19244 /* OPC_BGTZC */
19245 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19246 } else if (rs != 0 && rt != 0 && rs == rt) {
19247 /* OPC_BLTZC */
19248 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19249 } else {
19250 /* OPC_BLTC */
19251 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19253 break;
19254 case OPC_BEQZC:
19255 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19256 break;
19257 default:
19258 MIPS_INVAL("Compact conditional branch/jump");
19259 gen_reserved_instruction(ctx);
19260 goto out;
19263 /* branch completion */
19264 clear_branch_hflags(ctx);
19265 ctx->base.is_jmp = DISAS_NORETURN;
19267 /* Generating branch here as compact branches don't have delay slot */
19268 gen_goto_tb(ctx, 1, ctx->btarget);
19269 gen_set_label(fs);
19271 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19274 out:
19275 tcg_temp_free(t0);
19276 tcg_temp_free(t1);
19280 /* nanoMIPS CP1 Branches */
19281 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19282 int32_t ft, int32_t offset)
19284 target_ulong btarget;
19285 TCGv_i64 t0 = tcg_temp_new_i64();
19287 gen_load_fpr64(ctx, t0, ft);
19288 tcg_gen_andi_i64(t0, t0, 1);
19290 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19292 switch (op) {
19293 case NM_BC1EQZC:
19294 tcg_gen_xori_i64(t0, t0, 1);
19295 ctx->hflags |= MIPS_HFLAG_BC;
19296 break;
19297 case NM_BC1NEZC:
19298 /* t0 already set */
19299 ctx->hflags |= MIPS_HFLAG_BC;
19300 break;
19301 default:
19302 MIPS_INVAL("cp1 cond branch");
19303 gen_reserved_instruction(ctx);
19304 goto out;
19307 tcg_gen_trunc_i64_tl(bcond, t0);
19309 ctx->btarget = btarget;
19311 out:
19312 tcg_temp_free_i64(t0);
19316 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19318 TCGv t0, t1;
19319 t0 = tcg_temp_new();
19320 t1 = tcg_temp_new();
19322 gen_load_gpr(t0, rs);
19323 gen_load_gpr(t1, rt);
19325 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19326 /* PP.LSXS instructions require shifting */
19327 switch (extract32(ctx->opcode, 7, 4)) {
19328 case NM_SHXS:
19329 check_nms(ctx);
19330 /* fall through */
19331 case NM_LHXS:
19332 case NM_LHUXS:
19333 tcg_gen_shli_tl(t0, t0, 1);
19334 break;
19335 case NM_SWXS:
19336 check_nms(ctx);
19337 /* fall through */
19338 case NM_LWXS:
19339 case NM_LWC1XS:
19340 case NM_SWC1XS:
19341 tcg_gen_shli_tl(t0, t0, 2);
19342 break;
19343 case NM_LDC1XS:
19344 case NM_SDC1XS:
19345 tcg_gen_shli_tl(t0, t0, 3);
19346 break;
19349 gen_op_addr_add(ctx, t0, t0, t1);
19351 switch (extract32(ctx->opcode, 7, 4)) {
19352 case NM_LBX:
19353 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19354 MO_SB);
19355 gen_store_gpr(t0, rd);
19356 break;
19357 case NM_LHX:
19358 /*case NM_LHXS:*/
19359 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19360 MO_TESW);
19361 gen_store_gpr(t0, rd);
19362 break;
19363 case NM_LWX:
19364 /*case NM_LWXS:*/
19365 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19366 MO_TESL);
19367 gen_store_gpr(t0, rd);
19368 break;
19369 case NM_LBUX:
19370 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19371 MO_UB);
19372 gen_store_gpr(t0, rd);
19373 break;
19374 case NM_LHUX:
19375 /*case NM_LHUXS:*/
19376 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19377 MO_TEUW);
19378 gen_store_gpr(t0, rd);
19379 break;
19380 case NM_SBX:
19381 check_nms(ctx);
19382 gen_load_gpr(t1, rd);
19383 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19384 MO_8);
19385 break;
19386 case NM_SHX:
19387 /*case NM_SHXS:*/
19388 check_nms(ctx);
19389 gen_load_gpr(t1, rd);
19390 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19391 MO_TEUW);
19392 break;
19393 case NM_SWX:
19394 /*case NM_SWXS:*/
19395 check_nms(ctx);
19396 gen_load_gpr(t1, rd);
19397 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19398 MO_TEUL);
19399 break;
19400 case NM_LWC1X:
19401 /*case NM_LWC1XS:*/
19402 case NM_LDC1X:
19403 /*case NM_LDC1XS:*/
19404 case NM_SWC1X:
19405 /*case NM_SWC1XS:*/
19406 case NM_SDC1X:
19407 /*case NM_SDC1XS:*/
19408 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19409 check_cp1_enabled(ctx);
19410 switch (extract32(ctx->opcode, 7, 4)) {
19411 case NM_LWC1X:
19412 /*case NM_LWC1XS:*/
19413 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19414 break;
19415 case NM_LDC1X:
19416 /*case NM_LDC1XS:*/
19417 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19418 break;
19419 case NM_SWC1X:
19420 /*case NM_SWC1XS:*/
19421 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19422 break;
19423 case NM_SDC1X:
19424 /*case NM_SDC1XS:*/
19425 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19426 break;
19428 } else {
19429 generate_exception_err(ctx, EXCP_CpU, 1);
19431 break;
19432 default:
19433 gen_reserved_instruction(ctx);
19434 break;
19437 tcg_temp_free(t0);
19438 tcg_temp_free(t1);
19441 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19443 int rt, rs, rd;
19445 rt = extract32(ctx->opcode, 21, 5);
19446 rs = extract32(ctx->opcode, 16, 5);
19447 rd = extract32(ctx->opcode, 11, 5);
19449 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19450 gen_reserved_instruction(ctx);
19451 return;
19453 check_cp1_enabled(ctx);
19454 switch (extract32(ctx->opcode, 0, 3)) {
19455 case NM_POOL32F_0:
19456 switch (extract32(ctx->opcode, 3, 7)) {
19457 case NM_RINT_S:
19458 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19459 break;
19460 case NM_RINT_D:
19461 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19462 break;
19463 case NM_CLASS_S:
19464 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19465 break;
19466 case NM_CLASS_D:
19467 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19468 break;
19469 case NM_ADD_S:
19470 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19471 break;
19472 case NM_ADD_D:
19473 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19474 break;
19475 case NM_SUB_S:
19476 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19477 break;
19478 case NM_SUB_D:
19479 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19480 break;
19481 case NM_MUL_S:
19482 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19483 break;
19484 case NM_MUL_D:
19485 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19486 break;
19487 case NM_DIV_S:
19488 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19489 break;
19490 case NM_DIV_D:
19491 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19492 break;
19493 case NM_SELEQZ_S:
19494 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19495 break;
19496 case NM_SELEQZ_D:
19497 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19498 break;
19499 case NM_SELNEZ_S:
19500 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19501 break;
19502 case NM_SELNEZ_D:
19503 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19504 break;
19505 case NM_SEL_S:
19506 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19507 break;
19508 case NM_SEL_D:
19509 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19510 break;
19511 case NM_MADDF_S:
19512 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19513 break;
19514 case NM_MADDF_D:
19515 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19516 break;
19517 case NM_MSUBF_S:
19518 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19519 break;
19520 case NM_MSUBF_D:
19521 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19522 break;
19523 default:
19524 gen_reserved_instruction(ctx);
19525 break;
19527 break;
19528 case NM_POOL32F_3:
19529 switch (extract32(ctx->opcode, 3, 3)) {
19530 case NM_MIN_FMT:
19531 switch (extract32(ctx->opcode, 9, 1)) {
19532 case FMT_SDPS_S:
19533 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19534 break;
19535 case FMT_SDPS_D:
19536 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19537 break;
19539 break;
19540 case NM_MAX_FMT:
19541 switch (extract32(ctx->opcode, 9, 1)) {
19542 case FMT_SDPS_S:
19543 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19544 break;
19545 case FMT_SDPS_D:
19546 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19547 break;
19549 break;
19550 case NM_MINA_FMT:
19551 switch (extract32(ctx->opcode, 9, 1)) {
19552 case FMT_SDPS_S:
19553 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19554 break;
19555 case FMT_SDPS_D:
19556 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19557 break;
19559 break;
19560 case NM_MAXA_FMT:
19561 switch (extract32(ctx->opcode, 9, 1)) {
19562 case FMT_SDPS_S:
19563 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19564 break;
19565 case FMT_SDPS_D:
19566 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19567 break;
19569 break;
19570 case NM_POOL32FXF:
19571 switch (extract32(ctx->opcode, 6, 8)) {
19572 case NM_CFC1:
19573 gen_cp1(ctx, OPC_CFC1, rt, rs);
19574 break;
19575 case NM_CTC1:
19576 gen_cp1(ctx, OPC_CTC1, rt, rs);
19577 break;
19578 case NM_MFC1:
19579 gen_cp1(ctx, OPC_MFC1, rt, rs);
19580 break;
19581 case NM_MTC1:
19582 gen_cp1(ctx, OPC_MTC1, rt, rs);
19583 break;
19584 case NM_MFHC1:
19585 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19586 break;
19587 case NM_MTHC1:
19588 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19589 break;
19590 case NM_CVT_S_PL:
19591 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19592 break;
19593 case NM_CVT_S_PU:
19594 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19595 break;
19596 default:
19597 switch (extract32(ctx->opcode, 6, 9)) {
19598 case NM_CVT_L_S:
19599 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19600 break;
19601 case NM_CVT_L_D:
19602 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19603 break;
19604 case NM_CVT_W_S:
19605 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19606 break;
19607 case NM_CVT_W_D:
19608 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19609 break;
19610 case NM_RSQRT_S:
19611 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19612 break;
19613 case NM_RSQRT_D:
19614 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19615 break;
19616 case NM_SQRT_S:
19617 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19618 break;
19619 case NM_SQRT_D:
19620 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19621 break;
19622 case NM_RECIP_S:
19623 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19624 break;
19625 case NM_RECIP_D:
19626 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19627 break;
19628 case NM_FLOOR_L_S:
19629 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19630 break;
19631 case NM_FLOOR_L_D:
19632 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19633 break;
19634 case NM_FLOOR_W_S:
19635 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19636 break;
19637 case NM_FLOOR_W_D:
19638 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19639 break;
19640 case NM_CEIL_L_S:
19641 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19642 break;
19643 case NM_CEIL_L_D:
19644 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19645 break;
19646 case NM_CEIL_W_S:
19647 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19648 break;
19649 case NM_CEIL_W_D:
19650 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19651 break;
19652 case NM_TRUNC_L_S:
19653 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19654 break;
19655 case NM_TRUNC_L_D:
19656 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19657 break;
19658 case NM_TRUNC_W_S:
19659 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
19660 break;
19661 case NM_TRUNC_W_D:
19662 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
19663 break;
19664 case NM_ROUND_L_S:
19665 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
19666 break;
19667 case NM_ROUND_L_D:
19668 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
19669 break;
19670 case NM_ROUND_W_S:
19671 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
19672 break;
19673 case NM_ROUND_W_D:
19674 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
19675 break;
19676 case NM_MOV_S:
19677 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
19678 break;
19679 case NM_MOV_D:
19680 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
19681 break;
19682 case NM_ABS_S:
19683 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
19684 break;
19685 case NM_ABS_D:
19686 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
19687 break;
19688 case NM_NEG_S:
19689 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
19690 break;
19691 case NM_NEG_D:
19692 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
19693 break;
19694 case NM_CVT_D_S:
19695 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
19696 break;
19697 case NM_CVT_D_W:
19698 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
19699 break;
19700 case NM_CVT_D_L:
19701 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
19702 break;
19703 case NM_CVT_S_D:
19704 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
19705 break;
19706 case NM_CVT_S_W:
19707 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
19708 break;
19709 case NM_CVT_S_L:
19710 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
19711 break;
19712 default:
19713 gen_reserved_instruction(ctx);
19714 break;
19716 break;
19718 break;
19720 break;
19721 case NM_POOL32F_5:
19722 switch (extract32(ctx->opcode, 3, 3)) {
19723 case NM_CMP_CONDN_S:
19724 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19725 break;
19726 case NM_CMP_CONDN_D:
19727 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19728 break;
19729 default:
19730 gen_reserved_instruction(ctx);
19731 break;
19733 break;
19734 default:
19735 gen_reserved_instruction(ctx);
19736 break;
19740 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
19741 int rd, int rs, int rt)
19743 int ret = rd;
19744 TCGv t0 = tcg_temp_new();
19745 TCGv v1_t = tcg_temp_new();
19746 TCGv v2_t = tcg_temp_new();
19748 gen_load_gpr(v1_t, rs);
19749 gen_load_gpr(v2_t, rt);
19751 switch (opc) {
19752 case NM_CMP_EQ_PH:
19753 check_dsp(ctx);
19754 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
19755 break;
19756 case NM_CMP_LT_PH:
19757 check_dsp(ctx);
19758 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
19759 break;
19760 case NM_CMP_LE_PH:
19761 check_dsp(ctx);
19762 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
19763 break;
19764 case NM_CMPU_EQ_QB:
19765 check_dsp(ctx);
19766 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
19767 break;
19768 case NM_CMPU_LT_QB:
19769 check_dsp(ctx);
19770 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
19771 break;
19772 case NM_CMPU_LE_QB:
19773 check_dsp(ctx);
19774 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
19775 break;
19776 case NM_CMPGU_EQ_QB:
19777 check_dsp(ctx);
19778 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19779 gen_store_gpr(v1_t, ret);
19780 break;
19781 case NM_CMPGU_LT_QB:
19782 check_dsp(ctx);
19783 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19784 gen_store_gpr(v1_t, ret);
19785 break;
19786 case NM_CMPGU_LE_QB:
19787 check_dsp(ctx);
19788 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19789 gen_store_gpr(v1_t, ret);
19790 break;
19791 case NM_CMPGDU_EQ_QB:
19792 check_dsp_r2(ctx);
19793 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19794 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19795 gen_store_gpr(v1_t, ret);
19796 break;
19797 case NM_CMPGDU_LT_QB:
19798 check_dsp_r2(ctx);
19799 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19800 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19801 gen_store_gpr(v1_t, ret);
19802 break;
19803 case NM_CMPGDU_LE_QB:
19804 check_dsp_r2(ctx);
19805 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19806 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19807 gen_store_gpr(v1_t, ret);
19808 break;
19809 case NM_PACKRL_PH:
19810 check_dsp(ctx);
19811 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
19812 gen_store_gpr(v1_t, ret);
19813 break;
19814 case NM_PICK_QB:
19815 check_dsp(ctx);
19816 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
19817 gen_store_gpr(v1_t, ret);
19818 break;
19819 case NM_PICK_PH:
19820 check_dsp(ctx);
19821 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
19822 gen_store_gpr(v1_t, ret);
19823 break;
19824 case NM_ADDQ_S_W:
19825 check_dsp(ctx);
19826 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
19827 gen_store_gpr(v1_t, ret);
19828 break;
19829 case NM_SUBQ_S_W:
19830 check_dsp(ctx);
19831 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
19832 gen_store_gpr(v1_t, ret);
19833 break;
19834 case NM_ADDSC:
19835 check_dsp(ctx);
19836 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
19837 gen_store_gpr(v1_t, ret);
19838 break;
19839 case NM_ADDWC:
19840 check_dsp(ctx);
19841 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
19842 gen_store_gpr(v1_t, ret);
19843 break;
19844 case NM_ADDQ_S_PH:
19845 check_dsp(ctx);
19846 switch (extract32(ctx->opcode, 10, 1)) {
19847 case 0:
19848 /* ADDQ_PH */
19849 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
19850 gen_store_gpr(v1_t, ret);
19851 break;
19852 case 1:
19853 /* ADDQ_S_PH */
19854 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19855 gen_store_gpr(v1_t, ret);
19856 break;
19858 break;
19859 case NM_ADDQH_R_PH:
19860 check_dsp_r2(ctx);
19861 switch (extract32(ctx->opcode, 10, 1)) {
19862 case 0:
19863 /* ADDQH_PH */
19864 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
19865 gen_store_gpr(v1_t, ret);
19866 break;
19867 case 1:
19868 /* ADDQH_R_PH */
19869 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
19870 gen_store_gpr(v1_t, ret);
19871 break;
19873 break;
19874 case NM_ADDQH_R_W:
19875 check_dsp_r2(ctx);
19876 switch (extract32(ctx->opcode, 10, 1)) {
19877 case 0:
19878 /* ADDQH_W */
19879 gen_helper_addqh_w(v1_t, v1_t, v2_t);
19880 gen_store_gpr(v1_t, ret);
19881 break;
19882 case 1:
19883 /* ADDQH_R_W */
19884 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
19885 gen_store_gpr(v1_t, ret);
19886 break;
19888 break;
19889 case NM_ADDU_S_QB:
19890 check_dsp(ctx);
19891 switch (extract32(ctx->opcode, 10, 1)) {
19892 case 0:
19893 /* ADDU_QB */
19894 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
19895 gen_store_gpr(v1_t, ret);
19896 break;
19897 case 1:
19898 /* ADDU_S_QB */
19899 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19900 gen_store_gpr(v1_t, ret);
19901 break;
19903 break;
19904 case NM_ADDU_S_PH:
19905 check_dsp_r2(ctx);
19906 switch (extract32(ctx->opcode, 10, 1)) {
19907 case 0:
19908 /* ADDU_PH */
19909 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
19910 gen_store_gpr(v1_t, ret);
19911 break;
19912 case 1:
19913 /* ADDU_S_PH */
19914 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19915 gen_store_gpr(v1_t, ret);
19916 break;
19918 break;
19919 case NM_ADDUH_R_QB:
19920 check_dsp_r2(ctx);
19921 switch (extract32(ctx->opcode, 10, 1)) {
19922 case 0:
19923 /* ADDUH_QB */
19924 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
19925 gen_store_gpr(v1_t, ret);
19926 break;
19927 case 1:
19928 /* ADDUH_R_QB */
19929 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
19930 gen_store_gpr(v1_t, ret);
19931 break;
19933 break;
19934 case NM_SHRAV_R_PH:
19935 check_dsp(ctx);
19936 switch (extract32(ctx->opcode, 10, 1)) {
19937 case 0:
19938 /* SHRAV_PH */
19939 gen_helper_shra_ph(v1_t, v1_t, v2_t);
19940 gen_store_gpr(v1_t, ret);
19941 break;
19942 case 1:
19943 /* SHRAV_R_PH */
19944 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
19945 gen_store_gpr(v1_t, ret);
19946 break;
19948 break;
19949 case NM_SHRAV_R_QB:
19950 check_dsp_r2(ctx);
19951 switch (extract32(ctx->opcode, 10, 1)) {
19952 case 0:
19953 /* SHRAV_QB */
19954 gen_helper_shra_qb(v1_t, v1_t, v2_t);
19955 gen_store_gpr(v1_t, ret);
19956 break;
19957 case 1:
19958 /* SHRAV_R_QB */
19959 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
19960 gen_store_gpr(v1_t, ret);
19961 break;
19963 break;
19964 case NM_SUBQ_S_PH:
19965 check_dsp(ctx);
19966 switch (extract32(ctx->opcode, 10, 1)) {
19967 case 0:
19968 /* SUBQ_PH */
19969 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
19970 gen_store_gpr(v1_t, ret);
19971 break;
19972 case 1:
19973 /* SUBQ_S_PH */
19974 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19975 gen_store_gpr(v1_t, ret);
19976 break;
19978 break;
19979 case NM_SUBQH_R_PH:
19980 check_dsp_r2(ctx);
19981 switch (extract32(ctx->opcode, 10, 1)) {
19982 case 0:
19983 /* SUBQH_PH */
19984 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
19985 gen_store_gpr(v1_t, ret);
19986 break;
19987 case 1:
19988 /* SUBQH_R_PH */
19989 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
19990 gen_store_gpr(v1_t, ret);
19991 break;
19993 break;
19994 case NM_SUBQH_R_W:
19995 check_dsp_r2(ctx);
19996 switch (extract32(ctx->opcode, 10, 1)) {
19997 case 0:
19998 /* SUBQH_W */
19999 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20000 gen_store_gpr(v1_t, ret);
20001 break;
20002 case 1:
20003 /* SUBQH_R_W */
20004 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20005 gen_store_gpr(v1_t, ret);
20006 break;
20008 break;
20009 case NM_SUBU_S_QB:
20010 check_dsp(ctx);
20011 switch (extract32(ctx->opcode, 10, 1)) {
20012 case 0:
20013 /* SUBU_QB */
20014 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20015 gen_store_gpr(v1_t, ret);
20016 break;
20017 case 1:
20018 /* SUBU_S_QB */
20019 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20020 gen_store_gpr(v1_t, ret);
20021 break;
20023 break;
20024 case NM_SUBU_S_PH:
20025 check_dsp_r2(ctx);
20026 switch (extract32(ctx->opcode, 10, 1)) {
20027 case 0:
20028 /* SUBU_PH */
20029 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20030 gen_store_gpr(v1_t, ret);
20031 break;
20032 case 1:
20033 /* SUBU_S_PH */
20034 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20035 gen_store_gpr(v1_t, ret);
20036 break;
20038 break;
20039 case NM_SUBUH_R_QB:
20040 check_dsp_r2(ctx);
20041 switch (extract32(ctx->opcode, 10, 1)) {
20042 case 0:
20043 /* SUBUH_QB */
20044 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20045 gen_store_gpr(v1_t, ret);
20046 break;
20047 case 1:
20048 /* SUBUH_R_QB */
20049 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20050 gen_store_gpr(v1_t, ret);
20051 break;
20053 break;
20054 case NM_SHLLV_S_PH:
20055 check_dsp(ctx);
20056 switch (extract32(ctx->opcode, 10, 1)) {
20057 case 0:
20058 /* SHLLV_PH */
20059 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20060 gen_store_gpr(v1_t, ret);
20061 break;
20062 case 1:
20063 /* SHLLV_S_PH */
20064 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20065 gen_store_gpr(v1_t, ret);
20066 break;
20068 break;
20069 case NM_PRECR_SRA_R_PH_W:
20070 check_dsp_r2(ctx);
20071 switch (extract32(ctx->opcode, 10, 1)) {
20072 case 0:
20073 /* PRECR_SRA_PH_W */
20075 TCGv_i32 sa_t = tcg_const_i32(rd);
20076 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20077 cpu_gpr[rt]);
20078 gen_store_gpr(v1_t, rt);
20079 tcg_temp_free_i32(sa_t);
20081 break;
20082 case 1:
20083 /* PRECR_SRA_R_PH_W */
20085 TCGv_i32 sa_t = tcg_const_i32(rd);
20086 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20087 cpu_gpr[rt]);
20088 gen_store_gpr(v1_t, rt);
20089 tcg_temp_free_i32(sa_t);
20091 break;
20093 break;
20094 case NM_MULEU_S_PH_QBL:
20095 check_dsp(ctx);
20096 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20097 gen_store_gpr(v1_t, ret);
20098 break;
20099 case NM_MULEU_S_PH_QBR:
20100 check_dsp(ctx);
20101 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20102 gen_store_gpr(v1_t, ret);
20103 break;
20104 case NM_MULQ_RS_PH:
20105 check_dsp(ctx);
20106 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20107 gen_store_gpr(v1_t, ret);
20108 break;
20109 case NM_MULQ_S_PH:
20110 check_dsp_r2(ctx);
20111 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20112 gen_store_gpr(v1_t, ret);
20113 break;
20114 case NM_MULQ_RS_W:
20115 check_dsp_r2(ctx);
20116 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20117 gen_store_gpr(v1_t, ret);
20118 break;
20119 case NM_MULQ_S_W:
20120 check_dsp_r2(ctx);
20121 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20122 gen_store_gpr(v1_t, ret);
20123 break;
20124 case NM_APPEND:
20125 check_dsp_r2(ctx);
20126 gen_load_gpr(t0, rs);
20127 if (rd != 0) {
20128 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20130 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20131 break;
20132 case NM_MODSUB:
20133 check_dsp(ctx);
20134 gen_helper_modsub(v1_t, v1_t, v2_t);
20135 gen_store_gpr(v1_t, ret);
20136 break;
20137 case NM_SHRAV_R_W:
20138 check_dsp(ctx);
20139 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20140 gen_store_gpr(v1_t, ret);
20141 break;
20142 case NM_SHRLV_PH:
20143 check_dsp_r2(ctx);
20144 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20145 gen_store_gpr(v1_t, ret);
20146 break;
20147 case NM_SHRLV_QB:
20148 check_dsp(ctx);
20149 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20150 gen_store_gpr(v1_t, ret);
20151 break;
20152 case NM_SHLLV_QB:
20153 check_dsp(ctx);
20154 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20155 gen_store_gpr(v1_t, ret);
20156 break;
20157 case NM_SHLLV_S_W:
20158 check_dsp(ctx);
20159 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20160 gen_store_gpr(v1_t, ret);
20161 break;
20162 case NM_SHILO:
20163 check_dsp(ctx);
20165 TCGv tv0 = tcg_temp_new();
20166 TCGv tv1 = tcg_temp_new();
20167 int16_t imm = extract32(ctx->opcode, 16, 7);
20169 tcg_gen_movi_tl(tv0, rd >> 3);
20170 tcg_gen_movi_tl(tv1, imm);
20171 gen_helper_shilo(tv0, tv1, cpu_env);
20173 break;
20174 case NM_MULEQ_S_W_PHL:
20175 check_dsp(ctx);
20176 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20177 gen_store_gpr(v1_t, ret);
20178 break;
20179 case NM_MULEQ_S_W_PHR:
20180 check_dsp(ctx);
20181 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20182 gen_store_gpr(v1_t, ret);
20183 break;
20184 case NM_MUL_S_PH:
20185 check_dsp_r2(ctx);
20186 switch (extract32(ctx->opcode, 10, 1)) {
20187 case 0:
20188 /* MUL_PH */
20189 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20190 gen_store_gpr(v1_t, ret);
20191 break;
20192 case 1:
20193 /* MUL_S_PH */
20194 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20195 gen_store_gpr(v1_t, ret);
20196 break;
20198 break;
20199 case NM_PRECR_QB_PH:
20200 check_dsp_r2(ctx);
20201 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20202 gen_store_gpr(v1_t, ret);
20203 break;
20204 case NM_PRECRQ_QB_PH:
20205 check_dsp(ctx);
20206 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20207 gen_store_gpr(v1_t, ret);
20208 break;
20209 case NM_PRECRQ_PH_W:
20210 check_dsp(ctx);
20211 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20212 gen_store_gpr(v1_t, ret);
20213 break;
20214 case NM_PRECRQ_RS_PH_W:
20215 check_dsp(ctx);
20216 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20217 gen_store_gpr(v1_t, ret);
20218 break;
20219 case NM_PRECRQU_S_QB_PH:
20220 check_dsp(ctx);
20221 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20222 gen_store_gpr(v1_t, ret);
20223 break;
20224 case NM_SHRA_R_W:
20225 check_dsp(ctx);
20226 tcg_gen_movi_tl(t0, rd);
20227 gen_helper_shra_r_w(v1_t, t0, v1_t);
20228 gen_store_gpr(v1_t, rt);
20229 break;
20230 case NM_SHRA_R_PH:
20231 check_dsp(ctx);
20232 tcg_gen_movi_tl(t0, rd >> 1);
20233 switch (extract32(ctx->opcode, 10, 1)) {
20234 case 0:
20235 /* SHRA_PH */
20236 gen_helper_shra_ph(v1_t, t0, v1_t);
20237 gen_store_gpr(v1_t, rt);
20238 break;
20239 case 1:
20240 /* SHRA_R_PH */
20241 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20242 gen_store_gpr(v1_t, rt);
20243 break;
20245 break;
20246 case NM_SHLL_S_PH:
20247 check_dsp(ctx);
20248 tcg_gen_movi_tl(t0, rd >> 1);
20249 switch (extract32(ctx->opcode, 10, 2)) {
20250 case 0:
20251 /* SHLL_PH */
20252 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20253 gen_store_gpr(v1_t, rt);
20254 break;
20255 case 2:
20256 /* SHLL_S_PH */
20257 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20258 gen_store_gpr(v1_t, rt);
20259 break;
20260 default:
20261 gen_reserved_instruction(ctx);
20262 break;
20264 break;
20265 case NM_SHLL_S_W:
20266 check_dsp(ctx);
20267 tcg_gen_movi_tl(t0, rd);
20268 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20269 gen_store_gpr(v1_t, rt);
20270 break;
20271 case NM_REPL_PH:
20272 check_dsp(ctx);
20274 int16_t imm;
20275 imm = sextract32(ctx->opcode, 11, 11);
20276 imm = (int16_t)(imm << 6) >> 6;
20277 if (rt != 0) {
20278 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20281 break;
20282 default:
20283 gen_reserved_instruction(ctx);
20284 break;
20288 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20290 uint16_t insn;
20291 uint32_t op;
20292 int rt, rs, rd;
20293 int offset;
20294 int imm;
20296 insn = translator_lduw(env, ctx->base.pc_next + 2);
20297 ctx->opcode = (ctx->opcode << 16) | insn;
20299 rt = extract32(ctx->opcode, 21, 5);
20300 rs = extract32(ctx->opcode, 16, 5);
20301 rd = extract32(ctx->opcode, 11, 5);
20303 op = extract32(ctx->opcode, 26, 6);
20304 switch (op) {
20305 case NM_P_ADDIU:
20306 if (rt == 0) {
20307 /* P.RI */
20308 switch (extract32(ctx->opcode, 19, 2)) {
20309 case NM_SIGRIE:
20310 default:
20311 gen_reserved_instruction(ctx);
20312 break;
20313 case NM_P_SYSCALL:
20314 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20315 generate_exception_end(ctx, EXCP_SYSCALL);
20316 } else {
20317 gen_reserved_instruction(ctx);
20319 break;
20320 case NM_BREAK:
20321 generate_exception_end(ctx, EXCP_BREAK);
20322 break;
20323 case NM_SDBBP:
20324 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20325 gen_helper_do_semihosting(cpu_env);
20326 } else {
20327 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20328 gen_reserved_instruction(ctx);
20329 } else {
20330 generate_exception_end(ctx, EXCP_DBp);
20333 break;
20335 } else {
20336 /* NM_ADDIU */
20337 imm = extract32(ctx->opcode, 0, 16);
20338 if (rs != 0) {
20339 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20340 } else {
20341 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20343 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20345 break;
20346 case NM_ADDIUPC:
20347 if (rt != 0) {
20348 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20349 extract32(ctx->opcode, 1, 20) << 1;
20350 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20351 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20353 break;
20354 case NM_POOL32A:
20355 switch (ctx->opcode & 0x07) {
20356 case NM_POOL32A0:
20357 gen_pool32a0_nanomips_insn(env, ctx);
20358 break;
20359 case NM_POOL32A5:
20361 int32_t op1 = extract32(ctx->opcode, 3, 7);
20362 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20364 break;
20365 case NM_POOL32A7:
20366 switch (extract32(ctx->opcode, 3, 3)) {
20367 case NM_P_LSX:
20368 gen_p_lsx(ctx, rd, rs, rt);
20369 break;
20370 case NM_LSA:
20372 * In nanoMIPS, the shift field directly encodes the shift
20373 * amount, meaning that the supported shift values are in
20374 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
20376 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2) - 1);
20377 break;
20378 case NM_EXTW:
20379 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20380 break;
20381 case NM_POOL32AXF:
20382 gen_pool32axf_nanomips_insn(env, ctx);
20383 break;
20384 default:
20385 gen_reserved_instruction(ctx);
20386 break;
20388 break;
20389 default:
20390 gen_reserved_instruction(ctx);
20391 break;
20393 break;
20394 case NM_P_GP_W:
20395 switch (ctx->opcode & 0x03) {
20396 case NM_ADDIUGP_W:
20397 if (rt != 0) {
20398 offset = extract32(ctx->opcode, 0, 21);
20399 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20401 break;
20402 case NM_LWGP:
20403 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20404 break;
20405 case NM_SWGP:
20406 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20407 break;
20408 default:
20409 gen_reserved_instruction(ctx);
20410 break;
20412 break;
20413 case NM_P48I:
20415 insn = translator_lduw(env, ctx->base.pc_next + 4);
20416 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20417 switch (extract32(ctx->opcode, 16, 5)) {
20418 case NM_LI48:
20419 check_nms(ctx);
20420 if (rt != 0) {
20421 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20423 break;
20424 case NM_ADDIU48:
20425 check_nms(ctx);
20426 if (rt != 0) {
20427 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20428 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20430 break;
20431 case NM_ADDIUGP48:
20432 check_nms(ctx);
20433 if (rt != 0) {
20434 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20436 break;
20437 case NM_ADDIUPC48:
20438 check_nms(ctx);
20439 if (rt != 0) {
20440 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20441 addr_off);
20443 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20445 break;
20446 case NM_LWPC48:
20447 check_nms(ctx);
20448 if (rt != 0) {
20449 TCGv t0;
20450 t0 = tcg_temp_new();
20452 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20453 addr_off);
20455 tcg_gen_movi_tl(t0, addr);
20456 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20457 tcg_temp_free(t0);
20459 break;
20460 case NM_SWPC48:
20461 check_nms(ctx);
20463 TCGv t0, t1;
20464 t0 = tcg_temp_new();
20465 t1 = tcg_temp_new();
20467 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20468 addr_off);
20470 tcg_gen_movi_tl(t0, addr);
20471 gen_load_gpr(t1, rt);
20473 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20475 tcg_temp_free(t0);
20476 tcg_temp_free(t1);
20478 break;
20479 default:
20480 gen_reserved_instruction(ctx);
20481 break;
20483 return 6;
20485 case NM_P_U12:
20486 switch (extract32(ctx->opcode, 12, 4)) {
20487 case NM_ORI:
20488 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20489 break;
20490 case NM_XORI:
20491 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20492 break;
20493 case NM_ANDI:
20494 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20495 break;
20496 case NM_P_SR:
20497 switch (extract32(ctx->opcode, 20, 1)) {
20498 case NM_PP_SR:
20499 switch (ctx->opcode & 3) {
20500 case NM_SAVE:
20501 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20502 extract32(ctx->opcode, 2, 1),
20503 extract32(ctx->opcode, 3, 9) << 3);
20504 break;
20505 case NM_RESTORE:
20506 case NM_RESTORE_JRC:
20507 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20508 extract32(ctx->opcode, 2, 1),
20509 extract32(ctx->opcode, 3, 9) << 3);
20510 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20511 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20513 break;
20514 default:
20515 gen_reserved_instruction(ctx);
20516 break;
20518 break;
20519 case NM_P_SR_F:
20520 gen_reserved_instruction(ctx);
20521 break;
20523 break;
20524 case NM_SLTI:
20525 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20526 break;
20527 case NM_SLTIU:
20528 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20529 break;
20530 case NM_SEQI:
20532 TCGv t0 = tcg_temp_new();
20534 imm = extract32(ctx->opcode, 0, 12);
20535 gen_load_gpr(t0, rs);
20536 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20537 gen_store_gpr(t0, rt);
20539 tcg_temp_free(t0);
20541 break;
20542 case NM_ADDIUNEG:
20543 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20544 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20545 break;
20546 case NM_P_SHIFT:
20548 int shift = extract32(ctx->opcode, 0, 5);
20549 switch (extract32(ctx->opcode, 5, 4)) {
20550 case NM_P_SLL:
20551 if (rt == 0 && shift == 0) {
20552 /* NOP */
20553 } else if (rt == 0 && shift == 3) {
20554 /* EHB - treat as NOP */
20555 } else if (rt == 0 && shift == 5) {
20556 /* PAUSE - treat as NOP */
20557 } else if (rt == 0 && shift == 6) {
20558 /* SYNC */
20559 gen_sync(extract32(ctx->opcode, 16, 5));
20560 } else {
20561 /* SLL */
20562 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20563 extract32(ctx->opcode, 0, 5));
20565 break;
20566 case NM_SRL:
20567 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20568 extract32(ctx->opcode, 0, 5));
20569 break;
20570 case NM_SRA:
20571 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20572 extract32(ctx->opcode, 0, 5));
20573 break;
20574 case NM_ROTR:
20575 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20576 extract32(ctx->opcode, 0, 5));
20577 break;
20580 break;
20581 case NM_P_ROTX:
20582 check_nms(ctx);
20583 if (rt != 0) {
20584 TCGv t0 = tcg_temp_new();
20585 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20586 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20587 << 1);
20588 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20590 gen_load_gpr(t0, rs);
20591 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20592 tcg_temp_free(t0);
20594 tcg_temp_free_i32(shift);
20595 tcg_temp_free_i32(shiftx);
20596 tcg_temp_free_i32(stripe);
20598 break;
20599 case NM_P_INS:
20600 switch (((ctx->opcode >> 10) & 2) |
20601 (extract32(ctx->opcode, 5, 1))) {
20602 case NM_INS:
20603 check_nms(ctx);
20604 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20605 extract32(ctx->opcode, 6, 5));
20606 break;
20607 default:
20608 gen_reserved_instruction(ctx);
20609 break;
20611 break;
20612 case NM_P_EXT:
20613 switch (((ctx->opcode >> 10) & 2) |
20614 (extract32(ctx->opcode, 5, 1))) {
20615 case NM_EXT:
20616 check_nms(ctx);
20617 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20618 extract32(ctx->opcode, 6, 5));
20619 break;
20620 default:
20621 gen_reserved_instruction(ctx);
20622 break;
20624 break;
20625 default:
20626 gen_reserved_instruction(ctx);
20627 break;
20629 break;
20630 case NM_POOL32F:
20631 gen_pool32f_nanomips_insn(ctx);
20632 break;
20633 case NM_POOL32S:
20634 break;
20635 case NM_P_LUI:
20636 switch (extract32(ctx->opcode, 1, 1)) {
20637 case NM_LUI:
20638 if (rt != 0) {
20639 tcg_gen_movi_tl(cpu_gpr[rt],
20640 sextract32(ctx->opcode, 0, 1) << 31 |
20641 extract32(ctx->opcode, 2, 10) << 21 |
20642 extract32(ctx->opcode, 12, 9) << 12);
20644 break;
20645 case NM_ALUIPC:
20646 if (rt != 0) {
20647 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20648 extract32(ctx->opcode, 2, 10) << 21 |
20649 extract32(ctx->opcode, 12, 9) << 12;
20650 target_long addr;
20651 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20652 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20654 break;
20656 break;
20657 case NM_P_GP_BH:
20659 uint32_t u = extract32(ctx->opcode, 0, 18);
20661 switch (extract32(ctx->opcode, 18, 3)) {
20662 case NM_LBGP:
20663 gen_ld(ctx, OPC_LB, rt, 28, u);
20664 break;
20665 case NM_SBGP:
20666 gen_st(ctx, OPC_SB, rt, 28, u);
20667 break;
20668 case NM_LBUGP:
20669 gen_ld(ctx, OPC_LBU, rt, 28, u);
20670 break;
20671 case NM_ADDIUGP_B:
20672 if (rt != 0) {
20673 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
20675 break;
20676 case NM_P_GP_LH:
20677 u &= ~1;
20678 switch (ctx->opcode & 1) {
20679 case NM_LHGP:
20680 gen_ld(ctx, OPC_LH, rt, 28, u);
20681 break;
20682 case NM_LHUGP:
20683 gen_ld(ctx, OPC_LHU, rt, 28, u);
20684 break;
20686 break;
20687 case NM_P_GP_SH:
20688 u &= ~1;
20689 switch (ctx->opcode & 1) {
20690 case NM_SHGP:
20691 gen_st(ctx, OPC_SH, rt, 28, u);
20692 break;
20693 default:
20694 gen_reserved_instruction(ctx);
20695 break;
20697 break;
20698 case NM_P_GP_CP1:
20699 u &= ~0x3;
20700 switch (ctx->opcode & 0x3) {
20701 case NM_LWC1GP:
20702 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
20703 break;
20704 case NM_LDC1GP:
20705 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
20706 break;
20707 case NM_SWC1GP:
20708 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
20709 break;
20710 case NM_SDC1GP:
20711 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
20712 break;
20714 break;
20715 default:
20716 gen_reserved_instruction(ctx);
20717 break;
20720 break;
20721 case NM_P_LS_U12:
20723 uint32_t u = extract32(ctx->opcode, 0, 12);
20725 switch (extract32(ctx->opcode, 12, 4)) {
20726 case NM_P_PREFU12:
20727 if (rt == 31) {
20728 /* SYNCI */
20730 * Break the TB to be able to sync copied instructions
20731 * immediately.
20733 ctx->base.is_jmp = DISAS_STOP;
20734 } else {
20735 /* PREF */
20736 /* Treat as NOP. */
20738 break;
20739 case NM_LB:
20740 gen_ld(ctx, OPC_LB, rt, rs, u);
20741 break;
20742 case NM_LH:
20743 gen_ld(ctx, OPC_LH, rt, rs, u);
20744 break;
20745 case NM_LW:
20746 gen_ld(ctx, OPC_LW, rt, rs, u);
20747 break;
20748 case NM_LBU:
20749 gen_ld(ctx, OPC_LBU, rt, rs, u);
20750 break;
20751 case NM_LHU:
20752 gen_ld(ctx, OPC_LHU, rt, rs, u);
20753 break;
20754 case NM_SB:
20755 gen_st(ctx, OPC_SB, rt, rs, u);
20756 break;
20757 case NM_SH:
20758 gen_st(ctx, OPC_SH, rt, rs, u);
20759 break;
20760 case NM_SW:
20761 gen_st(ctx, OPC_SW, rt, rs, u);
20762 break;
20763 case NM_LWC1:
20764 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
20765 break;
20766 case NM_LDC1:
20767 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
20768 break;
20769 case NM_SWC1:
20770 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
20771 break;
20772 case NM_SDC1:
20773 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
20774 break;
20775 default:
20776 gen_reserved_instruction(ctx);
20777 break;
20780 break;
20781 case NM_P_LS_S9:
20783 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
20784 extract32(ctx->opcode, 0, 8);
20786 switch (extract32(ctx->opcode, 8, 3)) {
20787 case NM_P_LS_S0:
20788 switch (extract32(ctx->opcode, 11, 4)) {
20789 case NM_LBS9:
20790 gen_ld(ctx, OPC_LB, rt, rs, s);
20791 break;
20792 case NM_LHS9:
20793 gen_ld(ctx, OPC_LH, rt, rs, s);
20794 break;
20795 case NM_LWS9:
20796 gen_ld(ctx, OPC_LW, rt, rs, s);
20797 break;
20798 case NM_LBUS9:
20799 gen_ld(ctx, OPC_LBU, rt, rs, s);
20800 break;
20801 case NM_LHUS9:
20802 gen_ld(ctx, OPC_LHU, rt, rs, s);
20803 break;
20804 case NM_SBS9:
20805 gen_st(ctx, OPC_SB, rt, rs, s);
20806 break;
20807 case NM_SHS9:
20808 gen_st(ctx, OPC_SH, rt, rs, s);
20809 break;
20810 case NM_SWS9:
20811 gen_st(ctx, OPC_SW, rt, rs, s);
20812 break;
20813 case NM_LWC1S9:
20814 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
20815 break;
20816 case NM_LDC1S9:
20817 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
20818 break;
20819 case NM_SWC1S9:
20820 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
20821 break;
20822 case NM_SDC1S9:
20823 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
20824 break;
20825 case NM_P_PREFS9:
20826 if (rt == 31) {
20827 /* SYNCI */
20829 * Break the TB to be able to sync copied instructions
20830 * immediately.
20832 ctx->base.is_jmp = DISAS_STOP;
20833 } else {
20834 /* PREF */
20835 /* Treat as NOP. */
20837 break;
20838 default:
20839 gen_reserved_instruction(ctx);
20840 break;
20842 break;
20843 case NM_P_LS_S1:
20844 switch (extract32(ctx->opcode, 11, 4)) {
20845 case NM_UALH:
20846 case NM_UASH:
20847 check_nms(ctx);
20849 TCGv t0 = tcg_temp_new();
20850 TCGv t1 = tcg_temp_new();
20852 gen_base_offset_addr(ctx, t0, rs, s);
20854 switch (extract32(ctx->opcode, 11, 4)) {
20855 case NM_UALH:
20856 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
20857 MO_UNALN);
20858 gen_store_gpr(t0, rt);
20859 break;
20860 case NM_UASH:
20861 gen_load_gpr(t1, rt);
20862 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
20863 MO_UNALN);
20864 break;
20866 tcg_temp_free(t0);
20867 tcg_temp_free(t1);
20869 break;
20870 case NM_P_LL:
20871 switch (ctx->opcode & 0x03) {
20872 case NM_LL:
20873 gen_ld(ctx, OPC_LL, rt, rs, s);
20874 break;
20875 case NM_LLWP:
20876 check_xnp(ctx);
20877 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
20878 break;
20880 break;
20881 case NM_P_SC:
20882 switch (ctx->opcode & 0x03) {
20883 case NM_SC:
20884 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
20885 break;
20886 case NM_SCWP:
20887 check_xnp(ctx);
20888 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
20889 false);
20890 break;
20892 break;
20893 case NM_CACHE:
20894 check_cp0_enabled(ctx);
20895 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
20896 gen_cache_operation(ctx, rt, rs, s);
20898 break;
20900 break;
20901 case NM_P_LS_E0:
20902 switch (extract32(ctx->opcode, 11, 4)) {
20903 case NM_LBE:
20904 check_eva(ctx);
20905 check_cp0_enabled(ctx);
20906 gen_ld(ctx, OPC_LBE, rt, rs, s);
20907 break;
20908 case NM_SBE:
20909 check_eva(ctx);
20910 check_cp0_enabled(ctx);
20911 gen_st(ctx, OPC_SBE, rt, rs, s);
20912 break;
20913 case NM_LBUE:
20914 check_eva(ctx);
20915 check_cp0_enabled(ctx);
20916 gen_ld(ctx, OPC_LBUE, rt, rs, s);
20917 break;
20918 case NM_P_PREFE:
20919 if (rt == 31) {
20920 /* case NM_SYNCIE */
20921 check_eva(ctx);
20922 check_cp0_enabled(ctx);
20924 * Break the TB to be able to sync copied instructions
20925 * immediately.
20927 ctx->base.is_jmp = DISAS_STOP;
20928 } else {
20929 /* case NM_PREFE */
20930 check_eva(ctx);
20931 check_cp0_enabled(ctx);
20932 /* Treat as NOP. */
20934 break;
20935 case NM_LHE:
20936 check_eva(ctx);
20937 check_cp0_enabled(ctx);
20938 gen_ld(ctx, OPC_LHE, rt, rs, s);
20939 break;
20940 case NM_SHE:
20941 check_eva(ctx);
20942 check_cp0_enabled(ctx);
20943 gen_st(ctx, OPC_SHE, rt, rs, s);
20944 break;
20945 case NM_LHUE:
20946 check_eva(ctx);
20947 check_cp0_enabled(ctx);
20948 gen_ld(ctx, OPC_LHUE, rt, rs, s);
20949 break;
20950 case NM_CACHEE:
20951 check_eva(ctx);
20952 check_cp0_enabled(ctx);
20953 check_nms_dl_il_sl_tl_l2c(ctx);
20954 gen_cache_operation(ctx, rt, rs, s);
20955 break;
20956 case NM_LWE:
20957 check_eva(ctx);
20958 check_cp0_enabled(ctx);
20959 gen_ld(ctx, OPC_LWE, rt, rs, s);
20960 break;
20961 case NM_SWE:
20962 check_eva(ctx);
20963 check_cp0_enabled(ctx);
20964 gen_st(ctx, OPC_SWE, rt, rs, s);
20965 break;
20966 case NM_P_LLE:
20967 switch (extract32(ctx->opcode, 2, 2)) {
20968 case NM_LLE:
20969 check_xnp(ctx);
20970 check_eva(ctx);
20971 check_cp0_enabled(ctx);
20972 gen_ld(ctx, OPC_LLE, rt, rs, s);
20973 break;
20974 case NM_LLWPE:
20975 check_xnp(ctx);
20976 check_eva(ctx);
20977 check_cp0_enabled(ctx);
20978 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
20979 break;
20980 default:
20981 gen_reserved_instruction(ctx);
20982 break;
20984 break;
20985 case NM_P_SCE:
20986 switch (extract32(ctx->opcode, 2, 2)) {
20987 case NM_SCE:
20988 check_xnp(ctx);
20989 check_eva(ctx);
20990 check_cp0_enabled(ctx);
20991 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
20992 break;
20993 case NM_SCWPE:
20994 check_xnp(ctx);
20995 check_eva(ctx);
20996 check_cp0_enabled(ctx);
20997 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
20998 true);
20999 break;
21000 default:
21001 gen_reserved_instruction(ctx);
21002 break;
21004 break;
21006 break;
21007 case NM_P_LS_WM:
21008 case NM_P_LS_UAWM:
21009 check_nms(ctx);
21011 int count = extract32(ctx->opcode, 12, 3);
21012 int counter = 0;
21014 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21015 extract32(ctx->opcode, 0, 8);
21016 TCGv va = tcg_temp_new();
21017 TCGv t1 = tcg_temp_new();
21018 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21019 NM_P_LS_UAWM ? MO_UNALN : 0;
21021 count = (count == 0) ? 8 : count;
21022 while (counter != count) {
21023 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21024 int this_offset = offset + (counter << 2);
21026 gen_base_offset_addr(ctx, va, rs, this_offset);
21028 switch (extract32(ctx->opcode, 11, 1)) {
21029 case NM_LWM:
21030 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21031 memop | MO_TESL);
21032 gen_store_gpr(t1, this_rt);
21033 if ((this_rt == rs) &&
21034 (counter != (count - 1))) {
21035 /* UNPREDICTABLE */
21037 break;
21038 case NM_SWM:
21039 this_rt = (rt == 0) ? 0 : this_rt;
21040 gen_load_gpr(t1, this_rt);
21041 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21042 memop | MO_TEUL);
21043 break;
21045 counter++;
21047 tcg_temp_free(va);
21048 tcg_temp_free(t1);
21050 break;
21051 default:
21052 gen_reserved_instruction(ctx);
21053 break;
21056 break;
21057 case NM_MOVE_BALC:
21058 check_nms(ctx);
21060 TCGv t0 = tcg_temp_new();
21061 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21062 extract32(ctx->opcode, 1, 20) << 1;
21063 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21064 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21065 extract32(ctx->opcode, 21, 3));
21066 gen_load_gpr(t0, rt);
21067 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21068 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21069 tcg_temp_free(t0);
21071 break;
21072 case NM_P_BAL:
21074 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21075 extract32(ctx->opcode, 1, 24) << 1;
21077 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21078 /* BC */
21079 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21080 } else {
21081 /* BALC */
21082 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21085 break;
21086 case NM_P_J:
21087 switch (extract32(ctx->opcode, 12, 4)) {
21088 case NM_JALRC:
21089 case NM_JALRC_HB:
21090 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21091 break;
21092 case NM_P_BALRSC:
21093 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21094 break;
21095 default:
21096 gen_reserved_instruction(ctx);
21097 break;
21099 break;
21100 case NM_P_BR1:
21102 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21103 extract32(ctx->opcode, 1, 13) << 1;
21104 switch (extract32(ctx->opcode, 14, 2)) {
21105 case NM_BEQC:
21106 check_nms(ctx);
21107 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21108 break;
21109 case NM_P_BR3A:
21110 s = sextract32(ctx->opcode, 0, 1) << 14 |
21111 extract32(ctx->opcode, 1, 13) << 1;
21112 check_cp1_enabled(ctx);
21113 switch (extract32(ctx->opcode, 16, 5)) {
21114 case NM_BC1EQZC:
21115 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21116 break;
21117 case NM_BC1NEZC:
21118 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21119 break;
21120 case NM_BPOSGE32C:
21121 check_dsp_r3(ctx);
21123 int32_t imm = extract32(ctx->opcode, 1, 13) |
21124 extract32(ctx->opcode, 0, 1) << 13;
21126 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21127 imm);
21129 break;
21130 default:
21131 gen_reserved_instruction(ctx);
21132 break;
21134 break;
21135 case NM_BGEC:
21136 if (rs == rt) {
21137 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21138 } else {
21139 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21141 break;
21142 case NM_BGEUC:
21143 if (rs == rt || rt == 0) {
21144 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21145 } else if (rs == 0) {
21146 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21147 } else {
21148 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21150 break;
21153 break;
21154 case NM_P_BR2:
21156 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21157 extract32(ctx->opcode, 1, 13) << 1;
21158 switch (extract32(ctx->opcode, 14, 2)) {
21159 case NM_BNEC:
21160 check_nms(ctx);
21161 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21162 break;
21163 case NM_BLTC:
21164 if (rs != 0 && rt != 0 && rs == rt) {
21165 /* NOP */
21166 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21167 } else {
21168 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21170 break;
21171 case NM_BLTUC:
21172 if (rs == 0 || rs == rt) {
21173 /* NOP */
21174 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21175 } else {
21176 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21178 break;
21179 default:
21180 gen_reserved_instruction(ctx);
21181 break;
21184 break;
21185 case NM_P_BRI:
21187 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21188 extract32(ctx->opcode, 1, 10) << 1;
21189 uint32_t u = extract32(ctx->opcode, 11, 7);
21191 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21192 rt, u, s);
21194 break;
21195 default:
21196 gen_reserved_instruction(ctx);
21197 break;
21199 return 4;
21202 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21204 uint32_t op;
21205 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
21206 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21207 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
21208 int offset;
21209 int imm;
21211 /* make sure instructions are on a halfword boundary */
21212 if (ctx->base.pc_next & 0x1) {
21213 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21214 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21215 tcg_temp_free(tmp);
21216 generate_exception_end(ctx, EXCP_AdEL);
21217 return 2;
21220 op = extract32(ctx->opcode, 10, 6);
21221 switch (op) {
21222 case NM_P16_MV:
21223 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21224 if (rt != 0) {
21225 /* MOVE */
21226 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21227 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21228 } else {
21229 /* P16.RI */
21230 switch (extract32(ctx->opcode, 3, 2)) {
21231 case NM_P16_SYSCALL:
21232 if (extract32(ctx->opcode, 2, 1) == 0) {
21233 generate_exception_end(ctx, EXCP_SYSCALL);
21234 } else {
21235 gen_reserved_instruction(ctx);
21237 break;
21238 case NM_BREAK16:
21239 generate_exception_end(ctx, EXCP_BREAK);
21240 break;
21241 case NM_SDBBP16:
21242 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21243 gen_helper_do_semihosting(cpu_env);
21244 } else {
21245 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21246 gen_reserved_instruction(ctx);
21247 } else {
21248 generate_exception_end(ctx, EXCP_DBp);
21251 break;
21252 default:
21253 gen_reserved_instruction(ctx);
21254 break;
21257 break;
21258 case NM_P16_SHIFT:
21260 int shift = extract32(ctx->opcode, 0, 3);
21261 uint32_t opc = 0;
21262 shift = (shift == 0) ? 8 : shift;
21264 switch (extract32(ctx->opcode, 3, 1)) {
21265 case NM_SLL16:
21266 opc = OPC_SLL;
21267 break;
21268 case NM_SRL16:
21269 opc = OPC_SRL;
21270 break;
21272 gen_shift_imm(ctx, opc, rt, rs, shift);
21274 break;
21275 case NM_P16C:
21276 switch (ctx->opcode & 1) {
21277 case NM_POOL16C_0:
21278 gen_pool16c_nanomips_insn(ctx);
21279 break;
21280 case NM_LWXS16:
21281 gen_ldxs(ctx, rt, rs, rd);
21282 break;
21284 break;
21285 case NM_P16_A1:
21286 switch (extract32(ctx->opcode, 6, 1)) {
21287 case NM_ADDIUR1SP:
21288 imm = extract32(ctx->opcode, 0, 6) << 2;
21289 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21290 break;
21291 default:
21292 gen_reserved_instruction(ctx);
21293 break;
21295 break;
21296 case NM_P16_A2:
21297 switch (extract32(ctx->opcode, 3, 1)) {
21298 case NM_ADDIUR2:
21299 imm = extract32(ctx->opcode, 0, 3) << 2;
21300 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21301 break;
21302 case NM_P_ADDIURS5:
21303 rt = extract32(ctx->opcode, 5, 5);
21304 if (rt != 0) {
21305 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21306 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21307 (extract32(ctx->opcode, 0, 3));
21308 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21310 break;
21312 break;
21313 case NM_P16_ADDU:
21314 switch (ctx->opcode & 0x1) {
21315 case NM_ADDU16:
21316 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21317 break;
21318 case NM_SUBU16:
21319 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21320 break;
21322 break;
21323 case NM_P16_4X4:
21324 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21325 extract32(ctx->opcode, 5, 3);
21326 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21327 extract32(ctx->opcode, 0, 3);
21328 rt = decode_gpr_gpr4(rt);
21329 rs = decode_gpr_gpr4(rs);
21330 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21331 (extract32(ctx->opcode, 3, 1))) {
21332 case NM_ADDU4X4:
21333 check_nms(ctx);
21334 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21335 break;
21336 case NM_MUL4X4:
21337 check_nms(ctx);
21338 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21339 break;
21340 default:
21341 gen_reserved_instruction(ctx);
21342 break;
21344 break;
21345 case NM_LI16:
21347 int imm = extract32(ctx->opcode, 0, 7);
21348 imm = (imm == 0x7f ? -1 : imm);
21349 if (rt != 0) {
21350 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21353 break;
21354 case NM_ANDI16:
21356 uint32_t u = extract32(ctx->opcode, 0, 4);
21357 u = (u == 12) ? 0xff :
21358 (u == 13) ? 0xffff : u;
21359 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21361 break;
21362 case NM_P16_LB:
21363 offset = extract32(ctx->opcode, 0, 2);
21364 switch (extract32(ctx->opcode, 2, 2)) {
21365 case NM_LB16:
21366 gen_ld(ctx, OPC_LB, rt, rs, offset);
21367 break;
21368 case NM_SB16:
21369 rt = decode_gpr_gpr3_src_store(
21370 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21371 gen_st(ctx, OPC_SB, rt, rs, offset);
21372 break;
21373 case NM_LBU16:
21374 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21375 break;
21376 default:
21377 gen_reserved_instruction(ctx);
21378 break;
21380 break;
21381 case NM_P16_LH:
21382 offset = extract32(ctx->opcode, 1, 2) << 1;
21383 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21384 case NM_LH16:
21385 gen_ld(ctx, OPC_LH, rt, rs, offset);
21386 break;
21387 case NM_SH16:
21388 rt = decode_gpr_gpr3_src_store(
21389 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21390 gen_st(ctx, OPC_SH, rt, rs, offset);
21391 break;
21392 case NM_LHU16:
21393 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21394 break;
21395 default:
21396 gen_reserved_instruction(ctx);
21397 break;
21399 break;
21400 case NM_LW16:
21401 offset = extract32(ctx->opcode, 0, 4) << 2;
21402 gen_ld(ctx, OPC_LW, rt, rs, offset);
21403 break;
21404 case NM_LWSP16:
21405 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21406 offset = extract32(ctx->opcode, 0, 5) << 2;
21407 gen_ld(ctx, OPC_LW, rt, 29, offset);
21408 break;
21409 case NM_LW4X4:
21410 check_nms(ctx);
21411 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21412 extract32(ctx->opcode, 5, 3);
21413 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21414 extract32(ctx->opcode, 0, 3);
21415 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21416 (extract32(ctx->opcode, 8, 1) << 2);
21417 rt = decode_gpr_gpr4(rt);
21418 rs = decode_gpr_gpr4(rs);
21419 gen_ld(ctx, OPC_LW, rt, rs, offset);
21420 break;
21421 case NM_SW4X4:
21422 check_nms(ctx);
21423 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21424 extract32(ctx->opcode, 5, 3);
21425 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21426 extract32(ctx->opcode, 0, 3);
21427 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21428 (extract32(ctx->opcode, 8, 1) << 2);
21429 rt = decode_gpr_gpr4_zero(rt);
21430 rs = decode_gpr_gpr4(rs);
21431 gen_st(ctx, OPC_SW, rt, rs, offset);
21432 break;
21433 case NM_LWGP16:
21434 offset = extract32(ctx->opcode, 0, 7) << 2;
21435 gen_ld(ctx, OPC_LW, rt, 28, offset);
21436 break;
21437 case NM_SWSP16:
21438 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21439 offset = extract32(ctx->opcode, 0, 5) << 2;
21440 gen_st(ctx, OPC_SW, rt, 29, offset);
21441 break;
21442 case NM_SW16:
21443 rt = decode_gpr_gpr3_src_store(
21444 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21445 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21446 offset = extract32(ctx->opcode, 0, 4) << 2;
21447 gen_st(ctx, OPC_SW, rt, rs, offset);
21448 break;
21449 case NM_SWGP16:
21450 rt = decode_gpr_gpr3_src_store(
21451 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21452 offset = extract32(ctx->opcode, 0, 7) << 2;
21453 gen_st(ctx, OPC_SW, rt, 28, offset);
21454 break;
21455 case NM_BC16:
21456 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21457 (sextract32(ctx->opcode, 0, 1) << 10) |
21458 (extract32(ctx->opcode, 1, 9) << 1));
21459 break;
21460 case NM_BALC16:
21461 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21462 (sextract32(ctx->opcode, 0, 1) << 10) |
21463 (extract32(ctx->opcode, 1, 9) << 1));
21464 break;
21465 case NM_BEQZC16:
21466 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21467 (sextract32(ctx->opcode, 0, 1) << 7) |
21468 (extract32(ctx->opcode, 1, 6) << 1));
21469 break;
21470 case NM_BNEZC16:
21471 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21472 (sextract32(ctx->opcode, 0, 1) << 7) |
21473 (extract32(ctx->opcode, 1, 6) << 1));
21474 break;
21475 case NM_P16_BR:
21476 switch (ctx->opcode & 0xf) {
21477 case 0:
21478 /* P16.JRC */
21479 switch (extract32(ctx->opcode, 4, 1)) {
21480 case NM_JRC:
21481 gen_compute_branch_nm(ctx, OPC_JR, 2,
21482 extract32(ctx->opcode, 5, 5), 0, 0);
21483 break;
21484 case NM_JALRC16:
21485 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21486 extract32(ctx->opcode, 5, 5), 31, 0);
21487 break;
21489 break;
21490 default:
21492 /* P16.BRI */
21493 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21494 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21495 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21496 extract32(ctx->opcode, 0, 4) << 1);
21498 break;
21500 break;
21501 case NM_P16_SR:
21503 int count = extract32(ctx->opcode, 0, 4);
21504 int u = extract32(ctx->opcode, 4, 4) << 4;
21506 rt = 30 + extract32(ctx->opcode, 9, 1);
21507 switch (extract32(ctx->opcode, 8, 1)) {
21508 case NM_SAVE16:
21509 gen_save(ctx, rt, count, 0, u);
21510 break;
21511 case NM_RESTORE_JRC16:
21512 gen_restore(ctx, rt, count, 0, u);
21513 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21514 break;
21517 break;
21518 case NM_MOVEP:
21519 case NM_MOVEPREV:
21520 check_nms(ctx);
21522 static const int gpr2reg1[] = {4, 5, 6, 7};
21523 static const int gpr2reg2[] = {5, 6, 7, 8};
21524 int re;
21525 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21526 extract32(ctx->opcode, 8, 1);
21527 int r1 = gpr2reg1[rd2];
21528 int r2 = gpr2reg2[rd2];
21529 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21530 extract32(ctx->opcode, 0, 3);
21531 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21532 extract32(ctx->opcode, 5, 3);
21533 TCGv t0 = tcg_temp_new();
21534 TCGv t1 = tcg_temp_new();
21535 if (op == NM_MOVEP) {
21536 rd = r1;
21537 re = r2;
21538 rs = decode_gpr_gpr4_zero(r3);
21539 rt = decode_gpr_gpr4_zero(r4);
21540 } else {
21541 rd = decode_gpr_gpr4(r3);
21542 re = decode_gpr_gpr4(r4);
21543 rs = r1;
21544 rt = r2;
21546 gen_load_gpr(t0, rs);
21547 gen_load_gpr(t1, rt);
21548 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21549 tcg_gen_mov_tl(cpu_gpr[re], t1);
21550 tcg_temp_free(t0);
21551 tcg_temp_free(t1);
21553 break;
21554 default:
21555 return decode_nanomips_32_48_opc(env, ctx);
21558 return 2;
21562 /* SmartMIPS extension to MIPS32 */
21564 #if defined(TARGET_MIPS64)
21566 /* MDMX extension to MIPS64 */
21568 #endif
21570 /* MIPSDSP functions. */
21571 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21572 int rd, int base, int offset)
21574 TCGv t0;
21576 check_dsp(ctx);
21577 t0 = tcg_temp_new();
21579 if (base == 0) {
21580 gen_load_gpr(t0, offset);
21581 } else if (offset == 0) {
21582 gen_load_gpr(t0, base);
21583 } else {
21584 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21587 switch (opc) {
21588 case OPC_LBUX:
21589 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21590 gen_store_gpr(t0, rd);
21591 break;
21592 case OPC_LHX:
21593 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21594 gen_store_gpr(t0, rd);
21595 break;
21596 case OPC_LWX:
21597 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21598 gen_store_gpr(t0, rd);
21599 break;
21600 #if defined(TARGET_MIPS64)
21601 case OPC_LDX:
21602 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21603 gen_store_gpr(t0, rd);
21604 break;
21605 #endif
21607 tcg_temp_free(t0);
21610 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21611 int ret, int v1, int v2)
21613 TCGv v1_t;
21614 TCGv v2_t;
21616 if (ret == 0) {
21617 /* Treat as NOP. */
21618 return;
21621 v1_t = tcg_temp_new();
21622 v2_t = tcg_temp_new();
21624 gen_load_gpr(v1_t, v1);
21625 gen_load_gpr(v2_t, v2);
21627 switch (op1) {
21628 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21629 case OPC_MULT_G_2E:
21630 check_dsp_r2(ctx);
21631 switch (op2) {
21632 case OPC_ADDUH_QB:
21633 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21634 break;
21635 case OPC_ADDUH_R_QB:
21636 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21637 break;
21638 case OPC_ADDQH_PH:
21639 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21640 break;
21641 case OPC_ADDQH_R_PH:
21642 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21643 break;
21644 case OPC_ADDQH_W:
21645 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21646 break;
21647 case OPC_ADDQH_R_W:
21648 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21649 break;
21650 case OPC_SUBUH_QB:
21651 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21652 break;
21653 case OPC_SUBUH_R_QB:
21654 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21655 break;
21656 case OPC_SUBQH_PH:
21657 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
21658 break;
21659 case OPC_SUBQH_R_PH:
21660 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21661 break;
21662 case OPC_SUBQH_W:
21663 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
21664 break;
21665 case OPC_SUBQH_R_W:
21666 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21667 break;
21669 break;
21670 case OPC_ABSQ_S_PH_DSP:
21671 switch (op2) {
21672 case OPC_ABSQ_S_QB:
21673 check_dsp_r2(ctx);
21674 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
21675 break;
21676 case OPC_ABSQ_S_PH:
21677 check_dsp(ctx);
21678 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
21679 break;
21680 case OPC_ABSQ_S_W:
21681 check_dsp(ctx);
21682 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
21683 break;
21684 case OPC_PRECEQ_W_PHL:
21685 check_dsp(ctx);
21686 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
21687 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21688 break;
21689 case OPC_PRECEQ_W_PHR:
21690 check_dsp(ctx);
21691 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
21692 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
21693 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21694 break;
21695 case OPC_PRECEQU_PH_QBL:
21696 check_dsp(ctx);
21697 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
21698 break;
21699 case OPC_PRECEQU_PH_QBR:
21700 check_dsp(ctx);
21701 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
21702 break;
21703 case OPC_PRECEQU_PH_QBLA:
21704 check_dsp(ctx);
21705 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
21706 break;
21707 case OPC_PRECEQU_PH_QBRA:
21708 check_dsp(ctx);
21709 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
21710 break;
21711 case OPC_PRECEU_PH_QBL:
21712 check_dsp(ctx);
21713 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
21714 break;
21715 case OPC_PRECEU_PH_QBR:
21716 check_dsp(ctx);
21717 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
21718 break;
21719 case OPC_PRECEU_PH_QBLA:
21720 check_dsp(ctx);
21721 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
21722 break;
21723 case OPC_PRECEU_PH_QBRA:
21724 check_dsp(ctx);
21725 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
21726 break;
21728 break;
21729 case OPC_ADDU_QB_DSP:
21730 switch (op2) {
21731 case OPC_ADDQ_PH:
21732 check_dsp(ctx);
21733 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21734 break;
21735 case OPC_ADDQ_S_PH:
21736 check_dsp(ctx);
21737 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21738 break;
21739 case OPC_ADDQ_S_W:
21740 check_dsp(ctx);
21741 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21742 break;
21743 case OPC_ADDU_QB:
21744 check_dsp(ctx);
21745 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21746 break;
21747 case OPC_ADDU_S_QB:
21748 check_dsp(ctx);
21749 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21750 break;
21751 case OPC_ADDU_PH:
21752 check_dsp_r2(ctx);
21753 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21754 break;
21755 case OPC_ADDU_S_PH:
21756 check_dsp_r2(ctx);
21757 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21758 break;
21759 case OPC_SUBQ_PH:
21760 check_dsp(ctx);
21761 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21762 break;
21763 case OPC_SUBQ_S_PH:
21764 check_dsp(ctx);
21765 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21766 break;
21767 case OPC_SUBQ_S_W:
21768 check_dsp(ctx);
21769 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21770 break;
21771 case OPC_SUBU_QB:
21772 check_dsp(ctx);
21773 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21774 break;
21775 case OPC_SUBU_S_QB:
21776 check_dsp(ctx);
21777 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21778 break;
21779 case OPC_SUBU_PH:
21780 check_dsp_r2(ctx);
21781 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21782 break;
21783 case OPC_SUBU_S_PH:
21784 check_dsp_r2(ctx);
21785 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21786 break;
21787 case OPC_ADDSC:
21788 check_dsp(ctx);
21789 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21790 break;
21791 case OPC_ADDWC:
21792 check_dsp(ctx);
21793 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21794 break;
21795 case OPC_MODSUB:
21796 check_dsp(ctx);
21797 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
21798 break;
21799 case OPC_RADDU_W_QB:
21800 check_dsp(ctx);
21801 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
21802 break;
21804 break;
21805 case OPC_CMPU_EQ_QB_DSP:
21806 switch (op2) {
21807 case OPC_PRECR_QB_PH:
21808 check_dsp_r2(ctx);
21809 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21810 break;
21811 case OPC_PRECRQ_QB_PH:
21812 check_dsp(ctx);
21813 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21814 break;
21815 case OPC_PRECR_SRA_PH_W:
21816 check_dsp_r2(ctx);
21818 TCGv_i32 sa_t = tcg_const_i32(v2);
21819 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
21820 cpu_gpr[ret]);
21821 tcg_temp_free_i32(sa_t);
21822 break;
21824 case OPC_PRECR_SRA_R_PH_W:
21825 check_dsp_r2(ctx);
21827 TCGv_i32 sa_t = tcg_const_i32(v2);
21828 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
21829 cpu_gpr[ret]);
21830 tcg_temp_free_i32(sa_t);
21831 break;
21833 case OPC_PRECRQ_PH_W:
21834 check_dsp(ctx);
21835 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
21836 break;
21837 case OPC_PRECRQ_RS_PH_W:
21838 check_dsp(ctx);
21839 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21840 break;
21841 case OPC_PRECRQU_S_QB_PH:
21842 check_dsp(ctx);
21843 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21844 break;
21846 break;
21847 #ifdef TARGET_MIPS64
21848 case OPC_ABSQ_S_QH_DSP:
21849 switch (op2) {
21850 case OPC_PRECEQ_L_PWL:
21851 check_dsp(ctx);
21852 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
21853 break;
21854 case OPC_PRECEQ_L_PWR:
21855 check_dsp(ctx);
21856 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
21857 break;
21858 case OPC_PRECEQ_PW_QHL:
21859 check_dsp(ctx);
21860 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
21861 break;
21862 case OPC_PRECEQ_PW_QHR:
21863 check_dsp(ctx);
21864 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
21865 break;
21866 case OPC_PRECEQ_PW_QHLA:
21867 check_dsp(ctx);
21868 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
21869 break;
21870 case OPC_PRECEQ_PW_QHRA:
21871 check_dsp(ctx);
21872 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
21873 break;
21874 case OPC_PRECEQU_QH_OBL:
21875 check_dsp(ctx);
21876 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
21877 break;
21878 case OPC_PRECEQU_QH_OBR:
21879 check_dsp(ctx);
21880 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
21881 break;
21882 case OPC_PRECEQU_QH_OBLA:
21883 check_dsp(ctx);
21884 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
21885 break;
21886 case OPC_PRECEQU_QH_OBRA:
21887 check_dsp(ctx);
21888 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
21889 break;
21890 case OPC_PRECEU_QH_OBL:
21891 check_dsp(ctx);
21892 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
21893 break;
21894 case OPC_PRECEU_QH_OBR:
21895 check_dsp(ctx);
21896 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
21897 break;
21898 case OPC_PRECEU_QH_OBLA:
21899 check_dsp(ctx);
21900 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
21901 break;
21902 case OPC_PRECEU_QH_OBRA:
21903 check_dsp(ctx);
21904 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
21905 break;
21906 case OPC_ABSQ_S_OB:
21907 check_dsp_r2(ctx);
21908 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
21909 break;
21910 case OPC_ABSQ_S_PW:
21911 check_dsp(ctx);
21912 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
21913 break;
21914 case OPC_ABSQ_S_QH:
21915 check_dsp(ctx);
21916 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
21917 break;
21919 break;
21920 case OPC_ADDU_OB_DSP:
21921 switch (op2) {
21922 case OPC_RADDU_L_OB:
21923 check_dsp(ctx);
21924 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
21925 break;
21926 case OPC_SUBQ_PW:
21927 check_dsp(ctx);
21928 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21929 break;
21930 case OPC_SUBQ_S_PW:
21931 check_dsp(ctx);
21932 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21933 break;
21934 case OPC_SUBQ_QH:
21935 check_dsp(ctx);
21936 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21937 break;
21938 case OPC_SUBQ_S_QH:
21939 check_dsp(ctx);
21940 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21941 break;
21942 case OPC_SUBU_OB:
21943 check_dsp(ctx);
21944 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21945 break;
21946 case OPC_SUBU_S_OB:
21947 check_dsp(ctx);
21948 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21949 break;
21950 case OPC_SUBU_QH:
21951 check_dsp_r2(ctx);
21952 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21953 break;
21954 case OPC_SUBU_S_QH:
21955 check_dsp_r2(ctx);
21956 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21957 break;
21958 case OPC_SUBUH_OB:
21959 check_dsp_r2(ctx);
21960 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
21961 break;
21962 case OPC_SUBUH_R_OB:
21963 check_dsp_r2(ctx);
21964 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21965 break;
21966 case OPC_ADDQ_PW:
21967 check_dsp(ctx);
21968 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21969 break;
21970 case OPC_ADDQ_S_PW:
21971 check_dsp(ctx);
21972 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21973 break;
21974 case OPC_ADDQ_QH:
21975 check_dsp(ctx);
21976 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21977 break;
21978 case OPC_ADDQ_S_QH:
21979 check_dsp(ctx);
21980 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21981 break;
21982 case OPC_ADDU_OB:
21983 check_dsp(ctx);
21984 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21985 break;
21986 case OPC_ADDU_S_OB:
21987 check_dsp(ctx);
21988 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21989 break;
21990 case OPC_ADDU_QH:
21991 check_dsp_r2(ctx);
21992 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21993 break;
21994 case OPC_ADDU_S_QH:
21995 check_dsp_r2(ctx);
21996 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21997 break;
21998 case OPC_ADDUH_OB:
21999 check_dsp_r2(ctx);
22000 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22001 break;
22002 case OPC_ADDUH_R_OB:
22003 check_dsp_r2(ctx);
22004 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22005 break;
22007 break;
22008 case OPC_CMPU_EQ_OB_DSP:
22009 switch (op2) {
22010 case OPC_PRECR_OB_QH:
22011 check_dsp_r2(ctx);
22012 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22013 break;
22014 case OPC_PRECR_SRA_QH_PW:
22015 check_dsp_r2(ctx);
22017 TCGv_i32 ret_t = tcg_const_i32(ret);
22018 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22019 tcg_temp_free_i32(ret_t);
22020 break;
22022 case OPC_PRECR_SRA_R_QH_PW:
22023 check_dsp_r2(ctx);
22025 TCGv_i32 sa_v = tcg_const_i32(ret);
22026 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22027 tcg_temp_free_i32(sa_v);
22028 break;
22030 case OPC_PRECRQ_OB_QH:
22031 check_dsp(ctx);
22032 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22033 break;
22034 case OPC_PRECRQ_PW_L:
22035 check_dsp(ctx);
22036 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22037 break;
22038 case OPC_PRECRQ_QH_PW:
22039 check_dsp(ctx);
22040 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22041 break;
22042 case OPC_PRECRQ_RS_QH_PW:
22043 check_dsp(ctx);
22044 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22045 break;
22046 case OPC_PRECRQU_S_OB_QH:
22047 check_dsp(ctx);
22048 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22049 break;
22051 break;
22052 #endif
22055 tcg_temp_free(v1_t);
22056 tcg_temp_free(v2_t);
22059 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22060 int ret, int v1, int v2)
22062 uint32_t op2;
22063 TCGv t0;
22064 TCGv v1_t;
22065 TCGv v2_t;
22067 if (ret == 0) {
22068 /* Treat as NOP. */
22069 return;
22072 t0 = tcg_temp_new();
22073 v1_t = tcg_temp_new();
22074 v2_t = tcg_temp_new();
22076 tcg_gen_movi_tl(t0, v1);
22077 gen_load_gpr(v1_t, v1);
22078 gen_load_gpr(v2_t, v2);
22080 switch (opc) {
22081 case OPC_SHLL_QB_DSP:
22083 op2 = MASK_SHLL_QB(ctx->opcode);
22084 switch (op2) {
22085 case OPC_SHLL_QB:
22086 check_dsp(ctx);
22087 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22088 break;
22089 case OPC_SHLLV_QB:
22090 check_dsp(ctx);
22091 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22092 break;
22093 case OPC_SHLL_PH:
22094 check_dsp(ctx);
22095 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22096 break;
22097 case OPC_SHLLV_PH:
22098 check_dsp(ctx);
22099 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22100 break;
22101 case OPC_SHLL_S_PH:
22102 check_dsp(ctx);
22103 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22104 break;
22105 case OPC_SHLLV_S_PH:
22106 check_dsp(ctx);
22107 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22108 break;
22109 case OPC_SHLL_S_W:
22110 check_dsp(ctx);
22111 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22112 break;
22113 case OPC_SHLLV_S_W:
22114 check_dsp(ctx);
22115 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22116 break;
22117 case OPC_SHRL_QB:
22118 check_dsp(ctx);
22119 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22120 break;
22121 case OPC_SHRLV_QB:
22122 check_dsp(ctx);
22123 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22124 break;
22125 case OPC_SHRL_PH:
22126 check_dsp_r2(ctx);
22127 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22128 break;
22129 case OPC_SHRLV_PH:
22130 check_dsp_r2(ctx);
22131 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22132 break;
22133 case OPC_SHRA_QB:
22134 check_dsp_r2(ctx);
22135 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22136 break;
22137 case OPC_SHRA_R_QB:
22138 check_dsp_r2(ctx);
22139 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22140 break;
22141 case OPC_SHRAV_QB:
22142 check_dsp_r2(ctx);
22143 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22144 break;
22145 case OPC_SHRAV_R_QB:
22146 check_dsp_r2(ctx);
22147 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22148 break;
22149 case OPC_SHRA_PH:
22150 check_dsp(ctx);
22151 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22152 break;
22153 case OPC_SHRA_R_PH:
22154 check_dsp(ctx);
22155 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22156 break;
22157 case OPC_SHRAV_PH:
22158 check_dsp(ctx);
22159 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22160 break;
22161 case OPC_SHRAV_R_PH:
22162 check_dsp(ctx);
22163 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22164 break;
22165 case OPC_SHRA_R_W:
22166 check_dsp(ctx);
22167 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22168 break;
22169 case OPC_SHRAV_R_W:
22170 check_dsp(ctx);
22171 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22172 break;
22173 default: /* Invalid */
22174 MIPS_INVAL("MASK SHLL.QB");
22175 gen_reserved_instruction(ctx);
22176 break;
22178 break;
22180 #ifdef TARGET_MIPS64
22181 case OPC_SHLL_OB_DSP:
22182 op2 = MASK_SHLL_OB(ctx->opcode);
22183 switch (op2) {
22184 case OPC_SHLL_PW:
22185 check_dsp(ctx);
22186 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22187 break;
22188 case OPC_SHLLV_PW:
22189 check_dsp(ctx);
22190 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22191 break;
22192 case OPC_SHLL_S_PW:
22193 check_dsp(ctx);
22194 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22195 break;
22196 case OPC_SHLLV_S_PW:
22197 check_dsp(ctx);
22198 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22199 break;
22200 case OPC_SHLL_OB:
22201 check_dsp(ctx);
22202 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22203 break;
22204 case OPC_SHLLV_OB:
22205 check_dsp(ctx);
22206 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22207 break;
22208 case OPC_SHLL_QH:
22209 check_dsp(ctx);
22210 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22211 break;
22212 case OPC_SHLLV_QH:
22213 check_dsp(ctx);
22214 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22215 break;
22216 case OPC_SHLL_S_QH:
22217 check_dsp(ctx);
22218 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22219 break;
22220 case OPC_SHLLV_S_QH:
22221 check_dsp(ctx);
22222 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22223 break;
22224 case OPC_SHRA_OB:
22225 check_dsp_r2(ctx);
22226 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22227 break;
22228 case OPC_SHRAV_OB:
22229 check_dsp_r2(ctx);
22230 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22231 break;
22232 case OPC_SHRA_R_OB:
22233 check_dsp_r2(ctx);
22234 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22235 break;
22236 case OPC_SHRAV_R_OB:
22237 check_dsp_r2(ctx);
22238 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22239 break;
22240 case OPC_SHRA_PW:
22241 check_dsp(ctx);
22242 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22243 break;
22244 case OPC_SHRAV_PW:
22245 check_dsp(ctx);
22246 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22247 break;
22248 case OPC_SHRA_R_PW:
22249 check_dsp(ctx);
22250 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22251 break;
22252 case OPC_SHRAV_R_PW:
22253 check_dsp(ctx);
22254 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22255 break;
22256 case OPC_SHRA_QH:
22257 check_dsp(ctx);
22258 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22259 break;
22260 case OPC_SHRAV_QH:
22261 check_dsp(ctx);
22262 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22263 break;
22264 case OPC_SHRA_R_QH:
22265 check_dsp(ctx);
22266 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22267 break;
22268 case OPC_SHRAV_R_QH:
22269 check_dsp(ctx);
22270 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22271 break;
22272 case OPC_SHRL_OB:
22273 check_dsp(ctx);
22274 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22275 break;
22276 case OPC_SHRLV_OB:
22277 check_dsp(ctx);
22278 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22279 break;
22280 case OPC_SHRL_QH:
22281 check_dsp_r2(ctx);
22282 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22283 break;
22284 case OPC_SHRLV_QH:
22285 check_dsp_r2(ctx);
22286 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22287 break;
22288 default: /* Invalid */
22289 MIPS_INVAL("MASK SHLL.OB");
22290 gen_reserved_instruction(ctx);
22291 break;
22293 break;
22294 #endif
22297 tcg_temp_free(t0);
22298 tcg_temp_free(v1_t);
22299 tcg_temp_free(v2_t);
22302 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22303 int ret, int v1, int v2, int check_ret)
22305 TCGv_i32 t0;
22306 TCGv v1_t;
22307 TCGv v2_t;
22309 if ((ret == 0) && (check_ret == 1)) {
22310 /* Treat as NOP. */
22311 return;
22314 t0 = tcg_temp_new_i32();
22315 v1_t = tcg_temp_new();
22316 v2_t = tcg_temp_new();
22318 tcg_gen_movi_i32(t0, ret);
22319 gen_load_gpr(v1_t, v1);
22320 gen_load_gpr(v2_t, v2);
22322 switch (op1) {
22324 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22325 * the same mask and op1.
22327 case OPC_MULT_G_2E:
22328 check_dsp_r2(ctx);
22329 switch (op2) {
22330 case OPC_MUL_PH:
22331 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22332 break;
22333 case OPC_MUL_S_PH:
22334 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22335 break;
22336 case OPC_MULQ_S_W:
22337 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22338 break;
22339 case OPC_MULQ_RS_W:
22340 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22341 break;
22343 break;
22344 case OPC_DPA_W_PH_DSP:
22345 switch (op2) {
22346 case OPC_DPAU_H_QBL:
22347 check_dsp(ctx);
22348 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22349 break;
22350 case OPC_DPAU_H_QBR:
22351 check_dsp(ctx);
22352 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22353 break;
22354 case OPC_DPSU_H_QBL:
22355 check_dsp(ctx);
22356 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22357 break;
22358 case OPC_DPSU_H_QBR:
22359 check_dsp(ctx);
22360 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22361 break;
22362 case OPC_DPA_W_PH:
22363 check_dsp_r2(ctx);
22364 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22365 break;
22366 case OPC_DPAX_W_PH:
22367 check_dsp_r2(ctx);
22368 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22369 break;
22370 case OPC_DPAQ_S_W_PH:
22371 check_dsp(ctx);
22372 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22373 break;
22374 case OPC_DPAQX_S_W_PH:
22375 check_dsp_r2(ctx);
22376 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22377 break;
22378 case OPC_DPAQX_SA_W_PH:
22379 check_dsp_r2(ctx);
22380 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22381 break;
22382 case OPC_DPS_W_PH:
22383 check_dsp_r2(ctx);
22384 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22385 break;
22386 case OPC_DPSX_W_PH:
22387 check_dsp_r2(ctx);
22388 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22389 break;
22390 case OPC_DPSQ_S_W_PH:
22391 check_dsp(ctx);
22392 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22393 break;
22394 case OPC_DPSQX_S_W_PH:
22395 check_dsp_r2(ctx);
22396 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22397 break;
22398 case OPC_DPSQX_SA_W_PH:
22399 check_dsp_r2(ctx);
22400 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22401 break;
22402 case OPC_MULSAQ_S_W_PH:
22403 check_dsp(ctx);
22404 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22405 break;
22406 case OPC_DPAQ_SA_L_W:
22407 check_dsp(ctx);
22408 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22409 break;
22410 case OPC_DPSQ_SA_L_W:
22411 check_dsp(ctx);
22412 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22413 break;
22414 case OPC_MAQ_S_W_PHL:
22415 check_dsp(ctx);
22416 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22417 break;
22418 case OPC_MAQ_S_W_PHR:
22419 check_dsp(ctx);
22420 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22421 break;
22422 case OPC_MAQ_SA_W_PHL:
22423 check_dsp(ctx);
22424 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22425 break;
22426 case OPC_MAQ_SA_W_PHR:
22427 check_dsp(ctx);
22428 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22429 break;
22430 case OPC_MULSA_W_PH:
22431 check_dsp_r2(ctx);
22432 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22433 break;
22435 break;
22436 #ifdef TARGET_MIPS64
22437 case OPC_DPAQ_W_QH_DSP:
22439 int ac = ret & 0x03;
22440 tcg_gen_movi_i32(t0, ac);
22442 switch (op2) {
22443 case OPC_DMADD:
22444 check_dsp(ctx);
22445 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22446 break;
22447 case OPC_DMADDU:
22448 check_dsp(ctx);
22449 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22450 break;
22451 case OPC_DMSUB:
22452 check_dsp(ctx);
22453 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22454 break;
22455 case OPC_DMSUBU:
22456 check_dsp(ctx);
22457 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22458 break;
22459 case OPC_DPA_W_QH:
22460 check_dsp_r2(ctx);
22461 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22462 break;
22463 case OPC_DPAQ_S_W_QH:
22464 check_dsp(ctx);
22465 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22466 break;
22467 case OPC_DPAQ_SA_L_PW:
22468 check_dsp(ctx);
22469 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22470 break;
22471 case OPC_DPAU_H_OBL:
22472 check_dsp(ctx);
22473 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22474 break;
22475 case OPC_DPAU_H_OBR:
22476 check_dsp(ctx);
22477 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22478 break;
22479 case OPC_DPS_W_QH:
22480 check_dsp_r2(ctx);
22481 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22482 break;
22483 case OPC_DPSQ_S_W_QH:
22484 check_dsp(ctx);
22485 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22486 break;
22487 case OPC_DPSQ_SA_L_PW:
22488 check_dsp(ctx);
22489 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22490 break;
22491 case OPC_DPSU_H_OBL:
22492 check_dsp(ctx);
22493 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22494 break;
22495 case OPC_DPSU_H_OBR:
22496 check_dsp(ctx);
22497 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22498 break;
22499 case OPC_MAQ_S_L_PWL:
22500 check_dsp(ctx);
22501 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22502 break;
22503 case OPC_MAQ_S_L_PWR:
22504 check_dsp(ctx);
22505 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22506 break;
22507 case OPC_MAQ_S_W_QHLL:
22508 check_dsp(ctx);
22509 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22510 break;
22511 case OPC_MAQ_SA_W_QHLL:
22512 check_dsp(ctx);
22513 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22514 break;
22515 case OPC_MAQ_S_W_QHLR:
22516 check_dsp(ctx);
22517 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22518 break;
22519 case OPC_MAQ_SA_W_QHLR:
22520 check_dsp(ctx);
22521 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22522 break;
22523 case OPC_MAQ_S_W_QHRL:
22524 check_dsp(ctx);
22525 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22526 break;
22527 case OPC_MAQ_SA_W_QHRL:
22528 check_dsp(ctx);
22529 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22530 break;
22531 case OPC_MAQ_S_W_QHRR:
22532 check_dsp(ctx);
22533 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22534 break;
22535 case OPC_MAQ_SA_W_QHRR:
22536 check_dsp(ctx);
22537 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22538 break;
22539 case OPC_MULSAQ_S_L_PW:
22540 check_dsp(ctx);
22541 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22542 break;
22543 case OPC_MULSAQ_S_W_QH:
22544 check_dsp(ctx);
22545 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22546 break;
22549 break;
22550 #endif
22551 case OPC_ADDU_QB_DSP:
22552 switch (op2) {
22553 case OPC_MULEU_S_PH_QBL:
22554 check_dsp(ctx);
22555 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22556 break;
22557 case OPC_MULEU_S_PH_QBR:
22558 check_dsp(ctx);
22559 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22560 break;
22561 case OPC_MULQ_RS_PH:
22562 check_dsp(ctx);
22563 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22564 break;
22565 case OPC_MULEQ_S_W_PHL:
22566 check_dsp(ctx);
22567 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22568 break;
22569 case OPC_MULEQ_S_W_PHR:
22570 check_dsp(ctx);
22571 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22572 break;
22573 case OPC_MULQ_S_PH:
22574 check_dsp_r2(ctx);
22575 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22576 break;
22578 break;
22579 #ifdef TARGET_MIPS64
22580 case OPC_ADDU_OB_DSP:
22581 switch (op2) {
22582 case OPC_MULEQ_S_PW_QHL:
22583 check_dsp(ctx);
22584 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22585 break;
22586 case OPC_MULEQ_S_PW_QHR:
22587 check_dsp(ctx);
22588 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22589 break;
22590 case OPC_MULEU_S_QH_OBL:
22591 check_dsp(ctx);
22592 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22593 break;
22594 case OPC_MULEU_S_QH_OBR:
22595 check_dsp(ctx);
22596 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22597 break;
22598 case OPC_MULQ_RS_QH:
22599 check_dsp(ctx);
22600 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22601 break;
22603 break;
22604 #endif
22607 tcg_temp_free_i32(t0);
22608 tcg_temp_free(v1_t);
22609 tcg_temp_free(v2_t);
22612 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22613 int ret, int val)
22615 int16_t imm;
22616 TCGv t0;
22617 TCGv val_t;
22619 if (ret == 0) {
22620 /* Treat as NOP. */
22621 return;
22624 t0 = tcg_temp_new();
22625 val_t = tcg_temp_new();
22626 gen_load_gpr(val_t, val);
22628 switch (op1) {
22629 case OPC_ABSQ_S_PH_DSP:
22630 switch (op2) {
22631 case OPC_BITREV:
22632 check_dsp(ctx);
22633 gen_helper_bitrev(cpu_gpr[ret], val_t);
22634 break;
22635 case OPC_REPL_QB:
22636 check_dsp(ctx);
22638 target_long result;
22639 imm = (ctx->opcode >> 16) & 0xFF;
22640 result = (uint32_t)imm << 24 |
22641 (uint32_t)imm << 16 |
22642 (uint32_t)imm << 8 |
22643 (uint32_t)imm;
22644 result = (int32_t)result;
22645 tcg_gen_movi_tl(cpu_gpr[ret], result);
22647 break;
22648 case OPC_REPLV_QB:
22649 check_dsp(ctx);
22650 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22651 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22652 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22653 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22654 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22655 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22656 break;
22657 case OPC_REPL_PH:
22658 check_dsp(ctx);
22660 imm = (ctx->opcode >> 16) & 0x03FF;
22661 imm = (int16_t)(imm << 6) >> 6;
22662 tcg_gen_movi_tl(cpu_gpr[ret], \
22663 (target_long)((int32_t)imm << 16 | \
22664 (uint16_t)imm));
22666 break;
22667 case OPC_REPLV_PH:
22668 check_dsp(ctx);
22669 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22670 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22671 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22672 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22673 break;
22675 break;
22676 #ifdef TARGET_MIPS64
22677 case OPC_ABSQ_S_QH_DSP:
22678 switch (op2) {
22679 case OPC_REPL_OB:
22680 check_dsp(ctx);
22682 target_long temp;
22684 imm = (ctx->opcode >> 16) & 0xFF;
22685 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
22686 temp = (temp << 16) | temp;
22687 temp = (temp << 32) | temp;
22688 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22689 break;
22691 case OPC_REPL_PW:
22692 check_dsp(ctx);
22694 target_long temp;
22696 imm = (ctx->opcode >> 16) & 0x03FF;
22697 imm = (int16_t)(imm << 6) >> 6;
22698 temp = ((target_long)imm << 32) \
22699 | ((target_long)imm & 0xFFFFFFFF);
22700 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22701 break;
22703 case OPC_REPL_QH:
22704 check_dsp(ctx);
22706 target_long temp;
22708 imm = (ctx->opcode >> 16) & 0x03FF;
22709 imm = (int16_t)(imm << 6) >> 6;
22711 temp = ((uint64_t)(uint16_t)imm << 48) |
22712 ((uint64_t)(uint16_t)imm << 32) |
22713 ((uint64_t)(uint16_t)imm << 16) |
22714 (uint64_t)(uint16_t)imm;
22715 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22716 break;
22718 case OPC_REPLV_OB:
22719 check_dsp(ctx);
22720 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22721 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22722 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22723 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22724 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22725 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22726 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22727 break;
22728 case OPC_REPLV_PW:
22729 check_dsp(ctx);
22730 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
22731 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22732 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22733 break;
22734 case OPC_REPLV_QH:
22735 check_dsp(ctx);
22736 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22737 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22738 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22739 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22740 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22741 break;
22743 break;
22744 #endif
22746 tcg_temp_free(t0);
22747 tcg_temp_free(val_t);
22750 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
22751 uint32_t op1, uint32_t op2,
22752 int ret, int v1, int v2, int check_ret)
22754 TCGv t1;
22755 TCGv v1_t;
22756 TCGv v2_t;
22758 if ((ret == 0) && (check_ret == 1)) {
22759 /* Treat as NOP. */
22760 return;
22763 t1 = tcg_temp_new();
22764 v1_t = tcg_temp_new();
22765 v2_t = tcg_temp_new();
22767 gen_load_gpr(v1_t, v1);
22768 gen_load_gpr(v2_t, v2);
22770 switch (op1) {
22771 case OPC_CMPU_EQ_QB_DSP:
22772 switch (op2) {
22773 case OPC_CMPU_EQ_QB:
22774 check_dsp(ctx);
22775 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
22776 break;
22777 case OPC_CMPU_LT_QB:
22778 check_dsp(ctx);
22779 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
22780 break;
22781 case OPC_CMPU_LE_QB:
22782 check_dsp(ctx);
22783 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
22784 break;
22785 case OPC_CMPGU_EQ_QB:
22786 check_dsp(ctx);
22787 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
22788 break;
22789 case OPC_CMPGU_LT_QB:
22790 check_dsp(ctx);
22791 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
22792 break;
22793 case OPC_CMPGU_LE_QB:
22794 check_dsp(ctx);
22795 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
22796 break;
22797 case OPC_CMPGDU_EQ_QB:
22798 check_dsp_r2(ctx);
22799 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
22800 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22801 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22802 tcg_gen_shli_tl(t1, t1, 24);
22803 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22804 break;
22805 case OPC_CMPGDU_LT_QB:
22806 check_dsp_r2(ctx);
22807 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
22808 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22809 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22810 tcg_gen_shli_tl(t1, t1, 24);
22811 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22812 break;
22813 case OPC_CMPGDU_LE_QB:
22814 check_dsp_r2(ctx);
22815 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
22816 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22817 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22818 tcg_gen_shli_tl(t1, t1, 24);
22819 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22820 break;
22821 case OPC_CMP_EQ_PH:
22822 check_dsp(ctx);
22823 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
22824 break;
22825 case OPC_CMP_LT_PH:
22826 check_dsp(ctx);
22827 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
22828 break;
22829 case OPC_CMP_LE_PH:
22830 check_dsp(ctx);
22831 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
22832 break;
22833 case OPC_PICK_QB:
22834 check_dsp(ctx);
22835 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22836 break;
22837 case OPC_PICK_PH:
22838 check_dsp(ctx);
22839 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22840 break;
22841 case OPC_PACKRL_PH:
22842 check_dsp(ctx);
22843 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
22844 break;
22846 break;
22847 #ifdef TARGET_MIPS64
22848 case OPC_CMPU_EQ_OB_DSP:
22849 switch (op2) {
22850 case OPC_CMP_EQ_PW:
22851 check_dsp(ctx);
22852 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
22853 break;
22854 case OPC_CMP_LT_PW:
22855 check_dsp(ctx);
22856 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
22857 break;
22858 case OPC_CMP_LE_PW:
22859 check_dsp(ctx);
22860 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
22861 break;
22862 case OPC_CMP_EQ_QH:
22863 check_dsp(ctx);
22864 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
22865 break;
22866 case OPC_CMP_LT_QH:
22867 check_dsp(ctx);
22868 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
22869 break;
22870 case OPC_CMP_LE_QH:
22871 check_dsp(ctx);
22872 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
22873 break;
22874 case OPC_CMPGDU_EQ_OB:
22875 check_dsp_r2(ctx);
22876 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22877 break;
22878 case OPC_CMPGDU_LT_OB:
22879 check_dsp_r2(ctx);
22880 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22881 break;
22882 case OPC_CMPGDU_LE_OB:
22883 check_dsp_r2(ctx);
22884 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22885 break;
22886 case OPC_CMPGU_EQ_OB:
22887 check_dsp(ctx);
22888 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
22889 break;
22890 case OPC_CMPGU_LT_OB:
22891 check_dsp(ctx);
22892 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
22893 break;
22894 case OPC_CMPGU_LE_OB:
22895 check_dsp(ctx);
22896 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
22897 break;
22898 case OPC_CMPU_EQ_OB:
22899 check_dsp(ctx);
22900 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
22901 break;
22902 case OPC_CMPU_LT_OB:
22903 check_dsp(ctx);
22904 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
22905 break;
22906 case OPC_CMPU_LE_OB:
22907 check_dsp(ctx);
22908 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
22909 break;
22910 case OPC_PACKRL_PW:
22911 check_dsp(ctx);
22912 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
22913 break;
22914 case OPC_PICK_OB:
22915 check_dsp(ctx);
22916 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22917 break;
22918 case OPC_PICK_PW:
22919 check_dsp(ctx);
22920 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22921 break;
22922 case OPC_PICK_QH:
22923 check_dsp(ctx);
22924 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22925 break;
22927 break;
22928 #endif
22931 tcg_temp_free(t1);
22932 tcg_temp_free(v1_t);
22933 tcg_temp_free(v2_t);
22936 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
22937 uint32_t op1, int rt, int rs, int sa)
22939 TCGv t0;
22941 check_dsp_r2(ctx);
22943 if (rt == 0) {
22944 /* Treat as NOP. */
22945 return;
22948 t0 = tcg_temp_new();
22949 gen_load_gpr(t0, rs);
22951 switch (op1) {
22952 case OPC_APPEND_DSP:
22953 switch (MASK_APPEND(ctx->opcode)) {
22954 case OPC_APPEND:
22955 if (sa != 0) {
22956 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
22958 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22959 break;
22960 case OPC_PREPEND:
22961 if (sa != 0) {
22962 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
22963 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22964 tcg_gen_shli_tl(t0, t0, 32 - sa);
22965 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22967 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22968 break;
22969 case OPC_BALIGN:
22970 sa &= 3;
22971 if (sa != 0 && sa != 2) {
22972 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22973 tcg_gen_ext32u_tl(t0, t0);
22974 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
22975 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22977 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22978 break;
22979 default: /* Invalid */
22980 MIPS_INVAL("MASK APPEND");
22981 gen_reserved_instruction(ctx);
22982 break;
22984 break;
22985 #ifdef TARGET_MIPS64
22986 case OPC_DAPPEND_DSP:
22987 switch (MASK_DAPPEND(ctx->opcode)) {
22988 case OPC_DAPPEND:
22989 if (sa != 0) {
22990 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
22992 break;
22993 case OPC_PREPENDD:
22994 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
22995 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
22996 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
22997 break;
22998 case OPC_PREPENDW:
22999 if (sa != 0) {
23000 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23001 tcg_gen_shli_tl(t0, t0, 64 - sa);
23002 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23004 break;
23005 case OPC_DBALIGN:
23006 sa &= 7;
23007 if (sa != 0 && sa != 2 && sa != 4) {
23008 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23009 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23010 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23012 break;
23013 default: /* Invalid */
23014 MIPS_INVAL("MASK DAPPEND");
23015 gen_reserved_instruction(ctx);
23016 break;
23018 break;
23019 #endif
23021 tcg_temp_free(t0);
23024 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23025 int ret, int v1, int v2, int check_ret)
23028 TCGv t0;
23029 TCGv t1;
23030 TCGv v1_t;
23031 TCGv v2_t;
23032 int16_t imm;
23034 if ((ret == 0) && (check_ret == 1)) {
23035 /* Treat as NOP. */
23036 return;
23039 t0 = tcg_temp_new();
23040 t1 = tcg_temp_new();
23041 v1_t = tcg_temp_new();
23042 v2_t = tcg_temp_new();
23044 gen_load_gpr(v1_t, v1);
23045 gen_load_gpr(v2_t, v2);
23047 switch (op1) {
23048 case OPC_EXTR_W_DSP:
23049 check_dsp(ctx);
23050 switch (op2) {
23051 case OPC_EXTR_W:
23052 tcg_gen_movi_tl(t0, v2);
23053 tcg_gen_movi_tl(t1, v1);
23054 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23055 break;
23056 case OPC_EXTR_R_W:
23057 tcg_gen_movi_tl(t0, v2);
23058 tcg_gen_movi_tl(t1, v1);
23059 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23060 break;
23061 case OPC_EXTR_RS_W:
23062 tcg_gen_movi_tl(t0, v2);
23063 tcg_gen_movi_tl(t1, v1);
23064 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23065 break;
23066 case OPC_EXTR_S_H:
23067 tcg_gen_movi_tl(t0, v2);
23068 tcg_gen_movi_tl(t1, v1);
23069 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23070 break;
23071 case OPC_EXTRV_S_H:
23072 tcg_gen_movi_tl(t0, v2);
23073 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23074 break;
23075 case OPC_EXTRV_W:
23076 tcg_gen_movi_tl(t0, v2);
23077 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23078 break;
23079 case OPC_EXTRV_R_W:
23080 tcg_gen_movi_tl(t0, v2);
23081 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23082 break;
23083 case OPC_EXTRV_RS_W:
23084 tcg_gen_movi_tl(t0, v2);
23085 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23086 break;
23087 case OPC_EXTP:
23088 tcg_gen_movi_tl(t0, v2);
23089 tcg_gen_movi_tl(t1, v1);
23090 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23091 break;
23092 case OPC_EXTPV:
23093 tcg_gen_movi_tl(t0, v2);
23094 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23095 break;
23096 case OPC_EXTPDP:
23097 tcg_gen_movi_tl(t0, v2);
23098 tcg_gen_movi_tl(t1, v1);
23099 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23100 break;
23101 case OPC_EXTPDPV:
23102 tcg_gen_movi_tl(t0, v2);
23103 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23104 break;
23105 case OPC_SHILO:
23106 imm = (ctx->opcode >> 20) & 0x3F;
23107 tcg_gen_movi_tl(t0, ret);
23108 tcg_gen_movi_tl(t1, imm);
23109 gen_helper_shilo(t0, t1, cpu_env);
23110 break;
23111 case OPC_SHILOV:
23112 tcg_gen_movi_tl(t0, ret);
23113 gen_helper_shilo(t0, v1_t, cpu_env);
23114 break;
23115 case OPC_MTHLIP:
23116 tcg_gen_movi_tl(t0, ret);
23117 gen_helper_mthlip(t0, v1_t, cpu_env);
23118 break;
23119 case OPC_WRDSP:
23120 imm = (ctx->opcode >> 11) & 0x3FF;
23121 tcg_gen_movi_tl(t0, imm);
23122 gen_helper_wrdsp(v1_t, t0, cpu_env);
23123 break;
23124 case OPC_RDDSP:
23125 imm = (ctx->opcode >> 16) & 0x03FF;
23126 tcg_gen_movi_tl(t0, imm);
23127 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23128 break;
23130 break;
23131 #ifdef TARGET_MIPS64
23132 case OPC_DEXTR_W_DSP:
23133 check_dsp(ctx);
23134 switch (op2) {
23135 case OPC_DMTHLIP:
23136 tcg_gen_movi_tl(t0, ret);
23137 gen_helper_dmthlip(v1_t, t0, cpu_env);
23138 break;
23139 case OPC_DSHILO:
23141 int shift = (ctx->opcode >> 19) & 0x7F;
23142 int ac = (ctx->opcode >> 11) & 0x03;
23143 tcg_gen_movi_tl(t0, shift);
23144 tcg_gen_movi_tl(t1, ac);
23145 gen_helper_dshilo(t0, t1, cpu_env);
23146 break;
23148 case OPC_DSHILOV:
23150 int ac = (ctx->opcode >> 11) & 0x03;
23151 tcg_gen_movi_tl(t0, ac);
23152 gen_helper_dshilo(v1_t, t0, cpu_env);
23153 break;
23155 case OPC_DEXTP:
23156 tcg_gen_movi_tl(t0, v2);
23157 tcg_gen_movi_tl(t1, v1);
23159 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23160 break;
23161 case OPC_DEXTPV:
23162 tcg_gen_movi_tl(t0, v2);
23163 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23164 break;
23165 case OPC_DEXTPDP:
23166 tcg_gen_movi_tl(t0, v2);
23167 tcg_gen_movi_tl(t1, v1);
23168 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23169 break;
23170 case OPC_DEXTPDPV:
23171 tcg_gen_movi_tl(t0, v2);
23172 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23173 break;
23174 case OPC_DEXTR_L:
23175 tcg_gen_movi_tl(t0, v2);
23176 tcg_gen_movi_tl(t1, v1);
23177 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23178 break;
23179 case OPC_DEXTR_R_L:
23180 tcg_gen_movi_tl(t0, v2);
23181 tcg_gen_movi_tl(t1, v1);
23182 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23183 break;
23184 case OPC_DEXTR_RS_L:
23185 tcg_gen_movi_tl(t0, v2);
23186 tcg_gen_movi_tl(t1, v1);
23187 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23188 break;
23189 case OPC_DEXTR_W:
23190 tcg_gen_movi_tl(t0, v2);
23191 tcg_gen_movi_tl(t1, v1);
23192 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23193 break;
23194 case OPC_DEXTR_R_W:
23195 tcg_gen_movi_tl(t0, v2);
23196 tcg_gen_movi_tl(t1, v1);
23197 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23198 break;
23199 case OPC_DEXTR_RS_W:
23200 tcg_gen_movi_tl(t0, v2);
23201 tcg_gen_movi_tl(t1, v1);
23202 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23203 break;
23204 case OPC_DEXTR_S_H:
23205 tcg_gen_movi_tl(t0, v2);
23206 tcg_gen_movi_tl(t1, v1);
23207 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23208 break;
23209 case OPC_DEXTRV_S_H:
23210 tcg_gen_movi_tl(t0, v2);
23211 tcg_gen_movi_tl(t1, v1);
23212 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23213 break;
23214 case OPC_DEXTRV_L:
23215 tcg_gen_movi_tl(t0, v2);
23216 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23217 break;
23218 case OPC_DEXTRV_R_L:
23219 tcg_gen_movi_tl(t0, v2);
23220 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23221 break;
23222 case OPC_DEXTRV_RS_L:
23223 tcg_gen_movi_tl(t0, v2);
23224 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23225 break;
23226 case OPC_DEXTRV_W:
23227 tcg_gen_movi_tl(t0, v2);
23228 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23229 break;
23230 case OPC_DEXTRV_R_W:
23231 tcg_gen_movi_tl(t0, v2);
23232 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23233 break;
23234 case OPC_DEXTRV_RS_W:
23235 tcg_gen_movi_tl(t0, v2);
23236 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23237 break;
23239 break;
23240 #endif
23243 tcg_temp_free(t0);
23244 tcg_temp_free(t1);
23245 tcg_temp_free(v1_t);
23246 tcg_temp_free(v2_t);
23249 /* End MIPSDSP functions. */
23251 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23253 int rs, rt, rd, sa;
23254 uint32_t op1, op2;
23256 rs = (ctx->opcode >> 21) & 0x1f;
23257 rt = (ctx->opcode >> 16) & 0x1f;
23258 rd = (ctx->opcode >> 11) & 0x1f;
23259 sa = (ctx->opcode >> 6) & 0x1f;
23261 op1 = MASK_SPECIAL(ctx->opcode);
23262 switch (op1) {
23263 case OPC_MULT:
23264 case OPC_MULTU:
23265 case OPC_DIV:
23266 case OPC_DIVU:
23267 op2 = MASK_R6_MULDIV(ctx->opcode);
23268 switch (op2) {
23269 case R6_OPC_MUL:
23270 case R6_OPC_MUH:
23271 case R6_OPC_MULU:
23272 case R6_OPC_MUHU:
23273 case R6_OPC_DIV:
23274 case R6_OPC_MOD:
23275 case R6_OPC_DIVU:
23276 case R6_OPC_MODU:
23277 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23278 break;
23279 default:
23280 MIPS_INVAL("special_r6 muldiv");
23281 gen_reserved_instruction(ctx);
23282 break;
23284 break;
23285 case OPC_SELEQZ:
23286 case OPC_SELNEZ:
23287 gen_cond_move(ctx, op1, rd, rs, rt);
23288 break;
23289 case R6_OPC_CLO:
23290 case R6_OPC_CLZ:
23291 if (rt == 0 && sa == 1) {
23293 * Major opcode and function field is shared with preR6 MFHI/MTHI.
23294 * We need additionally to check other fields.
23296 gen_cl(ctx, op1, rd, rs);
23297 } else {
23298 gen_reserved_instruction(ctx);
23300 break;
23301 case R6_OPC_SDBBP:
23302 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23303 gen_helper_do_semihosting(cpu_env);
23304 } else {
23305 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23306 gen_reserved_instruction(ctx);
23307 } else {
23308 generate_exception_end(ctx, EXCP_DBp);
23311 break;
23312 #if defined(TARGET_MIPS64)
23313 case R6_OPC_DCLO:
23314 case R6_OPC_DCLZ:
23315 if (rt == 0 && sa == 1) {
23317 * Major opcode and function field is shared with preR6 MFHI/MTHI.
23318 * We need additionally to check other fields.
23320 check_mips_64(ctx);
23321 gen_cl(ctx, op1, rd, rs);
23322 } else {
23323 gen_reserved_instruction(ctx);
23325 break;
23326 case OPC_DMULT:
23327 case OPC_DMULTU:
23328 case OPC_DDIV:
23329 case OPC_DDIVU:
23331 op2 = MASK_R6_MULDIV(ctx->opcode);
23332 switch (op2) {
23333 case R6_OPC_DMUL:
23334 case R6_OPC_DMUH:
23335 case R6_OPC_DMULU:
23336 case R6_OPC_DMUHU:
23337 case R6_OPC_DDIV:
23338 case R6_OPC_DMOD:
23339 case R6_OPC_DDIVU:
23340 case R6_OPC_DMODU:
23341 check_mips_64(ctx);
23342 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23343 break;
23344 default:
23345 MIPS_INVAL("special_r6 muldiv");
23346 gen_reserved_instruction(ctx);
23347 break;
23349 break;
23350 #endif
23351 default: /* Invalid */
23352 MIPS_INVAL("special_r6");
23353 gen_reserved_instruction(ctx);
23354 break;
23358 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
23360 int rs = extract32(ctx->opcode, 21, 5);
23361 int rt = extract32(ctx->opcode, 16, 5);
23362 int rd = extract32(ctx->opcode, 11, 5);
23363 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
23365 switch (op1) {
23366 case OPC_MOVN: /* Conditional move */
23367 case OPC_MOVZ:
23368 gen_cond_move(ctx, op1, rd, rs, rt);
23369 break;
23370 case OPC_MFHI: /* Move from HI/LO */
23371 case OPC_MFLO:
23372 gen_HILO(ctx, op1, 0, rd);
23373 break;
23374 case OPC_MTHI:
23375 case OPC_MTLO: /* Move to HI/LO */
23376 gen_HILO(ctx, op1, 0, rs);
23377 break;
23378 case OPC_MULT:
23379 case OPC_MULTU:
23380 gen_mul_txx9(ctx, op1, rd, rs, rt);
23381 break;
23382 case OPC_DIV:
23383 case OPC_DIVU:
23384 gen_muldiv(ctx, op1, 0, rs, rt);
23385 break;
23386 #if defined(TARGET_MIPS64)
23387 case OPC_DMULT:
23388 case OPC_DMULTU:
23389 case OPC_DDIV:
23390 case OPC_DDIVU:
23391 check_insn_opc_user_only(ctx, INSN_R5900);
23392 gen_muldiv(ctx, op1, 0, rs, rt);
23393 break;
23394 #endif
23395 case OPC_JR:
23396 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
23397 break;
23398 default: /* Invalid */
23399 MIPS_INVAL("special_tx79");
23400 gen_reserved_instruction(ctx);
23401 break;
23405 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23407 int rs, rt, rd, sa;
23408 uint32_t op1;
23410 rs = (ctx->opcode >> 21) & 0x1f;
23411 rt = (ctx->opcode >> 16) & 0x1f;
23412 rd = (ctx->opcode >> 11) & 0x1f;
23413 sa = (ctx->opcode >> 6) & 0x1f;
23415 op1 = MASK_SPECIAL(ctx->opcode);
23416 switch (op1) {
23417 case OPC_MOVN: /* Conditional move */
23418 case OPC_MOVZ:
23419 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
23420 INSN_LOONGSON2E | INSN_LOONGSON2F);
23421 gen_cond_move(ctx, op1, rd, rs, rt);
23422 break;
23423 case OPC_MFHI: /* Move from HI/LO */
23424 case OPC_MFLO:
23425 gen_HILO(ctx, op1, rs & 3, rd);
23426 break;
23427 case OPC_MTHI:
23428 case OPC_MTLO: /* Move to HI/LO */
23429 gen_HILO(ctx, op1, rd & 3, rs);
23430 break;
23431 case OPC_MOVCI:
23432 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
23433 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23434 check_cp1_enabled(ctx);
23435 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23436 (ctx->opcode >> 16) & 1);
23437 } else {
23438 generate_exception_err(ctx, EXCP_CpU, 1);
23440 break;
23441 case OPC_MULT:
23442 case OPC_MULTU:
23443 if (sa) {
23444 check_insn(ctx, INSN_VR54XX);
23445 op1 = MASK_MUL_VR54XX(ctx->opcode);
23446 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23447 } else {
23448 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23450 break;
23451 case OPC_DIV:
23452 case OPC_DIVU:
23453 gen_muldiv(ctx, op1, 0, rs, rt);
23454 break;
23455 #if defined(TARGET_MIPS64)
23456 case OPC_DMULT:
23457 case OPC_DMULTU:
23458 case OPC_DDIV:
23459 case OPC_DDIVU:
23460 check_insn(ctx, ISA_MIPS3);
23461 check_mips_64(ctx);
23462 gen_muldiv(ctx, op1, 0, rs, rt);
23463 break;
23464 #endif
23465 case OPC_JR:
23466 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23467 break;
23468 case OPC_SPIM:
23469 #ifdef MIPS_STRICT_STANDARD
23470 MIPS_INVAL("SPIM");
23471 gen_reserved_instruction(ctx);
23472 #else
23473 /* Implemented as RI exception for now. */
23474 MIPS_INVAL("spim (unofficial)");
23475 gen_reserved_instruction(ctx);
23476 #endif
23477 break;
23478 default: /* Invalid */
23479 MIPS_INVAL("special_legacy");
23480 gen_reserved_instruction(ctx);
23481 break;
23485 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23487 int rs, rt, rd, sa;
23488 uint32_t op1;
23490 rs = (ctx->opcode >> 21) & 0x1f;
23491 rt = (ctx->opcode >> 16) & 0x1f;
23492 rd = (ctx->opcode >> 11) & 0x1f;
23493 sa = (ctx->opcode >> 6) & 0x1f;
23495 op1 = MASK_SPECIAL(ctx->opcode);
23496 switch (op1) {
23497 case OPC_SLL: /* Shift with immediate */
23498 if (sa == 5 && rd == 0 &&
23499 rs == 0 && rt == 0) { /* PAUSE */
23500 if ((ctx->insn_flags & ISA_MIPS_R6) &&
23501 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23502 gen_reserved_instruction(ctx);
23503 break;
23506 /* Fallthrough */
23507 case OPC_SRA:
23508 gen_shift_imm(ctx, op1, rd, rt, sa);
23509 break;
23510 case OPC_SRL:
23511 switch ((ctx->opcode >> 21) & 0x1f) {
23512 case 1:
23513 /* rotr is decoded as srl on non-R2 CPUs */
23514 if (ctx->insn_flags & ISA_MIPS_R2) {
23515 op1 = OPC_ROTR;
23517 /* Fallthrough */
23518 case 0:
23519 gen_shift_imm(ctx, op1, rd, rt, sa);
23520 break;
23521 default:
23522 gen_reserved_instruction(ctx);
23523 break;
23525 break;
23526 case OPC_ADD:
23527 case OPC_ADDU:
23528 case OPC_SUB:
23529 case OPC_SUBU:
23530 gen_arith(ctx, op1, rd, rs, rt);
23531 break;
23532 case OPC_SLLV: /* Shifts */
23533 case OPC_SRAV:
23534 gen_shift(ctx, op1, rd, rs, rt);
23535 break;
23536 case OPC_SRLV:
23537 switch ((ctx->opcode >> 6) & 0x1f) {
23538 case 1:
23539 /* rotrv is decoded as srlv on non-R2 CPUs */
23540 if (ctx->insn_flags & ISA_MIPS_R2) {
23541 op1 = OPC_ROTRV;
23543 /* Fallthrough */
23544 case 0:
23545 gen_shift(ctx, op1, rd, rs, rt);
23546 break;
23547 default:
23548 gen_reserved_instruction(ctx);
23549 break;
23551 break;
23552 case OPC_SLT: /* Set on less than */
23553 case OPC_SLTU:
23554 gen_slt(ctx, op1, rd, rs, rt);
23555 break;
23556 case OPC_AND: /* Logic*/
23557 case OPC_OR:
23558 case OPC_NOR:
23559 case OPC_XOR:
23560 gen_logic(ctx, op1, rd, rs, rt);
23561 break;
23562 case OPC_JALR:
23563 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23564 break;
23565 case OPC_TGE: /* Traps */
23566 case OPC_TGEU:
23567 case OPC_TLT:
23568 case OPC_TLTU:
23569 case OPC_TEQ:
23570 case OPC_TNE:
23571 check_insn(ctx, ISA_MIPS2);
23572 gen_trap(ctx, op1, rs, rt, -1);
23573 break;
23574 case OPC_PMON:
23575 /* Pmon entry point, also R4010 selsl */
23576 #ifdef MIPS_STRICT_STANDARD
23577 MIPS_INVAL("PMON / selsl");
23578 gen_reserved_instruction(ctx);
23579 #else
23580 gen_helper_0e0i(pmon, sa);
23581 #endif
23582 break;
23583 case OPC_SYSCALL:
23584 generate_exception_end(ctx, EXCP_SYSCALL);
23585 break;
23586 case OPC_BREAK:
23587 generate_exception_end(ctx, EXCP_BREAK);
23588 break;
23589 case OPC_SYNC:
23590 check_insn(ctx, ISA_MIPS2);
23591 gen_sync(extract32(ctx->opcode, 6, 5));
23592 break;
23594 #if defined(TARGET_MIPS64)
23595 /* MIPS64 specific opcodes */
23596 case OPC_DSLL:
23597 case OPC_DSRA:
23598 case OPC_DSLL32:
23599 case OPC_DSRA32:
23600 check_insn(ctx, ISA_MIPS3);
23601 check_mips_64(ctx);
23602 gen_shift_imm(ctx, op1, rd, rt, sa);
23603 break;
23604 case OPC_DSRL:
23605 switch ((ctx->opcode >> 21) & 0x1f) {
23606 case 1:
23607 /* drotr is decoded as dsrl on non-R2 CPUs */
23608 if (ctx->insn_flags & ISA_MIPS_R2) {
23609 op1 = OPC_DROTR;
23611 /* Fallthrough */
23612 case 0:
23613 check_insn(ctx, ISA_MIPS3);
23614 check_mips_64(ctx);
23615 gen_shift_imm(ctx, op1, rd, rt, sa);
23616 break;
23617 default:
23618 gen_reserved_instruction(ctx);
23619 break;
23621 break;
23622 case OPC_DSRL32:
23623 switch ((ctx->opcode >> 21) & 0x1f) {
23624 case 1:
23625 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23626 if (ctx->insn_flags & ISA_MIPS_R2) {
23627 op1 = OPC_DROTR32;
23629 /* Fallthrough */
23630 case 0:
23631 check_insn(ctx, ISA_MIPS3);
23632 check_mips_64(ctx);
23633 gen_shift_imm(ctx, op1, rd, rt, sa);
23634 break;
23635 default:
23636 gen_reserved_instruction(ctx);
23637 break;
23639 break;
23640 case OPC_DADD:
23641 case OPC_DADDU:
23642 case OPC_DSUB:
23643 case OPC_DSUBU:
23644 check_insn(ctx, ISA_MIPS3);
23645 check_mips_64(ctx);
23646 gen_arith(ctx, op1, rd, rs, rt);
23647 break;
23648 case OPC_DSLLV:
23649 case OPC_DSRAV:
23650 check_insn(ctx, ISA_MIPS3);
23651 check_mips_64(ctx);
23652 gen_shift(ctx, op1, rd, rs, rt);
23653 break;
23654 case OPC_DSRLV:
23655 switch ((ctx->opcode >> 6) & 0x1f) {
23656 case 1:
23657 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23658 if (ctx->insn_flags & ISA_MIPS_R2) {
23659 op1 = OPC_DROTRV;
23661 /* Fallthrough */
23662 case 0:
23663 check_insn(ctx, ISA_MIPS3);
23664 check_mips_64(ctx);
23665 gen_shift(ctx, op1, rd, rs, rt);
23666 break;
23667 default:
23668 gen_reserved_instruction(ctx);
23669 break;
23671 break;
23672 #endif
23673 default:
23674 if (ctx->insn_flags & ISA_MIPS_R6) {
23675 decode_opc_special_r6(env, ctx);
23676 } else if (ctx->insn_flags & INSN_R5900) {
23677 decode_opc_special_tx79(env, ctx);
23678 } else {
23679 decode_opc_special_legacy(env, ctx);
23685 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
23687 int rs, rt, rd;
23688 uint32_t op1;
23690 rs = (ctx->opcode >> 21) & 0x1f;
23691 rt = (ctx->opcode >> 16) & 0x1f;
23692 rd = (ctx->opcode >> 11) & 0x1f;
23694 op1 = MASK_SPECIAL2(ctx->opcode);
23695 switch (op1) {
23696 case OPC_MADD: /* Multiply and add/sub */
23697 case OPC_MADDU:
23698 case OPC_MSUB:
23699 case OPC_MSUBU:
23700 check_insn(ctx, ISA_MIPS_R1);
23701 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23702 break;
23703 case OPC_MUL:
23704 gen_arith(ctx, op1, rd, rs, rt);
23705 break;
23706 case OPC_DIV_G_2F:
23707 case OPC_DIVU_G_2F:
23708 case OPC_MULT_G_2F:
23709 case OPC_MULTU_G_2F:
23710 case OPC_MOD_G_2F:
23711 case OPC_MODU_G_2F:
23712 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
23713 gen_loongson_integer(ctx, op1, rd, rs, rt);
23714 break;
23715 case OPC_CLO:
23716 case OPC_CLZ:
23717 check_insn(ctx, ISA_MIPS_R1);
23718 gen_cl(ctx, op1, rd, rs);
23719 break;
23720 case OPC_SDBBP:
23721 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23722 gen_helper_do_semihosting(cpu_env);
23723 } else {
23725 * XXX: not clear which exception should be raised
23726 * when in debug mode...
23728 check_insn(ctx, ISA_MIPS_R1);
23729 generate_exception_end(ctx, EXCP_DBp);
23731 break;
23732 #if defined(TARGET_MIPS64)
23733 case OPC_DCLO:
23734 case OPC_DCLZ:
23735 check_insn(ctx, ISA_MIPS_R1);
23736 check_mips_64(ctx);
23737 gen_cl(ctx, op1, rd, rs);
23738 break;
23739 case OPC_DMULT_G_2F:
23740 case OPC_DMULTU_G_2F:
23741 case OPC_DDIV_G_2F:
23742 case OPC_DDIVU_G_2F:
23743 case OPC_DMOD_G_2F:
23744 case OPC_DMODU_G_2F:
23745 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
23746 gen_loongson_integer(ctx, op1, rd, rs, rt);
23747 break;
23748 #endif
23749 default: /* Invalid */
23750 MIPS_INVAL("special2_legacy");
23751 gen_reserved_instruction(ctx);
23752 break;
23756 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
23758 int rs, rt, rd, sa;
23759 uint32_t op1, op2;
23760 int16_t imm;
23762 rs = (ctx->opcode >> 21) & 0x1f;
23763 rt = (ctx->opcode >> 16) & 0x1f;
23764 rd = (ctx->opcode >> 11) & 0x1f;
23765 sa = (ctx->opcode >> 6) & 0x1f;
23766 imm = (int16_t)ctx->opcode >> 7;
23768 op1 = MASK_SPECIAL3(ctx->opcode);
23769 switch (op1) {
23770 case R6_OPC_PREF:
23771 if (rt >= 24) {
23772 /* hint codes 24-31 are reserved and signal RI */
23773 gen_reserved_instruction(ctx);
23775 /* Treat as NOP. */
23776 break;
23777 case R6_OPC_CACHE:
23778 check_cp0_enabled(ctx);
23779 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23780 gen_cache_operation(ctx, rt, rs, imm);
23782 break;
23783 case R6_OPC_SC:
23784 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
23785 break;
23786 case R6_OPC_LL:
23787 gen_ld(ctx, op1, rt, rs, imm);
23788 break;
23789 case OPC_BSHFL:
23791 if (rd == 0) {
23792 /* Treat as NOP. */
23793 break;
23795 op2 = MASK_BSHFL(ctx->opcode);
23796 switch (op2) {
23797 case OPC_ALIGN:
23798 case OPC_ALIGN_1:
23799 case OPC_ALIGN_2:
23800 case OPC_ALIGN_3:
23801 gen_align(ctx, 32, rd, rs, rt, sa & 3);
23802 break;
23803 case OPC_BITSWAP:
23804 gen_bitswap(ctx, op2, rd, rt);
23805 break;
23808 break;
23809 #ifndef CONFIG_USER_ONLY
23810 case OPC_GINV:
23811 if (unlikely(ctx->gi <= 1)) {
23812 gen_reserved_instruction(ctx);
23814 check_cp0_enabled(ctx);
23815 switch ((ctx->opcode >> 6) & 3) {
23816 case 0: /* GINVI */
23817 /* Treat as NOP. */
23818 break;
23819 case 2: /* GINVT */
23820 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
23821 break;
23822 default:
23823 gen_reserved_instruction(ctx);
23824 break;
23826 break;
23827 #endif
23828 #if defined(TARGET_MIPS64)
23829 case R6_OPC_SCD:
23830 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
23831 break;
23832 case R6_OPC_LLD:
23833 gen_ld(ctx, op1, rt, rs, imm);
23834 break;
23835 case OPC_DBSHFL:
23836 check_mips_64(ctx);
23838 if (rd == 0) {
23839 /* Treat as NOP. */
23840 break;
23842 op2 = MASK_DBSHFL(ctx->opcode);
23843 switch (op2) {
23844 case OPC_DALIGN:
23845 case OPC_DALIGN_1:
23846 case OPC_DALIGN_2:
23847 case OPC_DALIGN_3:
23848 case OPC_DALIGN_4:
23849 case OPC_DALIGN_5:
23850 case OPC_DALIGN_6:
23851 case OPC_DALIGN_7:
23852 gen_align(ctx, 64, rd, rs, rt, sa & 7);
23853 break;
23854 case OPC_DBITSWAP:
23855 gen_bitswap(ctx, op2, rd, rt);
23856 break;
23860 break;
23861 #endif
23862 default: /* Invalid */
23863 MIPS_INVAL("special3_r6");
23864 gen_reserved_instruction(ctx);
23865 break;
23869 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
23871 int rs, rt, rd;
23872 uint32_t op1, op2;
23874 rs = (ctx->opcode >> 21) & 0x1f;
23875 rt = (ctx->opcode >> 16) & 0x1f;
23876 rd = (ctx->opcode >> 11) & 0x1f;
23878 op1 = MASK_SPECIAL3(ctx->opcode);
23879 switch (op1) {
23880 case OPC_DIV_G_2E:
23881 case OPC_DIVU_G_2E:
23882 case OPC_MOD_G_2E:
23883 case OPC_MODU_G_2E:
23884 case OPC_MULT_G_2E:
23885 case OPC_MULTU_G_2E:
23887 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23888 * the same mask and op1.
23890 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
23891 op2 = MASK_ADDUH_QB(ctx->opcode);
23892 switch (op2) {
23893 case OPC_ADDUH_QB:
23894 case OPC_ADDUH_R_QB:
23895 case OPC_ADDQH_PH:
23896 case OPC_ADDQH_R_PH:
23897 case OPC_ADDQH_W:
23898 case OPC_ADDQH_R_W:
23899 case OPC_SUBUH_QB:
23900 case OPC_SUBUH_R_QB:
23901 case OPC_SUBQH_PH:
23902 case OPC_SUBQH_R_PH:
23903 case OPC_SUBQH_W:
23904 case OPC_SUBQH_R_W:
23905 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23906 break;
23907 case OPC_MUL_PH:
23908 case OPC_MUL_S_PH:
23909 case OPC_MULQ_S_W:
23910 case OPC_MULQ_RS_W:
23911 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23912 break;
23913 default:
23914 MIPS_INVAL("MASK ADDUH.QB");
23915 gen_reserved_instruction(ctx);
23916 break;
23918 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
23919 gen_loongson_integer(ctx, op1, rd, rs, rt);
23920 } else {
23921 gen_reserved_instruction(ctx);
23923 break;
23924 case OPC_LX_DSP:
23925 op2 = MASK_LX(ctx->opcode);
23926 switch (op2) {
23927 #if defined(TARGET_MIPS64)
23928 case OPC_LDX:
23929 #endif
23930 case OPC_LBUX:
23931 case OPC_LHX:
23932 case OPC_LWX:
23933 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
23934 break;
23935 default: /* Invalid */
23936 MIPS_INVAL("MASK LX");
23937 gen_reserved_instruction(ctx);
23938 break;
23940 break;
23941 case OPC_ABSQ_S_PH_DSP:
23942 op2 = MASK_ABSQ_S_PH(ctx->opcode);
23943 switch (op2) {
23944 case OPC_ABSQ_S_QB:
23945 case OPC_ABSQ_S_PH:
23946 case OPC_ABSQ_S_W:
23947 case OPC_PRECEQ_W_PHL:
23948 case OPC_PRECEQ_W_PHR:
23949 case OPC_PRECEQU_PH_QBL:
23950 case OPC_PRECEQU_PH_QBR:
23951 case OPC_PRECEQU_PH_QBLA:
23952 case OPC_PRECEQU_PH_QBRA:
23953 case OPC_PRECEU_PH_QBL:
23954 case OPC_PRECEU_PH_QBR:
23955 case OPC_PRECEU_PH_QBLA:
23956 case OPC_PRECEU_PH_QBRA:
23957 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23958 break;
23959 case OPC_BITREV:
23960 case OPC_REPL_QB:
23961 case OPC_REPLV_QB:
23962 case OPC_REPL_PH:
23963 case OPC_REPLV_PH:
23964 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23965 break;
23966 default:
23967 MIPS_INVAL("MASK ABSQ_S.PH");
23968 gen_reserved_instruction(ctx);
23969 break;
23971 break;
23972 case OPC_ADDU_QB_DSP:
23973 op2 = MASK_ADDU_QB(ctx->opcode);
23974 switch (op2) {
23975 case OPC_ADDQ_PH:
23976 case OPC_ADDQ_S_PH:
23977 case OPC_ADDQ_S_W:
23978 case OPC_ADDU_QB:
23979 case OPC_ADDU_S_QB:
23980 case OPC_ADDU_PH:
23981 case OPC_ADDU_S_PH:
23982 case OPC_SUBQ_PH:
23983 case OPC_SUBQ_S_PH:
23984 case OPC_SUBQ_S_W:
23985 case OPC_SUBU_QB:
23986 case OPC_SUBU_S_QB:
23987 case OPC_SUBU_PH:
23988 case OPC_SUBU_S_PH:
23989 case OPC_ADDSC:
23990 case OPC_ADDWC:
23991 case OPC_MODSUB:
23992 case OPC_RADDU_W_QB:
23993 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23994 break;
23995 case OPC_MULEU_S_PH_QBL:
23996 case OPC_MULEU_S_PH_QBR:
23997 case OPC_MULQ_RS_PH:
23998 case OPC_MULEQ_S_W_PHL:
23999 case OPC_MULEQ_S_W_PHR:
24000 case OPC_MULQ_S_PH:
24001 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24002 break;
24003 default: /* Invalid */
24004 MIPS_INVAL("MASK ADDU.QB");
24005 gen_reserved_instruction(ctx);
24006 break;
24009 break;
24010 case OPC_CMPU_EQ_QB_DSP:
24011 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
24012 switch (op2) {
24013 case OPC_PRECR_SRA_PH_W:
24014 case OPC_PRECR_SRA_R_PH_W:
24015 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24016 break;
24017 case OPC_PRECR_QB_PH:
24018 case OPC_PRECRQ_QB_PH:
24019 case OPC_PRECRQ_PH_W:
24020 case OPC_PRECRQ_RS_PH_W:
24021 case OPC_PRECRQU_S_QB_PH:
24022 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24023 break;
24024 case OPC_CMPU_EQ_QB:
24025 case OPC_CMPU_LT_QB:
24026 case OPC_CMPU_LE_QB:
24027 case OPC_CMP_EQ_PH:
24028 case OPC_CMP_LT_PH:
24029 case OPC_CMP_LE_PH:
24030 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24031 break;
24032 case OPC_CMPGU_EQ_QB:
24033 case OPC_CMPGU_LT_QB:
24034 case OPC_CMPGU_LE_QB:
24035 case OPC_CMPGDU_EQ_QB:
24036 case OPC_CMPGDU_LT_QB:
24037 case OPC_CMPGDU_LE_QB:
24038 case OPC_PICK_QB:
24039 case OPC_PICK_PH:
24040 case OPC_PACKRL_PH:
24041 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24042 break;
24043 default: /* Invalid */
24044 MIPS_INVAL("MASK CMPU.EQ.QB");
24045 gen_reserved_instruction(ctx);
24046 break;
24048 break;
24049 case OPC_SHLL_QB_DSP:
24050 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24051 break;
24052 case OPC_DPA_W_PH_DSP:
24053 op2 = MASK_DPA_W_PH(ctx->opcode);
24054 switch (op2) {
24055 case OPC_DPAU_H_QBL:
24056 case OPC_DPAU_H_QBR:
24057 case OPC_DPSU_H_QBL:
24058 case OPC_DPSU_H_QBR:
24059 case OPC_DPA_W_PH:
24060 case OPC_DPAX_W_PH:
24061 case OPC_DPAQ_S_W_PH:
24062 case OPC_DPAQX_S_W_PH:
24063 case OPC_DPAQX_SA_W_PH:
24064 case OPC_DPS_W_PH:
24065 case OPC_DPSX_W_PH:
24066 case OPC_DPSQ_S_W_PH:
24067 case OPC_DPSQX_S_W_PH:
24068 case OPC_DPSQX_SA_W_PH:
24069 case OPC_MULSAQ_S_W_PH:
24070 case OPC_DPAQ_SA_L_W:
24071 case OPC_DPSQ_SA_L_W:
24072 case OPC_MAQ_S_W_PHL:
24073 case OPC_MAQ_S_W_PHR:
24074 case OPC_MAQ_SA_W_PHL:
24075 case OPC_MAQ_SA_W_PHR:
24076 case OPC_MULSA_W_PH:
24077 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24078 break;
24079 default: /* Invalid */
24080 MIPS_INVAL("MASK DPAW.PH");
24081 gen_reserved_instruction(ctx);
24082 break;
24084 break;
24085 case OPC_INSV_DSP:
24086 op2 = MASK_INSV(ctx->opcode);
24087 switch (op2) {
24088 case OPC_INSV:
24089 check_dsp(ctx);
24091 TCGv t0, t1;
24093 if (rt == 0) {
24094 break;
24097 t0 = tcg_temp_new();
24098 t1 = tcg_temp_new();
24100 gen_load_gpr(t0, rt);
24101 gen_load_gpr(t1, rs);
24103 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
24105 tcg_temp_free(t0);
24106 tcg_temp_free(t1);
24107 break;
24109 default: /* Invalid */
24110 MIPS_INVAL("MASK INSV");
24111 gen_reserved_instruction(ctx);
24112 break;
24114 break;
24115 case OPC_APPEND_DSP:
24116 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24117 break;
24118 case OPC_EXTR_W_DSP:
24119 op2 = MASK_EXTR_W(ctx->opcode);
24120 switch (op2) {
24121 case OPC_EXTR_W:
24122 case OPC_EXTR_R_W:
24123 case OPC_EXTR_RS_W:
24124 case OPC_EXTR_S_H:
24125 case OPC_EXTRV_S_H:
24126 case OPC_EXTRV_W:
24127 case OPC_EXTRV_R_W:
24128 case OPC_EXTRV_RS_W:
24129 case OPC_EXTP:
24130 case OPC_EXTPV:
24131 case OPC_EXTPDP:
24132 case OPC_EXTPDPV:
24133 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24134 break;
24135 case OPC_RDDSP:
24136 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
24137 break;
24138 case OPC_SHILO:
24139 case OPC_SHILOV:
24140 case OPC_MTHLIP:
24141 case OPC_WRDSP:
24142 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24143 break;
24144 default: /* Invalid */
24145 MIPS_INVAL("MASK EXTR.W");
24146 gen_reserved_instruction(ctx);
24147 break;
24149 break;
24150 #if defined(TARGET_MIPS64)
24151 case OPC_DDIV_G_2E:
24152 case OPC_DDIVU_G_2E:
24153 case OPC_DMULT_G_2E:
24154 case OPC_DMULTU_G_2E:
24155 case OPC_DMOD_G_2E:
24156 case OPC_DMODU_G_2E:
24157 check_insn(ctx, INSN_LOONGSON2E);
24158 gen_loongson_integer(ctx, op1, rd, rs, rt);
24159 break;
24160 case OPC_ABSQ_S_QH_DSP:
24161 op2 = MASK_ABSQ_S_QH(ctx->opcode);
24162 switch (op2) {
24163 case OPC_PRECEQ_L_PWL:
24164 case OPC_PRECEQ_L_PWR:
24165 case OPC_PRECEQ_PW_QHL:
24166 case OPC_PRECEQ_PW_QHR:
24167 case OPC_PRECEQ_PW_QHLA:
24168 case OPC_PRECEQ_PW_QHRA:
24169 case OPC_PRECEQU_QH_OBL:
24170 case OPC_PRECEQU_QH_OBR:
24171 case OPC_PRECEQU_QH_OBLA:
24172 case OPC_PRECEQU_QH_OBRA:
24173 case OPC_PRECEU_QH_OBL:
24174 case OPC_PRECEU_QH_OBR:
24175 case OPC_PRECEU_QH_OBLA:
24176 case OPC_PRECEU_QH_OBRA:
24177 case OPC_ABSQ_S_OB:
24178 case OPC_ABSQ_S_PW:
24179 case OPC_ABSQ_S_QH:
24180 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24181 break;
24182 case OPC_REPL_OB:
24183 case OPC_REPL_PW:
24184 case OPC_REPL_QH:
24185 case OPC_REPLV_OB:
24186 case OPC_REPLV_PW:
24187 case OPC_REPLV_QH:
24188 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24189 break;
24190 default: /* Invalid */
24191 MIPS_INVAL("MASK ABSQ_S.QH");
24192 gen_reserved_instruction(ctx);
24193 break;
24195 break;
24196 case OPC_ADDU_OB_DSP:
24197 op2 = MASK_ADDU_OB(ctx->opcode);
24198 switch (op2) {
24199 case OPC_RADDU_L_OB:
24200 case OPC_SUBQ_PW:
24201 case OPC_SUBQ_S_PW:
24202 case OPC_SUBQ_QH:
24203 case OPC_SUBQ_S_QH:
24204 case OPC_SUBU_OB:
24205 case OPC_SUBU_S_OB:
24206 case OPC_SUBU_QH:
24207 case OPC_SUBU_S_QH:
24208 case OPC_SUBUH_OB:
24209 case OPC_SUBUH_R_OB:
24210 case OPC_ADDQ_PW:
24211 case OPC_ADDQ_S_PW:
24212 case OPC_ADDQ_QH:
24213 case OPC_ADDQ_S_QH:
24214 case OPC_ADDU_OB:
24215 case OPC_ADDU_S_OB:
24216 case OPC_ADDU_QH:
24217 case OPC_ADDU_S_QH:
24218 case OPC_ADDUH_OB:
24219 case OPC_ADDUH_R_OB:
24220 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24221 break;
24222 case OPC_MULEQ_S_PW_QHL:
24223 case OPC_MULEQ_S_PW_QHR:
24224 case OPC_MULEU_S_QH_OBL:
24225 case OPC_MULEU_S_QH_OBR:
24226 case OPC_MULQ_RS_QH:
24227 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24228 break;
24229 default: /* Invalid */
24230 MIPS_INVAL("MASK ADDU.OB");
24231 gen_reserved_instruction(ctx);
24232 break;
24234 break;
24235 case OPC_CMPU_EQ_OB_DSP:
24236 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
24237 switch (op2) {
24238 case OPC_PRECR_SRA_QH_PW:
24239 case OPC_PRECR_SRA_R_QH_PW:
24240 /* Return value is rt. */
24241 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24242 break;
24243 case OPC_PRECR_OB_QH:
24244 case OPC_PRECRQ_OB_QH:
24245 case OPC_PRECRQ_PW_L:
24246 case OPC_PRECRQ_QH_PW:
24247 case OPC_PRECRQ_RS_QH_PW:
24248 case OPC_PRECRQU_S_OB_QH:
24249 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24250 break;
24251 case OPC_CMPU_EQ_OB:
24252 case OPC_CMPU_LT_OB:
24253 case OPC_CMPU_LE_OB:
24254 case OPC_CMP_EQ_QH:
24255 case OPC_CMP_LT_QH:
24256 case OPC_CMP_LE_QH:
24257 case OPC_CMP_EQ_PW:
24258 case OPC_CMP_LT_PW:
24259 case OPC_CMP_LE_PW:
24260 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24261 break;
24262 case OPC_CMPGDU_EQ_OB:
24263 case OPC_CMPGDU_LT_OB:
24264 case OPC_CMPGDU_LE_OB:
24265 case OPC_CMPGU_EQ_OB:
24266 case OPC_CMPGU_LT_OB:
24267 case OPC_CMPGU_LE_OB:
24268 case OPC_PACKRL_PW:
24269 case OPC_PICK_OB:
24270 case OPC_PICK_PW:
24271 case OPC_PICK_QH:
24272 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24273 break;
24274 default: /* Invalid */
24275 MIPS_INVAL("MASK CMPU_EQ.OB");
24276 gen_reserved_instruction(ctx);
24277 break;
24279 break;
24280 case OPC_DAPPEND_DSP:
24281 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24282 break;
24283 case OPC_DEXTR_W_DSP:
24284 op2 = MASK_DEXTR_W(ctx->opcode);
24285 switch (op2) {
24286 case OPC_DEXTP:
24287 case OPC_DEXTPDP:
24288 case OPC_DEXTPDPV:
24289 case OPC_DEXTPV:
24290 case OPC_DEXTR_L:
24291 case OPC_DEXTR_R_L:
24292 case OPC_DEXTR_RS_L:
24293 case OPC_DEXTR_W:
24294 case OPC_DEXTR_R_W:
24295 case OPC_DEXTR_RS_W:
24296 case OPC_DEXTR_S_H:
24297 case OPC_DEXTRV_L:
24298 case OPC_DEXTRV_R_L:
24299 case OPC_DEXTRV_RS_L:
24300 case OPC_DEXTRV_S_H:
24301 case OPC_DEXTRV_W:
24302 case OPC_DEXTRV_R_W:
24303 case OPC_DEXTRV_RS_W:
24304 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24305 break;
24306 case OPC_DMTHLIP:
24307 case OPC_DSHILO:
24308 case OPC_DSHILOV:
24309 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24310 break;
24311 default: /* Invalid */
24312 MIPS_INVAL("MASK EXTR.W");
24313 gen_reserved_instruction(ctx);
24314 break;
24316 break;
24317 case OPC_DPAQ_W_QH_DSP:
24318 op2 = MASK_DPAQ_W_QH(ctx->opcode);
24319 switch (op2) {
24320 case OPC_DPAU_H_OBL:
24321 case OPC_DPAU_H_OBR:
24322 case OPC_DPSU_H_OBL:
24323 case OPC_DPSU_H_OBR:
24324 case OPC_DPA_W_QH:
24325 case OPC_DPAQ_S_W_QH:
24326 case OPC_DPS_W_QH:
24327 case OPC_DPSQ_S_W_QH:
24328 case OPC_MULSAQ_S_W_QH:
24329 case OPC_DPAQ_SA_L_PW:
24330 case OPC_DPSQ_SA_L_PW:
24331 case OPC_MULSAQ_S_L_PW:
24332 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24333 break;
24334 case OPC_MAQ_S_W_QHLL:
24335 case OPC_MAQ_S_W_QHLR:
24336 case OPC_MAQ_S_W_QHRL:
24337 case OPC_MAQ_S_W_QHRR:
24338 case OPC_MAQ_SA_W_QHLL:
24339 case OPC_MAQ_SA_W_QHLR:
24340 case OPC_MAQ_SA_W_QHRL:
24341 case OPC_MAQ_SA_W_QHRR:
24342 case OPC_MAQ_S_L_PWL:
24343 case OPC_MAQ_S_L_PWR:
24344 case OPC_DMADD:
24345 case OPC_DMADDU:
24346 case OPC_DMSUB:
24347 case OPC_DMSUBU:
24348 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24349 break;
24350 default: /* Invalid */
24351 MIPS_INVAL("MASK DPAQ.W.QH");
24352 gen_reserved_instruction(ctx);
24353 break;
24355 break;
24356 case OPC_DINSV_DSP:
24357 op2 = MASK_INSV(ctx->opcode);
24358 switch (op2) {
24359 case OPC_DINSV:
24361 TCGv t0, t1;
24363 if (rt == 0) {
24364 break;
24366 check_dsp(ctx);
24368 t0 = tcg_temp_new();
24369 t1 = tcg_temp_new();
24371 gen_load_gpr(t0, rt);
24372 gen_load_gpr(t1, rs);
24374 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
24376 tcg_temp_free(t0);
24377 tcg_temp_free(t1);
24378 break;
24380 default: /* Invalid */
24381 MIPS_INVAL("MASK DINSV");
24382 gen_reserved_instruction(ctx);
24383 break;
24385 break;
24386 case OPC_SHLL_OB_DSP:
24387 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24388 break;
24389 #endif
24390 default: /* Invalid */
24391 MIPS_INVAL("special3_legacy");
24392 gen_reserved_instruction(ctx);
24393 break;
24398 #if defined(TARGET_MIPS64)
24400 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
24402 uint32_t opc = MASK_MMI(ctx->opcode);
24403 int rs = extract32(ctx->opcode, 21, 5);
24404 int rt = extract32(ctx->opcode, 16, 5);
24405 int rd = extract32(ctx->opcode, 11, 5);
24407 switch (opc) {
24408 case MMI_OPC_MULT1:
24409 case MMI_OPC_MULTU1:
24410 case MMI_OPC_MADD:
24411 case MMI_OPC_MADDU:
24412 case MMI_OPC_MADD1:
24413 case MMI_OPC_MADDU1:
24414 gen_mul_txx9(ctx, opc, rd, rs, rt);
24415 break;
24416 case MMI_OPC_DIV1:
24417 case MMI_OPC_DIVU1:
24418 gen_div1_tx79(ctx, opc, rs, rt);
24419 break;
24420 default:
24421 MIPS_INVAL("TX79 MMI class");
24422 gen_reserved_instruction(ctx);
24423 break;
24427 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
24429 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_LQ */
24432 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
24434 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
24438 * The TX79-specific instruction Store Quadword
24440 * +--------+-------+-------+------------------------+
24441 * | 011111 | base | rt | offset | SQ
24442 * +--------+-------+-------+------------------------+
24443 * 6 5 5 16
24445 * has the same opcode as the Read Hardware Register instruction
24447 * +--------+-------+-------+-------+-------+--------+
24448 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
24449 * +--------+-------+-------+-------+-------+--------+
24450 * 6 5 5 5 5 6
24452 * that is required, trapped and emulated by the Linux kernel. However, all
24453 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
24454 * offset is odd. Therefore all valid SQ instructions can execute normally.
24455 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
24456 * between SQ and RDHWR, as the Linux kernel does.
24458 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
24460 int base = extract32(ctx->opcode, 21, 5);
24461 int rt = extract32(ctx->opcode, 16, 5);
24462 int offset = extract32(ctx->opcode, 0, 16);
24464 #ifdef CONFIG_USER_ONLY
24465 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
24466 uint32_t op2 = extract32(ctx->opcode, 6, 5);
24468 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
24469 int rd = extract32(ctx->opcode, 11, 5);
24471 gen_rdhwr(ctx, rt, rd, 0);
24472 return;
24474 #endif
24476 gen_mmi_sq(ctx, base, rt, offset);
24479 #endif
24481 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
24483 int rs, rt, rd, sa;
24484 uint32_t op1, op2;
24485 int16_t imm;
24487 rs = (ctx->opcode >> 21) & 0x1f;
24488 rt = (ctx->opcode >> 16) & 0x1f;
24489 rd = (ctx->opcode >> 11) & 0x1f;
24490 sa = (ctx->opcode >> 6) & 0x1f;
24491 imm = sextract32(ctx->opcode, 7, 9);
24493 op1 = MASK_SPECIAL3(ctx->opcode);
24496 * EVA loads and stores overlap Loongson 2E instructions decoded by
24497 * decode_opc_special3_legacy(), so be careful to allow their decoding when
24498 * EVA is absent.
24500 if (ctx->eva) {
24501 switch (op1) {
24502 case OPC_LWLE:
24503 case OPC_LWRE:
24504 case OPC_LBUE:
24505 case OPC_LHUE:
24506 case OPC_LBE:
24507 case OPC_LHE:
24508 case OPC_LLE:
24509 case OPC_LWE:
24510 check_cp0_enabled(ctx);
24511 gen_ld(ctx, op1, rt, rs, imm);
24512 return;
24513 case OPC_SWLE:
24514 case OPC_SWRE:
24515 case OPC_SBE:
24516 case OPC_SHE:
24517 case OPC_SWE:
24518 check_cp0_enabled(ctx);
24519 gen_st(ctx, op1, rt, rs, imm);
24520 return;
24521 case OPC_SCE:
24522 check_cp0_enabled(ctx);
24523 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
24524 return;
24525 case OPC_CACHEE:
24526 check_eva(ctx);
24527 check_cp0_enabled(ctx);
24528 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24529 gen_cache_operation(ctx, rt, rs, imm);
24531 return;
24532 case OPC_PREFE:
24533 check_cp0_enabled(ctx);
24534 /* Treat as NOP. */
24535 return;
24539 switch (op1) {
24540 case OPC_EXT:
24541 case OPC_INS:
24542 check_insn(ctx, ISA_MIPS_R2);
24543 gen_bitops(ctx, op1, rt, rs, sa, rd);
24544 break;
24545 case OPC_BSHFL:
24546 op2 = MASK_BSHFL(ctx->opcode);
24547 switch (op2) {
24548 case OPC_ALIGN:
24549 case OPC_ALIGN_1:
24550 case OPC_ALIGN_2:
24551 case OPC_ALIGN_3:
24552 case OPC_BITSWAP:
24553 check_insn(ctx, ISA_MIPS_R6);
24554 decode_opc_special3_r6(env, ctx);
24555 break;
24556 default:
24557 check_insn(ctx, ISA_MIPS_R2);
24558 gen_bshfl(ctx, op2, rt, rd);
24559 break;
24561 break;
24562 #if defined(TARGET_MIPS64)
24563 case OPC_DEXTM:
24564 case OPC_DEXTU:
24565 case OPC_DEXT:
24566 case OPC_DINSM:
24567 case OPC_DINSU:
24568 case OPC_DINS:
24569 check_insn(ctx, ISA_MIPS_R2);
24570 check_mips_64(ctx);
24571 gen_bitops(ctx, op1, rt, rs, sa, rd);
24572 break;
24573 case OPC_DBSHFL:
24574 op2 = MASK_DBSHFL(ctx->opcode);
24575 switch (op2) {
24576 case OPC_DALIGN:
24577 case OPC_DALIGN_1:
24578 case OPC_DALIGN_2:
24579 case OPC_DALIGN_3:
24580 case OPC_DALIGN_4:
24581 case OPC_DALIGN_5:
24582 case OPC_DALIGN_6:
24583 case OPC_DALIGN_7:
24584 case OPC_DBITSWAP:
24585 check_insn(ctx, ISA_MIPS_R6);
24586 decode_opc_special3_r6(env, ctx);
24587 break;
24588 default:
24589 check_insn(ctx, ISA_MIPS_R2);
24590 check_mips_64(ctx);
24591 op2 = MASK_DBSHFL(ctx->opcode);
24592 gen_bshfl(ctx, op2, rt, rd);
24593 break;
24595 break;
24596 #endif
24597 case OPC_RDHWR:
24598 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
24599 break;
24600 case OPC_FORK:
24601 check_mt(ctx);
24603 TCGv t0 = tcg_temp_new();
24604 TCGv t1 = tcg_temp_new();
24606 gen_load_gpr(t0, rt);
24607 gen_load_gpr(t1, rs);
24608 gen_helper_fork(t0, t1);
24609 tcg_temp_free(t0);
24610 tcg_temp_free(t1);
24612 break;
24613 case OPC_YIELD:
24614 check_mt(ctx);
24616 TCGv t0 = tcg_temp_new();
24618 gen_load_gpr(t0, rs);
24619 gen_helper_yield(t0, cpu_env, t0);
24620 gen_store_gpr(t0, rd);
24621 tcg_temp_free(t0);
24623 break;
24624 default:
24625 if (ctx->insn_flags & ISA_MIPS_R6) {
24626 decode_opc_special3_r6(env, ctx);
24627 } else {
24628 decode_opc_special3_legacy(env, ctx);
24633 static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
24635 int32_t offset;
24636 int rs, rt, rd, sa;
24637 uint32_t op, op1;
24638 int16_t imm;
24640 op = MASK_OP_MAJOR(ctx->opcode);
24641 rs = (ctx->opcode >> 21) & 0x1f;
24642 rt = (ctx->opcode >> 16) & 0x1f;
24643 rd = (ctx->opcode >> 11) & 0x1f;
24644 sa = (ctx->opcode >> 6) & 0x1f;
24645 imm = (int16_t)ctx->opcode;
24646 switch (op) {
24647 case OPC_SPECIAL:
24648 decode_opc_special(env, ctx);
24649 break;
24650 case OPC_SPECIAL2:
24651 #if defined(TARGET_MIPS64)
24652 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
24653 decode_mmi(env, ctx);
24654 break;
24656 #endif
24657 if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) {
24658 if (MASK_SPECIAL2(ctx->opcode) == OPC_MUL) {
24659 gen_arith(ctx, OPC_MUL, rd, rs, rt);
24660 } else {
24661 decode_ase_mxu(ctx, ctx->opcode);
24663 break;
24665 decode_opc_special2_legacy(env, ctx);
24666 break;
24667 case OPC_SPECIAL3:
24668 #if defined(TARGET_MIPS64)
24669 if (ctx->insn_flags & INSN_R5900) {
24670 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
24671 } else {
24672 decode_opc_special3(env, ctx);
24674 #else
24675 decode_opc_special3(env, ctx);
24676 #endif
24677 break;
24678 case OPC_REGIMM:
24679 op1 = MASK_REGIMM(ctx->opcode);
24680 switch (op1) {
24681 case OPC_BLTZL: /* REGIMM branches */
24682 case OPC_BGEZL:
24683 case OPC_BLTZALL:
24684 case OPC_BGEZALL:
24685 check_insn(ctx, ISA_MIPS2);
24686 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24687 /* Fallthrough */
24688 case OPC_BLTZ:
24689 case OPC_BGEZ:
24690 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
24691 break;
24692 case OPC_BLTZAL:
24693 case OPC_BGEZAL:
24694 if (ctx->insn_flags & ISA_MIPS_R6) {
24695 if (rs == 0) {
24696 /* OPC_NAL, OPC_BAL */
24697 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
24698 } else {
24699 gen_reserved_instruction(ctx);
24701 } else {
24702 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
24704 break;
24705 case OPC_TGEI: /* REGIMM traps */
24706 case OPC_TGEIU:
24707 case OPC_TLTI:
24708 case OPC_TLTIU:
24709 case OPC_TEQI:
24711 case OPC_TNEI:
24712 check_insn(ctx, ISA_MIPS2);
24713 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24714 gen_trap(ctx, op1, rs, -1, imm);
24715 break;
24716 case OPC_SIGRIE:
24717 check_insn(ctx, ISA_MIPS_R6);
24718 gen_reserved_instruction(ctx);
24719 break;
24720 case OPC_SYNCI:
24721 check_insn(ctx, ISA_MIPS_R2);
24723 * Break the TB to be able to sync copied instructions
24724 * immediately.
24726 ctx->base.is_jmp = DISAS_STOP;
24727 break;
24728 case OPC_BPOSGE32: /* MIPS DSP branch */
24729 #if defined(TARGET_MIPS64)
24730 case OPC_BPOSGE64:
24731 #endif
24732 check_dsp(ctx);
24733 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
24734 break;
24735 #if defined(TARGET_MIPS64)
24736 case OPC_DAHI:
24737 check_insn(ctx, ISA_MIPS_R6);
24738 check_mips_64(ctx);
24739 if (rs != 0) {
24740 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
24742 break;
24743 case OPC_DATI:
24744 check_insn(ctx, ISA_MIPS_R6);
24745 check_mips_64(ctx);
24746 if (rs != 0) {
24747 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
24749 break;
24750 #endif
24751 default: /* Invalid */
24752 MIPS_INVAL("regimm");
24753 gen_reserved_instruction(ctx);
24754 break;
24756 break;
24757 case OPC_CP0:
24758 check_cp0_enabled(ctx);
24759 op1 = MASK_CP0(ctx->opcode);
24760 switch (op1) {
24761 case OPC_MFC0:
24762 case OPC_MTC0:
24763 case OPC_MFTR:
24764 case OPC_MTTR:
24765 case OPC_MFHC0:
24766 case OPC_MTHC0:
24767 #if defined(TARGET_MIPS64)
24768 case OPC_DMFC0:
24769 case OPC_DMTC0:
24770 #endif
24771 #ifndef CONFIG_USER_ONLY
24772 gen_cp0(env, ctx, op1, rt, rd);
24773 #endif /* !CONFIG_USER_ONLY */
24774 break;
24775 case OPC_C0:
24776 case OPC_C0_1:
24777 case OPC_C0_2:
24778 case OPC_C0_3:
24779 case OPC_C0_4:
24780 case OPC_C0_5:
24781 case OPC_C0_6:
24782 case OPC_C0_7:
24783 case OPC_C0_8:
24784 case OPC_C0_9:
24785 case OPC_C0_A:
24786 case OPC_C0_B:
24787 case OPC_C0_C:
24788 case OPC_C0_D:
24789 case OPC_C0_E:
24790 case OPC_C0_F:
24791 #ifndef CONFIG_USER_ONLY
24792 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
24793 #endif /* !CONFIG_USER_ONLY */
24794 break;
24795 case OPC_MFMC0:
24796 #ifndef CONFIG_USER_ONLY
24798 uint32_t op2;
24799 TCGv t0 = tcg_temp_new();
24801 op2 = MASK_MFMC0(ctx->opcode);
24802 switch (op2) {
24803 case OPC_DMT:
24804 check_cp0_mt(ctx);
24805 gen_helper_dmt(t0);
24806 gen_store_gpr(t0, rt);
24807 break;
24808 case OPC_EMT:
24809 check_cp0_mt(ctx);
24810 gen_helper_emt(t0);
24811 gen_store_gpr(t0, rt);
24812 break;
24813 case OPC_DVPE:
24814 check_cp0_mt(ctx);
24815 gen_helper_dvpe(t0, cpu_env);
24816 gen_store_gpr(t0, rt);
24817 break;
24818 case OPC_EVPE:
24819 check_cp0_mt(ctx);
24820 gen_helper_evpe(t0, cpu_env);
24821 gen_store_gpr(t0, rt);
24822 break;
24823 case OPC_DVP:
24824 check_insn(ctx, ISA_MIPS_R6);
24825 if (ctx->vp) {
24826 gen_helper_dvp(t0, cpu_env);
24827 gen_store_gpr(t0, rt);
24829 break;
24830 case OPC_EVP:
24831 check_insn(ctx, ISA_MIPS_R6);
24832 if (ctx->vp) {
24833 gen_helper_evp(t0, cpu_env);
24834 gen_store_gpr(t0, rt);
24836 break;
24837 case OPC_DI:
24838 check_insn(ctx, ISA_MIPS_R2);
24839 save_cpu_state(ctx, 1);
24840 gen_helper_di(t0, cpu_env);
24841 gen_store_gpr(t0, rt);
24843 * Stop translation as we may have switched
24844 * the execution mode.
24846 ctx->base.is_jmp = DISAS_STOP;
24847 break;
24848 case OPC_EI:
24849 check_insn(ctx, ISA_MIPS_R2);
24850 save_cpu_state(ctx, 1);
24851 gen_helper_ei(t0, cpu_env);
24852 gen_store_gpr(t0, rt);
24854 * DISAS_STOP isn't sufficient, we need to ensure we break
24855 * out of translated code to check for pending interrupts.
24857 gen_save_pc(ctx->base.pc_next + 4);
24858 ctx->base.is_jmp = DISAS_EXIT;
24859 break;
24860 default: /* Invalid */
24861 MIPS_INVAL("mfmc0");
24862 gen_reserved_instruction(ctx);
24863 break;
24865 tcg_temp_free(t0);
24867 #endif /* !CONFIG_USER_ONLY */
24868 break;
24869 case OPC_RDPGPR:
24870 check_insn(ctx, ISA_MIPS_R2);
24871 gen_load_srsgpr(rt, rd);
24872 break;
24873 case OPC_WRPGPR:
24874 check_insn(ctx, ISA_MIPS_R2);
24875 gen_store_srsgpr(rt, rd);
24876 break;
24877 default:
24878 MIPS_INVAL("cp0");
24879 gen_reserved_instruction(ctx);
24880 break;
24882 break;
24883 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
24884 if (ctx->insn_flags & ISA_MIPS_R6) {
24885 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
24886 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24887 } else {
24888 /* OPC_ADDI */
24889 /* Arithmetic with immediate opcode */
24890 gen_arith_imm(ctx, op, rt, rs, imm);
24892 break;
24893 case OPC_ADDIU:
24894 gen_arith_imm(ctx, op, rt, rs, imm);
24895 break;
24896 case OPC_SLTI: /* Set on less than with immediate opcode */
24897 case OPC_SLTIU:
24898 gen_slt_imm(ctx, op, rt, rs, imm);
24899 break;
24900 case OPC_ANDI: /* Arithmetic with immediate opcode */
24901 case OPC_LUI: /* OPC_AUI */
24902 case OPC_ORI:
24903 case OPC_XORI:
24904 gen_logic_imm(ctx, op, rt, rs, imm);
24905 break;
24906 case OPC_J: /* Jump */
24907 case OPC_JAL:
24908 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
24909 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
24910 break;
24911 /* Branch */
24912 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
24913 if (ctx->insn_flags & ISA_MIPS_R6) {
24914 if (rt == 0) {
24915 gen_reserved_instruction(ctx);
24916 break;
24918 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
24919 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24920 } else {
24921 /* OPC_BLEZL */
24922 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24924 break;
24925 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
24926 if (ctx->insn_flags & ISA_MIPS_R6) {
24927 if (rt == 0) {
24928 gen_reserved_instruction(ctx);
24929 break;
24931 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
24932 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24933 } else {
24934 /* OPC_BGTZL */
24935 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24937 break;
24938 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
24939 if (rt == 0) {
24940 /* OPC_BLEZ */
24941 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24942 } else {
24943 check_insn(ctx, ISA_MIPS_R6);
24944 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
24945 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24947 break;
24948 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
24949 if (rt == 0) {
24950 /* OPC_BGTZ */
24951 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24952 } else {
24953 check_insn(ctx, ISA_MIPS_R6);
24954 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
24955 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24957 break;
24958 case OPC_BEQL:
24959 case OPC_BNEL:
24960 check_insn(ctx, ISA_MIPS2);
24961 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24962 /* Fallthrough */
24963 case OPC_BEQ:
24964 case OPC_BNE:
24965 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24966 break;
24967 case OPC_LL: /* Load and stores */
24968 check_insn(ctx, ISA_MIPS2);
24969 if (ctx->insn_flags & INSN_R5900) {
24970 check_insn_opc_user_only(ctx, INSN_R5900);
24972 /* Fallthrough */
24973 case OPC_LWL:
24974 case OPC_LWR:
24975 case OPC_LB:
24976 case OPC_LH:
24977 case OPC_LW:
24978 case OPC_LWPC:
24979 case OPC_LBU:
24980 case OPC_LHU:
24981 gen_ld(ctx, op, rt, rs, imm);
24982 break;
24983 case OPC_SWL:
24984 case OPC_SWR:
24985 case OPC_SB:
24986 case OPC_SH:
24987 case OPC_SW:
24988 gen_st(ctx, op, rt, rs, imm);
24989 break;
24990 case OPC_SC:
24991 check_insn(ctx, ISA_MIPS2);
24992 if (ctx->insn_flags & INSN_R5900) {
24993 check_insn_opc_user_only(ctx, INSN_R5900);
24995 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
24996 break;
24997 case OPC_CACHE:
24998 check_cp0_enabled(ctx);
24999 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
25000 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25001 gen_cache_operation(ctx, rt, rs, imm);
25003 /* Treat as NOP. */
25004 break;
25005 case OPC_PREF:
25006 if (ctx->insn_flags & INSN_R5900) {
25007 /* Treat as NOP. */
25008 } else {
25009 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
25010 /* Treat as NOP. */
25012 break;
25014 /* Floating point (COP1). */
25015 case OPC_LWC1:
25016 case OPC_LDC1:
25017 case OPC_SWC1:
25018 case OPC_SDC1:
25019 gen_cop1_ldst(ctx, op, rt, rs, imm);
25020 break;
25022 case OPC_CP1:
25023 op1 = MASK_CP1(ctx->opcode);
25025 switch (op1) {
25026 case OPC_MFHC1:
25027 case OPC_MTHC1:
25028 check_cp1_enabled(ctx);
25029 check_insn(ctx, ISA_MIPS_R2);
25030 /* fall through */
25031 case OPC_MFC1:
25032 case OPC_CFC1:
25033 case OPC_MTC1:
25034 case OPC_CTC1:
25035 check_cp1_enabled(ctx);
25036 gen_cp1(ctx, op1, rt, rd);
25037 break;
25038 #if defined(TARGET_MIPS64)
25039 case OPC_DMFC1:
25040 case OPC_DMTC1:
25041 check_cp1_enabled(ctx);
25042 check_insn(ctx, ISA_MIPS3);
25043 check_mips_64(ctx);
25044 gen_cp1(ctx, op1, rt, rd);
25045 break;
25046 #endif
25047 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
25048 check_cp1_enabled(ctx);
25049 if (ctx->insn_flags & ISA_MIPS_R6) {
25050 /* OPC_BC1EQZ */
25051 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25052 rt, imm << 2, 4);
25053 } else {
25054 /* OPC_BC1ANY2 */
25055 check_cop1x(ctx);
25056 check_insn(ctx, ASE_MIPS3D);
25057 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25058 (rt >> 2) & 0x7, imm << 2);
25060 break;
25061 case OPC_BC1NEZ:
25062 check_cp1_enabled(ctx);
25063 check_insn(ctx, ISA_MIPS_R6);
25064 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25065 rt, imm << 2, 4);
25066 break;
25067 case OPC_BC1ANY4:
25068 check_cp1_enabled(ctx);
25069 check_insn_opc_removed(ctx, ISA_MIPS_R6);
25070 check_cop1x(ctx);
25071 check_insn(ctx, ASE_MIPS3D);
25072 /* fall through */
25073 case OPC_BC1:
25074 check_cp1_enabled(ctx);
25075 check_insn_opc_removed(ctx, ISA_MIPS_R6);
25076 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25077 (rt >> 2) & 0x7, imm << 2);
25078 break;
25079 case OPC_PS_FMT:
25080 check_ps(ctx);
25081 /* fall through */
25082 case OPC_S_FMT:
25083 case OPC_D_FMT:
25084 check_cp1_enabled(ctx);
25085 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25086 (imm >> 8) & 0x7);
25087 break;
25088 case OPC_W_FMT:
25089 case OPC_L_FMT:
25091 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
25092 check_cp1_enabled(ctx);
25093 if (ctx->insn_flags & ISA_MIPS_R6) {
25094 switch (r6_op) {
25095 case R6_OPC_CMP_AF_S:
25096 case R6_OPC_CMP_UN_S:
25097 case R6_OPC_CMP_EQ_S:
25098 case R6_OPC_CMP_UEQ_S:
25099 case R6_OPC_CMP_LT_S:
25100 case R6_OPC_CMP_ULT_S:
25101 case R6_OPC_CMP_LE_S:
25102 case R6_OPC_CMP_ULE_S:
25103 case R6_OPC_CMP_SAF_S:
25104 case R6_OPC_CMP_SUN_S:
25105 case R6_OPC_CMP_SEQ_S:
25106 case R6_OPC_CMP_SEUQ_S:
25107 case R6_OPC_CMP_SLT_S:
25108 case R6_OPC_CMP_SULT_S:
25109 case R6_OPC_CMP_SLE_S:
25110 case R6_OPC_CMP_SULE_S:
25111 case R6_OPC_CMP_OR_S:
25112 case R6_OPC_CMP_UNE_S:
25113 case R6_OPC_CMP_NE_S:
25114 case R6_OPC_CMP_SOR_S:
25115 case R6_OPC_CMP_SUNE_S:
25116 case R6_OPC_CMP_SNE_S:
25117 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25118 break;
25119 case R6_OPC_CMP_AF_D:
25120 case R6_OPC_CMP_UN_D:
25121 case R6_OPC_CMP_EQ_D:
25122 case R6_OPC_CMP_UEQ_D:
25123 case R6_OPC_CMP_LT_D:
25124 case R6_OPC_CMP_ULT_D:
25125 case R6_OPC_CMP_LE_D:
25126 case R6_OPC_CMP_ULE_D:
25127 case R6_OPC_CMP_SAF_D:
25128 case R6_OPC_CMP_SUN_D:
25129 case R6_OPC_CMP_SEQ_D:
25130 case R6_OPC_CMP_SEUQ_D:
25131 case R6_OPC_CMP_SLT_D:
25132 case R6_OPC_CMP_SULT_D:
25133 case R6_OPC_CMP_SLE_D:
25134 case R6_OPC_CMP_SULE_D:
25135 case R6_OPC_CMP_OR_D:
25136 case R6_OPC_CMP_UNE_D:
25137 case R6_OPC_CMP_NE_D:
25138 case R6_OPC_CMP_SOR_D:
25139 case R6_OPC_CMP_SUNE_D:
25140 case R6_OPC_CMP_SNE_D:
25141 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25142 break;
25143 default:
25144 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
25145 rt, rd, sa, (imm >> 8) & 0x7);
25147 break;
25149 } else {
25150 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25151 (imm >> 8) & 0x7);
25153 break;
25155 default:
25156 MIPS_INVAL("cp1");
25157 gen_reserved_instruction(ctx);
25158 break;
25160 break;
25162 /* Compact branches [R6] and COP2 [non-R6] */
25163 case OPC_BC: /* OPC_LWC2 */
25164 case OPC_BALC: /* OPC_SWC2 */
25165 if (ctx->insn_flags & ISA_MIPS_R6) {
25166 /* OPC_BC, OPC_BALC */
25167 gen_compute_compact_branch(ctx, op, 0, 0,
25168 sextract32(ctx->opcode << 2, 0, 28));
25169 } else if (ctx->insn_flags & ASE_LEXT) {
25170 gen_loongson_lswc2(ctx, rt, rs, rd);
25171 } else {
25172 /* OPC_LWC2, OPC_SWC2 */
25173 /* COP2: Not implemented. */
25174 generate_exception_err(ctx, EXCP_CpU, 2);
25176 break;
25177 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
25178 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
25179 if (ctx->insn_flags & ISA_MIPS_R6) {
25180 if (rs != 0) {
25181 /* OPC_BEQZC, OPC_BNEZC */
25182 gen_compute_compact_branch(ctx, op, rs, 0,
25183 sextract32(ctx->opcode << 2, 0, 23));
25184 } else {
25185 /* OPC_JIC, OPC_JIALC */
25186 gen_compute_compact_branch(ctx, op, 0, rt, imm);
25188 } else if (ctx->insn_flags & ASE_LEXT) {
25189 gen_loongson_lsdc2(ctx, rt, rs, rd);
25190 } else {
25191 /* OPC_LWC2, OPC_SWC2 */
25192 /* COP2: Not implemented. */
25193 generate_exception_err(ctx, EXCP_CpU, 2);
25195 break;
25196 case OPC_CP2:
25197 check_insn(ctx, ASE_LMMI);
25198 /* Note that these instructions use different fields. */
25199 gen_loongson_multimedia(ctx, sa, rd, rt);
25200 break;
25202 case OPC_CP3:
25203 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
25204 check_cp1_enabled(ctx);
25205 op1 = MASK_CP3(ctx->opcode);
25206 switch (op1) {
25207 case OPC_LUXC1:
25208 case OPC_SUXC1:
25209 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
25210 /* Fallthrough */
25211 case OPC_LWXC1:
25212 case OPC_LDXC1:
25213 case OPC_SWXC1:
25214 case OPC_SDXC1:
25215 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25216 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
25217 break;
25218 case OPC_PREFX:
25219 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25220 /* Treat as NOP. */
25221 break;
25222 case OPC_ALNV_PS:
25223 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
25224 /* Fallthrough */
25225 case OPC_MADD_S:
25226 case OPC_MADD_D:
25227 case OPC_MADD_PS:
25228 case OPC_MSUB_S:
25229 case OPC_MSUB_D:
25230 case OPC_MSUB_PS:
25231 case OPC_NMADD_S:
25232 case OPC_NMADD_D:
25233 case OPC_NMADD_PS:
25234 case OPC_NMSUB_S:
25235 case OPC_NMSUB_D:
25236 case OPC_NMSUB_PS:
25237 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25238 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
25239 break;
25240 default:
25241 MIPS_INVAL("cp3");
25242 gen_reserved_instruction(ctx);
25243 break;
25245 } else {
25246 generate_exception_err(ctx, EXCP_CpU, 1);
25248 break;
25250 #if defined(TARGET_MIPS64)
25251 /* MIPS64 opcodes */
25252 case OPC_LLD:
25253 if (ctx->insn_flags & INSN_R5900) {
25254 check_insn_opc_user_only(ctx, INSN_R5900);
25256 /* fall through */
25257 case OPC_LDL:
25258 case OPC_LDR:
25259 case OPC_LWU:
25260 case OPC_LD:
25261 check_insn(ctx, ISA_MIPS3);
25262 check_mips_64(ctx);
25263 gen_ld(ctx, op, rt, rs, imm);
25264 break;
25265 case OPC_SDL:
25266 case OPC_SDR:
25267 case OPC_SD:
25268 check_insn(ctx, ISA_MIPS3);
25269 check_mips_64(ctx);
25270 gen_st(ctx, op, rt, rs, imm);
25271 break;
25272 case OPC_SCD:
25273 check_insn(ctx, ISA_MIPS3);
25274 if (ctx->insn_flags & INSN_R5900) {
25275 check_insn_opc_user_only(ctx, INSN_R5900);
25277 check_mips_64(ctx);
25278 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
25279 break;
25280 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
25281 if (ctx->insn_flags & ISA_MIPS_R6) {
25282 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
25283 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25284 } else {
25285 /* OPC_DADDI */
25286 check_insn(ctx, ISA_MIPS3);
25287 check_mips_64(ctx);
25288 gen_arith_imm(ctx, op, rt, rs, imm);
25290 break;
25291 case OPC_DADDIU:
25292 check_insn(ctx, ISA_MIPS3);
25293 check_mips_64(ctx);
25294 gen_arith_imm(ctx, op, rt, rs, imm);
25295 break;
25296 #else
25297 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
25298 if (ctx->insn_flags & ISA_MIPS_R6) {
25299 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25300 } else {
25301 MIPS_INVAL("major opcode");
25302 gen_reserved_instruction(ctx);
25304 break;
25305 #endif
25306 case OPC_DAUI: /* OPC_JALX */
25307 if (ctx->insn_flags & ISA_MIPS_R6) {
25308 #if defined(TARGET_MIPS64)
25309 /* OPC_DAUI */
25310 check_mips_64(ctx);
25311 if (rs == 0) {
25312 generate_exception(ctx, EXCP_RI);
25313 } else if (rt != 0) {
25314 TCGv t0 = tcg_temp_new();
25315 gen_load_gpr(t0, rs);
25316 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
25317 tcg_temp_free(t0);
25319 #else
25320 gen_reserved_instruction(ctx);
25321 MIPS_INVAL("major opcode");
25322 #endif
25323 } else {
25324 /* OPC_JALX */
25325 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
25326 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
25327 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
25329 break;
25330 case OPC_MDMX: /* MMI_OPC_LQ */
25331 if (ctx->insn_flags & INSN_R5900) {
25332 #if defined(TARGET_MIPS64)
25333 gen_mmi_lq(env, ctx);
25334 #endif
25335 } else {
25336 /* MDMX: Not implemented. */
25338 break;
25339 case OPC_PCREL:
25340 check_insn(ctx, ISA_MIPS_R6);
25341 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
25342 break;
25343 default: /* Invalid */
25344 MIPS_INVAL("major opcode");
25345 return false;
25347 return true;
25350 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
25352 /* make sure instructions are on a word boundary */
25353 if (ctx->base.pc_next & 0x3) {
25354 env->CP0_BadVAddr = ctx->base.pc_next;
25355 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
25356 return;
25359 /* Handle blikely not taken case */
25360 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
25361 TCGLabel *l1 = gen_new_label();
25363 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
25364 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
25365 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
25366 gen_set_label(l1);
25369 /* Transition to the auto-generated decoder. */
25371 /* ISA extensions */
25372 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
25373 return;
25376 /* ISA (from latest to oldest) */
25377 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
25378 return;
25380 if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
25381 return;
25384 if (decode_opc_legacy(env, ctx)) {
25385 return;
25388 gen_reserved_instruction(ctx);
25391 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
25393 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25394 CPUMIPSState *env = cs->env_ptr;
25396 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
25397 ctx->saved_pc = -1;
25398 ctx->insn_flags = env->insn_flags;
25399 ctx->CP0_Config1 = env->CP0_Config1;
25400 ctx->CP0_Config2 = env->CP0_Config2;
25401 ctx->CP0_Config3 = env->CP0_Config3;
25402 ctx->CP0_Config5 = env->CP0_Config5;
25403 ctx->btarget = 0;
25404 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
25405 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
25406 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
25407 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
25408 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
25409 ctx->PAMask = env->PAMask;
25410 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
25411 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
25412 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
25413 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
25414 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
25415 /* Restore delay slot state from the tb context. */
25416 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
25417 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
25418 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
25419 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
25420 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
25421 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
25422 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
25423 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
25424 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
25425 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
25426 restore_cpu_state(env, ctx);
25427 #ifdef CONFIG_USER_ONLY
25428 ctx->mem_idx = MIPS_HFLAG_UM;
25429 #else
25430 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
25431 #endif
25432 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
25433 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
25435 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
25436 ctx->hflags);
25439 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
25443 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
25445 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25447 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
25448 ctx->btarget);
25451 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
25452 const CPUBreakpoint *bp)
25454 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25456 save_cpu_state(ctx, 1);
25457 ctx->base.is_jmp = DISAS_NORETURN;
25458 gen_helper_raise_exception_debug(cpu_env);
25460 * The address covered by the breakpoint must be included in
25461 * [tb->pc, tb->pc + tb->size) in order to for it to be
25462 * properly cleared -- thus we increment the PC here so that
25463 * the logic setting tb->size below does the right thing.
25465 ctx->base.pc_next += 4;
25466 return true;
25469 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
25471 CPUMIPSState *env = cs->env_ptr;
25472 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25473 int insn_bytes;
25474 int is_slot;
25476 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
25477 if (ctx->insn_flags & ISA_NANOMIPS32) {
25478 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
25479 insn_bytes = decode_nanomips_opc(env, ctx);
25480 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
25481 ctx->opcode = translator_ldl(env, ctx->base.pc_next);
25482 insn_bytes = 4;
25483 decode_opc(env, ctx);
25484 } else if (ctx->insn_flags & ASE_MICROMIPS) {
25485 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
25486 insn_bytes = decode_micromips_opc(env, ctx);
25487 } else if (ctx->insn_flags & ASE_MIPS16) {
25488 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
25489 insn_bytes = decode_mips16_opc(env, ctx);
25490 } else {
25491 gen_reserved_instruction(ctx);
25492 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
25493 return;
25496 if (ctx->hflags & MIPS_HFLAG_BMASK) {
25497 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
25498 MIPS_HFLAG_FBNSLOT))) {
25500 * Force to generate branch as there is neither delay nor
25501 * forbidden slot.
25503 is_slot = 1;
25505 if ((ctx->hflags & MIPS_HFLAG_M16) &&
25506 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
25508 * Force to generate branch as microMIPS R6 doesn't restrict
25509 * branches in the forbidden slot.
25511 is_slot = 1;
25514 if (is_slot) {
25515 gen_branch(ctx, insn_bytes);
25517 ctx->base.pc_next += insn_bytes;
25519 if (ctx->base.is_jmp != DISAS_NEXT) {
25520 return;
25523 * Execute a branch and its delay slot as a single instruction.
25524 * This is what GDB expects and is consistent with what the
25525 * hardware does (e.g. if a delay slot instruction faults, the
25526 * reported PC is the PC of the branch).
25528 if (ctx->base.singlestep_enabled &&
25529 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
25530 ctx->base.is_jmp = DISAS_TOO_MANY;
25532 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
25533 ctx->base.is_jmp = DISAS_TOO_MANY;
25537 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
25539 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25541 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
25542 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
25543 gen_helper_raise_exception_debug(cpu_env);
25544 } else {
25545 switch (ctx->base.is_jmp) {
25546 case DISAS_STOP:
25547 gen_save_pc(ctx->base.pc_next);
25548 tcg_gen_lookup_and_goto_ptr();
25549 break;
25550 case DISAS_NEXT:
25551 case DISAS_TOO_MANY:
25552 save_cpu_state(ctx, 0);
25553 gen_goto_tb(ctx, 0, ctx->base.pc_next);
25554 break;
25555 case DISAS_EXIT:
25556 tcg_gen_exit_tb(NULL, 0);
25557 break;
25558 case DISAS_NORETURN:
25559 break;
25560 default:
25561 g_assert_not_reached();
25566 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
25568 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
25569 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
25572 static const TranslatorOps mips_tr_ops = {
25573 .init_disas_context = mips_tr_init_disas_context,
25574 .tb_start = mips_tr_tb_start,
25575 .insn_start = mips_tr_insn_start,
25576 .breakpoint_check = mips_tr_breakpoint_check,
25577 .translate_insn = mips_tr_translate_insn,
25578 .tb_stop = mips_tr_tb_stop,
25579 .disas_log = mips_tr_disas_log,
25582 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
25584 DisasContext ctx;
25586 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
25589 void mips_tcg_init(void)
25591 int i;
25593 cpu_gpr[0] = NULL;
25594 for (i = 1; i < 32; i++)
25595 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
25596 offsetof(CPUMIPSState,
25597 active_tc.gpr[i]),
25598 regnames[i]);
25599 #if defined(TARGET_MIPS64)
25600 cpu_gpr_hi[0] = NULL;
25602 for (unsigned i = 1; i < 32; i++) {
25603 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
25605 cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env,
25606 offsetof(CPUMIPSState,
25607 active_tc.gpr_hi[i]),
25608 rname);
25610 #endif /* !TARGET_MIPS64 */
25611 for (i = 0; i < 32; i++) {
25612 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
25614 fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
25616 msa_translate_init();
25617 cpu_PC = tcg_global_mem_new(cpu_env,
25618 offsetof(CPUMIPSState, active_tc.PC), "PC");
25619 for (i = 0; i < MIPS_DSP_ACC; i++) {
25620 cpu_HI[i] = tcg_global_mem_new(cpu_env,
25621 offsetof(CPUMIPSState, active_tc.HI[i]),
25622 regnames_HI[i]);
25623 cpu_LO[i] = tcg_global_mem_new(cpu_env,
25624 offsetof(CPUMIPSState, active_tc.LO[i]),
25625 regnames_LO[i]);
25627 cpu_dspctrl = tcg_global_mem_new(cpu_env,
25628 offsetof(CPUMIPSState,
25629 active_tc.DSPControl),
25630 "DSPControl");
25631 bcond = tcg_global_mem_new(cpu_env,
25632 offsetof(CPUMIPSState, bcond), "bcond");
25633 btarget = tcg_global_mem_new(cpu_env,
25634 offsetof(CPUMIPSState, btarget), "btarget");
25635 hflags = tcg_global_mem_new_i32(cpu_env,
25636 offsetof(CPUMIPSState, hflags), "hflags");
25638 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
25639 offsetof(CPUMIPSState, active_fpu.fcr0),
25640 "fcr0");
25641 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
25642 offsetof(CPUMIPSState, active_fpu.fcr31),
25643 "fcr31");
25644 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
25645 "lladdr");
25646 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
25647 "llval");
25649 if (TARGET_LONG_BITS == 32) {
25650 mxu_translate_init();
25654 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
25655 target_ulong *data)
25657 env->active_tc.PC = data[0];
25658 env->hflags &= ~MIPS_HFLAG_BMASK;
25659 env->hflags |= data[1];
25660 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
25661 case MIPS_HFLAG_BR:
25662 break;
25663 case MIPS_HFLAG_BC:
25664 case MIPS_HFLAG_BL:
25665 case MIPS_HFLAG_B:
25666 env->btarget = data[2];
25667 break;