target/mips: Remove 'C790 Multimedia Instructions' dead code
[qemu/ar7.git] / target / mips / translate.c
blob9334cd6df2e1be8ba643e0dbd194fc31fe33884d
1 /*
2 * MIPS emulation for QEMU - main translation routines
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
9 * Copyright (c) 2020 Philippe Mathieu-Daudé
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 #include "qemu/osdep.h"
26 #include "cpu.h"
27 #include "internal.h"
28 #include "tcg/tcg-op.h"
29 #include "exec/translator.h"
30 #include "exec/helper-proto.h"
31 #include "exec/helper-gen.h"
32 #include "semihosting/semihost.h"
34 #include "target/mips/trace.h"
35 #include "trace-tcg.h"
36 #include "exec/translator.h"
37 #include "exec/log.h"
38 #include "qemu/qemu-print.h"
39 #include "fpu_helper.h"
40 #include "translate.h"
42 enum {
43 /* indirect opcode tables */
44 OPC_SPECIAL = (0x00 << 26),
45 OPC_REGIMM = (0x01 << 26),
46 OPC_CP0 = (0x10 << 26),
47 OPC_CP2 = (0x12 << 26),
48 OPC_CP3 = (0x13 << 26),
49 OPC_SPECIAL2 = (0x1C << 26),
50 OPC_SPECIAL3 = (0x1F << 26),
51 /* arithmetic with immediate */
52 OPC_ADDI = (0x08 << 26),
53 OPC_ADDIU = (0x09 << 26),
54 OPC_SLTI = (0x0A << 26),
55 OPC_SLTIU = (0x0B << 26),
56 /* logic with immediate */
57 OPC_ANDI = (0x0C << 26),
58 OPC_ORI = (0x0D << 26),
59 OPC_XORI = (0x0E << 26),
60 OPC_LUI = (0x0F << 26),
61 /* arithmetic with immediate */
62 OPC_DADDI = (0x18 << 26),
63 OPC_DADDIU = (0x19 << 26),
64 /* Jump and branches */
65 OPC_J = (0x02 << 26),
66 OPC_JAL = (0x03 << 26),
67 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
68 OPC_BEQL = (0x14 << 26),
69 OPC_BNE = (0x05 << 26),
70 OPC_BNEL = (0x15 << 26),
71 OPC_BLEZ = (0x06 << 26),
72 OPC_BLEZL = (0x16 << 26),
73 OPC_BGTZ = (0x07 << 26),
74 OPC_BGTZL = (0x17 << 26),
75 OPC_JALX = (0x1D << 26),
76 OPC_DAUI = (0x1D << 26),
77 /* Load and stores */
78 OPC_LDL = (0x1A << 26),
79 OPC_LDR = (0x1B << 26),
80 OPC_LB = (0x20 << 26),
81 OPC_LH = (0x21 << 26),
82 OPC_LWL = (0x22 << 26),
83 OPC_LW = (0x23 << 26),
84 OPC_LWPC = OPC_LW | 0x5,
85 OPC_LBU = (0x24 << 26),
86 OPC_LHU = (0x25 << 26),
87 OPC_LWR = (0x26 << 26),
88 OPC_LWU = (0x27 << 26),
89 OPC_SB = (0x28 << 26),
90 OPC_SH = (0x29 << 26),
91 OPC_SWL = (0x2A << 26),
92 OPC_SW = (0x2B << 26),
93 OPC_SDL = (0x2C << 26),
94 OPC_SDR = (0x2D << 26),
95 OPC_SWR = (0x2E << 26),
96 OPC_LL = (0x30 << 26),
97 OPC_LLD = (0x34 << 26),
98 OPC_LD = (0x37 << 26),
99 OPC_LDPC = OPC_LD | 0x5,
100 OPC_SC = (0x38 << 26),
101 OPC_SCD = (0x3C << 26),
102 OPC_SD = (0x3F << 26),
103 /* Floating point load/store */
104 OPC_LWC1 = (0x31 << 26),
105 OPC_LWC2 = (0x32 << 26),
106 OPC_LDC1 = (0x35 << 26),
107 OPC_LDC2 = (0x36 << 26),
108 OPC_SWC1 = (0x39 << 26),
109 OPC_SWC2 = (0x3A << 26),
110 OPC_SDC1 = (0x3D << 26),
111 OPC_SDC2 = (0x3E << 26),
112 /* Compact Branches */
113 OPC_BLEZALC = (0x06 << 26),
114 OPC_BGEZALC = (0x06 << 26),
115 OPC_BGEUC = (0x06 << 26),
116 OPC_BGTZALC = (0x07 << 26),
117 OPC_BLTZALC = (0x07 << 26),
118 OPC_BLTUC = (0x07 << 26),
119 OPC_BOVC = (0x08 << 26),
120 OPC_BEQZALC = (0x08 << 26),
121 OPC_BEQC = (0x08 << 26),
122 OPC_BLEZC = (0x16 << 26),
123 OPC_BGEZC = (0x16 << 26),
124 OPC_BGEC = (0x16 << 26),
125 OPC_BGTZC = (0x17 << 26),
126 OPC_BLTZC = (0x17 << 26),
127 OPC_BLTC = (0x17 << 26),
128 OPC_BNVC = (0x18 << 26),
129 OPC_BNEZALC = (0x18 << 26),
130 OPC_BNEC = (0x18 << 26),
131 OPC_BC = (0x32 << 26),
132 OPC_BEQZC = (0x36 << 26),
133 OPC_JIC = (0x36 << 26),
134 OPC_BALC = (0x3A << 26),
135 OPC_BNEZC = (0x3E << 26),
136 OPC_JIALC = (0x3E << 26),
137 /* MDMX ASE specific */
138 OPC_MDMX = (0x1E << 26),
139 /* Cache and prefetch */
140 OPC_CACHE = (0x2F << 26),
141 OPC_PREF = (0x33 << 26),
142 /* PC-relative address computation / loads */
143 OPC_PCREL = (0x3B << 26),
146 /* PC-relative address computation / loads */
147 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
148 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
149 enum {
150 /* Instructions determined by bits 19 and 20 */
151 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
152 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
153 OPC_LWUPC = OPC_PCREL | (2 << 19),
155 /* Instructions determined by bits 16 ... 20 */
156 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
157 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
159 /* Other */
160 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
163 /* MIPS special opcodes */
164 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
166 enum {
167 /* Shifts */
168 OPC_SLL = 0x00 | OPC_SPECIAL,
169 /* NOP is SLL r0, r0, 0 */
170 /* SSNOP is SLL r0, r0, 1 */
171 /* EHB is SLL r0, r0, 3 */
172 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
173 OPC_ROTR = OPC_SRL | (1 << 21),
174 OPC_SRA = 0x03 | OPC_SPECIAL,
175 OPC_SLLV = 0x04 | OPC_SPECIAL,
176 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
177 OPC_ROTRV = OPC_SRLV | (1 << 6),
178 OPC_SRAV = 0x07 | OPC_SPECIAL,
179 OPC_DSLLV = 0x14 | OPC_SPECIAL,
180 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
181 OPC_DROTRV = OPC_DSRLV | (1 << 6),
182 OPC_DSRAV = 0x17 | OPC_SPECIAL,
183 OPC_DSLL = 0x38 | OPC_SPECIAL,
184 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
185 OPC_DROTR = OPC_DSRL | (1 << 21),
186 OPC_DSRA = 0x3B | OPC_SPECIAL,
187 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
188 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
189 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
190 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
191 /* Multiplication / division */
192 OPC_MULT = 0x18 | OPC_SPECIAL,
193 OPC_MULTU = 0x19 | OPC_SPECIAL,
194 OPC_DIV = 0x1A | OPC_SPECIAL,
195 OPC_DIVU = 0x1B | OPC_SPECIAL,
196 OPC_DMULT = 0x1C | OPC_SPECIAL,
197 OPC_DMULTU = 0x1D | OPC_SPECIAL,
198 OPC_DDIV = 0x1E | OPC_SPECIAL,
199 OPC_DDIVU = 0x1F | OPC_SPECIAL,
201 /* 2 registers arithmetic / logic */
202 OPC_ADD = 0x20 | OPC_SPECIAL,
203 OPC_ADDU = 0x21 | OPC_SPECIAL,
204 OPC_SUB = 0x22 | OPC_SPECIAL,
205 OPC_SUBU = 0x23 | OPC_SPECIAL,
206 OPC_AND = 0x24 | OPC_SPECIAL,
207 OPC_OR = 0x25 | OPC_SPECIAL,
208 OPC_XOR = 0x26 | OPC_SPECIAL,
209 OPC_NOR = 0x27 | OPC_SPECIAL,
210 OPC_SLT = 0x2A | OPC_SPECIAL,
211 OPC_SLTU = 0x2B | OPC_SPECIAL,
212 OPC_DADD = 0x2C | OPC_SPECIAL,
213 OPC_DADDU = 0x2D | OPC_SPECIAL,
214 OPC_DSUB = 0x2E | OPC_SPECIAL,
215 OPC_DSUBU = 0x2F | OPC_SPECIAL,
216 /* Jumps */
217 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
218 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
219 /* Traps */
220 OPC_TGE = 0x30 | OPC_SPECIAL,
221 OPC_TGEU = 0x31 | OPC_SPECIAL,
222 OPC_TLT = 0x32 | OPC_SPECIAL,
223 OPC_TLTU = 0x33 | OPC_SPECIAL,
224 OPC_TEQ = 0x34 | OPC_SPECIAL,
225 OPC_TNE = 0x36 | OPC_SPECIAL,
226 /* HI / LO registers load & stores */
227 OPC_MFHI = 0x10 | OPC_SPECIAL,
228 OPC_MTHI = 0x11 | OPC_SPECIAL,
229 OPC_MFLO = 0x12 | OPC_SPECIAL,
230 OPC_MTLO = 0x13 | OPC_SPECIAL,
231 /* Conditional moves */
232 OPC_MOVZ = 0x0A | OPC_SPECIAL,
233 OPC_MOVN = 0x0B | OPC_SPECIAL,
235 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
236 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
238 OPC_MOVCI = 0x01 | OPC_SPECIAL,
240 /* Special */
241 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
242 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
243 OPC_BREAK = 0x0D | OPC_SPECIAL,
244 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
245 OPC_SYNC = 0x0F | OPC_SPECIAL,
247 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
248 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
249 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
250 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
254 * R6 Multiply and Divide instructions have the same opcode
255 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
257 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
259 enum {
260 R6_OPC_MUL = OPC_MULT | (2 << 6),
261 R6_OPC_MUH = OPC_MULT | (3 << 6),
262 R6_OPC_MULU = OPC_MULTU | (2 << 6),
263 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
264 R6_OPC_DIV = OPC_DIV | (2 << 6),
265 R6_OPC_MOD = OPC_DIV | (3 << 6),
266 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
267 R6_OPC_MODU = OPC_DIVU | (3 << 6),
269 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
270 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
271 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
272 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
273 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
274 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
275 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
276 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
278 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
279 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
280 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
281 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
282 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
285 /* Multiplication variants of the vr54xx. */
286 #define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
288 enum {
289 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
290 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
291 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
292 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
293 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
294 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
295 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
296 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
297 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
298 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
299 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
300 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
301 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
302 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
305 /* REGIMM (rt field) opcodes */
306 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
308 enum {
309 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
310 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
311 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
312 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
313 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
314 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
315 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
316 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
317 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
318 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
319 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
320 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
321 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
322 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
323 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
324 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
326 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
327 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
330 /* Special2 opcodes */
331 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
333 enum {
334 /* Multiply & xxx operations */
335 OPC_MADD = 0x00 | OPC_SPECIAL2,
336 OPC_MADDU = 0x01 | OPC_SPECIAL2,
337 OPC_MUL = 0x02 | OPC_SPECIAL2,
338 OPC_MSUB = 0x04 | OPC_SPECIAL2,
339 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
340 /* Loongson 2F */
341 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
342 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
343 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
344 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
345 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
346 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
347 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
348 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
349 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
350 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
351 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
352 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
353 /* Misc */
354 OPC_CLZ = 0x20 | OPC_SPECIAL2,
355 OPC_CLO = 0x21 | OPC_SPECIAL2,
356 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
357 OPC_DCLO = 0x25 | OPC_SPECIAL2,
358 /* Special */
359 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
362 /* Special3 opcodes */
363 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
365 enum {
366 OPC_EXT = 0x00 | OPC_SPECIAL3,
367 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
368 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
369 OPC_DEXT = 0x03 | OPC_SPECIAL3,
370 OPC_INS = 0x04 | OPC_SPECIAL3,
371 OPC_DINSM = 0x05 | OPC_SPECIAL3,
372 OPC_DINSU = 0x06 | OPC_SPECIAL3,
373 OPC_DINS = 0x07 | OPC_SPECIAL3,
374 OPC_FORK = 0x08 | OPC_SPECIAL3,
375 OPC_YIELD = 0x09 | OPC_SPECIAL3,
376 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
377 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
378 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
379 OPC_GINV = 0x3D | OPC_SPECIAL3,
381 /* Loongson 2E */
382 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
383 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
384 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
385 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
386 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
387 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
388 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
389 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
390 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
391 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
392 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
393 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
395 /* MIPS DSP Load */
396 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
397 /* MIPS DSP Arithmetic */
398 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
399 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
400 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
401 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
402 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
403 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
404 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
405 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
406 /* MIPS DSP GPR-Based Shift Sub-class */
407 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
408 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
409 /* MIPS DSP Multiply Sub-class insns */
410 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
411 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
413 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
414 /* DSP Bit/Manipulation Sub-class */
415 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
416 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
417 /* MIPS DSP Append Sub-class */
418 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
419 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
420 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
421 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
422 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
424 /* EVA */
425 OPC_LWLE = 0x19 | OPC_SPECIAL3,
426 OPC_LWRE = 0x1A | OPC_SPECIAL3,
427 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
428 OPC_SBE = 0x1C | OPC_SPECIAL3,
429 OPC_SHE = 0x1D | OPC_SPECIAL3,
430 OPC_SCE = 0x1E | OPC_SPECIAL3,
431 OPC_SWE = 0x1F | OPC_SPECIAL3,
432 OPC_SWLE = 0x21 | OPC_SPECIAL3,
433 OPC_SWRE = 0x22 | OPC_SPECIAL3,
434 OPC_PREFE = 0x23 | OPC_SPECIAL3,
435 OPC_LBUE = 0x28 | OPC_SPECIAL3,
436 OPC_LHUE = 0x29 | OPC_SPECIAL3,
437 OPC_LBE = 0x2C | OPC_SPECIAL3,
438 OPC_LHE = 0x2D | OPC_SPECIAL3,
439 OPC_LLE = 0x2E | OPC_SPECIAL3,
440 OPC_LWE = 0x2F | OPC_SPECIAL3,
442 /* R6 */
443 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
444 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
445 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
446 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
447 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
448 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
451 /* Loongson EXT load/store quad word opcodes */
452 #define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
453 enum {
454 OPC_GSLQ = 0x0020 | OPC_LWC2,
455 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
456 OPC_GSSHFL = OPC_LWC2,
457 OPC_GSSQ = 0x0020 | OPC_SWC2,
458 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
459 OPC_GSSHFS = OPC_SWC2,
462 /* Loongson EXT shifted load/store opcodes */
463 #define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
464 enum {
465 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
466 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
467 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
468 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
469 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
470 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
471 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
472 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
475 /* Loongson EXT LDC2/SDC2 opcodes */
476 #define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
478 enum {
479 OPC_GSLBX = 0x0 | OPC_LDC2,
480 OPC_GSLHX = 0x1 | OPC_LDC2,
481 OPC_GSLWX = 0x2 | OPC_LDC2,
482 OPC_GSLDX = 0x3 | OPC_LDC2,
483 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
484 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
485 OPC_GSSBX = 0x0 | OPC_SDC2,
486 OPC_GSSHX = 0x1 | OPC_SDC2,
487 OPC_GSSWX = 0x2 | OPC_SDC2,
488 OPC_GSSDX = 0x3 | OPC_SDC2,
489 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
490 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
493 /* BSHFL opcodes */
494 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
496 enum {
497 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
498 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
499 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
500 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
501 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
502 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
503 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
504 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
507 /* DBSHFL opcodes */
508 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
510 enum {
511 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
512 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
513 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
514 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
515 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
516 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
517 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
518 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
519 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
520 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
521 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
524 /* MIPS DSP REGIMM opcodes */
525 enum {
526 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
527 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
530 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
531 /* MIPS DSP Load */
532 enum {
533 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
534 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
535 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
536 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
539 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
540 enum {
541 /* MIPS DSP Arithmetic Sub-class */
542 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
543 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
544 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
545 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
546 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
547 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
548 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
549 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
550 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
551 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
552 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
553 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
554 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
555 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
556 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
557 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
558 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
559 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
560 /* MIPS DSP Multiply Sub-class insns */
561 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
562 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
563 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
564 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
565 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
566 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
569 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
570 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
571 enum {
572 /* MIPS DSP Arithmetic Sub-class */
573 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
574 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
575 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
576 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
577 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
578 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
579 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
580 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
581 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
582 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
583 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
584 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
585 /* MIPS DSP Multiply Sub-class insns */
586 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
587 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
588 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
589 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
592 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
593 enum {
594 /* MIPS DSP Arithmetic Sub-class */
595 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
596 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
597 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
598 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
599 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
600 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
601 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
602 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
603 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
604 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
605 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
606 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
607 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
608 /* DSP Bit/Manipulation Sub-class */
609 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
610 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
611 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
612 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
613 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
616 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
617 enum {
618 /* MIPS DSP Arithmetic Sub-class */
619 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
620 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
621 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
622 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
623 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
624 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
625 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
626 /* DSP Compare-Pick Sub-class */
627 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
628 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
629 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
630 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
631 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
632 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
634 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
635 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
636 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
637 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
638 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
639 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
640 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
641 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
644 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
645 enum {
646 /* MIPS DSP GPR-Based Shift Sub-class */
647 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
648 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
649 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
650 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
651 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
652 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
653 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
654 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
655 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
656 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
657 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
658 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
659 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
660 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
661 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
662 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
663 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
664 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
665 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
666 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
667 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
668 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
671 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
672 enum {
673 /* MIPS DSP Multiply Sub-class insns */
674 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
675 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
676 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
677 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
678 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
679 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
680 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
681 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
682 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
683 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
684 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
685 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
686 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
687 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
688 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
689 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
690 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
691 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
692 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
693 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
694 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
695 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
698 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
699 enum {
700 /* DSP Bit/Manipulation Sub-class */
701 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
704 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
705 enum {
706 /* MIPS DSP Append Sub-class */
707 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
708 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
709 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
712 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
713 enum {
714 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
715 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
716 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
717 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
718 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
719 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
720 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
721 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
722 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
723 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
724 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
725 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
726 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
727 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
728 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
729 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
730 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
731 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
734 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
735 enum {
736 /* MIPS DSP Arithmetic Sub-class */
737 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
738 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
739 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
740 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
741 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
742 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
743 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
744 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
745 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
746 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
747 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
748 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
749 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
750 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
753 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
754 /* DSP Bit/Manipulation Sub-class */
755 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
756 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
757 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
758 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
759 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
760 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
763 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
764 enum {
765 /* MIPS DSP Multiply Sub-class insns */
766 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
767 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
768 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
769 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
770 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
771 /* MIPS DSP Arithmetic Sub-class */
772 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
773 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
774 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
775 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
776 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
777 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
778 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
779 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
780 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
781 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
782 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
783 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
784 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
785 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
786 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
787 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
788 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
789 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
790 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
791 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
792 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
795 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796 enum {
797 /* DSP Compare-Pick Sub-class */
798 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
799 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
800 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
801 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
802 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
803 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
804 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
805 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
806 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
807 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
808 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
809 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
810 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
811 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
817 /* MIPS DSP Arithmetic Sub-class */
818 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
819 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
820 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
821 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
822 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
823 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
824 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
825 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
828 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
829 enum {
830 /* DSP Append Sub-class */
831 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
832 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
833 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
834 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
837 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
838 enum {
839 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
840 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
841 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
842 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
843 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
844 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
845 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
846 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
847 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
848 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
849 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
850 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
851 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
852 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
853 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
854 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
855 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
856 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
857 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
858 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
859 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
860 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
863 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
864 enum {
865 /* DSP Bit/Manipulation Sub-class */
866 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
869 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
870 enum {
871 /* MIPS DSP Multiply Sub-class insns */
872 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
873 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
874 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
875 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
876 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
877 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
878 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
879 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
880 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
881 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
882 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
883 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
884 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
885 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
890 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
891 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
892 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
893 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
894 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
895 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
896 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
897 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
900 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
901 enum {
902 /* MIPS DSP GPR-Based Shift Sub-class */
903 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
904 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
905 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
906 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
907 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
908 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
909 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
910 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
911 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
912 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
913 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
914 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
915 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
916 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
921 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
922 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
923 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
924 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
925 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
926 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
927 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
928 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
931 /* Coprocessor 0 (rs field) */
932 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
934 enum {
935 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
936 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
937 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
938 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
939 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
940 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
941 OPC_MFTR = (0x08 << 21) | OPC_CP0,
942 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
943 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
944 OPC_MTTR = (0x0C << 21) | OPC_CP0,
945 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
946 OPC_C0 = (0x10 << 21) | OPC_CP0,
947 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
948 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
949 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
950 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
951 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
952 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
953 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
954 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
955 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
956 OPC_C0_A = (0x1A << 21) | OPC_CP0,
957 OPC_C0_B = (0x1B << 21) | OPC_CP0,
958 OPC_C0_C = (0x1C << 21) | OPC_CP0,
959 OPC_C0_D = (0x1D << 21) | OPC_CP0,
960 OPC_C0_E = (0x1E << 21) | OPC_CP0,
961 OPC_C0_F = (0x1F << 21) | OPC_CP0,
964 /* MFMC0 opcodes */
965 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
967 enum {
968 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
969 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
970 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
971 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
972 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
973 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
974 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
975 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
978 /* Coprocessor 0 (with rs == C0) */
979 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
981 enum {
982 OPC_TLBR = 0x01 | OPC_C0,
983 OPC_TLBWI = 0x02 | OPC_C0,
984 OPC_TLBINV = 0x03 | OPC_C0,
985 OPC_TLBINVF = 0x04 | OPC_C0,
986 OPC_TLBWR = 0x06 | OPC_C0,
987 OPC_TLBP = 0x08 | OPC_C0,
988 OPC_RFE = 0x10 | OPC_C0,
989 OPC_ERET = 0x18 | OPC_C0,
990 OPC_DERET = 0x1F | OPC_C0,
991 OPC_WAIT = 0x20 | OPC_C0,
994 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
996 enum {
997 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
998 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
999 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1000 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1001 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1002 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1003 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1004 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1005 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1006 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1007 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1010 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1012 enum {
1013 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1014 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1015 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1016 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1017 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1018 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1019 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1020 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1022 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1023 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1024 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1025 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1026 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1027 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1028 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1029 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1031 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1032 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1033 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1034 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1035 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1036 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1037 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1038 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1040 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1041 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1042 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1043 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1044 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1045 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1046 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1047 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1049 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1050 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1051 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1052 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1053 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1054 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1056 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1057 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1058 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1059 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1060 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1061 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1063 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1064 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1065 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1066 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1067 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1068 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1070 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1071 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1072 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1073 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1074 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1075 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1077 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1078 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1079 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1080 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1081 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1082 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1084 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1085 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1086 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1087 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1088 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1089 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1091 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1092 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1093 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1094 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1095 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1096 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1098 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1099 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1100 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1101 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1102 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1103 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1107 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1109 enum {
1110 OPC_LWXC1 = 0x00 | OPC_CP3,
1111 OPC_LDXC1 = 0x01 | OPC_CP3,
1112 OPC_LUXC1 = 0x05 | OPC_CP3,
1113 OPC_SWXC1 = 0x08 | OPC_CP3,
1114 OPC_SDXC1 = 0x09 | OPC_CP3,
1115 OPC_SUXC1 = 0x0D | OPC_CP3,
1116 OPC_PREFX = 0x0F | OPC_CP3,
1117 OPC_ALNV_PS = 0x1E | OPC_CP3,
1118 OPC_MADD_S = 0x20 | OPC_CP3,
1119 OPC_MADD_D = 0x21 | OPC_CP3,
1120 OPC_MADD_PS = 0x26 | OPC_CP3,
1121 OPC_MSUB_S = 0x28 | OPC_CP3,
1122 OPC_MSUB_D = 0x29 | OPC_CP3,
1123 OPC_MSUB_PS = 0x2E | OPC_CP3,
1124 OPC_NMADD_S = 0x30 | OPC_CP3,
1125 OPC_NMADD_D = 0x31 | OPC_CP3,
1126 OPC_NMADD_PS = 0x36 | OPC_CP3,
1127 OPC_NMSUB_S = 0x38 | OPC_CP3,
1128 OPC_NMSUB_D = 0x39 | OPC_CP3,
1129 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1133 * Overview of the TX79-specific instruction set
1134 * =============================================
1136 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
1137 * are only used by the specific quadword (128-bit) LQ/SQ load/store
1138 * instructions and certain multimedia instructions (MMIs). These MMIs
1139 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
1140 * or sixteen 8-bit paths.
1142 * Reference:
1144 * The Toshiba TX System RISC TX79 Core Architecture manual,
1145 * https://wiki.qemu.org/File:C790.pdf
1147 * Three-Operand Multiply and Multiply-Add (4 instructions)
1148 * --------------------------------------------------------
1149 * MADD [rd,] rs, rt Multiply/Add
1150 * MADDU [rd,] rs, rt Multiply/Add Unsigned
1151 * MULT [rd,] rs, rt Multiply (3-operand)
1152 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
1154 * Multiply Instructions for Pipeline 1 (10 instructions)
1155 * ------------------------------------------------------
1156 * MULT1 [rd,] rs, rt Multiply Pipeline 1
1157 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
1158 * DIV1 rs, rt Divide Pipeline 1
1159 * DIVU1 rs, rt Divide Unsigned Pipeline 1
1160 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
1161 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
1162 * MFHI1 rd Move From HI1 Register
1163 * MFLO1 rd Move From LO1 Register
1164 * MTHI1 rs Move To HI1 Register
1165 * MTLO1 rs Move To LO1 Register
1167 * Arithmetic (19 instructions)
1168 * ----------------------------
1169 * PADDB rd, rs, rt Parallel Add Byte
1170 * PSUBB rd, rs, rt Parallel Subtract Byte
1171 * PADDH rd, rs, rt Parallel Add Halfword
1172 * PSUBH rd, rs, rt Parallel Subtract Halfword
1173 * PADDW rd, rs, rt Parallel Add Word
1174 * PSUBW rd, rs, rt Parallel Subtract Word
1175 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
1176 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
1177 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
1178 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
1179 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
1180 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
1181 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
1182 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
1183 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
1184 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
1185 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
1186 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
1187 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
1189 * Min/Max (4 instructions)
1190 * ------------------------
1191 * PMAXH rd, rs, rt Parallel Maximum Halfword
1192 * PMINH rd, rs, rt Parallel Minimum Halfword
1193 * PMAXW rd, rs, rt Parallel Maximum Word
1194 * PMINW rd, rs, rt Parallel Minimum Word
1196 * Absolute (2 instructions)
1197 * -------------------------
1198 * PABSH rd, rt Parallel Absolute Halfword
1199 * PABSW rd, rt Parallel Absolute Word
1201 * Logical (4 instructions)
1202 * ------------------------
1203 * PAND rd, rs, rt Parallel AND
1204 * POR rd, rs, rt Parallel OR
1205 * PXOR rd, rs, rt Parallel XOR
1206 * PNOR rd, rs, rt Parallel NOR
1208 * Shift (9 instructions)
1209 * ----------------------
1210 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
1211 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
1212 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
1213 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
1214 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
1215 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
1216 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
1217 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
1218 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
1220 * Compare (6 instructions)
1221 * ------------------------
1222 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
1223 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
1224 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
1225 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
1226 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
1227 * PCEQW rd, rs, rt Parallel Compare for Equal Word
1229 * LZC (1 instruction)
1230 * -------------------
1231 * PLZCW rd, rs Parallel Leading Zero or One Count Word
1233 * Quadword Load and Store (2 instructions)
1234 * ----------------------------------------
1235 * LQ rt, offset(base) Load Quadword
1236 * SQ rt, offset(base) Store Quadword
1238 * Multiply and Divide (19 instructions)
1239 * -------------------------------------
1240 * PMULTW rd, rs, rt Parallel Multiply Word
1241 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
1242 * PDIVW rs, rt Parallel Divide Word
1243 * PDIVUW rs, rt Parallel Divide Unsigned Word
1244 * PMADDW rd, rs, rt Parallel Multiply-Add Word
1245 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
1246 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
1247 * PMULTH rd, rs, rt Parallel Multiply Halfword
1248 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
1249 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
1250 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
1251 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
1252 * PDIVBW rs, rt Parallel Divide Broadcast Word
1253 * PMFHI rd Parallel Move From HI Register
1254 * PMFLO rd Parallel Move From LO Register
1255 * PMTHI rs Parallel Move To HI Register
1256 * PMTLO rs Parallel Move To LO Register
1257 * PMFHL rd Parallel Move From HI/LO Register
1258 * PMTHL rs Parallel Move To HI/LO Register
1260 * Pack/Extend (11 instructions)
1261 * -----------------------------
1262 * PPAC5 rd, rt Parallel Pack to 5 bits
1263 * PPACB rd, rs, rt Parallel Pack to Byte
1264 * PPACH rd, rs, rt Parallel Pack to Halfword
1265 * PPACW rd, rs, rt Parallel Pack to Word
1266 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
1267 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
1268 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
1269 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
1270 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
1271 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
1272 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
1274 * Others (16 instructions)
1275 * ------------------------
1276 * PCPYH rd, rt Parallel Copy Halfword
1277 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
1278 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
1279 * PREVH rd, rt Parallel Reverse Halfword
1280 * PINTH rd, rs, rt Parallel Interleave Halfword
1281 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
1282 * PEXEH rd, rt Parallel Exchange Even Halfword
1283 * PEXCH rd, rt Parallel Exchange Center Halfword
1284 * PEXEW rd, rt Parallel Exchange Even Word
1285 * PEXCW rd, rt Parallel Exchange Center Word
1286 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
1287 * MFSA rd Move from Shift Amount Register
1288 * MTSA rs Move to Shift Amount Register
1289 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
1290 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
1291 * PROT3W rd, rt Parallel Rotate 3 Words
1293 * MMI (MultiMedia Instruction) encodings
1294 * ======================================
1296 * MMI instructions encoding table keys:
1298 * * This code is reserved for future use. An attempt to execute it
1299 * causes a Reserved Instruction exception.
1300 * % This code indicates an instruction class. The instruction word
1301 * must be further decoded by examining additional tables that show
1302 * the values for other instruction fields.
1303 * # This code is reserved for the unsupported instructions DMULT,
1304 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
1305 * to execute it causes a Reserved Instruction exception.
1307 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
1309 * 31 26 0
1310 * +--------+----------------------------------------+
1311 * | opcode | |
1312 * +--------+----------------------------------------+
1314 * opcode bits 28..26
1315 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1316 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1317 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1318 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
1319 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
1320 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
1321 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
1322 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
1323 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
1324 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
1325 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
1328 enum {
1329 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
1330 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
1331 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
1335 * MMI instructions with opcode field = MMI:
1337 * 31 26 5 0
1338 * +--------+-------------------------------+--------+
1339 * | MMI | |function|
1340 * +--------+-------------------------------+--------+
1342 * function bits 2..0
1343 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1344 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1345 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1346 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
1347 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
1348 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
1349 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
1350 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
1351 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
1352 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
1353 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
1356 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
1357 enum {
1358 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
1359 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
1360 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
1361 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
1362 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
1363 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
1364 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
1365 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
1368 /* global register indices */
1369 TCGv cpu_gpr[32], cpu_PC;
1371 * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[])
1372 * and the upper halves in cpu_gpr_hi[].
1374 TCGv_i64 cpu_gpr_hi[32];
1375 TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1376 static TCGv cpu_dspctrl, btarget;
1377 TCGv bcond;
1378 static TCGv cpu_lladdr, cpu_llval;
1379 static TCGv_i32 hflags;
1380 TCGv_i32 fpu_fcr0, fpu_fcr31;
1381 TCGv_i64 fpu_f64[32];
1383 #include "exec/gen-icount.h"
1385 #define gen_helper_0e0i(name, arg) do { \
1386 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1387 gen_helper_##name(cpu_env, helper_tmp); \
1388 tcg_temp_free_i32(helper_tmp); \
1389 } while (0)
1391 #define gen_helper_0e1i(name, arg1, arg2) do { \
1392 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1393 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1394 tcg_temp_free_i32(helper_tmp); \
1395 } while (0)
1397 #define gen_helper_1e0i(name, ret, arg1) do { \
1398 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1399 gen_helper_##name(ret, cpu_env, helper_tmp); \
1400 tcg_temp_free_i32(helper_tmp); \
1401 } while (0)
1403 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1404 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1405 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1406 tcg_temp_free_i32(helper_tmp); \
1407 } while (0)
1409 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1410 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1411 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1412 tcg_temp_free_i32(helper_tmp); \
1413 } while (0)
1415 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1416 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1417 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1418 tcg_temp_free_i32(helper_tmp); \
1419 } while (0)
1421 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1422 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1423 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1424 tcg_temp_free_i32(helper_tmp); \
1425 } while (0)
1427 #define DISAS_STOP DISAS_TARGET_0
1428 #define DISAS_EXIT DISAS_TARGET_1
1430 static const char * const regnames[] = {
1431 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1432 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1433 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1434 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1437 static const char * const regnames_HI[] = {
1438 "HI0", "HI1", "HI2", "HI3",
1441 static const char * const regnames_LO[] = {
1442 "LO0", "LO1", "LO2", "LO3",
1445 static const char * const fregnames[] = {
1446 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1447 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1448 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1449 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1452 /* General purpose registers moves. */
1453 void gen_load_gpr(TCGv t, int reg)
1455 if (reg == 0) {
1456 tcg_gen_movi_tl(t, 0);
1457 } else {
1458 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1462 void gen_store_gpr(TCGv t, int reg)
1464 if (reg != 0) {
1465 tcg_gen_mov_tl(cpu_gpr[reg], t);
1469 #if defined(TARGET_MIPS64)
1470 void gen_load_gpr_hi(TCGv_i64 t, int reg)
1472 if (reg == 0) {
1473 tcg_gen_movi_i64(t, 0);
1474 } else {
1475 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
1479 void gen_store_gpr_hi(TCGv_i64 t, int reg)
1481 if (reg != 0) {
1482 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
1485 #endif /* TARGET_MIPS64 */
1487 /* Moves to/from shadow registers. */
1488 static inline void gen_load_srsgpr(int from, int to)
1490 TCGv t0 = tcg_temp_new();
1492 if (from == 0) {
1493 tcg_gen_movi_tl(t0, 0);
1494 } else {
1495 TCGv_i32 t2 = tcg_temp_new_i32();
1496 TCGv_ptr addr = tcg_temp_new_ptr();
1498 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1499 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1500 tcg_gen_andi_i32(t2, t2, 0xf);
1501 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1502 tcg_gen_ext_i32_ptr(addr, t2);
1503 tcg_gen_add_ptr(addr, cpu_env, addr);
1505 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1506 tcg_temp_free_ptr(addr);
1507 tcg_temp_free_i32(t2);
1509 gen_store_gpr(t0, to);
1510 tcg_temp_free(t0);
1513 static inline void gen_store_srsgpr(int from, int to)
1515 if (to != 0) {
1516 TCGv t0 = tcg_temp_new();
1517 TCGv_i32 t2 = tcg_temp_new_i32();
1518 TCGv_ptr addr = tcg_temp_new_ptr();
1520 gen_load_gpr(t0, from);
1521 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1522 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1523 tcg_gen_andi_i32(t2, t2, 0xf);
1524 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1525 tcg_gen_ext_i32_ptr(addr, t2);
1526 tcg_gen_add_ptr(addr, cpu_env, addr);
1528 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1529 tcg_temp_free_ptr(addr);
1530 tcg_temp_free_i32(t2);
1531 tcg_temp_free(t0);
1535 /* Tests */
1536 static inline void gen_save_pc(target_ulong pc)
1538 tcg_gen_movi_tl(cpu_PC, pc);
1541 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1543 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1544 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1545 gen_save_pc(ctx->base.pc_next);
1546 ctx->saved_pc = ctx->base.pc_next;
1548 if (ctx->hflags != ctx->saved_hflags) {
1549 tcg_gen_movi_i32(hflags, ctx->hflags);
1550 ctx->saved_hflags = ctx->hflags;
1551 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1552 case MIPS_HFLAG_BR:
1553 break;
1554 case MIPS_HFLAG_BC:
1555 case MIPS_HFLAG_BL:
1556 case MIPS_HFLAG_B:
1557 tcg_gen_movi_tl(btarget, ctx->btarget);
1558 break;
1563 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1565 ctx->saved_hflags = ctx->hflags;
1566 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1567 case MIPS_HFLAG_BR:
1568 break;
1569 case MIPS_HFLAG_BC:
1570 case MIPS_HFLAG_BL:
1571 case MIPS_HFLAG_B:
1572 ctx->btarget = env->btarget;
1573 break;
1577 void generate_exception_err(DisasContext *ctx, int excp, int err)
1579 TCGv_i32 texcp = tcg_const_i32(excp);
1580 TCGv_i32 terr = tcg_const_i32(err);
1581 save_cpu_state(ctx, 1);
1582 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1583 tcg_temp_free_i32(terr);
1584 tcg_temp_free_i32(texcp);
1585 ctx->base.is_jmp = DISAS_NORETURN;
1588 void generate_exception(DisasContext *ctx, int excp)
1590 gen_helper_0e0i(raise_exception, excp);
1593 void generate_exception_end(DisasContext *ctx, int excp)
1595 generate_exception_err(ctx, excp, 0);
1598 void gen_reserved_instruction(DisasContext *ctx)
1600 generate_exception_end(ctx, EXCP_RI);
1603 /* Floating point register moves. */
1604 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1606 if (ctx->hflags & MIPS_HFLAG_FRE) {
1607 generate_exception(ctx, EXCP_RI);
1609 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1612 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1614 TCGv_i64 t64;
1615 if (ctx->hflags & MIPS_HFLAG_FRE) {
1616 generate_exception(ctx, EXCP_RI);
1618 t64 = tcg_temp_new_i64();
1619 tcg_gen_extu_i32_i64(t64, t);
1620 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1621 tcg_temp_free_i64(t64);
1624 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1626 if (ctx->hflags & MIPS_HFLAG_F64) {
1627 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1628 } else {
1629 gen_load_fpr32(ctx, t, reg | 1);
1633 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1635 if (ctx->hflags & MIPS_HFLAG_F64) {
1636 TCGv_i64 t64 = tcg_temp_new_i64();
1637 tcg_gen_extu_i32_i64(t64, t);
1638 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1639 tcg_temp_free_i64(t64);
1640 } else {
1641 gen_store_fpr32(ctx, t, reg | 1);
1645 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1647 if (ctx->hflags & MIPS_HFLAG_F64) {
1648 tcg_gen_mov_i64(t, fpu_f64[reg]);
1649 } else {
1650 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1654 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1656 if (ctx->hflags & MIPS_HFLAG_F64) {
1657 tcg_gen_mov_i64(fpu_f64[reg], t);
1658 } else {
1659 TCGv_i64 t0;
1660 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1661 t0 = tcg_temp_new_i64();
1662 tcg_gen_shri_i64(t0, t, 32);
1663 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1664 tcg_temp_free_i64(t0);
1668 int get_fp_bit(int cc)
1670 if (cc) {
1671 return 24 + cc;
1672 } else {
1673 return 23;
1677 /* Addresses computation */
1678 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1680 tcg_gen_add_tl(ret, arg0, arg1);
1682 #if defined(TARGET_MIPS64)
1683 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1684 tcg_gen_ext32s_i64(ret, ret);
1686 #endif
1689 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
1690 target_long ofs)
1692 tcg_gen_addi_tl(ret, base, ofs);
1694 #if defined(TARGET_MIPS64)
1695 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1696 tcg_gen_ext32s_i64(ret, ret);
1698 #endif
1701 /* Addresses computation (translation time) */
1702 static target_long addr_add(DisasContext *ctx, target_long base,
1703 target_long offset)
1705 target_long sum = base + offset;
1707 #if defined(TARGET_MIPS64)
1708 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1709 sum = (int32_t)sum;
1711 #endif
1712 return sum;
1715 /* Sign-extract the low 32-bits to a target_long. */
1716 void gen_move_low32(TCGv ret, TCGv_i64 arg)
1718 #if defined(TARGET_MIPS64)
1719 tcg_gen_ext32s_i64(ret, arg);
1720 #else
1721 tcg_gen_extrl_i64_i32(ret, arg);
1722 #endif
1725 /* Sign-extract the high 32-bits to a target_long. */
1726 void gen_move_high32(TCGv ret, TCGv_i64 arg)
1728 #if defined(TARGET_MIPS64)
1729 tcg_gen_sari_i64(ret, arg, 32);
1730 #else
1731 tcg_gen_extrh_i64_i32(ret, arg);
1732 #endif
1735 void check_cp0_enabled(DisasContext *ctx)
1737 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1738 generate_exception_end(ctx, EXCP_CpU);
1742 void check_cp1_enabled(DisasContext *ctx)
1744 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
1745 generate_exception_err(ctx, EXCP_CpU, 1);
1750 * Verify that the processor is running with COP1X instructions enabled.
1751 * This is associated with the nabla symbol in the MIPS32 and MIPS64
1752 * opcode tables.
1754 void check_cop1x(DisasContext *ctx)
1756 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
1757 gen_reserved_instruction(ctx);
1762 * Verify that the processor is running with 64-bit floating-point
1763 * operations enabled.
1765 void check_cp1_64bitmode(DisasContext *ctx)
1767 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
1768 gen_reserved_instruction(ctx);
1773 * Verify if floating point register is valid; an operation is not defined
1774 * if bit 0 of any register specification is set and the FR bit in the
1775 * Status register equals zero, since the register numbers specify an
1776 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1777 * in the Status register equals one, both even and odd register numbers
1778 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1780 * Multiple 64 bit wide registers can be checked by calling
1781 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1783 void check_cp1_registers(DisasContext *ctx, int regs)
1785 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
1786 gen_reserved_instruction(ctx);
1791 * Verify that the processor is running with DSP instructions enabled.
1792 * This is enabled by CP0 Status register MX(24) bit.
1794 static inline void check_dsp(DisasContext *ctx)
1796 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1797 if (ctx->insn_flags & ASE_DSP) {
1798 generate_exception_end(ctx, EXCP_DSPDIS);
1799 } else {
1800 gen_reserved_instruction(ctx);
1805 static inline void check_dsp_r2(DisasContext *ctx)
1807 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
1808 if (ctx->insn_flags & ASE_DSP) {
1809 generate_exception_end(ctx, EXCP_DSPDIS);
1810 } else {
1811 gen_reserved_instruction(ctx);
1816 static inline void check_dsp_r3(DisasContext *ctx)
1818 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
1819 if (ctx->insn_flags & ASE_DSP) {
1820 generate_exception_end(ctx, EXCP_DSPDIS);
1821 } else {
1822 gen_reserved_instruction(ctx);
1828 * This code generates a "reserved instruction" exception if the
1829 * CPU does not support the instruction set corresponding to flags.
1831 void check_insn(DisasContext *ctx, uint64_t flags)
1833 if (unlikely(!(ctx->insn_flags & flags))) {
1834 gen_reserved_instruction(ctx);
1839 * This code generates a "reserved instruction" exception if the
1840 * CPU has corresponding flag set which indicates that the instruction
1841 * has been removed.
1843 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
1845 if (unlikely(ctx->insn_flags & flags)) {
1846 gen_reserved_instruction(ctx);
1851 * The Linux kernel traps certain reserved instruction exceptions to
1852 * emulate the corresponding instructions. QEMU is the kernel in user
1853 * mode, so those traps are emulated by accepting the instructions.
1855 * A reserved instruction exception is generated for flagged CPUs if
1856 * QEMU runs in system mode.
1858 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
1860 #ifndef CONFIG_USER_ONLY
1861 check_insn_opc_removed(ctx, flags);
1862 #endif
1866 * This code generates a "reserved instruction" exception if the
1867 * CPU does not support 64-bit paired-single (PS) floating point data type.
1869 static inline void check_ps(DisasContext *ctx)
1871 if (unlikely(!ctx->ps)) {
1872 generate_exception(ctx, EXCP_RI);
1874 check_cp1_64bitmode(ctx);
1878 * This code generates a "reserved instruction" exception if cpu is not
1879 * 64-bit or 64-bit instructions are not enabled.
1881 void check_mips_64(DisasContext *ctx)
1883 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
1884 gen_reserved_instruction(ctx);
1888 #ifndef CONFIG_USER_ONLY
1889 static inline void check_mvh(DisasContext *ctx)
1891 if (unlikely(!ctx->mvh)) {
1892 generate_exception(ctx, EXCP_RI);
1895 #endif
1898 * This code generates a "reserved instruction" exception if the
1899 * Config5 XNP bit is set.
1901 static inline void check_xnp(DisasContext *ctx)
1903 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
1904 gen_reserved_instruction(ctx);
1908 #ifndef CONFIG_USER_ONLY
1910 * This code generates a "reserved instruction" exception if the
1911 * Config3 PW bit is NOT set.
1913 static inline void check_pw(DisasContext *ctx)
1915 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
1916 gen_reserved_instruction(ctx);
1919 #endif
1922 * This code generates a "reserved instruction" exception if the
1923 * Config3 MT bit is NOT set.
1925 static inline void check_mt(DisasContext *ctx)
1927 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1928 gen_reserved_instruction(ctx);
1932 #ifndef CONFIG_USER_ONLY
1934 * This code generates a "coprocessor unusable" exception if CP0 is not
1935 * available, and, if that is not the case, generates a "reserved instruction"
1936 * exception if the Config5 MT bit is NOT set. This is needed for availability
1937 * control of some of MT ASE instructions.
1939 static inline void check_cp0_mt(DisasContext *ctx)
1941 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1942 generate_exception_end(ctx, EXCP_CpU);
1943 } else {
1944 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1945 gen_reserved_instruction(ctx);
1949 #endif
1952 * This code generates a "reserved instruction" exception if the
1953 * Config5 NMS bit is set.
1955 static inline void check_nms(DisasContext *ctx)
1957 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
1958 gen_reserved_instruction(ctx);
1963 * This code generates a "reserved instruction" exception if the
1964 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
1965 * Config2 TL, and Config5 L2C are unset.
1967 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
1969 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
1970 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
1971 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
1972 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
1973 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
1974 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
1975 gen_reserved_instruction(ctx);
1980 * This code generates a "reserved instruction" exception if the
1981 * Config5 EVA bit is NOT set.
1983 static inline void check_eva(DisasContext *ctx)
1985 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
1986 gen_reserved_instruction(ctx);
1992 * Define small wrappers for gen_load_fpr* so that we have a uniform
1993 * calling interface for 32 and 64-bit FPRs. No sense in changing
1994 * all callers for gen_load_fpr32 when we need the CTX parameter for
1995 * this one use.
1997 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1998 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1999 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
2000 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
2001 int ft, int fs, int cc) \
2003 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
2004 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
2005 switch (ifmt) { \
2006 case FMT_PS: \
2007 check_ps(ctx); \
2008 break; \
2009 case FMT_D: \
2010 if (abs) { \
2011 check_cop1x(ctx); \
2013 check_cp1_registers(ctx, fs | ft); \
2014 break; \
2015 case FMT_S: \
2016 if (abs) { \
2017 check_cop1x(ctx); \
2019 break; \
2021 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
2022 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
2023 switch (n) { \
2024 case 0: \
2025 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
2026 break; \
2027 case 1: \
2028 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
2029 break; \
2030 case 2: \
2031 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
2032 break; \
2033 case 3: \
2034 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
2035 break; \
2036 case 4: \
2037 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
2038 break; \
2039 case 5: \
2040 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
2041 break; \
2042 case 6: \
2043 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
2044 break; \
2045 case 7: \
2046 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
2047 break; \
2048 case 8: \
2049 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
2050 break; \
2051 case 9: \
2052 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
2053 break; \
2054 case 10: \
2055 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
2056 break; \
2057 case 11: \
2058 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
2059 break; \
2060 case 12: \
2061 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
2062 break; \
2063 case 13: \
2064 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
2065 break; \
2066 case 14: \
2067 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
2068 break; \
2069 case 15: \
2070 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
2071 break; \
2072 default: \
2073 abort(); \
2075 tcg_temp_free_i##bits(fp0); \
2076 tcg_temp_free_i##bits(fp1); \
2079 FOP_CONDS(, 0, d, FMT_D, 64)
2080 FOP_CONDS(abs, 1, d, FMT_D, 64)
2081 FOP_CONDS(, 0, s, FMT_S, 32)
2082 FOP_CONDS(abs, 1, s, FMT_S, 32)
2083 FOP_CONDS(, 0, ps, FMT_PS, 64)
2084 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
2085 #undef FOP_CONDS
2087 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
2088 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
2089 int ft, int fs, int fd) \
2091 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
2092 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
2093 if (ifmt == FMT_D) { \
2094 check_cp1_registers(ctx, fs | ft | fd); \
2096 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
2097 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
2098 switch (n) { \
2099 case 0: \
2100 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
2101 break; \
2102 case 1: \
2103 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
2104 break; \
2105 case 2: \
2106 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
2107 break; \
2108 case 3: \
2109 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
2110 break; \
2111 case 4: \
2112 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
2113 break; \
2114 case 5: \
2115 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
2116 break; \
2117 case 6: \
2118 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
2119 break; \
2120 case 7: \
2121 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
2122 break; \
2123 case 8: \
2124 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
2125 break; \
2126 case 9: \
2127 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
2128 break; \
2129 case 10: \
2130 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2131 break; \
2132 case 11: \
2133 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2134 break; \
2135 case 12: \
2136 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2137 break; \
2138 case 13: \
2139 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2140 break; \
2141 case 14: \
2142 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
2143 break; \
2144 case 15: \
2145 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
2146 break; \
2147 case 17: \
2148 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
2149 break; \
2150 case 18: \
2151 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2152 break; \
2153 case 19: \
2154 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2155 break; \
2156 case 25: \
2157 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2158 break; \
2159 case 26: \
2160 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2161 break; \
2162 case 27: \
2163 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2164 break; \
2165 default: \
2166 abort(); \
2168 STORE; \
2169 tcg_temp_free_i ## bits(fp0); \
2170 tcg_temp_free_i ## bits(fp1); \
2173 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2174 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2175 #undef FOP_CONDNS
2176 #undef gen_ldcmp_fpr32
2177 #undef gen_ldcmp_fpr64
2179 /* load/store instructions. */
2180 #ifdef CONFIG_USER_ONLY
2181 #define OP_LD_ATOMIC(insn, fname) \
2182 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2183 DisasContext *ctx) \
2185 TCGv t0 = tcg_temp_new(); \
2186 tcg_gen_mov_tl(t0, arg1); \
2187 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2188 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2189 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2190 tcg_temp_free(t0); \
2192 #else
2193 #define OP_LD_ATOMIC(insn, fname) \
2194 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2195 DisasContext *ctx) \
2197 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2199 #endif
2200 OP_LD_ATOMIC(ll, ld32s);
2201 #if defined(TARGET_MIPS64)
2202 OP_LD_ATOMIC(lld, ld64);
2203 #endif
2204 #undef OP_LD_ATOMIC
2206 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
2208 if (base == 0) {
2209 tcg_gen_movi_tl(addr, offset);
2210 } else if (offset == 0) {
2211 gen_load_gpr(addr, base);
2212 } else {
2213 tcg_gen_movi_tl(addr, offset);
2214 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2218 static target_ulong pc_relative_pc(DisasContext *ctx)
2220 target_ulong pc = ctx->base.pc_next;
2222 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2223 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2225 pc -= branch_bytes;
2228 pc &= ~(target_ulong)3;
2229 return pc;
2232 /* Load */
2233 static void gen_ld(DisasContext *ctx, uint32_t opc,
2234 int rt, int base, int offset)
2236 TCGv t0, t1, t2;
2237 int mem_idx = ctx->mem_idx;
2239 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
2240 INSN_LOONGSON3A)) {
2242 * Loongson CPU uses a load to zero register for prefetch.
2243 * We emulate it as a NOP. On other CPU we must perform the
2244 * actual memory access.
2246 return;
2249 t0 = tcg_temp_new();
2250 gen_base_offset_addr(ctx, t0, base, offset);
2252 switch (opc) {
2253 #if defined(TARGET_MIPS64)
2254 case OPC_LWU:
2255 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
2256 ctx->default_tcg_memop_mask);
2257 gen_store_gpr(t0, rt);
2258 break;
2259 case OPC_LD:
2260 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
2261 ctx->default_tcg_memop_mask);
2262 gen_store_gpr(t0, rt);
2263 break;
2264 case OPC_LLD:
2265 case R6_OPC_LLD:
2266 op_ld_lld(t0, t0, mem_idx, ctx);
2267 gen_store_gpr(t0, rt);
2268 break;
2269 case OPC_LDL:
2270 t1 = tcg_temp_new();
2272 * Do a byte access to possibly trigger a page
2273 * fault with the unaligned address.
2275 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2276 tcg_gen_andi_tl(t1, t0, 7);
2277 #ifndef TARGET_WORDS_BIGENDIAN
2278 tcg_gen_xori_tl(t1, t1, 7);
2279 #endif
2280 tcg_gen_shli_tl(t1, t1, 3);
2281 tcg_gen_andi_tl(t0, t0, ~7);
2282 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2283 tcg_gen_shl_tl(t0, t0, t1);
2284 t2 = tcg_const_tl(-1);
2285 tcg_gen_shl_tl(t2, t2, t1);
2286 gen_load_gpr(t1, rt);
2287 tcg_gen_andc_tl(t1, t1, t2);
2288 tcg_temp_free(t2);
2289 tcg_gen_or_tl(t0, t0, t1);
2290 tcg_temp_free(t1);
2291 gen_store_gpr(t0, rt);
2292 break;
2293 case OPC_LDR:
2294 t1 = tcg_temp_new();
2296 * Do a byte access to possibly trigger a page
2297 * fault with the unaligned address.
2299 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2300 tcg_gen_andi_tl(t1, t0, 7);
2301 #ifdef TARGET_WORDS_BIGENDIAN
2302 tcg_gen_xori_tl(t1, t1, 7);
2303 #endif
2304 tcg_gen_shli_tl(t1, t1, 3);
2305 tcg_gen_andi_tl(t0, t0, ~7);
2306 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2307 tcg_gen_shr_tl(t0, t0, t1);
2308 tcg_gen_xori_tl(t1, t1, 63);
2309 t2 = tcg_const_tl(0xfffffffffffffffeull);
2310 tcg_gen_shl_tl(t2, t2, t1);
2311 gen_load_gpr(t1, rt);
2312 tcg_gen_and_tl(t1, t1, t2);
2313 tcg_temp_free(t2);
2314 tcg_gen_or_tl(t0, t0, t1);
2315 tcg_temp_free(t1);
2316 gen_store_gpr(t0, rt);
2317 break;
2318 case OPC_LDPC:
2319 t1 = tcg_const_tl(pc_relative_pc(ctx));
2320 gen_op_addr_add(ctx, t0, t0, t1);
2321 tcg_temp_free(t1);
2322 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2323 gen_store_gpr(t0, rt);
2324 break;
2325 #endif
2326 case OPC_LWPC:
2327 t1 = tcg_const_tl(pc_relative_pc(ctx));
2328 gen_op_addr_add(ctx, t0, t0, t1);
2329 tcg_temp_free(t1);
2330 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
2331 gen_store_gpr(t0, rt);
2332 break;
2333 case OPC_LWE:
2334 mem_idx = MIPS_HFLAG_UM;
2335 /* fall through */
2336 case OPC_LW:
2337 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
2338 ctx->default_tcg_memop_mask);
2339 gen_store_gpr(t0, rt);
2340 break;
2341 case OPC_LHE:
2342 mem_idx = MIPS_HFLAG_UM;
2343 /* fall through */
2344 case OPC_LH:
2345 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
2346 ctx->default_tcg_memop_mask);
2347 gen_store_gpr(t0, rt);
2348 break;
2349 case OPC_LHUE:
2350 mem_idx = MIPS_HFLAG_UM;
2351 /* fall through */
2352 case OPC_LHU:
2353 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
2354 ctx->default_tcg_memop_mask);
2355 gen_store_gpr(t0, rt);
2356 break;
2357 case OPC_LBE:
2358 mem_idx = MIPS_HFLAG_UM;
2359 /* fall through */
2360 case OPC_LB:
2361 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2362 gen_store_gpr(t0, rt);
2363 break;
2364 case OPC_LBUE:
2365 mem_idx = MIPS_HFLAG_UM;
2366 /* fall through */
2367 case OPC_LBU:
2368 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2369 gen_store_gpr(t0, rt);
2370 break;
2371 case OPC_LWLE:
2372 mem_idx = MIPS_HFLAG_UM;
2373 /* fall through */
2374 case OPC_LWL:
2375 t1 = tcg_temp_new();
2377 * Do a byte access to possibly trigger a page
2378 * fault with the unaligned address.
2380 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2381 tcg_gen_andi_tl(t1, t0, 3);
2382 #ifndef TARGET_WORDS_BIGENDIAN
2383 tcg_gen_xori_tl(t1, t1, 3);
2384 #endif
2385 tcg_gen_shli_tl(t1, t1, 3);
2386 tcg_gen_andi_tl(t0, t0, ~3);
2387 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2388 tcg_gen_shl_tl(t0, t0, t1);
2389 t2 = tcg_const_tl(-1);
2390 tcg_gen_shl_tl(t2, t2, t1);
2391 gen_load_gpr(t1, rt);
2392 tcg_gen_andc_tl(t1, t1, t2);
2393 tcg_temp_free(t2);
2394 tcg_gen_or_tl(t0, t0, t1);
2395 tcg_temp_free(t1);
2396 tcg_gen_ext32s_tl(t0, t0);
2397 gen_store_gpr(t0, rt);
2398 break;
2399 case OPC_LWRE:
2400 mem_idx = MIPS_HFLAG_UM;
2401 /* fall through */
2402 case OPC_LWR:
2403 t1 = tcg_temp_new();
2405 * Do a byte access to possibly trigger a page
2406 * fault with the unaligned address.
2408 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2409 tcg_gen_andi_tl(t1, t0, 3);
2410 #ifdef TARGET_WORDS_BIGENDIAN
2411 tcg_gen_xori_tl(t1, t1, 3);
2412 #endif
2413 tcg_gen_shli_tl(t1, t1, 3);
2414 tcg_gen_andi_tl(t0, t0, ~3);
2415 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2416 tcg_gen_shr_tl(t0, t0, t1);
2417 tcg_gen_xori_tl(t1, t1, 31);
2418 t2 = tcg_const_tl(0xfffffffeull);
2419 tcg_gen_shl_tl(t2, t2, t1);
2420 gen_load_gpr(t1, rt);
2421 tcg_gen_and_tl(t1, t1, t2);
2422 tcg_temp_free(t2);
2423 tcg_gen_or_tl(t0, t0, t1);
2424 tcg_temp_free(t1);
2425 tcg_gen_ext32s_tl(t0, t0);
2426 gen_store_gpr(t0, rt);
2427 break;
2428 case OPC_LLE:
2429 mem_idx = MIPS_HFLAG_UM;
2430 /* fall through */
2431 case OPC_LL:
2432 case R6_OPC_LL:
2433 op_ld_ll(t0, t0, mem_idx, ctx);
2434 gen_store_gpr(t0, rt);
2435 break;
2437 tcg_temp_free(t0);
2440 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
2441 uint32_t reg1, uint32_t reg2)
2443 TCGv taddr = tcg_temp_new();
2444 TCGv_i64 tval = tcg_temp_new_i64();
2445 TCGv tmp1 = tcg_temp_new();
2446 TCGv tmp2 = tcg_temp_new();
2448 gen_base_offset_addr(ctx, taddr, base, offset);
2449 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
2450 #ifdef TARGET_WORDS_BIGENDIAN
2451 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
2452 #else
2453 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
2454 #endif
2455 gen_store_gpr(tmp1, reg1);
2456 tcg_temp_free(tmp1);
2457 gen_store_gpr(tmp2, reg2);
2458 tcg_temp_free(tmp2);
2459 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2460 tcg_temp_free_i64(tval);
2461 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
2462 tcg_temp_free(taddr);
2465 /* Store */
2466 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
2467 int base, int offset)
2469 TCGv t0 = tcg_temp_new();
2470 TCGv t1 = tcg_temp_new();
2471 int mem_idx = ctx->mem_idx;
2473 gen_base_offset_addr(ctx, t0, base, offset);
2474 gen_load_gpr(t1, rt);
2475 switch (opc) {
2476 #if defined(TARGET_MIPS64)
2477 case OPC_SD:
2478 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
2479 ctx->default_tcg_memop_mask);
2480 break;
2481 case OPC_SDL:
2482 gen_helper_0e2i(sdl, t1, t0, mem_idx);
2483 break;
2484 case OPC_SDR:
2485 gen_helper_0e2i(sdr, t1, t0, mem_idx);
2486 break;
2487 #endif
2488 case OPC_SWE:
2489 mem_idx = MIPS_HFLAG_UM;
2490 /* fall through */
2491 case OPC_SW:
2492 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
2493 ctx->default_tcg_memop_mask);
2494 break;
2495 case OPC_SHE:
2496 mem_idx = MIPS_HFLAG_UM;
2497 /* fall through */
2498 case OPC_SH:
2499 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
2500 ctx->default_tcg_memop_mask);
2501 break;
2502 case OPC_SBE:
2503 mem_idx = MIPS_HFLAG_UM;
2504 /* fall through */
2505 case OPC_SB:
2506 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
2507 break;
2508 case OPC_SWLE:
2509 mem_idx = MIPS_HFLAG_UM;
2510 /* fall through */
2511 case OPC_SWL:
2512 gen_helper_0e2i(swl, t1, t0, mem_idx);
2513 break;
2514 case OPC_SWRE:
2515 mem_idx = MIPS_HFLAG_UM;
2516 /* fall through */
2517 case OPC_SWR:
2518 gen_helper_0e2i(swr, t1, t0, mem_idx);
2519 break;
2521 tcg_temp_free(t0);
2522 tcg_temp_free(t1);
2526 /* Store conditional */
2527 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
2528 MemOp tcg_mo, bool eva)
2530 TCGv addr, t0, val;
2531 TCGLabel *l1 = gen_new_label();
2532 TCGLabel *done = gen_new_label();
2534 t0 = tcg_temp_new();
2535 addr = tcg_temp_new();
2536 /* compare the address against that of the preceding LL */
2537 gen_base_offset_addr(ctx, addr, base, offset);
2538 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
2539 tcg_temp_free(addr);
2540 tcg_gen_movi_tl(t0, 0);
2541 gen_store_gpr(t0, rt);
2542 tcg_gen_br(done);
2544 gen_set_label(l1);
2545 /* generate cmpxchg */
2546 val = tcg_temp_new();
2547 gen_load_gpr(val, rt);
2548 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
2549 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
2550 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
2551 gen_store_gpr(t0, rt);
2552 tcg_temp_free(val);
2554 gen_set_label(done);
2555 tcg_temp_free(t0);
2559 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
2560 uint32_t reg1, uint32_t reg2, bool eva)
2562 TCGv taddr = tcg_temp_local_new();
2563 TCGv lladdr = tcg_temp_local_new();
2564 TCGv_i64 tval = tcg_temp_new_i64();
2565 TCGv_i64 llval = tcg_temp_new_i64();
2566 TCGv_i64 val = tcg_temp_new_i64();
2567 TCGv tmp1 = tcg_temp_new();
2568 TCGv tmp2 = tcg_temp_new();
2569 TCGLabel *lab_fail = gen_new_label();
2570 TCGLabel *lab_done = gen_new_label();
2572 gen_base_offset_addr(ctx, taddr, base, offset);
2574 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2575 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
2577 gen_load_gpr(tmp1, reg1);
2578 gen_load_gpr(tmp2, reg2);
2580 #ifdef TARGET_WORDS_BIGENDIAN
2581 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
2582 #else
2583 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
2584 #endif
2586 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2587 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
2588 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
2589 if (reg1 != 0) {
2590 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
2592 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
2594 gen_set_label(lab_fail);
2596 if (reg1 != 0) {
2597 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
2599 gen_set_label(lab_done);
2600 tcg_gen_movi_tl(lladdr, -1);
2601 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2604 /* Load and store */
2605 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
2606 TCGv t0)
2609 * Don't do NOP if destination is zero: we must perform the actual
2610 * memory access.
2612 switch (opc) {
2613 case OPC_LWC1:
2615 TCGv_i32 fp0 = tcg_temp_new_i32();
2616 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2617 ctx->default_tcg_memop_mask);
2618 gen_store_fpr32(ctx, fp0, ft);
2619 tcg_temp_free_i32(fp0);
2621 break;
2622 case OPC_SWC1:
2624 TCGv_i32 fp0 = tcg_temp_new_i32();
2625 gen_load_fpr32(ctx, fp0, ft);
2626 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2627 ctx->default_tcg_memop_mask);
2628 tcg_temp_free_i32(fp0);
2630 break;
2631 case OPC_LDC1:
2633 TCGv_i64 fp0 = tcg_temp_new_i64();
2634 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2635 ctx->default_tcg_memop_mask);
2636 gen_store_fpr64(ctx, fp0, ft);
2637 tcg_temp_free_i64(fp0);
2639 break;
2640 case OPC_SDC1:
2642 TCGv_i64 fp0 = tcg_temp_new_i64();
2643 gen_load_fpr64(ctx, fp0, ft);
2644 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2645 ctx->default_tcg_memop_mask);
2646 tcg_temp_free_i64(fp0);
2648 break;
2649 default:
2650 MIPS_INVAL("flt_ldst");
2651 gen_reserved_instruction(ctx);
2652 break;
2656 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2657 int rs, int16_t imm)
2659 TCGv t0 = tcg_temp_new();
2661 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2662 check_cp1_enabled(ctx);
2663 switch (op) {
2664 case OPC_LDC1:
2665 case OPC_SDC1:
2666 check_insn(ctx, ISA_MIPS2);
2667 /* Fallthrough */
2668 default:
2669 gen_base_offset_addr(ctx, t0, rs, imm);
2670 gen_flt_ldst(ctx, op, rt, t0);
2672 } else {
2673 generate_exception_err(ctx, EXCP_CpU, 1);
2675 tcg_temp_free(t0);
2678 /* Arithmetic with immediate operand */
2679 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2680 int rt, int rs, int imm)
2682 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2684 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2686 * If no destination, treat it as a NOP.
2687 * For addi, we must generate the overflow exception when needed.
2689 return;
2691 switch (opc) {
2692 case OPC_ADDI:
2694 TCGv t0 = tcg_temp_local_new();
2695 TCGv t1 = tcg_temp_new();
2696 TCGv t2 = tcg_temp_new();
2697 TCGLabel *l1 = gen_new_label();
2699 gen_load_gpr(t1, rs);
2700 tcg_gen_addi_tl(t0, t1, uimm);
2701 tcg_gen_ext32s_tl(t0, t0);
2703 tcg_gen_xori_tl(t1, t1, ~uimm);
2704 tcg_gen_xori_tl(t2, t0, uimm);
2705 tcg_gen_and_tl(t1, t1, t2);
2706 tcg_temp_free(t2);
2707 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2708 tcg_temp_free(t1);
2709 /* operands of same sign, result different sign */
2710 generate_exception(ctx, EXCP_OVERFLOW);
2711 gen_set_label(l1);
2712 tcg_gen_ext32s_tl(t0, t0);
2713 gen_store_gpr(t0, rt);
2714 tcg_temp_free(t0);
2716 break;
2717 case OPC_ADDIU:
2718 if (rs != 0) {
2719 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2720 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2721 } else {
2722 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2724 break;
2725 #if defined(TARGET_MIPS64)
2726 case OPC_DADDI:
2728 TCGv t0 = tcg_temp_local_new();
2729 TCGv t1 = tcg_temp_new();
2730 TCGv t2 = tcg_temp_new();
2731 TCGLabel *l1 = gen_new_label();
2733 gen_load_gpr(t1, rs);
2734 tcg_gen_addi_tl(t0, t1, uimm);
2736 tcg_gen_xori_tl(t1, t1, ~uimm);
2737 tcg_gen_xori_tl(t2, t0, uimm);
2738 tcg_gen_and_tl(t1, t1, t2);
2739 tcg_temp_free(t2);
2740 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2741 tcg_temp_free(t1);
2742 /* operands of same sign, result different sign */
2743 generate_exception(ctx, EXCP_OVERFLOW);
2744 gen_set_label(l1);
2745 gen_store_gpr(t0, rt);
2746 tcg_temp_free(t0);
2748 break;
2749 case OPC_DADDIU:
2750 if (rs != 0) {
2751 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2752 } else {
2753 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2755 break;
2756 #endif
2760 /* Logic with immediate operand */
2761 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2762 int rt, int rs, int16_t imm)
2764 target_ulong uimm;
2766 if (rt == 0) {
2767 /* If no destination, treat it as a NOP. */
2768 return;
2770 uimm = (uint16_t)imm;
2771 switch (opc) {
2772 case OPC_ANDI:
2773 if (likely(rs != 0)) {
2774 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2775 } else {
2776 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2778 break;
2779 case OPC_ORI:
2780 if (rs != 0) {
2781 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2782 } else {
2783 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2785 break;
2786 case OPC_XORI:
2787 if (likely(rs != 0)) {
2788 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2789 } else {
2790 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2792 break;
2793 case OPC_LUI:
2794 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
2795 /* OPC_AUI */
2796 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2797 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2798 } else {
2799 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2801 break;
2803 default:
2804 break;
2808 /* Set on less than with immediate operand */
2809 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2810 int rt, int rs, int16_t imm)
2812 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2813 TCGv t0;
2815 if (rt == 0) {
2816 /* If no destination, treat it as a NOP. */
2817 return;
2819 t0 = tcg_temp_new();
2820 gen_load_gpr(t0, rs);
2821 switch (opc) {
2822 case OPC_SLTI:
2823 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2824 break;
2825 case OPC_SLTIU:
2826 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2827 break;
2829 tcg_temp_free(t0);
2832 /* Shifts with immediate operand */
2833 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2834 int rt, int rs, int16_t imm)
2836 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2837 TCGv t0;
2839 if (rt == 0) {
2840 /* If no destination, treat it as a NOP. */
2841 return;
2844 t0 = tcg_temp_new();
2845 gen_load_gpr(t0, rs);
2846 switch (opc) {
2847 case OPC_SLL:
2848 tcg_gen_shli_tl(t0, t0, uimm);
2849 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2850 break;
2851 case OPC_SRA:
2852 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2853 break;
2854 case OPC_SRL:
2855 if (uimm != 0) {
2856 tcg_gen_ext32u_tl(t0, t0);
2857 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2858 } else {
2859 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2861 break;
2862 case OPC_ROTR:
2863 if (uimm != 0) {
2864 TCGv_i32 t1 = tcg_temp_new_i32();
2866 tcg_gen_trunc_tl_i32(t1, t0);
2867 tcg_gen_rotri_i32(t1, t1, uimm);
2868 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2869 tcg_temp_free_i32(t1);
2870 } else {
2871 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2873 break;
2874 #if defined(TARGET_MIPS64)
2875 case OPC_DSLL:
2876 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2877 break;
2878 case OPC_DSRA:
2879 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2880 break;
2881 case OPC_DSRL:
2882 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2883 break;
2884 case OPC_DROTR:
2885 if (uimm != 0) {
2886 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2887 } else {
2888 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2890 break;
2891 case OPC_DSLL32:
2892 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2893 break;
2894 case OPC_DSRA32:
2895 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2896 break;
2897 case OPC_DSRL32:
2898 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2899 break;
2900 case OPC_DROTR32:
2901 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2902 break;
2903 #endif
2905 tcg_temp_free(t0);
2908 /* Arithmetic */
2909 static void gen_arith(DisasContext *ctx, uint32_t opc,
2910 int rd, int rs, int rt)
2912 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2913 && opc != OPC_DADD && opc != OPC_DSUB) {
2915 * If no destination, treat it as a NOP.
2916 * For add & sub, we must generate the overflow exception when needed.
2918 return;
2921 switch (opc) {
2922 case OPC_ADD:
2924 TCGv t0 = tcg_temp_local_new();
2925 TCGv t1 = tcg_temp_new();
2926 TCGv t2 = tcg_temp_new();
2927 TCGLabel *l1 = gen_new_label();
2929 gen_load_gpr(t1, rs);
2930 gen_load_gpr(t2, rt);
2931 tcg_gen_add_tl(t0, t1, t2);
2932 tcg_gen_ext32s_tl(t0, t0);
2933 tcg_gen_xor_tl(t1, t1, t2);
2934 tcg_gen_xor_tl(t2, t0, t2);
2935 tcg_gen_andc_tl(t1, t2, t1);
2936 tcg_temp_free(t2);
2937 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2938 tcg_temp_free(t1);
2939 /* operands of same sign, result different sign */
2940 generate_exception(ctx, EXCP_OVERFLOW);
2941 gen_set_label(l1);
2942 gen_store_gpr(t0, rd);
2943 tcg_temp_free(t0);
2945 break;
2946 case OPC_ADDU:
2947 if (rs != 0 && rt != 0) {
2948 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2949 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2950 } else if (rs == 0 && rt != 0) {
2951 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2952 } else if (rs != 0 && rt == 0) {
2953 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2954 } else {
2955 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2957 break;
2958 case OPC_SUB:
2960 TCGv t0 = tcg_temp_local_new();
2961 TCGv t1 = tcg_temp_new();
2962 TCGv t2 = tcg_temp_new();
2963 TCGLabel *l1 = gen_new_label();
2965 gen_load_gpr(t1, rs);
2966 gen_load_gpr(t2, rt);
2967 tcg_gen_sub_tl(t0, t1, t2);
2968 tcg_gen_ext32s_tl(t0, t0);
2969 tcg_gen_xor_tl(t2, t1, t2);
2970 tcg_gen_xor_tl(t1, t0, t1);
2971 tcg_gen_and_tl(t1, t1, t2);
2972 tcg_temp_free(t2);
2973 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2974 tcg_temp_free(t1);
2976 * operands of different sign, first operand and the result
2977 * of different sign
2979 generate_exception(ctx, EXCP_OVERFLOW);
2980 gen_set_label(l1);
2981 gen_store_gpr(t0, rd);
2982 tcg_temp_free(t0);
2984 break;
2985 case OPC_SUBU:
2986 if (rs != 0 && rt != 0) {
2987 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2988 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2989 } else if (rs == 0 && rt != 0) {
2990 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2991 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2992 } else if (rs != 0 && rt == 0) {
2993 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2994 } else {
2995 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2997 break;
2998 #if defined(TARGET_MIPS64)
2999 case OPC_DADD:
3001 TCGv t0 = tcg_temp_local_new();
3002 TCGv t1 = tcg_temp_new();
3003 TCGv t2 = tcg_temp_new();
3004 TCGLabel *l1 = gen_new_label();
3006 gen_load_gpr(t1, rs);
3007 gen_load_gpr(t2, rt);
3008 tcg_gen_add_tl(t0, t1, t2);
3009 tcg_gen_xor_tl(t1, t1, t2);
3010 tcg_gen_xor_tl(t2, t0, t2);
3011 tcg_gen_andc_tl(t1, t2, t1);
3012 tcg_temp_free(t2);
3013 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3014 tcg_temp_free(t1);
3015 /* operands of same sign, result different sign */
3016 generate_exception(ctx, EXCP_OVERFLOW);
3017 gen_set_label(l1);
3018 gen_store_gpr(t0, rd);
3019 tcg_temp_free(t0);
3021 break;
3022 case OPC_DADDU:
3023 if (rs != 0 && rt != 0) {
3024 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3025 } else if (rs == 0 && rt != 0) {
3026 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3027 } else if (rs != 0 && rt == 0) {
3028 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3029 } else {
3030 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3032 break;
3033 case OPC_DSUB:
3035 TCGv t0 = tcg_temp_local_new();
3036 TCGv t1 = tcg_temp_new();
3037 TCGv t2 = tcg_temp_new();
3038 TCGLabel *l1 = gen_new_label();
3040 gen_load_gpr(t1, rs);
3041 gen_load_gpr(t2, rt);
3042 tcg_gen_sub_tl(t0, t1, t2);
3043 tcg_gen_xor_tl(t2, t1, t2);
3044 tcg_gen_xor_tl(t1, t0, t1);
3045 tcg_gen_and_tl(t1, t1, t2);
3046 tcg_temp_free(t2);
3047 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3048 tcg_temp_free(t1);
3050 * Operands of different sign, first operand and result different
3051 * sign.
3053 generate_exception(ctx, EXCP_OVERFLOW);
3054 gen_set_label(l1);
3055 gen_store_gpr(t0, rd);
3056 tcg_temp_free(t0);
3058 break;
3059 case OPC_DSUBU:
3060 if (rs != 0 && rt != 0) {
3061 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3062 } else if (rs == 0 && rt != 0) {
3063 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3064 } else if (rs != 0 && rt == 0) {
3065 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3066 } else {
3067 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3069 break;
3070 #endif
3071 case OPC_MUL:
3072 if (likely(rs != 0 && rt != 0)) {
3073 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3074 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3075 } else {
3076 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3078 break;
3082 /* Conditional move */
3083 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
3084 int rd, int rs, int rt)
3086 TCGv t0, t1, t2;
3088 if (rd == 0) {
3089 /* If no destination, treat it as a NOP. */
3090 return;
3093 t0 = tcg_temp_new();
3094 gen_load_gpr(t0, rt);
3095 t1 = tcg_const_tl(0);
3096 t2 = tcg_temp_new();
3097 gen_load_gpr(t2, rs);
3098 switch (opc) {
3099 case OPC_MOVN:
3100 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3101 break;
3102 case OPC_MOVZ:
3103 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3104 break;
3105 case OPC_SELNEZ:
3106 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
3107 break;
3108 case OPC_SELEQZ:
3109 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
3110 break;
3112 tcg_temp_free(t2);
3113 tcg_temp_free(t1);
3114 tcg_temp_free(t0);
3117 /* Logic */
3118 static void gen_logic(DisasContext *ctx, uint32_t opc,
3119 int rd, int rs, int rt)
3121 if (rd == 0) {
3122 /* If no destination, treat it as a NOP. */
3123 return;
3126 switch (opc) {
3127 case OPC_AND:
3128 if (likely(rs != 0 && rt != 0)) {
3129 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3130 } else {
3131 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3133 break;
3134 case OPC_NOR:
3135 if (rs != 0 && rt != 0) {
3136 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3137 } else if (rs == 0 && rt != 0) {
3138 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
3139 } else if (rs != 0 && rt == 0) {
3140 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
3141 } else {
3142 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
3144 break;
3145 case OPC_OR:
3146 if (likely(rs != 0 && rt != 0)) {
3147 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3148 } else if (rs == 0 && rt != 0) {
3149 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3150 } else if (rs != 0 && rt == 0) {
3151 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3152 } else {
3153 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3155 break;
3156 case OPC_XOR:
3157 if (likely(rs != 0 && rt != 0)) {
3158 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3159 } else if (rs == 0 && rt != 0) {
3160 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3161 } else if (rs != 0 && rt == 0) {
3162 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3163 } else {
3164 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3166 break;
3170 /* Set on lower than */
3171 static void gen_slt(DisasContext *ctx, uint32_t opc,
3172 int rd, int rs, int rt)
3174 TCGv t0, t1;
3176 if (rd == 0) {
3177 /* If no destination, treat it as a NOP. */
3178 return;
3181 t0 = tcg_temp_new();
3182 t1 = tcg_temp_new();
3183 gen_load_gpr(t0, rs);
3184 gen_load_gpr(t1, rt);
3185 switch (opc) {
3186 case OPC_SLT:
3187 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3188 break;
3189 case OPC_SLTU:
3190 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3191 break;
3193 tcg_temp_free(t0);
3194 tcg_temp_free(t1);
3197 /* Shifts */
3198 static void gen_shift(DisasContext *ctx, uint32_t opc,
3199 int rd, int rs, int rt)
3201 TCGv t0, t1;
3203 if (rd == 0) {
3205 * If no destination, treat it as a NOP.
3206 * For add & sub, we must generate the overflow exception when needed.
3208 return;
3211 t0 = tcg_temp_new();
3212 t1 = tcg_temp_new();
3213 gen_load_gpr(t0, rs);
3214 gen_load_gpr(t1, rt);
3215 switch (opc) {
3216 case OPC_SLLV:
3217 tcg_gen_andi_tl(t0, t0, 0x1f);
3218 tcg_gen_shl_tl(t0, t1, t0);
3219 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3220 break;
3221 case OPC_SRAV:
3222 tcg_gen_andi_tl(t0, t0, 0x1f);
3223 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3224 break;
3225 case OPC_SRLV:
3226 tcg_gen_ext32u_tl(t1, t1);
3227 tcg_gen_andi_tl(t0, t0, 0x1f);
3228 tcg_gen_shr_tl(t0, t1, t0);
3229 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3230 break;
3231 case OPC_ROTRV:
3233 TCGv_i32 t2 = tcg_temp_new_i32();
3234 TCGv_i32 t3 = tcg_temp_new_i32();
3236 tcg_gen_trunc_tl_i32(t2, t0);
3237 tcg_gen_trunc_tl_i32(t3, t1);
3238 tcg_gen_andi_i32(t2, t2, 0x1f);
3239 tcg_gen_rotr_i32(t2, t3, t2);
3240 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3241 tcg_temp_free_i32(t2);
3242 tcg_temp_free_i32(t3);
3244 break;
3245 #if defined(TARGET_MIPS64)
3246 case OPC_DSLLV:
3247 tcg_gen_andi_tl(t0, t0, 0x3f);
3248 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3249 break;
3250 case OPC_DSRAV:
3251 tcg_gen_andi_tl(t0, t0, 0x3f);
3252 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3253 break;
3254 case OPC_DSRLV:
3255 tcg_gen_andi_tl(t0, t0, 0x3f);
3256 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3257 break;
3258 case OPC_DROTRV:
3259 tcg_gen_andi_tl(t0, t0, 0x3f);
3260 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3261 break;
3262 #endif
3264 tcg_temp_free(t0);
3265 tcg_temp_free(t1);
3268 /* Arithmetic on HI/LO registers */
3269 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3271 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3272 /* Treat as NOP. */
3273 return;
3276 if (acc != 0) {
3277 check_dsp(ctx);
3280 switch (opc) {
3281 case OPC_MFHI:
3282 #if defined(TARGET_MIPS64)
3283 if (acc != 0) {
3284 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3285 } else
3286 #endif
3288 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3290 break;
3291 case OPC_MFLO:
3292 #if defined(TARGET_MIPS64)
3293 if (acc != 0) {
3294 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3295 } else
3296 #endif
3298 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3300 break;
3301 case OPC_MTHI:
3302 if (reg != 0) {
3303 #if defined(TARGET_MIPS64)
3304 if (acc != 0) {
3305 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3306 } else
3307 #endif
3309 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3311 } else {
3312 tcg_gen_movi_tl(cpu_HI[acc], 0);
3314 break;
3315 case OPC_MTLO:
3316 if (reg != 0) {
3317 #if defined(TARGET_MIPS64)
3318 if (acc != 0) {
3319 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3320 } else
3321 #endif
3323 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3325 } else {
3326 tcg_gen_movi_tl(cpu_LO[acc], 0);
3328 break;
3332 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3333 MemOp memop)
3335 TCGv t0 = tcg_const_tl(addr);
3336 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3337 gen_store_gpr(t0, reg);
3338 tcg_temp_free(t0);
3341 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3342 int rs)
3344 target_long offset;
3345 target_long addr;
3347 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3348 case OPC_ADDIUPC:
3349 if (rs != 0) {
3350 offset = sextract32(ctx->opcode << 2, 0, 21);
3351 addr = addr_add(ctx, pc, offset);
3352 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3354 break;
3355 case R6_OPC_LWPC:
3356 offset = sextract32(ctx->opcode << 2, 0, 21);
3357 addr = addr_add(ctx, pc, offset);
3358 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3359 break;
3360 #if defined(TARGET_MIPS64)
3361 case OPC_LWUPC:
3362 check_mips_64(ctx);
3363 offset = sextract32(ctx->opcode << 2, 0, 21);
3364 addr = addr_add(ctx, pc, offset);
3365 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3366 break;
3367 #endif
3368 default:
3369 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3370 case OPC_AUIPC:
3371 if (rs != 0) {
3372 offset = sextract32(ctx->opcode, 0, 16) << 16;
3373 addr = addr_add(ctx, pc, offset);
3374 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3376 break;
3377 case OPC_ALUIPC:
3378 if (rs != 0) {
3379 offset = sextract32(ctx->opcode, 0, 16) << 16;
3380 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3381 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3383 break;
3384 #if defined(TARGET_MIPS64)
3385 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3386 case R6_OPC_LDPC + (1 << 16):
3387 case R6_OPC_LDPC + (2 << 16):
3388 case R6_OPC_LDPC + (3 << 16):
3389 check_mips_64(ctx);
3390 offset = sextract32(ctx->opcode << 3, 0, 21);
3391 addr = addr_add(ctx, (pc & ~0x7), offset);
3392 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3393 break;
3394 #endif
3395 default:
3396 MIPS_INVAL("OPC_PCREL");
3397 gen_reserved_instruction(ctx);
3398 break;
3400 break;
3404 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3406 TCGv t0, t1;
3408 if (rd == 0) {
3409 /* Treat as NOP. */
3410 return;
3413 t0 = tcg_temp_new();
3414 t1 = tcg_temp_new();
3416 gen_load_gpr(t0, rs);
3417 gen_load_gpr(t1, rt);
3419 switch (opc) {
3420 case R6_OPC_DIV:
3422 TCGv t2 = tcg_temp_new();
3423 TCGv t3 = tcg_temp_new();
3424 tcg_gen_ext32s_tl(t0, t0);
3425 tcg_gen_ext32s_tl(t1, t1);
3426 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3427 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3428 tcg_gen_and_tl(t2, t2, t3);
3429 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3430 tcg_gen_or_tl(t2, t2, t3);
3431 tcg_gen_movi_tl(t3, 0);
3432 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3433 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3434 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3435 tcg_temp_free(t3);
3436 tcg_temp_free(t2);
3438 break;
3439 case R6_OPC_MOD:
3441 TCGv t2 = tcg_temp_new();
3442 TCGv t3 = tcg_temp_new();
3443 tcg_gen_ext32s_tl(t0, t0);
3444 tcg_gen_ext32s_tl(t1, t1);
3445 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3446 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3447 tcg_gen_and_tl(t2, t2, t3);
3448 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3449 tcg_gen_or_tl(t2, t2, t3);
3450 tcg_gen_movi_tl(t3, 0);
3451 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3452 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3453 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3454 tcg_temp_free(t3);
3455 tcg_temp_free(t2);
3457 break;
3458 case R6_OPC_DIVU:
3460 TCGv t2 = tcg_const_tl(0);
3461 TCGv t3 = tcg_const_tl(1);
3462 tcg_gen_ext32u_tl(t0, t0);
3463 tcg_gen_ext32u_tl(t1, t1);
3464 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3465 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3466 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3467 tcg_temp_free(t3);
3468 tcg_temp_free(t2);
3470 break;
3471 case R6_OPC_MODU:
3473 TCGv t2 = tcg_const_tl(0);
3474 TCGv t3 = tcg_const_tl(1);
3475 tcg_gen_ext32u_tl(t0, t0);
3476 tcg_gen_ext32u_tl(t1, t1);
3477 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3478 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3479 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3480 tcg_temp_free(t3);
3481 tcg_temp_free(t2);
3483 break;
3484 case R6_OPC_MUL:
3486 TCGv_i32 t2 = tcg_temp_new_i32();
3487 TCGv_i32 t3 = tcg_temp_new_i32();
3488 tcg_gen_trunc_tl_i32(t2, t0);
3489 tcg_gen_trunc_tl_i32(t3, t1);
3490 tcg_gen_mul_i32(t2, t2, t3);
3491 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3492 tcg_temp_free_i32(t2);
3493 tcg_temp_free_i32(t3);
3495 break;
3496 case R6_OPC_MUH:
3498 TCGv_i32 t2 = tcg_temp_new_i32();
3499 TCGv_i32 t3 = tcg_temp_new_i32();
3500 tcg_gen_trunc_tl_i32(t2, t0);
3501 tcg_gen_trunc_tl_i32(t3, t1);
3502 tcg_gen_muls2_i32(t2, t3, t2, t3);
3503 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3504 tcg_temp_free_i32(t2);
3505 tcg_temp_free_i32(t3);
3507 break;
3508 case R6_OPC_MULU:
3510 TCGv_i32 t2 = tcg_temp_new_i32();
3511 TCGv_i32 t3 = tcg_temp_new_i32();
3512 tcg_gen_trunc_tl_i32(t2, t0);
3513 tcg_gen_trunc_tl_i32(t3, t1);
3514 tcg_gen_mul_i32(t2, t2, t3);
3515 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3516 tcg_temp_free_i32(t2);
3517 tcg_temp_free_i32(t3);
3519 break;
3520 case R6_OPC_MUHU:
3522 TCGv_i32 t2 = tcg_temp_new_i32();
3523 TCGv_i32 t3 = tcg_temp_new_i32();
3524 tcg_gen_trunc_tl_i32(t2, t0);
3525 tcg_gen_trunc_tl_i32(t3, t1);
3526 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3527 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3528 tcg_temp_free_i32(t2);
3529 tcg_temp_free_i32(t3);
3531 break;
3532 #if defined(TARGET_MIPS64)
3533 case R6_OPC_DDIV:
3535 TCGv t2 = tcg_temp_new();
3536 TCGv t3 = tcg_temp_new();
3537 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3538 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3539 tcg_gen_and_tl(t2, t2, t3);
3540 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3541 tcg_gen_or_tl(t2, t2, t3);
3542 tcg_gen_movi_tl(t3, 0);
3543 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3544 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3545 tcg_temp_free(t3);
3546 tcg_temp_free(t2);
3548 break;
3549 case R6_OPC_DMOD:
3551 TCGv t2 = tcg_temp_new();
3552 TCGv t3 = tcg_temp_new();
3553 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3554 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3555 tcg_gen_and_tl(t2, t2, t3);
3556 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3557 tcg_gen_or_tl(t2, t2, t3);
3558 tcg_gen_movi_tl(t3, 0);
3559 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3560 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3561 tcg_temp_free(t3);
3562 tcg_temp_free(t2);
3564 break;
3565 case R6_OPC_DDIVU:
3567 TCGv t2 = tcg_const_tl(0);
3568 TCGv t3 = tcg_const_tl(1);
3569 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3570 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3571 tcg_temp_free(t3);
3572 tcg_temp_free(t2);
3574 break;
3575 case R6_OPC_DMODU:
3577 TCGv t2 = tcg_const_tl(0);
3578 TCGv t3 = tcg_const_tl(1);
3579 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3580 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3581 tcg_temp_free(t3);
3582 tcg_temp_free(t2);
3584 break;
3585 case R6_OPC_DMUL:
3586 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3587 break;
3588 case R6_OPC_DMUH:
3590 TCGv t2 = tcg_temp_new();
3591 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3592 tcg_temp_free(t2);
3594 break;
3595 case R6_OPC_DMULU:
3596 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3597 break;
3598 case R6_OPC_DMUHU:
3600 TCGv t2 = tcg_temp_new();
3601 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3602 tcg_temp_free(t2);
3604 break;
3605 #endif
3606 default:
3607 MIPS_INVAL("r6 mul/div");
3608 gen_reserved_instruction(ctx);
3609 goto out;
3611 out:
3612 tcg_temp_free(t0);
3613 tcg_temp_free(t1);
3616 #if defined(TARGET_MIPS64)
3617 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
3619 TCGv t0, t1;
3621 t0 = tcg_temp_new();
3622 t1 = tcg_temp_new();
3624 gen_load_gpr(t0, rs);
3625 gen_load_gpr(t1, rt);
3627 switch (opc) {
3628 case MMI_OPC_DIV1:
3630 TCGv t2 = tcg_temp_new();
3631 TCGv t3 = tcg_temp_new();
3632 tcg_gen_ext32s_tl(t0, t0);
3633 tcg_gen_ext32s_tl(t1, t1);
3634 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3635 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3636 tcg_gen_and_tl(t2, t2, t3);
3637 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3638 tcg_gen_or_tl(t2, t2, t3);
3639 tcg_gen_movi_tl(t3, 0);
3640 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3641 tcg_gen_div_tl(cpu_LO[1], t0, t1);
3642 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
3643 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3644 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3645 tcg_temp_free(t3);
3646 tcg_temp_free(t2);
3648 break;
3649 case MMI_OPC_DIVU1:
3651 TCGv t2 = tcg_const_tl(0);
3652 TCGv t3 = tcg_const_tl(1);
3653 tcg_gen_ext32u_tl(t0, t0);
3654 tcg_gen_ext32u_tl(t1, t1);
3655 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3656 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
3657 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
3658 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3659 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3660 tcg_temp_free(t3);
3661 tcg_temp_free(t2);
3663 break;
3664 default:
3665 MIPS_INVAL("div1 TX79");
3666 gen_reserved_instruction(ctx);
3667 goto out;
3669 out:
3670 tcg_temp_free(t0);
3671 tcg_temp_free(t1);
3673 #endif
3675 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3676 int acc, int rs, int rt)
3678 TCGv t0, t1;
3680 t0 = tcg_temp_new();
3681 t1 = tcg_temp_new();
3683 gen_load_gpr(t0, rs);
3684 gen_load_gpr(t1, rt);
3686 if (acc != 0) {
3687 check_dsp(ctx);
3690 switch (opc) {
3691 case OPC_DIV:
3693 TCGv t2 = tcg_temp_new();
3694 TCGv t3 = tcg_temp_new();
3695 tcg_gen_ext32s_tl(t0, t0);
3696 tcg_gen_ext32s_tl(t1, t1);
3697 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3698 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3699 tcg_gen_and_tl(t2, t2, t3);
3700 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3701 tcg_gen_or_tl(t2, t2, t3);
3702 tcg_gen_movi_tl(t3, 0);
3703 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3704 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3705 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3706 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3707 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3708 tcg_temp_free(t3);
3709 tcg_temp_free(t2);
3711 break;
3712 case OPC_DIVU:
3714 TCGv t2 = tcg_const_tl(0);
3715 TCGv t3 = tcg_const_tl(1);
3716 tcg_gen_ext32u_tl(t0, t0);
3717 tcg_gen_ext32u_tl(t1, t1);
3718 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3719 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3720 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3721 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3722 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3723 tcg_temp_free(t3);
3724 tcg_temp_free(t2);
3726 break;
3727 case OPC_MULT:
3729 TCGv_i32 t2 = tcg_temp_new_i32();
3730 TCGv_i32 t3 = tcg_temp_new_i32();
3731 tcg_gen_trunc_tl_i32(t2, t0);
3732 tcg_gen_trunc_tl_i32(t3, t1);
3733 tcg_gen_muls2_i32(t2, t3, t2, t3);
3734 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3735 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3736 tcg_temp_free_i32(t2);
3737 tcg_temp_free_i32(t3);
3739 break;
3740 case OPC_MULTU:
3742 TCGv_i32 t2 = tcg_temp_new_i32();
3743 TCGv_i32 t3 = tcg_temp_new_i32();
3744 tcg_gen_trunc_tl_i32(t2, t0);
3745 tcg_gen_trunc_tl_i32(t3, t1);
3746 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3747 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3748 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3749 tcg_temp_free_i32(t2);
3750 tcg_temp_free_i32(t3);
3752 break;
3753 #if defined(TARGET_MIPS64)
3754 case OPC_DDIV:
3756 TCGv t2 = tcg_temp_new();
3757 TCGv t3 = tcg_temp_new();
3758 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3759 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3760 tcg_gen_and_tl(t2, t2, t3);
3761 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3762 tcg_gen_or_tl(t2, t2, t3);
3763 tcg_gen_movi_tl(t3, 0);
3764 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3765 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3766 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3767 tcg_temp_free(t3);
3768 tcg_temp_free(t2);
3770 break;
3771 case OPC_DDIVU:
3773 TCGv t2 = tcg_const_tl(0);
3774 TCGv t3 = tcg_const_tl(1);
3775 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3776 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3777 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3778 tcg_temp_free(t3);
3779 tcg_temp_free(t2);
3781 break;
3782 case OPC_DMULT:
3783 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3784 break;
3785 case OPC_DMULTU:
3786 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3787 break;
3788 #endif
3789 case OPC_MADD:
3791 TCGv_i64 t2 = tcg_temp_new_i64();
3792 TCGv_i64 t3 = tcg_temp_new_i64();
3794 tcg_gen_ext_tl_i64(t2, t0);
3795 tcg_gen_ext_tl_i64(t3, t1);
3796 tcg_gen_mul_i64(t2, t2, t3);
3797 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3798 tcg_gen_add_i64(t2, t2, t3);
3799 tcg_temp_free_i64(t3);
3800 gen_move_low32(cpu_LO[acc], t2);
3801 gen_move_high32(cpu_HI[acc], t2);
3802 tcg_temp_free_i64(t2);
3804 break;
3805 case OPC_MADDU:
3807 TCGv_i64 t2 = tcg_temp_new_i64();
3808 TCGv_i64 t3 = tcg_temp_new_i64();
3810 tcg_gen_ext32u_tl(t0, t0);
3811 tcg_gen_ext32u_tl(t1, t1);
3812 tcg_gen_extu_tl_i64(t2, t0);
3813 tcg_gen_extu_tl_i64(t3, t1);
3814 tcg_gen_mul_i64(t2, t2, t3);
3815 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3816 tcg_gen_add_i64(t2, t2, t3);
3817 tcg_temp_free_i64(t3);
3818 gen_move_low32(cpu_LO[acc], t2);
3819 gen_move_high32(cpu_HI[acc], t2);
3820 tcg_temp_free_i64(t2);
3822 break;
3823 case OPC_MSUB:
3825 TCGv_i64 t2 = tcg_temp_new_i64();
3826 TCGv_i64 t3 = tcg_temp_new_i64();
3828 tcg_gen_ext_tl_i64(t2, t0);
3829 tcg_gen_ext_tl_i64(t3, t1);
3830 tcg_gen_mul_i64(t2, t2, t3);
3831 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3832 tcg_gen_sub_i64(t2, t3, t2);
3833 tcg_temp_free_i64(t3);
3834 gen_move_low32(cpu_LO[acc], t2);
3835 gen_move_high32(cpu_HI[acc], t2);
3836 tcg_temp_free_i64(t2);
3838 break;
3839 case OPC_MSUBU:
3841 TCGv_i64 t2 = tcg_temp_new_i64();
3842 TCGv_i64 t3 = tcg_temp_new_i64();
3844 tcg_gen_ext32u_tl(t0, t0);
3845 tcg_gen_ext32u_tl(t1, t1);
3846 tcg_gen_extu_tl_i64(t2, t0);
3847 tcg_gen_extu_tl_i64(t3, t1);
3848 tcg_gen_mul_i64(t2, t2, t3);
3849 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3850 tcg_gen_sub_i64(t2, t3, t2);
3851 tcg_temp_free_i64(t3);
3852 gen_move_low32(cpu_LO[acc], t2);
3853 gen_move_high32(cpu_HI[acc], t2);
3854 tcg_temp_free_i64(t2);
3856 break;
3857 default:
3858 MIPS_INVAL("mul/div");
3859 gen_reserved_instruction(ctx);
3860 goto out;
3862 out:
3863 tcg_temp_free(t0);
3864 tcg_temp_free(t1);
3868 * These MULT[U] and MADD[U] instructions implemented in for example
3869 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
3870 * architectures are special three-operand variants with the syntax
3872 * MULT[U][1] rd, rs, rt
3874 * such that
3876 * (rd, LO, HI) <- rs * rt
3878 * and
3880 * MADD[U][1] rd, rs, rt
3882 * such that
3884 * (rd, LO, HI) <- (LO, HI) + rs * rt
3886 * where the low-order 32-bits of the result is placed into both the
3887 * GPR rd and the special register LO. The high-order 32-bits of the
3888 * result is placed into the special register HI.
3890 * If the GPR rd is omitted in assembly language, it is taken to be 0,
3891 * which is the zero register that always reads as 0.
3893 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
3894 int rd, int rs, int rt)
3896 TCGv t0 = tcg_temp_new();
3897 TCGv t1 = tcg_temp_new();
3898 int acc = 0;
3900 gen_load_gpr(t0, rs);
3901 gen_load_gpr(t1, rt);
3903 switch (opc) {
3904 case MMI_OPC_MULT1:
3905 acc = 1;
3906 /* Fall through */
3907 case OPC_MULT:
3909 TCGv_i32 t2 = tcg_temp_new_i32();
3910 TCGv_i32 t3 = tcg_temp_new_i32();
3911 tcg_gen_trunc_tl_i32(t2, t0);
3912 tcg_gen_trunc_tl_i32(t3, t1);
3913 tcg_gen_muls2_i32(t2, t3, t2, t3);
3914 if (rd) {
3915 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3917 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3918 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3919 tcg_temp_free_i32(t2);
3920 tcg_temp_free_i32(t3);
3922 break;
3923 case MMI_OPC_MULTU1:
3924 acc = 1;
3925 /* Fall through */
3926 case OPC_MULTU:
3928 TCGv_i32 t2 = tcg_temp_new_i32();
3929 TCGv_i32 t3 = tcg_temp_new_i32();
3930 tcg_gen_trunc_tl_i32(t2, t0);
3931 tcg_gen_trunc_tl_i32(t3, t1);
3932 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3933 if (rd) {
3934 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3936 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3937 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3938 tcg_temp_free_i32(t2);
3939 tcg_temp_free_i32(t3);
3941 break;
3942 case MMI_OPC_MADD1:
3943 acc = 1;
3944 /* Fall through */
3945 case MMI_OPC_MADD:
3947 TCGv_i64 t2 = tcg_temp_new_i64();
3948 TCGv_i64 t3 = tcg_temp_new_i64();
3950 tcg_gen_ext_tl_i64(t2, t0);
3951 tcg_gen_ext_tl_i64(t3, t1);
3952 tcg_gen_mul_i64(t2, t2, t3);
3953 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3954 tcg_gen_add_i64(t2, t2, t3);
3955 tcg_temp_free_i64(t3);
3956 gen_move_low32(cpu_LO[acc], t2);
3957 gen_move_high32(cpu_HI[acc], t2);
3958 if (rd) {
3959 gen_move_low32(cpu_gpr[rd], t2);
3961 tcg_temp_free_i64(t2);
3963 break;
3964 case MMI_OPC_MADDU1:
3965 acc = 1;
3966 /* Fall through */
3967 case MMI_OPC_MADDU:
3969 TCGv_i64 t2 = tcg_temp_new_i64();
3970 TCGv_i64 t3 = tcg_temp_new_i64();
3972 tcg_gen_ext32u_tl(t0, t0);
3973 tcg_gen_ext32u_tl(t1, t1);
3974 tcg_gen_extu_tl_i64(t2, t0);
3975 tcg_gen_extu_tl_i64(t3, t1);
3976 tcg_gen_mul_i64(t2, t2, t3);
3977 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3978 tcg_gen_add_i64(t2, t2, t3);
3979 tcg_temp_free_i64(t3);
3980 gen_move_low32(cpu_LO[acc], t2);
3981 gen_move_high32(cpu_HI[acc], t2);
3982 if (rd) {
3983 gen_move_low32(cpu_gpr[rd], t2);
3985 tcg_temp_free_i64(t2);
3987 break;
3988 default:
3989 MIPS_INVAL("mul/madd TXx9");
3990 gen_reserved_instruction(ctx);
3991 goto out;
3994 out:
3995 tcg_temp_free(t0);
3996 tcg_temp_free(t1);
3999 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
4000 int rd, int rs, int rt)
4002 TCGv t0 = tcg_temp_new();
4003 TCGv t1 = tcg_temp_new();
4005 gen_load_gpr(t0, rs);
4006 gen_load_gpr(t1, rt);
4008 switch (opc) {
4009 case OPC_VR54XX_MULS:
4010 gen_helper_muls(t0, cpu_env, t0, t1);
4011 break;
4012 case OPC_VR54XX_MULSU:
4013 gen_helper_mulsu(t0, cpu_env, t0, t1);
4014 break;
4015 case OPC_VR54XX_MACC:
4016 gen_helper_macc(t0, cpu_env, t0, t1);
4017 break;
4018 case OPC_VR54XX_MACCU:
4019 gen_helper_maccu(t0, cpu_env, t0, t1);
4020 break;
4021 case OPC_VR54XX_MSAC:
4022 gen_helper_msac(t0, cpu_env, t0, t1);
4023 break;
4024 case OPC_VR54XX_MSACU:
4025 gen_helper_msacu(t0, cpu_env, t0, t1);
4026 break;
4027 case OPC_VR54XX_MULHI:
4028 gen_helper_mulhi(t0, cpu_env, t0, t1);
4029 break;
4030 case OPC_VR54XX_MULHIU:
4031 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4032 break;
4033 case OPC_VR54XX_MULSHI:
4034 gen_helper_mulshi(t0, cpu_env, t0, t1);
4035 break;
4036 case OPC_VR54XX_MULSHIU:
4037 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4038 break;
4039 case OPC_VR54XX_MACCHI:
4040 gen_helper_macchi(t0, cpu_env, t0, t1);
4041 break;
4042 case OPC_VR54XX_MACCHIU:
4043 gen_helper_macchiu(t0, cpu_env, t0, t1);
4044 break;
4045 case OPC_VR54XX_MSACHI:
4046 gen_helper_msachi(t0, cpu_env, t0, t1);
4047 break;
4048 case OPC_VR54XX_MSACHIU:
4049 gen_helper_msachiu(t0, cpu_env, t0, t1);
4050 break;
4051 default:
4052 MIPS_INVAL("mul vr54xx");
4053 gen_reserved_instruction(ctx);
4054 goto out;
4056 gen_store_gpr(t0, rd);
4058 out:
4059 tcg_temp_free(t0);
4060 tcg_temp_free(t1);
4063 static void gen_cl(DisasContext *ctx, uint32_t opc,
4064 int rd, int rs)
4066 TCGv t0;
4068 if (rd == 0) {
4069 /* Treat as NOP. */
4070 return;
4072 t0 = cpu_gpr[rd];
4073 gen_load_gpr(t0, rs);
4075 switch (opc) {
4076 case OPC_CLO:
4077 case R6_OPC_CLO:
4078 #if defined(TARGET_MIPS64)
4079 case OPC_DCLO:
4080 case R6_OPC_DCLO:
4081 #endif
4082 tcg_gen_not_tl(t0, t0);
4083 break;
4086 switch (opc) {
4087 case OPC_CLO:
4088 case R6_OPC_CLO:
4089 case OPC_CLZ:
4090 case R6_OPC_CLZ:
4091 tcg_gen_ext32u_tl(t0, t0);
4092 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4093 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
4094 break;
4095 #if defined(TARGET_MIPS64)
4096 case OPC_DCLO:
4097 case R6_OPC_DCLO:
4098 case OPC_DCLZ:
4099 case R6_OPC_DCLZ:
4100 tcg_gen_clzi_i64(t0, t0, 64);
4101 break;
4102 #endif
4106 /* Godson integer instructions */
4107 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
4108 int rd, int rs, int rt)
4110 TCGv t0, t1;
4112 if (rd == 0) {
4113 /* Treat as NOP. */
4114 return;
4117 switch (opc) {
4118 case OPC_MULT_G_2E:
4119 case OPC_MULT_G_2F:
4120 case OPC_MULTU_G_2E:
4121 case OPC_MULTU_G_2F:
4122 #if defined(TARGET_MIPS64)
4123 case OPC_DMULT_G_2E:
4124 case OPC_DMULT_G_2F:
4125 case OPC_DMULTU_G_2E:
4126 case OPC_DMULTU_G_2F:
4127 #endif
4128 t0 = tcg_temp_new();
4129 t1 = tcg_temp_new();
4130 break;
4131 default:
4132 t0 = tcg_temp_local_new();
4133 t1 = tcg_temp_local_new();
4134 break;
4137 gen_load_gpr(t0, rs);
4138 gen_load_gpr(t1, rt);
4140 switch (opc) {
4141 case OPC_MULT_G_2E:
4142 case OPC_MULT_G_2F:
4143 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4144 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4145 break;
4146 case OPC_MULTU_G_2E:
4147 case OPC_MULTU_G_2F:
4148 tcg_gen_ext32u_tl(t0, t0);
4149 tcg_gen_ext32u_tl(t1, t1);
4150 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4151 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4152 break;
4153 case OPC_DIV_G_2E:
4154 case OPC_DIV_G_2F:
4156 TCGLabel *l1 = gen_new_label();
4157 TCGLabel *l2 = gen_new_label();
4158 TCGLabel *l3 = gen_new_label();
4159 tcg_gen_ext32s_tl(t0, t0);
4160 tcg_gen_ext32s_tl(t1, t1);
4161 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4162 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4163 tcg_gen_br(l3);
4164 gen_set_label(l1);
4165 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4166 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4167 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4168 tcg_gen_br(l3);
4169 gen_set_label(l2);
4170 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4171 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4172 gen_set_label(l3);
4174 break;
4175 case OPC_DIVU_G_2E:
4176 case OPC_DIVU_G_2F:
4178 TCGLabel *l1 = gen_new_label();
4179 TCGLabel *l2 = gen_new_label();
4180 tcg_gen_ext32u_tl(t0, t0);
4181 tcg_gen_ext32u_tl(t1, t1);
4182 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4183 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4184 tcg_gen_br(l2);
4185 gen_set_label(l1);
4186 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4187 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4188 gen_set_label(l2);
4190 break;
4191 case OPC_MOD_G_2E:
4192 case OPC_MOD_G_2F:
4194 TCGLabel *l1 = gen_new_label();
4195 TCGLabel *l2 = gen_new_label();
4196 TCGLabel *l3 = gen_new_label();
4197 tcg_gen_ext32u_tl(t0, t0);
4198 tcg_gen_ext32u_tl(t1, t1);
4199 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4200 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4201 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4202 gen_set_label(l1);
4203 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4204 tcg_gen_br(l3);
4205 gen_set_label(l2);
4206 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4207 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4208 gen_set_label(l3);
4210 break;
4211 case OPC_MODU_G_2E:
4212 case OPC_MODU_G_2F:
4214 TCGLabel *l1 = gen_new_label();
4215 TCGLabel *l2 = gen_new_label();
4216 tcg_gen_ext32u_tl(t0, t0);
4217 tcg_gen_ext32u_tl(t1, t1);
4218 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4219 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4220 tcg_gen_br(l2);
4221 gen_set_label(l1);
4222 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4223 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4224 gen_set_label(l2);
4226 break;
4227 #if defined(TARGET_MIPS64)
4228 case OPC_DMULT_G_2E:
4229 case OPC_DMULT_G_2F:
4230 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4231 break;
4232 case OPC_DMULTU_G_2E:
4233 case OPC_DMULTU_G_2F:
4234 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4235 break;
4236 case OPC_DDIV_G_2E:
4237 case OPC_DDIV_G_2F:
4239 TCGLabel *l1 = gen_new_label();
4240 TCGLabel *l2 = gen_new_label();
4241 TCGLabel *l3 = gen_new_label();
4242 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4243 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4244 tcg_gen_br(l3);
4245 gen_set_label(l1);
4246 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4247 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4248 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4249 tcg_gen_br(l3);
4250 gen_set_label(l2);
4251 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4252 gen_set_label(l3);
4254 break;
4255 case OPC_DDIVU_G_2E:
4256 case OPC_DDIVU_G_2F:
4258 TCGLabel *l1 = gen_new_label();
4259 TCGLabel *l2 = gen_new_label();
4260 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4261 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4262 tcg_gen_br(l2);
4263 gen_set_label(l1);
4264 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4265 gen_set_label(l2);
4267 break;
4268 case OPC_DMOD_G_2E:
4269 case OPC_DMOD_G_2F:
4271 TCGLabel *l1 = gen_new_label();
4272 TCGLabel *l2 = gen_new_label();
4273 TCGLabel *l3 = gen_new_label();
4274 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4275 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4276 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4277 gen_set_label(l1);
4278 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4279 tcg_gen_br(l3);
4280 gen_set_label(l2);
4281 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4282 gen_set_label(l3);
4284 break;
4285 case OPC_DMODU_G_2E:
4286 case OPC_DMODU_G_2F:
4288 TCGLabel *l1 = gen_new_label();
4289 TCGLabel *l2 = gen_new_label();
4290 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4291 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4292 tcg_gen_br(l2);
4293 gen_set_label(l1);
4294 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4295 gen_set_label(l2);
4297 break;
4298 #endif
4301 tcg_temp_free(t0);
4302 tcg_temp_free(t1);
4305 /* Loongson multimedia instructions */
4306 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4308 uint32_t opc, shift_max;
4309 TCGv_i64 t0, t1;
4310 TCGCond cond;
4312 opc = MASK_LMMI(ctx->opcode);
4313 switch (opc) {
4314 case OPC_ADD_CP2:
4315 case OPC_SUB_CP2:
4316 case OPC_DADD_CP2:
4317 case OPC_DSUB_CP2:
4318 t0 = tcg_temp_local_new_i64();
4319 t1 = tcg_temp_local_new_i64();
4320 break;
4321 default:
4322 t0 = tcg_temp_new_i64();
4323 t1 = tcg_temp_new_i64();
4324 break;
4327 check_cp1_enabled(ctx);
4328 gen_load_fpr64(ctx, t0, rs);
4329 gen_load_fpr64(ctx, t1, rt);
4331 switch (opc) {
4332 case OPC_PADDSH:
4333 gen_helper_paddsh(t0, t0, t1);
4334 break;
4335 case OPC_PADDUSH:
4336 gen_helper_paddush(t0, t0, t1);
4337 break;
4338 case OPC_PADDH:
4339 gen_helper_paddh(t0, t0, t1);
4340 break;
4341 case OPC_PADDW:
4342 gen_helper_paddw(t0, t0, t1);
4343 break;
4344 case OPC_PADDSB:
4345 gen_helper_paddsb(t0, t0, t1);
4346 break;
4347 case OPC_PADDUSB:
4348 gen_helper_paddusb(t0, t0, t1);
4349 break;
4350 case OPC_PADDB:
4351 gen_helper_paddb(t0, t0, t1);
4352 break;
4354 case OPC_PSUBSH:
4355 gen_helper_psubsh(t0, t0, t1);
4356 break;
4357 case OPC_PSUBUSH:
4358 gen_helper_psubush(t0, t0, t1);
4359 break;
4360 case OPC_PSUBH:
4361 gen_helper_psubh(t0, t0, t1);
4362 break;
4363 case OPC_PSUBW:
4364 gen_helper_psubw(t0, t0, t1);
4365 break;
4366 case OPC_PSUBSB:
4367 gen_helper_psubsb(t0, t0, t1);
4368 break;
4369 case OPC_PSUBUSB:
4370 gen_helper_psubusb(t0, t0, t1);
4371 break;
4372 case OPC_PSUBB:
4373 gen_helper_psubb(t0, t0, t1);
4374 break;
4376 case OPC_PSHUFH:
4377 gen_helper_pshufh(t0, t0, t1);
4378 break;
4379 case OPC_PACKSSWH:
4380 gen_helper_packsswh(t0, t0, t1);
4381 break;
4382 case OPC_PACKSSHB:
4383 gen_helper_packsshb(t0, t0, t1);
4384 break;
4385 case OPC_PACKUSHB:
4386 gen_helper_packushb(t0, t0, t1);
4387 break;
4389 case OPC_PUNPCKLHW:
4390 gen_helper_punpcklhw(t0, t0, t1);
4391 break;
4392 case OPC_PUNPCKHHW:
4393 gen_helper_punpckhhw(t0, t0, t1);
4394 break;
4395 case OPC_PUNPCKLBH:
4396 gen_helper_punpcklbh(t0, t0, t1);
4397 break;
4398 case OPC_PUNPCKHBH:
4399 gen_helper_punpckhbh(t0, t0, t1);
4400 break;
4401 case OPC_PUNPCKLWD:
4402 gen_helper_punpcklwd(t0, t0, t1);
4403 break;
4404 case OPC_PUNPCKHWD:
4405 gen_helper_punpckhwd(t0, t0, t1);
4406 break;
4408 case OPC_PAVGH:
4409 gen_helper_pavgh(t0, t0, t1);
4410 break;
4411 case OPC_PAVGB:
4412 gen_helper_pavgb(t0, t0, t1);
4413 break;
4414 case OPC_PMAXSH:
4415 gen_helper_pmaxsh(t0, t0, t1);
4416 break;
4417 case OPC_PMINSH:
4418 gen_helper_pminsh(t0, t0, t1);
4419 break;
4420 case OPC_PMAXUB:
4421 gen_helper_pmaxub(t0, t0, t1);
4422 break;
4423 case OPC_PMINUB:
4424 gen_helper_pminub(t0, t0, t1);
4425 break;
4427 case OPC_PCMPEQW:
4428 gen_helper_pcmpeqw(t0, t0, t1);
4429 break;
4430 case OPC_PCMPGTW:
4431 gen_helper_pcmpgtw(t0, t0, t1);
4432 break;
4433 case OPC_PCMPEQH:
4434 gen_helper_pcmpeqh(t0, t0, t1);
4435 break;
4436 case OPC_PCMPGTH:
4437 gen_helper_pcmpgth(t0, t0, t1);
4438 break;
4439 case OPC_PCMPEQB:
4440 gen_helper_pcmpeqb(t0, t0, t1);
4441 break;
4442 case OPC_PCMPGTB:
4443 gen_helper_pcmpgtb(t0, t0, t1);
4444 break;
4446 case OPC_PSLLW:
4447 gen_helper_psllw(t0, t0, t1);
4448 break;
4449 case OPC_PSLLH:
4450 gen_helper_psllh(t0, t0, t1);
4451 break;
4452 case OPC_PSRLW:
4453 gen_helper_psrlw(t0, t0, t1);
4454 break;
4455 case OPC_PSRLH:
4456 gen_helper_psrlh(t0, t0, t1);
4457 break;
4458 case OPC_PSRAW:
4459 gen_helper_psraw(t0, t0, t1);
4460 break;
4461 case OPC_PSRAH:
4462 gen_helper_psrah(t0, t0, t1);
4463 break;
4465 case OPC_PMULLH:
4466 gen_helper_pmullh(t0, t0, t1);
4467 break;
4468 case OPC_PMULHH:
4469 gen_helper_pmulhh(t0, t0, t1);
4470 break;
4471 case OPC_PMULHUH:
4472 gen_helper_pmulhuh(t0, t0, t1);
4473 break;
4474 case OPC_PMADDHW:
4475 gen_helper_pmaddhw(t0, t0, t1);
4476 break;
4478 case OPC_PASUBUB:
4479 gen_helper_pasubub(t0, t0, t1);
4480 break;
4481 case OPC_BIADD:
4482 gen_helper_biadd(t0, t0);
4483 break;
4484 case OPC_PMOVMSKB:
4485 gen_helper_pmovmskb(t0, t0);
4486 break;
4488 case OPC_PADDD:
4489 tcg_gen_add_i64(t0, t0, t1);
4490 break;
4491 case OPC_PSUBD:
4492 tcg_gen_sub_i64(t0, t0, t1);
4493 break;
4494 case OPC_XOR_CP2:
4495 tcg_gen_xor_i64(t0, t0, t1);
4496 break;
4497 case OPC_NOR_CP2:
4498 tcg_gen_nor_i64(t0, t0, t1);
4499 break;
4500 case OPC_AND_CP2:
4501 tcg_gen_and_i64(t0, t0, t1);
4502 break;
4503 case OPC_OR_CP2:
4504 tcg_gen_or_i64(t0, t0, t1);
4505 break;
4507 case OPC_PANDN:
4508 tcg_gen_andc_i64(t0, t1, t0);
4509 break;
4511 case OPC_PINSRH_0:
4512 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4513 break;
4514 case OPC_PINSRH_1:
4515 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4516 break;
4517 case OPC_PINSRH_2:
4518 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4519 break;
4520 case OPC_PINSRH_3:
4521 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4522 break;
4524 case OPC_PEXTRH:
4525 tcg_gen_andi_i64(t1, t1, 3);
4526 tcg_gen_shli_i64(t1, t1, 4);
4527 tcg_gen_shr_i64(t0, t0, t1);
4528 tcg_gen_ext16u_i64(t0, t0);
4529 break;
4531 case OPC_ADDU_CP2:
4532 tcg_gen_add_i64(t0, t0, t1);
4533 tcg_gen_ext32s_i64(t0, t0);
4534 break;
4535 case OPC_SUBU_CP2:
4536 tcg_gen_sub_i64(t0, t0, t1);
4537 tcg_gen_ext32s_i64(t0, t0);
4538 break;
4540 case OPC_SLL_CP2:
4541 shift_max = 32;
4542 goto do_shift;
4543 case OPC_SRL_CP2:
4544 shift_max = 32;
4545 goto do_shift;
4546 case OPC_SRA_CP2:
4547 shift_max = 32;
4548 goto do_shift;
4549 case OPC_DSLL_CP2:
4550 shift_max = 64;
4551 goto do_shift;
4552 case OPC_DSRL_CP2:
4553 shift_max = 64;
4554 goto do_shift;
4555 case OPC_DSRA_CP2:
4556 shift_max = 64;
4557 goto do_shift;
4558 do_shift:
4559 /* Make sure shift count isn't TCG undefined behaviour. */
4560 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4562 switch (opc) {
4563 case OPC_SLL_CP2:
4564 case OPC_DSLL_CP2:
4565 tcg_gen_shl_i64(t0, t0, t1);
4566 break;
4567 case OPC_SRA_CP2:
4568 case OPC_DSRA_CP2:
4570 * Since SRA is UndefinedResult without sign-extended inputs,
4571 * we can treat SRA and DSRA the same.
4573 tcg_gen_sar_i64(t0, t0, t1);
4574 break;
4575 case OPC_SRL_CP2:
4576 /* We want to shift in zeros for SRL; zero-extend first. */
4577 tcg_gen_ext32u_i64(t0, t0);
4578 /* FALLTHRU */
4579 case OPC_DSRL_CP2:
4580 tcg_gen_shr_i64(t0, t0, t1);
4581 break;
4584 if (shift_max == 32) {
4585 tcg_gen_ext32s_i64(t0, t0);
4588 /* Shifts larger than MAX produce zero. */
4589 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4590 tcg_gen_neg_i64(t1, t1);
4591 tcg_gen_and_i64(t0, t0, t1);
4592 break;
4594 case OPC_ADD_CP2:
4595 case OPC_DADD_CP2:
4597 TCGv_i64 t2 = tcg_temp_new_i64();
4598 TCGLabel *lab = gen_new_label();
4600 tcg_gen_mov_i64(t2, t0);
4601 tcg_gen_add_i64(t0, t1, t2);
4602 if (opc == OPC_ADD_CP2) {
4603 tcg_gen_ext32s_i64(t0, t0);
4605 tcg_gen_xor_i64(t1, t1, t2);
4606 tcg_gen_xor_i64(t2, t2, t0);
4607 tcg_gen_andc_i64(t1, t2, t1);
4608 tcg_temp_free_i64(t2);
4609 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4610 generate_exception(ctx, EXCP_OVERFLOW);
4611 gen_set_label(lab);
4612 break;
4615 case OPC_SUB_CP2:
4616 case OPC_DSUB_CP2:
4618 TCGv_i64 t2 = tcg_temp_new_i64();
4619 TCGLabel *lab = gen_new_label();
4621 tcg_gen_mov_i64(t2, t0);
4622 tcg_gen_sub_i64(t0, t1, t2);
4623 if (opc == OPC_SUB_CP2) {
4624 tcg_gen_ext32s_i64(t0, t0);
4626 tcg_gen_xor_i64(t1, t1, t2);
4627 tcg_gen_xor_i64(t2, t2, t0);
4628 tcg_gen_and_i64(t1, t1, t2);
4629 tcg_temp_free_i64(t2);
4630 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4631 generate_exception(ctx, EXCP_OVERFLOW);
4632 gen_set_label(lab);
4633 break;
4636 case OPC_PMULUW:
4637 tcg_gen_ext32u_i64(t0, t0);
4638 tcg_gen_ext32u_i64(t1, t1);
4639 tcg_gen_mul_i64(t0, t0, t1);
4640 break;
4642 case OPC_SEQU_CP2:
4643 case OPC_SEQ_CP2:
4644 cond = TCG_COND_EQ;
4645 goto do_cc_cond;
4646 break;
4647 case OPC_SLTU_CP2:
4648 cond = TCG_COND_LTU;
4649 goto do_cc_cond;
4650 break;
4651 case OPC_SLT_CP2:
4652 cond = TCG_COND_LT;
4653 goto do_cc_cond;
4654 break;
4655 case OPC_SLEU_CP2:
4656 cond = TCG_COND_LEU;
4657 goto do_cc_cond;
4658 break;
4659 case OPC_SLE_CP2:
4660 cond = TCG_COND_LE;
4661 do_cc_cond:
4663 int cc = (ctx->opcode >> 8) & 0x7;
4664 TCGv_i64 t64 = tcg_temp_new_i64();
4665 TCGv_i32 t32 = tcg_temp_new_i32();
4667 tcg_gen_setcond_i64(cond, t64, t0, t1);
4668 tcg_gen_extrl_i64_i32(t32, t64);
4669 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
4670 get_fp_bit(cc), 1);
4672 tcg_temp_free_i32(t32);
4673 tcg_temp_free_i64(t64);
4675 goto no_rd;
4676 break;
4677 default:
4678 MIPS_INVAL("loongson_cp2");
4679 gen_reserved_instruction(ctx);
4680 return;
4683 gen_store_fpr64(ctx, t0, rd);
4685 no_rd:
4686 tcg_temp_free_i64(t0);
4687 tcg_temp_free_i64(t1);
4690 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
4691 int rs, int rd)
4693 TCGv t0, t1, t2;
4694 TCGv_i32 fp0;
4695 #if defined(TARGET_MIPS64)
4696 int lsq_rt1 = ctx->opcode & 0x1f;
4697 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
4698 #endif
4699 int shf_offset = sextract32(ctx->opcode, 6, 8);
4701 t0 = tcg_temp_new();
4703 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
4704 #if defined(TARGET_MIPS64)
4705 case OPC_GSLQ:
4706 t1 = tcg_temp_new();
4707 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4708 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4709 ctx->default_tcg_memop_mask);
4710 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4711 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4712 ctx->default_tcg_memop_mask);
4713 gen_store_gpr(t1, rt);
4714 gen_store_gpr(t0, lsq_rt1);
4715 tcg_temp_free(t1);
4716 break;
4717 case OPC_GSLQC1:
4718 check_cp1_enabled(ctx);
4719 t1 = tcg_temp_new();
4720 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4721 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4722 ctx->default_tcg_memop_mask);
4723 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4724 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4725 ctx->default_tcg_memop_mask);
4726 gen_store_fpr64(ctx, t1, rt);
4727 gen_store_fpr64(ctx, t0, lsq_rt1);
4728 tcg_temp_free(t1);
4729 break;
4730 case OPC_GSSQ:
4731 t1 = tcg_temp_new();
4732 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4733 gen_load_gpr(t1, rt);
4734 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4735 ctx->default_tcg_memop_mask);
4736 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4737 gen_load_gpr(t1, lsq_rt1);
4738 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4739 ctx->default_tcg_memop_mask);
4740 tcg_temp_free(t1);
4741 break;
4742 case OPC_GSSQC1:
4743 check_cp1_enabled(ctx);
4744 t1 = tcg_temp_new();
4745 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4746 gen_load_fpr64(ctx, t1, rt);
4747 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4748 ctx->default_tcg_memop_mask);
4749 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4750 gen_load_fpr64(ctx, t1, lsq_rt1);
4751 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4752 ctx->default_tcg_memop_mask);
4753 tcg_temp_free(t1);
4754 break;
4755 #endif
4756 case OPC_GSSHFL:
4757 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4758 case OPC_GSLWLC1:
4759 check_cp1_enabled(ctx);
4760 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4761 t1 = tcg_temp_new();
4762 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4763 tcg_gen_andi_tl(t1, t0, 3);
4764 #ifndef TARGET_WORDS_BIGENDIAN
4765 tcg_gen_xori_tl(t1, t1, 3);
4766 #endif
4767 tcg_gen_shli_tl(t1, t1, 3);
4768 tcg_gen_andi_tl(t0, t0, ~3);
4769 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4770 tcg_gen_shl_tl(t0, t0, t1);
4771 t2 = tcg_const_tl(-1);
4772 tcg_gen_shl_tl(t2, t2, t1);
4773 fp0 = tcg_temp_new_i32();
4774 gen_load_fpr32(ctx, fp0, rt);
4775 tcg_gen_ext_i32_tl(t1, fp0);
4776 tcg_gen_andc_tl(t1, t1, t2);
4777 tcg_temp_free(t2);
4778 tcg_gen_or_tl(t0, t0, t1);
4779 tcg_temp_free(t1);
4780 #if defined(TARGET_MIPS64)
4781 tcg_gen_extrl_i64_i32(fp0, t0);
4782 #else
4783 tcg_gen_ext32s_tl(fp0, t0);
4784 #endif
4785 gen_store_fpr32(ctx, fp0, rt);
4786 tcg_temp_free_i32(fp0);
4787 break;
4788 case OPC_GSLWRC1:
4789 check_cp1_enabled(ctx);
4790 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4791 t1 = tcg_temp_new();
4792 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4793 tcg_gen_andi_tl(t1, t0, 3);
4794 #ifdef TARGET_WORDS_BIGENDIAN
4795 tcg_gen_xori_tl(t1, t1, 3);
4796 #endif
4797 tcg_gen_shli_tl(t1, t1, 3);
4798 tcg_gen_andi_tl(t0, t0, ~3);
4799 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4800 tcg_gen_shr_tl(t0, t0, t1);
4801 tcg_gen_xori_tl(t1, t1, 31);
4802 t2 = tcg_const_tl(0xfffffffeull);
4803 tcg_gen_shl_tl(t2, t2, t1);
4804 fp0 = tcg_temp_new_i32();
4805 gen_load_fpr32(ctx, fp0, rt);
4806 tcg_gen_ext_i32_tl(t1, fp0);
4807 tcg_gen_and_tl(t1, t1, t2);
4808 tcg_temp_free(t2);
4809 tcg_gen_or_tl(t0, t0, t1);
4810 tcg_temp_free(t1);
4811 #if defined(TARGET_MIPS64)
4812 tcg_gen_extrl_i64_i32(fp0, t0);
4813 #else
4814 tcg_gen_ext32s_tl(fp0, t0);
4815 #endif
4816 gen_store_fpr32(ctx, fp0, rt);
4817 tcg_temp_free_i32(fp0);
4818 break;
4819 #if defined(TARGET_MIPS64)
4820 case OPC_GSLDLC1:
4821 check_cp1_enabled(ctx);
4822 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4823 t1 = tcg_temp_new();
4824 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4825 tcg_gen_andi_tl(t1, t0, 7);
4826 #ifndef TARGET_WORDS_BIGENDIAN
4827 tcg_gen_xori_tl(t1, t1, 7);
4828 #endif
4829 tcg_gen_shli_tl(t1, t1, 3);
4830 tcg_gen_andi_tl(t0, t0, ~7);
4831 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4832 tcg_gen_shl_tl(t0, t0, t1);
4833 t2 = tcg_const_tl(-1);
4834 tcg_gen_shl_tl(t2, t2, t1);
4835 gen_load_fpr64(ctx, t1, rt);
4836 tcg_gen_andc_tl(t1, t1, t2);
4837 tcg_temp_free(t2);
4838 tcg_gen_or_tl(t0, t0, t1);
4839 tcg_temp_free(t1);
4840 gen_store_fpr64(ctx, t0, rt);
4841 break;
4842 case OPC_GSLDRC1:
4843 check_cp1_enabled(ctx);
4844 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4845 t1 = tcg_temp_new();
4846 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4847 tcg_gen_andi_tl(t1, t0, 7);
4848 #ifdef TARGET_WORDS_BIGENDIAN
4849 tcg_gen_xori_tl(t1, t1, 7);
4850 #endif
4851 tcg_gen_shli_tl(t1, t1, 3);
4852 tcg_gen_andi_tl(t0, t0, ~7);
4853 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4854 tcg_gen_shr_tl(t0, t0, t1);
4855 tcg_gen_xori_tl(t1, t1, 63);
4856 t2 = tcg_const_tl(0xfffffffffffffffeull);
4857 tcg_gen_shl_tl(t2, t2, t1);
4858 gen_load_fpr64(ctx, t1, rt);
4859 tcg_gen_and_tl(t1, t1, t2);
4860 tcg_temp_free(t2);
4861 tcg_gen_or_tl(t0, t0, t1);
4862 tcg_temp_free(t1);
4863 gen_store_fpr64(ctx, t0, rt);
4864 break;
4865 #endif
4866 default:
4867 MIPS_INVAL("loongson_gsshfl");
4868 gen_reserved_instruction(ctx);
4869 break;
4871 break;
4872 case OPC_GSSHFS:
4873 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4874 case OPC_GSSWLC1:
4875 check_cp1_enabled(ctx);
4876 t1 = tcg_temp_new();
4877 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4878 fp0 = tcg_temp_new_i32();
4879 gen_load_fpr32(ctx, fp0, rt);
4880 tcg_gen_ext_i32_tl(t1, fp0);
4881 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
4882 tcg_temp_free_i32(fp0);
4883 tcg_temp_free(t1);
4884 break;
4885 case OPC_GSSWRC1:
4886 check_cp1_enabled(ctx);
4887 t1 = tcg_temp_new();
4888 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4889 fp0 = tcg_temp_new_i32();
4890 gen_load_fpr32(ctx, fp0, rt);
4891 tcg_gen_ext_i32_tl(t1, fp0);
4892 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
4893 tcg_temp_free_i32(fp0);
4894 tcg_temp_free(t1);
4895 break;
4896 #if defined(TARGET_MIPS64)
4897 case OPC_GSSDLC1:
4898 check_cp1_enabled(ctx);
4899 t1 = tcg_temp_new();
4900 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4901 gen_load_fpr64(ctx, t1, rt);
4902 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
4903 tcg_temp_free(t1);
4904 break;
4905 case OPC_GSSDRC1:
4906 check_cp1_enabled(ctx);
4907 t1 = tcg_temp_new();
4908 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4909 gen_load_fpr64(ctx, t1, rt);
4910 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
4911 tcg_temp_free(t1);
4912 break;
4913 #endif
4914 default:
4915 MIPS_INVAL("loongson_gsshfs");
4916 gen_reserved_instruction(ctx);
4917 break;
4919 break;
4920 default:
4921 MIPS_INVAL("loongson_gslsq");
4922 gen_reserved_instruction(ctx);
4923 break;
4925 tcg_temp_free(t0);
4928 /* Loongson EXT LDC2/SDC2 */
4929 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
4930 int rs, int rd)
4932 int offset = sextract32(ctx->opcode, 3, 8);
4933 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
4934 TCGv t0, t1;
4935 TCGv_i32 fp0;
4937 /* Pre-conditions */
4938 switch (opc) {
4939 case OPC_GSLBX:
4940 case OPC_GSLHX:
4941 case OPC_GSLWX:
4942 case OPC_GSLDX:
4943 /* prefetch, implement as NOP */
4944 if (rt == 0) {
4945 return;
4947 break;
4948 case OPC_GSSBX:
4949 case OPC_GSSHX:
4950 case OPC_GSSWX:
4951 case OPC_GSSDX:
4952 break;
4953 case OPC_GSLWXC1:
4954 #if defined(TARGET_MIPS64)
4955 case OPC_GSLDXC1:
4956 #endif
4957 check_cp1_enabled(ctx);
4958 /* prefetch, implement as NOP */
4959 if (rt == 0) {
4960 return;
4962 break;
4963 case OPC_GSSWXC1:
4964 #if defined(TARGET_MIPS64)
4965 case OPC_GSSDXC1:
4966 #endif
4967 check_cp1_enabled(ctx);
4968 break;
4969 default:
4970 MIPS_INVAL("loongson_lsdc2");
4971 gen_reserved_instruction(ctx);
4972 return;
4973 break;
4976 t0 = tcg_temp_new();
4978 gen_base_offset_addr(ctx, t0, rs, offset);
4979 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4981 switch (opc) {
4982 case OPC_GSLBX:
4983 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
4984 gen_store_gpr(t0, rt);
4985 break;
4986 case OPC_GSLHX:
4987 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
4988 ctx->default_tcg_memop_mask);
4989 gen_store_gpr(t0, rt);
4990 break;
4991 case OPC_GSLWX:
4992 gen_base_offset_addr(ctx, t0, rs, offset);
4993 if (rd) {
4994 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4996 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
4997 ctx->default_tcg_memop_mask);
4998 gen_store_gpr(t0, rt);
4999 break;
5000 #if defined(TARGET_MIPS64)
5001 case OPC_GSLDX:
5002 gen_base_offset_addr(ctx, t0, rs, offset);
5003 if (rd) {
5004 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5006 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5007 ctx->default_tcg_memop_mask);
5008 gen_store_gpr(t0, rt);
5009 break;
5010 #endif
5011 case OPC_GSLWXC1:
5012 check_cp1_enabled(ctx);
5013 gen_base_offset_addr(ctx, t0, rs, offset);
5014 if (rd) {
5015 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5017 fp0 = tcg_temp_new_i32();
5018 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
5019 ctx->default_tcg_memop_mask);
5020 gen_store_fpr32(ctx, fp0, rt);
5021 tcg_temp_free_i32(fp0);
5022 break;
5023 #if defined(TARGET_MIPS64)
5024 case OPC_GSLDXC1:
5025 check_cp1_enabled(ctx);
5026 gen_base_offset_addr(ctx, t0, rs, offset);
5027 if (rd) {
5028 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5030 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5031 ctx->default_tcg_memop_mask);
5032 gen_store_fpr64(ctx, t0, rt);
5033 break;
5034 #endif
5035 case OPC_GSSBX:
5036 t1 = tcg_temp_new();
5037 gen_load_gpr(t1, rt);
5038 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
5039 tcg_temp_free(t1);
5040 break;
5041 case OPC_GSSHX:
5042 t1 = tcg_temp_new();
5043 gen_load_gpr(t1, rt);
5044 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
5045 ctx->default_tcg_memop_mask);
5046 tcg_temp_free(t1);
5047 break;
5048 case OPC_GSSWX:
5049 t1 = tcg_temp_new();
5050 gen_load_gpr(t1, rt);
5051 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
5052 ctx->default_tcg_memop_mask);
5053 tcg_temp_free(t1);
5054 break;
5055 #if defined(TARGET_MIPS64)
5056 case OPC_GSSDX:
5057 t1 = tcg_temp_new();
5058 gen_load_gpr(t1, rt);
5059 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5060 ctx->default_tcg_memop_mask);
5061 tcg_temp_free(t1);
5062 break;
5063 #endif
5064 case OPC_GSSWXC1:
5065 fp0 = tcg_temp_new_i32();
5066 gen_load_fpr32(ctx, fp0, rt);
5067 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
5068 ctx->default_tcg_memop_mask);
5069 tcg_temp_free_i32(fp0);
5070 break;
5071 #if defined(TARGET_MIPS64)
5072 case OPC_GSSDXC1:
5073 t1 = tcg_temp_new();
5074 gen_load_fpr64(ctx, t1, rt);
5075 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
5076 ctx->default_tcg_memop_mask);
5077 tcg_temp_free(t1);
5078 break;
5079 #endif
5080 default:
5081 break;
5084 tcg_temp_free(t0);
5087 /* Traps */
5088 static void gen_trap(DisasContext *ctx, uint32_t opc,
5089 int rs, int rt, int16_t imm)
5091 int cond;
5092 TCGv t0 = tcg_temp_new();
5093 TCGv t1 = tcg_temp_new();
5095 cond = 0;
5096 /* Load needed operands */
5097 switch (opc) {
5098 case OPC_TEQ:
5099 case OPC_TGE:
5100 case OPC_TGEU:
5101 case OPC_TLT:
5102 case OPC_TLTU:
5103 case OPC_TNE:
5104 /* Compare two registers */
5105 if (rs != rt) {
5106 gen_load_gpr(t0, rs);
5107 gen_load_gpr(t1, rt);
5108 cond = 1;
5110 break;
5111 case OPC_TEQI:
5112 case OPC_TGEI:
5113 case OPC_TGEIU:
5114 case OPC_TLTI:
5115 case OPC_TLTIU:
5116 case OPC_TNEI:
5117 /* Compare register to immediate */
5118 if (rs != 0 || imm != 0) {
5119 gen_load_gpr(t0, rs);
5120 tcg_gen_movi_tl(t1, (int32_t)imm);
5121 cond = 1;
5123 break;
5125 if (cond == 0) {
5126 switch (opc) {
5127 case OPC_TEQ: /* rs == rs */
5128 case OPC_TEQI: /* r0 == 0 */
5129 case OPC_TGE: /* rs >= rs */
5130 case OPC_TGEI: /* r0 >= 0 */
5131 case OPC_TGEU: /* rs >= rs unsigned */
5132 case OPC_TGEIU: /* r0 >= 0 unsigned */
5133 /* Always trap */
5134 generate_exception_end(ctx, EXCP_TRAP);
5135 break;
5136 case OPC_TLT: /* rs < rs */
5137 case OPC_TLTI: /* r0 < 0 */
5138 case OPC_TLTU: /* rs < rs unsigned */
5139 case OPC_TLTIU: /* r0 < 0 unsigned */
5140 case OPC_TNE: /* rs != rs */
5141 case OPC_TNEI: /* r0 != 0 */
5142 /* Never trap: treat as NOP. */
5143 break;
5145 } else {
5146 TCGLabel *l1 = gen_new_label();
5148 switch (opc) {
5149 case OPC_TEQ:
5150 case OPC_TEQI:
5151 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5152 break;
5153 case OPC_TGE:
5154 case OPC_TGEI:
5155 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5156 break;
5157 case OPC_TGEU:
5158 case OPC_TGEIU:
5159 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5160 break;
5161 case OPC_TLT:
5162 case OPC_TLTI:
5163 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5164 break;
5165 case OPC_TLTU:
5166 case OPC_TLTIU:
5167 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5168 break;
5169 case OPC_TNE:
5170 case OPC_TNEI:
5171 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5172 break;
5174 generate_exception(ctx, EXCP_TRAP);
5175 gen_set_label(l1);
5177 tcg_temp_free(t0);
5178 tcg_temp_free(t1);
5181 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5183 if (unlikely(ctx->base.singlestep_enabled)) {
5184 return false;
5187 #ifndef CONFIG_USER_ONLY
5188 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5189 #else
5190 return true;
5191 #endif
5194 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5196 if (use_goto_tb(ctx, dest)) {
5197 tcg_gen_goto_tb(n);
5198 gen_save_pc(dest);
5199 tcg_gen_exit_tb(ctx->base.tb, n);
5200 } else {
5201 gen_save_pc(dest);
5202 if (ctx->base.singlestep_enabled) {
5203 save_cpu_state(ctx, 0);
5204 gen_helper_raise_exception_debug(cpu_env);
5206 tcg_gen_lookup_and_goto_ptr();
5210 /* Branches (before delay slot) */
5211 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
5212 int insn_bytes,
5213 int rs, int rt, int32_t offset,
5214 int delayslot_size)
5216 target_ulong btgt = -1;
5217 int blink = 0;
5218 int bcond_compute = 0;
5219 TCGv t0 = tcg_temp_new();
5220 TCGv t1 = tcg_temp_new();
5222 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5223 #ifdef MIPS_DEBUG_DISAS
5224 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5225 TARGET_FMT_lx "\n", ctx->base.pc_next);
5226 #endif
5227 gen_reserved_instruction(ctx);
5228 goto out;
5231 /* Load needed operands */
5232 switch (opc) {
5233 case OPC_BEQ:
5234 case OPC_BEQL:
5235 case OPC_BNE:
5236 case OPC_BNEL:
5237 /* Compare two registers */
5238 if (rs != rt) {
5239 gen_load_gpr(t0, rs);
5240 gen_load_gpr(t1, rt);
5241 bcond_compute = 1;
5243 btgt = ctx->base.pc_next + insn_bytes + offset;
5244 break;
5245 case OPC_BGEZ:
5246 case OPC_BGEZAL:
5247 case OPC_BGEZALL:
5248 case OPC_BGEZL:
5249 case OPC_BGTZ:
5250 case OPC_BGTZL:
5251 case OPC_BLEZ:
5252 case OPC_BLEZL:
5253 case OPC_BLTZ:
5254 case OPC_BLTZAL:
5255 case OPC_BLTZALL:
5256 case OPC_BLTZL:
5257 /* Compare to zero */
5258 if (rs != 0) {
5259 gen_load_gpr(t0, rs);
5260 bcond_compute = 1;
5262 btgt = ctx->base.pc_next + insn_bytes + offset;
5263 break;
5264 case OPC_BPOSGE32:
5265 #if defined(TARGET_MIPS64)
5266 case OPC_BPOSGE64:
5267 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5268 #else
5269 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5270 #endif
5271 bcond_compute = 1;
5272 btgt = ctx->base.pc_next + insn_bytes + offset;
5273 break;
5274 case OPC_J:
5275 case OPC_JAL:
5276 case OPC_JALX:
5277 /* Jump to immediate */
5278 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5279 (uint32_t)offset;
5280 break;
5281 case OPC_JR:
5282 case OPC_JALR:
5283 /* Jump to register */
5284 if (offset != 0 && offset != 16) {
5286 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5287 * others are reserved.
5289 MIPS_INVAL("jump hint");
5290 gen_reserved_instruction(ctx);
5291 goto out;
5293 gen_load_gpr(btarget, rs);
5294 break;
5295 default:
5296 MIPS_INVAL("branch/jump");
5297 gen_reserved_instruction(ctx);
5298 goto out;
5300 if (bcond_compute == 0) {
5301 /* No condition to be computed */
5302 switch (opc) {
5303 case OPC_BEQ: /* rx == rx */
5304 case OPC_BEQL: /* rx == rx likely */
5305 case OPC_BGEZ: /* 0 >= 0 */
5306 case OPC_BGEZL: /* 0 >= 0 likely */
5307 case OPC_BLEZ: /* 0 <= 0 */
5308 case OPC_BLEZL: /* 0 <= 0 likely */
5309 /* Always take */
5310 ctx->hflags |= MIPS_HFLAG_B;
5311 break;
5312 case OPC_BGEZAL: /* 0 >= 0 */
5313 case OPC_BGEZALL: /* 0 >= 0 likely */
5314 /* Always take and link */
5315 blink = 31;
5316 ctx->hflags |= MIPS_HFLAG_B;
5317 break;
5318 case OPC_BNE: /* rx != rx */
5319 case OPC_BGTZ: /* 0 > 0 */
5320 case OPC_BLTZ: /* 0 < 0 */
5321 /* Treat as NOP. */
5322 goto out;
5323 case OPC_BLTZAL: /* 0 < 0 */
5325 * Handle as an unconditional branch to get correct delay
5326 * slot checking.
5328 blink = 31;
5329 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5330 ctx->hflags |= MIPS_HFLAG_B;
5331 break;
5332 case OPC_BLTZALL: /* 0 < 0 likely */
5333 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5334 /* Skip the instruction in the delay slot */
5335 ctx->base.pc_next += 4;
5336 goto out;
5337 case OPC_BNEL: /* rx != rx likely */
5338 case OPC_BGTZL: /* 0 > 0 likely */
5339 case OPC_BLTZL: /* 0 < 0 likely */
5340 /* Skip the instruction in the delay slot */
5341 ctx->base.pc_next += 4;
5342 goto out;
5343 case OPC_J:
5344 ctx->hflags |= MIPS_HFLAG_B;
5345 break;
5346 case OPC_JALX:
5347 ctx->hflags |= MIPS_HFLAG_BX;
5348 /* Fallthrough */
5349 case OPC_JAL:
5350 blink = 31;
5351 ctx->hflags |= MIPS_HFLAG_B;
5352 break;
5353 case OPC_JR:
5354 ctx->hflags |= MIPS_HFLAG_BR;
5355 break;
5356 case OPC_JALR:
5357 blink = rt;
5358 ctx->hflags |= MIPS_HFLAG_BR;
5359 break;
5360 default:
5361 MIPS_INVAL("branch/jump");
5362 gen_reserved_instruction(ctx);
5363 goto out;
5365 } else {
5366 switch (opc) {
5367 case OPC_BEQ:
5368 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5369 goto not_likely;
5370 case OPC_BEQL:
5371 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5372 goto likely;
5373 case OPC_BNE:
5374 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5375 goto not_likely;
5376 case OPC_BNEL:
5377 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5378 goto likely;
5379 case OPC_BGEZ:
5380 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5381 goto not_likely;
5382 case OPC_BGEZL:
5383 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5384 goto likely;
5385 case OPC_BGEZAL:
5386 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5387 blink = 31;
5388 goto not_likely;
5389 case OPC_BGEZALL:
5390 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5391 blink = 31;
5392 goto likely;
5393 case OPC_BGTZ:
5394 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5395 goto not_likely;
5396 case OPC_BGTZL:
5397 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5398 goto likely;
5399 case OPC_BLEZ:
5400 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5401 goto not_likely;
5402 case OPC_BLEZL:
5403 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5404 goto likely;
5405 case OPC_BLTZ:
5406 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5407 goto not_likely;
5408 case OPC_BLTZL:
5409 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5410 goto likely;
5411 case OPC_BPOSGE32:
5412 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5413 goto not_likely;
5414 #if defined(TARGET_MIPS64)
5415 case OPC_BPOSGE64:
5416 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5417 goto not_likely;
5418 #endif
5419 case OPC_BLTZAL:
5420 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5421 blink = 31;
5422 not_likely:
5423 ctx->hflags |= MIPS_HFLAG_BC;
5424 break;
5425 case OPC_BLTZALL:
5426 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5427 blink = 31;
5428 likely:
5429 ctx->hflags |= MIPS_HFLAG_BL;
5430 break;
5431 default:
5432 MIPS_INVAL("conditional branch/jump");
5433 gen_reserved_instruction(ctx);
5434 goto out;
5438 ctx->btarget = btgt;
5440 switch (delayslot_size) {
5441 case 2:
5442 ctx->hflags |= MIPS_HFLAG_BDS16;
5443 break;
5444 case 4:
5445 ctx->hflags |= MIPS_HFLAG_BDS32;
5446 break;
5449 if (blink > 0) {
5450 int post_delay = insn_bytes + delayslot_size;
5451 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5453 tcg_gen_movi_tl(cpu_gpr[blink],
5454 ctx->base.pc_next + post_delay + lowbit);
5457 out:
5458 if (insn_bytes == 2) {
5459 ctx->hflags |= MIPS_HFLAG_B16;
5461 tcg_temp_free(t0);
5462 tcg_temp_free(t1);
5466 /* nanoMIPS Branches */
5467 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5468 int insn_bytes,
5469 int rs, int rt, int32_t offset)
5471 target_ulong btgt = -1;
5472 int bcond_compute = 0;
5473 TCGv t0 = tcg_temp_new();
5474 TCGv t1 = tcg_temp_new();
5476 /* Load needed operands */
5477 switch (opc) {
5478 case OPC_BEQ:
5479 case OPC_BNE:
5480 /* Compare two registers */
5481 if (rs != rt) {
5482 gen_load_gpr(t0, rs);
5483 gen_load_gpr(t1, rt);
5484 bcond_compute = 1;
5486 btgt = ctx->base.pc_next + insn_bytes + offset;
5487 break;
5488 case OPC_BGEZAL:
5489 /* Compare to zero */
5490 if (rs != 0) {
5491 gen_load_gpr(t0, rs);
5492 bcond_compute = 1;
5494 btgt = ctx->base.pc_next + insn_bytes + offset;
5495 break;
5496 case OPC_BPOSGE32:
5497 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5498 bcond_compute = 1;
5499 btgt = ctx->base.pc_next + insn_bytes + offset;
5500 break;
5501 case OPC_JR:
5502 case OPC_JALR:
5503 /* Jump to register */
5504 if (offset != 0 && offset != 16) {
5506 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5507 * others are reserved.
5509 MIPS_INVAL("jump hint");
5510 gen_reserved_instruction(ctx);
5511 goto out;
5513 gen_load_gpr(btarget, rs);
5514 break;
5515 default:
5516 MIPS_INVAL("branch/jump");
5517 gen_reserved_instruction(ctx);
5518 goto out;
5520 if (bcond_compute == 0) {
5521 /* No condition to be computed */
5522 switch (opc) {
5523 case OPC_BEQ: /* rx == rx */
5524 /* Always take */
5525 ctx->hflags |= MIPS_HFLAG_B;
5526 break;
5527 case OPC_BGEZAL: /* 0 >= 0 */
5528 /* Always take and link */
5529 tcg_gen_movi_tl(cpu_gpr[31],
5530 ctx->base.pc_next + insn_bytes);
5531 ctx->hflags |= MIPS_HFLAG_B;
5532 break;
5533 case OPC_BNE: /* rx != rx */
5534 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5535 /* Skip the instruction in the delay slot */
5536 ctx->base.pc_next += 4;
5537 goto out;
5538 case OPC_JR:
5539 ctx->hflags |= MIPS_HFLAG_BR;
5540 break;
5541 case OPC_JALR:
5542 if (rt > 0) {
5543 tcg_gen_movi_tl(cpu_gpr[rt],
5544 ctx->base.pc_next + insn_bytes);
5546 ctx->hflags |= MIPS_HFLAG_BR;
5547 break;
5548 default:
5549 MIPS_INVAL("branch/jump");
5550 gen_reserved_instruction(ctx);
5551 goto out;
5553 } else {
5554 switch (opc) {
5555 case OPC_BEQ:
5556 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5557 goto not_likely;
5558 case OPC_BNE:
5559 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5560 goto not_likely;
5561 case OPC_BGEZAL:
5562 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5563 tcg_gen_movi_tl(cpu_gpr[31],
5564 ctx->base.pc_next + insn_bytes);
5565 goto not_likely;
5566 case OPC_BPOSGE32:
5567 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5568 not_likely:
5569 ctx->hflags |= MIPS_HFLAG_BC;
5570 break;
5571 default:
5572 MIPS_INVAL("conditional branch/jump");
5573 gen_reserved_instruction(ctx);
5574 goto out;
5578 ctx->btarget = btgt;
5580 out:
5581 if (insn_bytes == 2) {
5582 ctx->hflags |= MIPS_HFLAG_B16;
5584 tcg_temp_free(t0);
5585 tcg_temp_free(t1);
5589 /* special3 bitfield operations */
5590 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
5591 int rs, int lsb, int msb)
5593 TCGv t0 = tcg_temp_new();
5594 TCGv t1 = tcg_temp_new();
5596 gen_load_gpr(t1, rs);
5597 switch (opc) {
5598 case OPC_EXT:
5599 if (lsb + msb > 31) {
5600 goto fail;
5602 if (msb != 31) {
5603 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5604 } else {
5606 * The two checks together imply that lsb == 0,
5607 * so this is a simple sign-extension.
5609 tcg_gen_ext32s_tl(t0, t1);
5611 break;
5612 #if defined(TARGET_MIPS64)
5613 case OPC_DEXTU:
5614 lsb += 32;
5615 goto do_dext;
5616 case OPC_DEXTM:
5617 msb += 32;
5618 goto do_dext;
5619 case OPC_DEXT:
5620 do_dext:
5621 if (lsb + msb > 63) {
5622 goto fail;
5624 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5625 break;
5626 #endif
5627 case OPC_INS:
5628 if (lsb > msb) {
5629 goto fail;
5631 gen_load_gpr(t0, rt);
5632 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5633 tcg_gen_ext32s_tl(t0, t0);
5634 break;
5635 #if defined(TARGET_MIPS64)
5636 case OPC_DINSU:
5637 lsb += 32;
5638 /* FALLTHRU */
5639 case OPC_DINSM:
5640 msb += 32;
5641 /* FALLTHRU */
5642 case OPC_DINS:
5643 if (lsb > msb) {
5644 goto fail;
5646 gen_load_gpr(t0, rt);
5647 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5648 break;
5649 #endif
5650 default:
5651 fail:
5652 MIPS_INVAL("bitops");
5653 gen_reserved_instruction(ctx);
5654 tcg_temp_free(t0);
5655 tcg_temp_free(t1);
5656 return;
5658 gen_store_gpr(t0, rt);
5659 tcg_temp_free(t0);
5660 tcg_temp_free(t1);
5663 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
5665 TCGv t0;
5667 if (rd == 0) {
5668 /* If no destination, treat it as a NOP. */
5669 return;
5672 t0 = tcg_temp_new();
5673 gen_load_gpr(t0, rt);
5674 switch (op2) {
5675 case OPC_WSBH:
5677 TCGv t1 = tcg_temp_new();
5678 TCGv t2 = tcg_const_tl(0x00FF00FF);
5680 tcg_gen_shri_tl(t1, t0, 8);
5681 tcg_gen_and_tl(t1, t1, t2);
5682 tcg_gen_and_tl(t0, t0, t2);
5683 tcg_gen_shli_tl(t0, t0, 8);
5684 tcg_gen_or_tl(t0, t0, t1);
5685 tcg_temp_free(t2);
5686 tcg_temp_free(t1);
5687 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5689 break;
5690 case OPC_SEB:
5691 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
5692 break;
5693 case OPC_SEH:
5694 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
5695 break;
5696 #if defined(TARGET_MIPS64)
5697 case OPC_DSBH:
5699 TCGv t1 = tcg_temp_new();
5700 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
5702 tcg_gen_shri_tl(t1, t0, 8);
5703 tcg_gen_and_tl(t1, t1, t2);
5704 tcg_gen_and_tl(t0, t0, t2);
5705 tcg_gen_shli_tl(t0, t0, 8);
5706 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5707 tcg_temp_free(t2);
5708 tcg_temp_free(t1);
5710 break;
5711 case OPC_DSHD:
5713 TCGv t1 = tcg_temp_new();
5714 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
5716 tcg_gen_shri_tl(t1, t0, 16);
5717 tcg_gen_and_tl(t1, t1, t2);
5718 tcg_gen_and_tl(t0, t0, t2);
5719 tcg_gen_shli_tl(t0, t0, 16);
5720 tcg_gen_or_tl(t0, t0, t1);
5721 tcg_gen_shri_tl(t1, t0, 32);
5722 tcg_gen_shli_tl(t0, t0, 32);
5723 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5724 tcg_temp_free(t2);
5725 tcg_temp_free(t1);
5727 break;
5728 #endif
5729 default:
5730 MIPS_INVAL("bsfhl");
5731 gen_reserved_instruction(ctx);
5732 tcg_temp_free(t0);
5733 return;
5735 tcg_temp_free(t0);
5738 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
5739 int rt, int bits)
5741 TCGv t0;
5742 if (rd == 0) {
5743 /* Treat as NOP. */
5744 return;
5746 t0 = tcg_temp_new();
5747 if (bits == 0 || bits == wordsz) {
5748 if (bits == 0) {
5749 gen_load_gpr(t0, rt);
5750 } else {
5751 gen_load_gpr(t0, rs);
5753 switch (wordsz) {
5754 case 32:
5755 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5756 break;
5757 #if defined(TARGET_MIPS64)
5758 case 64:
5759 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5760 break;
5761 #endif
5763 } else {
5764 TCGv t1 = tcg_temp_new();
5765 gen_load_gpr(t0, rt);
5766 gen_load_gpr(t1, rs);
5767 switch (wordsz) {
5768 case 32:
5770 TCGv_i64 t2 = tcg_temp_new_i64();
5771 tcg_gen_concat_tl_i64(t2, t1, t0);
5772 tcg_gen_shri_i64(t2, t2, 32 - bits);
5773 gen_move_low32(cpu_gpr[rd], t2);
5774 tcg_temp_free_i64(t2);
5776 break;
5777 #if defined(TARGET_MIPS64)
5778 case 64:
5779 tcg_gen_shli_tl(t0, t0, bits);
5780 tcg_gen_shri_tl(t1, t1, 64 - bits);
5781 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5782 break;
5783 #endif
5785 tcg_temp_free(t1);
5788 tcg_temp_free(t0);
5791 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5792 int bp)
5794 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5797 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5798 int shift)
5800 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5803 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5805 TCGv t0;
5806 if (rd == 0) {
5807 /* Treat as NOP. */
5808 return;
5810 t0 = tcg_temp_new();
5811 gen_load_gpr(t0, rt);
5812 switch (opc) {
5813 case OPC_BITSWAP:
5814 gen_helper_bitswap(cpu_gpr[rd], t0);
5815 break;
5816 #if defined(TARGET_MIPS64)
5817 case OPC_DBITSWAP:
5818 gen_helper_dbitswap(cpu_gpr[rd], t0);
5819 break;
5820 #endif
5822 tcg_temp_free(t0);
5825 #ifndef CONFIG_USER_ONLY
5826 /* CP0 (MMU and control) */
5827 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5829 TCGv_i64 t0 = tcg_temp_new_i64();
5830 TCGv_i64 t1 = tcg_temp_new_i64();
5832 tcg_gen_ext_tl_i64(t0, arg);
5833 tcg_gen_ld_i64(t1, cpu_env, off);
5834 #if defined(TARGET_MIPS64)
5835 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5836 #else
5837 tcg_gen_concat32_i64(t1, t1, t0);
5838 #endif
5839 tcg_gen_st_i64(t1, cpu_env, off);
5840 tcg_temp_free_i64(t1);
5841 tcg_temp_free_i64(t0);
5844 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5846 TCGv_i64 t0 = tcg_temp_new_i64();
5847 TCGv_i64 t1 = tcg_temp_new_i64();
5849 tcg_gen_ext_tl_i64(t0, arg);
5850 tcg_gen_ld_i64(t1, cpu_env, off);
5851 tcg_gen_concat32_i64(t1, t1, t0);
5852 tcg_gen_st_i64(t1, cpu_env, off);
5853 tcg_temp_free_i64(t1);
5854 tcg_temp_free_i64(t0);
5857 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5859 TCGv_i64 t0 = tcg_temp_new_i64();
5861 tcg_gen_ld_i64(t0, cpu_env, off);
5862 #if defined(TARGET_MIPS64)
5863 tcg_gen_shri_i64(t0, t0, 30);
5864 #else
5865 tcg_gen_shri_i64(t0, t0, 32);
5866 #endif
5867 gen_move_low32(arg, t0);
5868 tcg_temp_free_i64(t0);
5871 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5873 TCGv_i64 t0 = tcg_temp_new_i64();
5875 tcg_gen_ld_i64(t0, cpu_env, off);
5876 tcg_gen_shri_i64(t0, t0, 32 + shift);
5877 gen_move_low32(arg, t0);
5878 tcg_temp_free_i64(t0);
5881 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
5883 TCGv_i32 t0 = tcg_temp_new_i32();
5885 tcg_gen_ld_i32(t0, cpu_env, off);
5886 tcg_gen_ext_i32_tl(arg, t0);
5887 tcg_temp_free_i32(t0);
5890 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
5892 tcg_gen_ld_tl(arg, cpu_env, off);
5893 tcg_gen_ext32s_tl(arg, arg);
5896 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
5898 TCGv_i32 t0 = tcg_temp_new_i32();
5900 tcg_gen_trunc_tl_i32(t0, arg);
5901 tcg_gen_st_i32(t0, cpu_env, off);
5902 tcg_temp_free_i32(t0);
5905 #define CP0_CHECK(c) \
5906 do { \
5907 if (!(c)) { \
5908 goto cp0_unimplemented; \
5910 } while (0)
5912 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5914 const char *register_name = "invalid";
5916 switch (reg) {
5917 case CP0_REGISTER_02:
5918 switch (sel) {
5919 case 0:
5920 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5921 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5922 register_name = "EntryLo0";
5923 break;
5924 default:
5925 goto cp0_unimplemented;
5927 break;
5928 case CP0_REGISTER_03:
5929 switch (sel) {
5930 case CP0_REG03__ENTRYLO1:
5931 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5932 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5933 register_name = "EntryLo1";
5934 break;
5935 default:
5936 goto cp0_unimplemented;
5938 break;
5939 case CP0_REGISTER_09:
5940 switch (sel) {
5941 case CP0_REG09__SAAR:
5942 CP0_CHECK(ctx->saar);
5943 gen_helper_mfhc0_saar(arg, cpu_env);
5944 register_name = "SAAR";
5945 break;
5946 default:
5947 goto cp0_unimplemented;
5949 break;
5950 case CP0_REGISTER_17:
5951 switch (sel) {
5952 case CP0_REG17__LLADDR:
5953 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
5954 ctx->CP0_LLAddr_shift);
5955 register_name = "LLAddr";
5956 break;
5957 case CP0_REG17__MAAR:
5958 CP0_CHECK(ctx->mrp);
5959 gen_helper_mfhc0_maar(arg, cpu_env);
5960 register_name = "MAAR";
5961 break;
5962 default:
5963 goto cp0_unimplemented;
5965 break;
5966 case CP0_REGISTER_19:
5967 switch (sel) {
5968 case CP0_REG19__WATCHHI0:
5969 case CP0_REG19__WATCHHI1:
5970 case CP0_REG19__WATCHHI2:
5971 case CP0_REG19__WATCHHI3:
5972 case CP0_REG19__WATCHHI4:
5973 case CP0_REG19__WATCHHI5:
5974 case CP0_REG19__WATCHHI6:
5975 case CP0_REG19__WATCHHI7:
5976 /* upper 32 bits are only available when Config5MI != 0 */
5977 CP0_CHECK(ctx->mi);
5978 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
5979 register_name = "WatchHi";
5980 break;
5981 default:
5982 goto cp0_unimplemented;
5984 break;
5985 case CP0_REGISTER_28:
5986 switch (sel) {
5987 case 0:
5988 case 2:
5989 case 4:
5990 case 6:
5991 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5992 register_name = "TagLo";
5993 break;
5994 default:
5995 goto cp0_unimplemented;
5997 break;
5998 default:
5999 goto cp0_unimplemented;
6001 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6002 return;
6004 cp0_unimplemented:
6005 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6006 register_name, reg, sel);
6007 tcg_gen_movi_tl(arg, 0);
6010 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6012 const char *register_name = "invalid";
6013 uint64_t mask = ctx->PAMask >> 36;
6015 switch (reg) {
6016 case CP0_REGISTER_02:
6017 switch (sel) {
6018 case 0:
6019 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6020 tcg_gen_andi_tl(arg, arg, mask);
6021 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6022 register_name = "EntryLo0";
6023 break;
6024 default:
6025 goto cp0_unimplemented;
6027 break;
6028 case CP0_REGISTER_03:
6029 switch (sel) {
6030 case CP0_REG03__ENTRYLO1:
6031 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6032 tcg_gen_andi_tl(arg, arg, mask);
6033 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6034 register_name = "EntryLo1";
6035 break;
6036 default:
6037 goto cp0_unimplemented;
6039 break;
6040 case CP0_REGISTER_09:
6041 switch (sel) {
6042 case CP0_REG09__SAAR:
6043 CP0_CHECK(ctx->saar);
6044 gen_helper_mthc0_saar(cpu_env, arg);
6045 register_name = "SAAR";
6046 break;
6047 default:
6048 goto cp0_unimplemented;
6050 break;
6051 case CP0_REGISTER_17:
6052 switch (sel) {
6053 case CP0_REG17__LLADDR:
6055 * LLAddr is read-only (the only exception is bit 0 if LLB is
6056 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6057 * relevant for modern MIPS cores supporting MTHC0, therefore
6058 * treating MTHC0 to LLAddr as NOP.
6060 register_name = "LLAddr";
6061 break;
6062 case CP0_REG17__MAAR:
6063 CP0_CHECK(ctx->mrp);
6064 gen_helper_mthc0_maar(cpu_env, arg);
6065 register_name = "MAAR";
6066 break;
6067 default:
6068 goto cp0_unimplemented;
6070 break;
6071 case CP0_REGISTER_19:
6072 switch (sel) {
6073 case CP0_REG19__WATCHHI0:
6074 case CP0_REG19__WATCHHI1:
6075 case CP0_REG19__WATCHHI2:
6076 case CP0_REG19__WATCHHI3:
6077 case CP0_REG19__WATCHHI4:
6078 case CP0_REG19__WATCHHI5:
6079 case CP0_REG19__WATCHHI6:
6080 case CP0_REG19__WATCHHI7:
6081 /* upper 32 bits are only available when Config5MI != 0 */
6082 CP0_CHECK(ctx->mi);
6083 gen_helper_0e1i(mthc0_watchhi, arg, sel);
6084 register_name = "WatchHi";
6085 break;
6086 default:
6087 goto cp0_unimplemented;
6089 break;
6090 case CP0_REGISTER_28:
6091 switch (sel) {
6092 case 0:
6093 case 2:
6094 case 4:
6095 case 6:
6096 tcg_gen_andi_tl(arg, arg, mask);
6097 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6098 register_name = "TagLo";
6099 break;
6100 default:
6101 goto cp0_unimplemented;
6103 break;
6104 default:
6105 goto cp0_unimplemented;
6107 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6109 cp0_unimplemented:
6110 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6111 register_name, reg, sel);
6114 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6116 if (ctx->insn_flags & ISA_MIPS_R6) {
6117 tcg_gen_movi_tl(arg, 0);
6118 } else {
6119 tcg_gen_movi_tl(arg, ~0);
6123 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6125 const char *register_name = "invalid";
6127 if (sel != 0) {
6128 check_insn(ctx, ISA_MIPS_R1);
6131 switch (reg) {
6132 case CP0_REGISTER_00:
6133 switch (sel) {
6134 case CP0_REG00__INDEX:
6135 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6136 register_name = "Index";
6137 break;
6138 case CP0_REG00__MVPCONTROL:
6139 CP0_CHECK(ctx->insn_flags & ASE_MT);
6140 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6141 register_name = "MVPControl";
6142 break;
6143 case CP0_REG00__MVPCONF0:
6144 CP0_CHECK(ctx->insn_flags & ASE_MT);
6145 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6146 register_name = "MVPConf0";
6147 break;
6148 case CP0_REG00__MVPCONF1:
6149 CP0_CHECK(ctx->insn_flags & ASE_MT);
6150 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6151 register_name = "MVPConf1";
6152 break;
6153 case CP0_REG00__VPCONTROL:
6154 CP0_CHECK(ctx->vp);
6155 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6156 register_name = "VPControl";
6157 break;
6158 default:
6159 goto cp0_unimplemented;
6161 break;
6162 case CP0_REGISTER_01:
6163 switch (sel) {
6164 case CP0_REG01__RANDOM:
6165 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6166 gen_helper_mfc0_random(arg, cpu_env);
6167 register_name = "Random";
6168 break;
6169 case CP0_REG01__VPECONTROL:
6170 CP0_CHECK(ctx->insn_flags & ASE_MT);
6171 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6172 register_name = "VPEControl";
6173 break;
6174 case CP0_REG01__VPECONF0:
6175 CP0_CHECK(ctx->insn_flags & ASE_MT);
6176 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6177 register_name = "VPEConf0";
6178 break;
6179 case CP0_REG01__VPECONF1:
6180 CP0_CHECK(ctx->insn_flags & ASE_MT);
6181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6182 register_name = "VPEConf1";
6183 break;
6184 case CP0_REG01__YQMASK:
6185 CP0_CHECK(ctx->insn_flags & ASE_MT);
6186 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6187 register_name = "YQMask";
6188 break;
6189 case CP0_REG01__VPESCHEDULE:
6190 CP0_CHECK(ctx->insn_flags & ASE_MT);
6191 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6192 register_name = "VPESchedule";
6193 break;
6194 case CP0_REG01__VPESCHEFBACK:
6195 CP0_CHECK(ctx->insn_flags & ASE_MT);
6196 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6197 register_name = "VPEScheFBack";
6198 break;
6199 case CP0_REG01__VPEOPT:
6200 CP0_CHECK(ctx->insn_flags & ASE_MT);
6201 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6202 register_name = "VPEOpt";
6203 break;
6204 default:
6205 goto cp0_unimplemented;
6207 break;
6208 case CP0_REGISTER_02:
6209 switch (sel) {
6210 case CP0_REG02__ENTRYLO0:
6212 TCGv_i64 tmp = tcg_temp_new_i64();
6213 tcg_gen_ld_i64(tmp, cpu_env,
6214 offsetof(CPUMIPSState, CP0_EntryLo0));
6215 #if defined(TARGET_MIPS64)
6216 if (ctx->rxi) {
6217 /* Move RI/XI fields to bits 31:30 */
6218 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6219 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6221 #endif
6222 gen_move_low32(arg, tmp);
6223 tcg_temp_free_i64(tmp);
6225 register_name = "EntryLo0";
6226 break;
6227 case CP0_REG02__TCSTATUS:
6228 CP0_CHECK(ctx->insn_flags & ASE_MT);
6229 gen_helper_mfc0_tcstatus(arg, cpu_env);
6230 register_name = "TCStatus";
6231 break;
6232 case CP0_REG02__TCBIND:
6233 CP0_CHECK(ctx->insn_flags & ASE_MT);
6234 gen_helper_mfc0_tcbind(arg, cpu_env);
6235 register_name = "TCBind";
6236 break;
6237 case CP0_REG02__TCRESTART:
6238 CP0_CHECK(ctx->insn_flags & ASE_MT);
6239 gen_helper_mfc0_tcrestart(arg, cpu_env);
6240 register_name = "TCRestart";
6241 break;
6242 case CP0_REG02__TCHALT:
6243 CP0_CHECK(ctx->insn_flags & ASE_MT);
6244 gen_helper_mfc0_tchalt(arg, cpu_env);
6245 register_name = "TCHalt";
6246 break;
6247 case CP0_REG02__TCCONTEXT:
6248 CP0_CHECK(ctx->insn_flags & ASE_MT);
6249 gen_helper_mfc0_tccontext(arg, cpu_env);
6250 register_name = "TCContext";
6251 break;
6252 case CP0_REG02__TCSCHEDULE:
6253 CP0_CHECK(ctx->insn_flags & ASE_MT);
6254 gen_helper_mfc0_tcschedule(arg, cpu_env);
6255 register_name = "TCSchedule";
6256 break;
6257 case CP0_REG02__TCSCHEFBACK:
6258 CP0_CHECK(ctx->insn_flags & ASE_MT);
6259 gen_helper_mfc0_tcschefback(arg, cpu_env);
6260 register_name = "TCScheFBack";
6261 break;
6262 default:
6263 goto cp0_unimplemented;
6265 break;
6266 case CP0_REGISTER_03:
6267 switch (sel) {
6268 case CP0_REG03__ENTRYLO1:
6270 TCGv_i64 tmp = tcg_temp_new_i64();
6271 tcg_gen_ld_i64(tmp, cpu_env,
6272 offsetof(CPUMIPSState, CP0_EntryLo1));
6273 #if defined(TARGET_MIPS64)
6274 if (ctx->rxi) {
6275 /* Move RI/XI fields to bits 31:30 */
6276 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6277 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6279 #endif
6280 gen_move_low32(arg, tmp);
6281 tcg_temp_free_i64(tmp);
6283 register_name = "EntryLo1";
6284 break;
6285 case CP0_REG03__GLOBALNUM:
6286 CP0_CHECK(ctx->vp);
6287 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6288 register_name = "GlobalNumber";
6289 break;
6290 default:
6291 goto cp0_unimplemented;
6293 break;
6294 case CP0_REGISTER_04:
6295 switch (sel) {
6296 case CP0_REG04__CONTEXT:
6297 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6298 tcg_gen_ext32s_tl(arg, arg);
6299 register_name = "Context";
6300 break;
6301 case CP0_REG04__CONTEXTCONFIG:
6302 /* SmartMIPS ASE */
6303 /* gen_helper_mfc0_contextconfig(arg); */
6304 register_name = "ContextConfig";
6305 goto cp0_unimplemented;
6306 case CP0_REG04__USERLOCAL:
6307 CP0_CHECK(ctx->ulri);
6308 tcg_gen_ld_tl(arg, cpu_env,
6309 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6310 tcg_gen_ext32s_tl(arg, arg);
6311 register_name = "UserLocal";
6312 break;
6313 case CP0_REG04__MMID:
6314 CP0_CHECK(ctx->mi);
6315 gen_helper_mtc0_memorymapid(cpu_env, arg);
6316 register_name = "MMID";
6317 break;
6318 default:
6319 goto cp0_unimplemented;
6321 break;
6322 case CP0_REGISTER_05:
6323 switch (sel) {
6324 case CP0_REG05__PAGEMASK:
6325 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6326 register_name = "PageMask";
6327 break;
6328 case CP0_REG05__PAGEGRAIN:
6329 check_insn(ctx, ISA_MIPS_R2);
6330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6331 register_name = "PageGrain";
6332 break;
6333 case CP0_REG05__SEGCTL0:
6334 CP0_CHECK(ctx->sc);
6335 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6336 tcg_gen_ext32s_tl(arg, arg);
6337 register_name = "SegCtl0";
6338 break;
6339 case CP0_REG05__SEGCTL1:
6340 CP0_CHECK(ctx->sc);
6341 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6342 tcg_gen_ext32s_tl(arg, arg);
6343 register_name = "SegCtl1";
6344 break;
6345 case CP0_REG05__SEGCTL2:
6346 CP0_CHECK(ctx->sc);
6347 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6348 tcg_gen_ext32s_tl(arg, arg);
6349 register_name = "SegCtl2";
6350 break;
6351 case CP0_REG05__PWBASE:
6352 check_pw(ctx);
6353 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6354 register_name = "PWBase";
6355 break;
6356 case CP0_REG05__PWFIELD:
6357 check_pw(ctx);
6358 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6359 register_name = "PWField";
6360 break;
6361 case CP0_REG05__PWSIZE:
6362 check_pw(ctx);
6363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6364 register_name = "PWSize";
6365 break;
6366 default:
6367 goto cp0_unimplemented;
6369 break;
6370 case CP0_REGISTER_06:
6371 switch (sel) {
6372 case CP0_REG06__WIRED:
6373 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6374 register_name = "Wired";
6375 break;
6376 case CP0_REG06__SRSCONF0:
6377 check_insn(ctx, ISA_MIPS_R2);
6378 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6379 register_name = "SRSConf0";
6380 break;
6381 case CP0_REG06__SRSCONF1:
6382 check_insn(ctx, ISA_MIPS_R2);
6383 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6384 register_name = "SRSConf1";
6385 break;
6386 case CP0_REG06__SRSCONF2:
6387 check_insn(ctx, ISA_MIPS_R2);
6388 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6389 register_name = "SRSConf2";
6390 break;
6391 case CP0_REG06__SRSCONF3:
6392 check_insn(ctx, ISA_MIPS_R2);
6393 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6394 register_name = "SRSConf3";
6395 break;
6396 case CP0_REG06__SRSCONF4:
6397 check_insn(ctx, ISA_MIPS_R2);
6398 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6399 register_name = "SRSConf4";
6400 break;
6401 case CP0_REG06__PWCTL:
6402 check_pw(ctx);
6403 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6404 register_name = "PWCtl";
6405 break;
6406 default:
6407 goto cp0_unimplemented;
6409 break;
6410 case CP0_REGISTER_07:
6411 switch (sel) {
6412 case CP0_REG07__HWRENA:
6413 check_insn(ctx, ISA_MIPS_R2);
6414 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6415 register_name = "HWREna";
6416 break;
6417 default:
6418 goto cp0_unimplemented;
6420 break;
6421 case CP0_REGISTER_08:
6422 switch (sel) {
6423 case CP0_REG08__BADVADDR:
6424 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6425 tcg_gen_ext32s_tl(arg, arg);
6426 register_name = "BadVAddr";
6427 break;
6428 case CP0_REG08__BADINSTR:
6429 CP0_CHECK(ctx->bi);
6430 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6431 register_name = "BadInstr";
6432 break;
6433 case CP0_REG08__BADINSTRP:
6434 CP0_CHECK(ctx->bp);
6435 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6436 register_name = "BadInstrP";
6437 break;
6438 case CP0_REG08__BADINSTRX:
6439 CP0_CHECK(ctx->bi);
6440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6441 tcg_gen_andi_tl(arg, arg, ~0xffff);
6442 register_name = "BadInstrX";
6443 break;
6444 default:
6445 goto cp0_unimplemented;
6447 break;
6448 case CP0_REGISTER_09:
6449 switch (sel) {
6450 case CP0_REG09__COUNT:
6451 /* Mark as an IO operation because we read the time. */
6452 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6453 gen_io_start();
6455 gen_helper_mfc0_count(arg, cpu_env);
6457 * Break the TB to be able to take timer interrupts immediately
6458 * after reading count. DISAS_STOP isn't sufficient, we need to
6459 * ensure we break completely out of translated code.
6461 gen_save_pc(ctx->base.pc_next + 4);
6462 ctx->base.is_jmp = DISAS_EXIT;
6463 register_name = "Count";
6464 break;
6465 case CP0_REG09__SAARI:
6466 CP0_CHECK(ctx->saar);
6467 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
6468 register_name = "SAARI";
6469 break;
6470 case CP0_REG09__SAAR:
6471 CP0_CHECK(ctx->saar);
6472 gen_helper_mfc0_saar(arg, cpu_env);
6473 register_name = "SAAR";
6474 break;
6475 default:
6476 goto cp0_unimplemented;
6478 break;
6479 case CP0_REGISTER_10:
6480 switch (sel) {
6481 case CP0_REG10__ENTRYHI:
6482 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6483 tcg_gen_ext32s_tl(arg, arg);
6484 register_name = "EntryHi";
6485 break;
6486 default:
6487 goto cp0_unimplemented;
6489 break;
6490 case CP0_REGISTER_11:
6491 switch (sel) {
6492 case CP0_REG11__COMPARE:
6493 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6494 register_name = "Compare";
6495 break;
6496 /* 6,7 are implementation dependent */
6497 default:
6498 goto cp0_unimplemented;
6500 break;
6501 case CP0_REGISTER_12:
6502 switch (sel) {
6503 case CP0_REG12__STATUS:
6504 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6505 register_name = "Status";
6506 break;
6507 case CP0_REG12__INTCTL:
6508 check_insn(ctx, ISA_MIPS_R2);
6509 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6510 register_name = "IntCtl";
6511 break;
6512 case CP0_REG12__SRSCTL:
6513 check_insn(ctx, ISA_MIPS_R2);
6514 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6515 register_name = "SRSCtl";
6516 break;
6517 case CP0_REG12__SRSMAP:
6518 check_insn(ctx, ISA_MIPS_R2);
6519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6520 register_name = "SRSMap";
6521 break;
6522 default:
6523 goto cp0_unimplemented;
6525 break;
6526 case CP0_REGISTER_13:
6527 switch (sel) {
6528 case CP0_REG13__CAUSE:
6529 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6530 register_name = "Cause";
6531 break;
6532 default:
6533 goto cp0_unimplemented;
6535 break;
6536 case CP0_REGISTER_14:
6537 switch (sel) {
6538 case CP0_REG14__EPC:
6539 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6540 tcg_gen_ext32s_tl(arg, arg);
6541 register_name = "EPC";
6542 break;
6543 default:
6544 goto cp0_unimplemented;
6546 break;
6547 case CP0_REGISTER_15:
6548 switch (sel) {
6549 case CP0_REG15__PRID:
6550 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6551 register_name = "PRid";
6552 break;
6553 case CP0_REG15__EBASE:
6554 check_insn(ctx, ISA_MIPS_R2);
6555 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6556 tcg_gen_ext32s_tl(arg, arg);
6557 register_name = "EBase";
6558 break;
6559 case CP0_REG15__CMGCRBASE:
6560 check_insn(ctx, ISA_MIPS_R2);
6561 CP0_CHECK(ctx->cmgcr);
6562 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6563 tcg_gen_ext32s_tl(arg, arg);
6564 register_name = "CMGCRBase";
6565 break;
6566 default:
6567 goto cp0_unimplemented;
6569 break;
6570 case CP0_REGISTER_16:
6571 switch (sel) {
6572 case CP0_REG16__CONFIG:
6573 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6574 register_name = "Config";
6575 break;
6576 case CP0_REG16__CONFIG1:
6577 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6578 register_name = "Config1";
6579 break;
6580 case CP0_REG16__CONFIG2:
6581 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6582 register_name = "Config2";
6583 break;
6584 case CP0_REG16__CONFIG3:
6585 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6586 register_name = "Config3";
6587 break;
6588 case CP0_REG16__CONFIG4:
6589 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6590 register_name = "Config4";
6591 break;
6592 case CP0_REG16__CONFIG5:
6593 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6594 register_name = "Config5";
6595 break;
6596 /* 6,7 are implementation dependent */
6597 case CP0_REG16__CONFIG6:
6598 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6599 register_name = "Config6";
6600 break;
6601 case CP0_REG16__CONFIG7:
6602 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6603 register_name = "Config7";
6604 break;
6605 default:
6606 goto cp0_unimplemented;
6608 break;
6609 case CP0_REGISTER_17:
6610 switch (sel) {
6611 case CP0_REG17__LLADDR:
6612 gen_helper_mfc0_lladdr(arg, cpu_env);
6613 register_name = "LLAddr";
6614 break;
6615 case CP0_REG17__MAAR:
6616 CP0_CHECK(ctx->mrp);
6617 gen_helper_mfc0_maar(arg, cpu_env);
6618 register_name = "MAAR";
6619 break;
6620 case CP0_REG17__MAARI:
6621 CP0_CHECK(ctx->mrp);
6622 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6623 register_name = "MAARI";
6624 break;
6625 default:
6626 goto cp0_unimplemented;
6628 break;
6629 case CP0_REGISTER_18:
6630 switch (sel) {
6631 case CP0_REG18__WATCHLO0:
6632 case CP0_REG18__WATCHLO1:
6633 case CP0_REG18__WATCHLO2:
6634 case CP0_REG18__WATCHLO3:
6635 case CP0_REG18__WATCHLO4:
6636 case CP0_REG18__WATCHLO5:
6637 case CP0_REG18__WATCHLO6:
6638 case CP0_REG18__WATCHLO7:
6639 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6640 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6641 register_name = "WatchLo";
6642 break;
6643 default:
6644 goto cp0_unimplemented;
6646 break;
6647 case CP0_REGISTER_19:
6648 switch (sel) {
6649 case CP0_REG19__WATCHHI0:
6650 case CP0_REG19__WATCHHI1:
6651 case CP0_REG19__WATCHHI2:
6652 case CP0_REG19__WATCHHI3:
6653 case CP0_REG19__WATCHHI4:
6654 case CP0_REG19__WATCHHI5:
6655 case CP0_REG19__WATCHHI6:
6656 case CP0_REG19__WATCHHI7:
6657 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6658 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6659 register_name = "WatchHi";
6660 break;
6661 default:
6662 goto cp0_unimplemented;
6664 break;
6665 case CP0_REGISTER_20:
6666 switch (sel) {
6667 case CP0_REG20__XCONTEXT:
6668 #if defined(TARGET_MIPS64)
6669 check_insn(ctx, ISA_MIPS3);
6670 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6671 tcg_gen_ext32s_tl(arg, arg);
6672 register_name = "XContext";
6673 break;
6674 #endif
6675 default:
6676 goto cp0_unimplemented;
6678 break;
6679 case CP0_REGISTER_21:
6680 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6681 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6682 switch (sel) {
6683 case 0:
6684 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6685 register_name = "Framemask";
6686 break;
6687 default:
6688 goto cp0_unimplemented;
6690 break;
6691 case CP0_REGISTER_22:
6692 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6693 register_name = "'Diagnostic"; /* implementation dependent */
6694 break;
6695 case CP0_REGISTER_23:
6696 switch (sel) {
6697 case CP0_REG23__DEBUG:
6698 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6699 register_name = "Debug";
6700 break;
6701 case CP0_REG23__TRACECONTROL:
6702 /* PDtrace support */
6703 /* gen_helper_mfc0_tracecontrol(arg); */
6704 register_name = "TraceControl";
6705 goto cp0_unimplemented;
6706 case CP0_REG23__TRACECONTROL2:
6707 /* PDtrace support */
6708 /* gen_helper_mfc0_tracecontrol2(arg); */
6709 register_name = "TraceControl2";
6710 goto cp0_unimplemented;
6711 case CP0_REG23__USERTRACEDATA1:
6712 /* PDtrace support */
6713 /* gen_helper_mfc0_usertracedata1(arg);*/
6714 register_name = "UserTraceData1";
6715 goto cp0_unimplemented;
6716 case CP0_REG23__TRACEIBPC:
6717 /* PDtrace support */
6718 /* gen_helper_mfc0_traceibpc(arg); */
6719 register_name = "TraceIBPC";
6720 goto cp0_unimplemented;
6721 case CP0_REG23__TRACEDBPC:
6722 /* PDtrace support */
6723 /* gen_helper_mfc0_tracedbpc(arg); */
6724 register_name = "TraceDBPC";
6725 goto cp0_unimplemented;
6726 default:
6727 goto cp0_unimplemented;
6729 break;
6730 case CP0_REGISTER_24:
6731 switch (sel) {
6732 case CP0_REG24__DEPC:
6733 /* EJTAG support */
6734 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6735 tcg_gen_ext32s_tl(arg, arg);
6736 register_name = "DEPC";
6737 break;
6738 default:
6739 goto cp0_unimplemented;
6741 break;
6742 case CP0_REGISTER_25:
6743 switch (sel) {
6744 case CP0_REG25__PERFCTL0:
6745 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6746 register_name = "Performance0";
6747 break;
6748 case CP0_REG25__PERFCNT0:
6749 /* gen_helper_mfc0_performance1(arg); */
6750 register_name = "Performance1";
6751 goto cp0_unimplemented;
6752 case CP0_REG25__PERFCTL1:
6753 /* gen_helper_mfc0_performance2(arg); */
6754 register_name = "Performance2";
6755 goto cp0_unimplemented;
6756 case CP0_REG25__PERFCNT1:
6757 /* gen_helper_mfc0_performance3(arg); */
6758 register_name = "Performance3";
6759 goto cp0_unimplemented;
6760 case CP0_REG25__PERFCTL2:
6761 /* gen_helper_mfc0_performance4(arg); */
6762 register_name = "Performance4";
6763 goto cp0_unimplemented;
6764 case CP0_REG25__PERFCNT2:
6765 /* gen_helper_mfc0_performance5(arg); */
6766 register_name = "Performance5";
6767 goto cp0_unimplemented;
6768 case CP0_REG25__PERFCTL3:
6769 /* gen_helper_mfc0_performance6(arg); */
6770 register_name = "Performance6";
6771 goto cp0_unimplemented;
6772 case CP0_REG25__PERFCNT3:
6773 /* gen_helper_mfc0_performance7(arg); */
6774 register_name = "Performance7";
6775 goto cp0_unimplemented;
6776 default:
6777 goto cp0_unimplemented;
6779 break;
6780 case CP0_REGISTER_26:
6781 switch (sel) {
6782 case CP0_REG26__ERRCTL:
6783 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6784 register_name = "ErrCtl";
6785 break;
6786 default:
6787 goto cp0_unimplemented;
6789 break;
6790 case CP0_REGISTER_27:
6791 switch (sel) {
6792 case CP0_REG27__CACHERR:
6793 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6794 register_name = "CacheErr";
6795 break;
6796 default:
6797 goto cp0_unimplemented;
6799 break;
6800 case CP0_REGISTER_28:
6801 switch (sel) {
6802 case CP0_REG28__TAGLO:
6803 case CP0_REG28__TAGLO1:
6804 case CP0_REG28__TAGLO2:
6805 case CP0_REG28__TAGLO3:
6807 TCGv_i64 tmp = tcg_temp_new_i64();
6808 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
6809 gen_move_low32(arg, tmp);
6810 tcg_temp_free_i64(tmp);
6812 register_name = "TagLo";
6813 break;
6814 case CP0_REG28__DATALO:
6815 case CP0_REG28__DATALO1:
6816 case CP0_REG28__DATALO2:
6817 case CP0_REG28__DATALO3:
6818 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6819 register_name = "DataLo";
6820 break;
6821 default:
6822 goto cp0_unimplemented;
6824 break;
6825 case CP0_REGISTER_29:
6826 switch (sel) {
6827 case CP0_REG29__TAGHI:
6828 case CP0_REG29__TAGHI1:
6829 case CP0_REG29__TAGHI2:
6830 case CP0_REG29__TAGHI3:
6831 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6832 register_name = "TagHi";
6833 break;
6834 case CP0_REG29__DATAHI:
6835 case CP0_REG29__DATAHI1:
6836 case CP0_REG29__DATAHI2:
6837 case CP0_REG29__DATAHI3:
6838 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6839 register_name = "DataHi";
6840 break;
6841 default:
6842 goto cp0_unimplemented;
6844 break;
6845 case CP0_REGISTER_30:
6846 switch (sel) {
6847 case CP0_REG30__ERROREPC:
6848 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6849 tcg_gen_ext32s_tl(arg, arg);
6850 register_name = "ErrorEPC";
6851 break;
6852 default:
6853 goto cp0_unimplemented;
6855 break;
6856 case CP0_REGISTER_31:
6857 switch (sel) {
6858 case CP0_REG31__DESAVE:
6859 /* EJTAG support */
6860 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6861 register_name = "DESAVE";
6862 break;
6863 case CP0_REG31__KSCRATCH1:
6864 case CP0_REG31__KSCRATCH2:
6865 case CP0_REG31__KSCRATCH3:
6866 case CP0_REG31__KSCRATCH4:
6867 case CP0_REG31__KSCRATCH5:
6868 case CP0_REG31__KSCRATCH6:
6869 CP0_CHECK(ctx->kscrexist & (1 << sel));
6870 tcg_gen_ld_tl(arg, cpu_env,
6871 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
6872 tcg_gen_ext32s_tl(arg, arg);
6873 register_name = "KScratch";
6874 break;
6875 default:
6876 goto cp0_unimplemented;
6878 break;
6879 default:
6880 goto cp0_unimplemented;
6882 trace_mips_translate_c0("mfc0", register_name, reg, sel);
6883 return;
6885 cp0_unimplemented:
6886 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
6887 register_name, reg, sel);
6888 gen_mfc0_unimplemented(ctx, arg);
6891 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6893 const char *register_name = "invalid";
6895 if (sel != 0) {
6896 check_insn(ctx, ISA_MIPS_R1);
6899 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6900 gen_io_start();
6903 switch (reg) {
6904 case CP0_REGISTER_00:
6905 switch (sel) {
6906 case CP0_REG00__INDEX:
6907 gen_helper_mtc0_index(cpu_env, arg);
6908 register_name = "Index";
6909 break;
6910 case CP0_REG00__MVPCONTROL:
6911 CP0_CHECK(ctx->insn_flags & ASE_MT);
6912 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6913 register_name = "MVPControl";
6914 break;
6915 case CP0_REG00__MVPCONF0:
6916 CP0_CHECK(ctx->insn_flags & ASE_MT);
6917 /* ignored */
6918 register_name = "MVPConf0";
6919 break;
6920 case CP0_REG00__MVPCONF1:
6921 CP0_CHECK(ctx->insn_flags & ASE_MT);
6922 /* ignored */
6923 register_name = "MVPConf1";
6924 break;
6925 case CP0_REG00__VPCONTROL:
6926 CP0_CHECK(ctx->vp);
6927 /* ignored */
6928 register_name = "VPControl";
6929 break;
6930 default:
6931 goto cp0_unimplemented;
6933 break;
6934 case CP0_REGISTER_01:
6935 switch (sel) {
6936 case CP0_REG01__RANDOM:
6937 /* ignored */
6938 register_name = "Random";
6939 break;
6940 case CP0_REG01__VPECONTROL:
6941 CP0_CHECK(ctx->insn_flags & ASE_MT);
6942 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6943 register_name = "VPEControl";
6944 break;
6945 case CP0_REG01__VPECONF0:
6946 CP0_CHECK(ctx->insn_flags & ASE_MT);
6947 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6948 register_name = "VPEConf0";
6949 break;
6950 case CP0_REG01__VPECONF1:
6951 CP0_CHECK(ctx->insn_flags & ASE_MT);
6952 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6953 register_name = "VPEConf1";
6954 break;
6955 case CP0_REG01__YQMASK:
6956 CP0_CHECK(ctx->insn_flags & ASE_MT);
6957 gen_helper_mtc0_yqmask(cpu_env, arg);
6958 register_name = "YQMask";
6959 break;
6960 case CP0_REG01__VPESCHEDULE:
6961 CP0_CHECK(ctx->insn_flags & ASE_MT);
6962 tcg_gen_st_tl(arg, cpu_env,
6963 offsetof(CPUMIPSState, CP0_VPESchedule));
6964 register_name = "VPESchedule";
6965 break;
6966 case CP0_REG01__VPESCHEFBACK:
6967 CP0_CHECK(ctx->insn_flags & ASE_MT);
6968 tcg_gen_st_tl(arg, cpu_env,
6969 offsetof(CPUMIPSState, CP0_VPEScheFBack));
6970 register_name = "VPEScheFBack";
6971 break;
6972 case CP0_REG01__VPEOPT:
6973 CP0_CHECK(ctx->insn_flags & ASE_MT);
6974 gen_helper_mtc0_vpeopt(cpu_env, arg);
6975 register_name = "VPEOpt";
6976 break;
6977 default:
6978 goto cp0_unimplemented;
6980 break;
6981 case CP0_REGISTER_02:
6982 switch (sel) {
6983 case CP0_REG02__ENTRYLO0:
6984 gen_helper_mtc0_entrylo0(cpu_env, arg);
6985 register_name = "EntryLo0";
6986 break;
6987 case CP0_REG02__TCSTATUS:
6988 CP0_CHECK(ctx->insn_flags & ASE_MT);
6989 gen_helper_mtc0_tcstatus(cpu_env, arg);
6990 register_name = "TCStatus";
6991 break;
6992 case CP0_REG02__TCBIND:
6993 CP0_CHECK(ctx->insn_flags & ASE_MT);
6994 gen_helper_mtc0_tcbind(cpu_env, arg);
6995 register_name = "TCBind";
6996 break;
6997 case CP0_REG02__TCRESTART:
6998 CP0_CHECK(ctx->insn_flags & ASE_MT);
6999 gen_helper_mtc0_tcrestart(cpu_env, arg);
7000 register_name = "TCRestart";
7001 break;
7002 case CP0_REG02__TCHALT:
7003 CP0_CHECK(ctx->insn_flags & ASE_MT);
7004 gen_helper_mtc0_tchalt(cpu_env, arg);
7005 register_name = "TCHalt";
7006 break;
7007 case CP0_REG02__TCCONTEXT:
7008 CP0_CHECK(ctx->insn_flags & ASE_MT);
7009 gen_helper_mtc0_tccontext(cpu_env, arg);
7010 register_name = "TCContext";
7011 break;
7012 case CP0_REG02__TCSCHEDULE:
7013 CP0_CHECK(ctx->insn_flags & ASE_MT);
7014 gen_helper_mtc0_tcschedule(cpu_env, arg);
7015 register_name = "TCSchedule";
7016 break;
7017 case CP0_REG02__TCSCHEFBACK:
7018 CP0_CHECK(ctx->insn_flags & ASE_MT);
7019 gen_helper_mtc0_tcschefback(cpu_env, arg);
7020 register_name = "TCScheFBack";
7021 break;
7022 default:
7023 goto cp0_unimplemented;
7025 break;
7026 case CP0_REGISTER_03:
7027 switch (sel) {
7028 case CP0_REG03__ENTRYLO1:
7029 gen_helper_mtc0_entrylo1(cpu_env, arg);
7030 register_name = "EntryLo1";
7031 break;
7032 case CP0_REG03__GLOBALNUM:
7033 CP0_CHECK(ctx->vp);
7034 /* ignored */
7035 register_name = "GlobalNumber";
7036 break;
7037 default:
7038 goto cp0_unimplemented;
7040 break;
7041 case CP0_REGISTER_04:
7042 switch (sel) {
7043 case CP0_REG04__CONTEXT:
7044 gen_helper_mtc0_context(cpu_env, arg);
7045 register_name = "Context";
7046 break;
7047 case CP0_REG04__CONTEXTCONFIG:
7048 /* SmartMIPS ASE */
7049 /* gen_helper_mtc0_contextconfig(arg); */
7050 register_name = "ContextConfig";
7051 goto cp0_unimplemented;
7052 case CP0_REG04__USERLOCAL:
7053 CP0_CHECK(ctx->ulri);
7054 tcg_gen_st_tl(arg, cpu_env,
7055 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7056 register_name = "UserLocal";
7057 break;
7058 case CP0_REG04__MMID:
7059 CP0_CHECK(ctx->mi);
7060 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
7061 register_name = "MMID";
7062 break;
7063 default:
7064 goto cp0_unimplemented;
7066 break;
7067 case CP0_REGISTER_05:
7068 switch (sel) {
7069 case CP0_REG05__PAGEMASK:
7070 gen_helper_mtc0_pagemask(cpu_env, arg);
7071 register_name = "PageMask";
7072 break;
7073 case CP0_REG05__PAGEGRAIN:
7074 check_insn(ctx, ISA_MIPS_R2);
7075 gen_helper_mtc0_pagegrain(cpu_env, arg);
7076 register_name = "PageGrain";
7077 ctx->base.is_jmp = DISAS_STOP;
7078 break;
7079 case CP0_REG05__SEGCTL0:
7080 CP0_CHECK(ctx->sc);
7081 gen_helper_mtc0_segctl0(cpu_env, arg);
7082 register_name = "SegCtl0";
7083 break;
7084 case CP0_REG05__SEGCTL1:
7085 CP0_CHECK(ctx->sc);
7086 gen_helper_mtc0_segctl1(cpu_env, arg);
7087 register_name = "SegCtl1";
7088 break;
7089 case CP0_REG05__SEGCTL2:
7090 CP0_CHECK(ctx->sc);
7091 gen_helper_mtc0_segctl2(cpu_env, arg);
7092 register_name = "SegCtl2";
7093 break;
7094 case CP0_REG05__PWBASE:
7095 check_pw(ctx);
7096 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7097 register_name = "PWBase";
7098 break;
7099 case CP0_REG05__PWFIELD:
7100 check_pw(ctx);
7101 gen_helper_mtc0_pwfield(cpu_env, arg);
7102 register_name = "PWField";
7103 break;
7104 case CP0_REG05__PWSIZE:
7105 check_pw(ctx);
7106 gen_helper_mtc0_pwsize(cpu_env, arg);
7107 register_name = "PWSize";
7108 break;
7109 default:
7110 goto cp0_unimplemented;
7112 break;
7113 case CP0_REGISTER_06:
7114 switch (sel) {
7115 case CP0_REG06__WIRED:
7116 gen_helper_mtc0_wired(cpu_env, arg);
7117 register_name = "Wired";
7118 break;
7119 case CP0_REG06__SRSCONF0:
7120 check_insn(ctx, ISA_MIPS_R2);
7121 gen_helper_mtc0_srsconf0(cpu_env, arg);
7122 register_name = "SRSConf0";
7123 break;
7124 case CP0_REG06__SRSCONF1:
7125 check_insn(ctx, ISA_MIPS_R2);
7126 gen_helper_mtc0_srsconf1(cpu_env, arg);
7127 register_name = "SRSConf1";
7128 break;
7129 case CP0_REG06__SRSCONF2:
7130 check_insn(ctx, ISA_MIPS_R2);
7131 gen_helper_mtc0_srsconf2(cpu_env, arg);
7132 register_name = "SRSConf2";
7133 break;
7134 case CP0_REG06__SRSCONF3:
7135 check_insn(ctx, ISA_MIPS_R2);
7136 gen_helper_mtc0_srsconf3(cpu_env, arg);
7137 register_name = "SRSConf3";
7138 break;
7139 case CP0_REG06__SRSCONF4:
7140 check_insn(ctx, ISA_MIPS_R2);
7141 gen_helper_mtc0_srsconf4(cpu_env, arg);
7142 register_name = "SRSConf4";
7143 break;
7144 case CP0_REG06__PWCTL:
7145 check_pw(ctx);
7146 gen_helper_mtc0_pwctl(cpu_env, arg);
7147 register_name = "PWCtl";
7148 break;
7149 default:
7150 goto cp0_unimplemented;
7152 break;
7153 case CP0_REGISTER_07:
7154 switch (sel) {
7155 case CP0_REG07__HWRENA:
7156 check_insn(ctx, ISA_MIPS_R2);
7157 gen_helper_mtc0_hwrena(cpu_env, arg);
7158 ctx->base.is_jmp = DISAS_STOP;
7159 register_name = "HWREna";
7160 break;
7161 default:
7162 goto cp0_unimplemented;
7164 break;
7165 case CP0_REGISTER_08:
7166 switch (sel) {
7167 case CP0_REG08__BADVADDR:
7168 /* ignored */
7169 register_name = "BadVAddr";
7170 break;
7171 case CP0_REG08__BADINSTR:
7172 /* ignored */
7173 register_name = "BadInstr";
7174 break;
7175 case CP0_REG08__BADINSTRP:
7176 /* ignored */
7177 register_name = "BadInstrP";
7178 break;
7179 case CP0_REG08__BADINSTRX:
7180 /* ignored */
7181 register_name = "BadInstrX";
7182 break;
7183 default:
7184 goto cp0_unimplemented;
7186 break;
7187 case CP0_REGISTER_09:
7188 switch (sel) {
7189 case CP0_REG09__COUNT:
7190 gen_helper_mtc0_count(cpu_env, arg);
7191 register_name = "Count";
7192 break;
7193 case CP0_REG09__SAARI:
7194 CP0_CHECK(ctx->saar);
7195 gen_helper_mtc0_saari(cpu_env, arg);
7196 register_name = "SAARI";
7197 break;
7198 case CP0_REG09__SAAR:
7199 CP0_CHECK(ctx->saar);
7200 gen_helper_mtc0_saar(cpu_env, arg);
7201 register_name = "SAAR";
7202 break;
7203 default:
7204 goto cp0_unimplemented;
7206 break;
7207 case CP0_REGISTER_10:
7208 switch (sel) {
7209 case CP0_REG10__ENTRYHI:
7210 gen_helper_mtc0_entryhi(cpu_env, arg);
7211 register_name = "EntryHi";
7212 break;
7213 default:
7214 goto cp0_unimplemented;
7216 break;
7217 case CP0_REGISTER_11:
7218 switch (sel) {
7219 case CP0_REG11__COMPARE:
7220 gen_helper_mtc0_compare(cpu_env, arg);
7221 register_name = "Compare";
7222 break;
7223 /* 6,7 are implementation dependent */
7224 default:
7225 goto cp0_unimplemented;
7227 break;
7228 case CP0_REGISTER_12:
7229 switch (sel) {
7230 case CP0_REG12__STATUS:
7231 save_cpu_state(ctx, 1);
7232 gen_helper_mtc0_status(cpu_env, arg);
7233 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7234 gen_save_pc(ctx->base.pc_next + 4);
7235 ctx->base.is_jmp = DISAS_EXIT;
7236 register_name = "Status";
7237 break;
7238 case CP0_REG12__INTCTL:
7239 check_insn(ctx, ISA_MIPS_R2);
7240 gen_helper_mtc0_intctl(cpu_env, arg);
7241 /* Stop translation as we may have switched the execution mode */
7242 ctx->base.is_jmp = DISAS_STOP;
7243 register_name = "IntCtl";
7244 break;
7245 case CP0_REG12__SRSCTL:
7246 check_insn(ctx, ISA_MIPS_R2);
7247 gen_helper_mtc0_srsctl(cpu_env, arg);
7248 /* Stop translation as we may have switched the execution mode */
7249 ctx->base.is_jmp = DISAS_STOP;
7250 register_name = "SRSCtl";
7251 break;
7252 case CP0_REG12__SRSMAP:
7253 check_insn(ctx, ISA_MIPS_R2);
7254 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7255 /* Stop translation as we may have switched the execution mode */
7256 ctx->base.is_jmp = DISAS_STOP;
7257 register_name = "SRSMap";
7258 break;
7259 default:
7260 goto cp0_unimplemented;
7262 break;
7263 case CP0_REGISTER_13:
7264 switch (sel) {
7265 case CP0_REG13__CAUSE:
7266 save_cpu_state(ctx, 1);
7267 gen_helper_mtc0_cause(cpu_env, arg);
7269 * Stop translation as we may have triggered an interrupt.
7270 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7271 * translated code to check for pending interrupts.
7273 gen_save_pc(ctx->base.pc_next + 4);
7274 ctx->base.is_jmp = DISAS_EXIT;
7275 register_name = "Cause";
7276 break;
7277 default:
7278 goto cp0_unimplemented;
7280 break;
7281 case CP0_REGISTER_14:
7282 switch (sel) {
7283 case CP0_REG14__EPC:
7284 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7285 register_name = "EPC";
7286 break;
7287 default:
7288 goto cp0_unimplemented;
7290 break;
7291 case CP0_REGISTER_15:
7292 switch (sel) {
7293 case CP0_REG15__PRID:
7294 /* ignored */
7295 register_name = "PRid";
7296 break;
7297 case CP0_REG15__EBASE:
7298 check_insn(ctx, ISA_MIPS_R2);
7299 gen_helper_mtc0_ebase(cpu_env, arg);
7300 register_name = "EBase";
7301 break;
7302 default:
7303 goto cp0_unimplemented;
7305 break;
7306 case CP0_REGISTER_16:
7307 switch (sel) {
7308 case CP0_REG16__CONFIG:
7309 gen_helper_mtc0_config0(cpu_env, arg);
7310 register_name = "Config";
7311 /* Stop translation as we may have switched the execution mode */
7312 ctx->base.is_jmp = DISAS_STOP;
7313 break;
7314 case CP0_REG16__CONFIG1:
7315 /* ignored, read only */
7316 register_name = "Config1";
7317 break;
7318 case CP0_REG16__CONFIG2:
7319 gen_helper_mtc0_config2(cpu_env, arg);
7320 register_name = "Config2";
7321 /* Stop translation as we may have switched the execution mode */
7322 ctx->base.is_jmp = DISAS_STOP;
7323 break;
7324 case CP0_REG16__CONFIG3:
7325 gen_helper_mtc0_config3(cpu_env, arg);
7326 register_name = "Config3";
7327 /* Stop translation as we may have switched the execution mode */
7328 ctx->base.is_jmp = DISAS_STOP;
7329 break;
7330 case CP0_REG16__CONFIG4:
7331 gen_helper_mtc0_config4(cpu_env, arg);
7332 register_name = "Config4";
7333 ctx->base.is_jmp = DISAS_STOP;
7334 break;
7335 case CP0_REG16__CONFIG5:
7336 gen_helper_mtc0_config5(cpu_env, arg);
7337 register_name = "Config5";
7338 /* Stop translation as we may have switched the execution mode */
7339 ctx->base.is_jmp = DISAS_STOP;
7340 break;
7341 /* 6,7 are implementation dependent */
7342 case CP0_REG16__CONFIG6:
7343 /* ignored */
7344 register_name = "Config6";
7345 break;
7346 case CP0_REG16__CONFIG7:
7347 /* ignored */
7348 register_name = "Config7";
7349 break;
7350 default:
7351 register_name = "Invalid config selector";
7352 goto cp0_unimplemented;
7354 break;
7355 case CP0_REGISTER_17:
7356 switch (sel) {
7357 case CP0_REG17__LLADDR:
7358 gen_helper_mtc0_lladdr(cpu_env, arg);
7359 register_name = "LLAddr";
7360 break;
7361 case CP0_REG17__MAAR:
7362 CP0_CHECK(ctx->mrp);
7363 gen_helper_mtc0_maar(cpu_env, arg);
7364 register_name = "MAAR";
7365 break;
7366 case CP0_REG17__MAARI:
7367 CP0_CHECK(ctx->mrp);
7368 gen_helper_mtc0_maari(cpu_env, arg);
7369 register_name = "MAARI";
7370 break;
7371 default:
7372 goto cp0_unimplemented;
7374 break;
7375 case CP0_REGISTER_18:
7376 switch (sel) {
7377 case CP0_REG18__WATCHLO0:
7378 case CP0_REG18__WATCHLO1:
7379 case CP0_REG18__WATCHLO2:
7380 case CP0_REG18__WATCHLO3:
7381 case CP0_REG18__WATCHLO4:
7382 case CP0_REG18__WATCHLO5:
7383 case CP0_REG18__WATCHLO6:
7384 case CP0_REG18__WATCHLO7:
7385 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7386 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7387 register_name = "WatchLo";
7388 break;
7389 default:
7390 goto cp0_unimplemented;
7392 break;
7393 case CP0_REGISTER_19:
7394 switch (sel) {
7395 case CP0_REG19__WATCHHI0:
7396 case CP0_REG19__WATCHHI1:
7397 case CP0_REG19__WATCHHI2:
7398 case CP0_REG19__WATCHHI3:
7399 case CP0_REG19__WATCHHI4:
7400 case CP0_REG19__WATCHHI5:
7401 case CP0_REG19__WATCHHI6:
7402 case CP0_REG19__WATCHHI7:
7403 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7404 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7405 register_name = "WatchHi";
7406 break;
7407 default:
7408 goto cp0_unimplemented;
7410 break;
7411 case CP0_REGISTER_20:
7412 switch (sel) {
7413 case CP0_REG20__XCONTEXT:
7414 #if defined(TARGET_MIPS64)
7415 check_insn(ctx, ISA_MIPS3);
7416 gen_helper_mtc0_xcontext(cpu_env, arg);
7417 register_name = "XContext";
7418 break;
7419 #endif
7420 default:
7421 goto cp0_unimplemented;
7423 break;
7424 case CP0_REGISTER_21:
7425 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7426 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7427 switch (sel) {
7428 case 0:
7429 gen_helper_mtc0_framemask(cpu_env, arg);
7430 register_name = "Framemask";
7431 break;
7432 default:
7433 goto cp0_unimplemented;
7435 break;
7436 case CP0_REGISTER_22:
7437 /* ignored */
7438 register_name = "Diagnostic"; /* implementation dependent */
7439 break;
7440 case CP0_REGISTER_23:
7441 switch (sel) {
7442 case CP0_REG23__DEBUG:
7443 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7444 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7445 gen_save_pc(ctx->base.pc_next + 4);
7446 ctx->base.is_jmp = DISAS_EXIT;
7447 register_name = "Debug";
7448 break;
7449 case CP0_REG23__TRACECONTROL:
7450 /* PDtrace support */
7451 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
7452 register_name = "TraceControl";
7453 /* Stop translation as we may have switched the execution mode */
7454 ctx->base.is_jmp = DISAS_STOP;
7455 goto cp0_unimplemented;
7456 case CP0_REG23__TRACECONTROL2:
7457 /* PDtrace support */
7458 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
7459 register_name = "TraceControl2";
7460 /* Stop translation as we may have switched the execution mode */
7461 ctx->base.is_jmp = DISAS_STOP;
7462 goto cp0_unimplemented;
7463 case CP0_REG23__USERTRACEDATA1:
7464 /* Stop translation as we may have switched the execution mode */
7465 ctx->base.is_jmp = DISAS_STOP;
7466 /* PDtrace support */
7467 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
7468 register_name = "UserTraceData";
7469 /* Stop translation as we may have switched the execution mode */
7470 ctx->base.is_jmp = DISAS_STOP;
7471 goto cp0_unimplemented;
7472 case CP0_REG23__TRACEIBPC:
7473 /* PDtrace support */
7474 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
7475 /* Stop translation as we may have switched the execution mode */
7476 ctx->base.is_jmp = DISAS_STOP;
7477 register_name = "TraceIBPC";
7478 goto cp0_unimplemented;
7479 case CP0_REG23__TRACEDBPC:
7480 /* PDtrace support */
7481 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
7482 /* Stop translation as we may have switched the execution mode */
7483 ctx->base.is_jmp = DISAS_STOP;
7484 register_name = "TraceDBPC";
7485 goto cp0_unimplemented;
7486 default:
7487 goto cp0_unimplemented;
7489 break;
7490 case CP0_REGISTER_24:
7491 switch (sel) {
7492 case CP0_REG24__DEPC:
7493 /* EJTAG support */
7494 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7495 register_name = "DEPC";
7496 break;
7497 default:
7498 goto cp0_unimplemented;
7500 break;
7501 case CP0_REGISTER_25:
7502 switch (sel) {
7503 case CP0_REG25__PERFCTL0:
7504 gen_helper_mtc0_performance0(cpu_env, arg);
7505 register_name = "Performance0";
7506 break;
7507 case CP0_REG25__PERFCNT0:
7508 /* gen_helper_mtc0_performance1(arg); */
7509 register_name = "Performance1";
7510 goto cp0_unimplemented;
7511 case CP0_REG25__PERFCTL1:
7512 /* gen_helper_mtc0_performance2(arg); */
7513 register_name = "Performance2";
7514 goto cp0_unimplemented;
7515 case CP0_REG25__PERFCNT1:
7516 /* gen_helper_mtc0_performance3(arg); */
7517 register_name = "Performance3";
7518 goto cp0_unimplemented;
7519 case CP0_REG25__PERFCTL2:
7520 /* gen_helper_mtc0_performance4(arg); */
7521 register_name = "Performance4";
7522 goto cp0_unimplemented;
7523 case CP0_REG25__PERFCNT2:
7524 /* gen_helper_mtc0_performance5(arg); */
7525 register_name = "Performance5";
7526 goto cp0_unimplemented;
7527 case CP0_REG25__PERFCTL3:
7528 /* gen_helper_mtc0_performance6(arg); */
7529 register_name = "Performance6";
7530 goto cp0_unimplemented;
7531 case CP0_REG25__PERFCNT3:
7532 /* gen_helper_mtc0_performance7(arg); */
7533 register_name = "Performance7";
7534 goto cp0_unimplemented;
7535 default:
7536 goto cp0_unimplemented;
7538 break;
7539 case CP0_REGISTER_26:
7540 switch (sel) {
7541 case CP0_REG26__ERRCTL:
7542 gen_helper_mtc0_errctl(cpu_env, arg);
7543 ctx->base.is_jmp = DISAS_STOP;
7544 register_name = "ErrCtl";
7545 break;
7546 default:
7547 goto cp0_unimplemented;
7549 break;
7550 case CP0_REGISTER_27:
7551 switch (sel) {
7552 case CP0_REG27__CACHERR:
7553 /* ignored */
7554 register_name = "CacheErr";
7555 break;
7556 default:
7557 goto cp0_unimplemented;
7559 break;
7560 case CP0_REGISTER_28:
7561 switch (sel) {
7562 case CP0_REG28__TAGLO:
7563 case CP0_REG28__TAGLO1:
7564 case CP0_REG28__TAGLO2:
7565 case CP0_REG28__TAGLO3:
7566 gen_helper_mtc0_taglo(cpu_env, arg);
7567 register_name = "TagLo";
7568 break;
7569 case CP0_REG28__DATALO:
7570 case CP0_REG28__DATALO1:
7571 case CP0_REG28__DATALO2:
7572 case CP0_REG28__DATALO3:
7573 gen_helper_mtc0_datalo(cpu_env, arg);
7574 register_name = "DataLo";
7575 break;
7576 default:
7577 goto cp0_unimplemented;
7579 break;
7580 case CP0_REGISTER_29:
7581 switch (sel) {
7582 case CP0_REG29__TAGHI:
7583 case CP0_REG29__TAGHI1:
7584 case CP0_REG29__TAGHI2:
7585 case CP0_REG29__TAGHI3:
7586 gen_helper_mtc0_taghi(cpu_env, arg);
7587 register_name = "TagHi";
7588 break;
7589 case CP0_REG29__DATAHI:
7590 case CP0_REG29__DATAHI1:
7591 case CP0_REG29__DATAHI2:
7592 case CP0_REG29__DATAHI3:
7593 gen_helper_mtc0_datahi(cpu_env, arg);
7594 register_name = "DataHi";
7595 break;
7596 default:
7597 register_name = "invalid sel";
7598 goto cp0_unimplemented;
7600 break;
7601 case CP0_REGISTER_30:
7602 switch (sel) {
7603 case CP0_REG30__ERROREPC:
7604 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7605 register_name = "ErrorEPC";
7606 break;
7607 default:
7608 goto cp0_unimplemented;
7610 break;
7611 case CP0_REGISTER_31:
7612 switch (sel) {
7613 case CP0_REG31__DESAVE:
7614 /* EJTAG support */
7615 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7616 register_name = "DESAVE";
7617 break;
7618 case CP0_REG31__KSCRATCH1:
7619 case CP0_REG31__KSCRATCH2:
7620 case CP0_REG31__KSCRATCH3:
7621 case CP0_REG31__KSCRATCH4:
7622 case CP0_REG31__KSCRATCH5:
7623 case CP0_REG31__KSCRATCH6:
7624 CP0_CHECK(ctx->kscrexist & (1 << sel));
7625 tcg_gen_st_tl(arg, cpu_env,
7626 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7627 register_name = "KScratch";
7628 break;
7629 default:
7630 goto cp0_unimplemented;
7632 break;
7633 default:
7634 goto cp0_unimplemented;
7636 trace_mips_translate_c0("mtc0", register_name, reg, sel);
7638 /* For simplicity assume that all writes can cause interrupts. */
7639 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7641 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7642 * translated code to check for pending interrupts.
7644 gen_save_pc(ctx->base.pc_next + 4);
7645 ctx->base.is_jmp = DISAS_EXIT;
7647 return;
7649 cp0_unimplemented:
7650 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
7651 register_name, reg, sel);
7654 #if defined(TARGET_MIPS64)
7655 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7657 const char *register_name = "invalid";
7659 if (sel != 0) {
7660 check_insn(ctx, ISA_MIPS_R1);
7663 switch (reg) {
7664 case CP0_REGISTER_00:
7665 switch (sel) {
7666 case CP0_REG00__INDEX:
7667 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7668 register_name = "Index";
7669 break;
7670 case CP0_REG00__MVPCONTROL:
7671 CP0_CHECK(ctx->insn_flags & ASE_MT);
7672 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7673 register_name = "MVPControl";
7674 break;
7675 case CP0_REG00__MVPCONF0:
7676 CP0_CHECK(ctx->insn_flags & ASE_MT);
7677 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7678 register_name = "MVPConf0";
7679 break;
7680 case CP0_REG00__MVPCONF1:
7681 CP0_CHECK(ctx->insn_flags & ASE_MT);
7682 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7683 register_name = "MVPConf1";
7684 break;
7685 case CP0_REG00__VPCONTROL:
7686 CP0_CHECK(ctx->vp);
7687 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7688 register_name = "VPControl";
7689 break;
7690 default:
7691 goto cp0_unimplemented;
7693 break;
7694 case CP0_REGISTER_01:
7695 switch (sel) {
7696 case CP0_REG01__RANDOM:
7697 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7698 gen_helper_mfc0_random(arg, cpu_env);
7699 register_name = "Random";
7700 break;
7701 case CP0_REG01__VPECONTROL:
7702 CP0_CHECK(ctx->insn_flags & ASE_MT);
7703 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7704 register_name = "VPEControl";
7705 break;
7706 case CP0_REG01__VPECONF0:
7707 CP0_CHECK(ctx->insn_flags & ASE_MT);
7708 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7709 register_name = "VPEConf0";
7710 break;
7711 case CP0_REG01__VPECONF1:
7712 CP0_CHECK(ctx->insn_flags & ASE_MT);
7713 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7714 register_name = "VPEConf1";
7715 break;
7716 case CP0_REG01__YQMASK:
7717 CP0_CHECK(ctx->insn_flags & ASE_MT);
7718 tcg_gen_ld_tl(arg, cpu_env,
7719 offsetof(CPUMIPSState, CP0_YQMask));
7720 register_name = "YQMask";
7721 break;
7722 case CP0_REG01__VPESCHEDULE:
7723 CP0_CHECK(ctx->insn_flags & ASE_MT);
7724 tcg_gen_ld_tl(arg, cpu_env,
7725 offsetof(CPUMIPSState, CP0_VPESchedule));
7726 register_name = "VPESchedule";
7727 break;
7728 case CP0_REG01__VPESCHEFBACK:
7729 CP0_CHECK(ctx->insn_flags & ASE_MT);
7730 tcg_gen_ld_tl(arg, cpu_env,
7731 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7732 register_name = "VPEScheFBack";
7733 break;
7734 case CP0_REG01__VPEOPT:
7735 CP0_CHECK(ctx->insn_flags & ASE_MT);
7736 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7737 register_name = "VPEOpt";
7738 break;
7739 default:
7740 goto cp0_unimplemented;
7742 break;
7743 case CP0_REGISTER_02:
7744 switch (sel) {
7745 case CP0_REG02__ENTRYLO0:
7746 tcg_gen_ld_tl(arg, cpu_env,
7747 offsetof(CPUMIPSState, CP0_EntryLo0));
7748 register_name = "EntryLo0";
7749 break;
7750 case CP0_REG02__TCSTATUS:
7751 CP0_CHECK(ctx->insn_flags & ASE_MT);
7752 gen_helper_mfc0_tcstatus(arg, cpu_env);
7753 register_name = "TCStatus";
7754 break;
7755 case CP0_REG02__TCBIND:
7756 CP0_CHECK(ctx->insn_flags & ASE_MT);
7757 gen_helper_mfc0_tcbind(arg, cpu_env);
7758 register_name = "TCBind";
7759 break;
7760 case CP0_REG02__TCRESTART:
7761 CP0_CHECK(ctx->insn_flags & ASE_MT);
7762 gen_helper_dmfc0_tcrestart(arg, cpu_env);
7763 register_name = "TCRestart";
7764 break;
7765 case CP0_REG02__TCHALT:
7766 CP0_CHECK(ctx->insn_flags & ASE_MT);
7767 gen_helper_dmfc0_tchalt(arg, cpu_env);
7768 register_name = "TCHalt";
7769 break;
7770 case CP0_REG02__TCCONTEXT:
7771 CP0_CHECK(ctx->insn_flags & ASE_MT);
7772 gen_helper_dmfc0_tccontext(arg, cpu_env);
7773 register_name = "TCContext";
7774 break;
7775 case CP0_REG02__TCSCHEDULE:
7776 CP0_CHECK(ctx->insn_flags & ASE_MT);
7777 gen_helper_dmfc0_tcschedule(arg, cpu_env);
7778 register_name = "TCSchedule";
7779 break;
7780 case CP0_REG02__TCSCHEFBACK:
7781 CP0_CHECK(ctx->insn_flags & ASE_MT);
7782 gen_helper_dmfc0_tcschefback(arg, cpu_env);
7783 register_name = "TCScheFBack";
7784 break;
7785 default:
7786 goto cp0_unimplemented;
7788 break;
7789 case CP0_REGISTER_03:
7790 switch (sel) {
7791 case CP0_REG03__ENTRYLO1:
7792 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
7793 register_name = "EntryLo1";
7794 break;
7795 case CP0_REG03__GLOBALNUM:
7796 CP0_CHECK(ctx->vp);
7797 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7798 register_name = "GlobalNumber";
7799 break;
7800 default:
7801 goto cp0_unimplemented;
7803 break;
7804 case CP0_REGISTER_04:
7805 switch (sel) {
7806 case CP0_REG04__CONTEXT:
7807 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7808 register_name = "Context";
7809 break;
7810 case CP0_REG04__CONTEXTCONFIG:
7811 /* SmartMIPS ASE */
7812 /* gen_helper_dmfc0_contextconfig(arg); */
7813 register_name = "ContextConfig";
7814 goto cp0_unimplemented;
7815 case CP0_REG04__USERLOCAL:
7816 CP0_CHECK(ctx->ulri);
7817 tcg_gen_ld_tl(arg, cpu_env,
7818 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7819 register_name = "UserLocal";
7820 break;
7821 case CP0_REG04__MMID:
7822 CP0_CHECK(ctx->mi);
7823 gen_helper_mtc0_memorymapid(cpu_env, arg);
7824 register_name = "MMID";
7825 break;
7826 default:
7827 goto cp0_unimplemented;
7829 break;
7830 case CP0_REGISTER_05:
7831 switch (sel) {
7832 case CP0_REG05__PAGEMASK:
7833 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7834 register_name = "PageMask";
7835 break;
7836 case CP0_REG05__PAGEGRAIN:
7837 check_insn(ctx, ISA_MIPS_R2);
7838 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7839 register_name = "PageGrain";
7840 break;
7841 case CP0_REG05__SEGCTL0:
7842 CP0_CHECK(ctx->sc);
7843 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7844 register_name = "SegCtl0";
7845 break;
7846 case CP0_REG05__SEGCTL1:
7847 CP0_CHECK(ctx->sc);
7848 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7849 register_name = "SegCtl1";
7850 break;
7851 case CP0_REG05__SEGCTL2:
7852 CP0_CHECK(ctx->sc);
7853 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7854 register_name = "SegCtl2";
7855 break;
7856 case CP0_REG05__PWBASE:
7857 check_pw(ctx);
7858 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
7859 register_name = "PWBase";
7860 break;
7861 case CP0_REG05__PWFIELD:
7862 check_pw(ctx);
7863 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
7864 register_name = "PWField";
7865 break;
7866 case CP0_REG05__PWSIZE:
7867 check_pw(ctx);
7868 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
7869 register_name = "PWSize";
7870 break;
7871 default:
7872 goto cp0_unimplemented;
7874 break;
7875 case CP0_REGISTER_06:
7876 switch (sel) {
7877 case CP0_REG06__WIRED:
7878 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7879 register_name = "Wired";
7880 break;
7881 case CP0_REG06__SRSCONF0:
7882 check_insn(ctx, ISA_MIPS_R2);
7883 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7884 register_name = "SRSConf0";
7885 break;
7886 case CP0_REG06__SRSCONF1:
7887 check_insn(ctx, ISA_MIPS_R2);
7888 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7889 register_name = "SRSConf1";
7890 break;
7891 case CP0_REG06__SRSCONF2:
7892 check_insn(ctx, ISA_MIPS_R2);
7893 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7894 register_name = "SRSConf2";
7895 break;
7896 case CP0_REG06__SRSCONF3:
7897 check_insn(ctx, ISA_MIPS_R2);
7898 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7899 register_name = "SRSConf3";
7900 break;
7901 case CP0_REG06__SRSCONF4:
7902 check_insn(ctx, ISA_MIPS_R2);
7903 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7904 register_name = "SRSConf4";
7905 break;
7906 case CP0_REG06__PWCTL:
7907 check_pw(ctx);
7908 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7909 register_name = "PWCtl";
7910 break;
7911 default:
7912 goto cp0_unimplemented;
7914 break;
7915 case CP0_REGISTER_07:
7916 switch (sel) {
7917 case CP0_REG07__HWRENA:
7918 check_insn(ctx, ISA_MIPS_R2);
7919 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7920 register_name = "HWREna";
7921 break;
7922 default:
7923 goto cp0_unimplemented;
7925 break;
7926 case CP0_REGISTER_08:
7927 switch (sel) {
7928 case CP0_REG08__BADVADDR:
7929 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7930 register_name = "BadVAddr";
7931 break;
7932 case CP0_REG08__BADINSTR:
7933 CP0_CHECK(ctx->bi);
7934 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7935 register_name = "BadInstr";
7936 break;
7937 case CP0_REG08__BADINSTRP:
7938 CP0_CHECK(ctx->bp);
7939 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7940 register_name = "BadInstrP";
7941 break;
7942 case CP0_REG08__BADINSTRX:
7943 CP0_CHECK(ctx->bi);
7944 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7945 tcg_gen_andi_tl(arg, arg, ~0xffff);
7946 register_name = "BadInstrX";
7947 break;
7948 default:
7949 goto cp0_unimplemented;
7951 break;
7952 case CP0_REGISTER_09:
7953 switch (sel) {
7954 case CP0_REG09__COUNT:
7955 /* Mark as an IO operation because we read the time. */
7956 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7957 gen_io_start();
7959 gen_helper_mfc0_count(arg, cpu_env);
7961 * Break the TB to be able to take timer interrupts immediately
7962 * after reading count. DISAS_STOP isn't sufficient, we need to
7963 * ensure we break completely out of translated code.
7965 gen_save_pc(ctx->base.pc_next + 4);
7966 ctx->base.is_jmp = DISAS_EXIT;
7967 register_name = "Count";
7968 break;
7969 case CP0_REG09__SAARI:
7970 CP0_CHECK(ctx->saar);
7971 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7972 register_name = "SAARI";
7973 break;
7974 case CP0_REG09__SAAR:
7975 CP0_CHECK(ctx->saar);
7976 gen_helper_dmfc0_saar(arg, cpu_env);
7977 register_name = "SAAR";
7978 break;
7979 default:
7980 goto cp0_unimplemented;
7982 break;
7983 case CP0_REGISTER_10:
7984 switch (sel) {
7985 case CP0_REG10__ENTRYHI:
7986 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7987 register_name = "EntryHi";
7988 break;
7989 default:
7990 goto cp0_unimplemented;
7992 break;
7993 case CP0_REGISTER_11:
7994 switch (sel) {
7995 case CP0_REG11__COMPARE:
7996 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7997 register_name = "Compare";
7998 break;
7999 /* 6,7 are implementation dependent */
8000 default:
8001 goto cp0_unimplemented;
8003 break;
8004 case CP0_REGISTER_12:
8005 switch (sel) {
8006 case CP0_REG12__STATUS:
8007 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8008 register_name = "Status";
8009 break;
8010 case CP0_REG12__INTCTL:
8011 check_insn(ctx, ISA_MIPS_R2);
8012 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8013 register_name = "IntCtl";
8014 break;
8015 case CP0_REG12__SRSCTL:
8016 check_insn(ctx, ISA_MIPS_R2);
8017 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8018 register_name = "SRSCtl";
8019 break;
8020 case CP0_REG12__SRSMAP:
8021 check_insn(ctx, ISA_MIPS_R2);
8022 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8023 register_name = "SRSMap";
8024 break;
8025 default:
8026 goto cp0_unimplemented;
8028 break;
8029 case CP0_REGISTER_13:
8030 switch (sel) {
8031 case CP0_REG13__CAUSE:
8032 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8033 register_name = "Cause";
8034 break;
8035 default:
8036 goto cp0_unimplemented;
8038 break;
8039 case CP0_REGISTER_14:
8040 switch (sel) {
8041 case CP0_REG14__EPC:
8042 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8043 register_name = "EPC";
8044 break;
8045 default:
8046 goto cp0_unimplemented;
8048 break;
8049 case CP0_REGISTER_15:
8050 switch (sel) {
8051 case CP0_REG15__PRID:
8052 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8053 register_name = "PRid";
8054 break;
8055 case CP0_REG15__EBASE:
8056 check_insn(ctx, ISA_MIPS_R2);
8057 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8058 register_name = "EBase";
8059 break;
8060 case CP0_REG15__CMGCRBASE:
8061 check_insn(ctx, ISA_MIPS_R2);
8062 CP0_CHECK(ctx->cmgcr);
8063 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8064 register_name = "CMGCRBase";
8065 break;
8066 default:
8067 goto cp0_unimplemented;
8069 break;
8070 case CP0_REGISTER_16:
8071 switch (sel) {
8072 case CP0_REG16__CONFIG:
8073 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8074 register_name = "Config";
8075 break;
8076 case CP0_REG16__CONFIG1:
8077 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8078 register_name = "Config1";
8079 break;
8080 case CP0_REG16__CONFIG2:
8081 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8082 register_name = "Config2";
8083 break;
8084 case CP0_REG16__CONFIG3:
8085 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8086 register_name = "Config3";
8087 break;
8088 case CP0_REG16__CONFIG4:
8089 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8090 register_name = "Config4";
8091 break;
8092 case CP0_REG16__CONFIG5:
8093 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8094 register_name = "Config5";
8095 break;
8096 /* 6,7 are implementation dependent */
8097 case CP0_REG16__CONFIG6:
8098 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8099 register_name = "Config6";
8100 break;
8101 case CP0_REG16__CONFIG7:
8102 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8103 register_name = "Config7";
8104 break;
8105 default:
8106 goto cp0_unimplemented;
8108 break;
8109 case CP0_REGISTER_17:
8110 switch (sel) {
8111 case CP0_REG17__LLADDR:
8112 gen_helper_dmfc0_lladdr(arg, cpu_env);
8113 register_name = "LLAddr";
8114 break;
8115 case CP0_REG17__MAAR:
8116 CP0_CHECK(ctx->mrp);
8117 gen_helper_dmfc0_maar(arg, cpu_env);
8118 register_name = "MAAR";
8119 break;
8120 case CP0_REG17__MAARI:
8121 CP0_CHECK(ctx->mrp);
8122 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8123 register_name = "MAARI";
8124 break;
8125 default:
8126 goto cp0_unimplemented;
8128 break;
8129 case CP0_REGISTER_18:
8130 switch (sel) {
8131 case CP0_REG18__WATCHLO0:
8132 case CP0_REG18__WATCHLO1:
8133 case CP0_REG18__WATCHLO2:
8134 case CP0_REG18__WATCHLO3:
8135 case CP0_REG18__WATCHLO4:
8136 case CP0_REG18__WATCHLO5:
8137 case CP0_REG18__WATCHLO6:
8138 case CP0_REG18__WATCHLO7:
8139 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8140 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8141 register_name = "WatchLo";
8142 break;
8143 default:
8144 goto cp0_unimplemented;
8146 break;
8147 case CP0_REGISTER_19:
8148 switch (sel) {
8149 case CP0_REG19__WATCHHI0:
8150 case CP0_REG19__WATCHHI1:
8151 case CP0_REG19__WATCHHI2:
8152 case CP0_REG19__WATCHHI3:
8153 case CP0_REG19__WATCHHI4:
8154 case CP0_REG19__WATCHHI5:
8155 case CP0_REG19__WATCHHI6:
8156 case CP0_REG19__WATCHHI7:
8157 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8158 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
8159 register_name = "WatchHi";
8160 break;
8161 default:
8162 goto cp0_unimplemented;
8164 break;
8165 case CP0_REGISTER_20:
8166 switch (sel) {
8167 case CP0_REG20__XCONTEXT:
8168 check_insn(ctx, ISA_MIPS3);
8169 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8170 register_name = "XContext";
8171 break;
8172 default:
8173 goto cp0_unimplemented;
8175 break;
8176 case CP0_REGISTER_21:
8177 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8178 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8179 switch (sel) {
8180 case 0:
8181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8182 register_name = "Framemask";
8183 break;
8184 default:
8185 goto cp0_unimplemented;
8187 break;
8188 case CP0_REGISTER_22:
8189 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8190 register_name = "'Diagnostic"; /* implementation dependent */
8191 break;
8192 case CP0_REGISTER_23:
8193 switch (sel) {
8194 case CP0_REG23__DEBUG:
8195 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8196 register_name = "Debug";
8197 break;
8198 case CP0_REG23__TRACECONTROL:
8199 /* PDtrace support */
8200 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
8201 register_name = "TraceControl";
8202 goto cp0_unimplemented;
8203 case CP0_REG23__TRACECONTROL2:
8204 /* PDtrace support */
8205 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
8206 register_name = "TraceControl2";
8207 goto cp0_unimplemented;
8208 case CP0_REG23__USERTRACEDATA1:
8209 /* PDtrace support */
8210 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
8211 register_name = "UserTraceData1";
8212 goto cp0_unimplemented;
8213 case CP0_REG23__TRACEIBPC:
8214 /* PDtrace support */
8215 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
8216 register_name = "TraceIBPC";
8217 goto cp0_unimplemented;
8218 case CP0_REG23__TRACEDBPC:
8219 /* PDtrace support */
8220 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
8221 register_name = "TraceDBPC";
8222 goto cp0_unimplemented;
8223 default:
8224 goto cp0_unimplemented;
8226 break;
8227 case CP0_REGISTER_24:
8228 switch (sel) {
8229 case CP0_REG24__DEPC:
8230 /* EJTAG support */
8231 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8232 register_name = "DEPC";
8233 break;
8234 default:
8235 goto cp0_unimplemented;
8237 break;
8238 case CP0_REGISTER_25:
8239 switch (sel) {
8240 case CP0_REG25__PERFCTL0:
8241 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8242 register_name = "Performance0";
8243 break;
8244 case CP0_REG25__PERFCNT0:
8245 /* gen_helper_dmfc0_performance1(arg); */
8246 register_name = "Performance1";
8247 goto cp0_unimplemented;
8248 case CP0_REG25__PERFCTL1:
8249 /* gen_helper_dmfc0_performance2(arg); */
8250 register_name = "Performance2";
8251 goto cp0_unimplemented;
8252 case CP0_REG25__PERFCNT1:
8253 /* gen_helper_dmfc0_performance3(arg); */
8254 register_name = "Performance3";
8255 goto cp0_unimplemented;
8256 case CP0_REG25__PERFCTL2:
8257 /* gen_helper_dmfc0_performance4(arg); */
8258 register_name = "Performance4";
8259 goto cp0_unimplemented;
8260 case CP0_REG25__PERFCNT2:
8261 /* gen_helper_dmfc0_performance5(arg); */
8262 register_name = "Performance5";
8263 goto cp0_unimplemented;
8264 case CP0_REG25__PERFCTL3:
8265 /* gen_helper_dmfc0_performance6(arg); */
8266 register_name = "Performance6";
8267 goto cp0_unimplemented;
8268 case CP0_REG25__PERFCNT3:
8269 /* gen_helper_dmfc0_performance7(arg); */
8270 register_name = "Performance7";
8271 goto cp0_unimplemented;
8272 default:
8273 goto cp0_unimplemented;
8275 break;
8276 case CP0_REGISTER_26:
8277 switch (sel) {
8278 case CP0_REG26__ERRCTL:
8279 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8280 register_name = "ErrCtl";
8281 break;
8282 default:
8283 goto cp0_unimplemented;
8285 break;
8286 case CP0_REGISTER_27:
8287 switch (sel) {
8288 /* ignored */
8289 case CP0_REG27__CACHERR:
8290 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8291 register_name = "CacheErr";
8292 break;
8293 default:
8294 goto cp0_unimplemented;
8296 break;
8297 case CP0_REGISTER_28:
8298 switch (sel) {
8299 case CP0_REG28__TAGLO:
8300 case CP0_REG28__TAGLO1:
8301 case CP0_REG28__TAGLO2:
8302 case CP0_REG28__TAGLO3:
8303 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8304 register_name = "TagLo";
8305 break;
8306 case CP0_REG28__DATALO:
8307 case CP0_REG28__DATALO1:
8308 case CP0_REG28__DATALO2:
8309 case CP0_REG28__DATALO3:
8310 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8311 register_name = "DataLo";
8312 break;
8313 default:
8314 goto cp0_unimplemented;
8316 break;
8317 case CP0_REGISTER_29:
8318 switch (sel) {
8319 case CP0_REG29__TAGHI:
8320 case CP0_REG29__TAGHI1:
8321 case CP0_REG29__TAGHI2:
8322 case CP0_REG29__TAGHI3:
8323 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8324 register_name = "TagHi";
8325 break;
8326 case CP0_REG29__DATAHI:
8327 case CP0_REG29__DATAHI1:
8328 case CP0_REG29__DATAHI2:
8329 case CP0_REG29__DATAHI3:
8330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8331 register_name = "DataHi";
8332 break;
8333 default:
8334 goto cp0_unimplemented;
8336 break;
8337 case CP0_REGISTER_30:
8338 switch (sel) {
8339 case CP0_REG30__ERROREPC:
8340 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8341 register_name = "ErrorEPC";
8342 break;
8343 default:
8344 goto cp0_unimplemented;
8346 break;
8347 case CP0_REGISTER_31:
8348 switch (sel) {
8349 case CP0_REG31__DESAVE:
8350 /* EJTAG support */
8351 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8352 register_name = "DESAVE";
8353 break;
8354 case CP0_REG31__KSCRATCH1:
8355 case CP0_REG31__KSCRATCH2:
8356 case CP0_REG31__KSCRATCH3:
8357 case CP0_REG31__KSCRATCH4:
8358 case CP0_REG31__KSCRATCH5:
8359 case CP0_REG31__KSCRATCH6:
8360 CP0_CHECK(ctx->kscrexist & (1 << sel));
8361 tcg_gen_ld_tl(arg, cpu_env,
8362 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8363 register_name = "KScratch";
8364 break;
8365 default:
8366 goto cp0_unimplemented;
8368 break;
8369 default:
8370 goto cp0_unimplemented;
8372 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
8373 return;
8375 cp0_unimplemented:
8376 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
8377 register_name, reg, sel);
8378 gen_mfc0_unimplemented(ctx, arg);
8381 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8383 const char *register_name = "invalid";
8385 if (sel != 0) {
8386 check_insn(ctx, ISA_MIPS_R1);
8389 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8390 gen_io_start();
8393 switch (reg) {
8394 case CP0_REGISTER_00:
8395 switch (sel) {
8396 case CP0_REG00__INDEX:
8397 gen_helper_mtc0_index(cpu_env, arg);
8398 register_name = "Index";
8399 break;
8400 case CP0_REG00__MVPCONTROL:
8401 CP0_CHECK(ctx->insn_flags & ASE_MT);
8402 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8403 register_name = "MVPControl";
8404 break;
8405 case CP0_REG00__MVPCONF0:
8406 CP0_CHECK(ctx->insn_flags & ASE_MT);
8407 /* ignored */
8408 register_name = "MVPConf0";
8409 break;
8410 case CP0_REG00__MVPCONF1:
8411 CP0_CHECK(ctx->insn_flags & ASE_MT);
8412 /* ignored */
8413 register_name = "MVPConf1";
8414 break;
8415 case CP0_REG00__VPCONTROL:
8416 CP0_CHECK(ctx->vp);
8417 /* ignored */
8418 register_name = "VPControl";
8419 break;
8420 default:
8421 goto cp0_unimplemented;
8423 break;
8424 case CP0_REGISTER_01:
8425 switch (sel) {
8426 case CP0_REG01__RANDOM:
8427 /* ignored */
8428 register_name = "Random";
8429 break;
8430 case CP0_REG01__VPECONTROL:
8431 CP0_CHECK(ctx->insn_flags & ASE_MT);
8432 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8433 register_name = "VPEControl";
8434 break;
8435 case CP0_REG01__VPECONF0:
8436 CP0_CHECK(ctx->insn_flags & ASE_MT);
8437 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8438 register_name = "VPEConf0";
8439 break;
8440 case CP0_REG01__VPECONF1:
8441 CP0_CHECK(ctx->insn_flags & ASE_MT);
8442 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8443 register_name = "VPEConf1";
8444 break;
8445 case CP0_REG01__YQMASK:
8446 CP0_CHECK(ctx->insn_flags & ASE_MT);
8447 gen_helper_mtc0_yqmask(cpu_env, arg);
8448 register_name = "YQMask";
8449 break;
8450 case CP0_REG01__VPESCHEDULE:
8451 CP0_CHECK(ctx->insn_flags & ASE_MT);
8452 tcg_gen_st_tl(arg, cpu_env,
8453 offsetof(CPUMIPSState, CP0_VPESchedule));
8454 register_name = "VPESchedule";
8455 break;
8456 case CP0_REG01__VPESCHEFBACK:
8457 CP0_CHECK(ctx->insn_flags & ASE_MT);
8458 tcg_gen_st_tl(arg, cpu_env,
8459 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8460 register_name = "VPEScheFBack";
8461 break;
8462 case CP0_REG01__VPEOPT:
8463 CP0_CHECK(ctx->insn_flags & ASE_MT);
8464 gen_helper_mtc0_vpeopt(cpu_env, arg);
8465 register_name = "VPEOpt";
8466 break;
8467 default:
8468 goto cp0_unimplemented;
8470 break;
8471 case CP0_REGISTER_02:
8472 switch (sel) {
8473 case CP0_REG02__ENTRYLO0:
8474 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8475 register_name = "EntryLo0";
8476 break;
8477 case CP0_REG02__TCSTATUS:
8478 CP0_CHECK(ctx->insn_flags & ASE_MT);
8479 gen_helper_mtc0_tcstatus(cpu_env, arg);
8480 register_name = "TCStatus";
8481 break;
8482 case CP0_REG02__TCBIND:
8483 CP0_CHECK(ctx->insn_flags & ASE_MT);
8484 gen_helper_mtc0_tcbind(cpu_env, arg);
8485 register_name = "TCBind";
8486 break;
8487 case CP0_REG02__TCRESTART:
8488 CP0_CHECK(ctx->insn_flags & ASE_MT);
8489 gen_helper_mtc0_tcrestart(cpu_env, arg);
8490 register_name = "TCRestart";
8491 break;
8492 case CP0_REG02__TCHALT:
8493 CP0_CHECK(ctx->insn_flags & ASE_MT);
8494 gen_helper_mtc0_tchalt(cpu_env, arg);
8495 register_name = "TCHalt";
8496 break;
8497 case CP0_REG02__TCCONTEXT:
8498 CP0_CHECK(ctx->insn_flags & ASE_MT);
8499 gen_helper_mtc0_tccontext(cpu_env, arg);
8500 register_name = "TCContext";
8501 break;
8502 case CP0_REG02__TCSCHEDULE:
8503 CP0_CHECK(ctx->insn_flags & ASE_MT);
8504 gen_helper_mtc0_tcschedule(cpu_env, arg);
8505 register_name = "TCSchedule";
8506 break;
8507 case CP0_REG02__TCSCHEFBACK:
8508 CP0_CHECK(ctx->insn_flags & ASE_MT);
8509 gen_helper_mtc0_tcschefback(cpu_env, arg);
8510 register_name = "TCScheFBack";
8511 break;
8512 default:
8513 goto cp0_unimplemented;
8515 break;
8516 case CP0_REGISTER_03:
8517 switch (sel) {
8518 case CP0_REG03__ENTRYLO1:
8519 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8520 register_name = "EntryLo1";
8521 break;
8522 case CP0_REG03__GLOBALNUM:
8523 CP0_CHECK(ctx->vp);
8524 /* ignored */
8525 register_name = "GlobalNumber";
8526 break;
8527 default:
8528 goto cp0_unimplemented;
8530 break;
8531 case CP0_REGISTER_04:
8532 switch (sel) {
8533 case CP0_REG04__CONTEXT:
8534 gen_helper_mtc0_context(cpu_env, arg);
8535 register_name = "Context";
8536 break;
8537 case CP0_REG04__CONTEXTCONFIG:
8538 /* SmartMIPS ASE */
8539 /* gen_helper_dmtc0_contextconfig(arg); */
8540 register_name = "ContextConfig";
8541 goto cp0_unimplemented;
8542 case CP0_REG04__USERLOCAL:
8543 CP0_CHECK(ctx->ulri);
8544 tcg_gen_st_tl(arg, cpu_env,
8545 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8546 register_name = "UserLocal";
8547 break;
8548 case CP0_REG04__MMID:
8549 CP0_CHECK(ctx->mi);
8550 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8551 register_name = "MMID";
8552 break;
8553 default:
8554 goto cp0_unimplemented;
8556 break;
8557 case CP0_REGISTER_05:
8558 switch (sel) {
8559 case CP0_REG05__PAGEMASK:
8560 gen_helper_mtc0_pagemask(cpu_env, arg);
8561 register_name = "PageMask";
8562 break;
8563 case CP0_REG05__PAGEGRAIN:
8564 check_insn(ctx, ISA_MIPS_R2);
8565 gen_helper_mtc0_pagegrain(cpu_env, arg);
8566 register_name = "PageGrain";
8567 break;
8568 case CP0_REG05__SEGCTL0:
8569 CP0_CHECK(ctx->sc);
8570 gen_helper_mtc0_segctl0(cpu_env, arg);
8571 register_name = "SegCtl0";
8572 break;
8573 case CP0_REG05__SEGCTL1:
8574 CP0_CHECK(ctx->sc);
8575 gen_helper_mtc0_segctl1(cpu_env, arg);
8576 register_name = "SegCtl1";
8577 break;
8578 case CP0_REG05__SEGCTL2:
8579 CP0_CHECK(ctx->sc);
8580 gen_helper_mtc0_segctl2(cpu_env, arg);
8581 register_name = "SegCtl2";
8582 break;
8583 case CP0_REG05__PWBASE:
8584 check_pw(ctx);
8585 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8586 register_name = "PWBase";
8587 break;
8588 case CP0_REG05__PWFIELD:
8589 check_pw(ctx);
8590 gen_helper_mtc0_pwfield(cpu_env, arg);
8591 register_name = "PWField";
8592 break;
8593 case CP0_REG05__PWSIZE:
8594 check_pw(ctx);
8595 gen_helper_mtc0_pwsize(cpu_env, arg);
8596 register_name = "PWSize";
8597 break;
8598 default:
8599 goto cp0_unimplemented;
8601 break;
8602 case CP0_REGISTER_06:
8603 switch (sel) {
8604 case CP0_REG06__WIRED:
8605 gen_helper_mtc0_wired(cpu_env, arg);
8606 register_name = "Wired";
8607 break;
8608 case CP0_REG06__SRSCONF0:
8609 check_insn(ctx, ISA_MIPS_R2);
8610 gen_helper_mtc0_srsconf0(cpu_env, arg);
8611 register_name = "SRSConf0";
8612 break;
8613 case CP0_REG06__SRSCONF1:
8614 check_insn(ctx, ISA_MIPS_R2);
8615 gen_helper_mtc0_srsconf1(cpu_env, arg);
8616 register_name = "SRSConf1";
8617 break;
8618 case CP0_REG06__SRSCONF2:
8619 check_insn(ctx, ISA_MIPS_R2);
8620 gen_helper_mtc0_srsconf2(cpu_env, arg);
8621 register_name = "SRSConf2";
8622 break;
8623 case CP0_REG06__SRSCONF3:
8624 check_insn(ctx, ISA_MIPS_R2);
8625 gen_helper_mtc0_srsconf3(cpu_env, arg);
8626 register_name = "SRSConf3";
8627 break;
8628 case CP0_REG06__SRSCONF4:
8629 check_insn(ctx, ISA_MIPS_R2);
8630 gen_helper_mtc0_srsconf4(cpu_env, arg);
8631 register_name = "SRSConf4";
8632 break;
8633 case CP0_REG06__PWCTL:
8634 check_pw(ctx);
8635 gen_helper_mtc0_pwctl(cpu_env, arg);
8636 register_name = "PWCtl";
8637 break;
8638 default:
8639 goto cp0_unimplemented;
8641 break;
8642 case CP0_REGISTER_07:
8643 switch (sel) {
8644 case CP0_REG07__HWRENA:
8645 check_insn(ctx, ISA_MIPS_R2);
8646 gen_helper_mtc0_hwrena(cpu_env, arg);
8647 ctx->base.is_jmp = DISAS_STOP;
8648 register_name = "HWREna";
8649 break;
8650 default:
8651 goto cp0_unimplemented;
8653 break;
8654 case CP0_REGISTER_08:
8655 switch (sel) {
8656 case CP0_REG08__BADVADDR:
8657 /* ignored */
8658 register_name = "BadVAddr";
8659 break;
8660 case CP0_REG08__BADINSTR:
8661 /* ignored */
8662 register_name = "BadInstr";
8663 break;
8664 case CP0_REG08__BADINSTRP:
8665 /* ignored */
8666 register_name = "BadInstrP";
8667 break;
8668 case CP0_REG08__BADINSTRX:
8669 /* ignored */
8670 register_name = "BadInstrX";
8671 break;
8672 default:
8673 goto cp0_unimplemented;
8675 break;
8676 case CP0_REGISTER_09:
8677 switch (sel) {
8678 case CP0_REG09__COUNT:
8679 gen_helper_mtc0_count(cpu_env, arg);
8680 register_name = "Count";
8681 break;
8682 case CP0_REG09__SAARI:
8683 CP0_CHECK(ctx->saar);
8684 gen_helper_mtc0_saari(cpu_env, arg);
8685 register_name = "SAARI";
8686 break;
8687 case CP0_REG09__SAAR:
8688 CP0_CHECK(ctx->saar);
8689 gen_helper_mtc0_saar(cpu_env, arg);
8690 register_name = "SAAR";
8691 break;
8692 default:
8693 goto cp0_unimplemented;
8695 /* Stop translation as we may have switched the execution mode */
8696 ctx->base.is_jmp = DISAS_STOP;
8697 break;
8698 case CP0_REGISTER_10:
8699 switch (sel) {
8700 case CP0_REG10__ENTRYHI:
8701 gen_helper_mtc0_entryhi(cpu_env, arg);
8702 register_name = "EntryHi";
8703 break;
8704 default:
8705 goto cp0_unimplemented;
8707 break;
8708 case CP0_REGISTER_11:
8709 switch (sel) {
8710 case CP0_REG11__COMPARE:
8711 gen_helper_mtc0_compare(cpu_env, arg);
8712 register_name = "Compare";
8713 break;
8714 /* 6,7 are implementation dependent */
8715 default:
8716 goto cp0_unimplemented;
8718 /* Stop translation as we may have switched the execution mode */
8719 ctx->base.is_jmp = DISAS_STOP;
8720 break;
8721 case CP0_REGISTER_12:
8722 switch (sel) {
8723 case CP0_REG12__STATUS:
8724 save_cpu_state(ctx, 1);
8725 gen_helper_mtc0_status(cpu_env, arg);
8726 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8727 gen_save_pc(ctx->base.pc_next + 4);
8728 ctx->base.is_jmp = DISAS_EXIT;
8729 register_name = "Status";
8730 break;
8731 case CP0_REG12__INTCTL:
8732 check_insn(ctx, ISA_MIPS_R2);
8733 gen_helper_mtc0_intctl(cpu_env, arg);
8734 /* Stop translation as we may have switched the execution mode */
8735 ctx->base.is_jmp = DISAS_STOP;
8736 register_name = "IntCtl";
8737 break;
8738 case CP0_REG12__SRSCTL:
8739 check_insn(ctx, ISA_MIPS_R2);
8740 gen_helper_mtc0_srsctl(cpu_env, arg);
8741 /* Stop translation as we may have switched the execution mode */
8742 ctx->base.is_jmp = DISAS_STOP;
8743 register_name = "SRSCtl";
8744 break;
8745 case CP0_REG12__SRSMAP:
8746 check_insn(ctx, ISA_MIPS_R2);
8747 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8748 /* Stop translation as we may have switched the execution mode */
8749 ctx->base.is_jmp = DISAS_STOP;
8750 register_name = "SRSMap";
8751 break;
8752 default:
8753 goto cp0_unimplemented;
8755 break;
8756 case CP0_REGISTER_13:
8757 switch (sel) {
8758 case CP0_REG13__CAUSE:
8759 save_cpu_state(ctx, 1);
8760 gen_helper_mtc0_cause(cpu_env, arg);
8762 * Stop translation as we may have triggered an interrupt.
8763 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8764 * translated code to check for pending interrupts.
8766 gen_save_pc(ctx->base.pc_next + 4);
8767 ctx->base.is_jmp = DISAS_EXIT;
8768 register_name = "Cause";
8769 break;
8770 default:
8771 goto cp0_unimplemented;
8773 break;
8774 case CP0_REGISTER_14:
8775 switch (sel) {
8776 case CP0_REG14__EPC:
8777 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8778 register_name = "EPC";
8779 break;
8780 default:
8781 goto cp0_unimplemented;
8783 break;
8784 case CP0_REGISTER_15:
8785 switch (sel) {
8786 case CP0_REG15__PRID:
8787 /* ignored */
8788 register_name = "PRid";
8789 break;
8790 case CP0_REG15__EBASE:
8791 check_insn(ctx, ISA_MIPS_R2);
8792 gen_helper_mtc0_ebase(cpu_env, arg);
8793 register_name = "EBase";
8794 break;
8795 default:
8796 goto cp0_unimplemented;
8798 break;
8799 case CP0_REGISTER_16:
8800 switch (sel) {
8801 case CP0_REG16__CONFIG:
8802 gen_helper_mtc0_config0(cpu_env, arg);
8803 register_name = "Config";
8804 /* Stop translation as we may have switched the execution mode */
8805 ctx->base.is_jmp = DISAS_STOP;
8806 break;
8807 case CP0_REG16__CONFIG1:
8808 /* ignored, read only */
8809 register_name = "Config1";
8810 break;
8811 case CP0_REG16__CONFIG2:
8812 gen_helper_mtc0_config2(cpu_env, arg);
8813 register_name = "Config2";
8814 /* Stop translation as we may have switched the execution mode */
8815 ctx->base.is_jmp = DISAS_STOP;
8816 break;
8817 case CP0_REG16__CONFIG3:
8818 gen_helper_mtc0_config3(cpu_env, arg);
8819 register_name = "Config3";
8820 /* Stop translation as we may have switched the execution mode */
8821 ctx->base.is_jmp = DISAS_STOP;
8822 break;
8823 case CP0_REG16__CONFIG4:
8824 /* currently ignored */
8825 register_name = "Config4";
8826 break;
8827 case CP0_REG16__CONFIG5:
8828 gen_helper_mtc0_config5(cpu_env, arg);
8829 register_name = "Config5";
8830 /* Stop translation as we may have switched the execution mode */
8831 ctx->base.is_jmp = DISAS_STOP;
8832 break;
8833 /* 6,7 are implementation dependent */
8834 default:
8835 register_name = "Invalid config selector";
8836 goto cp0_unimplemented;
8838 break;
8839 case CP0_REGISTER_17:
8840 switch (sel) {
8841 case CP0_REG17__LLADDR:
8842 gen_helper_mtc0_lladdr(cpu_env, arg);
8843 register_name = "LLAddr";
8844 break;
8845 case CP0_REG17__MAAR:
8846 CP0_CHECK(ctx->mrp);
8847 gen_helper_mtc0_maar(cpu_env, arg);
8848 register_name = "MAAR";
8849 break;
8850 case CP0_REG17__MAARI:
8851 CP0_CHECK(ctx->mrp);
8852 gen_helper_mtc0_maari(cpu_env, arg);
8853 register_name = "MAARI";
8854 break;
8855 default:
8856 goto cp0_unimplemented;
8858 break;
8859 case CP0_REGISTER_18:
8860 switch (sel) {
8861 case CP0_REG18__WATCHLO0:
8862 case CP0_REG18__WATCHLO1:
8863 case CP0_REG18__WATCHLO2:
8864 case CP0_REG18__WATCHLO3:
8865 case CP0_REG18__WATCHLO4:
8866 case CP0_REG18__WATCHLO5:
8867 case CP0_REG18__WATCHLO6:
8868 case CP0_REG18__WATCHLO7:
8869 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8870 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8871 register_name = "WatchLo";
8872 break;
8873 default:
8874 goto cp0_unimplemented;
8876 break;
8877 case CP0_REGISTER_19:
8878 switch (sel) {
8879 case CP0_REG19__WATCHHI0:
8880 case CP0_REG19__WATCHHI1:
8881 case CP0_REG19__WATCHHI2:
8882 case CP0_REG19__WATCHHI3:
8883 case CP0_REG19__WATCHHI4:
8884 case CP0_REG19__WATCHHI5:
8885 case CP0_REG19__WATCHHI6:
8886 case CP0_REG19__WATCHHI7:
8887 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8888 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8889 register_name = "WatchHi";
8890 break;
8891 default:
8892 goto cp0_unimplemented;
8894 break;
8895 case CP0_REGISTER_20:
8896 switch (sel) {
8897 case CP0_REG20__XCONTEXT:
8898 check_insn(ctx, ISA_MIPS3);
8899 gen_helper_mtc0_xcontext(cpu_env, arg);
8900 register_name = "XContext";
8901 break;
8902 default:
8903 goto cp0_unimplemented;
8905 break;
8906 case CP0_REGISTER_21:
8907 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8908 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8909 switch (sel) {
8910 case 0:
8911 gen_helper_mtc0_framemask(cpu_env, arg);
8912 register_name = "Framemask";
8913 break;
8914 default:
8915 goto cp0_unimplemented;
8917 break;
8918 case CP0_REGISTER_22:
8919 /* ignored */
8920 register_name = "Diagnostic"; /* implementation dependent */
8921 break;
8922 case CP0_REGISTER_23:
8923 switch (sel) {
8924 case CP0_REG23__DEBUG:
8925 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8926 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8927 gen_save_pc(ctx->base.pc_next + 4);
8928 ctx->base.is_jmp = DISAS_EXIT;
8929 register_name = "Debug";
8930 break;
8931 case CP0_REG23__TRACECONTROL:
8932 /* PDtrace support */
8933 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8934 /* Stop translation as we may have switched the execution mode */
8935 ctx->base.is_jmp = DISAS_STOP;
8936 register_name = "TraceControl";
8937 goto cp0_unimplemented;
8938 case CP0_REG23__TRACECONTROL2:
8939 /* PDtrace support */
8940 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8941 /* Stop translation as we may have switched the execution mode */
8942 ctx->base.is_jmp = DISAS_STOP;
8943 register_name = "TraceControl2";
8944 goto cp0_unimplemented;
8945 case CP0_REG23__USERTRACEDATA1:
8946 /* PDtrace support */
8947 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8948 /* Stop translation as we may have switched the execution mode */
8949 ctx->base.is_jmp = DISAS_STOP;
8950 register_name = "UserTraceData1";
8951 goto cp0_unimplemented;
8952 case CP0_REG23__TRACEIBPC:
8953 /* PDtrace support */
8954 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8955 /* Stop translation as we may have switched the execution mode */
8956 ctx->base.is_jmp = DISAS_STOP;
8957 register_name = "TraceIBPC";
8958 goto cp0_unimplemented;
8959 case CP0_REG23__TRACEDBPC:
8960 /* PDtrace support */
8961 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8962 /* Stop translation as we may have switched the execution mode */
8963 ctx->base.is_jmp = DISAS_STOP;
8964 register_name = "TraceDBPC";
8965 goto cp0_unimplemented;
8966 default:
8967 goto cp0_unimplemented;
8969 break;
8970 case CP0_REGISTER_24:
8971 switch (sel) {
8972 case CP0_REG24__DEPC:
8973 /* EJTAG support */
8974 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8975 register_name = "DEPC";
8976 break;
8977 default:
8978 goto cp0_unimplemented;
8980 break;
8981 case CP0_REGISTER_25:
8982 switch (sel) {
8983 case CP0_REG25__PERFCTL0:
8984 gen_helper_mtc0_performance0(cpu_env, arg);
8985 register_name = "Performance0";
8986 break;
8987 case CP0_REG25__PERFCNT0:
8988 /* gen_helper_mtc0_performance1(cpu_env, arg); */
8989 register_name = "Performance1";
8990 goto cp0_unimplemented;
8991 case CP0_REG25__PERFCTL1:
8992 /* gen_helper_mtc0_performance2(cpu_env, arg); */
8993 register_name = "Performance2";
8994 goto cp0_unimplemented;
8995 case CP0_REG25__PERFCNT1:
8996 /* gen_helper_mtc0_performance3(cpu_env, arg); */
8997 register_name = "Performance3";
8998 goto cp0_unimplemented;
8999 case CP0_REG25__PERFCTL2:
9000 /* gen_helper_mtc0_performance4(cpu_env, arg); */
9001 register_name = "Performance4";
9002 goto cp0_unimplemented;
9003 case CP0_REG25__PERFCNT2:
9004 /* gen_helper_mtc0_performance5(cpu_env, arg); */
9005 register_name = "Performance5";
9006 goto cp0_unimplemented;
9007 case CP0_REG25__PERFCTL3:
9008 /* gen_helper_mtc0_performance6(cpu_env, arg); */
9009 register_name = "Performance6";
9010 goto cp0_unimplemented;
9011 case CP0_REG25__PERFCNT3:
9012 /* gen_helper_mtc0_performance7(cpu_env, arg); */
9013 register_name = "Performance7";
9014 goto cp0_unimplemented;
9015 default:
9016 goto cp0_unimplemented;
9018 break;
9019 case CP0_REGISTER_26:
9020 switch (sel) {
9021 case CP0_REG26__ERRCTL:
9022 gen_helper_mtc0_errctl(cpu_env, arg);
9023 ctx->base.is_jmp = DISAS_STOP;
9024 register_name = "ErrCtl";
9025 break;
9026 default:
9027 goto cp0_unimplemented;
9029 break;
9030 case CP0_REGISTER_27:
9031 switch (sel) {
9032 case CP0_REG27__CACHERR:
9033 /* ignored */
9034 register_name = "CacheErr";
9035 break;
9036 default:
9037 goto cp0_unimplemented;
9039 break;
9040 case CP0_REGISTER_28:
9041 switch (sel) {
9042 case CP0_REG28__TAGLO:
9043 case CP0_REG28__TAGLO1:
9044 case CP0_REG28__TAGLO2:
9045 case CP0_REG28__TAGLO3:
9046 gen_helper_mtc0_taglo(cpu_env, arg);
9047 register_name = "TagLo";
9048 break;
9049 case CP0_REG28__DATALO:
9050 case CP0_REG28__DATALO1:
9051 case CP0_REG28__DATALO2:
9052 case CP0_REG28__DATALO3:
9053 gen_helper_mtc0_datalo(cpu_env, arg);
9054 register_name = "DataLo";
9055 break;
9056 default:
9057 goto cp0_unimplemented;
9059 break;
9060 case CP0_REGISTER_29:
9061 switch (sel) {
9062 case CP0_REG29__TAGHI:
9063 case CP0_REG29__TAGHI1:
9064 case CP0_REG29__TAGHI2:
9065 case CP0_REG29__TAGHI3:
9066 gen_helper_mtc0_taghi(cpu_env, arg);
9067 register_name = "TagHi";
9068 break;
9069 case CP0_REG29__DATAHI:
9070 case CP0_REG29__DATAHI1:
9071 case CP0_REG29__DATAHI2:
9072 case CP0_REG29__DATAHI3:
9073 gen_helper_mtc0_datahi(cpu_env, arg);
9074 register_name = "DataHi";
9075 break;
9076 default:
9077 register_name = "invalid sel";
9078 goto cp0_unimplemented;
9080 break;
9081 case CP0_REGISTER_30:
9082 switch (sel) {
9083 case CP0_REG30__ERROREPC:
9084 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9085 register_name = "ErrorEPC";
9086 break;
9087 default:
9088 goto cp0_unimplemented;
9090 break;
9091 case CP0_REGISTER_31:
9092 switch (sel) {
9093 case CP0_REG31__DESAVE:
9094 /* EJTAG support */
9095 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9096 register_name = "DESAVE";
9097 break;
9098 case CP0_REG31__KSCRATCH1:
9099 case CP0_REG31__KSCRATCH2:
9100 case CP0_REG31__KSCRATCH3:
9101 case CP0_REG31__KSCRATCH4:
9102 case CP0_REG31__KSCRATCH5:
9103 case CP0_REG31__KSCRATCH6:
9104 CP0_CHECK(ctx->kscrexist & (1 << sel));
9105 tcg_gen_st_tl(arg, cpu_env,
9106 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9107 register_name = "KScratch";
9108 break;
9109 default:
9110 goto cp0_unimplemented;
9112 break;
9113 default:
9114 goto cp0_unimplemented;
9116 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9118 /* For simplicity assume that all writes can cause interrupts. */
9119 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9121 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9122 * translated code to check for pending interrupts.
9124 gen_save_pc(ctx->base.pc_next + 4);
9125 ctx->base.is_jmp = DISAS_EXIT;
9127 return;
9129 cp0_unimplemented:
9130 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9131 register_name, reg, sel);
9133 #endif /* TARGET_MIPS64 */
9135 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9136 int u, int sel, int h)
9138 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9139 TCGv t0 = tcg_temp_local_new();
9141 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9142 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9143 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9144 tcg_gen_movi_tl(t0, -1);
9145 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9146 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9147 tcg_gen_movi_tl(t0, -1);
9148 } else if (u == 0) {
9149 switch (rt) {
9150 case 1:
9151 switch (sel) {
9152 case 1:
9153 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9154 break;
9155 case 2:
9156 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9157 break;
9158 default:
9159 goto die;
9160 break;
9162 break;
9163 case 2:
9164 switch (sel) {
9165 case 1:
9166 gen_helper_mftc0_tcstatus(t0, cpu_env);
9167 break;
9168 case 2:
9169 gen_helper_mftc0_tcbind(t0, cpu_env);
9170 break;
9171 case 3:
9172 gen_helper_mftc0_tcrestart(t0, cpu_env);
9173 break;
9174 case 4:
9175 gen_helper_mftc0_tchalt(t0, cpu_env);
9176 break;
9177 case 5:
9178 gen_helper_mftc0_tccontext(t0, cpu_env);
9179 break;
9180 case 6:
9181 gen_helper_mftc0_tcschedule(t0, cpu_env);
9182 break;
9183 case 7:
9184 gen_helper_mftc0_tcschefback(t0, cpu_env);
9185 break;
9186 default:
9187 gen_mfc0(ctx, t0, rt, sel);
9188 break;
9190 break;
9191 case 10:
9192 switch (sel) {
9193 case 0:
9194 gen_helper_mftc0_entryhi(t0, cpu_env);
9195 break;
9196 default:
9197 gen_mfc0(ctx, t0, rt, sel);
9198 break;
9200 break;
9201 case 12:
9202 switch (sel) {
9203 case 0:
9204 gen_helper_mftc0_status(t0, cpu_env);
9205 break;
9206 default:
9207 gen_mfc0(ctx, t0, rt, sel);
9208 break;
9210 break;
9211 case 13:
9212 switch (sel) {
9213 case 0:
9214 gen_helper_mftc0_cause(t0, cpu_env);
9215 break;
9216 default:
9217 goto die;
9218 break;
9220 break;
9221 case 14:
9222 switch (sel) {
9223 case 0:
9224 gen_helper_mftc0_epc(t0, cpu_env);
9225 break;
9226 default:
9227 goto die;
9228 break;
9230 break;
9231 case 15:
9232 switch (sel) {
9233 case 1:
9234 gen_helper_mftc0_ebase(t0, cpu_env);
9235 break;
9236 default:
9237 goto die;
9238 break;
9240 break;
9241 case 16:
9242 switch (sel) {
9243 case 0:
9244 case 1:
9245 case 2:
9246 case 3:
9247 case 4:
9248 case 5:
9249 case 6:
9250 case 7:
9251 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9252 break;
9253 default:
9254 goto die;
9255 break;
9257 break;
9258 case 23:
9259 switch (sel) {
9260 case 0:
9261 gen_helper_mftc0_debug(t0, cpu_env);
9262 break;
9263 default:
9264 gen_mfc0(ctx, t0, rt, sel);
9265 break;
9267 break;
9268 default:
9269 gen_mfc0(ctx, t0, rt, sel);
9271 } else {
9272 switch (sel) {
9273 /* GPR registers. */
9274 case 0:
9275 gen_helper_1e0i(mftgpr, t0, rt);
9276 break;
9277 /* Auxiliary CPU registers */
9278 case 1:
9279 switch (rt) {
9280 case 0:
9281 gen_helper_1e0i(mftlo, t0, 0);
9282 break;
9283 case 1:
9284 gen_helper_1e0i(mfthi, t0, 0);
9285 break;
9286 case 2:
9287 gen_helper_1e0i(mftacx, t0, 0);
9288 break;
9289 case 4:
9290 gen_helper_1e0i(mftlo, t0, 1);
9291 break;
9292 case 5:
9293 gen_helper_1e0i(mfthi, t0, 1);
9294 break;
9295 case 6:
9296 gen_helper_1e0i(mftacx, t0, 1);
9297 break;
9298 case 8:
9299 gen_helper_1e0i(mftlo, t0, 2);
9300 break;
9301 case 9:
9302 gen_helper_1e0i(mfthi, t0, 2);
9303 break;
9304 case 10:
9305 gen_helper_1e0i(mftacx, t0, 2);
9306 break;
9307 case 12:
9308 gen_helper_1e0i(mftlo, t0, 3);
9309 break;
9310 case 13:
9311 gen_helper_1e0i(mfthi, t0, 3);
9312 break;
9313 case 14:
9314 gen_helper_1e0i(mftacx, t0, 3);
9315 break;
9316 case 16:
9317 gen_helper_mftdsp(t0, cpu_env);
9318 break;
9319 default:
9320 goto die;
9322 break;
9323 /* Floating point (COP1). */
9324 case 2:
9325 /* XXX: For now we support only a single FPU context. */
9326 if (h == 0) {
9327 TCGv_i32 fp0 = tcg_temp_new_i32();
9329 gen_load_fpr32(ctx, fp0, rt);
9330 tcg_gen_ext_i32_tl(t0, fp0);
9331 tcg_temp_free_i32(fp0);
9332 } else {
9333 TCGv_i32 fp0 = tcg_temp_new_i32();
9335 gen_load_fpr32h(ctx, fp0, rt);
9336 tcg_gen_ext_i32_tl(t0, fp0);
9337 tcg_temp_free_i32(fp0);
9339 break;
9340 case 3:
9341 /* XXX: For now we support only a single FPU context. */
9342 gen_helper_1e0i(cfc1, t0, rt);
9343 break;
9344 /* COP2: Not implemented. */
9345 case 4:
9346 case 5:
9347 /* fall through */
9348 default:
9349 goto die;
9352 trace_mips_translate_tr("mftr", rt, u, sel, h);
9353 gen_store_gpr(t0, rd);
9354 tcg_temp_free(t0);
9355 return;
9357 die:
9358 tcg_temp_free(t0);
9359 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9360 gen_reserved_instruction(ctx);
9363 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9364 int u, int sel, int h)
9366 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9367 TCGv t0 = tcg_temp_local_new();
9369 gen_load_gpr(t0, rt);
9370 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9371 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9372 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9373 /* NOP */
9375 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9376 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9377 /* NOP */
9379 } else if (u == 0) {
9380 switch (rd) {
9381 case 1:
9382 switch (sel) {
9383 case 1:
9384 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9385 break;
9386 case 2:
9387 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9388 break;
9389 default:
9390 goto die;
9391 break;
9393 break;
9394 case 2:
9395 switch (sel) {
9396 case 1:
9397 gen_helper_mttc0_tcstatus(cpu_env, t0);
9398 break;
9399 case 2:
9400 gen_helper_mttc0_tcbind(cpu_env, t0);
9401 break;
9402 case 3:
9403 gen_helper_mttc0_tcrestart(cpu_env, t0);
9404 break;
9405 case 4:
9406 gen_helper_mttc0_tchalt(cpu_env, t0);
9407 break;
9408 case 5:
9409 gen_helper_mttc0_tccontext(cpu_env, t0);
9410 break;
9411 case 6:
9412 gen_helper_mttc0_tcschedule(cpu_env, t0);
9413 break;
9414 case 7:
9415 gen_helper_mttc0_tcschefback(cpu_env, t0);
9416 break;
9417 default:
9418 gen_mtc0(ctx, t0, rd, sel);
9419 break;
9421 break;
9422 case 10:
9423 switch (sel) {
9424 case 0:
9425 gen_helper_mttc0_entryhi(cpu_env, t0);
9426 break;
9427 default:
9428 gen_mtc0(ctx, t0, rd, sel);
9429 break;
9431 break;
9432 case 12:
9433 switch (sel) {
9434 case 0:
9435 gen_helper_mttc0_status(cpu_env, t0);
9436 break;
9437 default:
9438 gen_mtc0(ctx, t0, rd, sel);
9439 break;
9441 break;
9442 case 13:
9443 switch (sel) {
9444 case 0:
9445 gen_helper_mttc0_cause(cpu_env, t0);
9446 break;
9447 default:
9448 goto die;
9449 break;
9451 break;
9452 case 15:
9453 switch (sel) {
9454 case 1:
9455 gen_helper_mttc0_ebase(cpu_env, t0);
9456 break;
9457 default:
9458 goto die;
9459 break;
9461 break;
9462 case 23:
9463 switch (sel) {
9464 case 0:
9465 gen_helper_mttc0_debug(cpu_env, t0);
9466 break;
9467 default:
9468 gen_mtc0(ctx, t0, rd, sel);
9469 break;
9471 break;
9472 default:
9473 gen_mtc0(ctx, t0, rd, sel);
9475 } else {
9476 switch (sel) {
9477 /* GPR registers. */
9478 case 0:
9479 gen_helper_0e1i(mttgpr, t0, rd);
9480 break;
9481 /* Auxiliary CPU registers */
9482 case 1:
9483 switch (rd) {
9484 case 0:
9485 gen_helper_0e1i(mttlo, t0, 0);
9486 break;
9487 case 1:
9488 gen_helper_0e1i(mtthi, t0, 0);
9489 break;
9490 case 2:
9491 gen_helper_0e1i(mttacx, t0, 0);
9492 break;
9493 case 4:
9494 gen_helper_0e1i(mttlo, t0, 1);
9495 break;
9496 case 5:
9497 gen_helper_0e1i(mtthi, t0, 1);
9498 break;
9499 case 6:
9500 gen_helper_0e1i(mttacx, t0, 1);
9501 break;
9502 case 8:
9503 gen_helper_0e1i(mttlo, t0, 2);
9504 break;
9505 case 9:
9506 gen_helper_0e1i(mtthi, t0, 2);
9507 break;
9508 case 10:
9509 gen_helper_0e1i(mttacx, t0, 2);
9510 break;
9511 case 12:
9512 gen_helper_0e1i(mttlo, t0, 3);
9513 break;
9514 case 13:
9515 gen_helper_0e1i(mtthi, t0, 3);
9516 break;
9517 case 14:
9518 gen_helper_0e1i(mttacx, t0, 3);
9519 break;
9520 case 16:
9521 gen_helper_mttdsp(cpu_env, t0);
9522 break;
9523 default:
9524 goto die;
9526 break;
9527 /* Floating point (COP1). */
9528 case 2:
9529 /* XXX: For now we support only a single FPU context. */
9530 if (h == 0) {
9531 TCGv_i32 fp0 = tcg_temp_new_i32();
9533 tcg_gen_trunc_tl_i32(fp0, t0);
9534 gen_store_fpr32(ctx, fp0, rd);
9535 tcg_temp_free_i32(fp0);
9536 } else {
9537 TCGv_i32 fp0 = tcg_temp_new_i32();
9539 tcg_gen_trunc_tl_i32(fp0, t0);
9540 gen_store_fpr32h(ctx, fp0, rd);
9541 tcg_temp_free_i32(fp0);
9543 break;
9544 case 3:
9545 /* XXX: For now we support only a single FPU context. */
9547 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9549 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9550 tcg_temp_free_i32(fs_tmp);
9552 /* Stop translation as we may have changed hflags */
9553 ctx->base.is_jmp = DISAS_STOP;
9554 break;
9555 /* COP2: Not implemented. */
9556 case 4:
9557 case 5:
9558 /* fall through */
9559 default:
9560 goto die;
9563 trace_mips_translate_tr("mttr", rd, u, sel, h);
9564 tcg_temp_free(t0);
9565 return;
9567 die:
9568 tcg_temp_free(t0);
9569 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9570 gen_reserved_instruction(ctx);
9573 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
9574 int rt, int rd)
9576 const char *opn = "ldst";
9578 check_cp0_enabled(ctx);
9579 switch (opc) {
9580 case OPC_MFC0:
9581 if (rt == 0) {
9582 /* Treat as NOP. */
9583 return;
9585 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9586 opn = "mfc0";
9587 break;
9588 case OPC_MTC0:
9590 TCGv t0 = tcg_temp_new();
9592 gen_load_gpr(t0, rt);
9593 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9594 tcg_temp_free(t0);
9596 opn = "mtc0";
9597 break;
9598 #if defined(TARGET_MIPS64)
9599 case OPC_DMFC0:
9600 check_insn(ctx, ISA_MIPS3);
9601 if (rt == 0) {
9602 /* Treat as NOP. */
9603 return;
9605 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9606 opn = "dmfc0";
9607 break;
9608 case OPC_DMTC0:
9609 check_insn(ctx, ISA_MIPS3);
9611 TCGv t0 = tcg_temp_new();
9613 gen_load_gpr(t0, rt);
9614 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9615 tcg_temp_free(t0);
9617 opn = "dmtc0";
9618 break;
9619 #endif
9620 case OPC_MFHC0:
9621 check_mvh(ctx);
9622 if (rt == 0) {
9623 /* Treat as NOP. */
9624 return;
9626 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9627 opn = "mfhc0";
9628 break;
9629 case OPC_MTHC0:
9630 check_mvh(ctx);
9632 TCGv t0 = tcg_temp_new();
9633 gen_load_gpr(t0, rt);
9634 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9635 tcg_temp_free(t0);
9637 opn = "mthc0";
9638 break;
9639 case OPC_MFTR:
9640 check_cp0_enabled(ctx);
9641 if (rd == 0) {
9642 /* Treat as NOP. */
9643 return;
9645 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9646 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9647 opn = "mftr";
9648 break;
9649 case OPC_MTTR:
9650 check_cp0_enabled(ctx);
9651 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9652 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9653 opn = "mttr";
9654 break;
9655 case OPC_TLBWI:
9656 opn = "tlbwi";
9657 if (!env->tlb->helper_tlbwi) {
9658 goto die;
9660 gen_helper_tlbwi(cpu_env);
9661 break;
9662 case OPC_TLBINV:
9663 opn = "tlbinv";
9664 if (ctx->ie >= 2) {
9665 if (!env->tlb->helper_tlbinv) {
9666 goto die;
9668 gen_helper_tlbinv(cpu_env);
9669 } /* treat as nop if TLBINV not supported */
9670 break;
9671 case OPC_TLBINVF:
9672 opn = "tlbinvf";
9673 if (ctx->ie >= 2) {
9674 if (!env->tlb->helper_tlbinvf) {
9675 goto die;
9677 gen_helper_tlbinvf(cpu_env);
9678 } /* treat as nop if TLBINV not supported */
9679 break;
9680 case OPC_TLBWR:
9681 opn = "tlbwr";
9682 if (!env->tlb->helper_tlbwr) {
9683 goto die;
9685 gen_helper_tlbwr(cpu_env);
9686 break;
9687 case OPC_TLBP:
9688 opn = "tlbp";
9689 if (!env->tlb->helper_tlbp) {
9690 goto die;
9692 gen_helper_tlbp(cpu_env);
9693 break;
9694 case OPC_TLBR:
9695 opn = "tlbr";
9696 if (!env->tlb->helper_tlbr) {
9697 goto die;
9699 gen_helper_tlbr(cpu_env);
9700 break;
9701 case OPC_ERET: /* OPC_ERETNC */
9702 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9703 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9704 goto die;
9705 } else {
9706 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9707 if (ctx->opcode & (1 << bit_shift)) {
9708 /* OPC_ERETNC */
9709 opn = "eretnc";
9710 check_insn(ctx, ISA_MIPS_R5);
9711 gen_helper_eretnc(cpu_env);
9712 } else {
9713 /* OPC_ERET */
9714 opn = "eret";
9715 check_insn(ctx, ISA_MIPS2);
9716 gen_helper_eret(cpu_env);
9718 ctx->base.is_jmp = DISAS_EXIT;
9720 break;
9721 case OPC_DERET:
9722 opn = "deret";
9723 check_insn(ctx, ISA_MIPS_R1);
9724 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9725 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9726 goto die;
9728 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9729 MIPS_INVAL(opn);
9730 gen_reserved_instruction(ctx);
9731 } else {
9732 gen_helper_deret(cpu_env);
9733 ctx->base.is_jmp = DISAS_EXIT;
9735 break;
9736 case OPC_WAIT:
9737 opn = "wait";
9738 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
9739 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9740 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9741 goto die;
9743 /* If we get an exception, we want to restart at next instruction */
9744 ctx->base.pc_next += 4;
9745 save_cpu_state(ctx, 1);
9746 ctx->base.pc_next -= 4;
9747 gen_helper_wait(cpu_env);
9748 ctx->base.is_jmp = DISAS_NORETURN;
9749 break;
9750 default:
9751 die:
9752 MIPS_INVAL(opn);
9753 gen_reserved_instruction(ctx);
9754 return;
9756 (void)opn; /* avoid a compiler warning */
9758 #endif /* !CONFIG_USER_ONLY */
9760 /* CP1 Branches (before delay slot) */
9761 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9762 int32_t cc, int32_t offset)
9764 target_ulong btarget;
9765 TCGv_i32 t0 = tcg_temp_new_i32();
9767 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9768 gen_reserved_instruction(ctx);
9769 goto out;
9772 if (cc != 0) {
9773 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
9776 btarget = ctx->base.pc_next + 4 + offset;
9778 switch (op) {
9779 case OPC_BC1F:
9780 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9781 tcg_gen_not_i32(t0, t0);
9782 tcg_gen_andi_i32(t0, t0, 1);
9783 tcg_gen_extu_i32_tl(bcond, t0);
9784 goto not_likely;
9785 case OPC_BC1FL:
9786 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9787 tcg_gen_not_i32(t0, t0);
9788 tcg_gen_andi_i32(t0, t0, 1);
9789 tcg_gen_extu_i32_tl(bcond, t0);
9790 goto likely;
9791 case OPC_BC1T:
9792 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9793 tcg_gen_andi_i32(t0, t0, 1);
9794 tcg_gen_extu_i32_tl(bcond, t0);
9795 goto not_likely;
9796 case OPC_BC1TL:
9797 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9798 tcg_gen_andi_i32(t0, t0, 1);
9799 tcg_gen_extu_i32_tl(bcond, t0);
9800 likely:
9801 ctx->hflags |= MIPS_HFLAG_BL;
9802 break;
9803 case OPC_BC1FANY2:
9805 TCGv_i32 t1 = tcg_temp_new_i32();
9806 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9807 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9808 tcg_gen_nand_i32(t0, t0, t1);
9809 tcg_temp_free_i32(t1);
9810 tcg_gen_andi_i32(t0, t0, 1);
9811 tcg_gen_extu_i32_tl(bcond, t0);
9813 goto not_likely;
9814 case OPC_BC1TANY2:
9816 TCGv_i32 t1 = tcg_temp_new_i32();
9817 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9818 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9819 tcg_gen_or_i32(t0, t0, t1);
9820 tcg_temp_free_i32(t1);
9821 tcg_gen_andi_i32(t0, t0, 1);
9822 tcg_gen_extu_i32_tl(bcond, t0);
9824 goto not_likely;
9825 case OPC_BC1FANY4:
9827 TCGv_i32 t1 = tcg_temp_new_i32();
9828 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9829 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9830 tcg_gen_and_i32(t0, t0, t1);
9831 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
9832 tcg_gen_and_i32(t0, t0, t1);
9833 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
9834 tcg_gen_nand_i32(t0, t0, t1);
9835 tcg_temp_free_i32(t1);
9836 tcg_gen_andi_i32(t0, t0, 1);
9837 tcg_gen_extu_i32_tl(bcond, t0);
9839 goto not_likely;
9840 case OPC_BC1TANY4:
9842 TCGv_i32 t1 = tcg_temp_new_i32();
9843 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9844 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9845 tcg_gen_or_i32(t0, t0, t1);
9846 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
9847 tcg_gen_or_i32(t0, t0, t1);
9848 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
9849 tcg_gen_or_i32(t0, t0, t1);
9850 tcg_temp_free_i32(t1);
9851 tcg_gen_andi_i32(t0, t0, 1);
9852 tcg_gen_extu_i32_tl(bcond, t0);
9854 not_likely:
9855 ctx->hflags |= MIPS_HFLAG_BC;
9856 break;
9857 default:
9858 MIPS_INVAL("cp1 cond branch");
9859 gen_reserved_instruction(ctx);
9860 goto out;
9862 ctx->btarget = btarget;
9863 ctx->hflags |= MIPS_HFLAG_BDS32;
9864 out:
9865 tcg_temp_free_i32(t0);
9868 /* R6 CP1 Branches */
9869 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
9870 int32_t ft, int32_t offset,
9871 int delayslot_size)
9873 target_ulong btarget;
9874 TCGv_i64 t0 = tcg_temp_new_i64();
9876 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9877 #ifdef MIPS_DEBUG_DISAS
9878 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
9879 "\n", ctx->base.pc_next);
9880 #endif
9881 gen_reserved_instruction(ctx);
9882 goto out;
9885 gen_load_fpr64(ctx, t0, ft);
9886 tcg_gen_andi_i64(t0, t0, 1);
9888 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
9890 switch (op) {
9891 case OPC_BC1EQZ:
9892 tcg_gen_xori_i64(t0, t0, 1);
9893 ctx->hflags |= MIPS_HFLAG_BC;
9894 break;
9895 case OPC_BC1NEZ:
9896 /* t0 already set */
9897 ctx->hflags |= MIPS_HFLAG_BC;
9898 break;
9899 default:
9900 MIPS_INVAL("cp1 cond branch");
9901 gen_reserved_instruction(ctx);
9902 goto out;
9905 tcg_gen_trunc_i64_tl(bcond, t0);
9907 ctx->btarget = btarget;
9909 switch (delayslot_size) {
9910 case 2:
9911 ctx->hflags |= MIPS_HFLAG_BDS16;
9912 break;
9913 case 4:
9914 ctx->hflags |= MIPS_HFLAG_BDS32;
9915 break;
9918 out:
9919 tcg_temp_free_i64(t0);
9922 /* Coprocessor 1 (FPU) */
9924 #define FOP(func, fmt) (((fmt) << 21) | (func))
9926 enum fopcode {
9927 OPC_ADD_S = FOP(0, FMT_S),
9928 OPC_SUB_S = FOP(1, FMT_S),
9929 OPC_MUL_S = FOP(2, FMT_S),
9930 OPC_DIV_S = FOP(3, FMT_S),
9931 OPC_SQRT_S = FOP(4, FMT_S),
9932 OPC_ABS_S = FOP(5, FMT_S),
9933 OPC_MOV_S = FOP(6, FMT_S),
9934 OPC_NEG_S = FOP(7, FMT_S),
9935 OPC_ROUND_L_S = FOP(8, FMT_S),
9936 OPC_TRUNC_L_S = FOP(9, FMT_S),
9937 OPC_CEIL_L_S = FOP(10, FMT_S),
9938 OPC_FLOOR_L_S = FOP(11, FMT_S),
9939 OPC_ROUND_W_S = FOP(12, FMT_S),
9940 OPC_TRUNC_W_S = FOP(13, FMT_S),
9941 OPC_CEIL_W_S = FOP(14, FMT_S),
9942 OPC_FLOOR_W_S = FOP(15, FMT_S),
9943 OPC_SEL_S = FOP(16, FMT_S),
9944 OPC_MOVCF_S = FOP(17, FMT_S),
9945 OPC_MOVZ_S = FOP(18, FMT_S),
9946 OPC_MOVN_S = FOP(19, FMT_S),
9947 OPC_SELEQZ_S = FOP(20, FMT_S),
9948 OPC_RECIP_S = FOP(21, FMT_S),
9949 OPC_RSQRT_S = FOP(22, FMT_S),
9950 OPC_SELNEZ_S = FOP(23, FMT_S),
9951 OPC_MADDF_S = FOP(24, FMT_S),
9952 OPC_MSUBF_S = FOP(25, FMT_S),
9953 OPC_RINT_S = FOP(26, FMT_S),
9954 OPC_CLASS_S = FOP(27, FMT_S),
9955 OPC_MIN_S = FOP(28, FMT_S),
9956 OPC_RECIP2_S = FOP(28, FMT_S),
9957 OPC_MINA_S = FOP(29, FMT_S),
9958 OPC_RECIP1_S = FOP(29, FMT_S),
9959 OPC_MAX_S = FOP(30, FMT_S),
9960 OPC_RSQRT1_S = FOP(30, FMT_S),
9961 OPC_MAXA_S = FOP(31, FMT_S),
9962 OPC_RSQRT2_S = FOP(31, FMT_S),
9963 OPC_CVT_D_S = FOP(33, FMT_S),
9964 OPC_CVT_W_S = FOP(36, FMT_S),
9965 OPC_CVT_L_S = FOP(37, FMT_S),
9966 OPC_CVT_PS_S = FOP(38, FMT_S),
9967 OPC_CMP_F_S = FOP(48, FMT_S),
9968 OPC_CMP_UN_S = FOP(49, FMT_S),
9969 OPC_CMP_EQ_S = FOP(50, FMT_S),
9970 OPC_CMP_UEQ_S = FOP(51, FMT_S),
9971 OPC_CMP_OLT_S = FOP(52, FMT_S),
9972 OPC_CMP_ULT_S = FOP(53, FMT_S),
9973 OPC_CMP_OLE_S = FOP(54, FMT_S),
9974 OPC_CMP_ULE_S = FOP(55, FMT_S),
9975 OPC_CMP_SF_S = FOP(56, FMT_S),
9976 OPC_CMP_NGLE_S = FOP(57, FMT_S),
9977 OPC_CMP_SEQ_S = FOP(58, FMT_S),
9978 OPC_CMP_NGL_S = FOP(59, FMT_S),
9979 OPC_CMP_LT_S = FOP(60, FMT_S),
9980 OPC_CMP_NGE_S = FOP(61, FMT_S),
9981 OPC_CMP_LE_S = FOP(62, FMT_S),
9982 OPC_CMP_NGT_S = FOP(63, FMT_S),
9984 OPC_ADD_D = FOP(0, FMT_D),
9985 OPC_SUB_D = FOP(1, FMT_D),
9986 OPC_MUL_D = FOP(2, FMT_D),
9987 OPC_DIV_D = FOP(3, FMT_D),
9988 OPC_SQRT_D = FOP(4, FMT_D),
9989 OPC_ABS_D = FOP(5, FMT_D),
9990 OPC_MOV_D = FOP(6, FMT_D),
9991 OPC_NEG_D = FOP(7, FMT_D),
9992 OPC_ROUND_L_D = FOP(8, FMT_D),
9993 OPC_TRUNC_L_D = FOP(9, FMT_D),
9994 OPC_CEIL_L_D = FOP(10, FMT_D),
9995 OPC_FLOOR_L_D = FOP(11, FMT_D),
9996 OPC_ROUND_W_D = FOP(12, FMT_D),
9997 OPC_TRUNC_W_D = FOP(13, FMT_D),
9998 OPC_CEIL_W_D = FOP(14, FMT_D),
9999 OPC_FLOOR_W_D = FOP(15, FMT_D),
10000 OPC_SEL_D = FOP(16, FMT_D),
10001 OPC_MOVCF_D = FOP(17, FMT_D),
10002 OPC_MOVZ_D = FOP(18, FMT_D),
10003 OPC_MOVN_D = FOP(19, FMT_D),
10004 OPC_SELEQZ_D = FOP(20, FMT_D),
10005 OPC_RECIP_D = FOP(21, FMT_D),
10006 OPC_RSQRT_D = FOP(22, FMT_D),
10007 OPC_SELNEZ_D = FOP(23, FMT_D),
10008 OPC_MADDF_D = FOP(24, FMT_D),
10009 OPC_MSUBF_D = FOP(25, FMT_D),
10010 OPC_RINT_D = FOP(26, FMT_D),
10011 OPC_CLASS_D = FOP(27, FMT_D),
10012 OPC_MIN_D = FOP(28, FMT_D),
10013 OPC_RECIP2_D = FOP(28, FMT_D),
10014 OPC_MINA_D = FOP(29, FMT_D),
10015 OPC_RECIP1_D = FOP(29, FMT_D),
10016 OPC_MAX_D = FOP(30, FMT_D),
10017 OPC_RSQRT1_D = FOP(30, FMT_D),
10018 OPC_MAXA_D = FOP(31, FMT_D),
10019 OPC_RSQRT2_D = FOP(31, FMT_D),
10020 OPC_CVT_S_D = FOP(32, FMT_D),
10021 OPC_CVT_W_D = FOP(36, FMT_D),
10022 OPC_CVT_L_D = FOP(37, FMT_D),
10023 OPC_CMP_F_D = FOP(48, FMT_D),
10024 OPC_CMP_UN_D = FOP(49, FMT_D),
10025 OPC_CMP_EQ_D = FOP(50, FMT_D),
10026 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10027 OPC_CMP_OLT_D = FOP(52, FMT_D),
10028 OPC_CMP_ULT_D = FOP(53, FMT_D),
10029 OPC_CMP_OLE_D = FOP(54, FMT_D),
10030 OPC_CMP_ULE_D = FOP(55, FMT_D),
10031 OPC_CMP_SF_D = FOP(56, FMT_D),
10032 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10033 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10034 OPC_CMP_NGL_D = FOP(59, FMT_D),
10035 OPC_CMP_LT_D = FOP(60, FMT_D),
10036 OPC_CMP_NGE_D = FOP(61, FMT_D),
10037 OPC_CMP_LE_D = FOP(62, FMT_D),
10038 OPC_CMP_NGT_D = FOP(63, FMT_D),
10040 OPC_CVT_S_W = FOP(32, FMT_W),
10041 OPC_CVT_D_W = FOP(33, FMT_W),
10042 OPC_CVT_S_L = FOP(32, FMT_L),
10043 OPC_CVT_D_L = FOP(33, FMT_L),
10044 OPC_CVT_PS_PW = FOP(38, FMT_W),
10046 OPC_ADD_PS = FOP(0, FMT_PS),
10047 OPC_SUB_PS = FOP(1, FMT_PS),
10048 OPC_MUL_PS = FOP(2, FMT_PS),
10049 OPC_DIV_PS = FOP(3, FMT_PS),
10050 OPC_ABS_PS = FOP(5, FMT_PS),
10051 OPC_MOV_PS = FOP(6, FMT_PS),
10052 OPC_NEG_PS = FOP(7, FMT_PS),
10053 OPC_MOVCF_PS = FOP(17, FMT_PS),
10054 OPC_MOVZ_PS = FOP(18, FMT_PS),
10055 OPC_MOVN_PS = FOP(19, FMT_PS),
10056 OPC_ADDR_PS = FOP(24, FMT_PS),
10057 OPC_MULR_PS = FOP(26, FMT_PS),
10058 OPC_RECIP2_PS = FOP(28, FMT_PS),
10059 OPC_RECIP1_PS = FOP(29, FMT_PS),
10060 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10061 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10063 OPC_CVT_S_PU = FOP(32, FMT_PS),
10064 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10065 OPC_CVT_S_PL = FOP(40, FMT_PS),
10066 OPC_PLL_PS = FOP(44, FMT_PS),
10067 OPC_PLU_PS = FOP(45, FMT_PS),
10068 OPC_PUL_PS = FOP(46, FMT_PS),
10069 OPC_PUU_PS = FOP(47, FMT_PS),
10070 OPC_CMP_F_PS = FOP(48, FMT_PS),
10071 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10072 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10073 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10074 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10075 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10076 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10077 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10078 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10079 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10080 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10081 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10082 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10083 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10084 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10085 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
10088 enum r6_f_cmp_op {
10089 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10090 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10091 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10092 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10093 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10094 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10095 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10096 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10097 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10098 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10099 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10100 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10101 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10102 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10103 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10104 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10105 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10106 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10107 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10108 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10109 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10110 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10112 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10113 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10114 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10115 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10116 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10117 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10118 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10119 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10120 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10121 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10122 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10123 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10124 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10125 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10126 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10127 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10128 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10129 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10130 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10131 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10132 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10133 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10136 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
10138 TCGv t0 = tcg_temp_new();
10140 switch (opc) {
10141 case OPC_MFC1:
10143 TCGv_i32 fp0 = tcg_temp_new_i32();
10145 gen_load_fpr32(ctx, fp0, fs);
10146 tcg_gen_ext_i32_tl(t0, fp0);
10147 tcg_temp_free_i32(fp0);
10149 gen_store_gpr(t0, rt);
10150 break;
10151 case OPC_MTC1:
10152 gen_load_gpr(t0, rt);
10154 TCGv_i32 fp0 = tcg_temp_new_i32();
10156 tcg_gen_trunc_tl_i32(fp0, t0);
10157 gen_store_fpr32(ctx, fp0, fs);
10158 tcg_temp_free_i32(fp0);
10160 break;
10161 case OPC_CFC1:
10162 gen_helper_1e0i(cfc1, t0, fs);
10163 gen_store_gpr(t0, rt);
10164 break;
10165 case OPC_CTC1:
10166 gen_load_gpr(t0, rt);
10167 save_cpu_state(ctx, 0);
10169 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10171 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10172 tcg_temp_free_i32(fs_tmp);
10174 /* Stop translation as we may have changed hflags */
10175 ctx->base.is_jmp = DISAS_STOP;
10176 break;
10177 #if defined(TARGET_MIPS64)
10178 case OPC_DMFC1:
10179 gen_load_fpr64(ctx, t0, fs);
10180 gen_store_gpr(t0, rt);
10181 break;
10182 case OPC_DMTC1:
10183 gen_load_gpr(t0, rt);
10184 gen_store_fpr64(ctx, t0, fs);
10185 break;
10186 #endif
10187 case OPC_MFHC1:
10189 TCGv_i32 fp0 = tcg_temp_new_i32();
10191 gen_load_fpr32h(ctx, fp0, fs);
10192 tcg_gen_ext_i32_tl(t0, fp0);
10193 tcg_temp_free_i32(fp0);
10195 gen_store_gpr(t0, rt);
10196 break;
10197 case OPC_MTHC1:
10198 gen_load_gpr(t0, rt);
10200 TCGv_i32 fp0 = tcg_temp_new_i32();
10202 tcg_gen_trunc_tl_i32(fp0, t0);
10203 gen_store_fpr32h(ctx, fp0, fs);
10204 tcg_temp_free_i32(fp0);
10206 break;
10207 default:
10208 MIPS_INVAL("cp1 move");
10209 gen_reserved_instruction(ctx);
10210 goto out;
10213 out:
10214 tcg_temp_free(t0);
10217 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
10219 TCGLabel *l1;
10220 TCGCond cond;
10221 TCGv_i32 t0;
10223 if (rd == 0) {
10224 /* Treat as NOP. */
10225 return;
10228 if (tf) {
10229 cond = TCG_COND_EQ;
10230 } else {
10231 cond = TCG_COND_NE;
10234 l1 = gen_new_label();
10235 t0 = tcg_temp_new_i32();
10236 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10237 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10238 tcg_temp_free_i32(t0);
10239 gen_load_gpr(cpu_gpr[rd], rs);
10240 gen_set_label(l1);
10243 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10244 int tf)
10246 int cond;
10247 TCGv_i32 t0 = tcg_temp_new_i32();
10248 TCGLabel *l1 = gen_new_label();
10250 if (tf) {
10251 cond = TCG_COND_EQ;
10252 } else {
10253 cond = TCG_COND_NE;
10256 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10257 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10258 gen_load_fpr32(ctx, t0, fs);
10259 gen_store_fpr32(ctx, t0, fd);
10260 gen_set_label(l1);
10261 tcg_temp_free_i32(t0);
10264 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
10265 int tf)
10267 int cond;
10268 TCGv_i32 t0 = tcg_temp_new_i32();
10269 TCGv_i64 fp0;
10270 TCGLabel *l1 = gen_new_label();
10272 if (tf) {
10273 cond = TCG_COND_EQ;
10274 } else {
10275 cond = TCG_COND_NE;
10278 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10279 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10280 tcg_temp_free_i32(t0);
10281 fp0 = tcg_temp_new_i64();
10282 gen_load_fpr64(ctx, fp0, fs);
10283 gen_store_fpr64(ctx, fp0, fd);
10284 tcg_temp_free_i64(fp0);
10285 gen_set_label(l1);
10288 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10289 int cc, int tf)
10291 int cond;
10292 TCGv_i32 t0 = tcg_temp_new_i32();
10293 TCGLabel *l1 = gen_new_label();
10294 TCGLabel *l2 = gen_new_label();
10296 if (tf) {
10297 cond = TCG_COND_EQ;
10298 } else {
10299 cond = TCG_COND_NE;
10302 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10303 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10304 gen_load_fpr32(ctx, t0, fs);
10305 gen_store_fpr32(ctx, t0, fd);
10306 gen_set_label(l1);
10308 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
10309 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10310 gen_load_fpr32h(ctx, t0, fs);
10311 gen_store_fpr32h(ctx, t0, fd);
10312 tcg_temp_free_i32(t0);
10313 gen_set_label(l2);
10316 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10317 int fs)
10319 TCGv_i32 t1 = tcg_const_i32(0);
10320 TCGv_i32 fp0 = tcg_temp_new_i32();
10321 TCGv_i32 fp1 = tcg_temp_new_i32();
10322 TCGv_i32 fp2 = tcg_temp_new_i32();
10323 gen_load_fpr32(ctx, fp0, fd);
10324 gen_load_fpr32(ctx, fp1, ft);
10325 gen_load_fpr32(ctx, fp2, fs);
10327 switch (op1) {
10328 case OPC_SEL_S:
10329 tcg_gen_andi_i32(fp0, fp0, 1);
10330 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10331 break;
10332 case OPC_SELEQZ_S:
10333 tcg_gen_andi_i32(fp1, fp1, 1);
10334 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10335 break;
10336 case OPC_SELNEZ_S:
10337 tcg_gen_andi_i32(fp1, fp1, 1);
10338 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10339 break;
10340 default:
10341 MIPS_INVAL("gen_sel_s");
10342 gen_reserved_instruction(ctx);
10343 break;
10346 gen_store_fpr32(ctx, fp0, fd);
10347 tcg_temp_free_i32(fp2);
10348 tcg_temp_free_i32(fp1);
10349 tcg_temp_free_i32(fp0);
10350 tcg_temp_free_i32(t1);
10353 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10354 int fs)
10356 TCGv_i64 t1 = tcg_const_i64(0);
10357 TCGv_i64 fp0 = tcg_temp_new_i64();
10358 TCGv_i64 fp1 = tcg_temp_new_i64();
10359 TCGv_i64 fp2 = tcg_temp_new_i64();
10360 gen_load_fpr64(ctx, fp0, fd);
10361 gen_load_fpr64(ctx, fp1, ft);
10362 gen_load_fpr64(ctx, fp2, fs);
10364 switch (op1) {
10365 case OPC_SEL_D:
10366 tcg_gen_andi_i64(fp0, fp0, 1);
10367 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10368 break;
10369 case OPC_SELEQZ_D:
10370 tcg_gen_andi_i64(fp1, fp1, 1);
10371 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10372 break;
10373 case OPC_SELNEZ_D:
10374 tcg_gen_andi_i64(fp1, fp1, 1);
10375 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10376 break;
10377 default:
10378 MIPS_INVAL("gen_sel_d");
10379 gen_reserved_instruction(ctx);
10380 break;
10383 gen_store_fpr64(ctx, fp0, fd);
10384 tcg_temp_free_i64(fp2);
10385 tcg_temp_free_i64(fp1);
10386 tcg_temp_free_i64(fp0);
10387 tcg_temp_free_i64(t1);
10390 static void gen_farith(DisasContext *ctx, enum fopcode op1,
10391 int ft, int fs, int fd, int cc)
10393 uint32_t func = ctx->opcode & 0x3f;
10394 switch (op1) {
10395 case OPC_ADD_S:
10397 TCGv_i32 fp0 = tcg_temp_new_i32();
10398 TCGv_i32 fp1 = tcg_temp_new_i32();
10400 gen_load_fpr32(ctx, fp0, fs);
10401 gen_load_fpr32(ctx, fp1, ft);
10402 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10403 tcg_temp_free_i32(fp1);
10404 gen_store_fpr32(ctx, fp0, fd);
10405 tcg_temp_free_i32(fp0);
10407 break;
10408 case OPC_SUB_S:
10410 TCGv_i32 fp0 = tcg_temp_new_i32();
10411 TCGv_i32 fp1 = tcg_temp_new_i32();
10413 gen_load_fpr32(ctx, fp0, fs);
10414 gen_load_fpr32(ctx, fp1, ft);
10415 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10416 tcg_temp_free_i32(fp1);
10417 gen_store_fpr32(ctx, fp0, fd);
10418 tcg_temp_free_i32(fp0);
10420 break;
10421 case OPC_MUL_S:
10423 TCGv_i32 fp0 = tcg_temp_new_i32();
10424 TCGv_i32 fp1 = tcg_temp_new_i32();
10426 gen_load_fpr32(ctx, fp0, fs);
10427 gen_load_fpr32(ctx, fp1, ft);
10428 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10429 tcg_temp_free_i32(fp1);
10430 gen_store_fpr32(ctx, fp0, fd);
10431 tcg_temp_free_i32(fp0);
10433 break;
10434 case OPC_DIV_S:
10436 TCGv_i32 fp0 = tcg_temp_new_i32();
10437 TCGv_i32 fp1 = tcg_temp_new_i32();
10439 gen_load_fpr32(ctx, fp0, fs);
10440 gen_load_fpr32(ctx, fp1, ft);
10441 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10442 tcg_temp_free_i32(fp1);
10443 gen_store_fpr32(ctx, fp0, fd);
10444 tcg_temp_free_i32(fp0);
10446 break;
10447 case OPC_SQRT_S:
10449 TCGv_i32 fp0 = tcg_temp_new_i32();
10451 gen_load_fpr32(ctx, fp0, fs);
10452 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10453 gen_store_fpr32(ctx, fp0, fd);
10454 tcg_temp_free_i32(fp0);
10456 break;
10457 case OPC_ABS_S:
10459 TCGv_i32 fp0 = tcg_temp_new_i32();
10461 gen_load_fpr32(ctx, fp0, fs);
10462 if (ctx->abs2008) {
10463 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10464 } else {
10465 gen_helper_float_abs_s(fp0, fp0);
10467 gen_store_fpr32(ctx, fp0, fd);
10468 tcg_temp_free_i32(fp0);
10470 break;
10471 case OPC_MOV_S:
10473 TCGv_i32 fp0 = tcg_temp_new_i32();
10475 gen_load_fpr32(ctx, fp0, fs);
10476 gen_store_fpr32(ctx, fp0, fd);
10477 tcg_temp_free_i32(fp0);
10479 break;
10480 case OPC_NEG_S:
10482 TCGv_i32 fp0 = tcg_temp_new_i32();
10484 gen_load_fpr32(ctx, fp0, fs);
10485 if (ctx->abs2008) {
10486 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10487 } else {
10488 gen_helper_float_chs_s(fp0, fp0);
10490 gen_store_fpr32(ctx, fp0, fd);
10491 tcg_temp_free_i32(fp0);
10493 break;
10494 case OPC_ROUND_L_S:
10495 check_cp1_64bitmode(ctx);
10497 TCGv_i32 fp32 = tcg_temp_new_i32();
10498 TCGv_i64 fp64 = tcg_temp_new_i64();
10500 gen_load_fpr32(ctx, fp32, fs);
10501 if (ctx->nan2008) {
10502 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10503 } else {
10504 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10506 tcg_temp_free_i32(fp32);
10507 gen_store_fpr64(ctx, fp64, fd);
10508 tcg_temp_free_i64(fp64);
10510 break;
10511 case OPC_TRUNC_L_S:
10512 check_cp1_64bitmode(ctx);
10514 TCGv_i32 fp32 = tcg_temp_new_i32();
10515 TCGv_i64 fp64 = tcg_temp_new_i64();
10517 gen_load_fpr32(ctx, fp32, fs);
10518 if (ctx->nan2008) {
10519 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10520 } else {
10521 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10523 tcg_temp_free_i32(fp32);
10524 gen_store_fpr64(ctx, fp64, fd);
10525 tcg_temp_free_i64(fp64);
10527 break;
10528 case OPC_CEIL_L_S:
10529 check_cp1_64bitmode(ctx);
10531 TCGv_i32 fp32 = tcg_temp_new_i32();
10532 TCGv_i64 fp64 = tcg_temp_new_i64();
10534 gen_load_fpr32(ctx, fp32, fs);
10535 if (ctx->nan2008) {
10536 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10537 } else {
10538 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10540 tcg_temp_free_i32(fp32);
10541 gen_store_fpr64(ctx, fp64, fd);
10542 tcg_temp_free_i64(fp64);
10544 break;
10545 case OPC_FLOOR_L_S:
10546 check_cp1_64bitmode(ctx);
10548 TCGv_i32 fp32 = tcg_temp_new_i32();
10549 TCGv_i64 fp64 = tcg_temp_new_i64();
10551 gen_load_fpr32(ctx, fp32, fs);
10552 if (ctx->nan2008) {
10553 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10554 } else {
10555 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10557 tcg_temp_free_i32(fp32);
10558 gen_store_fpr64(ctx, fp64, fd);
10559 tcg_temp_free_i64(fp64);
10561 break;
10562 case OPC_ROUND_W_S:
10564 TCGv_i32 fp0 = tcg_temp_new_i32();
10566 gen_load_fpr32(ctx, fp0, fs);
10567 if (ctx->nan2008) {
10568 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10569 } else {
10570 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10572 gen_store_fpr32(ctx, fp0, fd);
10573 tcg_temp_free_i32(fp0);
10575 break;
10576 case OPC_TRUNC_W_S:
10578 TCGv_i32 fp0 = tcg_temp_new_i32();
10580 gen_load_fpr32(ctx, fp0, fs);
10581 if (ctx->nan2008) {
10582 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10583 } else {
10584 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10586 gen_store_fpr32(ctx, fp0, fd);
10587 tcg_temp_free_i32(fp0);
10589 break;
10590 case OPC_CEIL_W_S:
10592 TCGv_i32 fp0 = tcg_temp_new_i32();
10594 gen_load_fpr32(ctx, fp0, fs);
10595 if (ctx->nan2008) {
10596 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10597 } else {
10598 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10600 gen_store_fpr32(ctx, fp0, fd);
10601 tcg_temp_free_i32(fp0);
10603 break;
10604 case OPC_FLOOR_W_S:
10606 TCGv_i32 fp0 = tcg_temp_new_i32();
10608 gen_load_fpr32(ctx, fp0, fs);
10609 if (ctx->nan2008) {
10610 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10611 } else {
10612 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10614 gen_store_fpr32(ctx, fp0, fd);
10615 tcg_temp_free_i32(fp0);
10617 break;
10618 case OPC_SEL_S:
10619 check_insn(ctx, ISA_MIPS_R6);
10620 gen_sel_s(ctx, op1, fd, ft, fs);
10621 break;
10622 case OPC_SELEQZ_S:
10623 check_insn(ctx, ISA_MIPS_R6);
10624 gen_sel_s(ctx, op1, fd, ft, fs);
10625 break;
10626 case OPC_SELNEZ_S:
10627 check_insn(ctx, ISA_MIPS_R6);
10628 gen_sel_s(ctx, op1, fd, ft, fs);
10629 break;
10630 case OPC_MOVCF_S:
10631 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10632 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10633 break;
10634 case OPC_MOVZ_S:
10635 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10637 TCGLabel *l1 = gen_new_label();
10638 TCGv_i32 fp0;
10640 if (ft != 0) {
10641 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10643 fp0 = tcg_temp_new_i32();
10644 gen_load_fpr32(ctx, fp0, fs);
10645 gen_store_fpr32(ctx, fp0, fd);
10646 tcg_temp_free_i32(fp0);
10647 gen_set_label(l1);
10649 break;
10650 case OPC_MOVN_S:
10651 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10653 TCGLabel *l1 = gen_new_label();
10654 TCGv_i32 fp0;
10656 if (ft != 0) {
10657 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10658 fp0 = tcg_temp_new_i32();
10659 gen_load_fpr32(ctx, fp0, fs);
10660 gen_store_fpr32(ctx, fp0, fd);
10661 tcg_temp_free_i32(fp0);
10662 gen_set_label(l1);
10665 break;
10666 case OPC_RECIP_S:
10668 TCGv_i32 fp0 = tcg_temp_new_i32();
10670 gen_load_fpr32(ctx, fp0, fs);
10671 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10672 gen_store_fpr32(ctx, fp0, fd);
10673 tcg_temp_free_i32(fp0);
10675 break;
10676 case OPC_RSQRT_S:
10678 TCGv_i32 fp0 = tcg_temp_new_i32();
10680 gen_load_fpr32(ctx, fp0, fs);
10681 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10682 gen_store_fpr32(ctx, fp0, fd);
10683 tcg_temp_free_i32(fp0);
10685 break;
10686 case OPC_MADDF_S:
10687 check_insn(ctx, ISA_MIPS_R6);
10689 TCGv_i32 fp0 = tcg_temp_new_i32();
10690 TCGv_i32 fp1 = tcg_temp_new_i32();
10691 TCGv_i32 fp2 = tcg_temp_new_i32();
10692 gen_load_fpr32(ctx, fp0, fs);
10693 gen_load_fpr32(ctx, fp1, ft);
10694 gen_load_fpr32(ctx, fp2, fd);
10695 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10696 gen_store_fpr32(ctx, fp2, fd);
10697 tcg_temp_free_i32(fp2);
10698 tcg_temp_free_i32(fp1);
10699 tcg_temp_free_i32(fp0);
10701 break;
10702 case OPC_MSUBF_S:
10703 check_insn(ctx, ISA_MIPS_R6);
10705 TCGv_i32 fp0 = tcg_temp_new_i32();
10706 TCGv_i32 fp1 = tcg_temp_new_i32();
10707 TCGv_i32 fp2 = tcg_temp_new_i32();
10708 gen_load_fpr32(ctx, fp0, fs);
10709 gen_load_fpr32(ctx, fp1, ft);
10710 gen_load_fpr32(ctx, fp2, fd);
10711 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10712 gen_store_fpr32(ctx, fp2, fd);
10713 tcg_temp_free_i32(fp2);
10714 tcg_temp_free_i32(fp1);
10715 tcg_temp_free_i32(fp0);
10717 break;
10718 case OPC_RINT_S:
10719 check_insn(ctx, ISA_MIPS_R6);
10721 TCGv_i32 fp0 = tcg_temp_new_i32();
10722 gen_load_fpr32(ctx, fp0, fs);
10723 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10724 gen_store_fpr32(ctx, fp0, fd);
10725 tcg_temp_free_i32(fp0);
10727 break;
10728 case OPC_CLASS_S:
10729 check_insn(ctx, ISA_MIPS_R6);
10731 TCGv_i32 fp0 = tcg_temp_new_i32();
10732 gen_load_fpr32(ctx, fp0, fs);
10733 gen_helper_float_class_s(fp0, cpu_env, fp0);
10734 gen_store_fpr32(ctx, fp0, fd);
10735 tcg_temp_free_i32(fp0);
10737 break;
10738 case OPC_MIN_S: /* OPC_RECIP2_S */
10739 if (ctx->insn_flags & ISA_MIPS_R6) {
10740 /* OPC_MIN_S */
10741 TCGv_i32 fp0 = tcg_temp_new_i32();
10742 TCGv_i32 fp1 = tcg_temp_new_i32();
10743 TCGv_i32 fp2 = tcg_temp_new_i32();
10744 gen_load_fpr32(ctx, fp0, fs);
10745 gen_load_fpr32(ctx, fp1, ft);
10746 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10747 gen_store_fpr32(ctx, fp2, fd);
10748 tcg_temp_free_i32(fp2);
10749 tcg_temp_free_i32(fp1);
10750 tcg_temp_free_i32(fp0);
10751 } else {
10752 /* OPC_RECIP2_S */
10753 check_cp1_64bitmode(ctx);
10755 TCGv_i32 fp0 = tcg_temp_new_i32();
10756 TCGv_i32 fp1 = tcg_temp_new_i32();
10758 gen_load_fpr32(ctx, fp0, fs);
10759 gen_load_fpr32(ctx, fp1, ft);
10760 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10761 tcg_temp_free_i32(fp1);
10762 gen_store_fpr32(ctx, fp0, fd);
10763 tcg_temp_free_i32(fp0);
10766 break;
10767 case OPC_MINA_S: /* OPC_RECIP1_S */
10768 if (ctx->insn_flags & ISA_MIPS_R6) {
10769 /* OPC_MINA_S */
10770 TCGv_i32 fp0 = tcg_temp_new_i32();
10771 TCGv_i32 fp1 = tcg_temp_new_i32();
10772 TCGv_i32 fp2 = tcg_temp_new_i32();
10773 gen_load_fpr32(ctx, fp0, fs);
10774 gen_load_fpr32(ctx, fp1, ft);
10775 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10776 gen_store_fpr32(ctx, fp2, fd);
10777 tcg_temp_free_i32(fp2);
10778 tcg_temp_free_i32(fp1);
10779 tcg_temp_free_i32(fp0);
10780 } else {
10781 /* OPC_RECIP1_S */
10782 check_cp1_64bitmode(ctx);
10784 TCGv_i32 fp0 = tcg_temp_new_i32();
10786 gen_load_fpr32(ctx, fp0, fs);
10787 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10788 gen_store_fpr32(ctx, fp0, fd);
10789 tcg_temp_free_i32(fp0);
10792 break;
10793 case OPC_MAX_S: /* OPC_RSQRT1_S */
10794 if (ctx->insn_flags & ISA_MIPS_R6) {
10795 /* OPC_MAX_S */
10796 TCGv_i32 fp0 = tcg_temp_new_i32();
10797 TCGv_i32 fp1 = tcg_temp_new_i32();
10798 gen_load_fpr32(ctx, fp0, fs);
10799 gen_load_fpr32(ctx, fp1, ft);
10800 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10801 gen_store_fpr32(ctx, fp1, fd);
10802 tcg_temp_free_i32(fp1);
10803 tcg_temp_free_i32(fp0);
10804 } else {
10805 /* OPC_RSQRT1_S */
10806 check_cp1_64bitmode(ctx);
10808 TCGv_i32 fp0 = tcg_temp_new_i32();
10810 gen_load_fpr32(ctx, fp0, fs);
10811 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
10812 gen_store_fpr32(ctx, fp0, fd);
10813 tcg_temp_free_i32(fp0);
10816 break;
10817 case OPC_MAXA_S: /* OPC_RSQRT2_S */
10818 if (ctx->insn_flags & ISA_MIPS_R6) {
10819 /* OPC_MAXA_S */
10820 TCGv_i32 fp0 = tcg_temp_new_i32();
10821 TCGv_i32 fp1 = tcg_temp_new_i32();
10822 gen_load_fpr32(ctx, fp0, fs);
10823 gen_load_fpr32(ctx, fp1, ft);
10824 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
10825 gen_store_fpr32(ctx, fp1, fd);
10826 tcg_temp_free_i32(fp1);
10827 tcg_temp_free_i32(fp0);
10828 } else {
10829 /* OPC_RSQRT2_S */
10830 check_cp1_64bitmode(ctx);
10832 TCGv_i32 fp0 = tcg_temp_new_i32();
10833 TCGv_i32 fp1 = tcg_temp_new_i32();
10835 gen_load_fpr32(ctx, fp0, fs);
10836 gen_load_fpr32(ctx, fp1, ft);
10837 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10838 tcg_temp_free_i32(fp1);
10839 gen_store_fpr32(ctx, fp0, fd);
10840 tcg_temp_free_i32(fp0);
10843 break;
10844 case OPC_CVT_D_S:
10845 check_cp1_registers(ctx, fd);
10847 TCGv_i32 fp32 = tcg_temp_new_i32();
10848 TCGv_i64 fp64 = tcg_temp_new_i64();
10850 gen_load_fpr32(ctx, fp32, fs);
10851 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
10852 tcg_temp_free_i32(fp32);
10853 gen_store_fpr64(ctx, fp64, fd);
10854 tcg_temp_free_i64(fp64);
10856 break;
10857 case OPC_CVT_W_S:
10859 TCGv_i32 fp0 = tcg_temp_new_i32();
10861 gen_load_fpr32(ctx, fp0, fs);
10862 if (ctx->nan2008) {
10863 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
10864 } else {
10865 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
10867 gen_store_fpr32(ctx, fp0, fd);
10868 tcg_temp_free_i32(fp0);
10870 break;
10871 case OPC_CVT_L_S:
10872 check_cp1_64bitmode(ctx);
10874 TCGv_i32 fp32 = tcg_temp_new_i32();
10875 TCGv_i64 fp64 = tcg_temp_new_i64();
10877 gen_load_fpr32(ctx, fp32, fs);
10878 if (ctx->nan2008) {
10879 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
10880 } else {
10881 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
10883 tcg_temp_free_i32(fp32);
10884 gen_store_fpr64(ctx, fp64, fd);
10885 tcg_temp_free_i64(fp64);
10887 break;
10888 case OPC_CVT_PS_S:
10889 check_ps(ctx);
10891 TCGv_i64 fp64 = tcg_temp_new_i64();
10892 TCGv_i32 fp32_0 = tcg_temp_new_i32();
10893 TCGv_i32 fp32_1 = tcg_temp_new_i32();
10895 gen_load_fpr32(ctx, fp32_0, fs);
10896 gen_load_fpr32(ctx, fp32_1, ft);
10897 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
10898 tcg_temp_free_i32(fp32_1);
10899 tcg_temp_free_i32(fp32_0);
10900 gen_store_fpr64(ctx, fp64, fd);
10901 tcg_temp_free_i64(fp64);
10903 break;
10904 case OPC_CMP_F_S:
10905 case OPC_CMP_UN_S:
10906 case OPC_CMP_EQ_S:
10907 case OPC_CMP_UEQ_S:
10908 case OPC_CMP_OLT_S:
10909 case OPC_CMP_ULT_S:
10910 case OPC_CMP_OLE_S:
10911 case OPC_CMP_ULE_S:
10912 case OPC_CMP_SF_S:
10913 case OPC_CMP_NGLE_S:
10914 case OPC_CMP_SEQ_S:
10915 case OPC_CMP_NGL_S:
10916 case OPC_CMP_LT_S:
10917 case OPC_CMP_NGE_S:
10918 case OPC_CMP_LE_S:
10919 case OPC_CMP_NGT_S:
10920 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10921 if (ctx->opcode & (1 << 6)) {
10922 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
10923 } else {
10924 gen_cmp_s(ctx, func - 48, ft, fs, cc);
10926 break;
10927 case OPC_ADD_D:
10928 check_cp1_registers(ctx, fs | ft | fd);
10930 TCGv_i64 fp0 = tcg_temp_new_i64();
10931 TCGv_i64 fp1 = tcg_temp_new_i64();
10933 gen_load_fpr64(ctx, fp0, fs);
10934 gen_load_fpr64(ctx, fp1, ft);
10935 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
10936 tcg_temp_free_i64(fp1);
10937 gen_store_fpr64(ctx, fp0, fd);
10938 tcg_temp_free_i64(fp0);
10940 break;
10941 case OPC_SUB_D:
10942 check_cp1_registers(ctx, fs | ft | fd);
10944 TCGv_i64 fp0 = tcg_temp_new_i64();
10945 TCGv_i64 fp1 = tcg_temp_new_i64();
10947 gen_load_fpr64(ctx, fp0, fs);
10948 gen_load_fpr64(ctx, fp1, ft);
10949 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
10950 tcg_temp_free_i64(fp1);
10951 gen_store_fpr64(ctx, fp0, fd);
10952 tcg_temp_free_i64(fp0);
10954 break;
10955 case OPC_MUL_D:
10956 check_cp1_registers(ctx, fs | ft | fd);
10958 TCGv_i64 fp0 = tcg_temp_new_i64();
10959 TCGv_i64 fp1 = tcg_temp_new_i64();
10961 gen_load_fpr64(ctx, fp0, fs);
10962 gen_load_fpr64(ctx, fp1, ft);
10963 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
10964 tcg_temp_free_i64(fp1);
10965 gen_store_fpr64(ctx, fp0, fd);
10966 tcg_temp_free_i64(fp0);
10968 break;
10969 case OPC_DIV_D:
10970 check_cp1_registers(ctx, fs | ft | fd);
10972 TCGv_i64 fp0 = tcg_temp_new_i64();
10973 TCGv_i64 fp1 = tcg_temp_new_i64();
10975 gen_load_fpr64(ctx, fp0, fs);
10976 gen_load_fpr64(ctx, fp1, ft);
10977 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
10978 tcg_temp_free_i64(fp1);
10979 gen_store_fpr64(ctx, fp0, fd);
10980 tcg_temp_free_i64(fp0);
10982 break;
10983 case OPC_SQRT_D:
10984 check_cp1_registers(ctx, fs | fd);
10986 TCGv_i64 fp0 = tcg_temp_new_i64();
10988 gen_load_fpr64(ctx, fp0, fs);
10989 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
10990 gen_store_fpr64(ctx, fp0, fd);
10991 tcg_temp_free_i64(fp0);
10993 break;
10994 case OPC_ABS_D:
10995 check_cp1_registers(ctx, fs | fd);
10997 TCGv_i64 fp0 = tcg_temp_new_i64();
10999 gen_load_fpr64(ctx, fp0, fs);
11000 if (ctx->abs2008) {
11001 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11002 } else {
11003 gen_helper_float_abs_d(fp0, fp0);
11005 gen_store_fpr64(ctx, fp0, fd);
11006 tcg_temp_free_i64(fp0);
11008 break;
11009 case OPC_MOV_D:
11010 check_cp1_registers(ctx, fs | fd);
11012 TCGv_i64 fp0 = tcg_temp_new_i64();
11014 gen_load_fpr64(ctx, fp0, fs);
11015 gen_store_fpr64(ctx, fp0, fd);
11016 tcg_temp_free_i64(fp0);
11018 break;
11019 case OPC_NEG_D:
11020 check_cp1_registers(ctx, fs | fd);
11022 TCGv_i64 fp0 = tcg_temp_new_i64();
11024 gen_load_fpr64(ctx, fp0, fs);
11025 if (ctx->abs2008) {
11026 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11027 } else {
11028 gen_helper_float_chs_d(fp0, fp0);
11030 gen_store_fpr64(ctx, fp0, fd);
11031 tcg_temp_free_i64(fp0);
11033 break;
11034 case OPC_ROUND_L_D:
11035 check_cp1_64bitmode(ctx);
11037 TCGv_i64 fp0 = tcg_temp_new_i64();
11039 gen_load_fpr64(ctx, fp0, fs);
11040 if (ctx->nan2008) {
11041 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11042 } else {
11043 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11045 gen_store_fpr64(ctx, fp0, fd);
11046 tcg_temp_free_i64(fp0);
11048 break;
11049 case OPC_TRUNC_L_D:
11050 check_cp1_64bitmode(ctx);
11052 TCGv_i64 fp0 = tcg_temp_new_i64();
11054 gen_load_fpr64(ctx, fp0, fs);
11055 if (ctx->nan2008) {
11056 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11057 } else {
11058 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11060 gen_store_fpr64(ctx, fp0, fd);
11061 tcg_temp_free_i64(fp0);
11063 break;
11064 case OPC_CEIL_L_D:
11065 check_cp1_64bitmode(ctx);
11067 TCGv_i64 fp0 = tcg_temp_new_i64();
11069 gen_load_fpr64(ctx, fp0, fs);
11070 if (ctx->nan2008) {
11071 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11072 } else {
11073 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11075 gen_store_fpr64(ctx, fp0, fd);
11076 tcg_temp_free_i64(fp0);
11078 break;
11079 case OPC_FLOOR_L_D:
11080 check_cp1_64bitmode(ctx);
11082 TCGv_i64 fp0 = tcg_temp_new_i64();
11084 gen_load_fpr64(ctx, fp0, fs);
11085 if (ctx->nan2008) {
11086 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11087 } else {
11088 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11090 gen_store_fpr64(ctx, fp0, fd);
11091 tcg_temp_free_i64(fp0);
11093 break;
11094 case OPC_ROUND_W_D:
11095 check_cp1_registers(ctx, fs);
11097 TCGv_i32 fp32 = tcg_temp_new_i32();
11098 TCGv_i64 fp64 = tcg_temp_new_i64();
11100 gen_load_fpr64(ctx, fp64, fs);
11101 if (ctx->nan2008) {
11102 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11103 } else {
11104 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11106 tcg_temp_free_i64(fp64);
11107 gen_store_fpr32(ctx, fp32, fd);
11108 tcg_temp_free_i32(fp32);
11110 break;
11111 case OPC_TRUNC_W_D:
11112 check_cp1_registers(ctx, fs);
11114 TCGv_i32 fp32 = tcg_temp_new_i32();
11115 TCGv_i64 fp64 = tcg_temp_new_i64();
11117 gen_load_fpr64(ctx, fp64, fs);
11118 if (ctx->nan2008) {
11119 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11120 } else {
11121 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11123 tcg_temp_free_i64(fp64);
11124 gen_store_fpr32(ctx, fp32, fd);
11125 tcg_temp_free_i32(fp32);
11127 break;
11128 case OPC_CEIL_W_D:
11129 check_cp1_registers(ctx, fs);
11131 TCGv_i32 fp32 = tcg_temp_new_i32();
11132 TCGv_i64 fp64 = tcg_temp_new_i64();
11134 gen_load_fpr64(ctx, fp64, fs);
11135 if (ctx->nan2008) {
11136 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11137 } else {
11138 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11140 tcg_temp_free_i64(fp64);
11141 gen_store_fpr32(ctx, fp32, fd);
11142 tcg_temp_free_i32(fp32);
11144 break;
11145 case OPC_FLOOR_W_D:
11146 check_cp1_registers(ctx, fs);
11148 TCGv_i32 fp32 = tcg_temp_new_i32();
11149 TCGv_i64 fp64 = tcg_temp_new_i64();
11151 gen_load_fpr64(ctx, fp64, fs);
11152 if (ctx->nan2008) {
11153 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11154 } else {
11155 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11157 tcg_temp_free_i64(fp64);
11158 gen_store_fpr32(ctx, fp32, fd);
11159 tcg_temp_free_i32(fp32);
11161 break;
11162 case OPC_SEL_D:
11163 check_insn(ctx, ISA_MIPS_R6);
11164 gen_sel_d(ctx, op1, fd, ft, fs);
11165 break;
11166 case OPC_SELEQZ_D:
11167 check_insn(ctx, ISA_MIPS_R6);
11168 gen_sel_d(ctx, op1, fd, ft, fs);
11169 break;
11170 case OPC_SELNEZ_D:
11171 check_insn(ctx, ISA_MIPS_R6);
11172 gen_sel_d(ctx, op1, fd, ft, fs);
11173 break;
11174 case OPC_MOVCF_D:
11175 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11176 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11177 break;
11178 case OPC_MOVZ_D:
11179 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11181 TCGLabel *l1 = gen_new_label();
11182 TCGv_i64 fp0;
11184 if (ft != 0) {
11185 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11187 fp0 = tcg_temp_new_i64();
11188 gen_load_fpr64(ctx, fp0, fs);
11189 gen_store_fpr64(ctx, fp0, fd);
11190 tcg_temp_free_i64(fp0);
11191 gen_set_label(l1);
11193 break;
11194 case OPC_MOVN_D:
11195 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11197 TCGLabel *l1 = gen_new_label();
11198 TCGv_i64 fp0;
11200 if (ft != 0) {
11201 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11202 fp0 = tcg_temp_new_i64();
11203 gen_load_fpr64(ctx, fp0, fs);
11204 gen_store_fpr64(ctx, fp0, fd);
11205 tcg_temp_free_i64(fp0);
11206 gen_set_label(l1);
11209 break;
11210 case OPC_RECIP_D:
11211 check_cp1_registers(ctx, fs | fd);
11213 TCGv_i64 fp0 = tcg_temp_new_i64();
11215 gen_load_fpr64(ctx, fp0, fs);
11216 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11217 gen_store_fpr64(ctx, fp0, fd);
11218 tcg_temp_free_i64(fp0);
11220 break;
11221 case OPC_RSQRT_D:
11222 check_cp1_registers(ctx, fs | fd);
11224 TCGv_i64 fp0 = tcg_temp_new_i64();
11226 gen_load_fpr64(ctx, fp0, fs);
11227 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11228 gen_store_fpr64(ctx, fp0, fd);
11229 tcg_temp_free_i64(fp0);
11231 break;
11232 case OPC_MADDF_D:
11233 check_insn(ctx, ISA_MIPS_R6);
11235 TCGv_i64 fp0 = tcg_temp_new_i64();
11236 TCGv_i64 fp1 = tcg_temp_new_i64();
11237 TCGv_i64 fp2 = tcg_temp_new_i64();
11238 gen_load_fpr64(ctx, fp0, fs);
11239 gen_load_fpr64(ctx, fp1, ft);
11240 gen_load_fpr64(ctx, fp2, fd);
11241 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11242 gen_store_fpr64(ctx, fp2, fd);
11243 tcg_temp_free_i64(fp2);
11244 tcg_temp_free_i64(fp1);
11245 tcg_temp_free_i64(fp0);
11247 break;
11248 case OPC_MSUBF_D:
11249 check_insn(ctx, ISA_MIPS_R6);
11251 TCGv_i64 fp0 = tcg_temp_new_i64();
11252 TCGv_i64 fp1 = tcg_temp_new_i64();
11253 TCGv_i64 fp2 = tcg_temp_new_i64();
11254 gen_load_fpr64(ctx, fp0, fs);
11255 gen_load_fpr64(ctx, fp1, ft);
11256 gen_load_fpr64(ctx, fp2, fd);
11257 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11258 gen_store_fpr64(ctx, fp2, fd);
11259 tcg_temp_free_i64(fp2);
11260 tcg_temp_free_i64(fp1);
11261 tcg_temp_free_i64(fp0);
11263 break;
11264 case OPC_RINT_D:
11265 check_insn(ctx, ISA_MIPS_R6);
11267 TCGv_i64 fp0 = tcg_temp_new_i64();
11268 gen_load_fpr64(ctx, fp0, fs);
11269 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11270 gen_store_fpr64(ctx, fp0, fd);
11271 tcg_temp_free_i64(fp0);
11273 break;
11274 case OPC_CLASS_D:
11275 check_insn(ctx, ISA_MIPS_R6);
11277 TCGv_i64 fp0 = tcg_temp_new_i64();
11278 gen_load_fpr64(ctx, fp0, fs);
11279 gen_helper_float_class_d(fp0, cpu_env, fp0);
11280 gen_store_fpr64(ctx, fp0, fd);
11281 tcg_temp_free_i64(fp0);
11283 break;
11284 case OPC_MIN_D: /* OPC_RECIP2_D */
11285 if (ctx->insn_flags & ISA_MIPS_R6) {
11286 /* OPC_MIN_D */
11287 TCGv_i64 fp0 = tcg_temp_new_i64();
11288 TCGv_i64 fp1 = tcg_temp_new_i64();
11289 gen_load_fpr64(ctx, fp0, fs);
11290 gen_load_fpr64(ctx, fp1, ft);
11291 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11292 gen_store_fpr64(ctx, fp1, fd);
11293 tcg_temp_free_i64(fp1);
11294 tcg_temp_free_i64(fp0);
11295 } else {
11296 /* OPC_RECIP2_D */
11297 check_cp1_64bitmode(ctx);
11299 TCGv_i64 fp0 = tcg_temp_new_i64();
11300 TCGv_i64 fp1 = tcg_temp_new_i64();
11302 gen_load_fpr64(ctx, fp0, fs);
11303 gen_load_fpr64(ctx, fp1, ft);
11304 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11305 tcg_temp_free_i64(fp1);
11306 gen_store_fpr64(ctx, fp0, fd);
11307 tcg_temp_free_i64(fp0);
11310 break;
11311 case OPC_MINA_D: /* OPC_RECIP1_D */
11312 if (ctx->insn_flags & ISA_MIPS_R6) {
11313 /* OPC_MINA_D */
11314 TCGv_i64 fp0 = tcg_temp_new_i64();
11315 TCGv_i64 fp1 = tcg_temp_new_i64();
11316 gen_load_fpr64(ctx, fp0, fs);
11317 gen_load_fpr64(ctx, fp1, ft);
11318 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11319 gen_store_fpr64(ctx, fp1, fd);
11320 tcg_temp_free_i64(fp1);
11321 tcg_temp_free_i64(fp0);
11322 } else {
11323 /* OPC_RECIP1_D */
11324 check_cp1_64bitmode(ctx);
11326 TCGv_i64 fp0 = tcg_temp_new_i64();
11328 gen_load_fpr64(ctx, fp0, fs);
11329 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11330 gen_store_fpr64(ctx, fp0, fd);
11331 tcg_temp_free_i64(fp0);
11334 break;
11335 case OPC_MAX_D: /* OPC_RSQRT1_D */
11336 if (ctx->insn_flags & ISA_MIPS_R6) {
11337 /* OPC_MAX_D */
11338 TCGv_i64 fp0 = tcg_temp_new_i64();
11339 TCGv_i64 fp1 = tcg_temp_new_i64();
11340 gen_load_fpr64(ctx, fp0, fs);
11341 gen_load_fpr64(ctx, fp1, ft);
11342 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11343 gen_store_fpr64(ctx, fp1, fd);
11344 tcg_temp_free_i64(fp1);
11345 tcg_temp_free_i64(fp0);
11346 } else {
11347 /* OPC_RSQRT1_D */
11348 check_cp1_64bitmode(ctx);
11350 TCGv_i64 fp0 = tcg_temp_new_i64();
11352 gen_load_fpr64(ctx, fp0, fs);
11353 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11354 gen_store_fpr64(ctx, fp0, fd);
11355 tcg_temp_free_i64(fp0);
11358 break;
11359 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11360 if (ctx->insn_flags & ISA_MIPS_R6) {
11361 /* OPC_MAXA_D */
11362 TCGv_i64 fp0 = tcg_temp_new_i64();
11363 TCGv_i64 fp1 = tcg_temp_new_i64();
11364 gen_load_fpr64(ctx, fp0, fs);
11365 gen_load_fpr64(ctx, fp1, ft);
11366 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11367 gen_store_fpr64(ctx, fp1, fd);
11368 tcg_temp_free_i64(fp1);
11369 tcg_temp_free_i64(fp0);
11370 } else {
11371 /* OPC_RSQRT2_D */
11372 check_cp1_64bitmode(ctx);
11374 TCGv_i64 fp0 = tcg_temp_new_i64();
11375 TCGv_i64 fp1 = tcg_temp_new_i64();
11377 gen_load_fpr64(ctx, fp0, fs);
11378 gen_load_fpr64(ctx, fp1, ft);
11379 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11380 tcg_temp_free_i64(fp1);
11381 gen_store_fpr64(ctx, fp0, fd);
11382 tcg_temp_free_i64(fp0);
11385 break;
11386 case OPC_CMP_F_D:
11387 case OPC_CMP_UN_D:
11388 case OPC_CMP_EQ_D:
11389 case OPC_CMP_UEQ_D:
11390 case OPC_CMP_OLT_D:
11391 case OPC_CMP_ULT_D:
11392 case OPC_CMP_OLE_D:
11393 case OPC_CMP_ULE_D:
11394 case OPC_CMP_SF_D:
11395 case OPC_CMP_NGLE_D:
11396 case OPC_CMP_SEQ_D:
11397 case OPC_CMP_NGL_D:
11398 case OPC_CMP_LT_D:
11399 case OPC_CMP_NGE_D:
11400 case OPC_CMP_LE_D:
11401 case OPC_CMP_NGT_D:
11402 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11403 if (ctx->opcode & (1 << 6)) {
11404 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
11405 } else {
11406 gen_cmp_d(ctx, func - 48, ft, fs, cc);
11408 break;
11409 case OPC_CVT_S_D:
11410 check_cp1_registers(ctx, fs);
11412 TCGv_i32 fp32 = tcg_temp_new_i32();
11413 TCGv_i64 fp64 = tcg_temp_new_i64();
11415 gen_load_fpr64(ctx, fp64, fs);
11416 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11417 tcg_temp_free_i64(fp64);
11418 gen_store_fpr32(ctx, fp32, fd);
11419 tcg_temp_free_i32(fp32);
11421 break;
11422 case OPC_CVT_W_D:
11423 check_cp1_registers(ctx, fs);
11425 TCGv_i32 fp32 = tcg_temp_new_i32();
11426 TCGv_i64 fp64 = tcg_temp_new_i64();
11428 gen_load_fpr64(ctx, fp64, fs);
11429 if (ctx->nan2008) {
11430 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11431 } else {
11432 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11434 tcg_temp_free_i64(fp64);
11435 gen_store_fpr32(ctx, fp32, fd);
11436 tcg_temp_free_i32(fp32);
11438 break;
11439 case OPC_CVT_L_D:
11440 check_cp1_64bitmode(ctx);
11442 TCGv_i64 fp0 = tcg_temp_new_i64();
11444 gen_load_fpr64(ctx, fp0, fs);
11445 if (ctx->nan2008) {
11446 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11447 } else {
11448 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11450 gen_store_fpr64(ctx, fp0, fd);
11451 tcg_temp_free_i64(fp0);
11453 break;
11454 case OPC_CVT_S_W:
11456 TCGv_i32 fp0 = tcg_temp_new_i32();
11458 gen_load_fpr32(ctx, fp0, fs);
11459 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11460 gen_store_fpr32(ctx, fp0, fd);
11461 tcg_temp_free_i32(fp0);
11463 break;
11464 case OPC_CVT_D_W:
11465 check_cp1_registers(ctx, fd);
11467 TCGv_i32 fp32 = tcg_temp_new_i32();
11468 TCGv_i64 fp64 = tcg_temp_new_i64();
11470 gen_load_fpr32(ctx, fp32, fs);
11471 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11472 tcg_temp_free_i32(fp32);
11473 gen_store_fpr64(ctx, fp64, fd);
11474 tcg_temp_free_i64(fp64);
11476 break;
11477 case OPC_CVT_S_L:
11478 check_cp1_64bitmode(ctx);
11480 TCGv_i32 fp32 = tcg_temp_new_i32();
11481 TCGv_i64 fp64 = tcg_temp_new_i64();
11483 gen_load_fpr64(ctx, fp64, fs);
11484 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11485 tcg_temp_free_i64(fp64);
11486 gen_store_fpr32(ctx, fp32, fd);
11487 tcg_temp_free_i32(fp32);
11489 break;
11490 case OPC_CVT_D_L:
11491 check_cp1_64bitmode(ctx);
11493 TCGv_i64 fp0 = tcg_temp_new_i64();
11495 gen_load_fpr64(ctx, fp0, fs);
11496 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11497 gen_store_fpr64(ctx, fp0, fd);
11498 tcg_temp_free_i64(fp0);
11500 break;
11501 case OPC_CVT_PS_PW:
11502 check_ps(ctx);
11504 TCGv_i64 fp0 = tcg_temp_new_i64();
11506 gen_load_fpr64(ctx, fp0, fs);
11507 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11508 gen_store_fpr64(ctx, fp0, fd);
11509 tcg_temp_free_i64(fp0);
11511 break;
11512 case OPC_ADD_PS:
11513 check_ps(ctx);
11515 TCGv_i64 fp0 = tcg_temp_new_i64();
11516 TCGv_i64 fp1 = tcg_temp_new_i64();
11518 gen_load_fpr64(ctx, fp0, fs);
11519 gen_load_fpr64(ctx, fp1, ft);
11520 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11521 tcg_temp_free_i64(fp1);
11522 gen_store_fpr64(ctx, fp0, fd);
11523 tcg_temp_free_i64(fp0);
11525 break;
11526 case OPC_SUB_PS:
11527 check_ps(ctx);
11529 TCGv_i64 fp0 = tcg_temp_new_i64();
11530 TCGv_i64 fp1 = tcg_temp_new_i64();
11532 gen_load_fpr64(ctx, fp0, fs);
11533 gen_load_fpr64(ctx, fp1, ft);
11534 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11535 tcg_temp_free_i64(fp1);
11536 gen_store_fpr64(ctx, fp0, fd);
11537 tcg_temp_free_i64(fp0);
11539 break;
11540 case OPC_MUL_PS:
11541 check_ps(ctx);
11543 TCGv_i64 fp0 = tcg_temp_new_i64();
11544 TCGv_i64 fp1 = tcg_temp_new_i64();
11546 gen_load_fpr64(ctx, fp0, fs);
11547 gen_load_fpr64(ctx, fp1, ft);
11548 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11549 tcg_temp_free_i64(fp1);
11550 gen_store_fpr64(ctx, fp0, fd);
11551 tcg_temp_free_i64(fp0);
11553 break;
11554 case OPC_ABS_PS:
11555 check_ps(ctx);
11557 TCGv_i64 fp0 = tcg_temp_new_i64();
11559 gen_load_fpr64(ctx, fp0, fs);
11560 gen_helper_float_abs_ps(fp0, fp0);
11561 gen_store_fpr64(ctx, fp0, fd);
11562 tcg_temp_free_i64(fp0);
11564 break;
11565 case OPC_MOV_PS:
11566 check_ps(ctx);
11568 TCGv_i64 fp0 = tcg_temp_new_i64();
11570 gen_load_fpr64(ctx, fp0, fs);
11571 gen_store_fpr64(ctx, fp0, fd);
11572 tcg_temp_free_i64(fp0);
11574 break;
11575 case OPC_NEG_PS:
11576 check_ps(ctx);
11578 TCGv_i64 fp0 = tcg_temp_new_i64();
11580 gen_load_fpr64(ctx, fp0, fs);
11581 gen_helper_float_chs_ps(fp0, fp0);
11582 gen_store_fpr64(ctx, fp0, fd);
11583 tcg_temp_free_i64(fp0);
11585 break;
11586 case OPC_MOVCF_PS:
11587 check_ps(ctx);
11588 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11589 break;
11590 case OPC_MOVZ_PS:
11591 check_ps(ctx);
11593 TCGLabel *l1 = gen_new_label();
11594 TCGv_i64 fp0;
11596 if (ft != 0) {
11597 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11599 fp0 = tcg_temp_new_i64();
11600 gen_load_fpr64(ctx, fp0, fs);
11601 gen_store_fpr64(ctx, fp0, fd);
11602 tcg_temp_free_i64(fp0);
11603 gen_set_label(l1);
11605 break;
11606 case OPC_MOVN_PS:
11607 check_ps(ctx);
11609 TCGLabel *l1 = gen_new_label();
11610 TCGv_i64 fp0;
11612 if (ft != 0) {
11613 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11614 fp0 = tcg_temp_new_i64();
11615 gen_load_fpr64(ctx, fp0, fs);
11616 gen_store_fpr64(ctx, fp0, fd);
11617 tcg_temp_free_i64(fp0);
11618 gen_set_label(l1);
11621 break;
11622 case OPC_ADDR_PS:
11623 check_ps(ctx);
11625 TCGv_i64 fp0 = tcg_temp_new_i64();
11626 TCGv_i64 fp1 = tcg_temp_new_i64();
11628 gen_load_fpr64(ctx, fp0, ft);
11629 gen_load_fpr64(ctx, fp1, fs);
11630 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11631 tcg_temp_free_i64(fp1);
11632 gen_store_fpr64(ctx, fp0, fd);
11633 tcg_temp_free_i64(fp0);
11635 break;
11636 case OPC_MULR_PS:
11637 check_ps(ctx);
11639 TCGv_i64 fp0 = tcg_temp_new_i64();
11640 TCGv_i64 fp1 = tcg_temp_new_i64();
11642 gen_load_fpr64(ctx, fp0, ft);
11643 gen_load_fpr64(ctx, fp1, fs);
11644 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11645 tcg_temp_free_i64(fp1);
11646 gen_store_fpr64(ctx, fp0, fd);
11647 tcg_temp_free_i64(fp0);
11649 break;
11650 case OPC_RECIP2_PS:
11651 check_ps(ctx);
11653 TCGv_i64 fp0 = tcg_temp_new_i64();
11654 TCGv_i64 fp1 = tcg_temp_new_i64();
11656 gen_load_fpr64(ctx, fp0, fs);
11657 gen_load_fpr64(ctx, fp1, ft);
11658 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11659 tcg_temp_free_i64(fp1);
11660 gen_store_fpr64(ctx, fp0, fd);
11661 tcg_temp_free_i64(fp0);
11663 break;
11664 case OPC_RECIP1_PS:
11665 check_ps(ctx);
11667 TCGv_i64 fp0 = tcg_temp_new_i64();
11669 gen_load_fpr64(ctx, fp0, fs);
11670 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11671 gen_store_fpr64(ctx, fp0, fd);
11672 tcg_temp_free_i64(fp0);
11674 break;
11675 case OPC_RSQRT1_PS:
11676 check_ps(ctx);
11678 TCGv_i64 fp0 = tcg_temp_new_i64();
11680 gen_load_fpr64(ctx, fp0, fs);
11681 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11682 gen_store_fpr64(ctx, fp0, fd);
11683 tcg_temp_free_i64(fp0);
11685 break;
11686 case OPC_RSQRT2_PS:
11687 check_ps(ctx);
11689 TCGv_i64 fp0 = tcg_temp_new_i64();
11690 TCGv_i64 fp1 = tcg_temp_new_i64();
11692 gen_load_fpr64(ctx, fp0, fs);
11693 gen_load_fpr64(ctx, fp1, ft);
11694 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11695 tcg_temp_free_i64(fp1);
11696 gen_store_fpr64(ctx, fp0, fd);
11697 tcg_temp_free_i64(fp0);
11699 break;
11700 case OPC_CVT_S_PU:
11701 check_cp1_64bitmode(ctx);
11703 TCGv_i32 fp0 = tcg_temp_new_i32();
11705 gen_load_fpr32h(ctx, fp0, fs);
11706 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11707 gen_store_fpr32(ctx, fp0, fd);
11708 tcg_temp_free_i32(fp0);
11710 break;
11711 case OPC_CVT_PW_PS:
11712 check_ps(ctx);
11714 TCGv_i64 fp0 = tcg_temp_new_i64();
11716 gen_load_fpr64(ctx, fp0, fs);
11717 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11718 gen_store_fpr64(ctx, fp0, fd);
11719 tcg_temp_free_i64(fp0);
11721 break;
11722 case OPC_CVT_S_PL:
11723 check_cp1_64bitmode(ctx);
11725 TCGv_i32 fp0 = tcg_temp_new_i32();
11727 gen_load_fpr32(ctx, fp0, fs);
11728 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11729 gen_store_fpr32(ctx, fp0, fd);
11730 tcg_temp_free_i32(fp0);
11732 break;
11733 case OPC_PLL_PS:
11734 check_ps(ctx);
11736 TCGv_i32 fp0 = tcg_temp_new_i32();
11737 TCGv_i32 fp1 = tcg_temp_new_i32();
11739 gen_load_fpr32(ctx, fp0, fs);
11740 gen_load_fpr32(ctx, fp1, ft);
11741 gen_store_fpr32h(ctx, fp0, fd);
11742 gen_store_fpr32(ctx, fp1, fd);
11743 tcg_temp_free_i32(fp0);
11744 tcg_temp_free_i32(fp1);
11746 break;
11747 case OPC_PLU_PS:
11748 check_ps(ctx);
11750 TCGv_i32 fp0 = tcg_temp_new_i32();
11751 TCGv_i32 fp1 = tcg_temp_new_i32();
11753 gen_load_fpr32(ctx, fp0, fs);
11754 gen_load_fpr32h(ctx, fp1, ft);
11755 gen_store_fpr32(ctx, fp1, fd);
11756 gen_store_fpr32h(ctx, fp0, fd);
11757 tcg_temp_free_i32(fp0);
11758 tcg_temp_free_i32(fp1);
11760 break;
11761 case OPC_PUL_PS:
11762 check_ps(ctx);
11764 TCGv_i32 fp0 = tcg_temp_new_i32();
11765 TCGv_i32 fp1 = tcg_temp_new_i32();
11767 gen_load_fpr32h(ctx, fp0, fs);
11768 gen_load_fpr32(ctx, fp1, ft);
11769 gen_store_fpr32(ctx, fp1, fd);
11770 gen_store_fpr32h(ctx, fp0, fd);
11771 tcg_temp_free_i32(fp0);
11772 tcg_temp_free_i32(fp1);
11774 break;
11775 case OPC_PUU_PS:
11776 check_ps(ctx);
11778 TCGv_i32 fp0 = tcg_temp_new_i32();
11779 TCGv_i32 fp1 = tcg_temp_new_i32();
11781 gen_load_fpr32h(ctx, fp0, fs);
11782 gen_load_fpr32h(ctx, fp1, ft);
11783 gen_store_fpr32(ctx, fp1, fd);
11784 gen_store_fpr32h(ctx, fp0, fd);
11785 tcg_temp_free_i32(fp0);
11786 tcg_temp_free_i32(fp1);
11788 break;
11789 case OPC_CMP_F_PS:
11790 case OPC_CMP_UN_PS:
11791 case OPC_CMP_EQ_PS:
11792 case OPC_CMP_UEQ_PS:
11793 case OPC_CMP_OLT_PS:
11794 case OPC_CMP_ULT_PS:
11795 case OPC_CMP_OLE_PS:
11796 case OPC_CMP_ULE_PS:
11797 case OPC_CMP_SF_PS:
11798 case OPC_CMP_NGLE_PS:
11799 case OPC_CMP_SEQ_PS:
11800 case OPC_CMP_NGL_PS:
11801 case OPC_CMP_LT_PS:
11802 case OPC_CMP_NGE_PS:
11803 case OPC_CMP_LE_PS:
11804 case OPC_CMP_NGT_PS:
11805 if (ctx->opcode & (1 << 6)) {
11806 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
11807 } else {
11808 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
11810 break;
11811 default:
11812 MIPS_INVAL("farith");
11813 gen_reserved_instruction(ctx);
11814 return;
11818 /* Coprocessor 3 (FPU) */
11819 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
11820 int fd, int fs, int base, int index)
11822 TCGv t0 = tcg_temp_new();
11824 if (base == 0) {
11825 gen_load_gpr(t0, index);
11826 } else if (index == 0) {
11827 gen_load_gpr(t0, base);
11828 } else {
11829 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
11832 * Don't do NOP if destination is zero: we must perform the actual
11833 * memory access.
11835 switch (opc) {
11836 case OPC_LWXC1:
11837 check_cop1x(ctx);
11839 TCGv_i32 fp0 = tcg_temp_new_i32();
11841 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
11842 tcg_gen_trunc_tl_i32(fp0, t0);
11843 gen_store_fpr32(ctx, fp0, fd);
11844 tcg_temp_free_i32(fp0);
11846 break;
11847 case OPC_LDXC1:
11848 check_cop1x(ctx);
11849 check_cp1_registers(ctx, fd);
11851 TCGv_i64 fp0 = tcg_temp_new_i64();
11852 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11853 gen_store_fpr64(ctx, fp0, fd);
11854 tcg_temp_free_i64(fp0);
11856 break;
11857 case OPC_LUXC1:
11858 check_cp1_64bitmode(ctx);
11859 tcg_gen_andi_tl(t0, t0, ~0x7);
11861 TCGv_i64 fp0 = tcg_temp_new_i64();
11863 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11864 gen_store_fpr64(ctx, fp0, fd);
11865 tcg_temp_free_i64(fp0);
11867 break;
11868 case OPC_SWXC1:
11869 check_cop1x(ctx);
11871 TCGv_i32 fp0 = tcg_temp_new_i32();
11872 gen_load_fpr32(ctx, fp0, fs);
11873 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
11874 tcg_temp_free_i32(fp0);
11876 break;
11877 case OPC_SDXC1:
11878 check_cop1x(ctx);
11879 check_cp1_registers(ctx, fs);
11881 TCGv_i64 fp0 = tcg_temp_new_i64();
11882 gen_load_fpr64(ctx, fp0, fs);
11883 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11884 tcg_temp_free_i64(fp0);
11886 break;
11887 case OPC_SUXC1:
11888 check_cp1_64bitmode(ctx);
11889 tcg_gen_andi_tl(t0, t0, ~0x7);
11891 TCGv_i64 fp0 = tcg_temp_new_i64();
11892 gen_load_fpr64(ctx, fp0, fs);
11893 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11894 tcg_temp_free_i64(fp0);
11896 break;
11898 tcg_temp_free(t0);
11901 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
11902 int fd, int fr, int fs, int ft)
11904 switch (opc) {
11905 case OPC_ALNV_PS:
11906 check_ps(ctx);
11908 TCGv t0 = tcg_temp_local_new();
11909 TCGv_i32 fp = tcg_temp_new_i32();
11910 TCGv_i32 fph = tcg_temp_new_i32();
11911 TCGLabel *l1 = gen_new_label();
11912 TCGLabel *l2 = gen_new_label();
11914 gen_load_gpr(t0, fr);
11915 tcg_gen_andi_tl(t0, t0, 0x7);
11917 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
11918 gen_load_fpr32(ctx, fp, fs);
11919 gen_load_fpr32h(ctx, fph, fs);
11920 gen_store_fpr32(ctx, fp, fd);
11921 gen_store_fpr32h(ctx, fph, fd);
11922 tcg_gen_br(l2);
11923 gen_set_label(l1);
11924 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
11925 tcg_temp_free(t0);
11926 #ifdef TARGET_WORDS_BIGENDIAN
11927 gen_load_fpr32(ctx, fp, fs);
11928 gen_load_fpr32h(ctx, fph, ft);
11929 gen_store_fpr32h(ctx, fp, fd);
11930 gen_store_fpr32(ctx, fph, fd);
11931 #else
11932 gen_load_fpr32h(ctx, fph, fs);
11933 gen_load_fpr32(ctx, fp, ft);
11934 gen_store_fpr32(ctx, fph, fd);
11935 gen_store_fpr32h(ctx, fp, fd);
11936 #endif
11937 gen_set_label(l2);
11938 tcg_temp_free_i32(fp);
11939 tcg_temp_free_i32(fph);
11941 break;
11942 case OPC_MADD_S:
11943 check_cop1x(ctx);
11945 TCGv_i32 fp0 = tcg_temp_new_i32();
11946 TCGv_i32 fp1 = tcg_temp_new_i32();
11947 TCGv_i32 fp2 = tcg_temp_new_i32();
11949 gen_load_fpr32(ctx, fp0, fs);
11950 gen_load_fpr32(ctx, fp1, ft);
11951 gen_load_fpr32(ctx, fp2, fr);
11952 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
11953 tcg_temp_free_i32(fp0);
11954 tcg_temp_free_i32(fp1);
11955 gen_store_fpr32(ctx, fp2, fd);
11956 tcg_temp_free_i32(fp2);
11958 break;
11959 case OPC_MADD_D:
11960 check_cop1x(ctx);
11961 check_cp1_registers(ctx, fd | fs | ft | fr);
11963 TCGv_i64 fp0 = tcg_temp_new_i64();
11964 TCGv_i64 fp1 = tcg_temp_new_i64();
11965 TCGv_i64 fp2 = tcg_temp_new_i64();
11967 gen_load_fpr64(ctx, fp0, fs);
11968 gen_load_fpr64(ctx, fp1, ft);
11969 gen_load_fpr64(ctx, fp2, fr);
11970 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
11971 tcg_temp_free_i64(fp0);
11972 tcg_temp_free_i64(fp1);
11973 gen_store_fpr64(ctx, fp2, fd);
11974 tcg_temp_free_i64(fp2);
11976 break;
11977 case OPC_MADD_PS:
11978 check_ps(ctx);
11980 TCGv_i64 fp0 = tcg_temp_new_i64();
11981 TCGv_i64 fp1 = tcg_temp_new_i64();
11982 TCGv_i64 fp2 = tcg_temp_new_i64();
11984 gen_load_fpr64(ctx, fp0, fs);
11985 gen_load_fpr64(ctx, fp1, ft);
11986 gen_load_fpr64(ctx, fp2, fr);
11987 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
11988 tcg_temp_free_i64(fp0);
11989 tcg_temp_free_i64(fp1);
11990 gen_store_fpr64(ctx, fp2, fd);
11991 tcg_temp_free_i64(fp2);
11993 break;
11994 case OPC_MSUB_S:
11995 check_cop1x(ctx);
11997 TCGv_i32 fp0 = tcg_temp_new_i32();
11998 TCGv_i32 fp1 = tcg_temp_new_i32();
11999 TCGv_i32 fp2 = tcg_temp_new_i32();
12001 gen_load_fpr32(ctx, fp0, fs);
12002 gen_load_fpr32(ctx, fp1, ft);
12003 gen_load_fpr32(ctx, fp2, fr);
12004 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12005 tcg_temp_free_i32(fp0);
12006 tcg_temp_free_i32(fp1);
12007 gen_store_fpr32(ctx, fp2, fd);
12008 tcg_temp_free_i32(fp2);
12010 break;
12011 case OPC_MSUB_D:
12012 check_cop1x(ctx);
12013 check_cp1_registers(ctx, fd | fs | ft | fr);
12015 TCGv_i64 fp0 = tcg_temp_new_i64();
12016 TCGv_i64 fp1 = tcg_temp_new_i64();
12017 TCGv_i64 fp2 = tcg_temp_new_i64();
12019 gen_load_fpr64(ctx, fp0, fs);
12020 gen_load_fpr64(ctx, fp1, ft);
12021 gen_load_fpr64(ctx, fp2, fr);
12022 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12023 tcg_temp_free_i64(fp0);
12024 tcg_temp_free_i64(fp1);
12025 gen_store_fpr64(ctx, fp2, fd);
12026 tcg_temp_free_i64(fp2);
12028 break;
12029 case OPC_MSUB_PS:
12030 check_ps(ctx);
12032 TCGv_i64 fp0 = tcg_temp_new_i64();
12033 TCGv_i64 fp1 = tcg_temp_new_i64();
12034 TCGv_i64 fp2 = tcg_temp_new_i64();
12036 gen_load_fpr64(ctx, fp0, fs);
12037 gen_load_fpr64(ctx, fp1, ft);
12038 gen_load_fpr64(ctx, fp2, fr);
12039 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12040 tcg_temp_free_i64(fp0);
12041 tcg_temp_free_i64(fp1);
12042 gen_store_fpr64(ctx, fp2, fd);
12043 tcg_temp_free_i64(fp2);
12045 break;
12046 case OPC_NMADD_S:
12047 check_cop1x(ctx);
12049 TCGv_i32 fp0 = tcg_temp_new_i32();
12050 TCGv_i32 fp1 = tcg_temp_new_i32();
12051 TCGv_i32 fp2 = tcg_temp_new_i32();
12053 gen_load_fpr32(ctx, fp0, fs);
12054 gen_load_fpr32(ctx, fp1, ft);
12055 gen_load_fpr32(ctx, fp2, fr);
12056 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12057 tcg_temp_free_i32(fp0);
12058 tcg_temp_free_i32(fp1);
12059 gen_store_fpr32(ctx, fp2, fd);
12060 tcg_temp_free_i32(fp2);
12062 break;
12063 case OPC_NMADD_D:
12064 check_cop1x(ctx);
12065 check_cp1_registers(ctx, fd | fs | ft | fr);
12067 TCGv_i64 fp0 = tcg_temp_new_i64();
12068 TCGv_i64 fp1 = tcg_temp_new_i64();
12069 TCGv_i64 fp2 = tcg_temp_new_i64();
12071 gen_load_fpr64(ctx, fp0, fs);
12072 gen_load_fpr64(ctx, fp1, ft);
12073 gen_load_fpr64(ctx, fp2, fr);
12074 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12075 tcg_temp_free_i64(fp0);
12076 tcg_temp_free_i64(fp1);
12077 gen_store_fpr64(ctx, fp2, fd);
12078 tcg_temp_free_i64(fp2);
12080 break;
12081 case OPC_NMADD_PS:
12082 check_ps(ctx);
12084 TCGv_i64 fp0 = tcg_temp_new_i64();
12085 TCGv_i64 fp1 = tcg_temp_new_i64();
12086 TCGv_i64 fp2 = tcg_temp_new_i64();
12088 gen_load_fpr64(ctx, fp0, fs);
12089 gen_load_fpr64(ctx, fp1, ft);
12090 gen_load_fpr64(ctx, fp2, fr);
12091 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12092 tcg_temp_free_i64(fp0);
12093 tcg_temp_free_i64(fp1);
12094 gen_store_fpr64(ctx, fp2, fd);
12095 tcg_temp_free_i64(fp2);
12097 break;
12098 case OPC_NMSUB_S:
12099 check_cop1x(ctx);
12101 TCGv_i32 fp0 = tcg_temp_new_i32();
12102 TCGv_i32 fp1 = tcg_temp_new_i32();
12103 TCGv_i32 fp2 = tcg_temp_new_i32();
12105 gen_load_fpr32(ctx, fp0, fs);
12106 gen_load_fpr32(ctx, fp1, ft);
12107 gen_load_fpr32(ctx, fp2, fr);
12108 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12109 tcg_temp_free_i32(fp0);
12110 tcg_temp_free_i32(fp1);
12111 gen_store_fpr32(ctx, fp2, fd);
12112 tcg_temp_free_i32(fp2);
12114 break;
12115 case OPC_NMSUB_D:
12116 check_cop1x(ctx);
12117 check_cp1_registers(ctx, fd | fs | ft | fr);
12119 TCGv_i64 fp0 = tcg_temp_new_i64();
12120 TCGv_i64 fp1 = tcg_temp_new_i64();
12121 TCGv_i64 fp2 = tcg_temp_new_i64();
12123 gen_load_fpr64(ctx, fp0, fs);
12124 gen_load_fpr64(ctx, fp1, ft);
12125 gen_load_fpr64(ctx, fp2, fr);
12126 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12127 tcg_temp_free_i64(fp0);
12128 tcg_temp_free_i64(fp1);
12129 gen_store_fpr64(ctx, fp2, fd);
12130 tcg_temp_free_i64(fp2);
12132 break;
12133 case OPC_NMSUB_PS:
12134 check_ps(ctx);
12136 TCGv_i64 fp0 = tcg_temp_new_i64();
12137 TCGv_i64 fp1 = tcg_temp_new_i64();
12138 TCGv_i64 fp2 = tcg_temp_new_i64();
12140 gen_load_fpr64(ctx, fp0, fs);
12141 gen_load_fpr64(ctx, fp1, ft);
12142 gen_load_fpr64(ctx, fp2, fr);
12143 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12144 tcg_temp_free_i64(fp0);
12145 tcg_temp_free_i64(fp1);
12146 gen_store_fpr64(ctx, fp2, fd);
12147 tcg_temp_free_i64(fp2);
12149 break;
12150 default:
12151 MIPS_INVAL("flt3_arith");
12152 gen_reserved_instruction(ctx);
12153 return;
12157 void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12159 TCGv t0;
12161 #if !defined(CONFIG_USER_ONLY)
12163 * The Linux kernel will emulate rdhwr if it's not supported natively.
12164 * Therefore only check the ISA in system mode.
12166 check_insn(ctx, ISA_MIPS_R2);
12167 #endif
12168 t0 = tcg_temp_new();
12170 switch (rd) {
12171 case 0:
12172 gen_helper_rdhwr_cpunum(t0, cpu_env);
12173 gen_store_gpr(t0, rt);
12174 break;
12175 case 1:
12176 gen_helper_rdhwr_synci_step(t0, cpu_env);
12177 gen_store_gpr(t0, rt);
12178 break;
12179 case 2:
12180 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12181 gen_io_start();
12183 gen_helper_rdhwr_cc(t0, cpu_env);
12184 gen_store_gpr(t0, rt);
12186 * Break the TB to be able to take timer interrupts immediately
12187 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12188 * we break completely out of translated code.
12190 gen_save_pc(ctx->base.pc_next + 4);
12191 ctx->base.is_jmp = DISAS_EXIT;
12192 break;
12193 case 3:
12194 gen_helper_rdhwr_ccres(t0, cpu_env);
12195 gen_store_gpr(t0, rt);
12196 break;
12197 case 4:
12198 check_insn(ctx, ISA_MIPS_R6);
12199 if (sel != 0) {
12201 * Performance counter registers are not implemented other than
12202 * control register 0.
12204 generate_exception(ctx, EXCP_RI);
12206 gen_helper_rdhwr_performance(t0, cpu_env);
12207 gen_store_gpr(t0, rt);
12208 break;
12209 case 5:
12210 check_insn(ctx, ISA_MIPS_R6);
12211 gen_helper_rdhwr_xnp(t0, cpu_env);
12212 gen_store_gpr(t0, rt);
12213 break;
12214 case 29:
12215 #if defined(CONFIG_USER_ONLY)
12216 tcg_gen_ld_tl(t0, cpu_env,
12217 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12218 gen_store_gpr(t0, rt);
12219 break;
12220 #else
12221 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12222 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12223 tcg_gen_ld_tl(t0, cpu_env,
12224 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12225 gen_store_gpr(t0, rt);
12226 } else {
12227 gen_reserved_instruction(ctx);
12229 break;
12230 #endif
12231 default: /* Invalid */
12232 MIPS_INVAL("rdhwr");
12233 gen_reserved_instruction(ctx);
12234 break;
12236 tcg_temp_free(t0);
12239 static inline void clear_branch_hflags(DisasContext *ctx)
12241 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12242 if (ctx->base.is_jmp == DISAS_NEXT) {
12243 save_cpu_state(ctx, 0);
12244 } else {
12246 * It is not safe to save ctx->hflags as hflags may be changed
12247 * in execution time by the instruction in delay / forbidden slot.
12249 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12253 static void gen_branch(DisasContext *ctx, int insn_bytes)
12255 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12256 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12257 /* Branches completion */
12258 clear_branch_hflags(ctx);
12259 ctx->base.is_jmp = DISAS_NORETURN;
12260 /* FIXME: Need to clear can_do_io. */
12261 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12262 case MIPS_HFLAG_FBNSLOT:
12263 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12264 break;
12265 case MIPS_HFLAG_B:
12266 /* unconditional branch */
12267 if (proc_hflags & MIPS_HFLAG_BX) {
12268 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12270 gen_goto_tb(ctx, 0, ctx->btarget);
12271 break;
12272 case MIPS_HFLAG_BL:
12273 /* blikely taken case */
12274 gen_goto_tb(ctx, 0, ctx->btarget);
12275 break;
12276 case MIPS_HFLAG_BC:
12277 /* Conditional branch */
12279 TCGLabel *l1 = gen_new_label();
12281 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12282 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12283 gen_set_label(l1);
12284 gen_goto_tb(ctx, 0, ctx->btarget);
12286 break;
12287 case MIPS_HFLAG_BR:
12288 /* unconditional branch to register */
12289 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12290 TCGv t0 = tcg_temp_new();
12291 TCGv_i32 t1 = tcg_temp_new_i32();
12293 tcg_gen_andi_tl(t0, btarget, 0x1);
12294 tcg_gen_trunc_tl_i32(t1, t0);
12295 tcg_temp_free(t0);
12296 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12297 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12298 tcg_gen_or_i32(hflags, hflags, t1);
12299 tcg_temp_free_i32(t1);
12301 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12302 } else {
12303 tcg_gen_mov_tl(cpu_PC, btarget);
12305 if (ctx->base.singlestep_enabled) {
12306 save_cpu_state(ctx, 0);
12307 gen_helper_raise_exception_debug(cpu_env);
12309 tcg_gen_lookup_and_goto_ptr();
12310 break;
12311 default:
12312 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12313 abort();
12318 /* Compact Branches */
12319 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12320 int rs, int rt, int32_t offset)
12322 int bcond_compute = 0;
12323 TCGv t0 = tcg_temp_new();
12324 TCGv t1 = tcg_temp_new();
12325 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12327 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12328 #ifdef MIPS_DEBUG_DISAS
12329 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12330 "\n", ctx->base.pc_next);
12331 #endif
12332 gen_reserved_instruction(ctx);
12333 goto out;
12336 /* Load needed operands and calculate btarget */
12337 switch (opc) {
12338 /* compact branch */
12339 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12340 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12341 gen_load_gpr(t0, rs);
12342 gen_load_gpr(t1, rt);
12343 bcond_compute = 1;
12344 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12345 if (rs <= rt && rs == 0) {
12346 /* OPC_BEQZALC, OPC_BNEZALC */
12347 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12349 break;
12350 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12351 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12352 gen_load_gpr(t0, rs);
12353 gen_load_gpr(t1, rt);
12354 bcond_compute = 1;
12355 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12356 break;
12357 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12358 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12359 if (rs == 0 || rs == rt) {
12360 /* OPC_BLEZALC, OPC_BGEZALC */
12361 /* OPC_BGTZALC, OPC_BLTZALC */
12362 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12364 gen_load_gpr(t0, rs);
12365 gen_load_gpr(t1, rt);
12366 bcond_compute = 1;
12367 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12368 break;
12369 case OPC_BC:
12370 case OPC_BALC:
12371 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12372 break;
12373 case OPC_BEQZC:
12374 case OPC_BNEZC:
12375 if (rs != 0) {
12376 /* OPC_BEQZC, OPC_BNEZC */
12377 gen_load_gpr(t0, rs);
12378 bcond_compute = 1;
12379 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12380 } else {
12381 /* OPC_JIC, OPC_JIALC */
12382 TCGv tbase = tcg_temp_new();
12383 TCGv toffset = tcg_temp_new();
12385 gen_load_gpr(tbase, rt);
12386 tcg_gen_movi_tl(toffset, offset);
12387 gen_op_addr_add(ctx, btarget, tbase, toffset);
12388 tcg_temp_free(tbase);
12389 tcg_temp_free(toffset);
12391 break;
12392 default:
12393 MIPS_INVAL("Compact branch/jump");
12394 gen_reserved_instruction(ctx);
12395 goto out;
12398 if (bcond_compute == 0) {
12399 /* Uncoditional compact branch */
12400 switch (opc) {
12401 case OPC_JIALC:
12402 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12403 /* Fallthrough */
12404 case OPC_JIC:
12405 ctx->hflags |= MIPS_HFLAG_BR;
12406 break;
12407 case OPC_BALC:
12408 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12409 /* Fallthrough */
12410 case OPC_BC:
12411 ctx->hflags |= MIPS_HFLAG_B;
12412 break;
12413 default:
12414 MIPS_INVAL("Compact branch/jump");
12415 gen_reserved_instruction(ctx);
12416 goto out;
12419 /* Generating branch here as compact branches don't have delay slot */
12420 gen_branch(ctx, 4);
12421 } else {
12422 /* Conditional compact branch */
12423 TCGLabel *fs = gen_new_label();
12424 save_cpu_state(ctx, 0);
12426 switch (opc) {
12427 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12428 if (rs == 0 && rt != 0) {
12429 /* OPC_BLEZALC */
12430 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12431 } else if (rs != 0 && rt != 0 && rs == rt) {
12432 /* OPC_BGEZALC */
12433 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12434 } else {
12435 /* OPC_BGEUC */
12436 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12438 break;
12439 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12440 if (rs == 0 && rt != 0) {
12441 /* OPC_BGTZALC */
12442 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12443 } else if (rs != 0 && rt != 0 && rs == rt) {
12444 /* OPC_BLTZALC */
12445 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12446 } else {
12447 /* OPC_BLTUC */
12448 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12450 break;
12451 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12452 if (rs == 0 && rt != 0) {
12453 /* OPC_BLEZC */
12454 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12455 } else if (rs != 0 && rt != 0 && rs == rt) {
12456 /* OPC_BGEZC */
12457 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12458 } else {
12459 /* OPC_BGEC */
12460 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12462 break;
12463 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12464 if (rs == 0 && rt != 0) {
12465 /* OPC_BGTZC */
12466 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12467 } else if (rs != 0 && rt != 0 && rs == rt) {
12468 /* OPC_BLTZC */
12469 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12470 } else {
12471 /* OPC_BLTC */
12472 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12474 break;
12475 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12476 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12477 if (rs >= rt) {
12478 /* OPC_BOVC, OPC_BNVC */
12479 TCGv t2 = tcg_temp_new();
12480 TCGv t3 = tcg_temp_new();
12481 TCGv t4 = tcg_temp_new();
12482 TCGv input_overflow = tcg_temp_new();
12484 gen_load_gpr(t0, rs);
12485 gen_load_gpr(t1, rt);
12486 tcg_gen_ext32s_tl(t2, t0);
12487 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12488 tcg_gen_ext32s_tl(t3, t1);
12489 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12490 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12492 tcg_gen_add_tl(t4, t2, t3);
12493 tcg_gen_ext32s_tl(t4, t4);
12494 tcg_gen_xor_tl(t2, t2, t3);
12495 tcg_gen_xor_tl(t3, t4, t3);
12496 tcg_gen_andc_tl(t2, t3, t2);
12497 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12498 tcg_gen_or_tl(t4, t4, input_overflow);
12499 if (opc == OPC_BOVC) {
12500 /* OPC_BOVC */
12501 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12502 } else {
12503 /* OPC_BNVC */
12504 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12506 tcg_temp_free(input_overflow);
12507 tcg_temp_free(t4);
12508 tcg_temp_free(t3);
12509 tcg_temp_free(t2);
12510 } else if (rs < rt && rs == 0) {
12511 /* OPC_BEQZALC, OPC_BNEZALC */
12512 if (opc == OPC_BEQZALC) {
12513 /* OPC_BEQZALC */
12514 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12515 } else {
12516 /* OPC_BNEZALC */
12517 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12519 } else {
12520 /* OPC_BEQC, OPC_BNEC */
12521 if (opc == OPC_BEQC) {
12522 /* OPC_BEQC */
12523 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12524 } else {
12525 /* OPC_BNEC */
12526 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12529 break;
12530 case OPC_BEQZC:
12531 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12532 break;
12533 case OPC_BNEZC:
12534 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12535 break;
12536 default:
12537 MIPS_INVAL("Compact conditional branch/jump");
12538 gen_reserved_instruction(ctx);
12539 goto out;
12542 /* Generating branch here as compact branches don't have delay slot */
12543 gen_goto_tb(ctx, 1, ctx->btarget);
12544 gen_set_label(fs);
12546 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12549 out:
12550 tcg_temp_free(t0);
12551 tcg_temp_free(t1);
12554 /* ISA extensions (ASEs) */
12555 /* MIPS16 extension to MIPS32 */
12557 /* MIPS16 major opcodes */
12558 enum {
12559 M16_OPC_ADDIUSP = 0x00,
12560 M16_OPC_ADDIUPC = 0x01,
12561 M16_OPC_B = 0x02,
12562 M16_OPC_JAL = 0x03,
12563 M16_OPC_BEQZ = 0x04,
12564 M16_OPC_BNEQZ = 0x05,
12565 M16_OPC_SHIFT = 0x06,
12566 M16_OPC_LD = 0x07,
12567 M16_OPC_RRIA = 0x08,
12568 M16_OPC_ADDIU8 = 0x09,
12569 M16_OPC_SLTI = 0x0a,
12570 M16_OPC_SLTIU = 0x0b,
12571 M16_OPC_I8 = 0x0c,
12572 M16_OPC_LI = 0x0d,
12573 M16_OPC_CMPI = 0x0e,
12574 M16_OPC_SD = 0x0f,
12575 M16_OPC_LB = 0x10,
12576 M16_OPC_LH = 0x11,
12577 M16_OPC_LWSP = 0x12,
12578 M16_OPC_LW = 0x13,
12579 M16_OPC_LBU = 0x14,
12580 M16_OPC_LHU = 0x15,
12581 M16_OPC_LWPC = 0x16,
12582 M16_OPC_LWU = 0x17,
12583 M16_OPC_SB = 0x18,
12584 M16_OPC_SH = 0x19,
12585 M16_OPC_SWSP = 0x1a,
12586 M16_OPC_SW = 0x1b,
12587 M16_OPC_RRR = 0x1c,
12588 M16_OPC_RR = 0x1d,
12589 M16_OPC_EXTEND = 0x1e,
12590 M16_OPC_I64 = 0x1f
12593 /* I8 funct field */
12594 enum {
12595 I8_BTEQZ = 0x0,
12596 I8_BTNEZ = 0x1,
12597 I8_SWRASP = 0x2,
12598 I8_ADJSP = 0x3,
12599 I8_SVRS = 0x4,
12600 I8_MOV32R = 0x5,
12601 I8_MOVR32 = 0x7
12604 /* RRR f field */
12605 enum {
12606 RRR_DADDU = 0x0,
12607 RRR_ADDU = 0x1,
12608 RRR_DSUBU = 0x2,
12609 RRR_SUBU = 0x3
12612 /* RR funct field */
12613 enum {
12614 RR_JR = 0x00,
12615 RR_SDBBP = 0x01,
12616 RR_SLT = 0x02,
12617 RR_SLTU = 0x03,
12618 RR_SLLV = 0x04,
12619 RR_BREAK = 0x05,
12620 RR_SRLV = 0x06,
12621 RR_SRAV = 0x07,
12622 RR_DSRL = 0x08,
12623 RR_CMP = 0x0a,
12624 RR_NEG = 0x0b,
12625 RR_AND = 0x0c,
12626 RR_OR = 0x0d,
12627 RR_XOR = 0x0e,
12628 RR_NOT = 0x0f,
12629 RR_MFHI = 0x10,
12630 RR_CNVT = 0x11,
12631 RR_MFLO = 0x12,
12632 RR_DSRA = 0x13,
12633 RR_DSLLV = 0x14,
12634 RR_DSRLV = 0x16,
12635 RR_DSRAV = 0x17,
12636 RR_MULT = 0x18,
12637 RR_MULTU = 0x19,
12638 RR_DIV = 0x1a,
12639 RR_DIVU = 0x1b,
12640 RR_DMULT = 0x1c,
12641 RR_DMULTU = 0x1d,
12642 RR_DDIV = 0x1e,
12643 RR_DDIVU = 0x1f
12646 /* I64 funct field */
12647 enum {
12648 I64_LDSP = 0x0,
12649 I64_SDSP = 0x1,
12650 I64_SDRASP = 0x2,
12651 I64_DADJSP = 0x3,
12652 I64_LDPC = 0x4,
12653 I64_DADDIU5 = 0x5,
12654 I64_DADDIUPC = 0x6,
12655 I64_DADDIUSP = 0x7
12658 /* RR ry field for CNVT */
12659 enum {
12660 RR_RY_CNVT_ZEB = 0x0,
12661 RR_RY_CNVT_ZEH = 0x1,
12662 RR_RY_CNVT_ZEW = 0x2,
12663 RR_RY_CNVT_SEB = 0x4,
12664 RR_RY_CNVT_SEH = 0x5,
12665 RR_RY_CNVT_SEW = 0x6,
12668 static int xlat(int r)
12670 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12672 return map[r];
12675 static void gen_mips16_save(DisasContext *ctx,
12676 int xsregs, int aregs,
12677 int do_ra, int do_s0, int do_s1,
12678 int framesize)
12680 TCGv t0 = tcg_temp_new();
12681 TCGv t1 = tcg_temp_new();
12682 TCGv t2 = tcg_temp_new();
12683 int args, astatic;
12685 switch (aregs) {
12686 case 0:
12687 case 1:
12688 case 2:
12689 case 3:
12690 case 11:
12691 args = 0;
12692 break;
12693 case 4:
12694 case 5:
12695 case 6:
12696 case 7:
12697 args = 1;
12698 break;
12699 case 8:
12700 case 9:
12701 case 10:
12702 args = 2;
12703 break;
12704 case 12:
12705 case 13:
12706 args = 3;
12707 break;
12708 case 14:
12709 args = 4;
12710 break;
12711 default:
12712 gen_reserved_instruction(ctx);
12713 return;
12716 switch (args) {
12717 case 4:
12718 gen_base_offset_addr(ctx, t0, 29, 12);
12719 gen_load_gpr(t1, 7);
12720 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12721 /* Fall through */
12722 case 3:
12723 gen_base_offset_addr(ctx, t0, 29, 8);
12724 gen_load_gpr(t1, 6);
12725 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12726 /* Fall through */
12727 case 2:
12728 gen_base_offset_addr(ctx, t0, 29, 4);
12729 gen_load_gpr(t1, 5);
12730 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12731 /* Fall through */
12732 case 1:
12733 gen_base_offset_addr(ctx, t0, 29, 0);
12734 gen_load_gpr(t1, 4);
12735 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12738 gen_load_gpr(t0, 29);
12740 #define DECR_AND_STORE(reg) do { \
12741 tcg_gen_movi_tl(t2, -4); \
12742 gen_op_addr_add(ctx, t0, t0, t2); \
12743 gen_load_gpr(t1, reg); \
12744 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12745 } while (0)
12747 if (do_ra) {
12748 DECR_AND_STORE(31);
12751 switch (xsregs) {
12752 case 7:
12753 DECR_AND_STORE(30);
12754 /* Fall through */
12755 case 6:
12756 DECR_AND_STORE(23);
12757 /* Fall through */
12758 case 5:
12759 DECR_AND_STORE(22);
12760 /* Fall through */
12761 case 4:
12762 DECR_AND_STORE(21);
12763 /* Fall through */
12764 case 3:
12765 DECR_AND_STORE(20);
12766 /* Fall through */
12767 case 2:
12768 DECR_AND_STORE(19);
12769 /* Fall through */
12770 case 1:
12771 DECR_AND_STORE(18);
12774 if (do_s1) {
12775 DECR_AND_STORE(17);
12777 if (do_s0) {
12778 DECR_AND_STORE(16);
12781 switch (aregs) {
12782 case 0:
12783 case 4:
12784 case 8:
12785 case 12:
12786 case 14:
12787 astatic = 0;
12788 break;
12789 case 1:
12790 case 5:
12791 case 9:
12792 case 13:
12793 astatic = 1;
12794 break;
12795 case 2:
12796 case 6:
12797 case 10:
12798 astatic = 2;
12799 break;
12800 case 3:
12801 case 7:
12802 astatic = 3;
12803 break;
12804 case 11:
12805 astatic = 4;
12806 break;
12807 default:
12808 gen_reserved_instruction(ctx);
12809 return;
12812 if (astatic > 0) {
12813 DECR_AND_STORE(7);
12814 if (astatic > 1) {
12815 DECR_AND_STORE(6);
12816 if (astatic > 2) {
12817 DECR_AND_STORE(5);
12818 if (astatic > 3) {
12819 DECR_AND_STORE(4);
12824 #undef DECR_AND_STORE
12826 tcg_gen_movi_tl(t2, -framesize);
12827 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12828 tcg_temp_free(t0);
12829 tcg_temp_free(t1);
12830 tcg_temp_free(t2);
12833 static void gen_mips16_restore(DisasContext *ctx,
12834 int xsregs, int aregs,
12835 int do_ra, int do_s0, int do_s1,
12836 int framesize)
12838 int astatic;
12839 TCGv t0 = tcg_temp_new();
12840 TCGv t1 = tcg_temp_new();
12841 TCGv t2 = tcg_temp_new();
12843 tcg_gen_movi_tl(t2, framesize);
12844 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
12846 #define DECR_AND_LOAD(reg) do { \
12847 tcg_gen_movi_tl(t2, -4); \
12848 gen_op_addr_add(ctx, t0, t0, t2); \
12849 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
12850 gen_store_gpr(t1, reg); \
12851 } while (0)
12853 if (do_ra) {
12854 DECR_AND_LOAD(31);
12857 switch (xsregs) {
12858 case 7:
12859 DECR_AND_LOAD(30);
12860 /* Fall through */
12861 case 6:
12862 DECR_AND_LOAD(23);
12863 /* Fall through */
12864 case 5:
12865 DECR_AND_LOAD(22);
12866 /* Fall through */
12867 case 4:
12868 DECR_AND_LOAD(21);
12869 /* Fall through */
12870 case 3:
12871 DECR_AND_LOAD(20);
12872 /* Fall through */
12873 case 2:
12874 DECR_AND_LOAD(19);
12875 /* Fall through */
12876 case 1:
12877 DECR_AND_LOAD(18);
12880 if (do_s1) {
12881 DECR_AND_LOAD(17);
12883 if (do_s0) {
12884 DECR_AND_LOAD(16);
12887 switch (aregs) {
12888 case 0:
12889 case 4:
12890 case 8:
12891 case 12:
12892 case 14:
12893 astatic = 0;
12894 break;
12895 case 1:
12896 case 5:
12897 case 9:
12898 case 13:
12899 astatic = 1;
12900 break;
12901 case 2:
12902 case 6:
12903 case 10:
12904 astatic = 2;
12905 break;
12906 case 3:
12907 case 7:
12908 astatic = 3;
12909 break;
12910 case 11:
12911 astatic = 4;
12912 break;
12913 default:
12914 gen_reserved_instruction(ctx);
12915 return;
12918 if (astatic > 0) {
12919 DECR_AND_LOAD(7);
12920 if (astatic > 1) {
12921 DECR_AND_LOAD(6);
12922 if (astatic > 2) {
12923 DECR_AND_LOAD(5);
12924 if (astatic > 3) {
12925 DECR_AND_LOAD(4);
12930 #undef DECR_AND_LOAD
12932 tcg_gen_movi_tl(t2, framesize);
12933 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12934 tcg_temp_free(t0);
12935 tcg_temp_free(t1);
12936 tcg_temp_free(t2);
12939 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
12940 int is_64_bit, int extended)
12942 TCGv t0;
12944 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12945 gen_reserved_instruction(ctx);
12946 return;
12949 t0 = tcg_temp_new();
12951 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
12952 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
12953 if (!is_64_bit) {
12954 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12957 tcg_temp_free(t0);
12960 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
12961 int16_t offset)
12963 TCGv_i32 t0 = tcg_const_i32(op);
12964 TCGv t1 = tcg_temp_new();
12965 gen_base_offset_addr(ctx, t1, base, offset);
12966 gen_helper_cache(cpu_env, t1, t0);
12969 #if defined(TARGET_MIPS64)
12970 static void decode_i64_mips16(DisasContext *ctx,
12971 int ry, int funct, int16_t offset,
12972 int extended)
12974 switch (funct) {
12975 case I64_LDSP:
12976 check_insn(ctx, ISA_MIPS3);
12977 check_mips_64(ctx);
12978 offset = extended ? offset : offset << 3;
12979 gen_ld(ctx, OPC_LD, ry, 29, offset);
12980 break;
12981 case I64_SDSP:
12982 check_insn(ctx, ISA_MIPS3);
12983 check_mips_64(ctx);
12984 offset = extended ? offset : offset << 3;
12985 gen_st(ctx, OPC_SD, ry, 29, offset);
12986 break;
12987 case I64_SDRASP:
12988 check_insn(ctx, ISA_MIPS3);
12989 check_mips_64(ctx);
12990 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
12991 gen_st(ctx, OPC_SD, 31, 29, offset);
12992 break;
12993 case I64_DADJSP:
12994 check_insn(ctx, ISA_MIPS3);
12995 check_mips_64(ctx);
12996 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
12997 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
12998 break;
12999 case I64_LDPC:
13000 check_insn(ctx, ISA_MIPS3);
13001 check_mips_64(ctx);
13002 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13003 gen_reserved_instruction(ctx);
13004 } else {
13005 offset = extended ? offset : offset << 3;
13006 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13008 break;
13009 case I64_DADDIU5:
13010 check_insn(ctx, ISA_MIPS3);
13011 check_mips_64(ctx);
13012 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13013 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13014 break;
13015 case I64_DADDIUPC:
13016 check_insn(ctx, ISA_MIPS3);
13017 check_mips_64(ctx);
13018 offset = extended ? offset : offset << 2;
13019 gen_addiupc(ctx, ry, offset, 1, extended);
13020 break;
13021 case I64_DADDIUSP:
13022 check_insn(ctx, ISA_MIPS3);
13023 check_mips_64(ctx);
13024 offset = extended ? offset : offset << 2;
13025 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13026 break;
13029 #endif
13031 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13033 int extend = translator_lduw(env, ctx->base.pc_next + 2);
13034 int op, rx, ry, funct, sa;
13035 int16_t imm, offset;
13037 ctx->opcode = (ctx->opcode << 16) | extend;
13038 op = (ctx->opcode >> 11) & 0x1f;
13039 sa = (ctx->opcode >> 22) & 0x1f;
13040 funct = (ctx->opcode >> 8) & 0x7;
13041 rx = xlat((ctx->opcode >> 8) & 0x7);
13042 ry = xlat((ctx->opcode >> 5) & 0x7);
13043 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13044 | ((ctx->opcode >> 21) & 0x3f) << 5
13045 | (ctx->opcode & 0x1f));
13048 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13049 * counterparts.
13051 switch (op) {
13052 case M16_OPC_ADDIUSP:
13053 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13054 break;
13055 case M16_OPC_ADDIUPC:
13056 gen_addiupc(ctx, rx, imm, 0, 1);
13057 break;
13058 case M16_OPC_B:
13059 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13060 /* No delay slot, so just process as a normal instruction */
13061 break;
13062 case M16_OPC_BEQZ:
13063 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13064 /* No delay slot, so just process as a normal instruction */
13065 break;
13066 case M16_OPC_BNEQZ:
13067 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13068 /* No delay slot, so just process as a normal instruction */
13069 break;
13070 case M16_OPC_SHIFT:
13071 switch (ctx->opcode & 0x3) {
13072 case 0x0:
13073 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13074 break;
13075 case 0x1:
13076 #if defined(TARGET_MIPS64)
13077 check_mips_64(ctx);
13078 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13079 #else
13080 gen_reserved_instruction(ctx);
13081 #endif
13082 break;
13083 case 0x2:
13084 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13085 break;
13086 case 0x3:
13087 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13088 break;
13090 break;
13091 #if defined(TARGET_MIPS64)
13092 case M16_OPC_LD:
13093 check_insn(ctx, ISA_MIPS3);
13094 check_mips_64(ctx);
13095 gen_ld(ctx, OPC_LD, ry, rx, offset);
13096 break;
13097 #endif
13098 case M16_OPC_RRIA:
13099 imm = ctx->opcode & 0xf;
13100 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13101 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13102 imm = (int16_t) (imm << 1) >> 1;
13103 if ((ctx->opcode >> 4) & 0x1) {
13104 #if defined(TARGET_MIPS64)
13105 check_mips_64(ctx);
13106 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13107 #else
13108 gen_reserved_instruction(ctx);
13109 #endif
13110 } else {
13111 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13113 break;
13114 case M16_OPC_ADDIU8:
13115 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13116 break;
13117 case M16_OPC_SLTI:
13118 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13119 break;
13120 case M16_OPC_SLTIU:
13121 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13122 break;
13123 case M16_OPC_I8:
13124 switch (funct) {
13125 case I8_BTEQZ:
13126 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13127 break;
13128 case I8_BTNEZ:
13129 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13130 break;
13131 case I8_SWRASP:
13132 gen_st(ctx, OPC_SW, 31, 29, imm);
13133 break;
13134 case I8_ADJSP:
13135 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13136 break;
13137 case I8_SVRS:
13138 check_insn(ctx, ISA_MIPS_R1);
13140 int xsregs = (ctx->opcode >> 24) & 0x7;
13141 int aregs = (ctx->opcode >> 16) & 0xf;
13142 int do_ra = (ctx->opcode >> 6) & 0x1;
13143 int do_s0 = (ctx->opcode >> 5) & 0x1;
13144 int do_s1 = (ctx->opcode >> 4) & 0x1;
13145 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13146 | (ctx->opcode & 0xf)) << 3;
13148 if (ctx->opcode & (1 << 7)) {
13149 gen_mips16_save(ctx, xsregs, aregs,
13150 do_ra, do_s0, do_s1,
13151 framesize);
13152 } else {
13153 gen_mips16_restore(ctx, xsregs, aregs,
13154 do_ra, do_s0, do_s1,
13155 framesize);
13158 break;
13159 default:
13160 gen_reserved_instruction(ctx);
13161 break;
13163 break;
13164 case M16_OPC_LI:
13165 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13166 break;
13167 case M16_OPC_CMPI:
13168 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13169 break;
13170 #if defined(TARGET_MIPS64)
13171 case M16_OPC_SD:
13172 check_insn(ctx, ISA_MIPS3);
13173 check_mips_64(ctx);
13174 gen_st(ctx, OPC_SD, ry, rx, offset);
13175 break;
13176 #endif
13177 case M16_OPC_LB:
13178 gen_ld(ctx, OPC_LB, ry, rx, offset);
13179 break;
13180 case M16_OPC_LH:
13181 gen_ld(ctx, OPC_LH, ry, rx, offset);
13182 break;
13183 case M16_OPC_LWSP:
13184 gen_ld(ctx, OPC_LW, rx, 29, offset);
13185 break;
13186 case M16_OPC_LW:
13187 gen_ld(ctx, OPC_LW, ry, rx, offset);
13188 break;
13189 case M16_OPC_LBU:
13190 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13191 break;
13192 case M16_OPC_LHU:
13193 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13194 break;
13195 case M16_OPC_LWPC:
13196 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13197 break;
13198 #if defined(TARGET_MIPS64)
13199 case M16_OPC_LWU:
13200 check_insn(ctx, ISA_MIPS3);
13201 check_mips_64(ctx);
13202 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13203 break;
13204 #endif
13205 case M16_OPC_SB:
13206 gen_st(ctx, OPC_SB, ry, rx, offset);
13207 break;
13208 case M16_OPC_SH:
13209 gen_st(ctx, OPC_SH, ry, rx, offset);
13210 break;
13211 case M16_OPC_SWSP:
13212 gen_st(ctx, OPC_SW, rx, 29, offset);
13213 break;
13214 case M16_OPC_SW:
13215 gen_st(ctx, OPC_SW, ry, rx, offset);
13216 break;
13217 #if defined(TARGET_MIPS64)
13218 case M16_OPC_I64:
13219 decode_i64_mips16(ctx, ry, funct, offset, 1);
13220 break;
13221 #endif
13222 default:
13223 gen_reserved_instruction(ctx);
13224 break;
13227 return 4;
13230 static inline bool is_uhi(int sdbbp_code)
13232 #ifdef CONFIG_USER_ONLY
13233 return false;
13234 #else
13235 return semihosting_enabled() && sdbbp_code == 1;
13236 #endif
13239 #ifdef CONFIG_USER_ONLY
13240 /* The above should dead-code away any calls to this..*/
13241 static inline void gen_helper_do_semihosting(void *env)
13243 g_assert_not_reached();
13245 #endif
13247 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13249 int rx, ry;
13250 int sa;
13251 int op, cnvt_op, op1, offset;
13252 int funct;
13253 int n_bytes;
13255 op = (ctx->opcode >> 11) & 0x1f;
13256 sa = (ctx->opcode >> 2) & 0x7;
13257 sa = sa == 0 ? 8 : sa;
13258 rx = xlat((ctx->opcode >> 8) & 0x7);
13259 cnvt_op = (ctx->opcode >> 5) & 0x7;
13260 ry = xlat((ctx->opcode >> 5) & 0x7);
13261 op1 = offset = ctx->opcode & 0x1f;
13263 n_bytes = 2;
13265 switch (op) {
13266 case M16_OPC_ADDIUSP:
13268 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13270 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13272 break;
13273 case M16_OPC_ADDIUPC:
13274 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13275 break;
13276 case M16_OPC_B:
13277 offset = (ctx->opcode & 0x7ff) << 1;
13278 offset = (int16_t)(offset << 4) >> 4;
13279 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13280 /* No delay slot, so just process as a normal instruction */
13281 break;
13282 case M16_OPC_JAL:
13283 offset = translator_lduw(env, ctx->base.pc_next + 2);
13284 offset = (((ctx->opcode & 0x1f) << 21)
13285 | ((ctx->opcode >> 5) & 0x1f) << 16
13286 | offset) << 2;
13287 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13288 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13289 n_bytes = 4;
13290 break;
13291 case M16_OPC_BEQZ:
13292 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13293 ((int8_t)ctx->opcode) << 1, 0);
13294 /* No delay slot, so just process as a normal instruction */
13295 break;
13296 case M16_OPC_BNEQZ:
13297 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13298 ((int8_t)ctx->opcode) << 1, 0);
13299 /* No delay slot, so just process as a normal instruction */
13300 break;
13301 case M16_OPC_SHIFT:
13302 switch (ctx->opcode & 0x3) {
13303 case 0x0:
13304 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13305 break;
13306 case 0x1:
13307 #if defined(TARGET_MIPS64)
13308 check_insn(ctx, ISA_MIPS3);
13309 check_mips_64(ctx);
13310 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13311 #else
13312 gen_reserved_instruction(ctx);
13313 #endif
13314 break;
13315 case 0x2:
13316 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13317 break;
13318 case 0x3:
13319 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13320 break;
13322 break;
13323 #if defined(TARGET_MIPS64)
13324 case M16_OPC_LD:
13325 check_insn(ctx, ISA_MIPS3);
13326 check_mips_64(ctx);
13327 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13328 break;
13329 #endif
13330 case M16_OPC_RRIA:
13332 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13334 if ((ctx->opcode >> 4) & 1) {
13335 #if defined(TARGET_MIPS64)
13336 check_insn(ctx, ISA_MIPS3);
13337 check_mips_64(ctx);
13338 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13339 #else
13340 gen_reserved_instruction(ctx);
13341 #endif
13342 } else {
13343 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13346 break;
13347 case M16_OPC_ADDIU8:
13349 int16_t imm = (int8_t) ctx->opcode;
13351 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13353 break;
13354 case M16_OPC_SLTI:
13356 int16_t imm = (uint8_t) ctx->opcode;
13357 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13359 break;
13360 case M16_OPC_SLTIU:
13362 int16_t imm = (uint8_t) ctx->opcode;
13363 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13365 break;
13366 case M16_OPC_I8:
13368 int reg32;
13370 funct = (ctx->opcode >> 8) & 0x7;
13371 switch (funct) {
13372 case I8_BTEQZ:
13373 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13374 ((int8_t)ctx->opcode) << 1, 0);
13375 break;
13376 case I8_BTNEZ:
13377 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13378 ((int8_t)ctx->opcode) << 1, 0);
13379 break;
13380 case I8_SWRASP:
13381 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13382 break;
13383 case I8_ADJSP:
13384 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13385 ((int8_t)ctx->opcode) << 3);
13386 break;
13387 case I8_SVRS:
13388 check_insn(ctx, ISA_MIPS_R1);
13390 int do_ra = ctx->opcode & (1 << 6);
13391 int do_s0 = ctx->opcode & (1 << 5);
13392 int do_s1 = ctx->opcode & (1 << 4);
13393 int framesize = ctx->opcode & 0xf;
13395 if (framesize == 0) {
13396 framesize = 128;
13397 } else {
13398 framesize = framesize << 3;
13401 if (ctx->opcode & (1 << 7)) {
13402 gen_mips16_save(ctx, 0, 0,
13403 do_ra, do_s0, do_s1, framesize);
13404 } else {
13405 gen_mips16_restore(ctx, 0, 0,
13406 do_ra, do_s0, do_s1, framesize);
13409 break;
13410 case I8_MOV32R:
13412 int rz = xlat(ctx->opcode & 0x7);
13414 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13415 ((ctx->opcode >> 5) & 0x7);
13416 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13418 break;
13419 case I8_MOVR32:
13420 reg32 = ctx->opcode & 0x1f;
13421 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13422 break;
13423 default:
13424 gen_reserved_instruction(ctx);
13425 break;
13428 break;
13429 case M16_OPC_LI:
13431 int16_t imm = (uint8_t) ctx->opcode;
13433 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13435 break;
13436 case M16_OPC_CMPI:
13438 int16_t imm = (uint8_t) ctx->opcode;
13439 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13441 break;
13442 #if defined(TARGET_MIPS64)
13443 case M16_OPC_SD:
13444 check_insn(ctx, ISA_MIPS3);
13445 check_mips_64(ctx);
13446 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13447 break;
13448 #endif
13449 case M16_OPC_LB:
13450 gen_ld(ctx, OPC_LB, ry, rx, offset);
13451 break;
13452 case M16_OPC_LH:
13453 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13454 break;
13455 case M16_OPC_LWSP:
13456 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13457 break;
13458 case M16_OPC_LW:
13459 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13460 break;
13461 case M16_OPC_LBU:
13462 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13463 break;
13464 case M16_OPC_LHU:
13465 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13466 break;
13467 case M16_OPC_LWPC:
13468 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13469 break;
13470 #if defined(TARGET_MIPS64)
13471 case M16_OPC_LWU:
13472 check_insn(ctx, ISA_MIPS3);
13473 check_mips_64(ctx);
13474 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13475 break;
13476 #endif
13477 case M16_OPC_SB:
13478 gen_st(ctx, OPC_SB, ry, rx, offset);
13479 break;
13480 case M16_OPC_SH:
13481 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13482 break;
13483 case M16_OPC_SWSP:
13484 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13485 break;
13486 case M16_OPC_SW:
13487 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13488 break;
13489 case M16_OPC_RRR:
13491 int rz = xlat((ctx->opcode >> 2) & 0x7);
13492 int mips32_op;
13494 switch (ctx->opcode & 0x3) {
13495 case RRR_ADDU:
13496 mips32_op = OPC_ADDU;
13497 break;
13498 case RRR_SUBU:
13499 mips32_op = OPC_SUBU;
13500 break;
13501 #if defined(TARGET_MIPS64)
13502 case RRR_DADDU:
13503 mips32_op = OPC_DADDU;
13504 check_insn(ctx, ISA_MIPS3);
13505 check_mips_64(ctx);
13506 break;
13507 case RRR_DSUBU:
13508 mips32_op = OPC_DSUBU;
13509 check_insn(ctx, ISA_MIPS3);
13510 check_mips_64(ctx);
13511 break;
13512 #endif
13513 default:
13514 gen_reserved_instruction(ctx);
13515 goto done;
13518 gen_arith(ctx, mips32_op, rz, rx, ry);
13519 done:
13522 break;
13523 case M16_OPC_RR:
13524 switch (op1) {
13525 case RR_JR:
13527 int nd = (ctx->opcode >> 7) & 0x1;
13528 int link = (ctx->opcode >> 6) & 0x1;
13529 int ra = (ctx->opcode >> 5) & 0x1;
13531 if (nd) {
13532 check_insn(ctx, ISA_MIPS_R1);
13535 if (link) {
13536 op = OPC_JALR;
13537 } else {
13538 op = OPC_JR;
13541 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13542 (nd ? 0 : 2));
13544 break;
13545 case RR_SDBBP:
13546 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13547 gen_helper_do_semihosting(cpu_env);
13548 } else {
13550 * XXX: not clear which exception should be raised
13551 * when in debug mode...
13553 check_insn(ctx, ISA_MIPS_R1);
13554 generate_exception_end(ctx, EXCP_DBp);
13556 break;
13557 case RR_SLT:
13558 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13559 break;
13560 case RR_SLTU:
13561 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13562 break;
13563 case RR_BREAK:
13564 generate_exception_end(ctx, EXCP_BREAK);
13565 break;
13566 case RR_SLLV:
13567 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13568 break;
13569 case RR_SRLV:
13570 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13571 break;
13572 case RR_SRAV:
13573 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13574 break;
13575 #if defined(TARGET_MIPS64)
13576 case RR_DSRL:
13577 check_insn(ctx, ISA_MIPS3);
13578 check_mips_64(ctx);
13579 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13580 break;
13581 #endif
13582 case RR_CMP:
13583 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13584 break;
13585 case RR_NEG:
13586 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13587 break;
13588 case RR_AND:
13589 gen_logic(ctx, OPC_AND, rx, rx, ry);
13590 break;
13591 case RR_OR:
13592 gen_logic(ctx, OPC_OR, rx, rx, ry);
13593 break;
13594 case RR_XOR:
13595 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13596 break;
13597 case RR_NOT:
13598 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13599 break;
13600 case RR_MFHI:
13601 gen_HILO(ctx, OPC_MFHI, 0, rx);
13602 break;
13603 case RR_CNVT:
13604 check_insn(ctx, ISA_MIPS_R1);
13605 switch (cnvt_op) {
13606 case RR_RY_CNVT_ZEB:
13607 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13608 break;
13609 case RR_RY_CNVT_ZEH:
13610 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13611 break;
13612 case RR_RY_CNVT_SEB:
13613 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13614 break;
13615 case RR_RY_CNVT_SEH:
13616 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13617 break;
13618 #if defined(TARGET_MIPS64)
13619 case RR_RY_CNVT_ZEW:
13620 check_insn(ctx, ISA_MIPS_R1);
13621 check_mips_64(ctx);
13622 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13623 break;
13624 case RR_RY_CNVT_SEW:
13625 check_insn(ctx, ISA_MIPS_R1);
13626 check_mips_64(ctx);
13627 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13628 break;
13629 #endif
13630 default:
13631 gen_reserved_instruction(ctx);
13632 break;
13634 break;
13635 case RR_MFLO:
13636 gen_HILO(ctx, OPC_MFLO, 0, rx);
13637 break;
13638 #if defined(TARGET_MIPS64)
13639 case RR_DSRA:
13640 check_insn(ctx, ISA_MIPS3);
13641 check_mips_64(ctx);
13642 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13643 break;
13644 case RR_DSLLV:
13645 check_insn(ctx, ISA_MIPS3);
13646 check_mips_64(ctx);
13647 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13648 break;
13649 case RR_DSRLV:
13650 check_insn(ctx, ISA_MIPS3);
13651 check_mips_64(ctx);
13652 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13653 break;
13654 case RR_DSRAV:
13655 check_insn(ctx, ISA_MIPS3);
13656 check_mips_64(ctx);
13657 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13658 break;
13659 #endif
13660 case RR_MULT:
13661 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13662 break;
13663 case RR_MULTU:
13664 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13665 break;
13666 case RR_DIV:
13667 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13668 break;
13669 case RR_DIVU:
13670 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13671 break;
13672 #if defined(TARGET_MIPS64)
13673 case RR_DMULT:
13674 check_insn(ctx, ISA_MIPS3);
13675 check_mips_64(ctx);
13676 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13677 break;
13678 case RR_DMULTU:
13679 check_insn(ctx, ISA_MIPS3);
13680 check_mips_64(ctx);
13681 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13682 break;
13683 case RR_DDIV:
13684 check_insn(ctx, ISA_MIPS3);
13685 check_mips_64(ctx);
13686 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13687 break;
13688 case RR_DDIVU:
13689 check_insn(ctx, ISA_MIPS3);
13690 check_mips_64(ctx);
13691 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13692 break;
13693 #endif
13694 default:
13695 gen_reserved_instruction(ctx);
13696 break;
13698 break;
13699 case M16_OPC_EXTEND:
13700 decode_extended_mips16_opc(env, ctx);
13701 n_bytes = 4;
13702 break;
13703 #if defined(TARGET_MIPS64)
13704 case M16_OPC_I64:
13705 funct = (ctx->opcode >> 8) & 0x7;
13706 decode_i64_mips16(ctx, ry, funct, offset, 0);
13707 break;
13708 #endif
13709 default:
13710 gen_reserved_instruction(ctx);
13711 break;
13714 return n_bytes;
13717 /* microMIPS extension to MIPS32/MIPS64 */
13720 * microMIPS32/microMIPS64 major opcodes
13722 * 1. MIPS Architecture for Programmers Volume II-B:
13723 * The microMIPS32 Instruction Set (Revision 3.05)
13725 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13727 * 2. MIPS Architecture For Programmers Volume II-A:
13728 * The MIPS64 Instruction Set (Revision 3.51)
13731 enum {
13732 POOL32A = 0x00,
13733 POOL16A = 0x01,
13734 LBU16 = 0x02,
13735 MOVE16 = 0x03,
13736 ADDI32 = 0x04,
13737 R6_LUI = 0x04,
13738 AUI = 0x04,
13739 LBU32 = 0x05,
13740 SB32 = 0x06,
13741 LB32 = 0x07,
13743 POOL32B = 0x08,
13744 POOL16B = 0x09,
13745 LHU16 = 0x0a,
13746 ANDI16 = 0x0b,
13747 ADDIU32 = 0x0c,
13748 LHU32 = 0x0d,
13749 SH32 = 0x0e,
13750 LH32 = 0x0f,
13752 POOL32I = 0x10,
13753 POOL16C = 0x11,
13754 LWSP16 = 0x12,
13755 POOL16D = 0x13,
13756 ORI32 = 0x14,
13757 POOL32F = 0x15,
13758 POOL32S = 0x16, /* MIPS64 */
13759 DADDIU32 = 0x17, /* MIPS64 */
13761 POOL32C = 0x18,
13762 LWGP16 = 0x19,
13763 LW16 = 0x1a,
13764 POOL16E = 0x1b,
13765 XORI32 = 0x1c,
13766 JALS32 = 0x1d,
13767 BOVC = 0x1d,
13768 BEQC = 0x1d,
13769 BEQZALC = 0x1d,
13770 ADDIUPC = 0x1e,
13771 PCREL = 0x1e,
13772 BNVC = 0x1f,
13773 BNEC = 0x1f,
13774 BNEZALC = 0x1f,
13776 R6_BEQZC = 0x20,
13777 JIC = 0x20,
13778 POOL16F = 0x21,
13779 SB16 = 0x22,
13780 BEQZ16 = 0x23,
13781 BEQZC16 = 0x23,
13782 SLTI32 = 0x24,
13783 BEQ32 = 0x25,
13784 BC = 0x25,
13785 SWC132 = 0x26,
13786 LWC132 = 0x27,
13788 /* 0x29 is reserved */
13789 RES_29 = 0x29,
13790 R6_BNEZC = 0x28,
13791 JIALC = 0x28,
13792 SH16 = 0x2a,
13793 BNEZ16 = 0x2b,
13794 BNEZC16 = 0x2b,
13795 SLTIU32 = 0x2c,
13796 BNE32 = 0x2d,
13797 BALC = 0x2d,
13798 SDC132 = 0x2e,
13799 LDC132 = 0x2f,
13801 /* 0x31 is reserved */
13802 RES_31 = 0x31,
13803 BLEZALC = 0x30,
13804 BGEZALC = 0x30,
13805 BGEUC = 0x30,
13806 SWSP16 = 0x32,
13807 B16 = 0x33,
13808 BC16 = 0x33,
13809 ANDI32 = 0x34,
13810 J32 = 0x35,
13811 BGTZC = 0x35,
13812 BLTZC = 0x35,
13813 BLTC = 0x35,
13814 SD32 = 0x36, /* MIPS64 */
13815 LD32 = 0x37, /* MIPS64 */
13817 /* 0x39 is reserved */
13818 RES_39 = 0x39,
13819 BGTZALC = 0x38,
13820 BLTZALC = 0x38,
13821 BLTUC = 0x38,
13822 SW16 = 0x3a,
13823 LI16 = 0x3b,
13824 JALX32 = 0x3c,
13825 JAL32 = 0x3d,
13826 BLEZC = 0x3d,
13827 BGEZC = 0x3d,
13828 BGEC = 0x3d,
13829 SW32 = 0x3e,
13830 LW32 = 0x3f
13833 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
13834 enum {
13835 ADDIUPC_00 = 0x00,
13836 ADDIUPC_01 = 0x01,
13837 ADDIUPC_02 = 0x02,
13838 ADDIUPC_03 = 0x03,
13839 ADDIUPC_04 = 0x04,
13840 ADDIUPC_05 = 0x05,
13841 ADDIUPC_06 = 0x06,
13842 ADDIUPC_07 = 0x07,
13843 AUIPC = 0x1e,
13844 ALUIPC = 0x1f,
13845 LWPC_08 = 0x08,
13846 LWPC_09 = 0x09,
13847 LWPC_0A = 0x0A,
13848 LWPC_0B = 0x0B,
13849 LWPC_0C = 0x0C,
13850 LWPC_0D = 0x0D,
13851 LWPC_0E = 0x0E,
13852 LWPC_0F = 0x0F,
13855 /* POOL32A encoding of minor opcode field */
13857 enum {
13859 * These opcodes are distinguished only by bits 9..6; those bits are
13860 * what are recorded below.
13862 SLL32 = 0x0,
13863 SRL32 = 0x1,
13864 SRA = 0x2,
13865 ROTR = 0x3,
13866 SELEQZ = 0x5,
13867 SELNEZ = 0x6,
13868 R6_RDHWR = 0x7,
13870 SLLV = 0x0,
13871 SRLV = 0x1,
13872 SRAV = 0x2,
13873 ROTRV = 0x3,
13874 ADD = 0x4,
13875 ADDU32 = 0x5,
13876 SUB = 0x6,
13877 SUBU32 = 0x7,
13878 MUL = 0x8,
13879 AND = 0x9,
13880 OR32 = 0xa,
13881 NOR = 0xb,
13882 XOR32 = 0xc,
13883 SLT = 0xd,
13884 SLTU = 0xe,
13886 MOVN = 0x0,
13887 R6_MUL = 0x0,
13888 MOVZ = 0x1,
13889 MUH = 0x1,
13890 MULU = 0x2,
13891 MUHU = 0x3,
13892 LWXS = 0x4,
13893 R6_DIV = 0x4,
13894 MOD = 0x5,
13895 R6_DIVU = 0x6,
13896 MODU = 0x7,
13898 /* The following can be distinguished by their lower 6 bits. */
13899 BREAK32 = 0x07,
13900 INS = 0x0c,
13901 LSA = 0x0f,
13902 ALIGN = 0x1f,
13903 EXT = 0x2c,
13904 POOL32AXF = 0x3c,
13905 SIGRIE = 0x3f
13908 /* POOL32AXF encoding of minor opcode field extension */
13911 * 1. MIPS Architecture for Programmers Volume II-B:
13912 * The microMIPS32 Instruction Set (Revision 3.05)
13914 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
13916 * 2. MIPS Architecture for Programmers VolumeIV-e:
13917 * The MIPS DSP Application-Specific Extension
13918 * to the microMIPS32 Architecture (Revision 2.34)
13920 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
13923 enum {
13924 /* bits 11..6 */
13925 TEQ = 0x00,
13926 TGE = 0x08,
13927 TGEU = 0x10,
13928 TLT = 0x20,
13929 TLTU = 0x28,
13930 TNE = 0x30,
13932 MFC0 = 0x03,
13933 MTC0 = 0x0b,
13935 /* begin of microMIPS32 DSP */
13937 /* bits 13..12 for 0x01 */
13938 MFHI_ACC = 0x0,
13939 MFLO_ACC = 0x1,
13940 MTHI_ACC = 0x2,
13941 MTLO_ACC = 0x3,
13943 /* bits 13..12 for 0x2a */
13944 MADD_ACC = 0x0,
13945 MADDU_ACC = 0x1,
13946 MSUB_ACC = 0x2,
13947 MSUBU_ACC = 0x3,
13949 /* bits 13..12 for 0x32 */
13950 MULT_ACC = 0x0,
13951 MULTU_ACC = 0x1,
13953 /* end of microMIPS32 DSP */
13955 /* bits 15..12 for 0x2c */
13956 BITSWAP = 0x0,
13957 SEB = 0x2,
13958 SEH = 0x3,
13959 CLO = 0x4,
13960 CLZ = 0x5,
13961 RDHWR = 0x6,
13962 WSBH = 0x7,
13963 MULT = 0x8,
13964 MULTU = 0x9,
13965 DIV = 0xa,
13966 DIVU = 0xb,
13967 MADD = 0xc,
13968 MADDU = 0xd,
13969 MSUB = 0xe,
13970 MSUBU = 0xf,
13972 /* bits 15..12 for 0x34 */
13973 MFC2 = 0x4,
13974 MTC2 = 0x5,
13975 MFHC2 = 0x8,
13976 MTHC2 = 0x9,
13977 CFC2 = 0xc,
13978 CTC2 = 0xd,
13980 /* bits 15..12 for 0x3c */
13981 JALR = 0x0,
13982 JR = 0x0, /* alias */
13983 JALRC = 0x0,
13984 JRC = 0x0,
13985 JALR_HB = 0x1,
13986 JALRC_HB = 0x1,
13987 JALRS = 0x4,
13988 JALRS_HB = 0x5,
13990 /* bits 15..12 for 0x05 */
13991 RDPGPR = 0xe,
13992 WRPGPR = 0xf,
13994 /* bits 15..12 for 0x0d */
13995 TLBP = 0x0,
13996 TLBR = 0x1,
13997 TLBWI = 0x2,
13998 TLBWR = 0x3,
13999 TLBINV = 0x4,
14000 TLBINVF = 0x5,
14001 WAIT = 0x9,
14002 IRET = 0xd,
14003 DERET = 0xe,
14004 ERET = 0xf,
14006 /* bits 15..12 for 0x15 */
14007 DMT = 0x0,
14008 DVPE = 0x1,
14009 EMT = 0x2,
14010 EVPE = 0x3,
14012 /* bits 15..12 for 0x1d */
14013 DI = 0x4,
14014 EI = 0x5,
14016 /* bits 15..12 for 0x2d */
14017 SYNC = 0x6,
14018 SYSCALL = 0x8,
14019 SDBBP = 0xd,
14021 /* bits 15..12 for 0x35 */
14022 MFHI32 = 0x0,
14023 MFLO32 = 0x1,
14024 MTHI32 = 0x2,
14025 MTLO32 = 0x3,
14028 /* POOL32B encoding of minor opcode field (bits 15..12) */
14030 enum {
14031 LWC2 = 0x0,
14032 LWP = 0x1,
14033 LDP = 0x4,
14034 LWM32 = 0x5,
14035 CACHE = 0x6,
14036 LDM = 0x7,
14037 SWC2 = 0x8,
14038 SWP = 0x9,
14039 SDP = 0xc,
14040 SWM32 = 0xd,
14041 SDM = 0xf
14044 /* POOL32C encoding of minor opcode field (bits 15..12) */
14046 enum {
14047 LWL = 0x0,
14048 SWL = 0x8,
14049 LWR = 0x1,
14050 SWR = 0x9,
14051 PREF = 0x2,
14052 ST_EVA = 0xa,
14053 LL = 0x3,
14054 SC = 0xb,
14055 LDL = 0x4,
14056 SDL = 0xc,
14057 LDR = 0x5,
14058 SDR = 0xd,
14059 LD_EVA = 0x6,
14060 LWU = 0xe,
14061 LLD = 0x7,
14062 SCD = 0xf
14065 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14067 enum {
14068 LBUE = 0x0,
14069 LHUE = 0x1,
14070 LWLE = 0x2,
14071 LWRE = 0x3,
14072 LBE = 0x4,
14073 LHE = 0x5,
14074 LLE = 0x6,
14075 LWE = 0x7,
14078 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14080 enum {
14081 SWLE = 0x0,
14082 SWRE = 0x1,
14083 PREFE = 0x2,
14084 CACHEE = 0x3,
14085 SBE = 0x4,
14086 SHE = 0x5,
14087 SCE = 0x6,
14088 SWE = 0x7,
14091 /* POOL32F encoding of minor opcode field (bits 5..0) */
14093 enum {
14094 /* These are the bit 7..6 values */
14095 ADD_FMT = 0x0,
14097 SUB_FMT = 0x1,
14099 MUL_FMT = 0x2,
14101 DIV_FMT = 0x3,
14103 /* These are the bit 8..6 values */
14104 MOVN_FMT = 0x0,
14105 RSQRT2_FMT = 0x0,
14106 MOVF_FMT = 0x0,
14107 RINT_FMT = 0x0,
14108 SELNEZ_FMT = 0x0,
14110 MOVZ_FMT = 0x1,
14111 LWXC1 = 0x1,
14112 MOVT_FMT = 0x1,
14113 CLASS_FMT = 0x1,
14114 SELEQZ_FMT = 0x1,
14116 PLL_PS = 0x2,
14117 SWXC1 = 0x2,
14118 SEL_FMT = 0x2,
14120 PLU_PS = 0x3,
14121 LDXC1 = 0x3,
14123 MOVN_FMT_04 = 0x4,
14124 PUL_PS = 0x4,
14125 SDXC1 = 0x4,
14126 RECIP2_FMT = 0x4,
14128 MOVZ_FMT_05 = 0x05,
14129 PUU_PS = 0x5,
14130 LUXC1 = 0x5,
14132 CVT_PS_S = 0x6,
14133 SUXC1 = 0x6,
14134 ADDR_PS = 0x6,
14135 PREFX = 0x6,
14136 MADDF_FMT = 0x6,
14138 MULR_PS = 0x7,
14139 MSUBF_FMT = 0x7,
14141 MADD_S = 0x01,
14142 MADD_D = 0x09,
14143 MADD_PS = 0x11,
14144 ALNV_PS = 0x19,
14145 MSUB_S = 0x21,
14146 MSUB_D = 0x29,
14147 MSUB_PS = 0x31,
14149 NMADD_S = 0x02,
14150 NMADD_D = 0x0a,
14151 NMADD_PS = 0x12,
14152 NMSUB_S = 0x22,
14153 NMSUB_D = 0x2a,
14154 NMSUB_PS = 0x32,
14156 MIN_FMT = 0x3,
14157 MAX_FMT = 0xb,
14158 MINA_FMT = 0x23,
14159 MAXA_FMT = 0x2b,
14160 POOL32FXF = 0x3b,
14162 CABS_COND_FMT = 0x1c, /* MIPS3D */
14163 C_COND_FMT = 0x3c,
14165 CMP_CONDN_S = 0x5,
14166 CMP_CONDN_D = 0x15
14169 /* POOL32Fxf encoding of minor opcode extension field */
14171 enum {
14172 CVT_L = 0x04,
14173 RSQRT_FMT = 0x08,
14174 FLOOR_L = 0x0c,
14175 CVT_PW_PS = 0x1c,
14176 CVT_W = 0x24,
14177 SQRT_FMT = 0x28,
14178 FLOOR_W = 0x2c,
14179 CVT_PS_PW = 0x3c,
14180 CFC1 = 0x40,
14181 RECIP_FMT = 0x48,
14182 CEIL_L = 0x4c,
14183 CTC1 = 0x60,
14184 CEIL_W = 0x6c,
14185 MFC1 = 0x80,
14186 CVT_S_PL = 0x84,
14187 TRUNC_L = 0x8c,
14188 MTC1 = 0xa0,
14189 CVT_S_PU = 0xa4,
14190 TRUNC_W = 0xac,
14191 MFHC1 = 0xc0,
14192 ROUND_L = 0xcc,
14193 MTHC1 = 0xe0,
14194 ROUND_W = 0xec,
14196 MOV_FMT = 0x01,
14197 MOVF = 0x05,
14198 ABS_FMT = 0x0d,
14199 RSQRT1_FMT = 0x1d,
14200 MOVT = 0x25,
14201 NEG_FMT = 0x2d,
14202 CVT_D = 0x4d,
14203 RECIP1_FMT = 0x5d,
14204 CVT_S = 0x6d
14207 /* POOL32I encoding of minor opcode field (bits 25..21) */
14209 enum {
14210 BLTZ = 0x00,
14211 BLTZAL = 0x01,
14212 BGEZ = 0x02,
14213 BGEZAL = 0x03,
14214 BLEZ = 0x04,
14215 BNEZC = 0x05,
14216 BGTZ = 0x06,
14217 BEQZC = 0x07,
14218 TLTI = 0x08,
14219 BC1EQZC = 0x08,
14220 TGEI = 0x09,
14221 BC1NEZC = 0x09,
14222 TLTIU = 0x0a,
14223 BC2EQZC = 0x0a,
14224 TGEIU = 0x0b,
14225 BC2NEZC = 0x0a,
14226 TNEI = 0x0c,
14227 R6_SYNCI = 0x0c,
14228 LUI = 0x0d,
14229 TEQI = 0x0e,
14230 SYNCI = 0x10,
14231 BLTZALS = 0x11,
14232 BGEZALS = 0x13,
14233 BC2F = 0x14,
14234 BC2T = 0x15,
14235 BPOSGE64 = 0x1a,
14236 BPOSGE32 = 0x1b,
14237 /* These overlap and are distinguished by bit16 of the instruction */
14238 BC1F = 0x1c,
14239 BC1T = 0x1d,
14240 BC1ANY2F = 0x1c,
14241 BC1ANY2T = 0x1d,
14242 BC1ANY4F = 0x1e,
14243 BC1ANY4T = 0x1f
14246 /* POOL16A encoding of minor opcode field */
14248 enum {
14249 ADDU16 = 0x0,
14250 SUBU16 = 0x1
14253 /* POOL16B encoding of minor opcode field */
14255 enum {
14256 SLL16 = 0x0,
14257 SRL16 = 0x1
14260 /* POOL16C encoding of minor opcode field */
14262 enum {
14263 NOT16 = 0x00,
14264 XOR16 = 0x04,
14265 AND16 = 0x08,
14266 OR16 = 0x0c,
14267 LWM16 = 0x10,
14268 SWM16 = 0x14,
14269 JR16 = 0x18,
14270 JRC16 = 0x1a,
14271 JALR16 = 0x1c,
14272 JALR16S = 0x1e,
14273 MFHI16 = 0x20,
14274 MFLO16 = 0x24,
14275 BREAK16 = 0x28,
14276 SDBBP16 = 0x2c,
14277 JRADDIUSP = 0x30
14280 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14282 enum {
14283 R6_NOT16 = 0x00,
14284 R6_AND16 = 0x01,
14285 R6_LWM16 = 0x02,
14286 R6_JRC16 = 0x03,
14287 MOVEP = 0x04,
14288 MOVEP_05 = 0x05,
14289 MOVEP_06 = 0x06,
14290 MOVEP_07 = 0x07,
14291 R6_XOR16 = 0x08,
14292 R6_OR16 = 0x09,
14293 R6_SWM16 = 0x0a,
14294 JALRC16 = 0x0b,
14295 MOVEP_0C = 0x0c,
14296 MOVEP_0D = 0x0d,
14297 MOVEP_0E = 0x0e,
14298 MOVEP_0F = 0x0f,
14299 JRCADDIUSP = 0x13,
14300 R6_BREAK16 = 0x1b,
14301 R6_SDBBP16 = 0x3b
14304 /* POOL16D encoding of minor opcode field */
14306 enum {
14307 ADDIUS5 = 0x0,
14308 ADDIUSP = 0x1
14311 /* POOL16E encoding of minor opcode field */
14313 enum {
14314 ADDIUR2 = 0x0,
14315 ADDIUR1SP = 0x1
14318 static int mmreg(int r)
14320 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14322 return map[r];
14325 /* Used for 16-bit store instructions. */
14326 static int mmreg2(int r)
14328 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14330 return map[r];
14333 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14334 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14335 #define uMIPS_RS2(op) uMIPS_RS(op)
14336 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14337 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14338 #define uMIPS_RS5(op) (op & 0x1f)
14340 /* Signed immediate */
14341 #define SIMM(op, start, width) \
14342 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
14343 << (32 - width)) \
14344 >> (32 - width))
14345 /* Zero-extended immediate */
14346 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
14348 static void gen_addiur1sp(DisasContext *ctx)
14350 int rd = mmreg(uMIPS_RD(ctx->opcode));
14352 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14355 static void gen_addiur2(DisasContext *ctx)
14357 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14358 int rd = mmreg(uMIPS_RD(ctx->opcode));
14359 int rs = mmreg(uMIPS_RS(ctx->opcode));
14361 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14364 static void gen_addiusp(DisasContext *ctx)
14366 int encoded = ZIMM(ctx->opcode, 1, 9);
14367 int decoded;
14369 if (encoded <= 1) {
14370 decoded = 256 + encoded;
14371 } else if (encoded <= 255) {
14372 decoded = encoded;
14373 } else if (encoded <= 509) {
14374 decoded = encoded - 512;
14375 } else {
14376 decoded = encoded - 768;
14379 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14382 static void gen_addius5(DisasContext *ctx)
14384 int imm = SIMM(ctx->opcode, 1, 4);
14385 int rd = (ctx->opcode >> 5) & 0x1f;
14387 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14390 static void gen_andi16(DisasContext *ctx)
14392 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14393 31, 32, 63, 64, 255, 32768, 65535 };
14394 int rd = mmreg(uMIPS_RD(ctx->opcode));
14395 int rs = mmreg(uMIPS_RS(ctx->opcode));
14396 int encoded = ZIMM(ctx->opcode, 0, 4);
14398 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14401 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
14402 int base, int16_t offset)
14404 TCGv t0, t1;
14405 TCGv_i32 t2;
14407 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14408 gen_reserved_instruction(ctx);
14409 return;
14412 t0 = tcg_temp_new();
14414 gen_base_offset_addr(ctx, t0, base, offset);
14416 t1 = tcg_const_tl(reglist);
14417 t2 = tcg_const_i32(ctx->mem_idx);
14419 save_cpu_state(ctx, 1);
14420 switch (opc) {
14421 case LWM32:
14422 gen_helper_lwm(cpu_env, t0, t1, t2);
14423 break;
14424 case SWM32:
14425 gen_helper_swm(cpu_env, t0, t1, t2);
14426 break;
14427 #ifdef TARGET_MIPS64
14428 case LDM:
14429 gen_helper_ldm(cpu_env, t0, t1, t2);
14430 break;
14431 case SDM:
14432 gen_helper_sdm(cpu_env, t0, t1, t2);
14433 break;
14434 #endif
14436 tcg_temp_free(t0);
14437 tcg_temp_free(t1);
14438 tcg_temp_free_i32(t2);
14442 static void gen_pool16c_insn(DisasContext *ctx)
14444 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14445 int rs = mmreg(ctx->opcode & 0x7);
14447 switch (((ctx->opcode) >> 4) & 0x3f) {
14448 case NOT16 + 0:
14449 case NOT16 + 1:
14450 case NOT16 + 2:
14451 case NOT16 + 3:
14452 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14453 break;
14454 case XOR16 + 0:
14455 case XOR16 + 1:
14456 case XOR16 + 2:
14457 case XOR16 + 3:
14458 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14459 break;
14460 case AND16 + 0:
14461 case AND16 + 1:
14462 case AND16 + 2:
14463 case AND16 + 3:
14464 gen_logic(ctx, OPC_AND, rd, rd, rs);
14465 break;
14466 case OR16 + 0:
14467 case OR16 + 1:
14468 case OR16 + 2:
14469 case OR16 + 3:
14470 gen_logic(ctx, OPC_OR, rd, rd, rs);
14471 break;
14472 case LWM16 + 0:
14473 case LWM16 + 1:
14474 case LWM16 + 2:
14475 case LWM16 + 3:
14477 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14478 int offset = ZIMM(ctx->opcode, 0, 4);
14480 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14481 29, offset << 2);
14483 break;
14484 case SWM16 + 0:
14485 case SWM16 + 1:
14486 case SWM16 + 2:
14487 case SWM16 + 3:
14489 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14490 int offset = ZIMM(ctx->opcode, 0, 4);
14492 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14493 29, offset << 2);
14495 break;
14496 case JR16 + 0:
14497 case JR16 + 1:
14499 int reg = ctx->opcode & 0x1f;
14501 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14503 break;
14504 case JRC16 + 0:
14505 case JRC16 + 1:
14507 int reg = ctx->opcode & 0x1f;
14508 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14510 * Let normal delay slot handling in our caller take us
14511 * to the branch target.
14514 break;
14515 case JALR16 + 0:
14516 case JALR16 + 1:
14517 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14518 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14519 break;
14520 case JALR16S + 0:
14521 case JALR16S + 1:
14522 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14523 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14524 break;
14525 case MFHI16 + 0:
14526 case MFHI16 + 1:
14527 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14528 break;
14529 case MFLO16 + 0:
14530 case MFLO16 + 1:
14531 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14532 break;
14533 case BREAK16:
14534 generate_exception_end(ctx, EXCP_BREAK);
14535 break;
14536 case SDBBP16:
14537 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14538 gen_helper_do_semihosting(cpu_env);
14539 } else {
14541 * XXX: not clear which exception should be raised
14542 * when in debug mode...
14544 check_insn(ctx, ISA_MIPS_R1);
14545 generate_exception_end(ctx, EXCP_DBp);
14547 break;
14548 case JRADDIUSP + 0:
14549 case JRADDIUSP + 1:
14551 int imm = ZIMM(ctx->opcode, 0, 5);
14552 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14553 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14555 * Let normal delay slot handling in our caller take us
14556 * to the branch target.
14559 break;
14560 default:
14561 gen_reserved_instruction(ctx);
14562 break;
14566 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14567 int enc_rs)
14569 int rd, re;
14570 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14571 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14572 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14574 rd = rd_enc[enc_dest];
14575 re = re_enc[enc_dest];
14576 gen_load_gpr(cpu_gpr[rd], rs_rt_enc[enc_rs]);
14577 gen_load_gpr(cpu_gpr[re], rs_rt_enc[enc_rt]);
14580 static void gen_pool16c_r6_insn(DisasContext *ctx)
14582 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14583 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14585 switch (ctx->opcode & 0xf) {
14586 case R6_NOT16:
14587 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14588 break;
14589 case R6_AND16:
14590 gen_logic(ctx, OPC_AND, rt, rt, rs);
14591 break;
14592 case R6_LWM16:
14594 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14595 int offset = extract32(ctx->opcode, 4, 4);
14596 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14598 break;
14599 case R6_JRC16: /* JRCADDIUSP */
14600 if ((ctx->opcode >> 4) & 1) {
14601 /* JRCADDIUSP */
14602 int imm = extract32(ctx->opcode, 5, 5);
14603 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14604 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14605 } else {
14606 /* JRC16 */
14607 rs = extract32(ctx->opcode, 5, 5);
14608 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14610 break;
14611 case MOVEP:
14612 case MOVEP_05:
14613 case MOVEP_06:
14614 case MOVEP_07:
14615 case MOVEP_0C:
14616 case MOVEP_0D:
14617 case MOVEP_0E:
14618 case MOVEP_0F:
14620 int enc_dest = uMIPS_RD(ctx->opcode);
14621 int enc_rt = uMIPS_RS2(ctx->opcode);
14622 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14623 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14625 break;
14626 case R6_XOR16:
14627 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14628 break;
14629 case R6_OR16:
14630 gen_logic(ctx, OPC_OR, rt, rt, rs);
14631 break;
14632 case R6_SWM16:
14634 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14635 int offset = extract32(ctx->opcode, 4, 4);
14636 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14638 break;
14639 case JALRC16: /* BREAK16, SDBBP16 */
14640 switch (ctx->opcode & 0x3f) {
14641 case JALRC16:
14642 case JALRC16 + 0x20:
14643 /* JALRC16 */
14644 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14645 31, 0, 0);
14646 break;
14647 case R6_BREAK16:
14648 /* BREAK16 */
14649 generate_exception(ctx, EXCP_BREAK);
14650 break;
14651 case R6_SDBBP16:
14652 /* SDBBP16 */
14653 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14654 gen_helper_do_semihosting(cpu_env);
14655 } else {
14656 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14657 generate_exception(ctx, EXCP_RI);
14658 } else {
14659 generate_exception(ctx, EXCP_DBp);
14662 break;
14664 break;
14665 default:
14666 generate_exception(ctx, EXCP_RI);
14667 break;
14671 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
14673 TCGv t0 = tcg_temp_new();
14674 TCGv t1 = tcg_temp_new();
14676 gen_load_gpr(t0, base);
14678 if (index != 0) {
14679 gen_load_gpr(t1, index);
14680 tcg_gen_shli_tl(t1, t1, 2);
14681 gen_op_addr_add(ctx, t0, t1, t0);
14684 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14685 gen_store_gpr(t1, rd);
14687 tcg_temp_free(t0);
14688 tcg_temp_free(t1);
14691 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
14692 int base, int16_t offset)
14694 TCGv t0, t1;
14696 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14697 gen_reserved_instruction(ctx);
14698 return;
14701 t0 = tcg_temp_new();
14702 t1 = tcg_temp_new();
14704 gen_base_offset_addr(ctx, t0, base, offset);
14706 switch (opc) {
14707 case LWP:
14708 if (rd == base) {
14709 gen_reserved_instruction(ctx);
14710 return;
14712 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14713 gen_store_gpr(t1, rd);
14714 tcg_gen_movi_tl(t1, 4);
14715 gen_op_addr_add(ctx, t0, t0, t1);
14716 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14717 gen_store_gpr(t1, rd + 1);
14718 break;
14719 case SWP:
14720 gen_load_gpr(t1, rd);
14721 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14722 tcg_gen_movi_tl(t1, 4);
14723 gen_op_addr_add(ctx, t0, t0, t1);
14724 gen_load_gpr(t1, rd + 1);
14725 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14726 break;
14727 #ifdef TARGET_MIPS64
14728 case LDP:
14729 if (rd == base) {
14730 gen_reserved_instruction(ctx);
14731 return;
14733 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14734 gen_store_gpr(t1, rd);
14735 tcg_gen_movi_tl(t1, 8);
14736 gen_op_addr_add(ctx, t0, t0, t1);
14737 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14738 gen_store_gpr(t1, rd + 1);
14739 break;
14740 case SDP:
14741 gen_load_gpr(t1, rd);
14742 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14743 tcg_gen_movi_tl(t1, 8);
14744 gen_op_addr_add(ctx, t0, t0, t1);
14745 gen_load_gpr(t1, rd + 1);
14746 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14747 break;
14748 #endif
14750 tcg_temp_free(t0);
14751 tcg_temp_free(t1);
14754 static void gen_sync(int stype)
14756 TCGBar tcg_mo = TCG_BAR_SC;
14758 switch (stype) {
14759 case 0x4: /* SYNC_WMB */
14760 tcg_mo |= TCG_MO_ST_ST;
14761 break;
14762 case 0x10: /* SYNC_MB */
14763 tcg_mo |= TCG_MO_ALL;
14764 break;
14765 case 0x11: /* SYNC_ACQUIRE */
14766 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14767 break;
14768 case 0x12: /* SYNC_RELEASE */
14769 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14770 break;
14771 case 0x13: /* SYNC_RMB */
14772 tcg_mo |= TCG_MO_LD_LD;
14773 break;
14774 default:
14775 tcg_mo |= TCG_MO_ALL;
14776 break;
14779 tcg_gen_mb(tcg_mo);
14782 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14784 int extension = (ctx->opcode >> 6) & 0x3f;
14785 int minor = (ctx->opcode >> 12) & 0xf;
14786 uint32_t mips32_op;
14788 switch (extension) {
14789 case TEQ:
14790 mips32_op = OPC_TEQ;
14791 goto do_trap;
14792 case TGE:
14793 mips32_op = OPC_TGE;
14794 goto do_trap;
14795 case TGEU:
14796 mips32_op = OPC_TGEU;
14797 goto do_trap;
14798 case TLT:
14799 mips32_op = OPC_TLT;
14800 goto do_trap;
14801 case TLTU:
14802 mips32_op = OPC_TLTU;
14803 goto do_trap;
14804 case TNE:
14805 mips32_op = OPC_TNE;
14806 do_trap:
14807 gen_trap(ctx, mips32_op, rs, rt, -1);
14808 break;
14809 #ifndef CONFIG_USER_ONLY
14810 case MFC0:
14811 case MFC0 + 32:
14812 check_cp0_enabled(ctx);
14813 if (rt == 0) {
14814 /* Treat as NOP. */
14815 break;
14817 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
14818 break;
14819 case MTC0:
14820 case MTC0 + 32:
14821 check_cp0_enabled(ctx);
14823 TCGv t0 = tcg_temp_new();
14825 gen_load_gpr(t0, rt);
14826 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
14827 tcg_temp_free(t0);
14829 break;
14830 #endif
14831 case 0x2a:
14832 switch (minor & 3) {
14833 case MADD_ACC:
14834 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
14835 break;
14836 case MADDU_ACC:
14837 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
14838 break;
14839 case MSUB_ACC:
14840 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
14841 break;
14842 case MSUBU_ACC:
14843 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
14844 break;
14845 default:
14846 goto pool32axf_invalid;
14848 break;
14849 case 0x32:
14850 switch (minor & 3) {
14851 case MULT_ACC:
14852 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
14853 break;
14854 case MULTU_ACC:
14855 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
14856 break;
14857 default:
14858 goto pool32axf_invalid;
14860 break;
14861 case 0x2c:
14862 switch (minor) {
14863 case BITSWAP:
14864 check_insn(ctx, ISA_MIPS_R6);
14865 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
14866 break;
14867 case SEB:
14868 gen_bshfl(ctx, OPC_SEB, rs, rt);
14869 break;
14870 case SEH:
14871 gen_bshfl(ctx, OPC_SEH, rs, rt);
14872 break;
14873 case CLO:
14874 mips32_op = OPC_CLO;
14875 goto do_cl;
14876 case CLZ:
14877 mips32_op = OPC_CLZ;
14878 do_cl:
14879 check_insn(ctx, ISA_MIPS_R1);
14880 gen_cl(ctx, mips32_op, rt, rs);
14881 break;
14882 case RDHWR:
14883 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14884 gen_rdhwr(ctx, rt, rs, 0);
14885 break;
14886 case WSBH:
14887 gen_bshfl(ctx, OPC_WSBH, rs, rt);
14888 break;
14889 case MULT:
14890 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14891 mips32_op = OPC_MULT;
14892 goto do_mul;
14893 case MULTU:
14894 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14895 mips32_op = OPC_MULTU;
14896 goto do_mul;
14897 case DIV:
14898 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14899 mips32_op = OPC_DIV;
14900 goto do_div;
14901 case DIVU:
14902 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14903 mips32_op = OPC_DIVU;
14904 goto do_div;
14905 do_div:
14906 check_insn(ctx, ISA_MIPS_R1);
14907 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14908 break;
14909 case MADD:
14910 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14911 mips32_op = OPC_MADD;
14912 goto do_mul;
14913 case MADDU:
14914 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14915 mips32_op = OPC_MADDU;
14916 goto do_mul;
14917 case MSUB:
14918 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14919 mips32_op = OPC_MSUB;
14920 goto do_mul;
14921 case MSUBU:
14922 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14923 mips32_op = OPC_MSUBU;
14924 do_mul:
14925 check_insn(ctx, ISA_MIPS_R1);
14926 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14927 break;
14928 default:
14929 goto pool32axf_invalid;
14931 break;
14932 case 0x34:
14933 switch (minor) {
14934 case MFC2:
14935 case MTC2:
14936 case MFHC2:
14937 case MTHC2:
14938 case CFC2:
14939 case CTC2:
14940 generate_exception_err(ctx, EXCP_CpU, 2);
14941 break;
14942 default:
14943 goto pool32axf_invalid;
14945 break;
14946 case 0x3c:
14947 switch (minor) {
14948 case JALR: /* JALRC */
14949 case JALR_HB: /* JALRC_HB */
14950 if (ctx->insn_flags & ISA_MIPS_R6) {
14951 /* JALRC, JALRC_HB */
14952 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
14953 } else {
14954 /* JALR, JALR_HB */
14955 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
14956 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14958 break;
14959 case JALRS:
14960 case JALRS_HB:
14961 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14962 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
14963 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14964 break;
14965 default:
14966 goto pool32axf_invalid;
14968 break;
14969 case 0x05:
14970 switch (minor) {
14971 case RDPGPR:
14972 check_cp0_enabled(ctx);
14973 check_insn(ctx, ISA_MIPS_R2);
14974 gen_load_srsgpr(rs, rt);
14975 break;
14976 case WRPGPR:
14977 check_cp0_enabled(ctx);
14978 check_insn(ctx, ISA_MIPS_R2);
14979 gen_store_srsgpr(rs, rt);
14980 break;
14981 default:
14982 goto pool32axf_invalid;
14984 break;
14985 #ifndef CONFIG_USER_ONLY
14986 case 0x0d:
14987 switch (minor) {
14988 case TLBP:
14989 mips32_op = OPC_TLBP;
14990 goto do_cp0;
14991 case TLBR:
14992 mips32_op = OPC_TLBR;
14993 goto do_cp0;
14994 case TLBWI:
14995 mips32_op = OPC_TLBWI;
14996 goto do_cp0;
14997 case TLBWR:
14998 mips32_op = OPC_TLBWR;
14999 goto do_cp0;
15000 case TLBINV:
15001 mips32_op = OPC_TLBINV;
15002 goto do_cp0;
15003 case TLBINVF:
15004 mips32_op = OPC_TLBINVF;
15005 goto do_cp0;
15006 case WAIT:
15007 mips32_op = OPC_WAIT;
15008 goto do_cp0;
15009 case DERET:
15010 mips32_op = OPC_DERET;
15011 goto do_cp0;
15012 case ERET:
15013 mips32_op = OPC_ERET;
15014 do_cp0:
15015 gen_cp0(env, ctx, mips32_op, rt, rs);
15016 break;
15017 default:
15018 goto pool32axf_invalid;
15020 break;
15021 case 0x1d:
15022 switch (minor) {
15023 case DI:
15024 check_cp0_enabled(ctx);
15026 TCGv t0 = tcg_temp_new();
15028 save_cpu_state(ctx, 1);
15029 gen_helper_di(t0, cpu_env);
15030 gen_store_gpr(t0, rs);
15032 * Stop translation as we may have switched the execution
15033 * mode.
15035 ctx->base.is_jmp = DISAS_STOP;
15036 tcg_temp_free(t0);
15038 break;
15039 case EI:
15040 check_cp0_enabled(ctx);
15042 TCGv t0 = tcg_temp_new();
15044 save_cpu_state(ctx, 1);
15045 gen_helper_ei(t0, cpu_env);
15046 gen_store_gpr(t0, rs);
15048 * DISAS_STOP isn't sufficient, we need to ensure we break out
15049 * of translated code to check for pending interrupts.
15051 gen_save_pc(ctx->base.pc_next + 4);
15052 ctx->base.is_jmp = DISAS_EXIT;
15053 tcg_temp_free(t0);
15055 break;
15056 default:
15057 goto pool32axf_invalid;
15059 break;
15060 #endif
15061 case 0x2d:
15062 switch (minor) {
15063 case SYNC:
15064 gen_sync(extract32(ctx->opcode, 16, 5));
15065 break;
15066 case SYSCALL:
15067 generate_exception_end(ctx, EXCP_SYSCALL);
15068 break;
15069 case SDBBP:
15070 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15071 gen_helper_do_semihosting(cpu_env);
15072 } else {
15073 check_insn(ctx, ISA_MIPS_R1);
15074 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15075 gen_reserved_instruction(ctx);
15076 } else {
15077 generate_exception_end(ctx, EXCP_DBp);
15080 break;
15081 default:
15082 goto pool32axf_invalid;
15084 break;
15085 case 0x01:
15086 switch (minor & 3) {
15087 case MFHI_ACC:
15088 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15089 break;
15090 case MFLO_ACC:
15091 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15092 break;
15093 case MTHI_ACC:
15094 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15095 break;
15096 case MTLO_ACC:
15097 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15098 break;
15099 default:
15100 goto pool32axf_invalid;
15102 break;
15103 case 0x35:
15104 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15105 switch (minor) {
15106 case MFHI32:
15107 gen_HILO(ctx, OPC_MFHI, 0, rs);
15108 break;
15109 case MFLO32:
15110 gen_HILO(ctx, OPC_MFLO, 0, rs);
15111 break;
15112 case MTHI32:
15113 gen_HILO(ctx, OPC_MTHI, 0, rs);
15114 break;
15115 case MTLO32:
15116 gen_HILO(ctx, OPC_MTLO, 0, rs);
15117 break;
15118 default:
15119 goto pool32axf_invalid;
15121 break;
15122 default:
15123 pool32axf_invalid:
15124 MIPS_INVAL("pool32axf");
15125 gen_reserved_instruction(ctx);
15126 break;
15131 * Values for microMIPS fmt field. Variable-width, depending on which
15132 * formats the instruction supports.
15134 enum {
15135 FMT_SD_S = 0,
15136 FMT_SD_D = 1,
15138 FMT_SDPS_S = 0,
15139 FMT_SDPS_D = 1,
15140 FMT_SDPS_PS = 2,
15142 FMT_SWL_S = 0,
15143 FMT_SWL_W = 1,
15144 FMT_SWL_L = 2,
15146 FMT_DWL_D = 0,
15147 FMT_DWL_W = 1,
15148 FMT_DWL_L = 2
15151 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15153 int extension = (ctx->opcode >> 6) & 0x3ff;
15154 uint32_t mips32_op;
15156 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
15157 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
15158 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
15160 switch (extension) {
15161 case FLOAT_1BIT_FMT(CFC1, 0):
15162 mips32_op = OPC_CFC1;
15163 goto do_cp1;
15164 case FLOAT_1BIT_FMT(CTC1, 0):
15165 mips32_op = OPC_CTC1;
15166 goto do_cp1;
15167 case FLOAT_1BIT_FMT(MFC1, 0):
15168 mips32_op = OPC_MFC1;
15169 goto do_cp1;
15170 case FLOAT_1BIT_FMT(MTC1, 0):
15171 mips32_op = OPC_MTC1;
15172 goto do_cp1;
15173 case FLOAT_1BIT_FMT(MFHC1, 0):
15174 mips32_op = OPC_MFHC1;
15175 goto do_cp1;
15176 case FLOAT_1BIT_FMT(MTHC1, 0):
15177 mips32_op = OPC_MTHC1;
15178 do_cp1:
15179 gen_cp1(ctx, mips32_op, rt, rs);
15180 break;
15182 /* Reciprocal square root */
15183 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15184 mips32_op = OPC_RSQRT_S;
15185 goto do_unaryfp;
15186 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15187 mips32_op = OPC_RSQRT_D;
15188 goto do_unaryfp;
15190 /* Square root */
15191 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15192 mips32_op = OPC_SQRT_S;
15193 goto do_unaryfp;
15194 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15195 mips32_op = OPC_SQRT_D;
15196 goto do_unaryfp;
15198 /* Reciprocal */
15199 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15200 mips32_op = OPC_RECIP_S;
15201 goto do_unaryfp;
15202 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15203 mips32_op = OPC_RECIP_D;
15204 goto do_unaryfp;
15206 /* Floor */
15207 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15208 mips32_op = OPC_FLOOR_L_S;
15209 goto do_unaryfp;
15210 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15211 mips32_op = OPC_FLOOR_L_D;
15212 goto do_unaryfp;
15213 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15214 mips32_op = OPC_FLOOR_W_S;
15215 goto do_unaryfp;
15216 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15217 mips32_op = OPC_FLOOR_W_D;
15218 goto do_unaryfp;
15220 /* Ceiling */
15221 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15222 mips32_op = OPC_CEIL_L_S;
15223 goto do_unaryfp;
15224 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15225 mips32_op = OPC_CEIL_L_D;
15226 goto do_unaryfp;
15227 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15228 mips32_op = OPC_CEIL_W_S;
15229 goto do_unaryfp;
15230 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15231 mips32_op = OPC_CEIL_W_D;
15232 goto do_unaryfp;
15234 /* Truncation */
15235 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15236 mips32_op = OPC_TRUNC_L_S;
15237 goto do_unaryfp;
15238 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15239 mips32_op = OPC_TRUNC_L_D;
15240 goto do_unaryfp;
15241 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15242 mips32_op = OPC_TRUNC_W_S;
15243 goto do_unaryfp;
15244 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15245 mips32_op = OPC_TRUNC_W_D;
15246 goto do_unaryfp;
15248 /* Round */
15249 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15250 mips32_op = OPC_ROUND_L_S;
15251 goto do_unaryfp;
15252 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15253 mips32_op = OPC_ROUND_L_D;
15254 goto do_unaryfp;
15255 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15256 mips32_op = OPC_ROUND_W_S;
15257 goto do_unaryfp;
15258 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15259 mips32_op = OPC_ROUND_W_D;
15260 goto do_unaryfp;
15262 /* Integer to floating-point conversion */
15263 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15264 mips32_op = OPC_CVT_L_S;
15265 goto do_unaryfp;
15266 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15267 mips32_op = OPC_CVT_L_D;
15268 goto do_unaryfp;
15269 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15270 mips32_op = OPC_CVT_W_S;
15271 goto do_unaryfp;
15272 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15273 mips32_op = OPC_CVT_W_D;
15274 goto do_unaryfp;
15276 /* Paired-foo conversions */
15277 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15278 mips32_op = OPC_CVT_S_PL;
15279 goto do_unaryfp;
15280 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15281 mips32_op = OPC_CVT_S_PU;
15282 goto do_unaryfp;
15283 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15284 mips32_op = OPC_CVT_PW_PS;
15285 goto do_unaryfp;
15286 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15287 mips32_op = OPC_CVT_PS_PW;
15288 goto do_unaryfp;
15290 /* Floating-point moves */
15291 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15292 mips32_op = OPC_MOV_S;
15293 goto do_unaryfp;
15294 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15295 mips32_op = OPC_MOV_D;
15296 goto do_unaryfp;
15297 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15298 mips32_op = OPC_MOV_PS;
15299 goto do_unaryfp;
15301 /* Absolute value */
15302 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15303 mips32_op = OPC_ABS_S;
15304 goto do_unaryfp;
15305 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15306 mips32_op = OPC_ABS_D;
15307 goto do_unaryfp;
15308 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15309 mips32_op = OPC_ABS_PS;
15310 goto do_unaryfp;
15312 /* Negation */
15313 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15314 mips32_op = OPC_NEG_S;
15315 goto do_unaryfp;
15316 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15317 mips32_op = OPC_NEG_D;
15318 goto do_unaryfp;
15319 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15320 mips32_op = OPC_NEG_PS;
15321 goto do_unaryfp;
15323 /* Reciprocal square root step */
15324 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15325 mips32_op = OPC_RSQRT1_S;
15326 goto do_unaryfp;
15327 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15328 mips32_op = OPC_RSQRT1_D;
15329 goto do_unaryfp;
15330 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15331 mips32_op = OPC_RSQRT1_PS;
15332 goto do_unaryfp;
15334 /* Reciprocal step */
15335 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15336 mips32_op = OPC_RECIP1_S;
15337 goto do_unaryfp;
15338 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15339 mips32_op = OPC_RECIP1_S;
15340 goto do_unaryfp;
15341 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15342 mips32_op = OPC_RECIP1_PS;
15343 goto do_unaryfp;
15345 /* Conversions from double */
15346 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15347 mips32_op = OPC_CVT_D_S;
15348 goto do_unaryfp;
15349 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15350 mips32_op = OPC_CVT_D_W;
15351 goto do_unaryfp;
15352 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15353 mips32_op = OPC_CVT_D_L;
15354 goto do_unaryfp;
15356 /* Conversions from single */
15357 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15358 mips32_op = OPC_CVT_S_D;
15359 goto do_unaryfp;
15360 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15361 mips32_op = OPC_CVT_S_W;
15362 goto do_unaryfp;
15363 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15364 mips32_op = OPC_CVT_S_L;
15365 do_unaryfp:
15366 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15367 break;
15369 /* Conditional moves on floating-point codes */
15370 case COND_FLOAT_MOV(MOVT, 0):
15371 case COND_FLOAT_MOV(MOVT, 1):
15372 case COND_FLOAT_MOV(MOVT, 2):
15373 case COND_FLOAT_MOV(MOVT, 3):
15374 case COND_FLOAT_MOV(MOVT, 4):
15375 case COND_FLOAT_MOV(MOVT, 5):
15376 case COND_FLOAT_MOV(MOVT, 6):
15377 case COND_FLOAT_MOV(MOVT, 7):
15378 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15379 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15380 break;
15381 case COND_FLOAT_MOV(MOVF, 0):
15382 case COND_FLOAT_MOV(MOVF, 1):
15383 case COND_FLOAT_MOV(MOVF, 2):
15384 case COND_FLOAT_MOV(MOVF, 3):
15385 case COND_FLOAT_MOV(MOVF, 4):
15386 case COND_FLOAT_MOV(MOVF, 5):
15387 case COND_FLOAT_MOV(MOVF, 6):
15388 case COND_FLOAT_MOV(MOVF, 7):
15389 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15390 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15391 break;
15392 default:
15393 MIPS_INVAL("pool32fxf");
15394 gen_reserved_instruction(ctx);
15395 break;
15399 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15401 int32_t offset;
15402 uint16_t insn;
15403 int rt, rs, rd, rr;
15404 int16_t imm;
15405 uint32_t op, minor, minor2, mips32_op;
15406 uint32_t cond, fmt, cc;
15408 insn = translator_lduw(env, ctx->base.pc_next + 2);
15409 ctx->opcode = (ctx->opcode << 16) | insn;
15411 rt = (ctx->opcode >> 21) & 0x1f;
15412 rs = (ctx->opcode >> 16) & 0x1f;
15413 rd = (ctx->opcode >> 11) & 0x1f;
15414 rr = (ctx->opcode >> 6) & 0x1f;
15415 imm = (int16_t) ctx->opcode;
15417 op = (ctx->opcode >> 26) & 0x3f;
15418 switch (op) {
15419 case POOL32A:
15420 minor = ctx->opcode & 0x3f;
15421 switch (minor) {
15422 case 0x00:
15423 minor = (ctx->opcode >> 6) & 0xf;
15424 switch (minor) {
15425 case SLL32:
15426 mips32_op = OPC_SLL;
15427 goto do_shifti;
15428 case SRA:
15429 mips32_op = OPC_SRA;
15430 goto do_shifti;
15431 case SRL32:
15432 mips32_op = OPC_SRL;
15433 goto do_shifti;
15434 case ROTR:
15435 mips32_op = OPC_ROTR;
15436 do_shifti:
15437 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15438 break;
15439 case SELEQZ:
15440 check_insn(ctx, ISA_MIPS_R6);
15441 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15442 break;
15443 case SELNEZ:
15444 check_insn(ctx, ISA_MIPS_R6);
15445 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15446 break;
15447 case R6_RDHWR:
15448 check_insn(ctx, ISA_MIPS_R6);
15449 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15450 break;
15451 default:
15452 goto pool32a_invalid;
15454 break;
15455 case 0x10:
15456 minor = (ctx->opcode >> 6) & 0xf;
15457 switch (minor) {
15458 /* Arithmetic */
15459 case ADD:
15460 mips32_op = OPC_ADD;
15461 goto do_arith;
15462 case ADDU32:
15463 mips32_op = OPC_ADDU;
15464 goto do_arith;
15465 case SUB:
15466 mips32_op = OPC_SUB;
15467 goto do_arith;
15468 case SUBU32:
15469 mips32_op = OPC_SUBU;
15470 goto do_arith;
15471 case MUL:
15472 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15473 mips32_op = OPC_MUL;
15474 do_arith:
15475 gen_arith(ctx, mips32_op, rd, rs, rt);
15476 break;
15477 /* Shifts */
15478 case SLLV:
15479 mips32_op = OPC_SLLV;
15480 goto do_shift;
15481 case SRLV:
15482 mips32_op = OPC_SRLV;
15483 goto do_shift;
15484 case SRAV:
15485 mips32_op = OPC_SRAV;
15486 goto do_shift;
15487 case ROTRV:
15488 mips32_op = OPC_ROTRV;
15489 do_shift:
15490 gen_shift(ctx, mips32_op, rd, rs, rt);
15491 break;
15492 /* Logical operations */
15493 case AND:
15494 mips32_op = OPC_AND;
15495 goto do_logic;
15496 case OR32:
15497 mips32_op = OPC_OR;
15498 goto do_logic;
15499 case NOR:
15500 mips32_op = OPC_NOR;
15501 goto do_logic;
15502 case XOR32:
15503 mips32_op = OPC_XOR;
15504 do_logic:
15505 gen_logic(ctx, mips32_op, rd, rs, rt);
15506 break;
15507 /* Set less than */
15508 case SLT:
15509 mips32_op = OPC_SLT;
15510 goto do_slt;
15511 case SLTU:
15512 mips32_op = OPC_SLTU;
15513 do_slt:
15514 gen_slt(ctx, mips32_op, rd, rs, rt);
15515 break;
15516 default:
15517 goto pool32a_invalid;
15519 break;
15520 case 0x18:
15521 minor = (ctx->opcode >> 6) & 0xf;
15522 switch (minor) {
15523 /* Conditional moves */
15524 case MOVN: /* MUL */
15525 if (ctx->insn_flags & ISA_MIPS_R6) {
15526 /* MUL */
15527 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15528 } else {
15529 /* MOVN */
15530 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15532 break;
15533 case MOVZ: /* MUH */
15534 if (ctx->insn_flags & ISA_MIPS_R6) {
15535 /* MUH */
15536 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15537 } else {
15538 /* MOVZ */
15539 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15541 break;
15542 case MULU:
15543 check_insn(ctx, ISA_MIPS_R6);
15544 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15545 break;
15546 case MUHU:
15547 check_insn(ctx, ISA_MIPS_R6);
15548 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15549 break;
15550 case LWXS: /* DIV */
15551 if (ctx->insn_flags & ISA_MIPS_R6) {
15552 /* DIV */
15553 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15554 } else {
15555 /* LWXS */
15556 gen_ldxs(ctx, rs, rt, rd);
15558 break;
15559 case MOD:
15560 check_insn(ctx, ISA_MIPS_R6);
15561 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15562 break;
15563 case R6_DIVU:
15564 check_insn(ctx, ISA_MIPS_R6);
15565 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15566 break;
15567 case MODU:
15568 check_insn(ctx, ISA_MIPS_R6);
15569 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15570 break;
15571 default:
15572 goto pool32a_invalid;
15574 break;
15575 case INS:
15576 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15577 return;
15578 case LSA:
15579 check_insn(ctx, ISA_MIPS_R6);
15580 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2));
15581 break;
15582 case ALIGN:
15583 check_insn(ctx, ISA_MIPS_R6);
15584 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15585 break;
15586 case EXT:
15587 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15588 return;
15589 case POOL32AXF:
15590 gen_pool32axf(env, ctx, rt, rs);
15591 break;
15592 case BREAK32:
15593 generate_exception_end(ctx, EXCP_BREAK);
15594 break;
15595 case SIGRIE:
15596 check_insn(ctx, ISA_MIPS_R6);
15597 gen_reserved_instruction(ctx);
15598 break;
15599 default:
15600 pool32a_invalid:
15601 MIPS_INVAL("pool32a");
15602 gen_reserved_instruction(ctx);
15603 break;
15605 break;
15606 case POOL32B:
15607 minor = (ctx->opcode >> 12) & 0xf;
15608 switch (minor) {
15609 case CACHE:
15610 check_cp0_enabled(ctx);
15611 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15612 gen_cache_operation(ctx, rt, rs, imm);
15614 break;
15615 case LWC2:
15616 case SWC2:
15617 /* COP2: Not implemented. */
15618 generate_exception_err(ctx, EXCP_CpU, 2);
15619 break;
15620 #ifdef TARGET_MIPS64
15621 case LDP:
15622 case SDP:
15623 check_insn(ctx, ISA_MIPS3);
15624 check_mips_64(ctx);
15625 #endif
15626 /* fall through */
15627 case LWP:
15628 case SWP:
15629 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15630 break;
15631 #ifdef TARGET_MIPS64
15632 case LDM:
15633 case SDM:
15634 check_insn(ctx, ISA_MIPS3);
15635 check_mips_64(ctx);
15636 #endif
15637 /* fall through */
15638 case LWM32:
15639 case SWM32:
15640 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15641 break;
15642 default:
15643 MIPS_INVAL("pool32b");
15644 gen_reserved_instruction(ctx);
15645 break;
15647 break;
15648 case POOL32F:
15649 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15650 minor = ctx->opcode & 0x3f;
15651 check_cp1_enabled(ctx);
15652 switch (minor) {
15653 case ALNV_PS:
15654 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15655 mips32_op = OPC_ALNV_PS;
15656 goto do_madd;
15657 case MADD_S:
15658 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15659 mips32_op = OPC_MADD_S;
15660 goto do_madd;
15661 case MADD_D:
15662 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15663 mips32_op = OPC_MADD_D;
15664 goto do_madd;
15665 case MADD_PS:
15666 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15667 mips32_op = OPC_MADD_PS;
15668 goto do_madd;
15669 case MSUB_S:
15670 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15671 mips32_op = OPC_MSUB_S;
15672 goto do_madd;
15673 case MSUB_D:
15674 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15675 mips32_op = OPC_MSUB_D;
15676 goto do_madd;
15677 case MSUB_PS:
15678 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15679 mips32_op = OPC_MSUB_PS;
15680 goto do_madd;
15681 case NMADD_S:
15682 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15683 mips32_op = OPC_NMADD_S;
15684 goto do_madd;
15685 case NMADD_D:
15686 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15687 mips32_op = OPC_NMADD_D;
15688 goto do_madd;
15689 case NMADD_PS:
15690 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15691 mips32_op = OPC_NMADD_PS;
15692 goto do_madd;
15693 case NMSUB_S:
15694 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15695 mips32_op = OPC_NMSUB_S;
15696 goto do_madd;
15697 case NMSUB_D:
15698 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15699 mips32_op = OPC_NMSUB_D;
15700 goto do_madd;
15701 case NMSUB_PS:
15702 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15703 mips32_op = OPC_NMSUB_PS;
15704 do_madd:
15705 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15706 break;
15707 case CABS_COND_FMT:
15708 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15709 cond = (ctx->opcode >> 6) & 0xf;
15710 cc = (ctx->opcode >> 13) & 0x7;
15711 fmt = (ctx->opcode >> 10) & 0x3;
15712 switch (fmt) {
15713 case 0x0:
15714 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15715 break;
15716 case 0x1:
15717 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15718 break;
15719 case 0x2:
15720 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15721 break;
15722 default:
15723 goto pool32f_invalid;
15725 break;
15726 case C_COND_FMT:
15727 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15728 cond = (ctx->opcode >> 6) & 0xf;
15729 cc = (ctx->opcode >> 13) & 0x7;
15730 fmt = (ctx->opcode >> 10) & 0x3;
15731 switch (fmt) {
15732 case 0x0:
15733 gen_cmp_s(ctx, cond, rt, rs, cc);
15734 break;
15735 case 0x1:
15736 gen_cmp_d(ctx, cond, rt, rs, cc);
15737 break;
15738 case 0x2:
15739 gen_cmp_ps(ctx, cond, rt, rs, cc);
15740 break;
15741 default:
15742 goto pool32f_invalid;
15744 break;
15745 case CMP_CONDN_S:
15746 check_insn(ctx, ISA_MIPS_R6);
15747 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15748 break;
15749 case CMP_CONDN_D:
15750 check_insn(ctx, ISA_MIPS_R6);
15751 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15752 break;
15753 case POOL32FXF:
15754 gen_pool32fxf(ctx, rt, rs);
15755 break;
15756 case 0x00:
15757 /* PLL foo */
15758 switch ((ctx->opcode >> 6) & 0x7) {
15759 case PLL_PS:
15760 mips32_op = OPC_PLL_PS;
15761 goto do_ps;
15762 case PLU_PS:
15763 mips32_op = OPC_PLU_PS;
15764 goto do_ps;
15765 case PUL_PS:
15766 mips32_op = OPC_PUL_PS;
15767 goto do_ps;
15768 case PUU_PS:
15769 mips32_op = OPC_PUU_PS;
15770 goto do_ps;
15771 case CVT_PS_S:
15772 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15773 mips32_op = OPC_CVT_PS_S;
15774 do_ps:
15775 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15776 break;
15777 default:
15778 goto pool32f_invalid;
15780 break;
15781 case MIN_FMT:
15782 check_insn(ctx, ISA_MIPS_R6);
15783 switch ((ctx->opcode >> 9) & 0x3) {
15784 case FMT_SDPS_S:
15785 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15786 break;
15787 case FMT_SDPS_D:
15788 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15789 break;
15790 default:
15791 goto pool32f_invalid;
15793 break;
15794 case 0x08:
15795 /* [LS][WDU]XC1 */
15796 switch ((ctx->opcode >> 6) & 0x7) {
15797 case LWXC1:
15798 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15799 mips32_op = OPC_LWXC1;
15800 goto do_ldst_cp1;
15801 case SWXC1:
15802 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15803 mips32_op = OPC_SWXC1;
15804 goto do_ldst_cp1;
15805 case LDXC1:
15806 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15807 mips32_op = OPC_LDXC1;
15808 goto do_ldst_cp1;
15809 case SDXC1:
15810 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15811 mips32_op = OPC_SDXC1;
15812 goto do_ldst_cp1;
15813 case LUXC1:
15814 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15815 mips32_op = OPC_LUXC1;
15816 goto do_ldst_cp1;
15817 case SUXC1:
15818 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15819 mips32_op = OPC_SUXC1;
15820 do_ldst_cp1:
15821 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15822 break;
15823 default:
15824 goto pool32f_invalid;
15826 break;
15827 case MAX_FMT:
15828 check_insn(ctx, ISA_MIPS_R6);
15829 switch ((ctx->opcode >> 9) & 0x3) {
15830 case FMT_SDPS_S:
15831 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
15832 break;
15833 case FMT_SDPS_D:
15834 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
15835 break;
15836 default:
15837 goto pool32f_invalid;
15839 break;
15840 case 0x18:
15841 /* 3D insns */
15842 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15843 fmt = (ctx->opcode >> 9) & 0x3;
15844 switch ((ctx->opcode >> 6) & 0x7) {
15845 case RSQRT2_FMT:
15846 switch (fmt) {
15847 case FMT_SDPS_S:
15848 mips32_op = OPC_RSQRT2_S;
15849 goto do_3d;
15850 case FMT_SDPS_D:
15851 mips32_op = OPC_RSQRT2_D;
15852 goto do_3d;
15853 case FMT_SDPS_PS:
15854 mips32_op = OPC_RSQRT2_PS;
15855 goto do_3d;
15856 default:
15857 goto pool32f_invalid;
15859 break;
15860 case RECIP2_FMT:
15861 switch (fmt) {
15862 case FMT_SDPS_S:
15863 mips32_op = OPC_RECIP2_S;
15864 goto do_3d;
15865 case FMT_SDPS_D:
15866 mips32_op = OPC_RECIP2_D;
15867 goto do_3d;
15868 case FMT_SDPS_PS:
15869 mips32_op = OPC_RECIP2_PS;
15870 goto do_3d;
15871 default:
15872 goto pool32f_invalid;
15874 break;
15875 case ADDR_PS:
15876 mips32_op = OPC_ADDR_PS;
15877 goto do_3d;
15878 case MULR_PS:
15879 mips32_op = OPC_MULR_PS;
15880 do_3d:
15881 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15882 break;
15883 default:
15884 goto pool32f_invalid;
15886 break;
15887 case 0x20:
15888 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
15889 cc = (ctx->opcode >> 13) & 0x7;
15890 fmt = (ctx->opcode >> 9) & 0x3;
15891 switch ((ctx->opcode >> 6) & 0x7) {
15892 case MOVF_FMT: /* RINT_FMT */
15893 if (ctx->insn_flags & ISA_MIPS_R6) {
15894 /* RINT_FMT */
15895 switch (fmt) {
15896 case FMT_SDPS_S:
15897 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
15898 break;
15899 case FMT_SDPS_D:
15900 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
15901 break;
15902 default:
15903 goto pool32f_invalid;
15905 } else {
15906 /* MOVF_FMT */
15907 switch (fmt) {
15908 case FMT_SDPS_S:
15909 gen_movcf_s(ctx, rs, rt, cc, 0);
15910 break;
15911 case FMT_SDPS_D:
15912 gen_movcf_d(ctx, rs, rt, cc, 0);
15913 break;
15914 case FMT_SDPS_PS:
15915 check_ps(ctx);
15916 gen_movcf_ps(ctx, rs, rt, cc, 0);
15917 break;
15918 default:
15919 goto pool32f_invalid;
15922 break;
15923 case MOVT_FMT: /* CLASS_FMT */
15924 if (ctx->insn_flags & ISA_MIPS_R6) {
15925 /* CLASS_FMT */
15926 switch (fmt) {
15927 case FMT_SDPS_S:
15928 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
15929 break;
15930 case FMT_SDPS_D:
15931 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
15932 break;
15933 default:
15934 goto pool32f_invalid;
15936 } else {
15937 /* MOVT_FMT */
15938 switch (fmt) {
15939 case FMT_SDPS_S:
15940 gen_movcf_s(ctx, rs, rt, cc, 1);
15941 break;
15942 case FMT_SDPS_D:
15943 gen_movcf_d(ctx, rs, rt, cc, 1);
15944 break;
15945 case FMT_SDPS_PS:
15946 check_ps(ctx);
15947 gen_movcf_ps(ctx, rs, rt, cc, 1);
15948 break;
15949 default:
15950 goto pool32f_invalid;
15953 break;
15954 case PREFX:
15955 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15956 break;
15957 default:
15958 goto pool32f_invalid;
15960 break;
15961 #define FINSN_3ARG_SDPS(prfx) \
15962 switch ((ctx->opcode >> 8) & 0x3) { \
15963 case FMT_SDPS_S: \
15964 mips32_op = OPC_##prfx##_S; \
15965 goto do_fpop; \
15966 case FMT_SDPS_D: \
15967 mips32_op = OPC_##prfx##_D; \
15968 goto do_fpop; \
15969 case FMT_SDPS_PS: \
15970 check_ps(ctx); \
15971 mips32_op = OPC_##prfx##_PS; \
15972 goto do_fpop; \
15973 default: \
15974 goto pool32f_invalid; \
15976 case MINA_FMT:
15977 check_insn(ctx, ISA_MIPS_R6);
15978 switch ((ctx->opcode >> 9) & 0x3) {
15979 case FMT_SDPS_S:
15980 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
15981 break;
15982 case FMT_SDPS_D:
15983 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
15984 break;
15985 default:
15986 goto pool32f_invalid;
15988 break;
15989 case MAXA_FMT:
15990 check_insn(ctx, ISA_MIPS_R6);
15991 switch ((ctx->opcode >> 9) & 0x3) {
15992 case FMT_SDPS_S:
15993 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
15994 break;
15995 case FMT_SDPS_D:
15996 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
15997 break;
15998 default:
15999 goto pool32f_invalid;
16001 break;
16002 case 0x30:
16003 /* regular FP ops */
16004 switch ((ctx->opcode >> 6) & 0x3) {
16005 case ADD_FMT:
16006 FINSN_3ARG_SDPS(ADD);
16007 break;
16008 case SUB_FMT:
16009 FINSN_3ARG_SDPS(SUB);
16010 break;
16011 case MUL_FMT:
16012 FINSN_3ARG_SDPS(MUL);
16013 break;
16014 case DIV_FMT:
16015 fmt = (ctx->opcode >> 8) & 0x3;
16016 if (fmt == 1) {
16017 mips32_op = OPC_DIV_D;
16018 } else if (fmt == 0) {
16019 mips32_op = OPC_DIV_S;
16020 } else {
16021 goto pool32f_invalid;
16023 goto do_fpop;
16024 default:
16025 goto pool32f_invalid;
16027 break;
16028 case 0x38:
16029 /* cmovs */
16030 switch ((ctx->opcode >> 6) & 0x7) {
16031 case MOVN_FMT: /* SELEQZ_FMT */
16032 if (ctx->insn_flags & ISA_MIPS_R6) {
16033 /* SELEQZ_FMT */
16034 switch ((ctx->opcode >> 9) & 0x3) {
16035 case FMT_SDPS_S:
16036 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16037 break;
16038 case FMT_SDPS_D:
16039 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16040 break;
16041 default:
16042 goto pool32f_invalid;
16044 } else {
16045 /* MOVN_FMT */
16046 FINSN_3ARG_SDPS(MOVN);
16048 break;
16049 case MOVN_FMT_04:
16050 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16051 FINSN_3ARG_SDPS(MOVN);
16052 break;
16053 case MOVZ_FMT: /* SELNEZ_FMT */
16054 if (ctx->insn_flags & ISA_MIPS_R6) {
16055 /* SELNEZ_FMT */
16056 switch ((ctx->opcode >> 9) & 0x3) {
16057 case FMT_SDPS_S:
16058 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16059 break;
16060 case FMT_SDPS_D:
16061 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16062 break;
16063 default:
16064 goto pool32f_invalid;
16066 } else {
16067 /* MOVZ_FMT */
16068 FINSN_3ARG_SDPS(MOVZ);
16070 break;
16071 case MOVZ_FMT_05:
16072 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16073 FINSN_3ARG_SDPS(MOVZ);
16074 break;
16075 case SEL_FMT:
16076 check_insn(ctx, ISA_MIPS_R6);
16077 switch ((ctx->opcode >> 9) & 0x3) {
16078 case FMT_SDPS_S:
16079 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16080 break;
16081 case FMT_SDPS_D:
16082 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16083 break;
16084 default:
16085 goto pool32f_invalid;
16087 break;
16088 case MADDF_FMT:
16089 check_insn(ctx, ISA_MIPS_R6);
16090 switch ((ctx->opcode >> 9) & 0x3) {
16091 case FMT_SDPS_S:
16092 mips32_op = OPC_MADDF_S;
16093 goto do_fpop;
16094 case FMT_SDPS_D:
16095 mips32_op = OPC_MADDF_D;
16096 goto do_fpop;
16097 default:
16098 goto pool32f_invalid;
16100 break;
16101 case MSUBF_FMT:
16102 check_insn(ctx, ISA_MIPS_R6);
16103 switch ((ctx->opcode >> 9) & 0x3) {
16104 case FMT_SDPS_S:
16105 mips32_op = OPC_MSUBF_S;
16106 goto do_fpop;
16107 case FMT_SDPS_D:
16108 mips32_op = OPC_MSUBF_D;
16109 goto do_fpop;
16110 default:
16111 goto pool32f_invalid;
16113 break;
16114 default:
16115 goto pool32f_invalid;
16117 break;
16118 do_fpop:
16119 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16120 break;
16121 default:
16122 pool32f_invalid:
16123 MIPS_INVAL("pool32f");
16124 gen_reserved_instruction(ctx);
16125 break;
16127 } else {
16128 generate_exception_err(ctx, EXCP_CpU, 1);
16130 break;
16131 case POOL32I:
16132 minor = (ctx->opcode >> 21) & 0x1f;
16133 switch (minor) {
16134 case BLTZ:
16135 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16136 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16137 break;
16138 case BLTZAL:
16139 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16140 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16141 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16142 break;
16143 case BLTZALS:
16144 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16145 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16146 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16147 break;
16148 case BGEZ:
16149 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16150 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16151 break;
16152 case BGEZAL:
16153 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16154 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16155 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16156 break;
16157 case BGEZALS:
16158 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16159 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16160 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16161 break;
16162 case BLEZ:
16163 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16164 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16165 break;
16166 case BGTZ:
16167 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16168 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16169 break;
16171 /* Traps */
16172 case TLTI: /* BC1EQZC */
16173 if (ctx->insn_flags & ISA_MIPS_R6) {
16174 /* BC1EQZC */
16175 check_cp1_enabled(ctx);
16176 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16177 } else {
16178 /* TLTI */
16179 mips32_op = OPC_TLTI;
16180 goto do_trapi;
16182 break;
16183 case TGEI: /* BC1NEZC */
16184 if (ctx->insn_flags & ISA_MIPS_R6) {
16185 /* BC1NEZC */
16186 check_cp1_enabled(ctx);
16187 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16188 } else {
16189 /* TGEI */
16190 mips32_op = OPC_TGEI;
16191 goto do_trapi;
16193 break;
16194 case TLTIU:
16195 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16196 mips32_op = OPC_TLTIU;
16197 goto do_trapi;
16198 case TGEIU:
16199 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16200 mips32_op = OPC_TGEIU;
16201 goto do_trapi;
16202 case TNEI: /* SYNCI */
16203 if (ctx->insn_flags & ISA_MIPS_R6) {
16204 /* SYNCI */
16206 * Break the TB to be able to sync copied instructions
16207 * immediately.
16209 ctx->base.is_jmp = DISAS_STOP;
16210 } else {
16211 /* TNEI */
16212 mips32_op = OPC_TNEI;
16213 goto do_trapi;
16215 break;
16216 case TEQI:
16217 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16218 mips32_op = OPC_TEQI;
16219 do_trapi:
16220 gen_trap(ctx, mips32_op, rs, -1, imm);
16221 break;
16223 case BNEZC:
16224 case BEQZC:
16225 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16226 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16227 4, rs, 0, imm << 1, 0);
16229 * Compact branches don't have a delay slot, so just let
16230 * the normal delay slot handling take us to the branch
16231 * target.
16233 break;
16234 case LUI:
16235 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16236 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16237 break;
16238 case SYNCI:
16239 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16241 * Break the TB to be able to sync copied instructions
16242 * immediately.
16244 ctx->base.is_jmp = DISAS_STOP;
16245 break;
16246 case BC2F:
16247 case BC2T:
16248 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16249 /* COP2: Not implemented. */
16250 generate_exception_err(ctx, EXCP_CpU, 2);
16251 break;
16252 case BC1F:
16253 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16254 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16255 goto do_cp1branch;
16256 case BC1T:
16257 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16258 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16259 goto do_cp1branch;
16260 case BC1ANY4F:
16261 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16262 mips32_op = OPC_BC1FANY4;
16263 goto do_cp1mips3d;
16264 case BC1ANY4T:
16265 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16266 mips32_op = OPC_BC1TANY4;
16267 do_cp1mips3d:
16268 check_cop1x(ctx);
16269 check_insn(ctx, ASE_MIPS3D);
16270 /* Fall through */
16271 do_cp1branch:
16272 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16273 check_cp1_enabled(ctx);
16274 gen_compute_branch1(ctx, mips32_op,
16275 (ctx->opcode >> 18) & 0x7, imm << 1);
16276 } else {
16277 generate_exception_err(ctx, EXCP_CpU, 1);
16279 break;
16280 case BPOSGE64:
16281 case BPOSGE32:
16282 /* MIPS DSP: not implemented */
16283 /* Fall through */
16284 default:
16285 MIPS_INVAL("pool32i");
16286 gen_reserved_instruction(ctx);
16287 break;
16289 break;
16290 case POOL32C:
16291 minor = (ctx->opcode >> 12) & 0xf;
16292 offset = sextract32(ctx->opcode, 0,
16293 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
16294 switch (minor) {
16295 case LWL:
16296 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16297 mips32_op = OPC_LWL;
16298 goto do_ld_lr;
16299 case SWL:
16300 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16301 mips32_op = OPC_SWL;
16302 goto do_st_lr;
16303 case LWR:
16304 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16305 mips32_op = OPC_LWR;
16306 goto do_ld_lr;
16307 case SWR:
16308 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16309 mips32_op = OPC_SWR;
16310 goto do_st_lr;
16311 #if defined(TARGET_MIPS64)
16312 case LDL:
16313 check_insn(ctx, ISA_MIPS3);
16314 check_mips_64(ctx);
16315 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16316 mips32_op = OPC_LDL;
16317 goto do_ld_lr;
16318 case SDL:
16319 check_insn(ctx, ISA_MIPS3);
16320 check_mips_64(ctx);
16321 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16322 mips32_op = OPC_SDL;
16323 goto do_st_lr;
16324 case LDR:
16325 check_insn(ctx, ISA_MIPS3);
16326 check_mips_64(ctx);
16327 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16328 mips32_op = OPC_LDR;
16329 goto do_ld_lr;
16330 case SDR:
16331 check_insn(ctx, ISA_MIPS3);
16332 check_mips_64(ctx);
16333 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16334 mips32_op = OPC_SDR;
16335 goto do_st_lr;
16336 case LWU:
16337 check_insn(ctx, ISA_MIPS3);
16338 check_mips_64(ctx);
16339 mips32_op = OPC_LWU;
16340 goto do_ld_lr;
16341 case LLD:
16342 check_insn(ctx, ISA_MIPS3);
16343 check_mips_64(ctx);
16344 mips32_op = OPC_LLD;
16345 goto do_ld_lr;
16346 #endif
16347 case LL:
16348 mips32_op = OPC_LL;
16349 goto do_ld_lr;
16350 do_ld_lr:
16351 gen_ld(ctx, mips32_op, rt, rs, offset);
16352 break;
16353 do_st_lr:
16354 gen_st(ctx, mips32_op, rt, rs, offset);
16355 break;
16356 case SC:
16357 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
16358 break;
16359 #if defined(TARGET_MIPS64)
16360 case SCD:
16361 check_insn(ctx, ISA_MIPS3);
16362 check_mips_64(ctx);
16363 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
16364 break;
16365 #endif
16366 case LD_EVA:
16367 if (!ctx->eva) {
16368 MIPS_INVAL("pool32c ld-eva");
16369 gen_reserved_instruction(ctx);
16370 break;
16372 check_cp0_enabled(ctx);
16374 minor2 = (ctx->opcode >> 9) & 0x7;
16375 offset = sextract32(ctx->opcode, 0, 9);
16376 switch (minor2) {
16377 case LBUE:
16378 mips32_op = OPC_LBUE;
16379 goto do_ld_lr;
16380 case LHUE:
16381 mips32_op = OPC_LHUE;
16382 goto do_ld_lr;
16383 case LWLE:
16384 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16385 mips32_op = OPC_LWLE;
16386 goto do_ld_lr;
16387 case LWRE:
16388 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16389 mips32_op = OPC_LWRE;
16390 goto do_ld_lr;
16391 case LBE:
16392 mips32_op = OPC_LBE;
16393 goto do_ld_lr;
16394 case LHE:
16395 mips32_op = OPC_LHE;
16396 goto do_ld_lr;
16397 case LLE:
16398 mips32_op = OPC_LLE;
16399 goto do_ld_lr;
16400 case LWE:
16401 mips32_op = OPC_LWE;
16402 goto do_ld_lr;
16404 break;
16405 case ST_EVA:
16406 if (!ctx->eva) {
16407 MIPS_INVAL("pool32c st-eva");
16408 gen_reserved_instruction(ctx);
16409 break;
16411 check_cp0_enabled(ctx);
16413 minor2 = (ctx->opcode >> 9) & 0x7;
16414 offset = sextract32(ctx->opcode, 0, 9);
16415 switch (minor2) {
16416 case SWLE:
16417 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16418 mips32_op = OPC_SWLE;
16419 goto do_st_lr;
16420 case SWRE:
16421 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16422 mips32_op = OPC_SWRE;
16423 goto do_st_lr;
16424 case PREFE:
16425 /* Treat as no-op */
16426 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
16427 /* hint codes 24-31 are reserved and signal RI */
16428 generate_exception(ctx, EXCP_RI);
16430 break;
16431 case CACHEE:
16432 /* Treat as no-op */
16433 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16434 gen_cache_operation(ctx, rt, rs, offset);
16436 break;
16437 case SBE:
16438 mips32_op = OPC_SBE;
16439 goto do_st_lr;
16440 case SHE:
16441 mips32_op = OPC_SHE;
16442 goto do_st_lr;
16443 case SCE:
16444 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
16445 break;
16446 case SWE:
16447 mips32_op = OPC_SWE;
16448 goto do_st_lr;
16450 break;
16451 case PREF:
16452 /* Treat as no-op */
16453 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
16454 /* hint codes 24-31 are reserved and signal RI */
16455 generate_exception(ctx, EXCP_RI);
16457 break;
16458 default:
16459 MIPS_INVAL("pool32c");
16460 gen_reserved_instruction(ctx);
16461 break;
16463 break;
16464 case ADDI32: /* AUI, LUI */
16465 if (ctx->insn_flags & ISA_MIPS_R6) {
16466 /* AUI, LUI */
16467 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16468 } else {
16469 /* ADDI32 */
16470 mips32_op = OPC_ADDI;
16471 goto do_addi;
16473 break;
16474 case ADDIU32:
16475 mips32_op = OPC_ADDIU;
16476 do_addi:
16477 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16478 break;
16480 /* Logical operations */
16481 case ORI32:
16482 mips32_op = OPC_ORI;
16483 goto do_logici;
16484 case XORI32:
16485 mips32_op = OPC_XORI;
16486 goto do_logici;
16487 case ANDI32:
16488 mips32_op = OPC_ANDI;
16489 do_logici:
16490 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16491 break;
16493 /* Set less than immediate */
16494 case SLTI32:
16495 mips32_op = OPC_SLTI;
16496 goto do_slti;
16497 case SLTIU32:
16498 mips32_op = OPC_SLTIU;
16499 do_slti:
16500 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16501 break;
16502 case JALX32:
16503 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16504 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16505 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16506 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16507 break;
16508 case JALS32: /* BOVC, BEQC, BEQZALC */
16509 if (ctx->insn_flags & ISA_MIPS_R6) {
16510 if (rs >= rt) {
16511 /* BOVC */
16512 mips32_op = OPC_BOVC;
16513 } else if (rs < rt && rs == 0) {
16514 /* BEQZALC */
16515 mips32_op = OPC_BEQZALC;
16516 } else {
16517 /* BEQC */
16518 mips32_op = OPC_BEQC;
16520 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16521 } else {
16522 /* JALS32 */
16523 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16524 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16525 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16527 break;
16528 case BEQ32: /* BC */
16529 if (ctx->insn_flags & ISA_MIPS_R6) {
16530 /* BC */
16531 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16532 sextract32(ctx->opcode << 1, 0, 27));
16533 } else {
16534 /* BEQ32 */
16535 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16537 break;
16538 case BNE32: /* BALC */
16539 if (ctx->insn_flags & ISA_MIPS_R6) {
16540 /* BALC */
16541 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16542 sextract32(ctx->opcode << 1, 0, 27));
16543 } else {
16544 /* BNE32 */
16545 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16547 break;
16548 case J32: /* BGTZC, BLTZC, BLTC */
16549 if (ctx->insn_flags & ISA_MIPS_R6) {
16550 if (rs == 0 && rt != 0) {
16551 /* BGTZC */
16552 mips32_op = OPC_BGTZC;
16553 } else if (rs != 0 && rt != 0 && rs == rt) {
16554 /* BLTZC */
16555 mips32_op = OPC_BLTZC;
16556 } else {
16557 /* BLTC */
16558 mips32_op = OPC_BLTC;
16560 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16561 } else {
16562 /* J32 */
16563 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16564 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16566 break;
16567 case JAL32: /* BLEZC, BGEZC, BGEC */
16568 if (ctx->insn_flags & ISA_MIPS_R6) {
16569 if (rs == 0 && rt != 0) {
16570 /* BLEZC */
16571 mips32_op = OPC_BLEZC;
16572 } else if (rs != 0 && rt != 0 && rs == rt) {
16573 /* BGEZC */
16574 mips32_op = OPC_BGEZC;
16575 } else {
16576 /* BGEC */
16577 mips32_op = OPC_BGEC;
16579 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16580 } else {
16581 /* JAL32 */
16582 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16583 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16584 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16586 break;
16587 /* Floating point (COP1) */
16588 case LWC132:
16589 mips32_op = OPC_LWC1;
16590 goto do_cop1;
16591 case LDC132:
16592 mips32_op = OPC_LDC1;
16593 goto do_cop1;
16594 case SWC132:
16595 mips32_op = OPC_SWC1;
16596 goto do_cop1;
16597 case SDC132:
16598 mips32_op = OPC_SDC1;
16599 do_cop1:
16600 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16601 break;
16602 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16603 if (ctx->insn_flags & ISA_MIPS_R6) {
16604 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16605 switch ((ctx->opcode >> 16) & 0x1f) {
16606 case ADDIUPC_00:
16607 case ADDIUPC_01:
16608 case ADDIUPC_02:
16609 case ADDIUPC_03:
16610 case ADDIUPC_04:
16611 case ADDIUPC_05:
16612 case ADDIUPC_06:
16613 case ADDIUPC_07:
16614 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16615 break;
16616 case AUIPC:
16617 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16618 break;
16619 case ALUIPC:
16620 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16621 break;
16622 case LWPC_08:
16623 case LWPC_09:
16624 case LWPC_0A:
16625 case LWPC_0B:
16626 case LWPC_0C:
16627 case LWPC_0D:
16628 case LWPC_0E:
16629 case LWPC_0F:
16630 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16631 break;
16632 default:
16633 generate_exception(ctx, EXCP_RI);
16634 break;
16636 } else {
16637 /* ADDIUPC */
16638 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16639 offset = SIMM(ctx->opcode, 0, 23) << 2;
16641 gen_addiupc(ctx, reg, offset, 0, 0);
16643 break;
16644 case BNVC: /* BNEC, BNEZALC */
16645 check_insn(ctx, ISA_MIPS_R6);
16646 if (rs >= rt) {
16647 /* BNVC */
16648 mips32_op = OPC_BNVC;
16649 } else if (rs < rt && rs == 0) {
16650 /* BNEZALC */
16651 mips32_op = OPC_BNEZALC;
16652 } else {
16653 /* BNEC */
16654 mips32_op = OPC_BNEC;
16656 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16657 break;
16658 case R6_BNEZC: /* JIALC */
16659 check_insn(ctx, ISA_MIPS_R6);
16660 if (rt != 0) {
16661 /* BNEZC */
16662 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16663 sextract32(ctx->opcode << 1, 0, 22));
16664 } else {
16665 /* JIALC */
16666 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16668 break;
16669 case R6_BEQZC: /* JIC */
16670 check_insn(ctx, ISA_MIPS_R6);
16671 if (rt != 0) {
16672 /* BEQZC */
16673 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16674 sextract32(ctx->opcode << 1, 0, 22));
16675 } else {
16676 /* JIC */
16677 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16679 break;
16680 case BLEZALC: /* BGEZALC, BGEUC */
16681 check_insn(ctx, ISA_MIPS_R6);
16682 if (rs == 0 && rt != 0) {
16683 /* BLEZALC */
16684 mips32_op = OPC_BLEZALC;
16685 } else if (rs != 0 && rt != 0 && rs == rt) {
16686 /* BGEZALC */
16687 mips32_op = OPC_BGEZALC;
16688 } else {
16689 /* BGEUC */
16690 mips32_op = OPC_BGEUC;
16692 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16693 break;
16694 case BGTZALC: /* BLTZALC, BLTUC */
16695 check_insn(ctx, ISA_MIPS_R6);
16696 if (rs == 0 && rt != 0) {
16697 /* BGTZALC */
16698 mips32_op = OPC_BGTZALC;
16699 } else if (rs != 0 && rt != 0 && rs == rt) {
16700 /* BLTZALC */
16701 mips32_op = OPC_BLTZALC;
16702 } else {
16703 /* BLTUC */
16704 mips32_op = OPC_BLTUC;
16706 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16707 break;
16708 /* Loads and stores */
16709 case LB32:
16710 mips32_op = OPC_LB;
16711 goto do_ld;
16712 case LBU32:
16713 mips32_op = OPC_LBU;
16714 goto do_ld;
16715 case LH32:
16716 mips32_op = OPC_LH;
16717 goto do_ld;
16718 case LHU32:
16719 mips32_op = OPC_LHU;
16720 goto do_ld;
16721 case LW32:
16722 mips32_op = OPC_LW;
16723 goto do_ld;
16724 #ifdef TARGET_MIPS64
16725 case LD32:
16726 check_insn(ctx, ISA_MIPS3);
16727 check_mips_64(ctx);
16728 mips32_op = OPC_LD;
16729 goto do_ld;
16730 case SD32:
16731 check_insn(ctx, ISA_MIPS3);
16732 check_mips_64(ctx);
16733 mips32_op = OPC_SD;
16734 goto do_st;
16735 #endif
16736 case SB32:
16737 mips32_op = OPC_SB;
16738 goto do_st;
16739 case SH32:
16740 mips32_op = OPC_SH;
16741 goto do_st;
16742 case SW32:
16743 mips32_op = OPC_SW;
16744 goto do_st;
16745 do_ld:
16746 gen_ld(ctx, mips32_op, rt, rs, imm);
16747 break;
16748 do_st:
16749 gen_st(ctx, mips32_op, rt, rs, imm);
16750 break;
16751 default:
16752 gen_reserved_instruction(ctx);
16753 break;
16757 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
16759 uint32_t op;
16761 /* make sure instructions are on a halfword boundary */
16762 if (ctx->base.pc_next & 0x1) {
16763 env->CP0_BadVAddr = ctx->base.pc_next;
16764 generate_exception_end(ctx, EXCP_AdEL);
16765 return 2;
16768 op = (ctx->opcode >> 10) & 0x3f;
16769 /* Enforce properly-sized instructions in a delay slot */
16770 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16771 switch (op & 0x7) { /* MSB-3..MSB-5 */
16772 case 0:
16773 /* POOL32A, POOL32B, POOL32I, POOL32C */
16774 case 4:
16775 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16776 case 5:
16777 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16778 case 6:
16779 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16780 case 7:
16781 /* LB32, LH32, LWC132, LDC132, LW32 */
16782 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16783 gen_reserved_instruction(ctx);
16784 return 2;
16786 break;
16787 case 1:
16788 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16789 case 2:
16790 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16791 case 3:
16792 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16793 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16794 gen_reserved_instruction(ctx);
16795 return 2;
16797 break;
16801 switch (op) {
16802 case POOL16A:
16804 int rd = mmreg(uMIPS_RD(ctx->opcode));
16805 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16806 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16807 uint32_t opc = 0;
16809 switch (ctx->opcode & 0x1) {
16810 case ADDU16:
16811 opc = OPC_ADDU;
16812 break;
16813 case SUBU16:
16814 opc = OPC_SUBU;
16815 break;
16817 if (ctx->insn_flags & ISA_MIPS_R6) {
16819 * In the Release 6, the register number location in
16820 * the instruction encoding has changed.
16822 gen_arith(ctx, opc, rs1, rd, rs2);
16823 } else {
16824 gen_arith(ctx, opc, rd, rs1, rs2);
16827 break;
16828 case POOL16B:
16830 int rd = mmreg(uMIPS_RD(ctx->opcode));
16831 int rs = mmreg(uMIPS_RS(ctx->opcode));
16832 int amount = (ctx->opcode >> 1) & 0x7;
16833 uint32_t opc = 0;
16834 amount = amount == 0 ? 8 : amount;
16836 switch (ctx->opcode & 0x1) {
16837 case SLL16:
16838 opc = OPC_SLL;
16839 break;
16840 case SRL16:
16841 opc = OPC_SRL;
16842 break;
16845 gen_shift_imm(ctx, opc, rd, rs, amount);
16847 break;
16848 case POOL16C:
16849 if (ctx->insn_flags & ISA_MIPS_R6) {
16850 gen_pool16c_r6_insn(ctx);
16851 } else {
16852 gen_pool16c_insn(ctx);
16854 break;
16855 case LWGP16:
16857 int rd = mmreg(uMIPS_RD(ctx->opcode));
16858 int rb = 28; /* GP */
16859 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
16861 gen_ld(ctx, OPC_LW, rd, rb, offset);
16863 break;
16864 case POOL16F:
16865 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16866 if (ctx->opcode & 1) {
16867 gen_reserved_instruction(ctx);
16868 } else {
16869 /* MOVEP */
16870 int enc_dest = uMIPS_RD(ctx->opcode);
16871 int enc_rt = uMIPS_RS2(ctx->opcode);
16872 int enc_rs = uMIPS_RS1(ctx->opcode);
16873 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
16875 break;
16876 case LBU16:
16878 int rd = mmreg(uMIPS_RD(ctx->opcode));
16879 int rb = mmreg(uMIPS_RS(ctx->opcode));
16880 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16881 offset = (offset == 0xf ? -1 : offset);
16883 gen_ld(ctx, OPC_LBU, rd, rb, offset);
16885 break;
16886 case LHU16:
16888 int rd = mmreg(uMIPS_RD(ctx->opcode));
16889 int rb = mmreg(uMIPS_RS(ctx->opcode));
16890 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16892 gen_ld(ctx, OPC_LHU, rd, rb, offset);
16894 break;
16895 case LWSP16:
16897 int rd = (ctx->opcode >> 5) & 0x1f;
16898 int rb = 29; /* SP */
16899 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16901 gen_ld(ctx, OPC_LW, rd, rb, offset);
16903 break;
16904 case LW16:
16906 int rd = mmreg(uMIPS_RD(ctx->opcode));
16907 int rb = mmreg(uMIPS_RS(ctx->opcode));
16908 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16910 gen_ld(ctx, OPC_LW, rd, rb, offset);
16912 break;
16913 case SB16:
16915 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16916 int rb = mmreg(uMIPS_RS(ctx->opcode));
16917 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16919 gen_st(ctx, OPC_SB, rd, rb, offset);
16921 break;
16922 case SH16:
16924 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16925 int rb = mmreg(uMIPS_RS(ctx->opcode));
16926 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16928 gen_st(ctx, OPC_SH, rd, rb, offset);
16930 break;
16931 case SWSP16:
16933 int rd = (ctx->opcode >> 5) & 0x1f;
16934 int rb = 29; /* SP */
16935 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16937 gen_st(ctx, OPC_SW, rd, rb, offset);
16939 break;
16940 case SW16:
16942 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16943 int rb = mmreg(uMIPS_RS(ctx->opcode));
16944 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16946 gen_st(ctx, OPC_SW, rd, rb, offset);
16948 break;
16949 case MOVE16:
16951 int rd = uMIPS_RD5(ctx->opcode);
16952 int rs = uMIPS_RS5(ctx->opcode);
16954 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
16956 break;
16957 case ANDI16:
16958 gen_andi16(ctx);
16959 break;
16960 case POOL16D:
16961 switch (ctx->opcode & 0x1) {
16962 case ADDIUS5:
16963 gen_addius5(ctx);
16964 break;
16965 case ADDIUSP:
16966 gen_addiusp(ctx);
16967 break;
16969 break;
16970 case POOL16E:
16971 switch (ctx->opcode & 0x1) {
16972 case ADDIUR2:
16973 gen_addiur2(ctx);
16974 break;
16975 case ADDIUR1SP:
16976 gen_addiur1sp(ctx);
16977 break;
16979 break;
16980 case B16: /* BC16 */
16981 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
16982 sextract32(ctx->opcode, 0, 10) << 1,
16983 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
16984 break;
16985 case BNEZ16: /* BNEZC16 */
16986 case BEQZ16: /* BEQZC16 */
16987 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
16988 mmreg(uMIPS_RD(ctx->opcode)),
16989 0, sextract32(ctx->opcode, 0, 7) << 1,
16990 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
16992 break;
16993 case LI16:
16995 int reg = mmreg(uMIPS_RD(ctx->opcode));
16996 int imm = ZIMM(ctx->opcode, 0, 7);
16998 imm = (imm == 0x7f ? -1 : imm);
16999 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17001 break;
17002 case RES_29:
17003 case RES_31:
17004 case RES_39:
17005 gen_reserved_instruction(ctx);
17006 break;
17007 default:
17008 decode_micromips32_opc(env, ctx);
17009 return 4;
17012 return 2;
17017 * nanoMIPS opcodes
17021 /* MAJOR, P16, and P32 pools opcodes */
17022 enum {
17023 NM_P_ADDIU = 0x00,
17024 NM_ADDIUPC = 0x01,
17025 NM_MOVE_BALC = 0x02,
17026 NM_P16_MV = 0x04,
17027 NM_LW16 = 0x05,
17028 NM_BC16 = 0x06,
17029 NM_P16_SR = 0x07,
17031 NM_POOL32A = 0x08,
17032 NM_P_BAL = 0x0a,
17033 NM_P16_SHIFT = 0x0c,
17034 NM_LWSP16 = 0x0d,
17035 NM_BALC16 = 0x0e,
17036 NM_P16_4X4 = 0x0f,
17038 NM_P_GP_W = 0x10,
17039 NM_P_GP_BH = 0x11,
17040 NM_P_J = 0x12,
17041 NM_P16C = 0x14,
17042 NM_LWGP16 = 0x15,
17043 NM_P16_LB = 0x17,
17045 NM_P48I = 0x18,
17046 NM_P16_A1 = 0x1c,
17047 NM_LW4X4 = 0x1d,
17048 NM_P16_LH = 0x1f,
17050 NM_P_U12 = 0x20,
17051 NM_P_LS_U12 = 0x21,
17052 NM_P_BR1 = 0x22,
17053 NM_P16_A2 = 0x24,
17054 NM_SW16 = 0x25,
17055 NM_BEQZC16 = 0x26,
17057 NM_POOL32F = 0x28,
17058 NM_P_LS_S9 = 0x29,
17059 NM_P_BR2 = 0x2a,
17061 NM_P16_ADDU = 0x2c,
17062 NM_SWSP16 = 0x2d,
17063 NM_BNEZC16 = 0x2e,
17064 NM_MOVEP = 0x2f,
17066 NM_POOL32S = 0x30,
17067 NM_P_BRI = 0x32,
17068 NM_LI16 = 0x34,
17069 NM_SWGP16 = 0x35,
17070 NM_P16_BR = 0x36,
17072 NM_P_LUI = 0x38,
17073 NM_ANDI16 = 0x3c,
17074 NM_SW4X4 = 0x3d,
17075 NM_MOVEPREV = 0x3f,
17078 /* POOL32A instruction pool */
17079 enum {
17080 NM_POOL32A0 = 0x00,
17081 NM_SPECIAL2 = 0x01,
17082 NM_COP2_1 = 0x02,
17083 NM_UDI = 0x03,
17084 NM_POOL32A5 = 0x05,
17085 NM_POOL32A7 = 0x07,
17088 /* P.GP.W instruction pool */
17089 enum {
17090 NM_ADDIUGP_W = 0x00,
17091 NM_LWGP = 0x02,
17092 NM_SWGP = 0x03,
17095 /* P48I instruction pool */
17096 enum {
17097 NM_LI48 = 0x00,
17098 NM_ADDIU48 = 0x01,
17099 NM_ADDIUGP48 = 0x02,
17100 NM_ADDIUPC48 = 0x03,
17101 NM_LWPC48 = 0x0b,
17102 NM_SWPC48 = 0x0f,
17105 /* P.U12 instruction pool */
17106 enum {
17107 NM_ORI = 0x00,
17108 NM_XORI = 0x01,
17109 NM_ANDI = 0x02,
17110 NM_P_SR = 0x03,
17111 NM_SLTI = 0x04,
17112 NM_SLTIU = 0x05,
17113 NM_SEQI = 0x06,
17114 NM_ADDIUNEG = 0x08,
17115 NM_P_SHIFT = 0x0c,
17116 NM_P_ROTX = 0x0d,
17117 NM_P_INS = 0x0e,
17118 NM_P_EXT = 0x0f,
17121 /* POOL32F instruction pool */
17122 enum {
17123 NM_POOL32F_0 = 0x00,
17124 NM_POOL32F_3 = 0x03,
17125 NM_POOL32F_5 = 0x05,
17128 /* POOL32S instruction pool */
17129 enum {
17130 NM_POOL32S_0 = 0x00,
17131 NM_POOL32S_4 = 0x04,
17134 /* P.LUI instruction pool */
17135 enum {
17136 NM_LUI = 0x00,
17137 NM_ALUIPC = 0x01,
17140 /* P.GP.BH instruction pool */
17141 enum {
17142 NM_LBGP = 0x00,
17143 NM_SBGP = 0x01,
17144 NM_LBUGP = 0x02,
17145 NM_ADDIUGP_B = 0x03,
17146 NM_P_GP_LH = 0x04,
17147 NM_P_GP_SH = 0x05,
17148 NM_P_GP_CP1 = 0x06,
17151 /* P.LS.U12 instruction pool */
17152 enum {
17153 NM_LB = 0x00,
17154 NM_SB = 0x01,
17155 NM_LBU = 0x02,
17156 NM_P_PREFU12 = 0x03,
17157 NM_LH = 0x04,
17158 NM_SH = 0x05,
17159 NM_LHU = 0x06,
17160 NM_LWU = 0x07,
17161 NM_LW = 0x08,
17162 NM_SW = 0x09,
17163 NM_LWC1 = 0x0a,
17164 NM_SWC1 = 0x0b,
17165 NM_LDC1 = 0x0e,
17166 NM_SDC1 = 0x0f,
17169 /* P.LS.S9 instruction pool */
17170 enum {
17171 NM_P_LS_S0 = 0x00,
17172 NM_P_LS_S1 = 0x01,
17173 NM_P_LS_E0 = 0x02,
17174 NM_P_LS_WM = 0x04,
17175 NM_P_LS_UAWM = 0x05,
17178 /* P.BAL instruction pool */
17179 enum {
17180 NM_BC = 0x00,
17181 NM_BALC = 0x01,
17184 /* P.J instruction pool */
17185 enum {
17186 NM_JALRC = 0x00,
17187 NM_JALRC_HB = 0x01,
17188 NM_P_BALRSC = 0x08,
17191 /* P.BR1 instruction pool */
17192 enum {
17193 NM_BEQC = 0x00,
17194 NM_P_BR3A = 0x01,
17195 NM_BGEC = 0x02,
17196 NM_BGEUC = 0x03,
17199 /* P.BR2 instruction pool */
17200 enum {
17201 NM_BNEC = 0x00,
17202 NM_BLTC = 0x02,
17203 NM_BLTUC = 0x03,
17206 /* P.BRI instruction pool */
17207 enum {
17208 NM_BEQIC = 0x00,
17209 NM_BBEQZC = 0x01,
17210 NM_BGEIC = 0x02,
17211 NM_BGEIUC = 0x03,
17212 NM_BNEIC = 0x04,
17213 NM_BBNEZC = 0x05,
17214 NM_BLTIC = 0x06,
17215 NM_BLTIUC = 0x07,
17218 /* P16.SHIFT instruction pool */
17219 enum {
17220 NM_SLL16 = 0x00,
17221 NM_SRL16 = 0x01,
17224 /* POOL16C instruction pool */
17225 enum {
17226 NM_POOL16C_0 = 0x00,
17227 NM_LWXS16 = 0x01,
17230 /* P16.A1 instruction pool */
17231 enum {
17232 NM_ADDIUR1SP = 0x01,
17235 /* P16.A2 instruction pool */
17236 enum {
17237 NM_ADDIUR2 = 0x00,
17238 NM_P_ADDIURS5 = 0x01,
17241 /* P16.ADDU instruction pool */
17242 enum {
17243 NM_ADDU16 = 0x00,
17244 NM_SUBU16 = 0x01,
17247 /* P16.SR instruction pool */
17248 enum {
17249 NM_SAVE16 = 0x00,
17250 NM_RESTORE_JRC16 = 0x01,
17253 /* P16.4X4 instruction pool */
17254 enum {
17255 NM_ADDU4X4 = 0x00,
17256 NM_MUL4X4 = 0x01,
17259 /* P16.LB instruction pool */
17260 enum {
17261 NM_LB16 = 0x00,
17262 NM_SB16 = 0x01,
17263 NM_LBU16 = 0x02,
17266 /* P16.LH instruction pool */
17267 enum {
17268 NM_LH16 = 0x00,
17269 NM_SH16 = 0x01,
17270 NM_LHU16 = 0x02,
17273 /* P.RI instruction pool */
17274 enum {
17275 NM_SIGRIE = 0x00,
17276 NM_P_SYSCALL = 0x01,
17277 NM_BREAK = 0x02,
17278 NM_SDBBP = 0x03,
17281 /* POOL32A0 instruction pool */
17282 enum {
17283 NM_P_TRAP = 0x00,
17284 NM_SEB = 0x01,
17285 NM_SLLV = 0x02,
17286 NM_MUL = 0x03,
17287 NM_MFC0 = 0x06,
17288 NM_MFHC0 = 0x07,
17289 NM_SEH = 0x09,
17290 NM_SRLV = 0x0a,
17291 NM_MUH = 0x0b,
17292 NM_MTC0 = 0x0e,
17293 NM_MTHC0 = 0x0f,
17294 NM_SRAV = 0x12,
17295 NM_MULU = 0x13,
17296 NM_ROTRV = 0x1a,
17297 NM_MUHU = 0x1b,
17298 NM_ADD = 0x22,
17299 NM_DIV = 0x23,
17300 NM_ADDU = 0x2a,
17301 NM_MOD = 0x2b,
17302 NM_SUB = 0x32,
17303 NM_DIVU = 0x33,
17304 NM_RDHWR = 0x38,
17305 NM_SUBU = 0x3a,
17306 NM_MODU = 0x3b,
17307 NM_P_CMOVE = 0x42,
17308 NM_FORK = 0x45,
17309 NM_MFTR = 0x46,
17310 NM_MFHTR = 0x47,
17311 NM_AND = 0x4a,
17312 NM_YIELD = 0x4d,
17313 NM_MTTR = 0x4e,
17314 NM_MTHTR = 0x4f,
17315 NM_OR = 0x52,
17316 NM_D_E_MT_VPE = 0x56,
17317 NM_NOR = 0x5a,
17318 NM_XOR = 0x62,
17319 NM_SLT = 0x6a,
17320 NM_P_SLTU = 0x72,
17321 NM_SOV = 0x7a,
17324 /* CRC32 instruction pool */
17325 enum {
17326 NM_CRC32B = 0x00,
17327 NM_CRC32H = 0x01,
17328 NM_CRC32W = 0x02,
17329 NM_CRC32CB = 0x04,
17330 NM_CRC32CH = 0x05,
17331 NM_CRC32CW = 0x06,
17334 /* POOL32A5 instruction pool */
17335 enum {
17336 NM_CMP_EQ_PH = 0x00,
17337 NM_CMP_LT_PH = 0x08,
17338 NM_CMP_LE_PH = 0x10,
17339 NM_CMPGU_EQ_QB = 0x18,
17340 NM_CMPGU_LT_QB = 0x20,
17341 NM_CMPGU_LE_QB = 0x28,
17342 NM_CMPGDU_EQ_QB = 0x30,
17343 NM_CMPGDU_LT_QB = 0x38,
17344 NM_CMPGDU_LE_QB = 0x40,
17345 NM_CMPU_EQ_QB = 0x48,
17346 NM_CMPU_LT_QB = 0x50,
17347 NM_CMPU_LE_QB = 0x58,
17348 NM_ADDQ_S_W = 0x60,
17349 NM_SUBQ_S_W = 0x68,
17350 NM_ADDSC = 0x70,
17351 NM_ADDWC = 0x78,
17353 NM_ADDQ_S_PH = 0x01,
17354 NM_ADDQH_R_PH = 0x09,
17355 NM_ADDQH_R_W = 0x11,
17356 NM_ADDU_S_QB = 0x19,
17357 NM_ADDU_S_PH = 0x21,
17358 NM_ADDUH_R_QB = 0x29,
17359 NM_SHRAV_R_PH = 0x31,
17360 NM_SHRAV_R_QB = 0x39,
17361 NM_SUBQ_S_PH = 0x41,
17362 NM_SUBQH_R_PH = 0x49,
17363 NM_SUBQH_R_W = 0x51,
17364 NM_SUBU_S_QB = 0x59,
17365 NM_SUBU_S_PH = 0x61,
17366 NM_SUBUH_R_QB = 0x69,
17367 NM_SHLLV_S_PH = 0x71,
17368 NM_PRECR_SRA_R_PH_W = 0x79,
17370 NM_MULEU_S_PH_QBL = 0x12,
17371 NM_MULEU_S_PH_QBR = 0x1a,
17372 NM_MULQ_RS_PH = 0x22,
17373 NM_MULQ_S_PH = 0x2a,
17374 NM_MULQ_RS_W = 0x32,
17375 NM_MULQ_S_W = 0x3a,
17376 NM_APPEND = 0x42,
17377 NM_MODSUB = 0x52,
17378 NM_SHRAV_R_W = 0x5a,
17379 NM_SHRLV_PH = 0x62,
17380 NM_SHRLV_QB = 0x6a,
17381 NM_SHLLV_QB = 0x72,
17382 NM_SHLLV_S_W = 0x7a,
17384 NM_SHILO = 0x03,
17386 NM_MULEQ_S_W_PHL = 0x04,
17387 NM_MULEQ_S_W_PHR = 0x0c,
17389 NM_MUL_S_PH = 0x05,
17390 NM_PRECR_QB_PH = 0x0d,
17391 NM_PRECRQ_QB_PH = 0x15,
17392 NM_PRECRQ_PH_W = 0x1d,
17393 NM_PRECRQ_RS_PH_W = 0x25,
17394 NM_PRECRQU_S_QB_PH = 0x2d,
17395 NM_PACKRL_PH = 0x35,
17396 NM_PICK_QB = 0x3d,
17397 NM_PICK_PH = 0x45,
17399 NM_SHRA_R_W = 0x5e,
17400 NM_SHRA_R_PH = 0x66,
17401 NM_SHLL_S_PH = 0x76,
17402 NM_SHLL_S_W = 0x7e,
17404 NM_REPL_PH = 0x07
17407 /* POOL32A7 instruction pool */
17408 enum {
17409 NM_P_LSX = 0x00,
17410 NM_LSA = 0x01,
17411 NM_EXTW = 0x03,
17412 NM_POOL32AXF = 0x07,
17415 /* P.SR instruction pool */
17416 enum {
17417 NM_PP_SR = 0x00,
17418 NM_P_SR_F = 0x01,
17421 /* P.SHIFT instruction pool */
17422 enum {
17423 NM_P_SLL = 0x00,
17424 NM_SRL = 0x02,
17425 NM_SRA = 0x04,
17426 NM_ROTR = 0x06,
17429 /* P.ROTX instruction pool */
17430 enum {
17431 NM_ROTX = 0x00,
17434 /* P.INS instruction pool */
17435 enum {
17436 NM_INS = 0x00,
17439 /* P.EXT instruction pool */
17440 enum {
17441 NM_EXT = 0x00,
17444 /* POOL32F_0 (fmt) instruction pool */
17445 enum {
17446 NM_RINT_S = 0x04,
17447 NM_RINT_D = 0x44,
17448 NM_ADD_S = 0x06,
17449 NM_SELEQZ_S = 0x07,
17450 NM_SELEQZ_D = 0x47,
17451 NM_CLASS_S = 0x0c,
17452 NM_CLASS_D = 0x4c,
17453 NM_SUB_S = 0x0e,
17454 NM_SELNEZ_S = 0x0f,
17455 NM_SELNEZ_D = 0x4f,
17456 NM_MUL_S = 0x16,
17457 NM_SEL_S = 0x17,
17458 NM_SEL_D = 0x57,
17459 NM_DIV_S = 0x1e,
17460 NM_ADD_D = 0x26,
17461 NM_SUB_D = 0x2e,
17462 NM_MUL_D = 0x36,
17463 NM_MADDF_S = 0x37,
17464 NM_MADDF_D = 0x77,
17465 NM_DIV_D = 0x3e,
17466 NM_MSUBF_S = 0x3f,
17467 NM_MSUBF_D = 0x7f,
17470 /* POOL32F_3 instruction pool */
17471 enum {
17472 NM_MIN_FMT = 0x00,
17473 NM_MAX_FMT = 0x01,
17474 NM_MINA_FMT = 0x04,
17475 NM_MAXA_FMT = 0x05,
17476 NM_POOL32FXF = 0x07,
17479 /* POOL32F_5 instruction pool */
17480 enum {
17481 NM_CMP_CONDN_S = 0x00,
17482 NM_CMP_CONDN_D = 0x02,
17485 /* P.GP.LH instruction pool */
17486 enum {
17487 NM_LHGP = 0x00,
17488 NM_LHUGP = 0x01,
17491 /* P.GP.SH instruction pool */
17492 enum {
17493 NM_SHGP = 0x00,
17496 /* P.GP.CP1 instruction pool */
17497 enum {
17498 NM_LWC1GP = 0x00,
17499 NM_SWC1GP = 0x01,
17500 NM_LDC1GP = 0x02,
17501 NM_SDC1GP = 0x03,
17504 /* P.LS.S0 instruction pool */
17505 enum {
17506 NM_LBS9 = 0x00,
17507 NM_LHS9 = 0x04,
17508 NM_LWS9 = 0x08,
17509 NM_LDS9 = 0x0c,
17511 NM_SBS9 = 0x01,
17512 NM_SHS9 = 0x05,
17513 NM_SWS9 = 0x09,
17514 NM_SDS9 = 0x0d,
17516 NM_LBUS9 = 0x02,
17517 NM_LHUS9 = 0x06,
17518 NM_LWC1S9 = 0x0a,
17519 NM_LDC1S9 = 0x0e,
17521 NM_P_PREFS9 = 0x03,
17522 NM_LWUS9 = 0x07,
17523 NM_SWC1S9 = 0x0b,
17524 NM_SDC1S9 = 0x0f,
17527 /* P.LS.S1 instruction pool */
17528 enum {
17529 NM_ASET_ACLR = 0x02,
17530 NM_UALH = 0x04,
17531 NM_UASH = 0x05,
17532 NM_CACHE = 0x07,
17533 NM_P_LL = 0x0a,
17534 NM_P_SC = 0x0b,
17537 /* P.LS.E0 instruction pool */
17538 enum {
17539 NM_LBE = 0x00,
17540 NM_SBE = 0x01,
17541 NM_LBUE = 0x02,
17542 NM_P_PREFE = 0x03,
17543 NM_LHE = 0x04,
17544 NM_SHE = 0x05,
17545 NM_LHUE = 0x06,
17546 NM_CACHEE = 0x07,
17547 NM_LWE = 0x08,
17548 NM_SWE = 0x09,
17549 NM_P_LLE = 0x0a,
17550 NM_P_SCE = 0x0b,
17553 /* P.PREFE instruction pool */
17554 enum {
17555 NM_SYNCIE = 0x00,
17556 NM_PREFE = 0x01,
17559 /* P.LLE instruction pool */
17560 enum {
17561 NM_LLE = 0x00,
17562 NM_LLWPE = 0x01,
17565 /* P.SCE instruction pool */
17566 enum {
17567 NM_SCE = 0x00,
17568 NM_SCWPE = 0x01,
17571 /* P.LS.WM instruction pool */
17572 enum {
17573 NM_LWM = 0x00,
17574 NM_SWM = 0x01,
17577 /* P.LS.UAWM instruction pool */
17578 enum {
17579 NM_UALWM = 0x00,
17580 NM_UASWM = 0x01,
17583 /* P.BR3A instruction pool */
17584 enum {
17585 NM_BC1EQZC = 0x00,
17586 NM_BC1NEZC = 0x01,
17587 NM_BC2EQZC = 0x02,
17588 NM_BC2NEZC = 0x03,
17589 NM_BPOSGE32C = 0x04,
17592 /* P16.RI instruction pool */
17593 enum {
17594 NM_P16_SYSCALL = 0x01,
17595 NM_BREAK16 = 0x02,
17596 NM_SDBBP16 = 0x03,
17599 /* POOL16C_0 instruction pool */
17600 enum {
17601 NM_POOL16C_00 = 0x00,
17604 /* P16.JRC instruction pool */
17605 enum {
17606 NM_JRC = 0x00,
17607 NM_JALRC16 = 0x01,
17610 /* P.SYSCALL instruction pool */
17611 enum {
17612 NM_SYSCALL = 0x00,
17613 NM_HYPCALL = 0x01,
17616 /* P.TRAP instruction pool */
17617 enum {
17618 NM_TEQ = 0x00,
17619 NM_TNE = 0x01,
17622 /* P.CMOVE instruction pool */
17623 enum {
17624 NM_MOVZ = 0x00,
17625 NM_MOVN = 0x01,
17628 /* POOL32Axf instruction pool */
17629 enum {
17630 NM_POOL32AXF_1 = 0x01,
17631 NM_POOL32AXF_2 = 0x02,
17632 NM_POOL32AXF_4 = 0x04,
17633 NM_POOL32AXF_5 = 0x05,
17634 NM_POOL32AXF_7 = 0x07,
17637 /* POOL32Axf_1 instruction pool */
17638 enum {
17639 NM_POOL32AXF_1_0 = 0x00,
17640 NM_POOL32AXF_1_1 = 0x01,
17641 NM_POOL32AXF_1_3 = 0x03,
17642 NM_POOL32AXF_1_4 = 0x04,
17643 NM_POOL32AXF_1_5 = 0x05,
17644 NM_POOL32AXF_1_7 = 0x07,
17647 /* POOL32Axf_2 instruction pool */
17648 enum {
17649 NM_POOL32AXF_2_0_7 = 0x00,
17650 NM_POOL32AXF_2_8_15 = 0x01,
17651 NM_POOL32AXF_2_16_23 = 0x02,
17652 NM_POOL32AXF_2_24_31 = 0x03,
17655 /* POOL32Axf_7 instruction pool */
17656 enum {
17657 NM_SHRA_R_QB = 0x0,
17658 NM_SHRL_PH = 0x1,
17659 NM_REPL_QB = 0x2,
17662 /* POOL32Axf_1_0 instruction pool */
17663 enum {
17664 NM_MFHI = 0x0,
17665 NM_MFLO = 0x1,
17666 NM_MTHI = 0x2,
17667 NM_MTLO = 0x3,
17670 /* POOL32Axf_1_1 instruction pool */
17671 enum {
17672 NM_MTHLIP = 0x0,
17673 NM_SHILOV = 0x1,
17676 /* POOL32Axf_1_3 instruction pool */
17677 enum {
17678 NM_RDDSP = 0x0,
17679 NM_WRDSP = 0x1,
17680 NM_EXTP = 0x2,
17681 NM_EXTPDP = 0x3,
17684 /* POOL32Axf_1_4 instruction pool */
17685 enum {
17686 NM_SHLL_QB = 0x0,
17687 NM_SHRL_QB = 0x1,
17690 /* POOL32Axf_1_5 instruction pool */
17691 enum {
17692 NM_MAQ_S_W_PHR = 0x0,
17693 NM_MAQ_S_W_PHL = 0x1,
17694 NM_MAQ_SA_W_PHR = 0x2,
17695 NM_MAQ_SA_W_PHL = 0x3,
17698 /* POOL32Axf_1_7 instruction pool */
17699 enum {
17700 NM_EXTR_W = 0x0,
17701 NM_EXTR_R_W = 0x1,
17702 NM_EXTR_RS_W = 0x2,
17703 NM_EXTR_S_H = 0x3,
17706 /* POOL32Axf_2_0_7 instruction pool */
17707 enum {
17708 NM_DPA_W_PH = 0x0,
17709 NM_DPAQ_S_W_PH = 0x1,
17710 NM_DPS_W_PH = 0x2,
17711 NM_DPSQ_S_W_PH = 0x3,
17712 NM_BALIGN = 0x4,
17713 NM_MADD = 0x5,
17714 NM_MULT = 0x6,
17715 NM_EXTRV_W = 0x7,
17718 /* POOL32Axf_2_8_15 instruction pool */
17719 enum {
17720 NM_DPAX_W_PH = 0x0,
17721 NM_DPAQ_SA_L_W = 0x1,
17722 NM_DPSX_W_PH = 0x2,
17723 NM_DPSQ_SA_L_W = 0x3,
17724 NM_MADDU = 0x5,
17725 NM_MULTU = 0x6,
17726 NM_EXTRV_R_W = 0x7,
17729 /* POOL32Axf_2_16_23 instruction pool */
17730 enum {
17731 NM_DPAU_H_QBL = 0x0,
17732 NM_DPAQX_S_W_PH = 0x1,
17733 NM_DPSU_H_QBL = 0x2,
17734 NM_DPSQX_S_W_PH = 0x3,
17735 NM_EXTPV = 0x4,
17736 NM_MSUB = 0x5,
17737 NM_MULSA_W_PH = 0x6,
17738 NM_EXTRV_RS_W = 0x7,
17741 /* POOL32Axf_2_24_31 instruction pool */
17742 enum {
17743 NM_DPAU_H_QBR = 0x0,
17744 NM_DPAQX_SA_W_PH = 0x1,
17745 NM_DPSU_H_QBR = 0x2,
17746 NM_DPSQX_SA_W_PH = 0x3,
17747 NM_EXTPDPV = 0x4,
17748 NM_MSUBU = 0x5,
17749 NM_MULSAQ_S_W_PH = 0x6,
17750 NM_EXTRV_S_H = 0x7,
17753 /* POOL32Axf_{4, 5} instruction pool */
17754 enum {
17755 NM_CLO = 0x25,
17756 NM_CLZ = 0x2d,
17758 NM_TLBP = 0x01,
17759 NM_TLBR = 0x09,
17760 NM_TLBWI = 0x11,
17761 NM_TLBWR = 0x19,
17762 NM_TLBINV = 0x03,
17763 NM_TLBINVF = 0x0b,
17764 NM_DI = 0x23,
17765 NM_EI = 0x2b,
17766 NM_RDPGPR = 0x70,
17767 NM_WRPGPR = 0x78,
17768 NM_WAIT = 0x61,
17769 NM_DERET = 0x71,
17770 NM_ERETX = 0x79,
17772 /* nanoMIPS DSP instructions */
17773 NM_ABSQ_S_QB = 0x00,
17774 NM_ABSQ_S_PH = 0x08,
17775 NM_ABSQ_S_W = 0x10,
17776 NM_PRECEQ_W_PHL = 0x28,
17777 NM_PRECEQ_W_PHR = 0x30,
17778 NM_PRECEQU_PH_QBL = 0x38,
17779 NM_PRECEQU_PH_QBR = 0x48,
17780 NM_PRECEU_PH_QBL = 0x58,
17781 NM_PRECEU_PH_QBR = 0x68,
17782 NM_PRECEQU_PH_QBLA = 0x39,
17783 NM_PRECEQU_PH_QBRA = 0x49,
17784 NM_PRECEU_PH_QBLA = 0x59,
17785 NM_PRECEU_PH_QBRA = 0x69,
17786 NM_REPLV_PH = 0x01,
17787 NM_REPLV_QB = 0x09,
17788 NM_BITREV = 0x18,
17789 NM_INSV = 0x20,
17790 NM_RADDU_W_QB = 0x78,
17792 NM_BITSWAP = 0x05,
17793 NM_WSBH = 0x3d,
17796 /* PP.SR instruction pool */
17797 enum {
17798 NM_SAVE = 0x00,
17799 NM_RESTORE = 0x02,
17800 NM_RESTORE_JRC = 0x03,
17803 /* P.SR.F instruction pool */
17804 enum {
17805 NM_SAVEF = 0x00,
17806 NM_RESTOREF = 0x01,
17809 /* P16.SYSCALL instruction pool */
17810 enum {
17811 NM_SYSCALL16 = 0x00,
17812 NM_HYPCALL16 = 0x01,
17815 /* POOL16C_00 instruction pool */
17816 enum {
17817 NM_NOT16 = 0x00,
17818 NM_XOR16 = 0x01,
17819 NM_AND16 = 0x02,
17820 NM_OR16 = 0x03,
17823 /* PP.LSX and PP.LSXS instruction pool */
17824 enum {
17825 NM_LBX = 0x00,
17826 NM_LHX = 0x04,
17827 NM_LWX = 0x08,
17828 NM_LDX = 0x0c,
17830 NM_SBX = 0x01,
17831 NM_SHX = 0x05,
17832 NM_SWX = 0x09,
17833 NM_SDX = 0x0d,
17835 NM_LBUX = 0x02,
17836 NM_LHUX = 0x06,
17837 NM_LWC1X = 0x0a,
17838 NM_LDC1X = 0x0e,
17840 NM_LWUX = 0x07,
17841 NM_SWC1X = 0x0b,
17842 NM_SDC1X = 0x0f,
17844 NM_LHXS = 0x04,
17845 NM_LWXS = 0x08,
17846 NM_LDXS = 0x0c,
17848 NM_SHXS = 0x05,
17849 NM_SWXS = 0x09,
17850 NM_SDXS = 0x0d,
17852 NM_LHUXS = 0x06,
17853 NM_LWC1XS = 0x0a,
17854 NM_LDC1XS = 0x0e,
17856 NM_LWUXS = 0x07,
17857 NM_SWC1XS = 0x0b,
17858 NM_SDC1XS = 0x0f,
17861 /* ERETx instruction pool */
17862 enum {
17863 NM_ERET = 0x00,
17864 NM_ERETNC = 0x01,
17867 /* POOL32FxF_{0, 1} insturction pool */
17868 enum {
17869 NM_CFC1 = 0x40,
17870 NM_CTC1 = 0x60,
17871 NM_MFC1 = 0x80,
17872 NM_MTC1 = 0xa0,
17873 NM_MFHC1 = 0xc0,
17874 NM_MTHC1 = 0xe0,
17876 NM_CVT_S_PL = 0x84,
17877 NM_CVT_S_PU = 0xa4,
17879 NM_CVT_L_S = 0x004,
17880 NM_CVT_L_D = 0x104,
17881 NM_CVT_W_S = 0x024,
17882 NM_CVT_W_D = 0x124,
17884 NM_RSQRT_S = 0x008,
17885 NM_RSQRT_D = 0x108,
17887 NM_SQRT_S = 0x028,
17888 NM_SQRT_D = 0x128,
17890 NM_RECIP_S = 0x048,
17891 NM_RECIP_D = 0x148,
17893 NM_FLOOR_L_S = 0x00c,
17894 NM_FLOOR_L_D = 0x10c,
17896 NM_FLOOR_W_S = 0x02c,
17897 NM_FLOOR_W_D = 0x12c,
17899 NM_CEIL_L_S = 0x04c,
17900 NM_CEIL_L_D = 0x14c,
17901 NM_CEIL_W_S = 0x06c,
17902 NM_CEIL_W_D = 0x16c,
17903 NM_TRUNC_L_S = 0x08c,
17904 NM_TRUNC_L_D = 0x18c,
17905 NM_TRUNC_W_S = 0x0ac,
17906 NM_TRUNC_W_D = 0x1ac,
17907 NM_ROUND_L_S = 0x0cc,
17908 NM_ROUND_L_D = 0x1cc,
17909 NM_ROUND_W_S = 0x0ec,
17910 NM_ROUND_W_D = 0x1ec,
17912 NM_MOV_S = 0x01,
17913 NM_MOV_D = 0x81,
17914 NM_ABS_S = 0x0d,
17915 NM_ABS_D = 0x8d,
17916 NM_NEG_S = 0x2d,
17917 NM_NEG_D = 0xad,
17918 NM_CVT_D_S = 0x04d,
17919 NM_CVT_D_W = 0x0cd,
17920 NM_CVT_D_L = 0x14d,
17921 NM_CVT_S_D = 0x06d,
17922 NM_CVT_S_W = 0x0ed,
17923 NM_CVT_S_L = 0x16d,
17926 /* P.LL instruction pool */
17927 enum {
17928 NM_LL = 0x00,
17929 NM_LLWP = 0x01,
17932 /* P.SC instruction pool */
17933 enum {
17934 NM_SC = 0x00,
17935 NM_SCWP = 0x01,
17938 /* P.DVP instruction pool */
17939 enum {
17940 NM_DVP = 0x00,
17941 NM_EVP = 0x01,
17947 * nanoMIPS decoding engine
17952 /* extraction utilities */
17954 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
17955 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
17956 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
17957 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17958 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17960 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
17961 static inline int decode_gpr_gpr3(int r)
17963 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
17965 return map[r & 0x7];
17968 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
17969 static inline int decode_gpr_gpr3_src_store(int r)
17971 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
17973 return map[r & 0x7];
17976 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
17977 static inline int decode_gpr_gpr4(int r)
17979 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
17980 16, 17, 18, 19, 20, 21, 22, 23 };
17982 return map[r & 0xf];
17985 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
17986 static inline int decode_gpr_gpr4_zero(int r)
17988 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
17989 16, 17, 18, 19, 20, 21, 22, 23 };
17991 return map[r & 0xf];
17995 static void gen_adjust_sp(DisasContext *ctx, int u)
17997 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18000 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18001 uint8_t gp, uint16_t u)
18003 int counter = 0;
18004 TCGv va = tcg_temp_new();
18005 TCGv t0 = tcg_temp_new();
18007 while (counter != count) {
18008 bool use_gp = gp && (counter == count - 1);
18009 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18010 int this_offset = -((counter + 1) << 2);
18011 gen_base_offset_addr(ctx, va, 29, this_offset);
18012 gen_load_gpr(t0, this_rt);
18013 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18014 (MO_TEUL | ctx->default_tcg_memop_mask));
18015 counter++;
18018 /* adjust stack pointer */
18019 gen_adjust_sp(ctx, -u);
18021 tcg_temp_free(t0);
18022 tcg_temp_free(va);
18025 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18026 uint8_t gp, uint16_t u)
18028 int counter = 0;
18029 TCGv va = tcg_temp_new();
18030 TCGv t0 = tcg_temp_new();
18032 while (counter != count) {
18033 bool use_gp = gp && (counter == count - 1);
18034 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18035 int this_offset = u - ((counter + 1) << 2);
18036 gen_base_offset_addr(ctx, va, 29, this_offset);
18037 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18038 ctx->default_tcg_memop_mask);
18039 tcg_gen_ext32s_tl(t0, t0);
18040 gen_store_gpr(t0, this_rt);
18041 counter++;
18044 /* adjust stack pointer */
18045 gen_adjust_sp(ctx, u);
18047 tcg_temp_free(t0);
18048 tcg_temp_free(va);
18051 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18053 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18054 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18056 switch (extract32(ctx->opcode, 2, 2)) {
18057 case NM_NOT16:
18058 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18059 break;
18060 case NM_AND16:
18061 gen_logic(ctx, OPC_AND, rt, rt, rs);
18062 break;
18063 case NM_XOR16:
18064 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18065 break;
18066 case NM_OR16:
18067 gen_logic(ctx, OPC_OR, rt, rt, rs);
18068 break;
18072 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18074 int rt = extract32(ctx->opcode, 21, 5);
18075 int rs = extract32(ctx->opcode, 16, 5);
18076 int rd = extract32(ctx->opcode, 11, 5);
18078 switch (extract32(ctx->opcode, 3, 7)) {
18079 case NM_P_TRAP:
18080 switch (extract32(ctx->opcode, 10, 1)) {
18081 case NM_TEQ:
18082 check_nms(ctx);
18083 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18084 break;
18085 case NM_TNE:
18086 check_nms(ctx);
18087 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18088 break;
18090 break;
18091 case NM_RDHWR:
18092 check_nms(ctx);
18093 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18094 break;
18095 case NM_SEB:
18096 check_nms(ctx);
18097 gen_bshfl(ctx, OPC_SEB, rs, rt);
18098 break;
18099 case NM_SEH:
18100 gen_bshfl(ctx, OPC_SEH, rs, rt);
18101 break;
18102 case NM_SLLV:
18103 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18104 break;
18105 case NM_SRLV:
18106 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18107 break;
18108 case NM_SRAV:
18109 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18110 break;
18111 case NM_ROTRV:
18112 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18113 break;
18114 case NM_ADD:
18115 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18116 break;
18117 case NM_ADDU:
18118 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18119 break;
18120 case NM_SUB:
18121 check_nms(ctx);
18122 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18123 break;
18124 case NM_SUBU:
18125 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18126 break;
18127 case NM_P_CMOVE:
18128 switch (extract32(ctx->opcode, 10, 1)) {
18129 case NM_MOVZ:
18130 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18131 break;
18132 case NM_MOVN:
18133 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18134 break;
18136 break;
18137 case NM_AND:
18138 gen_logic(ctx, OPC_AND, rd, rs, rt);
18139 break;
18140 case NM_OR:
18141 gen_logic(ctx, OPC_OR, rd, rs, rt);
18142 break;
18143 case NM_NOR:
18144 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18145 break;
18146 case NM_XOR:
18147 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18148 break;
18149 case NM_SLT:
18150 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18151 break;
18152 case NM_P_SLTU:
18153 if (rd == 0) {
18154 /* P_DVP */
18155 #ifndef CONFIG_USER_ONLY
18156 TCGv t0 = tcg_temp_new();
18157 switch (extract32(ctx->opcode, 10, 1)) {
18158 case NM_DVP:
18159 if (ctx->vp) {
18160 check_cp0_enabled(ctx);
18161 gen_helper_dvp(t0, cpu_env);
18162 gen_store_gpr(t0, rt);
18164 break;
18165 case NM_EVP:
18166 if (ctx->vp) {
18167 check_cp0_enabled(ctx);
18168 gen_helper_evp(t0, cpu_env);
18169 gen_store_gpr(t0, rt);
18171 break;
18173 tcg_temp_free(t0);
18174 #endif
18175 } else {
18176 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18178 break;
18179 case NM_SOV:
18181 TCGv t0 = tcg_temp_new();
18182 TCGv t1 = tcg_temp_new();
18183 TCGv t2 = tcg_temp_new();
18185 gen_load_gpr(t1, rs);
18186 gen_load_gpr(t2, rt);
18187 tcg_gen_add_tl(t0, t1, t2);
18188 tcg_gen_ext32s_tl(t0, t0);
18189 tcg_gen_xor_tl(t1, t1, t2);
18190 tcg_gen_xor_tl(t2, t0, t2);
18191 tcg_gen_andc_tl(t1, t2, t1);
18193 /* operands of same sign, result different sign */
18194 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18195 gen_store_gpr(t0, rd);
18197 tcg_temp_free(t0);
18198 tcg_temp_free(t1);
18199 tcg_temp_free(t2);
18201 break;
18202 case NM_MUL:
18203 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18204 break;
18205 case NM_MUH:
18206 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18207 break;
18208 case NM_MULU:
18209 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18210 break;
18211 case NM_MUHU:
18212 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18213 break;
18214 case NM_DIV:
18215 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18216 break;
18217 case NM_MOD:
18218 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18219 break;
18220 case NM_DIVU:
18221 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18222 break;
18223 case NM_MODU:
18224 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18225 break;
18226 #ifndef CONFIG_USER_ONLY
18227 case NM_MFC0:
18228 check_cp0_enabled(ctx);
18229 if (rt == 0) {
18230 /* Treat as NOP. */
18231 break;
18233 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18234 break;
18235 case NM_MTC0:
18236 check_cp0_enabled(ctx);
18238 TCGv t0 = tcg_temp_new();
18240 gen_load_gpr(t0, rt);
18241 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18242 tcg_temp_free(t0);
18244 break;
18245 case NM_D_E_MT_VPE:
18247 uint8_t sc = extract32(ctx->opcode, 10, 1);
18248 TCGv t0 = tcg_temp_new();
18250 switch (sc) {
18251 case 0:
18252 if (rs == 1) {
18253 /* DMT */
18254 check_cp0_mt(ctx);
18255 gen_helper_dmt(t0);
18256 gen_store_gpr(t0, rt);
18257 } else if (rs == 0) {
18258 /* DVPE */
18259 check_cp0_mt(ctx);
18260 gen_helper_dvpe(t0, cpu_env);
18261 gen_store_gpr(t0, rt);
18262 } else {
18263 gen_reserved_instruction(ctx);
18265 break;
18266 case 1:
18267 if (rs == 1) {
18268 /* EMT */
18269 check_cp0_mt(ctx);
18270 gen_helper_emt(t0);
18271 gen_store_gpr(t0, rt);
18272 } else if (rs == 0) {
18273 /* EVPE */
18274 check_cp0_mt(ctx);
18275 gen_helper_evpe(t0, cpu_env);
18276 gen_store_gpr(t0, rt);
18277 } else {
18278 gen_reserved_instruction(ctx);
18280 break;
18283 tcg_temp_free(t0);
18285 break;
18286 case NM_FORK:
18287 check_mt(ctx);
18289 TCGv t0 = tcg_temp_new();
18290 TCGv t1 = tcg_temp_new();
18292 gen_load_gpr(t0, rt);
18293 gen_load_gpr(t1, rs);
18294 gen_helper_fork(t0, t1);
18295 tcg_temp_free(t0);
18296 tcg_temp_free(t1);
18298 break;
18299 case NM_MFTR:
18300 case NM_MFHTR:
18301 check_cp0_enabled(ctx);
18302 if (rd == 0) {
18303 /* Treat as NOP. */
18304 return;
18306 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18307 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18308 break;
18309 case NM_MTTR:
18310 case NM_MTHTR:
18311 check_cp0_enabled(ctx);
18312 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18313 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18314 break;
18315 case NM_YIELD:
18316 check_mt(ctx);
18318 TCGv t0 = tcg_temp_new();
18320 gen_load_gpr(t0, rs);
18321 gen_helper_yield(t0, cpu_env, t0);
18322 gen_store_gpr(t0, rt);
18323 tcg_temp_free(t0);
18325 break;
18326 #endif
18327 default:
18328 gen_reserved_instruction(ctx);
18329 break;
18333 /* dsp */
18334 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18335 int ret, int v1, int v2)
18337 TCGv_i32 t0;
18338 TCGv v0_t;
18339 TCGv v1_t;
18341 t0 = tcg_temp_new_i32();
18343 v0_t = tcg_temp_new();
18344 v1_t = tcg_temp_new();
18346 tcg_gen_movi_i32(t0, v2 >> 3);
18348 gen_load_gpr(v0_t, ret);
18349 gen_load_gpr(v1_t, v1);
18351 switch (opc) {
18352 case NM_MAQ_S_W_PHR:
18353 check_dsp(ctx);
18354 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18355 break;
18356 case NM_MAQ_S_W_PHL:
18357 check_dsp(ctx);
18358 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18359 break;
18360 case NM_MAQ_SA_W_PHR:
18361 check_dsp(ctx);
18362 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18363 break;
18364 case NM_MAQ_SA_W_PHL:
18365 check_dsp(ctx);
18366 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18367 break;
18368 default:
18369 gen_reserved_instruction(ctx);
18370 break;
18373 tcg_temp_free_i32(t0);
18375 tcg_temp_free(v0_t);
18376 tcg_temp_free(v1_t);
18380 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18381 int ret, int v1, int v2)
18383 int16_t imm;
18384 TCGv t0 = tcg_temp_new();
18385 TCGv t1 = tcg_temp_new();
18386 TCGv v0_t = tcg_temp_new();
18388 gen_load_gpr(v0_t, v1);
18390 switch (opc) {
18391 case NM_POOL32AXF_1_0:
18392 check_dsp(ctx);
18393 switch (extract32(ctx->opcode, 12, 2)) {
18394 case NM_MFHI:
18395 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18396 break;
18397 case NM_MFLO:
18398 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18399 break;
18400 case NM_MTHI:
18401 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18402 break;
18403 case NM_MTLO:
18404 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18405 break;
18407 break;
18408 case NM_POOL32AXF_1_1:
18409 check_dsp(ctx);
18410 switch (extract32(ctx->opcode, 12, 2)) {
18411 case NM_MTHLIP:
18412 tcg_gen_movi_tl(t0, v2);
18413 gen_helper_mthlip(t0, v0_t, cpu_env);
18414 break;
18415 case NM_SHILOV:
18416 tcg_gen_movi_tl(t0, v2 >> 3);
18417 gen_helper_shilo(t0, v0_t, cpu_env);
18418 break;
18419 default:
18420 gen_reserved_instruction(ctx);
18421 break;
18423 break;
18424 case NM_POOL32AXF_1_3:
18425 check_dsp(ctx);
18426 imm = extract32(ctx->opcode, 14, 7);
18427 switch (extract32(ctx->opcode, 12, 2)) {
18428 case NM_RDDSP:
18429 tcg_gen_movi_tl(t0, imm);
18430 gen_helper_rddsp(t0, t0, cpu_env);
18431 gen_store_gpr(t0, ret);
18432 break;
18433 case NM_WRDSP:
18434 gen_load_gpr(t0, ret);
18435 tcg_gen_movi_tl(t1, imm);
18436 gen_helper_wrdsp(t0, t1, cpu_env);
18437 break;
18438 case NM_EXTP:
18439 tcg_gen_movi_tl(t0, v2 >> 3);
18440 tcg_gen_movi_tl(t1, v1);
18441 gen_helper_extp(t0, t0, t1, cpu_env);
18442 gen_store_gpr(t0, ret);
18443 break;
18444 case NM_EXTPDP:
18445 tcg_gen_movi_tl(t0, v2 >> 3);
18446 tcg_gen_movi_tl(t1, v1);
18447 gen_helper_extpdp(t0, t0, t1, cpu_env);
18448 gen_store_gpr(t0, ret);
18449 break;
18451 break;
18452 case NM_POOL32AXF_1_4:
18453 check_dsp(ctx);
18454 tcg_gen_movi_tl(t0, v2 >> 2);
18455 switch (extract32(ctx->opcode, 12, 1)) {
18456 case NM_SHLL_QB:
18457 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18458 gen_store_gpr(t0, ret);
18459 break;
18460 case NM_SHRL_QB:
18461 gen_helper_shrl_qb(t0, t0, v0_t);
18462 gen_store_gpr(t0, ret);
18463 break;
18465 break;
18466 case NM_POOL32AXF_1_5:
18467 opc = extract32(ctx->opcode, 12, 2);
18468 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18469 break;
18470 case NM_POOL32AXF_1_7:
18471 check_dsp(ctx);
18472 tcg_gen_movi_tl(t0, v2 >> 3);
18473 tcg_gen_movi_tl(t1, v1);
18474 switch (extract32(ctx->opcode, 12, 2)) {
18475 case NM_EXTR_W:
18476 gen_helper_extr_w(t0, t0, t1, cpu_env);
18477 gen_store_gpr(t0, ret);
18478 break;
18479 case NM_EXTR_R_W:
18480 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18481 gen_store_gpr(t0, ret);
18482 break;
18483 case NM_EXTR_RS_W:
18484 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18485 gen_store_gpr(t0, ret);
18486 break;
18487 case NM_EXTR_S_H:
18488 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18489 gen_store_gpr(t0, ret);
18490 break;
18492 break;
18493 default:
18494 gen_reserved_instruction(ctx);
18495 break;
18498 tcg_temp_free(t0);
18499 tcg_temp_free(t1);
18500 tcg_temp_free(v0_t);
18503 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18504 TCGv v0, TCGv v1, int rd)
18506 TCGv_i32 t0;
18508 t0 = tcg_temp_new_i32();
18510 tcg_gen_movi_i32(t0, rd >> 3);
18512 switch (opc) {
18513 case NM_POOL32AXF_2_0_7:
18514 switch (extract32(ctx->opcode, 9, 3)) {
18515 case NM_DPA_W_PH:
18516 check_dsp_r2(ctx);
18517 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18518 break;
18519 case NM_DPAQ_S_W_PH:
18520 check_dsp(ctx);
18521 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18522 break;
18523 case NM_DPS_W_PH:
18524 check_dsp_r2(ctx);
18525 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18526 break;
18527 case NM_DPSQ_S_W_PH:
18528 check_dsp(ctx);
18529 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18530 break;
18531 default:
18532 gen_reserved_instruction(ctx);
18533 break;
18535 break;
18536 case NM_POOL32AXF_2_8_15:
18537 switch (extract32(ctx->opcode, 9, 3)) {
18538 case NM_DPAX_W_PH:
18539 check_dsp_r2(ctx);
18540 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18541 break;
18542 case NM_DPAQ_SA_L_W:
18543 check_dsp(ctx);
18544 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18545 break;
18546 case NM_DPSX_W_PH:
18547 check_dsp_r2(ctx);
18548 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18549 break;
18550 case NM_DPSQ_SA_L_W:
18551 check_dsp(ctx);
18552 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18553 break;
18554 default:
18555 gen_reserved_instruction(ctx);
18556 break;
18558 break;
18559 case NM_POOL32AXF_2_16_23:
18560 switch (extract32(ctx->opcode, 9, 3)) {
18561 case NM_DPAU_H_QBL:
18562 check_dsp(ctx);
18563 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18564 break;
18565 case NM_DPAQX_S_W_PH:
18566 check_dsp_r2(ctx);
18567 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18568 break;
18569 case NM_DPSU_H_QBL:
18570 check_dsp(ctx);
18571 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18572 break;
18573 case NM_DPSQX_S_W_PH:
18574 check_dsp_r2(ctx);
18575 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18576 break;
18577 case NM_MULSA_W_PH:
18578 check_dsp_r2(ctx);
18579 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18580 break;
18581 default:
18582 gen_reserved_instruction(ctx);
18583 break;
18585 break;
18586 case NM_POOL32AXF_2_24_31:
18587 switch (extract32(ctx->opcode, 9, 3)) {
18588 case NM_DPAU_H_QBR:
18589 check_dsp(ctx);
18590 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18591 break;
18592 case NM_DPAQX_SA_W_PH:
18593 check_dsp_r2(ctx);
18594 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18595 break;
18596 case NM_DPSU_H_QBR:
18597 check_dsp(ctx);
18598 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18599 break;
18600 case NM_DPSQX_SA_W_PH:
18601 check_dsp_r2(ctx);
18602 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18603 break;
18604 case NM_MULSAQ_S_W_PH:
18605 check_dsp(ctx);
18606 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18607 break;
18608 default:
18609 gen_reserved_instruction(ctx);
18610 break;
18612 break;
18613 default:
18614 gen_reserved_instruction(ctx);
18615 break;
18618 tcg_temp_free_i32(t0);
18621 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18622 int rt, int rs, int rd)
18624 int ret = rt;
18625 TCGv t0 = tcg_temp_new();
18626 TCGv t1 = tcg_temp_new();
18627 TCGv v0_t = tcg_temp_new();
18628 TCGv v1_t = tcg_temp_new();
18630 gen_load_gpr(v0_t, rt);
18631 gen_load_gpr(v1_t, rs);
18633 switch (opc) {
18634 case NM_POOL32AXF_2_0_7:
18635 switch (extract32(ctx->opcode, 9, 3)) {
18636 case NM_DPA_W_PH:
18637 case NM_DPAQ_S_W_PH:
18638 case NM_DPS_W_PH:
18639 case NM_DPSQ_S_W_PH:
18640 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18641 break;
18642 case NM_BALIGN:
18643 check_dsp_r2(ctx);
18644 if (rt != 0) {
18645 gen_load_gpr(t0, rs);
18646 rd &= 3;
18647 if (rd != 0 && rd != 2) {
18648 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18649 tcg_gen_ext32u_tl(t0, t0);
18650 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18651 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18653 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18655 break;
18656 case NM_MADD:
18657 check_dsp(ctx);
18659 int acc = extract32(ctx->opcode, 14, 2);
18660 TCGv_i64 t2 = tcg_temp_new_i64();
18661 TCGv_i64 t3 = tcg_temp_new_i64();
18663 gen_load_gpr(t0, rt);
18664 gen_load_gpr(t1, rs);
18665 tcg_gen_ext_tl_i64(t2, t0);
18666 tcg_gen_ext_tl_i64(t3, t1);
18667 tcg_gen_mul_i64(t2, t2, t3);
18668 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18669 tcg_gen_add_i64(t2, t2, t3);
18670 tcg_temp_free_i64(t3);
18671 gen_move_low32(cpu_LO[acc], t2);
18672 gen_move_high32(cpu_HI[acc], t2);
18673 tcg_temp_free_i64(t2);
18675 break;
18676 case NM_MULT:
18677 check_dsp(ctx);
18679 int acc = extract32(ctx->opcode, 14, 2);
18680 TCGv_i32 t2 = tcg_temp_new_i32();
18681 TCGv_i32 t3 = tcg_temp_new_i32();
18683 gen_load_gpr(t0, rs);
18684 gen_load_gpr(t1, rt);
18685 tcg_gen_trunc_tl_i32(t2, t0);
18686 tcg_gen_trunc_tl_i32(t3, t1);
18687 tcg_gen_muls2_i32(t2, t3, t2, t3);
18688 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18689 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18690 tcg_temp_free_i32(t2);
18691 tcg_temp_free_i32(t3);
18693 break;
18694 case NM_EXTRV_W:
18695 check_dsp(ctx);
18696 gen_load_gpr(v1_t, rs);
18697 tcg_gen_movi_tl(t0, rd >> 3);
18698 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18699 gen_store_gpr(t0, ret);
18700 break;
18702 break;
18703 case NM_POOL32AXF_2_8_15:
18704 switch (extract32(ctx->opcode, 9, 3)) {
18705 case NM_DPAX_W_PH:
18706 case NM_DPAQ_SA_L_W:
18707 case NM_DPSX_W_PH:
18708 case NM_DPSQ_SA_L_W:
18709 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18710 break;
18711 case NM_MADDU:
18712 check_dsp(ctx);
18714 int acc = extract32(ctx->opcode, 14, 2);
18715 TCGv_i64 t2 = tcg_temp_new_i64();
18716 TCGv_i64 t3 = tcg_temp_new_i64();
18718 gen_load_gpr(t0, rs);
18719 gen_load_gpr(t1, rt);
18720 tcg_gen_ext32u_tl(t0, t0);
18721 tcg_gen_ext32u_tl(t1, t1);
18722 tcg_gen_extu_tl_i64(t2, t0);
18723 tcg_gen_extu_tl_i64(t3, t1);
18724 tcg_gen_mul_i64(t2, t2, t3);
18725 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18726 tcg_gen_add_i64(t2, t2, t3);
18727 tcg_temp_free_i64(t3);
18728 gen_move_low32(cpu_LO[acc], t2);
18729 gen_move_high32(cpu_HI[acc], t2);
18730 tcg_temp_free_i64(t2);
18732 break;
18733 case NM_MULTU:
18734 check_dsp(ctx);
18736 int acc = extract32(ctx->opcode, 14, 2);
18737 TCGv_i32 t2 = tcg_temp_new_i32();
18738 TCGv_i32 t3 = tcg_temp_new_i32();
18740 gen_load_gpr(t0, rs);
18741 gen_load_gpr(t1, rt);
18742 tcg_gen_trunc_tl_i32(t2, t0);
18743 tcg_gen_trunc_tl_i32(t3, t1);
18744 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18745 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18746 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18747 tcg_temp_free_i32(t2);
18748 tcg_temp_free_i32(t3);
18750 break;
18751 case NM_EXTRV_R_W:
18752 check_dsp(ctx);
18753 tcg_gen_movi_tl(t0, rd >> 3);
18754 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18755 gen_store_gpr(t0, ret);
18756 break;
18757 default:
18758 gen_reserved_instruction(ctx);
18759 break;
18761 break;
18762 case NM_POOL32AXF_2_16_23:
18763 switch (extract32(ctx->opcode, 9, 3)) {
18764 case NM_DPAU_H_QBL:
18765 case NM_DPAQX_S_W_PH:
18766 case NM_DPSU_H_QBL:
18767 case NM_DPSQX_S_W_PH:
18768 case NM_MULSA_W_PH:
18769 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18770 break;
18771 case NM_EXTPV:
18772 check_dsp(ctx);
18773 tcg_gen_movi_tl(t0, rd >> 3);
18774 gen_helper_extp(t0, t0, v1_t, cpu_env);
18775 gen_store_gpr(t0, ret);
18776 break;
18777 case NM_MSUB:
18778 check_dsp(ctx);
18780 int acc = extract32(ctx->opcode, 14, 2);
18781 TCGv_i64 t2 = tcg_temp_new_i64();
18782 TCGv_i64 t3 = tcg_temp_new_i64();
18784 gen_load_gpr(t0, rs);
18785 gen_load_gpr(t1, rt);
18786 tcg_gen_ext_tl_i64(t2, t0);
18787 tcg_gen_ext_tl_i64(t3, t1);
18788 tcg_gen_mul_i64(t2, t2, t3);
18789 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18790 tcg_gen_sub_i64(t2, t3, t2);
18791 tcg_temp_free_i64(t3);
18792 gen_move_low32(cpu_LO[acc], t2);
18793 gen_move_high32(cpu_HI[acc], t2);
18794 tcg_temp_free_i64(t2);
18796 break;
18797 case NM_EXTRV_RS_W:
18798 check_dsp(ctx);
18799 tcg_gen_movi_tl(t0, rd >> 3);
18800 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18801 gen_store_gpr(t0, ret);
18802 break;
18804 break;
18805 case NM_POOL32AXF_2_24_31:
18806 switch (extract32(ctx->opcode, 9, 3)) {
18807 case NM_DPAU_H_QBR:
18808 case NM_DPAQX_SA_W_PH:
18809 case NM_DPSU_H_QBR:
18810 case NM_DPSQX_SA_W_PH:
18811 case NM_MULSAQ_S_W_PH:
18812 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18813 break;
18814 case NM_EXTPDPV:
18815 check_dsp(ctx);
18816 tcg_gen_movi_tl(t0, rd >> 3);
18817 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18818 gen_store_gpr(t0, ret);
18819 break;
18820 case NM_MSUBU:
18821 check_dsp(ctx);
18823 int acc = extract32(ctx->opcode, 14, 2);
18824 TCGv_i64 t2 = tcg_temp_new_i64();
18825 TCGv_i64 t3 = tcg_temp_new_i64();
18827 gen_load_gpr(t0, rs);
18828 gen_load_gpr(t1, rt);
18829 tcg_gen_ext32u_tl(t0, t0);
18830 tcg_gen_ext32u_tl(t1, t1);
18831 tcg_gen_extu_tl_i64(t2, t0);
18832 tcg_gen_extu_tl_i64(t3, t1);
18833 tcg_gen_mul_i64(t2, t2, t3);
18834 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18835 tcg_gen_sub_i64(t2, t3, t2);
18836 tcg_temp_free_i64(t3);
18837 gen_move_low32(cpu_LO[acc], t2);
18838 gen_move_high32(cpu_HI[acc], t2);
18839 tcg_temp_free_i64(t2);
18841 break;
18842 case NM_EXTRV_S_H:
18843 check_dsp(ctx);
18844 tcg_gen_movi_tl(t0, rd >> 3);
18845 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
18846 gen_store_gpr(t0, ret);
18847 break;
18849 break;
18850 default:
18851 gen_reserved_instruction(ctx);
18852 break;
18855 tcg_temp_free(t0);
18856 tcg_temp_free(t1);
18858 tcg_temp_free(v0_t);
18859 tcg_temp_free(v1_t);
18862 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
18863 int rt, int rs)
18865 int ret = rt;
18866 TCGv t0 = tcg_temp_new();
18867 TCGv v0_t = tcg_temp_new();
18869 gen_load_gpr(v0_t, rs);
18871 switch (opc) {
18872 case NM_ABSQ_S_QB:
18873 check_dsp_r2(ctx);
18874 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
18875 gen_store_gpr(v0_t, ret);
18876 break;
18877 case NM_ABSQ_S_PH:
18878 check_dsp(ctx);
18879 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
18880 gen_store_gpr(v0_t, ret);
18881 break;
18882 case NM_ABSQ_S_W:
18883 check_dsp(ctx);
18884 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
18885 gen_store_gpr(v0_t, ret);
18886 break;
18887 case NM_PRECEQ_W_PHL:
18888 check_dsp(ctx);
18889 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
18890 tcg_gen_ext32s_tl(v0_t, v0_t);
18891 gen_store_gpr(v0_t, ret);
18892 break;
18893 case NM_PRECEQ_W_PHR:
18894 check_dsp(ctx);
18895 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
18896 tcg_gen_shli_tl(v0_t, v0_t, 16);
18897 tcg_gen_ext32s_tl(v0_t, v0_t);
18898 gen_store_gpr(v0_t, ret);
18899 break;
18900 case NM_PRECEQU_PH_QBL:
18901 check_dsp(ctx);
18902 gen_helper_precequ_ph_qbl(v0_t, v0_t);
18903 gen_store_gpr(v0_t, ret);
18904 break;
18905 case NM_PRECEQU_PH_QBR:
18906 check_dsp(ctx);
18907 gen_helper_precequ_ph_qbr(v0_t, v0_t);
18908 gen_store_gpr(v0_t, ret);
18909 break;
18910 case NM_PRECEQU_PH_QBLA:
18911 check_dsp(ctx);
18912 gen_helper_precequ_ph_qbla(v0_t, v0_t);
18913 gen_store_gpr(v0_t, ret);
18914 break;
18915 case NM_PRECEQU_PH_QBRA:
18916 check_dsp(ctx);
18917 gen_helper_precequ_ph_qbra(v0_t, v0_t);
18918 gen_store_gpr(v0_t, ret);
18919 break;
18920 case NM_PRECEU_PH_QBL:
18921 check_dsp(ctx);
18922 gen_helper_preceu_ph_qbl(v0_t, v0_t);
18923 gen_store_gpr(v0_t, ret);
18924 break;
18925 case NM_PRECEU_PH_QBR:
18926 check_dsp(ctx);
18927 gen_helper_preceu_ph_qbr(v0_t, v0_t);
18928 gen_store_gpr(v0_t, ret);
18929 break;
18930 case NM_PRECEU_PH_QBLA:
18931 check_dsp(ctx);
18932 gen_helper_preceu_ph_qbla(v0_t, v0_t);
18933 gen_store_gpr(v0_t, ret);
18934 break;
18935 case NM_PRECEU_PH_QBRA:
18936 check_dsp(ctx);
18937 gen_helper_preceu_ph_qbra(v0_t, v0_t);
18938 gen_store_gpr(v0_t, ret);
18939 break;
18940 case NM_REPLV_PH:
18941 check_dsp(ctx);
18942 tcg_gen_ext16u_tl(v0_t, v0_t);
18943 tcg_gen_shli_tl(t0, v0_t, 16);
18944 tcg_gen_or_tl(v0_t, v0_t, t0);
18945 tcg_gen_ext32s_tl(v0_t, v0_t);
18946 gen_store_gpr(v0_t, ret);
18947 break;
18948 case NM_REPLV_QB:
18949 check_dsp(ctx);
18950 tcg_gen_ext8u_tl(v0_t, v0_t);
18951 tcg_gen_shli_tl(t0, v0_t, 8);
18952 tcg_gen_or_tl(v0_t, v0_t, t0);
18953 tcg_gen_shli_tl(t0, v0_t, 16);
18954 tcg_gen_or_tl(v0_t, v0_t, t0);
18955 tcg_gen_ext32s_tl(v0_t, v0_t);
18956 gen_store_gpr(v0_t, ret);
18957 break;
18958 case NM_BITREV:
18959 check_dsp(ctx);
18960 gen_helper_bitrev(v0_t, v0_t);
18961 gen_store_gpr(v0_t, ret);
18962 break;
18963 case NM_INSV:
18964 check_dsp(ctx);
18966 TCGv tv0 = tcg_temp_new();
18968 gen_load_gpr(tv0, rt);
18969 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
18970 gen_store_gpr(v0_t, ret);
18971 tcg_temp_free(tv0);
18973 break;
18974 case NM_RADDU_W_QB:
18975 check_dsp(ctx);
18976 gen_helper_raddu_w_qb(v0_t, v0_t);
18977 gen_store_gpr(v0_t, ret);
18978 break;
18979 case NM_BITSWAP:
18980 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
18981 break;
18982 case NM_CLO:
18983 check_nms(ctx);
18984 gen_cl(ctx, OPC_CLO, ret, rs);
18985 break;
18986 case NM_CLZ:
18987 check_nms(ctx);
18988 gen_cl(ctx, OPC_CLZ, ret, rs);
18989 break;
18990 case NM_WSBH:
18991 gen_bshfl(ctx, OPC_WSBH, ret, rs);
18992 break;
18993 default:
18994 gen_reserved_instruction(ctx);
18995 break;
18998 tcg_temp_free(v0_t);
18999 tcg_temp_free(t0);
19002 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19003 int rt, int rs, int rd)
19005 TCGv t0 = tcg_temp_new();
19006 TCGv rs_t = tcg_temp_new();
19008 gen_load_gpr(rs_t, rs);
19010 switch (opc) {
19011 case NM_SHRA_R_QB:
19012 check_dsp_r2(ctx);
19013 tcg_gen_movi_tl(t0, rd >> 2);
19014 switch (extract32(ctx->opcode, 12, 1)) {
19015 case 0:
19016 /* NM_SHRA_QB */
19017 gen_helper_shra_qb(t0, t0, rs_t);
19018 gen_store_gpr(t0, rt);
19019 break;
19020 case 1:
19021 /* NM_SHRA_R_QB */
19022 gen_helper_shra_r_qb(t0, t0, rs_t);
19023 gen_store_gpr(t0, rt);
19024 break;
19026 break;
19027 case NM_SHRL_PH:
19028 check_dsp_r2(ctx);
19029 tcg_gen_movi_tl(t0, rd >> 1);
19030 gen_helper_shrl_ph(t0, t0, rs_t);
19031 gen_store_gpr(t0, rt);
19032 break;
19033 case NM_REPL_QB:
19034 check_dsp(ctx);
19036 int16_t imm;
19037 target_long result;
19038 imm = extract32(ctx->opcode, 13, 8);
19039 result = (uint32_t)imm << 24 |
19040 (uint32_t)imm << 16 |
19041 (uint32_t)imm << 8 |
19042 (uint32_t)imm;
19043 result = (int32_t)result;
19044 tcg_gen_movi_tl(t0, result);
19045 gen_store_gpr(t0, rt);
19047 break;
19048 default:
19049 gen_reserved_instruction(ctx);
19050 break;
19052 tcg_temp_free(t0);
19053 tcg_temp_free(rs_t);
19057 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19059 int rt = extract32(ctx->opcode, 21, 5);
19060 int rs = extract32(ctx->opcode, 16, 5);
19061 int rd = extract32(ctx->opcode, 11, 5);
19063 switch (extract32(ctx->opcode, 6, 3)) {
19064 case NM_POOL32AXF_1:
19066 int32_t op1 = extract32(ctx->opcode, 9, 3);
19067 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19069 break;
19070 case NM_POOL32AXF_2:
19072 int32_t op1 = extract32(ctx->opcode, 12, 2);
19073 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19075 break;
19076 case NM_POOL32AXF_4:
19078 int32_t op1 = extract32(ctx->opcode, 9, 7);
19079 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19081 break;
19082 case NM_POOL32AXF_5:
19083 switch (extract32(ctx->opcode, 9, 7)) {
19084 #ifndef CONFIG_USER_ONLY
19085 case NM_TLBP:
19086 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19087 break;
19088 case NM_TLBR:
19089 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19090 break;
19091 case NM_TLBWI:
19092 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19093 break;
19094 case NM_TLBWR:
19095 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19096 break;
19097 case NM_TLBINV:
19098 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19099 break;
19100 case NM_TLBINVF:
19101 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19102 break;
19103 case NM_DI:
19104 check_cp0_enabled(ctx);
19106 TCGv t0 = tcg_temp_new();
19108 save_cpu_state(ctx, 1);
19109 gen_helper_di(t0, cpu_env);
19110 gen_store_gpr(t0, rt);
19111 /* Stop translation as we may have switched the execution mode */
19112 ctx->base.is_jmp = DISAS_STOP;
19113 tcg_temp_free(t0);
19115 break;
19116 case NM_EI:
19117 check_cp0_enabled(ctx);
19119 TCGv t0 = tcg_temp_new();
19121 save_cpu_state(ctx, 1);
19122 gen_helper_ei(t0, cpu_env);
19123 gen_store_gpr(t0, rt);
19124 /* Stop translation as we may have switched the execution mode */
19125 ctx->base.is_jmp = DISAS_STOP;
19126 tcg_temp_free(t0);
19128 break;
19129 case NM_RDPGPR:
19130 gen_load_srsgpr(rs, rt);
19131 break;
19132 case NM_WRPGPR:
19133 gen_store_srsgpr(rs, rt);
19134 break;
19135 case NM_WAIT:
19136 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19137 break;
19138 case NM_DERET:
19139 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19140 break;
19141 case NM_ERETX:
19142 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19143 break;
19144 #endif
19145 default:
19146 gen_reserved_instruction(ctx);
19147 break;
19149 break;
19150 case NM_POOL32AXF_7:
19152 int32_t op1 = extract32(ctx->opcode, 9, 3);
19153 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19155 break;
19156 default:
19157 gen_reserved_instruction(ctx);
19158 break;
19162 /* Immediate Value Compact Branches */
19163 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19164 int rt, int32_t imm, int32_t offset)
19166 TCGCond cond = TCG_COND_ALWAYS;
19167 TCGv t0 = tcg_temp_new();
19168 TCGv t1 = tcg_temp_new();
19170 gen_load_gpr(t0, rt);
19171 tcg_gen_movi_tl(t1, imm);
19172 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19174 /* Load needed operands and calculate btarget */
19175 switch (opc) {
19176 case NM_BEQIC:
19177 if (rt == 0 && imm == 0) {
19178 /* Unconditional branch */
19179 } else if (rt == 0 && imm != 0) {
19180 /* Treat as NOP */
19181 goto out;
19182 } else {
19183 cond = TCG_COND_EQ;
19185 break;
19186 case NM_BBEQZC:
19187 case NM_BBNEZC:
19188 check_nms(ctx);
19189 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19190 gen_reserved_instruction(ctx);
19191 goto out;
19192 } else if (rt == 0 && opc == NM_BBEQZC) {
19193 /* Unconditional branch */
19194 } else if (rt == 0 && opc == NM_BBNEZC) {
19195 /* Treat as NOP */
19196 goto out;
19197 } else {
19198 tcg_gen_shri_tl(t0, t0, imm);
19199 tcg_gen_andi_tl(t0, t0, 1);
19200 tcg_gen_movi_tl(t1, 0);
19201 if (opc == NM_BBEQZC) {
19202 cond = TCG_COND_EQ;
19203 } else {
19204 cond = TCG_COND_NE;
19207 break;
19208 case NM_BNEIC:
19209 if (rt == 0 && imm == 0) {
19210 /* Treat as NOP */
19211 goto out;
19212 } else if (rt == 0 && imm != 0) {
19213 /* Unconditional branch */
19214 } else {
19215 cond = TCG_COND_NE;
19217 break;
19218 case NM_BGEIC:
19219 if (rt == 0 && imm == 0) {
19220 /* Unconditional branch */
19221 } else {
19222 cond = TCG_COND_GE;
19224 break;
19225 case NM_BLTIC:
19226 cond = TCG_COND_LT;
19227 break;
19228 case NM_BGEIUC:
19229 if (rt == 0 && imm == 0) {
19230 /* Unconditional branch */
19231 } else {
19232 cond = TCG_COND_GEU;
19234 break;
19235 case NM_BLTIUC:
19236 cond = TCG_COND_LTU;
19237 break;
19238 default:
19239 MIPS_INVAL("Immediate Value Compact branch");
19240 gen_reserved_instruction(ctx);
19241 goto out;
19244 /* branch completion */
19245 clear_branch_hflags(ctx);
19246 ctx->base.is_jmp = DISAS_NORETURN;
19248 if (cond == TCG_COND_ALWAYS) {
19249 /* Uncoditional compact branch */
19250 gen_goto_tb(ctx, 0, ctx->btarget);
19251 } else {
19252 /* Conditional compact branch */
19253 TCGLabel *fs = gen_new_label();
19255 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19257 gen_goto_tb(ctx, 1, ctx->btarget);
19258 gen_set_label(fs);
19260 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19263 out:
19264 tcg_temp_free(t0);
19265 tcg_temp_free(t1);
19268 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19269 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19270 int rt)
19272 TCGv t0 = tcg_temp_new();
19273 TCGv t1 = tcg_temp_new();
19275 /* load rs */
19276 gen_load_gpr(t0, rs);
19278 /* link */
19279 if (rt != 0) {
19280 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19283 /* calculate btarget */
19284 tcg_gen_shli_tl(t0, t0, 1);
19285 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19286 gen_op_addr_add(ctx, btarget, t1, t0);
19288 /* branch completion */
19289 clear_branch_hflags(ctx);
19290 ctx->base.is_jmp = DISAS_NORETURN;
19292 /* unconditional branch to register */
19293 tcg_gen_mov_tl(cpu_PC, btarget);
19294 tcg_gen_lookup_and_goto_ptr();
19296 tcg_temp_free(t0);
19297 tcg_temp_free(t1);
19300 /* nanoMIPS Branches */
19301 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19302 int rs, int rt, int32_t offset)
19304 int bcond_compute = 0;
19305 TCGv t0 = tcg_temp_new();
19306 TCGv t1 = tcg_temp_new();
19308 /* Load needed operands and calculate btarget */
19309 switch (opc) {
19310 /* compact branch */
19311 case OPC_BGEC:
19312 case OPC_BLTC:
19313 gen_load_gpr(t0, rs);
19314 gen_load_gpr(t1, rt);
19315 bcond_compute = 1;
19316 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19317 break;
19318 case OPC_BGEUC:
19319 case OPC_BLTUC:
19320 if (rs == 0 || rs == rt) {
19321 /* OPC_BLEZALC, OPC_BGEZALC */
19322 /* OPC_BGTZALC, OPC_BLTZALC */
19323 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19325 gen_load_gpr(t0, rs);
19326 gen_load_gpr(t1, rt);
19327 bcond_compute = 1;
19328 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19329 break;
19330 case OPC_BC:
19331 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19332 break;
19333 case OPC_BEQZC:
19334 if (rs != 0) {
19335 /* OPC_BEQZC, OPC_BNEZC */
19336 gen_load_gpr(t0, rs);
19337 bcond_compute = 1;
19338 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19339 } else {
19340 /* OPC_JIC, OPC_JIALC */
19341 TCGv tbase = tcg_temp_new();
19342 TCGv toffset = tcg_temp_new();
19344 gen_load_gpr(tbase, rt);
19345 tcg_gen_movi_tl(toffset, offset);
19346 gen_op_addr_add(ctx, btarget, tbase, toffset);
19347 tcg_temp_free(tbase);
19348 tcg_temp_free(toffset);
19350 break;
19351 default:
19352 MIPS_INVAL("Compact branch/jump");
19353 gen_reserved_instruction(ctx);
19354 goto out;
19357 if (bcond_compute == 0) {
19358 /* Uncoditional compact branch */
19359 switch (opc) {
19360 case OPC_BC:
19361 gen_goto_tb(ctx, 0, ctx->btarget);
19362 break;
19363 default:
19364 MIPS_INVAL("Compact branch/jump");
19365 gen_reserved_instruction(ctx);
19366 goto out;
19368 } else {
19369 /* Conditional compact branch */
19370 TCGLabel *fs = gen_new_label();
19372 switch (opc) {
19373 case OPC_BGEUC:
19374 if (rs == 0 && rt != 0) {
19375 /* OPC_BLEZALC */
19376 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19377 } else if (rs != 0 && rt != 0 && rs == rt) {
19378 /* OPC_BGEZALC */
19379 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19380 } else {
19381 /* OPC_BGEUC */
19382 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19384 break;
19385 case OPC_BLTUC:
19386 if (rs == 0 && rt != 0) {
19387 /* OPC_BGTZALC */
19388 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19389 } else if (rs != 0 && rt != 0 && rs == rt) {
19390 /* OPC_BLTZALC */
19391 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19392 } else {
19393 /* OPC_BLTUC */
19394 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19396 break;
19397 case OPC_BGEC:
19398 if (rs == 0 && rt != 0) {
19399 /* OPC_BLEZC */
19400 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19401 } else if (rs != 0 && rt != 0 && rs == rt) {
19402 /* OPC_BGEZC */
19403 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19404 } else {
19405 /* OPC_BGEC */
19406 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19408 break;
19409 case OPC_BLTC:
19410 if (rs == 0 && rt != 0) {
19411 /* OPC_BGTZC */
19412 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19413 } else if (rs != 0 && rt != 0 && rs == rt) {
19414 /* OPC_BLTZC */
19415 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19416 } else {
19417 /* OPC_BLTC */
19418 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19420 break;
19421 case OPC_BEQZC:
19422 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19423 break;
19424 default:
19425 MIPS_INVAL("Compact conditional branch/jump");
19426 gen_reserved_instruction(ctx);
19427 goto out;
19430 /* branch completion */
19431 clear_branch_hflags(ctx);
19432 ctx->base.is_jmp = DISAS_NORETURN;
19434 /* Generating branch here as compact branches don't have delay slot */
19435 gen_goto_tb(ctx, 1, ctx->btarget);
19436 gen_set_label(fs);
19438 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19441 out:
19442 tcg_temp_free(t0);
19443 tcg_temp_free(t1);
19447 /* nanoMIPS CP1 Branches */
19448 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19449 int32_t ft, int32_t offset)
19451 target_ulong btarget;
19452 TCGv_i64 t0 = tcg_temp_new_i64();
19454 gen_load_fpr64(ctx, t0, ft);
19455 tcg_gen_andi_i64(t0, t0, 1);
19457 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19459 switch (op) {
19460 case NM_BC1EQZC:
19461 tcg_gen_xori_i64(t0, t0, 1);
19462 ctx->hflags |= MIPS_HFLAG_BC;
19463 break;
19464 case NM_BC1NEZC:
19465 /* t0 already set */
19466 ctx->hflags |= MIPS_HFLAG_BC;
19467 break;
19468 default:
19469 MIPS_INVAL("cp1 cond branch");
19470 gen_reserved_instruction(ctx);
19471 goto out;
19474 tcg_gen_trunc_i64_tl(bcond, t0);
19476 ctx->btarget = btarget;
19478 out:
19479 tcg_temp_free_i64(t0);
19483 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19485 TCGv t0, t1;
19486 t0 = tcg_temp_new();
19487 t1 = tcg_temp_new();
19489 gen_load_gpr(t0, rs);
19490 gen_load_gpr(t1, rt);
19492 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19493 /* PP.LSXS instructions require shifting */
19494 switch (extract32(ctx->opcode, 7, 4)) {
19495 case NM_SHXS:
19496 check_nms(ctx);
19497 /* fall through */
19498 case NM_LHXS:
19499 case NM_LHUXS:
19500 tcg_gen_shli_tl(t0, t0, 1);
19501 break;
19502 case NM_SWXS:
19503 check_nms(ctx);
19504 /* fall through */
19505 case NM_LWXS:
19506 case NM_LWC1XS:
19507 case NM_SWC1XS:
19508 tcg_gen_shli_tl(t0, t0, 2);
19509 break;
19510 case NM_LDC1XS:
19511 case NM_SDC1XS:
19512 tcg_gen_shli_tl(t0, t0, 3);
19513 break;
19516 gen_op_addr_add(ctx, t0, t0, t1);
19518 switch (extract32(ctx->opcode, 7, 4)) {
19519 case NM_LBX:
19520 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19521 MO_SB);
19522 gen_store_gpr(t0, rd);
19523 break;
19524 case NM_LHX:
19525 /*case NM_LHXS:*/
19526 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19527 MO_TESW);
19528 gen_store_gpr(t0, rd);
19529 break;
19530 case NM_LWX:
19531 /*case NM_LWXS:*/
19532 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19533 MO_TESL);
19534 gen_store_gpr(t0, rd);
19535 break;
19536 case NM_LBUX:
19537 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19538 MO_UB);
19539 gen_store_gpr(t0, rd);
19540 break;
19541 case NM_LHUX:
19542 /*case NM_LHUXS:*/
19543 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19544 MO_TEUW);
19545 gen_store_gpr(t0, rd);
19546 break;
19547 case NM_SBX:
19548 check_nms(ctx);
19549 gen_load_gpr(t1, rd);
19550 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19551 MO_8);
19552 break;
19553 case NM_SHX:
19554 /*case NM_SHXS:*/
19555 check_nms(ctx);
19556 gen_load_gpr(t1, rd);
19557 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19558 MO_TEUW);
19559 break;
19560 case NM_SWX:
19561 /*case NM_SWXS:*/
19562 check_nms(ctx);
19563 gen_load_gpr(t1, rd);
19564 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19565 MO_TEUL);
19566 break;
19567 case NM_LWC1X:
19568 /*case NM_LWC1XS:*/
19569 case NM_LDC1X:
19570 /*case NM_LDC1XS:*/
19571 case NM_SWC1X:
19572 /*case NM_SWC1XS:*/
19573 case NM_SDC1X:
19574 /*case NM_SDC1XS:*/
19575 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19576 check_cp1_enabled(ctx);
19577 switch (extract32(ctx->opcode, 7, 4)) {
19578 case NM_LWC1X:
19579 /*case NM_LWC1XS:*/
19580 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19581 break;
19582 case NM_LDC1X:
19583 /*case NM_LDC1XS:*/
19584 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19585 break;
19586 case NM_SWC1X:
19587 /*case NM_SWC1XS:*/
19588 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19589 break;
19590 case NM_SDC1X:
19591 /*case NM_SDC1XS:*/
19592 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19593 break;
19595 } else {
19596 generate_exception_err(ctx, EXCP_CpU, 1);
19598 break;
19599 default:
19600 gen_reserved_instruction(ctx);
19601 break;
19604 tcg_temp_free(t0);
19605 tcg_temp_free(t1);
19608 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19610 int rt, rs, rd;
19612 rt = extract32(ctx->opcode, 21, 5);
19613 rs = extract32(ctx->opcode, 16, 5);
19614 rd = extract32(ctx->opcode, 11, 5);
19616 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19617 gen_reserved_instruction(ctx);
19618 return;
19620 check_cp1_enabled(ctx);
19621 switch (extract32(ctx->opcode, 0, 3)) {
19622 case NM_POOL32F_0:
19623 switch (extract32(ctx->opcode, 3, 7)) {
19624 case NM_RINT_S:
19625 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19626 break;
19627 case NM_RINT_D:
19628 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19629 break;
19630 case NM_CLASS_S:
19631 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19632 break;
19633 case NM_CLASS_D:
19634 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19635 break;
19636 case NM_ADD_S:
19637 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19638 break;
19639 case NM_ADD_D:
19640 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19641 break;
19642 case NM_SUB_S:
19643 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19644 break;
19645 case NM_SUB_D:
19646 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19647 break;
19648 case NM_MUL_S:
19649 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19650 break;
19651 case NM_MUL_D:
19652 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19653 break;
19654 case NM_DIV_S:
19655 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19656 break;
19657 case NM_DIV_D:
19658 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19659 break;
19660 case NM_SELEQZ_S:
19661 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19662 break;
19663 case NM_SELEQZ_D:
19664 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19665 break;
19666 case NM_SELNEZ_S:
19667 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19668 break;
19669 case NM_SELNEZ_D:
19670 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19671 break;
19672 case NM_SEL_S:
19673 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19674 break;
19675 case NM_SEL_D:
19676 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19677 break;
19678 case NM_MADDF_S:
19679 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19680 break;
19681 case NM_MADDF_D:
19682 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19683 break;
19684 case NM_MSUBF_S:
19685 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19686 break;
19687 case NM_MSUBF_D:
19688 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19689 break;
19690 default:
19691 gen_reserved_instruction(ctx);
19692 break;
19694 break;
19695 case NM_POOL32F_3:
19696 switch (extract32(ctx->opcode, 3, 3)) {
19697 case NM_MIN_FMT:
19698 switch (extract32(ctx->opcode, 9, 1)) {
19699 case FMT_SDPS_S:
19700 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19701 break;
19702 case FMT_SDPS_D:
19703 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19704 break;
19706 break;
19707 case NM_MAX_FMT:
19708 switch (extract32(ctx->opcode, 9, 1)) {
19709 case FMT_SDPS_S:
19710 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19711 break;
19712 case FMT_SDPS_D:
19713 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19714 break;
19716 break;
19717 case NM_MINA_FMT:
19718 switch (extract32(ctx->opcode, 9, 1)) {
19719 case FMT_SDPS_S:
19720 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19721 break;
19722 case FMT_SDPS_D:
19723 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19724 break;
19726 break;
19727 case NM_MAXA_FMT:
19728 switch (extract32(ctx->opcode, 9, 1)) {
19729 case FMT_SDPS_S:
19730 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19731 break;
19732 case FMT_SDPS_D:
19733 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19734 break;
19736 break;
19737 case NM_POOL32FXF:
19738 switch (extract32(ctx->opcode, 6, 8)) {
19739 case NM_CFC1:
19740 gen_cp1(ctx, OPC_CFC1, rt, rs);
19741 break;
19742 case NM_CTC1:
19743 gen_cp1(ctx, OPC_CTC1, rt, rs);
19744 break;
19745 case NM_MFC1:
19746 gen_cp1(ctx, OPC_MFC1, rt, rs);
19747 break;
19748 case NM_MTC1:
19749 gen_cp1(ctx, OPC_MTC1, rt, rs);
19750 break;
19751 case NM_MFHC1:
19752 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19753 break;
19754 case NM_MTHC1:
19755 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19756 break;
19757 case NM_CVT_S_PL:
19758 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19759 break;
19760 case NM_CVT_S_PU:
19761 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19762 break;
19763 default:
19764 switch (extract32(ctx->opcode, 6, 9)) {
19765 case NM_CVT_L_S:
19766 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19767 break;
19768 case NM_CVT_L_D:
19769 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19770 break;
19771 case NM_CVT_W_S:
19772 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19773 break;
19774 case NM_CVT_W_D:
19775 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19776 break;
19777 case NM_RSQRT_S:
19778 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19779 break;
19780 case NM_RSQRT_D:
19781 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19782 break;
19783 case NM_SQRT_S:
19784 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19785 break;
19786 case NM_SQRT_D:
19787 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19788 break;
19789 case NM_RECIP_S:
19790 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19791 break;
19792 case NM_RECIP_D:
19793 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19794 break;
19795 case NM_FLOOR_L_S:
19796 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19797 break;
19798 case NM_FLOOR_L_D:
19799 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19800 break;
19801 case NM_FLOOR_W_S:
19802 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19803 break;
19804 case NM_FLOOR_W_D:
19805 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19806 break;
19807 case NM_CEIL_L_S:
19808 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19809 break;
19810 case NM_CEIL_L_D:
19811 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19812 break;
19813 case NM_CEIL_W_S:
19814 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19815 break;
19816 case NM_CEIL_W_D:
19817 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19818 break;
19819 case NM_TRUNC_L_S:
19820 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19821 break;
19822 case NM_TRUNC_L_D:
19823 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19824 break;
19825 case NM_TRUNC_W_S:
19826 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
19827 break;
19828 case NM_TRUNC_W_D:
19829 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
19830 break;
19831 case NM_ROUND_L_S:
19832 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
19833 break;
19834 case NM_ROUND_L_D:
19835 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
19836 break;
19837 case NM_ROUND_W_S:
19838 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
19839 break;
19840 case NM_ROUND_W_D:
19841 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
19842 break;
19843 case NM_MOV_S:
19844 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
19845 break;
19846 case NM_MOV_D:
19847 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
19848 break;
19849 case NM_ABS_S:
19850 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
19851 break;
19852 case NM_ABS_D:
19853 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
19854 break;
19855 case NM_NEG_S:
19856 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
19857 break;
19858 case NM_NEG_D:
19859 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
19860 break;
19861 case NM_CVT_D_S:
19862 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
19863 break;
19864 case NM_CVT_D_W:
19865 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
19866 break;
19867 case NM_CVT_D_L:
19868 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
19869 break;
19870 case NM_CVT_S_D:
19871 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
19872 break;
19873 case NM_CVT_S_W:
19874 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
19875 break;
19876 case NM_CVT_S_L:
19877 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
19878 break;
19879 default:
19880 gen_reserved_instruction(ctx);
19881 break;
19883 break;
19885 break;
19887 break;
19888 case NM_POOL32F_5:
19889 switch (extract32(ctx->opcode, 3, 3)) {
19890 case NM_CMP_CONDN_S:
19891 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19892 break;
19893 case NM_CMP_CONDN_D:
19894 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19895 break;
19896 default:
19897 gen_reserved_instruction(ctx);
19898 break;
19900 break;
19901 default:
19902 gen_reserved_instruction(ctx);
19903 break;
19907 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
19908 int rd, int rs, int rt)
19910 int ret = rd;
19911 TCGv t0 = tcg_temp_new();
19912 TCGv v1_t = tcg_temp_new();
19913 TCGv v2_t = tcg_temp_new();
19915 gen_load_gpr(v1_t, rs);
19916 gen_load_gpr(v2_t, rt);
19918 switch (opc) {
19919 case NM_CMP_EQ_PH:
19920 check_dsp(ctx);
19921 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
19922 break;
19923 case NM_CMP_LT_PH:
19924 check_dsp(ctx);
19925 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
19926 break;
19927 case NM_CMP_LE_PH:
19928 check_dsp(ctx);
19929 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
19930 break;
19931 case NM_CMPU_EQ_QB:
19932 check_dsp(ctx);
19933 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
19934 break;
19935 case NM_CMPU_LT_QB:
19936 check_dsp(ctx);
19937 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
19938 break;
19939 case NM_CMPU_LE_QB:
19940 check_dsp(ctx);
19941 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
19942 break;
19943 case NM_CMPGU_EQ_QB:
19944 check_dsp(ctx);
19945 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19946 gen_store_gpr(v1_t, ret);
19947 break;
19948 case NM_CMPGU_LT_QB:
19949 check_dsp(ctx);
19950 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19951 gen_store_gpr(v1_t, ret);
19952 break;
19953 case NM_CMPGU_LE_QB:
19954 check_dsp(ctx);
19955 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19956 gen_store_gpr(v1_t, ret);
19957 break;
19958 case NM_CMPGDU_EQ_QB:
19959 check_dsp_r2(ctx);
19960 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19961 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19962 gen_store_gpr(v1_t, ret);
19963 break;
19964 case NM_CMPGDU_LT_QB:
19965 check_dsp_r2(ctx);
19966 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19967 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19968 gen_store_gpr(v1_t, ret);
19969 break;
19970 case NM_CMPGDU_LE_QB:
19971 check_dsp_r2(ctx);
19972 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19973 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19974 gen_store_gpr(v1_t, ret);
19975 break;
19976 case NM_PACKRL_PH:
19977 check_dsp(ctx);
19978 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
19979 gen_store_gpr(v1_t, ret);
19980 break;
19981 case NM_PICK_QB:
19982 check_dsp(ctx);
19983 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
19984 gen_store_gpr(v1_t, ret);
19985 break;
19986 case NM_PICK_PH:
19987 check_dsp(ctx);
19988 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
19989 gen_store_gpr(v1_t, ret);
19990 break;
19991 case NM_ADDQ_S_W:
19992 check_dsp(ctx);
19993 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
19994 gen_store_gpr(v1_t, ret);
19995 break;
19996 case NM_SUBQ_S_W:
19997 check_dsp(ctx);
19998 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
19999 gen_store_gpr(v1_t, ret);
20000 break;
20001 case NM_ADDSC:
20002 check_dsp(ctx);
20003 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20004 gen_store_gpr(v1_t, ret);
20005 break;
20006 case NM_ADDWC:
20007 check_dsp(ctx);
20008 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20009 gen_store_gpr(v1_t, ret);
20010 break;
20011 case NM_ADDQ_S_PH:
20012 check_dsp(ctx);
20013 switch (extract32(ctx->opcode, 10, 1)) {
20014 case 0:
20015 /* ADDQ_PH */
20016 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20017 gen_store_gpr(v1_t, ret);
20018 break;
20019 case 1:
20020 /* ADDQ_S_PH */
20021 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20022 gen_store_gpr(v1_t, ret);
20023 break;
20025 break;
20026 case NM_ADDQH_R_PH:
20027 check_dsp_r2(ctx);
20028 switch (extract32(ctx->opcode, 10, 1)) {
20029 case 0:
20030 /* ADDQH_PH */
20031 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20032 gen_store_gpr(v1_t, ret);
20033 break;
20034 case 1:
20035 /* ADDQH_R_PH */
20036 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20037 gen_store_gpr(v1_t, ret);
20038 break;
20040 break;
20041 case NM_ADDQH_R_W:
20042 check_dsp_r2(ctx);
20043 switch (extract32(ctx->opcode, 10, 1)) {
20044 case 0:
20045 /* ADDQH_W */
20046 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20047 gen_store_gpr(v1_t, ret);
20048 break;
20049 case 1:
20050 /* ADDQH_R_W */
20051 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20052 gen_store_gpr(v1_t, ret);
20053 break;
20055 break;
20056 case NM_ADDU_S_QB:
20057 check_dsp(ctx);
20058 switch (extract32(ctx->opcode, 10, 1)) {
20059 case 0:
20060 /* ADDU_QB */
20061 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20062 gen_store_gpr(v1_t, ret);
20063 break;
20064 case 1:
20065 /* ADDU_S_QB */
20066 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20067 gen_store_gpr(v1_t, ret);
20068 break;
20070 break;
20071 case NM_ADDU_S_PH:
20072 check_dsp_r2(ctx);
20073 switch (extract32(ctx->opcode, 10, 1)) {
20074 case 0:
20075 /* ADDU_PH */
20076 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20077 gen_store_gpr(v1_t, ret);
20078 break;
20079 case 1:
20080 /* ADDU_S_PH */
20081 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20082 gen_store_gpr(v1_t, ret);
20083 break;
20085 break;
20086 case NM_ADDUH_R_QB:
20087 check_dsp_r2(ctx);
20088 switch (extract32(ctx->opcode, 10, 1)) {
20089 case 0:
20090 /* ADDUH_QB */
20091 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20092 gen_store_gpr(v1_t, ret);
20093 break;
20094 case 1:
20095 /* ADDUH_R_QB */
20096 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20097 gen_store_gpr(v1_t, ret);
20098 break;
20100 break;
20101 case NM_SHRAV_R_PH:
20102 check_dsp(ctx);
20103 switch (extract32(ctx->opcode, 10, 1)) {
20104 case 0:
20105 /* SHRAV_PH */
20106 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20107 gen_store_gpr(v1_t, ret);
20108 break;
20109 case 1:
20110 /* SHRAV_R_PH */
20111 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20112 gen_store_gpr(v1_t, ret);
20113 break;
20115 break;
20116 case NM_SHRAV_R_QB:
20117 check_dsp_r2(ctx);
20118 switch (extract32(ctx->opcode, 10, 1)) {
20119 case 0:
20120 /* SHRAV_QB */
20121 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20122 gen_store_gpr(v1_t, ret);
20123 break;
20124 case 1:
20125 /* SHRAV_R_QB */
20126 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20127 gen_store_gpr(v1_t, ret);
20128 break;
20130 break;
20131 case NM_SUBQ_S_PH:
20132 check_dsp(ctx);
20133 switch (extract32(ctx->opcode, 10, 1)) {
20134 case 0:
20135 /* SUBQ_PH */
20136 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20137 gen_store_gpr(v1_t, ret);
20138 break;
20139 case 1:
20140 /* SUBQ_S_PH */
20141 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20142 gen_store_gpr(v1_t, ret);
20143 break;
20145 break;
20146 case NM_SUBQH_R_PH:
20147 check_dsp_r2(ctx);
20148 switch (extract32(ctx->opcode, 10, 1)) {
20149 case 0:
20150 /* SUBQH_PH */
20151 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20152 gen_store_gpr(v1_t, ret);
20153 break;
20154 case 1:
20155 /* SUBQH_R_PH */
20156 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20157 gen_store_gpr(v1_t, ret);
20158 break;
20160 break;
20161 case NM_SUBQH_R_W:
20162 check_dsp_r2(ctx);
20163 switch (extract32(ctx->opcode, 10, 1)) {
20164 case 0:
20165 /* SUBQH_W */
20166 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20167 gen_store_gpr(v1_t, ret);
20168 break;
20169 case 1:
20170 /* SUBQH_R_W */
20171 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20172 gen_store_gpr(v1_t, ret);
20173 break;
20175 break;
20176 case NM_SUBU_S_QB:
20177 check_dsp(ctx);
20178 switch (extract32(ctx->opcode, 10, 1)) {
20179 case 0:
20180 /* SUBU_QB */
20181 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20182 gen_store_gpr(v1_t, ret);
20183 break;
20184 case 1:
20185 /* SUBU_S_QB */
20186 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20187 gen_store_gpr(v1_t, ret);
20188 break;
20190 break;
20191 case NM_SUBU_S_PH:
20192 check_dsp_r2(ctx);
20193 switch (extract32(ctx->opcode, 10, 1)) {
20194 case 0:
20195 /* SUBU_PH */
20196 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20197 gen_store_gpr(v1_t, ret);
20198 break;
20199 case 1:
20200 /* SUBU_S_PH */
20201 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20202 gen_store_gpr(v1_t, ret);
20203 break;
20205 break;
20206 case NM_SUBUH_R_QB:
20207 check_dsp_r2(ctx);
20208 switch (extract32(ctx->opcode, 10, 1)) {
20209 case 0:
20210 /* SUBUH_QB */
20211 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20212 gen_store_gpr(v1_t, ret);
20213 break;
20214 case 1:
20215 /* SUBUH_R_QB */
20216 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20217 gen_store_gpr(v1_t, ret);
20218 break;
20220 break;
20221 case NM_SHLLV_S_PH:
20222 check_dsp(ctx);
20223 switch (extract32(ctx->opcode, 10, 1)) {
20224 case 0:
20225 /* SHLLV_PH */
20226 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20227 gen_store_gpr(v1_t, ret);
20228 break;
20229 case 1:
20230 /* SHLLV_S_PH */
20231 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20232 gen_store_gpr(v1_t, ret);
20233 break;
20235 break;
20236 case NM_PRECR_SRA_R_PH_W:
20237 check_dsp_r2(ctx);
20238 switch (extract32(ctx->opcode, 10, 1)) {
20239 case 0:
20240 /* PRECR_SRA_PH_W */
20242 TCGv_i32 sa_t = tcg_const_i32(rd);
20243 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20244 cpu_gpr[rt]);
20245 gen_store_gpr(v1_t, rt);
20246 tcg_temp_free_i32(sa_t);
20248 break;
20249 case 1:
20250 /* PRECR_SRA_R_PH_W */
20252 TCGv_i32 sa_t = tcg_const_i32(rd);
20253 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20254 cpu_gpr[rt]);
20255 gen_store_gpr(v1_t, rt);
20256 tcg_temp_free_i32(sa_t);
20258 break;
20260 break;
20261 case NM_MULEU_S_PH_QBL:
20262 check_dsp(ctx);
20263 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20264 gen_store_gpr(v1_t, ret);
20265 break;
20266 case NM_MULEU_S_PH_QBR:
20267 check_dsp(ctx);
20268 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20269 gen_store_gpr(v1_t, ret);
20270 break;
20271 case NM_MULQ_RS_PH:
20272 check_dsp(ctx);
20273 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20274 gen_store_gpr(v1_t, ret);
20275 break;
20276 case NM_MULQ_S_PH:
20277 check_dsp_r2(ctx);
20278 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20279 gen_store_gpr(v1_t, ret);
20280 break;
20281 case NM_MULQ_RS_W:
20282 check_dsp_r2(ctx);
20283 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20284 gen_store_gpr(v1_t, ret);
20285 break;
20286 case NM_MULQ_S_W:
20287 check_dsp_r2(ctx);
20288 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20289 gen_store_gpr(v1_t, ret);
20290 break;
20291 case NM_APPEND:
20292 check_dsp_r2(ctx);
20293 gen_load_gpr(t0, rs);
20294 if (rd != 0) {
20295 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20297 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20298 break;
20299 case NM_MODSUB:
20300 check_dsp(ctx);
20301 gen_helper_modsub(v1_t, v1_t, v2_t);
20302 gen_store_gpr(v1_t, ret);
20303 break;
20304 case NM_SHRAV_R_W:
20305 check_dsp(ctx);
20306 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20307 gen_store_gpr(v1_t, ret);
20308 break;
20309 case NM_SHRLV_PH:
20310 check_dsp_r2(ctx);
20311 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20312 gen_store_gpr(v1_t, ret);
20313 break;
20314 case NM_SHRLV_QB:
20315 check_dsp(ctx);
20316 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20317 gen_store_gpr(v1_t, ret);
20318 break;
20319 case NM_SHLLV_QB:
20320 check_dsp(ctx);
20321 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20322 gen_store_gpr(v1_t, ret);
20323 break;
20324 case NM_SHLLV_S_W:
20325 check_dsp(ctx);
20326 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20327 gen_store_gpr(v1_t, ret);
20328 break;
20329 case NM_SHILO:
20330 check_dsp(ctx);
20332 TCGv tv0 = tcg_temp_new();
20333 TCGv tv1 = tcg_temp_new();
20334 int16_t imm = extract32(ctx->opcode, 16, 7);
20336 tcg_gen_movi_tl(tv0, rd >> 3);
20337 tcg_gen_movi_tl(tv1, imm);
20338 gen_helper_shilo(tv0, tv1, cpu_env);
20340 break;
20341 case NM_MULEQ_S_W_PHL:
20342 check_dsp(ctx);
20343 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20344 gen_store_gpr(v1_t, ret);
20345 break;
20346 case NM_MULEQ_S_W_PHR:
20347 check_dsp(ctx);
20348 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20349 gen_store_gpr(v1_t, ret);
20350 break;
20351 case NM_MUL_S_PH:
20352 check_dsp_r2(ctx);
20353 switch (extract32(ctx->opcode, 10, 1)) {
20354 case 0:
20355 /* MUL_PH */
20356 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20357 gen_store_gpr(v1_t, ret);
20358 break;
20359 case 1:
20360 /* MUL_S_PH */
20361 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20362 gen_store_gpr(v1_t, ret);
20363 break;
20365 break;
20366 case NM_PRECR_QB_PH:
20367 check_dsp_r2(ctx);
20368 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20369 gen_store_gpr(v1_t, ret);
20370 break;
20371 case NM_PRECRQ_QB_PH:
20372 check_dsp(ctx);
20373 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20374 gen_store_gpr(v1_t, ret);
20375 break;
20376 case NM_PRECRQ_PH_W:
20377 check_dsp(ctx);
20378 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20379 gen_store_gpr(v1_t, ret);
20380 break;
20381 case NM_PRECRQ_RS_PH_W:
20382 check_dsp(ctx);
20383 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20384 gen_store_gpr(v1_t, ret);
20385 break;
20386 case NM_PRECRQU_S_QB_PH:
20387 check_dsp(ctx);
20388 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20389 gen_store_gpr(v1_t, ret);
20390 break;
20391 case NM_SHRA_R_W:
20392 check_dsp(ctx);
20393 tcg_gen_movi_tl(t0, rd);
20394 gen_helper_shra_r_w(v1_t, t0, v1_t);
20395 gen_store_gpr(v1_t, rt);
20396 break;
20397 case NM_SHRA_R_PH:
20398 check_dsp(ctx);
20399 tcg_gen_movi_tl(t0, rd >> 1);
20400 switch (extract32(ctx->opcode, 10, 1)) {
20401 case 0:
20402 /* SHRA_PH */
20403 gen_helper_shra_ph(v1_t, t0, v1_t);
20404 gen_store_gpr(v1_t, rt);
20405 break;
20406 case 1:
20407 /* SHRA_R_PH */
20408 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20409 gen_store_gpr(v1_t, rt);
20410 break;
20412 break;
20413 case NM_SHLL_S_PH:
20414 check_dsp(ctx);
20415 tcg_gen_movi_tl(t0, rd >> 1);
20416 switch (extract32(ctx->opcode, 10, 2)) {
20417 case 0:
20418 /* SHLL_PH */
20419 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20420 gen_store_gpr(v1_t, rt);
20421 break;
20422 case 2:
20423 /* SHLL_S_PH */
20424 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20425 gen_store_gpr(v1_t, rt);
20426 break;
20427 default:
20428 gen_reserved_instruction(ctx);
20429 break;
20431 break;
20432 case NM_SHLL_S_W:
20433 check_dsp(ctx);
20434 tcg_gen_movi_tl(t0, rd);
20435 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20436 gen_store_gpr(v1_t, rt);
20437 break;
20438 case NM_REPL_PH:
20439 check_dsp(ctx);
20441 int16_t imm;
20442 imm = sextract32(ctx->opcode, 11, 11);
20443 imm = (int16_t)(imm << 6) >> 6;
20444 if (rt != 0) {
20445 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20448 break;
20449 default:
20450 gen_reserved_instruction(ctx);
20451 break;
20455 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20457 uint16_t insn;
20458 uint32_t op;
20459 int rt, rs, rd;
20460 int offset;
20461 int imm;
20463 insn = translator_lduw(env, ctx->base.pc_next + 2);
20464 ctx->opcode = (ctx->opcode << 16) | insn;
20466 rt = extract32(ctx->opcode, 21, 5);
20467 rs = extract32(ctx->opcode, 16, 5);
20468 rd = extract32(ctx->opcode, 11, 5);
20470 op = extract32(ctx->opcode, 26, 6);
20471 switch (op) {
20472 case NM_P_ADDIU:
20473 if (rt == 0) {
20474 /* P.RI */
20475 switch (extract32(ctx->opcode, 19, 2)) {
20476 case NM_SIGRIE:
20477 default:
20478 gen_reserved_instruction(ctx);
20479 break;
20480 case NM_P_SYSCALL:
20481 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20482 generate_exception_end(ctx, EXCP_SYSCALL);
20483 } else {
20484 gen_reserved_instruction(ctx);
20486 break;
20487 case NM_BREAK:
20488 generate_exception_end(ctx, EXCP_BREAK);
20489 break;
20490 case NM_SDBBP:
20491 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20492 gen_helper_do_semihosting(cpu_env);
20493 } else {
20494 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20495 gen_reserved_instruction(ctx);
20496 } else {
20497 generate_exception_end(ctx, EXCP_DBp);
20500 break;
20502 } else {
20503 /* NM_ADDIU */
20504 imm = extract32(ctx->opcode, 0, 16);
20505 if (rs != 0) {
20506 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20507 } else {
20508 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20510 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20512 break;
20513 case NM_ADDIUPC:
20514 if (rt != 0) {
20515 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20516 extract32(ctx->opcode, 1, 20) << 1;
20517 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20518 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20520 break;
20521 case NM_POOL32A:
20522 switch (ctx->opcode & 0x07) {
20523 case NM_POOL32A0:
20524 gen_pool32a0_nanomips_insn(env, ctx);
20525 break;
20526 case NM_POOL32A5:
20528 int32_t op1 = extract32(ctx->opcode, 3, 7);
20529 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20531 break;
20532 case NM_POOL32A7:
20533 switch (extract32(ctx->opcode, 3, 3)) {
20534 case NM_P_LSX:
20535 gen_p_lsx(ctx, rd, rs, rt);
20536 break;
20537 case NM_LSA:
20539 * In nanoMIPS, the shift field directly encodes the shift
20540 * amount, meaning that the supported shift values are in
20541 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
20543 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2) - 1);
20544 break;
20545 case NM_EXTW:
20546 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20547 break;
20548 case NM_POOL32AXF:
20549 gen_pool32axf_nanomips_insn(env, ctx);
20550 break;
20551 default:
20552 gen_reserved_instruction(ctx);
20553 break;
20555 break;
20556 default:
20557 gen_reserved_instruction(ctx);
20558 break;
20560 break;
20561 case NM_P_GP_W:
20562 switch (ctx->opcode & 0x03) {
20563 case NM_ADDIUGP_W:
20564 if (rt != 0) {
20565 offset = extract32(ctx->opcode, 0, 21);
20566 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20568 break;
20569 case NM_LWGP:
20570 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20571 break;
20572 case NM_SWGP:
20573 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20574 break;
20575 default:
20576 gen_reserved_instruction(ctx);
20577 break;
20579 break;
20580 case NM_P48I:
20582 insn = translator_lduw(env, ctx->base.pc_next + 4);
20583 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20584 switch (extract32(ctx->opcode, 16, 5)) {
20585 case NM_LI48:
20586 check_nms(ctx);
20587 if (rt != 0) {
20588 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20590 break;
20591 case NM_ADDIU48:
20592 check_nms(ctx);
20593 if (rt != 0) {
20594 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20595 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20597 break;
20598 case NM_ADDIUGP48:
20599 check_nms(ctx);
20600 if (rt != 0) {
20601 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20603 break;
20604 case NM_ADDIUPC48:
20605 check_nms(ctx);
20606 if (rt != 0) {
20607 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20608 addr_off);
20610 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20612 break;
20613 case NM_LWPC48:
20614 check_nms(ctx);
20615 if (rt != 0) {
20616 TCGv t0;
20617 t0 = tcg_temp_new();
20619 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20620 addr_off);
20622 tcg_gen_movi_tl(t0, addr);
20623 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20624 tcg_temp_free(t0);
20626 break;
20627 case NM_SWPC48:
20628 check_nms(ctx);
20630 TCGv t0, t1;
20631 t0 = tcg_temp_new();
20632 t1 = tcg_temp_new();
20634 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20635 addr_off);
20637 tcg_gen_movi_tl(t0, addr);
20638 gen_load_gpr(t1, rt);
20640 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20642 tcg_temp_free(t0);
20643 tcg_temp_free(t1);
20645 break;
20646 default:
20647 gen_reserved_instruction(ctx);
20648 break;
20650 return 6;
20652 case NM_P_U12:
20653 switch (extract32(ctx->opcode, 12, 4)) {
20654 case NM_ORI:
20655 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20656 break;
20657 case NM_XORI:
20658 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20659 break;
20660 case NM_ANDI:
20661 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20662 break;
20663 case NM_P_SR:
20664 switch (extract32(ctx->opcode, 20, 1)) {
20665 case NM_PP_SR:
20666 switch (ctx->opcode & 3) {
20667 case NM_SAVE:
20668 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20669 extract32(ctx->opcode, 2, 1),
20670 extract32(ctx->opcode, 3, 9) << 3);
20671 break;
20672 case NM_RESTORE:
20673 case NM_RESTORE_JRC:
20674 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20675 extract32(ctx->opcode, 2, 1),
20676 extract32(ctx->opcode, 3, 9) << 3);
20677 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20678 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20680 break;
20681 default:
20682 gen_reserved_instruction(ctx);
20683 break;
20685 break;
20686 case NM_P_SR_F:
20687 gen_reserved_instruction(ctx);
20688 break;
20690 break;
20691 case NM_SLTI:
20692 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20693 break;
20694 case NM_SLTIU:
20695 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20696 break;
20697 case NM_SEQI:
20699 TCGv t0 = tcg_temp_new();
20701 imm = extract32(ctx->opcode, 0, 12);
20702 gen_load_gpr(t0, rs);
20703 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20704 gen_store_gpr(t0, rt);
20706 tcg_temp_free(t0);
20708 break;
20709 case NM_ADDIUNEG:
20710 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20711 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20712 break;
20713 case NM_P_SHIFT:
20715 int shift = extract32(ctx->opcode, 0, 5);
20716 switch (extract32(ctx->opcode, 5, 4)) {
20717 case NM_P_SLL:
20718 if (rt == 0 && shift == 0) {
20719 /* NOP */
20720 } else if (rt == 0 && shift == 3) {
20721 /* EHB - treat as NOP */
20722 } else if (rt == 0 && shift == 5) {
20723 /* PAUSE - treat as NOP */
20724 } else if (rt == 0 && shift == 6) {
20725 /* SYNC */
20726 gen_sync(extract32(ctx->opcode, 16, 5));
20727 } else {
20728 /* SLL */
20729 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20730 extract32(ctx->opcode, 0, 5));
20732 break;
20733 case NM_SRL:
20734 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20735 extract32(ctx->opcode, 0, 5));
20736 break;
20737 case NM_SRA:
20738 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20739 extract32(ctx->opcode, 0, 5));
20740 break;
20741 case NM_ROTR:
20742 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20743 extract32(ctx->opcode, 0, 5));
20744 break;
20747 break;
20748 case NM_P_ROTX:
20749 check_nms(ctx);
20750 if (rt != 0) {
20751 TCGv t0 = tcg_temp_new();
20752 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20753 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20754 << 1);
20755 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20757 gen_load_gpr(t0, rs);
20758 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20759 tcg_temp_free(t0);
20761 tcg_temp_free_i32(shift);
20762 tcg_temp_free_i32(shiftx);
20763 tcg_temp_free_i32(stripe);
20765 break;
20766 case NM_P_INS:
20767 switch (((ctx->opcode >> 10) & 2) |
20768 (extract32(ctx->opcode, 5, 1))) {
20769 case NM_INS:
20770 check_nms(ctx);
20771 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20772 extract32(ctx->opcode, 6, 5));
20773 break;
20774 default:
20775 gen_reserved_instruction(ctx);
20776 break;
20778 break;
20779 case NM_P_EXT:
20780 switch (((ctx->opcode >> 10) & 2) |
20781 (extract32(ctx->opcode, 5, 1))) {
20782 case NM_EXT:
20783 check_nms(ctx);
20784 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20785 extract32(ctx->opcode, 6, 5));
20786 break;
20787 default:
20788 gen_reserved_instruction(ctx);
20789 break;
20791 break;
20792 default:
20793 gen_reserved_instruction(ctx);
20794 break;
20796 break;
20797 case NM_POOL32F:
20798 gen_pool32f_nanomips_insn(ctx);
20799 break;
20800 case NM_POOL32S:
20801 break;
20802 case NM_P_LUI:
20803 switch (extract32(ctx->opcode, 1, 1)) {
20804 case NM_LUI:
20805 if (rt != 0) {
20806 tcg_gen_movi_tl(cpu_gpr[rt],
20807 sextract32(ctx->opcode, 0, 1) << 31 |
20808 extract32(ctx->opcode, 2, 10) << 21 |
20809 extract32(ctx->opcode, 12, 9) << 12);
20811 break;
20812 case NM_ALUIPC:
20813 if (rt != 0) {
20814 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20815 extract32(ctx->opcode, 2, 10) << 21 |
20816 extract32(ctx->opcode, 12, 9) << 12;
20817 target_long addr;
20818 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20819 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20821 break;
20823 break;
20824 case NM_P_GP_BH:
20826 uint32_t u = extract32(ctx->opcode, 0, 18);
20828 switch (extract32(ctx->opcode, 18, 3)) {
20829 case NM_LBGP:
20830 gen_ld(ctx, OPC_LB, rt, 28, u);
20831 break;
20832 case NM_SBGP:
20833 gen_st(ctx, OPC_SB, rt, 28, u);
20834 break;
20835 case NM_LBUGP:
20836 gen_ld(ctx, OPC_LBU, rt, 28, u);
20837 break;
20838 case NM_ADDIUGP_B:
20839 if (rt != 0) {
20840 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
20842 break;
20843 case NM_P_GP_LH:
20844 u &= ~1;
20845 switch (ctx->opcode & 1) {
20846 case NM_LHGP:
20847 gen_ld(ctx, OPC_LH, rt, 28, u);
20848 break;
20849 case NM_LHUGP:
20850 gen_ld(ctx, OPC_LHU, rt, 28, u);
20851 break;
20853 break;
20854 case NM_P_GP_SH:
20855 u &= ~1;
20856 switch (ctx->opcode & 1) {
20857 case NM_SHGP:
20858 gen_st(ctx, OPC_SH, rt, 28, u);
20859 break;
20860 default:
20861 gen_reserved_instruction(ctx);
20862 break;
20864 break;
20865 case NM_P_GP_CP1:
20866 u &= ~0x3;
20867 switch (ctx->opcode & 0x3) {
20868 case NM_LWC1GP:
20869 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
20870 break;
20871 case NM_LDC1GP:
20872 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
20873 break;
20874 case NM_SWC1GP:
20875 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
20876 break;
20877 case NM_SDC1GP:
20878 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
20879 break;
20881 break;
20882 default:
20883 gen_reserved_instruction(ctx);
20884 break;
20887 break;
20888 case NM_P_LS_U12:
20890 uint32_t u = extract32(ctx->opcode, 0, 12);
20892 switch (extract32(ctx->opcode, 12, 4)) {
20893 case NM_P_PREFU12:
20894 if (rt == 31) {
20895 /* SYNCI */
20897 * Break the TB to be able to sync copied instructions
20898 * immediately.
20900 ctx->base.is_jmp = DISAS_STOP;
20901 } else {
20902 /* PREF */
20903 /* Treat as NOP. */
20905 break;
20906 case NM_LB:
20907 gen_ld(ctx, OPC_LB, rt, rs, u);
20908 break;
20909 case NM_LH:
20910 gen_ld(ctx, OPC_LH, rt, rs, u);
20911 break;
20912 case NM_LW:
20913 gen_ld(ctx, OPC_LW, rt, rs, u);
20914 break;
20915 case NM_LBU:
20916 gen_ld(ctx, OPC_LBU, rt, rs, u);
20917 break;
20918 case NM_LHU:
20919 gen_ld(ctx, OPC_LHU, rt, rs, u);
20920 break;
20921 case NM_SB:
20922 gen_st(ctx, OPC_SB, rt, rs, u);
20923 break;
20924 case NM_SH:
20925 gen_st(ctx, OPC_SH, rt, rs, u);
20926 break;
20927 case NM_SW:
20928 gen_st(ctx, OPC_SW, rt, rs, u);
20929 break;
20930 case NM_LWC1:
20931 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
20932 break;
20933 case NM_LDC1:
20934 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
20935 break;
20936 case NM_SWC1:
20937 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
20938 break;
20939 case NM_SDC1:
20940 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
20941 break;
20942 default:
20943 gen_reserved_instruction(ctx);
20944 break;
20947 break;
20948 case NM_P_LS_S9:
20950 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
20951 extract32(ctx->opcode, 0, 8);
20953 switch (extract32(ctx->opcode, 8, 3)) {
20954 case NM_P_LS_S0:
20955 switch (extract32(ctx->opcode, 11, 4)) {
20956 case NM_LBS9:
20957 gen_ld(ctx, OPC_LB, rt, rs, s);
20958 break;
20959 case NM_LHS9:
20960 gen_ld(ctx, OPC_LH, rt, rs, s);
20961 break;
20962 case NM_LWS9:
20963 gen_ld(ctx, OPC_LW, rt, rs, s);
20964 break;
20965 case NM_LBUS9:
20966 gen_ld(ctx, OPC_LBU, rt, rs, s);
20967 break;
20968 case NM_LHUS9:
20969 gen_ld(ctx, OPC_LHU, rt, rs, s);
20970 break;
20971 case NM_SBS9:
20972 gen_st(ctx, OPC_SB, rt, rs, s);
20973 break;
20974 case NM_SHS9:
20975 gen_st(ctx, OPC_SH, rt, rs, s);
20976 break;
20977 case NM_SWS9:
20978 gen_st(ctx, OPC_SW, rt, rs, s);
20979 break;
20980 case NM_LWC1S9:
20981 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
20982 break;
20983 case NM_LDC1S9:
20984 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
20985 break;
20986 case NM_SWC1S9:
20987 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
20988 break;
20989 case NM_SDC1S9:
20990 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
20991 break;
20992 case NM_P_PREFS9:
20993 if (rt == 31) {
20994 /* SYNCI */
20996 * Break the TB to be able to sync copied instructions
20997 * immediately.
20999 ctx->base.is_jmp = DISAS_STOP;
21000 } else {
21001 /* PREF */
21002 /* Treat as NOP. */
21004 break;
21005 default:
21006 gen_reserved_instruction(ctx);
21007 break;
21009 break;
21010 case NM_P_LS_S1:
21011 switch (extract32(ctx->opcode, 11, 4)) {
21012 case NM_UALH:
21013 case NM_UASH:
21014 check_nms(ctx);
21016 TCGv t0 = tcg_temp_new();
21017 TCGv t1 = tcg_temp_new();
21019 gen_base_offset_addr(ctx, t0, rs, s);
21021 switch (extract32(ctx->opcode, 11, 4)) {
21022 case NM_UALH:
21023 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21024 MO_UNALN);
21025 gen_store_gpr(t0, rt);
21026 break;
21027 case NM_UASH:
21028 gen_load_gpr(t1, rt);
21029 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21030 MO_UNALN);
21031 break;
21033 tcg_temp_free(t0);
21034 tcg_temp_free(t1);
21036 break;
21037 case NM_P_LL:
21038 switch (ctx->opcode & 0x03) {
21039 case NM_LL:
21040 gen_ld(ctx, OPC_LL, rt, rs, s);
21041 break;
21042 case NM_LLWP:
21043 check_xnp(ctx);
21044 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21045 break;
21047 break;
21048 case NM_P_SC:
21049 switch (ctx->opcode & 0x03) {
21050 case NM_SC:
21051 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21052 break;
21053 case NM_SCWP:
21054 check_xnp(ctx);
21055 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21056 false);
21057 break;
21059 break;
21060 case NM_CACHE:
21061 check_cp0_enabled(ctx);
21062 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21063 gen_cache_operation(ctx, rt, rs, s);
21065 break;
21067 break;
21068 case NM_P_LS_E0:
21069 switch (extract32(ctx->opcode, 11, 4)) {
21070 case NM_LBE:
21071 check_eva(ctx);
21072 check_cp0_enabled(ctx);
21073 gen_ld(ctx, OPC_LBE, rt, rs, s);
21074 break;
21075 case NM_SBE:
21076 check_eva(ctx);
21077 check_cp0_enabled(ctx);
21078 gen_st(ctx, OPC_SBE, rt, rs, s);
21079 break;
21080 case NM_LBUE:
21081 check_eva(ctx);
21082 check_cp0_enabled(ctx);
21083 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21084 break;
21085 case NM_P_PREFE:
21086 if (rt == 31) {
21087 /* case NM_SYNCIE */
21088 check_eva(ctx);
21089 check_cp0_enabled(ctx);
21091 * Break the TB to be able to sync copied instructions
21092 * immediately.
21094 ctx->base.is_jmp = DISAS_STOP;
21095 } else {
21096 /* case NM_PREFE */
21097 check_eva(ctx);
21098 check_cp0_enabled(ctx);
21099 /* Treat as NOP. */
21101 break;
21102 case NM_LHE:
21103 check_eva(ctx);
21104 check_cp0_enabled(ctx);
21105 gen_ld(ctx, OPC_LHE, rt, rs, s);
21106 break;
21107 case NM_SHE:
21108 check_eva(ctx);
21109 check_cp0_enabled(ctx);
21110 gen_st(ctx, OPC_SHE, rt, rs, s);
21111 break;
21112 case NM_LHUE:
21113 check_eva(ctx);
21114 check_cp0_enabled(ctx);
21115 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21116 break;
21117 case NM_CACHEE:
21118 check_nms_dl_il_sl_tl_l2c(ctx);
21119 gen_cache_operation(ctx, rt, rs, s);
21120 break;
21121 case NM_LWE:
21122 check_eva(ctx);
21123 check_cp0_enabled(ctx);
21124 gen_ld(ctx, OPC_LWE, rt, rs, s);
21125 break;
21126 case NM_SWE:
21127 check_eva(ctx);
21128 check_cp0_enabled(ctx);
21129 gen_st(ctx, OPC_SWE, rt, rs, s);
21130 break;
21131 case NM_P_LLE:
21132 switch (extract32(ctx->opcode, 2, 2)) {
21133 case NM_LLE:
21134 check_xnp(ctx);
21135 check_eva(ctx);
21136 check_cp0_enabled(ctx);
21137 gen_ld(ctx, OPC_LLE, rt, rs, s);
21138 break;
21139 case NM_LLWPE:
21140 check_xnp(ctx);
21141 check_eva(ctx);
21142 check_cp0_enabled(ctx);
21143 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21144 break;
21145 default:
21146 gen_reserved_instruction(ctx);
21147 break;
21149 break;
21150 case NM_P_SCE:
21151 switch (extract32(ctx->opcode, 2, 2)) {
21152 case NM_SCE:
21153 check_xnp(ctx);
21154 check_eva(ctx);
21155 check_cp0_enabled(ctx);
21156 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
21157 break;
21158 case NM_SCWPE:
21159 check_xnp(ctx);
21160 check_eva(ctx);
21161 check_cp0_enabled(ctx);
21162 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21163 true);
21164 break;
21165 default:
21166 gen_reserved_instruction(ctx);
21167 break;
21169 break;
21171 break;
21172 case NM_P_LS_WM:
21173 case NM_P_LS_UAWM:
21174 check_nms(ctx);
21176 int count = extract32(ctx->opcode, 12, 3);
21177 int counter = 0;
21179 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21180 extract32(ctx->opcode, 0, 8);
21181 TCGv va = tcg_temp_new();
21182 TCGv t1 = tcg_temp_new();
21183 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21184 NM_P_LS_UAWM ? MO_UNALN : 0;
21186 count = (count == 0) ? 8 : count;
21187 while (counter != count) {
21188 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21189 int this_offset = offset + (counter << 2);
21191 gen_base_offset_addr(ctx, va, rs, this_offset);
21193 switch (extract32(ctx->opcode, 11, 1)) {
21194 case NM_LWM:
21195 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21196 memop | MO_TESL);
21197 gen_store_gpr(t1, this_rt);
21198 if ((this_rt == rs) &&
21199 (counter != (count - 1))) {
21200 /* UNPREDICTABLE */
21202 break;
21203 case NM_SWM:
21204 this_rt = (rt == 0) ? 0 : this_rt;
21205 gen_load_gpr(t1, this_rt);
21206 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21207 memop | MO_TEUL);
21208 break;
21210 counter++;
21212 tcg_temp_free(va);
21213 tcg_temp_free(t1);
21215 break;
21216 default:
21217 gen_reserved_instruction(ctx);
21218 break;
21221 break;
21222 case NM_MOVE_BALC:
21223 check_nms(ctx);
21225 TCGv t0 = tcg_temp_new();
21226 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21227 extract32(ctx->opcode, 1, 20) << 1;
21228 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21229 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21230 extract32(ctx->opcode, 21, 3));
21231 gen_load_gpr(t0, rt);
21232 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21233 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21234 tcg_temp_free(t0);
21236 break;
21237 case NM_P_BAL:
21239 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21240 extract32(ctx->opcode, 1, 24) << 1;
21242 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21243 /* BC */
21244 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21245 } else {
21246 /* BALC */
21247 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21250 break;
21251 case NM_P_J:
21252 switch (extract32(ctx->opcode, 12, 4)) {
21253 case NM_JALRC:
21254 case NM_JALRC_HB:
21255 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21256 break;
21257 case NM_P_BALRSC:
21258 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21259 break;
21260 default:
21261 gen_reserved_instruction(ctx);
21262 break;
21264 break;
21265 case NM_P_BR1:
21267 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21268 extract32(ctx->opcode, 1, 13) << 1;
21269 switch (extract32(ctx->opcode, 14, 2)) {
21270 case NM_BEQC:
21271 check_nms(ctx);
21272 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21273 break;
21274 case NM_P_BR3A:
21275 s = sextract32(ctx->opcode, 0, 1) << 14 |
21276 extract32(ctx->opcode, 1, 13) << 1;
21277 check_cp1_enabled(ctx);
21278 switch (extract32(ctx->opcode, 16, 5)) {
21279 case NM_BC1EQZC:
21280 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21281 break;
21282 case NM_BC1NEZC:
21283 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21284 break;
21285 case NM_BPOSGE32C:
21286 check_dsp_r3(ctx);
21288 int32_t imm = extract32(ctx->opcode, 1, 13) |
21289 extract32(ctx->opcode, 0, 1) << 13;
21291 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21292 imm);
21294 break;
21295 default:
21296 gen_reserved_instruction(ctx);
21297 break;
21299 break;
21300 case NM_BGEC:
21301 if (rs == rt) {
21302 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21303 } else {
21304 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21306 break;
21307 case NM_BGEUC:
21308 if (rs == rt || rt == 0) {
21309 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21310 } else if (rs == 0) {
21311 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21312 } else {
21313 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21315 break;
21318 break;
21319 case NM_P_BR2:
21321 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21322 extract32(ctx->opcode, 1, 13) << 1;
21323 switch (extract32(ctx->opcode, 14, 2)) {
21324 case NM_BNEC:
21325 check_nms(ctx);
21326 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21327 break;
21328 case NM_BLTC:
21329 if (rs != 0 && rt != 0 && rs == rt) {
21330 /* NOP */
21331 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21332 } else {
21333 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21335 break;
21336 case NM_BLTUC:
21337 if (rs == 0 || rs == rt) {
21338 /* NOP */
21339 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21340 } else {
21341 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21343 break;
21344 default:
21345 gen_reserved_instruction(ctx);
21346 break;
21349 break;
21350 case NM_P_BRI:
21352 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21353 extract32(ctx->opcode, 1, 10) << 1;
21354 uint32_t u = extract32(ctx->opcode, 11, 7);
21356 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21357 rt, u, s);
21359 break;
21360 default:
21361 gen_reserved_instruction(ctx);
21362 break;
21364 return 4;
21367 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21369 uint32_t op;
21370 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
21371 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21372 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
21373 int offset;
21374 int imm;
21376 /* make sure instructions are on a halfword boundary */
21377 if (ctx->base.pc_next & 0x1) {
21378 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21379 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21380 tcg_temp_free(tmp);
21381 generate_exception_end(ctx, EXCP_AdEL);
21382 return 2;
21385 op = extract32(ctx->opcode, 10, 6);
21386 switch (op) {
21387 case NM_P16_MV:
21388 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21389 if (rt != 0) {
21390 /* MOVE */
21391 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21392 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21393 } else {
21394 /* P16.RI */
21395 switch (extract32(ctx->opcode, 3, 2)) {
21396 case NM_P16_SYSCALL:
21397 if (extract32(ctx->opcode, 2, 1) == 0) {
21398 generate_exception_end(ctx, EXCP_SYSCALL);
21399 } else {
21400 gen_reserved_instruction(ctx);
21402 break;
21403 case NM_BREAK16:
21404 generate_exception_end(ctx, EXCP_BREAK);
21405 break;
21406 case NM_SDBBP16:
21407 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21408 gen_helper_do_semihosting(cpu_env);
21409 } else {
21410 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21411 gen_reserved_instruction(ctx);
21412 } else {
21413 generate_exception_end(ctx, EXCP_DBp);
21416 break;
21417 default:
21418 gen_reserved_instruction(ctx);
21419 break;
21422 break;
21423 case NM_P16_SHIFT:
21425 int shift = extract32(ctx->opcode, 0, 3);
21426 uint32_t opc = 0;
21427 shift = (shift == 0) ? 8 : shift;
21429 switch (extract32(ctx->opcode, 3, 1)) {
21430 case NM_SLL16:
21431 opc = OPC_SLL;
21432 break;
21433 case NM_SRL16:
21434 opc = OPC_SRL;
21435 break;
21437 gen_shift_imm(ctx, opc, rt, rs, shift);
21439 break;
21440 case NM_P16C:
21441 switch (ctx->opcode & 1) {
21442 case NM_POOL16C_0:
21443 gen_pool16c_nanomips_insn(ctx);
21444 break;
21445 case NM_LWXS16:
21446 gen_ldxs(ctx, rt, rs, rd);
21447 break;
21449 break;
21450 case NM_P16_A1:
21451 switch (extract32(ctx->opcode, 6, 1)) {
21452 case NM_ADDIUR1SP:
21453 imm = extract32(ctx->opcode, 0, 6) << 2;
21454 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21455 break;
21456 default:
21457 gen_reserved_instruction(ctx);
21458 break;
21460 break;
21461 case NM_P16_A2:
21462 switch (extract32(ctx->opcode, 3, 1)) {
21463 case NM_ADDIUR2:
21464 imm = extract32(ctx->opcode, 0, 3) << 2;
21465 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21466 break;
21467 case NM_P_ADDIURS5:
21468 rt = extract32(ctx->opcode, 5, 5);
21469 if (rt != 0) {
21470 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21471 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21472 (extract32(ctx->opcode, 0, 3));
21473 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21475 break;
21477 break;
21478 case NM_P16_ADDU:
21479 switch (ctx->opcode & 0x1) {
21480 case NM_ADDU16:
21481 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21482 break;
21483 case NM_SUBU16:
21484 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21485 break;
21487 break;
21488 case NM_P16_4X4:
21489 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21490 extract32(ctx->opcode, 5, 3);
21491 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21492 extract32(ctx->opcode, 0, 3);
21493 rt = decode_gpr_gpr4(rt);
21494 rs = decode_gpr_gpr4(rs);
21495 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21496 (extract32(ctx->opcode, 3, 1))) {
21497 case NM_ADDU4X4:
21498 check_nms(ctx);
21499 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21500 break;
21501 case NM_MUL4X4:
21502 check_nms(ctx);
21503 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21504 break;
21505 default:
21506 gen_reserved_instruction(ctx);
21507 break;
21509 break;
21510 case NM_LI16:
21512 int imm = extract32(ctx->opcode, 0, 7);
21513 imm = (imm == 0x7f ? -1 : imm);
21514 if (rt != 0) {
21515 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21518 break;
21519 case NM_ANDI16:
21521 uint32_t u = extract32(ctx->opcode, 0, 4);
21522 u = (u == 12) ? 0xff :
21523 (u == 13) ? 0xffff : u;
21524 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21526 break;
21527 case NM_P16_LB:
21528 offset = extract32(ctx->opcode, 0, 2);
21529 switch (extract32(ctx->opcode, 2, 2)) {
21530 case NM_LB16:
21531 gen_ld(ctx, OPC_LB, rt, rs, offset);
21532 break;
21533 case NM_SB16:
21534 rt = decode_gpr_gpr3_src_store(
21535 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21536 gen_st(ctx, OPC_SB, rt, rs, offset);
21537 break;
21538 case NM_LBU16:
21539 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21540 break;
21541 default:
21542 gen_reserved_instruction(ctx);
21543 break;
21545 break;
21546 case NM_P16_LH:
21547 offset = extract32(ctx->opcode, 1, 2) << 1;
21548 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21549 case NM_LH16:
21550 gen_ld(ctx, OPC_LH, rt, rs, offset);
21551 break;
21552 case NM_SH16:
21553 rt = decode_gpr_gpr3_src_store(
21554 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21555 gen_st(ctx, OPC_SH, rt, rs, offset);
21556 break;
21557 case NM_LHU16:
21558 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21559 break;
21560 default:
21561 gen_reserved_instruction(ctx);
21562 break;
21564 break;
21565 case NM_LW16:
21566 offset = extract32(ctx->opcode, 0, 4) << 2;
21567 gen_ld(ctx, OPC_LW, rt, rs, offset);
21568 break;
21569 case NM_LWSP16:
21570 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21571 offset = extract32(ctx->opcode, 0, 5) << 2;
21572 gen_ld(ctx, OPC_LW, rt, 29, offset);
21573 break;
21574 case NM_LW4X4:
21575 check_nms(ctx);
21576 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21577 extract32(ctx->opcode, 5, 3);
21578 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21579 extract32(ctx->opcode, 0, 3);
21580 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21581 (extract32(ctx->opcode, 8, 1) << 2);
21582 rt = decode_gpr_gpr4(rt);
21583 rs = decode_gpr_gpr4(rs);
21584 gen_ld(ctx, OPC_LW, rt, rs, offset);
21585 break;
21586 case NM_SW4X4:
21587 check_nms(ctx);
21588 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21589 extract32(ctx->opcode, 5, 3);
21590 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21591 extract32(ctx->opcode, 0, 3);
21592 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21593 (extract32(ctx->opcode, 8, 1) << 2);
21594 rt = decode_gpr_gpr4_zero(rt);
21595 rs = decode_gpr_gpr4(rs);
21596 gen_st(ctx, OPC_SW, rt, rs, offset);
21597 break;
21598 case NM_LWGP16:
21599 offset = extract32(ctx->opcode, 0, 7) << 2;
21600 gen_ld(ctx, OPC_LW, rt, 28, offset);
21601 break;
21602 case NM_SWSP16:
21603 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21604 offset = extract32(ctx->opcode, 0, 5) << 2;
21605 gen_st(ctx, OPC_SW, rt, 29, offset);
21606 break;
21607 case NM_SW16:
21608 rt = decode_gpr_gpr3_src_store(
21609 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21610 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21611 offset = extract32(ctx->opcode, 0, 4) << 2;
21612 gen_st(ctx, OPC_SW, rt, rs, offset);
21613 break;
21614 case NM_SWGP16:
21615 rt = decode_gpr_gpr3_src_store(
21616 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21617 offset = extract32(ctx->opcode, 0, 7) << 2;
21618 gen_st(ctx, OPC_SW, rt, 28, offset);
21619 break;
21620 case NM_BC16:
21621 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21622 (sextract32(ctx->opcode, 0, 1) << 10) |
21623 (extract32(ctx->opcode, 1, 9) << 1));
21624 break;
21625 case NM_BALC16:
21626 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21627 (sextract32(ctx->opcode, 0, 1) << 10) |
21628 (extract32(ctx->opcode, 1, 9) << 1));
21629 break;
21630 case NM_BEQZC16:
21631 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21632 (sextract32(ctx->opcode, 0, 1) << 7) |
21633 (extract32(ctx->opcode, 1, 6) << 1));
21634 break;
21635 case NM_BNEZC16:
21636 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21637 (sextract32(ctx->opcode, 0, 1) << 7) |
21638 (extract32(ctx->opcode, 1, 6) << 1));
21639 break;
21640 case NM_P16_BR:
21641 switch (ctx->opcode & 0xf) {
21642 case 0:
21643 /* P16.JRC */
21644 switch (extract32(ctx->opcode, 4, 1)) {
21645 case NM_JRC:
21646 gen_compute_branch_nm(ctx, OPC_JR, 2,
21647 extract32(ctx->opcode, 5, 5), 0, 0);
21648 break;
21649 case NM_JALRC16:
21650 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21651 extract32(ctx->opcode, 5, 5), 31, 0);
21652 break;
21654 break;
21655 default:
21657 /* P16.BRI */
21658 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21659 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21660 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21661 extract32(ctx->opcode, 0, 4) << 1);
21663 break;
21665 break;
21666 case NM_P16_SR:
21668 int count = extract32(ctx->opcode, 0, 4);
21669 int u = extract32(ctx->opcode, 4, 4) << 4;
21671 rt = 30 + extract32(ctx->opcode, 9, 1);
21672 switch (extract32(ctx->opcode, 8, 1)) {
21673 case NM_SAVE16:
21674 gen_save(ctx, rt, count, 0, u);
21675 break;
21676 case NM_RESTORE_JRC16:
21677 gen_restore(ctx, rt, count, 0, u);
21678 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21679 break;
21682 break;
21683 case NM_MOVEP:
21684 case NM_MOVEPREV:
21685 check_nms(ctx);
21687 static const int gpr2reg1[] = {4, 5, 6, 7};
21688 static const int gpr2reg2[] = {5, 6, 7, 8};
21689 int re;
21690 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21691 extract32(ctx->opcode, 8, 1);
21692 int r1 = gpr2reg1[rd2];
21693 int r2 = gpr2reg2[rd2];
21694 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21695 extract32(ctx->opcode, 0, 3);
21696 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21697 extract32(ctx->opcode, 5, 3);
21698 TCGv t0 = tcg_temp_new();
21699 TCGv t1 = tcg_temp_new();
21700 if (op == NM_MOVEP) {
21701 rd = r1;
21702 re = r2;
21703 rs = decode_gpr_gpr4_zero(r3);
21704 rt = decode_gpr_gpr4_zero(r4);
21705 } else {
21706 rd = decode_gpr_gpr4(r3);
21707 re = decode_gpr_gpr4(r4);
21708 rs = r1;
21709 rt = r2;
21711 gen_load_gpr(t0, rs);
21712 gen_load_gpr(t1, rt);
21713 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21714 tcg_gen_mov_tl(cpu_gpr[re], t1);
21715 tcg_temp_free(t0);
21716 tcg_temp_free(t1);
21718 break;
21719 default:
21720 return decode_nanomips_32_48_opc(env, ctx);
21723 return 2;
21727 /* SmartMIPS extension to MIPS32 */
21729 #if defined(TARGET_MIPS64)
21731 /* MDMX extension to MIPS64 */
21733 #endif
21735 /* MIPSDSP functions. */
21736 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21737 int rd, int base, int offset)
21739 TCGv t0;
21741 check_dsp(ctx);
21742 t0 = tcg_temp_new();
21744 if (base == 0) {
21745 gen_load_gpr(t0, offset);
21746 } else if (offset == 0) {
21747 gen_load_gpr(t0, base);
21748 } else {
21749 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21752 switch (opc) {
21753 case OPC_LBUX:
21754 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21755 gen_store_gpr(t0, rd);
21756 break;
21757 case OPC_LHX:
21758 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21759 gen_store_gpr(t0, rd);
21760 break;
21761 case OPC_LWX:
21762 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21763 gen_store_gpr(t0, rd);
21764 break;
21765 #if defined(TARGET_MIPS64)
21766 case OPC_LDX:
21767 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21768 gen_store_gpr(t0, rd);
21769 break;
21770 #endif
21772 tcg_temp_free(t0);
21775 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21776 int ret, int v1, int v2)
21778 TCGv v1_t;
21779 TCGv v2_t;
21781 if (ret == 0) {
21782 /* Treat as NOP. */
21783 return;
21786 v1_t = tcg_temp_new();
21787 v2_t = tcg_temp_new();
21789 gen_load_gpr(v1_t, v1);
21790 gen_load_gpr(v2_t, v2);
21792 switch (op1) {
21793 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21794 case OPC_MULT_G_2E:
21795 check_dsp_r2(ctx);
21796 switch (op2) {
21797 case OPC_ADDUH_QB:
21798 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21799 break;
21800 case OPC_ADDUH_R_QB:
21801 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21802 break;
21803 case OPC_ADDQH_PH:
21804 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21805 break;
21806 case OPC_ADDQH_R_PH:
21807 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21808 break;
21809 case OPC_ADDQH_W:
21810 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21811 break;
21812 case OPC_ADDQH_R_W:
21813 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21814 break;
21815 case OPC_SUBUH_QB:
21816 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21817 break;
21818 case OPC_SUBUH_R_QB:
21819 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21820 break;
21821 case OPC_SUBQH_PH:
21822 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
21823 break;
21824 case OPC_SUBQH_R_PH:
21825 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21826 break;
21827 case OPC_SUBQH_W:
21828 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
21829 break;
21830 case OPC_SUBQH_R_W:
21831 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21832 break;
21834 break;
21835 case OPC_ABSQ_S_PH_DSP:
21836 switch (op2) {
21837 case OPC_ABSQ_S_QB:
21838 check_dsp_r2(ctx);
21839 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
21840 break;
21841 case OPC_ABSQ_S_PH:
21842 check_dsp(ctx);
21843 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
21844 break;
21845 case OPC_ABSQ_S_W:
21846 check_dsp(ctx);
21847 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
21848 break;
21849 case OPC_PRECEQ_W_PHL:
21850 check_dsp(ctx);
21851 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
21852 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21853 break;
21854 case OPC_PRECEQ_W_PHR:
21855 check_dsp(ctx);
21856 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
21857 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
21858 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21859 break;
21860 case OPC_PRECEQU_PH_QBL:
21861 check_dsp(ctx);
21862 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
21863 break;
21864 case OPC_PRECEQU_PH_QBR:
21865 check_dsp(ctx);
21866 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
21867 break;
21868 case OPC_PRECEQU_PH_QBLA:
21869 check_dsp(ctx);
21870 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
21871 break;
21872 case OPC_PRECEQU_PH_QBRA:
21873 check_dsp(ctx);
21874 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
21875 break;
21876 case OPC_PRECEU_PH_QBL:
21877 check_dsp(ctx);
21878 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
21879 break;
21880 case OPC_PRECEU_PH_QBR:
21881 check_dsp(ctx);
21882 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
21883 break;
21884 case OPC_PRECEU_PH_QBLA:
21885 check_dsp(ctx);
21886 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
21887 break;
21888 case OPC_PRECEU_PH_QBRA:
21889 check_dsp(ctx);
21890 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
21891 break;
21893 break;
21894 case OPC_ADDU_QB_DSP:
21895 switch (op2) {
21896 case OPC_ADDQ_PH:
21897 check_dsp(ctx);
21898 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21899 break;
21900 case OPC_ADDQ_S_PH:
21901 check_dsp(ctx);
21902 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21903 break;
21904 case OPC_ADDQ_S_W:
21905 check_dsp(ctx);
21906 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21907 break;
21908 case OPC_ADDU_QB:
21909 check_dsp(ctx);
21910 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21911 break;
21912 case OPC_ADDU_S_QB:
21913 check_dsp(ctx);
21914 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21915 break;
21916 case OPC_ADDU_PH:
21917 check_dsp_r2(ctx);
21918 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21919 break;
21920 case OPC_ADDU_S_PH:
21921 check_dsp_r2(ctx);
21922 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21923 break;
21924 case OPC_SUBQ_PH:
21925 check_dsp(ctx);
21926 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21927 break;
21928 case OPC_SUBQ_S_PH:
21929 check_dsp(ctx);
21930 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21931 break;
21932 case OPC_SUBQ_S_W:
21933 check_dsp(ctx);
21934 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21935 break;
21936 case OPC_SUBU_QB:
21937 check_dsp(ctx);
21938 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21939 break;
21940 case OPC_SUBU_S_QB:
21941 check_dsp(ctx);
21942 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21943 break;
21944 case OPC_SUBU_PH:
21945 check_dsp_r2(ctx);
21946 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21947 break;
21948 case OPC_SUBU_S_PH:
21949 check_dsp_r2(ctx);
21950 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21951 break;
21952 case OPC_ADDSC:
21953 check_dsp(ctx);
21954 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21955 break;
21956 case OPC_ADDWC:
21957 check_dsp(ctx);
21958 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21959 break;
21960 case OPC_MODSUB:
21961 check_dsp(ctx);
21962 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
21963 break;
21964 case OPC_RADDU_W_QB:
21965 check_dsp(ctx);
21966 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
21967 break;
21969 break;
21970 case OPC_CMPU_EQ_QB_DSP:
21971 switch (op2) {
21972 case OPC_PRECR_QB_PH:
21973 check_dsp_r2(ctx);
21974 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21975 break;
21976 case OPC_PRECRQ_QB_PH:
21977 check_dsp(ctx);
21978 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21979 break;
21980 case OPC_PRECR_SRA_PH_W:
21981 check_dsp_r2(ctx);
21983 TCGv_i32 sa_t = tcg_const_i32(v2);
21984 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
21985 cpu_gpr[ret]);
21986 tcg_temp_free_i32(sa_t);
21987 break;
21989 case OPC_PRECR_SRA_R_PH_W:
21990 check_dsp_r2(ctx);
21992 TCGv_i32 sa_t = tcg_const_i32(v2);
21993 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
21994 cpu_gpr[ret]);
21995 tcg_temp_free_i32(sa_t);
21996 break;
21998 case OPC_PRECRQ_PH_W:
21999 check_dsp(ctx);
22000 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22001 break;
22002 case OPC_PRECRQ_RS_PH_W:
22003 check_dsp(ctx);
22004 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22005 break;
22006 case OPC_PRECRQU_S_QB_PH:
22007 check_dsp(ctx);
22008 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22009 break;
22011 break;
22012 #ifdef TARGET_MIPS64
22013 case OPC_ABSQ_S_QH_DSP:
22014 switch (op2) {
22015 case OPC_PRECEQ_L_PWL:
22016 check_dsp(ctx);
22017 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22018 break;
22019 case OPC_PRECEQ_L_PWR:
22020 check_dsp(ctx);
22021 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22022 break;
22023 case OPC_PRECEQ_PW_QHL:
22024 check_dsp(ctx);
22025 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22026 break;
22027 case OPC_PRECEQ_PW_QHR:
22028 check_dsp(ctx);
22029 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22030 break;
22031 case OPC_PRECEQ_PW_QHLA:
22032 check_dsp(ctx);
22033 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22034 break;
22035 case OPC_PRECEQ_PW_QHRA:
22036 check_dsp(ctx);
22037 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22038 break;
22039 case OPC_PRECEQU_QH_OBL:
22040 check_dsp(ctx);
22041 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22042 break;
22043 case OPC_PRECEQU_QH_OBR:
22044 check_dsp(ctx);
22045 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22046 break;
22047 case OPC_PRECEQU_QH_OBLA:
22048 check_dsp(ctx);
22049 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22050 break;
22051 case OPC_PRECEQU_QH_OBRA:
22052 check_dsp(ctx);
22053 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22054 break;
22055 case OPC_PRECEU_QH_OBL:
22056 check_dsp(ctx);
22057 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22058 break;
22059 case OPC_PRECEU_QH_OBR:
22060 check_dsp(ctx);
22061 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22062 break;
22063 case OPC_PRECEU_QH_OBLA:
22064 check_dsp(ctx);
22065 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22066 break;
22067 case OPC_PRECEU_QH_OBRA:
22068 check_dsp(ctx);
22069 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22070 break;
22071 case OPC_ABSQ_S_OB:
22072 check_dsp_r2(ctx);
22073 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22074 break;
22075 case OPC_ABSQ_S_PW:
22076 check_dsp(ctx);
22077 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22078 break;
22079 case OPC_ABSQ_S_QH:
22080 check_dsp(ctx);
22081 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22082 break;
22084 break;
22085 case OPC_ADDU_OB_DSP:
22086 switch (op2) {
22087 case OPC_RADDU_L_OB:
22088 check_dsp(ctx);
22089 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22090 break;
22091 case OPC_SUBQ_PW:
22092 check_dsp(ctx);
22093 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22094 break;
22095 case OPC_SUBQ_S_PW:
22096 check_dsp(ctx);
22097 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22098 break;
22099 case OPC_SUBQ_QH:
22100 check_dsp(ctx);
22101 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22102 break;
22103 case OPC_SUBQ_S_QH:
22104 check_dsp(ctx);
22105 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22106 break;
22107 case OPC_SUBU_OB:
22108 check_dsp(ctx);
22109 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22110 break;
22111 case OPC_SUBU_S_OB:
22112 check_dsp(ctx);
22113 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22114 break;
22115 case OPC_SUBU_QH:
22116 check_dsp_r2(ctx);
22117 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22118 break;
22119 case OPC_SUBU_S_QH:
22120 check_dsp_r2(ctx);
22121 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22122 break;
22123 case OPC_SUBUH_OB:
22124 check_dsp_r2(ctx);
22125 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22126 break;
22127 case OPC_SUBUH_R_OB:
22128 check_dsp_r2(ctx);
22129 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22130 break;
22131 case OPC_ADDQ_PW:
22132 check_dsp(ctx);
22133 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22134 break;
22135 case OPC_ADDQ_S_PW:
22136 check_dsp(ctx);
22137 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22138 break;
22139 case OPC_ADDQ_QH:
22140 check_dsp(ctx);
22141 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22142 break;
22143 case OPC_ADDQ_S_QH:
22144 check_dsp(ctx);
22145 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22146 break;
22147 case OPC_ADDU_OB:
22148 check_dsp(ctx);
22149 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22150 break;
22151 case OPC_ADDU_S_OB:
22152 check_dsp(ctx);
22153 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22154 break;
22155 case OPC_ADDU_QH:
22156 check_dsp_r2(ctx);
22157 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22158 break;
22159 case OPC_ADDU_S_QH:
22160 check_dsp_r2(ctx);
22161 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22162 break;
22163 case OPC_ADDUH_OB:
22164 check_dsp_r2(ctx);
22165 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22166 break;
22167 case OPC_ADDUH_R_OB:
22168 check_dsp_r2(ctx);
22169 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22170 break;
22172 break;
22173 case OPC_CMPU_EQ_OB_DSP:
22174 switch (op2) {
22175 case OPC_PRECR_OB_QH:
22176 check_dsp_r2(ctx);
22177 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22178 break;
22179 case OPC_PRECR_SRA_QH_PW:
22180 check_dsp_r2(ctx);
22182 TCGv_i32 ret_t = tcg_const_i32(ret);
22183 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22184 tcg_temp_free_i32(ret_t);
22185 break;
22187 case OPC_PRECR_SRA_R_QH_PW:
22188 check_dsp_r2(ctx);
22190 TCGv_i32 sa_v = tcg_const_i32(ret);
22191 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22192 tcg_temp_free_i32(sa_v);
22193 break;
22195 case OPC_PRECRQ_OB_QH:
22196 check_dsp(ctx);
22197 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22198 break;
22199 case OPC_PRECRQ_PW_L:
22200 check_dsp(ctx);
22201 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22202 break;
22203 case OPC_PRECRQ_QH_PW:
22204 check_dsp(ctx);
22205 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22206 break;
22207 case OPC_PRECRQ_RS_QH_PW:
22208 check_dsp(ctx);
22209 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22210 break;
22211 case OPC_PRECRQU_S_OB_QH:
22212 check_dsp(ctx);
22213 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22214 break;
22216 break;
22217 #endif
22220 tcg_temp_free(v1_t);
22221 tcg_temp_free(v2_t);
22224 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22225 int ret, int v1, int v2)
22227 uint32_t op2;
22228 TCGv t0;
22229 TCGv v1_t;
22230 TCGv v2_t;
22232 if (ret == 0) {
22233 /* Treat as NOP. */
22234 return;
22237 t0 = tcg_temp_new();
22238 v1_t = tcg_temp_new();
22239 v2_t = tcg_temp_new();
22241 tcg_gen_movi_tl(t0, v1);
22242 gen_load_gpr(v1_t, v1);
22243 gen_load_gpr(v2_t, v2);
22245 switch (opc) {
22246 case OPC_SHLL_QB_DSP:
22248 op2 = MASK_SHLL_QB(ctx->opcode);
22249 switch (op2) {
22250 case OPC_SHLL_QB:
22251 check_dsp(ctx);
22252 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22253 break;
22254 case OPC_SHLLV_QB:
22255 check_dsp(ctx);
22256 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22257 break;
22258 case OPC_SHLL_PH:
22259 check_dsp(ctx);
22260 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22261 break;
22262 case OPC_SHLLV_PH:
22263 check_dsp(ctx);
22264 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22265 break;
22266 case OPC_SHLL_S_PH:
22267 check_dsp(ctx);
22268 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22269 break;
22270 case OPC_SHLLV_S_PH:
22271 check_dsp(ctx);
22272 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22273 break;
22274 case OPC_SHLL_S_W:
22275 check_dsp(ctx);
22276 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22277 break;
22278 case OPC_SHLLV_S_W:
22279 check_dsp(ctx);
22280 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22281 break;
22282 case OPC_SHRL_QB:
22283 check_dsp(ctx);
22284 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22285 break;
22286 case OPC_SHRLV_QB:
22287 check_dsp(ctx);
22288 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22289 break;
22290 case OPC_SHRL_PH:
22291 check_dsp_r2(ctx);
22292 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22293 break;
22294 case OPC_SHRLV_PH:
22295 check_dsp_r2(ctx);
22296 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22297 break;
22298 case OPC_SHRA_QB:
22299 check_dsp_r2(ctx);
22300 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22301 break;
22302 case OPC_SHRA_R_QB:
22303 check_dsp_r2(ctx);
22304 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22305 break;
22306 case OPC_SHRAV_QB:
22307 check_dsp_r2(ctx);
22308 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22309 break;
22310 case OPC_SHRAV_R_QB:
22311 check_dsp_r2(ctx);
22312 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22313 break;
22314 case OPC_SHRA_PH:
22315 check_dsp(ctx);
22316 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22317 break;
22318 case OPC_SHRA_R_PH:
22319 check_dsp(ctx);
22320 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22321 break;
22322 case OPC_SHRAV_PH:
22323 check_dsp(ctx);
22324 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22325 break;
22326 case OPC_SHRAV_R_PH:
22327 check_dsp(ctx);
22328 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22329 break;
22330 case OPC_SHRA_R_W:
22331 check_dsp(ctx);
22332 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22333 break;
22334 case OPC_SHRAV_R_W:
22335 check_dsp(ctx);
22336 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22337 break;
22338 default: /* Invalid */
22339 MIPS_INVAL("MASK SHLL.QB");
22340 gen_reserved_instruction(ctx);
22341 break;
22343 break;
22345 #ifdef TARGET_MIPS64
22346 case OPC_SHLL_OB_DSP:
22347 op2 = MASK_SHLL_OB(ctx->opcode);
22348 switch (op2) {
22349 case OPC_SHLL_PW:
22350 check_dsp(ctx);
22351 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22352 break;
22353 case OPC_SHLLV_PW:
22354 check_dsp(ctx);
22355 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22356 break;
22357 case OPC_SHLL_S_PW:
22358 check_dsp(ctx);
22359 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22360 break;
22361 case OPC_SHLLV_S_PW:
22362 check_dsp(ctx);
22363 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22364 break;
22365 case OPC_SHLL_OB:
22366 check_dsp(ctx);
22367 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22368 break;
22369 case OPC_SHLLV_OB:
22370 check_dsp(ctx);
22371 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22372 break;
22373 case OPC_SHLL_QH:
22374 check_dsp(ctx);
22375 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22376 break;
22377 case OPC_SHLLV_QH:
22378 check_dsp(ctx);
22379 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22380 break;
22381 case OPC_SHLL_S_QH:
22382 check_dsp(ctx);
22383 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22384 break;
22385 case OPC_SHLLV_S_QH:
22386 check_dsp(ctx);
22387 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22388 break;
22389 case OPC_SHRA_OB:
22390 check_dsp_r2(ctx);
22391 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22392 break;
22393 case OPC_SHRAV_OB:
22394 check_dsp_r2(ctx);
22395 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22396 break;
22397 case OPC_SHRA_R_OB:
22398 check_dsp_r2(ctx);
22399 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22400 break;
22401 case OPC_SHRAV_R_OB:
22402 check_dsp_r2(ctx);
22403 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22404 break;
22405 case OPC_SHRA_PW:
22406 check_dsp(ctx);
22407 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22408 break;
22409 case OPC_SHRAV_PW:
22410 check_dsp(ctx);
22411 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22412 break;
22413 case OPC_SHRA_R_PW:
22414 check_dsp(ctx);
22415 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22416 break;
22417 case OPC_SHRAV_R_PW:
22418 check_dsp(ctx);
22419 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22420 break;
22421 case OPC_SHRA_QH:
22422 check_dsp(ctx);
22423 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22424 break;
22425 case OPC_SHRAV_QH:
22426 check_dsp(ctx);
22427 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22428 break;
22429 case OPC_SHRA_R_QH:
22430 check_dsp(ctx);
22431 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22432 break;
22433 case OPC_SHRAV_R_QH:
22434 check_dsp(ctx);
22435 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22436 break;
22437 case OPC_SHRL_OB:
22438 check_dsp(ctx);
22439 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22440 break;
22441 case OPC_SHRLV_OB:
22442 check_dsp(ctx);
22443 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22444 break;
22445 case OPC_SHRL_QH:
22446 check_dsp_r2(ctx);
22447 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22448 break;
22449 case OPC_SHRLV_QH:
22450 check_dsp_r2(ctx);
22451 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22452 break;
22453 default: /* Invalid */
22454 MIPS_INVAL("MASK SHLL.OB");
22455 gen_reserved_instruction(ctx);
22456 break;
22458 break;
22459 #endif
22462 tcg_temp_free(t0);
22463 tcg_temp_free(v1_t);
22464 tcg_temp_free(v2_t);
22467 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22468 int ret, int v1, int v2, int check_ret)
22470 TCGv_i32 t0;
22471 TCGv v1_t;
22472 TCGv v2_t;
22474 if ((ret == 0) && (check_ret == 1)) {
22475 /* Treat as NOP. */
22476 return;
22479 t0 = tcg_temp_new_i32();
22480 v1_t = tcg_temp_new();
22481 v2_t = tcg_temp_new();
22483 tcg_gen_movi_i32(t0, ret);
22484 gen_load_gpr(v1_t, v1);
22485 gen_load_gpr(v2_t, v2);
22487 switch (op1) {
22489 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22490 * the same mask and op1.
22492 case OPC_MULT_G_2E:
22493 check_dsp_r2(ctx);
22494 switch (op2) {
22495 case OPC_MUL_PH:
22496 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22497 break;
22498 case OPC_MUL_S_PH:
22499 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22500 break;
22501 case OPC_MULQ_S_W:
22502 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22503 break;
22504 case OPC_MULQ_RS_W:
22505 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22506 break;
22508 break;
22509 case OPC_DPA_W_PH_DSP:
22510 switch (op2) {
22511 case OPC_DPAU_H_QBL:
22512 check_dsp(ctx);
22513 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22514 break;
22515 case OPC_DPAU_H_QBR:
22516 check_dsp(ctx);
22517 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22518 break;
22519 case OPC_DPSU_H_QBL:
22520 check_dsp(ctx);
22521 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22522 break;
22523 case OPC_DPSU_H_QBR:
22524 check_dsp(ctx);
22525 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22526 break;
22527 case OPC_DPA_W_PH:
22528 check_dsp_r2(ctx);
22529 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22530 break;
22531 case OPC_DPAX_W_PH:
22532 check_dsp_r2(ctx);
22533 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22534 break;
22535 case OPC_DPAQ_S_W_PH:
22536 check_dsp(ctx);
22537 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22538 break;
22539 case OPC_DPAQX_S_W_PH:
22540 check_dsp_r2(ctx);
22541 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22542 break;
22543 case OPC_DPAQX_SA_W_PH:
22544 check_dsp_r2(ctx);
22545 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22546 break;
22547 case OPC_DPS_W_PH:
22548 check_dsp_r2(ctx);
22549 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22550 break;
22551 case OPC_DPSX_W_PH:
22552 check_dsp_r2(ctx);
22553 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22554 break;
22555 case OPC_DPSQ_S_W_PH:
22556 check_dsp(ctx);
22557 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22558 break;
22559 case OPC_DPSQX_S_W_PH:
22560 check_dsp_r2(ctx);
22561 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22562 break;
22563 case OPC_DPSQX_SA_W_PH:
22564 check_dsp_r2(ctx);
22565 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22566 break;
22567 case OPC_MULSAQ_S_W_PH:
22568 check_dsp(ctx);
22569 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22570 break;
22571 case OPC_DPAQ_SA_L_W:
22572 check_dsp(ctx);
22573 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22574 break;
22575 case OPC_DPSQ_SA_L_W:
22576 check_dsp(ctx);
22577 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22578 break;
22579 case OPC_MAQ_S_W_PHL:
22580 check_dsp(ctx);
22581 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22582 break;
22583 case OPC_MAQ_S_W_PHR:
22584 check_dsp(ctx);
22585 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22586 break;
22587 case OPC_MAQ_SA_W_PHL:
22588 check_dsp(ctx);
22589 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22590 break;
22591 case OPC_MAQ_SA_W_PHR:
22592 check_dsp(ctx);
22593 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22594 break;
22595 case OPC_MULSA_W_PH:
22596 check_dsp_r2(ctx);
22597 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22598 break;
22600 break;
22601 #ifdef TARGET_MIPS64
22602 case OPC_DPAQ_W_QH_DSP:
22604 int ac = ret & 0x03;
22605 tcg_gen_movi_i32(t0, ac);
22607 switch (op2) {
22608 case OPC_DMADD:
22609 check_dsp(ctx);
22610 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22611 break;
22612 case OPC_DMADDU:
22613 check_dsp(ctx);
22614 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22615 break;
22616 case OPC_DMSUB:
22617 check_dsp(ctx);
22618 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22619 break;
22620 case OPC_DMSUBU:
22621 check_dsp(ctx);
22622 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22623 break;
22624 case OPC_DPA_W_QH:
22625 check_dsp_r2(ctx);
22626 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22627 break;
22628 case OPC_DPAQ_S_W_QH:
22629 check_dsp(ctx);
22630 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22631 break;
22632 case OPC_DPAQ_SA_L_PW:
22633 check_dsp(ctx);
22634 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22635 break;
22636 case OPC_DPAU_H_OBL:
22637 check_dsp(ctx);
22638 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22639 break;
22640 case OPC_DPAU_H_OBR:
22641 check_dsp(ctx);
22642 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22643 break;
22644 case OPC_DPS_W_QH:
22645 check_dsp_r2(ctx);
22646 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22647 break;
22648 case OPC_DPSQ_S_W_QH:
22649 check_dsp(ctx);
22650 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22651 break;
22652 case OPC_DPSQ_SA_L_PW:
22653 check_dsp(ctx);
22654 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22655 break;
22656 case OPC_DPSU_H_OBL:
22657 check_dsp(ctx);
22658 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22659 break;
22660 case OPC_DPSU_H_OBR:
22661 check_dsp(ctx);
22662 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22663 break;
22664 case OPC_MAQ_S_L_PWL:
22665 check_dsp(ctx);
22666 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22667 break;
22668 case OPC_MAQ_S_L_PWR:
22669 check_dsp(ctx);
22670 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22671 break;
22672 case OPC_MAQ_S_W_QHLL:
22673 check_dsp(ctx);
22674 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22675 break;
22676 case OPC_MAQ_SA_W_QHLL:
22677 check_dsp(ctx);
22678 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22679 break;
22680 case OPC_MAQ_S_W_QHLR:
22681 check_dsp(ctx);
22682 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22683 break;
22684 case OPC_MAQ_SA_W_QHLR:
22685 check_dsp(ctx);
22686 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22687 break;
22688 case OPC_MAQ_S_W_QHRL:
22689 check_dsp(ctx);
22690 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22691 break;
22692 case OPC_MAQ_SA_W_QHRL:
22693 check_dsp(ctx);
22694 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22695 break;
22696 case OPC_MAQ_S_W_QHRR:
22697 check_dsp(ctx);
22698 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22699 break;
22700 case OPC_MAQ_SA_W_QHRR:
22701 check_dsp(ctx);
22702 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22703 break;
22704 case OPC_MULSAQ_S_L_PW:
22705 check_dsp(ctx);
22706 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22707 break;
22708 case OPC_MULSAQ_S_W_QH:
22709 check_dsp(ctx);
22710 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22711 break;
22714 break;
22715 #endif
22716 case OPC_ADDU_QB_DSP:
22717 switch (op2) {
22718 case OPC_MULEU_S_PH_QBL:
22719 check_dsp(ctx);
22720 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22721 break;
22722 case OPC_MULEU_S_PH_QBR:
22723 check_dsp(ctx);
22724 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22725 break;
22726 case OPC_MULQ_RS_PH:
22727 check_dsp(ctx);
22728 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22729 break;
22730 case OPC_MULEQ_S_W_PHL:
22731 check_dsp(ctx);
22732 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22733 break;
22734 case OPC_MULEQ_S_W_PHR:
22735 check_dsp(ctx);
22736 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22737 break;
22738 case OPC_MULQ_S_PH:
22739 check_dsp_r2(ctx);
22740 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22741 break;
22743 break;
22744 #ifdef TARGET_MIPS64
22745 case OPC_ADDU_OB_DSP:
22746 switch (op2) {
22747 case OPC_MULEQ_S_PW_QHL:
22748 check_dsp(ctx);
22749 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22750 break;
22751 case OPC_MULEQ_S_PW_QHR:
22752 check_dsp(ctx);
22753 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22754 break;
22755 case OPC_MULEU_S_QH_OBL:
22756 check_dsp(ctx);
22757 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22758 break;
22759 case OPC_MULEU_S_QH_OBR:
22760 check_dsp(ctx);
22761 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22762 break;
22763 case OPC_MULQ_RS_QH:
22764 check_dsp(ctx);
22765 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22766 break;
22768 break;
22769 #endif
22772 tcg_temp_free_i32(t0);
22773 tcg_temp_free(v1_t);
22774 tcg_temp_free(v2_t);
22777 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22778 int ret, int val)
22780 int16_t imm;
22781 TCGv t0;
22782 TCGv val_t;
22784 if (ret == 0) {
22785 /* Treat as NOP. */
22786 return;
22789 t0 = tcg_temp_new();
22790 val_t = tcg_temp_new();
22791 gen_load_gpr(val_t, val);
22793 switch (op1) {
22794 case OPC_ABSQ_S_PH_DSP:
22795 switch (op2) {
22796 case OPC_BITREV:
22797 check_dsp(ctx);
22798 gen_helper_bitrev(cpu_gpr[ret], val_t);
22799 break;
22800 case OPC_REPL_QB:
22801 check_dsp(ctx);
22803 target_long result;
22804 imm = (ctx->opcode >> 16) & 0xFF;
22805 result = (uint32_t)imm << 24 |
22806 (uint32_t)imm << 16 |
22807 (uint32_t)imm << 8 |
22808 (uint32_t)imm;
22809 result = (int32_t)result;
22810 tcg_gen_movi_tl(cpu_gpr[ret], result);
22812 break;
22813 case OPC_REPLV_QB:
22814 check_dsp(ctx);
22815 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22816 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22817 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22818 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22819 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22820 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22821 break;
22822 case OPC_REPL_PH:
22823 check_dsp(ctx);
22825 imm = (ctx->opcode >> 16) & 0x03FF;
22826 imm = (int16_t)(imm << 6) >> 6;
22827 tcg_gen_movi_tl(cpu_gpr[ret], \
22828 (target_long)((int32_t)imm << 16 | \
22829 (uint16_t)imm));
22831 break;
22832 case OPC_REPLV_PH:
22833 check_dsp(ctx);
22834 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22835 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22836 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22837 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22838 break;
22840 break;
22841 #ifdef TARGET_MIPS64
22842 case OPC_ABSQ_S_QH_DSP:
22843 switch (op2) {
22844 case OPC_REPL_OB:
22845 check_dsp(ctx);
22847 target_long temp;
22849 imm = (ctx->opcode >> 16) & 0xFF;
22850 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
22851 temp = (temp << 16) | temp;
22852 temp = (temp << 32) | temp;
22853 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22854 break;
22856 case OPC_REPL_PW:
22857 check_dsp(ctx);
22859 target_long temp;
22861 imm = (ctx->opcode >> 16) & 0x03FF;
22862 imm = (int16_t)(imm << 6) >> 6;
22863 temp = ((target_long)imm << 32) \
22864 | ((target_long)imm & 0xFFFFFFFF);
22865 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22866 break;
22868 case OPC_REPL_QH:
22869 check_dsp(ctx);
22871 target_long temp;
22873 imm = (ctx->opcode >> 16) & 0x03FF;
22874 imm = (int16_t)(imm << 6) >> 6;
22876 temp = ((uint64_t)(uint16_t)imm << 48) |
22877 ((uint64_t)(uint16_t)imm << 32) |
22878 ((uint64_t)(uint16_t)imm << 16) |
22879 (uint64_t)(uint16_t)imm;
22880 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22881 break;
22883 case OPC_REPLV_OB:
22884 check_dsp(ctx);
22885 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22886 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22887 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22888 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22889 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22890 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22891 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22892 break;
22893 case OPC_REPLV_PW:
22894 check_dsp(ctx);
22895 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
22896 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22897 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22898 break;
22899 case OPC_REPLV_QH:
22900 check_dsp(ctx);
22901 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22902 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22903 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22904 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22905 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22906 break;
22908 break;
22909 #endif
22911 tcg_temp_free(t0);
22912 tcg_temp_free(val_t);
22915 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
22916 uint32_t op1, uint32_t op2,
22917 int ret, int v1, int v2, int check_ret)
22919 TCGv t1;
22920 TCGv v1_t;
22921 TCGv v2_t;
22923 if ((ret == 0) && (check_ret == 1)) {
22924 /* Treat as NOP. */
22925 return;
22928 t1 = tcg_temp_new();
22929 v1_t = tcg_temp_new();
22930 v2_t = tcg_temp_new();
22932 gen_load_gpr(v1_t, v1);
22933 gen_load_gpr(v2_t, v2);
22935 switch (op1) {
22936 case OPC_CMPU_EQ_QB_DSP:
22937 switch (op2) {
22938 case OPC_CMPU_EQ_QB:
22939 check_dsp(ctx);
22940 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
22941 break;
22942 case OPC_CMPU_LT_QB:
22943 check_dsp(ctx);
22944 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
22945 break;
22946 case OPC_CMPU_LE_QB:
22947 check_dsp(ctx);
22948 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
22949 break;
22950 case OPC_CMPGU_EQ_QB:
22951 check_dsp(ctx);
22952 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
22953 break;
22954 case OPC_CMPGU_LT_QB:
22955 check_dsp(ctx);
22956 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
22957 break;
22958 case OPC_CMPGU_LE_QB:
22959 check_dsp(ctx);
22960 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
22961 break;
22962 case OPC_CMPGDU_EQ_QB:
22963 check_dsp_r2(ctx);
22964 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
22965 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22966 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22967 tcg_gen_shli_tl(t1, t1, 24);
22968 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22969 break;
22970 case OPC_CMPGDU_LT_QB:
22971 check_dsp_r2(ctx);
22972 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
22973 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22974 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22975 tcg_gen_shli_tl(t1, t1, 24);
22976 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22977 break;
22978 case OPC_CMPGDU_LE_QB:
22979 check_dsp_r2(ctx);
22980 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
22981 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22982 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22983 tcg_gen_shli_tl(t1, t1, 24);
22984 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22985 break;
22986 case OPC_CMP_EQ_PH:
22987 check_dsp(ctx);
22988 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
22989 break;
22990 case OPC_CMP_LT_PH:
22991 check_dsp(ctx);
22992 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
22993 break;
22994 case OPC_CMP_LE_PH:
22995 check_dsp(ctx);
22996 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
22997 break;
22998 case OPC_PICK_QB:
22999 check_dsp(ctx);
23000 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23001 break;
23002 case OPC_PICK_PH:
23003 check_dsp(ctx);
23004 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23005 break;
23006 case OPC_PACKRL_PH:
23007 check_dsp(ctx);
23008 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23009 break;
23011 break;
23012 #ifdef TARGET_MIPS64
23013 case OPC_CMPU_EQ_OB_DSP:
23014 switch (op2) {
23015 case OPC_CMP_EQ_PW:
23016 check_dsp(ctx);
23017 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23018 break;
23019 case OPC_CMP_LT_PW:
23020 check_dsp(ctx);
23021 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23022 break;
23023 case OPC_CMP_LE_PW:
23024 check_dsp(ctx);
23025 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23026 break;
23027 case OPC_CMP_EQ_QH:
23028 check_dsp(ctx);
23029 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23030 break;
23031 case OPC_CMP_LT_QH:
23032 check_dsp(ctx);
23033 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23034 break;
23035 case OPC_CMP_LE_QH:
23036 check_dsp(ctx);
23037 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23038 break;
23039 case OPC_CMPGDU_EQ_OB:
23040 check_dsp_r2(ctx);
23041 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23042 break;
23043 case OPC_CMPGDU_LT_OB:
23044 check_dsp_r2(ctx);
23045 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23046 break;
23047 case OPC_CMPGDU_LE_OB:
23048 check_dsp_r2(ctx);
23049 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23050 break;
23051 case OPC_CMPGU_EQ_OB:
23052 check_dsp(ctx);
23053 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23054 break;
23055 case OPC_CMPGU_LT_OB:
23056 check_dsp(ctx);
23057 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23058 break;
23059 case OPC_CMPGU_LE_OB:
23060 check_dsp(ctx);
23061 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23062 break;
23063 case OPC_CMPU_EQ_OB:
23064 check_dsp(ctx);
23065 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23066 break;
23067 case OPC_CMPU_LT_OB:
23068 check_dsp(ctx);
23069 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23070 break;
23071 case OPC_CMPU_LE_OB:
23072 check_dsp(ctx);
23073 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23074 break;
23075 case OPC_PACKRL_PW:
23076 check_dsp(ctx);
23077 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23078 break;
23079 case OPC_PICK_OB:
23080 check_dsp(ctx);
23081 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23082 break;
23083 case OPC_PICK_PW:
23084 check_dsp(ctx);
23085 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23086 break;
23087 case OPC_PICK_QH:
23088 check_dsp(ctx);
23089 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23090 break;
23092 break;
23093 #endif
23096 tcg_temp_free(t1);
23097 tcg_temp_free(v1_t);
23098 tcg_temp_free(v2_t);
23101 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23102 uint32_t op1, int rt, int rs, int sa)
23104 TCGv t0;
23106 check_dsp_r2(ctx);
23108 if (rt == 0) {
23109 /* Treat as NOP. */
23110 return;
23113 t0 = tcg_temp_new();
23114 gen_load_gpr(t0, rs);
23116 switch (op1) {
23117 case OPC_APPEND_DSP:
23118 switch (MASK_APPEND(ctx->opcode)) {
23119 case OPC_APPEND:
23120 if (sa != 0) {
23121 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23123 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23124 break;
23125 case OPC_PREPEND:
23126 if (sa != 0) {
23127 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23128 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23129 tcg_gen_shli_tl(t0, t0, 32 - sa);
23130 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23132 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23133 break;
23134 case OPC_BALIGN:
23135 sa &= 3;
23136 if (sa != 0 && sa != 2) {
23137 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23138 tcg_gen_ext32u_tl(t0, t0);
23139 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23140 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23142 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23143 break;
23144 default: /* Invalid */
23145 MIPS_INVAL("MASK APPEND");
23146 gen_reserved_instruction(ctx);
23147 break;
23149 break;
23150 #ifdef TARGET_MIPS64
23151 case OPC_DAPPEND_DSP:
23152 switch (MASK_DAPPEND(ctx->opcode)) {
23153 case OPC_DAPPEND:
23154 if (sa != 0) {
23155 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23157 break;
23158 case OPC_PREPENDD:
23159 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23160 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23161 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23162 break;
23163 case OPC_PREPENDW:
23164 if (sa != 0) {
23165 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23166 tcg_gen_shli_tl(t0, t0, 64 - sa);
23167 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23169 break;
23170 case OPC_DBALIGN:
23171 sa &= 7;
23172 if (sa != 0 && sa != 2 && sa != 4) {
23173 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23174 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23175 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23177 break;
23178 default: /* Invalid */
23179 MIPS_INVAL("MASK DAPPEND");
23180 gen_reserved_instruction(ctx);
23181 break;
23183 break;
23184 #endif
23186 tcg_temp_free(t0);
23189 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23190 int ret, int v1, int v2, int check_ret)
23193 TCGv t0;
23194 TCGv t1;
23195 TCGv v1_t;
23196 TCGv v2_t;
23197 int16_t imm;
23199 if ((ret == 0) && (check_ret == 1)) {
23200 /* Treat as NOP. */
23201 return;
23204 t0 = tcg_temp_new();
23205 t1 = tcg_temp_new();
23206 v1_t = tcg_temp_new();
23207 v2_t = tcg_temp_new();
23209 gen_load_gpr(v1_t, v1);
23210 gen_load_gpr(v2_t, v2);
23212 switch (op1) {
23213 case OPC_EXTR_W_DSP:
23214 check_dsp(ctx);
23215 switch (op2) {
23216 case OPC_EXTR_W:
23217 tcg_gen_movi_tl(t0, v2);
23218 tcg_gen_movi_tl(t1, v1);
23219 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23220 break;
23221 case OPC_EXTR_R_W:
23222 tcg_gen_movi_tl(t0, v2);
23223 tcg_gen_movi_tl(t1, v1);
23224 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23225 break;
23226 case OPC_EXTR_RS_W:
23227 tcg_gen_movi_tl(t0, v2);
23228 tcg_gen_movi_tl(t1, v1);
23229 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23230 break;
23231 case OPC_EXTR_S_H:
23232 tcg_gen_movi_tl(t0, v2);
23233 tcg_gen_movi_tl(t1, v1);
23234 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23235 break;
23236 case OPC_EXTRV_S_H:
23237 tcg_gen_movi_tl(t0, v2);
23238 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23239 break;
23240 case OPC_EXTRV_W:
23241 tcg_gen_movi_tl(t0, v2);
23242 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23243 break;
23244 case OPC_EXTRV_R_W:
23245 tcg_gen_movi_tl(t0, v2);
23246 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23247 break;
23248 case OPC_EXTRV_RS_W:
23249 tcg_gen_movi_tl(t0, v2);
23250 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23251 break;
23252 case OPC_EXTP:
23253 tcg_gen_movi_tl(t0, v2);
23254 tcg_gen_movi_tl(t1, v1);
23255 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23256 break;
23257 case OPC_EXTPV:
23258 tcg_gen_movi_tl(t0, v2);
23259 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23260 break;
23261 case OPC_EXTPDP:
23262 tcg_gen_movi_tl(t0, v2);
23263 tcg_gen_movi_tl(t1, v1);
23264 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23265 break;
23266 case OPC_EXTPDPV:
23267 tcg_gen_movi_tl(t0, v2);
23268 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23269 break;
23270 case OPC_SHILO:
23271 imm = (ctx->opcode >> 20) & 0x3F;
23272 tcg_gen_movi_tl(t0, ret);
23273 tcg_gen_movi_tl(t1, imm);
23274 gen_helper_shilo(t0, t1, cpu_env);
23275 break;
23276 case OPC_SHILOV:
23277 tcg_gen_movi_tl(t0, ret);
23278 gen_helper_shilo(t0, v1_t, cpu_env);
23279 break;
23280 case OPC_MTHLIP:
23281 tcg_gen_movi_tl(t0, ret);
23282 gen_helper_mthlip(t0, v1_t, cpu_env);
23283 break;
23284 case OPC_WRDSP:
23285 imm = (ctx->opcode >> 11) & 0x3FF;
23286 tcg_gen_movi_tl(t0, imm);
23287 gen_helper_wrdsp(v1_t, t0, cpu_env);
23288 break;
23289 case OPC_RDDSP:
23290 imm = (ctx->opcode >> 16) & 0x03FF;
23291 tcg_gen_movi_tl(t0, imm);
23292 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23293 break;
23295 break;
23296 #ifdef TARGET_MIPS64
23297 case OPC_DEXTR_W_DSP:
23298 check_dsp(ctx);
23299 switch (op2) {
23300 case OPC_DMTHLIP:
23301 tcg_gen_movi_tl(t0, ret);
23302 gen_helper_dmthlip(v1_t, t0, cpu_env);
23303 break;
23304 case OPC_DSHILO:
23306 int shift = (ctx->opcode >> 19) & 0x7F;
23307 int ac = (ctx->opcode >> 11) & 0x03;
23308 tcg_gen_movi_tl(t0, shift);
23309 tcg_gen_movi_tl(t1, ac);
23310 gen_helper_dshilo(t0, t1, cpu_env);
23311 break;
23313 case OPC_DSHILOV:
23315 int ac = (ctx->opcode >> 11) & 0x03;
23316 tcg_gen_movi_tl(t0, ac);
23317 gen_helper_dshilo(v1_t, t0, cpu_env);
23318 break;
23320 case OPC_DEXTP:
23321 tcg_gen_movi_tl(t0, v2);
23322 tcg_gen_movi_tl(t1, v1);
23324 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23325 break;
23326 case OPC_DEXTPV:
23327 tcg_gen_movi_tl(t0, v2);
23328 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23329 break;
23330 case OPC_DEXTPDP:
23331 tcg_gen_movi_tl(t0, v2);
23332 tcg_gen_movi_tl(t1, v1);
23333 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23334 break;
23335 case OPC_DEXTPDPV:
23336 tcg_gen_movi_tl(t0, v2);
23337 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23338 break;
23339 case OPC_DEXTR_L:
23340 tcg_gen_movi_tl(t0, v2);
23341 tcg_gen_movi_tl(t1, v1);
23342 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23343 break;
23344 case OPC_DEXTR_R_L:
23345 tcg_gen_movi_tl(t0, v2);
23346 tcg_gen_movi_tl(t1, v1);
23347 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23348 break;
23349 case OPC_DEXTR_RS_L:
23350 tcg_gen_movi_tl(t0, v2);
23351 tcg_gen_movi_tl(t1, v1);
23352 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23353 break;
23354 case OPC_DEXTR_W:
23355 tcg_gen_movi_tl(t0, v2);
23356 tcg_gen_movi_tl(t1, v1);
23357 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23358 break;
23359 case OPC_DEXTR_R_W:
23360 tcg_gen_movi_tl(t0, v2);
23361 tcg_gen_movi_tl(t1, v1);
23362 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23363 break;
23364 case OPC_DEXTR_RS_W:
23365 tcg_gen_movi_tl(t0, v2);
23366 tcg_gen_movi_tl(t1, v1);
23367 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23368 break;
23369 case OPC_DEXTR_S_H:
23370 tcg_gen_movi_tl(t0, v2);
23371 tcg_gen_movi_tl(t1, v1);
23372 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23373 break;
23374 case OPC_DEXTRV_S_H:
23375 tcg_gen_movi_tl(t0, v2);
23376 tcg_gen_movi_tl(t1, v1);
23377 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23378 break;
23379 case OPC_DEXTRV_L:
23380 tcg_gen_movi_tl(t0, v2);
23381 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23382 break;
23383 case OPC_DEXTRV_R_L:
23384 tcg_gen_movi_tl(t0, v2);
23385 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23386 break;
23387 case OPC_DEXTRV_RS_L:
23388 tcg_gen_movi_tl(t0, v2);
23389 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23390 break;
23391 case OPC_DEXTRV_W:
23392 tcg_gen_movi_tl(t0, v2);
23393 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23394 break;
23395 case OPC_DEXTRV_R_W:
23396 tcg_gen_movi_tl(t0, v2);
23397 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23398 break;
23399 case OPC_DEXTRV_RS_W:
23400 tcg_gen_movi_tl(t0, v2);
23401 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23402 break;
23404 break;
23405 #endif
23408 tcg_temp_free(t0);
23409 tcg_temp_free(t1);
23410 tcg_temp_free(v1_t);
23411 tcg_temp_free(v2_t);
23414 /* End MIPSDSP functions. */
23416 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23418 int rs, rt, rd, sa;
23419 uint32_t op1, op2;
23421 rs = (ctx->opcode >> 21) & 0x1f;
23422 rt = (ctx->opcode >> 16) & 0x1f;
23423 rd = (ctx->opcode >> 11) & 0x1f;
23424 sa = (ctx->opcode >> 6) & 0x1f;
23426 op1 = MASK_SPECIAL(ctx->opcode);
23427 switch (op1) {
23428 case OPC_MULT:
23429 case OPC_MULTU:
23430 case OPC_DIV:
23431 case OPC_DIVU:
23432 op2 = MASK_R6_MULDIV(ctx->opcode);
23433 switch (op2) {
23434 case R6_OPC_MUL:
23435 case R6_OPC_MUH:
23436 case R6_OPC_MULU:
23437 case R6_OPC_MUHU:
23438 case R6_OPC_DIV:
23439 case R6_OPC_MOD:
23440 case R6_OPC_DIVU:
23441 case R6_OPC_MODU:
23442 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23443 break;
23444 default:
23445 MIPS_INVAL("special_r6 muldiv");
23446 gen_reserved_instruction(ctx);
23447 break;
23449 break;
23450 case OPC_SELEQZ:
23451 case OPC_SELNEZ:
23452 gen_cond_move(ctx, op1, rd, rs, rt);
23453 break;
23454 case R6_OPC_CLO:
23455 case R6_OPC_CLZ:
23456 if (rt == 0 && sa == 1) {
23458 * Major opcode and function field is shared with preR6 MFHI/MTHI.
23459 * We need additionally to check other fields.
23461 gen_cl(ctx, op1, rd, rs);
23462 } else {
23463 gen_reserved_instruction(ctx);
23465 break;
23466 case R6_OPC_SDBBP:
23467 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23468 gen_helper_do_semihosting(cpu_env);
23469 } else {
23470 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23471 gen_reserved_instruction(ctx);
23472 } else {
23473 generate_exception_end(ctx, EXCP_DBp);
23476 break;
23477 #if defined(TARGET_MIPS64)
23478 case R6_OPC_DCLO:
23479 case R6_OPC_DCLZ:
23480 if (rt == 0 && sa == 1) {
23482 * Major opcode and function field is shared with preR6 MFHI/MTHI.
23483 * We need additionally to check other fields.
23485 check_mips_64(ctx);
23486 gen_cl(ctx, op1, rd, rs);
23487 } else {
23488 gen_reserved_instruction(ctx);
23490 break;
23491 case OPC_DMULT:
23492 case OPC_DMULTU:
23493 case OPC_DDIV:
23494 case OPC_DDIVU:
23496 op2 = MASK_R6_MULDIV(ctx->opcode);
23497 switch (op2) {
23498 case R6_OPC_DMUL:
23499 case R6_OPC_DMUH:
23500 case R6_OPC_DMULU:
23501 case R6_OPC_DMUHU:
23502 case R6_OPC_DDIV:
23503 case R6_OPC_DMOD:
23504 case R6_OPC_DDIVU:
23505 case R6_OPC_DMODU:
23506 check_mips_64(ctx);
23507 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23508 break;
23509 default:
23510 MIPS_INVAL("special_r6 muldiv");
23511 gen_reserved_instruction(ctx);
23512 break;
23514 break;
23515 #endif
23516 default: /* Invalid */
23517 MIPS_INVAL("special_r6");
23518 gen_reserved_instruction(ctx);
23519 break;
23523 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
23525 int rs = extract32(ctx->opcode, 21, 5);
23526 int rt = extract32(ctx->opcode, 16, 5);
23527 int rd = extract32(ctx->opcode, 11, 5);
23528 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
23530 switch (op1) {
23531 case OPC_MOVN: /* Conditional move */
23532 case OPC_MOVZ:
23533 gen_cond_move(ctx, op1, rd, rs, rt);
23534 break;
23535 case OPC_MFHI: /* Move from HI/LO */
23536 case OPC_MFLO:
23537 gen_HILO(ctx, op1, 0, rd);
23538 break;
23539 case OPC_MTHI:
23540 case OPC_MTLO: /* Move to HI/LO */
23541 gen_HILO(ctx, op1, 0, rs);
23542 break;
23543 case OPC_MULT:
23544 case OPC_MULTU:
23545 gen_mul_txx9(ctx, op1, rd, rs, rt);
23546 break;
23547 case OPC_DIV:
23548 case OPC_DIVU:
23549 gen_muldiv(ctx, op1, 0, rs, rt);
23550 break;
23551 #if defined(TARGET_MIPS64)
23552 case OPC_DMULT:
23553 case OPC_DMULTU:
23554 case OPC_DDIV:
23555 case OPC_DDIVU:
23556 check_insn_opc_user_only(ctx, INSN_R5900);
23557 gen_muldiv(ctx, op1, 0, rs, rt);
23558 break;
23559 #endif
23560 case OPC_JR:
23561 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
23562 break;
23563 default: /* Invalid */
23564 MIPS_INVAL("special_tx79");
23565 gen_reserved_instruction(ctx);
23566 break;
23570 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23572 int rs, rt, rd, sa;
23573 uint32_t op1;
23575 rs = (ctx->opcode >> 21) & 0x1f;
23576 rt = (ctx->opcode >> 16) & 0x1f;
23577 rd = (ctx->opcode >> 11) & 0x1f;
23578 sa = (ctx->opcode >> 6) & 0x1f;
23580 op1 = MASK_SPECIAL(ctx->opcode);
23581 switch (op1) {
23582 case OPC_MOVN: /* Conditional move */
23583 case OPC_MOVZ:
23584 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
23585 INSN_LOONGSON2E | INSN_LOONGSON2F);
23586 gen_cond_move(ctx, op1, rd, rs, rt);
23587 break;
23588 case OPC_MFHI: /* Move from HI/LO */
23589 case OPC_MFLO:
23590 gen_HILO(ctx, op1, rs & 3, rd);
23591 break;
23592 case OPC_MTHI:
23593 case OPC_MTLO: /* Move to HI/LO */
23594 gen_HILO(ctx, op1, rd & 3, rs);
23595 break;
23596 case OPC_MOVCI:
23597 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
23598 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23599 check_cp1_enabled(ctx);
23600 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23601 (ctx->opcode >> 16) & 1);
23602 } else {
23603 generate_exception_err(ctx, EXCP_CpU, 1);
23605 break;
23606 case OPC_MULT:
23607 case OPC_MULTU:
23608 if (sa) {
23609 check_insn(ctx, INSN_VR54XX);
23610 op1 = MASK_MUL_VR54XX(ctx->opcode);
23611 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23612 } else {
23613 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23615 break;
23616 case OPC_DIV:
23617 case OPC_DIVU:
23618 gen_muldiv(ctx, op1, 0, rs, rt);
23619 break;
23620 #if defined(TARGET_MIPS64)
23621 case OPC_DMULT:
23622 case OPC_DMULTU:
23623 case OPC_DDIV:
23624 case OPC_DDIVU:
23625 check_insn(ctx, ISA_MIPS3);
23626 check_mips_64(ctx);
23627 gen_muldiv(ctx, op1, 0, rs, rt);
23628 break;
23629 #endif
23630 case OPC_JR:
23631 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23632 break;
23633 case OPC_SPIM:
23634 #ifdef MIPS_STRICT_STANDARD
23635 MIPS_INVAL("SPIM");
23636 gen_reserved_instruction(ctx);
23637 #else
23638 /* Implemented as RI exception for now. */
23639 MIPS_INVAL("spim (unofficial)");
23640 gen_reserved_instruction(ctx);
23641 #endif
23642 break;
23643 default: /* Invalid */
23644 MIPS_INVAL("special_legacy");
23645 gen_reserved_instruction(ctx);
23646 break;
23650 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23652 int rs, rt, rd, sa;
23653 uint32_t op1;
23655 rs = (ctx->opcode >> 21) & 0x1f;
23656 rt = (ctx->opcode >> 16) & 0x1f;
23657 rd = (ctx->opcode >> 11) & 0x1f;
23658 sa = (ctx->opcode >> 6) & 0x1f;
23660 op1 = MASK_SPECIAL(ctx->opcode);
23661 switch (op1) {
23662 case OPC_SLL: /* Shift with immediate */
23663 if (sa == 5 && rd == 0 &&
23664 rs == 0 && rt == 0) { /* PAUSE */
23665 if ((ctx->insn_flags & ISA_MIPS_R6) &&
23666 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23667 gen_reserved_instruction(ctx);
23668 break;
23671 /* Fallthrough */
23672 case OPC_SRA:
23673 gen_shift_imm(ctx, op1, rd, rt, sa);
23674 break;
23675 case OPC_SRL:
23676 switch ((ctx->opcode >> 21) & 0x1f) {
23677 case 1:
23678 /* rotr is decoded as srl on non-R2 CPUs */
23679 if (ctx->insn_flags & ISA_MIPS_R2) {
23680 op1 = OPC_ROTR;
23682 /* Fallthrough */
23683 case 0:
23684 gen_shift_imm(ctx, op1, rd, rt, sa);
23685 break;
23686 default:
23687 gen_reserved_instruction(ctx);
23688 break;
23690 break;
23691 case OPC_ADD:
23692 case OPC_ADDU:
23693 case OPC_SUB:
23694 case OPC_SUBU:
23695 gen_arith(ctx, op1, rd, rs, rt);
23696 break;
23697 case OPC_SLLV: /* Shifts */
23698 case OPC_SRAV:
23699 gen_shift(ctx, op1, rd, rs, rt);
23700 break;
23701 case OPC_SRLV:
23702 switch ((ctx->opcode >> 6) & 0x1f) {
23703 case 1:
23704 /* rotrv is decoded as srlv on non-R2 CPUs */
23705 if (ctx->insn_flags & ISA_MIPS_R2) {
23706 op1 = OPC_ROTRV;
23708 /* Fallthrough */
23709 case 0:
23710 gen_shift(ctx, op1, rd, rs, rt);
23711 break;
23712 default:
23713 gen_reserved_instruction(ctx);
23714 break;
23716 break;
23717 case OPC_SLT: /* Set on less than */
23718 case OPC_SLTU:
23719 gen_slt(ctx, op1, rd, rs, rt);
23720 break;
23721 case OPC_AND: /* Logic*/
23722 case OPC_OR:
23723 case OPC_NOR:
23724 case OPC_XOR:
23725 gen_logic(ctx, op1, rd, rs, rt);
23726 break;
23727 case OPC_JALR:
23728 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23729 break;
23730 case OPC_TGE: /* Traps */
23731 case OPC_TGEU:
23732 case OPC_TLT:
23733 case OPC_TLTU:
23734 case OPC_TEQ:
23735 case OPC_TNE:
23736 check_insn(ctx, ISA_MIPS2);
23737 gen_trap(ctx, op1, rs, rt, -1);
23738 break;
23739 case OPC_PMON:
23740 /* Pmon entry point, also R4010 selsl */
23741 #ifdef MIPS_STRICT_STANDARD
23742 MIPS_INVAL("PMON / selsl");
23743 gen_reserved_instruction(ctx);
23744 #else
23745 gen_helper_0e0i(pmon, sa);
23746 #endif
23747 break;
23748 case OPC_SYSCALL:
23749 generate_exception_end(ctx, EXCP_SYSCALL);
23750 break;
23751 case OPC_BREAK:
23752 generate_exception_end(ctx, EXCP_BREAK);
23753 break;
23754 case OPC_SYNC:
23755 check_insn(ctx, ISA_MIPS2);
23756 gen_sync(extract32(ctx->opcode, 6, 5));
23757 break;
23759 #if defined(TARGET_MIPS64)
23760 /* MIPS64 specific opcodes */
23761 case OPC_DSLL:
23762 case OPC_DSRA:
23763 case OPC_DSLL32:
23764 case OPC_DSRA32:
23765 check_insn(ctx, ISA_MIPS3);
23766 check_mips_64(ctx);
23767 gen_shift_imm(ctx, op1, rd, rt, sa);
23768 break;
23769 case OPC_DSRL:
23770 switch ((ctx->opcode >> 21) & 0x1f) {
23771 case 1:
23772 /* drotr is decoded as dsrl on non-R2 CPUs */
23773 if (ctx->insn_flags & ISA_MIPS_R2) {
23774 op1 = OPC_DROTR;
23776 /* Fallthrough */
23777 case 0:
23778 check_insn(ctx, ISA_MIPS3);
23779 check_mips_64(ctx);
23780 gen_shift_imm(ctx, op1, rd, rt, sa);
23781 break;
23782 default:
23783 gen_reserved_instruction(ctx);
23784 break;
23786 break;
23787 case OPC_DSRL32:
23788 switch ((ctx->opcode >> 21) & 0x1f) {
23789 case 1:
23790 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23791 if (ctx->insn_flags & ISA_MIPS_R2) {
23792 op1 = OPC_DROTR32;
23794 /* Fallthrough */
23795 case 0:
23796 check_insn(ctx, ISA_MIPS3);
23797 check_mips_64(ctx);
23798 gen_shift_imm(ctx, op1, rd, rt, sa);
23799 break;
23800 default:
23801 gen_reserved_instruction(ctx);
23802 break;
23804 break;
23805 case OPC_DADD:
23806 case OPC_DADDU:
23807 case OPC_DSUB:
23808 case OPC_DSUBU:
23809 check_insn(ctx, ISA_MIPS3);
23810 check_mips_64(ctx);
23811 gen_arith(ctx, op1, rd, rs, rt);
23812 break;
23813 case OPC_DSLLV:
23814 case OPC_DSRAV:
23815 check_insn(ctx, ISA_MIPS3);
23816 check_mips_64(ctx);
23817 gen_shift(ctx, op1, rd, rs, rt);
23818 break;
23819 case OPC_DSRLV:
23820 switch ((ctx->opcode >> 6) & 0x1f) {
23821 case 1:
23822 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23823 if (ctx->insn_flags & ISA_MIPS_R2) {
23824 op1 = OPC_DROTRV;
23826 /* Fallthrough */
23827 case 0:
23828 check_insn(ctx, ISA_MIPS3);
23829 check_mips_64(ctx);
23830 gen_shift(ctx, op1, rd, rs, rt);
23831 break;
23832 default:
23833 gen_reserved_instruction(ctx);
23834 break;
23836 break;
23837 #endif
23838 default:
23839 if (ctx->insn_flags & ISA_MIPS_R6) {
23840 decode_opc_special_r6(env, ctx);
23841 } else if (ctx->insn_flags & INSN_R5900) {
23842 decode_opc_special_tx79(env, ctx);
23843 } else {
23844 decode_opc_special_legacy(env, ctx);
23850 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
23852 int rs, rt, rd;
23853 uint32_t op1;
23855 rs = (ctx->opcode >> 21) & 0x1f;
23856 rt = (ctx->opcode >> 16) & 0x1f;
23857 rd = (ctx->opcode >> 11) & 0x1f;
23859 op1 = MASK_SPECIAL2(ctx->opcode);
23860 switch (op1) {
23861 case OPC_MADD: /* Multiply and add/sub */
23862 case OPC_MADDU:
23863 case OPC_MSUB:
23864 case OPC_MSUBU:
23865 check_insn(ctx, ISA_MIPS_R1);
23866 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23867 break;
23868 case OPC_MUL:
23869 gen_arith(ctx, op1, rd, rs, rt);
23870 break;
23871 case OPC_DIV_G_2F:
23872 case OPC_DIVU_G_2F:
23873 case OPC_MULT_G_2F:
23874 case OPC_MULTU_G_2F:
23875 case OPC_MOD_G_2F:
23876 case OPC_MODU_G_2F:
23877 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
23878 gen_loongson_integer(ctx, op1, rd, rs, rt);
23879 break;
23880 case OPC_CLO:
23881 case OPC_CLZ:
23882 check_insn(ctx, ISA_MIPS_R1);
23883 gen_cl(ctx, op1, rd, rs);
23884 break;
23885 case OPC_SDBBP:
23886 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23887 gen_helper_do_semihosting(cpu_env);
23888 } else {
23890 * XXX: not clear which exception should be raised
23891 * when in debug mode...
23893 check_insn(ctx, ISA_MIPS_R1);
23894 generate_exception_end(ctx, EXCP_DBp);
23896 break;
23897 #if defined(TARGET_MIPS64)
23898 case OPC_DCLO:
23899 case OPC_DCLZ:
23900 check_insn(ctx, ISA_MIPS_R1);
23901 check_mips_64(ctx);
23902 gen_cl(ctx, op1, rd, rs);
23903 break;
23904 case OPC_DMULT_G_2F:
23905 case OPC_DMULTU_G_2F:
23906 case OPC_DDIV_G_2F:
23907 case OPC_DDIVU_G_2F:
23908 case OPC_DMOD_G_2F:
23909 case OPC_DMODU_G_2F:
23910 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
23911 gen_loongson_integer(ctx, op1, rd, rs, rt);
23912 break;
23913 #endif
23914 default: /* Invalid */
23915 MIPS_INVAL("special2_legacy");
23916 gen_reserved_instruction(ctx);
23917 break;
23921 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
23923 int rs, rt, rd, sa;
23924 uint32_t op1, op2;
23925 int16_t imm;
23927 rs = (ctx->opcode >> 21) & 0x1f;
23928 rt = (ctx->opcode >> 16) & 0x1f;
23929 rd = (ctx->opcode >> 11) & 0x1f;
23930 sa = (ctx->opcode >> 6) & 0x1f;
23931 imm = (int16_t)ctx->opcode >> 7;
23933 op1 = MASK_SPECIAL3(ctx->opcode);
23934 switch (op1) {
23935 case R6_OPC_PREF:
23936 if (rt >= 24) {
23937 /* hint codes 24-31 are reserved and signal RI */
23938 gen_reserved_instruction(ctx);
23940 /* Treat as NOP. */
23941 break;
23942 case R6_OPC_CACHE:
23943 check_cp0_enabled(ctx);
23944 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23945 gen_cache_operation(ctx, rt, rs, imm);
23947 break;
23948 case R6_OPC_SC:
23949 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
23950 break;
23951 case R6_OPC_LL:
23952 gen_ld(ctx, op1, rt, rs, imm);
23953 break;
23954 case OPC_BSHFL:
23956 if (rd == 0) {
23957 /* Treat as NOP. */
23958 break;
23960 op2 = MASK_BSHFL(ctx->opcode);
23961 switch (op2) {
23962 case OPC_ALIGN:
23963 case OPC_ALIGN_1:
23964 case OPC_ALIGN_2:
23965 case OPC_ALIGN_3:
23966 gen_align(ctx, 32, rd, rs, rt, sa & 3);
23967 break;
23968 case OPC_BITSWAP:
23969 gen_bitswap(ctx, op2, rd, rt);
23970 break;
23973 break;
23974 #ifndef CONFIG_USER_ONLY
23975 case OPC_GINV:
23976 if (unlikely(ctx->gi <= 1)) {
23977 gen_reserved_instruction(ctx);
23979 check_cp0_enabled(ctx);
23980 switch ((ctx->opcode >> 6) & 3) {
23981 case 0: /* GINVI */
23982 /* Treat as NOP. */
23983 break;
23984 case 2: /* GINVT */
23985 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
23986 break;
23987 default:
23988 gen_reserved_instruction(ctx);
23989 break;
23991 break;
23992 #endif
23993 #if defined(TARGET_MIPS64)
23994 case R6_OPC_SCD:
23995 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
23996 break;
23997 case R6_OPC_LLD:
23998 gen_ld(ctx, op1, rt, rs, imm);
23999 break;
24000 case OPC_DBSHFL:
24001 check_mips_64(ctx);
24003 if (rd == 0) {
24004 /* Treat as NOP. */
24005 break;
24007 op2 = MASK_DBSHFL(ctx->opcode);
24008 switch (op2) {
24009 case OPC_DALIGN:
24010 case OPC_DALIGN_1:
24011 case OPC_DALIGN_2:
24012 case OPC_DALIGN_3:
24013 case OPC_DALIGN_4:
24014 case OPC_DALIGN_5:
24015 case OPC_DALIGN_6:
24016 case OPC_DALIGN_7:
24017 gen_align(ctx, 64, rd, rs, rt, sa & 7);
24018 break;
24019 case OPC_DBITSWAP:
24020 gen_bitswap(ctx, op2, rd, rt);
24021 break;
24025 break;
24026 #endif
24027 default: /* Invalid */
24028 MIPS_INVAL("special3_r6");
24029 gen_reserved_instruction(ctx);
24030 break;
24034 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
24036 int rs, rt, rd;
24037 uint32_t op1, op2;
24039 rs = (ctx->opcode >> 21) & 0x1f;
24040 rt = (ctx->opcode >> 16) & 0x1f;
24041 rd = (ctx->opcode >> 11) & 0x1f;
24043 op1 = MASK_SPECIAL3(ctx->opcode);
24044 switch (op1) {
24045 case OPC_DIV_G_2E:
24046 case OPC_DIVU_G_2E:
24047 case OPC_MOD_G_2E:
24048 case OPC_MODU_G_2E:
24049 case OPC_MULT_G_2E:
24050 case OPC_MULTU_G_2E:
24052 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
24053 * the same mask and op1.
24055 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
24056 op2 = MASK_ADDUH_QB(ctx->opcode);
24057 switch (op2) {
24058 case OPC_ADDUH_QB:
24059 case OPC_ADDUH_R_QB:
24060 case OPC_ADDQH_PH:
24061 case OPC_ADDQH_R_PH:
24062 case OPC_ADDQH_W:
24063 case OPC_ADDQH_R_W:
24064 case OPC_SUBUH_QB:
24065 case OPC_SUBUH_R_QB:
24066 case OPC_SUBQH_PH:
24067 case OPC_SUBQH_R_PH:
24068 case OPC_SUBQH_W:
24069 case OPC_SUBQH_R_W:
24070 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24071 break;
24072 case OPC_MUL_PH:
24073 case OPC_MUL_S_PH:
24074 case OPC_MULQ_S_W:
24075 case OPC_MULQ_RS_W:
24076 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24077 break;
24078 default:
24079 MIPS_INVAL("MASK ADDUH.QB");
24080 gen_reserved_instruction(ctx);
24081 break;
24083 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
24084 gen_loongson_integer(ctx, op1, rd, rs, rt);
24085 } else {
24086 gen_reserved_instruction(ctx);
24088 break;
24089 case OPC_LX_DSP:
24090 op2 = MASK_LX(ctx->opcode);
24091 switch (op2) {
24092 #if defined(TARGET_MIPS64)
24093 case OPC_LDX:
24094 #endif
24095 case OPC_LBUX:
24096 case OPC_LHX:
24097 case OPC_LWX:
24098 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
24099 break;
24100 default: /* Invalid */
24101 MIPS_INVAL("MASK LX");
24102 gen_reserved_instruction(ctx);
24103 break;
24105 break;
24106 case OPC_ABSQ_S_PH_DSP:
24107 op2 = MASK_ABSQ_S_PH(ctx->opcode);
24108 switch (op2) {
24109 case OPC_ABSQ_S_QB:
24110 case OPC_ABSQ_S_PH:
24111 case OPC_ABSQ_S_W:
24112 case OPC_PRECEQ_W_PHL:
24113 case OPC_PRECEQ_W_PHR:
24114 case OPC_PRECEQU_PH_QBL:
24115 case OPC_PRECEQU_PH_QBR:
24116 case OPC_PRECEQU_PH_QBLA:
24117 case OPC_PRECEQU_PH_QBRA:
24118 case OPC_PRECEU_PH_QBL:
24119 case OPC_PRECEU_PH_QBR:
24120 case OPC_PRECEU_PH_QBLA:
24121 case OPC_PRECEU_PH_QBRA:
24122 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24123 break;
24124 case OPC_BITREV:
24125 case OPC_REPL_QB:
24126 case OPC_REPLV_QB:
24127 case OPC_REPL_PH:
24128 case OPC_REPLV_PH:
24129 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24130 break;
24131 default:
24132 MIPS_INVAL("MASK ABSQ_S.PH");
24133 gen_reserved_instruction(ctx);
24134 break;
24136 break;
24137 case OPC_ADDU_QB_DSP:
24138 op2 = MASK_ADDU_QB(ctx->opcode);
24139 switch (op2) {
24140 case OPC_ADDQ_PH:
24141 case OPC_ADDQ_S_PH:
24142 case OPC_ADDQ_S_W:
24143 case OPC_ADDU_QB:
24144 case OPC_ADDU_S_QB:
24145 case OPC_ADDU_PH:
24146 case OPC_ADDU_S_PH:
24147 case OPC_SUBQ_PH:
24148 case OPC_SUBQ_S_PH:
24149 case OPC_SUBQ_S_W:
24150 case OPC_SUBU_QB:
24151 case OPC_SUBU_S_QB:
24152 case OPC_SUBU_PH:
24153 case OPC_SUBU_S_PH:
24154 case OPC_ADDSC:
24155 case OPC_ADDWC:
24156 case OPC_MODSUB:
24157 case OPC_RADDU_W_QB:
24158 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24159 break;
24160 case OPC_MULEU_S_PH_QBL:
24161 case OPC_MULEU_S_PH_QBR:
24162 case OPC_MULQ_RS_PH:
24163 case OPC_MULEQ_S_W_PHL:
24164 case OPC_MULEQ_S_W_PHR:
24165 case OPC_MULQ_S_PH:
24166 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24167 break;
24168 default: /* Invalid */
24169 MIPS_INVAL("MASK ADDU.QB");
24170 gen_reserved_instruction(ctx);
24171 break;
24174 break;
24175 case OPC_CMPU_EQ_QB_DSP:
24176 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
24177 switch (op2) {
24178 case OPC_PRECR_SRA_PH_W:
24179 case OPC_PRECR_SRA_R_PH_W:
24180 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24181 break;
24182 case OPC_PRECR_QB_PH:
24183 case OPC_PRECRQ_QB_PH:
24184 case OPC_PRECRQ_PH_W:
24185 case OPC_PRECRQ_RS_PH_W:
24186 case OPC_PRECRQU_S_QB_PH:
24187 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24188 break;
24189 case OPC_CMPU_EQ_QB:
24190 case OPC_CMPU_LT_QB:
24191 case OPC_CMPU_LE_QB:
24192 case OPC_CMP_EQ_PH:
24193 case OPC_CMP_LT_PH:
24194 case OPC_CMP_LE_PH:
24195 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24196 break;
24197 case OPC_CMPGU_EQ_QB:
24198 case OPC_CMPGU_LT_QB:
24199 case OPC_CMPGU_LE_QB:
24200 case OPC_CMPGDU_EQ_QB:
24201 case OPC_CMPGDU_LT_QB:
24202 case OPC_CMPGDU_LE_QB:
24203 case OPC_PICK_QB:
24204 case OPC_PICK_PH:
24205 case OPC_PACKRL_PH:
24206 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24207 break;
24208 default: /* Invalid */
24209 MIPS_INVAL("MASK CMPU.EQ.QB");
24210 gen_reserved_instruction(ctx);
24211 break;
24213 break;
24214 case OPC_SHLL_QB_DSP:
24215 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24216 break;
24217 case OPC_DPA_W_PH_DSP:
24218 op2 = MASK_DPA_W_PH(ctx->opcode);
24219 switch (op2) {
24220 case OPC_DPAU_H_QBL:
24221 case OPC_DPAU_H_QBR:
24222 case OPC_DPSU_H_QBL:
24223 case OPC_DPSU_H_QBR:
24224 case OPC_DPA_W_PH:
24225 case OPC_DPAX_W_PH:
24226 case OPC_DPAQ_S_W_PH:
24227 case OPC_DPAQX_S_W_PH:
24228 case OPC_DPAQX_SA_W_PH:
24229 case OPC_DPS_W_PH:
24230 case OPC_DPSX_W_PH:
24231 case OPC_DPSQ_S_W_PH:
24232 case OPC_DPSQX_S_W_PH:
24233 case OPC_DPSQX_SA_W_PH:
24234 case OPC_MULSAQ_S_W_PH:
24235 case OPC_DPAQ_SA_L_W:
24236 case OPC_DPSQ_SA_L_W:
24237 case OPC_MAQ_S_W_PHL:
24238 case OPC_MAQ_S_W_PHR:
24239 case OPC_MAQ_SA_W_PHL:
24240 case OPC_MAQ_SA_W_PHR:
24241 case OPC_MULSA_W_PH:
24242 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24243 break;
24244 default: /* Invalid */
24245 MIPS_INVAL("MASK DPAW.PH");
24246 gen_reserved_instruction(ctx);
24247 break;
24249 break;
24250 case OPC_INSV_DSP:
24251 op2 = MASK_INSV(ctx->opcode);
24252 switch (op2) {
24253 case OPC_INSV:
24254 check_dsp(ctx);
24256 TCGv t0, t1;
24258 if (rt == 0) {
24259 break;
24262 t0 = tcg_temp_new();
24263 t1 = tcg_temp_new();
24265 gen_load_gpr(t0, rt);
24266 gen_load_gpr(t1, rs);
24268 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
24270 tcg_temp_free(t0);
24271 tcg_temp_free(t1);
24272 break;
24274 default: /* Invalid */
24275 MIPS_INVAL("MASK INSV");
24276 gen_reserved_instruction(ctx);
24277 break;
24279 break;
24280 case OPC_APPEND_DSP:
24281 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24282 break;
24283 case OPC_EXTR_W_DSP:
24284 op2 = MASK_EXTR_W(ctx->opcode);
24285 switch (op2) {
24286 case OPC_EXTR_W:
24287 case OPC_EXTR_R_W:
24288 case OPC_EXTR_RS_W:
24289 case OPC_EXTR_S_H:
24290 case OPC_EXTRV_S_H:
24291 case OPC_EXTRV_W:
24292 case OPC_EXTRV_R_W:
24293 case OPC_EXTRV_RS_W:
24294 case OPC_EXTP:
24295 case OPC_EXTPV:
24296 case OPC_EXTPDP:
24297 case OPC_EXTPDPV:
24298 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24299 break;
24300 case OPC_RDDSP:
24301 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
24302 break;
24303 case OPC_SHILO:
24304 case OPC_SHILOV:
24305 case OPC_MTHLIP:
24306 case OPC_WRDSP:
24307 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24308 break;
24309 default: /* Invalid */
24310 MIPS_INVAL("MASK EXTR.W");
24311 gen_reserved_instruction(ctx);
24312 break;
24314 break;
24315 #if defined(TARGET_MIPS64)
24316 case OPC_DDIV_G_2E:
24317 case OPC_DDIVU_G_2E:
24318 case OPC_DMULT_G_2E:
24319 case OPC_DMULTU_G_2E:
24320 case OPC_DMOD_G_2E:
24321 case OPC_DMODU_G_2E:
24322 check_insn(ctx, INSN_LOONGSON2E);
24323 gen_loongson_integer(ctx, op1, rd, rs, rt);
24324 break;
24325 case OPC_ABSQ_S_QH_DSP:
24326 op2 = MASK_ABSQ_S_QH(ctx->opcode);
24327 switch (op2) {
24328 case OPC_PRECEQ_L_PWL:
24329 case OPC_PRECEQ_L_PWR:
24330 case OPC_PRECEQ_PW_QHL:
24331 case OPC_PRECEQ_PW_QHR:
24332 case OPC_PRECEQ_PW_QHLA:
24333 case OPC_PRECEQ_PW_QHRA:
24334 case OPC_PRECEQU_QH_OBL:
24335 case OPC_PRECEQU_QH_OBR:
24336 case OPC_PRECEQU_QH_OBLA:
24337 case OPC_PRECEQU_QH_OBRA:
24338 case OPC_PRECEU_QH_OBL:
24339 case OPC_PRECEU_QH_OBR:
24340 case OPC_PRECEU_QH_OBLA:
24341 case OPC_PRECEU_QH_OBRA:
24342 case OPC_ABSQ_S_OB:
24343 case OPC_ABSQ_S_PW:
24344 case OPC_ABSQ_S_QH:
24345 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24346 break;
24347 case OPC_REPL_OB:
24348 case OPC_REPL_PW:
24349 case OPC_REPL_QH:
24350 case OPC_REPLV_OB:
24351 case OPC_REPLV_PW:
24352 case OPC_REPLV_QH:
24353 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24354 break;
24355 default: /* Invalid */
24356 MIPS_INVAL("MASK ABSQ_S.QH");
24357 gen_reserved_instruction(ctx);
24358 break;
24360 break;
24361 case OPC_ADDU_OB_DSP:
24362 op2 = MASK_ADDU_OB(ctx->opcode);
24363 switch (op2) {
24364 case OPC_RADDU_L_OB:
24365 case OPC_SUBQ_PW:
24366 case OPC_SUBQ_S_PW:
24367 case OPC_SUBQ_QH:
24368 case OPC_SUBQ_S_QH:
24369 case OPC_SUBU_OB:
24370 case OPC_SUBU_S_OB:
24371 case OPC_SUBU_QH:
24372 case OPC_SUBU_S_QH:
24373 case OPC_SUBUH_OB:
24374 case OPC_SUBUH_R_OB:
24375 case OPC_ADDQ_PW:
24376 case OPC_ADDQ_S_PW:
24377 case OPC_ADDQ_QH:
24378 case OPC_ADDQ_S_QH:
24379 case OPC_ADDU_OB:
24380 case OPC_ADDU_S_OB:
24381 case OPC_ADDU_QH:
24382 case OPC_ADDU_S_QH:
24383 case OPC_ADDUH_OB:
24384 case OPC_ADDUH_R_OB:
24385 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24386 break;
24387 case OPC_MULEQ_S_PW_QHL:
24388 case OPC_MULEQ_S_PW_QHR:
24389 case OPC_MULEU_S_QH_OBL:
24390 case OPC_MULEU_S_QH_OBR:
24391 case OPC_MULQ_RS_QH:
24392 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24393 break;
24394 default: /* Invalid */
24395 MIPS_INVAL("MASK ADDU.OB");
24396 gen_reserved_instruction(ctx);
24397 break;
24399 break;
24400 case OPC_CMPU_EQ_OB_DSP:
24401 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
24402 switch (op2) {
24403 case OPC_PRECR_SRA_QH_PW:
24404 case OPC_PRECR_SRA_R_QH_PW:
24405 /* Return value is rt. */
24406 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24407 break;
24408 case OPC_PRECR_OB_QH:
24409 case OPC_PRECRQ_OB_QH:
24410 case OPC_PRECRQ_PW_L:
24411 case OPC_PRECRQ_QH_PW:
24412 case OPC_PRECRQ_RS_QH_PW:
24413 case OPC_PRECRQU_S_OB_QH:
24414 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24415 break;
24416 case OPC_CMPU_EQ_OB:
24417 case OPC_CMPU_LT_OB:
24418 case OPC_CMPU_LE_OB:
24419 case OPC_CMP_EQ_QH:
24420 case OPC_CMP_LT_QH:
24421 case OPC_CMP_LE_QH:
24422 case OPC_CMP_EQ_PW:
24423 case OPC_CMP_LT_PW:
24424 case OPC_CMP_LE_PW:
24425 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24426 break;
24427 case OPC_CMPGDU_EQ_OB:
24428 case OPC_CMPGDU_LT_OB:
24429 case OPC_CMPGDU_LE_OB:
24430 case OPC_CMPGU_EQ_OB:
24431 case OPC_CMPGU_LT_OB:
24432 case OPC_CMPGU_LE_OB:
24433 case OPC_PACKRL_PW:
24434 case OPC_PICK_OB:
24435 case OPC_PICK_PW:
24436 case OPC_PICK_QH:
24437 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24438 break;
24439 default: /* Invalid */
24440 MIPS_INVAL("MASK CMPU_EQ.OB");
24441 gen_reserved_instruction(ctx);
24442 break;
24444 break;
24445 case OPC_DAPPEND_DSP:
24446 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24447 break;
24448 case OPC_DEXTR_W_DSP:
24449 op2 = MASK_DEXTR_W(ctx->opcode);
24450 switch (op2) {
24451 case OPC_DEXTP:
24452 case OPC_DEXTPDP:
24453 case OPC_DEXTPDPV:
24454 case OPC_DEXTPV:
24455 case OPC_DEXTR_L:
24456 case OPC_DEXTR_R_L:
24457 case OPC_DEXTR_RS_L:
24458 case OPC_DEXTR_W:
24459 case OPC_DEXTR_R_W:
24460 case OPC_DEXTR_RS_W:
24461 case OPC_DEXTR_S_H:
24462 case OPC_DEXTRV_L:
24463 case OPC_DEXTRV_R_L:
24464 case OPC_DEXTRV_RS_L:
24465 case OPC_DEXTRV_S_H:
24466 case OPC_DEXTRV_W:
24467 case OPC_DEXTRV_R_W:
24468 case OPC_DEXTRV_RS_W:
24469 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24470 break;
24471 case OPC_DMTHLIP:
24472 case OPC_DSHILO:
24473 case OPC_DSHILOV:
24474 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24475 break;
24476 default: /* Invalid */
24477 MIPS_INVAL("MASK EXTR.W");
24478 gen_reserved_instruction(ctx);
24479 break;
24481 break;
24482 case OPC_DPAQ_W_QH_DSP:
24483 op2 = MASK_DPAQ_W_QH(ctx->opcode);
24484 switch (op2) {
24485 case OPC_DPAU_H_OBL:
24486 case OPC_DPAU_H_OBR:
24487 case OPC_DPSU_H_OBL:
24488 case OPC_DPSU_H_OBR:
24489 case OPC_DPA_W_QH:
24490 case OPC_DPAQ_S_W_QH:
24491 case OPC_DPS_W_QH:
24492 case OPC_DPSQ_S_W_QH:
24493 case OPC_MULSAQ_S_W_QH:
24494 case OPC_DPAQ_SA_L_PW:
24495 case OPC_DPSQ_SA_L_PW:
24496 case OPC_MULSAQ_S_L_PW:
24497 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24498 break;
24499 case OPC_MAQ_S_W_QHLL:
24500 case OPC_MAQ_S_W_QHLR:
24501 case OPC_MAQ_S_W_QHRL:
24502 case OPC_MAQ_S_W_QHRR:
24503 case OPC_MAQ_SA_W_QHLL:
24504 case OPC_MAQ_SA_W_QHLR:
24505 case OPC_MAQ_SA_W_QHRL:
24506 case OPC_MAQ_SA_W_QHRR:
24507 case OPC_MAQ_S_L_PWL:
24508 case OPC_MAQ_S_L_PWR:
24509 case OPC_DMADD:
24510 case OPC_DMADDU:
24511 case OPC_DMSUB:
24512 case OPC_DMSUBU:
24513 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24514 break;
24515 default: /* Invalid */
24516 MIPS_INVAL("MASK DPAQ.W.QH");
24517 gen_reserved_instruction(ctx);
24518 break;
24520 break;
24521 case OPC_DINSV_DSP:
24522 op2 = MASK_INSV(ctx->opcode);
24523 switch (op2) {
24524 case OPC_DINSV:
24526 TCGv t0, t1;
24528 if (rt == 0) {
24529 break;
24531 check_dsp(ctx);
24533 t0 = tcg_temp_new();
24534 t1 = tcg_temp_new();
24536 gen_load_gpr(t0, rt);
24537 gen_load_gpr(t1, rs);
24539 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
24541 tcg_temp_free(t0);
24542 tcg_temp_free(t1);
24543 break;
24545 default: /* Invalid */
24546 MIPS_INVAL("MASK DINSV");
24547 gen_reserved_instruction(ctx);
24548 break;
24550 break;
24551 case OPC_SHLL_OB_DSP:
24552 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24553 break;
24554 #endif
24555 default: /* Invalid */
24556 MIPS_INVAL("special3_legacy");
24557 gen_reserved_instruction(ctx);
24558 break;
24563 #if defined(TARGET_MIPS64)
24565 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
24567 uint32_t opc = MASK_MMI(ctx->opcode);
24568 int rs = extract32(ctx->opcode, 21, 5);
24569 int rt = extract32(ctx->opcode, 16, 5);
24570 int rd = extract32(ctx->opcode, 11, 5);
24572 switch (opc) {
24573 case MMI_OPC_MULT1:
24574 case MMI_OPC_MULTU1:
24575 case MMI_OPC_MADD:
24576 case MMI_OPC_MADDU:
24577 case MMI_OPC_MADD1:
24578 case MMI_OPC_MADDU1:
24579 gen_mul_txx9(ctx, opc, rd, rs, rt);
24580 break;
24581 case MMI_OPC_DIV1:
24582 case MMI_OPC_DIVU1:
24583 gen_div1_tx79(ctx, opc, rs, rt);
24584 break;
24585 default:
24586 MIPS_INVAL("TX79 MMI class");
24587 gen_reserved_instruction(ctx);
24588 break;
24592 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
24594 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_LQ */
24597 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
24599 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
24603 * The TX79-specific instruction Store Quadword
24605 * +--------+-------+-------+------------------------+
24606 * | 011111 | base | rt | offset | SQ
24607 * +--------+-------+-------+------------------------+
24608 * 6 5 5 16
24610 * has the same opcode as the Read Hardware Register instruction
24612 * +--------+-------+-------+-------+-------+--------+
24613 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
24614 * +--------+-------+-------+-------+-------+--------+
24615 * 6 5 5 5 5 6
24617 * that is required, trapped and emulated by the Linux kernel. However, all
24618 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
24619 * offset is odd. Therefore all valid SQ instructions can execute normally.
24620 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
24621 * between SQ and RDHWR, as the Linux kernel does.
24623 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
24625 int base = extract32(ctx->opcode, 21, 5);
24626 int rt = extract32(ctx->opcode, 16, 5);
24627 int offset = extract32(ctx->opcode, 0, 16);
24629 #ifdef CONFIG_USER_ONLY
24630 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
24631 uint32_t op2 = extract32(ctx->opcode, 6, 5);
24633 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
24634 int rd = extract32(ctx->opcode, 11, 5);
24636 gen_rdhwr(ctx, rt, rd, 0);
24637 return;
24639 #endif
24641 gen_mmi_sq(ctx, base, rt, offset);
24644 #endif
24646 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
24648 int rs, rt, rd, sa;
24649 uint32_t op1, op2;
24650 int16_t imm;
24652 rs = (ctx->opcode >> 21) & 0x1f;
24653 rt = (ctx->opcode >> 16) & 0x1f;
24654 rd = (ctx->opcode >> 11) & 0x1f;
24655 sa = (ctx->opcode >> 6) & 0x1f;
24656 imm = sextract32(ctx->opcode, 7, 9);
24658 op1 = MASK_SPECIAL3(ctx->opcode);
24661 * EVA loads and stores overlap Loongson 2E instructions decoded by
24662 * decode_opc_special3_legacy(), so be careful to allow their decoding when
24663 * EVA is absent.
24665 if (ctx->eva) {
24666 switch (op1) {
24667 case OPC_LWLE:
24668 case OPC_LWRE:
24669 case OPC_LBUE:
24670 case OPC_LHUE:
24671 case OPC_LBE:
24672 case OPC_LHE:
24673 case OPC_LLE:
24674 case OPC_LWE:
24675 check_cp0_enabled(ctx);
24676 gen_ld(ctx, op1, rt, rs, imm);
24677 return;
24678 case OPC_SWLE:
24679 case OPC_SWRE:
24680 case OPC_SBE:
24681 case OPC_SHE:
24682 case OPC_SWE:
24683 check_cp0_enabled(ctx);
24684 gen_st(ctx, op1, rt, rs, imm);
24685 return;
24686 case OPC_SCE:
24687 check_cp0_enabled(ctx);
24688 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
24689 return;
24690 case OPC_CACHEE:
24691 check_cp0_enabled(ctx);
24692 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24693 gen_cache_operation(ctx, rt, rs, imm);
24695 /* Treat as NOP. */
24696 return;
24697 case OPC_PREFE:
24698 check_cp0_enabled(ctx);
24699 /* Treat as NOP. */
24700 return;
24704 switch (op1) {
24705 case OPC_EXT:
24706 case OPC_INS:
24707 check_insn(ctx, ISA_MIPS_R2);
24708 gen_bitops(ctx, op1, rt, rs, sa, rd);
24709 break;
24710 case OPC_BSHFL:
24711 op2 = MASK_BSHFL(ctx->opcode);
24712 switch (op2) {
24713 case OPC_ALIGN:
24714 case OPC_ALIGN_1:
24715 case OPC_ALIGN_2:
24716 case OPC_ALIGN_3:
24717 case OPC_BITSWAP:
24718 check_insn(ctx, ISA_MIPS_R6);
24719 decode_opc_special3_r6(env, ctx);
24720 break;
24721 default:
24722 check_insn(ctx, ISA_MIPS_R2);
24723 gen_bshfl(ctx, op2, rt, rd);
24724 break;
24726 break;
24727 #if defined(TARGET_MIPS64)
24728 case OPC_DEXTM:
24729 case OPC_DEXTU:
24730 case OPC_DEXT:
24731 case OPC_DINSM:
24732 case OPC_DINSU:
24733 case OPC_DINS:
24734 check_insn(ctx, ISA_MIPS_R2);
24735 check_mips_64(ctx);
24736 gen_bitops(ctx, op1, rt, rs, sa, rd);
24737 break;
24738 case OPC_DBSHFL:
24739 op2 = MASK_DBSHFL(ctx->opcode);
24740 switch (op2) {
24741 case OPC_DALIGN:
24742 case OPC_DALIGN_1:
24743 case OPC_DALIGN_2:
24744 case OPC_DALIGN_3:
24745 case OPC_DALIGN_4:
24746 case OPC_DALIGN_5:
24747 case OPC_DALIGN_6:
24748 case OPC_DALIGN_7:
24749 case OPC_DBITSWAP:
24750 check_insn(ctx, ISA_MIPS_R6);
24751 decode_opc_special3_r6(env, ctx);
24752 break;
24753 default:
24754 check_insn(ctx, ISA_MIPS_R2);
24755 check_mips_64(ctx);
24756 op2 = MASK_DBSHFL(ctx->opcode);
24757 gen_bshfl(ctx, op2, rt, rd);
24758 break;
24760 break;
24761 #endif
24762 case OPC_RDHWR:
24763 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
24764 break;
24765 case OPC_FORK:
24766 check_mt(ctx);
24768 TCGv t0 = tcg_temp_new();
24769 TCGv t1 = tcg_temp_new();
24771 gen_load_gpr(t0, rt);
24772 gen_load_gpr(t1, rs);
24773 gen_helper_fork(t0, t1);
24774 tcg_temp_free(t0);
24775 tcg_temp_free(t1);
24777 break;
24778 case OPC_YIELD:
24779 check_mt(ctx);
24781 TCGv t0 = tcg_temp_new();
24783 gen_load_gpr(t0, rs);
24784 gen_helper_yield(t0, cpu_env, t0);
24785 gen_store_gpr(t0, rd);
24786 tcg_temp_free(t0);
24788 break;
24789 default:
24790 if (ctx->insn_flags & ISA_MIPS_R6) {
24791 decode_opc_special3_r6(env, ctx);
24792 } else {
24793 decode_opc_special3_legacy(env, ctx);
24798 static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
24800 int32_t offset;
24801 int rs, rt, rd, sa;
24802 uint32_t op, op1;
24803 int16_t imm;
24805 op = MASK_OP_MAJOR(ctx->opcode);
24806 rs = (ctx->opcode >> 21) & 0x1f;
24807 rt = (ctx->opcode >> 16) & 0x1f;
24808 rd = (ctx->opcode >> 11) & 0x1f;
24809 sa = (ctx->opcode >> 6) & 0x1f;
24810 imm = (int16_t)ctx->opcode;
24811 switch (op) {
24812 case OPC_SPECIAL:
24813 decode_opc_special(env, ctx);
24814 break;
24815 case OPC_SPECIAL2:
24816 #if defined(TARGET_MIPS64)
24817 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
24818 decode_mmi(env, ctx);
24819 break;
24821 #endif
24822 if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) {
24823 if (MASK_SPECIAL2(ctx->opcode) == OPC_MUL) {
24824 gen_arith(ctx, OPC_MUL, rd, rs, rt);
24825 } else {
24826 decode_ase_mxu(ctx, ctx->opcode);
24828 break;
24830 decode_opc_special2_legacy(env, ctx);
24831 break;
24832 case OPC_SPECIAL3:
24833 #if defined(TARGET_MIPS64)
24834 if (ctx->insn_flags & INSN_R5900) {
24835 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
24836 } else {
24837 decode_opc_special3(env, ctx);
24839 #else
24840 decode_opc_special3(env, ctx);
24841 #endif
24842 break;
24843 case OPC_REGIMM:
24844 op1 = MASK_REGIMM(ctx->opcode);
24845 switch (op1) {
24846 case OPC_BLTZL: /* REGIMM branches */
24847 case OPC_BGEZL:
24848 case OPC_BLTZALL:
24849 case OPC_BGEZALL:
24850 check_insn(ctx, ISA_MIPS2);
24851 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24852 /* Fallthrough */
24853 case OPC_BLTZ:
24854 case OPC_BGEZ:
24855 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
24856 break;
24857 case OPC_BLTZAL:
24858 case OPC_BGEZAL:
24859 if (ctx->insn_flags & ISA_MIPS_R6) {
24860 if (rs == 0) {
24861 /* OPC_NAL, OPC_BAL */
24862 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
24863 } else {
24864 gen_reserved_instruction(ctx);
24866 } else {
24867 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
24869 break;
24870 case OPC_TGEI: /* REGIMM traps */
24871 case OPC_TGEIU:
24872 case OPC_TLTI:
24873 case OPC_TLTIU:
24874 case OPC_TEQI:
24876 case OPC_TNEI:
24877 check_insn(ctx, ISA_MIPS2);
24878 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24879 gen_trap(ctx, op1, rs, -1, imm);
24880 break;
24881 case OPC_SIGRIE:
24882 check_insn(ctx, ISA_MIPS_R6);
24883 gen_reserved_instruction(ctx);
24884 break;
24885 case OPC_SYNCI:
24886 check_insn(ctx, ISA_MIPS_R2);
24888 * Break the TB to be able to sync copied instructions
24889 * immediately.
24891 ctx->base.is_jmp = DISAS_STOP;
24892 break;
24893 case OPC_BPOSGE32: /* MIPS DSP branch */
24894 #if defined(TARGET_MIPS64)
24895 case OPC_BPOSGE64:
24896 #endif
24897 check_dsp(ctx);
24898 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
24899 break;
24900 #if defined(TARGET_MIPS64)
24901 case OPC_DAHI:
24902 check_insn(ctx, ISA_MIPS_R6);
24903 check_mips_64(ctx);
24904 if (rs != 0) {
24905 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
24907 break;
24908 case OPC_DATI:
24909 check_insn(ctx, ISA_MIPS_R6);
24910 check_mips_64(ctx);
24911 if (rs != 0) {
24912 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
24914 break;
24915 #endif
24916 default: /* Invalid */
24917 MIPS_INVAL("regimm");
24918 gen_reserved_instruction(ctx);
24919 break;
24921 break;
24922 case OPC_CP0:
24923 check_cp0_enabled(ctx);
24924 op1 = MASK_CP0(ctx->opcode);
24925 switch (op1) {
24926 case OPC_MFC0:
24927 case OPC_MTC0:
24928 case OPC_MFTR:
24929 case OPC_MTTR:
24930 case OPC_MFHC0:
24931 case OPC_MTHC0:
24932 #if defined(TARGET_MIPS64)
24933 case OPC_DMFC0:
24934 case OPC_DMTC0:
24935 #endif
24936 #ifndef CONFIG_USER_ONLY
24937 gen_cp0(env, ctx, op1, rt, rd);
24938 #endif /* !CONFIG_USER_ONLY */
24939 break;
24940 case OPC_C0:
24941 case OPC_C0_1:
24942 case OPC_C0_2:
24943 case OPC_C0_3:
24944 case OPC_C0_4:
24945 case OPC_C0_5:
24946 case OPC_C0_6:
24947 case OPC_C0_7:
24948 case OPC_C0_8:
24949 case OPC_C0_9:
24950 case OPC_C0_A:
24951 case OPC_C0_B:
24952 case OPC_C0_C:
24953 case OPC_C0_D:
24954 case OPC_C0_E:
24955 case OPC_C0_F:
24956 #ifndef CONFIG_USER_ONLY
24957 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
24958 #endif /* !CONFIG_USER_ONLY */
24959 break;
24960 case OPC_MFMC0:
24961 #ifndef CONFIG_USER_ONLY
24963 uint32_t op2;
24964 TCGv t0 = tcg_temp_new();
24966 op2 = MASK_MFMC0(ctx->opcode);
24967 switch (op2) {
24968 case OPC_DMT:
24969 check_cp0_mt(ctx);
24970 gen_helper_dmt(t0);
24971 gen_store_gpr(t0, rt);
24972 break;
24973 case OPC_EMT:
24974 check_cp0_mt(ctx);
24975 gen_helper_emt(t0);
24976 gen_store_gpr(t0, rt);
24977 break;
24978 case OPC_DVPE:
24979 check_cp0_mt(ctx);
24980 gen_helper_dvpe(t0, cpu_env);
24981 gen_store_gpr(t0, rt);
24982 break;
24983 case OPC_EVPE:
24984 check_cp0_mt(ctx);
24985 gen_helper_evpe(t0, cpu_env);
24986 gen_store_gpr(t0, rt);
24987 break;
24988 case OPC_DVP:
24989 check_insn(ctx, ISA_MIPS_R6);
24990 if (ctx->vp) {
24991 gen_helper_dvp(t0, cpu_env);
24992 gen_store_gpr(t0, rt);
24994 break;
24995 case OPC_EVP:
24996 check_insn(ctx, ISA_MIPS_R6);
24997 if (ctx->vp) {
24998 gen_helper_evp(t0, cpu_env);
24999 gen_store_gpr(t0, rt);
25001 break;
25002 case OPC_DI:
25003 check_insn(ctx, ISA_MIPS_R2);
25004 save_cpu_state(ctx, 1);
25005 gen_helper_di(t0, cpu_env);
25006 gen_store_gpr(t0, rt);
25008 * Stop translation as we may have switched
25009 * the execution mode.
25011 ctx->base.is_jmp = DISAS_STOP;
25012 break;
25013 case OPC_EI:
25014 check_insn(ctx, ISA_MIPS_R2);
25015 save_cpu_state(ctx, 1);
25016 gen_helper_ei(t0, cpu_env);
25017 gen_store_gpr(t0, rt);
25019 * DISAS_STOP isn't sufficient, we need to ensure we break
25020 * out of translated code to check for pending interrupts.
25022 gen_save_pc(ctx->base.pc_next + 4);
25023 ctx->base.is_jmp = DISAS_EXIT;
25024 break;
25025 default: /* Invalid */
25026 MIPS_INVAL("mfmc0");
25027 gen_reserved_instruction(ctx);
25028 break;
25030 tcg_temp_free(t0);
25032 #endif /* !CONFIG_USER_ONLY */
25033 break;
25034 case OPC_RDPGPR:
25035 check_insn(ctx, ISA_MIPS_R2);
25036 gen_load_srsgpr(rt, rd);
25037 break;
25038 case OPC_WRPGPR:
25039 check_insn(ctx, ISA_MIPS_R2);
25040 gen_store_srsgpr(rt, rd);
25041 break;
25042 default:
25043 MIPS_INVAL("cp0");
25044 gen_reserved_instruction(ctx);
25045 break;
25047 break;
25048 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
25049 if (ctx->insn_flags & ISA_MIPS_R6) {
25050 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
25051 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25052 } else {
25053 /* OPC_ADDI */
25054 /* Arithmetic with immediate opcode */
25055 gen_arith_imm(ctx, op, rt, rs, imm);
25057 break;
25058 case OPC_ADDIU:
25059 gen_arith_imm(ctx, op, rt, rs, imm);
25060 break;
25061 case OPC_SLTI: /* Set on less than with immediate opcode */
25062 case OPC_SLTIU:
25063 gen_slt_imm(ctx, op, rt, rs, imm);
25064 break;
25065 case OPC_ANDI: /* Arithmetic with immediate opcode */
25066 case OPC_LUI: /* OPC_AUI */
25067 case OPC_ORI:
25068 case OPC_XORI:
25069 gen_logic_imm(ctx, op, rt, rs, imm);
25070 break;
25071 case OPC_J: /* Jump */
25072 case OPC_JAL:
25073 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
25074 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
25075 break;
25076 /* Branch */
25077 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
25078 if (ctx->insn_flags & ISA_MIPS_R6) {
25079 if (rt == 0) {
25080 gen_reserved_instruction(ctx);
25081 break;
25083 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
25084 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25085 } else {
25086 /* OPC_BLEZL */
25087 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25089 break;
25090 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
25091 if (ctx->insn_flags & ISA_MIPS_R6) {
25092 if (rt == 0) {
25093 gen_reserved_instruction(ctx);
25094 break;
25096 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
25097 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25098 } else {
25099 /* OPC_BGTZL */
25100 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25102 break;
25103 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
25104 if (rt == 0) {
25105 /* OPC_BLEZ */
25106 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25107 } else {
25108 check_insn(ctx, ISA_MIPS_R6);
25109 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
25110 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25112 break;
25113 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
25114 if (rt == 0) {
25115 /* OPC_BGTZ */
25116 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25117 } else {
25118 check_insn(ctx, ISA_MIPS_R6);
25119 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
25120 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25122 break;
25123 case OPC_BEQL:
25124 case OPC_BNEL:
25125 check_insn(ctx, ISA_MIPS2);
25126 check_insn_opc_removed(ctx, ISA_MIPS_R6);
25127 /* Fallthrough */
25128 case OPC_BEQ:
25129 case OPC_BNE:
25130 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25131 break;
25132 case OPC_LL: /* Load and stores */
25133 check_insn(ctx, ISA_MIPS2);
25134 if (ctx->insn_flags & INSN_R5900) {
25135 check_insn_opc_user_only(ctx, INSN_R5900);
25137 /* Fallthrough */
25138 case OPC_LWL:
25139 case OPC_LWR:
25140 case OPC_LB:
25141 case OPC_LH:
25142 case OPC_LW:
25143 case OPC_LWPC:
25144 case OPC_LBU:
25145 case OPC_LHU:
25146 gen_ld(ctx, op, rt, rs, imm);
25147 break;
25148 case OPC_SWL:
25149 case OPC_SWR:
25150 case OPC_SB:
25151 case OPC_SH:
25152 case OPC_SW:
25153 gen_st(ctx, op, rt, rs, imm);
25154 break;
25155 case OPC_SC:
25156 check_insn(ctx, ISA_MIPS2);
25157 if (ctx->insn_flags & INSN_R5900) {
25158 check_insn_opc_user_only(ctx, INSN_R5900);
25160 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
25161 break;
25162 case OPC_CACHE:
25163 check_cp0_enabled(ctx);
25164 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
25165 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25166 gen_cache_operation(ctx, rt, rs, imm);
25168 /* Treat as NOP. */
25169 break;
25170 case OPC_PREF:
25171 if (ctx->insn_flags & INSN_R5900) {
25172 /* Treat as NOP. */
25173 } else {
25174 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
25175 /* Treat as NOP. */
25177 break;
25179 /* Floating point (COP1). */
25180 case OPC_LWC1:
25181 case OPC_LDC1:
25182 case OPC_SWC1:
25183 case OPC_SDC1:
25184 gen_cop1_ldst(ctx, op, rt, rs, imm);
25185 break;
25187 case OPC_CP1:
25188 op1 = MASK_CP1(ctx->opcode);
25190 switch (op1) {
25191 case OPC_MFHC1:
25192 case OPC_MTHC1:
25193 check_cp1_enabled(ctx);
25194 check_insn(ctx, ISA_MIPS_R2);
25195 /* fall through */
25196 case OPC_MFC1:
25197 case OPC_CFC1:
25198 case OPC_MTC1:
25199 case OPC_CTC1:
25200 check_cp1_enabled(ctx);
25201 gen_cp1(ctx, op1, rt, rd);
25202 break;
25203 #if defined(TARGET_MIPS64)
25204 case OPC_DMFC1:
25205 case OPC_DMTC1:
25206 check_cp1_enabled(ctx);
25207 check_insn(ctx, ISA_MIPS3);
25208 check_mips_64(ctx);
25209 gen_cp1(ctx, op1, rt, rd);
25210 break;
25211 #endif
25212 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
25213 check_cp1_enabled(ctx);
25214 if (ctx->insn_flags & ISA_MIPS_R6) {
25215 /* OPC_BC1EQZ */
25216 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25217 rt, imm << 2, 4);
25218 } else {
25219 /* OPC_BC1ANY2 */
25220 check_cop1x(ctx);
25221 check_insn(ctx, ASE_MIPS3D);
25222 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25223 (rt >> 2) & 0x7, imm << 2);
25225 break;
25226 case OPC_BC1NEZ:
25227 check_cp1_enabled(ctx);
25228 check_insn(ctx, ISA_MIPS_R6);
25229 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25230 rt, imm << 2, 4);
25231 break;
25232 case OPC_BC1ANY4:
25233 check_cp1_enabled(ctx);
25234 check_insn_opc_removed(ctx, ISA_MIPS_R6);
25235 check_cop1x(ctx);
25236 check_insn(ctx, ASE_MIPS3D);
25237 /* fall through */
25238 case OPC_BC1:
25239 check_cp1_enabled(ctx);
25240 check_insn_opc_removed(ctx, ISA_MIPS_R6);
25241 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25242 (rt >> 2) & 0x7, imm << 2);
25243 break;
25244 case OPC_PS_FMT:
25245 check_ps(ctx);
25246 /* fall through */
25247 case OPC_S_FMT:
25248 case OPC_D_FMT:
25249 check_cp1_enabled(ctx);
25250 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25251 (imm >> 8) & 0x7);
25252 break;
25253 case OPC_W_FMT:
25254 case OPC_L_FMT:
25256 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
25257 check_cp1_enabled(ctx);
25258 if (ctx->insn_flags & ISA_MIPS_R6) {
25259 switch (r6_op) {
25260 case R6_OPC_CMP_AF_S:
25261 case R6_OPC_CMP_UN_S:
25262 case R6_OPC_CMP_EQ_S:
25263 case R6_OPC_CMP_UEQ_S:
25264 case R6_OPC_CMP_LT_S:
25265 case R6_OPC_CMP_ULT_S:
25266 case R6_OPC_CMP_LE_S:
25267 case R6_OPC_CMP_ULE_S:
25268 case R6_OPC_CMP_SAF_S:
25269 case R6_OPC_CMP_SUN_S:
25270 case R6_OPC_CMP_SEQ_S:
25271 case R6_OPC_CMP_SEUQ_S:
25272 case R6_OPC_CMP_SLT_S:
25273 case R6_OPC_CMP_SULT_S:
25274 case R6_OPC_CMP_SLE_S:
25275 case R6_OPC_CMP_SULE_S:
25276 case R6_OPC_CMP_OR_S:
25277 case R6_OPC_CMP_UNE_S:
25278 case R6_OPC_CMP_NE_S:
25279 case R6_OPC_CMP_SOR_S:
25280 case R6_OPC_CMP_SUNE_S:
25281 case R6_OPC_CMP_SNE_S:
25282 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25283 break;
25284 case R6_OPC_CMP_AF_D:
25285 case R6_OPC_CMP_UN_D:
25286 case R6_OPC_CMP_EQ_D:
25287 case R6_OPC_CMP_UEQ_D:
25288 case R6_OPC_CMP_LT_D:
25289 case R6_OPC_CMP_ULT_D:
25290 case R6_OPC_CMP_LE_D:
25291 case R6_OPC_CMP_ULE_D:
25292 case R6_OPC_CMP_SAF_D:
25293 case R6_OPC_CMP_SUN_D:
25294 case R6_OPC_CMP_SEQ_D:
25295 case R6_OPC_CMP_SEUQ_D:
25296 case R6_OPC_CMP_SLT_D:
25297 case R6_OPC_CMP_SULT_D:
25298 case R6_OPC_CMP_SLE_D:
25299 case R6_OPC_CMP_SULE_D:
25300 case R6_OPC_CMP_OR_D:
25301 case R6_OPC_CMP_UNE_D:
25302 case R6_OPC_CMP_NE_D:
25303 case R6_OPC_CMP_SOR_D:
25304 case R6_OPC_CMP_SUNE_D:
25305 case R6_OPC_CMP_SNE_D:
25306 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25307 break;
25308 default:
25309 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
25310 rt, rd, sa, (imm >> 8) & 0x7);
25312 break;
25314 } else {
25315 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25316 (imm >> 8) & 0x7);
25318 break;
25320 default:
25321 MIPS_INVAL("cp1");
25322 gen_reserved_instruction(ctx);
25323 break;
25325 break;
25327 /* Compact branches [R6] and COP2 [non-R6] */
25328 case OPC_BC: /* OPC_LWC2 */
25329 case OPC_BALC: /* OPC_SWC2 */
25330 if (ctx->insn_flags & ISA_MIPS_R6) {
25331 /* OPC_BC, OPC_BALC */
25332 gen_compute_compact_branch(ctx, op, 0, 0,
25333 sextract32(ctx->opcode << 2, 0, 28));
25334 } else if (ctx->insn_flags & ASE_LEXT) {
25335 gen_loongson_lswc2(ctx, rt, rs, rd);
25336 } else {
25337 /* OPC_LWC2, OPC_SWC2 */
25338 /* COP2: Not implemented. */
25339 generate_exception_err(ctx, EXCP_CpU, 2);
25341 break;
25342 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
25343 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
25344 if (ctx->insn_flags & ISA_MIPS_R6) {
25345 if (rs != 0) {
25346 /* OPC_BEQZC, OPC_BNEZC */
25347 gen_compute_compact_branch(ctx, op, rs, 0,
25348 sextract32(ctx->opcode << 2, 0, 23));
25349 } else {
25350 /* OPC_JIC, OPC_JIALC */
25351 gen_compute_compact_branch(ctx, op, 0, rt, imm);
25353 } else if (ctx->insn_flags & ASE_LEXT) {
25354 gen_loongson_lsdc2(ctx, rt, rs, rd);
25355 } else {
25356 /* OPC_LWC2, OPC_SWC2 */
25357 /* COP2: Not implemented. */
25358 generate_exception_err(ctx, EXCP_CpU, 2);
25360 break;
25361 case OPC_CP2:
25362 check_insn(ctx, ASE_LMMI);
25363 /* Note that these instructions use different fields. */
25364 gen_loongson_multimedia(ctx, sa, rd, rt);
25365 break;
25367 case OPC_CP3:
25368 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
25369 check_cp1_enabled(ctx);
25370 op1 = MASK_CP3(ctx->opcode);
25371 switch (op1) {
25372 case OPC_LUXC1:
25373 case OPC_SUXC1:
25374 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
25375 /* Fallthrough */
25376 case OPC_LWXC1:
25377 case OPC_LDXC1:
25378 case OPC_SWXC1:
25379 case OPC_SDXC1:
25380 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25381 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
25382 break;
25383 case OPC_PREFX:
25384 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25385 /* Treat as NOP. */
25386 break;
25387 case OPC_ALNV_PS:
25388 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
25389 /* Fallthrough */
25390 case OPC_MADD_S:
25391 case OPC_MADD_D:
25392 case OPC_MADD_PS:
25393 case OPC_MSUB_S:
25394 case OPC_MSUB_D:
25395 case OPC_MSUB_PS:
25396 case OPC_NMADD_S:
25397 case OPC_NMADD_D:
25398 case OPC_NMADD_PS:
25399 case OPC_NMSUB_S:
25400 case OPC_NMSUB_D:
25401 case OPC_NMSUB_PS:
25402 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25403 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
25404 break;
25405 default:
25406 MIPS_INVAL("cp3");
25407 gen_reserved_instruction(ctx);
25408 break;
25410 } else {
25411 generate_exception_err(ctx, EXCP_CpU, 1);
25413 break;
25415 #if defined(TARGET_MIPS64)
25416 /* MIPS64 opcodes */
25417 case OPC_LLD:
25418 if (ctx->insn_flags & INSN_R5900) {
25419 check_insn_opc_user_only(ctx, INSN_R5900);
25421 /* fall through */
25422 case OPC_LDL:
25423 case OPC_LDR:
25424 case OPC_LWU:
25425 case OPC_LD:
25426 check_insn(ctx, ISA_MIPS3);
25427 check_mips_64(ctx);
25428 gen_ld(ctx, op, rt, rs, imm);
25429 break;
25430 case OPC_SDL:
25431 case OPC_SDR:
25432 case OPC_SD:
25433 check_insn(ctx, ISA_MIPS3);
25434 check_mips_64(ctx);
25435 gen_st(ctx, op, rt, rs, imm);
25436 break;
25437 case OPC_SCD:
25438 check_insn(ctx, ISA_MIPS3);
25439 if (ctx->insn_flags & INSN_R5900) {
25440 check_insn_opc_user_only(ctx, INSN_R5900);
25442 check_mips_64(ctx);
25443 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
25444 break;
25445 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
25446 if (ctx->insn_flags & ISA_MIPS_R6) {
25447 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
25448 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25449 } else {
25450 /* OPC_DADDI */
25451 check_insn(ctx, ISA_MIPS3);
25452 check_mips_64(ctx);
25453 gen_arith_imm(ctx, op, rt, rs, imm);
25455 break;
25456 case OPC_DADDIU:
25457 check_insn(ctx, ISA_MIPS3);
25458 check_mips_64(ctx);
25459 gen_arith_imm(ctx, op, rt, rs, imm);
25460 break;
25461 #else
25462 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
25463 if (ctx->insn_flags & ISA_MIPS_R6) {
25464 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25465 } else {
25466 MIPS_INVAL("major opcode");
25467 gen_reserved_instruction(ctx);
25469 break;
25470 #endif
25471 case OPC_DAUI: /* OPC_JALX */
25472 if (ctx->insn_flags & ISA_MIPS_R6) {
25473 #if defined(TARGET_MIPS64)
25474 /* OPC_DAUI */
25475 check_mips_64(ctx);
25476 if (rs == 0) {
25477 generate_exception(ctx, EXCP_RI);
25478 } else if (rt != 0) {
25479 TCGv t0 = tcg_temp_new();
25480 gen_load_gpr(t0, rs);
25481 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
25482 tcg_temp_free(t0);
25484 #else
25485 gen_reserved_instruction(ctx);
25486 MIPS_INVAL("major opcode");
25487 #endif
25488 } else {
25489 /* OPC_JALX */
25490 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
25491 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
25492 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
25494 break;
25495 case OPC_MDMX: /* MMI_OPC_LQ */
25496 if (ctx->insn_flags & INSN_R5900) {
25497 #if defined(TARGET_MIPS64)
25498 gen_mmi_lq(env, ctx);
25499 #endif
25500 } else {
25501 /* MDMX: Not implemented. */
25503 break;
25504 case OPC_PCREL:
25505 check_insn(ctx, ISA_MIPS_R6);
25506 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
25507 break;
25508 default: /* Invalid */
25509 MIPS_INVAL("major opcode");
25510 return false;
25512 return true;
25515 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
25517 /* make sure instructions are on a word boundary */
25518 if (ctx->base.pc_next & 0x3) {
25519 env->CP0_BadVAddr = ctx->base.pc_next;
25520 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
25521 return;
25524 /* Handle blikely not taken case */
25525 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
25526 TCGLabel *l1 = gen_new_label();
25528 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
25529 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
25530 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
25531 gen_set_label(l1);
25534 /* Transition to the auto-generated decoder. */
25536 /* ISA extensions */
25537 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
25538 return;
25541 /* ISA (from latest to oldest) */
25542 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
25543 return;
25545 if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
25546 return;
25549 if (decode_opc_legacy(env, ctx)) {
25550 return;
25553 gen_reserved_instruction(ctx);
25556 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
25558 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25559 CPUMIPSState *env = cs->env_ptr;
25561 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
25562 ctx->saved_pc = -1;
25563 ctx->insn_flags = env->insn_flags;
25564 ctx->CP0_Config1 = env->CP0_Config1;
25565 ctx->CP0_Config2 = env->CP0_Config2;
25566 ctx->CP0_Config3 = env->CP0_Config3;
25567 ctx->CP0_Config5 = env->CP0_Config5;
25568 ctx->btarget = 0;
25569 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
25570 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
25571 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
25572 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
25573 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
25574 ctx->PAMask = env->PAMask;
25575 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
25576 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
25577 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
25578 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
25579 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
25580 /* Restore delay slot state from the tb context. */
25581 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
25582 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
25583 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
25584 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
25585 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
25586 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
25587 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
25588 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
25589 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
25590 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
25591 restore_cpu_state(env, ctx);
25592 #ifdef CONFIG_USER_ONLY
25593 ctx->mem_idx = MIPS_HFLAG_UM;
25594 #else
25595 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
25596 #endif
25597 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
25598 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
25600 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
25601 ctx->hflags);
25604 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
25608 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
25610 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25612 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
25613 ctx->btarget);
25616 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
25617 const CPUBreakpoint *bp)
25619 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25621 save_cpu_state(ctx, 1);
25622 ctx->base.is_jmp = DISAS_NORETURN;
25623 gen_helper_raise_exception_debug(cpu_env);
25625 * The address covered by the breakpoint must be included in
25626 * [tb->pc, tb->pc + tb->size) in order to for it to be
25627 * properly cleared -- thus we increment the PC here so that
25628 * the logic setting tb->size below does the right thing.
25630 ctx->base.pc_next += 4;
25631 return true;
25634 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
25636 CPUMIPSState *env = cs->env_ptr;
25637 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25638 int insn_bytes;
25639 int is_slot;
25641 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
25642 if (ctx->insn_flags & ISA_NANOMIPS32) {
25643 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
25644 insn_bytes = decode_nanomips_opc(env, ctx);
25645 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
25646 ctx->opcode = translator_ldl(env, ctx->base.pc_next);
25647 insn_bytes = 4;
25648 decode_opc(env, ctx);
25649 } else if (ctx->insn_flags & ASE_MICROMIPS) {
25650 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
25651 insn_bytes = decode_micromips_opc(env, ctx);
25652 } else if (ctx->insn_flags & ASE_MIPS16) {
25653 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
25654 insn_bytes = decode_mips16_opc(env, ctx);
25655 } else {
25656 gen_reserved_instruction(ctx);
25657 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
25658 return;
25661 if (ctx->hflags & MIPS_HFLAG_BMASK) {
25662 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
25663 MIPS_HFLAG_FBNSLOT))) {
25665 * Force to generate branch as there is neither delay nor
25666 * forbidden slot.
25668 is_slot = 1;
25670 if ((ctx->hflags & MIPS_HFLAG_M16) &&
25671 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
25673 * Force to generate branch as microMIPS R6 doesn't restrict
25674 * branches in the forbidden slot.
25676 is_slot = 1;
25679 if (is_slot) {
25680 gen_branch(ctx, insn_bytes);
25682 ctx->base.pc_next += insn_bytes;
25684 if (ctx->base.is_jmp != DISAS_NEXT) {
25685 return;
25688 * Execute a branch and its delay slot as a single instruction.
25689 * This is what GDB expects and is consistent with what the
25690 * hardware does (e.g. if a delay slot instruction faults, the
25691 * reported PC is the PC of the branch).
25693 if (ctx->base.singlestep_enabled &&
25694 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
25695 ctx->base.is_jmp = DISAS_TOO_MANY;
25697 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
25698 ctx->base.is_jmp = DISAS_TOO_MANY;
25702 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
25704 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25706 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
25707 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
25708 gen_helper_raise_exception_debug(cpu_env);
25709 } else {
25710 switch (ctx->base.is_jmp) {
25711 case DISAS_STOP:
25712 gen_save_pc(ctx->base.pc_next);
25713 tcg_gen_lookup_and_goto_ptr();
25714 break;
25715 case DISAS_NEXT:
25716 case DISAS_TOO_MANY:
25717 save_cpu_state(ctx, 0);
25718 gen_goto_tb(ctx, 0, ctx->base.pc_next);
25719 break;
25720 case DISAS_EXIT:
25721 tcg_gen_exit_tb(NULL, 0);
25722 break;
25723 case DISAS_NORETURN:
25724 break;
25725 default:
25726 g_assert_not_reached();
25731 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
25733 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
25734 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
25737 static const TranslatorOps mips_tr_ops = {
25738 .init_disas_context = mips_tr_init_disas_context,
25739 .tb_start = mips_tr_tb_start,
25740 .insn_start = mips_tr_insn_start,
25741 .breakpoint_check = mips_tr_breakpoint_check,
25742 .translate_insn = mips_tr_translate_insn,
25743 .tb_stop = mips_tr_tb_stop,
25744 .disas_log = mips_tr_disas_log,
25747 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
25749 DisasContext ctx;
25751 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
25754 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
25756 int i;
25757 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
25759 #define printfpr(fp) \
25760 do { \
25761 if (is_fpu64) \
25762 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
25763 " fd:%13g fs:%13g psu: %13g\n", \
25764 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
25765 (double)(fp)->fd, \
25766 (double)(fp)->fs[FP_ENDIAN_IDX], \
25767 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
25768 else { \
25769 fpr_t tmp; \
25770 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
25771 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
25772 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
25773 " fd:%13g fs:%13g psu:%13g\n", \
25774 tmp.w[FP_ENDIAN_IDX], tmp.d, \
25775 (double)tmp.fd, \
25776 (double)tmp.fs[FP_ENDIAN_IDX], \
25777 (double)tmp.fs[!FP_ENDIAN_IDX]); \
25779 } while (0)
25782 qemu_fprintf(f,
25783 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
25784 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
25785 get_float_exception_flags(&env->active_fpu.fp_status));
25786 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
25787 qemu_fprintf(f, "%3s: ", fregnames[i]);
25788 printfpr(&env->active_fpu.fpr[i]);
25791 #undef printfpr
25794 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
25796 MIPSCPU *cpu = MIPS_CPU(cs);
25797 CPUMIPSState *env = &cpu->env;
25798 int i;
25800 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
25801 " LO=0x" TARGET_FMT_lx " ds %04x "
25802 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
25803 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
25804 env->hflags, env->btarget, env->bcond);
25805 for (i = 0; i < 32; i++) {
25806 if ((i & 3) == 0) {
25807 qemu_fprintf(f, "GPR%02d:", i);
25809 qemu_fprintf(f, " %s " TARGET_FMT_lx,
25810 regnames[i], env->active_tc.gpr[i]);
25811 if ((i & 3) == 3) {
25812 qemu_fprintf(f, "\n");
25816 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
25817 TARGET_FMT_lx "\n",
25818 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
25819 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
25820 PRIx64 "\n",
25821 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
25822 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
25823 env->CP0_Config2, env->CP0_Config3);
25824 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
25825 env->CP0_Config4, env->CP0_Config5);
25826 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
25827 fpu_dump_state(env, f, flags);
25831 void mips_tcg_init(void)
25833 int i;
25835 cpu_gpr[0] = NULL;
25836 for (i = 1; i < 32; i++)
25837 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
25838 offsetof(CPUMIPSState,
25839 active_tc.gpr[i]),
25840 regnames[i]);
25841 #if defined(TARGET_MIPS64)
25842 cpu_gpr_hi[0] = NULL;
25844 for (unsigned i = 1; i < 32; i++) {
25845 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
25847 cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env,
25848 offsetof(CPUMIPSState,
25849 active_tc.gpr_hi[i]),
25850 rname);
25852 #endif /* !TARGET_MIPS64 */
25853 for (i = 0; i < 32; i++) {
25854 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
25856 fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
25858 msa_translate_init();
25859 cpu_PC = tcg_global_mem_new(cpu_env,
25860 offsetof(CPUMIPSState, active_tc.PC), "PC");
25861 for (i = 0; i < MIPS_DSP_ACC; i++) {
25862 cpu_HI[i] = tcg_global_mem_new(cpu_env,
25863 offsetof(CPUMIPSState, active_tc.HI[i]),
25864 regnames_HI[i]);
25865 cpu_LO[i] = tcg_global_mem_new(cpu_env,
25866 offsetof(CPUMIPSState, active_tc.LO[i]),
25867 regnames_LO[i]);
25869 cpu_dspctrl = tcg_global_mem_new(cpu_env,
25870 offsetof(CPUMIPSState,
25871 active_tc.DSPControl),
25872 "DSPControl");
25873 bcond = tcg_global_mem_new(cpu_env,
25874 offsetof(CPUMIPSState, bcond), "bcond");
25875 btarget = tcg_global_mem_new(cpu_env,
25876 offsetof(CPUMIPSState, btarget), "btarget");
25877 hflags = tcg_global_mem_new_i32(cpu_env,
25878 offsetof(CPUMIPSState, hflags), "hflags");
25880 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
25881 offsetof(CPUMIPSState, active_fpu.fcr0),
25882 "fcr0");
25883 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
25884 offsetof(CPUMIPSState, active_fpu.fcr31),
25885 "fcr31");
25886 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
25887 "lladdr");
25888 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
25889 "llval");
25891 if (TARGET_LONG_BITS == 32) {
25892 mxu_translate_init();
25896 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
25897 target_ulong *data)
25899 env->active_tc.PC = data[0];
25900 env->hflags &= ~MIPS_HFLAG_BMASK;
25901 env->hflags |= data[1];
25902 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
25903 case MIPS_HFLAG_BR:
25904 break;
25905 case MIPS_HFLAG_BC:
25906 case MIPS_HFLAG_BL:
25907 case MIPS_HFLAG_B:
25908 env->btarget = data[2];
25909 break;