]> Git Repo - qemu.git/blame - target/mips/translate.c
target/mips: nanoMIPS: Remove duplicate macro definitions
[qemu.git] / target / mips / translate.c
CommitLineData
6af0bf9c 1/*
ab99e0e4 2 * MIPS emulation for QEMU - main translation routines
5fafdf24 3 *
6af0bf9c 4 * Copyright (c) 2004-2005 Jocelyn Mayer
6ea83fed 5 * Copyright (c) 2006 Marius Groeger (FPU operations)
bb8a53ad 6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
3c824109 7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
4133498f 8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
6af0bf9c
FB
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
8167ee88 21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
6af0bf9c
FB
22 */
23
c684822a 24#include "qemu/osdep.h"
6af0bf9c 25#include "cpu.h"
26aa3d9a 26#include "internal.h"
76cad711 27#include "disas/disas.h"
63c91552 28#include "exec/exec-all.h"
57fec1fe 29#include "tcg-op.h"
f08b6170 30#include "exec/cpu_ldst.h"
d3d93c6c 31#include "hw/mips/cpudevs.h"
6af0bf9c 32
2ef6175a
RH
33#include "exec/helper-proto.h"
34#include "exec/helper-gen.h"
3b3c1694 35#include "exec/semihost.h"
a7812ae4 36
b44a7fb1 37#include "target/mips/trace.h"
a7e30d84 38#include "trace-tcg.h"
b28425ba 39#include "exec/translator.h"
508127e2 40#include "exec/log.h"
a7e30d84 41
fb7729e2 42#define MIPS_DEBUG_DISAS 0
6af0bf9c 43
7a387fff
TS
44/* MIPS major opcodes */
45#define MASK_OP_MAJOR(op) (op & (0x3F << 26))
e37e863f
FB
46
47enum {
48 /* indirect opcode tables */
7a387fff
TS
49 OPC_SPECIAL = (0x00 << 26),
50 OPC_REGIMM = (0x01 << 26),
51 OPC_CP0 = (0x10 << 26),
52 OPC_CP1 = (0x11 << 26),
53 OPC_CP2 = (0x12 << 26),
54 OPC_CP3 = (0x13 << 26),
55 OPC_SPECIAL2 = (0x1C << 26),
56 OPC_SPECIAL3 = (0x1F << 26),
e37e863f 57 /* arithmetic with immediate */
7a387fff
TS
58 OPC_ADDI = (0x08 << 26),
59 OPC_ADDIU = (0x09 << 26),
60 OPC_SLTI = (0x0A << 26),
61 OPC_SLTIU = (0x0B << 26),
324d9e32 62 /* logic with immediate */
7a387fff
TS
63 OPC_ANDI = (0x0C << 26),
64 OPC_ORI = (0x0D << 26),
65 OPC_XORI = (0x0E << 26),
66 OPC_LUI = (0x0F << 26),
324d9e32 67 /* arithmetic with immediate */
7a387fff
TS
68 OPC_DADDI = (0x18 << 26),
69 OPC_DADDIU = (0x19 << 26),
e37e863f 70 /* Jump and branches */
7a387fff
TS
71 OPC_J = (0x02 << 26),
72 OPC_JAL = (0x03 << 26),
73 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
74 OPC_BEQL = (0x14 << 26),
75 OPC_BNE = (0x05 << 26),
76 OPC_BNEL = (0x15 << 26),
77 OPC_BLEZ = (0x06 << 26),
78 OPC_BLEZL = (0x16 << 26),
79 OPC_BGTZ = (0x07 << 26),
80 OPC_BGTZL = (0x17 << 26),
b231c103 81 OPC_JALX = (0x1D << 26),
d4ea6acd 82 OPC_DAUI = (0x1D << 26),
e37e863f 83 /* Load and stores */
7a387fff
TS
84 OPC_LDL = (0x1A << 26),
85 OPC_LDR = (0x1B << 26),
86 OPC_LB = (0x20 << 26),
87 OPC_LH = (0x21 << 26),
88 OPC_LWL = (0x22 << 26),
89 OPC_LW = (0x23 << 26),
364d4831 90 OPC_LWPC = OPC_LW | 0x5,
7a387fff
TS
91 OPC_LBU = (0x24 << 26),
92 OPC_LHU = (0x25 << 26),
93 OPC_LWR = (0x26 << 26),
94 OPC_LWU = (0x27 << 26),
95 OPC_SB = (0x28 << 26),
96 OPC_SH = (0x29 << 26),
97 OPC_SWL = (0x2A << 26),
98 OPC_SW = (0x2B << 26),
99 OPC_SDL = (0x2C << 26),
100 OPC_SDR = (0x2D << 26),
101 OPC_SWR = (0x2E << 26),
102 OPC_LL = (0x30 << 26),
103 OPC_LLD = (0x34 << 26),
104 OPC_LD = (0x37 << 26),
364d4831 105 OPC_LDPC = OPC_LD | 0x5,
7a387fff
TS
106 OPC_SC = (0x38 << 26),
107 OPC_SCD = (0x3C << 26),
108 OPC_SD = (0x3F << 26),
e37e863f 109 /* Floating point load/store */
7a387fff
TS
110 OPC_LWC1 = (0x31 << 26),
111 OPC_LWC2 = (0x32 << 26),
112 OPC_LDC1 = (0x35 << 26),
113 OPC_LDC2 = (0x36 << 26),
114 OPC_SWC1 = (0x39 << 26),
115 OPC_SWC2 = (0x3A << 26),
116 OPC_SDC1 = (0x3D << 26),
117 OPC_SDC2 = (0x3E << 26),
31837be3
YK
118 /* Compact Branches */
119 OPC_BLEZALC = (0x06 << 26),
120 OPC_BGEZALC = (0x06 << 26),
121 OPC_BGEUC = (0x06 << 26),
122 OPC_BGTZALC = (0x07 << 26),
123 OPC_BLTZALC = (0x07 << 26),
124 OPC_BLTUC = (0x07 << 26),
125 OPC_BOVC = (0x08 << 26),
126 OPC_BEQZALC = (0x08 << 26),
127 OPC_BEQC = (0x08 << 26),
128 OPC_BLEZC = (0x16 << 26),
129 OPC_BGEZC = (0x16 << 26),
130 OPC_BGEC = (0x16 << 26),
131 OPC_BGTZC = (0x17 << 26),
132 OPC_BLTZC = (0x17 << 26),
133 OPC_BLTC = (0x17 << 26),
134 OPC_BNVC = (0x18 << 26),
135 OPC_BNEZALC = (0x18 << 26),
136 OPC_BNEC = (0x18 << 26),
137 OPC_BC = (0x32 << 26),
138 OPC_BEQZC = (0x36 << 26),
139 OPC_JIC = (0x36 << 26),
140 OPC_BALC = (0x3A << 26),
141 OPC_BNEZC = (0x3E << 26),
142 OPC_JIALC = (0x3E << 26),
7a387fff
TS
143 /* MDMX ASE specific */
144 OPC_MDMX = (0x1E << 26),
239dfebe
YK
145 /* MSA ASE, same as MDMX */
146 OPC_MSA = OPC_MDMX,
e37e863f 147 /* Cache and prefetch */
7a387fff
TS
148 OPC_CACHE = (0x2F << 26),
149 OPC_PREF = (0x33 << 26),
d4ea6acd
LA
150 /* PC-relative address computation / loads */
151 OPC_PCREL = (0x3B << 26),
152};
153
154/* PC-relative address computation / loads */
155#define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
156#define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
157enum {
158 /* Instructions determined by bits 19 and 20 */
159 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
160 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
161 OPC_LWUPC = OPC_PCREL | (2 << 19),
162
163 /* Instructions determined by bits 16 ... 20 */
164 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
165 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
166
167 /* Other */
168 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
e37e863f
FB
169};
170
171/* MIPS special opcodes */
7a387fff
TS
172#define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
173
e37e863f
FB
174enum {
175 /* Shifts */
7a387fff 176 OPC_SLL = 0x00 | OPC_SPECIAL,
e37e863f
FB
177 /* NOP is SLL r0, r0, 0 */
178 /* SSNOP is SLL r0, r0, 1 */
7a387fff
TS
179 /* EHB is SLL r0, r0, 3 */
180 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
ea63e2c3 181 OPC_ROTR = OPC_SRL | (1 << 21),
7a387fff
TS
182 OPC_SRA = 0x03 | OPC_SPECIAL,
183 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 184 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
ea63e2c3 185 OPC_ROTRV = OPC_SRLV | (1 << 6),
7a387fff
TS
186 OPC_SRAV = 0x07 | OPC_SPECIAL,
187 OPC_DSLLV = 0x14 | OPC_SPECIAL,
188 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
ea63e2c3 189 OPC_DROTRV = OPC_DSRLV | (1 << 6),
7a387fff
TS
190 OPC_DSRAV = 0x17 | OPC_SPECIAL,
191 OPC_DSLL = 0x38 | OPC_SPECIAL,
192 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
ea63e2c3 193 OPC_DROTR = OPC_DSRL | (1 << 21),
7a387fff
TS
194 OPC_DSRA = 0x3B | OPC_SPECIAL,
195 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
196 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
ea63e2c3 197 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
7a387fff 198 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 199 /* Multiplication / division */
7a387fff
TS
200 OPC_MULT = 0x18 | OPC_SPECIAL,
201 OPC_MULTU = 0x19 | OPC_SPECIAL,
202 OPC_DIV = 0x1A | OPC_SPECIAL,
203 OPC_DIVU = 0x1B | OPC_SPECIAL,
204 OPC_DMULT = 0x1C | OPC_SPECIAL,
205 OPC_DMULTU = 0x1D | OPC_SPECIAL,
206 OPC_DDIV = 0x1E | OPC_SPECIAL,
207 OPC_DDIVU = 0x1F | OPC_SPECIAL,
b42ee5e1 208
e37e863f 209 /* 2 registers arithmetic / logic */
7a387fff
TS
210 OPC_ADD = 0x20 | OPC_SPECIAL,
211 OPC_ADDU = 0x21 | OPC_SPECIAL,
212 OPC_SUB = 0x22 | OPC_SPECIAL,
213 OPC_SUBU = 0x23 | OPC_SPECIAL,
214 OPC_AND = 0x24 | OPC_SPECIAL,
215 OPC_OR = 0x25 | OPC_SPECIAL,
216 OPC_XOR = 0x26 | OPC_SPECIAL,
217 OPC_NOR = 0x27 | OPC_SPECIAL,
218 OPC_SLT = 0x2A | OPC_SPECIAL,
219 OPC_SLTU = 0x2B | OPC_SPECIAL,
220 OPC_DADD = 0x2C | OPC_SPECIAL,
221 OPC_DADDU = 0x2D | OPC_SPECIAL,
222 OPC_DSUB = 0x2E | OPC_SPECIAL,
223 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 224 /* Jumps */
7a387fff
TS
225 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
226 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
e37e863f 227 /* Traps */
7a387fff
TS
228 OPC_TGE = 0x30 | OPC_SPECIAL,
229 OPC_TGEU = 0x31 | OPC_SPECIAL,
230 OPC_TLT = 0x32 | OPC_SPECIAL,
231 OPC_TLTU = 0x33 | OPC_SPECIAL,
232 OPC_TEQ = 0x34 | OPC_SPECIAL,
233 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 234 /* HI / LO registers load & stores */
7a387fff
TS
235 OPC_MFHI = 0x10 | OPC_SPECIAL,
236 OPC_MTHI = 0x11 | OPC_SPECIAL,
237 OPC_MFLO = 0x12 | OPC_SPECIAL,
238 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 239 /* Conditional moves */
7a387fff
TS
240 OPC_MOVZ = 0x0A | OPC_SPECIAL,
241 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 242
b691d9d2
LA
243 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
244 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
245
7a387fff 246 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
247
248 /* Special */
a0d700e4 249 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
7a387fff
TS
250 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
251 OPC_BREAK = 0x0D | OPC_SPECIAL,
a0d700e4 252 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
7a387fff
TS
253 OPC_SYNC = 0x0F | OPC_SPECIAL,
254
7a387fff
TS
255 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
256 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
7a387fff
TS
257 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
258 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
259};
260
b42ee5e1
LA
261/* R6 Multiply and Divide instructions have the same Opcode
262 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
263#define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
264
265enum {
266 R6_OPC_MUL = OPC_MULT | (2 << 6),
267 R6_OPC_MUH = OPC_MULT | (3 << 6),
268 R6_OPC_MULU = OPC_MULTU | (2 << 6),
269 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
270 R6_OPC_DIV = OPC_DIV | (2 << 6),
271 R6_OPC_MOD = OPC_DIV | (3 << 6),
272 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
273 R6_OPC_MODU = OPC_DIVU | (3 << 6),
274
275 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
276 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
277 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
278 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
279 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
280 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
281 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
282 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
4267d3e6
LA
283
284 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
285 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
286 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
287 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
288 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
d4ea6acd
LA
289
290 OPC_LSA = 0x05 | OPC_SPECIAL,
291 OPC_DLSA = 0x15 | OPC_SPECIAL,
b42ee5e1
LA
292};
293
e9c71dd1
TS
294/* Multiplication variants of the vr54xx. */
295#define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
296
297enum {
298 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
299 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
300 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
301 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
302 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
303 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
304 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
305 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
306 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
307 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
308 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
309 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
310 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
311 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
312};
313
7a387fff
TS
314/* REGIMM (rt field) opcodes */
315#define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
316
317enum {
318 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
319 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
320 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
321 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
322 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
323 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
324 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
325 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
326 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
327 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
328 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
329 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
330 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
331 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
bb238210 332 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
7a387fff 333 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
d4ea6acd
LA
334
335 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
336 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
e37e863f
FB
337};
338
7a387fff
TS
339/* Special2 opcodes */
340#define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
341
e37e863f 342enum {
7a387fff
TS
343 /* Multiply & xxx operations */
344 OPC_MADD = 0x00 | OPC_SPECIAL2,
345 OPC_MADDU = 0x01 | OPC_SPECIAL2,
346 OPC_MUL = 0x02 | OPC_SPECIAL2,
347 OPC_MSUB = 0x04 | OPC_SPECIAL2,
348 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
161f85e6
AJ
349 /* Loongson 2F */
350 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
351 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
352 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
353 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
354 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
355 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
356 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
357 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
358 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
359 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
360 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
361 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
e37e863f 362 /* Misc */
7a387fff
TS
363 OPC_CLZ = 0x20 | OPC_SPECIAL2,
364 OPC_CLO = 0x21 | OPC_SPECIAL2,
365 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
366 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 367 /* Special */
7a387fff
TS
368 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
369};
370
371/* Special3 opcodes */
372#define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
373
374enum {
375 OPC_EXT = 0x00 | OPC_SPECIAL3,
376 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
377 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
378 OPC_DEXT = 0x03 | OPC_SPECIAL3,
379 OPC_INS = 0x04 | OPC_SPECIAL3,
380 OPC_DINSM = 0x05 | OPC_SPECIAL3,
381 OPC_DINSU = 0x06 | OPC_SPECIAL3,
382 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
383 OPC_FORK = 0x08 | OPC_SPECIAL3,
384 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
385 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
386 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
387 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
161f85e6
AJ
388
389 /* Loongson 2E */
390 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
391 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
392 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
393 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
394 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
395 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
396 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
397 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
398 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
399 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
400 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
401 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
9b1a1d68
JL
402
403 /* MIPS DSP Load */
404 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
461c08df
JL
405 /* MIPS DSP Arithmetic */
406 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
461c08df 407 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
461c08df 408 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
461c08df 409 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
461c08df
JL
410 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
411 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
461c08df 413 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
77c5fa8b
JL
414 /* MIPS DSP GPR-Based Shift Sub-class */
415 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
77c5fa8b 416 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
77c5fa8b
JL
417 /* MIPS DSP Multiply Sub-class insns */
418 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
419 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
420 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
77c5fa8b 421 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
1cb6686c
JL
422 /* DSP Bit/Manipulation Sub-class */
423 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
1cb6686c 424 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
df6126a7 425 /* MIPS DSP Append Sub-class */
26690560 426 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
26690560 427 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
b53371ed
JL
428 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
429 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
b53371ed 430 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
4368b29a 431
76964147
JH
432 /* EVA */
433 OPC_LWLE = 0x19 | OPC_SPECIAL3,
434 OPC_LWRE = 0x1A | OPC_SPECIAL3,
435 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
436 OPC_SBE = 0x1C | OPC_SPECIAL3,
437 OPC_SHE = 0x1D | OPC_SPECIAL3,
438 OPC_SCE = 0x1E | OPC_SPECIAL3,
439 OPC_SWE = 0x1F | OPC_SPECIAL3,
440 OPC_SWLE = 0x21 | OPC_SPECIAL3,
441 OPC_SWRE = 0x22 | OPC_SPECIAL3,
442 OPC_PREFE = 0x23 | OPC_SPECIAL3,
443 OPC_LBUE = 0x28 | OPC_SPECIAL3,
444 OPC_LHUE = 0x29 | OPC_SPECIAL3,
445 OPC_LBE = 0x2C | OPC_SPECIAL3,
446 OPC_LHE = 0x2D | OPC_SPECIAL3,
447 OPC_LLE = 0x2E | OPC_SPECIAL3,
448 OPC_LWE = 0x2F | OPC_SPECIAL3,
449
4368b29a 450 /* R6 */
bf7910c6
LA
451 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
452 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
4368b29a
LA
453 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
454 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
bf7910c6
LA
455 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
456 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
e37e863f
FB
457};
458
7a387fff
TS
459/* BSHFL opcodes */
460#define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
461
e37e863f 462enum {
15eacb9b
YK
463 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
464 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
465 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
373ecd38
AM
466 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
467 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
468 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
469 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
15eacb9b 470 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
e37e863f
FB
471};
472
7a387fff
TS
473/* DBSHFL opcodes */
474#define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
475
e37e863f 476enum {
15eacb9b
YK
477 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
478 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
373ecd38
AM
479 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
480 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
481 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
482 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
483 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
484 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
485 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
486 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
15eacb9b 487 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
e37e863f
FB
488};
489
e45a93e2
JL
490/* MIPS DSP REGIMM opcodes */
491enum {
492 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
e45a93e2 493 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
e45a93e2
JL
494};
495
9b1a1d68
JL
496#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
497/* MIPS DSP Load */
498enum {
499 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
500 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
501 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
9b1a1d68 502 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
9b1a1d68
JL
503};
504
461c08df
JL
505#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
506enum {
507 /* MIPS DSP Arithmetic Sub-class */
508 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
509 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
510 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
511 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
512 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
515 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
516 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
517 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
518 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
522 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
523 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
524 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
525 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
a22260ae
JL
526 /* MIPS DSP Multiply Sub-class insns */
527 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
528 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
529 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
530 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
531 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
461c08df
JL
533};
534
535#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
536#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
537enum {
538 /* MIPS DSP Arithmetic Sub-class */
539 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
541 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
543 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
546 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
a22260ae
JL
551 /* MIPS DSP Multiply Sub-class insns */
552 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
553 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
554 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
555 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
461c08df
JL
556};
557
558#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
559enum {
560 /* MIPS DSP Arithmetic Sub-class */
561 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
1cb6686c
JL
574 /* DSP Bit/Manipulation Sub-class */
575 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
576 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
577 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
578 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
579 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
461c08df
JL
580};
581
582#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
583enum {
584 /* MIPS DSP Arithmetic Sub-class */
585 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
26690560
JL
592 /* DSP Compare-Pick Sub-class */
593 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
461c08df 608};
a22260ae 609
77c5fa8b
JL
610#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
611enum {
612 /* MIPS DSP GPR-Based Shift Sub-class */
613 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
635};
461c08df 636
a22260ae
JL
637#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
638enum {
639 /* MIPS DSP Multiply Sub-class insns */
640 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
654 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
657 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
658 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
659 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
660 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
662};
663
1cb6686c
JL
664#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
665enum {
666 /* DSP Bit/Manipulation Sub-class */
667 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
668};
669
26690560
JL
670#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671enum {
df6126a7 672 /* MIPS DSP Append Sub-class */
26690560
JL
673 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
674 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
675 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
676};
677
b53371ed
JL
678#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
679enum {
680 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
681 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
685 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
693 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
694 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
695 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
696 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
697 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
698};
699
461c08df
JL
700#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
701enum {
702 /* MIPS DSP Arithmetic Sub-class */
703 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
1cb6686c
JL
720 /* DSP Bit/Manipulation Sub-class */
721 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
722 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
723 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
724 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
725 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
461c08df 727};
461c08df 728
461c08df
JL
729#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
730enum {
a22260ae
JL
731 /* MIPS DSP Multiply Sub-class insns */
732 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
733 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
734 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
735 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
736 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
461c08df
JL
737 /* MIPS DSP Arithmetic Sub-class */
738 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
741 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
742 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
751 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
752 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
759};
461c08df 760
461c08df
JL
761#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
762enum {
26690560
JL
763 /* DSP Compare-Pick Sub-class */
764 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
461c08df
JL
783 /* MIPS DSP Arithmetic Sub-class */
784 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
786 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
787 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
788 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
792};
461c08df 793
26690560
JL
794#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
795enum {
df6126a7 796 /* DSP Append Sub-class */
26690560
JL
797 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
798 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
799 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
800 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
801};
26690560 802
b53371ed
JL
803#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
804enum {
805 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
806 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
807 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
826 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
827};
828
1cb6686c
JL
829#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
830enum {
831 /* DSP Bit/Manipulation Sub-class */
832 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
833};
1cb6686c 834
a22260ae
JL
835#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
836enum {
837 /* MIPS DSP Multiply Sub-class insns */
838 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
864};
a22260ae 865
77c5fa8b
JL
866#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
867enum {
868 /* MIPS DSP GPR-Based Shift Sub-class */
869 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
895};
77c5fa8b 896
7a387fff
TS
897/* Coprocessor 0 (rs field) */
898#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
899
6ea83fed 900enum {
7a387fff
TS
901 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
902 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
5204ea79 903 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
7a387fff
TS
904 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
905 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
5204ea79 906 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
ead9360e 907 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
908 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
909 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 910 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
911 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
912 OPC_C0 = (0x10 << 21) | OPC_CP0,
c38a1d52
AR
913 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
914 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
915 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
916 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
917 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
918 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
919 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
920 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
921 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
922 OPC_C0_A = (0x1A << 21) | OPC_CP0,
923 OPC_C0_B = (0x1B << 21) | OPC_CP0,
924 OPC_C0_C = (0x1C << 21) | OPC_CP0,
925 OPC_C0_D = (0x1D << 21) | OPC_CP0,
926 OPC_C0_E = (0x1E << 21) | OPC_CP0,
927 OPC_C0_F = (0x1F << 21) | OPC_CP0,
6ea83fed 928};
7a387fff
TS
929
930/* MFMC0 opcodes */
b48cfdff 931#define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
7a387fff
TS
932
933enum {
ead9360e
TS
934 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
935 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
936 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
937 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
938 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
939 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
01bc435b
YK
940 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
941 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
7a387fff
TS
942};
943
944/* Coprocessor 0 (with rs == C0) */
945#define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
946
947enum {
948 OPC_TLBR = 0x01 | OPC_C0,
949 OPC_TLBWI = 0x02 | OPC_C0,
9456c2fb
LA
950 OPC_TLBINV = 0x03 | OPC_C0,
951 OPC_TLBINVF = 0x04 | OPC_C0,
7a387fff
TS
952 OPC_TLBWR = 0x06 | OPC_C0,
953 OPC_TLBP = 0x08 | OPC_C0,
954 OPC_RFE = 0x10 | OPC_C0,
955 OPC_ERET = 0x18 | OPC_C0,
956 OPC_DERET = 0x1F | OPC_C0,
957 OPC_WAIT = 0x20 | OPC_C0,
958};
959
960/* Coprocessor 1 (rs field) */
961#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
962
bf4120ad
NF
963/* Values for the fmt field in FP instructions */
964enum {
965 /* 0 - 15 are reserved */
e459440a
AJ
966 FMT_S = 16, /* single fp */
967 FMT_D = 17, /* double fp */
968 FMT_E = 18, /* extended fp */
969 FMT_Q = 19, /* quad fp */
970 FMT_W = 20, /* 32-bit fixed */
971 FMT_L = 21, /* 64-bit fixed */
972 FMT_PS = 22, /* paired single fp */
bf4120ad
NF
973 /* 23 - 31 are reserved */
974};
975
7a387fff
TS
976enum {
977 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
978 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
979 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
5a5012ec 980 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
7a387fff
TS
981 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
982 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
983 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
5a5012ec 984 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
7a387fff 985 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
5a5012ec
TS
986 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
987 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
239dfebe
YK
988 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
989 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
e459440a
AJ
990 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
991 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
992 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
993 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
994 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
995 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
996 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
31837be3
YK
997 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
998 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
239dfebe
YK
999 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1000 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1001 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1002 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1003 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1004 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1005 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1006 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
7a387fff
TS
1007};
1008
5a5012ec
TS
1009#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1010#define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1011
7a387fff
TS
1012enum {
1013 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1014 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1015 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1016 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1017};
1018
5a5012ec
TS
1019enum {
1020 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1021 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1022};
1023
1024enum {
1025 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1026 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1027};
7a387fff
TS
1028
1029#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
e0c84da7
TS
1030
1031enum {
1032 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1033 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1034 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1035 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1036 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1037 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1038 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1039 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1040 OPC_BC2 = (0x08 << 21) | OPC_CP2,
31837be3
YK
1041 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1042 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
e0c84da7
TS
1043};
1044
bd277fa1
RH
1045#define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1046
1047enum {
1048 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1049 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1050 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1051 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1052 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1056
1057 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1058 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1059 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1060 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1061 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1065
1066 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1067 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1068 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1069 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1070 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1071 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1072 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1073 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1074
1075 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1076 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1077 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1078 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1079 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1080 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1081 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1082 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1083
1084 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1085 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1086 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1087 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1088 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1089 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1090
1091 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1092 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1093 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1094 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1095 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1097
1098 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1099 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1100 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1101 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1102 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1104
1105 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1106 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1107 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1108 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1109 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1111
1112 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1113 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1114 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1115 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1116 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1117 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1118
1119 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1120 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1121 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1122 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1123 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1124 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1125
1126 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1127 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1128 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1129 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1130 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1131 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1132
1133 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1134 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1135 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1136 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1137 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1138 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1139};
1140
1141
e0c84da7
TS
1142#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1143
1144enum {
1145 OPC_LWXC1 = 0x00 | OPC_CP3,
1146 OPC_LDXC1 = 0x01 | OPC_CP3,
1147 OPC_LUXC1 = 0x05 | OPC_CP3,
1148 OPC_SWXC1 = 0x08 | OPC_CP3,
1149 OPC_SDXC1 = 0x09 | OPC_CP3,
1150 OPC_SUXC1 = 0x0D | OPC_CP3,
1151 OPC_PREFX = 0x0F | OPC_CP3,
1152 OPC_ALNV_PS = 0x1E | OPC_CP3,
1153 OPC_MADD_S = 0x20 | OPC_CP3,
1154 OPC_MADD_D = 0x21 | OPC_CP3,
1155 OPC_MADD_PS = 0x26 | OPC_CP3,
1156 OPC_MSUB_S = 0x28 | OPC_CP3,
1157 OPC_MSUB_D = 0x29 | OPC_CP3,
1158 OPC_MSUB_PS = 0x2E | OPC_CP3,
1159 OPC_NMADD_S = 0x30 | OPC_CP3,
fbcc6828 1160 OPC_NMADD_D = 0x31 | OPC_CP3,
e0c84da7
TS
1161 OPC_NMADD_PS= 0x36 | OPC_CP3,
1162 OPC_NMSUB_S = 0x38 | OPC_CP3,
1163 OPC_NMSUB_D = 0x39 | OPC_CP3,
1164 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1165};
1166
239dfebe
YK
1167/* MSA Opcodes */
1168#define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1169enum {
1170 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1171 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1172 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1173 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1174 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1175 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1176 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1177 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1178 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1179 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1180 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1181 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1182 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1183 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1184 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1185 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1186 OPC_MSA_ELM = 0x19 | OPC_MSA,
1187 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1188 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1189 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1190 OPC_MSA_VEC = 0x1E | OPC_MSA,
1191
1192 /* MI10 instruction */
1193 OPC_LD_B = (0x20) | OPC_MSA,
1194 OPC_LD_H = (0x21) | OPC_MSA,
1195 OPC_LD_W = (0x22) | OPC_MSA,
1196 OPC_LD_D = (0x23) | OPC_MSA,
1197 OPC_ST_B = (0x24) | OPC_MSA,
1198 OPC_ST_H = (0x25) | OPC_MSA,
1199 OPC_ST_W = (0x26) | OPC_MSA,
1200 OPC_ST_D = (0x27) | OPC_MSA,
1201};
1202
1203enum {
1204 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1205 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1206 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1207 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1208 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1209 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1210 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1211 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1212 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1213 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1214 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1215 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1216 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1217
1218 /* I8 instruction */
1219 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1220 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1221 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1222 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1223 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1224 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1225 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1226 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1227 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1228 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1229
1230 /* VEC/2R/2RF instruction */
1231 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1232 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1233 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1234 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1235 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1236 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1237 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1238
1239 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1240 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1241
1242 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1243 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1244 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1245 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1246 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1247
1248 /* 2RF instruction df(bit 16) = _w, _d */
1249 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1250 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1251 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1252 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1253 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1254 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1255 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1256 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1257 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1258 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1259 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1260 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1261 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1262 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1263 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1264 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1265
1266 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1267 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1268 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1269 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1270 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1271 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1272 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1273 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1274 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1275 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1276 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1277 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1278 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1279 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1280 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1281 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1282 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1283 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1284 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1285 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1286 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1287 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1288 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1289 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1290 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1291 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1292 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1293 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1294 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1295 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1296 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1297 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1298 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1299 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1300 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1301 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1302 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1303 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1304 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1305 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1306 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1307 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1308 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1309 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1310 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1311 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1312 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1313 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1314 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1315 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1316 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1317 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1318 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1319 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1320 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1321 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1322 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1323 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1324 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1325 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1326 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1327 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1328 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1329 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1330
1331 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1332 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1333 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1334 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1335 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1336 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1337 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1338 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1339 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1340 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1341
1342 /* 3RF instruction _df(bit 21) = _w, _d */
1343 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1344 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1345 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1346 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1347 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1348 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1349 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1350 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1351 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1352 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1353 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1356 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1357 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1358 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1359 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1361 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1362 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1363 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1364 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1365 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1366 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1367 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1368 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1369 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1370 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1372 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1373 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1374 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1375 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1376 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1377 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1378 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1379 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1380 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1381 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1382 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1383 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1384
1385 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1386 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1387 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1388 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1389 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1390 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1391 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1392 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1393 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1394 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1395 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1396 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1397 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1398};
1399
b158d449
AM
1400
1401/*
b158d449 1402 *
84e2c895
AM
1403 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1404 * ============================================
1405 *
1406 *
1407 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
b158d449
AM
1408 * instructions set. It is designed to fit the needs of signal, graphical and
1409 * video processing applications. MXU instruction set is used in Xburst family
1410 * of microprocessors by Ingenic.
1411 *
1412 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1413 * the control register.
1414 *
093ade12 1415 *
84e2c895
AM
1416 * The notation used in MXU assembler mnemonics
1417 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1418 *
1419 * Register operands:
1d0e663c
AM
1420 *
1421 * XRa, XRb, XRc, XRd - MXU registers
1422 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
093ade12 1423 *
84e2c895 1424 * Non-register operands:
093ade12 1425 *
84e2c895
AM
1426 * aptn1 - 1-bit accumulate add/subtract pattern
1427 * aptn2 - 2-bit accumulate add/subtract pattern
1428 * eptn2 - 2-bit execute add/subtract pattern
1429 * optn2 - 2-bit operand pattern
1430 * optn3 - 3-bit operand pattern
1431 * sft4 - 4-bit shift amount
1432 * strd2 - 2-bit stride amount
093ade12
AM
1433 *
1434 * Prefixes:
1435 *
84e2c895
AM
1436 * Level of parallelism: Operand size:
1437 * S - single operation at a time 32 - word
1438 * D - two operations in parallel 16 - half word
1439 * Q - four operations in parallel 8 - byte
093ade12
AM
1440 *
1441 * Operations:
1442 *
1443 * ADD - Add or subtract
1444 * ADDC - Add with carry-in
1445 * ACC - Accumulate
1446 * ASUM - Sum together then accumulate (add or subtract)
1447 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1448 * AVG - Average between 2 operands
1449 * ABD - Absolute difference
1450 * ALN - Align data
1451 * AND - Logical bitwise 'and' operation
1452 * CPS - Copy sign
1453 * EXTR - Extract bits
1454 * I2M - Move from GPR register to MXU register
1455 * LDD - Load data from memory to XRF
1456 * LDI - Load data from memory to XRF (and increase the address base)
1457 * LUI - Load unsigned immediate
1458 * MUL - Multiply
1459 * MULU - Unsigned multiply
1460 * MADD - 64-bit operand add 32x32 product
1461 * MSUB - 64-bit operand subtract 32x32 product
1462 * MAC - Multiply and accumulate (add or subtract)
1463 * MAD - Multiply and add or subtract
1464 * MAX - Maximum between 2 operands
1465 * MIN - Minimum between 2 operands
1466 * M2I - Move from MXU register to GPR register
1467 * MOVZ - Move if zero
1468 * MOVN - Move if non-zero
1469 * NOR - Logical bitwise 'nor' operation
1470 * OR - Logical bitwise 'or' operation
1471 * STD - Store data from XRF to memory
1472 * SDI - Store data from XRF to memory (and increase the address base)
1473 * SLT - Set of less than comparison
1474 * SAD - Sum of absolute differences
1475 * SLL - Logical shift left
1476 * SLR - Logical shift right
1477 * SAR - Arithmetic shift right
1478 * SAT - Saturation
1479 * SFL - Shuffle
1480 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1481 * XOR - Logical bitwise 'exclusive or' operation
1d0e663c 1482 *
84e2c895
AM
1483 * Suffixes:
1484 *
1485 * E - Expand results
1486 * F - Fixed point multiplication
1487 * L - Low part result
1488 * R - Doing rounding
1489 * V - Variable instead of immediate
1490 * W - Combine above L and V
1491 *
1492 *
1493 * The list of MXU instructions grouped by functionality
1494 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1495 *
1d0e663c
AM
1496 * Load/Store instructions Multiplication instructions
1497 * ----------------------- ---------------------------
1498 *
1499 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1500 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
093ade12
AM
1501 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1502 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1d0e663c
AM
1503 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1504 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1505 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1506 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1507 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1508 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1509 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1510 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1511 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1512 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1513 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1514 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1515 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1516 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1517 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1518 * S16SDI XRa, Rb, s10, eptn2
1519 * S8LDD XRa, Rb, s8, eptn3
1520 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1521 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1522 * S8SDI XRa, Rb, s8, eptn3
1523 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1524 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1525 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1526 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1527 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1528 * S32CPS XRa, XRb, XRc
1529 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1530 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1531 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1532 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1533 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1534 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1535 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1536 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1537 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1538 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1539 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1540 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1541 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1542 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1543 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1544 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1545 * Q8SLT XRa, XRb, XRc
1546 * Q8SLTU XRa, XRb, XRc
1547 * Q8MOVZ XRa, XRb, XRc Shift instructions
1548 * Q8MOVN XRa, XRb, XRc ------------------
1549 *
1550 * D32SLL XRa, XRb, XRc, XRd, sft4
1551 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1552 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1553 * D32SARL XRa, XRb, XRc, sft4
1554 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1555 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1556 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1557 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1558 * Q16SLL XRa, XRb, XRc, XRd, sft4
1559 * Q16SLR XRa, XRb, XRc, XRd, sft4
eab0bdb0 1560 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1d0e663c
AM
1561 * ------------------------- Q16SLLV XRa, XRb, Rb
1562 * Q16SLRV XRa, XRb, Rb
1563 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1564 * S32ALN XRa, XRb, XRc, Rb
1565 * S32ALNI XRa, XRb, XRc, s3
1566 * S32LUI XRa, s8, optn3 Move instructions
1567 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1568 * S32EXTRV XRa, XRb, Rs, Rt
1569 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1570 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1571 *
9ef5bff9 1572 *
84e2c895
AM
1573 * The opcode organization of MXU instructions
1574 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1575 *
1576 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1577 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1578 * other bits up to the instruction level is as follows:
1579 *
9ef5bff9
AM
1580 * bits
1581 * 05..00
1582 *
1583 * ┌─ 000000 ─ OPC_MXU_S32MADD
1584 * ├─ 000001 ─ OPC_MXU_S32MADDU
eab0bdb0
AM
1585 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1586 * │
9ef5bff9
AM
1587 * │ 20..18
1588 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1589 * │ ├─ 001 ─ OPC_MXU_S32MIN
1590 * │ ├─ 010 ─ OPC_MXU_D16MAX
1591 * │ ├─ 011 ─ OPC_MXU_D16MIN
1592 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1593 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1594 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1595 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1596 * ├─ 000100 ─ OPC_MXU_S32MSUB
1597 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1598 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1599 * │ ├─ 001 ─ OPC_MXU_D16SLT
1600 * │ ├─ 010 ─ OPC_MXU_D16AVG
1601 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1602 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1603 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1604 * │ └─ 111 ─ OPC_MXU_Q8ADD
1605 * │
1606 * │ 20..18
1607 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1608 * │ ├─ 010 ─ OPC_MXU_D16CPS
1609 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1610 * │ └─ 110 ─ OPC_MXU_Q16SAT
1611 * ├─ 001000 ─ OPC_MXU_D16MUL
1612 * │ 25..24
1613 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1614 * │ └─ 01 ─ OPC_MXU_D16MULE
1615 * ├─ 001010 ─ OPC_MXU_D16MAC
1616 * ├─ 001011 ─ OPC_MXU_D16MACF
1617 * ├─ 001100 ─ OPC_MXU_D16MADL
eab0bdb0 1618 * ├─ 001101 ─ OPC_MXU_S16MAD
9ef5bff9 1619 * ├─ 001110 ─ OPC_MXU_Q16ADD
eab0bdb0
AM
1620 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1621 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1622 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
9ef5bff9
AM
1623 * │
1624 * │ 23
eab0bdb0 1625 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
9ef5bff9
AM
1626 * │ └─ 1 ─ OPC_MXU_S32STDR
1627 * │
1628 * │ 13..10
eab0bdb0 1629 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
9ef5bff9
AM
1630 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1631 * │
1632 * │ 13..10
eab0bdb0 1633 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
9ef5bff9
AM
1634 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1635 * │
1636 * │ 23
eab0bdb0 1637 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
9ef5bff9
AM
1638 * │ └─ 1 ─ OPC_MXU_S32LDIR
1639 * │
1640 * │ 23
eab0bdb0 1641 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
9ef5bff9
AM
1642 * │ └─ 1 ─ OPC_MXU_S32SDIR
1643 * │
1644 * │ 13..10
eab0bdb0 1645 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
9ef5bff9
AM
1646 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1647 * │
1648 * │ 13..10
eab0bdb0 1649 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
9ef5bff9
AM
1650 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1651 * ├─ 011000 ─ OPC_MXU_D32ADD
1652 * │ 23..22
eab0bdb0 1653 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
9ef5bff9
AM
1654 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1655 * │ └─ 10 ─ OPC_MXU_D32ASUM
1656 * ├─ 011010 ─ <not assigned>
1657 * │ 23..22
eab0bdb0 1658 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
9ef5bff9
AM
1659 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1660 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1661 * │
1662 * │ 23..22
eab0bdb0 1663 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
9ef5bff9
AM
1664 * │ ├─ 01 ─ OPC_MXU_D8SUM
1665 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1666 * ├─ 011110 ─ <not assigned>
1667 * ├─ 011111 ─ <not assigned>
eab0bdb0
AM
1668 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1669 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
9ef5bff9 1670 * ├─ 100010 ─ OPC_MXU_S8LDD
eab0bdb0
AM
1671 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1672 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1673 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
9ef5bff9 1674 * │ ├─ 00 ─ OPC_MXU_S32EXTR
eab0bdb0 1675 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
9ef5bff9
AM
1676 * │
1677 * │ 20..18
eab0bdb0 1678 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
9ef5bff9 1679 * │ ├─ 001 ─ OPC_MXU_S32ALN
c233bf07 1680 * │ ├─ 010 ─ OPC_MXU_S32ALNI
b621f018
AM
1681 * │ ├─ 011 ─ OPC_MXU_S32LUI
1682 * │ ├─ 100 ─ OPC_MXU_S32NOR
1683 * │ ├─ 101 ─ OPC_MXU_S32AND
1684 * │ ├─ 110 ─ OPC_MXU_S32OR
1685 * │ └─ 111 ─ OPC_MXU_S32XOR
c233bf07
AM
1686 * │
1687 * │ 7..5
1688 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1689 * │ ├─ 001 ─ OPC_MXU_LXH
1690 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1691 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1692 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1693 * ├─ 101100 ─ OPC_MXU_S16LDI
1694 * ├─ 101101 ─ OPC_MXU_S16SDI
9ef5bff9
AM
1695 * ├─ 101110 ─ OPC_MXU_S32M2I
1696 * ├─ 101111 ─ OPC_MXU_S32I2M
1697 * ├─ 110000 ─ OPC_MXU_D32SLL
eab0bdb0
AM
1698 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1699 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1700 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1701 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1702 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
9ef5bff9 1703 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
c233bf07 1704 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
eab0bdb0 1705 * │
9ef5bff9
AM
1706 * ├─ 110111 ─ OPC_MXU_Q16SAR
1707 * │ 23..22
c233bf07 1708 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
9ef5bff9
AM
1709 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1710 * │
1711 * │ 20..18
c233bf07 1712 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
9ef5bff9
AM
1713 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1714 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1715 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1716 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
84e2c895 1717 * │ └─ 101 ─ OPC_MXU_S32MOVN
9ef5bff9
AM
1718 * │
1719 * │ 23..22
c233bf07 1720 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
9ef5bff9
AM
1721 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1722 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1723 * ├─ 111100 ─ OPC_MXU_Q8MADL
1724 * ├─ 111101 ─ OPC_MXU_S32SFL
1725 * ├─ 111110 ─ OPC_MXU_Q8SAD
eab0bdb0 1726 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
9ef5bff9
AM
1727 *
1728 *
84e2c895 1729 * Compiled after:
b158d449
AM
1730 *
1731 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
84e2c895 1732 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
b158d449
AM
1733 */
1734
8bacd1ff
AM
1735enum {
1736 OPC_MXU_S32MADD = 0x00,
1737 OPC_MXU_S32MADDU = 0x01,
11d56f61 1738 OPC__MXU_MUL = 0x02,
8bacd1ff
AM
1739 OPC_MXU__POOL00 = 0x03,
1740 OPC_MXU_S32MSUB = 0x04,
1741 OPC_MXU_S32MSUBU = 0x05,
1742 OPC_MXU__POOL01 = 0x06,
1743 OPC_MXU__POOL02 = 0x07,
1744 OPC_MXU_D16MUL = 0x08,
1745 OPC_MXU__POOL03 = 0x09,
1746 OPC_MXU_D16MAC = 0x0A,
1747 OPC_MXU_D16MACF = 0x0B,
1748 OPC_MXU_D16MADL = 0x0C,
eab0bdb0 1749 OPC_MXU_S16MAD = 0x0D,
8bacd1ff
AM
1750 OPC_MXU_Q16ADD = 0x0E,
1751 OPC_MXU_D16MACE = 0x0F,
eab0bdb0
AM
1752 OPC_MXU__POOL04 = 0x10,
1753 OPC_MXU__POOL05 = 0x11,
1754 OPC_MXU__POOL06 = 0x12,
1755 OPC_MXU__POOL07 = 0x13,
1756 OPC_MXU__POOL08 = 0x14,
1757 OPC_MXU__POOL09 = 0x15,
1758 OPC_MXU__POOL10 = 0x16,
1759 OPC_MXU__POOL11 = 0x17,
8bacd1ff 1760 OPC_MXU_D32ADD = 0x18,
eab0bdb0 1761 OPC_MXU__POOL12 = 0x19,
8bacd1ff 1762 /* not assigned 0x1A */
eab0bdb0
AM
1763 OPC_MXU__POOL13 = 0x1B,
1764 OPC_MXU__POOL14 = 0x1C,
8bacd1ff
AM
1765 OPC_MXU_Q8ACCE = 0x1D,
1766 /* not assigned 0x1E */
1767 /* not assigned 0x1F */
1768 /* not assigned 0x20 */
1769 /* not assigned 0x21 */
1770 OPC_MXU_S8LDD = 0x22,
1771 OPC_MXU_S8STD = 0x23,
1772 OPC_MXU_S8LDI = 0x24,
1773 OPC_MXU_S8SDI = 0x25,
eab0bdb0
AM
1774 OPC_MXU__POOL15 = 0x26,
1775 OPC_MXU__POOL16 = 0x27,
c233bf07 1776 OPC_MXU__POOL17 = 0x28,
8bacd1ff
AM
1777 /* not assigned 0x29 */
1778 OPC_MXU_S16LDD = 0x2A,
1779 OPC_MXU_S16STD = 0x2B,
1780 OPC_MXU_S16LDI = 0x2C,
1781 OPC_MXU_S16SDI = 0x2D,
1782 OPC_MXU_S32M2I = 0x2E,
1783 OPC_MXU_S32I2M = 0x2F,
1784 OPC_MXU_D32SLL = 0x30,
1785 OPC_MXU_D32SLR = 0x31,
1786 OPC_MXU_D32SARL = 0x32,
1787 OPC_MXU_D32SAR = 0x33,
1788 OPC_MXU_Q16SLL = 0x34,
1789 OPC_MXU_Q16SLR = 0x35,
c233bf07 1790 OPC_MXU__POOL18 = 0x36,
8bacd1ff 1791 OPC_MXU_Q16SAR = 0x37,
c233bf07
AM
1792 OPC_MXU__POOL19 = 0x38,
1793 OPC_MXU__POOL20 = 0x39,
1794 OPC_MXU__POOL21 = 0x3A,
8bacd1ff
AM
1795 OPC_MXU_Q16SCOP = 0x3B,
1796 OPC_MXU_Q8MADL = 0x3C,
1797 OPC_MXU_S32SFL = 0x3D,
1798 OPC_MXU_Q8SAD = 0x3E,
1799 /* not assigned 0x3F */
1800};
1801
1802
1803/*
1804 * MXU pool 00
1805 */
1806enum {
1807 OPC_MXU_S32MAX = 0x00,
1808 OPC_MXU_S32MIN = 0x01,
1809 OPC_MXU_D16MAX = 0x02,
1810 OPC_MXU_D16MIN = 0x03,
1811 OPC_MXU_Q8MAX = 0x04,
1812 OPC_MXU_Q8MIN = 0x05,
1813 OPC_MXU_Q8SLT = 0x06,
1814 OPC_MXU_Q8SLTU = 0x07,
1815};
1816
1817/*
1818 * MXU pool 01
1819 */
1820enum {
1821 OPC_MXU_S32SLT = 0x00,
1822 OPC_MXU_D16SLT = 0x01,
1823 OPC_MXU_D16AVG = 0x02,
1824 OPC_MXU_D16AVGR = 0x03,
1825 OPC_MXU_Q8AVG = 0x04,
1826 OPC_MXU_Q8AVGR = 0x05,
1827 OPC_MXU_Q8ADD = 0x07,
1828};
1829
1830/*
1831 * MXU pool 02
1832 */
1833enum {
1834 OPC_MXU_S32CPS = 0x00,
1835 OPC_MXU_D16CPS = 0x02,
1836 OPC_MXU_Q8ABD = 0x04,
1837 OPC_MXU_Q16SAT = 0x06,
1838};
1839
1840/*
1841 * MXU pool 03
1842 */
1843enum {
1844 OPC_MXU_D16MULF = 0x00,
1845 OPC_MXU_D16MULE = 0x01,
1846};
1847
1848/*
1849 * MXU pool 04
1850 */
8bacd1ff
AM
1851enum {
1852 OPC_MXU_S32LDD = 0x00,
1853 OPC_MXU_S32LDDR = 0x01,
1854};
1855
1856/*
eab0bdb0 1857 * MXU pool 05
8bacd1ff
AM
1858 */
1859enum {
1860 OPC_MXU_S32STD = 0x00,
1861 OPC_MXU_S32STDR = 0x01,
1862};
1863
1864/*
eab0bdb0 1865 * MXU pool 06
8bacd1ff
AM
1866 */
1867enum {
1868 OPC_MXU_S32LDDV = 0x00,
1869 OPC_MXU_S32LDDVR = 0x01,
1870};
1871
1872/*
eab0bdb0 1873 * MXU pool 07
8bacd1ff
AM
1874 */
1875enum {
1876 OPC_MXU_S32STDV = 0x00,
1877 OPC_MXU_S32STDVR = 0x01,
1878};
1879
1880/*
eab0bdb0 1881 * MXU pool 08
8bacd1ff
AM
1882 */
1883enum {
1884 OPC_MXU_S32LDI = 0x00,
1885 OPC_MXU_S32LDIR = 0x01,
1886};
1887
1888/*
eab0bdb0 1889 * MXU pool 09
8bacd1ff
AM
1890 */
1891enum {
1892 OPC_MXU_S32SDI = 0x00,
1893 OPC_MXU_S32SDIR = 0x01,
1894};
1895
1896/*
eab0bdb0 1897 * MXU pool 10
8bacd1ff
AM
1898 */
1899enum {
1900 OPC_MXU_S32LDIV = 0x00,
1901 OPC_MXU_S32LDIVR = 0x01,
1902};
1903
1904/*
eab0bdb0 1905 * MXU pool 11
8bacd1ff
AM
1906 */
1907enum {
1908 OPC_MXU_S32SDIV = 0x00,
1909 OPC_MXU_S32SDIVR = 0x01,
1910};
1911
1912/*
eab0bdb0 1913 * MXU pool 12
8bacd1ff
AM
1914 */
1915enum {
1916 OPC_MXU_D32ACC = 0x00,
1917 OPC_MXU_D32ACCM = 0x01,
1918 OPC_MXU_D32ASUM = 0x02,
1919};
1920
1921/*
eab0bdb0 1922 * MXU pool 13
8bacd1ff
AM
1923 */
1924enum {
1925 OPC_MXU_Q16ACC = 0x00,
1926 OPC_MXU_Q16ACCM = 0x01,
1927 OPC_MXU_Q16ASUM = 0x02,
1928};
1929
1930/*
eab0bdb0 1931 * MXU pool 14
8bacd1ff
AM
1932 */
1933enum {
1934 OPC_MXU_Q8ADDE = 0x00,
1935 OPC_MXU_D8SUM = 0x01,
1936 OPC_MXU_D8SUMC = 0x02,
1937};
1938
1939/*
eab0bdb0 1940 * MXU pool 15
8bacd1ff
AM
1941 */
1942enum {
1943 OPC_MXU_S32MUL = 0x00,
1944 OPC_MXU_S32MULU = 0x01,
1945 OPC_MXU_S32EXTR = 0x02,
1946 OPC_MXU_S32EXTRV = 0x03,
1947};
1948
1949/*
eab0bdb0 1950 * MXU pool 16
8bacd1ff
AM
1951 */
1952enum {
1953 OPC_MXU_D32SARW = 0x00,
1954 OPC_MXU_S32ALN = 0x01,
1955 OPC_MXU_S32ALNI = 0x02,
b621f018
AM
1956 OPC_MXU_S32LUI = 0x03,
1957 OPC_MXU_S32NOR = 0x04,
1958 OPC_MXU_S32AND = 0x05,
1959 OPC_MXU_S32OR = 0x06,
1960 OPC_MXU_S32XOR = 0x07,
8bacd1ff
AM
1961};
1962
1963/*
eab0bdb0 1964 * MXU pool 17
8bacd1ff 1965 */
c233bf07
AM
1966enum {
1967 OPC_MXU_LXB = 0x00,
1968 OPC_MXU_LXH = 0x01,
1969 OPC_MXU_LXW = 0x03,
1970 OPC_MXU_LXBU = 0x04,
1971 OPC_MXU_LXHU = 0x05,
1972};
1973
1974/*
1975 * MXU pool 18
1976 */
8bacd1ff
AM
1977enum {
1978 OPC_MXU_D32SLLV = 0x00,
1979 OPC_MXU_D32SLRV = 0x01,
1980 OPC_MXU_D32SARV = 0x03,
1981 OPC_MXU_Q16SLLV = 0x04,
1982 OPC_MXU_Q16SLRV = 0x05,
1983 OPC_MXU_Q16SARV = 0x07,
1984};
1985
1986/*
c233bf07 1987 * MXU pool 19
8bacd1ff
AM
1988 */
1989enum {
1990 OPC_MXU_Q8MUL = 0x00,
1991 OPC_MXU_Q8MULSU = 0x01,
1992};
1993
1994/*
c233bf07 1995 * MXU pool 20
8bacd1ff
AM
1996 */
1997enum {
1998 OPC_MXU_Q8MOVZ = 0x00,
1999 OPC_MXU_Q8MOVN = 0x01,
2000 OPC_MXU_D16MOVZ = 0x02,
2001 OPC_MXU_D16MOVN = 0x03,
2002 OPC_MXU_S32MOVZ = 0x04,
2003 OPC_MXU_S32MOVN = 0x05,
2004};
2005
2006/*
c233bf07 2007 * MXU pool 21
8bacd1ff
AM
2008 */
2009enum {
2010 OPC_MXU_Q8MAC = 0x00,
2011 OPC_MXU_Q8MACSU = 0x01,
2012};
2013
497f072b
FN
2014/*
2015 * Overview of the TX79-specific instruction set
2016 * =============================================
2017 *
2018 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2019 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2020 * instructions and certain multimedia instructions (MMIs). These MMIs
2021 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2022 * or sixteen 8-bit paths.
2023 *
2024 * Reference:
2025 *
2026 * The Toshiba TX System RISC TX79 Core Architecture manual,
2027 * https://wiki.qemu.org/File:C790.pdf
2028 *
2029 * Three-Operand Multiply and Multiply-Add (4 instructions)
2030 * --------------------------------------------------------
2031 * MADD [rd,] rs, rt Multiply/Add
2032 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2033 * MULT [rd,] rs, rt Multiply (3-operand)
2034 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2035 *
2036 * Multiply Instructions for Pipeline 1 (10 instructions)
2037 * ------------------------------------------------------
2038 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2039 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2040 * DIV1 rs, rt Divide Pipeline 1
2041 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2042 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2043 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2044 * MFHI1 rd Move From HI1 Register
2045 * MFLO1 rd Move From LO1 Register
2046 * MTHI1 rs Move To HI1 Register
2047 * MTLO1 rs Move To LO1 Register
2048 *
2049 * Arithmetic (19 instructions)
2050 * ----------------------------
2051 * PADDB rd, rs, rt Parallel Add Byte
2052 * PSUBB rd, rs, rt Parallel Subtract Byte
2053 * PADDH rd, rs, rt Parallel Add Halfword
2054 * PSUBH rd, rs, rt Parallel Subtract Halfword
2055 * PADDW rd, rs, rt Parallel Add Word
2056 * PSUBW rd, rs, rt Parallel Subtract Word
2057 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2058 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2059 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2060 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2061 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2062 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2063 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2064 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2065 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2066 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2067 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2068 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2069 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2070 *
2071 * Min/Max (4 instructions)
2072 * ------------------------
2073 * PMAXH rd, rs, rt Parallel Maximum Halfword
2074 * PMINH rd, rs, rt Parallel Minimum Halfword
2075 * PMAXW rd, rs, rt Parallel Maximum Word
2076 * PMINW rd, rs, rt Parallel Minimum Word
2077 *
2078 * Absolute (2 instructions)
2079 * -------------------------
2080 * PABSH rd, rt Parallel Absolute Halfword
2081 * PABSW rd, rt Parallel Absolute Word
2082 *
2083 * Logical (4 instructions)
2084 * ------------------------
2085 * PAND rd, rs, rt Parallel AND
2086 * POR rd, rs, rt Parallel OR
2087 * PXOR rd, rs, rt Parallel XOR
2088 * PNOR rd, rs, rt Parallel NOR
2089 *
2090 * Shift (9 instructions)
2091 * ----------------------
2092 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2093 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2094 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2095 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2096 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2097 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2098 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2099 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2100 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2101 *
2102 * Compare (6 instructions)
2103 * ------------------------
2104 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2105 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2106 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2107 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2108 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2109 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2110 *
2111 * LZC (1 instruction)
2112 * -------------------
2113 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2114 *
2115 * Quadword Load and Store (2 instructions)
2116 * ----------------------------------------
2117 * LQ rt, offset(base) Load Quadword
2118 * SQ rt, offset(base) Store Quadword
2119 *
2120 * Multiply and Divide (19 instructions)
2121 * -------------------------------------
2122 * PMULTW rd, rs, rt Parallel Multiply Word
2123 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2124 * PDIVW rs, rt Parallel Divide Word
2125 * PDIVUW rs, rt Parallel Divide Unsigned Word
2126 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2127 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2128 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2129 * PMULTH rd, rs, rt Parallel Multiply Halfword
2130 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2131 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2132 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2133 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2134 * PDIVBW rs, rt Parallel Divide Broadcast Word
2135 * PMFHI rd Parallel Move From HI Register
2136 * PMFLO rd Parallel Move From LO Register
2137 * PMTHI rs Parallel Move To HI Register
2138 * PMTLO rs Parallel Move To LO Register
2139 * PMFHL rd Parallel Move From HI/LO Register
2140 * PMTHL rs Parallel Move To HI/LO Register
2141 *
2142 * Pack/Extend (11 instructions)
2143 * -----------------------------
2144 * PPAC5 rd, rt Parallel Pack to 5 bits
2145 * PPACB rd, rs, rt Parallel Pack to Byte
2146 * PPACH rd, rs, rt Parallel Pack to Halfword
2147 * PPACW rd, rs, rt Parallel Pack to Word
2148 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2149 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2150 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2151 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2152 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2153 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2154 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2155 *
2156 * Others (16 instructions)
2157 * ------------------------
2158 * PCPYH rd, rt Parallel Copy Halfword
2159 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2160 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2161 * PREVH rd, rt Parallel Reverse Halfword
2162 * PINTH rd, rs, rt Parallel Interleave Halfword
2163 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2164 * PEXEH rd, rt Parallel Exchange Even Halfword
2165 * PEXCH rd, rt Parallel Exchange Center Halfword
2166 * PEXEW rd, rt Parallel Exchange Even Word
2167 * PEXCW rd, rt Parallel Exchange Center Word
2168 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2169 * MFSA rd Move from Shift Amount Register
2170 * MTSA rs Move to Shift Amount Register
2171 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2172 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2173 * PROT3W rd, rt Parallel Rotate 3 Words
f99c0d6d 2174 *
baa609db
AM
2175 * MMI (MultiMedia Instruction) encodings
2176 * ======================================
f99c0d6d 2177 *
baa609db 2178 * MMI instructions encoding table keys:
f99c0d6d
FN
2179 *
2180 * * This code is reserved for future use. An attempt to execute it
2181 * causes a Reserved Instruction exception.
2182 * % This code indicates an instruction class. The instruction word
2183 * must be further decoded by examining additional tables that show
2184 * the values for other instruction fields.
2185 * # This code is reserved for the unsupported instructions DMULT,
2186 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2187 * to execute it causes a Reserved Instruction exception.
2188 *
baa609db 2189 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
f99c0d6d
FN
2190 *
2191 * 31 26 0
2192 * +--------+----------------------------------------+
2193 * | opcode | |
2194 * +--------+----------------------------------------+
2195 *
2196 * opcode bits 28..26
2197 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2198 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2199 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2200 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2201 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2202 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2203 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2204 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2205 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2206 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2207 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
497f072b 2208 */
b158d449 2209
f99c0d6d 2210enum {
baa609db
AM
2211 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2212 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2213 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
f99c0d6d
FN
2214};
2215
d3297211 2216/*
baa609db 2217 * MMI instructions with opcode field = MMI:
d3297211
FN
2218 *
2219 * 31 26 5 0
2220 * +--------+-------------------------------+--------+
2221 * | MMI | |function|
2222 * +--------+-------------------------------+--------+
2223 *
2224 * function bits 2..0
2225 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2226 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2227 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2228 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2229 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2230 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2231 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2232 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2233 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2234 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2235 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2236 */
2237
c8341e00 2238#define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
d3297211 2239enum {
baa609db
AM
2240 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2241 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2242 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2243 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2244 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2245 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2246 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2247 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2248 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2249 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2250 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2251 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2252 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2253 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2254 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2255 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2256 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2257 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2258 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2259 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2260 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2261 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2262 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2263 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2264 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
d3297211
FN
2265};
2266
3ef65697 2267/*
baa609db 2268 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
3ef65697
FN
2269 *
2270 * 31 26 10 6 5 0
2271 * +--------+----------------------+--------+--------+
2272 * | MMI | |function| MMI0 |
2273 * +--------+----------------------+--------+--------+
2274 *
2275 * function bits 7..6
2276 * bits | 0 | 1 | 2 | 3
2277 * 10..8 | 00 | 01 | 10 | 11
2278 * -------+-------+-------+-------+-------
2279 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2280 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2281 * 2 010 | PADDB | PSUBB | PCGTB | *
2282 * 3 011 | * | * | * | *
2283 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2284 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2285 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2286 * 7 111 | * | * | PEXT5 | PPAC5
2287 */
2288
c8341e00 2289#define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
3ef65697 2290enum {
baa609db
AM
2291 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2292 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2293 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2294 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2295 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2296 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2297 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2298 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2299 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2300 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2301 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2302 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2303 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2304 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2305 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2306 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2307 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2308 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2309 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2310 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2311 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2312 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2313 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2314 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2315 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
3ef65697
FN
2316};
2317
77596541 2318/*
baa609db 2319 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
77596541
FN
2320 *
2321 * 31 26 10 6 5 0
2322 * +--------+----------------------+--------+--------+
2323 * | MMI | |function| MMI1 |
2324 * +--------+----------------------+--------+--------+
2325 *
2326 * function bits 7..6
2327 * bits | 0 | 1 | 2 | 3
2328 * 10..8 | 00 | 01 | 10 | 11
2329 * -------+-------+-------+-------+-------
2330 * 0 000 | * | PABSW | PCEQW | PMINW
2331 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2332 * 2 010 | * | * | PCEQB | *
2333 * 3 011 | * | * | * | *
2334 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2335 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2336 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2337 * 7 111 | * | * | * | *
2338 */
2339
c8341e00 2340#define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
77596541 2341enum {
baa609db
AM
2342 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2343 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2344 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2345 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2346 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2347 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2348 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2349 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2350 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2351 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2352 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2353 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2354 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2355 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2356 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2357 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2358 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2359 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
77596541
FN
2360};
2361
6c03ef6a 2362/*
baa609db 2363 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
6c03ef6a
FN
2364 *
2365 * 31 26 10 6 5 0
2366 * +--------+----------------------+--------+--------+
2367 * | MMI | |function| MMI2 |
2368 * +--------+----------------------+--------+--------+
2369 *
2370 * function bits 7..6
2371 * bits | 0 | 1 | 2 | 3
2372 * 10..8 | 00 | 01 | 10 | 11
2373 * -------+-------+-------+-------+-------
2374 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2375 * 1 001 | PMSUBW| * | * | *
2376 * 2 010 | PMFHI | PMFLO | PINTH | *
2377 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2378 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2379 * 5 101 | PMSUBH| PHMSBH| * | *
2380 * 6 110 | * | * | PEXEH | PREVH
2381 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2382 */
2383
c8341e00 2384#define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
6c03ef6a 2385enum {
baa609db
AM
2386 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2387 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2388 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2389 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2390 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2391 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2392 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2393 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2394 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2395 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2396 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2397 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2398 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2399 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2400 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2401 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2402 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2403 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2404 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2405 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2406 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2407 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
6c03ef6a
FN
2408};
2409
dd581bf9 2410/*
baa609db 2411 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
dd581bf9
FN
2412 *
2413 * 31 26 10 6 5 0
2414 * +--------+----------------------+--------+--------+
2415 * | MMI | |function| MMI3 |
2416 * +--------+----------------------+--------+--------+
2417 *
2418 * function bits 7..6
2419 * bits | 0 | 1 | 2 | 3
2420 * 10..8 | 00 | 01 | 10 | 11
2421 * -------+-------+-------+-------+-------
2422 * 0 000 |PMADDUW| * | * | PSRAVW
2423 * 1 001 | * | * | * | *
2424 * 2 010 | PMTHI | PMTLO | PINTEH| *
2425 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2426 * 4 100 | * | * | POR | PNOR
2427 * 5 101 | * | * | * | *
2428 * 6 110 | * | * | PEXCH | PCPYH
2429 * 7 111 | * | * | PEXCW | *
2430 */
2431
c8341e00 2432#define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
dd581bf9 2433enum {
baa609db
AM
2434 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2435 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2436 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2437 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2438 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2439 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2440 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2441 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2442 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2443 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2444 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2445 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2446 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
dd581bf9
FN
2447};
2448
39454628 2449/* global register indices */
a7812ae4 2450static TCGv cpu_gpr[32], cpu_PC;
340fff72 2451static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
41db4607
AJ
2452static TCGv cpu_dspctrl, btarget, bcond;
2453static TCGv_i32 hflags;
a7812ae4 2454static TCGv_i32 fpu_fcr0, fpu_fcr31;
d73ee8a2 2455static TCGv_i64 fpu_f64[32];
863f264d 2456static TCGv_i64 msa_wr_d[64];
aa0bf00b 2457
a168a796
FN
2458#if defined(TARGET_MIPS64)
2459/* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2460static TCGv_i64 cpu_mmr[32];
2461#endif
2462
b621f018 2463#if !defined(TARGET_MIPS64)
eb5559f6
CJ
2464/* MXU registers */
2465static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2466static TCGv mxu_CR;
b621f018 2467#endif
eb5559f6 2468
022c62cb 2469#include "exec/gen-icount.h"
2e70f6ef 2470
895c2d04 2471#define gen_helper_0e0i(name, arg) do { \
a7812ae4 2472 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
895c2d04 2473 gen_helper_##name(cpu_env, helper_tmp); \
a7812ae4
PB
2474 tcg_temp_free_i32(helper_tmp); \
2475 } while(0)
be24bb4f 2476
895c2d04 2477#define gen_helper_0e1i(name, arg1, arg2) do { \
a7812ae4 2478 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
895c2d04 2479 gen_helper_##name(cpu_env, arg1, helper_tmp); \
a7812ae4
PB
2480 tcg_temp_free_i32(helper_tmp); \
2481 } while(0)
be24bb4f 2482
895c2d04
BS
2483#define gen_helper_1e0i(name, ret, arg1) do { \
2484 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2485 gen_helper_##name(ret, cpu_env, helper_tmp); \
2486 tcg_temp_free_i32(helper_tmp); \
2487 } while(0)
2488
2489#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2490 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2491 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2492 tcg_temp_free_i32(helper_tmp); \
2493 } while(0)
2494
2495#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2496 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2497 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2498 tcg_temp_free_i32(helper_tmp); \
2499 } while(0)
2500
2501#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
a7812ae4 2502 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
895c2d04 2503 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
a7812ae4
PB
2504 tcg_temp_free_i32(helper_tmp); \
2505 } while(0)
be24bb4f 2506
895c2d04 2507#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
a7812ae4 2508 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
895c2d04 2509 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
a7812ae4
PB
2510 tcg_temp_free_i32(helper_tmp); \
2511 } while(0)
c239529e 2512
8e9ade68 2513typedef struct DisasContext {
eeb3bba8
EC
2514 DisasContextBase base;
2515 target_ulong saved_pc;
18f440ed 2516 target_ulong page_start;
8e9ade68 2517 uint32_t opcode;
f9c9cd63 2518 uint64_t insn_flags;
5ab5c041 2519 int32_t CP0_Config1;
49735f76 2520 int32_t CP0_Config2;
ab77fc61
DN
2521 int32_t CP0_Config3;
2522 int32_t CP0_Config5;
8e9ade68
TS
2523 /* Routine used to access memory */
2524 int mem_idx;
be3a8c53 2525 TCGMemOp default_tcg_memop_mask;
8e9ade68 2526 uint32_t hflags, saved_hflags;
8e9ade68 2527 target_ulong btarget;
d279279e 2528 bool ulri;
e98c0d17 2529 int kscrexist;
7207c7f9 2530 bool rxi;
9456c2fb 2531 int ie;
aea14095
LA
2532 bool bi;
2533 bool bp;
5204ea79
LA
2534 uint64_t PAMask;
2535 bool mvh;
76964147 2536 bool eva;
cec56a73 2537 bool sc;
5204ea79 2538 int CP0_LLAddr_shift;
e29c9628 2539 bool ps;
01bc435b 2540 bool vp;
c870e3f5 2541 bool cmgcr;
f6d4dd81 2542 bool mrp;
87552089 2543 bool nan2008;
6be77480 2544 bool abs2008;
5fb2dcd1 2545 bool saar;
8e9ade68
TS
2546} DisasContext;
2547
b28425ba
EC
2548#define DISAS_STOP DISAS_TARGET_0
2549#define DISAS_EXIT DISAS_TARGET_1
8e9ade68 2550
d73ee8a2
RH
2551static const char * const regnames[] = {
2552 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2553 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2554 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2555 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2556};
6af0bf9c 2557
d73ee8a2
RH
2558static const char * const regnames_HI[] = {
2559 "HI0", "HI1", "HI2", "HI3",
2560};
4b2eb8d2 2561
d73ee8a2
RH
2562static const char * const regnames_LO[] = {
2563 "LO0", "LO1", "LO2", "LO3",
2564};
4b2eb8d2 2565
d73ee8a2
RH
2566static const char * const fregnames[] = {
2567 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2568 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2569 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2570 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2571};
958fb4a9 2572
863f264d
YK
2573static const char * const msaregnames[] = {
2574 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2575 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2576 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2577 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2578 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2579 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2580 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2581 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2582 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2583 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2584 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2585 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2586 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2587 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2588 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2589 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2590};
2591
b621f018 2592#if !defined(TARGET_MIPS64)
eb5559f6
CJ
2593static const char * const mxuregnames[] = {
2594 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2595 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2596};
b621f018 2597#endif
eb5559f6 2598
9d68ac14 2599#define LOG_DISAS(...) \
fb7729e2
RH
2600 do { \
2601 if (MIPS_DEBUG_DISAS) { \
9d68ac14 2602 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
fb7729e2
RH
2603 } \
2604 } while (0)
2605
9d68ac14 2606#define MIPS_INVAL(op) \
fb7729e2
RH
2607 do { \
2608 if (MIPS_DEBUG_DISAS) { \
9d68ac14
AJ
2609 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2610 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
eeb3bba8
EC
2611 ctx->base.pc_next, ctx->opcode, op, \
2612 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2613 ((ctx->opcode >> 16) & 0x1F)); \
fb7729e2
RH
2614 } \
2615 } while (0)
958fb4a9 2616
8e9ade68
TS
2617/* General purpose registers moves. */
2618static inline void gen_load_gpr (TCGv t, int reg)
aaa9128a 2619{
8e9ade68
TS
2620 if (reg == 0)
2621 tcg_gen_movi_tl(t, 0);
2622 else
4b2eb8d2 2623 tcg_gen_mov_tl(t, cpu_gpr[reg]);
aaa9128a
TS
2624}
2625
8e9ade68 2626static inline void gen_store_gpr (TCGv t, int reg)
aaa9128a 2627{
8e9ade68 2628 if (reg != 0)
4b2eb8d2 2629 tcg_gen_mov_tl(cpu_gpr[reg], t);
aaa9128a
TS
2630}
2631
8e9ade68 2632/* Moves to/from shadow registers. */
be24bb4f 2633static inline void gen_load_srsgpr (int from, int to)
aaa9128a 2634{
d9bea114 2635 TCGv t0 = tcg_temp_new();
be24bb4f
TS
2636
2637 if (from == 0)
d9bea114 2638 tcg_gen_movi_tl(t0, 0);
8e9ade68 2639 else {
d9bea114 2640 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 2641 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 2642
7db13fae 2643 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
2644 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2645 tcg_gen_andi_i32(t2, t2, 0xf);
2646 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2647 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 2648 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 2649
d9bea114 2650 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 2651 tcg_temp_free_ptr(addr);
d9bea114 2652 tcg_temp_free_i32(t2);
8e9ade68 2653 }
d9bea114
AJ
2654 gen_store_gpr(t0, to);
2655 tcg_temp_free(t0);
aaa9128a
TS
2656}
2657
be24bb4f 2658static inline void gen_store_srsgpr (int from, int to)
aaa9128a 2659{
be24bb4f 2660 if (to != 0) {
d9bea114
AJ
2661 TCGv t0 = tcg_temp_new();
2662 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 2663 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 2664
d9bea114 2665 gen_load_gpr(t0, from);
7db13fae 2666 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
2667 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2668 tcg_gen_andi_i32(t2, t2, 0xf);
2669 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2670 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 2671 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 2672
d9bea114 2673 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 2674 tcg_temp_free_ptr(addr);
d9bea114
AJ
2675 tcg_temp_free_i32(t2);
2676 tcg_temp_free(t0);
8e9ade68 2677 }
aaa9128a
TS
2678}
2679
b621f018 2680#if !defined(TARGET_MIPS64)
96992d1a
CJ
2681/* MXU General purpose registers moves. */
2682static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2683{
2684 if (reg == 0) {
2685 tcg_gen_movi_tl(t, 0);
2686 } else if (reg <= 15) {
2687 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2688 }
2689}
2690
2691static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2692{
2693 if (reg > 0 && reg <= 15) {
2694 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2695 }
2696}
2697
2698/* MXU control register moves. */
2699static inline void gen_load_mxu_cr(TCGv t)
2700{
2701 tcg_gen_mov_tl(t, mxu_CR);
2702}
2703
2704static inline void gen_store_mxu_cr(TCGv t)
2705{
2706 /* TODO: Add handling of RW rules for MXU_CR. */
2707 tcg_gen_mov_tl(mxu_CR, t);
2708}
b621f018 2709#endif
96992d1a
CJ
2710
2711
eab9944c
LA
2712/* Tests */
2713static inline void gen_save_pc(target_ulong pc)
2714{
2715 tcg_gen_movi_tl(cpu_PC, pc);
2716}
2717
2718static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2719{
2720 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
eeb3bba8
EC
2721 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2722 gen_save_pc(ctx->base.pc_next);
2723 ctx->saved_pc = ctx->base.pc_next;
eab9944c
LA
2724 }
2725 if (ctx->hflags != ctx->saved_hflags) {
2726 tcg_gen_movi_i32(hflags, ctx->hflags);
2727 ctx->saved_hflags = ctx->hflags;
2728 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2729 case MIPS_HFLAG_BR:
2730 break;
2731 case MIPS_HFLAG_BC:
2732 case MIPS_HFLAG_BL:
2733 case MIPS_HFLAG_B:
2734 tcg_gen_movi_tl(btarget, ctx->btarget);
2735 break;
2736 }
2737 }
2738}
2739
2740static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2741{
2742 ctx->saved_hflags = ctx->hflags;
2743 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2744 case MIPS_HFLAG_BR:
2745 break;
2746 case MIPS_HFLAG_BC:
2747 case MIPS_HFLAG_BL:
2748 case MIPS_HFLAG_B:
2749 ctx->btarget = env->btarget;
2750 break;
2751 }
2752}
2753
2754static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2755{
2756 TCGv_i32 texcp = tcg_const_i32(excp);
2757 TCGv_i32 terr = tcg_const_i32(err);
2758 save_cpu_state(ctx, 1);
2759 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2760 tcg_temp_free_i32(terr);
2761 tcg_temp_free_i32(texcp);
eeb3bba8 2762 ctx->base.is_jmp = DISAS_NORETURN;
eab9944c
LA
2763}
2764
2765static inline void generate_exception(DisasContext *ctx, int excp)
2766{
eab9944c
LA
2767 gen_helper_0e0i(raise_exception, excp);
2768}
2769
9c708c7f
PD
2770static inline void generate_exception_end(DisasContext *ctx, int excp)
2771{
2772 generate_exception_err(ctx, excp, 0);
2773}
2774
aaa9128a 2775/* Floating point register moves. */
7c979afd 2776static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 2777{
7c979afd
LA
2778 if (ctx->hflags & MIPS_HFLAG_FRE) {
2779 generate_exception(ctx, EXCP_RI);
2780 }
ecc7b3aa 2781 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
2782}
2783
7c979afd 2784static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 2785{
7c979afd
LA
2786 TCGv_i64 t64;
2787 if (ctx->hflags & MIPS_HFLAG_FRE) {
2788 generate_exception(ctx, EXCP_RI);
2789 }
2790 t64 = tcg_temp_new_i64();
d73ee8a2
RH
2791 tcg_gen_extu_i32_i64(t64, t);
2792 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2793 tcg_temp_free_i64(t64);
6d066274
AJ
2794}
2795
7f6613ce 2796static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 2797{
7f6613ce 2798 if (ctx->hflags & MIPS_HFLAG_F64) {
71f303cd 2799 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
7f6613ce 2800 } else {
7c979afd 2801 gen_load_fpr32(ctx, t, reg | 1);
7f6613ce 2802 }
6d066274
AJ
2803}
2804
7f6613ce 2805static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 2806{
7f6613ce
PJ
2807 if (ctx->hflags & MIPS_HFLAG_F64) {
2808 TCGv_i64 t64 = tcg_temp_new_i64();
2809 tcg_gen_extu_i32_i64(t64, t);
2810 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2811 tcg_temp_free_i64(t64);
2812 } else {
7c979afd 2813 gen_store_fpr32(ctx, t, reg | 1);
7f6613ce 2814 }
aa0bf00b 2815}
6ea83fed 2816
d73ee8a2 2817static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 2818{
f364515c 2819 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 2820 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 2821 } else {
d73ee8a2 2822 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
2823 }
2824}
6ea83fed 2825
d73ee8a2 2826static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 2827{
f364515c 2828 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 2829 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 2830 } else {
d73ee8a2
RH
2831 TCGv_i64 t0;
2832 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2833 t0 = tcg_temp_new_i64();
6d066274 2834 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 2835 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
6d066274 2836 tcg_temp_free_i64(t0);
aa0bf00b
TS
2837 }
2838}
6ea83fed 2839
d94536f4 2840static inline int get_fp_bit (int cc)
a16336e4 2841{
d94536f4
AJ
2842 if (cc)
2843 return 24 + cc;
2844 else
2845 return 23;
a16336e4
TS
2846}
2847
48d38ca5 2848/* Addresses computation */
941694d0 2849static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
4ad40f36 2850{
941694d0 2851 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
2852
2853#if defined(TARGET_MIPS64)
01f72885 2854 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
941694d0 2855 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
2856 }
2857#endif
4ad40f36
FB
2858}
2859
bf0718c5
SM
2860static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2861 target_long ofs)
2862{
2863 tcg_gen_addi_tl(ret, base, ofs);
2864
2865#if defined(TARGET_MIPS64)
2866 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2867 tcg_gen_ext32s_i64(ret, ret);
2868 }
2869#endif
2870}
2871
31837be3
YK
2872/* Addresses computation (translation time) */
2873static target_long addr_add(DisasContext *ctx, target_long base,
2874 target_long offset)
2875{
2876 target_long sum = base + offset;
2877
2878#if defined(TARGET_MIPS64)
2879 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2880 sum = (int32_t)sum;
2881 }
2882#endif
2883 return sum;
2884}
2885
71f303cd 2886/* Sign-extract the low 32-bits to a target_long. */
1f1b4c00
YK
2887static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2888{
2889#if defined(TARGET_MIPS64)
71f303cd
RH
2890 tcg_gen_ext32s_i64(ret, arg);
2891#else
2892 tcg_gen_extrl_i64_i32(ret, arg);
2893#endif
2894}
2895
2896/* Sign-extract the high 32-bits to a target_long. */
2897static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2898{
2899#if defined(TARGET_MIPS64)
2900 tcg_gen_sari_i64(ret, arg, 32);
1f1b4c00 2901#else
71f303cd 2902 tcg_gen_extrh_i64_i32(ret, arg);
1f1b4c00
YK
2903#endif
2904}
2905
356265ae 2906static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 2907{
fe253235 2908 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
c2c65dab 2909 generate_exception_err(ctx, EXCP_CpU, 0);
387a8fe5
TS
2910}
2911
356265ae 2912static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 2913{
fe253235 2914 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
5e755519
TS
2915 generate_exception_err(ctx, EXCP_CpU, 1);
2916}
2917
b8aa4598
TS
2918/* Verify that the processor is running with COP1X instructions enabled.
2919 This is associated with the nabla symbol in the MIPS32 and MIPS64
2920 opcode tables. */
2921
356265ae 2922static inline void check_cop1x(DisasContext *ctx)
b8aa4598
TS
2923{
2924 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
9c708c7f 2925 generate_exception_end(ctx, EXCP_RI);
b8aa4598
TS
2926}
2927
2928/* Verify that the processor is running with 64-bit floating-point
2929 operations enabled. */
2930
356265ae 2931static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 2932{
b8aa4598 2933 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
9c708c7f 2934 generate_exception_end(ctx, EXCP_RI);
5e755519
TS
2935}
2936
2937/*
2938 * Verify if floating point register is valid; an operation is not defined
2939 * if bit 0 of any register specification is set and the FR bit in the
2940 * Status register equals zero, since the register numbers specify an
2941 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2942 * in the Status register equals one, both even and odd register numbers
2943 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2944 *
2945 * Multiple 64 bit wide registers can be checked by calling
2946 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2947 */
356265ae 2948static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 2949{
fe253235 2950 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
9c708c7f 2951 generate_exception_end(ctx, EXCP_RI);
5e755519
TS
2952}
2953
853c3240
JL
2954/* Verify that the processor is running with DSP instructions enabled.
2955 This is enabled by CP0 Status register MX(24) bit.
2956 */
2957
2958static inline void check_dsp(DisasContext *ctx)
2959{
2960 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
ad153f15 2961 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 2962 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 2963 } else {
9c708c7f 2964 generate_exception_end(ctx, EXCP_RI);
ad153f15 2965 }
853c3240
JL
2966 }
2967}
2968
908f6be1 2969static inline void check_dsp_r2(DisasContext *ctx)
853c3240 2970{
908f6be1 2971 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
ad153f15 2972 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 2973 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 2974 } else {
9c708c7f 2975 generate_exception_end(ctx, EXCP_RI);
ad153f15 2976 }
853c3240
JL
2977 }
2978}
2979
908f6be1 2980static inline void check_dsp_r3(DisasContext *ctx)
59e781fb 2981{
908f6be1 2982 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
59e781fb
SM
2983 if (ctx->insn_flags & ASE_DSP) {
2984 generate_exception_end(ctx, EXCP_DSPDIS);
2985 } else {
2986 generate_exception_end(ctx, EXCP_RI);
2987 }
2988 }
2989}
2990
3a95e3a7 2991/* This code generates a "reserved instruction" exception if the
e189e748 2992 CPU does not support the instruction set corresponding to flags. */
f9c9cd63 2993static inline void check_insn(DisasContext *ctx, uint64_t flags)
3a95e3a7 2994{
d75c135e 2995 if (unlikely(!(ctx->insn_flags & flags))) {
9c708c7f 2996 generate_exception_end(ctx, EXCP_RI);
d75c135e 2997 }
3a95e3a7
TS
2998}
2999
fecd2646
LA
3000/* This code generates a "reserved instruction" exception if the
3001 CPU has corresponding flag set which indicates that the instruction
3002 has been removed. */
f9c9cd63 3003static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
fecd2646
LA
3004{
3005 if (unlikely(ctx->insn_flags & flags)) {
9c708c7f 3006 generate_exception_end(ctx, EXCP_RI);
fecd2646
LA
3007 }
3008}
3009
96631327
FN
3010/*
3011 * The Linux kernel traps certain reserved instruction exceptions to
3012 * emulate the corresponding instructions. QEMU is the kernel in user
3013 * mode, so those traps are emulated by accepting the instructions.
3014 *
3015 * A reserved instruction exception is generated for flagged CPUs if
3016 * QEMU runs in system mode.
3017 */
3018static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3019{
3020#ifndef CONFIG_USER_ONLY
3021 check_insn_opc_removed(ctx, flags);
3022#endif
3023}
3024
e29c9628
YK
3025/* This code generates a "reserved instruction" exception if the
3026 CPU does not support 64-bit paired-single (PS) floating point data type */
3027static inline void check_ps(DisasContext *ctx)
3028{
3029 if (unlikely(!ctx->ps)) {
3030 generate_exception(ctx, EXCP_RI);
3031 }
3032 check_cp1_64bitmode(ctx);
3033}
3034
c7986fd6 3035#ifdef TARGET_MIPS64
e189e748
TS
3036/* This code generates a "reserved instruction" exception if 64-bit
3037 instructions are not enabled. */
356265ae 3038static inline void check_mips_64(DisasContext *ctx)
e189e748 3039{
fe253235 3040 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
9c708c7f 3041 generate_exception_end(ctx, EXCP_RI);
e189e748 3042}
c7986fd6 3043#endif
e189e748 3044
5204ea79
LA
3045#ifndef CONFIG_USER_ONLY
3046static inline void check_mvh(DisasContext *ctx)
3047{
3048 if (unlikely(!ctx->mvh)) {
3049 generate_exception(ctx, EXCP_RI);
3050 }
3051}
3052#endif
3053
0b16dcd1
AR
3054/*
3055 * This code generates a "reserved instruction" exception if the
3056 * Config5 XNP bit is set.
3057 */
3058static inline void check_xnp(DisasContext *ctx)
3059{
3060 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3061 generate_exception_end(ctx, EXCP_RI);
3062 }
3063}
3064
5e31fdd5
YK
3065#ifndef CONFIG_USER_ONLY
3066/*
3067 * This code generates a "reserved instruction" exception if the
3068 * Config3 PW bit is NOT set.
3069 */
3070static inline void check_pw(DisasContext *ctx)
3071{
3072 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3073 generate_exception_end(ctx, EXCP_RI);
3074 }
3075}
3076#endif
3077
9affc1c5
AR
3078/*
3079 * This code generates a "reserved instruction" exception if the
3080 * Config3 MT bit is NOT set.
3081 */
3082static inline void check_mt(DisasContext *ctx)
3083{
3084 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3085 generate_exception_end(ctx, EXCP_RI);
3086 }
3087}
3088
3089#ifndef CONFIG_USER_ONLY
3090/*
3091 * This code generates a "coprocessor unusable" exception if CP0 is not
3092 * available, and, if that is not the case, generates a "reserved instruction"
3093 * exception if the Config5 MT bit is NOT set. This is needed for availability
3094 * control of some of MT ASE instructions.
3095 */
3096static inline void check_cp0_mt(DisasContext *ctx)
3097{
3098 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3099 generate_exception_err(ctx, EXCP_CpU, 0);
3100 } else {
3101 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3102 generate_exception_err(ctx, EXCP_RI, 0);
3103 }
3104 }
3105}
3106#endif
3107
fb32f8c8
DN
3108/*
3109 * This code generates a "reserved instruction" exception if the
3110 * Config5 NMS bit is set.
3111 */
3112static inline void check_nms(DisasContext *ctx)
3113{
3114 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3115 generate_exception_end(ctx, EXCP_RI);
3116 }
3117}
3118
d046a9ea
DN
3119/*
3120 * This code generates a "reserved instruction" exception if the
3121 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3122 * Config2 TL, and Config5 L2C are unset.
3123 */
3124static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3125{
3126 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3127 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3128 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3129 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3130 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3131 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))
3132 {
3133 generate_exception_end(ctx, EXCP_RI);
3134 }
3135}
3136
3137/*
3138 * This code generates a "reserved instruction" exception if the
3139 * Config5 EVA bit is NOT set.
3140 */
3141static inline void check_eva(DisasContext *ctx)
3142{
3143 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3144 generate_exception_end(ctx, EXCP_RI);
3145 }
3146}
3147
0b16dcd1 3148
8153667c
NF
3149/* Define small wrappers for gen_load_fpr* so that we have a uniform
3150 calling interface for 32 and 64-bit FPRs. No sense in changing
3151 all callers for gen_load_fpr32 when we need the CTX parameter for
3152 this one use. */
7c979afd 3153#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
8153667c
NF
3154#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3155#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3156static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3157 int ft, int fs, int cc) \
3158{ \
3159 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
3160 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
3161 switch (ifmt) { \
3162 case FMT_PS: \
e29c9628 3163 check_ps(ctx); \
8153667c
NF
3164 break; \
3165 case FMT_D: \
3166 if (abs) { \
3167 check_cop1x(ctx); \
3168 } \
3169 check_cp1_registers(ctx, fs | ft); \
3170 break; \
3171 case FMT_S: \
3172 if (abs) { \
3173 check_cop1x(ctx); \
3174 } \
3175 break; \
3176 } \
3177 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
3178 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
3179 switch (n) { \
895c2d04
BS
3180 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
3181 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
3182 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
3183 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
3184 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
3185 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
3186 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
3187 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
3188 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
3189 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
3190 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
3191 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
3192 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
3193 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
3194 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
3195 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
8153667c
NF
3196 default: abort(); \
3197 } \
3198 tcg_temp_free_i##bits (fp0); \
3199 tcg_temp_free_i##bits (fp1); \
3200}
3201
3202FOP_CONDS(, 0, d, FMT_D, 64)
3203FOP_CONDS(abs, 1, d, FMT_D, 64)
3204FOP_CONDS(, 0, s, FMT_S, 32)
3205FOP_CONDS(abs, 1, s, FMT_S, 32)
3206FOP_CONDS(, 0, ps, FMT_PS, 64)
3207FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3208#undef FOP_CONDS
3f493883
YK
3209
3210#define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3211static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
3212 int ft, int fs, int fd) \
3213{ \
3214 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3215 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
00fb4a11 3216 if (ifmt == FMT_D) { \
3f493883 3217 check_cp1_registers(ctx, fs | ft | fd); \
3f493883
YK
3218 } \
3219 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3220 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3221 switch (n) { \
3222 case 0: \
3223 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3224 break; \
3225 case 1: \
3226 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3227 break; \
3228 case 2: \
3229 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3230 break; \
3231 case 3: \
3232 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3233 break; \
3234 case 4: \
3235 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3236 break; \
3237 case 5: \
3238 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3239 break; \
3240 case 6: \
3241 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3242 break; \
3243 case 7: \
3244 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3245 break; \
3246 case 8: \
3247 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3248 break; \
3249 case 9: \
3250 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3251 break; \
3252 case 10: \
3253 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3254 break; \
3255 case 11: \
3256 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3257 break; \
3258 case 12: \
3259 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3260 break; \
3261 case 13: \
3262 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3263 break; \
3264 case 14: \
3265 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3266 break; \
3267 case 15: \
3268 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3269 break; \
3270 case 17: \
3271 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3272 break; \
3273 case 18: \
3274 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3275 break; \
3276 case 19: \
3277 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3278 break; \
3279 case 25: \
3280 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3281 break; \
3282 case 26: \
3283 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3284 break; \
3285 case 27: \
3286 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3287 break; \
3288 default: \
3289 abort(); \
3290 } \
3291 STORE; \
3292 tcg_temp_free_i ## bits (fp0); \
3293 tcg_temp_free_i ## bits (fp1); \
3294}
3295
3296FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
7c979afd 3297FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3f493883 3298#undef FOP_CONDNS
8153667c
NF
3299#undef gen_ldcmp_fpr32
3300#undef gen_ldcmp_fpr64
3301
958fb4a9 3302/* load/store instructions. */
e7139c44 3303#ifdef CONFIG_USER_ONLY
d9bea114 3304#define OP_LD_ATOMIC(insn,fname) \
dd4096cd
JH
3305static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3306 DisasContext *ctx) \
d9bea114
AJ
3307{ \
3308 TCGv t0 = tcg_temp_new(); \
3309 tcg_gen_mov_tl(t0, arg1); \
3310 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
7db13fae
AF
3311 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3312 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 3313 tcg_temp_free(t0); \
aaa9128a 3314}
e7139c44
AJ
3315#else
3316#define OP_LD_ATOMIC(insn,fname) \
dd4096cd
JH
3317static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3318 DisasContext *ctx) \
e7139c44 3319{ \
dd4096cd 3320 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
e7139c44
AJ
3321}
3322#endif
aaa9128a
TS
3323OP_LD_ATOMIC(ll,ld32s);
3324#if defined(TARGET_MIPS64)
3325OP_LD_ATOMIC(lld,ld64);
3326#endif
3327#undef OP_LD_ATOMIC
3328
590bc601
PB
3329#ifdef CONFIG_USER_ONLY
3330#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
dd4096cd
JH
3331static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3332 DisasContext *ctx) \
590bc601
PB
3333{ \
3334 TCGv t0 = tcg_temp_new(); \
42a268c2
RH
3335 TCGLabel *l1 = gen_new_label(); \
3336 TCGLabel *l2 = gen_new_label(); \
590bc601
PB
3337 \
3338 tcg_gen_andi_tl(t0, arg2, almask); \
3339 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
7db13fae 3340 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
590bc601
PB
3341 generate_exception(ctx, EXCP_AdES); \
3342 gen_set_label(l1); \
7db13fae 3343 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
590bc601
PB
3344 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
3345 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
7db13fae
AF
3346 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
3347 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
9c708c7f 3348 generate_exception_end(ctx, EXCP_SC); \
590bc601
PB
3349 gen_set_label(l2); \
3350 tcg_gen_movi_tl(t0, 0); \
3351 gen_store_gpr(t0, rt); \
3352 tcg_temp_free(t0); \
3353}
3354#else
3355#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
dd4096cd
JH
3356static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3357 DisasContext *ctx) \
590bc601
PB
3358{ \
3359 TCGv t0 = tcg_temp_new(); \
dd4096cd 3360 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
590bc601 3361 gen_store_gpr(t0, rt); \
590bc601
PB
3362 tcg_temp_free(t0); \
3363}
3364#endif
590bc601 3365OP_ST_ATOMIC(sc,st32,ld32s,0x3);
aaa9128a 3366#if defined(TARGET_MIPS64)
590bc601 3367OP_ST_ATOMIC(scd,st64,ld64,0x7);
aaa9128a
TS
3368#endif
3369#undef OP_ST_ATOMIC
3370
662d7485 3371static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
72e1f16f 3372 int base, int offset)
662d7485
NF
3373{
3374 if (base == 0) {
3375 tcg_gen_movi_tl(addr, offset);
3376 } else if (offset == 0) {
3377 gen_load_gpr(addr, base);
3378 } else {
3379 tcg_gen_movi_tl(addr, offset);
3380 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3381 }
3382}
3383
364d4831
NF
3384static target_ulong pc_relative_pc (DisasContext *ctx)
3385{
eeb3bba8 3386 target_ulong pc = ctx->base.pc_next;
364d4831
NF
3387
3388 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3389 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3390
3391 pc -= branch_bytes;
3392 }
3393
3394 pc &= ~(target_ulong)3;
3395 return pc;
3396}
3397
5c13fdfd 3398/* Load */
d75c135e 3399static void gen_ld(DisasContext *ctx, uint32_t opc,
72e1f16f 3400 int rt, int base, int offset)
6af0bf9c 3401{
fc40787a 3402 TCGv t0, t1, t2;
dd4096cd 3403 int mem_idx = ctx->mem_idx;
afa88c3a 3404
d75c135e 3405 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
afa88c3a
AJ
3406 /* Loongson CPU uses a load to zero register for prefetch.
3407 We emulate it as a NOP. On other CPU we must perform the
3408 actual memory access. */
afa88c3a
AJ
3409 return;
3410 }
6af0bf9c 3411
afa88c3a 3412 t0 = tcg_temp_new();
662d7485 3413 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 3414
6af0bf9c 3415 switch (opc) {
d26bc211 3416#if defined(TARGET_MIPS64)
6e473128 3417 case OPC_LWU:
dd4096cd 3418 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
be3a8c53 3419 ctx->default_tcg_memop_mask);
78723684 3420 gen_store_gpr(t0, rt);
6e473128 3421 break;
6af0bf9c 3422 case OPC_LD:
dd4096cd 3423 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
be3a8c53 3424 ctx->default_tcg_memop_mask);
78723684 3425 gen_store_gpr(t0, rt);
6af0bf9c 3426 break;
7a387fff 3427 case OPC_LLD:
bf7910c6 3428 case R6_OPC_LLD:
dd4096cd 3429 op_ld_lld(t0, t0, mem_idx, ctx);
78723684 3430 gen_store_gpr(t0, rt);
7a387fff 3431 break;
6af0bf9c 3432 case OPC_LDL:
3cee3050 3433 t1 = tcg_temp_new();
908680c6
AJ
3434 /* Do a byte access to possibly trigger a page
3435 fault with the unaligned address. */
dd4096cd 3436 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3437 tcg_gen_andi_tl(t1, t0, 7);
3438#ifndef TARGET_WORDS_BIGENDIAN
3439 tcg_gen_xori_tl(t1, t1, 7);
3440#endif
3441 tcg_gen_shli_tl(t1, t1, 3);
3442 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 3443 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a 3444 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
3445 t2 = tcg_const_tl(-1);
3446 tcg_gen_shl_tl(t2, t2, t1);
78723684 3447 gen_load_gpr(t1, rt);
eb02cc3f 3448 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
3449 tcg_temp_free(t2);
3450 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3451 tcg_temp_free(t1);
fc40787a 3452 gen_store_gpr(t0, rt);
6af0bf9c 3453 break;
6af0bf9c 3454 case OPC_LDR:
3cee3050 3455 t1 = tcg_temp_new();
908680c6
AJ
3456 /* Do a byte access to possibly trigger a page
3457 fault with the unaligned address. */
dd4096cd 3458 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3459 tcg_gen_andi_tl(t1, t0, 7);
3460#ifdef TARGET_WORDS_BIGENDIAN
3461 tcg_gen_xori_tl(t1, t1, 7);
3462#endif
3463 tcg_gen_shli_tl(t1, t1, 3);
3464 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 3465 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a
AJ
3466 tcg_gen_shr_tl(t0, t0, t1);
3467 tcg_gen_xori_tl(t1, t1, 63);
3468 t2 = tcg_const_tl(0xfffffffffffffffeull);
3469 tcg_gen_shl_tl(t2, t2, t1);
78723684 3470 gen_load_gpr(t1, rt);
fc40787a
AJ
3471 tcg_gen_and_tl(t1, t1, t2);
3472 tcg_temp_free(t2);
3473 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3474 tcg_temp_free(t1);
fc40787a 3475 gen_store_gpr(t0, rt);
6af0bf9c 3476 break;
364d4831 3477 case OPC_LDPC:
3cee3050 3478 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 3479 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 3480 tcg_temp_free(t1);
dd4096cd 3481 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
364d4831
NF
3482 gen_store_gpr(t0, rt);
3483 break;
6af0bf9c 3484#endif
364d4831 3485 case OPC_LWPC:
3cee3050 3486 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 3487 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 3488 tcg_temp_free(t1);
dd4096cd 3489 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
364d4831
NF
3490 gen_store_gpr(t0, rt);
3491 break;
76964147
JH
3492 case OPC_LWE:
3493 mem_idx = MIPS_HFLAG_UM;
3494 /* fall through */
6af0bf9c 3495 case OPC_LW:
dd4096cd 3496 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
be3a8c53 3497 ctx->default_tcg_memop_mask);
78723684 3498 gen_store_gpr(t0, rt);
6af0bf9c 3499 break;
76964147
JH
3500 case OPC_LHE:
3501 mem_idx = MIPS_HFLAG_UM;
3502 /* fall through */
6af0bf9c 3503 case OPC_LH:
dd4096cd 3504 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
be3a8c53 3505 ctx->default_tcg_memop_mask);
78723684 3506 gen_store_gpr(t0, rt);
6af0bf9c 3507 break;
76964147
JH
3508 case OPC_LHUE:
3509 mem_idx = MIPS_HFLAG_UM;
3510 /* fall through */
6af0bf9c 3511 case OPC_LHU:
dd4096cd 3512 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
be3a8c53 3513 ctx->default_tcg_memop_mask);
78723684 3514 gen_store_gpr(t0, rt);
6af0bf9c 3515 break;
76964147
JH
3516 case OPC_LBE:
3517 mem_idx = MIPS_HFLAG_UM;
3518 /* fall through */
6af0bf9c 3519 case OPC_LB:
dd4096cd 3520 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
78723684 3521 gen_store_gpr(t0, rt);
6af0bf9c 3522 break;
76964147
JH
3523 case OPC_LBUE:
3524 mem_idx = MIPS_HFLAG_UM;
3525 /* fall through */
6af0bf9c 3526 case OPC_LBU:
dd4096cd 3527 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
78723684 3528 gen_store_gpr(t0, rt);
6af0bf9c 3529 break;
76964147
JH
3530 case OPC_LWLE:
3531 mem_idx = MIPS_HFLAG_UM;
3532 /* fall through */
6af0bf9c 3533 case OPC_LWL:
3cee3050 3534 t1 = tcg_temp_new();
908680c6
AJ
3535 /* Do a byte access to possibly trigger a page
3536 fault with the unaligned address. */
dd4096cd 3537 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3538 tcg_gen_andi_tl(t1, t0, 3);
3539#ifndef TARGET_WORDS_BIGENDIAN
3540 tcg_gen_xori_tl(t1, t1, 3);
3541#endif
3542 tcg_gen_shli_tl(t1, t1, 3);
3543 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 3544 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a 3545 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
3546 t2 = tcg_const_tl(-1);
3547 tcg_gen_shl_tl(t2, t2, t1);
6958549d 3548 gen_load_gpr(t1, rt);
eb02cc3f 3549 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
3550 tcg_temp_free(t2);
3551 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3552 tcg_temp_free(t1);
fc40787a
AJ
3553 tcg_gen_ext32s_tl(t0, t0);
3554 gen_store_gpr(t0, rt);
6af0bf9c 3555 break;
76964147
JH
3556 case OPC_LWRE:
3557 mem_idx = MIPS_HFLAG_UM;
3558 /* fall through */
6af0bf9c 3559 case OPC_LWR:
3cee3050 3560 t1 = tcg_temp_new();
908680c6
AJ
3561 /* Do a byte access to possibly trigger a page
3562 fault with the unaligned address. */
dd4096cd 3563 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3564 tcg_gen_andi_tl(t1, t0, 3);
3565#ifdef TARGET_WORDS_BIGENDIAN
3566 tcg_gen_xori_tl(t1, t1, 3);
3567#endif
3568 tcg_gen_shli_tl(t1, t1, 3);
3569 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 3570 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a
AJ
3571 tcg_gen_shr_tl(t0, t0, t1);
3572 tcg_gen_xori_tl(t1, t1, 31);
3573 t2 = tcg_const_tl(0xfffffffeull);
3574 tcg_gen_shl_tl(t2, t2, t1);
6958549d 3575 gen_load_gpr(t1, rt);
fc40787a
AJ
3576 tcg_gen_and_tl(t1, t1, t2);
3577 tcg_temp_free(t2);
3578 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3579 tcg_temp_free(t1);
c728154b 3580 tcg_gen_ext32s_tl(t0, t0);
fc40787a 3581 gen_store_gpr(t0, rt);
6af0bf9c 3582 break;
76964147
JH
3583 case OPC_LLE:
3584 mem_idx = MIPS_HFLAG_UM;
3585 /* fall through */
6af0bf9c 3586 case OPC_LL:
4368b29a 3587 case R6_OPC_LL:
dd4096cd 3588 op_ld_ll(t0, t0, mem_idx, ctx);
78723684 3589 gen_store_gpr(t0, rt);
6af0bf9c 3590 break;
d66c7132 3591 }
d66c7132 3592 tcg_temp_free(t0);
d66c7132
AJ
3593}
3594
0b16dcd1
AR
3595static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3596 uint32_t reg1, uint32_t reg2)
3597{
3598 TCGv taddr = tcg_temp_new();
3599 TCGv_i64 tval = tcg_temp_new_i64();
3600 TCGv tmp1 = tcg_temp_new();
3601 TCGv tmp2 = tcg_temp_new();
3602
3603 gen_base_offset_addr(ctx, taddr, base, offset);
3604 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3605#ifdef TARGET_WORDS_BIGENDIAN
3606 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3607#else
3608 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3609#endif
3610 gen_store_gpr(tmp1, reg1);
3611 tcg_temp_free(tmp1);
3612 gen_store_gpr(tmp2, reg2);
3613 tcg_temp_free(tmp2);
3614 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3615 tcg_temp_free_i64(tval);
3616 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3617 tcg_temp_free(taddr);
3618}
3619
5c13fdfd
AJ
3620/* Store */
3621static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
72e1f16f 3622 int base, int offset)
5c13fdfd 3623{
5c13fdfd
AJ
3624 TCGv t0 = tcg_temp_new();
3625 TCGv t1 = tcg_temp_new();
dd4096cd 3626 int mem_idx = ctx->mem_idx;
5c13fdfd
AJ
3627
3628 gen_base_offset_addr(ctx, t0, base, offset);
3629 gen_load_gpr(t1, rt);
3630 switch (opc) {
3631#if defined(TARGET_MIPS64)
3632 case OPC_SD:
dd4096cd 3633 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
be3a8c53 3634 ctx->default_tcg_memop_mask);
5c13fdfd
AJ
3635 break;
3636 case OPC_SDL:
dd4096cd 3637 gen_helper_0e2i(sdl, t1, t0, mem_idx);
5c13fdfd
AJ
3638 break;
3639 case OPC_SDR:
dd4096cd 3640 gen_helper_0e2i(sdr, t1, t0, mem_idx);
5c13fdfd
AJ
3641 break;
3642#endif
76964147
JH
3643 case OPC_SWE:
3644 mem_idx = MIPS_HFLAG_UM;
3645 /* fall through */
5c13fdfd 3646 case OPC_SW:
dd4096cd 3647 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
be3a8c53 3648 ctx->default_tcg_memop_mask);
5c13fdfd 3649 break;
76964147
JH
3650 case OPC_SHE:
3651 mem_idx = MIPS_HFLAG_UM;
3652 /* fall through */
5c13fdfd 3653 case OPC_SH:
dd4096cd 3654 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
be3a8c53 3655 ctx->default_tcg_memop_mask);
5c13fdfd 3656 break;
76964147
JH
3657 case OPC_SBE:
3658 mem_idx = MIPS_HFLAG_UM;
3659 /* fall through */
5c13fdfd 3660 case OPC_SB:
dd4096cd 3661 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
5c13fdfd 3662 break;
76964147
JH
3663 case OPC_SWLE:
3664 mem_idx = MIPS_HFLAG_UM;
3665 /* fall through */
5c13fdfd 3666 case OPC_SWL:
dd4096cd 3667 gen_helper_0e2i(swl, t1, t0, mem_idx);
5c13fdfd 3668 break;
76964147
JH
3669 case OPC_SWRE:
3670 mem_idx = MIPS_HFLAG_UM;
3671 /* fall through */
5c13fdfd 3672 case OPC_SWR:
dd4096cd 3673 gen_helper_0e2i(swr, t1, t0, mem_idx);
5c13fdfd
AJ
3674 break;
3675 }
5c13fdfd
AJ
3676 tcg_temp_free(t0);
3677 tcg_temp_free(t1);
3678}
3679
3680
d66c7132
AJ
3681/* Store conditional */
3682static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
3683 int base, int16_t offset)
3684{
d66c7132 3685 TCGv t0, t1;
dd4096cd 3686 int mem_idx = ctx->mem_idx;
d66c7132 3687
2d2826b9 3688#ifdef CONFIG_USER_ONLY
d66c7132 3689 t0 = tcg_temp_local_new();
d66c7132 3690 t1 = tcg_temp_local_new();
2d2826b9
AJ
3691#else
3692 t0 = tcg_temp_new();
3693 t1 = tcg_temp_new();
3694#endif
3695 gen_base_offset_addr(ctx, t0, base, offset);
d66c7132
AJ
3696 gen_load_gpr(t1, rt);
3697 switch (opc) {
3698#if defined(TARGET_MIPS64)
3699 case OPC_SCD:
bf7910c6 3700 case R6_OPC_SCD:
dd4096cd 3701 op_st_scd(t1, t0, rt, mem_idx, ctx);
d66c7132
AJ
3702 break;
3703#endif
76964147
JH
3704 case OPC_SCE:
3705 mem_idx = MIPS_HFLAG_UM;
3706 /* fall through */
6af0bf9c 3707 case OPC_SC:
4368b29a 3708 case R6_OPC_SC:
dd4096cd 3709 op_st_sc(t1, t0, rt, mem_idx, ctx);
6af0bf9c 3710 break;
6af0bf9c 3711 }
78723684 3712 tcg_temp_free(t1);
d66c7132 3713 tcg_temp_free(t0);
6af0bf9c
FB
3714}
3715
0b16dcd1
AR
3716static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3717 uint32_t reg1, uint32_t reg2)
3718{
3719 TCGv taddr = tcg_temp_local_new();
3720 TCGv lladdr = tcg_temp_local_new();
3721 TCGv_i64 tval = tcg_temp_new_i64();
3722 TCGv_i64 llval = tcg_temp_new_i64();
3723 TCGv_i64 val = tcg_temp_new_i64();
3724 TCGv tmp1 = tcg_temp_new();
3725 TCGv tmp2 = tcg_temp_new();
3726 TCGLabel *lab_fail = gen_new_label();
3727 TCGLabel *lab_done = gen_new_label();
3728
3729 gen_base_offset_addr(ctx, taddr, base, offset);
3730
3731 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3732 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3733
3734 gen_load_gpr(tmp1, reg1);
3735 gen_load_gpr(tmp2, reg2);
3736
3737#ifdef TARGET_WORDS_BIGENDIAN
3738 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3739#else
3740 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3741#endif
3742
3743 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3744 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3745 ctx->mem_idx, MO_64);
3746 if (reg1 != 0) {
3747 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3748 }
3749 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3750
3751 gen_set_label(lab_fail);
3752
3753 if (reg1 != 0) {
3754 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3755 }
3756 gen_set_label(lab_done);
3757 tcg_gen_movi_tl(lladdr, -1);
3758 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3759}
3760
6ea83fed 3761/* Load and store */
7a387fff 3762static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
b52d3bfa 3763 TCGv t0)
6ea83fed 3764{
6ea83fed 3765 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 3766 memory access. */
6ea83fed
FB
3767 switch (opc) {
3768 case OPC_LWC1:
b6d96bed 3769 {
a7812ae4 3770 TCGv_i32 fp0 = tcg_temp_new_i32();
be3a8c53
YK
3771 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3772 ctx->default_tcg_memop_mask);
7c979afd 3773 gen_store_fpr32(ctx, fp0, ft);
a7812ae4 3774 tcg_temp_free_i32(fp0);
b6d96bed 3775 }
6ea83fed
FB
3776 break;
3777 case OPC_SWC1:
b6d96bed 3778 {
a7812ae4 3779 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 3780 gen_load_fpr32(ctx, fp0, ft);
be3a8c53
YK
3781 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3782 ctx->default_tcg_memop_mask);
a7812ae4 3783 tcg_temp_free_i32(fp0);
b6d96bed 3784 }
6ea83fed
FB
3785 break;
3786 case OPC_LDC1:
b6d96bed 3787 {
a7812ae4 3788 TCGv_i64 fp0 = tcg_temp_new_i64();
be3a8c53
YK
3789 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3790 ctx->default_tcg_memop_mask);
b6d96bed 3791 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 3792 tcg_temp_free_i64(fp0);
b6d96bed 3793 }
6ea83fed
FB
3794 break;
3795 case OPC_SDC1:
b6d96bed 3796 {
a7812ae4 3797 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 3798 gen_load_fpr64(ctx, fp0, ft);
be3a8c53
YK
3799 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3800 ctx->default_tcg_memop_mask);
a7812ae4 3801 tcg_temp_free_i64(fp0);
b6d96bed 3802 }
6ea83fed
FB
3803 break;
3804 default:
9d68ac14 3805 MIPS_INVAL("flt_ldst");
9c708c7f 3806 generate_exception_end(ctx, EXCP_RI);
b52d3bfa 3807 break;
6ea83fed 3808 }
6ea83fed 3809}
6ea83fed 3810
5ab5c041
AJ
3811static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3812 int rs, int16_t imm)
26ebe468 3813{
b52d3bfa
YK
3814 TCGv t0 = tcg_temp_new();
3815
5ab5c041 3816 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26ebe468 3817 check_cp1_enabled(ctx);
d9224450
MR
3818 switch (op) {
3819 case OPC_LDC1:
3820 case OPC_SDC1:
3821 check_insn(ctx, ISA_MIPS2);
3822 /* Fallthrough */
3823 default:
b52d3bfa
YK
3824 gen_base_offset_addr(ctx, t0, rs, imm);
3825 gen_flt_ldst(ctx, op, rt, t0);
d9224450 3826 }
26ebe468
NF
3827 } else {
3828 generate_exception_err(ctx, EXCP_CpU, 1);
3829 }
b52d3bfa 3830 tcg_temp_free(t0);
26ebe468
NF
3831}
3832
6af0bf9c 3833/* Arithmetic with immediate operand */
d75c135e 3834static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
72e1f16f 3835 int rt, int rs, int imm)
6af0bf9c 3836{
324d9e32 3837 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
6af0bf9c 3838
7a387fff 3839 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
ead9360e
TS
3840 /* If no destination, treat it as a NOP.
3841 For addi, we must generate the overflow exception when needed. */
324d9e32 3842 return;
6af0bf9c
FB
3843 }
3844 switch (opc) {
3845 case OPC_ADDI:
48d38ca5 3846 {
324d9e32
AJ
3847 TCGv t0 = tcg_temp_local_new();
3848 TCGv t1 = tcg_temp_new();
3849 TCGv t2 = tcg_temp_new();
42a268c2 3850 TCGLabel *l1 = gen_new_label();
48d38ca5 3851
324d9e32
AJ
3852 gen_load_gpr(t1, rs);
3853 tcg_gen_addi_tl(t0, t1, uimm);
3854 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 3855
324d9e32
AJ
3856 tcg_gen_xori_tl(t1, t1, ~uimm);
3857 tcg_gen_xori_tl(t2, t0, uimm);
3858 tcg_gen_and_tl(t1, t1, t2);
3859 tcg_temp_free(t2);
3860 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3861 tcg_temp_free(t1);
48d38ca5
TS
3862 /* operands of same sign, result different sign */
3863 generate_exception(ctx, EXCP_OVERFLOW);
3864 gen_set_label(l1);
78723684 3865 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
3866 gen_store_gpr(t0, rt);
3867 tcg_temp_free(t0);
48d38ca5 3868 }
6af0bf9c
FB
3869 break;
3870 case OPC_ADDIU:
324d9e32
AJ
3871 if (rs != 0) {
3872 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3873 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3874 } else {
3875 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3876 }
6af0bf9c 3877 break;
d26bc211 3878#if defined(TARGET_MIPS64)
7a387fff 3879 case OPC_DADDI:
48d38ca5 3880 {
324d9e32
AJ
3881 TCGv t0 = tcg_temp_local_new();
3882 TCGv t1 = tcg_temp_new();
3883 TCGv t2 = tcg_temp_new();
42a268c2 3884 TCGLabel *l1 = gen_new_label();
48d38ca5 3885
324d9e32
AJ
3886 gen_load_gpr(t1, rs);
3887 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 3888
324d9e32
AJ
3889 tcg_gen_xori_tl(t1, t1, ~uimm);
3890 tcg_gen_xori_tl(t2, t0, uimm);
3891 tcg_gen_and_tl(t1, t1, t2);
3892 tcg_temp_free(t2);
3893 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3894 tcg_temp_free(t1);
48d38ca5
TS
3895 /* operands of same sign, result different sign */
3896 generate_exception(ctx, EXCP_OVERFLOW);
3897 gen_set_label(l1);
324d9e32
AJ
3898 gen_store_gpr(t0, rt);
3899 tcg_temp_free(t0);
48d38ca5 3900 }
7a387fff
TS
3901 break;
3902 case OPC_DADDIU:
324d9e32
AJ
3903 if (rs != 0) {
3904 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3905 } else {
3906 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3907 }
7a387fff
TS
3908 break;
3909#endif
324d9e32 3910 }
324d9e32
AJ
3911}
3912
3913/* Logic with immediate operand */
d75c135e 3914static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3915 int rt, int rs, int16_t imm)
324d9e32
AJ
3916{
3917 target_ulong uimm;
324d9e32
AJ
3918
3919 if (rt == 0) {
3920 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3921 return;
3922 }
3923 uimm = (uint16_t)imm;
3924 switch (opc) {
6af0bf9c 3925 case OPC_ANDI:
324d9e32
AJ
3926 if (likely(rs != 0))
3927 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3928 else
3929 tcg_gen_movi_tl(cpu_gpr[rt], 0);
6af0bf9c
FB
3930 break;
3931 case OPC_ORI:
324d9e32
AJ
3932 if (rs != 0)
3933 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3934 else
3935 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
3936 break;
3937 case OPC_XORI:
324d9e32
AJ
3938 if (likely(rs != 0))
3939 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3940 else
3941 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
3942 break;
3943 case OPC_LUI:
d4ea6acd
LA
3944 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3945 /* OPC_AUI */
3946 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3947 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
d4ea6acd
LA
3948 } else {
3949 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
d4ea6acd 3950 }
7c2c3ea3
EJ
3951 break;
3952
3953 default:
6af0bf9c 3954 break;
324d9e32 3955 }
324d9e32
AJ
3956}
3957
3958/* Set on less than with immediate operand */
d75c135e 3959static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3960 int rt, int rs, int16_t imm)
324d9e32
AJ
3961{
3962 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
324d9e32
AJ
3963 TCGv t0;
3964
3965 if (rt == 0) {
3966 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3967 return;
3968 }
3969 t0 = tcg_temp_new();
3970 gen_load_gpr(t0, rs);
3971 switch (opc) {
3972 case OPC_SLTI:
e68dd28f 3973 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
3974 break;
3975 case OPC_SLTIU:
e68dd28f 3976 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
3977 break;
3978 }
324d9e32
AJ
3979 tcg_temp_free(t0);
3980}
3981
3982/* Shifts with immediate operand */
d75c135e 3983static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
324d9e32
AJ
3984 int rt, int rs, int16_t imm)
3985{
3986 target_ulong uimm = ((uint16_t)imm) & 0x1f;
324d9e32
AJ
3987 TCGv t0;
3988
3989 if (rt == 0) {
3990 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3991 return;
3992 }
3993
3994 t0 = tcg_temp_new();
3995 gen_load_gpr(t0, rs);
3996 switch (opc) {
6af0bf9c 3997 case OPC_SLL:
78723684 3998 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 3999 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
4000 break;
4001 case OPC_SRA:
324d9e32 4002 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
4003 break;
4004 case OPC_SRL:
ea63e2c3
NF
4005 if (uimm != 0) {
4006 tcg_gen_ext32u_tl(t0, t0);
4007 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4008 } else {
4009 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 4010 }
ea63e2c3
NF
4011 break;
4012 case OPC_ROTR:
4013 if (uimm != 0) {
4014 TCGv_i32 t1 = tcg_temp_new_i32();
4015
4016 tcg_gen_trunc_tl_i32(t1, t0);
4017 tcg_gen_rotri_i32(t1, t1, uimm);
4018 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4019 tcg_temp_free_i32(t1);
3399e30f
NF
4020 } else {
4021 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3 4022 }
7a387fff 4023 break;
d26bc211 4024#if defined(TARGET_MIPS64)
7a387fff 4025 case OPC_DSLL:
324d9e32 4026 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
4027 break;
4028 case OPC_DSRA:
324d9e32 4029 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
4030 break;
4031 case OPC_DSRL:
ea63e2c3 4032 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
ea63e2c3
NF
4033 break;
4034 case OPC_DROTR:
4035 if (uimm != 0) {
4036 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
4037 } else {
4038 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 4039 }
7a387fff
TS
4040 break;
4041 case OPC_DSLL32:
324d9e32 4042 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
4043 break;
4044 case OPC_DSRA32:
324d9e32 4045 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
4046 break;
4047 case OPC_DSRL32:
ea63e2c3 4048 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
ea63e2c3
NF
4049 break;
4050 case OPC_DROTR32:
4051 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
6af0bf9c 4052 break;
7a387fff 4053#endif
6af0bf9c 4054 }
78723684 4055 tcg_temp_free(t0);
6af0bf9c
FB
4056}
4057
4058/* Arithmetic */
d75c135e
AJ
4059static void gen_arith(DisasContext *ctx, uint32_t opc,
4060 int rd, int rs, int rt)
6af0bf9c 4061{
7a387fff
TS
4062 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4063 && opc != OPC_DADD && opc != OPC_DSUB) {
ead9360e
TS
4064 /* If no destination, treat it as a NOP.
4065 For add & sub, we must generate the overflow exception when needed. */
460f00c4 4066 return;
185f0762 4067 }
460f00c4 4068
6af0bf9c
FB
4069 switch (opc) {
4070 case OPC_ADD:
48d38ca5 4071 {
460f00c4
AJ
4072 TCGv t0 = tcg_temp_local_new();
4073 TCGv t1 = tcg_temp_new();
4074 TCGv t2 = tcg_temp_new();
42a268c2 4075 TCGLabel *l1 = gen_new_label();
48d38ca5 4076
460f00c4
AJ
4077 gen_load_gpr(t1, rs);
4078 gen_load_gpr(t2, rt);
4079 tcg_gen_add_tl(t0, t1, t2);
4080 tcg_gen_ext32s_tl(t0, t0);
4081 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 4082 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 4083 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
4084 tcg_temp_free(t2);
4085 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4086 tcg_temp_free(t1);
48d38ca5
TS
4087 /* operands of same sign, result different sign */
4088 generate_exception(ctx, EXCP_OVERFLOW);
4089 gen_set_label(l1);
460f00c4
AJ
4090 gen_store_gpr(t0, rd);
4091 tcg_temp_free(t0);
48d38ca5 4092 }
6af0bf9c
FB
4093 break;
4094 case OPC_ADDU:
460f00c4
AJ
4095 if (rs != 0 && rt != 0) {
4096 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4097 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4098 } else if (rs == 0 && rt != 0) {
4099 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4100 } else if (rs != 0 && rt == 0) {
4101 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4102 } else {
4103 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4104 }
6af0bf9c
FB
4105 break;
4106 case OPC_SUB:
48d38ca5 4107 {
460f00c4
AJ
4108 TCGv t0 = tcg_temp_local_new();
4109 TCGv t1 = tcg_temp_new();
4110 TCGv t2 = tcg_temp_new();
42a268c2 4111 TCGLabel *l1 = gen_new_label();
48d38ca5 4112
460f00c4
AJ
4113 gen_load_gpr(t1, rs);
4114 gen_load_gpr(t2, rt);
4115 tcg_gen_sub_tl(t0, t1, t2);
4116 tcg_gen_ext32s_tl(t0, t0);
4117 tcg_gen_xor_tl(t2, t1, t2);
4118 tcg_gen_xor_tl(t1, t0, t1);
4119 tcg_gen_and_tl(t1, t1, t2);
4120 tcg_temp_free(t2);
4121 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4122 tcg_temp_free(t1);
31e3104f 4123 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
4124 generate_exception(ctx, EXCP_OVERFLOW);
4125 gen_set_label(l1);
460f00c4
AJ
4126 gen_store_gpr(t0, rd);
4127 tcg_temp_free(t0);
48d38ca5 4128 }
6af0bf9c
FB
4129 break;
4130 case OPC_SUBU:
460f00c4
AJ
4131 if (rs != 0 && rt != 0) {
4132 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4133 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4134 } else if (rs == 0 && rt != 0) {
4135 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 4136 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
4137 } else if (rs != 0 && rt == 0) {
4138 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4139 } else {
4140 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4141 }
6af0bf9c 4142 break;
d26bc211 4143#if defined(TARGET_MIPS64)
7a387fff 4144 case OPC_DADD:
48d38ca5 4145 {
460f00c4
AJ
4146 TCGv t0 = tcg_temp_local_new();
4147 TCGv t1 = tcg_temp_new();
4148 TCGv t2 = tcg_temp_new();
42a268c2 4149 TCGLabel *l1 = gen_new_label();
48d38ca5 4150
460f00c4
AJ
4151 gen_load_gpr(t1, rs);
4152 gen_load_gpr(t2, rt);
4153 tcg_gen_add_tl(t0, t1, t2);
4154 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 4155 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 4156 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
4157 tcg_temp_free(t2);
4158 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4159 tcg_temp_free(t1);
48d38ca5
TS
4160 /* operands of same sign, result different sign */
4161 generate_exception(ctx, EXCP_OVERFLOW);
4162 gen_set_label(l1);
460f00c4
AJ
4163 gen_store_gpr(t0, rd);
4164 tcg_temp_free(t0);
48d38ca5 4165 }
7a387fff
TS
4166 break;
4167 case OPC_DADDU:
460f00c4
AJ
4168 if (rs != 0 && rt != 0) {
4169 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4170 } else if (rs == 0 && rt != 0) {
4171 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4172 } else if (rs != 0 && rt == 0) {
4173 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4174 } else {
4175 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4176 }
7a387fff
TS
4177 break;
4178 case OPC_DSUB:
48d38ca5 4179 {
460f00c4
AJ
4180 TCGv t0 = tcg_temp_local_new();
4181 TCGv t1 = tcg_temp_new();
4182 TCGv t2 = tcg_temp_new();
42a268c2 4183 TCGLabel *l1 = gen_new_label();
48d38ca5 4184
460f00c4
AJ
4185 gen_load_gpr(t1, rs);
4186 gen_load_gpr(t2, rt);
4187 tcg_gen_sub_tl(t0, t1, t2);
4188 tcg_gen_xor_tl(t2, t1, t2);
4189 tcg_gen_xor_tl(t1, t0, t1);
4190 tcg_gen_and_tl(t1, t1, t2);
4191 tcg_temp_free(t2);
4192 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4193 tcg_temp_free(t1);
31e3104f 4194 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
4195 generate_exception(ctx, EXCP_OVERFLOW);
4196 gen_set_label(l1);
460f00c4
AJ
4197 gen_store_gpr(t0, rd);
4198 tcg_temp_free(t0);
48d38ca5 4199 }
7a387fff
TS
4200 break;
4201 case OPC_DSUBU:
460f00c4
AJ
4202 if (rs != 0 && rt != 0) {
4203 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4204 } else if (rs == 0 && rt != 0) {
4205 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4206 } else if (rs != 0 && rt == 0) {
4207 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4208 } else {
4209 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4210 }
7a387fff
TS
4211 break;
4212#endif
460f00c4
AJ
4213 case OPC_MUL:
4214 if (likely(rs != 0 && rt != 0)) {
4215 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4216 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4217 } else {
4218 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4219 }
6af0bf9c 4220 break;
460f00c4 4221 }
460f00c4
AJ
4222}
4223
4224/* Conditional move */
d75c135e 4225static void gen_cond_move(DisasContext *ctx, uint32_t opc,
9fa77488 4226 int rd, int rs, int rt)
460f00c4 4227{
acf12465 4228 TCGv t0, t1, t2;
460f00c4
AJ
4229
4230 if (rd == 0) {
acf12465 4231 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4232 return;
4233 }
4234
acf12465
AJ
4235 t0 = tcg_temp_new();
4236 gen_load_gpr(t0, rt);
4237 t1 = tcg_const_tl(0);
4238 t2 = tcg_temp_new();
4239 gen_load_gpr(t2, rs);
460f00c4
AJ
4240 switch (opc) {
4241 case OPC_MOVN:
acf12465 4242 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
6af0bf9c 4243 break;
460f00c4 4244 case OPC_MOVZ:
acf12465 4245 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
460f00c4 4246 break;
b691d9d2
LA
4247 case OPC_SELNEZ:
4248 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2
LA
4249 break;
4250 case OPC_SELEQZ:
4251 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2 4252 break;
460f00c4 4253 }
acf12465
AJ
4254 tcg_temp_free(t2);
4255 tcg_temp_free(t1);
4256 tcg_temp_free(t0);
460f00c4
AJ
4257}
4258
4259/* Logic */
d75c135e 4260static void gen_logic(DisasContext *ctx, uint32_t opc,
9fa77488 4261 int rd, int rs, int rt)
460f00c4 4262{
460f00c4
AJ
4263 if (rd == 0) {
4264 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4265 return;
4266 }
4267
4268 switch (opc) {
6af0bf9c 4269 case OPC_AND:
460f00c4
AJ
4270 if (likely(rs != 0 && rt != 0)) {
4271 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4272 } else {
4273 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4274 }
6af0bf9c
FB
4275 break;
4276 case OPC_NOR:
460f00c4
AJ
4277 if (rs != 0 && rt != 0) {
4278 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4279 } else if (rs == 0 && rt != 0) {
4280 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4281 } else if (rs != 0 && rt == 0) {
4282 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4283 } else {
4284 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4285 }
6af0bf9c
FB
4286 break;
4287 case OPC_OR:
460f00c4
AJ
4288 if (likely(rs != 0 && rt != 0)) {
4289 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4290 } else if (rs == 0 && rt != 0) {
4291 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4292 } else if (rs != 0 && rt == 0) {
4293 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4294 } else {
4295 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4296 }
6af0bf9c
FB
4297 break;
4298 case OPC_XOR:
460f00c4
AJ
4299 if (likely(rs != 0 && rt != 0)) {
4300 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4301 } else if (rs == 0 && rt != 0) {
4302 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4303 } else if (rs != 0 && rt == 0) {
4304 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4305 } else {
4306 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4307 }
6af0bf9c 4308 break;
460f00c4 4309 }
460f00c4
AJ
4310}
4311
4312/* Set on lower than */
d75c135e 4313static void gen_slt(DisasContext *ctx, uint32_t opc,
9fa77488 4314 int rd, int rs, int rt)
460f00c4 4315{
460f00c4
AJ
4316 TCGv t0, t1;
4317
4318 if (rd == 0) {
4319 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4320 return;
4321 }
4322
4323 t0 = tcg_temp_new();
4324 t1 = tcg_temp_new();
4325 gen_load_gpr(t0, rs);
4326 gen_load_gpr(t1, rt);
4327 switch (opc) {
4328 case OPC_SLT:
e68dd28f 4329 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
6af0bf9c 4330 break;
460f00c4 4331 case OPC_SLTU:
e68dd28f 4332 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
4333 break;
4334 }
460f00c4
AJ
4335 tcg_temp_free(t0);
4336 tcg_temp_free(t1);
4337}
20c4c97c 4338
460f00c4 4339/* Shifts */
d75c135e
AJ
4340static void gen_shift(DisasContext *ctx, uint32_t opc,
4341 int rd, int rs, int rt)
460f00c4 4342{
460f00c4 4343 TCGv t0, t1;
20c4c97c 4344
460f00c4
AJ
4345 if (rd == 0) {
4346 /* If no destination, treat it as a NOP.
4347 For add & sub, we must generate the overflow exception when needed. */
460f00c4
AJ
4348 return;
4349 }
4350
4351 t0 = tcg_temp_new();
4352 t1 = tcg_temp_new();
4353 gen_load_gpr(t0, rs);
4354 gen_load_gpr(t1, rt);
4355 switch (opc) {
6af0bf9c 4356 case OPC_SLLV:
78723684
TS
4357 tcg_gen_andi_tl(t0, t0, 0x1f);
4358 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 4359 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
4360 break;
4361 case OPC_SRAV:
78723684 4362 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 4363 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
4364 break;
4365 case OPC_SRLV:
ea63e2c3
NF
4366 tcg_gen_ext32u_tl(t1, t1);
4367 tcg_gen_andi_tl(t0, t0, 0x1f);
4368 tcg_gen_shr_tl(t0, t1, t0);
4369 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
ea63e2c3
NF
4370 break;
4371 case OPC_ROTRV:
4372 {
4373 TCGv_i32 t2 = tcg_temp_new_i32();
4374 TCGv_i32 t3 = tcg_temp_new_i32();
4375
4376 tcg_gen_trunc_tl_i32(t2, t0);
4377 tcg_gen_trunc_tl_i32(t3, t1);
4378 tcg_gen_andi_i32(t2, t2, 0x1f);
4379 tcg_gen_rotr_i32(t2, t3, t2);
4380 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4381 tcg_temp_free_i32(t2);
4382 tcg_temp_free_i32(t3);
5a63bcb2 4383 }
7a387fff 4384 break;
d26bc211 4385#if defined(TARGET_MIPS64)
7a387fff 4386 case OPC_DSLLV:
78723684 4387 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 4388 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
4389 break;
4390 case OPC_DSRAV:
78723684 4391 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 4392 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
4393 break;
4394 case OPC_DSRLV:
ea63e2c3
NF
4395 tcg_gen_andi_tl(t0, t0, 0x3f);
4396 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
ea63e2c3
NF
4397 break;
4398 case OPC_DROTRV:
4399 tcg_gen_andi_tl(t0, t0, 0x3f);
4400 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
6af0bf9c 4401 break;
7a387fff 4402#endif
6af0bf9c 4403 }
78723684
TS
4404 tcg_temp_free(t0);
4405 tcg_temp_free(t1);
6af0bf9c
FB
4406}
4407
86efbfb6
FN
4408/* Copy GPR to and from TX79 HI1/LO1 register. */
4409static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4410{
baa609db 4411 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
86efbfb6
FN
4412 /* Treat as NOP. */
4413 return;
4414 }
4415
4416 switch (opc) {
baa609db 4417 case MMI_OPC_MFHI1:
86efbfb6
FN
4418 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4419 break;
baa609db 4420 case MMI_OPC_MFLO1:
86efbfb6
FN
4421 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4422 break;
baa609db 4423 case MMI_OPC_MTHI1:
86efbfb6
FN
4424 if (reg != 0) {
4425 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4426 } else {
4427 tcg_gen_movi_tl(cpu_HI[1], 0);
4428 }
4429 break;
baa609db 4430 case MMI_OPC_MTLO1:
86efbfb6
FN
4431 if (reg != 0) {
4432 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4433 } else {
4434 tcg_gen_movi_tl(cpu_LO[1], 0);
4435 }
4436 break;
4437 default:
4438 MIPS_INVAL("mfthilo1 TX79");
4439 generate_exception_end(ctx, EXCP_RI);
4440 break;
4441 }
4442}
4443
6af0bf9c 4444/* Arithmetic on HI/LO registers */
26135ead 4445static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
6af0bf9c 4446{
86efbfb6 4447 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 4448 /* Treat as NOP. */
a1f6684d 4449 return;
6af0bf9c 4450 }
4133498f 4451
4133498f 4452 if (acc != 0) {
86efbfb6 4453 check_dsp(ctx);
4133498f
JL
4454 }
4455
6af0bf9c
FB
4456 switch (opc) {
4457 case OPC_MFHI:
4133498f
JL
4458#if defined(TARGET_MIPS64)
4459 if (acc != 0) {
4460 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4461 } else
4462#endif
4463 {
4464 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4465 }
6af0bf9c
FB
4466 break;
4467 case OPC_MFLO:
4133498f
JL
4468#if defined(TARGET_MIPS64)
4469 if (acc != 0) {
4470 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4471 } else
4472#endif
4473 {
4474 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4475 }
6af0bf9c
FB
4476 break;
4477 case OPC_MTHI:
4133498f
JL
4478 if (reg != 0) {
4479#if defined(TARGET_MIPS64)
4480 if (acc != 0) {
4481 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4482 } else
4483#endif
4484 {
4485 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4486 }
4487 } else {
4488 tcg_gen_movi_tl(cpu_HI[acc], 0);
4489 }
6af0bf9c
FB
4490 break;
4491 case OPC_MTLO:
4133498f
JL
4492 if (reg != 0) {
4493#if defined(TARGET_MIPS64)
4494 if (acc != 0) {
4495 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4496 } else
4497#endif
4498 {
4499 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4500 }
4501 } else {
4502 tcg_gen_movi_tl(cpu_LO[acc], 0);
4503 }
6af0bf9c 4504 break;
6af0bf9c 4505 }
6af0bf9c
FB
4506}
4507
d4ea6acd
LA
4508static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4509 TCGMemOp memop)
4510{
4511 TCGv t0 = tcg_const_tl(addr);
4512 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4513 gen_store_gpr(t0, reg);
4514 tcg_temp_free(t0);
4515}
4516
ab39ee45
YK
4517static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4518 int rs)
d4ea6acd
LA
4519{
4520 target_long offset;
4521 target_long addr;
4522
ab39ee45 4523 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
d4ea6acd
LA
4524 case OPC_ADDIUPC:
4525 if (rs != 0) {
4526 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4527 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4528 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4529 }
4530 break;
4531 case R6_OPC_LWPC:
4532 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4533 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4534 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4535 break;
4536#if defined(TARGET_MIPS64)
4537 case OPC_LWUPC:
4538 check_mips_64(ctx);
4539 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4540 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4541 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4542 break;
4543#endif
4544 default:
ab39ee45 4545 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
d4ea6acd
LA
4546 case OPC_AUIPC:
4547 if (rs != 0) {
ab39ee45
YK
4548 offset = sextract32(ctx->opcode, 0, 16) << 16;
4549 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4550 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4551 }
4552 break;
4553 case OPC_ALUIPC:
4554 if (rs != 0) {
ab39ee45
YK
4555 offset = sextract32(ctx->opcode, 0, 16) << 16;
4556 addr = ~0xFFFF & addr_add(ctx, pc, offset);
d4ea6acd
LA
4557 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4558 }
4559 break;
4560#if defined(TARGET_MIPS64)
4561 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4562 case R6_OPC_LDPC + (1 << 16):
4563 case R6_OPC_LDPC + (2 << 16):
4564 case R6_OPC_LDPC + (3 << 16):
4565 check_mips_64(ctx);
4566 offset = sextract32(ctx->opcode << 3, 0, 21);
ab39ee45 4567 addr = addr_add(ctx, (pc & ~0x7), offset);
d4ea6acd
LA
4568 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4569 break;
4570#endif
4571 default:
4572 MIPS_INVAL("OPC_PCREL");
9c708c7f 4573 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
4574 break;
4575 }
4576 break;
4577 }
4578}
4579
b42ee5e1
LA
4580static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4581{
b42ee5e1
LA
4582 TCGv t0, t1;
4583
4584 if (rd == 0) {
4585 /* Treat as NOP. */
b42ee5e1
LA
4586 return;
4587 }
4588
4589 t0 = tcg_temp_new();
4590 t1 = tcg_temp_new();
4591
4592 gen_load_gpr(t0, rs);
4593 gen_load_gpr(t1, rt);
4594
4595 switch (opc) {
4596 case R6_OPC_DIV:
4597 {
4598 TCGv t2 = tcg_temp_new();
4599 TCGv t3 = tcg_temp_new();
4600 tcg_gen_ext32s_tl(t0, t0);
4601 tcg_gen_ext32s_tl(t1, t1);
4602 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4603 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4604 tcg_gen_and_tl(t2, t2, t3);
4605 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4606 tcg_gen_or_tl(t2, t2, t3);
4607 tcg_gen_movi_tl(t3, 0);
4608 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4609 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4610 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4611 tcg_temp_free(t3);
4612 tcg_temp_free(t2);
4613 }
b42ee5e1
LA
4614 break;
4615 case R6_OPC_MOD:
4616 {
4617 TCGv t2 = tcg_temp_new();
4618 TCGv t3 = tcg_temp_new();
4619 tcg_gen_ext32s_tl(t0, t0);
4620 tcg_gen_ext32s_tl(t1, t1);
4621 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4622 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4623 tcg_gen_and_tl(t2, t2, t3);
4624 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4625 tcg_gen_or_tl(t2, t2, t3);
4626 tcg_gen_movi_tl(t3, 0);
4627 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4628 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4629 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4630 tcg_temp_free(t3);
4631 tcg_temp_free(t2);
4632 }
b42ee5e1
LA
4633 break;
4634 case R6_OPC_DIVU:
4635 {
4636 TCGv t2 = tcg_const_tl(0);
4637 TCGv t3 = tcg_const_tl(1);
4638 tcg_gen_ext32u_tl(t0, t0);
4639 tcg_gen_ext32u_tl(t1, t1);
4640 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4641 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4642 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4643 tcg_temp_free(t3);
4644 tcg_temp_free(t2);
4645 }
b42ee5e1
LA
4646 break;
4647 case R6_OPC_MODU:
4648 {
4649 TCGv t2 = tcg_const_tl(0);
4650 TCGv t3 = tcg_const_tl(1);
4651 tcg_gen_ext32u_tl(t0, t0);
4652 tcg_gen_ext32u_tl(t1, t1);
4653 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4654 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4655 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4656 tcg_temp_free(t3);
4657 tcg_temp_free(t2);
4658 }
b42ee5e1
LA
4659 break;
4660 case R6_OPC_MUL:
4661 {
4662 TCGv_i32 t2 = tcg_temp_new_i32();
4663 TCGv_i32 t3 = tcg_temp_new_i32();
4664 tcg_gen_trunc_tl_i32(t2, t0);
4665 tcg_gen_trunc_tl_i32(t3, t1);
4666 tcg_gen_mul_i32(t2, t2, t3);
4667 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4668 tcg_temp_free_i32(t2);
4669 tcg_temp_free_i32(t3);
4670 }
b42ee5e1
LA
4671 break;
4672 case R6_OPC_MUH:
4673 {
4674 TCGv_i32 t2 = tcg_temp_new_i32();
4675 TCGv_i32 t3 = tcg_temp_new_i32();
4676 tcg_gen_trunc_tl_i32(t2, t0);
4677 tcg_gen_trunc_tl_i32(t3, t1);
4678 tcg_gen_muls2_i32(t2, t3, t2, t3);
4679 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4680 tcg_temp_free_i32(t2);
4681 tcg_temp_free_i32(t3);
4682 }
b42ee5e1
LA
4683 break;
4684 case R6_OPC_MULU:
4685 {
4686 TCGv_i32 t2 = tcg_temp_new_i32();
4687 TCGv_i32 t3 = tcg_temp_new_i32();
4688 tcg_gen_trunc_tl_i32(t2, t0);
4689 tcg_gen_trunc_tl_i32(t3, t1);
4690 tcg_gen_mul_i32(t2, t2, t3);
4691 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4692 tcg_temp_free_i32(t2);
4693 tcg_temp_free_i32(t3);
4694 }
b42ee5e1
LA
4695 break;
4696 case R6_OPC_MUHU:
4697 {
4698 TCGv_i32 t2 = tcg_temp_new_i32();
4699 TCGv_i32 t3 = tcg_temp_new_i32();
4700 tcg_gen_trunc_tl_i32(t2, t0);
4701 tcg_gen_trunc_tl_i32(t3, t1);
4702 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4703 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4704 tcg_temp_free_i32(t2);
4705 tcg_temp_free_i32(t3);
4706 }
b42ee5e1
LA
4707 break;
4708#if defined(TARGET_MIPS64)
4709 case R6_OPC_DDIV:
4710 {
4711 TCGv t2 = tcg_temp_new();
4712 TCGv t3 = tcg_temp_new();
4713 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4714 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4715 tcg_gen_and_tl(t2, t2, t3);
4716 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4717 tcg_gen_or_tl(t2, t2, t3);
4718 tcg_gen_movi_tl(t3, 0);
4719 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4720 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4721 tcg_temp_free(t3);
4722 tcg_temp_free(t2);
4723 }
b42ee5e1
LA
4724 break;
4725 case R6_OPC_DMOD:
4726 {
4727 TCGv t2 = tcg_temp_new();
4728 TCGv t3 = tcg_temp_new();
4729 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4730 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4731 tcg_gen_and_tl(t2, t2, t3);
4732 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4733 tcg_gen_or_tl(t2, t2, t3);
4734 tcg_gen_movi_tl(t3, 0);
4735 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4736 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4737 tcg_temp_free(t3);
4738 tcg_temp_free(t2);
4739 }
b42ee5e1
LA
4740 break;
4741 case R6_OPC_DDIVU:
4742 {
4743 TCGv t2 = tcg_const_tl(0);
4744 TCGv t3 = tcg_const_tl(1);
4745 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4746 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4747 tcg_temp_free(t3);
4748 tcg_temp_free(t2);
4749 }
b42ee5e1
LA
4750 break;
4751 case R6_OPC_DMODU:
4752 {
4753 TCGv t2 = tcg_const_tl(0);
4754 TCGv t3 = tcg_const_tl(1);
4755 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4756 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4757 tcg_temp_free(t3);
4758 tcg_temp_free(t2);
4759 }
b42ee5e1
LA
4760 break;
4761 case R6_OPC_DMUL:
4762 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
4763 break;
4764 case R6_OPC_DMUH:
4765 {
4766 TCGv t2 = tcg_temp_new();
4767 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4768 tcg_temp_free(t2);
4769 }
b42ee5e1
LA
4770 break;
4771 case R6_OPC_DMULU:
4772 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
4773 break;
4774 case R6_OPC_DMUHU:
4775 {
4776 TCGv t2 = tcg_temp_new();
4777 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4778 tcg_temp_free(t2);
4779 }
b42ee5e1
LA
4780 break;
4781#endif
4782 default:
9d68ac14 4783 MIPS_INVAL("r6 mul/div");
9c708c7f 4784 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
4785 goto out;
4786 }
b42ee5e1
LA
4787 out:
4788 tcg_temp_free(t0);
4789 tcg_temp_free(t1);
4790}
4791
c42171c3
FN
4792static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4793{
4794 TCGv t0, t1;
4795
4796 t0 = tcg_temp_new();
4797 t1 = tcg_temp_new();
4798
4799 gen_load_gpr(t0, rs);
4800 gen_load_gpr(t1, rt);
4801
4802 switch (opc) {
baa609db 4803 case MMI_OPC_DIV1:
c42171c3
FN
4804 {
4805 TCGv t2 = tcg_temp_new();
4806 TCGv t3 = tcg_temp_new();
4807 tcg_gen_ext32s_tl(t0, t0);
4808 tcg_gen_ext32s_tl(t1, t1);
4809 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4810 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4811 tcg_gen_and_tl(t2, t2, t3);
4812 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4813 tcg_gen_or_tl(t2, t2, t3);
4814 tcg_gen_movi_tl(t3, 0);
4815 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4816 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4817 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4818 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4819 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4820 tcg_temp_free(t3);
4821 tcg_temp_free(t2);
4822 }
4823 break;
baa609db 4824 case MMI_OPC_DIVU1:
c42171c3
FN
4825 {
4826 TCGv t2 = tcg_const_tl(0);
4827 TCGv t3 = tcg_const_tl(1);
4828 tcg_gen_ext32u_tl(t0, t0);
4829 tcg_gen_ext32u_tl(t1, t1);
4830 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4831 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4832 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4833 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4834 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4835 tcg_temp_free(t3);
4836 tcg_temp_free(t2);
4837 }
4838 break;
4839 default:
4840 MIPS_INVAL("div1 TX79");
4841 generate_exception_end(ctx, EXCP_RI);
4842 goto out;
4843 }
4844 out:
4845 tcg_temp_free(t0);
4846 tcg_temp_free(t1);
4847}
4848
26135ead
RS
4849static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4850 int acc, int rs, int rt)
6af0bf9c 4851{
d45f89f4
AJ
4852 TCGv t0, t1;
4853
51127181
AJ
4854 t0 = tcg_temp_new();
4855 t1 = tcg_temp_new();
6af0bf9c 4856
78723684
TS
4857 gen_load_gpr(t0, rs);
4858 gen_load_gpr(t1, rt);
51127181 4859
26135ead 4860 if (acc != 0) {
c42171c3 4861 check_dsp(ctx);
26135ead
RS
4862 }
4863
6af0bf9c
FB
4864 switch (opc) {
4865 case OPC_DIV:
48d38ca5 4866 {
51127181
AJ
4867 TCGv t2 = tcg_temp_new();
4868 TCGv t3 = tcg_temp_new();
d45f89f4
AJ
4869 tcg_gen_ext32s_tl(t0, t0);
4870 tcg_gen_ext32s_tl(t1, t1);
51127181
AJ
4871 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4872 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4873 tcg_gen_and_tl(t2, t2, t3);
4874 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4875 tcg_gen_or_tl(t2, t2, t3);
4876 tcg_gen_movi_tl(t3, 0);
4877 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
4878 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4879 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4880 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4881 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
4882 tcg_temp_free(t3);
4883 tcg_temp_free(t2);
48d38ca5 4884 }
6af0bf9c
FB
4885 break;
4886 case OPC_DIVU:
48d38ca5 4887 {
51127181
AJ
4888 TCGv t2 = tcg_const_tl(0);
4889 TCGv t3 = tcg_const_tl(1);
0c0ed03b
AJ
4890 tcg_gen_ext32u_tl(t0, t0);
4891 tcg_gen_ext32u_tl(t1, t1);
51127181 4892 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
4893 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4894 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4895 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4896 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
4897 tcg_temp_free(t3);
4898 tcg_temp_free(t2);
48d38ca5 4899 }
6af0bf9c
FB
4900 break;
4901 case OPC_MULT:
214c465f 4902 {
ce1dd5d1
RH
4903 TCGv_i32 t2 = tcg_temp_new_i32();
4904 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
4905 tcg_gen_trunc_tl_i32(t2, t0);
4906 tcg_gen_trunc_tl_i32(t3, t1);
4907 tcg_gen_muls2_i32(t2, t3, t2, t3);
4908 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4909 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4910 tcg_temp_free_i32(t2);
4911 tcg_temp_free_i32(t3);
214c465f 4912 }
6af0bf9c
FB
4913 break;
4914 case OPC_MULTU:
214c465f 4915 {
ce1dd5d1
RH
4916 TCGv_i32 t2 = tcg_temp_new_i32();
4917 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
4918 tcg_gen_trunc_tl_i32(t2, t0);
4919 tcg_gen_trunc_tl_i32(t3, t1);
4920 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4921 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4922 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4923 tcg_temp_free_i32(t2);
4924 tcg_temp_free_i32(t3);
214c465f 4925 }
6af0bf9c 4926 break;
d26bc211 4927#if defined(TARGET_MIPS64)
7a387fff 4928 case OPC_DDIV:
48d38ca5 4929 {
51127181
AJ
4930 TCGv t2 = tcg_temp_new();
4931 TCGv t3 = tcg_temp_new();
4932 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4933 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4934 tcg_gen_and_tl(t2, t2, t3);
4935 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4936 tcg_gen_or_tl(t2, t2, t3);
4937 tcg_gen_movi_tl(t3, 0);
4938 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
4939 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4940 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
51127181
AJ
4941 tcg_temp_free(t3);
4942 tcg_temp_free(t2);
48d38ca5 4943 }
7a387fff
TS
4944 break;
4945 case OPC_DDIVU:
48d38ca5 4946 {
51127181
AJ
4947 TCGv t2 = tcg_const_tl(0);
4948 TCGv t3 = tcg_const_tl(1);
4949 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
4950 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4951 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
51127181
AJ
4952 tcg_temp_free(t3);
4953 tcg_temp_free(t2);
48d38ca5 4954 }
7a387fff
TS
4955 break;
4956 case OPC_DMULT:
26135ead 4957 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
4958 break;
4959 case OPC_DMULTU:
26135ead 4960 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
4961 break;
4962#endif
6af0bf9c 4963 case OPC_MADD:
214c465f 4964 {
d45f89f4
AJ
4965 TCGv_i64 t2 = tcg_temp_new_i64();
4966 TCGv_i64 t3 = tcg_temp_new_i64();
4967
4968 tcg_gen_ext_tl_i64(t2, t0);
4969 tcg_gen_ext_tl_i64(t3, t1);
4970 tcg_gen_mul_i64(t2, t2, t3);
4133498f 4971 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
4972 tcg_gen_add_i64(t2, t2, t3);
4973 tcg_temp_free_i64(t3);
71f303cd
RH
4974 gen_move_low32(cpu_LO[acc], t2);
4975 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 4976 tcg_temp_free_i64(t2);
214c465f 4977 }
6af0bf9c
FB
4978 break;
4979 case OPC_MADDU:
4133498f 4980 {
d45f89f4
AJ
4981 TCGv_i64 t2 = tcg_temp_new_i64();
4982 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 4983
78723684
TS
4984 tcg_gen_ext32u_tl(t0, t0);
4985 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
4986 tcg_gen_extu_tl_i64(t2, t0);
4987 tcg_gen_extu_tl_i64(t3, t1);
4988 tcg_gen_mul_i64(t2, t2, t3);
4133498f 4989 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
4990 tcg_gen_add_i64(t2, t2, t3);
4991 tcg_temp_free_i64(t3);
71f303cd
RH
4992 gen_move_low32(cpu_LO[acc], t2);
4993 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 4994 tcg_temp_free_i64(t2);
214c465f 4995 }
6af0bf9c
FB
4996 break;
4997 case OPC_MSUB:
214c465f 4998 {
d45f89f4
AJ
4999 TCGv_i64 t2 = tcg_temp_new_i64();
5000 TCGv_i64 t3 = tcg_temp_new_i64();
5001
5002 tcg_gen_ext_tl_i64(t2, t0);
5003 tcg_gen_ext_tl_i64(t3, t1);
5004 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5005 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 5006 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 5007 tcg_temp_free_i64(t3);
71f303cd
RH
5008 gen_move_low32(cpu_LO[acc], t2);
5009 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5010 tcg_temp_free_i64(t2);
214c465f 5011 }
6af0bf9c
FB
5012 break;
5013 case OPC_MSUBU:
214c465f 5014 {
d45f89f4
AJ
5015 TCGv_i64 t2 = tcg_temp_new_i64();
5016 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 5017
78723684
TS
5018 tcg_gen_ext32u_tl(t0, t0);
5019 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
5020 tcg_gen_extu_tl_i64(t2, t0);
5021 tcg_gen_extu_tl_i64(t3, t1);
5022 tcg_gen_mul_i64(t2, t2, t3);
4133498f 5023 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 5024 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 5025 tcg_temp_free_i64(t3);
71f303cd
RH
5026 gen_move_low32(cpu_LO[acc], t2);
5027 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 5028 tcg_temp_free_i64(t2);
214c465f 5029 }
6af0bf9c
FB
5030 break;
5031 default:
9d68ac14 5032 MIPS_INVAL("mul/div");
9c708c7f 5033 generate_exception_end(ctx, EXCP_RI);
78723684 5034 goto out;
6af0bf9c 5035 }
78723684
TS
5036 out:
5037 tcg_temp_free(t0);
5038 tcg_temp_free(t1);
6af0bf9c
FB
5039}
5040
21e8e8b2 5041/*
3b948f05
PMD
5042 * These MULT[U] and MADD[U] instructions implemented in for example
5043 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
21e8e8b2
FN
5044 * architectures are special three-operand variants with the syntax
5045 *
06de726b 5046 * MULT[U][1] rd, rs, rt
21e8e8b2
FN
5047 *
5048 * such that
5049 *
5050 * (rd, LO, HI) <- rs * rt
5051 *
3b948f05
PMD
5052 * and
5053 *
a95c4c26 5054 * MADD[U][1] rd, rs, rt
3b948f05
PMD
5055 *
5056 * such that
5057 *
5058 * (rd, LO, HI) <- (LO, HI) + rs * rt
5059 *
21e8e8b2
FN
5060 * where the low-order 32-bits of the result is placed into both the
5061 * GPR rd and the special register LO. The high-order 32-bits of the
5062 * result is placed into the special register HI.
5063 *
5064 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5065 * which is the zero register that always reads as 0.
5066 */
5067static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5068 int rd, int rs, int rt)
5069{
5070 TCGv t0 = tcg_temp_new();
5071 TCGv t1 = tcg_temp_new();
5072 int acc = 0;
5073
5074 gen_load_gpr(t0, rs);
5075 gen_load_gpr(t1, rt);
5076
5077 switch (opc) {
baa609db 5078 case MMI_OPC_MULT1:
06de726b
FN
5079 acc = 1;
5080 /* Fall through */
21e8e8b2
FN
5081 case OPC_MULT:
5082 {
5083 TCGv_i32 t2 = tcg_temp_new_i32();
5084 TCGv_i32 t3 = tcg_temp_new_i32();
5085 tcg_gen_trunc_tl_i32(t2, t0);
5086 tcg_gen_trunc_tl_i32(t3, t1);
5087 tcg_gen_muls2_i32(t2, t3, t2, t3);
5088 if (rd) {
5089 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5090 }
5091 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5092 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5093 tcg_temp_free_i32(t2);
5094 tcg_temp_free_i32(t3);
5095 }
5096 break;
baa609db 5097 case MMI_OPC_MULTU1:
06de726b
FN
5098 acc = 1;
5099 /* Fall through */
21e8e8b2
FN
5100 case OPC_MULTU:
5101 {
5102 TCGv_i32 t2 = tcg_temp_new_i32();
5103 TCGv_i32 t3 = tcg_temp_new_i32();
5104 tcg_gen_trunc_tl_i32(t2, t0);
5105 tcg_gen_trunc_tl_i32(t3, t1);
5106 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5107 if (rd) {
5108 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5109 }
5110 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5111 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5112 tcg_temp_free_i32(t2);
5113 tcg_temp_free_i32(t3);
5114 }
5115 break;
a95c4c26
FN
5116 case MMI_OPC_MADD1:
5117 acc = 1;
5118 /* Fall through */
3b948f05
PMD
5119 case MMI_OPC_MADD:
5120 {
5121 TCGv_i64 t2 = tcg_temp_new_i64();
5122 TCGv_i64 t3 = tcg_temp_new_i64();
5123
5124 tcg_gen_ext_tl_i64(t2, t0);
5125 tcg_gen_ext_tl_i64(t3, t1);
5126 tcg_gen_mul_i64(t2, t2, t3);
5127 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5128 tcg_gen_add_i64(t2, t2, t3);
5129 tcg_temp_free_i64(t3);
5130 gen_move_low32(cpu_LO[acc], t2);
5131 gen_move_high32(cpu_HI[acc], t2);
5132 if (rd) {
5133 gen_move_low32(cpu_gpr[rd], t2);
5134 }
5135 tcg_temp_free_i64(t2);
5136 }
5137 break;
a95c4c26
FN
5138 case MMI_OPC_MADDU1:
5139 acc = 1;
5140 /* Fall through */
3b948f05
PMD
5141 case MMI_OPC_MADDU:
5142 {
5143 TCGv_i64 t2 = tcg_temp_new_i64();
5144 TCGv_i64 t3 = tcg_temp_new_i64();
5145
5146 tcg_gen_ext32u_tl(t0, t0);
5147 tcg_gen_ext32u_tl(t1, t1);
5148 tcg_gen_extu_tl_i64(t2, t0);
5149 tcg_gen_extu_tl_i64(t3, t1);
5150 tcg_gen_mul_i64(t2, t2, t3);
5151 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5152 tcg_gen_add_i64(t2, t2, t3);
5153 tcg_temp_free_i64(t3);
5154 gen_move_low32(cpu_LO[acc], t2);
5155 gen_move_high32(cpu_HI[acc], t2);
5156 if (rd) {
5157 gen_move_low32(cpu_gpr[rd], t2);
5158 }
5159 tcg_temp_free_i64(t2);
5160 }
5161 break;
21e8e8b2 5162 default:
3b948f05 5163 MIPS_INVAL("mul/madd TXx9");
21e8e8b2
FN
5164 generate_exception_end(ctx, EXCP_RI);
5165 goto out;
5166 }
5167
5168 out:
5169 tcg_temp_free(t0);
5170 tcg_temp_free(t1);
5171}
5172
e9c71dd1
TS
5173static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
5174 int rd, int rs, int rt)
5175{
f157bfe1
AJ
5176 TCGv t0 = tcg_temp_new();
5177 TCGv t1 = tcg_temp_new();
e9c71dd1 5178
6c5c1e20
TS
5179 gen_load_gpr(t0, rs);
5180 gen_load_gpr(t1, rt);
e9c71dd1
TS
5181
5182 switch (opc) {
5183 case OPC_VR54XX_MULS:
895c2d04 5184 gen_helper_muls(t0, cpu_env, t0, t1);
6958549d 5185 break;
e9c71dd1 5186 case OPC_VR54XX_MULSU:
895c2d04 5187 gen_helper_mulsu(t0, cpu_env, t0, t1);
6958549d 5188 break;
e9c71dd1 5189 case OPC_VR54XX_MACC:
895c2d04 5190 gen_helper_macc(t0, cpu_env, t0, t1);
6958549d 5191 break;
e9c71dd1 5192 case OPC_VR54XX_MACCU:
895c2d04 5193 gen_helper_maccu(t0, cpu_env, t0, t1);
6958549d 5194 break;
e9c71dd1 5195 case OPC_VR54XX_MSAC:
895c2d04 5196 gen_helper_msac(t0, cpu_env, t0, t1);
6958549d 5197 break;
e9c71dd1 5198 case OPC_VR54XX_MSACU:
895c2d04 5199 gen_helper_msacu(t0, cpu_env, t0, t1);
6958549d 5200 break;
e9c71dd1 5201 case OPC_VR54XX_MULHI:
895c2d04 5202 gen_helper_mulhi(t0, cpu_env, t0, t1);
6958549d 5203 break;
e9c71dd1 5204 case OPC_VR54XX_MULHIU:
895c2d04 5205 gen_helper_mulhiu(t0, cpu_env, t0, t1);
6958549d 5206 break;
e9c71dd1 5207 case OPC_VR54XX_MULSHI:
895c2d04 5208 gen_helper_mulshi(t0, cpu_env, t0, t1);
6958549d 5209 break;
e9c71dd1 5210 case OPC_VR54XX_MULSHIU:
895c2d04 5211 gen_helper_mulshiu(t0, cpu_env, t0, t1);
6958549d 5212 break;
e9c71dd1 5213 case OPC_VR54XX_MACCHI:
895c2d04 5214 gen_helper_macchi(t0, cpu_env, t0, t1);
6958549d 5215 break;
e9c71dd1 5216 case OPC_VR54XX_MACCHIU:
895c2d04 5217 gen_helper_macchiu(t0, cpu_env, t0, t1);
6958549d 5218 break;
e9c71dd1 5219 case OPC_VR54XX_MSACHI:
895c2d04 5220 gen_helper_msachi(t0, cpu_env, t0, t1);
6958549d 5221 break;
e9c71dd1 5222 case OPC_VR54XX_MSACHIU:
895c2d04 5223 gen_helper_msachiu(t0, cpu_env, t0, t1);
6958549d 5224 break;
e9c71dd1
TS
5225 default:
5226 MIPS_INVAL("mul vr54xx");
9c708c7f 5227 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5228 goto out;
e9c71dd1 5229 }
6c5c1e20 5230 gen_store_gpr(t0, rd);
6c5c1e20
TS
5231
5232 out:
5233 tcg_temp_free(t0);
5234 tcg_temp_free(t1);
e9c71dd1
TS
5235}
5236
7a387fff 5237static void gen_cl (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
5238 int rd, int rs)
5239{
20e1fb52 5240 TCGv t0;
6c5c1e20 5241
6af0bf9c 5242 if (rd == 0) {
ead9360e 5243 /* Treat as NOP. */
20e1fb52 5244 return;
6af0bf9c 5245 }
1a0196c5 5246 t0 = cpu_gpr[rd];
6c5c1e20 5247 gen_load_gpr(t0, rs);
1a0196c5 5248
6af0bf9c
FB
5249 switch (opc) {
5250 case OPC_CLO:
4267d3e6 5251 case R6_OPC_CLO:
1a0196c5
RH
5252#if defined(TARGET_MIPS64)
5253 case OPC_DCLO:
5254 case R6_OPC_DCLO:
5255#endif
5256 tcg_gen_not_tl(t0, t0);
6af0bf9c 5257 break;
1a0196c5
RH
5258 }
5259
5260 switch (opc) {
5261 case OPC_CLO:
5262 case R6_OPC_CLO:
6af0bf9c 5263 case OPC_CLZ:
4267d3e6 5264 case R6_OPC_CLZ:
1a0196c5
RH
5265 tcg_gen_ext32u_tl(t0, t0);
5266 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5267 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
6af0bf9c 5268 break;
d26bc211 5269#if defined(TARGET_MIPS64)
7a387fff 5270 case OPC_DCLO:
4267d3e6 5271 case R6_OPC_DCLO:
7a387fff 5272 case OPC_DCLZ:
4267d3e6 5273 case R6_OPC_DCLZ:
1a0196c5 5274 tcg_gen_clzi_i64(t0, t0, 64);
7a387fff
TS
5275 break;
5276#endif
6af0bf9c 5277 }
6af0bf9c
FB
5278}
5279
161f85e6 5280/* Godson integer instructions */
bd277fa1
RH
5281static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5282 int rd, int rs, int rt)
161f85e6 5283{
161f85e6
AJ
5284 TCGv t0, t1;
5285
5286 if (rd == 0) {
5287 /* Treat as NOP. */
161f85e6
AJ
5288 return;
5289 }
5290
5291 switch (opc) {
5292 case OPC_MULT_G_2E:
5293 case OPC_MULT_G_2F:
5294 case OPC_MULTU_G_2E:
5295 case OPC_MULTU_G_2F:
5296#if defined(TARGET_MIPS64)
5297 case OPC_DMULT_G_2E:
5298 case OPC_DMULT_G_2F:
5299 case OPC_DMULTU_G_2E:
5300 case OPC_DMULTU_G_2F:
5301#endif
5302 t0 = tcg_temp_new();
5303 t1 = tcg_temp_new();
5304 break;
5305 default:
5306 t0 = tcg_temp_local_new();
5307 t1 = tcg_temp_local_new();
5308 break;
5309 }
5310
5311 gen_load_gpr(t0, rs);
5312 gen_load_gpr(t1, rt);
5313
5314 switch (opc) {
5315 case OPC_MULT_G_2E:
5316 case OPC_MULT_G_2F:
5317 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5318 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
5319 break;
5320 case OPC_MULTU_G_2E:
5321 case OPC_MULTU_G_2F:
5322 tcg_gen_ext32u_tl(t0, t0);
5323 tcg_gen_ext32u_tl(t1, t1);
5324 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5325 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
5326 break;
5327 case OPC_DIV_G_2E:
5328 case OPC_DIV_G_2F:
5329 {
42a268c2
RH
5330 TCGLabel *l1 = gen_new_label();
5331 TCGLabel *l2 = gen_new_label();
5332 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5333 tcg_gen_ext32s_tl(t0, t0);
5334 tcg_gen_ext32s_tl(t1, t1);
5335 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5336 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5337 tcg_gen_br(l3);
5338 gen_set_label(l1);
5339 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5340 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5341 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5342 tcg_gen_br(l3);
5343 gen_set_label(l2);
5344 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5345 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5346 gen_set_label(l3);
5347 }
161f85e6
AJ
5348 break;
5349 case OPC_DIVU_G_2E:
5350 case OPC_DIVU_G_2F:
5351 {
42a268c2
RH
5352 TCGLabel *l1 = gen_new_label();
5353 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5354 tcg_gen_ext32u_tl(t0, t0);
5355 tcg_gen_ext32u_tl(t1, t1);
5356 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5357 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5358 tcg_gen_br(l2);
5359 gen_set_label(l1);
5360 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5361 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5362 gen_set_label(l2);
5363 }
161f85e6
AJ
5364 break;
5365 case OPC_MOD_G_2E:
5366 case OPC_MOD_G_2F:
5367 {
42a268c2
RH
5368 TCGLabel *l1 = gen_new_label();
5369 TCGLabel *l2 = gen_new_label();
5370 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5371 tcg_gen_ext32u_tl(t0, t0);
5372 tcg_gen_ext32u_tl(t1, t1);
5373 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5374 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5375 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5376 gen_set_label(l1);
5377 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5378 tcg_gen_br(l3);
5379 gen_set_label(l2);
5380 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5381 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5382 gen_set_label(l3);
5383 }
161f85e6
AJ
5384 break;
5385 case OPC_MODU_G_2E:
5386 case OPC_MODU_G_2F:
5387 {
42a268c2
RH
5388 TCGLabel *l1 = gen_new_label();
5389 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5390 tcg_gen_ext32u_tl(t0, t0);
5391 tcg_gen_ext32u_tl(t1, t1);
5392 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5393 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5394 tcg_gen_br(l2);
5395 gen_set_label(l1);
5396 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5397 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5398 gen_set_label(l2);
5399 }
161f85e6
AJ
5400 break;
5401#if defined(TARGET_MIPS64)
5402 case OPC_DMULT_G_2E:
5403 case OPC_DMULT_G_2F:
5404 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
5405 break;
5406 case OPC_DMULTU_G_2E:
5407 case OPC_DMULTU_G_2F:
5408 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
5409 break;
5410 case OPC_DDIV_G_2E:
5411 case OPC_DDIV_G_2F:
5412 {
42a268c2
RH
5413 TCGLabel *l1 = gen_new_label();
5414 TCGLabel *l2 = gen_new_label();
5415 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5416 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5417 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5418 tcg_gen_br(l3);
5419 gen_set_label(l1);
5420 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5421 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5422 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5423 tcg_gen_br(l3);
5424 gen_set_label(l2);
5425 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5426 gen_set_label(l3);
5427 }
161f85e6
AJ
5428 break;
5429 case OPC_DDIVU_G_2E:
5430 case OPC_DDIVU_G_2F:
5431 {
42a268c2
RH
5432 TCGLabel *l1 = gen_new_label();
5433 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5434 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5435 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5436 tcg_gen_br(l2);
5437 gen_set_label(l1);
5438 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5439 gen_set_label(l2);
5440 }
161f85e6
AJ
5441 break;
5442 case OPC_DMOD_G_2E:
5443 case OPC_DMOD_G_2F:
5444 {
42a268c2
RH
5445 TCGLabel *l1 = gen_new_label();
5446 TCGLabel *l2 = gen_new_label();
5447 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5448 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5449 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5450 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5451 gen_set_label(l1);
5452 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5453 tcg_gen_br(l3);
5454 gen_set_label(l2);
5455 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5456 gen_set_label(l3);
5457 }
161f85e6
AJ
5458 break;
5459 case OPC_DMODU_G_2E:
5460 case OPC_DMODU_G_2F:
5461 {
42a268c2
RH
5462 TCGLabel *l1 = gen_new_label();
5463 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5464 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5465 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5466 tcg_gen_br(l2);
5467 gen_set_label(l1);
5468 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5469 gen_set_label(l2);
5470 }
161f85e6
AJ
5471 break;
5472#endif
5473 }
5474
161f85e6
AJ
5475 tcg_temp_free(t0);
5476 tcg_temp_free(t1);
5477}
5478
bd277fa1
RH
5479/* Loongson multimedia instructions */
5480static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5481{
bd277fa1
RH
5482 uint32_t opc, shift_max;
5483 TCGv_i64 t0, t1;
5484
5485 opc = MASK_LMI(ctx->opcode);
5486 switch (opc) {
5487 case OPC_ADD_CP2:
5488 case OPC_SUB_CP2:
5489 case OPC_DADD_CP2:
5490 case OPC_DSUB_CP2:
5491 t0 = tcg_temp_local_new_i64();
5492 t1 = tcg_temp_local_new_i64();
5493 break;
5494 default:
5495 t0 = tcg_temp_new_i64();
5496 t1 = tcg_temp_new_i64();
5497 break;
5498 }
5499
b5a587b6 5500 check_cp1_enabled(ctx);
bd277fa1
RH
5501 gen_load_fpr64(ctx, t0, rs);
5502 gen_load_fpr64(ctx, t1, rt);
5503
5504#define LMI_HELPER(UP, LO) \
9d68ac14 5505 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
bd277fa1 5506#define LMI_HELPER_1(UP, LO) \
9d68ac14 5507 case OPC_##UP: gen_helper_##LO(t0, t0); break
bd277fa1 5508#define LMI_DIRECT(UP, LO, OP) \
9d68ac14 5509 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
bd277fa1
RH
5510
5511 switch (opc) {
5512 LMI_HELPER(PADDSH, paddsh);
5513 LMI_HELPER(PADDUSH, paddush);
5514 LMI_HELPER(PADDH, paddh);
5515 LMI_HELPER(PADDW, paddw);
5516 LMI_HELPER(PADDSB, paddsb);
5517 LMI_HELPER(PADDUSB, paddusb);
5518 LMI_HELPER(PADDB, paddb);
5519
5520 LMI_HELPER(PSUBSH, psubsh);
5521 LMI_HELPER(PSUBUSH, psubush);
5522 LMI_HELPER(PSUBH, psubh);
5523 LMI_HELPER(PSUBW, psubw);
5524 LMI_HELPER(PSUBSB, psubsb);
5525 LMI_HELPER(PSUBUSB, psubusb);
5526 LMI_HELPER(PSUBB, psubb);
5527
5528 LMI_HELPER(PSHUFH, pshufh);
5529 LMI_HELPER(PACKSSWH, packsswh);
5530 LMI_HELPER(PACKSSHB, packsshb);
5531 LMI_HELPER(PACKUSHB, packushb);
5532
5533 LMI_HELPER(PUNPCKLHW, punpcklhw);
5534 LMI_HELPER(PUNPCKHHW, punpckhhw);
5535 LMI_HELPER(PUNPCKLBH, punpcklbh);
5536 LMI_HELPER(PUNPCKHBH, punpckhbh);
5537 LMI_HELPER(PUNPCKLWD, punpcklwd);
5538 LMI_HELPER(PUNPCKHWD, punpckhwd);
5539
5540 LMI_HELPER(PAVGH, pavgh);
5541 LMI_HELPER(PAVGB, pavgb);
5542 LMI_HELPER(PMAXSH, pmaxsh);
5543 LMI_HELPER(PMINSH, pminsh);
5544 LMI_HELPER(PMAXUB, pmaxub);
5545 LMI_HELPER(PMINUB, pminub);
5546
5547 LMI_HELPER(PCMPEQW, pcmpeqw);
5548 LMI_HELPER(PCMPGTW, pcmpgtw);
5549 LMI_HELPER(PCMPEQH, pcmpeqh);
5550 LMI_HELPER(PCMPGTH, pcmpgth);
5551 LMI_HELPER(PCMPEQB, pcmpeqb);
5552 LMI_HELPER(PCMPGTB, pcmpgtb);
5553
5554 LMI_HELPER(PSLLW, psllw);
5555 LMI_HELPER(PSLLH, psllh);
5556 LMI_HELPER(PSRLW, psrlw);
5557 LMI_HELPER(PSRLH, psrlh);
5558 LMI_HELPER(PSRAW, psraw);
5559 LMI_HELPER(PSRAH, psrah);
5560
5561 LMI_HELPER(PMULLH, pmullh);
5562 LMI_HELPER(PMULHH, pmulhh);
5563 LMI_HELPER(PMULHUH, pmulhuh);
5564 LMI_HELPER(PMADDHW, pmaddhw);
5565
5566 LMI_HELPER(PASUBUB, pasubub);
5567 LMI_HELPER_1(BIADD, biadd);
5568 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5569
5570 LMI_DIRECT(PADDD, paddd, add);
5571 LMI_DIRECT(PSUBD, psubd, sub);
5572 LMI_DIRECT(XOR_CP2, xor, xor);
5573 LMI_DIRECT(NOR_CP2, nor, nor);
5574 LMI_DIRECT(AND_CP2, and, and);
bb7cab5f 5575 LMI_DIRECT(OR_CP2, or, or);
bd277fa1 5576
9099a36b
H
5577 case OPC_PANDN:
5578 tcg_gen_andc_i64(t0, t1, t0);
5579 break;
5580
bd277fa1
RH
5581 case OPC_PINSRH_0:
5582 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
bd277fa1
RH
5583 break;
5584 case OPC_PINSRH_1:
5585 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
bd277fa1
RH
5586 break;
5587 case OPC_PINSRH_2:
5588 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
bd277fa1
RH
5589 break;
5590 case OPC_PINSRH_3:
5591 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
bd277fa1
RH
5592 break;
5593
5594 case OPC_PEXTRH:
5595 tcg_gen_andi_i64(t1, t1, 3);
5596 tcg_gen_shli_i64(t1, t1, 4);
5597 tcg_gen_shr_i64(t0, t0, t1);
5598 tcg_gen_ext16u_i64(t0, t0);
bd277fa1
RH
5599 break;
5600
5601 case OPC_ADDU_CP2:
5602 tcg_gen_add_i64(t0, t0, t1);
5603 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
5604 break;
5605 case OPC_SUBU_CP2:
5606 tcg_gen_sub_i64(t0, t0, t1);
5607 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
5608 break;
5609
5610 case OPC_SLL_CP2:
bd277fa1
RH
5611 shift_max = 32;
5612 goto do_shift;
5613 case OPC_SRL_CP2:
bd277fa1
RH
5614 shift_max = 32;
5615 goto do_shift;
5616 case OPC_SRA_CP2:
bd277fa1
RH
5617 shift_max = 32;
5618 goto do_shift;
5619 case OPC_DSLL_CP2:
bd277fa1
RH
5620 shift_max = 64;
5621 goto do_shift;
5622 case OPC_DSRL_CP2:
bd277fa1
RH
5623 shift_max = 64;
5624 goto do_shift;
5625 case OPC_DSRA_CP2:
bd277fa1
RH
5626 shift_max = 64;
5627 goto do_shift;
5628 do_shift:
5629 /* Make sure shift count isn't TCG undefined behaviour. */
5630 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5631
5632 switch (opc) {
5633 case OPC_SLL_CP2:
5634 case OPC_DSLL_CP2:
5635 tcg_gen_shl_i64(t0, t0, t1);
5636 break;
5637 case OPC_SRA_CP2:
5638 case OPC_DSRA_CP2:
5639 /* Since SRA is UndefinedResult without sign-extended inputs,
5640 we can treat SRA and DSRA the same. */
5641 tcg_gen_sar_i64(t0, t0, t1);
5642 break;
5643 case OPC_SRL_CP2:
5644 /* We want to shift in zeros for SRL; zero-extend first. */
5645 tcg_gen_ext32u_i64(t0, t0);
5646 /* FALLTHRU */
5647 case OPC_DSRL_CP2:
5648 tcg_gen_shr_i64(t0, t0, t1);
5649 break;
5650 }
5651
5652 if (shift_max == 32) {
5653 tcg_gen_ext32s_i64(t0, t0);
5654 }
5655
5656 /* Shifts larger than MAX produce zero. */
5657 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5658 tcg_gen_neg_i64(t1, t1);
5659 tcg_gen_and_i64(t0, t0, t1);
5660 break;
5661
5662 case OPC_ADD_CP2:
5663 case OPC_DADD_CP2:
5664 {
5665 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 5666 TCGLabel *lab = gen_new_label();
bd277fa1
RH
5667
5668 tcg_gen_mov_i64(t2, t0);
5669 tcg_gen_add_i64(t0, t1, t2);
5670 if (opc == OPC_ADD_CP2) {
5671 tcg_gen_ext32s_i64(t0, t0);
5672 }
5673 tcg_gen_xor_i64(t1, t1, t2);
5674 tcg_gen_xor_i64(t2, t2, t0);
5675 tcg_gen_andc_i64(t1, t2, t1);
5676 tcg_temp_free_i64(t2);
5677 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5678 generate_exception(ctx, EXCP_OVERFLOW);
5679 gen_set_label(lab);
bd277fa1
RH
5680 break;
5681 }
5682
5683 case OPC_SUB_CP2:
5684 case OPC_DSUB_CP2:
5685 {
5686 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 5687 TCGLabel *lab = gen_new_label();
bd277fa1
RH
5688
5689 tcg_gen_mov_i64(t2, t0);
5690 tcg_gen_sub_i64(t0, t1, t2);
5691 if (opc == OPC_SUB_CP2) {
5692 tcg_gen_ext32s_i64(t0, t0);
5693 }
5694 tcg_gen_xor_i64(t1, t1, t2);
5695 tcg_gen_xor_i64(t2, t2, t0);
5696 tcg_gen_and_i64(t1, t1, t2);
5697 tcg_temp_free_i64(t2);
5698 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5699 generate_exception(ctx, EXCP_OVERFLOW);
5700 gen_set_label(lab);
bd277fa1
RH
5701 break;
5702 }
5703
5704 case OPC_PMULUW:
5705 tcg_gen_ext32u_i64(t0, t0);
5706 tcg_gen_ext32u_i64(t1, t1);
5707 tcg_gen_mul_i64(t0, t0, t1);
bd277fa1
RH
5708 break;
5709
5710 case OPC_SEQU_CP2:
5711 case OPC_SEQ_CP2:
5712 case OPC_SLTU_CP2:
5713 case OPC_SLT_CP2:
5714 case OPC_SLEU_CP2:
5715 case OPC_SLE_CP2:
5716 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5717 FD field is the CC field? */
5718 default:
9d68ac14 5719 MIPS_INVAL("loongson_cp2");
9c708c7f 5720 generate_exception_end(ctx, EXCP_RI);
bd277fa1
RH
5721 return;
5722 }
5723
5724#undef LMI_HELPER
5725#undef LMI_DIRECT
5726
5727 gen_store_fpr64(ctx, t0, rd);
5728
bd277fa1
RH
5729 tcg_temp_free_i64(t0);
5730 tcg_temp_free_i64(t1);
5731}
5732
6af0bf9c 5733/* Traps */
7a387fff 5734static void gen_trap (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
5735 int rs, int rt, int16_t imm)
5736{
5737 int cond;
cdc0faa6 5738 TCGv t0 = tcg_temp_new();
1ba74fb8 5739 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
5740
5741 cond = 0;
5742 /* Load needed operands */
5743 switch (opc) {
5744 case OPC_TEQ:
5745 case OPC_TGE:
5746 case OPC_TGEU:
5747 case OPC_TLT:
5748 case OPC_TLTU:
5749 case OPC_TNE:
5750 /* Compare two registers */
5751 if (rs != rt) {
be24bb4f
TS
5752 gen_load_gpr(t0, rs);
5753 gen_load_gpr(t1, rt);
6af0bf9c
FB
5754 cond = 1;
5755 }
179e32bb 5756 break;
6af0bf9c
FB
5757 case OPC_TEQI:
5758 case OPC_TGEI:
5759 case OPC_TGEIU:
5760 case OPC_TLTI:
5761 case OPC_TLTIU:
5762 case OPC_TNEI:
5763 /* Compare register to immediate */
5764 if (rs != 0 || imm != 0) {
be24bb4f
TS
5765 gen_load_gpr(t0, rs);
5766 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
5767 cond = 1;
5768 }
5769 break;
5770 }
5771 if (cond == 0) {
5772 switch (opc) {
5773 case OPC_TEQ: /* rs == rs */
5774 case OPC_TEQI: /* r0 == 0 */
5775 case OPC_TGE: /* rs >= rs */
5776 case OPC_TGEI: /* r0 >= 0 */
5777 case OPC_TGEU: /* rs >= rs unsigned */
5778 case OPC_TGEIU: /* r0 >= 0 unsigned */
5779 /* Always trap */
9c708c7f 5780 generate_exception_end(ctx, EXCP_TRAP);
6af0bf9c
FB
5781 break;
5782 case OPC_TLT: /* rs < rs */
5783 case OPC_TLTI: /* r0 < 0 */
5784 case OPC_TLTU: /* rs < rs unsigned */
5785 case OPC_TLTIU: /* r0 < 0 unsigned */
5786 case OPC_TNE: /* rs != rs */
5787 case OPC_TNEI: /* r0 != 0 */
ead9360e 5788 /* Never trap: treat as NOP. */
cdc0faa6 5789 break;
6af0bf9c
FB
5790 }
5791 } else {
42a268c2 5792 TCGLabel *l1 = gen_new_label();
cdc0faa6 5793
6af0bf9c
FB
5794 switch (opc) {
5795 case OPC_TEQ:
5796 case OPC_TEQI:
cdc0faa6 5797 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
5798 break;
5799 case OPC_TGE:
5800 case OPC_TGEI:
cdc0faa6 5801 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
5802 break;
5803 case OPC_TGEU:
5804 case OPC_TGEIU:
cdc0faa6 5805 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
5806 break;
5807 case OPC_TLT:
5808 case OPC_TLTI:
cdc0faa6 5809 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
5810 break;
5811 case OPC_TLTU:
5812 case OPC_TLTIU:
cdc0faa6 5813 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
5814 break;
5815 case OPC_TNE:
5816 case OPC_TNEI:
cdc0faa6 5817 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 5818 break;
6af0bf9c 5819 }
cdc0faa6 5820 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
5821 gen_set_label(l1);
5822 }
be24bb4f
TS
5823 tcg_temp_free(t0);
5824 tcg_temp_free(t1);
6af0bf9c
FB
5825}
5826
90aa39a1
SF
5827static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5828{
eeb3bba8 5829 if (unlikely(ctx->base.singlestep_enabled)) {
90aa39a1
SF
5830 return false;
5831 }
5832
5833#ifndef CONFIG_USER_ONLY
eeb3bba8 5834 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
90aa39a1
SF
5835#else
5836 return true;
5837#endif
5838}
5839
356265ae 5840static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 5841{
90aa39a1 5842 if (use_goto_tb(ctx, dest)) {
57fec1fe 5843 tcg_gen_goto_tb(n);
9b9e4393 5844 gen_save_pc(dest);
07ea28b4 5845 tcg_gen_exit_tb(ctx->base.tb, n);
6e256c93 5846 } else {
9b9e4393 5847 gen_save_pc(dest);
eeb3bba8 5848 if (ctx->base.singlestep_enabled) {
7b270ef2 5849 save_cpu_state(ctx, 0);
9c708c7f 5850 gen_helper_raise_exception_debug(cpu_env);
7b270ef2 5851 }
7f11636d 5852 tcg_gen_lookup_and_goto_ptr();
6e256c93 5853 }
c53be334
FB
5854}
5855
6af0bf9c 5856/* Branches (before delay slot) */
7a387fff 5857static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
7dca4ad0 5858 int insn_bytes,
b231c103
YK
5859 int rs, int rt, int32_t offset,
5860 int delayslot_size)
6af0bf9c 5861{
d077b6f7 5862 target_ulong btgt = -1;
3ad4bb2d 5863 int blink = 0;
2fdbad25 5864 int bcond_compute = 0;
1ba74fb8
AJ
5865 TCGv t0 = tcg_temp_new();
5866 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
5867
5868 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 5869#ifdef MIPS_DEBUG_DISAS
339cd2a8 5870 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
eeb3bba8 5871 TARGET_FMT_lx "\n", ctx->base.pc_next);
923617a3 5872#endif
9c708c7f 5873 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5874 goto out;
3ad4bb2d 5875 }
6af0bf9c 5876
6af0bf9c
FB
5877 /* Load needed operands */
5878 switch (opc) {
5879 case OPC_BEQ:
5880 case OPC_BEQL:
5881 case OPC_BNE:
5882 case OPC_BNEL:
5883 /* Compare two registers */
5884 if (rs != rt) {
6c5c1e20
TS
5885 gen_load_gpr(t0, rs);
5886 gen_load_gpr(t1, rt);
2fdbad25 5887 bcond_compute = 1;
6af0bf9c 5888 }
eeb3bba8 5889 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c
FB
5890 break;
5891 case OPC_BGEZ:
5892 case OPC_BGEZAL:
5893 case OPC_BGEZALL:
5894 case OPC_BGEZL:
5895 case OPC_BGTZ:
5896 case OPC_BGTZL:
5897 case OPC_BLEZ:
5898 case OPC_BLEZL:
5899 case OPC_BLTZ:
5900 case OPC_BLTZAL:
5901 case OPC_BLTZALL:
5902 case OPC_BLTZL:
5903 /* Compare to zero */
5904 if (rs != 0) {
6c5c1e20 5905 gen_load_gpr(t0, rs);
2fdbad25 5906 bcond_compute = 1;
6af0bf9c 5907 }
eeb3bba8 5908 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c 5909 break;
e45a93e2
JL
5910 case OPC_BPOSGE32:
5911#if defined(TARGET_MIPS64)
5912 case OPC_BPOSGE64:
5913 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5914#else
5915 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5916#endif
5917 bcond_compute = 1;
eeb3bba8 5918 btgt = ctx->base.pc_next + insn_bytes + offset;
e45a93e2 5919 break;
6af0bf9c
FB
5920 case OPC_J:
5921 case OPC_JAL:
364d4831 5922 case OPC_JALX:
6af0bf9c 5923 /* Jump to immediate */
eeb3bba8
EC
5924 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5925 (uint32_t)offset;
6af0bf9c
FB
5926 break;
5927 case OPC_JR:
5928 case OPC_JALR:
5929 /* Jump to register */
7a387fff
TS
5930 if (offset != 0 && offset != 16) {
5931 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
cbeb0857 5932 others are reserved. */
923617a3 5933 MIPS_INVAL("jump hint");
9c708c7f 5934 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5935 goto out;
6af0bf9c 5936 }
d077b6f7 5937 gen_load_gpr(btarget, rs);
6af0bf9c
FB
5938 break;
5939 default:
5940 MIPS_INVAL("branch/jump");
9c708c7f 5941 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5942 goto out;
6af0bf9c 5943 }
2fdbad25 5944 if (bcond_compute == 0) {
6af0bf9c
FB
5945 /* No condition to be computed */
5946 switch (opc) {
5947 case OPC_BEQ: /* rx == rx */
5948 case OPC_BEQL: /* rx == rx likely */
5949 case OPC_BGEZ: /* 0 >= 0 */
5950 case OPC_BGEZL: /* 0 >= 0 likely */
5951 case OPC_BLEZ: /* 0 <= 0 */
5952 case OPC_BLEZL: /* 0 <= 0 likely */
5953 /* Always take */
4ad40f36 5954 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
5955 break;
5956 case OPC_BGEZAL: /* 0 >= 0 */
5957 case OPC_BGEZALL: /* 0 >= 0 likely */
5958 /* Always take and link */
5959 blink = 31;
4ad40f36 5960 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
5961 break;
5962 case OPC_BNE: /* rx != rx */
5963 case OPC_BGTZ: /* 0 > 0 */
5964 case OPC_BLTZ: /* 0 < 0 */
ead9360e 5965 /* Treat as NOP. */
6c5c1e20 5966 goto out;
eeef26cd 5967 case OPC_BLTZAL: /* 0 < 0 */
3c824109
NF
5968 /* Handle as an unconditional branch to get correct delay
5969 slot checking. */
5970 blink = 31;
eeb3bba8 5971 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
3c824109 5972 ctx->hflags |= MIPS_HFLAG_B;
3c824109 5973 break;
eeef26cd 5974 case OPC_BLTZALL: /* 0 < 0 likely */
eeb3bba8 5975 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
9898128f 5976 /* Skip the instruction in the delay slot */
eeb3bba8 5977 ctx->base.pc_next += 4;
6c5c1e20 5978 goto out;
6af0bf9c
FB
5979 case OPC_BNEL: /* rx != rx likely */
5980 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
5981 case OPC_BLTZL: /* 0 < 0 likely */
5982 /* Skip the instruction in the delay slot */
eeb3bba8 5983 ctx->base.pc_next += 4;
6c5c1e20 5984 goto out;
6af0bf9c 5985 case OPC_J:
4ad40f36 5986 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c 5987 break;
364d4831
NF
5988 case OPC_JALX:
5989 ctx->hflags |= MIPS_HFLAG_BX;
5990 /* Fallthrough */
6af0bf9c
FB
5991 case OPC_JAL:
5992 blink = 31;
4ad40f36 5993 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
5994 break;
5995 case OPC_JR:
4ad40f36 5996 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
5997 break;
5998 case OPC_JALR:
5999 blink = rt;
4ad40f36 6000 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
6001 break;
6002 default:
6003 MIPS_INVAL("branch/jump");
9c708c7f 6004 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6005 goto out;
6af0bf9c
FB
6006 }
6007 } else {
6008 switch (opc) {
6009 case OPC_BEQ:
e68dd28f 6010 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
6011 goto not_likely;
6012 case OPC_BEQL:
e68dd28f 6013 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
6014 goto likely;
6015 case OPC_BNE:
e68dd28f 6016 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
6017 goto not_likely;
6018 case OPC_BNEL:
e68dd28f 6019 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
6020 goto likely;
6021 case OPC_BGEZ:
e68dd28f 6022 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6023 goto not_likely;
6024 case OPC_BGEZL:
e68dd28f 6025 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6026 goto likely;
6027 case OPC_BGEZAL:
e68dd28f 6028 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
6029 blink = 31;
6030 goto not_likely;
6031 case OPC_BGEZALL:
e68dd28f 6032 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 6033 blink = 31;
6af0bf9c
FB
6034 goto likely;
6035 case OPC_BGTZ:
e68dd28f 6036 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
6037 goto not_likely;
6038 case OPC_BGTZL:
e68dd28f 6039 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
6040 goto likely;
6041 case OPC_BLEZ:
e68dd28f 6042 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
6043 goto not_likely;
6044 case OPC_BLEZL:
e68dd28f 6045 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
6046 goto likely;
6047 case OPC_BLTZ:
e68dd28f 6048 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c
FB
6049 goto not_likely;
6050 case OPC_BLTZL:
e68dd28f 6051 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6052 goto likely;
e45a93e2
JL
6053 case OPC_BPOSGE32:
6054 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
e45a93e2
JL
6055 goto not_likely;
6056#if defined(TARGET_MIPS64)
6057 case OPC_BPOSGE64:
6058 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
e45a93e2
JL
6059 goto not_likely;
6060#endif
6af0bf9c 6061 case OPC_BLTZAL:
e68dd28f 6062 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6063 blink = 31;
6af0bf9c 6064 not_likely:
4ad40f36 6065 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
6066 break;
6067 case OPC_BLTZALL:
e68dd28f 6068 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 6069 blink = 31;
6af0bf9c 6070 likely:
4ad40f36 6071 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 6072 break;
c53f4a62
TS
6073 default:
6074 MIPS_INVAL("conditional branch/jump");
9c708c7f 6075 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 6076 goto out;
6af0bf9c 6077 }
6af0bf9c 6078 }
9b9e4393 6079
d077b6f7 6080 ctx->btarget = btgt;
b231c103
YK
6081
6082 switch (delayslot_size) {
6083 case 2:
6084 ctx->hflags |= MIPS_HFLAG_BDS16;
6085 break;
6086 case 4:
6087 ctx->hflags |= MIPS_HFLAG_BDS32;
6088 break;
6089 }
6090
6af0bf9c 6091 if (blink > 0) {
b231c103 6092 int post_delay = insn_bytes + delayslot_size;
364d4831
NF
6093 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6094
eeb3bba8
EC
6095 tcg_gen_movi_tl(cpu_gpr[blink],
6096 ctx->base.pc_next + post_delay + lowbit);
6af0bf9c 6097 }
6c5c1e20
TS
6098
6099 out:
364d4831
NF
6100 if (insn_bytes == 2)
6101 ctx->hflags |= MIPS_HFLAG_B16;
6c5c1e20
TS
6102 tcg_temp_free(t0);
6103 tcg_temp_free(t1);
6af0bf9c
FB
6104}
6105
764371d2
SM
6106
6107/* nanoMIPS Branches */
6108static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6109 int insn_bytes,
6110 int rs, int rt, int32_t offset)
6111{
6112 target_ulong btgt = -1;
6113 int bcond_compute = 0;
6114 TCGv t0 = tcg_temp_new();
6115 TCGv t1 = tcg_temp_new();
6116
6117 /* Load needed operands */
6118 switch (opc) {
6119 case OPC_BEQ:
6120 case OPC_BNE:
6121 /* Compare two registers */
6122 if (rs != rt) {
6123 gen_load_gpr(t0, rs);
6124 gen_load_gpr(t1, rt);
6125 bcond_compute = 1;
6126 }
6127 btgt = ctx->base.pc_next + insn_bytes + offset;
6128 break;
6129 case OPC_BGEZAL:
6130 /* Compare to zero */
6131 if (rs != 0) {
6132 gen_load_gpr(t0, rs);
6133 bcond_compute = 1;
6134 }
6135 btgt = ctx->base.pc_next + insn_bytes + offset;
6136 break;
6137 case OPC_BPOSGE32:
6138 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6139 bcond_compute = 1;
6140 btgt = ctx->base.pc_next + insn_bytes + offset;
6141 break;
6142 case OPC_JR:
6143 case OPC_JALR:
6144 /* Jump to register */
6145 if (offset != 0 && offset != 16) {
6146 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6147 others are reserved. */
6148 MIPS_INVAL("jump hint");
6149 generate_exception_end(ctx, EXCP_RI);
6150 goto out;
6151 }
6152 gen_load_gpr(btarget, rs);
6153 break;
6154 default:
6155 MIPS_INVAL("branch/jump");
6156 generate_exception_end(ctx, EXCP_RI);
6157 goto out;
6158 }
6159 if (bcond_compute == 0) {
6160 /* No condition to be computed */
6161 switch (opc) {
6162 case OPC_BEQ: /* rx == rx */
6163 /* Always take */
6164 ctx->hflags |= MIPS_HFLAG_B;
6165 break;
6166 case OPC_BGEZAL: /* 0 >= 0 */
6167 /* Always take and link */
6168 tcg_gen_movi_tl(cpu_gpr[31],
6169 ctx->base.pc_next + insn_bytes);
6170 ctx->hflags |= MIPS_HFLAG_B;
6171 break;
6172 case OPC_BNE: /* rx != rx */
6173 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6174 /* Skip the instruction in the delay slot */
6175 ctx->base.pc_next += 4;
6176 goto out;
6177 case OPC_JR:
6178 ctx->hflags |= MIPS_HFLAG_BR;
6179 break;
6180 case OPC_JALR:
6181 if (rt > 0) {
6182 tcg_gen_movi_tl(cpu_gpr[rt],
6183 ctx->base.pc_next + insn_bytes);
6184 }
6185 ctx->hflags |= MIPS_HFLAG_BR;
6186 break;
6187 default:
6188 MIPS_INVAL("branch/jump");
6189 generate_exception_end(ctx, EXCP_RI);
6190 goto out;
6191 }
6192 } else {
6193 switch (opc) {
6194 case OPC_BEQ:
6195 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6196 goto not_likely;
6197 case OPC_BNE:
6198 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6199 goto not_likely;
6200 case OPC_BGEZAL:
6201 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6202 tcg_gen_movi_tl(cpu_gpr[31],
6203 ctx->base.pc_next + insn_bytes);
6204 goto not_likely;
6205 case OPC_BPOSGE32:
6206 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6207 not_likely:
6208 ctx->hflags |= MIPS_HFLAG_BC;
6209 break;
6210 default:
6211 MIPS_INVAL("conditional branch/jump");
6212 generate_exception_end(ctx, EXCP_RI);
6213 goto out;
6214 }
6215 }
6216
6217 ctx->btarget = btgt;
6218
6219 out:
6220 if (insn_bytes == 2) {
6221 ctx->hflags |= MIPS_HFLAG_B16;
6222 }
6223 tcg_temp_free(t0);
6224 tcg_temp_free(t1);
6225}
6226
6227
7a387fff
TS
6228/* special3 bitfield operations */
6229static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
356265ae 6230 int rs, int lsb, int msb)
7a387fff 6231{
a7812ae4
PB
6232 TCGv t0 = tcg_temp_new();
6233 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
6234
6235 gen_load_gpr(t1, rs);
7a387fff
TS
6236 switch (opc) {
6237 case OPC_EXT:
b7f26e52 6238 if (lsb + msb > 31) {
7a387fff 6239 goto fail;
b7f26e52 6240 }
505ad7c2 6241 if (msb != 31) {
6eebb7a4 6242 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
505ad7c2 6243 } else {
6eebb7a4
RH
6244 /* The two checks together imply that lsb == 0,
6245 so this is a simple sign-extension. */
6246 tcg_gen_ext32s_tl(t0, t1);
505ad7c2 6247 }
7a387fff 6248 break;
c6d6dd7c 6249#if defined(TARGET_MIPS64)
7a387fff 6250 case OPC_DEXTU:
b7f26e52
RH
6251 lsb += 32;
6252 goto do_dext;
6253 case OPC_DEXTM:
6254 msb += 32;
6255 goto do_dext;
7a387fff 6256 case OPC_DEXT:
b7f26e52
RH
6257 do_dext:
6258 if (lsb + msb > 63) {
6259 goto fail;
6260 }
6eebb7a4 6261 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
7a387fff 6262 break;
c6d6dd7c 6263#endif
7a387fff 6264 case OPC_INS:
b7f26e52 6265 if (lsb > msb) {
7a387fff 6266 goto fail;
b7f26e52 6267 }
6c5c1e20 6268 gen_load_gpr(t0, rt);
e0d002f1 6269 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
505ad7c2 6270 tcg_gen_ext32s_tl(t0, t0);
7a387fff 6271 break;
c6d6dd7c 6272#if defined(TARGET_MIPS64)
7a387fff 6273 case OPC_DINSU:
b7f26e52
RH
6274 lsb += 32;
6275 /* FALLTHRU */
6276 case OPC_DINSM:
6277 msb += 32;
6278 /* FALLTHRU */
7a387fff 6279 case OPC_DINS:
b7f26e52
RH
6280 if (lsb > msb) {
6281 goto fail;
6282 }
6c5c1e20 6283 gen_load_gpr(t0, rt);
e0d002f1 6284 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
7a387fff 6285 break;
c6d6dd7c 6286#endif
7a387fff
TS
6287 default:
6288fail:
6289 MIPS_INVAL("bitops");
9c708c7f 6290 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
6291 tcg_temp_free(t0);
6292 tcg_temp_free(t1);
7a387fff
TS
6293 return;
6294 }
6c5c1e20
TS
6295 gen_store_gpr(t0, rt);
6296 tcg_temp_free(t0);
6297 tcg_temp_free(t1);
7a387fff
TS
6298}
6299
49bcf33c
AJ
6300static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
6301{
3a55fa47 6302 TCGv t0;
49bcf33c 6303
3a55fa47
AJ
6304 if (rd == 0) {
6305 /* If no destination, treat it as a NOP. */
3a55fa47
AJ
6306 return;
6307 }
6308
6309 t0 = tcg_temp_new();
6310 gen_load_gpr(t0, rt);
49bcf33c
AJ
6311 switch (op2) {
6312 case OPC_WSBH:
3a55fa47
AJ
6313 {
6314 TCGv t1 = tcg_temp_new();
06a57e5c 6315 TCGv t2 = tcg_const_tl(0x00FF00FF);
3a55fa47
AJ
6316
6317 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
6318 tcg_gen_and_tl(t1, t1, t2);
6319 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6320 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 6321 tcg_gen_or_tl(t0, t0, t1);
06a57e5c 6322 tcg_temp_free(t2);
3a55fa47
AJ
6323 tcg_temp_free(t1);
6324 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6325 }
49bcf33c
AJ
6326 break;
6327 case OPC_SEB:
3a55fa47 6328 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
6329 break;
6330 case OPC_SEH:
3a55fa47 6331 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
6332 break;
6333#if defined(TARGET_MIPS64)
6334 case OPC_DSBH:
3a55fa47
AJ
6335 {
6336 TCGv t1 = tcg_temp_new();
06a57e5c 6337 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
3a55fa47
AJ
6338
6339 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
6340 tcg_gen_and_tl(t1, t1, t2);
6341 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6342 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 6343 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 6344 tcg_temp_free(t2);
3a55fa47
AJ
6345 tcg_temp_free(t1);
6346 }
49bcf33c
AJ
6347 break;
6348 case OPC_DSHD:
3a55fa47
AJ
6349 {
6350 TCGv t1 = tcg_temp_new();
06a57e5c 6351 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
3a55fa47
AJ
6352
6353 tcg_gen_shri_tl(t1, t0, 16);
06a57e5c
AJ
6354 tcg_gen_and_tl(t1, t1, t2);
6355 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6356 tcg_gen_shli_tl(t0, t0, 16);
3a55fa47
AJ
6357 tcg_gen_or_tl(t0, t0, t1);
6358 tcg_gen_shri_tl(t1, t0, 32);
6359 tcg_gen_shli_tl(t0, t0, 32);
6360 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 6361 tcg_temp_free(t2);
3a55fa47
AJ
6362 tcg_temp_free(t1);
6363 }
49bcf33c
AJ
6364 break;
6365#endif
6366 default:
6367 MIPS_INVAL("bsfhl");
9c708c7f 6368 generate_exception_end(ctx, EXCP_RI);
49bcf33c 6369 tcg_temp_free(t0);
49bcf33c
AJ
6370 return;
6371 }
49bcf33c 6372 tcg_temp_free(t0);
49bcf33c
AJ
6373}
6374
1f1b4c00
YK
6375static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6376 int imm2)
6377{
6378 TCGv t0;
6379 TCGv t1;
6380 if (rd == 0) {
6381 /* Treat as NOP. */
6382 return;
6383 }
6384 t0 = tcg_temp_new();
6385 t1 = tcg_temp_new();
6386 gen_load_gpr(t0, rs);
6387 gen_load_gpr(t1, rt);
6388 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6389 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6390 if (opc == OPC_LSA) {
6391 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6392 }
6393
6394 tcg_temp_free(t1);
6395 tcg_temp_free(t0);
6396
6397 return;
6398}
6399
821f2008
JH
6400static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6401 int rt, int bits)
284b731a 6402{
1f1b4c00
YK
6403 TCGv t0;
6404 if (rd == 0) {
6405 /* Treat as NOP. */
6406 return;
6407 }
6408 t0 = tcg_temp_new();
821f2008
JH
6409 if (bits == 0 || bits == wordsz) {
6410 if (bits == 0) {
6411 gen_load_gpr(t0, rt);
6412 } else {
6413 gen_load_gpr(t0, rs);
6414 }
6415 switch (wordsz) {
6416 case 32:
51243852
MD
6417 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6418 break;
6419#if defined(TARGET_MIPS64)
821f2008 6420 case 64:
51243852
MD
6421 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6422 break;
6423#endif
6424 }
1f1b4c00
YK
6425 } else {
6426 TCGv t1 = tcg_temp_new();
821f2008 6427 gen_load_gpr(t0, rt);
1f1b4c00 6428 gen_load_gpr(t1, rs);
821f2008
JH
6429 switch (wordsz) {
6430 case 32:
1f1b4c00
YK
6431 {
6432 TCGv_i64 t2 = tcg_temp_new_i64();
6433 tcg_gen_concat_tl_i64(t2, t1, t0);
821f2008 6434 tcg_gen_shri_i64(t2, t2, 32 - bits);
1f1b4c00
YK
6435 gen_move_low32(cpu_gpr[rd], t2);
6436 tcg_temp_free_i64(t2);
6437 }
6438 break;
284b731a 6439#if defined(TARGET_MIPS64)
821f2008
JH
6440 case 64:
6441 tcg_gen_shli_tl(t0, t0, bits);
6442 tcg_gen_shri_tl(t1, t1, 64 - bits);
1f1b4c00
YK
6443 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6444 break;
284b731a 6445#endif
1f1b4c00
YK
6446 }
6447 tcg_temp_free(t1);
6448 }
6449
6450 tcg_temp_free(t0);
6451}
6452
821f2008
JH
6453static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6454 int bp)
6455{
6456 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6457}
6458
6459static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6460 int shift)
6461{
6462 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6463}
6464
1f1b4c00
YK
6465static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6466{
6467 TCGv t0;
6468 if (rd == 0) {
6469 /* Treat as NOP. */
6470 return;
6471 }
6472 t0 = tcg_temp_new();
6473 gen_load_gpr(t0, rt);
6474 switch (opc) {
6475 case OPC_BITSWAP:
6476 gen_helper_bitswap(cpu_gpr[rd], t0);
6477 break;
6478#if defined(TARGET_MIPS64)
6479 case OPC_DBITSWAP:
6480 gen_helper_dbitswap(cpu_gpr[rd], t0);
6481 break;
6482#endif
6483 }
6484 tcg_temp_free(t0);
284b731a
LA
6485}
6486
1f1b4c00
YK
6487#ifndef CONFIG_USER_ONLY
6488/* CP0 (MMU and control) */
5204ea79
LA
6489static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6490{
6491 TCGv_i64 t0 = tcg_temp_new_i64();
6492 TCGv_i64 t1 = tcg_temp_new_i64();
6493
6494 tcg_gen_ext_tl_i64(t0, arg);
6495 tcg_gen_ld_i64(t1, cpu_env, off);
6496#if defined(TARGET_MIPS64)
6497 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6498#else
6499 tcg_gen_concat32_i64(t1, t1, t0);
6500#endif
6501 tcg_gen_st_i64(t1, cpu_env, off);
6502 tcg_temp_free_i64(t1);
6503 tcg_temp_free_i64(t0);
6504}
6505
6506static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6507{
6508 TCGv_i64 t0 = tcg_temp_new_i64();
6509 TCGv_i64 t1 = tcg_temp_new_i64();
6510
6511 tcg_gen_ext_tl_i64(t0, arg);
6512 tcg_gen_ld_i64(t1, cpu_env, off);
6513 tcg_gen_concat32_i64(t1, t1, t0);
6514 tcg_gen_st_i64(t1, cpu_env, off);
6515 tcg_temp_free_i64(t1);
6516 tcg_temp_free_i64(t0);
6517}
6518
6519static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6520{
6521 TCGv_i64 t0 = tcg_temp_new_i64();
6522
6523 tcg_gen_ld_i64(t0, cpu_env, off);
6524#if defined(TARGET_MIPS64)
6525 tcg_gen_shri_i64(t0, t0, 30);
6526#else
6527 tcg_gen_shri_i64(t0, t0, 32);
6528#endif
6529 gen_move_low32(arg, t0);
6530 tcg_temp_free_i64(t0);
6531}
6532
6533static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6534{
6535 TCGv_i64 t0 = tcg_temp_new_i64();
6536
6537 tcg_gen_ld_i64(t0, cpu_env, off);
6538 tcg_gen_shri_i64(t0, t0, 32 + shift);
6539 gen_move_low32(arg, t0);
6540 tcg_temp_free_i64(t0);
6541}
6542
d9bea114 6543static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4f57689a 6544{
d9bea114 6545 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 6546
d9bea114
AJ
6547 tcg_gen_ld_i32(t0, cpu_env, off);
6548 tcg_gen_ext_i32_tl(arg, t0);
6549 tcg_temp_free_i32(t0);
4f57689a
TS
6550}
6551
d9bea114 6552static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4f57689a 6553{
d9bea114
AJ
6554 tcg_gen_ld_tl(arg, cpu_env, off);
6555 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
6556}
6557
d9bea114 6558static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
f1aa6320 6559{
d9bea114 6560 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 6561
d9bea114
AJ
6562 tcg_gen_trunc_tl_i32(t0, arg);
6563 tcg_gen_st_i32(t0, cpu_env, off);
6564 tcg_temp_free_i32(t0);
f1aa6320
TS
6565}
6566
c98d3d79
YK
6567#define CP0_CHECK(c) \
6568 do { \
6569 if (!(c)) { \
6570 goto cp0_unimplemented; \
6571 } \
6572 } while (0)
6573
5204ea79
LA
6574static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6575{
294fc2ea 6576 const char *register_name = "invalid";
5204ea79 6577
5204ea79 6578 switch (reg) {
04992c8c 6579 case CP0_REGISTER_02:
5204ea79
LA
6580 switch (sel) {
6581 case 0:
59488dda 6582 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 6583 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 6584 register_name = "EntryLo0";
5204ea79
LA
6585 break;
6586 default:
c98d3d79 6587 goto cp0_unimplemented;
5204ea79
LA
6588 }
6589 break;
04992c8c 6590 case CP0_REGISTER_03:
5204ea79
LA
6591 switch (sel) {
6592 case 0:
59488dda 6593 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79 6594 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 6595 register_name = "EntryLo1";
5204ea79
LA
6596 break;
6597 default:
c98d3d79 6598 goto cp0_unimplemented;
5204ea79
LA
6599 }
6600 break;
04992c8c 6601 case CP0_REGISTER_09:
5fb2dcd1
YK
6602 switch (sel) {
6603 case 7:
6604 CP0_CHECK(ctx->saar);
6605 gen_helper_mfhc0_saar(arg, cpu_env);
294fc2ea 6606 register_name = "SAAR";
5fb2dcd1
YK
6607 break;
6608 default:
6609 goto cp0_unimplemented;
6610 }
6611 break;
04992c8c 6612 case CP0_REGISTER_17:
5204ea79
LA
6613 switch (sel) {
6614 case 0:
6615 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
6616 ctx->CP0_LLAddr_shift);
294fc2ea 6617 register_name = "LLAddr";
5204ea79 6618 break;
f6d4dd81
YK
6619 case 1:
6620 CP0_CHECK(ctx->mrp);
6621 gen_helper_mfhc0_maar(arg, cpu_env);
294fc2ea 6622 register_name = "MAAR";
f6d4dd81 6623 break;
5204ea79 6624 default:
c98d3d79 6625 goto cp0_unimplemented;
5204ea79
LA
6626 }
6627 break;
04992c8c 6628 case CP0_REGISTER_28:
5204ea79
LA
6629 switch (sel) {
6630 case 0:
6631 case 2:
6632 case 4:
6633 case 6:
6634 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
294fc2ea 6635 register_name = "TagLo";
5204ea79
LA
6636 break;
6637 default:
c98d3d79 6638 goto cp0_unimplemented;
5204ea79
LA
6639 }
6640 break;
6641 default:
c98d3d79 6642 goto cp0_unimplemented;
5204ea79 6643 }
294fc2ea 6644 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
5204ea79
LA
6645 return;
6646
c98d3d79 6647cp0_unimplemented:
294fc2ea
AM
6648 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6649 register_name, reg, sel);
5204ea79
LA
6650 tcg_gen_movi_tl(arg, 0);
6651}
6652
6653static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6654{
294fc2ea 6655 const char *register_name = "invalid";
5204ea79
LA
6656 uint64_t mask = ctx->PAMask >> 36;
6657
5204ea79 6658 switch (reg) {
04992c8c 6659 case CP0_REGISTER_02:
5204ea79
LA
6660 switch (sel) {
6661 case 0:
59488dda 6662 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
6663 tcg_gen_andi_tl(arg, arg, mask);
6664 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 6665 register_name = "EntryLo0";
5204ea79
LA
6666 break;
6667 default:
c98d3d79 6668 goto cp0_unimplemented;
5204ea79
LA
6669 }
6670 break;
04992c8c 6671 case CP0_REGISTER_03:
5204ea79
LA
6672 switch (sel) {
6673 case 0:
59488dda 6674 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
6675 tcg_gen_andi_tl(arg, arg, mask);
6676 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 6677 register_name = "EntryLo1";
5204ea79
LA
6678 break;
6679 default:
c98d3d79 6680 goto cp0_unimplemented;
5204ea79
LA
6681 }
6682 break;
04992c8c 6683 case CP0_REGISTER_09:
5fb2dcd1
YK
6684 switch (sel) {
6685 case 7:
6686 CP0_CHECK(ctx->saar);
6687 gen_helper_mthc0_saar(cpu_env, arg);
294fc2ea 6688 register_name = "SAAR";
5fb2dcd1
YK
6689 break;
6690 default:
6691 goto cp0_unimplemented;
6692 }
04992c8c 6693 case CP0_REGISTER_17:
5204ea79
LA
6694 switch (sel) {
6695 case 0:
6696 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6697 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6698 relevant for modern MIPS cores supporting MTHC0, therefore
6699 treating MTHC0 to LLAddr as NOP. */
294fc2ea 6700 register_name = "LLAddr";
5204ea79 6701 break;
f6d4dd81
YK
6702 case 1:
6703 CP0_CHECK(ctx->mrp);
6704 gen_helper_mthc0_maar(cpu_env, arg);
294fc2ea 6705 register_name = "MAAR";
f6d4dd81 6706 break;
5204ea79 6707 default:
c98d3d79 6708 goto cp0_unimplemented;
5204ea79
LA
6709 }
6710 break;
04992c8c 6711 case CP0_REGISTER_28:
5204ea79
LA
6712 switch (sel) {
6713 case 0:
6714 case 2:
6715 case 4:
6716 case 6:
6717 tcg_gen_andi_tl(arg, arg, mask);
6718 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 6719 register_name = "TagLo";
5204ea79
LA
6720 break;
6721 default:
c98d3d79 6722 goto cp0_unimplemented;
5204ea79
LA
6723 }
6724 break;
6725 default:
c98d3d79 6726 goto cp0_unimplemented;
5204ea79 6727 }
294fc2ea 6728 trace_mips_translate_c0("mthc0", register_name, reg, sel);
5204ea79 6729
c98d3d79 6730cp0_unimplemented:
294fc2ea
AM
6731 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6732 register_name, reg, sel);
5204ea79
LA
6733}
6734
e98c0d17
LA
6735static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6736{
6737 if (ctx->insn_flags & ISA_MIPS32R6) {
6738 tcg_gen_movi_tl(arg, 0);
6739 } else {
6740 tcg_gen_movi_tl(arg, ~0);
6741 }
6742}
6743
d75c135e 6744static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 6745{
294fc2ea 6746 const char *register_name = "invalid";
873eb012 6747
e189e748 6748 if (sel != 0)
d75c135e 6749 check_insn(ctx, ISA_MIPS32);
e189e748 6750
873eb012 6751 switch (reg) {
04992c8c 6752 case CP0_REGISTER_00:
7a387fff
TS
6753 switch (sel) {
6754 case 0:
7db13fae 6755 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 6756 register_name = "Index";
7a387fff
TS
6757 break;
6758 case 1:
f31b035a 6759 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6760 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 6761 register_name = "MVPControl";
ead9360e 6762 break;
7a387fff 6763 case 2:
f31b035a 6764 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6765 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 6766 register_name = "MVPConf0";
ead9360e 6767 break;
7a387fff 6768 case 3:
f31b035a 6769 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6770 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 6771 register_name = "MVPConf1";
ead9360e 6772 break;
01bc435b
YK
6773 case 4:
6774 CP0_CHECK(ctx->vp);
6775 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 6776 register_name = "VPControl";
01bc435b 6777 break;
7a387fff 6778 default:
f31b035a 6779 goto cp0_unimplemented;
7a387fff 6780 }
873eb012 6781 break;
04992c8c 6782 case CP0_REGISTER_01:
7a387fff
TS
6783 switch (sel) {
6784 case 0:
f31b035a 6785 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 6786 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 6787 register_name = "Random";
2423f660 6788 break;
7a387fff 6789 case 1:
f31b035a 6790 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6791 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 6792 register_name = "VPEControl";
ead9360e 6793 break;
7a387fff 6794 case 2:
f31b035a 6795 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6796 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 6797 register_name = "VPEConf0";
ead9360e 6798 break;
7a387fff 6799 case 3:
f31b035a 6800 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6801 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 6802 register_name = "VPEConf1";
ead9360e 6803 break;
7a387fff 6804 case 4:
f31b035a 6805 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6806 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 6807 register_name = "YQMask";
ead9360e 6808 break;
7a387fff 6809 case 5:
f31b035a 6810 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6811 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 6812 register_name = "VPESchedule";
ead9360e 6813 break;
7a387fff 6814 case 6:
f31b035a 6815 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6816 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 6817 register_name = "VPEScheFBack";
ead9360e 6818 break;
7a387fff 6819 case 7:
f31b035a 6820 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6821 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 6822 register_name = "VPEOpt";
ead9360e 6823 break;
7a387fff 6824 default:
f31b035a 6825 goto cp0_unimplemented;
7a387fff 6826 }
873eb012 6827 break;
04992c8c 6828 case CP0_REGISTER_02:
7a387fff
TS
6829 switch (sel) {
6830 case 0:
284b731a
LA
6831 {
6832 TCGv_i64 tmp = tcg_temp_new_i64();
6833 tcg_gen_ld_i64(tmp, cpu_env,
6834 offsetof(CPUMIPSState, CP0_EntryLo0));
7207c7f9 6835#if defined(TARGET_MIPS64)
284b731a
LA
6836 if (ctx->rxi) {
6837 /* Move RI/XI fields to bits 31:30 */
6838 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6839 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6840 }
7207c7f9 6841#endif
284b731a
LA
6842 gen_move_low32(arg, tmp);
6843 tcg_temp_free_i64(tmp);
6844 }
294fc2ea 6845 register_name = "EntryLo0";
2423f660 6846 break;
7a387fff 6847 case 1:
f31b035a 6848 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6849 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 6850 register_name = "TCStatus";
ead9360e 6851 break;
7a387fff 6852 case 2:
f31b035a 6853 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6854 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 6855 register_name = "TCBind";
ead9360e 6856 break;
7a387fff 6857 case 3:
f31b035a 6858 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6859 gen_helper_mfc0_tcrestart(arg, cpu_env);
294fc2ea 6860 register_name = "TCRestart";
ead9360e 6861 break;
7a387fff 6862 case 4:
f31b035a 6863 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6864 gen_helper_mfc0_tchalt(arg, cpu_env);
294fc2ea 6865 register_name = "TCHalt";
ead9360e 6866 break;
7a387fff 6867 case 5:
f31b035a 6868 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6869 gen_helper_mfc0_tccontext(arg, cpu_env);
294fc2ea 6870 register_name = "TCContext";
ead9360e 6871 break;
7a387fff 6872 case 6:
f31b035a 6873 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6874 gen_helper_mfc0_tcschedule(arg, cpu_env);
294fc2ea 6875 register_name = "TCSchedule";
ead9360e 6876 break;
7a387fff 6877 case 7:
f31b035a 6878 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6879 gen_helper_mfc0_tcschefback(arg, cpu_env);
294fc2ea 6880 register_name = "TCScheFBack";
ead9360e 6881 break;
7a387fff 6882 default:
f31b035a 6883 goto cp0_unimplemented;
7a387fff 6884 }
873eb012 6885 break;
04992c8c 6886 case CP0_REGISTER_03:
7a387fff
TS
6887 switch (sel) {
6888 case 0:
284b731a
LA
6889 {
6890 TCGv_i64 tmp = tcg_temp_new_i64();
6891 tcg_gen_ld_i64(tmp, cpu_env,
6892 offsetof(CPUMIPSState, CP0_EntryLo1));
7207c7f9 6893#if defined(TARGET_MIPS64)
284b731a
LA
6894 if (ctx->rxi) {
6895 /* Move RI/XI fields to bits 31:30 */
6896 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6897 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6898 }
7207c7f9 6899#endif
284b731a
LA
6900 gen_move_low32(arg, tmp);
6901 tcg_temp_free_i64(tmp);
6902 }
294fc2ea 6903 register_name = "EntryLo1";
2423f660 6904 break;
01bc435b
YK
6905 case 1:
6906 CP0_CHECK(ctx->vp);
6907 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 6908 register_name = "GlobalNumber";
01bc435b 6909 break;
7a387fff 6910 default:
f31b035a 6911 goto cp0_unimplemented;
1579a72e 6912 }
873eb012 6913 break;
04992c8c 6914 case CP0_REGISTER_04:
7a387fff
TS
6915 switch (sel) {
6916 case 0:
7db13fae 6917 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 6918 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6919 register_name = "Context";
2423f660 6920 break;
7a387fff 6921 case 1:
d9bea114 6922// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
294fc2ea 6923 register_name = "ContextConfig";
f31b035a 6924 goto cp0_unimplemented;
d279279e 6925 case 2:
f31b035a 6926 CP0_CHECK(ctx->ulri);
e40df9a8
JH
6927 tcg_gen_ld_tl(arg, cpu_env,
6928 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6929 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6930 register_name = "UserLocal";
d279279e 6931 break;
7a387fff 6932 default:
f31b035a 6933 goto cp0_unimplemented;
1579a72e 6934 }
873eb012 6935 break;
04992c8c 6936 case CP0_REGISTER_05:
7a387fff
TS
6937 switch (sel) {
6938 case 0:
7db13fae 6939 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 6940 register_name = "PageMask";
2423f660 6941 break;
7a387fff 6942 case 1:
d75c135e 6943 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6944 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 6945 register_name = "PageGrain";
2423f660 6946 break;
cec56a73
JH
6947 case 2:
6948 CP0_CHECK(ctx->sc);
6949 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6950 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6951 register_name = "SegCtl0";
cec56a73
JH
6952 break;
6953 case 3:
6954 CP0_CHECK(ctx->sc);
6955 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6956 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6957 register_name = "SegCtl1";
cec56a73
JH
6958 break;
6959 case 4:
6960 CP0_CHECK(ctx->sc);
6961 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6962 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 6963 register_name = "SegCtl2";
cec56a73 6964 break;
5e31fdd5
YK
6965 case 5:
6966 check_pw(ctx);
6967 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 6968 register_name = "PWBase";
5e31fdd5 6969 break;
fa75ad14
YK
6970 case 6:
6971 check_pw(ctx);
6972 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 6973 register_name = "PWField";
fa75ad14 6974 break;
20b28ebc
YK
6975 case 7:
6976 check_pw(ctx);
6977 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 6978 register_name = "PWSize";
20b28ebc 6979 break;
7a387fff 6980 default:
f31b035a 6981 goto cp0_unimplemented;
1579a72e 6982 }
873eb012 6983 break;
04992c8c 6984 case CP0_REGISTER_06:
7a387fff
TS
6985 switch (sel) {
6986 case 0:
7db13fae 6987 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 6988 register_name = "Wired";
2423f660 6989 break;
7a387fff 6990 case 1:
d75c135e 6991 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6992 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 6993 register_name = "SRSConf0";
ead9360e 6994 break;
7a387fff 6995 case 2:
d75c135e 6996 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6997 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 6998 register_name = "SRSConf1";
ead9360e 6999 break;
7a387fff 7000 case 3:
d75c135e 7001 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7002 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 7003 register_name = "SRSConf2";
ead9360e 7004 break;
7a387fff 7005 case 4:
d75c135e 7006 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7007 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 7008 register_name = "SRSConf3";
ead9360e 7009 break;
7a387fff 7010 case 5:
d75c135e 7011 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7012 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 7013 register_name = "SRSConf4";
ead9360e 7014 break;
103be64c
YK
7015 case 6:
7016 check_pw(ctx);
7017 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 7018 register_name = "PWCtl";
103be64c 7019 break;
7a387fff 7020 default:
f31b035a 7021 goto cp0_unimplemented;
1579a72e 7022 }
873eb012 7023 break;
04992c8c 7024 case CP0_REGISTER_07:
7a387fff
TS
7025 switch (sel) {
7026 case 0:
d75c135e 7027 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7028 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 7029 register_name = "HWREna";
2423f660 7030 break;
7a387fff 7031 default:
f31b035a 7032 goto cp0_unimplemented;
1579a72e 7033 }
8c0fdd85 7034 break;
04992c8c 7035 case CP0_REGISTER_08:
7a387fff
TS
7036 switch (sel) {
7037 case 0:
7db13fae 7038 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 7039 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7040 register_name = "BadVAddr";
2423f660 7041 break;
aea14095 7042 case 1:
f31b035a
LA
7043 CP0_CHECK(ctx->bi);
7044 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 7045 register_name = "BadInstr";
aea14095
LA
7046 break;
7047 case 2:
f31b035a
LA
7048 CP0_CHECK(ctx->bp);
7049 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 7050 register_name = "BadInstrP";
aea14095 7051 break;
25beba9b
SM
7052 case 3:
7053 CP0_CHECK(ctx->bi);
7054 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7055 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 7056 register_name = "BadInstrX";
25beba9b
SM
7057 break;
7058 default:
f31b035a 7059 goto cp0_unimplemented;
aea14095 7060 }
873eb012 7061 break;
04992c8c 7062 case CP0_REGISTER_09:
7a387fff
TS
7063 switch (sel) {
7064 case 0:
2e70f6ef 7065 /* Mark as an IO operation because we read the time. */
eeb3bba8 7066 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7067 gen_io_start();
7d37435b 7068 }
895c2d04 7069 gen_helper_mfc0_count(arg, cpu_env);
eeb3bba8 7070 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7071 gen_io_end();
2e70f6ef 7072 }
55807224 7073 /* Break the TB to be able to take timer interrupts immediately
b28425ba
EC
7074 after reading count. DISAS_STOP isn't sufficient, we need to
7075 ensure we break completely out of translated code. */
eeb3bba8
EC
7076 gen_save_pc(ctx->base.pc_next + 4);
7077 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7078 register_name = "Count";
2423f660 7079 break;
5fb2dcd1
YK
7080 case 6:
7081 CP0_CHECK(ctx->saar);
7082 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 7083 register_name = "SAARI";
5fb2dcd1
YK
7084 break;
7085 case 7:
7086 CP0_CHECK(ctx->saar);
7087 gen_helper_mfc0_saar(arg, cpu_env);
294fc2ea 7088 register_name = "SAAR";
5fb2dcd1 7089 break;
7a387fff 7090 default:
f31b035a 7091 goto cp0_unimplemented;
2423f660 7092 }
873eb012 7093 break;
04992c8c 7094 case CP0_REGISTER_10:
7a387fff
TS
7095 switch (sel) {
7096 case 0:
7db13fae 7097 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 7098 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7099 register_name = "EntryHi";
2423f660 7100 break;
7a387fff 7101 default:
f31b035a 7102 goto cp0_unimplemented;
1579a72e 7103 }
873eb012 7104 break;
04992c8c 7105 case CP0_REGISTER_11:
7a387fff
TS
7106 switch (sel) {
7107 case 0:
7db13fae 7108 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 7109 register_name = "Compare";
2423f660
TS
7110 break;
7111 /* 6,7 are implementation dependent */
7a387fff 7112 default:
f31b035a 7113 goto cp0_unimplemented;
2423f660 7114 }
873eb012 7115 break;
04992c8c 7116 case CP0_REGISTER_12:
7a387fff
TS
7117 switch (sel) {
7118 case 0:
7db13fae 7119 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 7120 register_name = "Status";
2423f660 7121 break;
7a387fff 7122 case 1:
d75c135e 7123 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7124 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 7125 register_name = "IntCtl";
2423f660 7126 break;
7a387fff 7127 case 2:
d75c135e 7128 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7129 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 7130 register_name = "SRSCtl";
2423f660 7131 break;
7a387fff 7132 case 3:
d75c135e 7133 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7134 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 7135 register_name = "SRSMap";
fd88b6ab 7136 break;
7a387fff 7137 default:
f31b035a 7138 goto cp0_unimplemented;
7a387fff 7139 }
873eb012 7140 break;
04992c8c 7141 case CP0_REGISTER_13:
7a387fff
TS
7142 switch (sel) {
7143 case 0:
7db13fae 7144 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 7145 register_name = "Cause";
2423f660 7146 break;
7a387fff 7147 default:
f31b035a 7148 goto cp0_unimplemented;
7a387fff 7149 }
873eb012 7150 break;
04992c8c 7151 case CP0_REGISTER_14:
7a387fff
TS
7152 switch (sel) {
7153 case 0:
7db13fae 7154 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 7155 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7156 register_name = "EPC";
2423f660 7157 break;
7a387fff 7158 default:
f31b035a 7159 goto cp0_unimplemented;
1579a72e 7160 }
873eb012 7161 break;
04992c8c 7162 case CP0_REGISTER_15:
7a387fff
TS
7163 switch (sel) {
7164 case 0:
7db13fae 7165 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 7166 register_name = "PRid";
2423f660 7167 break;
7a387fff 7168 case 1:
d75c135e 7169 check_insn(ctx, ISA_MIPS32R2);
74dbf824
JH
7170 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7171 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7172 register_name = "EBase";
2423f660 7173 break;
c870e3f5
YK
7174 case 3:
7175 check_insn(ctx, ISA_MIPS32R2);
7176 CP0_CHECK(ctx->cmgcr);
7177 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7178 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7179 register_name = "CMGCRBase";
c870e3f5 7180 break;
7a387fff 7181 default:
f31b035a 7182 goto cp0_unimplemented;
7a387fff 7183 }
873eb012 7184 break;
04992c8c 7185 case CP0_REGISTER_16:
873eb012
TS
7186 switch (sel) {
7187 case 0:
7db13fae 7188 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 7189 register_name = "Config";
873eb012
TS
7190 break;
7191 case 1:
7db13fae 7192 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 7193 register_name = "Config1";
873eb012 7194 break;
7a387fff 7195 case 2:
7db13fae 7196 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 7197 register_name = "Config2";
7a387fff
TS
7198 break;
7199 case 3:
7db13fae 7200 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 7201 register_name = "Config3";
7a387fff 7202 break;
b4160af1
PJ
7203 case 4:
7204 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 7205 register_name = "Config4";
b4160af1 7206 break;
b4dd99a3
PJ
7207 case 5:
7208 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 7209 register_name = "Config5";
b4dd99a3 7210 break;
e397ee33
TS
7211 /* 6,7 are implementation dependent */
7212 case 6:
7db13fae 7213 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 7214 register_name = "Config6";
e397ee33
TS
7215 break;
7216 case 7:
7db13fae 7217 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 7218 register_name = "Config7";
e397ee33 7219 break;
873eb012 7220 default:
f31b035a 7221 goto cp0_unimplemented;
873eb012
TS
7222 }
7223 break;
04992c8c 7224 case CP0_REGISTER_17:
7a387fff
TS
7225 switch (sel) {
7226 case 0:
895c2d04 7227 gen_helper_mfc0_lladdr(arg, cpu_env);
294fc2ea 7228 register_name = "LLAddr";
2423f660 7229 break;
f6d4dd81
YK
7230 case 1:
7231 CP0_CHECK(ctx->mrp);
7232 gen_helper_mfc0_maar(arg, cpu_env);
294fc2ea 7233 register_name = "MAAR";
f6d4dd81
YK
7234 break;
7235 case 2:
7236 CP0_CHECK(ctx->mrp);
7237 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 7238 register_name = "MAARI";
f6d4dd81 7239 break;
7a387fff 7240 default:
f31b035a 7241 goto cp0_unimplemented;
7a387fff 7242 }
873eb012 7243 break;
04992c8c 7244 case CP0_REGISTER_18:
7a387fff 7245 switch (sel) {
c2e19f3c
AM
7246 case 0:
7247 case 1:
7248 case 2:
7249 case 3:
7250 case 4:
7251 case 5:
7252 case 6:
7253 case 7:
fa192d49 7254 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7255 gen_helper_1e0i(mfc0_watchlo, arg, sel);
294fc2ea 7256 register_name = "WatchLo";
2423f660 7257 break;
7a387fff 7258 default:
f31b035a 7259 goto cp0_unimplemented;
7a387fff 7260 }
873eb012 7261 break;
04992c8c 7262 case CP0_REGISTER_19:
7a387fff 7263 switch (sel) {
c2e19f3c
AM
7264 case 0:
7265 case 1:
7266 case 2:
7267 case 3:
7268 case 4:
7269 case 5:
7270 case 6:
7271 case 7:
fa192d49 7272 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7273 gen_helper_1e0i(mfc0_watchhi, arg, sel);
294fc2ea 7274 register_name = "WatchHi";
2423f660 7275 break;
7a387fff 7276 default:
f31b035a 7277 goto cp0_unimplemented;
7a387fff 7278 }
873eb012 7279 break;
04992c8c 7280 case CP0_REGISTER_20:
7a387fff
TS
7281 switch (sel) {
7282 case 0:
d26bc211 7283#if defined(TARGET_MIPS64)
d75c135e 7284 check_insn(ctx, ISA_MIPS3);
7db13fae 7285 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 7286 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7287 register_name = "XContext";
2423f660 7288 break;
703eaf37 7289#endif
7a387fff 7290 default:
f31b035a 7291 goto cp0_unimplemented;
7a387fff 7292 }
8c0fdd85 7293 break;
04992c8c 7294 case CP0_REGISTER_21:
7a387fff 7295 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 7296 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
7297 switch (sel) {
7298 case 0:
7db13fae 7299 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 7300 register_name = "Framemask";
2423f660 7301 break;
7a387fff 7302 default:
f31b035a 7303 goto cp0_unimplemented;
7a387fff 7304 }
8c0fdd85 7305 break;
04992c8c 7306 case CP0_REGISTER_22:
d9bea114 7307 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 7308 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 7309 break;
04992c8c 7310 case CP0_REGISTER_23:
7a387fff
TS
7311 switch (sel) {
7312 case 0:
895c2d04 7313 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 7314 register_name = "Debug";
2423f660 7315 break;
7a387fff 7316 case 1:
d9bea114 7317// gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
294fc2ea 7318 register_name = "TraceControl";
3570d7f6 7319 goto cp0_unimplemented;
7a387fff 7320 case 2:
d9bea114 7321// gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
294fc2ea 7322 register_name = "TraceControl2";
3570d7f6 7323 goto cp0_unimplemented;
7a387fff 7324 case 3:
d9bea114 7325// gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
294fc2ea 7326 register_name = "UserTraceData";
3570d7f6 7327 goto cp0_unimplemented;
7a387fff 7328 case 4:
d9bea114 7329// gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
294fc2ea 7330 register_name = "TraceBPC";
3570d7f6 7331 goto cp0_unimplemented;
7a387fff 7332 default:
f31b035a 7333 goto cp0_unimplemented;
7a387fff 7334 }
873eb012 7335 break;
04992c8c 7336 case CP0_REGISTER_24:
7a387fff
TS
7337 switch (sel) {
7338 case 0:
f0b3f3ae 7339 /* EJTAG support */
7db13fae 7340 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 7341 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7342 register_name = "DEPC";
2423f660 7343 break;
7a387fff 7344 default:
f31b035a 7345 goto cp0_unimplemented;
7a387fff 7346 }
873eb012 7347 break;
04992c8c 7348 case CP0_REGISTER_25:
7a387fff
TS
7349 switch (sel) {
7350 case 0:
7db13fae 7351 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 7352 register_name = "Performance0";
7a387fff
TS
7353 break;
7354 case 1:
d9bea114 7355// gen_helper_mfc0_performance1(arg);
294fc2ea 7356 register_name = "Performance1";
3570d7f6 7357 goto cp0_unimplemented;
7a387fff 7358 case 2:
d9bea114 7359// gen_helper_mfc0_performance2(arg);
294fc2ea 7360 register_name = "Performance2";
3570d7f6 7361 goto cp0_unimplemented;
7a387fff 7362 case 3:
d9bea114 7363// gen_helper_mfc0_performance3(arg);
294fc2ea 7364 register_name = "Performance3";
3570d7f6 7365 goto cp0_unimplemented;
7a387fff 7366 case 4:
d9bea114 7367// gen_helper_mfc0_performance4(arg);
294fc2ea 7368 register_name = "Performance4";
3570d7f6 7369 goto cp0_unimplemented;
7a387fff 7370 case 5:
d9bea114 7371// gen_helper_mfc0_performance5(arg);
294fc2ea 7372 register_name = "Performance5";
3570d7f6 7373 goto cp0_unimplemented;
7a387fff 7374 case 6:
d9bea114 7375// gen_helper_mfc0_performance6(arg);
294fc2ea 7376 register_name = "Performance6";
3570d7f6 7377 goto cp0_unimplemented;
7a387fff 7378 case 7:
d9bea114 7379// gen_helper_mfc0_performance7(arg);
294fc2ea 7380 register_name = "Performance7";
3570d7f6 7381 goto cp0_unimplemented;
7a387fff 7382 default:
f31b035a 7383 goto cp0_unimplemented;
7a387fff 7384 }
8c0fdd85 7385 break;
04992c8c 7386 case CP0_REGISTER_26:
0d74a222
LA
7387 switch (sel) {
7388 case 0:
7389 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 7390 register_name = "ErrCtl";
0d74a222
LA
7391 break;
7392 default:
7393 goto cp0_unimplemented;
7394 }
da80682b 7395 break;
04992c8c 7396 case CP0_REGISTER_27:
7a387fff 7397 switch (sel) {
c2e19f3c
AM
7398 case 0:
7399 case 1:
7400 case 2:
7401 case 3:
d9bea114 7402 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 7403 register_name = "CacheErr";
2423f660 7404 break;
7a387fff 7405 default:
f31b035a 7406 goto cp0_unimplemented;
7a387fff 7407 }
8c0fdd85 7408 break;
04992c8c 7409 case CP0_REGISTER_28:
873eb012
TS
7410 switch (sel) {
7411 case 0:
7a387fff
TS
7412 case 2:
7413 case 4:
7414 case 6:
284b731a
LA
7415 {
7416 TCGv_i64 tmp = tcg_temp_new_i64();
7417 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7418 gen_move_low32(arg, tmp);
7419 tcg_temp_free_i64(tmp);
7420 }
294fc2ea 7421 register_name = "TagLo";
873eb012
TS
7422 break;
7423 case 1:
7a387fff
TS
7424 case 3:
7425 case 5:
7426 case 7:
7db13fae 7427 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 7428 register_name = "DataLo";
873eb012
TS
7429 break;
7430 default:
f31b035a 7431 goto cp0_unimplemented;
873eb012
TS
7432 }
7433 break;
04992c8c 7434 case CP0_REGISTER_29:
7a387fff
TS
7435 switch (sel) {
7436 case 0:
7437 case 2:
7438 case 4:
7439 case 6:
7db13fae 7440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 7441 register_name = "TagHi";
7a387fff
TS
7442 break;
7443 case 1:
7444 case 3:
7445 case 5:
7446 case 7:
7db13fae 7447 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 7448 register_name = "DataHi";
7a387fff
TS
7449 break;
7450 default:
f31b035a 7451 goto cp0_unimplemented;
7a387fff 7452 }
8c0fdd85 7453 break;
04992c8c 7454 case CP0_REGISTER_30:
7a387fff
TS
7455 switch (sel) {
7456 case 0:
7db13fae 7457 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 7458 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7459 register_name = "ErrorEPC";
2423f660 7460 break;
7a387fff 7461 default:
f31b035a 7462 goto cp0_unimplemented;
7a387fff 7463 }
873eb012 7464 break;
04992c8c 7465 case CP0_REGISTER_31:
7a387fff
TS
7466 switch (sel) {
7467 case 0:
f0b3f3ae 7468 /* EJTAG support */
7db13fae 7469 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 7470 register_name = "DESAVE";
2423f660 7471 break;
c2e19f3c
AM
7472 case 2:
7473 case 3:
7474 case 4:
7475 case 5:
7476 case 6:
7477 case 7:
f31b035a
LA
7478 CP0_CHECK(ctx->kscrexist & (1 << sel));
7479 tcg_gen_ld_tl(arg, cpu_env,
7480 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7481 tcg_gen_ext32s_tl(arg, arg);
294fc2ea 7482 register_name = "KScratch";
e98c0d17 7483 break;
7a387fff 7484 default:
f31b035a 7485 goto cp0_unimplemented;
7a387fff 7486 }
873eb012
TS
7487 break;
7488 default:
f31b035a 7489 goto cp0_unimplemented;
873eb012 7490 }
294fc2ea 7491 trace_mips_translate_c0("mfc0", register_name, reg, sel);
873eb012
TS
7492 return;
7493
f31b035a 7494cp0_unimplemented:
294fc2ea
AM
7495 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7496 register_name, reg, sel);
f31b035a 7497 gen_mfc0_unimplemented(ctx, arg);
873eb012
TS
7498}
7499
d75c135e 7500static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 7501{
294fc2ea 7502 const char *register_name = "invalid";
7a387fff 7503
e189e748 7504 if (sel != 0)
d75c135e 7505 check_insn(ctx, ISA_MIPS32);
e189e748 7506
eeb3bba8 7507 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7508 gen_io_start();
bd79255d 7509 }
2e70f6ef 7510
8c0fdd85 7511 switch (reg) {
04992c8c 7512 case CP0_REGISTER_00:
7a387fff
TS
7513 switch (sel) {
7514 case 0:
895c2d04 7515 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 7516 register_name = "Index";
7a387fff
TS
7517 break;
7518 case 1:
f31b035a 7519 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7520 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 7521 register_name = "MVPControl";
ead9360e 7522 break;
7a387fff 7523 case 2:
f31b035a 7524 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7525 /* ignored */
294fc2ea 7526 register_name = "MVPConf0";
ead9360e 7527 break;
7a387fff 7528 case 3:
f31b035a 7529 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7530 /* ignored */
294fc2ea 7531 register_name = "MVPConf1";
ead9360e 7532 break;
01bc435b
YK
7533 case 4:
7534 CP0_CHECK(ctx->vp);
7535 /* ignored */
294fc2ea 7536 register_name = "VPControl";
01bc435b 7537 break;
7a387fff 7538 default:
f31b035a 7539 goto cp0_unimplemented;
7a387fff 7540 }
8c0fdd85 7541 break;
04992c8c 7542 case CP0_REGISTER_01:
7a387fff
TS
7543 switch (sel) {
7544 case 0:
2423f660 7545 /* ignored */
294fc2ea 7546 register_name = "Random";
2423f660 7547 break;
7a387fff 7548 case 1:
f31b035a 7549 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7550 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 7551 register_name = "VPEControl";
ead9360e 7552 break;
7a387fff 7553 case 2:
f31b035a 7554 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7555 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 7556 register_name = "VPEConf0";
ead9360e 7557 break;
7a387fff 7558 case 3:
f31b035a 7559 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7560 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 7561 register_name = "VPEConf1";
ead9360e 7562 break;
7a387fff 7563 case 4:
f31b035a 7564 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7565 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 7566 register_name = "YQMask";
ead9360e 7567 break;
7a387fff 7568 case 5:
f31b035a 7569 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
7570 tcg_gen_st_tl(arg, cpu_env,
7571 offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 7572 register_name = "VPESchedule";
ead9360e 7573 break;
7a387fff 7574 case 6:
f31b035a 7575 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
7576 tcg_gen_st_tl(arg, cpu_env,
7577 offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 7578 register_name = "VPEScheFBack";
ead9360e 7579 break;
7a387fff 7580 case 7:
f31b035a 7581 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7582 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 7583 register_name = "VPEOpt";
ead9360e 7584 break;
7a387fff 7585 default:
f31b035a 7586 goto cp0_unimplemented;
7a387fff 7587 }
8c0fdd85 7588 break;
04992c8c 7589 case CP0_REGISTER_02:
7a387fff
TS
7590 switch (sel) {
7591 case 0:
895c2d04 7592 gen_helper_mtc0_entrylo0(cpu_env, arg);
294fc2ea 7593 register_name = "EntryLo0";
2423f660 7594 break;
7a387fff 7595 case 1:
f31b035a 7596 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7597 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 7598 register_name = "TCStatus";
ead9360e 7599 break;
7a387fff 7600 case 2:
f31b035a 7601 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7602 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 7603 register_name = "TCBind";
ead9360e 7604 break;
7a387fff 7605 case 3:
f31b035a 7606 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7607 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 7608 register_name = "TCRestart";
ead9360e 7609 break;
7a387fff 7610 case 4:
f31b035a 7611 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7612 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 7613 register_name = "TCHalt";
ead9360e 7614 break;
7a387fff 7615 case 5:
f31b035a 7616 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7617 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 7618 register_name = "TCContext";
ead9360e 7619 break;
7a387fff 7620 case 6:
f31b035a 7621 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7622 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 7623 register_name = "TCSchedule";
ead9360e 7624 break;
7a387fff 7625 case 7:
f31b035a 7626 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7627 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 7628 register_name = "TCScheFBack";
ead9360e 7629 break;
7a387fff 7630 default:
f31b035a 7631 goto cp0_unimplemented;
7a387fff 7632 }
8c0fdd85 7633 break;
04992c8c 7634 case CP0_REGISTER_03:
7a387fff
TS
7635 switch (sel) {
7636 case 0:
895c2d04 7637 gen_helper_mtc0_entrylo1(cpu_env, arg);
294fc2ea 7638 register_name = "EntryLo1";
2423f660 7639 break;
01bc435b
YK
7640 case 1:
7641 CP0_CHECK(ctx->vp);
7642 /* ignored */
294fc2ea 7643 register_name = "GlobalNumber";
01bc435b 7644 break;
7a387fff 7645 default:
f31b035a 7646 goto cp0_unimplemented;
876d4b07 7647 }
8c0fdd85 7648 break;
04992c8c 7649 case CP0_REGISTER_04:
7a387fff
TS
7650 switch (sel) {
7651 case 0:
895c2d04 7652 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 7653 register_name = "Context";
2423f660 7654 break;
7a387fff 7655 case 1:
895c2d04 7656// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
294fc2ea 7657 register_name = "ContextConfig";
f31b035a 7658 goto cp0_unimplemented;
d279279e 7659 case 2:
f31b035a
LA
7660 CP0_CHECK(ctx->ulri);
7661 tcg_gen_st_tl(arg, cpu_env,
7662 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 7663 register_name = "UserLocal";
d279279e 7664 break;
7a387fff 7665 default:
f31b035a 7666 goto cp0_unimplemented;
876d4b07 7667 }
8c0fdd85 7668 break;
04992c8c 7669 case CP0_REGISTER_05:
7a387fff
TS
7670 switch (sel) {
7671 case 0:
895c2d04 7672 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 7673 register_name = "PageMask";
2423f660 7674 break;
7a387fff 7675 case 1:
d75c135e 7676 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7677 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 7678 register_name = "PageGrain";
eeb3bba8 7679 ctx->base.is_jmp = DISAS_STOP;
2423f660 7680 break;
cec56a73
JH
7681 case 2:
7682 CP0_CHECK(ctx->sc);
7683 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 7684 register_name = "SegCtl0";
cec56a73
JH
7685 break;
7686 case 3:
7687 CP0_CHECK(ctx->sc);
7688 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 7689 register_name = "SegCtl1";
cec56a73
JH
7690 break;
7691 case 4:
7692 CP0_CHECK(ctx->sc);
7693 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 7694 register_name = "SegCtl2";
cec56a73 7695 break;
5e31fdd5
YK
7696 case 5:
7697 check_pw(ctx);
7698 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 7699 register_name = "PWBase";
5e31fdd5 7700 break;
fa75ad14
YK
7701 case 6:
7702 check_pw(ctx);
7703 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 7704 register_name = "PWField";
fa75ad14 7705 break;
20b28ebc
YK
7706 case 7:
7707 check_pw(ctx);
7708 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 7709 register_name = "PWSize";
20b28ebc 7710 break;
7a387fff 7711 default:
f31b035a 7712 goto cp0_unimplemented;
876d4b07 7713 }
8c0fdd85 7714 break;
04992c8c 7715 case CP0_REGISTER_06:
7a387fff
TS
7716 switch (sel) {
7717 case 0:
895c2d04 7718 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 7719 register_name = "Wired";
2423f660 7720 break;
7a387fff 7721 case 1:
d75c135e 7722 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7723 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 7724 register_name = "SRSConf0";
ead9360e 7725 break;
7a387fff 7726 case 2:
d75c135e 7727 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7728 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 7729 register_name = "SRSConf1";
ead9360e 7730 break;
7a387fff 7731 case 3:
d75c135e 7732 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7733 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 7734 register_name = "SRSConf2";
ead9360e 7735 break;
7a387fff 7736 case 4:
d75c135e 7737 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7738 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 7739 register_name = "SRSConf3";
ead9360e 7740 break;
7a387fff 7741 case 5:
d75c135e 7742 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7743 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 7744 register_name = "SRSConf4";
ead9360e 7745 break;
103be64c
YK
7746 case 6:
7747 check_pw(ctx);
7748 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 7749 register_name = "PWCtl";
103be64c 7750 break;
7a387fff 7751 default:
f31b035a 7752 goto cp0_unimplemented;
876d4b07 7753 }
8c0fdd85 7754 break;
04992c8c 7755 case CP0_REGISTER_07:
7a387fff
TS
7756 switch (sel) {
7757 case 0:
d75c135e 7758 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7759 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 7760 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7761 register_name = "HWREna";
2423f660 7762 break;
7a387fff 7763 default:
f31b035a 7764 goto cp0_unimplemented;
876d4b07 7765 }
8c0fdd85 7766 break;
04992c8c 7767 case CP0_REGISTER_08:
aea14095
LA
7768 switch (sel) {
7769 case 0:
7770 /* ignored */
294fc2ea 7771 register_name = "BadVAddr";
aea14095
LA
7772 break;
7773 case 1:
7774 /* ignored */
294fc2ea 7775 register_name = "BadInstr";
aea14095
LA
7776 break;
7777 case 2:
7778 /* ignored */
294fc2ea 7779 register_name = "BadInstrP";
aea14095 7780 break;
25beba9b
SM
7781 case 3:
7782 /* ignored */
294fc2ea 7783 register_name = "BadInstrX";
25beba9b 7784 break;
aea14095 7785 default:
f31b035a 7786 goto cp0_unimplemented;
aea14095 7787 }
8c0fdd85 7788 break;
04992c8c 7789 case CP0_REGISTER_09:
7a387fff
TS
7790 switch (sel) {
7791 case 0:
895c2d04 7792 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 7793 register_name = "Count";
2423f660 7794 break;
5fb2dcd1
YK
7795 case 6:
7796 CP0_CHECK(ctx->saar);
7797 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 7798 register_name = "SAARI";
5fb2dcd1
YK
7799 break;
7800 case 7:
7801 CP0_CHECK(ctx->saar);
7802 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 7803 register_name = "SAAR";
5fb2dcd1 7804 break;
7a387fff 7805 default:
f31b035a 7806 goto cp0_unimplemented;
876d4b07 7807 }
8c0fdd85 7808 break;
04992c8c 7809 case CP0_REGISTER_10:
7a387fff
TS
7810 switch (sel) {
7811 case 0:
895c2d04 7812 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 7813 register_name = "EntryHi";
2423f660 7814 break;
7a387fff 7815 default:
f31b035a 7816 goto cp0_unimplemented;
876d4b07 7817 }
8c0fdd85 7818 break;
04992c8c 7819 case CP0_REGISTER_11:
7a387fff
TS
7820 switch (sel) {
7821 case 0:
895c2d04 7822 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 7823 register_name = "Compare";
2423f660
TS
7824 break;
7825 /* 6,7 are implementation dependent */
7a387fff 7826 default:
f31b035a 7827 goto cp0_unimplemented;
876d4b07 7828 }
8c0fdd85 7829 break;
04992c8c 7830 case CP0_REGISTER_12:
7a387fff
TS
7831 switch (sel) {
7832 case 0:
867abc7e 7833 save_cpu_state(ctx, 1);
895c2d04 7834 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 7835 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
7836 gen_save_pc(ctx->base.pc_next + 4);
7837 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7838 register_name = "Status";
2423f660 7839 break;
7a387fff 7840 case 1:
d75c135e 7841 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7842 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 7843 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7844 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7845 register_name = "IntCtl";
2423f660 7846 break;
7a387fff 7847 case 2:
d75c135e 7848 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7849 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 7850 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7851 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7852 register_name = "SRSCtl";
2423f660 7853 break;
7a387fff 7854 case 3:
d75c135e 7855 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7856 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 7857 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7858 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 7859 register_name = "SRSMap";
fd88b6ab 7860 break;
7a387fff 7861 default:
f31b035a 7862 goto cp0_unimplemented;
876d4b07 7863 }
8c0fdd85 7864 break;
04992c8c 7865 case CP0_REGISTER_13:
7a387fff
TS
7866 switch (sel) {
7867 case 0:
867abc7e 7868 save_cpu_state(ctx, 1);
895c2d04 7869 gen_helper_mtc0_cause(cpu_env, arg);
b28425ba
EC
7870 /* Stop translation as we may have triggered an interrupt.
7871 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7872 * translated code to check for pending interrupts. */
eeb3bba8
EC
7873 gen_save_pc(ctx->base.pc_next + 4);
7874 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 7875 register_name = "Cause";
2423f660 7876 break;
7a387fff 7877 default:
f31b035a 7878 goto cp0_unimplemented;
876d4b07 7879 }
8c0fdd85 7880 break;
04992c8c 7881 case CP0_REGISTER_14:
7a387fff
TS
7882 switch (sel) {
7883 case 0:
d54a299b 7884 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 7885 register_name = "EPC";
2423f660 7886 break;
7a387fff 7887 default:
f31b035a 7888 goto cp0_unimplemented;
876d4b07 7889 }
8c0fdd85 7890 break;
04992c8c 7891 case CP0_REGISTER_15:
7a387fff
TS
7892 switch (sel) {
7893 case 0:
2423f660 7894 /* ignored */
294fc2ea 7895 register_name = "PRid";
2423f660 7896 break;
7a387fff 7897 case 1:
d75c135e 7898 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7899 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 7900 register_name = "EBase";
2423f660 7901 break;
7a387fff 7902 default:
f31b035a 7903 goto cp0_unimplemented;
1579a72e 7904 }
8c0fdd85 7905 break;
04992c8c 7906 case CP0_REGISTER_16:
8c0fdd85
TS
7907 switch (sel) {
7908 case 0:
895c2d04 7909 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 7910 register_name = "Config";
2423f660 7911 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7912 ctx->base.is_jmp = DISAS_STOP;
7a387fff
TS
7913 break;
7914 case 1:
e397ee33 7915 /* ignored, read only */
294fc2ea 7916 register_name = "Config1";
7a387fff
TS
7917 break;
7918 case 2:
895c2d04 7919 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 7920 register_name = "Config2";
2423f660 7921 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7922 ctx->base.is_jmp = DISAS_STOP;
8c0fdd85 7923 break;
7a387fff 7924 case 3:
90f12d73 7925 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 7926 register_name = "Config3";
90f12d73 7927 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7928 ctx->base.is_jmp = DISAS_STOP;
7a387fff 7929 break;
b4160af1
PJ
7930 case 4:
7931 gen_helper_mtc0_config4(cpu_env, arg);
294fc2ea 7932 register_name = "Config4";
eeb3bba8 7933 ctx->base.is_jmp = DISAS_STOP;
b4160af1 7934 break;
b4dd99a3
PJ
7935 case 5:
7936 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 7937 register_name = "Config5";
b4dd99a3 7938 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7939 ctx->base.is_jmp = DISAS_STOP;
b4dd99a3 7940 break;
e397ee33
TS
7941 /* 6,7 are implementation dependent */
7942 case 6:
7943 /* ignored */
294fc2ea 7944 register_name = "Config6";
e397ee33
TS
7945 break;
7946 case 7:
7947 /* ignored */
294fc2ea 7948 register_name = "Config7";
e397ee33 7949 break;
8c0fdd85 7950 default:
294fc2ea 7951 register_name = "Invalid config selector";
f31b035a 7952 goto cp0_unimplemented;
8c0fdd85
TS
7953 }
7954 break;
04992c8c 7955 case CP0_REGISTER_17:
7a387fff
TS
7956 switch (sel) {
7957 case 0:
895c2d04 7958 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 7959 register_name = "LLAddr";
2423f660 7960 break;
f6d4dd81
YK
7961 case 1:
7962 CP0_CHECK(ctx->mrp);
7963 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 7964 register_name = "MAAR";
f6d4dd81
YK
7965 break;
7966 case 2:
7967 CP0_CHECK(ctx->mrp);
7968 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 7969 register_name = "MAARI";
f6d4dd81 7970 break;
7a387fff 7971 default:
f31b035a 7972 goto cp0_unimplemented;
7a387fff 7973 }
8c0fdd85 7974 break;
04992c8c 7975 case CP0_REGISTER_18:
7a387fff 7976 switch (sel) {
c2e19f3c
AM
7977 case 0:
7978 case 1:
7979 case 2:
7980 case 3:
7981 case 4:
7982 case 5:
7983 case 6:
7984 case 7:
fa192d49 7985 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7986 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 7987 register_name = "WatchLo";
2423f660 7988 break;
7a387fff 7989 default:
f31b035a 7990 goto cp0_unimplemented;
7a387fff 7991 }
8c0fdd85 7992 break;
04992c8c 7993 case CP0_REGISTER_19:
7a387fff 7994 switch (sel) {
c2e19f3c
AM
7995 case 0:
7996 case 1:
7997 case 2:
7998 case 3:
7999 case 4:
8000 case 5:
8001 case 6:
8002 case 7:
fa192d49 8003 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8004 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 8005 register_name = "WatchHi";
2423f660 8006 break;
7a387fff 8007 default:
f31b035a 8008 goto cp0_unimplemented;
7a387fff 8009 }
8c0fdd85 8010 break;
04992c8c 8011 case CP0_REGISTER_20:
7a387fff
TS
8012 switch (sel) {
8013 case 0:
d26bc211 8014#if defined(TARGET_MIPS64)
d75c135e 8015 check_insn(ctx, ISA_MIPS3);
895c2d04 8016 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 8017 register_name = "XContext";
2423f660 8018 break;
703eaf37 8019#endif
7a387fff 8020 default:
f31b035a 8021 goto cp0_unimplemented;
7a387fff 8022 }
8c0fdd85 8023 break;
04992c8c 8024 case CP0_REGISTER_21:
7a387fff 8025 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 8026 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
8027 switch (sel) {
8028 case 0:
895c2d04 8029 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 8030 register_name = "Framemask";
2423f660 8031 break;
7a387fff 8032 default:
f31b035a 8033 goto cp0_unimplemented;
7a387fff
TS
8034 }
8035 break;
04992c8c 8036 case CP0_REGISTER_22:
7a387fff 8037 /* ignored */
294fc2ea 8038 register_name = "Diagnostic"; /* implementation dependent */
2423f660 8039 break;
04992c8c 8040 case CP0_REGISTER_23:
7a387fff
TS
8041 switch (sel) {
8042 case 0:
895c2d04 8043 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 8044 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8045 gen_save_pc(ctx->base.pc_next + 4);
8046 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8047 register_name = "Debug";
2423f660 8048 break;
7a387fff 8049 case 1:
895c2d04 8050// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
294fc2ea 8051 register_name = "TraceControl";
8487327a 8052 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8053 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8054 goto cp0_unimplemented;
7a387fff 8055 case 2:
895c2d04 8056// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
294fc2ea 8057 register_name = "TraceControl2";
8487327a 8058 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8059 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8060 goto cp0_unimplemented;
7a387fff 8061 case 3:
8487327a 8062 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8063 ctx->base.is_jmp = DISAS_STOP;
895c2d04 8064// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
294fc2ea 8065 register_name = "UserTraceData";
8487327a 8066 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8067 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 8068 goto cp0_unimplemented;
7a387fff 8069 case 4:
895c2d04 8070// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a 8071 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8072 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8073 register_name = "TraceBPC";
3570d7f6 8074 goto cp0_unimplemented;
7a387fff 8075 default:
f31b035a 8076 goto cp0_unimplemented;
7a387fff 8077 }
8c0fdd85 8078 break;
04992c8c 8079 case CP0_REGISTER_24:
7a387fff
TS
8080 switch (sel) {
8081 case 0:
f1aa6320 8082 /* EJTAG support */
d54a299b 8083 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 8084 register_name = "DEPC";
2423f660 8085 break;
7a387fff 8086 default:
f31b035a 8087 goto cp0_unimplemented;
7a387fff 8088 }
8c0fdd85 8089 break;
04992c8c 8090 case CP0_REGISTER_25:
7a387fff
TS
8091 switch (sel) {
8092 case 0:
895c2d04 8093 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 8094 register_name = "Performance0";
2423f660 8095 break;
7a387fff 8096 case 1:
d9bea114 8097// gen_helper_mtc0_performance1(arg);
294fc2ea 8098 register_name = "Performance1";
3570d7f6 8099 goto cp0_unimplemented;
7a387fff 8100 case 2:
d9bea114 8101// gen_helper_mtc0_performance2(arg);
294fc2ea 8102 register_name = "Performance2";
3570d7f6 8103 goto cp0_unimplemented;
7a387fff 8104 case 3:
d9bea114 8105// gen_helper_mtc0_performance3(arg);
294fc2ea 8106 register_name = "Performance3";
3570d7f6 8107 goto cp0_unimplemented;
7a387fff 8108 case 4:
d9bea114 8109// gen_helper_mtc0_performance4(arg);
294fc2ea 8110 register_name = "Performance4";
3570d7f6 8111 goto cp0_unimplemented;
7a387fff 8112 case 5:
d9bea114 8113// gen_helper_mtc0_performance5(arg);
294fc2ea 8114 register_name = "Performance5";
3570d7f6 8115 goto cp0_unimplemented;
7a387fff 8116 case 6:
d9bea114 8117// gen_helper_mtc0_performance6(arg);
294fc2ea 8118 register_name = "Performance6";
3570d7f6 8119 goto cp0_unimplemented;
7a387fff 8120 case 7:
d9bea114 8121// gen_helper_mtc0_performance7(arg);
294fc2ea 8122 register_name = "Performance7";
3570d7f6 8123 goto cp0_unimplemented;
7a387fff 8124 default:
f31b035a 8125 goto cp0_unimplemented;
7a387fff 8126 }
8c0fdd85 8127 break;
04992c8c 8128 case CP0_REGISTER_26:
0d74a222
LA
8129 switch (sel) {
8130 case 0:
8131 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 8132 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 8133 register_name = "ErrCtl";
0d74a222
LA
8134 break;
8135 default:
8136 goto cp0_unimplemented;
8137 }
2423f660 8138 break;
04992c8c 8139 case CP0_REGISTER_27:
7a387fff 8140 switch (sel) {
c2e19f3c
AM
8141 case 0:
8142 case 1:
8143 case 2:
8144 case 3:
2423f660 8145 /* ignored */
294fc2ea 8146 register_name = "CacheErr";
2423f660 8147 break;
7a387fff 8148 default:
f31b035a 8149 goto cp0_unimplemented;
7a387fff 8150 }
8c0fdd85 8151 break;
04992c8c 8152 case CP0_REGISTER_28:
8c0fdd85
TS
8153 switch (sel) {
8154 case 0:
7a387fff
TS
8155 case 2:
8156 case 4:
8157 case 6:
895c2d04 8158 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 8159 register_name = "TagLo";
8c0fdd85 8160 break;
7a387fff
TS
8161 case 1:
8162 case 3:
8163 case 5:
8164 case 7:
895c2d04 8165 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 8166 register_name = "DataLo";
7a387fff 8167 break;
8c0fdd85 8168 default:
f31b035a 8169 goto cp0_unimplemented;
8c0fdd85
TS
8170 }
8171 break;
04992c8c 8172 case CP0_REGISTER_29:
7a387fff
TS
8173 switch (sel) {
8174 case 0:
8175 case 2:
8176 case 4:
8177 case 6:
895c2d04 8178 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 8179 register_name = "TagHi";
7a387fff
TS
8180 break;
8181 case 1:
8182 case 3:
8183 case 5:
8184 case 7:
895c2d04 8185 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 8186 register_name = "DataHi";
7a387fff
TS
8187 break;
8188 default:
294fc2ea 8189 register_name = "invalid sel";
f31b035a 8190 goto cp0_unimplemented;
7a387fff 8191 }
8c0fdd85 8192 break;
04992c8c 8193 case CP0_REGISTER_30:
7a387fff
TS
8194 switch (sel) {
8195 case 0:
d54a299b 8196 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 8197 register_name = "ErrorEPC";
2423f660 8198 break;
7a387fff 8199 default:
f31b035a 8200 goto cp0_unimplemented;
7a387fff 8201 }
8c0fdd85 8202 break;
04992c8c 8203 case CP0_REGISTER_31:
7a387fff
TS
8204 switch (sel) {
8205 case 0:
f1aa6320 8206 /* EJTAG support */
7db13fae 8207 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 8208 register_name = "DESAVE";
2423f660 8209 break;
c2e19f3c
AM
8210 case 2:
8211 case 3:
8212 case 4:
8213 case 5:
8214 case 6:
8215 case 7:
f31b035a
LA
8216 CP0_CHECK(ctx->kscrexist & (1 << sel));
8217 tcg_gen_st_tl(arg, cpu_env,
8218 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
294fc2ea 8219 register_name = "KScratch";
e98c0d17 8220 break;
7a387fff 8221 default:
f31b035a 8222 goto cp0_unimplemented;
7a387fff 8223 }
8c0fdd85
TS
8224 break;
8225 default:
f31b035a 8226 goto cp0_unimplemented;
8c0fdd85 8227 }
294fc2ea 8228 trace_mips_translate_c0("mtc0", register_name, reg, sel);
b44a7fb1 8229
bf20dc07 8230 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 8231 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8232 gen_io_end();
b28425ba 8233 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
b74cddcb 8234 * translated code to check for pending interrupts. */
eeb3bba8
EC
8235 gen_save_pc(ctx->base.pc_next + 4);
8236 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 8237 }
8c0fdd85
TS
8238 return;
8239
f31b035a 8240cp0_unimplemented:
294fc2ea
AM
8241 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8242 register_name, reg, sel);
8c0fdd85
TS
8243}
8244
d26bc211 8245#if defined(TARGET_MIPS64)
d75c135e 8246static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 8247{
294fc2ea 8248 const char *register_name = "invalid";
9c2149c8 8249
e189e748 8250 if (sel != 0)
d75c135e 8251 check_insn(ctx, ISA_MIPS64);
e189e748 8252
9c2149c8 8253 switch (reg) {
04992c8c 8254 case CP0_REGISTER_00:
9c2149c8
TS
8255 switch (sel) {
8256 case 0:
7db13fae 8257 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
294fc2ea 8258 register_name = "Index";
9c2149c8
TS
8259 break;
8260 case 1:
f31b035a 8261 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8262 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
294fc2ea 8263 register_name = "MVPControl";
ead9360e 8264 break;
9c2149c8 8265 case 2:
f31b035a 8266 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8267 gen_helper_mfc0_mvpconf0(arg, cpu_env);
294fc2ea 8268 register_name = "MVPConf0";
ead9360e 8269 break;
9c2149c8 8270 case 3:
f31b035a 8271 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8272 gen_helper_mfc0_mvpconf1(arg, cpu_env);
294fc2ea 8273 register_name = "MVPConf1";
ead9360e 8274 break;
01bc435b
YK
8275 case 4:
8276 CP0_CHECK(ctx->vp);
8277 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
294fc2ea 8278 register_name = "VPControl";
01bc435b 8279 break;
9c2149c8 8280 default:
f31b035a 8281 goto cp0_unimplemented;
9c2149c8
TS
8282 }
8283 break;
04992c8c 8284 case CP0_REGISTER_01:
9c2149c8
TS
8285 switch (sel) {
8286 case 0:
f31b035a 8287 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 8288 gen_helper_mfc0_random(arg, cpu_env);
294fc2ea 8289 register_name = "Random";
2423f660 8290 break;
9c2149c8 8291 case 1:
f31b035a 8292 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8293 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
294fc2ea 8294 register_name = "VPEControl";
ead9360e 8295 break;
9c2149c8 8296 case 2:
f31b035a 8297 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8298 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
294fc2ea 8299 register_name = "VPEConf0";
ead9360e 8300 break;
9c2149c8 8301 case 3:
f31b035a 8302 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8303 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
294fc2ea 8304 register_name = "VPEConf1";
ead9360e 8305 break;
9c2149c8 8306 case 4:
f31b035a 8307 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8308 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
294fc2ea 8309 register_name = "YQMask";
ead9360e 8310 break;
9c2149c8 8311 case 5:
f31b035a 8312 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8313 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 8314 register_name = "VPESchedule";
ead9360e 8315 break;
9c2149c8 8316 case 6:
f31b035a 8317 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8318 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 8319 register_name = "VPEScheFBack";
ead9360e 8320 break;
9c2149c8 8321 case 7:
f31b035a 8322 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8323 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
294fc2ea 8324 register_name = "VPEOpt";
ead9360e 8325 break;
9c2149c8 8326 default:
f31b035a 8327 goto cp0_unimplemented;
9c2149c8
TS
8328 }
8329 break;
04992c8c 8330 case CP0_REGISTER_02:
9c2149c8
TS
8331 switch (sel) {
8332 case 0:
7db13fae 8333 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
294fc2ea 8334 register_name = "EntryLo0";
2423f660 8335 break;
9c2149c8 8336 case 1:
f31b035a 8337 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8338 gen_helper_mfc0_tcstatus(arg, cpu_env);
294fc2ea 8339 register_name = "TCStatus";
ead9360e 8340 break;
9c2149c8 8341 case 2:
f31b035a 8342 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8343 gen_helper_mfc0_tcbind(arg, cpu_env);
294fc2ea 8344 register_name = "TCBind";
ead9360e 8345 break;
9c2149c8 8346 case 3:
f31b035a 8347 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8348 gen_helper_dmfc0_tcrestart(arg, cpu_env);
294fc2ea 8349 register_name = "TCRestart";
ead9360e 8350 break;
9c2149c8 8351 case 4:
f31b035a 8352 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8353 gen_helper_dmfc0_tchalt(arg, cpu_env);
294fc2ea 8354 register_name = "TCHalt";
ead9360e 8355 break;
9c2149c8 8356 case 5:
f31b035a 8357 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8358 gen_helper_dmfc0_tccontext(arg, cpu_env);
294fc2ea 8359 register_name = "TCContext";
ead9360e 8360 break;
9c2149c8 8361 case 6:
f31b035a 8362 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8363 gen_helper_dmfc0_tcschedule(arg, cpu_env);
294fc2ea 8364 register_name = "TCSchedule";
ead9360e 8365 break;
9c2149c8 8366 case 7:
f31b035a 8367 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8368 gen_helper_dmfc0_tcschefback(arg, cpu_env);
294fc2ea 8369 register_name = "TCScheFBack";
ead9360e 8370 break;
9c2149c8 8371 default:
f31b035a 8372 goto cp0_unimplemented;
9c2149c8
TS
8373 }
8374 break;
04992c8c 8375 case CP0_REGISTER_03:
9c2149c8
TS
8376 switch (sel) {
8377 case 0:
7db13fae 8378 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
294fc2ea 8379 register_name = "EntryLo1";
2423f660 8380 break;
01bc435b
YK
8381 case 1:
8382 CP0_CHECK(ctx->vp);
8383 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
294fc2ea 8384 register_name = "GlobalNumber";
01bc435b 8385 break;
9c2149c8 8386 default:
f31b035a 8387 goto cp0_unimplemented;
1579a72e 8388 }
9c2149c8 8389 break;
04992c8c 8390 case CP0_REGISTER_04:
9c2149c8
TS
8391 switch (sel) {
8392 case 0:
7db13fae 8393 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
294fc2ea 8394 register_name = "Context";
2423f660 8395 break;
9c2149c8 8396 case 1:
d9bea114 8397// gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
294fc2ea 8398 register_name = "ContextConfig";
f31b035a 8399 goto cp0_unimplemented;
d279279e 8400 case 2:
f31b035a
LA
8401 CP0_CHECK(ctx->ulri);
8402 tcg_gen_ld_tl(arg, cpu_env,
8403 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 8404 register_name = "UserLocal";
d279279e 8405 break;
9c2149c8 8406 default:
f31b035a 8407 goto cp0_unimplemented;
876d4b07 8408 }
9c2149c8 8409 break;
04992c8c 8410 case CP0_REGISTER_05:
9c2149c8
TS
8411 switch (sel) {
8412 case 0:
7db13fae 8413 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
294fc2ea 8414 register_name = "PageMask";
2423f660 8415 break;
9c2149c8 8416 case 1:
d75c135e 8417 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8418 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
294fc2ea 8419 register_name = "PageGrain";
2423f660 8420 break;
cec56a73
JH
8421 case 2:
8422 CP0_CHECK(ctx->sc);
8423 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
294fc2ea 8424 register_name = "SegCtl0";
cec56a73
JH
8425 break;
8426 case 3:
8427 CP0_CHECK(ctx->sc);
8428 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
294fc2ea 8429 register_name = "SegCtl1";
cec56a73
JH
8430 break;
8431 case 4:
8432 CP0_CHECK(ctx->sc);
8433 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
294fc2ea 8434 register_name = "SegCtl2";
cec56a73 8435 break;
5e31fdd5
YK
8436 case 5:
8437 check_pw(ctx);
8438 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 8439 register_name = "PWBase";
5e31fdd5 8440 break;
fa75ad14
YK
8441 case 6:
8442 check_pw(ctx);
8443 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
294fc2ea 8444 register_name = "PWField";
fa75ad14 8445 break;
20b28ebc
YK
8446 case 7:
8447 check_pw(ctx);
8448 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
294fc2ea 8449 register_name = "PWSize";
20b28ebc 8450 break;
9c2149c8 8451 default:
f31b035a 8452 goto cp0_unimplemented;
876d4b07 8453 }
9c2149c8 8454 break;
04992c8c 8455 case CP0_REGISTER_06:
9c2149c8
TS
8456 switch (sel) {
8457 case 0:
7db13fae 8458 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
294fc2ea 8459 register_name = "Wired";
2423f660 8460 break;
9c2149c8 8461 case 1:
d75c135e 8462 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8463 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
294fc2ea 8464 register_name = "SRSConf0";
ead9360e 8465 break;
9c2149c8 8466 case 2:
d75c135e 8467 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8468 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
294fc2ea 8469 register_name = "SRSConf1";
ead9360e 8470 break;
9c2149c8 8471 case 3:
d75c135e 8472 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8473 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
294fc2ea 8474 register_name = "SRSConf2";
ead9360e 8475 break;
9c2149c8 8476 case 4:
d75c135e 8477 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8478 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
294fc2ea 8479 register_name = "SRSConf3";
ead9360e 8480 break;
9c2149c8 8481 case 5:
d75c135e 8482 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8483 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
294fc2ea 8484 register_name = "SRSConf4";
ead9360e 8485 break;
103be64c
YK
8486 case 6:
8487 check_pw(ctx);
8488 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
294fc2ea 8489 register_name = "PWCtl";
103be64c 8490 break;
9c2149c8 8491 default:
f31b035a 8492 goto cp0_unimplemented;
876d4b07 8493 }
9c2149c8 8494 break;
04992c8c 8495 case CP0_REGISTER_07:
9c2149c8
TS
8496 switch (sel) {
8497 case 0:
d75c135e 8498 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8499 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
294fc2ea 8500 register_name = "HWREna";
2423f660 8501 break;
9c2149c8 8502 default:
f31b035a 8503 goto cp0_unimplemented;
876d4b07 8504 }
9c2149c8 8505 break;
04992c8c 8506 case CP0_REGISTER_08:
9c2149c8
TS
8507 switch (sel) {
8508 case 0:
7db13fae 8509 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
294fc2ea 8510 register_name = "BadVAddr";
2423f660 8511 break;
aea14095 8512 case 1:
f31b035a
LA
8513 CP0_CHECK(ctx->bi);
8514 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
294fc2ea 8515 register_name = "BadInstr";
aea14095
LA
8516 break;
8517 case 2:
f31b035a
LA
8518 CP0_CHECK(ctx->bp);
8519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
294fc2ea 8520 register_name = "BadInstrP";
aea14095 8521 break;
25beba9b
SM
8522 case 3:
8523 CP0_CHECK(ctx->bi);
8524 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8525 tcg_gen_andi_tl(arg, arg, ~0xffff);
294fc2ea 8526 register_name = "BadInstrX";
25beba9b 8527 break;
9c2149c8 8528 default:
f31b035a 8529 goto cp0_unimplemented;
876d4b07 8530 }
9c2149c8 8531 break;
04992c8c 8532 case CP0_REGISTER_09:
9c2149c8
TS
8533 switch (sel) {
8534 case 0:
2e70f6ef 8535 /* Mark as an IO operation because we read the time. */
eeb3bba8 8536 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8537 gen_io_start();
bd79255d 8538 }
895c2d04 8539 gen_helper_mfc0_count(arg, cpu_env);
eeb3bba8 8540 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8541 gen_io_end();
2e70f6ef 8542 }
55807224 8543 /* Break the TB to be able to take timer interrupts immediately
b28425ba
EC
8544 after reading count. DISAS_STOP isn't sufficient, we need to
8545 ensure we break completely out of translated code. */
eeb3bba8
EC
8546 gen_save_pc(ctx->base.pc_next + 4);
8547 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 8548 register_name = "Count";
2423f660 8549 break;
5fb2dcd1
YK
8550 case 6:
8551 CP0_CHECK(ctx->saar);
8552 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
294fc2ea 8553 register_name = "SAARI";
5fb2dcd1
YK
8554 break;
8555 case 7:
8556 CP0_CHECK(ctx->saar);
8557 gen_helper_dmfc0_saar(arg, cpu_env);
294fc2ea 8558 register_name = "SAAR";
5fb2dcd1 8559 break;
9c2149c8 8560 default:
f31b035a 8561 goto cp0_unimplemented;
876d4b07 8562 }
9c2149c8 8563 break;
04992c8c 8564 case CP0_REGISTER_10:
9c2149c8
TS
8565 switch (sel) {
8566 case 0:
7db13fae 8567 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
294fc2ea 8568 register_name = "EntryHi";
2423f660 8569 break;
9c2149c8 8570 default:
f31b035a 8571 goto cp0_unimplemented;
876d4b07 8572 }
9c2149c8 8573 break;
04992c8c 8574 case CP0_REGISTER_11:
9c2149c8
TS
8575 switch (sel) {
8576 case 0:
7db13fae 8577 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
294fc2ea 8578 register_name = "Compare";
2423f660 8579 break;
876d4b07 8580 /* 6,7 are implementation dependent */
9c2149c8 8581 default:
f31b035a 8582 goto cp0_unimplemented;
876d4b07 8583 }
9c2149c8 8584 break;
04992c8c 8585 case CP0_REGISTER_12:
9c2149c8
TS
8586 switch (sel) {
8587 case 0:
7db13fae 8588 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
294fc2ea 8589 register_name = "Status";
2423f660 8590 break;
9c2149c8 8591 case 1:
d75c135e 8592 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8593 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
294fc2ea 8594 register_name = "IntCtl";
2423f660 8595 break;
9c2149c8 8596 case 2:
d75c135e 8597 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8598 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
294fc2ea 8599 register_name = "SRSCtl";
2423f660 8600 break;
9c2149c8 8601 case 3:
d75c135e 8602 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8603 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
294fc2ea 8604 register_name = "SRSMap";
2423f660 8605 break;
9c2149c8 8606 default:
f31b035a 8607 goto cp0_unimplemented;
876d4b07 8608 }
9c2149c8 8609 break;
04992c8c 8610 case CP0_REGISTER_13:
9c2149c8
TS
8611 switch (sel) {
8612 case 0:
7db13fae 8613 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
294fc2ea 8614 register_name = "Cause";
2423f660 8615 break;
9c2149c8 8616 default:
f31b035a 8617 goto cp0_unimplemented;
876d4b07 8618 }
9c2149c8 8619 break;
04992c8c 8620 case CP0_REGISTER_14:
9c2149c8
TS
8621 switch (sel) {
8622 case 0:
7db13fae 8623 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 8624 register_name = "EPC";
2423f660 8625 break;
9c2149c8 8626 default:
f31b035a 8627 goto cp0_unimplemented;
876d4b07 8628 }
9c2149c8 8629 break;
04992c8c 8630 case CP0_REGISTER_15:
9c2149c8
TS
8631 switch (sel) {
8632 case 0:
7db13fae 8633 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
294fc2ea 8634 register_name = "PRid";
2423f660 8635 break;
9c2149c8 8636 case 1:
d75c135e 8637 check_insn(ctx, ISA_MIPS32R2);
74dbf824 8638 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
294fc2ea 8639 register_name = "EBase";
2423f660 8640 break;
c870e3f5
YK
8641 case 3:
8642 check_insn(ctx, ISA_MIPS32R2);
8643 CP0_CHECK(ctx->cmgcr);
8644 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
294fc2ea 8645 register_name = "CMGCRBase";
c870e3f5 8646 break;
9c2149c8 8647 default:
f31b035a 8648 goto cp0_unimplemented;
876d4b07 8649 }
9c2149c8 8650 break;
04992c8c 8651 case CP0_REGISTER_16:
9c2149c8
TS
8652 switch (sel) {
8653 case 0:
7db13fae 8654 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
294fc2ea 8655 register_name = "Config";
9c2149c8
TS
8656 break;
8657 case 1:
7db13fae 8658 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
294fc2ea 8659 register_name = "Config1";
9c2149c8
TS
8660 break;
8661 case 2:
7db13fae 8662 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
294fc2ea 8663 register_name = "Config2";
9c2149c8
TS
8664 break;
8665 case 3:
7db13fae 8666 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
294fc2ea 8667 register_name = "Config3";
9c2149c8 8668 break;
faf1f68b
LA
8669 case 4:
8670 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
294fc2ea 8671 register_name = "Config4";
faf1f68b
LA
8672 break;
8673 case 5:
8674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
294fc2ea 8675 register_name = "Config5";
faf1f68b 8676 break;
9c2149c8 8677 /* 6,7 are implementation dependent */
f0b3f3ae 8678 case 6:
7db13fae 8679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
294fc2ea 8680 register_name = "Config6";
f0b3f3ae
TS
8681 break;
8682 case 7:
7db13fae 8683 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
294fc2ea 8684 register_name = "Config7";
f0b3f3ae 8685 break;
9c2149c8 8686 default:
f31b035a 8687 goto cp0_unimplemented;
9c2149c8
TS
8688 }
8689 break;
04992c8c 8690 case CP0_REGISTER_17:
9c2149c8
TS
8691 switch (sel) {
8692 case 0:
895c2d04 8693 gen_helper_dmfc0_lladdr(arg, cpu_env);
294fc2ea 8694 register_name = "LLAddr";
2423f660 8695 break;
f6d4dd81
YK
8696 case 1:
8697 CP0_CHECK(ctx->mrp);
8698 gen_helper_dmfc0_maar(arg, cpu_env);
294fc2ea 8699 register_name = "MAAR";
f6d4dd81
YK
8700 break;
8701 case 2:
8702 CP0_CHECK(ctx->mrp);
8703 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
294fc2ea 8704 register_name = "MAARI";
f6d4dd81 8705 break;
9c2149c8 8706 default:
f31b035a 8707 goto cp0_unimplemented;
9c2149c8
TS
8708 }
8709 break;
04992c8c 8710 case CP0_REGISTER_18:
9c2149c8 8711 switch (sel) {
c2e19f3c
AM
8712 case 0:
8713 case 1:
8714 case 2:
8715 case 3:
8716 case 4:
8717 case 5:
8718 case 6:
8719 case 7:
fa192d49 8720 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8721 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
294fc2ea 8722 register_name = "WatchLo";
2423f660 8723 break;
9c2149c8 8724 default:
f31b035a 8725 goto cp0_unimplemented;
9c2149c8
TS
8726 }
8727 break;
04992c8c 8728 case CP0_REGISTER_19:
9c2149c8 8729 switch (sel) {
c2e19f3c
AM
8730 case 0:
8731 case 1:
8732 case 2:
8733 case 3:
8734 case 4:
8735 case 5:
8736 case 6:
8737 case 7:
fa192d49 8738 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8739 gen_helper_1e0i(mfc0_watchhi, arg, sel);
294fc2ea 8740 register_name = "WatchHi";
2423f660 8741 break;
9c2149c8 8742 default:
f31b035a 8743 goto cp0_unimplemented;
9c2149c8
TS
8744 }
8745 break;
04992c8c 8746 case CP0_REGISTER_20:
9c2149c8
TS
8747 switch (sel) {
8748 case 0:
d75c135e 8749 check_insn(ctx, ISA_MIPS3);
7db13fae 8750 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
294fc2ea 8751 register_name = "XContext";
2423f660 8752 break;
9c2149c8 8753 default:
f31b035a 8754 goto cp0_unimplemented;
9c2149c8
TS
8755 }
8756 break;
04992c8c 8757 case CP0_REGISTER_21:
9c2149c8 8758 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 8759 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
8760 switch (sel) {
8761 case 0:
7db13fae 8762 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
294fc2ea 8763 register_name = "Framemask";
2423f660 8764 break;
9c2149c8 8765 default:
f31b035a 8766 goto cp0_unimplemented;
9c2149c8
TS
8767 }
8768 break;
04992c8c 8769 case CP0_REGISTER_22:
d9bea114 8770 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 8771 register_name = "'Diagnostic"; /* implementation dependent */
2423f660 8772 break;
04992c8c 8773 case CP0_REGISTER_23:
9c2149c8
TS
8774 switch (sel) {
8775 case 0:
895c2d04 8776 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
294fc2ea 8777 register_name = "Debug";
2423f660 8778 break;
9c2149c8 8779 case 1:
895c2d04 8780// gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
294fc2ea 8781 register_name = "TraceControl";
3570d7f6 8782 goto cp0_unimplemented;
9c2149c8 8783 case 2:
895c2d04 8784// gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
294fc2ea 8785 register_name = "TraceControl2";
3570d7f6 8786 goto cp0_unimplemented;
9c2149c8 8787 case 3:
895c2d04 8788// gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
294fc2ea 8789 register_name = "UserTraceData";
3570d7f6 8790 goto cp0_unimplemented;
9c2149c8 8791 case 4:
895c2d04 8792// gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
294fc2ea 8793 register_name = "TraceBPC";
3570d7f6 8794 goto cp0_unimplemented;
9c2149c8 8795 default:
f31b035a 8796 goto cp0_unimplemented;
9c2149c8
TS
8797 }
8798 break;
04992c8c 8799 case CP0_REGISTER_24:
9c2149c8
TS
8800 switch (sel) {
8801 case 0:
f0b3f3ae 8802 /* EJTAG support */
7db13fae 8803 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 8804 register_name = "DEPC";
2423f660 8805 break;
9c2149c8 8806 default:
f31b035a 8807 goto cp0_unimplemented;
9c2149c8
TS
8808 }
8809 break;
04992c8c 8810 case CP0_REGISTER_25:
9c2149c8
TS
8811 switch (sel) {
8812 case 0:
7db13fae 8813 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
294fc2ea 8814 register_name = "Performance0";
9c2149c8
TS
8815 break;
8816 case 1:
d9bea114 8817// gen_helper_dmfc0_performance1(arg);
294fc2ea 8818 register_name = "Performance1";
3570d7f6 8819 goto cp0_unimplemented;
9c2149c8 8820 case 2:
d9bea114 8821// gen_helper_dmfc0_performance2(arg);
294fc2ea 8822 register_name = "Performance2";
3570d7f6 8823 goto cp0_unimplemented;
9c2149c8 8824 case 3:
d9bea114 8825// gen_helper_dmfc0_performance3(arg);
294fc2ea 8826 register_name = "Performance3";
3570d7f6 8827 goto cp0_unimplemented;
9c2149c8 8828 case 4:
d9bea114 8829// gen_helper_dmfc0_performance4(arg);
294fc2ea 8830 register_name = "Performance4";
3570d7f6 8831 goto cp0_unimplemented;
9c2149c8 8832 case 5:
d9bea114 8833// gen_helper_dmfc0_performance5(arg);
294fc2ea 8834 register_name = "Performance5";
3570d7f6 8835 goto cp0_unimplemented;
9c2149c8 8836 case 6:
d9bea114 8837// gen_helper_dmfc0_performance6(arg);
294fc2ea 8838 register_name = "Performance6";
3570d7f6 8839 goto cp0_unimplemented;
9c2149c8 8840 case 7:
d9bea114 8841// gen_helper_dmfc0_performance7(arg);
294fc2ea 8842 register_name = "Performance7";
3570d7f6 8843 goto cp0_unimplemented;
9c2149c8 8844 default:
f31b035a 8845 goto cp0_unimplemented;
9c2149c8
TS
8846 }
8847 break;
04992c8c 8848 case CP0_REGISTER_26:
0d74a222
LA
8849 switch (sel) {
8850 case 0:
8851 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
294fc2ea 8852 register_name = "ErrCtl";
0d74a222
LA
8853 break;
8854 default:
8855 goto cp0_unimplemented;
8856 }
da80682b 8857 break;
04992c8c 8858 case CP0_REGISTER_27:
9c2149c8
TS
8859 switch (sel) {
8860 /* ignored */
c2e19f3c
AM
8861 case 0:
8862 case 1:
8863 case 2:
8864 case 3:
d9bea114 8865 tcg_gen_movi_tl(arg, 0); /* unimplemented */
294fc2ea 8866 register_name = "CacheErr";
2423f660 8867 break;
9c2149c8 8868 default:
f31b035a 8869 goto cp0_unimplemented;
9c2149c8
TS
8870 }
8871 break;
04992c8c 8872 case CP0_REGISTER_28:
9c2149c8
TS
8873 switch (sel) {
8874 case 0:
8875 case 2:
8876 case 4:
8877 case 6:
7db13fae 8878 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
294fc2ea 8879 register_name = "TagLo";
9c2149c8
TS
8880 break;
8881 case 1:
8882 case 3:
8883 case 5:
8884 case 7:
7db13fae 8885 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
294fc2ea 8886 register_name = "DataLo";
9c2149c8
TS
8887 break;
8888 default:
f31b035a 8889 goto cp0_unimplemented;
9c2149c8
TS
8890 }
8891 break;
04992c8c 8892 case CP0_REGISTER_29:
9c2149c8
TS
8893 switch (sel) {
8894 case 0:
8895 case 2:
8896 case 4:
8897 case 6:
7db13fae 8898 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
294fc2ea 8899 register_name = "TagHi";
9c2149c8
TS
8900 break;
8901 case 1:
8902 case 3:
8903 case 5:
8904 case 7:
7db13fae 8905 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
294fc2ea 8906 register_name = "DataHi";
9c2149c8
TS
8907 break;
8908 default:
f31b035a 8909 goto cp0_unimplemented;
9c2149c8
TS
8910 }
8911 break;
04992c8c 8912 case CP0_REGISTER_30:
9c2149c8
TS
8913 switch (sel) {
8914 case 0:
7db13fae 8915 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 8916 register_name = "ErrorEPC";
2423f660 8917 break;
9c2149c8 8918 default:
f31b035a 8919 goto cp0_unimplemented;
9c2149c8
TS
8920 }
8921 break;
04992c8c 8922 case CP0_REGISTER_31:
9c2149c8
TS
8923 switch (sel) {
8924 case 0:
f0b3f3ae 8925 /* EJTAG support */
7db13fae 8926 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 8927 register_name = "DESAVE";
2423f660 8928 break;
c2e19f3c
AM
8929 case 2:
8930 case 3:
8931 case 4:
8932 case 5:
8933 case 6:
8934 case 7:
f31b035a
LA
8935 CP0_CHECK(ctx->kscrexist & (1 << sel));
8936 tcg_gen_ld_tl(arg, cpu_env,
8937 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
294fc2ea 8938 register_name = "KScratch";
e98c0d17 8939 break;
9c2149c8 8940 default:
f31b035a 8941 goto cp0_unimplemented;
9c2149c8
TS
8942 }
8943 break;
8944 default:
f31b035a 8945 goto cp0_unimplemented;
9c2149c8 8946 }
294fc2ea 8947 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9c2149c8
TS
8948 return;
8949
f31b035a 8950cp0_unimplemented:
294fc2ea
AM
8951 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
8952 register_name, reg, sel);
f31b035a 8953 gen_mfc0_unimplemented(ctx, arg);
9c2149c8
TS
8954}
8955
d75c135e 8956static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8 8957{
294fc2ea 8958 const char *register_name = "invalid";
9c2149c8 8959
e189e748 8960 if (sel != 0)
d75c135e 8961 check_insn(ctx, ISA_MIPS64);
e189e748 8962
eeb3bba8 8963 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8964 gen_io_start();
bd79255d 8965 }
2e70f6ef 8966
9c2149c8 8967 switch (reg) {
04992c8c 8968 case CP0_REGISTER_00:
9c2149c8
TS
8969 switch (sel) {
8970 case 0:
895c2d04 8971 gen_helper_mtc0_index(cpu_env, arg);
294fc2ea 8972 register_name = "Index";
9c2149c8
TS
8973 break;
8974 case 1:
f31b035a 8975 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8976 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
294fc2ea 8977 register_name = "MVPControl";
ead9360e 8978 break;
9c2149c8 8979 case 2:
f31b035a 8980 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 8981 /* ignored */
294fc2ea 8982 register_name = "MVPConf0";
ead9360e 8983 break;
9c2149c8 8984 case 3:
f31b035a 8985 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 8986 /* ignored */
294fc2ea 8987 register_name = "MVPConf1";
ead9360e 8988 break;
01bc435b
YK
8989 case 4:
8990 CP0_CHECK(ctx->vp);
8991 /* ignored */
294fc2ea 8992 register_name = "VPControl";
01bc435b 8993 break;
9c2149c8 8994 default:
f31b035a 8995 goto cp0_unimplemented;
9c2149c8
TS
8996 }
8997 break;
04992c8c 8998 case CP0_REGISTER_01:
9c2149c8
TS
8999 switch (sel) {
9000 case 0:
2423f660 9001 /* ignored */
294fc2ea 9002 register_name = "Random";
2423f660 9003 break;
9c2149c8 9004 case 1:
f31b035a 9005 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9006 gen_helper_mtc0_vpecontrol(cpu_env, arg);
294fc2ea 9007 register_name = "VPEControl";
ead9360e 9008 break;
9c2149c8 9009 case 2:
f31b035a 9010 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9011 gen_helper_mtc0_vpeconf0(cpu_env, arg);
294fc2ea 9012 register_name = "VPEConf0";
ead9360e 9013 break;
9c2149c8 9014 case 3:
f31b035a 9015 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9016 gen_helper_mtc0_vpeconf1(cpu_env, arg);
294fc2ea 9017 register_name = "VPEConf1";
ead9360e 9018 break;
9c2149c8 9019 case 4:
f31b035a 9020 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9021 gen_helper_mtc0_yqmask(cpu_env, arg);
294fc2ea 9022 register_name = "YQMask";
ead9360e 9023 break;
9c2149c8 9024 case 5:
f31b035a 9025 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 9026 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
294fc2ea 9027 register_name = "VPESchedule";
ead9360e 9028 break;
9c2149c8 9029 case 6:
f31b035a 9030 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 9031 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
294fc2ea 9032 register_name = "VPEScheFBack";
ead9360e 9033 break;
9c2149c8 9034 case 7:
f31b035a 9035 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9036 gen_helper_mtc0_vpeopt(cpu_env, arg);
294fc2ea 9037 register_name = "VPEOpt";
ead9360e 9038 break;
9c2149c8 9039 default:
f31b035a 9040 goto cp0_unimplemented;
9c2149c8
TS
9041 }
9042 break;
04992c8c 9043 case CP0_REGISTER_02:
9c2149c8
TS
9044 switch (sel) {
9045 case 0:
7207c7f9 9046 gen_helper_dmtc0_entrylo0(cpu_env, arg);
294fc2ea 9047 register_name = "EntryLo0";
2423f660 9048 break;
9c2149c8 9049 case 1:
f31b035a 9050 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9051 gen_helper_mtc0_tcstatus(cpu_env, arg);
294fc2ea 9052 register_name = "TCStatus";
ead9360e 9053 break;
9c2149c8 9054 case 2:
f31b035a 9055 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9056 gen_helper_mtc0_tcbind(cpu_env, arg);
294fc2ea 9057 register_name = "TCBind";
ead9360e 9058 break;
9c2149c8 9059 case 3:
f31b035a 9060 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9061 gen_helper_mtc0_tcrestart(cpu_env, arg);
294fc2ea 9062 register_name = "TCRestart";
ead9360e 9063 break;
9c2149c8 9064 case 4:
f31b035a 9065 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9066 gen_helper_mtc0_tchalt(cpu_env, arg);
294fc2ea 9067 register_name = "TCHalt";
ead9360e 9068 break;
9c2149c8 9069 case 5:
f31b035a 9070 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9071 gen_helper_mtc0_tccontext(cpu_env, arg);
294fc2ea 9072 register_name = "TCContext";
ead9360e 9073 break;
9c2149c8 9074 case 6:
f31b035a 9075 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9076 gen_helper_mtc0_tcschedule(cpu_env, arg);
294fc2ea 9077 register_name = "TCSchedule";
ead9360e 9078 break;
9c2149c8 9079 case 7:
f31b035a 9080 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 9081 gen_helper_mtc0_tcschefback(cpu_env, arg);
294fc2ea 9082 register_name = "TCScheFBack";
ead9360e 9083 break;
9c2149c8 9084 default:
f31b035a 9085 goto cp0_unimplemented;
9c2149c8
TS
9086 }
9087 break;
04992c8c 9088 case CP0_REGISTER_03:
9c2149c8
TS
9089 switch (sel) {
9090 case 0:
7207c7f9 9091 gen_helper_dmtc0_entrylo1(cpu_env, arg);
294fc2ea 9092 register_name = "EntryLo1";
2423f660 9093 break;
01bc435b
YK
9094 case 1:
9095 CP0_CHECK(ctx->vp);
9096 /* ignored */
294fc2ea 9097 register_name = "GlobalNumber";
01bc435b 9098 break;
9c2149c8 9099 default:
f31b035a 9100 goto cp0_unimplemented;
876d4b07 9101 }
9c2149c8 9102 break;
04992c8c 9103 case CP0_REGISTER_04:
9c2149c8
TS
9104 switch (sel) {
9105 case 0:
895c2d04 9106 gen_helper_mtc0_context(cpu_env, arg);
294fc2ea 9107 register_name = "Context";
2423f660 9108 break;
9c2149c8 9109 case 1:
895c2d04 9110// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
294fc2ea 9111 register_name = "ContextConfig";
f31b035a 9112 goto cp0_unimplemented;
d279279e 9113 case 2:
f31b035a
LA
9114 CP0_CHECK(ctx->ulri);
9115 tcg_gen_st_tl(arg, cpu_env,
9116 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
294fc2ea 9117 register_name = "UserLocal";
d279279e 9118 break;
9c2149c8 9119 default:
f31b035a 9120 goto cp0_unimplemented;
876d4b07 9121 }
9c2149c8 9122 break;
04992c8c 9123 case CP0_REGISTER_05:
9c2149c8
TS
9124 switch (sel) {
9125 case 0:
895c2d04 9126 gen_helper_mtc0_pagemask(cpu_env, arg);
294fc2ea 9127 register_name = "PageMask";
2423f660 9128 break;
9c2149c8 9129 case 1:
d75c135e 9130 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9131 gen_helper_mtc0_pagegrain(cpu_env, arg);
294fc2ea 9132 register_name = "PageGrain";
2423f660 9133 break;
cec56a73
JH
9134 case 2:
9135 CP0_CHECK(ctx->sc);
9136 gen_helper_mtc0_segctl0(cpu_env, arg);
294fc2ea 9137 register_name = "SegCtl0";
cec56a73
JH
9138 break;
9139 case 3:
9140 CP0_CHECK(ctx->sc);
9141 gen_helper_mtc0_segctl1(cpu_env, arg);
294fc2ea 9142 register_name = "SegCtl1";
cec56a73
JH
9143 break;
9144 case 4:
9145 CP0_CHECK(ctx->sc);
9146 gen_helper_mtc0_segctl2(cpu_env, arg);
294fc2ea 9147 register_name = "SegCtl2";
cec56a73 9148 break;
5e31fdd5
YK
9149 case 5:
9150 check_pw(ctx);
9151 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
294fc2ea 9152 register_name = "PWBase";
5e31fdd5 9153 break;
fa75ad14
YK
9154 case 6:
9155 check_pw(ctx);
9156 gen_helper_mtc0_pwfield(cpu_env, arg);
294fc2ea 9157 register_name = "PWField";
fa75ad14 9158 break;
20b28ebc
YK
9159 case 7:
9160 check_pw(ctx);
9161 gen_helper_mtc0_pwsize(cpu_env, arg);
294fc2ea 9162 register_name = "PWSize";
20b28ebc 9163 break;
9c2149c8 9164 default:
f31b035a 9165 goto cp0_unimplemented;
876d4b07 9166 }
9c2149c8 9167 break;
04992c8c 9168 case CP0_REGISTER_06:
9c2149c8
TS
9169 switch (sel) {
9170 case 0:
895c2d04 9171 gen_helper_mtc0_wired(cpu_env, arg);
294fc2ea 9172 register_name = "Wired";
2423f660 9173 break;
9c2149c8 9174 case 1:
d75c135e 9175 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9176 gen_helper_mtc0_srsconf0(cpu_env, arg);
294fc2ea 9177 register_name = "SRSConf0";
ead9360e 9178 break;
9c2149c8 9179 case 2:
d75c135e 9180 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9181 gen_helper_mtc0_srsconf1(cpu_env, arg);
294fc2ea 9182 register_name = "SRSConf1";
ead9360e 9183 break;
9c2149c8 9184 case 3:
d75c135e 9185 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9186 gen_helper_mtc0_srsconf2(cpu_env, arg);
294fc2ea 9187 register_name = "SRSConf2";
ead9360e 9188 break;
9c2149c8 9189 case 4:
d75c135e 9190 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9191 gen_helper_mtc0_srsconf3(cpu_env, arg);
294fc2ea 9192 register_name = "SRSConf3";
ead9360e 9193 break;
9c2149c8 9194 case 5:
d75c135e 9195 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9196 gen_helper_mtc0_srsconf4(cpu_env, arg);
294fc2ea 9197 register_name = "SRSConf4";
ead9360e 9198 break;
103be64c
YK
9199 case 6:
9200 check_pw(ctx);
9201 gen_helper_mtc0_pwctl(cpu_env, arg);
294fc2ea 9202 register_name = "PWCtl";
103be64c 9203 break;
9c2149c8 9204 default:
f31b035a 9205 goto cp0_unimplemented;
876d4b07 9206 }
9c2149c8 9207 break;
04992c8c 9208 case CP0_REGISTER_07:
9c2149c8
TS
9209 switch (sel) {
9210 case 0:
d75c135e 9211 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9212 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 9213 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9214 register_name = "HWREna";
2423f660 9215 break;
9c2149c8 9216 default:
f31b035a 9217 goto cp0_unimplemented;
876d4b07 9218 }
9c2149c8 9219 break;
04992c8c 9220 case CP0_REGISTER_08:
aea14095
LA
9221 switch (sel) {
9222 case 0:
9223 /* ignored */
294fc2ea 9224 register_name = "BadVAddr";
aea14095
LA
9225 break;
9226 case 1:
9227 /* ignored */
294fc2ea 9228 register_name = "BadInstr";
aea14095
LA
9229 break;
9230 case 2:
9231 /* ignored */
294fc2ea 9232 register_name = "BadInstrP";
aea14095 9233 break;
25beba9b
SM
9234 case 3:
9235 /* ignored */
294fc2ea 9236 register_name = "BadInstrX";
25beba9b 9237 break;
aea14095 9238 default:
f31b035a 9239 goto cp0_unimplemented;
aea14095 9240 }
9c2149c8 9241 break;
04992c8c 9242 case CP0_REGISTER_09:
9c2149c8
TS
9243 switch (sel) {
9244 case 0:
895c2d04 9245 gen_helper_mtc0_count(cpu_env, arg);
294fc2ea 9246 register_name = "Count";
2423f660 9247 break;
5fb2dcd1
YK
9248 case 6:
9249 CP0_CHECK(ctx->saar);
9250 gen_helper_mtc0_saari(cpu_env, arg);
294fc2ea 9251 register_name = "SAARI";
5fb2dcd1
YK
9252 break;
9253 case 7:
9254 CP0_CHECK(ctx->saar);
9255 gen_helper_mtc0_saar(cpu_env, arg);
294fc2ea 9256 register_name = "SAAR";
5fb2dcd1 9257 break;
9c2149c8 9258 default:
f31b035a 9259 goto cp0_unimplemented;
876d4b07
TS
9260 }
9261 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9262 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9263 break;
04992c8c 9264 case CP0_REGISTER_10:
9c2149c8
TS
9265 switch (sel) {
9266 case 0:
895c2d04 9267 gen_helper_mtc0_entryhi(cpu_env, arg);
294fc2ea 9268 register_name = "EntryHi";
2423f660 9269 break;
9c2149c8 9270 default:
f31b035a 9271 goto cp0_unimplemented;
876d4b07 9272 }
9c2149c8 9273 break;
04992c8c 9274 case CP0_REGISTER_11:
9c2149c8
TS
9275 switch (sel) {
9276 case 0:
895c2d04 9277 gen_helper_mtc0_compare(cpu_env, arg);
294fc2ea 9278 register_name = "Compare";
2423f660 9279 break;
876d4b07 9280 /* 6,7 are implementation dependent */
9c2149c8 9281 default:
f31b035a 9282 goto cp0_unimplemented;
876d4b07 9283 }
de9a95f0 9284 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9285 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9286 break;
04992c8c 9287 case CP0_REGISTER_12:
9c2149c8
TS
9288 switch (sel) {
9289 case 0:
867abc7e 9290 save_cpu_state(ctx, 1);
895c2d04 9291 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 9292 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
9293 gen_save_pc(ctx->base.pc_next + 4);
9294 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9295 register_name = "Status";
2423f660 9296 break;
9c2149c8 9297 case 1:
d75c135e 9298 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9299 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 9300 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9301 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9302 register_name = "IntCtl";
2423f660 9303 break;
9c2149c8 9304 case 2:
d75c135e 9305 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9306 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 9307 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9308 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9309 register_name = "SRSCtl";
2423f660 9310 break;
9c2149c8 9311 case 3:
d75c135e 9312 check_insn(ctx, ISA_MIPS32R2);
7db13fae 9313 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 9314 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9315 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9316 register_name = "SRSMap";
2423f660
TS
9317 break;
9318 default:
f31b035a 9319 goto cp0_unimplemented;
876d4b07 9320 }
9c2149c8 9321 break;
04992c8c 9322 case CP0_REGISTER_13:
9c2149c8
TS
9323 switch (sel) {
9324 case 0:
867abc7e 9325 save_cpu_state(ctx, 1);
895c2d04 9326 gen_helper_mtc0_cause(cpu_env, arg);
b28425ba
EC
9327 /* Stop translation as we may have triggered an interrupt.
9328 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9329 * translated code to check for pending interrupts. */
eeb3bba8
EC
9330 gen_save_pc(ctx->base.pc_next + 4);
9331 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9332 register_name = "Cause";
2423f660 9333 break;
9c2149c8 9334 default:
f31b035a 9335 goto cp0_unimplemented;
876d4b07 9336 }
9c2149c8 9337 break;
04992c8c 9338 case CP0_REGISTER_14:
9c2149c8
TS
9339 switch (sel) {
9340 case 0:
7db13fae 9341 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
294fc2ea 9342 register_name = "EPC";
2423f660 9343 break;
9c2149c8 9344 default:
f31b035a 9345 goto cp0_unimplemented;
876d4b07 9346 }
9c2149c8 9347 break;
04992c8c 9348 case CP0_REGISTER_15:
9c2149c8
TS
9349 switch (sel) {
9350 case 0:
2423f660 9351 /* ignored */
294fc2ea 9352 register_name = "PRid";
2423f660 9353 break;
9c2149c8 9354 case 1:
d75c135e 9355 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9356 gen_helper_mtc0_ebase(cpu_env, arg);
294fc2ea 9357 register_name = "EBase";
2423f660 9358 break;
9c2149c8 9359 default:
f31b035a 9360 goto cp0_unimplemented;
876d4b07 9361 }
9c2149c8 9362 break;
04992c8c 9363 case CP0_REGISTER_16:
9c2149c8
TS
9364 switch (sel) {
9365 case 0:
895c2d04 9366 gen_helper_mtc0_config0(cpu_env, arg);
294fc2ea 9367 register_name = "Config";
2423f660 9368 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9369 ctx->base.is_jmp = DISAS_STOP;
9c2149c8
TS
9370 break;
9371 case 1:
1fc7bf6e 9372 /* ignored, read only */
294fc2ea 9373 register_name = "Config1";
9c2149c8
TS
9374 break;
9375 case 2:
895c2d04 9376 gen_helper_mtc0_config2(cpu_env, arg);
294fc2ea 9377 register_name = "Config2";
2423f660 9378 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9379 ctx->base.is_jmp = DISAS_STOP;
9c2149c8
TS
9380 break;
9381 case 3:
90f12d73 9382 gen_helper_mtc0_config3(cpu_env, arg);
294fc2ea 9383 register_name = "Config3";
90f12d73 9384 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9385 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9386 break;
faf1f68b
LA
9387 case 4:
9388 /* currently ignored */
294fc2ea 9389 register_name = "Config4";
faf1f68b
LA
9390 break;
9391 case 5:
9392 gen_helper_mtc0_config5(cpu_env, arg);
294fc2ea 9393 register_name = "Config5";
faf1f68b 9394 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9395 ctx->base.is_jmp = DISAS_STOP;
faf1f68b 9396 break;
9c2149c8
TS
9397 /* 6,7 are implementation dependent */
9398 default:
294fc2ea 9399 register_name = "Invalid config selector";
f31b035a 9400 goto cp0_unimplemented;
9c2149c8 9401 }
9c2149c8 9402 break;
04992c8c 9403 case CP0_REGISTER_17:
9c2149c8
TS
9404 switch (sel) {
9405 case 0:
895c2d04 9406 gen_helper_mtc0_lladdr(cpu_env, arg);
294fc2ea 9407 register_name = "LLAddr";
2423f660 9408 break;
f6d4dd81
YK
9409 case 1:
9410 CP0_CHECK(ctx->mrp);
9411 gen_helper_mtc0_maar(cpu_env, arg);
294fc2ea 9412 register_name = "MAAR";
f6d4dd81
YK
9413 break;
9414 case 2:
9415 CP0_CHECK(ctx->mrp);
9416 gen_helper_mtc0_maari(cpu_env, arg);
294fc2ea 9417 register_name = "MAARI";
f6d4dd81 9418 break;
9c2149c8 9419 default:
f31b035a 9420 goto cp0_unimplemented;
9c2149c8
TS
9421 }
9422 break;
04992c8c 9423 case CP0_REGISTER_18:
9c2149c8 9424 switch (sel) {
c2e19f3c
AM
9425 case 0:
9426 case 1:
9427 case 2:
9428 case 3:
9429 case 4:
9430 case 5:
9431 case 6:
9432 case 7:
fa192d49 9433 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 9434 gen_helper_0e1i(mtc0_watchlo, arg, sel);
294fc2ea 9435 register_name = "WatchLo";
2423f660 9436 break;
9c2149c8 9437 default:
f31b035a 9438 goto cp0_unimplemented;
9c2149c8
TS
9439 }
9440 break;
04992c8c 9441 case CP0_REGISTER_19:
9c2149c8 9442 switch (sel) {
c2e19f3c
AM
9443 case 0:
9444 case 1:
9445 case 2:
9446 case 3:
9447 case 4:
9448 case 5:
9449 case 6:
9450 case 7:
fa192d49 9451 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 9452 gen_helper_0e1i(mtc0_watchhi, arg, sel);
294fc2ea 9453 register_name = "WatchHi";
2423f660 9454 break;
9c2149c8 9455 default:
f31b035a 9456 goto cp0_unimplemented;
9c2149c8
TS
9457 }
9458 break;
04992c8c 9459 case CP0_REGISTER_20:
9c2149c8
TS
9460 switch (sel) {
9461 case 0:
d75c135e 9462 check_insn(ctx, ISA_MIPS3);
895c2d04 9463 gen_helper_mtc0_xcontext(cpu_env, arg);
294fc2ea 9464 register_name = "XContext";
2423f660 9465 break;
9c2149c8 9466 default:
f31b035a 9467 goto cp0_unimplemented;
9c2149c8
TS
9468 }
9469 break;
04992c8c 9470 case CP0_REGISTER_21:
9c2149c8 9471 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 9472 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
9473 switch (sel) {
9474 case 0:
895c2d04 9475 gen_helper_mtc0_framemask(cpu_env, arg);
294fc2ea 9476 register_name = "Framemask";
2423f660 9477 break;
9c2149c8 9478 default:
f31b035a 9479 goto cp0_unimplemented;
9c2149c8
TS
9480 }
9481 break;
04992c8c 9482 case CP0_REGISTER_22:
9c2149c8 9483 /* ignored */
294fc2ea 9484 register_name = "Diagnostic"; /* implementation dependent */
876d4b07 9485 break;
04992c8c 9486 case CP0_REGISTER_23:
9c2149c8
TS
9487 switch (sel) {
9488 case 0:
895c2d04 9489 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 9490 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
9491 gen_save_pc(ctx->base.pc_next + 4);
9492 ctx->base.is_jmp = DISAS_EXIT;
294fc2ea 9493 register_name = "Debug";
2423f660 9494 break;
9c2149c8 9495 case 1:
895c2d04 9496// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8487327a 9497 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9498 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9499 register_name = "TraceControl";
3570d7f6 9500 goto cp0_unimplemented;
9c2149c8 9501 case 2:
895c2d04 9502// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8487327a 9503 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9504 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9505 register_name = "TraceControl2";
3570d7f6 9506 goto cp0_unimplemented;
9c2149c8 9507 case 3:
895c2d04 9508// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8487327a 9509 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9510 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9511 register_name = "UserTraceData";
3570d7f6 9512 goto cp0_unimplemented;
9c2149c8 9513 case 4:
895c2d04 9514// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a 9515 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9516 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9517 register_name = "TraceBPC";
3570d7f6 9518 goto cp0_unimplemented;
9c2149c8 9519 default:
f31b035a 9520 goto cp0_unimplemented;
9c2149c8 9521 }
9c2149c8 9522 break;
04992c8c 9523 case CP0_REGISTER_24:
9c2149c8
TS
9524 switch (sel) {
9525 case 0:
f1aa6320 9526 /* EJTAG support */
7db13fae 9527 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
294fc2ea 9528 register_name = "DEPC";
2423f660 9529 break;
9c2149c8 9530 default:
f31b035a 9531 goto cp0_unimplemented;
9c2149c8
TS
9532 }
9533 break;
04992c8c 9534 case CP0_REGISTER_25:
9c2149c8
TS
9535 switch (sel) {
9536 case 0:
895c2d04 9537 gen_helper_mtc0_performance0(cpu_env, arg);
294fc2ea 9538 register_name = "Performance0";
2423f660 9539 break;
9c2149c8 9540 case 1:
895c2d04 9541// gen_helper_mtc0_performance1(cpu_env, arg);
294fc2ea 9542 register_name = "Performance1";
3570d7f6 9543 goto cp0_unimplemented;
9c2149c8 9544 case 2:
895c2d04 9545// gen_helper_mtc0_performance2(cpu_env, arg);
294fc2ea 9546 register_name = "Performance2";
3570d7f6 9547 goto cp0_unimplemented;
9c2149c8 9548 case 3:
895c2d04 9549// gen_helper_mtc0_performance3(cpu_env, arg);
294fc2ea 9550 register_name = "Performance3";
3570d7f6 9551 goto cp0_unimplemented;
9c2149c8 9552 case 4:
895c2d04 9553// gen_helper_mtc0_performance4(cpu_env, arg);
294fc2ea 9554 register_name = "Performance4";
3570d7f6 9555 goto cp0_unimplemented;
9c2149c8 9556 case 5:
895c2d04 9557// gen_helper_mtc0_performance5(cpu_env, arg);
294fc2ea 9558 register_name = "Performance5";
3570d7f6 9559 goto cp0_unimplemented;
9c2149c8 9560 case 6:
895c2d04 9561// gen_helper_mtc0_performance6(cpu_env, arg);
294fc2ea 9562 register_name = "Performance6";
3570d7f6 9563 goto cp0_unimplemented;
9c2149c8 9564 case 7:
895c2d04 9565// gen_helper_mtc0_performance7(cpu_env, arg);
294fc2ea 9566 register_name = "Performance7";
3570d7f6 9567 goto cp0_unimplemented;
9c2149c8 9568 default:
f31b035a 9569 goto cp0_unimplemented;
9c2149c8 9570 }
876d4b07 9571 break;
04992c8c 9572 case CP0_REGISTER_26:
0d74a222
LA
9573 switch (sel) {
9574 case 0:
9575 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 9576 ctx->base.is_jmp = DISAS_STOP;
294fc2ea 9577 register_name = "ErrCtl";
0d74a222
LA
9578 break;
9579 default:
9580 goto cp0_unimplemented;
9581 }
876d4b07 9582 break;
04992c8c 9583 case CP0_REGISTER_27:
9c2149c8 9584 switch (sel) {
c2e19f3c
AM
9585 case 0:
9586 case 1:
9587 case 2:
9588 case 3:
2423f660 9589 /* ignored */
294fc2ea 9590 register_name = "CacheErr";
2423f660 9591 break;
9c2149c8 9592 default:
f31b035a 9593 goto cp0_unimplemented;
9c2149c8 9594 }
876d4b07 9595 break;
04992c8c 9596 case CP0_REGISTER_28:
9c2149c8
TS
9597 switch (sel) {
9598 case 0:
9599 case 2:
9600 case 4:
9601 case 6:
895c2d04 9602 gen_helper_mtc0_taglo(cpu_env, arg);
294fc2ea 9603 register_name = "TagLo";
9c2149c8
TS
9604 break;
9605 case 1:
9606 case 3:
9607 case 5:
9608 case 7:
895c2d04 9609 gen_helper_mtc0_datalo(cpu_env, arg);
294fc2ea 9610 register_name = "DataLo";
9c2149c8
TS
9611 break;
9612 default:
f31b035a 9613 goto cp0_unimplemented;
9c2149c8
TS
9614 }
9615 break;
04992c8c 9616 case CP0_REGISTER_29:
9c2149c8
TS
9617 switch (sel) {
9618 case 0:
9619 case 2:
9620 case 4:
9621 case 6:
895c2d04 9622 gen_helper_mtc0_taghi(cpu_env, arg);
294fc2ea 9623 register_name = "TagHi";
9c2149c8
TS
9624 break;
9625 case 1:
9626 case 3:
9627 case 5:
9628 case 7:
895c2d04 9629 gen_helper_mtc0_datahi(cpu_env, arg);
294fc2ea 9630 register_name = "DataHi";
9c2149c8
TS
9631 break;
9632 default:
294fc2ea 9633 register_name = "invalid sel";
f31b035a 9634 goto cp0_unimplemented;
9c2149c8 9635 }
876d4b07 9636 break;
04992c8c 9637 case CP0_REGISTER_30:
9c2149c8
TS
9638 switch (sel) {
9639 case 0:
7db13fae 9640 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
294fc2ea 9641 register_name = "ErrorEPC";
2423f660 9642 break;
9c2149c8 9643 default:
f31b035a 9644 goto cp0_unimplemented;
9c2149c8
TS
9645 }
9646 break;
04992c8c 9647 case CP0_REGISTER_31:
9c2149c8
TS
9648 switch (sel) {
9649 case 0:
f1aa6320 9650 /* EJTAG support */
7db13fae 9651 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
294fc2ea 9652 register_name = "DESAVE";
2423f660 9653 break;
c2e19f3c
AM
9654 case 2:
9655 case 3:
9656 case 4:
9657 case 5:
9658 case 6:
9659 case 7:
f31b035a
LA
9660 CP0_CHECK(ctx->kscrexist & (1 << sel));
9661 tcg_gen_st_tl(arg, cpu_env,
9662 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
294fc2ea 9663 register_name = "KScratch";
e98c0d17 9664 break;
9c2149c8 9665 default:
f31b035a 9666 goto cp0_unimplemented;
9c2149c8 9667 }
9c2149c8
TS
9668 break;
9669 default:
f31b035a 9670 goto cp0_unimplemented;
9c2149c8 9671 }
294fc2ea 9672 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
b44a7fb1 9673
bf20dc07 9674 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 9675 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 9676 gen_io_end();
b28425ba 9677 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
b74cddcb 9678 * translated code to check for pending interrupts. */
eeb3bba8
EC
9679 gen_save_pc(ctx->base.pc_next + 4);
9680 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 9681 }
9c2149c8
TS
9682 return;
9683
f31b035a 9684cp0_unimplemented:
294fc2ea
AM
9685 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9686 register_name, reg, sel);
9c2149c8 9687}
d26bc211 9688#endif /* TARGET_MIPS64 */
9c2149c8 9689
7db13fae 9690static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
9691 int u, int sel, int h)
9692{
9693 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 9694 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
9695
9696 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
9697 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9698 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 9699 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
9700 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9701 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 9702 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
9703 else if (u == 0) {
9704 switch (rt) {
5a25ce94
EI
9705 case 1:
9706 switch (sel) {
9707 case 1:
895c2d04 9708 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
9709 break;
9710 case 2:
895c2d04 9711 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
9712 break;
9713 default:
9714 goto die;
9715 break;
9716 }
9717 break;
ead9360e
TS
9718 case 2:
9719 switch (sel) {
9720 case 1:
895c2d04 9721 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
9722 break;
9723 case 2:
895c2d04 9724 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
9725 break;
9726 case 3:
895c2d04 9727 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
9728 break;
9729 case 4:
895c2d04 9730 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
9731 break;
9732 case 5:
895c2d04 9733 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
9734 break;
9735 case 6:
895c2d04 9736 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
9737 break;
9738 case 7:
895c2d04 9739 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
9740 break;
9741 default:
d75c135e 9742 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9743 break;
9744 }
9745 break;
9746 case 10:
9747 switch (sel) {
9748 case 0:
895c2d04 9749 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
9750 break;
9751 default:
d75c135e 9752 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9753 break;
9754 }
9755 case 12:
9756 switch (sel) {
9757 case 0:
895c2d04 9758 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
9759 break;
9760 default:
d75c135e 9761 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9762 break;
9763 }
5a25ce94
EI
9764 case 13:
9765 switch (sel) {
9766 case 0:
895c2d04 9767 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
9768 break;
9769 default:
9770 goto die;
9771 break;
9772 }
9773 break;
9774 case 14:
9775 switch (sel) {
9776 case 0:
895c2d04 9777 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
9778 break;
9779 default:
9780 goto die;
9781 break;
9782 }
9783 break;
9784 case 15:
9785 switch (sel) {
9786 case 1:
895c2d04 9787 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
9788 break;
9789 default:
9790 goto die;
9791 break;
9792 }
9793 break;
9794 case 16:
9795 switch (sel) {
c2e19f3c
AM
9796 case 0:
9797 case 1:
9798 case 2:
9799 case 3:
9800 case 4:
9801 case 5:
9802 case 6:
9803 case 7:
895c2d04 9804 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
9805 break;
9806 default:
9807 goto die;
9808 break;
9809 }
9810 break;
ead9360e
TS
9811 case 23:
9812 switch (sel) {
9813 case 0:
895c2d04 9814 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
9815 break;
9816 default:
d75c135e 9817 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9818 break;
9819 }
9820 break;
9821 default:
d75c135e 9822 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9823 }
9824 } else switch (sel) {
9825 /* GPR registers. */
9826 case 0:
895c2d04 9827 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e
TS
9828 break;
9829 /* Auxiliary CPU registers */
9830 case 1:
9831 switch (rt) {
9832 case 0:
895c2d04 9833 gen_helper_1e0i(mftlo, t0, 0);
ead9360e
TS
9834 break;
9835 case 1:
895c2d04 9836 gen_helper_1e0i(mfthi, t0, 0);
ead9360e
TS
9837 break;
9838 case 2:
895c2d04 9839 gen_helper_1e0i(mftacx, t0, 0);
ead9360e
TS
9840 break;
9841 case 4:
895c2d04 9842 gen_helper_1e0i(mftlo, t0, 1);
ead9360e
TS
9843 break;
9844 case 5:
895c2d04 9845 gen_helper_1e0i(mfthi, t0, 1);
ead9360e
TS
9846 break;
9847 case 6:
895c2d04 9848 gen_helper_1e0i(mftacx, t0, 1);
ead9360e
TS
9849 break;
9850 case 8:
895c2d04 9851 gen_helper_1e0i(mftlo, t0, 2);
ead9360e
TS
9852 break;
9853 case 9:
895c2d04 9854 gen_helper_1e0i(mfthi, t0, 2);
ead9360e
TS
9855 break;
9856 case 10:
895c2d04 9857 gen_helper_1e0i(mftacx, t0, 2);
ead9360e
TS
9858 break;
9859 case 12:
895c2d04 9860 gen_helper_1e0i(mftlo, t0, 3);
ead9360e
TS
9861 break;
9862 case 13:
895c2d04 9863 gen_helper_1e0i(mfthi, t0, 3);
ead9360e
TS
9864 break;
9865 case 14:
895c2d04 9866 gen_helper_1e0i(mftacx, t0, 3);
ead9360e
TS
9867 break;
9868 case 16:
895c2d04 9869 gen_helper_mftdsp(t0, cpu_env);
ead9360e
TS
9870 break;
9871 default:
9872 goto die;
9873 }
9874 break;
9875 /* Floating point (COP1). */
9876 case 2:
9877 /* XXX: For now we support only a single FPU context. */
9878 if (h == 0) {
a7812ae4 9879 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9880
7c979afd 9881 gen_load_fpr32(ctx, fp0, rt);
b6d96bed 9882 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 9883 tcg_temp_free_i32(fp0);
ead9360e 9884 } else {
a7812ae4 9885 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9886
7f6613ce 9887 gen_load_fpr32h(ctx, fp0, rt);
b6d96bed 9888 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 9889 tcg_temp_free_i32(fp0);
ead9360e
TS
9890 }
9891 break;
9892 case 3:
9893 /* XXX: For now we support only a single FPU context. */
895c2d04 9894 gen_helper_1e0i(cfc1, t0, rt);
ead9360e
TS
9895 break;
9896 /* COP2: Not implemented. */
9897 case 4:
9898 case 5:
9899 /* fall through */
9900 default:
9901 goto die;
9902 }
b44a7fb1 9903 trace_mips_translate_tr("mftr", rt, u, sel, h);
1a3fd9c3
TS
9904 gen_store_gpr(t0, rd);
9905 tcg_temp_free(t0);
ead9360e
TS
9906 return;
9907
9908die:
1a3fd9c3 9909 tcg_temp_free(t0);
d12d51d5 9910 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9c708c7f 9911 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
9912}
9913
7db13fae 9914static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
9915 int u, int sel, int h)
9916{
9917 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 9918 TCGv t0 = tcg_temp_local_new();
ead9360e 9919
1a3fd9c3 9920 gen_load_gpr(t0, rt);
ead9360e 9921 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
9922 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9923 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
9924 /* NOP */ ;
9925 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9926 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9927 /* NOP */ ;
9928 else if (u == 0) {
9929 switch (rd) {
5a25ce94
EI
9930 case 1:
9931 switch (sel) {
9932 case 1:
895c2d04 9933 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
9934 break;
9935 case 2:
895c2d04 9936 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
9937 break;
9938 default:
9939 goto die;
9940 break;
9941 }
9942 break;
ead9360e
TS
9943 case 2:
9944 switch (sel) {
9945 case 1:
895c2d04 9946 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
9947 break;
9948 case 2:
895c2d04 9949 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
9950 break;
9951 case 3:
895c2d04 9952 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
9953 break;
9954 case 4:
895c2d04 9955 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
9956 break;
9957 case 5:
895c2d04 9958 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
9959 break;
9960 case 6:
895c2d04 9961 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
9962 break;
9963 case 7:
895c2d04 9964 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
9965 break;
9966 default:
d75c135e 9967 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9968 break;
9969 }
9970 break;
9971 case 10:
9972 switch (sel) {
9973 case 0:
895c2d04 9974 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
9975 break;
9976 default:
d75c135e 9977 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9978 break;
9979 }
9980 case 12:
9981 switch (sel) {
9982 case 0:
895c2d04 9983 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
9984 break;
9985 default:
d75c135e 9986 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9987 break;
9988 }
5a25ce94
EI
9989 case 13:
9990 switch (sel) {
9991 case 0:
895c2d04 9992 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
9993 break;
9994 default:
9995 goto die;
9996 break;
9997 }
9998 break;
9999 case 15:
10000 switch (sel) {
10001 case 1:
895c2d04 10002 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
10003 break;
10004 default:
10005 goto die;
10006 break;
10007 }
10008 break;
ead9360e
TS
10009 case 23:
10010 switch (sel) {
10011 case 0:
895c2d04 10012 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
10013 break;
10014 default:
d75c135e 10015 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10016 break;
10017 }
10018 break;
10019 default:
d75c135e 10020 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
10021 }
10022 } else switch (sel) {
10023 /* GPR registers. */
10024 case 0:
895c2d04 10025 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e
TS
10026 break;
10027 /* Auxiliary CPU registers */
10028 case 1:
10029 switch (rd) {
10030 case 0:
895c2d04 10031 gen_helper_0e1i(mttlo, t0, 0);
ead9360e
TS
10032 break;
10033 case 1:
895c2d04 10034 gen_helper_0e1i(mtthi, t0, 0);
ead9360e
TS
10035 break;
10036 case 2:
895c2d04 10037 gen_helper_0e1i(mttacx, t0, 0);
ead9360e
TS
10038 break;
10039 case 4:
895c2d04 10040 gen_helper_0e1i(mttlo, t0, 1);
ead9360e
TS
10041 break;
10042 case 5:
895c2d04 10043 gen_helper_0e1i(mtthi, t0, 1);
ead9360e
TS
10044 break;
10045 case 6:
895c2d04 10046 gen_helper_0e1i(mttacx, t0, 1);
ead9360e
TS
10047 break;
10048 case 8:
895c2d04 10049 gen_helper_0e1i(mttlo, t0, 2);
ead9360e
TS
10050 break;
10051 case 9:
895c2d04 10052 gen_helper_0e1i(mtthi, t0, 2);
ead9360e
TS
10053 break;
10054 case 10:
895c2d04 10055 gen_helper_0e1i(mttacx, t0, 2);
ead9360e
TS
10056 break;
10057 case 12:
895c2d04 10058 gen_helper_0e1i(mttlo, t0, 3);
ead9360e
TS
10059 break;
10060 case 13:
895c2d04 10061 gen_helper_0e1i(mtthi, t0, 3);
ead9360e
TS
10062 break;
10063 case 14:
895c2d04 10064 gen_helper_0e1i(mttacx, t0, 3);
ead9360e
TS
10065 break;
10066 case 16:
895c2d04 10067 gen_helper_mttdsp(cpu_env, t0);
ead9360e
TS
10068 break;
10069 default:
10070 goto die;
10071 }
10072 break;
10073 /* Floating point (COP1). */
10074 case 2:
10075 /* XXX: For now we support only a single FPU context. */
10076 if (h == 0) {
a7812ae4 10077 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
10078
10079 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 10080 gen_store_fpr32(ctx, fp0, rd);
a7812ae4 10081 tcg_temp_free_i32(fp0);
ead9360e 10082 } else {
a7812ae4 10083 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
10084
10085 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 10086 gen_store_fpr32h(ctx, fp0, rd);
a7812ae4 10087 tcg_temp_free_i32(fp0);
ead9360e
TS
10088 }
10089 break;
10090 case 3:
10091 /* XXX: For now we support only a single FPU context. */
736d120a
PJ
10092 {
10093 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10094
10095 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10096 tcg_temp_free_i32(fs_tmp);
10097 }
4cf8a45f 10098 /* Stop translation as we may have changed hflags */
eeb3bba8 10099 ctx->base.is_jmp = DISAS_STOP;
ead9360e
TS
10100 break;
10101 /* COP2: Not implemented. */
10102 case 4:
10103 case 5:
10104 /* fall through */
10105 default:
10106 goto die;
10107 }
b44a7fb1 10108 trace_mips_translate_tr("mttr", rd, u, sel, h);
1a3fd9c3 10109 tcg_temp_free(t0);
ead9360e
TS
10110 return;
10111
10112die:
1a3fd9c3 10113 tcg_temp_free(t0);
d12d51d5 10114 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9c708c7f 10115 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
10116}
10117
7db13fae 10118static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 10119{
287c4b84 10120 const char *opn = "ldst";
6af0bf9c 10121
2e15497c 10122 check_cp0_enabled(ctx);
6af0bf9c
FB
10123 switch (opc) {
10124 case OPC_MFC0:
10125 if (rt == 0) {
ead9360e 10126 /* Treat as NOP. */
6af0bf9c
FB
10127 return;
10128 }
d75c135e 10129 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
10130 opn = "mfc0";
10131 break;
10132 case OPC_MTC0:
1a3fd9c3 10133 {
1fc7bf6e 10134 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
10135
10136 gen_load_gpr(t0, rt);
d75c135e 10137 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
10138 tcg_temp_free(t0);
10139 }
6af0bf9c
FB
10140 opn = "mtc0";
10141 break;
d26bc211 10142#if defined(TARGET_MIPS64)
9c2149c8 10143 case OPC_DMFC0:
d75c135e 10144 check_insn(ctx, ISA_MIPS3);
9c2149c8 10145 if (rt == 0) {
ead9360e 10146 /* Treat as NOP. */
9c2149c8
TS
10147 return;
10148 }
d75c135e 10149 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
10150 opn = "dmfc0";
10151 break;
10152 case OPC_DMTC0:
d75c135e 10153 check_insn(ctx, ISA_MIPS3);
1a3fd9c3 10154 {
1fc7bf6e 10155 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
10156
10157 gen_load_gpr(t0, rt);
d75c135e 10158 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
10159 tcg_temp_free(t0);
10160 }
9c2149c8
TS
10161 opn = "dmtc0";
10162 break;
534ce69f 10163#endif
5204ea79
LA
10164 case OPC_MFHC0:
10165 check_mvh(ctx);
10166 if (rt == 0) {
10167 /* Treat as NOP. */
10168 return;
10169 }
10170 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10171 opn = "mfhc0";
10172 break;
10173 case OPC_MTHC0:
10174 check_mvh(ctx);
10175 {
10176 TCGv t0 = tcg_temp_new();
10177 gen_load_gpr(t0, rt);
10178 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10179 tcg_temp_free(t0);
10180 }
10181 opn = "mthc0";
10182 break;
ead9360e 10183 case OPC_MFTR:
9affc1c5 10184 check_cp0_enabled(ctx);
ead9360e
TS
10185 if (rd == 0) {
10186 /* Treat as NOP. */
10187 return;
10188 }
6c5c1e20 10189 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 10190 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
10191 opn = "mftr";
10192 break;
10193 case OPC_MTTR:
9affc1c5 10194 check_cp0_enabled(ctx);
6c5c1e20 10195 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
10196 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10197 opn = "mttr";
10198 break;
6af0bf9c 10199 case OPC_TLBWI:
6af0bf9c 10200 opn = "tlbwi";
c01fccd2 10201 if (!env->tlb->helper_tlbwi)
29929e34 10202 goto die;
895c2d04 10203 gen_helper_tlbwi(cpu_env);
6af0bf9c 10204 break;
9456c2fb
LA
10205 case OPC_TLBINV:
10206 opn = "tlbinv";
10207 if (ctx->ie >= 2) {
10208 if (!env->tlb->helper_tlbinv) {
10209 goto die;
10210 }
10211 gen_helper_tlbinv(cpu_env);
10212 } /* treat as nop if TLBINV not supported */
10213 break;
10214 case OPC_TLBINVF:
10215 opn = "tlbinvf";
10216 if (ctx->ie >= 2) {
10217 if (!env->tlb->helper_tlbinvf) {
10218 goto die;
10219 }
10220 gen_helper_tlbinvf(cpu_env);
10221 } /* treat as nop if TLBINV not supported */
10222 break;
6af0bf9c 10223 case OPC_TLBWR:
6af0bf9c 10224 opn = "tlbwr";
c01fccd2 10225 if (!env->tlb->helper_tlbwr)
29929e34 10226 goto die;
895c2d04 10227 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
10228 break;
10229 case OPC_TLBP:
6af0bf9c 10230 opn = "tlbp";
c01fccd2 10231 if (!env->tlb->helper_tlbp)
29929e34 10232 goto die;
895c2d04 10233 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
10234 break;
10235 case OPC_TLBR:
6af0bf9c 10236 opn = "tlbr";
c01fccd2 10237 if (!env->tlb->helper_tlbr)
29929e34 10238 goto die;
895c2d04 10239 gen_helper_tlbr(cpu_env);
6af0bf9c 10240 break;
ce9782f4 10241 case OPC_ERET: /* OPC_ERETNC */
339cd2a8
LA
10242 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10243 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8 10244 goto die;
ce9782f4
LA
10245 } else {
10246 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10247 if (ctx->opcode & (1 << bit_shift)) {
10248 /* OPC_ERETNC */
10249 opn = "eretnc";
10250 check_insn(ctx, ISA_MIPS32R5);
10251 gen_helper_eretnc(cpu_env);
10252 } else {
10253 /* OPC_ERET */
10254 opn = "eret";
10255 check_insn(ctx, ISA_MIPS2);
10256 gen_helper_eret(cpu_env);
10257 }
eeb3bba8 10258 ctx->base.is_jmp = DISAS_EXIT;
339cd2a8 10259 }
6af0bf9c
FB
10260 break;
10261 case OPC_DERET:
10262 opn = "deret";
d75c135e 10263 check_insn(ctx, ISA_MIPS32);
339cd2a8
LA
10264 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10265 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
10266 goto die;
10267 }
6af0bf9c 10268 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 10269 MIPS_INVAL(opn);
9c708c7f 10270 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 10271 } else {
895c2d04 10272 gen_helper_deret(cpu_env);
eeb3bba8 10273 ctx->base.is_jmp = DISAS_EXIT;
6af0bf9c
FB
10274 }
10275 break;
4ad40f36
FB
10276 case OPC_WAIT:
10277 opn = "wait";
d75c135e 10278 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
339cd2a8
LA
10279 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10280 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
10281 goto die;
10282 }
4ad40f36 10283 /* If we get an exception, we want to restart at next instruction */
eeb3bba8 10284 ctx->base.pc_next += 4;
4ad40f36 10285 save_cpu_state(ctx, 1);
eeb3bba8 10286 ctx->base.pc_next -= 4;
895c2d04 10287 gen_helper_wait(cpu_env);
eeb3bba8 10288 ctx->base.is_jmp = DISAS_NORETURN;
4ad40f36 10289 break;
6af0bf9c 10290 default:
29929e34 10291 die:
923617a3 10292 MIPS_INVAL(opn);
9c708c7f 10293 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
10294 return;
10295 }
2abf314d 10296 (void)opn; /* avoid a compiler warning */
6af0bf9c 10297}
f1aa6320 10298#endif /* !CONFIG_USER_ONLY */
6af0bf9c 10299
6ea83fed 10300/* CP1 Branches (before delay slot) */
d75c135e
AJ
10301static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10302 int32_t cc, int32_t offset)
6ea83fed
FB
10303{
10304 target_ulong btarget;
a7812ae4 10305 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 10306
339cd2a8 10307 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 10308 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
10309 goto out;
10310 }
10311
e189e748 10312 if (cc != 0)
d75c135e 10313 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
e189e748 10314
eeb3bba8 10315 btarget = ctx->base.pc_next + 4 + offset;
6ea83fed 10316
7a387fff
TS
10317 switch (op) {
10318 case OPC_BC1F:
d94536f4
AJ
10319 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10320 tcg_gen_not_i32(t0, t0);
10321 tcg_gen_andi_i32(t0, t0, 1);
10322 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 10323 goto not_likely;
7a387fff 10324 case OPC_BC1FL:
d94536f4
AJ
10325 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10326 tcg_gen_not_i32(t0, t0);
10327 tcg_gen_andi_i32(t0, t0, 1);
10328 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 10329 goto likely;
7a387fff 10330 case OPC_BC1T:
d94536f4
AJ
10331 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10332 tcg_gen_andi_i32(t0, t0, 1);
10333 tcg_gen_extu_i32_tl(bcond, t0);
5a5012ec 10334 goto not_likely;
7a387fff 10335 case OPC_BC1TL:
d94536f4
AJ
10336 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10337 tcg_gen_andi_i32(t0, t0, 1);
10338 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed
FB
10339 likely:
10340 ctx->hflags |= MIPS_HFLAG_BL;
10341 break;
5a5012ec 10342 case OPC_BC1FANY2:
a16336e4 10343 {
d94536f4
AJ
10344 TCGv_i32 t1 = tcg_temp_new_i32();
10345 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10346 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 10347 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 10348 tcg_temp_free_i32(t1);
d94536f4
AJ
10349 tcg_gen_andi_i32(t0, t0, 1);
10350 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10351 }
5a5012ec
TS
10352 goto not_likely;
10353 case OPC_BC1TANY2:
a16336e4 10354 {
d94536f4
AJ
10355 TCGv_i32 t1 = tcg_temp_new_i32();
10356 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10357 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10358 tcg_gen_or_i32(t0, t0, t1);
10359 tcg_temp_free_i32(t1);
10360 tcg_gen_andi_i32(t0, t0, 1);
10361 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10362 }
5a5012ec
TS
10363 goto not_likely;
10364 case OPC_BC1FANY4:
a16336e4 10365 {
d94536f4
AJ
10366 TCGv_i32 t1 = tcg_temp_new_i32();
10367 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10368 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 10369 tcg_gen_and_i32(t0, t0, t1);
d94536f4 10370 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
d7f66b52 10371 tcg_gen_and_i32(t0, t0, t1);
d94536f4 10372 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
d7f66b52 10373 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 10374 tcg_temp_free_i32(t1);
d94536f4
AJ
10375 tcg_gen_andi_i32(t0, t0, 1);
10376 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10377 }
5a5012ec
TS
10378 goto not_likely;
10379 case OPC_BC1TANY4:
a16336e4 10380 {
d94536f4
AJ
10381 TCGv_i32 t1 = tcg_temp_new_i32();
10382 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10383 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10384 tcg_gen_or_i32(t0, t0, t1);
10385 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10386 tcg_gen_or_i32(t0, t0, t1);
10387 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10388 tcg_gen_or_i32(t0, t0, t1);
10389 tcg_temp_free_i32(t1);
10390 tcg_gen_andi_i32(t0, t0, 1);
10391 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10392 }
5a5012ec
TS
10393 not_likely:
10394 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
10395 break;
10396 default:
9d68ac14 10397 MIPS_INVAL("cp1 cond branch");
9c708c7f 10398 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 10399 goto out;
6ea83fed 10400 }
6ea83fed 10401 ctx->btarget = btarget;
b231c103 10402 ctx->hflags |= MIPS_HFLAG_BDS32;
6c5c1e20 10403 out:
a7812ae4 10404 tcg_temp_free_i32(t0);
6ea83fed
FB
10405}
10406
31837be3
YK
10407/* R6 CP1 Branches */
10408static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
65935f07
YK
10409 int32_t ft, int32_t offset,
10410 int delayslot_size)
31837be3
YK
10411{
10412 target_ulong btarget;
31837be3
YK
10413 TCGv_i64 t0 = tcg_temp_new_i64();
10414
10415 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10416#ifdef MIPS_DEBUG_DISAS
339cd2a8 10417 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 10418 "\n", ctx->base.pc_next);
31837be3 10419#endif
9c708c7f 10420 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
10421 goto out;
10422 }
10423
10424 gen_load_fpr64(ctx, t0, ft);
10425 tcg_gen_andi_i64(t0, t0, 1);
10426
eeb3bba8 10427 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
31837be3
YK
10428
10429 switch (op) {
10430 case OPC_BC1EQZ:
10431 tcg_gen_xori_i64(t0, t0, 1);
31837be3
YK
10432 ctx->hflags |= MIPS_HFLAG_BC;
10433 break;
10434 case OPC_BC1NEZ:
10435 /* t0 already set */
31837be3
YK
10436 ctx->hflags |= MIPS_HFLAG_BC;
10437 break;
10438 default:
9d68ac14 10439 MIPS_INVAL("cp1 cond branch");
9c708c7f 10440 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
10441 goto out;
10442 }
10443
10444 tcg_gen_trunc_i64_tl(bcond, t0);
10445
31837be3 10446 ctx->btarget = btarget;
65935f07
YK
10447
10448 switch (delayslot_size) {
10449 case 2:
10450 ctx->hflags |= MIPS_HFLAG_BDS16;
10451 break;
10452 case 4:
10453 ctx->hflags |= MIPS_HFLAG_BDS32;
10454 break;
10455 }
31837be3
YK
10456
10457out:
10458 tcg_temp_free_i64(t0);
10459}
10460
6af0bf9c 10461/* Coprocessor 1 (FPU) */
5a5012ec 10462
5a5012ec
TS
10463#define FOP(func, fmt) (((fmt) << 21) | (func))
10464
bf4120ad
NF
10465enum fopcode {
10466 OPC_ADD_S = FOP(0, FMT_S),
10467 OPC_SUB_S = FOP(1, FMT_S),
10468 OPC_MUL_S = FOP(2, FMT_S),
10469 OPC_DIV_S = FOP(3, FMT_S),
10470 OPC_SQRT_S = FOP(4, FMT_S),
10471 OPC_ABS_S = FOP(5, FMT_S),
10472 OPC_MOV_S = FOP(6, FMT_S),
10473 OPC_NEG_S = FOP(7, FMT_S),
10474 OPC_ROUND_L_S = FOP(8, FMT_S),
10475 OPC_TRUNC_L_S = FOP(9, FMT_S),
10476 OPC_CEIL_L_S = FOP(10, FMT_S),
10477 OPC_FLOOR_L_S = FOP(11, FMT_S),
10478 OPC_ROUND_W_S = FOP(12, FMT_S),
10479 OPC_TRUNC_W_S = FOP(13, FMT_S),
10480 OPC_CEIL_W_S = FOP(14, FMT_S),
10481 OPC_FLOOR_W_S = FOP(15, FMT_S),
e7f16abb 10482 OPC_SEL_S = FOP(16, FMT_S),
bf4120ad
NF
10483 OPC_MOVCF_S = FOP(17, FMT_S),
10484 OPC_MOVZ_S = FOP(18, FMT_S),
10485 OPC_MOVN_S = FOP(19, FMT_S),
e7f16abb 10486 OPC_SELEQZ_S = FOP(20, FMT_S),
bf4120ad
NF
10487 OPC_RECIP_S = FOP(21, FMT_S),
10488 OPC_RSQRT_S = FOP(22, FMT_S),
e7f16abb
LA
10489 OPC_SELNEZ_S = FOP(23, FMT_S),
10490 OPC_MADDF_S = FOP(24, FMT_S),
10491 OPC_MSUBF_S = FOP(25, FMT_S),
10492 OPC_RINT_S = FOP(26, FMT_S),
10493 OPC_CLASS_S = FOP(27, FMT_S),
10494 OPC_MIN_S = FOP(28, FMT_S),
bf4120ad 10495 OPC_RECIP2_S = FOP(28, FMT_S),
e7f16abb 10496 OPC_MINA_S = FOP(29, FMT_S),
bf4120ad 10497 OPC_RECIP1_S = FOP(29, FMT_S),
e7f16abb 10498 OPC_MAX_S = FOP(30, FMT_S),
bf4120ad 10499 OPC_RSQRT1_S = FOP(30, FMT_S),
e7f16abb 10500 OPC_MAXA_S = FOP(31, FMT_S),
bf4120ad
NF
10501 OPC_RSQRT2_S = FOP(31, FMT_S),
10502 OPC_CVT_D_S = FOP(33, FMT_S),
10503 OPC_CVT_W_S = FOP(36, FMT_S),
10504 OPC_CVT_L_S = FOP(37, FMT_S),
10505 OPC_CVT_PS_S = FOP(38, FMT_S),
10506 OPC_CMP_F_S = FOP (48, FMT_S),
10507 OPC_CMP_UN_S = FOP (49, FMT_S),
10508 OPC_CMP_EQ_S = FOP (50, FMT_S),
10509 OPC_CMP_UEQ_S = FOP (51, FMT_S),
10510 OPC_CMP_OLT_S = FOP (52, FMT_S),
10511 OPC_CMP_ULT_S = FOP (53, FMT_S),
10512 OPC_CMP_OLE_S = FOP (54, FMT_S),
10513 OPC_CMP_ULE_S = FOP (55, FMT_S),
10514 OPC_CMP_SF_S = FOP (56, FMT_S),
10515 OPC_CMP_NGLE_S = FOP (57, FMT_S),
10516 OPC_CMP_SEQ_S = FOP (58, FMT_S),
10517 OPC_CMP_NGL_S = FOP (59, FMT_S),
10518 OPC_CMP_LT_S = FOP (60, FMT_S),
10519 OPC_CMP_NGE_S = FOP (61, FMT_S),
10520 OPC_CMP_LE_S = FOP (62, FMT_S),
10521 OPC_CMP_NGT_S = FOP (63, FMT_S),
10522
10523 OPC_ADD_D = FOP(0, FMT_D),
10524 OPC_SUB_D = FOP(1, FMT_D),
10525 OPC_MUL_D = FOP(2, FMT_D),
10526 OPC_DIV_D = FOP(3, FMT_D),
10527 OPC_SQRT_D = FOP(4, FMT_D),
10528 OPC_ABS_D = FOP(5, FMT_D),
10529 OPC_MOV_D = FOP(6, FMT_D),
10530 OPC_NEG_D = FOP(7, FMT_D),
10531 OPC_ROUND_L_D = FOP(8, FMT_D),
10532 OPC_TRUNC_L_D = FOP(9, FMT_D),
10533 OPC_CEIL_L_D = FOP(10, FMT_D),
10534 OPC_FLOOR_L_D = FOP(11, FMT_D),
10535 OPC_ROUND_W_D = FOP(12, FMT_D),
10536 OPC_TRUNC_W_D = FOP(13, FMT_D),
10537 OPC_CEIL_W_D = FOP(14, FMT_D),
10538 OPC_FLOOR_W_D = FOP(15, FMT_D),
e7f16abb 10539 OPC_SEL_D = FOP(16, FMT_D),
bf4120ad
NF
10540 OPC_MOVCF_D = FOP(17, FMT_D),
10541 OPC_MOVZ_D = FOP(18, FMT_D),
10542 OPC_MOVN_D = FOP(19, FMT_D),
e7f16abb 10543 OPC_SELEQZ_D = FOP(20, FMT_D),
bf4120ad
NF
10544 OPC_RECIP_D = FOP(21, FMT_D),
10545 OPC_RSQRT_D = FOP(22, FMT_D),
e7f16abb
LA
10546 OPC_SELNEZ_D = FOP(23, FMT_D),
10547 OPC_MADDF_D = FOP(24, FMT_D),
10548 OPC_MSUBF_D = FOP(25, FMT_D),
10549 OPC_RINT_D = FOP(26, FMT_D),
10550 OPC_CLASS_D = FOP(27, FMT_D),
10551 OPC_MIN_D = FOP(28, FMT_D),
bf4120ad 10552 OPC_RECIP2_D = FOP(28, FMT_D),
e7f16abb 10553 OPC_MINA_D = FOP(29, FMT_D),
bf4120ad 10554 OPC_RECIP1_D = FOP(29, FMT_D),
e7f16abb 10555 OPC_MAX_D = FOP(30, FMT_D),
bf4120ad 10556 OPC_RSQRT1_D = FOP(30, FMT_D),
e7f16abb 10557 OPC_MAXA_D = FOP(31, FMT_D),
bf4120ad
NF
10558 OPC_RSQRT2_D = FOP(31, FMT_D),
10559 OPC_CVT_S_D = FOP(32, FMT_D),
10560 OPC_CVT_W_D = FOP(36, FMT_D),
10561 OPC_CVT_L_D = FOP(37, FMT_D),
10562 OPC_CMP_F_D = FOP (48, FMT_D),
10563 OPC_CMP_UN_D = FOP (49, FMT_D),
10564 OPC_CMP_EQ_D = FOP (50, FMT_D),
10565 OPC_CMP_UEQ_D = FOP (51, FMT_D),
10566 OPC_CMP_OLT_D = FOP (52, FMT_D),
10567 OPC_CMP_ULT_D = FOP (53, FMT_D),
10568 OPC_CMP_OLE_D = FOP (54, FMT_D),
10569 OPC_CMP_ULE_D = FOP (55, FMT_D),
10570 OPC_CMP_SF_D = FOP (56, FMT_D),
10571 OPC_CMP_NGLE_D = FOP (57, FMT_D),
10572 OPC_CMP_SEQ_D = FOP (58, FMT_D),
10573 OPC_CMP_NGL_D = FOP (59, FMT_D),
10574 OPC_CMP_LT_D = FOP (60, FMT_D),
10575 OPC_CMP_NGE_D = FOP (61, FMT_D),
10576 OPC_CMP_LE_D = FOP (62, FMT_D),
10577 OPC_CMP_NGT_D = FOP (63, FMT_D),
10578
10579 OPC_CVT_S_W = FOP(32, FMT_W),
10580 OPC_CVT_D_W = FOP(33, FMT_W),
10581 OPC_CVT_S_L = FOP(32, FMT_L),
10582 OPC_CVT_D_L = FOP(33, FMT_L),
10583 OPC_CVT_PS_PW = FOP(38, FMT_W),
10584
10585 OPC_ADD_PS = FOP(0, FMT_PS),
10586 OPC_SUB_PS = FOP(1, FMT_PS),
10587 OPC_MUL_PS = FOP(2, FMT_PS),
10588 OPC_DIV_PS = FOP(3, FMT_PS),
10589 OPC_ABS_PS = FOP(5, FMT_PS),
10590 OPC_MOV_PS = FOP(6, FMT_PS),
10591 OPC_NEG_PS = FOP(7, FMT_PS),
10592 OPC_MOVCF_PS = FOP(17, FMT_PS),
10593 OPC_MOVZ_PS = FOP(18, FMT_PS),
10594 OPC_MOVN_PS = FOP(19, FMT_PS),
10595 OPC_ADDR_PS = FOP(24, FMT_PS),
10596 OPC_MULR_PS = FOP(26, FMT_PS),
10597 OPC_RECIP2_PS = FOP(28, FMT_PS),
10598 OPC_RECIP1_PS = FOP(29, FMT_PS),
10599 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10600 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10601
10602 OPC_CVT_S_PU = FOP(32, FMT_PS),
10603 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10604 OPC_CVT_S_PL = FOP(40, FMT_PS),
10605 OPC_PLL_PS = FOP(44, FMT_PS),
10606 OPC_PLU_PS = FOP(45, FMT_PS),
10607 OPC_PUL_PS = FOP(46, FMT_PS),
10608 OPC_PUU_PS = FOP(47, FMT_PS),
10609 OPC_CMP_F_PS = FOP (48, FMT_PS),
10610 OPC_CMP_UN_PS = FOP (49, FMT_PS),
10611 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
10612 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
10613 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
10614 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
10615 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
10616 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
10617 OPC_CMP_SF_PS = FOP (56, FMT_PS),
10618 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
10619 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
10620 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
10621 OPC_CMP_LT_PS = FOP (60, FMT_PS),
10622 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
10623 OPC_CMP_LE_PS = FOP (62, FMT_PS),
10624 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
10625};
10626
3f493883
YK
10627enum r6_f_cmp_op {
10628 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10629 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10630 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10631 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10632 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10633 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10634 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10635 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10636 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10637 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10638 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10639 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10640 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10641 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10642 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10643 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10644 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10645 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10646 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10647 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10648 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10649 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10650
10651 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10652 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10653 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10654 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10655 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10656 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10657 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10658 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10659 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10660 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10661 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10662 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10663 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10664 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10665 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10666 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10667 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10668 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10669 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10670 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10671 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10672 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10673};
7a387fff 10674static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 10675{
72c3a3ee 10676 TCGv t0 = tcg_temp_new();
6ea83fed
FB
10677
10678 switch (opc) {
10679 case OPC_MFC1:
b6d96bed 10680 {
a7812ae4 10681 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10682
7c979afd 10683 gen_load_fpr32(ctx, fp0, fs);
b6d96bed 10684 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 10685 tcg_temp_free_i32(fp0);
6958549d 10686 }
6c5c1e20 10687 gen_store_gpr(t0, rt);
6ea83fed
FB
10688 break;
10689 case OPC_MTC1:
6c5c1e20 10690 gen_load_gpr(t0, rt);
b6d96bed 10691 {
a7812ae4 10692 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
10693
10694 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 10695 gen_store_fpr32(ctx, fp0, fs);
a7812ae4 10696 tcg_temp_free_i32(fp0);
6958549d 10697 }
6ea83fed
FB
10698 break;
10699 case OPC_CFC1:
895c2d04 10700 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 10701 gen_store_gpr(t0, rt);
6ea83fed
FB
10702 break;
10703 case OPC_CTC1:
6c5c1e20 10704 gen_load_gpr(t0, rt);
9c708c7f 10705 save_cpu_state(ctx, 0);
736d120a
PJ
10706 {
10707 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10708
10709 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10710 tcg_temp_free_i32(fs_tmp);
10711 }
4cf8a45f 10712 /* Stop translation as we may have changed hflags */
eeb3bba8 10713 ctx->base.is_jmp = DISAS_STOP;
6ea83fed 10714 break;
72c3a3ee 10715#if defined(TARGET_MIPS64)
9c2149c8 10716 case OPC_DMFC1:
72c3a3ee 10717 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 10718 gen_store_gpr(t0, rt);
5a5012ec 10719 break;
9c2149c8 10720 case OPC_DMTC1:
6c5c1e20 10721 gen_load_gpr(t0, rt);
72c3a3ee 10722 gen_store_fpr64(ctx, t0, fs);
5a5012ec 10723 break;
72c3a3ee 10724#endif
5a5012ec 10725 case OPC_MFHC1:
b6d96bed 10726 {
a7812ae4 10727 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10728
7f6613ce 10729 gen_load_fpr32h(ctx, fp0, fs);
b6d96bed 10730 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 10731 tcg_temp_free_i32(fp0);
6958549d 10732 }
6c5c1e20 10733 gen_store_gpr(t0, rt);
5a5012ec
TS
10734 break;
10735 case OPC_MTHC1:
6c5c1e20 10736 gen_load_gpr(t0, rt);
b6d96bed 10737 {
a7812ae4 10738 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
10739
10740 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 10741 gen_store_fpr32h(ctx, fp0, fs);
a7812ae4 10742 tcg_temp_free_i32(fp0);
6958549d 10743 }
5a5012ec 10744 break;
6ea83fed 10745 default:
9d68ac14 10746 MIPS_INVAL("cp1 move");
9c708c7f 10747 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 10748 goto out;
6ea83fed 10749 }
6c5c1e20
TS
10750
10751 out:
10752 tcg_temp_free(t0);
6ea83fed
FB
10753}
10754
5a5012ec
TS
10755static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
10756{
42a268c2 10757 TCGLabel *l1;
e214b9bb 10758 TCGCond cond;
af58f9ca
AJ
10759 TCGv_i32 t0;
10760
10761 if (rd == 0) {
10762 /* Treat as NOP. */
10763 return;
10764 }
6ea83fed 10765
e214b9bb 10766 if (tf)
e214b9bb 10767 cond = TCG_COND_EQ;
27848470
TS
10768 else
10769 cond = TCG_COND_NE;
10770
af58f9ca
AJ
10771 l1 = gen_new_label();
10772 t0 = tcg_temp_new_i32();
fa31af0e 10773 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 10774 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 10775 tcg_temp_free_i32(t0);
af58f9ca
AJ
10776 if (rs == 0) {
10777 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10778 } else {
10779 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10780 }
e214b9bb 10781 gen_set_label(l1);
5a5012ec
TS
10782}
10783
7c979afd
LA
10784static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10785 int tf)
a16336e4 10786{
a16336e4 10787 int cond;
cbc37b28 10788 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2 10789 TCGLabel *l1 = gen_new_label();
a16336e4 10790
a16336e4
TS
10791 if (tf)
10792 cond = TCG_COND_EQ;
10793 else
10794 cond = TCG_COND_NE;
10795
fa31af0e 10796 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10797 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
10798 gen_load_fpr32(ctx, t0, fs);
10799 gen_store_fpr32(ctx, t0, fd);
a16336e4 10800 gen_set_label(l1);
cbc37b28 10801 tcg_temp_free_i32(t0);
5a5012ec 10802}
a16336e4 10803
b6d96bed 10804static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4 10805{
a16336e4 10806 int cond;
cbc37b28
AJ
10807 TCGv_i32 t0 = tcg_temp_new_i32();
10808 TCGv_i64 fp0;
42a268c2 10809 TCGLabel *l1 = gen_new_label();
a16336e4 10810
a16336e4
TS
10811 if (tf)
10812 cond = TCG_COND_EQ;
10813 else
10814 cond = TCG_COND_NE;
10815
fa31af0e 10816 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10817 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 10818 tcg_temp_free_i32(t0);
11f94258 10819 fp0 = tcg_temp_new_i64();
9bf3eb2c 10820 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 10821 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10822 tcg_temp_free_i64(fp0);
cbc37b28 10823 gen_set_label(l1);
a16336e4
TS
10824}
10825
7f6613ce
PJ
10826static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10827 int cc, int tf)
a16336e4
TS
10828{
10829 int cond;
cbc37b28 10830 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2
RH
10831 TCGLabel *l1 = gen_new_label();
10832 TCGLabel *l2 = gen_new_label();
a16336e4
TS
10833
10834 if (tf)
10835 cond = TCG_COND_EQ;
10836 else
10837 cond = TCG_COND_NE;
10838
fa31af0e 10839 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10840 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
10841 gen_load_fpr32(ctx, t0, fs);
10842 gen_store_fpr32(ctx, t0, fd);
a16336e4 10843 gen_set_label(l1);
9bf3eb2c 10844
fa31af0e 10845 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
cbc37b28 10846 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7f6613ce
PJ
10847 gen_load_fpr32h(ctx, t0, fs);
10848 gen_store_fpr32h(ctx, t0, fd);
52a0e9eb 10849 tcg_temp_free_i32(t0);
a16336e4 10850 gen_set_label(l2);
a16336e4
TS
10851}
10852
e7f16abb
LA
10853static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10854 int fs)
10855{
10856 TCGv_i32 t1 = tcg_const_i32(0);
10857 TCGv_i32 fp0 = tcg_temp_new_i32();
10858 TCGv_i32 fp1 = tcg_temp_new_i32();
10859 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10860 gen_load_fpr32(ctx, fp0, fd);
10861 gen_load_fpr32(ctx, fp1, ft);
10862 gen_load_fpr32(ctx, fp2, fs);
e7f16abb
LA
10863
10864 switch (op1) {
10865 case OPC_SEL_S:
10866 tcg_gen_andi_i32(fp0, fp0, 1);
10867 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10868 break;
10869 case OPC_SELEQZ_S:
10870 tcg_gen_andi_i32(fp1, fp1, 1);
10871 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10872 break;
10873 case OPC_SELNEZ_S:
10874 tcg_gen_andi_i32(fp1, fp1, 1);
10875 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10876 break;
10877 default:
10878 MIPS_INVAL("gen_sel_s");
9c708c7f 10879 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
10880 break;
10881 }
10882
7c979afd 10883 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10884 tcg_temp_free_i32(fp2);
10885 tcg_temp_free_i32(fp1);
10886 tcg_temp_free_i32(fp0);
10887 tcg_temp_free_i32(t1);
10888}
10889
10890static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10891 int fs)
10892{
10893 TCGv_i64 t1 = tcg_const_i64(0);
10894 TCGv_i64 fp0 = tcg_temp_new_i64();
10895 TCGv_i64 fp1 = tcg_temp_new_i64();
10896 TCGv_i64 fp2 = tcg_temp_new_i64();
10897 gen_load_fpr64(ctx, fp0, fd);
10898 gen_load_fpr64(ctx, fp1, ft);
10899 gen_load_fpr64(ctx, fp2, fs);
10900
10901 switch (op1) {
10902 case OPC_SEL_D:
10903 tcg_gen_andi_i64(fp0, fp0, 1);
10904 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10905 break;
10906 case OPC_SELEQZ_D:
10907 tcg_gen_andi_i64(fp1, fp1, 1);
10908 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10909 break;
10910 case OPC_SELNEZ_D:
10911 tcg_gen_andi_i64(fp1, fp1, 1);
10912 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10913 break;
10914 default:
10915 MIPS_INVAL("gen_sel_d");
9c708c7f 10916 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
10917 break;
10918 }
10919
10920 gen_store_fpr64(ctx, fp0, fd);
10921 tcg_temp_free_i64(fp2);
10922 tcg_temp_free_i64(fp1);
10923 tcg_temp_free_i64(fp0);
10924 tcg_temp_free_i64(t1);
10925}
6ea83fed 10926
bf4120ad 10927static void gen_farith (DisasContext *ctx, enum fopcode op1,
5e755519 10928 int ft, int fs, int fd, int cc)
6ea83fed 10929{
7a387fff 10930 uint32_t func = ctx->opcode & 0x3f;
bf4120ad
NF
10931 switch (op1) {
10932 case OPC_ADD_S:
b6d96bed 10933 {
a7812ae4
PB
10934 TCGv_i32 fp0 = tcg_temp_new_i32();
10935 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10936
7c979afd
LA
10937 gen_load_fpr32(ctx, fp0, fs);
10938 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10939 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10940 tcg_temp_free_i32(fp1);
7c979afd 10941 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10942 tcg_temp_free_i32(fp0);
b6d96bed 10943 }
5a5012ec 10944 break;
bf4120ad 10945 case OPC_SUB_S:
b6d96bed 10946 {
a7812ae4
PB
10947 TCGv_i32 fp0 = tcg_temp_new_i32();
10948 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10949
7c979afd
LA
10950 gen_load_fpr32(ctx, fp0, fs);
10951 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10952 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10953 tcg_temp_free_i32(fp1);
7c979afd 10954 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10955 tcg_temp_free_i32(fp0);
b6d96bed 10956 }
5a5012ec 10957 break;
bf4120ad 10958 case OPC_MUL_S:
b6d96bed 10959 {
a7812ae4
PB
10960 TCGv_i32 fp0 = tcg_temp_new_i32();
10961 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10962
7c979afd
LA
10963 gen_load_fpr32(ctx, fp0, fs);
10964 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10965 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10966 tcg_temp_free_i32(fp1);
7c979afd 10967 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10968 tcg_temp_free_i32(fp0);
b6d96bed 10969 }
5a5012ec 10970 break;
bf4120ad 10971 case OPC_DIV_S:
b6d96bed 10972 {
a7812ae4
PB
10973 TCGv_i32 fp0 = tcg_temp_new_i32();
10974 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10975
7c979afd
LA
10976 gen_load_fpr32(ctx, fp0, fs);
10977 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10978 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10979 tcg_temp_free_i32(fp1);
7c979afd 10980 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10981 tcg_temp_free_i32(fp0);
b6d96bed 10982 }
5a5012ec 10983 break;
bf4120ad 10984 case OPC_SQRT_S:
b6d96bed 10985 {
a7812ae4 10986 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10987
7c979afd 10988 gen_load_fpr32(ctx, fp0, fs);
895c2d04 10989 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
7c979afd 10990 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10991 tcg_temp_free_i32(fp0);
b6d96bed 10992 }
5a5012ec 10993 break;
bf4120ad 10994 case OPC_ABS_S:
b6d96bed 10995 {
a7812ae4 10996 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10997
7c979afd 10998 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
10999 if (ctx->abs2008) {
11000 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11001 } else {
11002 gen_helper_float_abs_s(fp0, fp0);
11003 }
7c979afd 11004 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11005 tcg_temp_free_i32(fp0);
b6d96bed 11006 }
5a5012ec 11007 break;
bf4120ad 11008 case OPC_MOV_S:
b6d96bed 11009 {
a7812ae4 11010 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11011
7c979afd
LA
11012 gen_load_fpr32(ctx, fp0, fs);
11013 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11014 tcg_temp_free_i32(fp0);
b6d96bed 11015 }
5a5012ec 11016 break;
bf4120ad 11017 case OPC_NEG_S:
b6d96bed 11018 {
a7812ae4 11019 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11020
7c979afd 11021 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
11022 if (ctx->abs2008) {
11023 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11024 } else {
11025 gen_helper_float_chs_s(fp0, fp0);
11026 }
7c979afd 11027 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11028 tcg_temp_free_i32(fp0);
b6d96bed 11029 }
5a5012ec 11030 break;
bf4120ad 11031 case OPC_ROUND_L_S:
5e755519 11032 check_cp1_64bitmode(ctx);
b6d96bed 11033 {
a7812ae4
PB
11034 TCGv_i32 fp32 = tcg_temp_new_i32();
11035 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11036
7c979afd 11037 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11038 if (ctx->nan2008) {
11039 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11040 } else {
11041 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11042 }
a7812ae4 11043 tcg_temp_free_i32(fp32);
b6d96bed 11044 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11045 tcg_temp_free_i64(fp64);
b6d96bed 11046 }
5a5012ec 11047 break;
bf4120ad 11048 case OPC_TRUNC_L_S:
5e755519 11049 check_cp1_64bitmode(ctx);
b6d96bed 11050 {
a7812ae4
PB
11051 TCGv_i32 fp32 = tcg_temp_new_i32();
11052 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11053
7c979afd 11054 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11055 if (ctx->nan2008) {
11056 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11057 } else {
11058 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11059 }
a7812ae4 11060 tcg_temp_free_i32(fp32);
b6d96bed 11061 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11062 tcg_temp_free_i64(fp64);
b6d96bed 11063 }
5a5012ec 11064 break;
bf4120ad 11065 case OPC_CEIL_L_S:
5e755519 11066 check_cp1_64bitmode(ctx);
b6d96bed 11067 {
a7812ae4
PB
11068 TCGv_i32 fp32 = tcg_temp_new_i32();
11069 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11070
7c979afd 11071 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11072 if (ctx->nan2008) {
11073 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11074 } else {
11075 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11076 }
a7812ae4 11077 tcg_temp_free_i32(fp32);
b6d96bed 11078 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11079 tcg_temp_free_i64(fp64);
b6d96bed 11080 }
5a5012ec 11081 break;
bf4120ad 11082 case OPC_FLOOR_L_S:
5e755519 11083 check_cp1_64bitmode(ctx);
b6d96bed 11084 {
a7812ae4
PB
11085 TCGv_i32 fp32 = tcg_temp_new_i32();
11086 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11087
7c979afd 11088 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11089 if (ctx->nan2008) {
11090 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11091 } else {
11092 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11093 }
a7812ae4 11094 tcg_temp_free_i32(fp32);
b6d96bed 11095 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11096 tcg_temp_free_i64(fp64);
b6d96bed 11097 }
5a5012ec 11098 break;
bf4120ad 11099 case OPC_ROUND_W_S:
b6d96bed 11100 {
a7812ae4 11101 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11102
7c979afd 11103 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11104 if (ctx->nan2008) {
11105 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11106 } else {
11107 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11108 }
7c979afd 11109 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11110 tcg_temp_free_i32(fp0);
b6d96bed 11111 }
5a5012ec 11112 break;
bf4120ad 11113 case OPC_TRUNC_W_S:
b6d96bed 11114 {
a7812ae4 11115 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11116
7c979afd 11117 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11118 if (ctx->nan2008) {
11119 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11120 } else {
11121 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11122 }
7c979afd 11123 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11124 tcg_temp_free_i32(fp0);
b6d96bed 11125 }
5a5012ec 11126 break;
bf4120ad 11127 case OPC_CEIL_W_S:
b6d96bed 11128 {
a7812ae4 11129 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11130
7c979afd 11131 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11132 if (ctx->nan2008) {
11133 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11134 } else {
11135 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11136 }
7c979afd 11137 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11138 tcg_temp_free_i32(fp0);
b6d96bed 11139 }
5a5012ec 11140 break;
bf4120ad 11141 case OPC_FLOOR_W_S:
b6d96bed 11142 {
a7812ae4 11143 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11144
7c979afd 11145 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11146 if (ctx->nan2008) {
11147 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11148 } else {
11149 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11150 }
7c979afd 11151 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11152 tcg_temp_free_i32(fp0);
b6d96bed 11153 }
5a5012ec 11154 break;
e7f16abb
LA
11155 case OPC_SEL_S:
11156 check_insn(ctx, ISA_MIPS32R6);
11157 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
11158 break;
11159 case OPC_SELEQZ_S:
11160 check_insn(ctx, ISA_MIPS32R6);
11161 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
11162 break;
11163 case OPC_SELNEZ_S:
11164 check_insn(ctx, ISA_MIPS32R6);
11165 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb 11166 break;
bf4120ad 11167 case OPC_MOVCF_S:
fecd2646 11168 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7c979afd 11169 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 11170 break;
bf4120ad 11171 case OPC_MOVZ_S:
fecd2646 11172 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11173 {
42a268c2 11174 TCGLabel *l1 = gen_new_label();
c9297f4d 11175 TCGv_i32 fp0;
a16336e4 11176
c9297f4d
AJ
11177 if (ft != 0) {
11178 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11179 }
11180 fp0 = tcg_temp_new_i32();
7c979afd
LA
11181 gen_load_fpr32(ctx, fp0, fs);
11182 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11183 tcg_temp_free_i32(fp0);
a16336e4
TS
11184 gen_set_label(l1);
11185 }
5a5012ec 11186 break;
bf4120ad 11187 case OPC_MOVN_S:
fecd2646 11188 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11189 {
42a268c2 11190 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
11191 TCGv_i32 fp0;
11192
11193 if (ft != 0) {
11194 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11195 fp0 = tcg_temp_new_i32();
7c979afd
LA
11196 gen_load_fpr32(ctx, fp0, fs);
11197 gen_store_fpr32(ctx, fp0, fd);
c9297f4d
AJ
11198 tcg_temp_free_i32(fp0);
11199 gen_set_label(l1);
11200 }
a16336e4 11201 }
5a5012ec 11202 break;
bf4120ad 11203 case OPC_RECIP_S:
b6d96bed 11204 {
a7812ae4 11205 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11206
7c979afd 11207 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11208 gen_helper_float_recip_s(fp0, cpu_env, fp0);
7c979afd 11209 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11210 tcg_temp_free_i32(fp0);
b6d96bed 11211 }
57fa1fb3 11212 break;
bf4120ad 11213 case OPC_RSQRT_S:
b6d96bed 11214 {
a7812ae4 11215 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11216
7c979afd 11217 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11218 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
7c979afd 11219 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11220 tcg_temp_free_i32(fp0);
b6d96bed 11221 }
57fa1fb3 11222 break;
e7f16abb
LA
11223 case OPC_MADDF_S:
11224 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11225 {
a7812ae4
PB
11226 TCGv_i32 fp0 = tcg_temp_new_i32();
11227 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 11228 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11229 gen_load_fpr32(ctx, fp0, fs);
11230 gen_load_fpr32(ctx, fp1, ft);
11231 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 11232 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 11233 gen_store_fpr32(ctx, fp2, fd);
e7f16abb 11234 tcg_temp_free_i32(fp2);
a7812ae4 11235 tcg_temp_free_i32(fp1);
a7812ae4 11236 tcg_temp_free_i32(fp0);
b6d96bed 11237 }
57fa1fb3 11238 break;
e7f16abb
LA
11239 case OPC_MSUBF_S:
11240 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11241 {
a7812ae4 11242 TCGv_i32 fp0 = tcg_temp_new_i32();
e7f16abb
LA
11243 TCGv_i32 fp1 = tcg_temp_new_i32();
11244 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11245 gen_load_fpr32(ctx, fp0, fs);
11246 gen_load_fpr32(ctx, fp1, ft);
11247 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 11248 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 11249 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11250 tcg_temp_free_i32(fp2);
11251 tcg_temp_free_i32(fp1);
a7812ae4 11252 tcg_temp_free_i32(fp0);
b6d96bed 11253 }
57fa1fb3 11254 break;
e7f16abb
LA
11255 case OPC_RINT_S:
11256 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11257 {
a7812ae4 11258 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 11259 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11260 gen_helper_float_rint_s(fp0, cpu_env, fp0);
7c979afd 11261 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11262 tcg_temp_free_i32(fp0);
b6d96bed 11263 }
57fa1fb3 11264 break;
e7f16abb
LA
11265 case OPC_CLASS_S:
11266 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11267 {
e7f16abb 11268 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 11269 gen_load_fpr32(ctx, fp0, fs);
af39bc8c 11270 gen_helper_float_class_s(fp0, cpu_env, fp0);
7c979afd 11271 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 11272 tcg_temp_free_i32(fp0);
e7f16abb
LA
11273 }
11274 break;
11275 case OPC_MIN_S: /* OPC_RECIP2_S */
11276 if (ctx->insn_flags & ISA_MIPS32R6) {
11277 /* OPC_MIN_S */
a7812ae4
PB
11278 TCGv_i32 fp0 = tcg_temp_new_i32();
11279 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 11280 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11281 gen_load_fpr32(ctx, fp0, fs);
11282 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11283 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
7c979afd 11284 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11285 tcg_temp_free_i32(fp2);
11286 tcg_temp_free_i32(fp1);
11287 tcg_temp_free_i32(fp0);
e7f16abb
LA
11288 } else {
11289 /* OPC_RECIP2_S */
11290 check_cp1_64bitmode(ctx);
11291 {
11292 TCGv_i32 fp0 = tcg_temp_new_i32();
11293 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11294
7c979afd
LA
11295 gen_load_fpr32(ctx, fp0, fs);
11296 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
11297 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11298 tcg_temp_free_i32(fp1);
7c979afd 11299 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11300 tcg_temp_free_i32(fp0);
11301 }
e7f16abb
LA
11302 }
11303 break;
11304 case OPC_MINA_S: /* OPC_RECIP1_S */
11305 if (ctx->insn_flags & ISA_MIPS32R6) {
11306 /* OPC_MINA_S */
11307 TCGv_i32 fp0 = tcg_temp_new_i32();
11308 TCGv_i32 fp1 = tcg_temp_new_i32();
11309 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
11310 gen_load_fpr32(ctx, fp0, fs);
11311 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11312 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
7c979afd 11313 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
11314 tcg_temp_free_i32(fp2);
11315 tcg_temp_free_i32(fp1);
11316 tcg_temp_free_i32(fp0);
e7f16abb
LA
11317 } else {
11318 /* OPC_RECIP1_S */
11319 check_cp1_64bitmode(ctx);
11320 {
11321 TCGv_i32 fp0 = tcg_temp_new_i32();
11322
7c979afd 11323 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11324 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
7c979afd 11325 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11326 tcg_temp_free_i32(fp0);
11327 }
e7f16abb
LA
11328 }
11329 break;
11330 case OPC_MAX_S: /* OPC_RSQRT1_S */
11331 if (ctx->insn_flags & ISA_MIPS32R6) {
11332 /* OPC_MAX_S */
11333 TCGv_i32 fp0 = tcg_temp_new_i32();
11334 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
11335 gen_load_fpr32(ctx, fp0, fs);
11336 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11337 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
7c979afd 11338 gen_store_fpr32(ctx, fp1, fd);
e7f16abb
LA
11339 tcg_temp_free_i32(fp1);
11340 tcg_temp_free_i32(fp0);
e7f16abb
LA
11341 } else {
11342 /* OPC_RSQRT1_S */
11343 check_cp1_64bitmode(ctx);
11344 {
11345 TCGv_i32 fp0 = tcg_temp_new_i32();
11346
7c979afd 11347 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11348 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
7c979afd 11349 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11350 tcg_temp_free_i32(fp0);
11351 }
e7f16abb
LA
11352 }
11353 break;
11354 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11355 if (ctx->insn_flags & ISA_MIPS32R6) {
11356 /* OPC_MAXA_S */
11357 TCGv_i32 fp0 = tcg_temp_new_i32();
11358 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
11359 gen_load_fpr32(ctx, fp0, fs);
11360 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11361 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
7c979afd 11362 gen_store_fpr32(ctx, fp1, fd);
a7812ae4 11363 tcg_temp_free_i32(fp1);
a7812ae4 11364 tcg_temp_free_i32(fp0);
e7f16abb
LA
11365 } else {
11366 /* OPC_RSQRT2_S */
11367 check_cp1_64bitmode(ctx);
11368 {
11369 TCGv_i32 fp0 = tcg_temp_new_i32();
11370 TCGv_i32 fp1 = tcg_temp_new_i32();
11371
7c979afd
LA
11372 gen_load_fpr32(ctx, fp0, fs);
11373 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
11374 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11375 tcg_temp_free_i32(fp1);
7c979afd 11376 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11377 tcg_temp_free_i32(fp0);
11378 }
b6d96bed 11379 }
57fa1fb3 11380 break;
bf4120ad 11381 case OPC_CVT_D_S:
5e755519 11382 check_cp1_registers(ctx, fd);
b6d96bed 11383 {
a7812ae4
PB
11384 TCGv_i32 fp32 = tcg_temp_new_i32();
11385 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11386
7c979afd 11387 gen_load_fpr32(ctx, fp32, fs);
895c2d04 11388 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 11389 tcg_temp_free_i32(fp32);
b6d96bed 11390 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11391 tcg_temp_free_i64(fp64);
b6d96bed 11392 }
5a5012ec 11393 break;
bf4120ad 11394 case OPC_CVT_W_S:
b6d96bed 11395 {
a7812ae4 11396 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11397
7c979afd 11398 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11399 if (ctx->nan2008) {
11400 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11401 } else {
11402 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11403 }
7c979afd 11404 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11405 tcg_temp_free_i32(fp0);
b6d96bed 11406 }
5a5012ec 11407 break;
bf4120ad 11408 case OPC_CVT_L_S:
5e755519 11409 check_cp1_64bitmode(ctx);
b6d96bed 11410 {
a7812ae4
PB
11411 TCGv_i32 fp32 = tcg_temp_new_i32();
11412 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11413
7c979afd 11414 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
11415 if (ctx->nan2008) {
11416 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11417 } else {
11418 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11419 }
a7812ae4 11420 tcg_temp_free_i32(fp32);
b6d96bed 11421 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11422 tcg_temp_free_i64(fp64);
b6d96bed 11423 }
5a5012ec 11424 break;
bf4120ad 11425 case OPC_CVT_PS_S:
e29c9628 11426 check_ps(ctx);
b6d96bed 11427 {
a7812ae4
PB
11428 TCGv_i64 fp64 = tcg_temp_new_i64();
11429 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11430 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed 11431
7c979afd
LA
11432 gen_load_fpr32(ctx, fp32_0, fs);
11433 gen_load_fpr32(ctx, fp32_1, ft);
13d24f49 11434 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
11435 tcg_temp_free_i32(fp32_1);
11436 tcg_temp_free_i32(fp32_0);
36aa55dc 11437 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11438 tcg_temp_free_i64(fp64);
b6d96bed 11439 }
5a5012ec 11440 break;
bf4120ad
NF
11441 case OPC_CMP_F_S:
11442 case OPC_CMP_UN_S:
11443 case OPC_CMP_EQ_S:
11444 case OPC_CMP_UEQ_S:
11445 case OPC_CMP_OLT_S:
11446 case OPC_CMP_ULT_S:
11447 case OPC_CMP_OLE_S:
11448 case OPC_CMP_ULE_S:
11449 case OPC_CMP_SF_S:
11450 case OPC_CMP_NGLE_S:
11451 case OPC_CMP_SEQ_S:
11452 case OPC_CMP_NGL_S:
11453 case OPC_CMP_LT_S:
11454 case OPC_CMP_NGE_S:
11455 case OPC_CMP_LE_S:
11456 case OPC_CMP_NGT_S:
fecd2646 11457 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c
NF
11458 if (ctx->opcode & (1 << 6)) {
11459 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
8153667c
NF
11460 } else {
11461 gen_cmp_s(ctx, func-48, ft, fs, cc);
5a1e8ffb 11462 }
5a5012ec 11463 break;
bf4120ad 11464 case OPC_ADD_D:
5e755519 11465 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11466 {
a7812ae4
PB
11467 TCGv_i64 fp0 = tcg_temp_new_i64();
11468 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11469
11470 gen_load_fpr64(ctx, fp0, fs);
11471 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11472 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11473 tcg_temp_free_i64(fp1);
b6d96bed 11474 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11475 tcg_temp_free_i64(fp0);
b6d96bed 11476 }
6ea83fed 11477 break;
bf4120ad 11478 case OPC_SUB_D:
5e755519 11479 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11480 {
a7812ae4
PB
11481 TCGv_i64 fp0 = tcg_temp_new_i64();
11482 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11483
11484 gen_load_fpr64(ctx, fp0, fs);
11485 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11486 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11487 tcg_temp_free_i64(fp1);
b6d96bed 11488 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11489 tcg_temp_free_i64(fp0);
b6d96bed 11490 }
6ea83fed 11491 break;
bf4120ad 11492 case OPC_MUL_D:
5e755519 11493 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11494 {
a7812ae4
PB
11495 TCGv_i64 fp0 = tcg_temp_new_i64();
11496 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11497
11498 gen_load_fpr64(ctx, fp0, fs);
11499 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11500 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11501 tcg_temp_free_i64(fp1);
b6d96bed 11502 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11503 tcg_temp_free_i64(fp0);
b6d96bed 11504 }
6ea83fed 11505 break;
bf4120ad 11506 case OPC_DIV_D:
5e755519 11507 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11508 {
a7812ae4
PB
11509 TCGv_i64 fp0 = tcg_temp_new_i64();
11510 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11511
11512 gen_load_fpr64(ctx, fp0, fs);
11513 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11514 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11515 tcg_temp_free_i64(fp1);
b6d96bed 11516 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11517 tcg_temp_free_i64(fp0);
b6d96bed 11518 }
6ea83fed 11519 break;
bf4120ad 11520 case OPC_SQRT_D:
5e755519 11521 check_cp1_registers(ctx, fs | fd);
b6d96bed 11522 {
a7812ae4 11523 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11524
11525 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11526 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 11527 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11528 tcg_temp_free_i64(fp0);
b6d96bed 11529 }
6ea83fed 11530 break;
bf4120ad 11531 case OPC_ABS_D:
5e755519 11532 check_cp1_registers(ctx, fs | fd);
b6d96bed 11533 {
a7812ae4 11534 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11535
11536 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
11537 if (ctx->abs2008) {
11538 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11539 } else {
11540 gen_helper_float_abs_d(fp0, fp0);
11541 }
b6d96bed 11542 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11543 tcg_temp_free_i64(fp0);
b6d96bed 11544 }
6ea83fed 11545 break;
bf4120ad 11546 case OPC_MOV_D:
5e755519 11547 check_cp1_registers(ctx, fs | fd);
b6d96bed 11548 {
a7812ae4 11549 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11550
11551 gen_load_fpr64(ctx, fp0, fs);
11552 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11553 tcg_temp_free_i64(fp0);
b6d96bed 11554 }
6ea83fed 11555 break;
bf4120ad 11556 case OPC_NEG_D:
5e755519 11557 check_cp1_registers(ctx, fs | fd);
b6d96bed 11558 {
a7812ae4 11559 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11560
11561 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
11562 if (ctx->abs2008) {
11563 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11564 } else {
11565 gen_helper_float_chs_d(fp0, fp0);
11566 }
b6d96bed 11567 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11568 tcg_temp_free_i64(fp0);
b6d96bed 11569 }
6ea83fed 11570 break;
bf4120ad 11571 case OPC_ROUND_L_D:
5e755519 11572 check_cp1_64bitmode(ctx);
b6d96bed 11573 {
a7812ae4 11574 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11575
11576 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11577 if (ctx->nan2008) {
11578 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11579 } else {
11580 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11581 }
b6d96bed 11582 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11583 tcg_temp_free_i64(fp0);
b6d96bed 11584 }
5a5012ec 11585 break;
bf4120ad 11586 case OPC_TRUNC_L_D:
5e755519 11587 check_cp1_64bitmode(ctx);
b6d96bed 11588 {
a7812ae4 11589 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11590
11591 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11592 if (ctx->nan2008) {
11593 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11594 } else {
11595 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11596 }
b6d96bed 11597 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11598 tcg_temp_free_i64(fp0);
b6d96bed 11599 }
5a5012ec 11600 break;
bf4120ad 11601 case OPC_CEIL_L_D:
5e755519 11602 check_cp1_64bitmode(ctx);
b6d96bed 11603 {
a7812ae4 11604 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11605
11606 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11607 if (ctx->nan2008) {
11608 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11609 } else {
11610 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11611 }
b6d96bed 11612 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11613 tcg_temp_free_i64(fp0);
b6d96bed 11614 }
5a5012ec 11615 break;
bf4120ad 11616 case OPC_FLOOR_L_D:
5e755519 11617 check_cp1_64bitmode(ctx);
b6d96bed 11618 {
a7812ae4 11619 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11620
11621 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11622 if (ctx->nan2008) {
11623 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11624 } else {
11625 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11626 }
b6d96bed 11627 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11628 tcg_temp_free_i64(fp0);
b6d96bed 11629 }
5a5012ec 11630 break;
bf4120ad 11631 case OPC_ROUND_W_D:
5e755519 11632 check_cp1_registers(ctx, fs);
b6d96bed 11633 {
a7812ae4
PB
11634 TCGv_i32 fp32 = tcg_temp_new_i32();
11635 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11636
11637 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11638 if (ctx->nan2008) {
11639 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11640 } else {
11641 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11642 }
a7812ae4 11643 tcg_temp_free_i64(fp64);
7c979afd 11644 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11645 tcg_temp_free_i32(fp32);
b6d96bed 11646 }
6ea83fed 11647 break;
bf4120ad 11648 case OPC_TRUNC_W_D:
5e755519 11649 check_cp1_registers(ctx, fs);
b6d96bed 11650 {
a7812ae4
PB
11651 TCGv_i32 fp32 = tcg_temp_new_i32();
11652 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11653
11654 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11655 if (ctx->nan2008) {
11656 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11657 } else {
11658 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11659 }
a7812ae4 11660 tcg_temp_free_i64(fp64);
7c979afd 11661 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11662 tcg_temp_free_i32(fp32);
b6d96bed 11663 }
6ea83fed 11664 break;
bf4120ad 11665 case OPC_CEIL_W_D:
5e755519 11666 check_cp1_registers(ctx, fs);
b6d96bed 11667 {
a7812ae4
PB
11668 TCGv_i32 fp32 = tcg_temp_new_i32();
11669 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11670
11671 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11672 if (ctx->nan2008) {
11673 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11674 } else {
11675 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11676 }
a7812ae4 11677 tcg_temp_free_i64(fp64);
7c979afd 11678 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11679 tcg_temp_free_i32(fp32);
b6d96bed 11680 }
6ea83fed 11681 break;
bf4120ad 11682 case OPC_FLOOR_W_D:
5e755519 11683 check_cp1_registers(ctx, fs);
b6d96bed 11684 {
a7812ae4
PB
11685 TCGv_i32 fp32 = tcg_temp_new_i32();
11686 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11687
11688 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11689 if (ctx->nan2008) {
11690 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11691 } else {
11692 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11693 }
a7812ae4 11694 tcg_temp_free_i64(fp64);
7c979afd 11695 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11696 tcg_temp_free_i32(fp32);
b6d96bed 11697 }
6ea83fed 11698 break;
e7f16abb
LA
11699 case OPC_SEL_D:
11700 check_insn(ctx, ISA_MIPS32R6);
11701 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
11702 break;
11703 case OPC_SELEQZ_D:
11704 check_insn(ctx, ISA_MIPS32R6);
11705 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
11706 break;
11707 case OPC_SELNEZ_D:
11708 check_insn(ctx, ISA_MIPS32R6);
11709 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb 11710 break;
bf4120ad 11711 case OPC_MOVCF_D:
fecd2646 11712 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6d96bed 11713 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
dd016883 11714 break;
bf4120ad 11715 case OPC_MOVZ_D:
fecd2646 11716 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11717 {
42a268c2 11718 TCGLabel *l1 = gen_new_label();
c9297f4d 11719 TCGv_i64 fp0;
a16336e4 11720
c9297f4d
AJ
11721 if (ft != 0) {
11722 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11723 }
11724 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11725 gen_load_fpr64(ctx, fp0, fs);
11726 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11727 tcg_temp_free_i64(fp0);
a16336e4
TS
11728 gen_set_label(l1);
11729 }
5a5012ec 11730 break;
bf4120ad 11731 case OPC_MOVN_D:
fecd2646 11732 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11733 {
42a268c2 11734 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
11735 TCGv_i64 fp0;
11736
11737 if (ft != 0) {
11738 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11739 fp0 = tcg_temp_new_i64();
11740 gen_load_fpr64(ctx, fp0, fs);
11741 gen_store_fpr64(ctx, fp0, fd);
11742 tcg_temp_free_i64(fp0);
11743 gen_set_label(l1);
11744 }
a16336e4 11745 }
6ea83fed 11746 break;
bf4120ad 11747 case OPC_RECIP_D:
ca6c7803 11748 check_cp1_registers(ctx, fs | fd);
b6d96bed 11749 {
a7812ae4 11750 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11751
11752 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11753 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 11754 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11755 tcg_temp_free_i64(fp0);
b6d96bed 11756 }
57fa1fb3 11757 break;
bf4120ad 11758 case OPC_RSQRT_D:
ca6c7803 11759 check_cp1_registers(ctx, fs | fd);
b6d96bed 11760 {
a7812ae4 11761 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11762
11763 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11764 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 11765 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11766 tcg_temp_free_i64(fp0);
b6d96bed 11767 }
57fa1fb3 11768 break;
e7f16abb
LA
11769 case OPC_MADDF_D:
11770 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11771 {
a7812ae4
PB
11772 TCGv_i64 fp0 = tcg_temp_new_i64();
11773 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb 11774 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11775 gen_load_fpr64(ctx, fp0, fs);
11776 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
11777 gen_load_fpr64(ctx, fp2, fd);
11778 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11779 gen_store_fpr64(ctx, fp2, fd);
11780 tcg_temp_free_i64(fp2);
a7812ae4 11781 tcg_temp_free_i64(fp1);
a7812ae4 11782 tcg_temp_free_i64(fp0);
b6d96bed 11783 }
57fa1fb3 11784 break;
e7f16abb
LA
11785 case OPC_MSUBF_D:
11786 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11787 {
a7812ae4 11788 TCGv_i64 fp0 = tcg_temp_new_i64();
e7f16abb
LA
11789 TCGv_i64 fp1 = tcg_temp_new_i64();
11790 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed 11791 gen_load_fpr64(ctx, fp0, fs);
e7f16abb
LA
11792 gen_load_fpr64(ctx, fp1, ft);
11793 gen_load_fpr64(ctx, fp2, fd);
11794 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11795 gen_store_fpr64(ctx, fp2, fd);
11796 tcg_temp_free_i64(fp2);
11797 tcg_temp_free_i64(fp1);
a7812ae4 11798 tcg_temp_free_i64(fp0);
b6d96bed 11799 }
57fa1fb3 11800 break;
e7f16abb
LA
11801 case OPC_RINT_D:
11802 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11803 {
a7812ae4 11804 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11805 gen_load_fpr64(ctx, fp0, fs);
e7f16abb 11806 gen_helper_float_rint_d(fp0, cpu_env, fp0);
b6d96bed 11807 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11808 tcg_temp_free_i64(fp0);
b6d96bed 11809 }
57fa1fb3 11810 break;
e7f16abb
LA
11811 case OPC_CLASS_D:
11812 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11813 {
e7f16abb
LA
11814 TCGv_i64 fp0 = tcg_temp_new_i64();
11815 gen_load_fpr64(ctx, fp0, fs);
af39bc8c 11816 gen_helper_float_class_d(fp0, cpu_env, fp0);
e7f16abb
LA
11817 gen_store_fpr64(ctx, fp0, fd);
11818 tcg_temp_free_i64(fp0);
e7f16abb
LA
11819 }
11820 break;
11821 case OPC_MIN_D: /* OPC_RECIP2_D */
11822 if (ctx->insn_flags & ISA_MIPS32R6) {
11823 /* OPC_MIN_D */
a7812ae4
PB
11824 TCGv_i64 fp0 = tcg_temp_new_i64();
11825 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb
LA
11826 gen_load_fpr64(ctx, fp0, fs);
11827 gen_load_fpr64(ctx, fp1, ft);
11828 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11829 gen_store_fpr64(ctx, fp1, fd);
11830 tcg_temp_free_i64(fp1);
11831 tcg_temp_free_i64(fp0);
e7f16abb
LA
11832 } else {
11833 /* OPC_RECIP2_D */
11834 check_cp1_64bitmode(ctx);
11835 {
11836 TCGv_i64 fp0 = tcg_temp_new_i64();
11837 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed 11838
e7f16abb
LA
11839 gen_load_fpr64(ctx, fp0, fs);
11840 gen_load_fpr64(ctx, fp1, ft);
11841 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11842 tcg_temp_free_i64(fp1);
11843 gen_store_fpr64(ctx, fp0, fd);
11844 tcg_temp_free_i64(fp0);
11845 }
e7f16abb
LA
11846 }
11847 break;
11848 case OPC_MINA_D: /* OPC_RECIP1_D */
11849 if (ctx->insn_flags & ISA_MIPS32R6) {
11850 /* OPC_MINA_D */
11851 TCGv_i64 fp0 = tcg_temp_new_i64();
11852 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11853 gen_load_fpr64(ctx, fp0, fs);
11854 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
11855 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11856 gen_store_fpr64(ctx, fp1, fd);
11857 tcg_temp_free_i64(fp1);
11858 tcg_temp_free_i64(fp0);
e7f16abb
LA
11859 } else {
11860 /* OPC_RECIP1_D */
11861 check_cp1_64bitmode(ctx);
11862 {
11863 TCGv_i64 fp0 = tcg_temp_new_i64();
11864
11865 gen_load_fpr64(ctx, fp0, fs);
11866 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11867 gen_store_fpr64(ctx, fp0, fd);
11868 tcg_temp_free_i64(fp0);
11869 }
e7f16abb
LA
11870 }
11871 break;
11872 case OPC_MAX_D: /* OPC_RSQRT1_D */
11873 if (ctx->insn_flags & ISA_MIPS32R6) {
11874 /* OPC_MAX_D */
11875 TCGv_i64 fp0 = tcg_temp_new_i64();
11876 TCGv_i64 fp1 = tcg_temp_new_i64();
11877 gen_load_fpr64(ctx, fp0, fs);
11878 gen_load_fpr64(ctx, fp1, ft);
11879 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11880 gen_store_fpr64(ctx, fp1, fd);
a7812ae4 11881 tcg_temp_free_i64(fp1);
a7812ae4 11882 tcg_temp_free_i64(fp0);
e7f16abb
LA
11883 } else {
11884 /* OPC_RSQRT1_D */
11885 check_cp1_64bitmode(ctx);
11886 {
11887 TCGv_i64 fp0 = tcg_temp_new_i64();
11888
11889 gen_load_fpr64(ctx, fp0, fs);
11890 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11891 gen_store_fpr64(ctx, fp0, fd);
11892 tcg_temp_free_i64(fp0);
11893 }
e7f16abb
LA
11894 }
11895 break;
11896 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11897 if (ctx->insn_flags & ISA_MIPS32R6) {
11898 /* OPC_MAXA_D */
11899 TCGv_i64 fp0 = tcg_temp_new_i64();
11900 TCGv_i64 fp1 = tcg_temp_new_i64();
11901 gen_load_fpr64(ctx, fp0, fs);
11902 gen_load_fpr64(ctx, fp1, ft);
11903 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11904 gen_store_fpr64(ctx, fp1, fd);
11905 tcg_temp_free_i64(fp1);
11906 tcg_temp_free_i64(fp0);
e7f16abb
LA
11907 } else {
11908 /* OPC_RSQRT2_D */
11909 check_cp1_64bitmode(ctx);
11910 {
11911 TCGv_i64 fp0 = tcg_temp_new_i64();
11912 TCGv_i64 fp1 = tcg_temp_new_i64();
11913
11914 gen_load_fpr64(ctx, fp0, fs);
11915 gen_load_fpr64(ctx, fp1, ft);
11916 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11917 tcg_temp_free_i64(fp1);
11918 gen_store_fpr64(ctx, fp0, fd);
11919 tcg_temp_free_i64(fp0);
11920 }
b6d96bed 11921 }
57fa1fb3 11922 break;
bf4120ad
NF
11923 case OPC_CMP_F_D:
11924 case OPC_CMP_UN_D:
11925 case OPC_CMP_EQ_D:
11926 case OPC_CMP_UEQ_D:
11927 case OPC_CMP_OLT_D:
11928 case OPC_CMP_ULT_D:
11929 case OPC_CMP_OLE_D:
11930 case OPC_CMP_ULE_D:
11931 case OPC_CMP_SF_D:
11932 case OPC_CMP_NGLE_D:
11933 case OPC_CMP_SEQ_D:
11934 case OPC_CMP_NGL_D:
11935 case OPC_CMP_LT_D:
11936 case OPC_CMP_NGE_D:
11937 case OPC_CMP_LE_D:
11938 case OPC_CMP_NGT_D:
fecd2646 11939 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c
NF
11940 if (ctx->opcode & (1 << 6)) {
11941 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
8153667c
NF
11942 } else {
11943 gen_cmp_d(ctx, func-48, ft, fs, cc);
5a1e8ffb 11944 }
6ea83fed 11945 break;
bf4120ad 11946 case OPC_CVT_S_D:
5e755519 11947 check_cp1_registers(ctx, fs);
b6d96bed 11948 {
a7812ae4
PB
11949 TCGv_i32 fp32 = tcg_temp_new_i32();
11950 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11951
11952 gen_load_fpr64(ctx, fp64, fs);
895c2d04 11953 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 11954 tcg_temp_free_i64(fp64);
7c979afd 11955 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11956 tcg_temp_free_i32(fp32);
b6d96bed 11957 }
5a5012ec 11958 break;
bf4120ad 11959 case OPC_CVT_W_D:
5e755519 11960 check_cp1_registers(ctx, fs);
b6d96bed 11961 {
a7812ae4
PB
11962 TCGv_i32 fp32 = tcg_temp_new_i32();
11963 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11964
11965 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11966 if (ctx->nan2008) {
11967 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11968 } else {
11969 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11970 }
a7812ae4 11971 tcg_temp_free_i64(fp64);
7c979afd 11972 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11973 tcg_temp_free_i32(fp32);
b6d96bed 11974 }
5a5012ec 11975 break;
bf4120ad 11976 case OPC_CVT_L_D:
5e755519 11977 check_cp1_64bitmode(ctx);
b6d96bed 11978 {
a7812ae4 11979 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11980
11981 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11982 if (ctx->nan2008) {
11983 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11984 } else {
11985 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11986 }
b6d96bed 11987 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11988 tcg_temp_free_i64(fp0);
b6d96bed 11989 }
5a5012ec 11990 break;
bf4120ad 11991 case OPC_CVT_S_W:
b6d96bed 11992 {
a7812ae4 11993 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11994
7c979afd 11995 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11996 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
7c979afd 11997 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11998 tcg_temp_free_i32(fp0);
b6d96bed 11999 }
6ea83fed 12000 break;
bf4120ad 12001 case OPC_CVT_D_W:
5e755519 12002 check_cp1_registers(ctx, fd);
b6d96bed 12003 {
a7812ae4
PB
12004 TCGv_i32 fp32 = tcg_temp_new_i32();
12005 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 12006
7c979afd 12007 gen_load_fpr32(ctx, fp32, fs);
895c2d04 12008 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 12009 tcg_temp_free_i32(fp32);
b6d96bed 12010 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 12011 tcg_temp_free_i64(fp64);
b6d96bed 12012 }
5a5012ec 12013 break;
bf4120ad 12014 case OPC_CVT_S_L:
5e755519 12015 check_cp1_64bitmode(ctx);
b6d96bed 12016 {
a7812ae4
PB
12017 TCGv_i32 fp32 = tcg_temp_new_i32();
12018 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
12019
12020 gen_load_fpr64(ctx, fp64, fs);
895c2d04 12021 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 12022 tcg_temp_free_i64(fp64);
7c979afd 12023 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 12024 tcg_temp_free_i32(fp32);
b6d96bed 12025 }
5a5012ec 12026 break;
bf4120ad 12027 case OPC_CVT_D_L:
5e755519 12028 check_cp1_64bitmode(ctx);
b6d96bed 12029 {
a7812ae4 12030 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12031
12032 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12033 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 12034 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12035 tcg_temp_free_i64(fp0);
b6d96bed 12036 }
5a5012ec 12037 break;
bf4120ad 12038 case OPC_CVT_PS_PW:
e29c9628 12039 check_ps(ctx);
b6d96bed 12040 {
a7812ae4 12041 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12042
12043 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12044 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 12045 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12046 tcg_temp_free_i64(fp0);
b6d96bed 12047 }
5a5012ec 12048 break;
bf4120ad 12049 case OPC_ADD_PS:
e29c9628 12050 check_ps(ctx);
b6d96bed 12051 {
a7812ae4
PB
12052 TCGv_i64 fp0 = tcg_temp_new_i64();
12053 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12054
12055 gen_load_fpr64(ctx, fp0, fs);
12056 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12057 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12058 tcg_temp_free_i64(fp1);
b6d96bed 12059 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12060 tcg_temp_free_i64(fp0);
b6d96bed 12061 }
6ea83fed 12062 break;
bf4120ad 12063 case OPC_SUB_PS:
e29c9628 12064 check_ps(ctx);
b6d96bed 12065 {
a7812ae4
PB
12066 TCGv_i64 fp0 = tcg_temp_new_i64();
12067 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12068
12069 gen_load_fpr64(ctx, fp0, fs);
12070 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12071 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12072 tcg_temp_free_i64(fp1);
b6d96bed 12073 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12074 tcg_temp_free_i64(fp0);
b6d96bed 12075 }
6ea83fed 12076 break;
bf4120ad 12077 case OPC_MUL_PS:
e29c9628 12078 check_ps(ctx);
b6d96bed 12079 {
a7812ae4
PB
12080 TCGv_i64 fp0 = tcg_temp_new_i64();
12081 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12082
12083 gen_load_fpr64(ctx, fp0, fs);
12084 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12085 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12086 tcg_temp_free_i64(fp1);
b6d96bed 12087 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12088 tcg_temp_free_i64(fp0);
b6d96bed 12089 }
6ea83fed 12090 break;
bf4120ad 12091 case OPC_ABS_PS:
e29c9628 12092 check_ps(ctx);
b6d96bed 12093 {
a7812ae4 12094 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12095
12096 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 12097 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 12098 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12099 tcg_temp_free_i64(fp0);
b6d96bed 12100 }
6ea83fed 12101 break;
bf4120ad 12102 case OPC_MOV_PS:
e29c9628 12103 check_ps(ctx);
b6d96bed 12104 {
a7812ae4 12105 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12106
12107 gen_load_fpr64(ctx, fp0, fs);
12108 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12109 tcg_temp_free_i64(fp0);
b6d96bed 12110 }
6ea83fed 12111 break;
bf4120ad 12112 case OPC_NEG_PS:
e29c9628 12113 check_ps(ctx);
b6d96bed 12114 {
a7812ae4 12115 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12116
12117 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 12118 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 12119 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12120 tcg_temp_free_i64(fp0);
b6d96bed 12121 }
6ea83fed 12122 break;
bf4120ad 12123 case OPC_MOVCF_PS:
e29c9628 12124 check_ps(ctx);
7f6613ce 12125 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6ea83fed 12126 break;
bf4120ad 12127 case OPC_MOVZ_PS:
e29c9628 12128 check_ps(ctx);
a16336e4 12129 {
42a268c2 12130 TCGLabel *l1 = gen_new_label();
30a3848b 12131 TCGv_i64 fp0;
a16336e4 12132
c9297f4d
AJ
12133 if (ft != 0)
12134 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12135 fp0 = tcg_temp_new_i64();
12136 gen_load_fpr64(ctx, fp0, fs);
12137 gen_store_fpr64(ctx, fp0, fd);
12138 tcg_temp_free_i64(fp0);
a16336e4
TS
12139 gen_set_label(l1);
12140 }
6ea83fed 12141 break;
bf4120ad 12142 case OPC_MOVN_PS:
e29c9628 12143 check_ps(ctx);
a16336e4 12144 {
42a268c2 12145 TCGLabel *l1 = gen_new_label();
30a3848b 12146 TCGv_i64 fp0;
c9297f4d
AJ
12147
12148 if (ft != 0) {
12149 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12150 fp0 = tcg_temp_new_i64();
12151 gen_load_fpr64(ctx, fp0, fs);
12152 gen_store_fpr64(ctx, fp0, fd);
12153 tcg_temp_free_i64(fp0);
12154 gen_set_label(l1);
12155 }
a16336e4 12156 }
6ea83fed 12157 break;
bf4120ad 12158 case OPC_ADDR_PS:
e29c9628 12159 check_ps(ctx);
b6d96bed 12160 {
a7812ae4
PB
12161 TCGv_i64 fp0 = tcg_temp_new_i64();
12162 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12163
12164 gen_load_fpr64(ctx, fp0, ft);
12165 gen_load_fpr64(ctx, fp1, fs);
895c2d04 12166 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12167 tcg_temp_free_i64(fp1);
b6d96bed 12168 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12169 tcg_temp_free_i64(fp0);
b6d96bed 12170 }
fbcc6828 12171 break;
bf4120ad 12172 case OPC_MULR_PS:
e29c9628 12173 check_ps(ctx);
b6d96bed 12174 {
a7812ae4
PB
12175 TCGv_i64 fp0 = tcg_temp_new_i64();
12176 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12177
12178 gen_load_fpr64(ctx, fp0, ft);
12179 gen_load_fpr64(ctx, fp1, fs);
895c2d04 12180 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12181 tcg_temp_free_i64(fp1);
b6d96bed 12182 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12183 tcg_temp_free_i64(fp0);
b6d96bed 12184 }
57fa1fb3 12185 break;
bf4120ad 12186 case OPC_RECIP2_PS:
e29c9628 12187 check_ps(ctx);
b6d96bed 12188 {
a7812ae4
PB
12189 TCGv_i64 fp0 = tcg_temp_new_i64();
12190 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12191
12192 gen_load_fpr64(ctx, fp0, fs);
d22d7289 12193 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12194 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12195 tcg_temp_free_i64(fp1);
b6d96bed 12196 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12197 tcg_temp_free_i64(fp0);
b6d96bed 12198 }
57fa1fb3 12199 break;
bf4120ad 12200 case OPC_RECIP1_PS:
e29c9628 12201 check_ps(ctx);
b6d96bed 12202 {
a7812ae4 12203 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12204
12205 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12206 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 12207 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12208 tcg_temp_free_i64(fp0);
b6d96bed 12209 }
57fa1fb3 12210 break;
bf4120ad 12211 case OPC_RSQRT1_PS:
e29c9628 12212 check_ps(ctx);
b6d96bed 12213 {
a7812ae4 12214 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12215
12216 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12217 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 12218 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12219 tcg_temp_free_i64(fp0);
b6d96bed 12220 }
57fa1fb3 12221 break;
bf4120ad 12222 case OPC_RSQRT2_PS:
e29c9628 12223 check_ps(ctx);
b6d96bed 12224 {
a7812ae4
PB
12225 TCGv_i64 fp0 = tcg_temp_new_i64();
12226 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
12227
12228 gen_load_fpr64(ctx, fp0, fs);
12229 gen_load_fpr64(ctx, fp1, ft);
895c2d04 12230 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 12231 tcg_temp_free_i64(fp1);
b6d96bed 12232 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12233 tcg_temp_free_i64(fp0);
b6d96bed 12234 }
57fa1fb3 12235 break;
bf4120ad 12236 case OPC_CVT_S_PU:
5e755519 12237 check_cp1_64bitmode(ctx);
b6d96bed 12238 {
a7812ae4 12239 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12240
7f6613ce 12241 gen_load_fpr32h(ctx, fp0, fs);
895c2d04 12242 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
7c979afd 12243 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12244 tcg_temp_free_i32(fp0);
b6d96bed 12245 }
dd016883 12246 break;
bf4120ad 12247 case OPC_CVT_PW_PS:
e29c9628 12248 check_ps(ctx);
b6d96bed 12249 {
a7812ae4 12250 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
12251
12252 gen_load_fpr64(ctx, fp0, fs);
895c2d04 12253 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 12254 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12255 tcg_temp_free_i64(fp0);
b6d96bed 12256 }
6ea83fed 12257 break;
bf4120ad 12258 case OPC_CVT_S_PL:
5e755519 12259 check_cp1_64bitmode(ctx);
b6d96bed 12260 {
a7812ae4 12261 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12262
7c979afd 12263 gen_load_fpr32(ctx, fp0, fs);
895c2d04 12264 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
7c979afd 12265 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12266 tcg_temp_free_i32(fp0);
b6d96bed 12267 }
6ea83fed 12268 break;
bf4120ad 12269 case OPC_PLL_PS:
e29c9628 12270 check_ps(ctx);
b6d96bed 12271 {
a7812ae4
PB
12272 TCGv_i32 fp0 = tcg_temp_new_i32();
12273 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12274
7c979afd
LA
12275 gen_load_fpr32(ctx, fp0, fs);
12276 gen_load_fpr32(ctx, fp1, ft);
7f6613ce 12277 gen_store_fpr32h(ctx, fp0, fd);
7c979afd 12278 gen_store_fpr32(ctx, fp1, fd);
a7812ae4
PB
12279 tcg_temp_free_i32(fp0);
12280 tcg_temp_free_i32(fp1);
b6d96bed 12281 }
6ea83fed 12282 break;
bf4120ad 12283 case OPC_PLU_PS:
e29c9628 12284 check_ps(ctx);
b6d96bed 12285 {
a7812ae4
PB
12286 TCGv_i32 fp0 = tcg_temp_new_i32();
12287 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12288
7c979afd 12289 gen_load_fpr32(ctx, fp0, fs);
7f6613ce 12290 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 12291 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12292 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12293 tcg_temp_free_i32(fp0);
12294 tcg_temp_free_i32(fp1);
b6d96bed 12295 }
5a5012ec 12296 break;
bf4120ad 12297 case OPC_PUL_PS:
e29c9628 12298 check_ps(ctx);
b6d96bed 12299 {
a7812ae4
PB
12300 TCGv_i32 fp0 = tcg_temp_new_i32();
12301 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12302
7f6613ce 12303 gen_load_fpr32h(ctx, fp0, fs);
7c979afd
LA
12304 gen_load_fpr32(ctx, fp1, ft);
12305 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12306 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12307 tcg_temp_free_i32(fp0);
12308 tcg_temp_free_i32(fp1);
b6d96bed 12309 }
5a5012ec 12310 break;
bf4120ad 12311 case OPC_PUU_PS:
e29c9628 12312 check_ps(ctx);
b6d96bed 12313 {
a7812ae4
PB
12314 TCGv_i32 fp0 = tcg_temp_new_i32();
12315 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 12316
7f6613ce
PJ
12317 gen_load_fpr32h(ctx, fp0, fs);
12318 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 12319 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 12320 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
12321 tcg_temp_free_i32(fp0);
12322 tcg_temp_free_i32(fp1);
b6d96bed 12323 }
5a5012ec 12324 break;
bf4120ad
NF
12325 case OPC_CMP_F_PS:
12326 case OPC_CMP_UN_PS:
12327 case OPC_CMP_EQ_PS:
12328 case OPC_CMP_UEQ_PS:
12329 case OPC_CMP_OLT_PS:
12330 case OPC_CMP_ULT_PS:
12331 case OPC_CMP_OLE_PS:
12332 case OPC_CMP_ULE_PS:
12333 case OPC_CMP_SF_PS:
12334 case OPC_CMP_NGLE_PS:
12335 case OPC_CMP_SEQ_PS:
12336 case OPC_CMP_NGL_PS:
12337 case OPC_CMP_LT_PS:
12338 case OPC_CMP_NGE_PS:
12339 case OPC_CMP_LE_PS:
12340 case OPC_CMP_NGT_PS:
8153667c
NF
12341 if (ctx->opcode & (1 << 6)) {
12342 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
8153667c
NF
12343 } else {
12344 gen_cmp_ps(ctx, func-48, ft, fs, cc);
5a1e8ffb 12345 }
6ea83fed 12346 break;
5a5012ec 12347 default:
9d68ac14 12348 MIPS_INVAL("farith");
9c708c7f 12349 generate_exception_end(ctx, EXCP_RI);
6ea83fed
FB
12350 return;
12351 }
6ea83fed 12352}
6af0bf9c 12353
5a5012ec 12354/* Coprocessor 3 (FPU) */
5e755519
TS
12355static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
12356 int fd, int fs, int base, int index)
7a387fff 12357{
4e2474d6 12358 TCGv t0 = tcg_temp_new();
7a387fff 12359
93b12ccc 12360 if (base == 0) {
6c5c1e20 12361 gen_load_gpr(t0, index);
93b12ccc 12362 } else if (index == 0) {
6c5c1e20 12363 gen_load_gpr(t0, base);
93b12ccc 12364 } else {
05168674 12365 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 12366 }
5a5012ec 12367 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 12368 memory access. */
5a5012ec
TS
12369 switch (opc) {
12370 case OPC_LWXC1:
8c0ab41f 12371 check_cop1x(ctx);
b6d96bed 12372 {
a7812ae4 12373 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12374
5f68f5ae 12375 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
585c88d5 12376 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 12377 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12378 tcg_temp_free_i32(fp0);
b6d96bed 12379 }
5a5012ec
TS
12380 break;
12381 case OPC_LDXC1:
8c0ab41f
AJ
12382 check_cop1x(ctx);
12383 check_cp1_registers(ctx, fd);
b6d96bed 12384 {
a7812ae4 12385 TCGv_i64 fp0 = tcg_temp_new_i64();
5f68f5ae 12386 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 12387 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12388 tcg_temp_free_i64(fp0);
b6d96bed 12389 }
5a5012ec
TS
12390 break;
12391 case OPC_LUXC1:
8c0ab41f 12392 check_cp1_64bitmode(ctx);
6c5c1e20 12393 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 12394 {
a7812ae4 12395 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12396
5f68f5ae 12397 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 12398 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12399 tcg_temp_free_i64(fp0);
b6d96bed 12400 }
5a5012ec
TS
12401 break;
12402 case OPC_SWXC1:
8c0ab41f 12403 check_cop1x(ctx);
b6d96bed 12404 {
a7812ae4 12405 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 12406 gen_load_fpr32(ctx, fp0, fs);
5f68f5ae 12407 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
a7812ae4 12408 tcg_temp_free_i32(fp0);
b6d96bed 12409 }
5a5012ec
TS
12410 break;
12411 case OPC_SDXC1:
8c0ab41f
AJ
12412 check_cop1x(ctx);
12413 check_cp1_registers(ctx, fs);
b6d96bed 12414 {
a7812ae4 12415 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12416 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 12417 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 12418 tcg_temp_free_i64(fp0);
b6d96bed 12419 }
5a5012ec
TS
12420 break;
12421 case OPC_SUXC1:
8c0ab41f 12422 check_cp1_64bitmode(ctx);
6c5c1e20 12423 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 12424 {
a7812ae4 12425 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12426 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 12427 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 12428 tcg_temp_free_i64(fp0);
b6d96bed 12429 }
5a5012ec 12430 break;
5a5012ec 12431 }
6c5c1e20 12432 tcg_temp_free(t0);
5a5012ec
TS
12433}
12434
5e755519
TS
12435static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
12436 int fd, int fr, int fs, int ft)
5a5012ec 12437{
5a5012ec
TS
12438 switch (opc) {
12439 case OPC_ALNV_PS:
e29c9628 12440 check_ps(ctx);
a16336e4 12441 {
a7812ae4 12442 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
12443 TCGv_i32 fp = tcg_temp_new_i32();
12444 TCGv_i32 fph = tcg_temp_new_i32();
42a268c2
RH
12445 TCGLabel *l1 = gen_new_label();
12446 TCGLabel *l2 = gen_new_label();
a16336e4 12447
6c5c1e20
TS
12448 gen_load_gpr(t0, fr);
12449 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
12450
12451 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7c979afd 12452 gen_load_fpr32(ctx, fp, fs);
7f6613ce 12453 gen_load_fpr32h(ctx, fph, fs);
7c979afd 12454 gen_store_fpr32(ctx, fp, fd);
7f6613ce 12455 gen_store_fpr32h(ctx, fph, fd);
a16336e4
TS
12456 tcg_gen_br(l2);
12457 gen_set_label(l1);
6c5c1e20
TS
12458 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12459 tcg_temp_free(t0);
a16336e4 12460#ifdef TARGET_WORDS_BIGENDIAN
7c979afd 12461 gen_load_fpr32(ctx, fp, fs);
7f6613ce
PJ
12462 gen_load_fpr32h(ctx, fph, ft);
12463 gen_store_fpr32h(ctx, fp, fd);
7c979afd 12464 gen_store_fpr32(ctx, fph, fd);
a16336e4 12465#else
7f6613ce 12466 gen_load_fpr32h(ctx, fph, fs);
7c979afd
LA
12467 gen_load_fpr32(ctx, fp, ft);
12468 gen_store_fpr32(ctx, fph, fd);
7f6613ce 12469 gen_store_fpr32h(ctx, fp, fd);
a16336e4
TS
12470#endif
12471 gen_set_label(l2);
c905fdac
AJ
12472 tcg_temp_free_i32(fp);
12473 tcg_temp_free_i32(fph);
a16336e4 12474 }
5a5012ec
TS
12475 break;
12476 case OPC_MADD_S:
b8aa4598 12477 check_cop1x(ctx);
b6d96bed 12478 {
a7812ae4
PB
12479 TCGv_i32 fp0 = tcg_temp_new_i32();
12480 TCGv_i32 fp1 = tcg_temp_new_i32();
12481 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12482
7c979afd
LA
12483 gen_load_fpr32(ctx, fp0, fs);
12484 gen_load_fpr32(ctx, fp1, ft);
12485 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12486 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12487 tcg_temp_free_i32(fp0);
12488 tcg_temp_free_i32(fp1);
7c979afd 12489 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12490 tcg_temp_free_i32(fp2);
b6d96bed 12491 }
5a5012ec
TS
12492 break;
12493 case OPC_MADD_D:
b8aa4598
TS
12494 check_cop1x(ctx);
12495 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12496 {
a7812ae4
PB
12497 TCGv_i64 fp0 = tcg_temp_new_i64();
12498 TCGv_i64 fp1 = tcg_temp_new_i64();
12499 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12500
12501 gen_load_fpr64(ctx, fp0, fs);
12502 gen_load_fpr64(ctx, fp1, ft);
12503 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12504 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12505 tcg_temp_free_i64(fp0);
12506 tcg_temp_free_i64(fp1);
b6d96bed 12507 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12508 tcg_temp_free_i64(fp2);
b6d96bed 12509 }
5a5012ec
TS
12510 break;
12511 case OPC_MADD_PS:
e29c9628 12512 check_ps(ctx);
b6d96bed 12513 {
a7812ae4
PB
12514 TCGv_i64 fp0 = tcg_temp_new_i64();
12515 TCGv_i64 fp1 = tcg_temp_new_i64();
12516 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12517
12518 gen_load_fpr64(ctx, fp0, fs);
12519 gen_load_fpr64(ctx, fp1, ft);
12520 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12521 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12522 tcg_temp_free_i64(fp0);
12523 tcg_temp_free_i64(fp1);
b6d96bed 12524 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12525 tcg_temp_free_i64(fp2);
b6d96bed 12526 }
5a5012ec
TS
12527 break;
12528 case OPC_MSUB_S:
b8aa4598 12529 check_cop1x(ctx);
b6d96bed 12530 {
a7812ae4
PB
12531 TCGv_i32 fp0 = tcg_temp_new_i32();
12532 TCGv_i32 fp1 = tcg_temp_new_i32();
12533 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12534
7c979afd
LA
12535 gen_load_fpr32(ctx, fp0, fs);
12536 gen_load_fpr32(ctx, fp1, ft);
12537 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12538 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12539 tcg_temp_free_i32(fp0);
12540 tcg_temp_free_i32(fp1);
7c979afd 12541 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12542 tcg_temp_free_i32(fp2);
b6d96bed 12543 }
5a5012ec
TS
12544 break;
12545 case OPC_MSUB_D:
b8aa4598
TS
12546 check_cop1x(ctx);
12547 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12548 {
a7812ae4
PB
12549 TCGv_i64 fp0 = tcg_temp_new_i64();
12550 TCGv_i64 fp1 = tcg_temp_new_i64();
12551 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12552
12553 gen_load_fpr64(ctx, fp0, fs);
12554 gen_load_fpr64(ctx, fp1, ft);
12555 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12556 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12557 tcg_temp_free_i64(fp0);
12558 tcg_temp_free_i64(fp1);
b6d96bed 12559 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12560 tcg_temp_free_i64(fp2);
b6d96bed 12561 }
5a5012ec
TS
12562 break;
12563 case OPC_MSUB_PS:
e29c9628 12564 check_ps(ctx);
b6d96bed 12565 {
a7812ae4
PB
12566 TCGv_i64 fp0 = tcg_temp_new_i64();
12567 TCGv_i64 fp1 = tcg_temp_new_i64();
12568 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12569
12570 gen_load_fpr64(ctx, fp0, fs);
12571 gen_load_fpr64(ctx, fp1, ft);
12572 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12573 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12574 tcg_temp_free_i64(fp0);
12575 tcg_temp_free_i64(fp1);
b6d96bed 12576 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12577 tcg_temp_free_i64(fp2);
b6d96bed 12578 }
5a5012ec
TS
12579 break;
12580 case OPC_NMADD_S:
b8aa4598 12581 check_cop1x(ctx);
b6d96bed 12582 {
a7812ae4
PB
12583 TCGv_i32 fp0 = tcg_temp_new_i32();
12584 TCGv_i32 fp1 = tcg_temp_new_i32();
12585 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12586
7c979afd
LA
12587 gen_load_fpr32(ctx, fp0, fs);
12588 gen_load_fpr32(ctx, fp1, ft);
12589 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12590 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12591 tcg_temp_free_i32(fp0);
12592 tcg_temp_free_i32(fp1);
7c979afd 12593 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12594 tcg_temp_free_i32(fp2);
b6d96bed 12595 }
5a5012ec
TS
12596 break;
12597 case OPC_NMADD_D:
b8aa4598
TS
12598 check_cop1x(ctx);
12599 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12600 {
a7812ae4
PB
12601 TCGv_i64 fp0 = tcg_temp_new_i64();
12602 TCGv_i64 fp1 = tcg_temp_new_i64();
12603 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12604
12605 gen_load_fpr64(ctx, fp0, fs);
12606 gen_load_fpr64(ctx, fp1, ft);
12607 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12608 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12609 tcg_temp_free_i64(fp0);
12610 tcg_temp_free_i64(fp1);
b6d96bed 12611 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12612 tcg_temp_free_i64(fp2);
b6d96bed 12613 }
5a5012ec
TS
12614 break;
12615 case OPC_NMADD_PS:
e29c9628 12616 check_ps(ctx);
b6d96bed 12617 {
a7812ae4
PB
12618 TCGv_i64 fp0 = tcg_temp_new_i64();
12619 TCGv_i64 fp1 = tcg_temp_new_i64();
12620 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12621
12622 gen_load_fpr64(ctx, fp0, fs);
12623 gen_load_fpr64(ctx, fp1, ft);
12624 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12625 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12626 tcg_temp_free_i64(fp0);
12627 tcg_temp_free_i64(fp1);
b6d96bed 12628 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12629 tcg_temp_free_i64(fp2);
b6d96bed 12630 }
5a5012ec
TS
12631 break;
12632 case OPC_NMSUB_S:
b8aa4598 12633 check_cop1x(ctx);
b6d96bed 12634 {
a7812ae4
PB
12635 TCGv_i32 fp0 = tcg_temp_new_i32();
12636 TCGv_i32 fp1 = tcg_temp_new_i32();
12637 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12638
7c979afd
LA
12639 gen_load_fpr32(ctx, fp0, fs);
12640 gen_load_fpr32(ctx, fp1, ft);
12641 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12642 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12643 tcg_temp_free_i32(fp0);
12644 tcg_temp_free_i32(fp1);
7c979afd 12645 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12646 tcg_temp_free_i32(fp2);
b6d96bed 12647 }
5a5012ec
TS
12648 break;
12649 case OPC_NMSUB_D:
b8aa4598
TS
12650 check_cop1x(ctx);
12651 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12652 {
a7812ae4
PB
12653 TCGv_i64 fp0 = tcg_temp_new_i64();
12654 TCGv_i64 fp1 = tcg_temp_new_i64();
12655 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12656
12657 gen_load_fpr64(ctx, fp0, fs);
12658 gen_load_fpr64(ctx, fp1, ft);
12659 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12660 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12661 tcg_temp_free_i64(fp0);
12662 tcg_temp_free_i64(fp1);
b6d96bed 12663 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12664 tcg_temp_free_i64(fp2);
b6d96bed 12665 }
5a5012ec
TS
12666 break;
12667 case OPC_NMSUB_PS:
e29c9628 12668 check_ps(ctx);
b6d96bed 12669 {
a7812ae4
PB
12670 TCGv_i64 fp0 = tcg_temp_new_i64();
12671 TCGv_i64 fp1 = tcg_temp_new_i64();
12672 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12673
12674 gen_load_fpr64(ctx, fp0, fs);
12675 gen_load_fpr64(ctx, fp1, ft);
12676 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12677 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12678 tcg_temp_free_i64(fp0);
12679 tcg_temp_free_i64(fp1);
b6d96bed 12680 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12681 tcg_temp_free_i64(fp2);
b6d96bed 12682 }
5a5012ec 12683 break;
923617a3 12684 default:
9d68ac14 12685 MIPS_INVAL("flt3_arith");
9c708c7f 12686 generate_exception_end(ctx, EXCP_RI);
5a5012ec
TS
12687 return;
12688 }
7a387fff
TS
12689}
12690
b00c7218 12691static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
26ebe468
NF
12692{
12693 TCGv t0;
12694
b3167288
RH
12695#if !defined(CONFIG_USER_ONLY)
12696 /* The Linux kernel will emulate rdhwr if it's not supported natively.
12697 Therefore only check the ISA in system mode. */
d75c135e 12698 check_insn(ctx, ISA_MIPS32R2);
b3167288 12699#endif
26ebe468
NF
12700 t0 = tcg_temp_new();
12701
12702 switch (rd) {
12703 case 0:
895c2d04 12704 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
12705 gen_store_gpr(t0, rt);
12706 break;
12707 case 1:
895c2d04 12708 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
12709 gen_store_gpr(t0, rt);
12710 break;
12711 case 2:
eeb3bba8 12712 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
12713 gen_io_start();
12714 }
895c2d04 12715 gen_helper_rdhwr_cc(t0, cpu_env);
eeb3bba8 12716 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
12717 gen_io_end();
12718 }
26ebe468 12719 gen_store_gpr(t0, rt);
d673a68d 12720 /* Break the TB to be able to take timer interrupts immediately
b28425ba 12721 after reading count. DISAS_STOP isn't sufficient, we need to ensure
d673a68d 12722 we break completely out of translated code. */
eeb3bba8
EC
12723 gen_save_pc(ctx->base.pc_next + 4);
12724 ctx->base.is_jmp = DISAS_EXIT;
26ebe468
NF
12725 break;
12726 case 3:
895c2d04 12727 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
12728 gen_store_gpr(t0, rt);
12729 break;
b00c7218
YK
12730 case 4:
12731 check_insn(ctx, ISA_MIPS32R6);
12732 if (sel != 0) {
12733 /* Performance counter registers are not implemented other than
12734 * control register 0.
12735 */
12736 generate_exception(ctx, EXCP_RI);
12737 }
12738 gen_helper_rdhwr_performance(t0, cpu_env);
12739 gen_store_gpr(t0, rt);
12740 break;
12741 case 5:
12742 check_insn(ctx, ISA_MIPS32R6);
12743 gen_helper_rdhwr_xnp(t0, cpu_env);
12744 gen_store_gpr(t0, rt);
12745 break;
26ebe468
NF
12746 case 29:
12747#if defined(CONFIG_USER_ONLY)
d279279e
PJ
12748 tcg_gen_ld_tl(t0, cpu_env,
12749 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
26ebe468
NF
12750 gen_store_gpr(t0, rt);
12751 break;
12752#else
d279279e
PJ
12753 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12754 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12755 tcg_gen_ld_tl(t0, cpu_env,
12756 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12757 gen_store_gpr(t0, rt);
12758 } else {
9c708c7f 12759 generate_exception_end(ctx, EXCP_RI);
d279279e
PJ
12760 }
12761 break;
26ebe468
NF
12762#endif
12763 default: /* Invalid */
12764 MIPS_INVAL("rdhwr");
9c708c7f 12765 generate_exception_end(ctx, EXCP_RI);
26ebe468
NF
12766 break;
12767 }
12768 tcg_temp_free(t0);
12769}
12770
a5f53390
LA
12771static inline void clear_branch_hflags(DisasContext *ctx)
12772{
12773 ctx->hflags &= ~MIPS_HFLAG_BMASK;
eeb3bba8 12774 if (ctx->base.is_jmp == DISAS_NEXT) {
a5f53390
LA
12775 save_cpu_state(ctx, 0);
12776 } else {
12777 /* it is not safe to save ctx->hflags as hflags may be changed
12778 in execution time by the instruction in delay / forbidden slot. */
12779 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12780 }
12781}
12782
31837be3 12783static void gen_branch(DisasContext *ctx, int insn_bytes)
c9602061
NF
12784{
12785 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 12786 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061 12787 /* Branches completion */
a5f53390 12788 clear_branch_hflags(ctx);
eeb3bba8 12789 ctx->base.is_jmp = DISAS_NORETURN;
c9602061 12790 /* FIXME: Need to clear can_do_io. */
364d4831 12791 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
339cd2a8 12792 case MIPS_HFLAG_FBNSLOT:
eeb3bba8 12793 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
339cd2a8 12794 break;
c9602061
NF
12795 case MIPS_HFLAG_B:
12796 /* unconditional branch */
364d4831
NF
12797 if (proc_hflags & MIPS_HFLAG_BX) {
12798 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12799 }
c9602061
NF
12800 gen_goto_tb(ctx, 0, ctx->btarget);
12801 break;
12802 case MIPS_HFLAG_BL:
12803 /* blikely taken case */
c9602061
NF
12804 gen_goto_tb(ctx, 0, ctx->btarget);
12805 break;
12806 case MIPS_HFLAG_BC:
12807 /* Conditional branch */
c9602061 12808 {
42a268c2 12809 TCGLabel *l1 = gen_new_label();
c9602061
NF
12810
12811 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
eeb3bba8 12812 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
c9602061
NF
12813 gen_set_label(l1);
12814 gen_goto_tb(ctx, 0, ctx->btarget);
12815 }
12816 break;
12817 case MIPS_HFLAG_BR:
12818 /* unconditional branch to register */
d75c135e 12819 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
12820 TCGv t0 = tcg_temp_new();
12821 TCGv_i32 t1 = tcg_temp_new_i32();
12822
12823 tcg_gen_andi_tl(t0, btarget, 0x1);
12824 tcg_gen_trunc_tl_i32(t1, t0);
12825 tcg_temp_free(t0);
12826 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12827 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12828 tcg_gen_or_i32(hflags, hflags, t1);
12829 tcg_temp_free_i32(t1);
12830
12831 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12832 } else {
12833 tcg_gen_mov_tl(cpu_PC, btarget);
12834 }
eeb3bba8 12835 if (ctx->base.singlestep_enabled) {
c9602061 12836 save_cpu_state(ctx, 0);
9c708c7f 12837 gen_helper_raise_exception_debug(cpu_env);
c9602061 12838 }
7f11636d 12839 tcg_gen_lookup_and_goto_ptr();
c9602061
NF
12840 break;
12841 default:
a5f53390
LA
12842 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12843 abort();
c9602061
NF
12844 }
12845 }
12846}
12847
6893f074
YK
12848/* Compact Branches */
12849static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12850 int rs, int rt, int32_t offset)
12851{
12852 int bcond_compute = 0;
12853 TCGv t0 = tcg_temp_new();
12854 TCGv t1 = tcg_temp_new();
65935f07 12855 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
6893f074
YK
12856
12857 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12858#ifdef MIPS_DEBUG_DISAS
12859 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 12860 "\n", ctx->base.pc_next);
6893f074 12861#endif
9c708c7f 12862 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
12863 goto out;
12864 }
12865
12866 /* Load needed operands and calculate btarget */
12867 switch (opc) {
12868 /* compact branch */
12869 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12870 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12871 gen_load_gpr(t0, rs);
12872 gen_load_gpr(t1, rt);
12873 bcond_compute = 1;
eeb3bba8 12874 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12875 if (rs <= rt && rs == 0) {
12876 /* OPC_BEQZALC, OPC_BNEZALC */
eeb3bba8 12877 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12878 }
12879 break;
12880 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12881 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12882 gen_load_gpr(t0, rs);
12883 gen_load_gpr(t1, rt);
12884 bcond_compute = 1;
eeb3bba8 12885 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12886 break;
12887 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12888 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12889 if (rs == 0 || rs == rt) {
12890 /* OPC_BLEZALC, OPC_BGEZALC */
12891 /* OPC_BGTZALC, OPC_BLTZALC */
eeb3bba8 12892 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12893 }
12894 gen_load_gpr(t0, rs);
12895 gen_load_gpr(t1, rt);
12896 bcond_compute = 1;
eeb3bba8 12897 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12898 break;
12899 case OPC_BC:
12900 case OPC_BALC:
eeb3bba8 12901 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12902 break;
12903 case OPC_BEQZC:
12904 case OPC_BNEZC:
12905 if (rs != 0) {
12906 /* OPC_BEQZC, OPC_BNEZC */
12907 gen_load_gpr(t0, rs);
12908 bcond_compute = 1;
eeb3bba8 12909 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12910 } else {
12911 /* OPC_JIC, OPC_JIALC */
12912 TCGv tbase = tcg_temp_new();
12913 TCGv toffset = tcg_temp_new();
12914
12915 gen_load_gpr(tbase, rt);
12916 tcg_gen_movi_tl(toffset, offset);
12917 gen_op_addr_add(ctx, btarget, tbase, toffset);
12918 tcg_temp_free(tbase);
12919 tcg_temp_free(toffset);
12920 }
12921 break;
12922 default:
12923 MIPS_INVAL("Compact branch/jump");
9c708c7f 12924 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
12925 goto out;
12926 }
12927
12928 if (bcond_compute == 0) {
12929 /* Uncoditional compact branch */
12930 switch (opc) {
12931 case OPC_JIALC:
eeb3bba8 12932 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12933 /* Fallthrough */
12934 case OPC_JIC:
12935 ctx->hflags |= MIPS_HFLAG_BR;
12936 break;
12937 case OPC_BALC:
eeb3bba8 12938 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12939 /* Fallthrough */
12940 case OPC_BC:
12941 ctx->hflags |= MIPS_HFLAG_B;
12942 break;
12943 default:
12944 MIPS_INVAL("Compact branch/jump");
9c708c7f 12945 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
12946 goto out;
12947 }
12948
12949 /* Generating branch here as compact branches don't have delay slot */
12950 gen_branch(ctx, 4);
12951 } else {
12952 /* Conditional compact branch */
12953 TCGLabel *fs = gen_new_label();
12954 save_cpu_state(ctx, 0);
12955
12956 switch (opc) {
12957 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12958 if (rs == 0 && rt != 0) {
12959 /* OPC_BLEZALC */
12960 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12961 } else if (rs != 0 && rt != 0 && rs == rt) {
12962 /* OPC_BGEZALC */
12963 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12964 } else {
12965 /* OPC_BGEUC */
12966 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12967 }
12968 break;
12969 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12970 if (rs == 0 && rt != 0) {
12971 /* OPC_BGTZALC */
12972 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12973 } else if (rs != 0 && rt != 0 && rs == rt) {
12974 /* OPC_BLTZALC */
12975 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12976 } else {
12977 /* OPC_BLTUC */
12978 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12979 }
12980 break;
12981 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12982 if (rs == 0 && rt != 0) {
12983 /* OPC_BLEZC */
12984 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12985 } else if (rs != 0 && rt != 0 && rs == rt) {
12986 /* OPC_BGEZC */
12987 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12988 } else {
12989 /* OPC_BGEC */
12990 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12991 }
12992 break;
12993 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12994 if (rs == 0 && rt != 0) {
12995 /* OPC_BGTZC */
12996 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12997 } else if (rs != 0 && rt != 0 && rs == rt) {
12998 /* OPC_BLTZC */
12999 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13000 } else {
13001 /* OPC_BLTC */
13002 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13003 }
13004 break;
13005 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13006 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13007 if (rs >= rt) {
13008 /* OPC_BOVC, OPC_BNVC */
13009 TCGv t2 = tcg_temp_new();
13010 TCGv t3 = tcg_temp_new();
13011 TCGv t4 = tcg_temp_new();
13012 TCGv input_overflow = tcg_temp_new();
13013
13014 gen_load_gpr(t0, rs);
13015 gen_load_gpr(t1, rt);
13016 tcg_gen_ext32s_tl(t2, t0);
13017 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13018 tcg_gen_ext32s_tl(t3, t1);
13019 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13020 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13021
13022 tcg_gen_add_tl(t4, t2, t3);
13023 tcg_gen_ext32s_tl(t4, t4);
13024 tcg_gen_xor_tl(t2, t2, t3);
13025 tcg_gen_xor_tl(t3, t4, t3);
13026 tcg_gen_andc_tl(t2, t3, t2);
13027 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13028 tcg_gen_or_tl(t4, t4, input_overflow);
13029 if (opc == OPC_BOVC) {
13030 /* OPC_BOVC */
13031 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13032 } else {
13033 /* OPC_BNVC */
13034 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13035 }
13036 tcg_temp_free(input_overflow);
13037 tcg_temp_free(t4);
13038 tcg_temp_free(t3);
13039 tcg_temp_free(t2);
13040 } else if (rs < rt && rs == 0) {
13041 /* OPC_BEQZALC, OPC_BNEZALC */
13042 if (opc == OPC_BEQZALC) {
13043 /* OPC_BEQZALC */
13044 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13045 } else {
13046 /* OPC_BNEZALC */
13047 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13048 }
13049 } else {
13050 /* OPC_BEQC, OPC_BNEC */
13051 if (opc == OPC_BEQC) {
13052 /* OPC_BEQC */
13053 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13054 } else {
13055 /* OPC_BNEC */
13056 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13057 }
13058 }
13059 break;
13060 case OPC_BEQZC:
13061 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13062 break;
13063 case OPC_BNEZC:
13064 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13065 break;
13066 default:
13067 MIPS_INVAL("Compact conditional branch/jump");
9c708c7f 13068 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
13069 goto out;
13070 }
13071
13072 /* Generating branch here as compact branches don't have delay slot */
13073 gen_goto_tb(ctx, 1, ctx->btarget);
13074 gen_set_label(fs);
13075
13076 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
6893f074
YK
13077 }
13078
13079out:
13080 tcg_temp_free(t0);
13081 tcg_temp_free(t1);
13082}
13083
7a387fff 13084/* ISA extensions (ASEs) */
6af0bf9c 13085/* MIPS16 extension to MIPS32 */
6ea219d0
NF
13086
13087/* MIPS16 major opcodes */
13088enum {
13089 M16_OPC_ADDIUSP = 0x00,
13090 M16_OPC_ADDIUPC = 0x01,
13091 M16_OPC_B = 0x02,
13092 M16_OPC_JAL = 0x03,
13093 M16_OPC_BEQZ = 0x04,
13094 M16_OPC_BNEQZ = 0x05,
13095 M16_OPC_SHIFT = 0x06,
13096 M16_OPC_LD = 0x07,
13097 M16_OPC_RRIA = 0x08,
13098 M16_OPC_ADDIU8 = 0x09,
13099 M16_OPC_SLTI = 0x0a,
13100 M16_OPC_SLTIU = 0x0b,
13101 M16_OPC_I8 = 0x0c,
13102 M16_OPC_LI = 0x0d,
13103 M16_OPC_CMPI = 0x0e,
13104 M16_OPC_SD = 0x0f,
13105 M16_OPC_LB = 0x10,
13106 M16_OPC_LH = 0x11,
13107 M16_OPC_LWSP = 0x12,
13108 M16_OPC_LW = 0x13,
13109 M16_OPC_LBU = 0x14,
13110 M16_OPC_LHU = 0x15,
13111 M16_OPC_LWPC = 0x16,
13112 M16_OPC_LWU = 0x17,
13113 M16_OPC_SB = 0x18,
13114 M16_OPC_SH = 0x19,
13115 M16_OPC_SWSP = 0x1a,
13116 M16_OPC_SW = 0x1b,
13117 M16_OPC_RRR = 0x1c,
13118 M16_OPC_RR = 0x1d,
13119 M16_OPC_EXTEND = 0x1e,
13120 M16_OPC_I64 = 0x1f
13121};
13122
13123/* I8 funct field */
13124enum {
13125 I8_BTEQZ = 0x0,
13126 I8_BTNEZ = 0x1,
13127 I8_SWRASP = 0x2,
13128 I8_ADJSP = 0x3,
13129 I8_SVRS = 0x4,
13130 I8_MOV32R = 0x5,
13131 I8_MOVR32 = 0x7
13132};
13133
13134/* RRR f field */
13135enum {
13136 RRR_DADDU = 0x0,
13137 RRR_ADDU = 0x1,
13138 RRR_DSUBU = 0x2,
13139 RRR_SUBU = 0x3
13140};
13141
13142/* RR funct field */
13143enum {
13144 RR_JR = 0x00,
13145 RR_SDBBP = 0x01,
13146 RR_SLT = 0x02,
13147 RR_SLTU = 0x03,
13148 RR_SLLV = 0x04,
13149 RR_BREAK = 0x05,
13150 RR_SRLV = 0x06,
13151 RR_SRAV = 0x07,
13152 RR_DSRL = 0x08,
13153 RR_CMP = 0x0a,
13154 RR_NEG = 0x0b,
13155 RR_AND = 0x0c,
13156 RR_OR = 0x0d,
13157 RR_XOR = 0x0e,
13158 RR_NOT = 0x0f,
13159 RR_MFHI = 0x10,
13160 RR_CNVT = 0x11,
13161 RR_MFLO = 0x12,
13162 RR_DSRA = 0x13,
13163 RR_DSLLV = 0x14,
13164 RR_DSRLV = 0x16,
13165 RR_DSRAV = 0x17,
13166 RR_MULT = 0x18,
13167 RR_MULTU = 0x19,
13168 RR_DIV = 0x1a,
13169 RR_DIVU = 0x1b,
13170 RR_DMULT = 0x1c,
13171 RR_DMULTU = 0x1d,
13172 RR_DDIV = 0x1e,
13173 RR_DDIVU = 0x1f
13174};
13175
13176/* I64 funct field */
13177enum {
13178 I64_LDSP = 0x0,
13179 I64_SDSP = 0x1,
13180 I64_SDRASP = 0x2,
13181 I64_DADJSP = 0x3,
13182 I64_LDPC = 0x4,
364d4831 13183 I64_DADDIU5 = 0x5,
6ea219d0
NF
13184 I64_DADDIUPC = 0x6,
13185 I64_DADDIUSP = 0x7
13186};
13187
13188/* RR ry field for CNVT */
13189enum {
13190 RR_RY_CNVT_ZEB = 0x0,
13191 RR_RY_CNVT_ZEH = 0x1,
13192 RR_RY_CNVT_ZEW = 0x2,
13193 RR_RY_CNVT_SEB = 0x4,
13194 RR_RY_CNVT_SEH = 0x5,
13195 RR_RY_CNVT_SEW = 0x6,
13196};
13197
364d4831
NF
13198static int xlat (int r)
13199{
13200 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13201
13202 return map[r];
13203}
13204
13205static void gen_mips16_save (DisasContext *ctx,
13206 int xsregs, int aregs,
13207 int do_ra, int do_s0, int do_s1,
13208 int framesize)
13209{
13210 TCGv t0 = tcg_temp_new();
13211 TCGv t1 = tcg_temp_new();
c48245f0 13212 TCGv t2 = tcg_temp_new();
364d4831
NF
13213 int args, astatic;
13214
13215 switch (aregs) {
13216 case 0:
13217 case 1:
13218 case 2:
13219 case 3:
13220 case 11:
13221 args = 0;
13222 break;
13223 case 4:
13224 case 5:
13225 case 6:
13226 case 7:
13227 args = 1;
13228 break;
13229 case 8:
13230 case 9:
13231 case 10:
13232 args = 2;
13233 break;
13234 case 12:
13235 case 13:
13236 args = 3;
13237 break;
13238 case 14:
13239 args = 4;
13240 break;
13241 default:
9c708c7f 13242 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13243 return;
13244 }
13245
13246 switch (args) {
13247 case 4:
13248 gen_base_offset_addr(ctx, t0, 29, 12);
13249 gen_load_gpr(t1, 7);
5f68f5ae 13250 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13251 /* Fall through */
13252 case 3:
13253 gen_base_offset_addr(ctx, t0, 29, 8);
13254 gen_load_gpr(t1, 6);
5f68f5ae 13255 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13256 /* Fall through */
13257 case 2:
13258 gen_base_offset_addr(ctx, t0, 29, 4);
13259 gen_load_gpr(t1, 5);
5f68f5ae 13260 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13261 /* Fall through */
13262 case 1:
13263 gen_base_offset_addr(ctx, t0, 29, 0);
13264 gen_load_gpr(t1, 4);
5f68f5ae 13265 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
13266 }
13267
13268 gen_load_gpr(t0, 29);
13269
5f68f5ae 13270#define DECR_AND_STORE(reg) do { \
c48245f0
MR
13271 tcg_gen_movi_tl(t2, -4); \
13272 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
13273 gen_load_gpr(t1, reg); \
13274 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
364d4831
NF
13275 } while (0)
13276
13277 if (do_ra) {
13278 DECR_AND_STORE(31);
13279 }
13280
13281 switch (xsregs) {
13282 case 7:
13283 DECR_AND_STORE(30);
13284 /* Fall through */
13285 case 6:
13286 DECR_AND_STORE(23);
13287 /* Fall through */
13288 case 5:
13289 DECR_AND_STORE(22);
13290 /* Fall through */
13291 case 4:
13292 DECR_AND_STORE(21);
13293 /* Fall through */
13294 case 3:
13295 DECR_AND_STORE(20);
13296 /* Fall through */
13297 case 2:
13298 DECR_AND_STORE(19);
13299 /* Fall through */
13300 case 1:
13301 DECR_AND_STORE(18);
13302 }
13303
13304 if (do_s1) {
13305 DECR_AND_STORE(17);
13306 }
13307 if (do_s0) {
13308 DECR_AND_STORE(16);
13309 }
13310
13311 switch (aregs) {
13312 case 0:
13313 case 4:
13314 case 8:
13315 case 12:
13316 case 14:
13317 astatic = 0;
13318 break;
13319 case 1:
13320 case 5:
13321 case 9:
13322 case 13:
13323 astatic = 1;
13324 break;
13325 case 2:
13326 case 6:
13327 case 10:
13328 astatic = 2;
13329 break;
13330 case 3:
13331 case 7:
13332 astatic = 3;
13333 break;
13334 case 11:
13335 astatic = 4;
13336 break;
13337 default:
9c708c7f 13338 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13339 return;
13340 }
13341
13342 if (astatic > 0) {
13343 DECR_AND_STORE(7);
13344 if (astatic > 1) {
13345 DECR_AND_STORE(6);
13346 if (astatic > 2) {
13347 DECR_AND_STORE(5);
13348 if (astatic > 3) {
13349 DECR_AND_STORE(4);
13350 }
13351 }
13352 }
13353 }
13354#undef DECR_AND_STORE
13355
c48245f0
MR
13356 tcg_gen_movi_tl(t2, -framesize);
13357 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
13358 tcg_temp_free(t0);
13359 tcg_temp_free(t1);
c48245f0 13360 tcg_temp_free(t2);
364d4831
NF
13361}
13362
13363static void gen_mips16_restore (DisasContext *ctx,
13364 int xsregs, int aregs,
13365 int do_ra, int do_s0, int do_s1,
13366 int framesize)
13367{
13368 int astatic;
13369 TCGv t0 = tcg_temp_new();
13370 TCGv t1 = tcg_temp_new();
c48245f0 13371 TCGv t2 = tcg_temp_new();
364d4831 13372
c48245f0
MR
13373 tcg_gen_movi_tl(t2, framesize);
13374 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
364d4831 13375
5f68f5ae 13376#define DECR_AND_LOAD(reg) do { \
c48245f0
MR
13377 tcg_gen_movi_tl(t2, -4); \
13378 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
13379 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13380 gen_store_gpr(t1, reg); \
364d4831
NF
13381 } while (0)
13382
13383 if (do_ra) {
13384 DECR_AND_LOAD(31);
13385 }
13386
13387 switch (xsregs) {
13388 case 7:
13389 DECR_AND_LOAD(30);
13390 /* Fall through */
13391 case 6:
13392 DECR_AND_LOAD(23);
13393 /* Fall through */
13394 case 5:
13395 DECR_AND_LOAD(22);
13396 /* Fall through */
13397 case 4:
13398 DECR_AND_LOAD(21);
13399 /* Fall through */
13400 case 3:
13401 DECR_AND_LOAD(20);
13402 /* Fall through */
13403 case 2:
13404 DECR_AND_LOAD(19);
13405 /* Fall through */
13406 case 1:
13407 DECR_AND_LOAD(18);
13408 }
13409
13410 if (do_s1) {
13411 DECR_AND_LOAD(17);
13412 }
13413 if (do_s0) {
13414 DECR_AND_LOAD(16);
13415 }
13416
13417 switch (aregs) {
13418 case 0:
13419 case 4:
13420 case 8:
13421 case 12:
13422 case 14:
13423 astatic = 0;
13424 break;
13425 case 1:
13426 case 5:
13427 case 9:
13428 case 13:
13429 astatic = 1;
13430 break;
13431 case 2:
13432 case 6:
13433 case 10:
13434 astatic = 2;
13435 break;
13436 case 3:
13437 case 7:
13438 astatic = 3;
13439 break;
13440 case 11:
13441 astatic = 4;
13442 break;
13443 default:
9c708c7f 13444 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13445 return;
13446 }
13447
13448 if (astatic > 0) {
13449 DECR_AND_LOAD(7);
13450 if (astatic > 1) {
13451 DECR_AND_LOAD(6);
13452 if (astatic > 2) {
13453 DECR_AND_LOAD(5);
13454 if (astatic > 3) {
13455 DECR_AND_LOAD(4);
13456 }
13457 }
13458 }
13459 }
13460#undef DECR_AND_LOAD
13461
c48245f0
MR
13462 tcg_gen_movi_tl(t2, framesize);
13463 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
13464 tcg_temp_free(t0);
13465 tcg_temp_free(t1);
c48245f0 13466 tcg_temp_free(t2);
364d4831
NF
13467}
13468
13469static void gen_addiupc (DisasContext *ctx, int rx, int imm,
13470 int is_64_bit, int extended)
13471{
13472 TCGv t0;
13473
13474 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 13475 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13476 return;
13477 }
13478
13479 t0 = tcg_temp_new();
13480
13481 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13482 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13483 if (!is_64_bit) {
13484 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13485 }
13486
13487 tcg_temp_free(t0);
13488}
13489
0d74a222
LA
13490static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13491 int16_t offset)
13492{
13493 TCGv_i32 t0 = tcg_const_i32(op);
13494 TCGv t1 = tcg_temp_new();
13495 gen_base_offset_addr(ctx, t1, base, offset);
13496 gen_helper_cache(cpu_env, t1, t0);
13497}
13498
364d4831 13499#if defined(TARGET_MIPS64)
d75c135e 13500static void decode_i64_mips16 (DisasContext *ctx,
364d4831
NF
13501 int ry, int funct, int16_t offset,
13502 int extended)
13503{
13504 switch (funct) {
13505 case I64_LDSP:
d9224450 13506 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13507 check_mips_64(ctx);
13508 offset = extended ? offset : offset << 3;
d75c135e 13509 gen_ld(ctx, OPC_LD, ry, 29, offset);
364d4831
NF
13510 break;
13511 case I64_SDSP:
d9224450 13512 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13513 check_mips_64(ctx);
13514 offset = extended ? offset : offset << 3;
5c13fdfd 13515 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
13516 break;
13517 case I64_SDRASP:
d9224450 13518 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13519 check_mips_64(ctx);
13520 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 13521 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
13522 break;
13523 case I64_DADJSP:
d9224450 13524 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13525 check_mips_64(ctx);
13526 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
d75c135e 13527 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
364d4831
NF
13528 break;
13529 case I64_LDPC:
d9224450
MR
13530 check_insn(ctx, ISA_MIPS3);
13531 check_mips_64(ctx);
364d4831 13532 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 13533 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13534 } else {
13535 offset = extended ? offset : offset << 3;
d75c135e 13536 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
13537 }
13538 break;
13539 case I64_DADDIU5:
d9224450 13540 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13541 check_mips_64(ctx);
13542 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
d75c135e 13543 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
364d4831
NF
13544 break;
13545 case I64_DADDIUPC:
d9224450 13546 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13547 check_mips_64(ctx);
13548 offset = extended ? offset : offset << 2;
13549 gen_addiupc(ctx, ry, offset, 1, extended);
13550 break;
13551 case I64_DADDIUSP:
d9224450 13552 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13553 check_mips_64(ctx);
13554 offset = extended ? offset : offset << 2;
d75c135e 13555 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
364d4831
NF
13556 break;
13557 }
13558}
13559#endif
13560
240ce26a 13561static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
364d4831 13562{
eeb3bba8 13563 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
13564 int op, rx, ry, funct, sa;
13565 int16_t imm, offset;
13566
13567 ctx->opcode = (ctx->opcode << 16) | extend;
13568 op = (ctx->opcode >> 11) & 0x1f;
13569 sa = (ctx->opcode >> 22) & 0x1f;
13570 funct = (ctx->opcode >> 8) & 0x7;
13571 rx = xlat((ctx->opcode >> 8) & 0x7);
13572 ry = xlat((ctx->opcode >> 5) & 0x7);
13573 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13574 | ((ctx->opcode >> 21) & 0x3f) << 5
13575 | (ctx->opcode & 0x1f));
13576
13577 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
13578 counterparts. */
13579 switch (op) {
13580 case M16_OPC_ADDIUSP:
d75c135e 13581 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
13582 break;
13583 case M16_OPC_ADDIUPC:
13584 gen_addiupc(ctx, rx, imm, 0, 1);
13585 break;
13586 case M16_OPC_B:
b231c103 13587 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
364d4831
NF
13588 /* No delay slot, so just process as a normal instruction */
13589 break;
13590 case M16_OPC_BEQZ:
b231c103 13591 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
364d4831
NF
13592 /* No delay slot, so just process as a normal instruction */
13593 break;
13594 case M16_OPC_BNEQZ:
b231c103 13595 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
364d4831
NF
13596 /* No delay slot, so just process as a normal instruction */
13597 break;
13598 case M16_OPC_SHIFT:
13599 switch (ctx->opcode & 0x3) {
13600 case 0x0:
d75c135e 13601 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
13602 break;
13603 case 0x1:
13604#if defined(TARGET_MIPS64)
13605 check_mips_64(ctx);
d75c135e 13606 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 13607#else
9c708c7f 13608 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13609#endif
13610 break;
13611 case 0x2:
d75c135e 13612 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
13613 break;
13614 case 0x3:
d75c135e 13615 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
13616 break;
13617 }
13618 break;
13619#if defined(TARGET_MIPS64)
13620 case M16_OPC_LD:
d9224450 13621 check_insn(ctx, ISA_MIPS3);
d75de749 13622 check_mips_64(ctx);
d75c135e 13623 gen_ld(ctx, OPC_LD, ry, rx, offset);
364d4831
NF
13624 break;
13625#endif
13626 case M16_OPC_RRIA:
13627 imm = ctx->opcode & 0xf;
13628 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13629 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13630 imm = (int16_t) (imm << 1) >> 1;
13631 if ((ctx->opcode >> 4) & 0x1) {
13632#if defined(TARGET_MIPS64)
13633 check_mips_64(ctx);
d75c135e 13634 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 13635#else
9c708c7f 13636 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13637#endif
13638 } else {
d75c135e 13639 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
13640 }
13641 break;
13642 case M16_OPC_ADDIU8:
d75c135e 13643 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
13644 break;
13645 case M16_OPC_SLTI:
d75c135e 13646 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
13647 break;
13648 case M16_OPC_SLTIU:
d75c135e 13649 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
13650 break;
13651 case M16_OPC_I8:
13652 switch (funct) {
13653 case I8_BTEQZ:
b231c103 13654 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
364d4831
NF
13655 break;
13656 case I8_BTNEZ:
b231c103 13657 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
364d4831
NF
13658 break;
13659 case I8_SWRASP:
5c13fdfd 13660 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
13661 break;
13662 case I8_ADJSP:
d75c135e 13663 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
364d4831
NF
13664 break;
13665 case I8_SVRS:
d9224450 13666 check_insn(ctx, ISA_MIPS32);
364d4831
NF
13667 {
13668 int xsregs = (ctx->opcode >> 24) & 0x7;
13669 int aregs = (ctx->opcode >> 16) & 0xf;
13670 int do_ra = (ctx->opcode >> 6) & 0x1;
13671 int do_s0 = (ctx->opcode >> 5) & 0x1;
13672 int do_s1 = (ctx->opcode >> 4) & 0x1;
13673 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13674 | (ctx->opcode & 0xf)) << 3;
13675
13676 if (ctx->opcode & (1 << 7)) {
13677 gen_mips16_save(ctx, xsregs, aregs,
13678 do_ra, do_s0, do_s1,
13679 framesize);
13680 } else {
13681 gen_mips16_restore(ctx, xsregs, aregs,
13682 do_ra, do_s0, do_s1,
13683 framesize);
13684 }
13685 }
13686 break;
13687 default:
9c708c7f 13688 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13689 break;
13690 }
13691 break;
13692 case M16_OPC_LI:
13693 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13694 break;
13695 case M16_OPC_CMPI:
13696 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13697 break;
13698#if defined(TARGET_MIPS64)
13699 case M16_OPC_SD:
d9224450
MR
13700 check_insn(ctx, ISA_MIPS3);
13701 check_mips_64(ctx);
5c13fdfd 13702 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
13703 break;
13704#endif
13705 case M16_OPC_LB:
d75c135e 13706 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
13707 break;
13708 case M16_OPC_LH:
d75c135e 13709 gen_ld(ctx, OPC_LH, ry, rx, offset);
364d4831
NF
13710 break;
13711 case M16_OPC_LWSP:
d75c135e 13712 gen_ld(ctx, OPC_LW, rx, 29, offset);
364d4831
NF
13713 break;
13714 case M16_OPC_LW:
d75c135e 13715 gen_ld(ctx, OPC_LW, ry, rx, offset);
364d4831
NF
13716 break;
13717 case M16_OPC_LBU:
d75c135e 13718 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
13719 break;
13720 case M16_OPC_LHU:
d75c135e 13721 gen_ld(ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
13722 break;
13723 case M16_OPC_LWPC:
d75c135e 13724 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
13725 break;
13726#if defined(TARGET_MIPS64)
13727 case M16_OPC_LWU:
d9224450
MR
13728 check_insn(ctx, ISA_MIPS3);
13729 check_mips_64(ctx);
d75c135e 13730 gen_ld(ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
13731 break;
13732#endif
13733 case M16_OPC_SB:
5c13fdfd 13734 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
13735 break;
13736 case M16_OPC_SH:
5c13fdfd 13737 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
13738 break;
13739 case M16_OPC_SWSP:
5c13fdfd 13740 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
13741 break;
13742 case M16_OPC_SW:
5c13fdfd 13743 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
13744 break;
13745#if defined(TARGET_MIPS64)
13746 case M16_OPC_I64:
d75c135e 13747 decode_i64_mips16(ctx, ry, funct, offset, 1);
364d4831
NF
13748 break;
13749#endif
13750 default:
9c708c7f 13751 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13752 break;
13753 }
13754
13755 return 4;
13756}
13757
3b3c1694
LA
13758static inline bool is_uhi(int sdbbp_code)
13759{
13760#ifdef CONFIG_USER_ONLY
13761 return false;
13762#else
13763 return semihosting_enabled() && sdbbp_code == 1;
13764#endif
13765}
13766
240ce26a 13767static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
364d4831
NF
13768{
13769 int rx, ry;
13770 int sa;
13771 int op, cnvt_op, op1, offset;
13772 int funct;
13773 int n_bytes;
13774
13775 op = (ctx->opcode >> 11) & 0x1f;
13776 sa = (ctx->opcode >> 2) & 0x7;
13777 sa = sa == 0 ? 8 : sa;
13778 rx = xlat((ctx->opcode >> 8) & 0x7);
13779 cnvt_op = (ctx->opcode >> 5) & 0x7;
13780 ry = xlat((ctx->opcode >> 5) & 0x7);
13781 op1 = offset = ctx->opcode & 0x1f;
13782
13783 n_bytes = 2;
13784
13785 switch (op) {
13786 case M16_OPC_ADDIUSP:
13787 {
13788 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13789
d75c135e 13790 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
13791 }
13792 break;
13793 case M16_OPC_ADDIUPC:
13794 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13795 break;
13796 case M16_OPC_B:
13797 offset = (ctx->opcode & 0x7ff) << 1;
13798 offset = (int16_t)(offset << 4) >> 4;
b231c103 13799 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
364d4831
NF
13800 /* No delay slot, so just process as a normal instruction */
13801 break;
13802 case M16_OPC_JAL:
eeb3bba8 13803 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
13804 offset = (((ctx->opcode & 0x1f) << 21)
13805 | ((ctx->opcode >> 5) & 0x1f) << 16
13806 | offset) << 2;
b231c103
YK
13807 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13808 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
364d4831 13809 n_bytes = 4;
364d4831
NF
13810 break;
13811 case M16_OPC_BEQZ:
b231c103
YK
13812 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13813 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13814 /* No delay slot, so just process as a normal instruction */
13815 break;
13816 case M16_OPC_BNEQZ:
b231c103
YK
13817 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13818 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13819 /* No delay slot, so just process as a normal instruction */
13820 break;
13821 case M16_OPC_SHIFT:
13822 switch (ctx->opcode & 0x3) {
13823 case 0x0:
d75c135e 13824 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
13825 break;
13826 case 0x1:
13827#if defined(TARGET_MIPS64)
d9224450 13828 check_insn(ctx, ISA_MIPS3);
364d4831 13829 check_mips_64(ctx);
d75c135e 13830 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 13831#else
9c708c7f 13832 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13833#endif
13834 break;
13835 case 0x2:
d75c135e 13836 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
13837 break;
13838 case 0x3:
d75c135e 13839 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
13840 break;
13841 }
13842 break;
13843#if defined(TARGET_MIPS64)
13844 case M16_OPC_LD:
d9224450 13845 check_insn(ctx, ISA_MIPS3);
364d4831 13846 check_mips_64(ctx);
d75c135e 13847 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
13848 break;
13849#endif
13850 case M16_OPC_RRIA:
13851 {
13852 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13853
13854 if ((ctx->opcode >> 4) & 1) {
13855#if defined(TARGET_MIPS64)
d9224450 13856 check_insn(ctx, ISA_MIPS3);
364d4831 13857 check_mips_64(ctx);
d75c135e 13858 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 13859#else
9c708c7f 13860 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13861#endif
13862 } else {
d75c135e 13863 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
13864 }
13865 }
13866 break;
13867 case M16_OPC_ADDIU8:
13868 {
13869 int16_t imm = (int8_t) ctx->opcode;
13870
d75c135e 13871 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
13872 }
13873 break;
13874 case M16_OPC_SLTI:
13875 {
13876 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 13877 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
13878 }
13879 break;
13880 case M16_OPC_SLTIU:
13881 {
13882 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 13883 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
13884 }
13885 break;
13886 case M16_OPC_I8:
13887 {
13888 int reg32;
13889
13890 funct = (ctx->opcode >> 8) & 0x7;
13891 switch (funct) {
13892 case I8_BTEQZ:
13893 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
b231c103 13894 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13895 break;
13896 case I8_BTNEZ:
13897 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
b231c103 13898 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13899 break;
13900 case I8_SWRASP:
5c13fdfd 13901 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
13902 break;
13903 case I8_ADJSP:
d75c135e 13904 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
364d4831
NF
13905 ((int8_t)ctx->opcode) << 3);
13906 break;
13907 case I8_SVRS:
d9224450 13908 check_insn(ctx, ISA_MIPS32);
364d4831
NF
13909 {
13910 int do_ra = ctx->opcode & (1 << 6);
13911 int do_s0 = ctx->opcode & (1 << 5);
13912 int do_s1 = ctx->opcode & (1 << 4);
13913 int framesize = ctx->opcode & 0xf;
13914
13915 if (framesize == 0) {
13916 framesize = 128;
13917 } else {
13918 framesize = framesize << 3;
13919 }
13920
13921 if (ctx->opcode & (1 << 7)) {
13922 gen_mips16_save(ctx, 0, 0,
13923 do_ra, do_s0, do_s1, framesize);
13924 } else {
13925 gen_mips16_restore(ctx, 0, 0,
13926 do_ra, do_s0, do_s1, framesize);
13927 }
13928 }
13929 break;
13930 case I8_MOV32R:
13931 {
13932 int rz = xlat(ctx->opcode & 0x7);
13933
13934 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13935 ((ctx->opcode >> 5) & 0x7);
d75c135e 13936 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
364d4831
NF
13937 }
13938 break;
13939 case I8_MOVR32:
13940 reg32 = ctx->opcode & 0x1f;
d75c135e 13941 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
364d4831
NF
13942 break;
13943 default:
9c708c7f 13944 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13945 break;
13946 }
13947 }
13948 break;
13949 case M16_OPC_LI:
13950 {
13951 int16_t imm = (uint8_t) ctx->opcode;
13952
d75c135e 13953 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
364d4831
NF
13954 }
13955 break;
13956 case M16_OPC_CMPI:
13957 {
13958 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 13959 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
13960 }
13961 break;
13962#if defined(TARGET_MIPS64)
13963 case M16_OPC_SD:
d9224450 13964 check_insn(ctx, ISA_MIPS3);
364d4831 13965 check_mips_64(ctx);
5c13fdfd 13966 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
13967 break;
13968#endif
13969 case M16_OPC_LB:
d75c135e 13970 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
13971 break;
13972 case M16_OPC_LH:
d75c135e 13973 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
13974 break;
13975 case M16_OPC_LWSP:
d75c135e 13976 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
13977 break;
13978 case M16_OPC_LW:
d75c135e 13979 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
13980 break;
13981 case M16_OPC_LBU:
d75c135e 13982 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
13983 break;
13984 case M16_OPC_LHU:
d75c135e 13985 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
13986 break;
13987 case M16_OPC_LWPC:
d75c135e 13988 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
13989 break;
13990#if defined (TARGET_MIPS64)
13991 case M16_OPC_LWU:
d9224450 13992 check_insn(ctx, ISA_MIPS3);
364d4831 13993 check_mips_64(ctx);
d75c135e 13994 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
13995 break;
13996#endif
13997 case M16_OPC_SB:
5c13fdfd 13998 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
13999 break;
14000 case M16_OPC_SH:
5c13fdfd 14001 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
14002 break;
14003 case M16_OPC_SWSP:
5c13fdfd 14004 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
14005 break;
14006 case M16_OPC_SW:
5c13fdfd 14007 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
14008 break;
14009 case M16_OPC_RRR:
14010 {
14011 int rz = xlat((ctx->opcode >> 2) & 0x7);
14012 int mips32_op;
14013
14014 switch (ctx->opcode & 0x3) {
14015 case RRR_ADDU:
14016 mips32_op = OPC_ADDU;
14017 break;
14018 case RRR_SUBU:
14019 mips32_op = OPC_SUBU;
14020 break;
14021#if defined(TARGET_MIPS64)
14022 case RRR_DADDU:
14023 mips32_op = OPC_DADDU;
d9224450 14024 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14025 check_mips_64(ctx);
14026 break;
14027 case RRR_DSUBU:
14028 mips32_op = OPC_DSUBU;
d9224450 14029 check_insn(ctx, ISA_MIPS3);
364d4831
NF
14030 check_mips_64(ctx);
14031 break;
14032#endif
14033 default:
9c708c7f 14034 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14035 goto done;
14036 }
14037
d75c135e 14038 gen_arith(ctx, mips32_op, rz, rx, ry);
364d4831
NF
14039 done:
14040 ;
14041 }
14042 break;
14043 case M16_OPC_RR:
14044 switch (op1) {
14045 case RR_JR:
14046 {
14047 int nd = (ctx->opcode >> 7) & 0x1;
14048 int link = (ctx->opcode >> 6) & 0x1;
14049 int ra = (ctx->opcode >> 5) & 0x1;
14050
d9224450
MR
14051 if (nd) {
14052 check_insn(ctx, ISA_MIPS32);
14053 }
14054
364d4831 14055 if (link) {
b231c103 14056 op = OPC_JALR;
364d4831
NF
14057 } else {
14058 op = OPC_JR;
14059 }
14060
b231c103
YK
14061 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14062 (nd ? 0 : 2));
364d4831
NF
14063 }
14064 break;
14065 case RR_SDBBP:
3b3c1694
LA
14066 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14067 gen_helper_do_semihosting(cpu_env);
14068 } else {
14069 /* XXX: not clear which exception should be raised
14070 * when in debug mode...
14071 */
14072 check_insn(ctx, ISA_MIPS32);
9c708c7f 14073 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 14074 }
364d4831
NF
14075 break;
14076 case RR_SLT:
d75c135e 14077 gen_slt(ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
14078 break;
14079 case RR_SLTU:
d75c135e 14080 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
14081 break;
14082 case RR_BREAK:
9c708c7f 14083 generate_exception_end(ctx, EXCP_BREAK);
364d4831
NF
14084 break;
14085 case RR_SLLV:
d75c135e 14086 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
364d4831
NF
14087 break;
14088 case RR_SRLV:
d75c135e 14089 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
364d4831
NF
14090 break;
14091 case RR_SRAV:
d75c135e 14092 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
364d4831
NF
14093 break;
14094#if defined (TARGET_MIPS64)
14095 case RR_DSRL:
d9224450 14096 check_insn(ctx, ISA_MIPS3);
364d4831 14097 check_mips_64(ctx);
d75c135e 14098 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
364d4831
NF
14099 break;
14100#endif
14101 case RR_CMP:
d75c135e 14102 gen_logic(ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
14103 break;
14104 case RR_NEG:
d75c135e 14105 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
364d4831
NF
14106 break;
14107 case RR_AND:
d75c135e 14108 gen_logic(ctx, OPC_AND, rx, rx, ry);
364d4831
NF
14109 break;
14110 case RR_OR:
d75c135e 14111 gen_logic(ctx, OPC_OR, rx, rx, ry);
364d4831
NF
14112 break;
14113 case RR_XOR:
d75c135e 14114 gen_logic(ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
14115 break;
14116 case RR_NOT:
d75c135e 14117 gen_logic(ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
14118 break;
14119 case RR_MFHI:
26135ead 14120 gen_HILO(ctx, OPC_MFHI, 0, rx);
364d4831
NF
14121 break;
14122 case RR_CNVT:
d9224450 14123 check_insn(ctx, ISA_MIPS32);
364d4831
NF
14124 switch (cnvt_op) {
14125 case RR_RY_CNVT_ZEB:
14126 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14127 break;
14128 case RR_RY_CNVT_ZEH:
14129 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14130 break;
14131 case RR_RY_CNVT_SEB:
14132 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14133 break;
14134 case RR_RY_CNVT_SEH:
14135 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14136 break;
14137#if defined (TARGET_MIPS64)
14138 case RR_RY_CNVT_ZEW:
d9224450 14139 check_insn(ctx, ISA_MIPS64);
364d4831
NF
14140 check_mips_64(ctx);
14141 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14142 break;
14143 case RR_RY_CNVT_SEW:
d9224450 14144 check_insn(ctx, ISA_MIPS64);
364d4831
NF
14145 check_mips_64(ctx);
14146 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14147 break;
14148#endif
14149 default:
9c708c7f 14150 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14151 break;
14152 }
14153 break;
14154 case RR_MFLO:
26135ead 14155 gen_HILO(ctx, OPC_MFLO, 0, rx);
364d4831
NF
14156 break;
14157#if defined (TARGET_MIPS64)
14158 case RR_DSRA:
d9224450 14159 check_insn(ctx, ISA_MIPS3);
364d4831 14160 check_mips_64(ctx);
d75c135e 14161 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
364d4831
NF
14162 break;
14163 case RR_DSLLV:
d9224450 14164 check_insn(ctx, ISA_MIPS3);
364d4831 14165 check_mips_64(ctx);
d75c135e 14166 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
364d4831
NF
14167 break;
14168 case RR_DSRLV:
d9224450 14169 check_insn(ctx, ISA_MIPS3);
364d4831 14170 check_mips_64(ctx);
d75c135e 14171 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
364d4831
NF
14172 break;
14173 case RR_DSRAV:
d9224450 14174 check_insn(ctx, ISA_MIPS3);
364d4831 14175 check_mips_64(ctx);
d75c135e 14176 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
364d4831
NF
14177 break;
14178#endif
14179 case RR_MULT:
26135ead 14180 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
364d4831
NF
14181 break;
14182 case RR_MULTU:
26135ead 14183 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
364d4831
NF
14184 break;
14185 case RR_DIV:
26135ead 14186 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
364d4831
NF
14187 break;
14188 case RR_DIVU:
26135ead 14189 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
364d4831
NF
14190 break;
14191#if defined (TARGET_MIPS64)
14192 case RR_DMULT:
d9224450 14193 check_insn(ctx, ISA_MIPS3);
364d4831 14194 check_mips_64(ctx);
26135ead 14195 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
364d4831
NF
14196 break;
14197 case RR_DMULTU:
d9224450 14198 check_insn(ctx, ISA_MIPS3);
364d4831 14199 check_mips_64(ctx);
26135ead 14200 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
364d4831
NF
14201 break;
14202 case RR_DDIV:
d9224450 14203 check_insn(ctx, ISA_MIPS3);
364d4831 14204 check_mips_64(ctx);
26135ead 14205 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
364d4831
NF
14206 break;
14207 case RR_DDIVU:
d9224450 14208 check_insn(ctx, ISA_MIPS3);
364d4831 14209 check_mips_64(ctx);
26135ead 14210 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
364d4831
NF
14211 break;
14212#endif
14213 default:
9c708c7f 14214 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14215 break;
14216 }
14217 break;
14218 case M16_OPC_EXTEND:
240ce26a 14219 decode_extended_mips16_opc(env, ctx);
364d4831
NF
14220 n_bytes = 4;
14221 break;
14222#if defined(TARGET_MIPS64)
14223 case M16_OPC_I64:
14224 funct = (ctx->opcode >> 8) & 0x7;
d75c135e 14225 decode_i64_mips16(ctx, ry, funct, offset, 0);
364d4831
NF
14226 break;
14227#endif
14228 default:
9c708c7f 14229 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
14230 break;
14231 }
14232
14233 return n_bytes;
14234}
14235
211da992 14236/* microMIPS extension to MIPS32/MIPS64 */
6af0bf9c 14237
211da992
CWR
14238/*
14239 * microMIPS32/microMIPS64 major opcodes
14240 *
14241 * 1. MIPS Architecture for Programmers Volume II-B:
14242 * The microMIPS32 Instruction Set (Revision 3.05)
14243 *
14244 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14245 *
14246 * 2. MIPS Architecture For Programmers Volume II-A:
14247 * The MIPS64 Instruction Set (Revision 3.51)
14248 */
6af0bf9c 14249
3c824109
NF
14250enum {
14251 POOL32A = 0x00,
14252 POOL16A = 0x01,
14253 LBU16 = 0x02,
14254 MOVE16 = 0x03,
14255 ADDI32 = 0x04,
3a1f4268
YK
14256 R6_LUI = 0x04,
14257 AUI = 0x04,
3c824109
NF
14258 LBU32 = 0x05,
14259 SB32 = 0x06,
14260 LB32 = 0x07,
14261
14262 POOL32B = 0x08,
14263 POOL16B = 0x09,
14264 LHU16 = 0x0a,
14265 ANDI16 = 0x0b,
14266 ADDIU32 = 0x0c,
14267 LHU32 = 0x0d,
14268 SH32 = 0x0e,
14269 LH32 = 0x0f,
14270
14271 POOL32I = 0x10,
14272 POOL16C = 0x11,
14273 LWSP16 = 0x12,
14274 POOL16D = 0x13,
14275 ORI32 = 0x14,
14276 POOL32F = 0x15,
211da992
CWR
14277 POOL32S = 0x16, /* MIPS64 */
14278 DADDIU32 = 0x17, /* MIPS64 */
3c824109
NF
14279
14280 POOL32C = 0x18,
14281 LWGP16 = 0x19,
14282 LW16 = 0x1a,
14283 POOL16E = 0x1b,
14284 XORI32 = 0x1c,
14285 JALS32 = 0x1d,
3a1f4268
YK
14286 BOVC = 0x1d,
14287 BEQC = 0x1d,
14288 BEQZALC = 0x1d,
3c824109 14289 ADDIUPC = 0x1e,
3a1f4268
YK
14290 PCREL = 0x1e,
14291 BNVC = 0x1f,
14292 BNEC = 0x1f,
14293 BNEZALC = 0x1f,
3c824109 14294
3a1f4268
YK
14295 R6_BEQZC = 0x20,
14296 JIC = 0x20,
3c824109
NF
14297 POOL16F = 0x21,
14298 SB16 = 0x22,
14299 BEQZ16 = 0x23,
3a1f4268 14300 BEQZC16 = 0x23,
3c824109
NF
14301 SLTI32 = 0x24,
14302 BEQ32 = 0x25,
3a1f4268 14303 BC = 0x25,
3c824109
NF
14304 SWC132 = 0x26,
14305 LWC132 = 0x27,
14306
3a1f4268 14307 /* 0x29 is reserved */
3c824109 14308 RES_29 = 0x29,
3a1f4268
YK
14309 R6_BNEZC = 0x28,
14310 JIALC = 0x28,
3c824109
NF
14311 SH16 = 0x2a,
14312 BNEZ16 = 0x2b,
3a1f4268 14313 BNEZC16 = 0x2b,
3c824109
NF
14314 SLTIU32 = 0x2c,
14315 BNE32 = 0x2d,
3a1f4268 14316 BALC = 0x2d,
3c824109
NF
14317 SDC132 = 0x2e,
14318 LDC132 = 0x2f,
14319
3a1f4268 14320 /* 0x31 is reserved */
3c824109 14321 RES_31 = 0x31,
3a1f4268
YK
14322 BLEZALC = 0x30,
14323 BGEZALC = 0x30,
14324 BGEUC = 0x30,
3c824109
NF
14325 SWSP16 = 0x32,
14326 B16 = 0x33,
3a1f4268 14327 BC16 = 0x33,
3c824109
NF
14328 ANDI32 = 0x34,
14329 J32 = 0x35,
3a1f4268
YK
14330 BGTZC = 0x35,
14331 BLTZC = 0x35,
14332 BLTC = 0x35,
211da992
CWR
14333 SD32 = 0x36, /* MIPS64 */
14334 LD32 = 0x37, /* MIPS64 */
3c824109 14335
3a1f4268 14336 /* 0x39 is reserved */
3c824109 14337 RES_39 = 0x39,
3a1f4268
YK
14338 BGTZALC = 0x38,
14339 BLTZALC = 0x38,
14340 BLTUC = 0x38,
3c824109
NF
14341 SW16 = 0x3a,
14342 LI16 = 0x3b,
14343 JALX32 = 0x3c,
14344 JAL32 = 0x3d,
3a1f4268
YK
14345 BLEZC = 0x3d,
14346 BGEZC = 0x3d,
14347 BGEC = 0x3d,
3c824109
NF
14348 SW32 = 0x3e,
14349 LW32 = 0x3f
14350};
14351
3a1f4268
YK
14352/* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14353enum {
14354 ADDIUPC_00 = 0x00,
c38a1d52
AR
14355 ADDIUPC_01 = 0x01,
14356 ADDIUPC_02 = 0x02,
14357 ADDIUPC_03 = 0x03,
14358 ADDIUPC_04 = 0x04,
14359 ADDIUPC_05 = 0x05,
14360 ADDIUPC_06 = 0x06,
3a1f4268
YK
14361 ADDIUPC_07 = 0x07,
14362 AUIPC = 0x1e,
14363 ALUIPC = 0x1f,
14364 LWPC_08 = 0x08,
c38a1d52
AR
14365 LWPC_09 = 0x09,
14366 LWPC_0A = 0x0A,
14367 LWPC_0B = 0x0B,
14368 LWPC_0C = 0x0C,
14369 LWPC_0D = 0x0D,
14370 LWPC_0E = 0x0E,
3a1f4268
YK
14371 LWPC_0F = 0x0F,
14372};
14373
3c824109
NF
14374/* POOL32A encoding of minor opcode field */
14375
14376enum {
14377 /* These opcodes are distinguished only by bits 9..6; those bits are
14378 * what are recorded below. */
14379 SLL32 = 0x0,
14380 SRL32 = 0x1,
14381 SRA = 0x2,
14382 ROTR = 0x3,
3a1f4268
YK
14383 SELEQZ = 0x5,
14384 SELNEZ = 0x6,
b00c7218 14385 R6_RDHWR = 0x7,
3c824109
NF
14386
14387 SLLV = 0x0,
14388 SRLV = 0x1,
14389 SRAV = 0x2,
14390 ROTRV = 0x3,
14391 ADD = 0x4,
14392 ADDU32 = 0x5,
14393 SUB = 0x6,
14394 SUBU32 = 0x7,
14395 MUL = 0x8,
14396 AND = 0x9,
14397 OR32 = 0xa,
14398 NOR = 0xb,
14399 XOR32 = 0xc,
14400 SLT = 0xd,
14401 SLTU = 0xe,
14402
14403 MOVN = 0x0,
3a1f4268 14404 R6_MUL = 0x0,
3c824109 14405 MOVZ = 0x1,
3a1f4268
YK
14406 MUH = 0x1,
14407 MULU = 0x2,
14408 MUHU = 0x3,
3c824109 14409 LWXS = 0x4,
3a1f4268
YK
14410 R6_DIV = 0x4,
14411 MOD = 0x5,
14412 R6_DIVU = 0x6,
14413 MODU = 0x7,
3c824109
NF
14414
14415 /* The following can be distinguished by their lower 6 bits. */
dbd8af98 14416 BREAK32 = 0x07,
3c824109 14417 INS = 0x0c,
3a1f4268
YK
14418 LSA = 0x0f,
14419 ALIGN = 0x1f,
3c824109 14420 EXT = 0x2c,
bb238210
YK
14421 POOL32AXF = 0x3c,
14422 SIGRIE = 0x3f
3c824109
NF
14423};
14424
14425/* POOL32AXF encoding of minor opcode field extension */
14426
d132c79f
CWR
14427/*
14428 * 1. MIPS Architecture for Programmers Volume II-B:
14429 * The microMIPS32 Instruction Set (Revision 3.05)
14430 *
14431 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14432 *
14433 * 2. MIPS Architecture for Programmers VolumeIV-e:
14434 * The MIPS DSP Application-Specific Extension
14435 * to the microMIPS32 Architecture (Revision 2.34)
14436 *
14437 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14438 */
14439
3c824109
NF
14440enum {
14441 /* bits 11..6 */
14442 TEQ = 0x00,
14443 TGE = 0x08,
14444 TGEU = 0x10,
14445 TLT = 0x20,
14446 TLTU = 0x28,
14447 TNE = 0x30,
14448
14449 MFC0 = 0x03,
14450 MTC0 = 0x0b,
14451
d132c79f
CWR
14452 /* begin of microMIPS32 DSP */
14453
3c824109
NF
14454 /* bits 13..12 for 0x01 */
14455 MFHI_ACC = 0x0,
14456 MFLO_ACC = 0x1,
14457 MTHI_ACC = 0x2,
14458 MTLO_ACC = 0x3,
14459
14460 /* bits 13..12 for 0x2a */
14461 MADD_ACC = 0x0,
14462 MADDU_ACC = 0x1,
14463 MSUB_ACC = 0x2,
14464 MSUBU_ACC = 0x3,
14465
14466 /* bits 13..12 for 0x32 */
14467 MULT_ACC = 0x0,
6801038b 14468 MULTU_ACC = 0x1,
3c824109 14469
d132c79f
CWR
14470 /* end of microMIPS32 DSP */
14471
3c824109 14472 /* bits 15..12 for 0x2c */
3a1f4268 14473 BITSWAP = 0x0,
3c824109
NF
14474 SEB = 0x2,
14475 SEH = 0x3,
14476 CLO = 0x4,
14477 CLZ = 0x5,
14478 RDHWR = 0x6,
14479 WSBH = 0x7,
14480 MULT = 0x8,
14481 MULTU = 0x9,
14482 DIV = 0xa,
14483 DIVU = 0xb,
14484 MADD = 0xc,
14485 MADDU = 0xd,
14486 MSUB = 0xe,
14487 MSUBU = 0xf,
14488
14489 /* bits 15..12 for 0x34 */
14490 MFC2 = 0x4,
14491 MTC2 = 0x5,
14492 MFHC2 = 0x8,
14493 MTHC2 = 0x9,
14494 CFC2 = 0xc,
14495 CTC2 = 0xd,
14496
14497 /* bits 15..12 for 0x3c */
14498 JALR = 0x0,
14499 JR = 0x0, /* alias */
3a1f4268
YK
14500 JALRC = 0x0,
14501 JRC = 0x0,
3c824109 14502 JALR_HB = 0x1,
3a1f4268 14503 JALRC_HB = 0x1,
3c824109
NF
14504 JALRS = 0x4,
14505 JALRS_HB = 0x5,
14506
14507 /* bits 15..12 for 0x05 */
14508 RDPGPR = 0xe,
14509 WRPGPR = 0xf,
14510
14511 /* bits 15..12 for 0x0d */
14512 TLBP = 0x0,
14513 TLBR = 0x1,
14514 TLBWI = 0x2,
14515 TLBWR = 0x3,
e60ec063
YK
14516 TLBINV = 0x4,
14517 TLBINVF = 0x5,
3c824109
NF
14518 WAIT = 0x9,
14519 IRET = 0xd,
14520 DERET = 0xe,
14521 ERET = 0xf,
14522
14523 /* bits 15..12 for 0x15 */
14524 DMT = 0x0,
14525 DVPE = 0x1,
14526 EMT = 0x2,
14527 EVPE = 0x3,
14528
14529 /* bits 15..12 for 0x1d */
14530 DI = 0x4,
14531 EI = 0x5,
14532
14533 /* bits 15..12 for 0x2d */
14534 SYNC = 0x6,
14535 SYSCALL = 0x8,
14536 SDBBP = 0xd,
14537
14538 /* bits 15..12 for 0x35 */
14539 MFHI32 = 0x0,
14540 MFLO32 = 0x1,
14541 MTHI32 = 0x2,
14542 MTLO32 = 0x3,
14543};
14544
14545/* POOL32B encoding of minor opcode field (bits 15..12) */
14546
14547enum {
14548 LWC2 = 0x0,
14549 LWP = 0x1,
14550 LDP = 0x4,
14551 LWM32 = 0x5,
14552 CACHE = 0x6,
14553 LDM = 0x7,
14554 SWC2 = 0x8,
14555 SWP = 0x9,
14556 SDP = 0xc,
14557 SWM32 = 0xd,
14558 SDM = 0xf
14559};
14560
14561/* POOL32C encoding of minor opcode field (bits 15..12) */
14562
14563enum {
14564 LWL = 0x0,
14565 SWL = 0x8,
14566 LWR = 0x1,
14567 SWR = 0x9,
14568 PREF = 0x2,
8fffc646 14569 ST_EVA = 0xa,
3c824109
NF
14570 LL = 0x3,
14571 SC = 0xb,
14572 LDL = 0x4,
14573 SDL = 0xc,
14574 LDR = 0x5,
14575 SDR = 0xd,
8fffc646 14576 LD_EVA = 0x6,
3c824109
NF
14577 LWU = 0xe,
14578 LLD = 0x7,
14579 SCD = 0xf
14580};
14581
8fffc646
JH
14582/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14583
14584enum {
14585 LBUE = 0x0,
14586 LHUE = 0x1,
14587 LWLE = 0x2,
14588 LWRE = 0x3,
14589 LBE = 0x4,
14590 LHE = 0x5,
14591 LLE = 0x6,
14592 LWE = 0x7,
14593};
14594
14595/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14596
14597enum {
14598 SWLE = 0x0,
14599 SWRE = 0x1,
14600 PREFE = 0x2,
14601 CACHEE = 0x3,
14602 SBE = 0x4,
14603 SHE = 0x5,
14604 SCE = 0x6,
14605 SWE = 0x7,
14606};
14607
3c824109
NF
14608/* POOL32F encoding of minor opcode field (bits 5..0) */
14609
14610enum {
14611 /* These are the bit 7..6 values */
14612 ADD_FMT = 0x0,
3c824109
NF
14613
14614 SUB_FMT = 0x1,
3c824109
NF
14615
14616 MUL_FMT = 0x2,
14617
14618 DIV_FMT = 0x3,
14619
14620 /* These are the bit 8..6 values */
3a1f4268 14621 MOVN_FMT = 0x0,
3c824109
NF
14622 RSQRT2_FMT = 0x0,
14623 MOVF_FMT = 0x0,
3a1f4268
YK
14624 RINT_FMT = 0x0,
14625 SELNEZ_FMT = 0x0,
3c824109 14626
3a1f4268 14627 MOVZ_FMT = 0x1,
3c824109
NF
14628 LWXC1 = 0x1,
14629 MOVT_FMT = 0x1,
3a1f4268
YK
14630 CLASS_FMT = 0x1,
14631 SELEQZ_FMT = 0x1,
3c824109
NF
14632
14633 PLL_PS = 0x2,
14634 SWXC1 = 0x2,
3a1f4268 14635 SEL_FMT = 0x2,
3c824109
NF
14636
14637 PLU_PS = 0x3,
14638 LDXC1 = 0x3,
14639
3a1f4268 14640 MOVN_FMT_04 = 0x4,
3c824109
NF
14641 PUL_PS = 0x4,
14642 SDXC1 = 0x4,
14643 RECIP2_FMT = 0x4,
14644
3a1f4268 14645 MOVZ_FMT_05 = 0x05,
3c824109
NF
14646 PUU_PS = 0x5,
14647 LUXC1 = 0x5,
14648
14649 CVT_PS_S = 0x6,
14650 SUXC1 = 0x6,
14651 ADDR_PS = 0x6,
14652 PREFX = 0x6,
3a1f4268 14653 MADDF_FMT = 0x6,
3c824109
NF
14654
14655 MULR_PS = 0x7,
3a1f4268 14656 MSUBF_FMT = 0x7,
3c824109
NF
14657
14658 MADD_S = 0x01,
14659 MADD_D = 0x09,
14660 MADD_PS = 0x11,
14661 ALNV_PS = 0x19,
14662 MSUB_S = 0x21,
14663 MSUB_D = 0x29,
14664 MSUB_PS = 0x31,
14665
14666 NMADD_S = 0x02,
14667 NMADD_D = 0x0a,
14668 NMADD_PS = 0x12,
14669 NMSUB_S = 0x22,
14670 NMSUB_D = 0x2a,
14671 NMSUB_PS = 0x32,
14672
3a1f4268
YK
14673 MIN_FMT = 0x3,
14674 MAX_FMT = 0xb,
14675 MINA_FMT = 0x23,
14676 MAXA_FMT = 0x2b,
3c824109
NF
14677 POOL32FXF = 0x3b,
14678
14679 CABS_COND_FMT = 0x1c, /* MIPS3D */
3a1f4268
YK
14680 C_COND_FMT = 0x3c,
14681
14682 CMP_CONDN_S = 0x5,
14683 CMP_CONDN_D = 0x15
3c824109
NF
14684};
14685
14686/* POOL32Fxf encoding of minor opcode extension field */
14687
14688enum {
14689 CVT_L = 0x04,
14690 RSQRT_FMT = 0x08,
14691 FLOOR_L = 0x0c,
14692 CVT_PW_PS = 0x1c,
14693 CVT_W = 0x24,
14694 SQRT_FMT = 0x28,
14695 FLOOR_W = 0x2c,
14696 CVT_PS_PW = 0x3c,
14697 CFC1 = 0x40,
14698 RECIP_FMT = 0x48,
14699 CEIL_L = 0x4c,
14700 CTC1 = 0x60,
14701 CEIL_W = 0x6c,
14702 MFC1 = 0x80,
14703 CVT_S_PL = 0x84,
14704 TRUNC_L = 0x8c,
14705 MTC1 = 0xa0,
14706 CVT_S_PU = 0xa4,
14707 TRUNC_W = 0xac,
14708 MFHC1 = 0xc0,
14709 ROUND_L = 0xcc,
14710 MTHC1 = 0xe0,
14711 ROUND_W = 0xec,
14712
14713 MOV_FMT = 0x01,
14714 MOVF = 0x05,
14715 ABS_FMT = 0x0d,
14716 RSQRT1_FMT = 0x1d,
14717 MOVT = 0x25,
14718 NEG_FMT = 0x2d,
14719 CVT_D = 0x4d,
14720 RECIP1_FMT = 0x5d,
14721 CVT_S = 0x6d
14722};
14723
14724/* POOL32I encoding of minor opcode field (bits 25..21) */
14725
14726enum {
14727 BLTZ = 0x00,
14728 BLTZAL = 0x01,
14729 BGEZ = 0x02,
14730 BGEZAL = 0x03,
14731 BLEZ = 0x04,
14732 BNEZC = 0x05,
14733 BGTZ = 0x06,
14734 BEQZC = 0x07,
14735 TLTI = 0x08,
3a1f4268 14736 BC1EQZC = 0x08,
3c824109 14737 TGEI = 0x09,
3a1f4268 14738 BC1NEZC = 0x09,
3c824109 14739 TLTIU = 0x0a,
3a1f4268 14740 BC2EQZC = 0x0a,
3c824109 14741 TGEIU = 0x0b,
3a1f4268 14742 BC2NEZC = 0x0a,
3c824109 14743 TNEI = 0x0c,
3a1f4268 14744 R6_SYNCI = 0x0c,
3c824109
NF
14745 LUI = 0x0d,
14746 TEQI = 0x0e,
14747 SYNCI = 0x10,
14748 BLTZALS = 0x11,
14749 BGEZALS = 0x13,
14750 BC2F = 0x14,
14751 BC2T = 0x15,
14752 BPOSGE64 = 0x1a,
14753 BPOSGE32 = 0x1b,
14754 /* These overlap and are distinguished by bit16 of the instruction */
14755 BC1F = 0x1c,
14756 BC1T = 0x1d,
14757 BC1ANY2F = 0x1c,
14758 BC1ANY2T = 0x1d,
14759 BC1ANY4F = 0x1e,
14760 BC1ANY4T = 0x1f
14761};
14762
14763/* POOL16A encoding of minor opcode field */
14764
14765enum {
14766 ADDU16 = 0x0,
14767 SUBU16 = 0x1
14768};
14769
14770/* POOL16B encoding of minor opcode field */
14771
14772enum {
14773 SLL16 = 0x0,
14774 SRL16 = 0x1
14775};
14776
14777/* POOL16C encoding of minor opcode field */
14778
14779enum {
14780 NOT16 = 0x00,
14781 XOR16 = 0x04,
14782 AND16 = 0x08,
14783 OR16 = 0x0c,
14784 LWM16 = 0x10,
14785 SWM16 = 0x14,
14786 JR16 = 0x18,
14787 JRC16 = 0x1a,
14788 JALR16 = 0x1c,
14789 JALR16S = 0x1e,
14790 MFHI16 = 0x20,
14791 MFLO16 = 0x24,
14792 BREAK16 = 0x28,
14793 SDBBP16 = 0x2c,
14794 JRADDIUSP = 0x30
14795};
14796
3a1f4268
YK
14797/* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14798
14799enum {
14800 R6_NOT16 = 0x00,
14801 R6_AND16 = 0x01,
14802 R6_LWM16 = 0x02,
14803 R6_JRC16 = 0x03,
14804 MOVEP = 0x04,
c38a1d52
AR
14805 MOVEP_05 = 0x05,
14806 MOVEP_06 = 0x06,
3a1f4268
YK
14807 MOVEP_07 = 0x07,
14808 R6_XOR16 = 0x08,
14809 R6_OR16 = 0x09,
14810 R6_SWM16 = 0x0a,
14811 JALRC16 = 0x0b,
14812 MOVEP_0C = 0x0c,
c38a1d52
AR
14813 MOVEP_0D = 0x0d,
14814 MOVEP_0E = 0x0e,
3a1f4268
YK
14815 MOVEP_0F = 0x0f,
14816 JRCADDIUSP = 0x13,
14817 R6_BREAK16 = 0x1b,
14818 R6_SDBBP16 = 0x3b
14819};
14820
3c824109
NF
14821/* POOL16D encoding of minor opcode field */
14822
14823enum {
14824 ADDIUS5 = 0x0,
14825 ADDIUSP = 0x1
14826};
14827
14828/* POOL16E encoding of minor opcode field */
14829
14830enum {
14831 ADDIUR2 = 0x0,
14832 ADDIUR1SP = 0x1
14833};
14834
14835static int mmreg (int r)
14836{
14837 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14838
14839 return map[r];
14840}
14841
14842/* Used for 16-bit store instructions. */
14843static int mmreg2 (int r)
14844{
14845 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14846
14847 return map[r];
14848}
14849
14850#define uMIPS_RD(op) ((op >> 7) & 0x7)
14851#define uMIPS_RS(op) ((op >> 4) & 0x7)
14852#define uMIPS_RS2(op) uMIPS_RS(op)
14853#define uMIPS_RS1(op) ((op >> 1) & 0x7)
14854#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14855#define uMIPS_RS5(op) (op & 0x1f)
14856
14857/* Signed immediate */
14858#define SIMM(op, start, width) \
14859 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14860 << (32-width)) \
14861 >> (32-width))
14862/* Zero-extended immediate */
14863#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14864
d75c135e 14865static void gen_addiur1sp(DisasContext *ctx)
3c824109
NF
14866{
14867 int rd = mmreg(uMIPS_RD(ctx->opcode));
14868
d75c135e 14869 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
3c824109
NF
14870}
14871
d75c135e 14872static void gen_addiur2(DisasContext *ctx)
3c824109
NF
14873{
14874 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14875 int rd = mmreg(uMIPS_RD(ctx->opcode));
14876 int rs = mmreg(uMIPS_RS(ctx->opcode));
14877
d75c135e 14878 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
3c824109
NF
14879}
14880
d75c135e 14881static void gen_addiusp(DisasContext *ctx)
3c824109
NF
14882{
14883 int encoded = ZIMM(ctx->opcode, 1, 9);
14884 int decoded;
14885
14886 if (encoded <= 1) {
14887 decoded = 256 + encoded;
14888 } else if (encoded <= 255) {
14889 decoded = encoded;
14890 } else if (encoded <= 509) {
14891 decoded = encoded - 512;
14892 } else {
14893 decoded = encoded - 768;
14894 }
14895
d75c135e 14896 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
3c824109
NF
14897}
14898
d75c135e 14899static void gen_addius5(DisasContext *ctx)
3c824109
NF
14900{
14901 int imm = SIMM(ctx->opcode, 1, 4);
14902 int rd = (ctx->opcode >> 5) & 0x1f;
14903
d75c135e 14904 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
3c824109
NF
14905}
14906
d75c135e 14907static void gen_andi16(DisasContext *ctx)
3c824109
NF
14908{
14909 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14910 31, 32, 63, 64, 255, 32768, 65535 };
14911 int rd = mmreg(uMIPS_RD(ctx->opcode));
14912 int rs = mmreg(uMIPS_RS(ctx->opcode));
14913 int encoded = ZIMM(ctx->opcode, 0, 4);
14914
d75c135e 14915 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
14916}
14917
14918static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14919 int base, int16_t offset)
14920{
14921 TCGv t0, t1;
14922 TCGv_i32 t2;
14923
14924 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 14925 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
14926 return;
14927 }
14928
14929 t0 = tcg_temp_new();
14930
14931 gen_base_offset_addr(ctx, t0, base, offset);
14932
14933 t1 = tcg_const_tl(reglist);
14934 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 14935
3c824109
NF
14936 save_cpu_state(ctx, 1);
14937 switch (opc) {
14938 case LWM32:
895c2d04 14939 gen_helper_lwm(cpu_env, t0, t1, t2);
3c824109
NF
14940 break;
14941 case SWM32:
895c2d04 14942 gen_helper_swm(cpu_env, t0, t1, t2);
3c824109
NF
14943 break;
14944#ifdef TARGET_MIPS64
14945 case LDM:
895c2d04 14946 gen_helper_ldm(cpu_env, t0, t1, t2);
3c824109
NF
14947 break;
14948 case SDM:
895c2d04 14949 gen_helper_sdm(cpu_env, t0, t1, t2);
3c824109 14950 break;
6af0bf9c 14951#endif
3c824109 14952 }
3c824109 14953 tcg_temp_free(t0);
33087598 14954 tcg_temp_free(t1);
3c824109
NF
14955 tcg_temp_free_i32(t2);
14956}
6af0bf9c 14957
3c824109 14958
240ce26a 14959static void gen_pool16c_insn(DisasContext *ctx)
6af0bf9c 14960{
3c824109
NF
14961 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14962 int rs = mmreg(ctx->opcode & 0x7);
6af0bf9c 14963
3c824109
NF
14964 switch (((ctx->opcode) >> 4) & 0x3f) {
14965 case NOT16 + 0:
14966 case NOT16 + 1:
14967 case NOT16 + 2:
14968 case NOT16 + 3:
d75c135e 14969 gen_logic(ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
14970 break;
14971 case XOR16 + 0:
14972 case XOR16 + 1:
14973 case XOR16 + 2:
14974 case XOR16 + 3:
d75c135e 14975 gen_logic(ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
14976 break;
14977 case AND16 + 0:
14978 case AND16 + 1:
14979 case AND16 + 2:
14980 case AND16 + 3:
d75c135e 14981 gen_logic(ctx, OPC_AND, rd, rd, rs);
3c824109
NF
14982 break;
14983 case OR16 + 0:
14984 case OR16 + 1:
14985 case OR16 + 2:
14986 case OR16 + 3:
d75c135e 14987 gen_logic(ctx, OPC_OR, rd, rd, rs);
3c824109
NF
14988 break;
14989 case LWM16 + 0:
14990 case LWM16 + 1:
14991 case LWM16 + 2:
14992 case LWM16 + 3:
14993 {
14994 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14995 int offset = ZIMM(ctx->opcode, 0, 4);
14996
14997 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14998 29, offset << 2);
14999 }
15000 break;
15001 case SWM16 + 0:
15002 case SWM16 + 1:
15003 case SWM16 + 2:
15004 case SWM16 + 3:
15005 {
15006 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15007 int offset = ZIMM(ctx->opcode, 0, 4);
15008
15009 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15010 29, offset << 2);
15011 }
15012 break;
15013 case JR16 + 0:
15014 case JR16 + 1:
15015 {
15016 int reg = ctx->opcode & 0x1f;
15017
b231c103 15018 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
3c824109 15019 }
3c824109
NF
15020 break;
15021 case JRC16 + 0:
15022 case JRC16 + 1:
15023 {
15024 int reg = ctx->opcode & 0x1f;
b231c103 15025 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
3c824109
NF
15026 /* Let normal delay slot handling in our caller take us
15027 to the branch target. */
15028 }
15029 break;
15030 case JALR16 + 0:
15031 case JALR16 + 1:
b231c103
YK
15032 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15033 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15034 break;
3c824109
NF
15035 case JALR16S + 0:
15036 case JALR16S + 1:
b231c103
YK
15037 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15038 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
15039 break;
15040 case MFHI16 + 0:
15041 case MFHI16 + 1:
26135ead 15042 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
15043 break;
15044 case MFLO16 + 0:
15045 case MFLO16 + 1:
26135ead 15046 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
15047 break;
15048 case BREAK16:
9c708c7f 15049 generate_exception_end(ctx, EXCP_BREAK);
3c824109
NF
15050 break;
15051 case SDBBP16:
3b3c1694
LA
15052 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15053 gen_helper_do_semihosting(cpu_env);
15054 } else {
15055 /* XXX: not clear which exception should be raised
15056 * when in debug mode...
15057 */
15058 check_insn(ctx, ISA_MIPS32);
9c708c7f 15059 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 15060 }
3c824109
NF
15061 break;
15062 case JRADDIUSP + 0:
15063 case JRADDIUSP + 1:
15064 {
15065 int imm = ZIMM(ctx->opcode, 0, 5);
b231c103 15066 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
d75c135e 15067 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
3c824109
NF
15068 /* Let normal delay slot handling in our caller take us
15069 to the branch target. */
15070 }
15071 break;
15072 default:
9c708c7f 15073 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15074 break;
15075 }
15076}
15077
ed7ce6c0
YK
15078static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15079 int enc_rs)
15080{
15081 int rd, rs, re, rt;
15082 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15083 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15084 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15085 rd = rd_enc[enc_dest];
15086 re = re_enc[enc_dest];
15087 rs = rs_rt_enc[enc_rs];
15088 rt = rs_rt_enc[enc_rt];
15089 if (rs) {
15090 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15091 } else {
15092 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15093 }
15094 if (rt) {
15095 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15096 } else {
15097 tcg_gen_movi_tl(cpu_gpr[re], 0);
15098 }
15099}
15100
15101static void gen_pool16c_r6_insn(DisasContext *ctx)
15102{
15103 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15104 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15105
15106 switch (ctx->opcode & 0xf) {
15107 case R6_NOT16:
15108 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15109 break;
15110 case R6_AND16:
15111 gen_logic(ctx, OPC_AND, rt, rt, rs);
15112 break;
15113 case R6_LWM16:
15114 {
15115 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15116 int offset = extract32(ctx->opcode, 4, 4);
15117 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15118 }
15119 break;
15120 case R6_JRC16: /* JRCADDIUSP */
15121 if ((ctx->opcode >> 4) & 1) {
15122 /* JRCADDIUSP */
15123 int imm = extract32(ctx->opcode, 5, 5);
15124 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15125 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15126 } else {
15127 /* JRC16 */
e1555d7d 15128 rs = extract32(ctx->opcode, 5, 5);
ed7ce6c0
YK
15129 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15130 }
15131 break;
c38a1d52
AR
15132 case MOVEP:
15133 case MOVEP_05:
15134 case MOVEP_06:
15135 case MOVEP_07:
15136 case MOVEP_0C:
15137 case MOVEP_0D:
15138 case MOVEP_0E:
15139 case MOVEP_0F:
ed7ce6c0
YK
15140 {
15141 int enc_dest = uMIPS_RD(ctx->opcode);
15142 int enc_rt = uMIPS_RS2(ctx->opcode);
15143 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15144 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15145 }
15146 break;
15147 case R6_XOR16:
15148 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15149 break;
15150 case R6_OR16:
15151 gen_logic(ctx, OPC_OR, rt, rt, rs);
15152 break;
15153 case R6_SWM16:
15154 {
15155 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15156 int offset = extract32(ctx->opcode, 4, 4);
15157 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15158 }
15159 break;
15160 case JALRC16: /* BREAK16, SDBBP16 */
15161 switch (ctx->opcode & 0x3f) {
15162 case JALRC16:
15163 case JALRC16 + 0x20:
15164 /* JALRC16 */
15165 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15166 31, 0, 0);
15167 break;
15168 case R6_BREAK16:
15169 /* BREAK16 */
15170 generate_exception(ctx, EXCP_BREAK);
15171 break;
15172 case R6_SDBBP16:
15173 /* SDBBP16 */
060ebfef
LA
15174 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15175 gen_helper_do_semihosting(cpu_env);
ed7ce6c0 15176 } else {
060ebfef
LA
15177 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15178 generate_exception(ctx, EXCP_RI);
15179 } else {
15180 generate_exception(ctx, EXCP_DBp);
15181 }
ed7ce6c0
YK
15182 }
15183 break;
15184 }
15185 break;
15186 default:
15187 generate_exception(ctx, EXCP_RI);
15188 break;
15189 }
15190}
15191
3c824109
NF
15192static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
15193{
15194 TCGv t0 = tcg_temp_new();
15195 TCGv t1 = tcg_temp_new();
15196
15197 gen_load_gpr(t0, base);
15198
15199 if (index != 0) {
15200 gen_load_gpr(t1, index);
15201 tcg_gen_shli_tl(t1, t1, 2);
15202 gen_op_addr_add(ctx, t0, t1, t0);
15203 }
15204
5f68f5ae 15205 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
15206 gen_store_gpr(t1, rd);
15207
15208 tcg_temp_free(t0);
15209 tcg_temp_free(t1);
15210}
15211
15212static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
15213 int base, int16_t offset)
15214{
3c824109
NF
15215 TCGv t0, t1;
15216
36c6711b 15217 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
9c708c7f 15218 generate_exception_end(ctx, EXCP_RI);
d796321b
FB
15219 return;
15220 }
15221
3c824109
NF
15222 t0 = tcg_temp_new();
15223 t1 = tcg_temp_new();
8e9ade68 15224
3c824109
NF
15225 gen_base_offset_addr(ctx, t0, base, offset);
15226
15227 switch (opc) {
15228 case LWP:
36c6711b 15229 if (rd == base) {
9c708c7f 15230 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
15231 return;
15232 }
5f68f5ae 15233 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
15234 gen_store_gpr(t1, rd);
15235 tcg_gen_movi_tl(t1, 4);
15236 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 15237 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109 15238 gen_store_gpr(t1, rd+1);
3c824109
NF
15239 break;
15240 case SWP:
3c824109 15241 gen_load_gpr(t1, rd);
5f68f5ae 15242 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
15243 tcg_gen_movi_tl(t1, 4);
15244 gen_op_addr_add(ctx, t0, t0, t1);
15245 gen_load_gpr(t1, rd+1);
5f68f5ae 15246 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
15247 break;
15248#ifdef TARGET_MIPS64
15249 case LDP:
36c6711b 15250 if (rd == base) {
9c708c7f 15251 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
15252 return;
15253 }
5f68f5ae 15254 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15255 gen_store_gpr(t1, rd);
15256 tcg_gen_movi_tl(t1, 8);
15257 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 15258 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109 15259 gen_store_gpr(t1, rd+1);
3c824109
NF
15260 break;
15261 case SDP:
3c824109 15262 gen_load_gpr(t1, rd);
5f68f5ae 15263 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15264 tcg_gen_movi_tl(t1, 8);
15265 gen_op_addr_add(ctx, t0, t0, t1);
15266 gen_load_gpr(t1, rd+1);
5f68f5ae 15267 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
15268 break;
15269#endif
6af0bf9c 15270 }
3c824109
NF
15271 tcg_temp_free(t0);
15272 tcg_temp_free(t1);
15273}
618b0fe9 15274
d208ac0c
LA
15275static void gen_sync(int stype)
15276{
15277 TCGBar tcg_mo = TCG_BAR_SC;
15278
15279 switch (stype) {
15280 case 0x4: /* SYNC_WMB */
15281 tcg_mo |= TCG_MO_ST_ST;
15282 break;
15283 case 0x10: /* SYNC_MB */
15284 tcg_mo |= TCG_MO_ALL;
15285 break;
15286 case 0x11: /* SYNC_ACQUIRE */
15287 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15288 break;
15289 case 0x12: /* SYNC_RELEASE */
15290 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15291 break;
15292 case 0x13: /* SYNC_RMB */
15293 tcg_mo |= TCG_MO_LD_LD;
15294 break;
15295 default:
15296 tcg_mo |= TCG_MO_ALL;
15297 break;
15298 }
15299
15300 tcg_gen_mb(tcg_mo);
15301}
15302
240ce26a 15303static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
15304{
15305 int extension = (ctx->opcode >> 6) & 0x3f;
15306 int minor = (ctx->opcode >> 12) & 0xf;
15307 uint32_t mips32_op;
15308
15309 switch (extension) {
15310 case TEQ:
15311 mips32_op = OPC_TEQ;
15312 goto do_trap;
15313 case TGE:
15314 mips32_op = OPC_TGE;
15315 goto do_trap;
15316 case TGEU:
15317 mips32_op = OPC_TGEU;
15318 goto do_trap;
15319 case TLT:
15320 mips32_op = OPC_TLT;
15321 goto do_trap;
15322 case TLTU:
15323 mips32_op = OPC_TLTU;
15324 goto do_trap;
15325 case TNE:
15326 mips32_op = OPC_TNE;
15327 do_trap:
15328 gen_trap(ctx, mips32_op, rs, rt, -1);
15329 break;
15330#ifndef CONFIG_USER_ONLY
15331 case MFC0:
15332 case MFC0 + 32:
2e15497c 15333 check_cp0_enabled(ctx);
3c824109
NF
15334 if (rt == 0) {
15335 /* Treat as NOP. */
15336 break;
15337 }
d75c135e 15338 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
15339 break;
15340 case MTC0:
15341 case MTC0 + 32:
2e15497c 15342 check_cp0_enabled(ctx);
3c824109
NF
15343 {
15344 TCGv t0 = tcg_temp_new();
618b0fe9 15345
3c824109 15346 gen_load_gpr(t0, rt);
d75c135e 15347 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
15348 tcg_temp_free(t0);
15349 }
15350 break;
15351#endif
a1fc6246
LA
15352 case 0x2a:
15353 switch (minor & 3) {
15354 case MADD_ACC:
15355 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15356 break;
15357 case MADDU_ACC:
15358 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15359 break;
15360 case MSUB_ACC:
15361 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15362 break;
15363 case MSUBU_ACC:
15364 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15365 break;
15366 default:
15367 goto pool32axf_invalid;
15368 }
15369 break;
15370 case 0x32:
15371 switch (minor & 3) {
15372 case MULT_ACC:
15373 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15374 break;
15375 case MULTU_ACC:
15376 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15377 break;
15378 default:
15379 goto pool32axf_invalid;
15380 }
15381 break;
3c824109
NF
15382 case 0x2c:
15383 switch (minor) {
e0332095
YK
15384 case BITSWAP:
15385 check_insn(ctx, ISA_MIPS32R6);
15386 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15387 break;
3c824109
NF
15388 case SEB:
15389 gen_bshfl(ctx, OPC_SEB, rs, rt);
15390 break;
15391 case SEH:
15392 gen_bshfl(ctx, OPC_SEH, rs, rt);
15393 break;
15394 case CLO:
15395 mips32_op = OPC_CLO;
15396 goto do_cl;
15397 case CLZ:
15398 mips32_op = OPC_CLZ;
15399 do_cl:
d75c135e 15400 check_insn(ctx, ISA_MIPS32);
3c824109
NF
15401 gen_cl(ctx, mips32_op, rt, rs);
15402 break;
15403 case RDHWR:
b00c7218
YK
15404 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15405 gen_rdhwr(ctx, rt, rs, 0);
3c824109
NF
15406 break;
15407 case WSBH:
15408 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15409 break;
15410 case MULT:
9e8f441a 15411 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15412 mips32_op = OPC_MULT;
26135ead 15413 goto do_mul;
3c824109 15414 case MULTU:
9e8f441a 15415 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15416 mips32_op = OPC_MULTU;
26135ead 15417 goto do_mul;
3c824109 15418 case DIV:
9e8f441a 15419 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15420 mips32_op = OPC_DIV;
26135ead 15421 goto do_div;
3c824109 15422 case DIVU:
9e8f441a 15423 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15424 mips32_op = OPC_DIVU;
26135ead
RS
15425 goto do_div;
15426 do_div:
15427 check_insn(ctx, ISA_MIPS32);
15428 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15429 break;
3c824109 15430 case MADD:
9e8f441a 15431 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15432 mips32_op = OPC_MADD;
26135ead 15433 goto do_mul;
3c824109 15434 case MADDU:
9e8f441a 15435 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15436 mips32_op = OPC_MADDU;
26135ead 15437 goto do_mul;
3c824109 15438 case MSUB:
9e8f441a 15439 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15440 mips32_op = OPC_MSUB;
26135ead 15441 goto do_mul;
3c824109 15442 case MSUBU:
9e8f441a 15443 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15444 mips32_op = OPC_MSUBU;
26135ead 15445 do_mul:
d75c135e 15446 check_insn(ctx, ISA_MIPS32);
a1fc6246 15447 gen_muldiv(ctx, mips32_op, 0, rs, rt);
3c824109
NF
15448 break;
15449 default:
15450 goto pool32axf_invalid;
15451 }
15452 break;
15453 case 0x34:
15454 switch (minor) {
15455 case MFC2:
15456 case MTC2:
15457 case MFHC2:
15458 case MTHC2:
15459 case CFC2:
15460 case CTC2:
15461 generate_exception_err(ctx, EXCP_CpU, 2);
15462 break;
15463 default:
15464 goto pool32axf_invalid;
15465 }
15466 break;
15467 case 0x3c:
15468 switch (minor) {
65935f07
YK
15469 case JALR: /* JALRC */
15470 case JALR_HB: /* JALRC_HB */
15471 if (ctx->insn_flags & ISA_MIPS32R6) {
15472 /* JALRC, JALRC_HB */
15473 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15474 } else {
15475 /* JALR, JALR_HB */
15476 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15477 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15478 }
3c824109
NF
15479 break;
15480 case JALRS:
15481 case JALRS_HB:
9e8f441a 15482 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15483 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15484 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
15485 break;
15486 default:
15487 goto pool32axf_invalid;
15488 }
15489 break;
15490 case 0x05:
15491 switch (minor) {
15492 case RDPGPR:
2e15497c 15493 check_cp0_enabled(ctx);
d75c135e 15494 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 15495 gen_load_srsgpr(rs, rt);
3c824109
NF
15496 break;
15497 case WRPGPR:
2e15497c 15498 check_cp0_enabled(ctx);
d75c135e 15499 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 15500 gen_store_srsgpr(rs, rt);
3c824109
NF
15501 break;
15502 default:
15503 goto pool32axf_invalid;
15504 }
15505 break;
15506#ifndef CONFIG_USER_ONLY
15507 case 0x0d:
15508 switch (minor) {
15509 case TLBP:
15510 mips32_op = OPC_TLBP;
15511 goto do_cp0;
15512 case TLBR:
15513 mips32_op = OPC_TLBR;
15514 goto do_cp0;
15515 case TLBWI:
15516 mips32_op = OPC_TLBWI;
15517 goto do_cp0;
15518 case TLBWR:
15519 mips32_op = OPC_TLBWR;
15520 goto do_cp0;
e60ec063
YK
15521 case TLBINV:
15522 mips32_op = OPC_TLBINV;
15523 goto do_cp0;
15524 case TLBINVF:
15525 mips32_op = OPC_TLBINVF;
15526 goto do_cp0;
3c824109
NF
15527 case WAIT:
15528 mips32_op = OPC_WAIT;
15529 goto do_cp0;
15530 case DERET:
15531 mips32_op = OPC_DERET;
15532 goto do_cp0;
15533 case ERET:
15534 mips32_op = OPC_ERET;
15535 do_cp0:
15536 gen_cp0(env, ctx, mips32_op, rt, rs);
15537 break;
15538 default:
15539 goto pool32axf_invalid;
15540 }
15541 break;
15542 case 0x1d:
15543 switch (minor) {
15544 case DI:
2e15497c 15545 check_cp0_enabled(ctx);
3c824109
NF
15546 {
15547 TCGv t0 = tcg_temp_new();
15548
15549 save_cpu_state(ctx, 1);
895c2d04 15550 gen_helper_di(t0, cpu_env);
3c824109
NF
15551 gen_store_gpr(t0, rs);
15552 /* Stop translation as we may have switched the execution mode */
eeb3bba8 15553 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
15554 tcg_temp_free(t0);
15555 }
15556 break;
15557 case EI:
2e15497c 15558 check_cp0_enabled(ctx);
3c824109
NF
15559 {
15560 TCGv t0 = tcg_temp_new();
15561
15562 save_cpu_state(ctx, 1);
895c2d04 15563 gen_helper_ei(t0, cpu_env);
3c824109 15564 gen_store_gpr(t0, rs);
b28425ba 15565 /* DISAS_STOP isn't sufficient, we need to ensure we break out
b74cddcb 15566 of translated code to check for pending interrupts. */
eeb3bba8
EC
15567 gen_save_pc(ctx->base.pc_next + 4);
15568 ctx->base.is_jmp = DISAS_EXIT;
3c824109
NF
15569 tcg_temp_free(t0);
15570 }
15571 break;
15572 default:
15573 goto pool32axf_invalid;
15574 }
15575 break;
15576#endif
15577 case 0x2d:
15578 switch (minor) {
15579 case SYNC:
d208ac0c 15580 gen_sync(extract32(ctx->opcode, 16, 5));
3c824109
NF
15581 break;
15582 case SYSCALL:
9c708c7f 15583 generate_exception_end(ctx, EXCP_SYSCALL);
3c824109
NF
15584 break;
15585 case SDBBP:
3b3c1694
LA
15586 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15587 gen_helper_do_semihosting(cpu_env);
15588 } else {
15589 check_insn(ctx, ISA_MIPS32);
e0332095 15590 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 15591 generate_exception_end(ctx, EXCP_RI);
e0332095 15592 } else {
9c708c7f 15593 generate_exception_end(ctx, EXCP_DBp);
e0332095 15594 }
3b3c1694 15595 }
3c824109
NF
15596 break;
15597 default:
15598 goto pool32axf_invalid;
15599 }
15600 break;
a1fc6246 15601 case 0x01:
26135ead 15602 switch (minor & 3) {
a1fc6246 15603 case MFHI_ACC:
26135ead 15604 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
3c824109 15605 break;
a1fc6246 15606 case MFLO_ACC:
26135ead 15607 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
3c824109 15608 break;
a1fc6246 15609 case MTHI_ACC:
26135ead 15610 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
3c824109 15611 break;
a1fc6246 15612 case MTLO_ACC:
26135ead 15613 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
3c824109
NF
15614 break;
15615 default:
15616 goto pool32axf_invalid;
15617 }
15618 break;
a1fc6246 15619 case 0x35:
9e8f441a 15620 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a1fc6246
LA
15621 switch (minor) {
15622 case MFHI32:
15623 gen_HILO(ctx, OPC_MFHI, 0, rs);
15624 break;
15625 case MFLO32:
15626 gen_HILO(ctx, OPC_MFLO, 0, rs);
15627 break;
15628 case MTHI32:
15629 gen_HILO(ctx, OPC_MTHI, 0, rs);
15630 break;
15631 case MTLO32:
15632 gen_HILO(ctx, OPC_MTLO, 0, rs);
15633 break;
15634 default:
15635 goto pool32axf_invalid;
15636 }
15637 break;
3c824109
NF
15638 default:
15639 pool32axf_invalid:
15640 MIPS_INVAL("pool32axf");
9c708c7f 15641 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15642 break;
15643 }
15644}
15645
15646/* Values for microMIPS fmt field. Variable-width, depending on which
15647 formats the instruction supports. */
15648
15649enum {
15650 FMT_SD_S = 0,
15651 FMT_SD_D = 1,
15652
15653 FMT_SDPS_S = 0,
15654 FMT_SDPS_D = 1,
15655 FMT_SDPS_PS = 2,
15656
15657 FMT_SWL_S = 0,
15658 FMT_SWL_W = 1,
15659 FMT_SWL_L = 2,
15660
15661 FMT_DWL_D = 0,
15662 FMT_DWL_W = 1,
15663 FMT_DWL_L = 2
15664};
15665
d75c135e 15666static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
3c824109
NF
15667{
15668 int extension = (ctx->opcode >> 6) & 0x3ff;
15669 uint32_t mips32_op;
15670
15671#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
15672#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
15673#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
15674
15675 switch (extension) {
15676 case FLOAT_1BIT_FMT(CFC1, 0):
15677 mips32_op = OPC_CFC1;
15678 goto do_cp1;
15679 case FLOAT_1BIT_FMT(CTC1, 0):
15680 mips32_op = OPC_CTC1;
15681 goto do_cp1;
15682 case FLOAT_1BIT_FMT(MFC1, 0):
15683 mips32_op = OPC_MFC1;
15684 goto do_cp1;
15685 case FLOAT_1BIT_FMT(MTC1, 0):
15686 mips32_op = OPC_MTC1;
15687 goto do_cp1;
15688 case FLOAT_1BIT_FMT(MFHC1, 0):
15689 mips32_op = OPC_MFHC1;
15690 goto do_cp1;
15691 case FLOAT_1BIT_FMT(MTHC1, 0):
15692 mips32_op = OPC_MTHC1;
15693 do_cp1:
15694 gen_cp1(ctx, mips32_op, rt, rs);
15695 break;
15696
15697 /* Reciprocal square root */
15698 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15699 mips32_op = OPC_RSQRT_S;
15700 goto do_unaryfp;
15701 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15702 mips32_op = OPC_RSQRT_D;
15703 goto do_unaryfp;
15704
15705 /* Square root */
15706 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15707 mips32_op = OPC_SQRT_S;
15708 goto do_unaryfp;
15709 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15710 mips32_op = OPC_SQRT_D;
15711 goto do_unaryfp;
15712
15713 /* Reciprocal */
15714 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15715 mips32_op = OPC_RECIP_S;
15716 goto do_unaryfp;
15717 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15718 mips32_op = OPC_RECIP_D;
15719 goto do_unaryfp;
15720
15721 /* Floor */
15722 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15723 mips32_op = OPC_FLOOR_L_S;
15724 goto do_unaryfp;
15725 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15726 mips32_op = OPC_FLOOR_L_D;
15727 goto do_unaryfp;
15728 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15729 mips32_op = OPC_FLOOR_W_S;
15730 goto do_unaryfp;
15731 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15732 mips32_op = OPC_FLOOR_W_D;
15733 goto do_unaryfp;
15734
15735 /* Ceiling */
15736 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15737 mips32_op = OPC_CEIL_L_S;
15738 goto do_unaryfp;
15739 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15740 mips32_op = OPC_CEIL_L_D;
15741 goto do_unaryfp;
15742 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15743 mips32_op = OPC_CEIL_W_S;
15744 goto do_unaryfp;
15745 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15746 mips32_op = OPC_CEIL_W_D;
15747 goto do_unaryfp;
15748
15749 /* Truncation */
15750 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15751 mips32_op = OPC_TRUNC_L_S;
15752 goto do_unaryfp;
15753 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15754 mips32_op = OPC_TRUNC_L_D;
15755 goto do_unaryfp;
15756 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15757 mips32_op = OPC_TRUNC_W_S;
15758 goto do_unaryfp;
15759 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15760 mips32_op = OPC_TRUNC_W_D;
15761 goto do_unaryfp;
15762
15763 /* Round */
15764 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15765 mips32_op = OPC_ROUND_L_S;
15766 goto do_unaryfp;
15767 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15768 mips32_op = OPC_ROUND_L_D;
15769 goto do_unaryfp;
15770 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15771 mips32_op = OPC_ROUND_W_S;
15772 goto do_unaryfp;
15773 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15774 mips32_op = OPC_ROUND_W_D;
15775 goto do_unaryfp;
15776
15777 /* Integer to floating-point conversion */
15778 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15779 mips32_op = OPC_CVT_L_S;
15780 goto do_unaryfp;
15781 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15782 mips32_op = OPC_CVT_L_D;
15783 goto do_unaryfp;
15784 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15785 mips32_op = OPC_CVT_W_S;
15786 goto do_unaryfp;
15787 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15788 mips32_op = OPC_CVT_W_D;
15789 goto do_unaryfp;
15790
15791 /* Paired-foo conversions */
15792 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15793 mips32_op = OPC_CVT_S_PL;
15794 goto do_unaryfp;
15795 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15796 mips32_op = OPC_CVT_S_PU;
15797 goto do_unaryfp;
15798 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15799 mips32_op = OPC_CVT_PW_PS;
15800 goto do_unaryfp;
15801 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15802 mips32_op = OPC_CVT_PS_PW;
15803 goto do_unaryfp;
15804
15805 /* Floating-point moves */
15806 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15807 mips32_op = OPC_MOV_S;
15808 goto do_unaryfp;
15809 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15810 mips32_op = OPC_MOV_D;
15811 goto do_unaryfp;
15812 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15813 mips32_op = OPC_MOV_PS;
15814 goto do_unaryfp;
15815
15816 /* Absolute value */
15817 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15818 mips32_op = OPC_ABS_S;
15819 goto do_unaryfp;
15820 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15821 mips32_op = OPC_ABS_D;
15822 goto do_unaryfp;
15823 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15824 mips32_op = OPC_ABS_PS;
15825 goto do_unaryfp;
15826
15827 /* Negation */
15828 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15829 mips32_op = OPC_NEG_S;
15830 goto do_unaryfp;
15831 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15832 mips32_op = OPC_NEG_D;
15833 goto do_unaryfp;
15834 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15835 mips32_op = OPC_NEG_PS;
15836 goto do_unaryfp;
15837
15838 /* Reciprocal square root step */
15839 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15840 mips32_op = OPC_RSQRT1_S;
15841 goto do_unaryfp;
15842 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15843 mips32_op = OPC_RSQRT1_D;
15844 goto do_unaryfp;
15845 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15846 mips32_op = OPC_RSQRT1_PS;
15847 goto do_unaryfp;
15848
15849 /* Reciprocal step */
15850 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15851 mips32_op = OPC_RECIP1_S;
15852 goto do_unaryfp;
15853 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15854 mips32_op = OPC_RECIP1_S;
15855 goto do_unaryfp;
15856 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15857 mips32_op = OPC_RECIP1_PS;
15858 goto do_unaryfp;
15859
15860 /* Conversions from double */
15861 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15862 mips32_op = OPC_CVT_D_S;
15863 goto do_unaryfp;
15864 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15865 mips32_op = OPC_CVT_D_W;
15866 goto do_unaryfp;
15867 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15868 mips32_op = OPC_CVT_D_L;
15869 goto do_unaryfp;
15870
15871 /* Conversions from single */
15872 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15873 mips32_op = OPC_CVT_S_D;
15874 goto do_unaryfp;
15875 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15876 mips32_op = OPC_CVT_S_W;
15877 goto do_unaryfp;
15878 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15879 mips32_op = OPC_CVT_S_L;
15880 do_unaryfp:
15881 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15882 break;
15883
15884 /* Conditional moves on floating-point codes */
15885 case COND_FLOAT_MOV(MOVT, 0):
15886 case COND_FLOAT_MOV(MOVT, 1):
15887 case COND_FLOAT_MOV(MOVT, 2):
15888 case COND_FLOAT_MOV(MOVT, 3):
15889 case COND_FLOAT_MOV(MOVT, 4):
15890 case COND_FLOAT_MOV(MOVT, 5):
15891 case COND_FLOAT_MOV(MOVT, 6):
15892 case COND_FLOAT_MOV(MOVT, 7):
9e8f441a 15893 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15894 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15895 break;
15896 case COND_FLOAT_MOV(MOVF, 0):
15897 case COND_FLOAT_MOV(MOVF, 1):
15898 case COND_FLOAT_MOV(MOVF, 2):
15899 case COND_FLOAT_MOV(MOVF, 3):
15900 case COND_FLOAT_MOV(MOVF, 4):
15901 case COND_FLOAT_MOV(MOVF, 5):
15902 case COND_FLOAT_MOV(MOVF, 6):
15903 case COND_FLOAT_MOV(MOVF, 7):
9e8f441a 15904 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15905 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15906 break;
15907 default:
15908 MIPS_INVAL("pool32fxf");
9c708c7f 15909 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15910 break;
15911 }
15912}
15913
f60eeb0c 15914static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
15915{
15916 int32_t offset;
15917 uint16_t insn;
15918 int rt, rs, rd, rr;
15919 int16_t imm;
8fffc646 15920 uint32_t op, minor, minor2, mips32_op;
3c824109
NF
15921 uint32_t cond, fmt, cc;
15922
eeb3bba8 15923 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
3c824109
NF
15924 ctx->opcode = (ctx->opcode << 16) | insn;
15925
15926 rt = (ctx->opcode >> 21) & 0x1f;
15927 rs = (ctx->opcode >> 16) & 0x1f;
15928 rd = (ctx->opcode >> 11) & 0x1f;
15929 rr = (ctx->opcode >> 6) & 0x1f;
15930 imm = (int16_t) ctx->opcode;
15931
15932 op = (ctx->opcode >> 26) & 0x3f;
15933 switch (op) {
15934 case POOL32A:
15935 minor = ctx->opcode & 0x3f;
15936 switch (minor) {
15937 case 0x00:
15938 minor = (ctx->opcode >> 6) & 0xf;
15939 switch (minor) {
15940 case SLL32:
15941 mips32_op = OPC_SLL;
15942 goto do_shifti;
15943 case SRA:
15944 mips32_op = OPC_SRA;
15945 goto do_shifti;
15946 case SRL32:
15947 mips32_op = OPC_SRL;
15948 goto do_shifti;
15949 case ROTR:
15950 mips32_op = OPC_ROTR;
15951 do_shifti:
d75c135e 15952 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
3c824109 15953 break;
e0332095
YK
15954 case SELEQZ:
15955 check_insn(ctx, ISA_MIPS32R6);
15956 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15957 break;
15958 case SELNEZ:
15959 check_insn(ctx, ISA_MIPS32R6);
15960 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15961 break;
b00c7218
YK
15962 case R6_RDHWR:
15963 check_insn(ctx, ISA_MIPS32R6);
15964 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15965 break;
3c824109
NF
15966 default:
15967 goto pool32a_invalid;
15968 }
15969 break;
15970 case 0x10:
15971 minor = (ctx->opcode >> 6) & 0xf;
15972 switch (minor) {
15973 /* Arithmetic */
15974 case ADD:
15975 mips32_op = OPC_ADD;
15976 goto do_arith;
15977 case ADDU32:
15978 mips32_op = OPC_ADDU;
15979 goto do_arith;
15980 case SUB:
15981 mips32_op = OPC_SUB;
15982 goto do_arith;
15983 case SUBU32:
15984 mips32_op = OPC_SUBU;
15985 goto do_arith;
15986 case MUL:
9e8f441a 15987 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15988 mips32_op = OPC_MUL;
15989 do_arith:
d75c135e 15990 gen_arith(ctx, mips32_op, rd, rs, rt);
3c824109
NF
15991 break;
15992 /* Shifts */
15993 case SLLV:
15994 mips32_op = OPC_SLLV;
15995 goto do_shift;
15996 case SRLV:
15997 mips32_op = OPC_SRLV;
15998 goto do_shift;
15999 case SRAV:
16000 mips32_op = OPC_SRAV;
16001 goto do_shift;
16002 case ROTRV:
16003 mips32_op = OPC_ROTRV;
16004 do_shift:
d75c135e 16005 gen_shift(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16006 break;
16007 /* Logical operations */
16008 case AND:
16009 mips32_op = OPC_AND;
16010 goto do_logic;
16011 case OR32:
16012 mips32_op = OPC_OR;
16013 goto do_logic;
16014 case NOR:
16015 mips32_op = OPC_NOR;
16016 goto do_logic;
16017 case XOR32:
16018 mips32_op = OPC_XOR;
16019 do_logic:
d75c135e 16020 gen_logic(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16021 break;
16022 /* Set less than */
16023 case SLT:
16024 mips32_op = OPC_SLT;
16025 goto do_slt;
16026 case SLTU:
16027 mips32_op = OPC_SLTU;
16028 do_slt:
d75c135e 16029 gen_slt(ctx, mips32_op, rd, rs, rt);
3c824109
NF
16030 break;
16031 default:
16032 goto pool32a_invalid;
16033 }
16034 break;
16035 case 0x18:
16036 minor = (ctx->opcode >> 6) & 0xf;
16037 switch (minor) {
16038 /* Conditional moves */
e0332095
YK
16039 case MOVN: /* MUL */
16040 if (ctx->insn_flags & ISA_MIPS32R6) {
16041 /* MUL */
16042 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16043 } else {
16044 /* MOVN */
16045 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16046 }
16047 break;
16048 case MOVZ: /* MUH */
16049 if (ctx->insn_flags & ISA_MIPS32R6) {
16050 /* MUH */
16051 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16052 } else {
16053 /* MOVZ */
16054 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16055 }
16056 break;
16057 case MULU:
16058 check_insn(ctx, ISA_MIPS32R6);
16059 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16060 break;
16061 case MUHU:
16062 check_insn(ctx, ISA_MIPS32R6);
16063 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16064 break;
16065 case LWXS: /* DIV */
16066 if (ctx->insn_flags & ISA_MIPS32R6) {
16067 /* DIV */
16068 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16069 } else {
16070 /* LWXS */
16071 gen_ldxs(ctx, rs, rt, rd);
16072 }
16073 break;
16074 case MOD:
16075 check_insn(ctx, ISA_MIPS32R6);
16076 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16077 break;
16078 case R6_DIVU:
16079 check_insn(ctx, ISA_MIPS32R6);
16080 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
3c824109 16081 break;
e0332095
YK
16082 case MODU:
16083 check_insn(ctx, ISA_MIPS32R6);
16084 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
3c824109
NF
16085 break;
16086 default:
16087 goto pool32a_invalid;
16088 }
16089 break;
16090 case INS:
16091 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16092 return;
e0332095
YK
16093 case LSA:
16094 check_insn(ctx, ISA_MIPS32R6);
16095 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16096 extract32(ctx->opcode, 9, 2));
16097 break;
16098 case ALIGN:
16099 check_insn(ctx, ISA_MIPS32R6);
821f2008 16100 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
e0332095 16101 break;
3c824109
NF
16102 case EXT:
16103 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16104 return;
16105 case POOL32AXF:
240ce26a 16106 gen_pool32axf(env, ctx, rt, rs);
3c824109 16107 break;
dbd8af98 16108 case BREAK32:
9c708c7f 16109 generate_exception_end(ctx, EXCP_BREAK);
3c824109 16110 break;
bb238210
YK
16111 case SIGRIE:
16112 check_insn(ctx, ISA_MIPS32R6);
16113 generate_exception_end(ctx, EXCP_RI);
16114 break;
3c824109
NF
16115 default:
16116 pool32a_invalid:
16117 MIPS_INVAL("pool32a");
9c708c7f 16118 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16119 break;
16120 }
16121 break;
16122 case POOL32B:
16123 minor = (ctx->opcode >> 12) & 0xf;
16124 switch (minor) {
16125 case CACHE:
2e15497c 16126 check_cp0_enabled(ctx);
0d74a222
LA
16127 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16128 gen_cache_operation(ctx, rt, rs, imm);
16129 }
3c824109
NF
16130 break;
16131 case LWC2:
16132 case SWC2:
16133 /* COP2: Not implemented. */
16134 generate_exception_err(ctx, EXCP_CpU, 2);
16135 break;
3c824109
NF
16136#ifdef TARGET_MIPS64
16137 case LDP:
16138 case SDP:
d9224450
MR
16139 check_insn(ctx, ISA_MIPS3);
16140 check_mips_64(ctx);
3c824109 16141#endif
146dd620 16142 /* fall through */
d9224450
MR
16143 case LWP:
16144 case SWP:
3c824109
NF
16145 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16146 break;
3c824109
NF
16147#ifdef TARGET_MIPS64
16148 case LDM:
16149 case SDM:
d9224450
MR
16150 check_insn(ctx, ISA_MIPS3);
16151 check_mips_64(ctx);
3c824109 16152#endif
146dd620 16153 /* fall through */
d9224450
MR
16154 case LWM32:
16155 case SWM32:
3c824109
NF
16156 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16157 break;
16158 default:
16159 MIPS_INVAL("pool32b");
9c708c7f 16160 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16161 break;
16162 }
16163 break;
16164 case POOL32F:
5ab5c041 16165 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3c824109
NF
16166 minor = ctx->opcode & 0x3f;
16167 check_cp1_enabled(ctx);
16168 switch (minor) {
16169 case ALNV_PS:
9e8f441a 16170 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16171 mips32_op = OPC_ALNV_PS;
16172 goto do_madd;
16173 case MADD_S:
9e8f441a 16174 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16175 mips32_op = OPC_MADD_S;
16176 goto do_madd;
16177 case MADD_D:
9e8f441a 16178 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16179 mips32_op = OPC_MADD_D;
16180 goto do_madd;
16181 case MADD_PS:
9e8f441a 16182 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16183 mips32_op = OPC_MADD_PS;
16184 goto do_madd;
16185 case MSUB_S:
9e8f441a 16186 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16187 mips32_op = OPC_MSUB_S;
16188 goto do_madd;
16189 case MSUB_D:
9e8f441a 16190 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16191 mips32_op = OPC_MSUB_D;
16192 goto do_madd;
16193 case MSUB_PS:
9e8f441a 16194 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16195 mips32_op = OPC_MSUB_PS;
16196 goto do_madd;
16197 case NMADD_S:
9e8f441a 16198 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16199 mips32_op = OPC_NMADD_S;
16200 goto do_madd;
16201 case NMADD_D:
9e8f441a 16202 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16203 mips32_op = OPC_NMADD_D;
16204 goto do_madd;
16205 case NMADD_PS:
9e8f441a 16206 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16207 mips32_op = OPC_NMADD_PS;
16208 goto do_madd;
16209 case NMSUB_S:
9e8f441a 16210 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16211 mips32_op = OPC_NMSUB_S;
16212 goto do_madd;
16213 case NMSUB_D:
9e8f441a 16214 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16215 mips32_op = OPC_NMSUB_D;
16216 goto do_madd;
16217 case NMSUB_PS:
9e8f441a 16218 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16219 mips32_op = OPC_NMSUB_PS;
16220 do_madd:
16221 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16222 break;
16223 case CABS_COND_FMT:
9e8f441a 16224 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16225 cond = (ctx->opcode >> 6) & 0xf;
16226 cc = (ctx->opcode >> 13) & 0x7;
16227 fmt = (ctx->opcode >> 10) & 0x3;
16228 switch (fmt) {
16229 case 0x0:
16230 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16231 break;
16232 case 0x1:
16233 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16234 break;
16235 case 0x2:
16236 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16237 break;
16238 default:
16239 goto pool32f_invalid;
16240 }
16241 break;
16242 case C_COND_FMT:
9e8f441a 16243 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16244 cond = (ctx->opcode >> 6) & 0xf;
16245 cc = (ctx->opcode >> 13) & 0x7;
16246 fmt = (ctx->opcode >> 10) & 0x3;
16247 switch (fmt) {
16248 case 0x0:
16249 gen_cmp_s(ctx, cond, rt, rs, cc);
16250 break;
16251 case 0x1:
16252 gen_cmp_d(ctx, cond, rt, rs, cc);
16253 break;
16254 case 0x2:
16255 gen_cmp_ps(ctx, cond, rt, rs, cc);
16256 break;
16257 default:
16258 goto pool32f_invalid;
16259 }
16260 break;
2a24a7ba
YK
16261 case CMP_CONDN_S:
16262 check_insn(ctx, ISA_MIPS32R6);
16263 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16264 break;
16265 case CMP_CONDN_D:
16266 check_insn(ctx, ISA_MIPS32R6);
16267 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16268 break;
3c824109 16269 case POOL32FXF:
d75c135e 16270 gen_pool32fxf(ctx, rt, rs);
3c824109
NF
16271 break;
16272 case 0x00:
16273 /* PLL foo */
16274 switch ((ctx->opcode >> 6) & 0x7) {
16275 case PLL_PS:
16276 mips32_op = OPC_PLL_PS;
16277 goto do_ps;
16278 case PLU_PS:
16279 mips32_op = OPC_PLU_PS;
16280 goto do_ps;
16281 case PUL_PS:
16282 mips32_op = OPC_PUL_PS;
16283 goto do_ps;
16284 case PUU_PS:
16285 mips32_op = OPC_PUU_PS;
16286 goto do_ps;
16287 case CVT_PS_S:
9e8f441a 16288 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16289 mips32_op = OPC_CVT_PS_S;
16290 do_ps:
16291 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16292 break;
16293 default:
16294 goto pool32f_invalid;
16295 }
16296 break;
2a24a7ba
YK
16297 case MIN_FMT:
16298 check_insn(ctx, ISA_MIPS32R6);
16299 switch ((ctx->opcode >> 9) & 0x3) {
16300 case FMT_SDPS_S:
16301 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16302 break;
16303 case FMT_SDPS_D:
16304 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16305 break;
16306 default:
16307 goto pool32f_invalid;
16308 }
16309 break;
3c824109
NF
16310 case 0x08:
16311 /* [LS][WDU]XC1 */
16312 switch ((ctx->opcode >> 6) & 0x7) {
16313 case LWXC1:
9e8f441a 16314 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16315 mips32_op = OPC_LWXC1;
16316 goto do_ldst_cp1;
16317 case SWXC1:
9e8f441a 16318 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16319 mips32_op = OPC_SWXC1;
16320 goto do_ldst_cp1;
16321 case LDXC1:
9e8f441a 16322 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16323 mips32_op = OPC_LDXC1;
16324 goto do_ldst_cp1;
16325 case SDXC1:
9e8f441a 16326 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16327 mips32_op = OPC_SDXC1;
16328 goto do_ldst_cp1;
16329 case LUXC1:
9e8f441a 16330 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16331 mips32_op = OPC_LUXC1;
16332 goto do_ldst_cp1;
16333 case SUXC1:
9e8f441a 16334 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16335 mips32_op = OPC_SUXC1;
16336 do_ldst_cp1:
16337 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16338 break;
16339 default:
16340 goto pool32f_invalid;
16341 }
16342 break;
2a24a7ba
YK
16343 case MAX_FMT:
16344 check_insn(ctx, ISA_MIPS32R6);
16345 switch ((ctx->opcode >> 9) & 0x3) {
16346 case FMT_SDPS_S:
16347 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16348 break;
16349 case FMT_SDPS_D:
16350 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16351 break;
16352 default:
16353 goto pool32f_invalid;
16354 }
16355 break;
3c824109
NF
16356 case 0x18:
16357 /* 3D insns */
9e8f441a 16358 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16359 fmt = (ctx->opcode >> 9) & 0x3;
16360 switch ((ctx->opcode >> 6) & 0x7) {
16361 case RSQRT2_FMT:
16362 switch (fmt) {
16363 case FMT_SDPS_S:
16364 mips32_op = OPC_RSQRT2_S;
16365 goto do_3d;
16366 case FMT_SDPS_D:
16367 mips32_op = OPC_RSQRT2_D;
16368 goto do_3d;
16369 case FMT_SDPS_PS:
16370 mips32_op = OPC_RSQRT2_PS;
16371 goto do_3d;
16372 default:
16373 goto pool32f_invalid;
16374 }
16375 break;
16376 case RECIP2_FMT:
16377 switch (fmt) {
16378 case FMT_SDPS_S:
16379 mips32_op = OPC_RECIP2_S;
16380 goto do_3d;
16381 case FMT_SDPS_D:
16382 mips32_op = OPC_RECIP2_D;
16383 goto do_3d;
16384 case FMT_SDPS_PS:
16385 mips32_op = OPC_RECIP2_PS;
16386 goto do_3d;
16387 default:
16388 goto pool32f_invalid;
16389 }
16390 break;
16391 case ADDR_PS:
16392 mips32_op = OPC_ADDR_PS;
16393 goto do_3d;
16394 case MULR_PS:
16395 mips32_op = OPC_MULR_PS;
16396 do_3d:
16397 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16398 break;
16399 default:
16400 goto pool32f_invalid;
16401 }
16402 break;
16403 case 0x20:
2a24a7ba 16404 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
3c824109
NF
16405 cc = (ctx->opcode >> 13) & 0x7;
16406 fmt = (ctx->opcode >> 9) & 0x3;
16407 switch ((ctx->opcode >> 6) & 0x7) {
2a24a7ba
YK
16408 case MOVF_FMT: /* RINT_FMT */
16409 if (ctx->insn_flags & ISA_MIPS32R6) {
16410 /* RINT_FMT */
16411 switch (fmt) {
16412 case FMT_SDPS_S:
16413 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16414 break;
16415 case FMT_SDPS_D:
16416 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16417 break;
16418 default:
16419 goto pool32f_invalid;
16420 }
16421 } else {
16422 /* MOVF_FMT */
16423 switch (fmt) {
16424 case FMT_SDPS_S:
16425 gen_movcf_s(ctx, rs, rt, cc, 0);
16426 break;
16427 case FMT_SDPS_D:
16428 gen_movcf_d(ctx, rs, rt, cc, 0);
16429 break;
16430 case FMT_SDPS_PS:
16431 check_ps(ctx);
16432 gen_movcf_ps(ctx, rs, rt, cc, 0);
16433 break;
16434 default:
16435 goto pool32f_invalid;
16436 }
3c824109
NF
16437 }
16438 break;
2a24a7ba
YK
16439 case MOVT_FMT: /* CLASS_FMT */
16440 if (ctx->insn_flags & ISA_MIPS32R6) {
16441 /* CLASS_FMT */
16442 switch (fmt) {
16443 case FMT_SDPS_S:
16444 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16445 break;
16446 case FMT_SDPS_D:
16447 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16448 break;
16449 default:
16450 goto pool32f_invalid;
16451 }
16452 } else {
16453 /* MOVT_FMT */
16454 switch (fmt) {
16455 case FMT_SDPS_S:
16456 gen_movcf_s(ctx, rs, rt, cc, 1);
16457 break;
16458 case FMT_SDPS_D:
16459 gen_movcf_d(ctx, rs, rt, cc, 1);
16460 break;
16461 case FMT_SDPS_PS:
16462 check_ps(ctx);
16463 gen_movcf_ps(ctx, rs, rt, cc, 1);
16464 break;
16465 default:
16466 goto pool32f_invalid;
16467 }
3c824109
NF
16468 }
16469 break;
16470 case PREFX:
9e8f441a 16471 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16472 break;
16473 default:
16474 goto pool32f_invalid;
16475 }
16476 break;
16477#define FINSN_3ARG_SDPS(prfx) \
16478 switch ((ctx->opcode >> 8) & 0x3) { \
16479 case FMT_SDPS_S: \
16480 mips32_op = OPC_##prfx##_S; \
16481 goto do_fpop; \
16482 case FMT_SDPS_D: \
16483 mips32_op = OPC_##prfx##_D; \
16484 goto do_fpop; \
16485 case FMT_SDPS_PS: \
e29c9628 16486 check_ps(ctx); \
3c824109
NF
16487 mips32_op = OPC_##prfx##_PS; \
16488 goto do_fpop; \
16489 default: \
16490 goto pool32f_invalid; \
16491 }
2a24a7ba
YK
16492 case MINA_FMT:
16493 check_insn(ctx, ISA_MIPS32R6);
16494 switch ((ctx->opcode >> 9) & 0x3) {
16495 case FMT_SDPS_S:
16496 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16497 break;
16498 case FMT_SDPS_D:
16499 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16500 break;
16501 default:
16502 goto pool32f_invalid;
16503 }
16504 break;
16505 case MAXA_FMT:
16506 check_insn(ctx, ISA_MIPS32R6);
16507 switch ((ctx->opcode >> 9) & 0x3) {
16508 case FMT_SDPS_S:
16509 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16510 break;
16511 case FMT_SDPS_D:
16512 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16513 break;
16514 default:
16515 goto pool32f_invalid;
16516 }
16517 break;
3c824109
NF
16518 case 0x30:
16519 /* regular FP ops */
16520 switch ((ctx->opcode >> 6) & 0x3) {
16521 case ADD_FMT:
16522 FINSN_3ARG_SDPS(ADD);
16523 break;
16524 case SUB_FMT:
16525 FINSN_3ARG_SDPS(SUB);
16526 break;
16527 case MUL_FMT:
16528 FINSN_3ARG_SDPS(MUL);
16529 break;
16530 case DIV_FMT:
16531 fmt = (ctx->opcode >> 8) & 0x3;
16532 if (fmt == 1) {
16533 mips32_op = OPC_DIV_D;
16534 } else if (fmt == 0) {
16535 mips32_op = OPC_DIV_S;
16536 } else {
16537 goto pool32f_invalid;
16538 }
16539 goto do_fpop;
16540 default:
16541 goto pool32f_invalid;
16542 }
16543 break;
16544 case 0x38:
16545 /* cmovs */
2a24a7ba 16546 switch ((ctx->opcode >> 6) & 0x7) {
fdac60cd 16547 case MOVN_FMT: /* SELEQZ_FMT */
2a24a7ba 16548 if (ctx->insn_flags & ISA_MIPS32R6) {
fdac60cd 16549 /* SELEQZ_FMT */
2a24a7ba
YK
16550 switch ((ctx->opcode >> 9) & 0x3) {
16551 case FMT_SDPS_S:
fdac60cd 16552 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
2a24a7ba
YK
16553 break;
16554 case FMT_SDPS_D:
fdac60cd 16555 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
2a24a7ba
YK
16556 break;
16557 default:
16558 goto pool32f_invalid;
16559 }
16560 } else {
16561 /* MOVN_FMT */
16562 FINSN_3ARG_SDPS(MOVN);
16563 }
16564 break;
16565 case MOVN_FMT_04:
16566 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16567 FINSN_3ARG_SDPS(MOVN);
16568 break;
fdac60cd 16569 case MOVZ_FMT: /* SELNEZ_FMT */
2a24a7ba 16570 if (ctx->insn_flags & ISA_MIPS32R6) {
fdac60cd 16571 /* SELNEZ_FMT */
2a24a7ba
YK
16572 switch ((ctx->opcode >> 9) & 0x3) {
16573 case FMT_SDPS_S:
fdac60cd 16574 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
2a24a7ba
YK
16575 break;
16576 case FMT_SDPS_D:
fdac60cd 16577 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
2a24a7ba
YK
16578 break;
16579 default:
16580 goto pool32f_invalid;
16581 }
16582 } else {
16583 /* MOVZ_FMT */
16584 FINSN_3ARG_SDPS(MOVZ);
16585 }
16586 break;
16587 case MOVZ_FMT_05:
16588 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16589 FINSN_3ARG_SDPS(MOVZ);
16590 break;
2a24a7ba
YK
16591 case SEL_FMT:
16592 check_insn(ctx, ISA_MIPS32R6);
16593 switch ((ctx->opcode >> 9) & 0x3) {
16594 case FMT_SDPS_S:
16595 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16596 break;
16597 case FMT_SDPS_D:
16598 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16599 break;
16600 default:
16601 goto pool32f_invalid;
16602 }
16603 break;
16604 case MADDF_FMT:
16605 check_insn(ctx, ISA_MIPS32R6);
16606 switch ((ctx->opcode >> 9) & 0x3) {
16607 case FMT_SDPS_S:
16608 mips32_op = OPC_MADDF_S;
16609 goto do_fpop;
16610 case FMT_SDPS_D:
16611 mips32_op = OPC_MADDF_D;
16612 goto do_fpop;
16613 default:
16614 goto pool32f_invalid;
16615 }
16616 break;
16617 case MSUBF_FMT:
16618 check_insn(ctx, ISA_MIPS32R6);
16619 switch ((ctx->opcode >> 9) & 0x3) {
16620 case FMT_SDPS_S:
16621 mips32_op = OPC_MSUBF_S;
16622 goto do_fpop;
16623 case FMT_SDPS_D:
16624 mips32_op = OPC_MSUBF_D;
16625 goto do_fpop;
16626 default:
16627 goto pool32f_invalid;
16628 }
16629 break;
3c824109
NF
16630 default:
16631 goto pool32f_invalid;
16632 }
16633 break;
16634 do_fpop:
16635 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16636 break;
16637 default:
16638 pool32f_invalid:
16639 MIPS_INVAL("pool32f");
9c708c7f 16640 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16641 break;
16642 }
16643 } else {
16644 generate_exception_err(ctx, EXCP_CpU, 1);
16645 }
16646 break;
16647 case POOL32I:
16648 minor = (ctx->opcode >> 21) & 0x1f;
16649 switch (minor) {
16650 case BLTZ:
9e8f441a 16651 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16652 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16653 break;
3c824109 16654 case BLTZAL:
9e8f441a 16655 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16656 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16657 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16658 break;
3c824109 16659 case BLTZALS:
9e8f441a 16660 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16661 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16662 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16663 break;
3c824109 16664 case BGEZ:
9e8f441a 16665 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16666 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16667 break;
3c824109 16668 case BGEZAL:
9e8f441a 16669 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16670 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16671 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16672 break;
3c824109 16673 case BGEZALS:
9e8f441a 16674 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16675 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16676 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16677 break;
3c824109 16678 case BLEZ:
9e8f441a 16679 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16680 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16681 break;
3c824109 16682 case BGTZ:
9e8f441a 16683 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103 16684 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
3c824109
NF
16685 break;
16686
16687 /* Traps */
65935f07
YK
16688 case TLTI: /* BC1EQZC */
16689 if (ctx->insn_flags & ISA_MIPS32R6) {
16690 /* BC1EQZC */
16691 check_cp1_enabled(ctx);
16692 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16693 } else {
16694 /* TLTI */
16695 mips32_op = OPC_TLTI;
16696 goto do_trapi;
16697 }
16698 break;
16699 case TGEI: /* BC1NEZC */
16700 if (ctx->insn_flags & ISA_MIPS32R6) {
16701 /* BC1NEZC */
16702 check_cp1_enabled(ctx);
16703 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16704 } else {
16705 /* TGEI */
16706 mips32_op = OPC_TGEI;
16707 goto do_trapi;
16708 }
16709 break;
3c824109 16710 case TLTIU:
9e8f441a 16711 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16712 mips32_op = OPC_TLTIU;
16713 goto do_trapi;
16714 case TGEIU:
9e8f441a 16715 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16716 mips32_op = OPC_TGEIU;
16717 goto do_trapi;
3b4a5489
YK
16718 case TNEI: /* SYNCI */
16719 if (ctx->insn_flags & ISA_MIPS32R6) {
16720 /* SYNCI */
16721 /* Break the TB to be able to sync copied instructions
16722 immediately */
eeb3bba8 16723 ctx->base.is_jmp = DISAS_STOP;
3b4a5489
YK
16724 } else {
16725 /* TNEI */
16726 mips32_op = OPC_TNEI;
16727 goto do_trapi;
16728 }
16729 break;
3c824109 16730 case TEQI:
9e8f441a 16731 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16732 mips32_op = OPC_TEQI;
16733 do_trapi:
16734 gen_trap(ctx, mips32_op, rs, -1, imm);
16735 break;
16736
16737 case BNEZC:
16738 case BEQZC:
9e8f441a 16739 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16740 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
b231c103 16741 4, rs, 0, imm << 1, 0);
3c824109
NF
16742 /* Compact branches don't have a delay slot, so just let
16743 the normal delay slot handling take us to the branch
16744 target. */
16745 break;
16746 case LUI:
9e8f441a 16747 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5e88759a 16748 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
3c824109
NF
16749 break;
16750 case SYNCI:
9e8f441a 16751 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a83bddd6
DZ
16752 /* Break the TB to be able to sync copied instructions
16753 immediately */
eeb3bba8 16754 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
16755 break;
16756 case BC2F:
16757 case BC2T:
9e8f441a 16758 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16759 /* COP2: Not implemented. */
16760 generate_exception_err(ctx, EXCP_CpU, 2);
16761 break;
16762 case BC1F:
9e8f441a 16763 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16764 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16765 goto do_cp1branch;
16766 case BC1T:
9e8f441a 16767 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16768 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16769 goto do_cp1branch;
16770 case BC1ANY4F:
9e8f441a 16771 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16772 mips32_op = OPC_BC1FANY4;
16773 goto do_cp1mips3d;
16774 case BC1ANY4T:
9e8f441a 16775 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16776 mips32_op = OPC_BC1TANY4;
16777 do_cp1mips3d:
16778 check_cop1x(ctx);
d75c135e 16779 check_insn(ctx, ASE_MIPS3D);
3c824109
NF
16780 /* Fall through */
16781 do_cp1branch:
272f458d
MR
16782 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16783 check_cp1_enabled(ctx);
16784 gen_compute_branch1(ctx, mips32_op,
16785 (ctx->opcode >> 18) & 0x7, imm << 1);
16786 } else {
16787 generate_exception_err(ctx, EXCP_CpU, 1);
16788 }
3c824109
NF
16789 break;
16790 case BPOSGE64:
16791 case BPOSGE32:
16792 /* MIPS DSP: not implemented */
16793 /* Fall through */
16794 default:
16795 MIPS_INVAL("pool32i");
9c708c7f 16796 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16797 break;
16798 }
16799 break;
16800 case POOL32C:
16801 minor = (ctx->opcode >> 12) & 0xf;
3b4a5489
YK
16802 offset = sextract32(ctx->opcode, 0,
16803 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
3c824109
NF
16804 switch (minor) {
16805 case LWL:
9e8f441a 16806 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16807 mips32_op = OPC_LWL;
5c13fdfd 16808 goto do_ld_lr;
3c824109 16809 case SWL:
9e8f441a 16810 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16811 mips32_op = OPC_SWL;
5c13fdfd 16812 goto do_st_lr;
3c824109 16813 case LWR:
9e8f441a 16814 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16815 mips32_op = OPC_LWR;
5c13fdfd 16816 goto do_ld_lr;
3c824109 16817 case SWR:
9e8f441a 16818 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16819 mips32_op = OPC_SWR;
5c13fdfd 16820 goto do_st_lr;
3c824109
NF
16821#if defined(TARGET_MIPS64)
16822 case LDL:
d9224450
MR
16823 check_insn(ctx, ISA_MIPS3);
16824 check_mips_64(ctx);
9e8f441a 16825 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16826 mips32_op = OPC_LDL;
5c13fdfd 16827 goto do_ld_lr;
3c824109 16828 case SDL:
d9224450
MR
16829 check_insn(ctx, ISA_MIPS3);
16830 check_mips_64(ctx);
9e8f441a 16831 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16832 mips32_op = OPC_SDL;
5c13fdfd 16833 goto do_st_lr;
3c824109 16834 case LDR:
d9224450
MR
16835 check_insn(ctx, ISA_MIPS3);
16836 check_mips_64(ctx);
9e8f441a 16837 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16838 mips32_op = OPC_LDR;
5c13fdfd 16839 goto do_ld_lr;
3c824109 16840 case SDR:
d9224450
MR
16841 check_insn(ctx, ISA_MIPS3);
16842 check_mips_64(ctx);
9e8f441a 16843 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16844 mips32_op = OPC_SDR;
5c13fdfd 16845 goto do_st_lr;
3c824109 16846 case LWU:
d9224450
MR
16847 check_insn(ctx, ISA_MIPS3);
16848 check_mips_64(ctx);
3c824109 16849 mips32_op = OPC_LWU;
5c13fdfd 16850 goto do_ld_lr;
3c824109 16851 case LLD:
d9224450
MR
16852 check_insn(ctx, ISA_MIPS3);
16853 check_mips_64(ctx);
3c824109 16854 mips32_op = OPC_LLD;
5c13fdfd 16855 goto do_ld_lr;
3c824109
NF
16856#endif
16857 case LL:
16858 mips32_op = OPC_LL;
5c13fdfd
AJ
16859 goto do_ld_lr;
16860 do_ld_lr:
3b4a5489 16861 gen_ld(ctx, mips32_op, rt, rs, offset);
5c13fdfd
AJ
16862 break;
16863 do_st_lr:
8fffc646 16864 gen_st(ctx, mips32_op, rt, rs, offset);
3c824109
NF
16865 break;
16866 case SC:
3b4a5489 16867 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
3c824109
NF
16868 break;
16869#if defined(TARGET_MIPS64)
16870 case SCD:
d9224450
MR
16871 check_insn(ctx, ISA_MIPS3);
16872 check_mips_64(ctx);
3b4a5489 16873 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
3c824109
NF
16874 break;
16875#endif
8fffc646
JH
16876 case LD_EVA:
16877 if (!ctx->eva) {
16878 MIPS_INVAL("pool32c ld-eva");
16879 generate_exception_end(ctx, EXCP_RI);
16880 break;
16881 }
16882 check_cp0_enabled(ctx);
16883
16884 minor2 = (ctx->opcode >> 9) & 0x7;
16885 offset = sextract32(ctx->opcode, 0, 9);
16886 switch (minor2) {
16887 case LBUE:
16888 mips32_op = OPC_LBUE;
16889 goto do_ld_lr;
16890 case LHUE:
16891 mips32_op = OPC_LHUE;
16892 goto do_ld_lr;
16893 case LWLE:
16894 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16895 mips32_op = OPC_LWLE;
16896 goto do_ld_lr;
16897 case LWRE:
16898 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16899 mips32_op = OPC_LWRE;
16900 goto do_ld_lr;
16901 case LBE:
16902 mips32_op = OPC_LBE;
16903 goto do_ld_lr;
16904 case LHE:
16905 mips32_op = OPC_LHE;
16906 goto do_ld_lr;
16907 case LLE:
16908 mips32_op = OPC_LLE;
16909 goto do_ld_lr;
16910 case LWE:
16911 mips32_op = OPC_LWE;
16912 goto do_ld_lr;
16913 };
16914 break;
16915 case ST_EVA:
16916 if (!ctx->eva) {
16917 MIPS_INVAL("pool32c st-eva");
16918 generate_exception_end(ctx, EXCP_RI);
16919 break;
16920 }
16921 check_cp0_enabled(ctx);
16922
16923 minor2 = (ctx->opcode >> 9) & 0x7;
16924 offset = sextract32(ctx->opcode, 0, 9);
16925 switch (minor2) {
16926 case SWLE:
16927 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16928 mips32_op = OPC_SWLE;
16929 goto do_st_lr;
16930 case SWRE:
16931 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16932 mips32_op = OPC_SWRE;
16933 goto do_st_lr;
16934 case PREFE:
16935 /* Treat as no-op */
16936 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16937 /* hint codes 24-31 are reserved and signal RI */
16938 generate_exception(ctx, EXCP_RI);
16939 }
16940 break;
16941 case CACHEE:
16942 /* Treat as no-op */
16943 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16944 gen_cache_operation(ctx, rt, rs, offset);
16945 }
16946 break;
16947 case SBE:
16948 mips32_op = OPC_SBE;
16949 goto do_st_lr;
16950 case SHE:
16951 mips32_op = OPC_SHE;
16952 goto do_st_lr;
16953 case SCE:
16954 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
16955 break;
16956 case SWE:
16957 mips32_op = OPC_SWE;
16958 goto do_st_lr;
16959 };
16960 break;
3c824109
NF
16961 case PREF:
16962 /* Treat as no-op */
3b4a5489
YK
16963 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16964 /* hint codes 24-31 are reserved and signal RI */
16965 generate_exception(ctx, EXCP_RI);
16966 }
3c824109
NF
16967 break;
16968 default:
16969 MIPS_INVAL("pool32c");
9c708c7f 16970 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16971 break;
16972 }
16973 break;
ab39ee45
YK
16974 case ADDI32: /* AUI, LUI */
16975 if (ctx->insn_flags & ISA_MIPS32R6) {
16976 /* AUI, LUI */
16977 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16978 } else {
16979 /* ADDI32 */
16980 mips32_op = OPC_ADDI;
16981 goto do_addi;
16982 }
16983 break;
3c824109
NF
16984 case ADDIU32:
16985 mips32_op = OPC_ADDIU;
16986 do_addi:
d75c135e 16987 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
16988 break;
16989
16990 /* Logical operations */
16991 case ORI32:
16992 mips32_op = OPC_ORI;
16993 goto do_logici;
16994 case XORI32:
16995 mips32_op = OPC_XORI;
16996 goto do_logici;
16997 case ANDI32:
16998 mips32_op = OPC_ANDI;
16999 do_logici:
d75c135e 17000 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17001 break;
17002
17003 /* Set less than immediate */
17004 case SLTI32:
17005 mips32_op = OPC_SLTI;
17006 goto do_slti;
17007 case SLTIU32:
17008 mips32_op = OPC_SLTIU;
17009 do_slti:
d75c135e 17010 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17011 break;
17012 case JALX32:
9e8f441a 17013 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17014 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103
YK
17015 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17016 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109 17017 break;
65935f07
YK
17018 case JALS32: /* BOVC, BEQC, BEQZALC */
17019 if (ctx->insn_flags & ISA_MIPS32R6) {
17020 if (rs >= rt) {
17021 /* BOVC */
17022 mips32_op = OPC_BOVC;
17023 } else if (rs < rt && rs == 0) {
17024 /* BEQZALC */
17025 mips32_op = OPC_BEQZALC;
17026 } else {
17027 /* BEQC */
17028 mips32_op = OPC_BEQC;
17029 }
17030 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17031 } else {
17032 /* JALS32 */
17033 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17034 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17035 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17036 }
3c824109 17037 break;
65935f07
YK
17038 case BEQ32: /* BC */
17039 if (ctx->insn_flags & ISA_MIPS32R6) {
17040 /* BC */
17041 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17042 sextract32(ctx->opcode << 1, 0, 27));
17043 } else {
17044 /* BEQ32 */
17045 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17046 }
3c824109 17047 break;
65935f07
YK
17048 case BNE32: /* BALC */
17049 if (ctx->insn_flags & ISA_MIPS32R6) {
17050 /* BALC */
17051 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17052 sextract32(ctx->opcode << 1, 0, 27));
17053 } else {
17054 /* BNE32 */
17055 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17056 }
3c824109 17057 break;
65935f07
YK
17058 case J32: /* BGTZC, BLTZC, BLTC */
17059 if (ctx->insn_flags & ISA_MIPS32R6) {
17060 if (rs == 0 && rt != 0) {
17061 /* BGTZC */
17062 mips32_op = OPC_BGTZC;
17063 } else if (rs != 0 && rt != 0 && rs == rt) {
17064 /* BLTZC */
17065 mips32_op = OPC_BLTZC;
17066 } else {
17067 /* BLTC */
17068 mips32_op = OPC_BLTC;
17069 }
17070 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17071 } else {
17072 /* J32 */
17073 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17074 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17075 }
3c824109 17076 break;
65935f07
YK
17077 case JAL32: /* BLEZC, BGEZC, BGEC */
17078 if (ctx->insn_flags & ISA_MIPS32R6) {
17079 if (rs == 0 && rt != 0) {
17080 /* BLEZC */
17081 mips32_op = OPC_BLEZC;
17082 } else if (rs != 0 && rt != 0 && rs == rt) {
17083 /* BGEZC */
17084 mips32_op = OPC_BGEZC;
17085 } else {
17086 /* BGEC */
17087 mips32_op = OPC_BGEC;
17088 }
17089 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17090 } else {
17091 /* JAL32 */
17092 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17093 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17094 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17095 }
3c824109
NF
17096 break;
17097 /* Floating point (COP1) */
17098 case LWC132:
17099 mips32_op = OPC_LWC1;
17100 goto do_cop1;
17101 case LDC132:
17102 mips32_op = OPC_LDC1;
17103 goto do_cop1;
17104 case SWC132:
17105 mips32_op = OPC_SWC1;
17106 goto do_cop1;
17107 case SDC132:
17108 mips32_op = OPC_SDC1;
17109 do_cop1:
5ab5c041 17110 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
3c824109 17111 break;
ab39ee45
YK
17112 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17113 if (ctx->insn_flags & ISA_MIPS32R6) {
17114 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17115 switch ((ctx->opcode >> 16) & 0x1f) {
c38a1d52
AR
17116 case ADDIUPC_00:
17117 case ADDIUPC_01:
17118 case ADDIUPC_02:
17119 case ADDIUPC_03:
17120 case ADDIUPC_04:
17121 case ADDIUPC_05:
17122 case ADDIUPC_06:
17123 case ADDIUPC_07:
eeb3bba8 17124 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
17125 break;
17126 case AUIPC:
eeb3bba8 17127 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
ab39ee45
YK
17128 break;
17129 case ALUIPC:
eeb3bba8 17130 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
ab39ee45 17131 break;
c38a1d52
AR
17132 case LWPC_08:
17133 case LWPC_09:
17134 case LWPC_0A:
17135 case LWPC_0B:
17136 case LWPC_0C:
17137 case LWPC_0D:
17138 case LWPC_0E:
17139 case LWPC_0F:
eeb3bba8 17140 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
17141 break;
17142 default:
17143 generate_exception(ctx, EXCP_RI);
17144 break;
17145 }
17146 } else {
17147 /* ADDIUPC */
3c824109 17148 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
e1555d7d 17149 offset = SIMM(ctx->opcode, 0, 23) << 2;
3c824109
NF
17150
17151 gen_addiupc(ctx, reg, offset, 0, 0);
17152 }
17153 break;
65935f07
YK
17154 case BNVC: /* BNEC, BNEZALC */
17155 check_insn(ctx, ISA_MIPS32R6);
17156 if (rs >= rt) {
17157 /* BNVC */
17158 mips32_op = OPC_BNVC;
17159 } else if (rs < rt && rs == 0) {
17160 /* BNEZALC */
17161 mips32_op = OPC_BNEZALC;
17162 } else {
17163 /* BNEC */
17164 mips32_op = OPC_BNEC;
17165 }
17166 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17167 break;
17168 case R6_BNEZC: /* JIALC */
17169 check_insn(ctx, ISA_MIPS32R6);
17170 if (rt != 0) {
17171 /* BNEZC */
17172 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17173 sextract32(ctx->opcode << 1, 0, 22));
17174 } else {
17175 /* JIALC */
17176 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17177 }
17178 break;
17179 case R6_BEQZC: /* JIC */
17180 check_insn(ctx, ISA_MIPS32R6);
17181 if (rt != 0) {
17182 /* BEQZC */
17183 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17184 sextract32(ctx->opcode << 1, 0, 22));
17185 } else {
17186 /* JIC */
17187 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17188 }
17189 break;
17190 case BLEZALC: /* BGEZALC, BGEUC */
17191 check_insn(ctx, ISA_MIPS32R6);
17192 if (rs == 0 && rt != 0) {
17193 /* BLEZALC */
17194 mips32_op = OPC_BLEZALC;
17195 } else if (rs != 0 && rt != 0 && rs == rt) {
17196 /* BGEZALC */
17197 mips32_op = OPC_BGEZALC;
17198 } else {
17199 /* BGEUC */
17200 mips32_op = OPC_BGEUC;
17201 }
17202 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17203 break;
17204 case BGTZALC: /* BLTZALC, BLTUC */
17205 check_insn(ctx, ISA_MIPS32R6);
17206 if (rs == 0 && rt != 0) {
17207 /* BGTZALC */
17208 mips32_op = OPC_BGTZALC;
17209 } else if (rs != 0 && rt != 0 && rs == rt) {
17210 /* BLTZALC */
17211 mips32_op = OPC_BLTZALC;
17212 } else {
17213 /* BLTUC */
17214 mips32_op = OPC_BLTUC;
17215 }
17216 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17217 break;
3c824109
NF
17218 /* Loads and stores */
17219 case LB32:
17220 mips32_op = OPC_LB;
5c13fdfd 17221 goto do_ld;
3c824109
NF
17222 case LBU32:
17223 mips32_op = OPC_LBU;
5c13fdfd 17224 goto do_ld;
3c824109
NF
17225 case LH32:
17226 mips32_op = OPC_LH;
5c13fdfd 17227 goto do_ld;
3c824109
NF
17228 case LHU32:
17229 mips32_op = OPC_LHU;
5c13fdfd 17230 goto do_ld;
3c824109
NF
17231 case LW32:
17232 mips32_op = OPC_LW;
5c13fdfd 17233 goto do_ld;
3c824109
NF
17234#ifdef TARGET_MIPS64
17235 case LD32:
d9224450
MR
17236 check_insn(ctx, ISA_MIPS3);
17237 check_mips_64(ctx);
3c824109 17238 mips32_op = OPC_LD;
5c13fdfd 17239 goto do_ld;
3c824109 17240 case SD32:
d9224450
MR
17241 check_insn(ctx, ISA_MIPS3);
17242 check_mips_64(ctx);
3c824109 17243 mips32_op = OPC_SD;
5c13fdfd 17244 goto do_st;
3c824109
NF
17245#endif
17246 case SB32:
17247 mips32_op = OPC_SB;
5c13fdfd 17248 goto do_st;
3c824109
NF
17249 case SH32:
17250 mips32_op = OPC_SH;
5c13fdfd 17251 goto do_st;
3c824109
NF
17252 case SW32:
17253 mips32_op = OPC_SW;
5c13fdfd
AJ
17254 goto do_st;
17255 do_ld:
d75c135e 17256 gen_ld(ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
17257 break;
17258 do_st:
17259 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
17260 break;
17261 default:
9c708c7f 17262 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17263 break;
17264 }
17265}
17266
240ce26a 17267static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
17268{
17269 uint32_t op;
17270
17271 /* make sure instructions are on a halfword boundary */
eeb3bba8
EC
17272 if (ctx->base.pc_next & 0x1) {
17273 env->CP0_BadVAddr = ctx->base.pc_next;
9c708c7f 17274 generate_exception_end(ctx, EXCP_AdEL);
3c824109
NF
17275 return 2;
17276 }
17277
17278 op = (ctx->opcode >> 10) & 0x3f;
17279 /* Enforce properly-sized instructions in a delay slot */
b231c103
YK
17280 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17281 switch (op & 0x7) { /* MSB-3..MSB-5 */
17282 case 0:
17283 /* POOL32A, POOL32B, POOL32I, POOL32C */
17284 case 4:
17285 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17286 case 5:
17287 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17288 case 6:
17289 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17290 case 7:
17291 /* LB32, LH32, LWC132, LDC132, LW32 */
17292 if (ctx->hflags & MIPS_HFLAG_BDS16) {
9c708c7f 17293 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17294 return 2;
17295 }
17296 break;
b231c103
YK
17297 case 1:
17298 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17299 case 2:
17300 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17301 case 3:
17302 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17303 if (ctx->hflags & MIPS_HFLAG_BDS32) {
9c708c7f 17304 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17305 return 2;
17306 }
17307 break;
3c824109
NF
17308 }
17309 }
b231c103 17310
3c824109
NF
17311 switch (op) {
17312 case POOL16A:
17313 {
17314 int rd = mmreg(uMIPS_RD(ctx->opcode));
17315 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17316 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17317 uint32_t opc = 0;
17318
17319 switch (ctx->opcode & 0x1) {
17320 case ADDU16:
17321 opc = OPC_ADDU;
17322 break;
17323 case SUBU16:
17324 opc = OPC_SUBU;
17325 break;
17326 }
ed7ce6c0
YK
17327 if (ctx->insn_flags & ISA_MIPS32R6) {
17328 /* In the Release 6 the register number location in
17329 * the instruction encoding has changed.
17330 */
17331 gen_arith(ctx, opc, rs1, rd, rs2);
17332 } else {
17333 gen_arith(ctx, opc, rd, rs1, rs2);
17334 }
3c824109
NF
17335 }
17336 break;
17337 case POOL16B:
17338 {
17339 int rd = mmreg(uMIPS_RD(ctx->opcode));
17340 int rs = mmreg(uMIPS_RS(ctx->opcode));
17341 int amount = (ctx->opcode >> 1) & 0x7;
17342 uint32_t opc = 0;
17343 amount = amount == 0 ? 8 : amount;
17344
17345 switch (ctx->opcode & 0x1) {
17346 case SLL16:
17347 opc = OPC_SLL;
17348 break;
17349 case SRL16:
17350 opc = OPC_SRL;
17351 break;
17352 }
17353
d75c135e 17354 gen_shift_imm(ctx, opc, rd, rs, amount);
3c824109
NF
17355 }
17356 break;
17357 case POOL16C:
ed7ce6c0
YK
17358 if (ctx->insn_flags & ISA_MIPS32R6) {
17359 gen_pool16c_r6_insn(ctx);
17360 } else {
17361 gen_pool16c_insn(ctx);
17362 }
3c824109
NF
17363 break;
17364 case LWGP16:
17365 {
17366 int rd = mmreg(uMIPS_RD(ctx->opcode));
17367 int rb = 28; /* GP */
17368 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17369
d75c135e 17370 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17371 }
17372 break;
17373 case POOL16F:
9e8f441a 17374 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17375 if (ctx->opcode & 1) {
9c708c7f 17376 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17377 } else {
17378 /* MOVEP */
17379 int enc_dest = uMIPS_RD(ctx->opcode);
17380 int enc_rt = uMIPS_RS2(ctx->opcode);
17381 int enc_rs = uMIPS_RS1(ctx->opcode);
ed7ce6c0 17382 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
3c824109
NF
17383 }
17384 break;
17385 case LBU16:
17386 {
17387 int rd = mmreg(uMIPS_RD(ctx->opcode));
17388 int rb = mmreg(uMIPS_RS(ctx->opcode));
17389 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17390 offset = (offset == 0xf ? -1 : offset);
17391
d75c135e 17392 gen_ld(ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
17393 }
17394 break;
17395 case LHU16:
17396 {
17397 int rd = mmreg(uMIPS_RD(ctx->opcode));
17398 int rb = mmreg(uMIPS_RS(ctx->opcode));
17399 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17400
d75c135e 17401 gen_ld(ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
17402 }
17403 break;
17404 case LWSP16:
17405 {
17406 int rd = (ctx->opcode >> 5) & 0x1f;
17407 int rb = 29; /* SP */
17408 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17409
d75c135e 17410 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17411 }
17412 break;
17413 case LW16:
17414 {
17415 int rd = mmreg(uMIPS_RD(ctx->opcode));
17416 int rb = mmreg(uMIPS_RS(ctx->opcode));
17417 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17418
d75c135e 17419 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17420 }
17421 break;
17422 case SB16:
17423 {
17424 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17425 int rb = mmreg(uMIPS_RS(ctx->opcode));
17426 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17427
5c13fdfd 17428 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
17429 }
17430 break;
17431 case SH16:
17432 {
17433 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17434 int rb = mmreg(uMIPS_RS(ctx->opcode));
17435 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17436
5c13fdfd 17437 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
17438 }
17439 break;
17440 case SWSP16:
17441 {
17442 int rd = (ctx->opcode >> 5) & 0x1f;
17443 int rb = 29; /* SP */
17444 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17445
5c13fdfd 17446 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
17447 }
17448 break;
17449 case SW16:
17450 {
17451 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17452 int rb = mmreg(uMIPS_RS(ctx->opcode));
17453 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17454
5c13fdfd 17455 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
17456 }
17457 break;
17458 case MOVE16:
17459 {
17460 int rd = uMIPS_RD5(ctx->opcode);
17461 int rs = uMIPS_RS5(ctx->opcode);
17462
7215d7e7 17463 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
3c824109
NF
17464 }
17465 break;
17466 case ANDI16:
d75c135e 17467 gen_andi16(ctx);
3c824109
NF
17468 break;
17469 case POOL16D:
17470 switch (ctx->opcode & 0x1) {
17471 case ADDIUS5:
d75c135e 17472 gen_addius5(ctx);
3c824109
NF
17473 break;
17474 case ADDIUSP:
d75c135e 17475 gen_addiusp(ctx);
3c824109
NF
17476 break;
17477 }
17478 break;
17479 case POOL16E:
17480 switch (ctx->opcode & 0x1) {
17481 case ADDIUR2:
d75c135e 17482 gen_addiur2(ctx);
3c824109
NF
17483 break;
17484 case ADDIUR1SP:
d75c135e 17485 gen_addiur1sp(ctx);
3c824109
NF
17486 break;
17487 }
17488 break;
65935f07 17489 case B16: /* BC16 */
3c824109 17490 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
65935f07
YK
17491 sextract32(ctx->opcode, 0, 10) << 1,
17492 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
3c824109 17493 break;
65935f07
YK
17494 case BNEZ16: /* BNEZC16 */
17495 case BEQZ16: /* BEQZC16 */
3c824109
NF
17496 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17497 mmreg(uMIPS_RD(ctx->opcode)),
65935f07
YK
17498 0, sextract32(ctx->opcode, 0, 7) << 1,
17499 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17500
3c824109
NF
17501 break;
17502 case LI16:
17503 {
17504 int reg = mmreg(uMIPS_RD(ctx->opcode));
17505 int imm = ZIMM(ctx->opcode, 0, 7);
17506
17507 imm = (imm == 0x7f ? -1 : imm);
17508 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17509 }
17510 break;
3c824109 17511 case RES_29:
3c824109 17512 case RES_31:
3c824109 17513 case RES_39:
9c708c7f 17514 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17515 break;
17516 default:
f60eeb0c 17517 decode_micromips32_opc(env, ctx);
3c824109
NF
17518 return 4;
17519 }
17520
17521 return 2;
17522}
17523
261c95a0
YK
17524/*
17525 *
17526 * nanoMIPS opcodes
17527 *
17528 */
17529
17530/* MAJOR, P16, and P32 pools opcodes */
17531enum {
17532 NM_P_ADDIU = 0x00,
17533 NM_ADDIUPC = 0x01,
17534 NM_MOVE_BALC = 0x02,
17535 NM_P16_MV = 0x04,
17536 NM_LW16 = 0x05,
17537 NM_BC16 = 0x06,
17538 NM_P16_SR = 0x07,
17539
17540 NM_POOL32A = 0x08,
17541 NM_P_BAL = 0x0a,
17542 NM_P16_SHIFT = 0x0c,
17543 NM_LWSP16 = 0x0d,
17544 NM_BALC16 = 0x0e,
17545 NM_P16_4X4 = 0x0f,
17546
17547 NM_P_GP_W = 0x10,
17548 NM_P_GP_BH = 0x11,
17549 NM_P_J = 0x12,
17550 NM_P16C = 0x14,
17551 NM_LWGP16 = 0x15,
17552 NM_P16_LB = 0x17,
17553
17554 NM_P48I = 0x18,
17555 NM_P16_A1 = 0x1c,
17556 NM_LW4X4 = 0x1d,
17557 NM_P16_LH = 0x1f,
17558
17559 NM_P_U12 = 0x20,
17560 NM_P_LS_U12 = 0x21,
17561 NM_P_BR1 = 0x22,
17562 NM_P16_A2 = 0x24,
17563 NM_SW16 = 0x25,
17564 NM_BEQZC16 = 0x26,
17565
17566 NM_POOL32F = 0x28,
17567 NM_P_LS_S9 = 0x29,
17568 NM_P_BR2 = 0x2a,
17569
17570 NM_P16_ADDU = 0x2c,
17571 NM_SWSP16 = 0x2d,
17572 NM_BNEZC16 = 0x2e,
17573 NM_MOVEP = 0x2f,
17574
17575 NM_POOL32S = 0x30,
17576 NM_P_BRI = 0x32,
17577 NM_LI16 = 0x34,
17578 NM_SWGP16 = 0x35,
17579 NM_P16_BR = 0x36,
17580
17581 NM_P_LUI = 0x38,
17582 NM_ANDI16 = 0x3c,
17583 NM_SW4X4 = 0x3d,
17584 NM_MOVEPREV = 0x3f,
17585};
17586
17587/* POOL32A instruction pool */
17588enum {
17589 NM_POOL32A0 = 0x00,
17590 NM_SPECIAL2 = 0x01,
17591 NM_COP2_1 = 0x02,
17592 NM_UDI = 0x03,
17593 NM_POOL32A5 = 0x05,
17594 NM_POOL32A7 = 0x07,
17595};
17596
17597/* P.GP.W instruction pool */
17598enum {
17599 NM_ADDIUGP_W = 0x00,
17600 NM_LWGP = 0x02,
17601 NM_SWGP = 0x03,
17602};
17603
17604/* P48I instruction pool */
17605enum {
17606 NM_LI48 = 0x00,
17607 NM_ADDIU48 = 0x01,
17608 NM_ADDIUGP48 = 0x02,
17609 NM_ADDIUPC48 = 0x03,
17610 NM_LWPC48 = 0x0b,
17611 NM_SWPC48 = 0x0f,
17612};
17613
17614/* P.U12 instruction pool */
17615enum {
17616 NM_ORI = 0x00,
17617 NM_XORI = 0x01,
17618 NM_ANDI = 0x02,
17619 NM_P_SR = 0x03,
17620 NM_SLTI = 0x04,
17621 NM_SLTIU = 0x05,
17622 NM_SEQI = 0x06,
17623 NM_ADDIUNEG = 0x08,
17624 NM_P_SHIFT = 0x0c,
17625 NM_P_ROTX = 0x0d,
17626 NM_P_INS = 0x0e,
17627 NM_P_EXT = 0x0f,
17628};
17629
17630/* POOL32F instruction pool */
17631enum {
17632 NM_POOL32F_0 = 0x00,
17633 NM_POOL32F_3 = 0x03,
17634 NM_POOL32F_5 = 0x05,
17635};
17636
17637/* POOL32S instruction pool */
17638enum {
17639 NM_POOL32S_0 = 0x00,
17640 NM_POOL32S_4 = 0x04,
17641};
17642
17643/* P.LUI instruction pool */
17644enum {
17645 NM_LUI = 0x00,
17646 NM_ALUIPC = 0x01,
17647};
17648
17649/* P.GP.BH instruction pool */
17650enum {
17651 NM_LBGP = 0x00,
17652 NM_SBGP = 0x01,
17653 NM_LBUGP = 0x02,
17654 NM_ADDIUGP_B = 0x03,
17655 NM_P_GP_LH = 0x04,
17656 NM_P_GP_SH = 0x05,
17657 NM_P_GP_CP1 = 0x06,
17658};
17659
17660/* P.LS.U12 instruction pool */
17661enum {
17662 NM_LB = 0x00,
17663 NM_SB = 0x01,
17664 NM_LBU = 0x02,
17665 NM_P_PREFU12 = 0x03,
17666 NM_LH = 0x04,
17667 NM_SH = 0x05,
17668 NM_LHU = 0x06,
17669 NM_LWU = 0x07,
17670 NM_LW = 0x08,
17671 NM_SW = 0x09,
17672 NM_LWC1 = 0x0a,
17673 NM_SWC1 = 0x0b,
17674 NM_LDC1 = 0x0e,
17675 NM_SDC1 = 0x0f,
17676};
17677
17678/* P.LS.S9 instruction pool */
17679enum {
17680 NM_P_LS_S0 = 0x00,
17681 NM_P_LS_S1 = 0x01,
17682 NM_P_LS_E0 = 0x02,
17683 NM_P_LS_WM = 0x04,
17684 NM_P_LS_UAWM = 0x05,
17685};
17686
17687/* P.BAL instruction pool */
17688enum {
17689 NM_BC = 0x00,
17690 NM_BALC = 0x01,
17691};
17692
17693/* P.J instruction pool */
17694enum {
17695 NM_JALRC = 0x00,
17696 NM_JALRC_HB = 0x01,
17697 NM_P_BALRSC = 0x08,
17698};
17699
17700/* P.BR1 instruction pool */
17701enum {
17702 NM_BEQC = 0x00,
17703 NM_P_BR3A = 0x01,
17704 NM_BGEC = 0x02,
17705 NM_BGEUC = 0x03,
17706};
17707
17708/* P.BR2 instruction pool */
17709enum {
17710 NM_BNEC = 0x00,
17711 NM_BLTC = 0x02,
17712 NM_BLTUC = 0x03,
17713};
17714
17715/* P.BRI instruction pool */
17716enum {
17717 NM_BEQIC = 0x00,
17718 NM_BBEQZC = 0x01,
17719 NM_BGEIC = 0x02,
17720 NM_BGEIUC = 0x03,
17721 NM_BNEIC = 0x04,
17722 NM_BBNEZC = 0x05,
17723 NM_BLTIC = 0x06,
17724 NM_BLTIUC = 0x07,
17725};
17726
17727/* P16.SHIFT instruction pool */
17728enum {
17729 NM_SLL16 = 0x00,
17730 NM_SRL16 = 0x01,
17731};
17732
17733/* POOL16C instruction pool */
17734enum {
17735 NM_POOL16C_0 = 0x00,
17736 NM_LWXS16 = 0x01,
17737};
17738
17739/* P16.A1 instruction pool */
17740enum {
17741 NM_ADDIUR1SP = 0x01,
17742};
17743
17744/* P16.A2 instruction pool */
17745enum {
17746 NM_ADDIUR2 = 0x00,
17747 NM_P_ADDIURS5 = 0x01,
17748};
17749
17750/* P16.ADDU instruction pool */
17751enum {
17752 NM_ADDU16 = 0x00,
17753 NM_SUBU16 = 0x01,
17754};
17755
17756/* P16.SR instruction pool */
17757enum {
17758 NM_SAVE16 = 0x00,
17759 NM_RESTORE_JRC16 = 0x01,
17760};
17761
17762/* P16.4X4 instruction pool */
17763enum {
17764 NM_ADDU4X4 = 0x00,
17765 NM_MUL4X4 = 0x01,
17766};
17767
17768/* P16.LB instruction pool */
17769enum {
17770 NM_LB16 = 0x00,
17771 NM_SB16 = 0x01,
17772 NM_LBU16 = 0x02,
17773};
17774
17775/* P16.LH instruction pool */
17776enum {
17777 NM_LH16 = 0x00,
17778 NM_SH16 = 0x01,
17779 NM_LHU16 = 0x02,
17780};
17781
17782/* P.RI instruction pool */
17783enum {
17784 NM_SIGRIE = 0x00,
17785 NM_P_SYSCALL = 0x01,
17786 NM_BREAK = 0x02,
17787 NM_SDBBP = 0x03,
17788};
17789
17790/* POOL32A0 instruction pool */
17791enum {
17792 NM_P_TRAP = 0x00,
17793 NM_SEB = 0x01,
17794 NM_SLLV = 0x02,
17795 NM_MUL = 0x03,
17796 NM_MFC0 = 0x06,
17797 NM_MFHC0 = 0x07,
17798 NM_SEH = 0x09,
17799 NM_SRLV = 0x0a,
17800 NM_MUH = 0x0b,
17801 NM_MTC0 = 0x0e,
17802 NM_MTHC0 = 0x0f,
17803 NM_SRAV = 0x12,
17804 NM_MULU = 0x13,
17805 NM_ROTRV = 0x1a,
17806 NM_MUHU = 0x1b,
17807 NM_ADD = 0x22,
17808 NM_DIV = 0x23,
17809 NM_ADDU = 0x2a,
17810 NM_MOD = 0x2b,
17811 NM_SUB = 0x32,
17812 NM_DIVU = 0x33,
17813 NM_RDHWR = 0x38,
17814 NM_SUBU = 0x3a,
17815 NM_MODU = 0x3b,
17816 NM_P_CMOVE = 0x42,
17817 NM_FORK = 0x45,
17818 NM_MFTR = 0x46,
17819 NM_MFHTR = 0x47,
17820 NM_AND = 0x4a,
17821 NM_YIELD = 0x4d,
17822 NM_MTTR = 0x4e,
17823 NM_MTHTR = 0x4f,
17824 NM_OR = 0x52,
17825 NM_D_E_MT_VPE = 0x56,
17826 NM_NOR = 0x5a,
17827 NM_XOR = 0x62,
17828 NM_SLT = 0x6a,
17829 NM_P_SLTU = 0x72,
17830 NM_SOV = 0x7a,
17831};
17832
ba1e8117
AM
17833/* CRC32 instruction pool */
17834enum {
17835 NM_CRC32B = 0x00,
17836 NM_CRC32H = 0x01,
17837 NM_CRC32W = 0x02,
17838 NM_CRC32CB = 0x04,
17839 NM_CRC32CH = 0x05,
17840 NM_CRC32CW = 0x06,
17841};
17842
b3979b6f
SM
17843/* POOL32A5 instruction pool */
17844enum {
17845 NM_CMP_EQ_PH = 0x00,
17846 NM_CMP_LT_PH = 0x08,
17847 NM_CMP_LE_PH = 0x10,
17848 NM_CMPGU_EQ_QB = 0x18,
17849 NM_CMPGU_LT_QB = 0x20,
17850 NM_CMPGU_LE_QB = 0x28,
17851 NM_CMPGDU_EQ_QB = 0x30,
17852 NM_CMPGDU_LT_QB = 0x38,
17853 NM_CMPGDU_LE_QB = 0x40,
17854 NM_CMPU_EQ_QB = 0x48,
17855 NM_CMPU_LT_QB = 0x50,
17856 NM_CMPU_LE_QB = 0x58,
17857 NM_ADDQ_S_W = 0x60,
17858 NM_SUBQ_S_W = 0x68,
17859 NM_ADDSC = 0x70,
17860 NM_ADDWC = 0x78,
17861
17862 NM_ADDQ_S_PH = 0x01,
17863 NM_ADDQH_R_PH = 0x09,
17864 NM_ADDQH_R_W = 0x11,
17865 NM_ADDU_S_QB = 0x19,
17866 NM_ADDU_S_PH = 0x21,
17867 NM_ADDUH_R_QB = 0x29,
17868 NM_SHRAV_R_PH = 0x31,
17869 NM_SHRAV_R_QB = 0x39,
17870 NM_SUBQ_S_PH = 0x41,
17871 NM_SUBQH_R_PH = 0x49,
17872 NM_SUBQH_R_W = 0x51,
17873 NM_SUBU_S_QB = 0x59,
17874 NM_SUBU_S_PH = 0x61,
17875 NM_SUBUH_R_QB = 0x69,
17876 NM_SHLLV_S_PH = 0x71,
17877 NM_PRECR_SRA_R_PH_W = 0x79,
17878
17879 NM_MULEU_S_PH_QBL = 0x12,
17880 NM_MULEU_S_PH_QBR = 0x1a,
17881 NM_MULQ_RS_PH = 0x22,
17882 NM_MULQ_S_PH = 0x2a,
17883 NM_MULQ_RS_W = 0x32,
17884 NM_MULQ_S_W = 0x3a,
17885 NM_APPEND = 0x42,
17886 NM_MODSUB = 0x52,
17887 NM_SHRAV_R_W = 0x5a,
17888 NM_SHRLV_PH = 0x62,
17889 NM_SHRLV_QB = 0x6a,
17890 NM_SHLLV_QB = 0x72,
17891 NM_SHLLV_S_W = 0x7a,
17892
17893 NM_SHILO = 0x03,
17894
17895 NM_MULEQ_S_W_PHL = 0x04,
17896 NM_MULEQ_S_W_PHR = 0x0c,
17897
17898 NM_MUL_S_PH = 0x05,
17899 NM_PRECR_QB_PH = 0x0d,
17900 NM_PRECRQ_QB_PH = 0x15,
17901 NM_PRECRQ_PH_W = 0x1d,
17902 NM_PRECRQ_RS_PH_W = 0x25,
17903 NM_PRECRQU_S_QB_PH = 0x2d,
17904 NM_PACKRL_PH = 0x35,
17905 NM_PICK_QB = 0x3d,
17906 NM_PICK_PH = 0x45,
17907
17908 NM_SHRA_R_W = 0x5e,
17909 NM_SHRA_R_PH = 0x66,
17910 NM_SHLL_S_PH = 0x76,
17911 NM_SHLL_S_W = 0x7e,
17912
17913 NM_REPL_PH = 0x07
17914};
17915
261c95a0
YK
17916/* POOL32A7 instruction pool */
17917enum {
17918 NM_P_LSX = 0x00,
17919 NM_LSA = 0x01,
17920 NM_EXTW = 0x03,
17921 NM_POOL32AXF = 0x07,
17922};
17923
17924/* P.SR instruction pool */
17925enum {
17926 NM_PP_SR = 0x00,
17927 NM_P_SR_F = 0x01,
17928};
17929
17930/* P.SHIFT instruction pool */
17931enum {
17932 NM_P_SLL = 0x00,
17933 NM_SRL = 0x02,
17934 NM_SRA = 0x04,
17935 NM_ROTR = 0x06,
17936};
17937
17938/* P.ROTX instruction pool */
17939enum {
17940 NM_ROTX = 0x00,
17941};
17942
17943/* P.INS instruction pool */
17944enum {
17945 NM_INS = 0x00,
17946};
17947
17948/* P.EXT instruction pool */
17949enum {
17950 NM_EXT = 0x00,
17951};
17952
17953/* POOL32F_0 (fmt) instruction pool */
17954enum {
17955 NM_RINT_S = 0x04,
17956 NM_RINT_D = 0x44,
17957 NM_ADD_S = 0x06,
17958 NM_SELEQZ_S = 0x07,
17959 NM_SELEQZ_D = 0x47,
17960 NM_CLASS_S = 0x0c,
17961 NM_CLASS_D = 0x4c,
17962 NM_SUB_S = 0x0e,
17963 NM_SELNEZ_S = 0x0f,
17964 NM_SELNEZ_D = 0x4f,
17965 NM_MUL_S = 0x16,
17966 NM_SEL_S = 0x17,
17967 NM_SEL_D = 0x57,
17968 NM_DIV_S = 0x1e,
17969 NM_ADD_D = 0x26,
17970 NM_SUB_D = 0x2e,
17971 NM_MUL_D = 0x36,
17972 NM_MADDF_S = 0x37,
17973 NM_MADDF_D = 0x77,
17974 NM_DIV_D = 0x3e,
17975 NM_MSUBF_S = 0x3f,
17976 NM_MSUBF_D = 0x7f,
17977};
17978
17979/* POOL32F_3 instruction pool */
17980enum {
17981 NM_MIN_FMT = 0x00,
17982 NM_MAX_FMT = 0x01,
17983 NM_MINA_FMT = 0x04,
17984 NM_MAXA_FMT = 0x05,
17985 NM_POOL32FXF = 0x07,
17986};
17987
17988/* POOL32F_5 instruction pool */
17989enum {
17990 NM_CMP_CONDN_S = 0x00,
17991 NM_CMP_CONDN_D = 0x02,
17992};
17993
17994/* P.GP.LH instruction pool */
17995enum {
17996 NM_LHGP = 0x00,
17997 NM_LHUGP = 0x01,
17998};
17999
18000/* P.GP.SH instruction pool */
18001enum {
18002 NM_SHGP = 0x00,
18003};
18004
18005/* P.GP.CP1 instruction pool */
18006enum {
18007 NM_LWC1GP = 0x00,
18008 NM_SWC1GP = 0x01,
18009 NM_LDC1GP = 0x02,
18010 NM_SDC1GP = 0x03,
18011};
18012
18013/* P.LS.S0 instruction pool */
18014enum {
18015 NM_LBS9 = 0x00,
18016 NM_LHS9 = 0x04,
18017 NM_LWS9 = 0x08,
18018 NM_LDS9 = 0x0c,
18019
18020 NM_SBS9 = 0x01,
18021 NM_SHS9 = 0x05,
18022 NM_SWS9 = 0x09,
18023 NM_SDS9 = 0x0d,
18024
18025 NM_LBUS9 = 0x02,
18026 NM_LHUS9 = 0x06,
18027 NM_LWC1S9 = 0x0a,
18028 NM_LDC1S9 = 0x0e,
18029
18030 NM_P_PREFS9 = 0x03,
18031 NM_LWUS9 = 0x07,
18032 NM_SWC1S9 = 0x0b,
18033 NM_SDC1S9 = 0x0f,
18034};
18035
18036/* P.LS.S1 instruction pool */
18037enum {
18038 NM_ASET_ACLR = 0x02,
18039 NM_UALH = 0x04,
18040 NM_UASH = 0x05,
18041 NM_CACHE = 0x07,
18042 NM_P_LL = 0x0a,
18043 NM_P_SC = 0x0b,
18044};
18045
0d30b3bb
DN
18046/* P.LS.E0 instruction pool */
18047enum {
18048 NM_LBE = 0x00,
18049 NM_SBE = 0x01,
18050 NM_LBUE = 0x02,
18051 NM_P_PREFE = 0x03,
18052 NM_LHE = 0x04,
18053 NM_SHE = 0x05,
18054 NM_LHUE = 0x06,
18055 NM_CACHEE = 0x07,
18056 NM_LWE = 0x08,
18057 NM_SWE = 0x09,
18058 NM_P_LLE = 0x0a,
18059 NM_P_SCE = 0x0b,
18060};
18061
18062/* P.PREFE instruction pool */
18063enum {
18064 NM_SYNCIE = 0x00,
18065 NM_PREFE = 0x01,
18066};
18067
18068/* P.LLE instruction pool */
18069enum {
18070 NM_LLE = 0x00,
18071 NM_LLWPE = 0x01,
18072};
18073
18074/* P.SCE instruction pool */
18075enum {
18076 NM_SCE = 0x00,
18077 NM_SCWPE = 0x01,
18078};
18079
261c95a0
YK
18080/* P.LS.WM instruction pool */
18081enum {
18082 NM_LWM = 0x00,
18083 NM_SWM = 0x01,
18084};
18085
18086/* P.LS.UAWM instruction pool */
18087enum {
18088 NM_UALWM = 0x00,
18089 NM_UASWM = 0x01,
18090};
18091
18092/* P.BR3A instruction pool */
18093enum {
18094 NM_BC1EQZC = 0x00,
18095 NM_BC1NEZC = 0x01,
18096 NM_BC2EQZC = 0x02,
18097 NM_BC2NEZC = 0x03,
18098 NM_BPOSGE32C = 0x04,
18099};
18100
18101/* P16.RI instruction pool */
18102enum {
18103 NM_P16_SYSCALL = 0x01,
18104 NM_BREAK16 = 0x02,
18105 NM_SDBBP16 = 0x03,
18106};
18107
18108/* POOL16C_0 instruction pool */
18109enum {
18110 NM_POOL16C_00 = 0x00,
18111};
18112
18113/* P16.JRC instruction pool */
18114enum {
18115 NM_JRC = 0x00,
18116 NM_JALRC16 = 0x01,
18117};
18118
18119/* P.SYSCALL instruction pool */
18120enum {
18121 NM_SYSCALL = 0x00,
18122 NM_HYPCALL = 0x01,
18123};
18124
18125/* P.TRAP instruction pool */
18126enum {
18127 NM_TEQ = 0x00,
18128 NM_TNE = 0x01,
18129};
18130
18131/* P.CMOVE instruction pool */
18132enum {
18133 NM_MOVZ = 0x00,
18134 NM_MOVN = 0x01,
18135};
18136
18137/* POOL32Axf instruction pool */
18138enum {
b3979b6f
SM
18139 NM_POOL32AXF_1 = 0x01,
18140 NM_POOL32AXF_2 = 0x02,
261c95a0
YK
18141 NM_POOL32AXF_4 = 0x04,
18142 NM_POOL32AXF_5 = 0x05,
b3979b6f
SM
18143 NM_POOL32AXF_7 = 0x07,
18144};
18145
18146/* POOL32Axf_1 instruction pool */
18147enum {
18148 NM_POOL32AXF_1_0 = 0x00,
18149 NM_POOL32AXF_1_1 = 0x01,
18150 NM_POOL32AXF_1_3 = 0x03,
18151 NM_POOL32AXF_1_4 = 0x04,
18152 NM_POOL32AXF_1_5 = 0x05,
18153 NM_POOL32AXF_1_7 = 0x07,
18154};
18155
18156/* POOL32Axf_2 instruction pool */
18157enum {
18158 NM_POOL32AXF_2_0_7 = 0x00,
18159 NM_POOL32AXF_2_8_15 = 0x01,
18160 NM_POOL32AXF_2_16_23 = 0x02,
18161 NM_POOL32AXF_2_24_31 = 0x03,
18162};
18163
18164/* POOL32Axf_7 instruction pool */
18165enum {
18166 NM_SHRA_R_QB = 0x0,
18167 NM_SHRL_PH = 0x1,
18168 NM_REPL_QB = 0x2,
18169};
18170
18171/* POOL32Axf_1_0 instruction pool */
18172enum {
18173 NM_MFHI = 0x0,
18174 NM_MFLO = 0x1,
18175 NM_MTHI = 0x2,
18176 NM_MTLO = 0x3,
18177};
18178
18179/* POOL32Axf_1_1 instruction pool */
18180enum {
18181 NM_MTHLIP = 0x0,
18182 NM_SHILOV = 0x1,
18183};
18184
18185/* POOL32Axf_1_3 instruction pool */
18186enum {
18187 NM_RDDSP = 0x0,
18188 NM_WRDSP = 0x1,
18189 NM_EXTP = 0x2,
18190 NM_EXTPDP = 0x3,
18191};
18192
18193/* POOL32Axf_1_4 instruction pool */
18194enum {
18195 NM_SHLL_QB = 0x0,
18196 NM_SHRL_QB = 0x1,
18197};
18198
18199/* POOL32Axf_1_5 instruction pool */
18200enum {
18201 NM_MAQ_S_W_PHR = 0x0,
18202 NM_MAQ_S_W_PHL = 0x1,
18203 NM_MAQ_SA_W_PHR = 0x2,
18204 NM_MAQ_SA_W_PHL = 0x3,
18205};
18206
18207/* POOL32Axf_1_7 instruction pool */
18208enum {
18209 NM_EXTR_W = 0x0,
18210 NM_EXTR_R_W = 0x1,
18211 NM_EXTR_RS_W = 0x2,
18212 NM_EXTR_S_H = 0x3,
18213};
18214
18215/* POOL32Axf_2_0_7 instruction pool */
18216enum {
18217 NM_DPA_W_PH = 0x0,
18218 NM_DPAQ_S_W_PH = 0x1,
18219 NM_DPS_W_PH = 0x2,
18220 NM_DPSQ_S_W_PH = 0x3,
18221 NM_BALIGN = 0x4,
18222 NM_MADD = 0x5,
18223 NM_MULT = 0x6,
18224 NM_EXTRV_W = 0x7,
18225};
18226
18227/* POOL32Axf_2_8_15 instruction pool */
18228enum {
18229 NM_DPAX_W_PH = 0x0,
18230 NM_DPAQ_SA_L_W = 0x1,
18231 NM_DPSX_W_PH = 0x2,
18232 NM_DPSQ_SA_L_W = 0x3,
18233 NM_MADDU = 0x5,
18234 NM_MULTU = 0x6,
18235 NM_EXTRV_R_W = 0x7,
18236};
18237
18238/* POOL32Axf_2_16_23 instruction pool */
18239enum {
18240 NM_DPAU_H_QBL = 0x0,
18241 NM_DPAQX_S_W_PH = 0x1,
18242 NM_DPSU_H_QBL = 0x2,
18243 NM_DPSQX_S_W_PH = 0x3,
18244 NM_EXTPV = 0x4,
18245 NM_MSUB = 0x5,
18246 NM_MULSA_W_PH = 0x6,
18247 NM_EXTRV_RS_W = 0x7,
18248};
18249
18250/* POOL32Axf_2_24_31 instruction pool */
18251enum {
18252 NM_DPAU_H_QBR = 0x0,
18253 NM_DPAQX_SA_W_PH = 0x1,
18254 NM_DPSU_H_QBR = 0x2,
18255 NM_DPSQX_SA_W_PH = 0x3,
18256 NM_EXTPDPV = 0x4,
18257 NM_MSUBU = 0x5,
18258 NM_MULSAQ_S_W_PH = 0x6,
18259 NM_EXTRV_S_H = 0x7,
261c95a0
YK
18260};
18261
18262/* POOL32Axf_{4, 5} instruction pool */
18263enum {
18264 NM_CLO = 0x25,
18265 NM_CLZ = 0x2d,
18266
18267 NM_TLBP = 0x01,
18268 NM_TLBR = 0x09,
18269 NM_TLBWI = 0x11,
18270 NM_TLBWR = 0x19,
18271 NM_TLBINV = 0x03,
18272 NM_TLBINVF = 0x0b,
18273 NM_DI = 0x23,
18274 NM_EI = 0x2b,
18275 NM_RDPGPR = 0x70,
18276 NM_WRPGPR = 0x78,
18277 NM_WAIT = 0x61,
18278 NM_DERET = 0x71,
18279 NM_ERETX = 0x79,
b3979b6f
SM
18280
18281 /* nanoMIPS DSP instructions */
18282 NM_ABSQ_S_QB = 0x00,
18283 NM_ABSQ_S_PH = 0x08,
18284 NM_ABSQ_S_W = 0x10,
18285 NM_PRECEQ_W_PHL = 0x28,
18286 NM_PRECEQ_W_PHR = 0x30,
18287 NM_PRECEQU_PH_QBL = 0x38,
18288 NM_PRECEQU_PH_QBR = 0x48,
18289 NM_PRECEU_PH_QBL = 0x58,
18290 NM_PRECEU_PH_QBR = 0x68,
18291 NM_PRECEQU_PH_QBLA = 0x39,
18292 NM_PRECEQU_PH_QBRA = 0x49,
18293 NM_PRECEU_PH_QBLA = 0x59,
18294 NM_PRECEU_PH_QBRA = 0x69,
18295 NM_REPLV_PH = 0x01,
18296 NM_REPLV_QB = 0x09,
18297 NM_BITREV = 0x18,
18298 NM_INSV = 0x20,
18299 NM_RADDU_W_QB = 0x78,
18300
18301 NM_BITSWAP = 0x05,
18302 NM_WSBH = 0x3d,
261c95a0
YK
18303};
18304
18305/* PP.SR instruction pool */
18306enum {
18307 NM_SAVE = 0x00,
18308 NM_RESTORE = 0x02,
18309 NM_RESTORE_JRC = 0x03,
18310};
18311
18312/* P.SR.F instruction pool */
18313enum {
18314 NM_SAVEF = 0x00,
18315 NM_RESTOREF = 0x01,
18316};
18317
18318/* P16.SYSCALL instruction pool */
18319enum {
18320 NM_SYSCALL16 = 0x00,
18321 NM_HYPCALL16 = 0x01,
18322};
18323
18324/* POOL16C_00 instruction pool */
18325enum {
18326 NM_NOT16 = 0x00,
18327 NM_XOR16 = 0x01,
18328 NM_AND16 = 0x02,
18329 NM_OR16 = 0x03,
18330};
18331
18332/* PP.LSX and PP.LSXS instruction pool */
18333enum {
18334 NM_LBX = 0x00,
18335 NM_LHX = 0x04,
18336 NM_LWX = 0x08,
18337 NM_LDX = 0x0c,
18338
18339 NM_SBX = 0x01,
18340 NM_SHX = 0x05,
18341 NM_SWX = 0x09,
18342 NM_SDX = 0x0d,
18343
18344 NM_LBUX = 0x02,
18345 NM_LHUX = 0x06,
18346 NM_LWC1X = 0x0a,
18347 NM_LDC1X = 0x0e,
18348
18349 NM_LWUX = 0x07,
18350 NM_SWC1X = 0x0b,
18351 NM_SDC1X = 0x0f,
18352
18353 NM_LHXS = 0x04,
18354 NM_LWXS = 0x08,
18355 NM_LDXS = 0x0c,
18356
18357 NM_SHXS = 0x05,
18358 NM_SWXS = 0x09,
18359 NM_SDXS = 0x0d,
18360
18361 NM_LHUXS = 0x06,
18362 NM_LWC1XS = 0x0a,
18363 NM_LDC1XS = 0x0e,
18364
18365 NM_LWUXS = 0x07,
18366 NM_SWC1XS = 0x0b,
18367 NM_SDC1XS = 0x0f,
18368};
18369
18370/* ERETx instruction pool */
18371enum {
18372 NM_ERET = 0x00,
18373 NM_ERETNC = 0x01,
18374};
18375
18376/* POOL32FxF_{0, 1} insturction pool */
18377enum {
18378 NM_CFC1 = 0x40,
18379 NM_CTC1 = 0x60,
18380 NM_MFC1 = 0x80,
18381 NM_MTC1 = 0xa0,
18382 NM_MFHC1 = 0xc0,
18383 NM_MTHC1 = 0xe0,
18384
18385 NM_CVT_S_PL = 0x84,
18386 NM_CVT_S_PU = 0xa4,
18387
18388 NM_CVT_L_S = 0x004,
18389 NM_CVT_L_D = 0x104,
18390 NM_CVT_W_S = 0x024,
18391 NM_CVT_W_D = 0x124,
18392
18393 NM_RSQRT_S = 0x008,
18394 NM_RSQRT_D = 0x108,
18395
18396 NM_SQRT_S = 0x028,
18397 NM_SQRT_D = 0x128,
18398
18399 NM_RECIP_S = 0x048,
18400 NM_RECIP_D = 0x148,
18401
18402 NM_FLOOR_L_S = 0x00c,
18403 NM_FLOOR_L_D = 0x10c,
18404
18405 NM_FLOOR_W_S = 0x02c,
18406 NM_FLOOR_W_D = 0x12c,
18407
18408 NM_CEIL_L_S = 0x04c,
18409 NM_CEIL_L_D = 0x14c,
18410 NM_CEIL_W_S = 0x06c,
18411 NM_CEIL_W_D = 0x16c,
18412 NM_TRUNC_L_S = 0x08c,
18413 NM_TRUNC_L_D = 0x18c,
18414 NM_TRUNC_W_S = 0x0ac,
18415 NM_TRUNC_W_D = 0x1ac,
18416 NM_ROUND_L_S = 0x0cc,
18417 NM_ROUND_L_D = 0x1cc,
18418 NM_ROUND_W_S = 0x0ec,
18419 NM_ROUND_W_D = 0x1ec,
18420
18421 NM_MOV_S = 0x01,
18422 NM_MOV_D = 0x81,
18423 NM_ABS_S = 0x0d,
18424 NM_ABS_D = 0x8d,
18425 NM_NEG_S = 0x2d,
18426 NM_NEG_D = 0xad,
18427 NM_CVT_D_S = 0x04d,
18428 NM_CVT_D_W = 0x0cd,
18429 NM_CVT_D_L = 0x14d,
18430 NM_CVT_S_D = 0x06d,
18431 NM_CVT_S_W = 0x0ed,
18432 NM_CVT_S_L = 0x16d,
18433};
18434
18435/* P.LL instruction pool */
18436enum {
18437 NM_LL = 0x00,
18438 NM_LLWP = 0x01,
18439};
18440
18441/* P.SC instruction pool */
18442enum {
18443 NM_SC = 0x00,
18444 NM_SCWP = 0x01,
18445};
18446
18447/* P.DVP instruction pool */
18448enum {
18449 NM_DVP = 0x00,
18450 NM_EVP = 0x01,
18451};
18452
c533c0f4
AM
18453
18454/*
18455 *
18456 * nanoMIPS decoding engine
18457 *
18458 */
18459
6bfa9f4c
AM
18460
18461/* extraction utilities */
18462
18463#define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18464#define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18465#define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18466#define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18467#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18468#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18469
ea4ca3c2
YK
18470/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18471static inline int decode_gpr_gpr3(int r)
18472{
18473 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18474
18475 return map[r & 0x7];
18476}
18477
8bdb7029
YK
18478/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18479static inline int decode_gpr_gpr3_src_store(int r)
18480{
18481 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18482
18483 return map[r & 0x7];
18484}
18485
ea4ca3c2
YK
18486/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18487static inline int decode_gpr_gpr4(int r)
18488{
18489 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18490 16, 17, 18, 19, 20, 21, 22, 23 };
18491
18492 return map[r & 0xf];
18493}
18494
8bdb7029
YK
18495/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18496static inline int decode_gpr_gpr4_zero(int r)
18497{
18498 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18499 16, 17, 18, 19, 20, 21, 22, 23 };
18500
18501 return map[r & 0xf];
18502}
18503
6bfa9f4c 18504
bf0718c5
SM
18505static void gen_adjust_sp(DisasContext *ctx, int u)
18506{
18507 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18508}
18509
18510static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18511 uint8_t gp, uint16_t u)
18512{
18513 int counter = 0;
18514 TCGv va = tcg_temp_new();
18515 TCGv t0 = tcg_temp_new();
18516
18517 while (counter != count) {
18518 bool use_gp = gp && (counter == count - 1);
18519 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18520 int this_offset = -((counter + 1) << 2);
18521 gen_base_offset_addr(ctx, va, 29, this_offset);
18522 gen_load_gpr(t0, this_rt);
18523 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18524 (MO_TEUL | ctx->default_tcg_memop_mask));
18525 counter++;
18526 }
18527
18528 /* adjust stack pointer */
18529 gen_adjust_sp(ctx, -u);
18530
18531 tcg_temp_free(t0);
18532 tcg_temp_free(va);
18533}
18534
18535static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18536 uint8_t gp, uint16_t u)
18537{
18538 int counter = 0;
18539 TCGv va = tcg_temp_new();
18540 TCGv t0 = tcg_temp_new();
18541
18542 while (counter != count) {
18543 bool use_gp = gp && (counter == count - 1);
18544 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18545 int this_offset = u - ((counter + 1) << 2);
18546 gen_base_offset_addr(ctx, va, 29, this_offset);
18547 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18548 ctx->default_tcg_memop_mask);
18549 tcg_gen_ext32s_tl(t0, t0);
18550 gen_store_gpr(t0, this_rt);
18551 counter++;
18552 }
18553
18554 /* adjust stack pointer */
18555 gen_adjust_sp(ctx, u);
18556
18557 tcg_temp_free(t0);
18558 tcg_temp_free(va);
18559}
18560
80845edf
YK
18561static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18562{
18563 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
18564 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
18565
18566 switch (extract32(ctx->opcode, 2, 2)) {
18567 case NM_NOT16:
18568 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18569 break;
18570 case NM_AND16:
18571 gen_logic(ctx, OPC_AND, rt, rt, rs);
18572 break;
18573 case NM_XOR16:
18574 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18575 break;
18576 case NM_OR16:
18577 gen_logic(ctx, OPC_OR, rt, rt, rs);
18578 break;
18579 }
18580}
18581
0a1a6ed7 18582static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
e0cf0e65
YK
18583{
18584 int rt = extract32(ctx->opcode, 21, 5);
18585 int rs = extract32(ctx->opcode, 16, 5);
18586 int rd = extract32(ctx->opcode, 11, 5);
18587
18588 switch (extract32(ctx->opcode, 3, 7)) {
18589 case NM_P_TRAP:
18590 switch (extract32(ctx->opcode, 10, 1)) {
18591 case NM_TEQ:
fb32f8c8 18592 check_nms(ctx);
e0cf0e65
YK
18593 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18594 break;
18595 case NM_TNE:
fb32f8c8 18596 check_nms(ctx);
e0cf0e65
YK
18597 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18598 break;
18599 }
18600 break;
18601 case NM_RDHWR:
fb32f8c8 18602 check_nms(ctx);
e0cf0e65
YK
18603 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18604 break;
18605 case NM_SEB:
fb32f8c8 18606 check_nms(ctx);
e0cf0e65
YK
18607 gen_bshfl(ctx, OPC_SEB, rs, rt);
18608 break;
18609 case NM_SEH:
18610 gen_bshfl(ctx, OPC_SEH, rs, rt);
18611 break;
18612 case NM_SLLV:
18613 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18614 break;
18615 case NM_SRLV:
18616 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18617 break;
18618 case NM_SRAV:
18619 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18620 break;
18621 case NM_ROTRV:
18622 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18623 break;
18624 case NM_ADD:
18625 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18626 break;
18627 case NM_ADDU:
18628 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18629 break;
18630 case NM_SUB:
fb32f8c8 18631 check_nms(ctx);
e0cf0e65
YK
18632 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18633 break;
18634 case NM_SUBU:
18635 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18636 break;
18637 case NM_P_CMOVE:
18638 switch (extract32(ctx->opcode, 10, 1)) {
18639 case NM_MOVZ:
18640 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18641 break;
18642 case NM_MOVN:
18643 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18644 break;
18645 }
18646 break;
18647 case NM_AND:
18648 gen_logic(ctx, OPC_AND, rd, rs, rt);
18649 break;
18650 case NM_OR:
18651 gen_logic(ctx, OPC_OR, rd, rs, rt);
18652 break;
18653 case NM_NOR:
18654 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18655 break;
18656 case NM_XOR:
18657 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18658 break;
18659 case NM_SLT:
18660 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18661 break;
18662 case NM_P_SLTU:
18663 if (rd == 0) {
18664 /* P_DVP */
18665#ifndef CONFIG_USER_ONLY
18666 TCGv t0 = tcg_temp_new();
18667 switch (extract32(ctx->opcode, 10, 1)) {
18668 case NM_DVP:
18669 if (ctx->vp) {
18670 check_cp0_enabled(ctx);
18671 gen_helper_dvp(t0, cpu_env);
18672 gen_store_gpr(t0, rt);
18673 }
18674 break;
18675 case NM_EVP:
18676 if (ctx->vp) {
18677 check_cp0_enabled(ctx);
18678 gen_helper_evp(t0, cpu_env);
18679 gen_store_gpr(t0, rt);
18680 }
18681 break;
18682 }
18683 tcg_temp_free(t0);
18684#endif
18685 } else {
18686 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18687 }
18688 break;
18689 case NM_SOV:
18690 {
18691 TCGv t0 = tcg_temp_new();
18692 TCGv t1 = tcg_temp_new();
18693 TCGv t2 = tcg_temp_new();
18694
18695 gen_load_gpr(t1, rs);
18696 gen_load_gpr(t2, rt);
18697 tcg_gen_add_tl(t0, t1, t2);
18698 tcg_gen_ext32s_tl(t0, t0);
18699 tcg_gen_xor_tl(t1, t1, t2);
18700 tcg_gen_xor_tl(t2, t0, t2);
18701 tcg_gen_andc_tl(t1, t2, t1);
18702
18703 /* operands of same sign, result different sign */
18704 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18705 gen_store_gpr(t0, rd);
18706
18707 tcg_temp_free(t0);
18708 tcg_temp_free(t1);
18709 tcg_temp_free(t2);
18710 }
18711 break;
18712 case NM_MUL:
18713 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18714 break;
18715 case NM_MUH:
18716 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18717 break;
18718 case NM_MULU:
18719 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18720 break;
18721 case NM_MUHU:
18722 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18723 break;
18724 case NM_DIV:
18725 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18726 break;
18727 case NM_MOD:
18728 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18729 break;
18730 case NM_DIVU:
18731 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18732 break;
18733 case NM_MODU:
18734 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18735 break;
18736#ifndef CONFIG_USER_ONLY
18737 case NM_MFC0:
18738 check_cp0_enabled(ctx);
18739 if (rt == 0) {
18740 /* Treat as NOP. */
18741 break;
18742 }
18743 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18744 break;
18745 case NM_MTC0:
18746 check_cp0_enabled(ctx);
18747 {
18748 TCGv t0 = tcg_temp_new();
18749
18750 gen_load_gpr(t0, rt);
18751 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18752 tcg_temp_free(t0);
18753 }
18754 break;
0a1a6ed7
SM
18755 case NM_D_E_MT_VPE:
18756 {
18757 uint8_t sc = extract32(ctx->opcode, 10, 1);
18758 TCGv t0 = tcg_temp_new();
18759
18760 switch (sc) {
18761 case 0:
18762 if (rs == 1) {
18763 /* DMT */
18764 check_cp0_mt(ctx);
18765 gen_helper_dmt(t0);
18766 gen_store_gpr(t0, rt);
18767 } else if (rs == 0) {
18768 /* DVPE */
18769 check_cp0_mt(ctx);
18770 gen_helper_dvpe(t0, cpu_env);
18771 gen_store_gpr(t0, rt);
18772 } else {
18773 generate_exception_end(ctx, EXCP_RI);
18774 }
18775 break;
18776 case 1:
18777 if (rs == 1) {
18778 /* EMT */
18779 check_cp0_mt(ctx);
18780 gen_helper_emt(t0);
18781 gen_store_gpr(t0, rt);
18782 } else if (rs == 0) {
18783 /* EVPE */
18784 check_cp0_mt(ctx);
18785 gen_helper_evpe(t0, cpu_env);
18786 gen_store_gpr(t0, rt);
18787 } else {
18788 generate_exception_end(ctx, EXCP_RI);
18789 }
18790 break;
18791 }
18792
18793 tcg_temp_free(t0);
18794 }
18795 break;
18796 case NM_FORK:
18797 check_mt(ctx);
18798 {
18799 TCGv t0 = tcg_temp_new();
18800 TCGv t1 = tcg_temp_new();
18801
18802 gen_load_gpr(t0, rt);
18803 gen_load_gpr(t1, rs);
18804 gen_helper_fork(t0, t1);
18805 tcg_temp_free(t0);
18806 tcg_temp_free(t1);
18807 }
18808 break;
18809 case NM_MFTR:
18810 case NM_MFHTR:
18811 check_cp0_enabled(ctx);
18812 if (rd == 0) {
18813 /* Treat as NOP. */
18814 return;
18815 }
18816 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18817 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18818 break;
18819 case NM_MTTR:
18820 case NM_MTHTR:
18821 check_cp0_enabled(ctx);
18822 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18823 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18824 break;
18825 case NM_YIELD:
18826 check_mt(ctx);
18827 {
18828 TCGv t0 = tcg_temp_new();
18829
18830 gen_load_gpr(t0, rs);
18831 gen_helper_yield(t0, cpu_env, t0);
18832 gen_store_gpr(t0, rt);
18833 tcg_temp_free(t0);
18834 }
18835 break;
e0cf0e65
YK
18836#endif
18837 default:
18838 generate_exception_end(ctx, EXCP_RI);
18839 break;
18840 }
18841}
18842
2ed42efa
SM
18843/* dsp */
18844static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18845 int ret, int v1, int v2)
18846{
18847 TCGv_i32 t0;
18848 TCGv v0_t;
18849 TCGv v1_t;
18850
18851 t0 = tcg_temp_new_i32();
18852
18853 v0_t = tcg_temp_new();
18854 v1_t = tcg_temp_new();
18855
18856 tcg_gen_movi_i32(t0, v2 >> 3);
18857
18858 gen_load_gpr(v0_t, ret);
18859 gen_load_gpr(v1_t, v1);
18860
18861 switch (opc) {
18862 case NM_MAQ_S_W_PHR:
18863 check_dsp(ctx);
18864 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18865 break;
18866 case NM_MAQ_S_W_PHL:
18867 check_dsp(ctx);
18868 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18869 break;
18870 case NM_MAQ_SA_W_PHR:
18871 check_dsp(ctx);
18872 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18873 break;
18874 case NM_MAQ_SA_W_PHL:
18875 check_dsp(ctx);
18876 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18877 break;
18878 default:
18879 generate_exception_end(ctx, EXCP_RI);
18880 break;
18881 }
18882
18883 tcg_temp_free_i32(t0);
18884
18885 tcg_temp_free(v0_t);
18886 tcg_temp_free(v1_t);
18887}
18888
18889
18890static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18891 int ret, int v1, int v2)
18892{
18893 int16_t imm;
18894 TCGv t0 = tcg_temp_new();
18895 TCGv t1 = tcg_temp_new();
18896 TCGv v0_t = tcg_temp_new();
18897
18898 gen_load_gpr(v0_t, v1);
18899
18900 switch (opc) {
18901 case NM_POOL32AXF_1_0:
18902 check_dsp(ctx);
18903 switch (extract32(ctx->opcode, 12, 2)) {
18904 case NM_MFHI:
18905 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18906 break;
18907 case NM_MFLO:
18908 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18909 break;
18910 case NM_MTHI:
18911 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18912 break;
18913 case NM_MTLO:
18914 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18915 break;
18916 }
18917 break;
18918 case NM_POOL32AXF_1_1:
18919 check_dsp(ctx);
18920 switch (extract32(ctx->opcode, 12, 2)) {
18921 case NM_MTHLIP:
18922 tcg_gen_movi_tl(t0, v2);
18923 gen_helper_mthlip(t0, v0_t, cpu_env);
18924 break;
18925 case NM_SHILOV:
18926 tcg_gen_movi_tl(t0, v2 >> 3);
18927 gen_helper_shilo(t0, v0_t, cpu_env);
18928 break;
18929 default:
18930 generate_exception_end(ctx, EXCP_RI);
18931 break;
18932 }
18933 break;
18934 case NM_POOL32AXF_1_3:
18935 check_dsp(ctx);
18936 imm = extract32(ctx->opcode, 14, 7);
18937 switch (extract32(ctx->opcode, 12, 2)) {
18938 case NM_RDDSP:
18939 tcg_gen_movi_tl(t0, imm);
18940 gen_helper_rddsp(t0, t0, cpu_env);
18941 gen_store_gpr(t0, ret);
18942 break;
18943 case NM_WRDSP:
18944 gen_load_gpr(t0, ret);
18945 tcg_gen_movi_tl(t1, imm);
18946 gen_helper_wrdsp(t0, t1, cpu_env);
18947 break;
18948 case NM_EXTP:
18949 tcg_gen_movi_tl(t0, v2 >> 3);
18950 tcg_gen_movi_tl(t1, v1);
18951 gen_helper_extp(t0, t0, t1, cpu_env);
18952 gen_store_gpr(t0, ret);
18953 break;
18954 case NM_EXTPDP:
18955 tcg_gen_movi_tl(t0, v2 >> 3);
18956 tcg_gen_movi_tl(t1, v1);
18957 gen_helper_extpdp(t0, t0, t1, cpu_env);
18958 gen_store_gpr(t0, ret);
18959 break;
18960 }
18961 break;
18962 case NM_POOL32AXF_1_4:
18963 check_dsp(ctx);
18964 tcg_gen_movi_tl(t0, v2 >> 2);
18965 switch (extract32(ctx->opcode, 12, 1)) {
18966 case NM_SHLL_QB:
18967 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18968 gen_store_gpr(t0, ret);
18969 break;
18970 case NM_SHRL_QB:
18971 gen_helper_shrl_qb(t0, t0, v0_t);
18972 gen_store_gpr(t0, ret);
18973 break;
18974 }
18975 break;
18976 case NM_POOL32AXF_1_5:
18977 opc = extract32(ctx->opcode, 12, 2);
18978 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18979 break;
18980 case NM_POOL32AXF_1_7:
18981 check_dsp(ctx);
18982 tcg_gen_movi_tl(t0, v2 >> 3);
18983 tcg_gen_movi_tl(t1, v1);
18984 switch (extract32(ctx->opcode, 12, 2)) {
18985 case NM_EXTR_W:
18986 gen_helper_extr_w(t0, t0, t1, cpu_env);
18987 gen_store_gpr(t0, ret);
18988 break;
18989 case NM_EXTR_R_W:
18990 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18991 gen_store_gpr(t0, ret);
18992 break;
18993 case NM_EXTR_RS_W:
18994 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18995 gen_store_gpr(t0, ret);
18996 break;
18997 case NM_EXTR_S_H:
18998 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18999 gen_store_gpr(t0, ret);
19000 break;
19001 }
19002 break;
19003 default:
19004 generate_exception_end(ctx, EXCP_RI);
19005 break;
19006 }
19007
19008 tcg_temp_free(t0);
19009 tcg_temp_free(t1);
19010 tcg_temp_free(v0_t);
19011}
19012
8b3698b2
SM
19013static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19014 TCGv v0, TCGv v1, int rd)
19015{
19016 TCGv_i32 t0;
19017
19018 t0 = tcg_temp_new_i32();
19019
19020 tcg_gen_movi_i32(t0, rd >> 3);
19021
19022 switch (opc) {
19023 case NM_POOL32AXF_2_0_7:
19024 switch (extract32(ctx->opcode, 9, 3)) {
19025 case NM_DPA_W_PH:
908f6be1 19026 check_dsp_r2(ctx);
8b3698b2
SM
19027 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19028 break;
19029 case NM_DPAQ_S_W_PH:
19030 check_dsp(ctx);
19031 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19032 break;
19033 case NM_DPS_W_PH:
908f6be1 19034 check_dsp_r2(ctx);
8b3698b2
SM
19035 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19036 break;
19037 case NM_DPSQ_S_W_PH:
19038 check_dsp(ctx);
19039 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19040 break;
19041 default:
19042 generate_exception_end(ctx, EXCP_RI);
19043 break;
19044 }
19045 break;
19046 case NM_POOL32AXF_2_8_15:
19047 switch (extract32(ctx->opcode, 9, 3)) {
19048 case NM_DPAX_W_PH:
908f6be1 19049 check_dsp_r2(ctx);
8b3698b2
SM
19050 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19051 break;
19052 case NM_DPAQ_SA_L_W:
19053 check_dsp(ctx);
19054 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19055 break;
19056 case NM_DPSX_W_PH:
908f6be1 19057 check_dsp_r2(ctx);
8b3698b2
SM
19058 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19059 break;
19060 case NM_DPSQ_SA_L_W:
19061 check_dsp(ctx);
19062 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19063 break;
19064 default:
19065 generate_exception_end(ctx, EXCP_RI);
19066 break;
19067 }
19068 break;
19069 case NM_POOL32AXF_2_16_23:
19070 switch (extract32(ctx->opcode, 9, 3)) {
19071 case NM_DPAU_H_QBL:
19072 check_dsp(ctx);
19073 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19074 break;
19075 case NM_DPAQX_S_W_PH:
908f6be1 19076 check_dsp_r2(ctx);
8b3698b2
SM
19077 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19078 break;
19079 case NM_DPSU_H_QBL:
19080 check_dsp(ctx);
19081 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19082 break;
19083 case NM_DPSQX_S_W_PH:
908f6be1 19084 check_dsp_r2(ctx);
8b3698b2
SM
19085 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19086 break;
19087 case NM_MULSA_W_PH:
908f6be1 19088 check_dsp_r2(ctx);
8b3698b2
SM
19089 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19090 break;
19091 default:
19092 generate_exception_end(ctx, EXCP_RI);
19093 break;
19094 }
19095 break;
19096 case NM_POOL32AXF_2_24_31:
19097 switch (extract32(ctx->opcode, 9, 3)) {
19098 case NM_DPAU_H_QBR:
19099 check_dsp(ctx);
19100 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19101 break;
19102 case NM_DPAQX_SA_W_PH:
908f6be1 19103 check_dsp_r2(ctx);
8b3698b2
SM
19104 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19105 break;
19106 case NM_DPSU_H_QBR:
19107 check_dsp(ctx);
19108 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19109 break;
19110 case NM_DPSQX_SA_W_PH:
908f6be1 19111 check_dsp_r2(ctx);
8b3698b2
SM
19112 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19113 break;
19114 case NM_MULSAQ_S_W_PH:
19115 check_dsp(ctx);
19116 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19117 break;
19118 default:
19119 generate_exception_end(ctx, EXCP_RI);
19120 break;
19121 }
19122 break;
19123 default:
19124 generate_exception_end(ctx, EXCP_RI);
19125 break;
19126 }
19127
19128 tcg_temp_free_i32(t0);
19129}
19130
19131static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19132 int rt, int rs, int rd)
19133{
19134 int ret = rt;
19135 TCGv t0 = tcg_temp_new();
19136 TCGv t1 = tcg_temp_new();
19137 TCGv v0_t = tcg_temp_new();
19138 TCGv v1_t = tcg_temp_new();
19139
19140 gen_load_gpr(v0_t, rt);
19141 gen_load_gpr(v1_t, rs);
19142
19143 switch (opc) {
19144 case NM_POOL32AXF_2_0_7:
19145 switch (extract32(ctx->opcode, 9, 3)) {
19146 case NM_DPA_W_PH:
19147 case NM_DPAQ_S_W_PH:
19148 case NM_DPS_W_PH:
19149 case NM_DPSQ_S_W_PH:
19150 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19151 break;
19152 case NM_BALIGN:
908f6be1 19153 check_dsp_r2(ctx);
8b3698b2
SM
19154 if (rt != 0) {
19155 gen_load_gpr(t0, rs);
19156 rd &= 3;
19157 if (rd != 0 && rd != 2) {
19158 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19159 tcg_gen_ext32u_tl(t0, t0);
19160 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19161 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19162 }
19163 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19164 }
19165 break;
19166 case NM_MADD:
19167 check_dsp(ctx);
19168 {
19169 int acc = extract32(ctx->opcode, 14, 2);
19170 TCGv_i64 t2 = tcg_temp_new_i64();
19171 TCGv_i64 t3 = tcg_temp_new_i64();
19172
19173 gen_load_gpr(t0, rt);
19174 gen_load_gpr(t1, rs);
19175 tcg_gen_ext_tl_i64(t2, t0);
19176 tcg_gen_ext_tl_i64(t3, t1);
19177 tcg_gen_mul_i64(t2, t2, t3);
19178 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19179 tcg_gen_add_i64(t2, t2, t3);
19180 tcg_temp_free_i64(t3);
19181 gen_move_low32(cpu_LO[acc], t2);
19182 gen_move_high32(cpu_HI[acc], t2);
19183 tcg_temp_free_i64(t2);
19184 }
19185 break;
19186 case NM_MULT:
19187 check_dsp(ctx);
19188 {
19189 int acc = extract32(ctx->opcode, 14, 2);
19190 TCGv_i32 t2 = tcg_temp_new_i32();
19191 TCGv_i32 t3 = tcg_temp_new_i32();
19192
19193 gen_load_gpr(t0, rs);
19194 gen_load_gpr(t1, rt);
19195 tcg_gen_trunc_tl_i32(t2, t0);
19196 tcg_gen_trunc_tl_i32(t3, t1);
19197 tcg_gen_muls2_i32(t2, t3, t2, t3);
19198 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19199 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19200 tcg_temp_free_i32(t2);
19201 tcg_temp_free_i32(t3);
19202 }
19203 break;
19204 case NM_EXTRV_W:
19205 check_dsp(ctx);
19206 gen_load_gpr(v1_t, rs);
19207 tcg_gen_movi_tl(t0, rd >> 3);
19208 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19209 gen_store_gpr(t0, ret);
19210 break;
19211 }
19212 break;
19213 case NM_POOL32AXF_2_8_15:
19214 switch (extract32(ctx->opcode, 9, 3)) {
19215 case NM_DPAX_W_PH:
19216 case NM_DPAQ_SA_L_W:
19217 case NM_DPSX_W_PH:
19218 case NM_DPSQ_SA_L_W:
19219 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19220 break;
19221 case NM_MADDU:
19222 check_dsp(ctx);
19223 {
19224 int acc = extract32(ctx->opcode, 14, 2);
19225 TCGv_i64 t2 = tcg_temp_new_i64();
19226 TCGv_i64 t3 = tcg_temp_new_i64();
19227
19228 gen_load_gpr(t0, rs);
19229 gen_load_gpr(t1, rt);
19230 tcg_gen_ext32u_tl(t0, t0);
19231 tcg_gen_ext32u_tl(t1, t1);
19232 tcg_gen_extu_tl_i64(t2, t0);
19233 tcg_gen_extu_tl_i64(t3, t1);
19234 tcg_gen_mul_i64(t2, t2, t3);
19235 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19236 tcg_gen_add_i64(t2, t2, t3);
19237 tcg_temp_free_i64(t3);
19238 gen_move_low32(cpu_LO[acc], t2);
19239 gen_move_high32(cpu_HI[acc], t2);
19240 tcg_temp_free_i64(t2);
19241 }
19242 break;
19243 case NM_MULTU:
19244 check_dsp(ctx);
19245 {
19246 int acc = extract32(ctx->opcode, 14, 2);
19247 TCGv_i32 t2 = tcg_temp_new_i32();
19248 TCGv_i32 t3 = tcg_temp_new_i32();
19249
19250 gen_load_gpr(t0, rs);
19251 gen_load_gpr(t1, rt);
19252 tcg_gen_trunc_tl_i32(t2, t0);
19253 tcg_gen_trunc_tl_i32(t3, t1);
19254 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19255 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19256 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19257 tcg_temp_free_i32(t2);
19258 tcg_temp_free_i32(t3);
19259 }
19260 break;
19261 case NM_EXTRV_R_W:
19262 check_dsp(ctx);
19263 tcg_gen_movi_tl(t0, rd >> 3);
19264 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19265 gen_store_gpr(t0, ret);
19266 break;
19267 default:
19268 generate_exception_end(ctx, EXCP_RI);
19269 break;
19270 }
19271 break;
19272 case NM_POOL32AXF_2_16_23:
19273 switch (extract32(ctx->opcode, 9, 3)) {
19274 case NM_DPAU_H_QBL:
19275 case NM_DPAQX_S_W_PH:
19276 case NM_DPSU_H_QBL:
19277 case NM_DPSQX_S_W_PH:
19278 case NM_MULSA_W_PH:
19279 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19280 break;
19281 case NM_EXTPV:
19282 check_dsp(ctx);
19283 tcg_gen_movi_tl(t0, rd >> 3);
19284 gen_helper_extp(t0, t0, v1_t, cpu_env);
19285 gen_store_gpr(t0, ret);
19286 break;
19287 case NM_MSUB:
19288 check_dsp(ctx);
19289 {
19290 int acc = extract32(ctx->opcode, 14, 2);
19291 TCGv_i64 t2 = tcg_temp_new_i64();
19292 TCGv_i64 t3 = tcg_temp_new_i64();
19293
19294 gen_load_gpr(t0, rs);
19295 gen_load_gpr(t1, rt);
19296 tcg_gen_ext_tl_i64(t2, t0);
19297 tcg_gen_ext_tl_i64(t3, t1);
19298 tcg_gen_mul_i64(t2, t2, t3);
19299 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19300 tcg_gen_sub_i64(t2, t3, t2);
19301 tcg_temp_free_i64(t3);
19302 gen_move_low32(cpu_LO[acc], t2);
19303 gen_move_high32(cpu_HI[acc], t2);
19304 tcg_temp_free_i64(t2);
19305 }
19306 break;
19307 case NM_EXTRV_RS_W:
19308 check_dsp(ctx);
19309 tcg_gen_movi_tl(t0, rd >> 3);
19310 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19311 gen_store_gpr(t0, ret);
19312 break;
19313 }
19314 break;
19315 case NM_POOL32AXF_2_24_31:
19316 switch (extract32(ctx->opcode, 9, 3)) {
19317 case NM_DPAU_H_QBR:
19318 case NM_DPAQX_SA_W_PH:
19319 case NM_DPSU_H_QBR:
19320 case NM_DPSQX_SA_W_PH:
19321 case NM_MULSAQ_S_W_PH:
19322 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19323 break;
19324 case NM_EXTPDPV:
19325 check_dsp(ctx);
19326 tcg_gen_movi_tl(t0, rd >> 3);
19327 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19328 gen_store_gpr(t0, ret);
19329 break;
19330 case NM_MSUBU:
19331 check_dsp(ctx);
19332 {
19333 int acc = extract32(ctx->opcode, 14, 2);
19334 TCGv_i64 t2 = tcg_temp_new_i64();
19335 TCGv_i64 t3 = tcg_temp_new_i64();
19336
19337 gen_load_gpr(t0, rs);
19338 gen_load_gpr(t1, rt);
19339 tcg_gen_ext32u_tl(t0, t0);
19340 tcg_gen_ext32u_tl(t1, t1);
19341 tcg_gen_extu_tl_i64(t2, t0);
19342 tcg_gen_extu_tl_i64(t3, t1);
19343 tcg_gen_mul_i64(t2, t2, t3);
19344 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19345 tcg_gen_sub_i64(t2, t3, t2);
19346 tcg_temp_free_i64(t3);
19347 gen_move_low32(cpu_LO[acc], t2);
19348 gen_move_high32(cpu_HI[acc], t2);
19349 tcg_temp_free_i64(t2);
19350 }
19351 break;
19352 case NM_EXTRV_S_H:
19353 check_dsp(ctx);
19354 tcg_gen_movi_tl(t0, rd >> 3);
19355 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19356 gen_store_gpr(t0, ret);
19357 break;
19358 }
19359 break;
19360 default:
19361 generate_exception_end(ctx, EXCP_RI);
19362 break;
19363 }
19364
19365 tcg_temp_free(t0);
19366 tcg_temp_free(t1);
19367
19368 tcg_temp_free(v0_t);
19369 tcg_temp_free(v1_t);
19370}
19371
4c75c985
SM
19372static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19373 int rt, int rs)
19374{
19375 int ret = rt;
19376 TCGv t0 = tcg_temp_new();
19377 TCGv v0_t = tcg_temp_new();
19378
19379 gen_load_gpr(v0_t, rs);
19380
19381 switch (opc) {
19382 case NM_ABSQ_S_QB:
908f6be1 19383 check_dsp_r2(ctx);
4c75c985
SM
19384 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19385 gen_store_gpr(v0_t, ret);
19386 break;
19387 case NM_ABSQ_S_PH:
19388 check_dsp(ctx);
19389 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19390 gen_store_gpr(v0_t, ret);
19391 break;
19392 case NM_ABSQ_S_W:
19393 check_dsp(ctx);
19394 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19395 gen_store_gpr(v0_t, ret);
19396 break;
19397 case NM_PRECEQ_W_PHL:
19398 check_dsp(ctx);
19399 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19400 tcg_gen_ext32s_tl(v0_t, v0_t);
19401 gen_store_gpr(v0_t, ret);
19402 break;
19403 case NM_PRECEQ_W_PHR:
19404 check_dsp(ctx);
19405 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19406 tcg_gen_shli_tl(v0_t, v0_t, 16);
19407 tcg_gen_ext32s_tl(v0_t, v0_t);
19408 gen_store_gpr(v0_t, ret);
19409 break;
19410 case NM_PRECEQU_PH_QBL:
19411 check_dsp(ctx);
19412 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19413 gen_store_gpr(v0_t, ret);
19414 break;
19415 case NM_PRECEQU_PH_QBR:
19416 check_dsp(ctx);
19417 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19418 gen_store_gpr(v0_t, ret);
19419 break;
19420 case NM_PRECEQU_PH_QBLA:
19421 check_dsp(ctx);
19422 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19423 gen_store_gpr(v0_t, ret);
19424 break;
19425 case NM_PRECEQU_PH_QBRA:
19426 check_dsp(ctx);
19427 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19428 gen_store_gpr(v0_t, ret);
19429 break;
19430 case NM_PRECEU_PH_QBL:
19431 check_dsp(ctx);
19432 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19433 gen_store_gpr(v0_t, ret);
19434 break;
19435 case NM_PRECEU_PH_QBR:
19436 check_dsp(ctx);
19437 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19438 gen_store_gpr(v0_t, ret);
19439 break;
19440 case NM_PRECEU_PH_QBLA:
19441 check_dsp(ctx);
19442 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19443 gen_store_gpr(v0_t, ret);
19444 break;
19445 case NM_PRECEU_PH_QBRA:
19446 check_dsp(ctx);
19447 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19448 gen_store_gpr(v0_t, ret);
19449 break;
19450 case NM_REPLV_PH:
19451 check_dsp(ctx);
19452 tcg_gen_ext16u_tl(v0_t, v0_t);
19453 tcg_gen_shli_tl(t0, v0_t, 16);
19454 tcg_gen_or_tl(v0_t, v0_t, t0);
19455 tcg_gen_ext32s_tl(v0_t, v0_t);
19456 gen_store_gpr(v0_t, ret);
19457 break;
19458 case NM_REPLV_QB:
19459 check_dsp(ctx);
19460 tcg_gen_ext8u_tl(v0_t, v0_t);
19461 tcg_gen_shli_tl(t0, v0_t, 8);
19462 tcg_gen_or_tl(v0_t, v0_t, t0);
19463 tcg_gen_shli_tl(t0, v0_t, 16);
19464 tcg_gen_or_tl(v0_t, v0_t, t0);
19465 tcg_gen_ext32s_tl(v0_t, v0_t);
19466 gen_store_gpr(v0_t, ret);
19467 break;
19468 case NM_BITREV:
19469 check_dsp(ctx);
19470 gen_helper_bitrev(v0_t, v0_t);
19471 gen_store_gpr(v0_t, ret);
19472 break;
19473 case NM_INSV:
19474 check_dsp(ctx);
19475 {
19476 TCGv tv0 = tcg_temp_new();
19477
19478 gen_load_gpr(tv0, rt);
19479 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19480 gen_store_gpr(v0_t, ret);
19481 tcg_temp_free(tv0);
19482 }
19483 break;
19484 case NM_RADDU_W_QB:
19485 check_dsp(ctx);
19486 gen_helper_raddu_w_qb(v0_t, v0_t);
19487 gen_store_gpr(v0_t, ret);
19488 break;
19489 case NM_BITSWAP:
19490 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19491 break;
19492 case NM_CLO:
fb32f8c8 19493 check_nms(ctx);
4c75c985
SM
19494 gen_cl(ctx, OPC_CLO, ret, rs);
19495 break;
19496 case NM_CLZ:
fb32f8c8 19497 check_nms(ctx);
4c75c985
SM
19498 gen_cl(ctx, OPC_CLZ, ret, rs);
19499 break;
19500 case NM_WSBH:
19501 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19502 break;
19503 default:
19504 generate_exception_end(ctx, EXCP_RI);
19505 break;
19506 }
19507
19508 tcg_temp_free(v0_t);
19509 tcg_temp_free(t0);
19510}
19511
0b591184
SM
19512static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19513 int rt, int rs, int rd)
19514{
19515 TCGv t0 = tcg_temp_new();
19516 TCGv rs_t = tcg_temp_new();
19517
19518 gen_load_gpr(rs_t, rs);
19519
19520 switch (opc) {
19521 case NM_SHRA_R_QB:
908f6be1 19522 check_dsp_r2(ctx);
0b591184
SM
19523 tcg_gen_movi_tl(t0, rd >> 2);
19524 switch (extract32(ctx->opcode, 12, 1)) {
19525 case 0:
19526 /* NM_SHRA_QB */
19527 gen_helper_shra_qb(t0, t0, rs_t);
19528 gen_store_gpr(t0, rt);
19529 break;
19530 case 1:
19531 /* NM_SHRA_R_QB */
19532 gen_helper_shra_r_qb(t0, t0, rs_t);
19533 gen_store_gpr(t0, rt);
19534 break;
19535 }
19536 break;
19537 case NM_SHRL_PH:
908f6be1 19538 check_dsp_r2(ctx);
0b591184
SM
19539 tcg_gen_movi_tl(t0, rd >> 1);
19540 gen_helper_shrl_ph(t0, t0, rs_t);
19541 gen_store_gpr(t0, rt);
19542 break;
19543 case NM_REPL_QB:
19544 check_dsp(ctx);
19545 {
19546 int16_t imm;
19547 target_long result;
19548 imm = extract32(ctx->opcode, 13, 8);
19549 result = (uint32_t)imm << 24 |
19550 (uint32_t)imm << 16 |
19551 (uint32_t)imm << 8 |
19552 (uint32_t)imm;
19553 result = (int32_t)result;
19554 tcg_gen_movi_tl(t0, result);
19555 gen_store_gpr(t0, rt);
19556 }
19557 break;
19558 default:
19559 generate_exception_end(ctx, EXCP_RI);
19560 break;
19561 }
19562 tcg_temp_free(t0);
19563 tcg_temp_free(rs_t);
19564}
19565
2ed42efa 19566
64224187
YK
19567static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19568{
64224187
YK
19569 int rt = extract32(ctx->opcode, 21, 5);
19570 int rs = extract32(ctx->opcode, 16, 5);
2ed42efa 19571 int rd = extract32(ctx->opcode, 11, 5);
64224187
YK
19572
19573 switch (extract32(ctx->opcode, 6, 3)) {
2ed42efa
SM
19574 case NM_POOL32AXF_1:
19575 {
19576 int32_t op1 = extract32(ctx->opcode, 9, 3);
19577 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19578 }
19579 break;
19580 case NM_POOL32AXF_2:
8b3698b2
SM
19581 {
19582 int32_t op1 = extract32(ctx->opcode, 12, 2);
19583 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19584 }
2ed42efa 19585 break;
64224187 19586 case NM_POOL32AXF_4:
4c75c985
SM
19587 {
19588 int32_t op1 = extract32(ctx->opcode, 9, 7);
19589 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19590 }
2ed42efa 19591 break;
64224187
YK
19592 case NM_POOL32AXF_5:
19593 switch (extract32(ctx->opcode, 9, 7)) {
19594#ifndef CONFIG_USER_ONLY
19595 case NM_TLBP:
19596 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19597 break;
19598 case NM_TLBR:
19599 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19600 break;
19601 case NM_TLBWI:
19602 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19603 break;
19604 case NM_TLBWR:
19605 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19606 break;
19607 case NM_TLBINV:
19608 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19609 break;
19610 case NM_TLBINVF:
19611 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19612 break;
19613 case NM_DI:
19614 check_cp0_enabled(ctx);
19615 {
19616 TCGv t0 = tcg_temp_new();
19617
19618 save_cpu_state(ctx, 1);
19619 gen_helper_di(t0, cpu_env);
19620 gen_store_gpr(t0, rt);
19621 /* Stop translation as we may have switched the execution mode */
19622 ctx->base.is_jmp = DISAS_STOP;
19623 tcg_temp_free(t0);
19624 }
19625 break;
19626 case NM_EI:
19627 check_cp0_enabled(ctx);
19628 {
19629 TCGv t0 = tcg_temp_new();
19630
19631 save_cpu_state(ctx, 1);
19632 gen_helper_ei(t0, cpu_env);
19633 gen_store_gpr(t0, rt);
19634 /* Stop translation as we may have switched the execution mode */
19635 ctx->base.is_jmp = DISAS_STOP;
19636 tcg_temp_free(t0);
19637 }
19638 break;
19639 case NM_RDPGPR:
19640 gen_load_srsgpr(rs, rt);
19641 break;
19642 case NM_WRPGPR:
19643 gen_store_srsgpr(rs, rt);
19644 break;
19645 case NM_WAIT:
19646 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19647 break;
19648 case NM_DERET:
19649 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19650 break;
19651 case NM_ERETX:
19652 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19653 break;
19654#endif
19655 default:
19656 generate_exception_end(ctx, EXCP_RI);
19657 break;
19658 }
19659 break;
2ed42efa 19660 case NM_POOL32AXF_7:
0b591184
SM
19661 {
19662 int32_t op1 = extract32(ctx->opcode, 9, 3);
19663 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19664 }
2ed42efa 19665 break;
64224187
YK
19666 default:
19667 generate_exception_end(ctx, EXCP_RI);
19668 break;
19669 }
19670}
19671
11d0fc10
SM
19672/* Immediate Value Compact Branches */
19673static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19674 int rt, int32_t imm, int32_t offset)
19675{
19676 TCGCond cond;
19677 int bcond_compute = 0;
19678 TCGv t0 = tcg_temp_new();
19679 TCGv t1 = tcg_temp_new();
19680
19681 gen_load_gpr(t0, rt);
19682 tcg_gen_movi_tl(t1, imm);
19683 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19684
19685 /* Load needed operands and calculate btarget */
19686 switch (opc) {
19687 case NM_BEQIC:
19688 if (rt == 0 && imm == 0) {
19689 /* Unconditional branch */
19690 } else if (rt == 0 && imm != 0) {
19691 /* Treat as NOP */
19692 goto out;
19693 } else {
19694 bcond_compute = 1;
19695 cond = TCG_COND_EQ;
19696 }
19697 break;
19698 case NM_BBEQZC:
19699 case NM_BBNEZC:
fb32f8c8 19700 check_nms(ctx);
11d0fc10
SM
19701 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19702 generate_exception_end(ctx, EXCP_RI);
19703 goto out;
19704 } else if (rt == 0 && opc == NM_BBEQZC) {
19705 /* Unconditional branch */
19706 } else if (rt == 0 && opc == NM_BBNEZC) {
19707 /* Treat as NOP */
19708 goto out;
19709 } else {
19710 tcg_gen_shri_tl(t0, t0, imm);
19711 tcg_gen_andi_tl(t0, t0, 1);
19712 tcg_gen_movi_tl(t1, 0);
19713 bcond_compute = 1;
19714 if (opc == NM_BBEQZC) {
19715 cond = TCG_COND_EQ;
19716 } else {
19717 cond = TCG_COND_NE;
19718 }
19719 }
19720 break;
19721 case NM_BNEIC:
19722 if (rt == 0 && imm == 0) {
19723 /* Treat as NOP */
19724 goto out;
19725 } else if (rt == 0 && imm != 0) {
19726 /* Unconditional branch */
19727 } else {
19728 bcond_compute = 1;
19729 cond = TCG_COND_NE;
19730 }
19731 break;
19732 case NM_BGEIC:
19733 if (rt == 0 && imm == 0) {
19734 /* Unconditional branch */
19735 } else {
19736 bcond_compute = 1;
19737 cond = TCG_COND_GE;
19738 }
19739 break;
19740 case NM_BLTIC:
19741 bcond_compute = 1;
19742 cond = TCG_COND_LT;
19743 break;
19744 case NM_BGEIUC:
19745 if (rt == 0 && imm == 0) {
19746 /* Unconditional branch */
19747 } else {
19748 bcond_compute = 1;
19749 cond = TCG_COND_GEU;
19750 }
19751 break;
19752 case NM_BLTIUC:
19753 bcond_compute = 1;
19754 cond = TCG_COND_LTU;
19755 break;
19756 default:
19757 MIPS_INVAL("Immediate Value Compact branch");
19758 generate_exception_end(ctx, EXCP_RI);
19759 goto out;
19760 }
19761
19762 if (bcond_compute == 0) {
19763 /* Uncoditional compact branch */
19764 gen_goto_tb(ctx, 0, ctx->btarget);
19765 } else {
19766 /* Conditional compact branch */
19767 TCGLabel *fs = gen_new_label();
19768
19769 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19770
19771 gen_goto_tb(ctx, 1, ctx->btarget);
19772 gen_set_label(fs);
19773
19774 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19775 }
19776
19777out:
19778 tcg_temp_free(t0);
19779 tcg_temp_free(t1);
19780}
19781
19782/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19783static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19784 int rt)
19785{
19786 TCGv t0 = tcg_temp_new();
19787 TCGv t1 = tcg_temp_new();
19788
19789 /* load rs */
19790 gen_load_gpr(t0, rs);
19791
19792 /* link */
19793 if (rt != 0) {
19794 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19795 }
19796
19797 /* calculate btarget */
19798 tcg_gen_shli_tl(t0, t0, 1);
19799 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19800 gen_op_addr_add(ctx, btarget, t1, t0);
19801
19802 /* unconditional branch to register */
19803 tcg_gen_mov_tl(cpu_PC, btarget);
19804 tcg_gen_lookup_and_goto_ptr();
19805
19806 tcg_temp_free(t0);
19807 tcg_temp_free(t1);
19808}
19809
19810/* nanoMIPS Branches */
19811static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19812 int rs, int rt, int32_t offset)
19813{
19814 int bcond_compute = 0;
19815 TCGv t0 = tcg_temp_new();
19816 TCGv t1 = tcg_temp_new();
19817
19818 /* Load needed operands and calculate btarget */
19819 switch (opc) {
19820 /* compact branch */
19821 case OPC_BGEC:
19822 case OPC_BLTC:
19823 gen_load_gpr(t0, rs);
19824 gen_load_gpr(t1, rt);
19825 bcond_compute = 1;
19826 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19827 break;
19828 case OPC_BGEUC:
19829 case OPC_BLTUC:
19830 if (rs == 0 || rs == rt) {
19831 /* OPC_BLEZALC, OPC_BGEZALC */
19832 /* OPC_BGTZALC, OPC_BLTZALC */
19833 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19834 }
19835 gen_load_gpr(t0, rs);
19836 gen_load_gpr(t1, rt);
19837 bcond_compute = 1;
19838 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19839 break;
19840 case OPC_BC:
19841 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19842 break;
19843 case OPC_BEQZC:
19844 if (rs != 0) {
19845 /* OPC_BEQZC, OPC_BNEZC */
19846 gen_load_gpr(t0, rs);
19847 bcond_compute = 1;
19848 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19849 } else {
19850 /* OPC_JIC, OPC_JIALC */
19851 TCGv tbase = tcg_temp_new();
19852 TCGv toffset = tcg_temp_new();
19853
19854 gen_load_gpr(tbase, rt);
19855 tcg_gen_movi_tl(toffset, offset);
19856 gen_op_addr_add(ctx, btarget, tbase, toffset);
19857 tcg_temp_free(tbase);
19858 tcg_temp_free(toffset);
19859 }
19860 break;
19861 default:
19862 MIPS_INVAL("Compact branch/jump");
19863 generate_exception_end(ctx, EXCP_RI);
19864 goto out;
19865 }
19866
19867 if (bcond_compute == 0) {
19868 /* Uncoditional compact branch */
19869 switch (opc) {
19870 case OPC_BC:
19871 gen_goto_tb(ctx, 0, ctx->btarget);
19872 break;
19873 default:
19874 MIPS_INVAL("Compact branch/jump");
19875 generate_exception_end(ctx, EXCP_RI);
19876 goto out;
19877 }
19878 } else {
19879 /* Conditional compact branch */
19880 TCGLabel *fs = gen_new_label();
19881
19882 switch (opc) {
19883 case OPC_BGEUC:
19884 if (rs == 0 && rt != 0) {
19885 /* OPC_BLEZALC */
19886 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19887 } else if (rs != 0 && rt != 0 && rs == rt) {
19888 /* OPC_BGEZALC */
19889 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19890 } else {
19891 /* OPC_BGEUC */
19892 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19893 }
19894 break;
19895 case OPC_BLTUC:
19896 if (rs == 0 && rt != 0) {
19897 /* OPC_BGTZALC */
19898 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19899 } else if (rs != 0 && rt != 0 && rs == rt) {
19900 /* OPC_BLTZALC */
19901 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19902 } else {
19903 /* OPC_BLTUC */
19904 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19905 }
19906 break;
19907 case OPC_BGEC:
19908 if (rs == 0 && rt != 0) {
19909 /* OPC_BLEZC */
19910 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19911 } else if (rs != 0 && rt != 0 && rs == rt) {
19912 /* OPC_BGEZC */
19913 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19914 } else {
19915 /* OPC_BGEC */
19916 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19917 }
19918 break;
19919 case OPC_BLTC:
19920 if (rs == 0 && rt != 0) {
19921 /* OPC_BGTZC */
19922 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19923 } else if (rs != 0 && rt != 0 && rs == rt) {
19924 /* OPC_BLTZC */
19925 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19926 } else {
19927 /* OPC_BLTC */
19928 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19929 }
19930 break;
19931 case OPC_BEQZC:
19932 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19933 break;
19934 default:
19935 MIPS_INVAL("Compact conditional branch/jump");
19936 generate_exception_end(ctx, EXCP_RI);
19937 goto out;
19938 }
19939
19940 /* Generating branch here as compact branches don't have delay slot */
19941 gen_goto_tb(ctx, 1, ctx->btarget);
19942 gen_set_label(fs);
19943
19944 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19945 }
19946
19947out:
19948 tcg_temp_free(t0);
19949 tcg_temp_free(t1);
19950}
19951
19952
19953/* nanoMIPS CP1 Branches */
19954static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19955 int32_t ft, int32_t offset)
19956{
19957 target_ulong btarget;
19958 TCGv_i64 t0 = tcg_temp_new_i64();
19959
19960 gen_load_fpr64(ctx, t0, ft);
19961 tcg_gen_andi_i64(t0, t0, 1);
19962
19963 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19964
19965 switch (op) {
19966 case NM_BC1EQZC:
19967 tcg_gen_xori_i64(t0, t0, 1);
19968 ctx->hflags |= MIPS_HFLAG_BC;
19969 break;
19970 case NM_BC1NEZC:
19971 /* t0 already set */
19972 ctx->hflags |= MIPS_HFLAG_BC;
19973 break;
19974 default:
19975 MIPS_INVAL("cp1 cond branch");
19976 generate_exception_end(ctx, EXCP_RI);
19977 goto out;
19978 }
19979
19980 tcg_gen_trunc_i64_tl(bcond, t0);
19981
19982 ctx->btarget = btarget;
19983
19984out:
19985 tcg_temp_free_i64(t0);
19986}
19987
eac52664
YK
19988
19989static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19990{
19991 TCGv t0, t1;
19992 t0 = tcg_temp_new();
19993 t1 = tcg_temp_new();
19994
19995 gen_load_gpr(t0, rs);
19996 gen_load_gpr(t1, rt);
19997
19998 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19999 /* PP.LSXS instructions require shifting */
20000 switch (extract32(ctx->opcode, 7, 4)) {
eac52664 20001 case NM_SHXS:
fb32f8c8
DN
20002 check_nms(ctx);
20003 case NM_LHXS:
eac52664
YK
20004 case NM_LHUXS:
20005 tcg_gen_shli_tl(t0, t0, 1);
20006 break;
eac52664 20007 case NM_SWXS:
fb32f8c8
DN
20008 check_nms(ctx);
20009 case NM_LWXS:
eac52664
YK
20010 case NM_LWC1XS:
20011 case NM_SWC1XS:
20012 tcg_gen_shli_tl(t0, t0, 2);
20013 break;
20014 case NM_LDC1XS:
20015 case NM_SDC1XS:
20016 tcg_gen_shli_tl(t0, t0, 3);
20017 break;
20018 }
20019 }
20020 gen_op_addr_add(ctx, t0, t0, t1);
20021
20022 switch (extract32(ctx->opcode, 7, 4)) {
20023 case NM_LBX:
20024 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20025 MO_SB);
20026 gen_store_gpr(t0, rd);
20027 break;
20028 case NM_LHX:
20029 /*case NM_LHXS:*/
20030 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20031 MO_TESW);
20032 gen_store_gpr(t0, rd);
20033 break;
20034 case NM_LWX:
20035 /*case NM_LWXS:*/
20036 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20037 MO_TESL);
20038 gen_store_gpr(t0, rd);
20039 break;
20040 case NM_LBUX:
20041 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20042 MO_UB);
20043 gen_store_gpr(t0, rd);
20044 break;
20045 case NM_LHUX:
20046 /*case NM_LHUXS:*/
20047 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20048 MO_TEUW);
20049 gen_store_gpr(t0, rd);
20050 break;
20051 case NM_SBX:
fb32f8c8 20052 check_nms(ctx);
eac52664
YK
20053 gen_load_gpr(t1, rd);
20054 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20055 MO_8);
20056 break;
20057 case NM_SHX:
20058 /*case NM_SHXS:*/
fb32f8c8 20059 check_nms(ctx);
eac52664
YK
20060 gen_load_gpr(t1, rd);
20061 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20062 MO_TEUW);
20063 break;
20064 case NM_SWX:
20065 /*case NM_SWXS:*/
fb32f8c8 20066 check_nms(ctx);
eac52664
YK
20067 gen_load_gpr(t1, rd);
20068 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20069 MO_TEUL);
20070 break;
20071 case NM_LWC1X:
20072 /*case NM_LWC1XS:*/
20073 case NM_LDC1X:
20074 /*case NM_LDC1XS:*/
20075 case NM_SWC1X:
20076 /*case NM_SWC1XS:*/
20077 case NM_SDC1X:
20078 /*case NM_SDC1XS:*/
20079 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20080 check_cp1_enabled(ctx);
20081 switch (extract32(ctx->opcode, 7, 4)) {
20082 case NM_LWC1X:
20083 /*case NM_LWC1XS:*/
20084 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20085 break;
20086 case NM_LDC1X:
20087 /*case NM_LDC1XS:*/
20088 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20089 break;
20090 case NM_SWC1X:
20091 /*case NM_SWC1XS:*/
20092 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20093 break;
20094 case NM_SDC1X:
20095 /*case NM_SDC1XS:*/
20096 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20097 break;
20098 }
20099 } else {
20100 generate_exception_err(ctx, EXCP_CpU, 1);
20101 }
20102 break;
20103 default:
20104 generate_exception_end(ctx, EXCP_RI);
20105 break;
20106 }
20107
20108 tcg_temp_free(t0);
20109 tcg_temp_free(t1);
20110}
20111
579b8ea9
YK
20112static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20113{
20114 int rt, rs, rd;
20115
20116 rt = extract32(ctx->opcode, 21, 5);
20117 rs = extract32(ctx->opcode, 16, 5);
20118 rd = extract32(ctx->opcode, 11, 5);
20119
20120 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20121 generate_exception_end(ctx, EXCP_RI);
20122 return;
20123 }
20124 check_cp1_enabled(ctx);
20125 switch (extract32(ctx->opcode, 0, 3)) {
20126 case NM_POOL32F_0:
20127 switch (extract32(ctx->opcode, 3, 7)) {
20128 case NM_RINT_S:
20129 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20130 break;
20131 case NM_RINT_D:
20132 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20133 break;
20134 case NM_CLASS_S:
20135 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20136 break;
20137 case NM_CLASS_D:
20138 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20139 break;
20140 case NM_ADD_S:
20141 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20142 break;
20143 case NM_ADD_D:
20144 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20145 break;
20146 case NM_SUB_S:
20147 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20148 break;
20149 case NM_SUB_D:
20150 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20151 break;
20152 case NM_MUL_S:
20153 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20154 break;
20155 case NM_MUL_D:
20156 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20157 break;
20158 case NM_DIV_S:
20159 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20160 break;
20161 case NM_DIV_D:
20162 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20163 break;
20164 case NM_SELEQZ_S:
20165 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20166 break;
20167 case NM_SELEQZ_D:
20168 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20169 break;
20170 case NM_SELNEZ_S:
20171 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20172 break;
20173 case NM_SELNEZ_D:
20174 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20175 break;
20176 case NM_SEL_S:
20177 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20178 break;
20179 case NM_SEL_D:
20180 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20181 break;
20182 case NM_MADDF_S:
20183 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20184 break;
20185 case NM_MADDF_D:
20186 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20187 break;
20188 case NM_MSUBF_S:
20189 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20190 break;
20191 case NM_MSUBF_D:
20192 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20193 break;
20194 default:
20195 generate_exception_end(ctx, EXCP_RI);
20196 break;
20197 }
20198 break;
20199 case NM_POOL32F_3:
20200 switch (extract32(ctx->opcode, 3, 3)) {
20201 case NM_MIN_FMT:
20202 switch (extract32(ctx->opcode, 9, 1)) {
20203 case FMT_SDPS_S:
20204 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20205 break;
20206 case FMT_SDPS_D:
20207 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20208 break;
20209 }
20210 break;
20211 case NM_MAX_FMT:
20212 switch (extract32(ctx->opcode, 9, 1)) {
20213 case FMT_SDPS_S:
20214 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20215 break;
20216 case FMT_SDPS_D:
20217 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20218 break;
20219 }
20220 break;
20221 case NM_MINA_FMT:
20222 switch (extract32(ctx->opcode, 9, 1)) {
20223 case FMT_SDPS_S:
20224 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20225 break;
20226 case FMT_SDPS_D:
20227 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20228 break;
20229 }
20230 break;
20231 case NM_MAXA_FMT:
20232 switch (extract32(ctx->opcode, 9, 1)) {
20233 case FMT_SDPS_S:
20234 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20235 break;
20236 case FMT_SDPS_D:
20237 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20238 break;
20239 }
20240 break;
20241 case NM_POOL32FXF:
20242 switch (extract32(ctx->opcode, 6, 8)) {
20243 case NM_CFC1:
20244 gen_cp1(ctx, OPC_CFC1, rt, rs);
20245 break;
20246 case NM_CTC1:
20247 gen_cp1(ctx, OPC_CTC1, rt, rs);
20248 break;
20249 case NM_MFC1:
20250 gen_cp1(ctx, OPC_MFC1, rt, rs);
20251 break;
20252 case NM_MTC1:
20253 gen_cp1(ctx, OPC_MTC1, rt, rs);
20254 break;
20255 case NM_MFHC1:
20256 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20257 break;
20258 case NM_MTHC1:
20259 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20260 break;
20261 case NM_CVT_S_PL:
20262 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20263 break;
20264 case NM_CVT_S_PU:
20265 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20266 break;
20267 default:
20268 switch (extract32(ctx->opcode, 6, 9)) {
20269 case NM_CVT_L_S:
20270 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20271 break;
20272 case NM_CVT_L_D:
20273 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20274 break;
20275 case NM_CVT_W_S:
20276 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20277 break;
20278 case NM_CVT_W_D:
20279 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20280 break;
20281 case NM_RSQRT_S:
20282 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20283 break;
20284 case NM_RSQRT_D:
20285 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20286 break;
20287 case NM_SQRT_S:
20288 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20289 break;
20290 case NM_SQRT_D:
20291 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20292 break;
20293 case NM_RECIP_S:
20294 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20295 break;
20296 case NM_RECIP_D:
20297 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20298 break;
20299 case NM_FLOOR_L_S:
20300 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20301 break;
20302 case NM_FLOOR_L_D:
20303 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20304 break;
20305 case NM_FLOOR_W_S:
20306 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20307 break;
20308 case NM_FLOOR_W_D:
20309 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20310 break;
20311 case NM_CEIL_L_S:
20312 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20313 break;
20314 case NM_CEIL_L_D:
20315 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20316 break;
20317 case NM_CEIL_W_S:
20318 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20319 break;
20320 case NM_CEIL_W_D:
20321 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20322 break;
20323 case NM_TRUNC_L_S:
20324 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20325 break;
20326 case NM_TRUNC_L_D:
20327 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20328 break;
20329 case NM_TRUNC_W_S:
20330 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20331 break;
20332 case NM_TRUNC_W_D:
20333 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20334 break;
20335 case NM_ROUND_L_S:
20336 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20337 break;
20338 case NM_ROUND_L_D:
20339 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20340 break;
20341 case NM_ROUND_W_S:
20342 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20343 break;
20344 case NM_ROUND_W_D:
20345 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20346 break;
20347 case NM_MOV_S:
20348 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20349 break;
20350 case NM_MOV_D:
20351 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20352 break;
20353 case NM_ABS_S:
20354 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20355 break;
20356 case NM_ABS_D:
20357 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20358 break;
20359 case NM_NEG_S:
20360 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20361 break;
20362 case NM_NEG_D:
20363 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20364 break;
20365 case NM_CVT_D_S:
20366 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20367 break;
20368 case NM_CVT_D_W:
20369 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20370 break;
20371 case NM_CVT_D_L:
20372 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20373 break;
20374 case NM_CVT_S_D:
20375 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20376 break;
20377 case NM_CVT_S_W:
20378 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20379 break;
20380 case NM_CVT_S_L:
20381 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20382 break;
20383 default:
20384 generate_exception_end(ctx, EXCP_RI);
20385 break;
20386 }
20387 break;
20388 }
20389 break;
20390 }
20391 break;
20392 case NM_POOL32F_5:
20393 switch (extract32(ctx->opcode, 3, 3)) {
20394 case NM_CMP_CONDN_S:
20395 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20396 break;
20397 case NM_CMP_CONDN_D:
20398 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20399 break;
20400 default:
20401 generate_exception_end(ctx, EXCP_RI);
20402 break;
20403 }
20404 break;
20405 default:
20406 generate_exception_end(ctx, EXCP_RI);
20407 break;
20408 }
20409}
20410
3285a3e4
SM
20411static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20412 int rd, int rs, int rt)
20413{
20414 int ret = rd;
20415 TCGv t0 = tcg_temp_new();
20416 TCGv v1_t = tcg_temp_new();
20417 TCGv v2_t = tcg_temp_new();
20418
20419 gen_load_gpr(v1_t, rs);
20420 gen_load_gpr(v2_t, rt);
20421
20422 switch (opc) {
20423 case NM_CMP_EQ_PH:
20424 check_dsp(ctx);
20425 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20426 break;
20427 case NM_CMP_LT_PH:
20428 check_dsp(ctx);
20429 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20430 break;
20431 case NM_CMP_LE_PH:
20432 check_dsp(ctx);
20433 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20434 break;
20435 case NM_CMPU_EQ_QB:
20436 check_dsp(ctx);
20437 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20438 break;
20439 case NM_CMPU_LT_QB:
20440 check_dsp(ctx);
20441 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20442 break;
20443 case NM_CMPU_LE_QB:
20444 check_dsp(ctx);
20445 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20446 break;
20447 case NM_CMPGU_EQ_QB:
20448 check_dsp(ctx);
20449 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20450 gen_store_gpr(v1_t, ret);
20451 break;
20452 case NM_CMPGU_LT_QB:
20453 check_dsp(ctx);
20454 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20455 gen_store_gpr(v1_t, ret);
20456 break;
20457 case NM_CMPGU_LE_QB:
20458 check_dsp(ctx);
20459 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20460 gen_store_gpr(v1_t, ret);
20461 break;
20462 case NM_CMPGDU_EQ_QB:
908f6be1 20463 check_dsp_r2(ctx);
3285a3e4
SM
20464 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20465 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20466 gen_store_gpr(v1_t, ret);
20467 break;
20468 case NM_CMPGDU_LT_QB:
908f6be1 20469 check_dsp_r2(ctx);
3285a3e4
SM
20470 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20471 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20472 gen_store_gpr(v1_t, ret);
20473 break;
20474 case NM_CMPGDU_LE_QB:
908f6be1 20475 check_dsp_r2(ctx);
3285a3e4
SM
20476 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20477 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20478 gen_store_gpr(v1_t, ret);
20479 break;
20480 case NM_PACKRL_PH:
20481 check_dsp(ctx);
20482 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20483 gen_store_gpr(v1_t, ret);
20484 break;
20485 case NM_PICK_QB:
20486 check_dsp(ctx);
20487 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20488 gen_store_gpr(v1_t, ret);
20489 break;
20490 case NM_PICK_PH:
20491 check_dsp(ctx);
20492 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20493 gen_store_gpr(v1_t, ret);
20494 break;
20495 case NM_ADDQ_S_W:
20496 check_dsp(ctx);
20497 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20498 gen_store_gpr(v1_t, ret);
20499 break;
20500 case NM_SUBQ_S_W:
20501 check_dsp(ctx);
20502 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20503 gen_store_gpr(v1_t, ret);
20504 break;
20505 case NM_ADDSC:
20506 check_dsp(ctx);
20507 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20508 gen_store_gpr(v1_t, ret);
20509 break;
20510 case NM_ADDWC:
20511 check_dsp(ctx);
20512 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20513 gen_store_gpr(v1_t, ret);
20514 break;
20515 case NM_ADDQ_S_PH:
20516 check_dsp(ctx);
20517 switch (extract32(ctx->opcode, 10, 1)) {
20518 case 0:
20519 /* ADDQ_PH */
20520 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20521 gen_store_gpr(v1_t, ret);
20522 break;
20523 case 1:
20524 /* ADDQ_S_PH */
20525 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20526 gen_store_gpr(v1_t, ret);
20527 break;
20528 }
20529 break;
20530 case NM_ADDQH_R_PH:
908f6be1 20531 check_dsp_r2(ctx);
3285a3e4
SM
20532 switch (extract32(ctx->opcode, 10, 1)) {
20533 case 0:
20534 /* ADDQH_PH */
20535 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20536 gen_store_gpr(v1_t, ret);
20537 break;
20538 case 1:
20539 /* ADDQH_R_PH */
20540 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20541 gen_store_gpr(v1_t, ret);
20542 break;
20543 }
20544 break;
20545 case NM_ADDQH_R_W:
908f6be1 20546 check_dsp_r2(ctx);
3285a3e4
SM
20547 switch (extract32(ctx->opcode, 10, 1)) {
20548 case 0:
20549 /* ADDQH_W */
20550 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20551 gen_store_gpr(v1_t, ret);
20552 break;
20553 case 1:
20554 /* ADDQH_R_W */
20555 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20556 gen_store_gpr(v1_t, ret);
20557 break;
20558 }
20559 break;
20560 case NM_ADDU_S_QB:
20561 check_dsp(ctx);
20562 switch (extract32(ctx->opcode, 10, 1)) {
20563 case 0:
20564 /* ADDU_QB */
20565 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20566 gen_store_gpr(v1_t, ret);
20567 break;
20568 case 1:
20569 /* ADDU_S_QB */
20570 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20571 gen_store_gpr(v1_t, ret);
20572 break;
20573 }
20574 break;
20575 case NM_ADDU_S_PH:
908f6be1 20576 check_dsp_r2(ctx);
3285a3e4
SM
20577 switch (extract32(ctx->opcode, 10, 1)) {
20578 case 0:
20579 /* ADDU_PH */
20580 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20581 gen_store_gpr(v1_t, ret);
20582 break;
20583 case 1:
20584 /* ADDU_S_PH */
20585 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20586 gen_store_gpr(v1_t, ret);
20587 break;
20588 }
20589 break;
20590 case NM_ADDUH_R_QB:
908f6be1 20591 check_dsp_r2(ctx);
3285a3e4
SM
20592 switch (extract32(ctx->opcode, 10, 1)) {
20593 case 0:
20594 /* ADDUH_QB */
20595 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20596 gen_store_gpr(v1_t, ret);
20597 break;
20598 case 1:
20599 /* ADDUH_R_QB */
20600 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20601 gen_store_gpr(v1_t, ret);
20602 break;
20603 }
20604 break;
20605 case NM_SHRAV_R_PH:
20606 check_dsp(ctx);
20607 switch (extract32(ctx->opcode, 10, 1)) {
20608 case 0:
20609 /* SHRAV_PH */
20610 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20611 gen_store_gpr(v1_t, ret);
20612 break;
20613 case 1:
20614 /* SHRAV_R_PH */
20615 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20616 gen_store_gpr(v1_t, ret);
20617 break;
20618 }
20619 break;
20620 case NM_SHRAV_R_QB:
908f6be1 20621 check_dsp_r2(ctx);
3285a3e4
SM
20622 switch (extract32(ctx->opcode, 10, 1)) {
20623 case 0:
20624 /* SHRAV_QB */
20625 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20626 gen_store_gpr(v1_t, ret);
20627 break;
20628 case 1:
20629 /* SHRAV_R_QB */
20630 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20631 gen_store_gpr(v1_t, ret);
20632 break;
20633 }
20634 break;
20635 case NM_SUBQ_S_PH:
20636 check_dsp(ctx);
20637 switch (extract32(ctx->opcode, 10, 1)) {
20638 case 0:
20639 /* SUBQ_PH */
20640 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20641 gen_store_gpr(v1_t, ret);
20642 break;
20643 case 1:
20644 /* SUBQ_S_PH */
20645 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20646 gen_store_gpr(v1_t, ret);
20647 break;
20648 }
20649 break;
20650 case NM_SUBQH_R_PH:
908f6be1 20651 check_dsp_r2(ctx);
3285a3e4
SM
20652 switch (extract32(ctx->opcode, 10, 1)) {
20653 case 0:
20654 /* SUBQH_PH */
20655 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20656 gen_store_gpr(v1_t, ret);
20657 break;
20658 case 1:
20659 /* SUBQH_R_PH */
20660 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20661 gen_store_gpr(v1_t, ret);
20662 break;
20663 }
20664 break;
20665 case NM_SUBQH_R_W:
908f6be1 20666 check_dsp_r2(ctx);
3285a3e4
SM
20667 switch (extract32(ctx->opcode, 10, 1)) {
20668 case 0:
20669 /* SUBQH_W */
20670 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20671 gen_store_gpr(v1_t, ret);
20672 break;
20673 case 1:
20674 /* SUBQH_R_W */
20675 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20676 gen_store_gpr(v1_t, ret);
20677 break;
20678 }
20679 break;
20680 case NM_SUBU_S_QB:
20681 check_dsp(ctx);
20682 switch (extract32(ctx->opcode, 10, 1)) {
20683 case 0:
20684 /* SUBU_QB */
20685 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20686 gen_store_gpr(v1_t, ret);
20687 break;
20688 case 1:
20689 /* SUBU_S_QB */
20690 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20691 gen_store_gpr(v1_t, ret);
20692 break;
20693 }
20694 break;
20695 case NM_SUBU_S_PH:
908f6be1 20696 check_dsp_r2(ctx);
3285a3e4
SM
20697 switch (extract32(ctx->opcode, 10, 1)) {
20698 case 0:
20699 /* SUBU_PH */
20700 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20701 gen_store_gpr(v1_t, ret);
20702 break;
20703 case 1:
20704 /* SUBU_S_PH */
20705 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20706 gen_store_gpr(v1_t, ret);
20707 break;
20708 }
20709 break;
20710 case NM_SUBUH_R_QB:
908f6be1 20711 check_dsp_r2(ctx);
3285a3e4
SM
20712 switch (extract32(ctx->opcode, 10, 1)) {
20713 case 0:
20714 /* SUBUH_QB */
20715 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20716 gen_store_gpr(v1_t, ret);
20717 break;
20718 case 1:
20719 /* SUBUH_R_QB */
20720 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20721 gen_store_gpr(v1_t, ret);
20722 break;
20723 }
20724 break;
20725 case NM_SHLLV_S_PH:
20726 check_dsp(ctx);
20727 switch (extract32(ctx->opcode, 10, 1)) {
20728 case 0:
20729 /* SHLLV_PH */
20730 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20731 gen_store_gpr(v1_t, ret);
20732 break;
20733 case 1:
20734 /* SHLLV_S_PH */
20735 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20736 gen_store_gpr(v1_t, ret);
20737 break;
20738 }
20739 break;
20740 case NM_PRECR_SRA_R_PH_W:
908f6be1 20741 check_dsp_r2(ctx);
3285a3e4
SM
20742 switch (extract32(ctx->opcode, 10, 1)) {
20743 case 0:
20744 /* PRECR_SRA_PH_W */
20745 {
20746 TCGv_i32 sa_t = tcg_const_i32(rd);
20747 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20748 cpu_gpr[rt]);
20749 gen_store_gpr(v1_t, rt);
20750 tcg_temp_free_i32(sa_t);
20751 }
20752 break;
20753 case 1:
20754 /* PRECR_SRA_R_PH_W */
20755 {
20756 TCGv_i32 sa_t = tcg_const_i32(rd);
20757 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20758 cpu_gpr[rt]);
20759 gen_store_gpr(v1_t, rt);
20760 tcg_temp_free_i32(sa_t);
20761 }
20762 break;
20763 }
20764 break;
20765 case NM_MULEU_S_PH_QBL:
20766 check_dsp(ctx);
20767 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20768 gen_store_gpr(v1_t, ret);
20769 break;
20770 case NM_MULEU_S_PH_QBR:
20771 check_dsp(ctx);
20772 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20773 gen_store_gpr(v1_t, ret);
20774 break;
20775 case NM_MULQ_RS_PH:
20776 check_dsp(ctx);
20777 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20778 gen_store_gpr(v1_t, ret);
20779 break;
20780 case NM_MULQ_S_PH:
908f6be1 20781 check_dsp_r2(ctx);
3285a3e4
SM
20782 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20783 gen_store_gpr(v1_t, ret);
20784 break;
20785 case NM_MULQ_RS_W:
908f6be1 20786 check_dsp_r2(ctx);
3285a3e4
SM
20787 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20788 gen_store_gpr(v1_t, ret);
20789 break;
20790 case NM_MULQ_S_W:
908f6be1 20791 check_dsp_r2(ctx);
3285a3e4
SM
20792 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20793 gen_store_gpr(v1_t, ret);
20794 break;
20795 case NM_APPEND:
908f6be1 20796 check_dsp_r2(ctx);
3285a3e4
SM
20797 gen_load_gpr(t0, rs);
20798 if (rd != 0) {
20799 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20800 }
20801 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20802 break;
20803 case NM_MODSUB:
20804 check_dsp(ctx);
20805 gen_helper_modsub(v1_t, v1_t, v2_t);
20806 gen_store_gpr(v1_t, ret);
20807 break;
20808 case NM_SHRAV_R_W:
20809 check_dsp(ctx);
20810 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20811 gen_store_gpr(v1_t, ret);
20812 break;
20813 case NM_SHRLV_PH:
908f6be1 20814 check_dsp_r2(ctx);
3285a3e4
SM
20815 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20816 gen_store_gpr(v1_t, ret);
20817 break;
20818 case NM_SHRLV_QB:
20819 check_dsp(ctx);
20820 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20821 gen_store_gpr(v1_t, ret);
20822 break;
20823 case NM_SHLLV_QB:
20824 check_dsp(ctx);
20825 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20826 gen_store_gpr(v1_t, ret);
20827 break;
20828 case NM_SHLLV_S_W:
20829 check_dsp(ctx);
20830 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20831 gen_store_gpr(v1_t, ret);
20832 break;
20833 case NM_SHILO:
20834 check_dsp(ctx);
20835 {
20836 TCGv tv0 = tcg_temp_new();
20837 TCGv tv1 = tcg_temp_new();
20838 int16_t imm = extract32(ctx->opcode, 16, 7);
20839
20840 tcg_gen_movi_tl(tv0, rd >> 3);
20841 tcg_gen_movi_tl(tv1, imm);
20842 gen_helper_shilo(tv0, tv1, cpu_env);
20843 }
20844 break;
20845 case NM_MULEQ_S_W_PHL:
20846 check_dsp(ctx);
20847 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20848 gen_store_gpr(v1_t, ret);
20849 break;
20850 case NM_MULEQ_S_W_PHR:
20851 check_dsp(ctx);
20852 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20853 gen_store_gpr(v1_t, ret);
20854 break;
20855 case NM_MUL_S_PH:
908f6be1 20856 check_dsp_r2(ctx);
3285a3e4
SM
20857 switch (extract32(ctx->opcode, 10, 1)) {
20858 case 0:
20859 /* MUL_PH */
20860 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20861 gen_store_gpr(v1_t, ret);
20862 break;
20863 case 1:
20864 /* MUL_S_PH */
20865 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20866 gen_store_gpr(v1_t, ret);
20867 break;
20868 }
20869 break;
20870 case NM_PRECR_QB_PH:
908f6be1 20871 check_dsp_r2(ctx);
3285a3e4
SM
20872 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20873 gen_store_gpr(v1_t, ret);
20874 break;
20875 case NM_PRECRQ_QB_PH:
20876 check_dsp(ctx);
20877 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20878 gen_store_gpr(v1_t, ret);
20879 break;
20880 case NM_PRECRQ_PH_W:
20881 check_dsp(ctx);
20882 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20883 gen_store_gpr(v1_t, ret);
20884 break;
20885 case NM_PRECRQ_RS_PH_W:
20886 check_dsp(ctx);
20887 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20888 gen_store_gpr(v1_t, ret);
20889 break;
20890 case NM_PRECRQU_S_QB_PH:
20891 check_dsp(ctx);
20892 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20893 gen_store_gpr(v1_t, ret);
20894 break;
20895 case NM_SHRA_R_W:
20896 check_dsp(ctx);
20897 tcg_gen_movi_tl(t0, rd);
20898 gen_helper_shra_r_w(v1_t, t0, v1_t);
20899 gen_store_gpr(v1_t, rt);
20900 break;
20901 case NM_SHRA_R_PH:
20902 check_dsp(ctx);
20903 tcg_gen_movi_tl(t0, rd >> 1);
20904 switch (extract32(ctx->opcode, 10, 1)) {
20905 case 0:
20906 /* SHRA_PH */
20907 gen_helper_shra_ph(v1_t, t0, v1_t);
3285a3e4 20908 gen_store_gpr(v1_t, rt);
d5ebcbaf 20909 break;
3285a3e4
SM
20910 case 1:
20911 /* SHRA_R_PH */
20912 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20913 gen_store_gpr(v1_t, rt);
20914 break;
20915 }
20916 break;
20917 case NM_SHLL_S_PH:
20918 check_dsp(ctx);
20919 tcg_gen_movi_tl(t0, rd >> 1);
20920 switch (extract32(ctx->opcode, 10, 2)) {
20921 case 0:
20922 /* SHLL_PH */
20923 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20924 gen_store_gpr(v1_t, rt);
20925 break;
20926 case 2:
20927 /* SHLL_S_PH */
20928 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20929 gen_store_gpr(v1_t, rt);
20930 break;
20931 default:
20932 generate_exception_end(ctx, EXCP_RI);
20933 break;
20934 }
20935 break;
20936 case NM_SHLL_S_W:
20937 check_dsp(ctx);
20938 tcg_gen_movi_tl(t0, rd);
20939 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20940 gen_store_gpr(v1_t, rt);
20941 break;
20942 case NM_REPL_PH:
20943 check_dsp(ctx);
20944 {
20945 int16_t imm;
20946 imm = sextract32(ctx->opcode, 11, 11);
20947 imm = (int16_t)(imm << 6) >> 6;
20948 if (rt != 0) {
20949 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20950 }
20951 }
20952 break;
20953 default:
20954 generate_exception_end(ctx, EXCP_RI);
20955 break;
20956 }
20957}
20958
c0280983
YK
20959static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20960{
20961 uint16_t insn;
20962 uint32_t op;
eac52664 20963 int rt, rs, rd;
c0280983
YK
20964 int offset;
20965 int imm;
20966
20967 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20968 ctx->opcode = (ctx->opcode << 16) | insn;
20969
20970 rt = extract32(ctx->opcode, 21, 5);
20971 rs = extract32(ctx->opcode, 16, 5);
eac52664 20972 rd = extract32(ctx->opcode, 11, 5);
c0280983
YK
20973
20974 op = extract32(ctx->opcode, 26, 6);
20975 switch (op) {
20976 case NM_P_ADDIU:
20977 if (rt == 0) {
20978 /* P.RI */
20979 switch (extract32(ctx->opcode, 19, 2)) {
20980 case NM_SIGRIE:
20981 default:
20982 generate_exception_end(ctx, EXCP_RI);
20983 break;
20984 case NM_P_SYSCALL:
20985 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20986 generate_exception_end(ctx, EXCP_SYSCALL);
20987 } else {
20988 generate_exception_end(ctx, EXCP_RI);
20989 }
20990 break;
20991 case NM_BREAK:
20992 generate_exception_end(ctx, EXCP_BREAK);
20993 break;
20994 case NM_SDBBP:
20995 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20996 gen_helper_do_semihosting(cpu_env);
20997 } else {
20998 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20999 generate_exception_end(ctx, EXCP_RI);
21000 } else {
21001 generate_exception_end(ctx, EXCP_DBp);
21002 }
21003 }
21004 break;
21005 }
21006 } else {
21007 /* NM_ADDIU */
21008 imm = extract32(ctx->opcode, 0, 16);
21009 if (rs != 0) {
21010 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21011 } else {
21012 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21013 }
21014 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21015 }
21016 break;
21017 case NM_ADDIUPC:
21018 if (rt != 0) {
21019 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21020 extract32(ctx->opcode, 1, 20) << 1;
21021 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21022 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21023 }
21024 break;
21025 case NM_POOL32A:
e0cf0e65
YK
21026 switch (ctx->opcode & 0x07) {
21027 case NM_POOL32A0:
0a1a6ed7 21028 gen_pool32a0_nanomips_insn(env, ctx);
e0cf0e65 21029 break;
3285a3e4
SM
21030 case NM_POOL32A5:
21031 {
21032 int32_t op1 = extract32(ctx->opcode, 3, 7);
21033 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21034 }
21035 break;
e0cf0e65 21036 case NM_POOL32A7:
64224187 21037 switch (extract32(ctx->opcode, 3, 3)) {
eac52664
YK
21038 case NM_P_LSX:
21039 gen_p_lsx(ctx, rd, rs, rt);
21040 break;
21041 case NM_LSA:
21042 /* In nanoMIPS, the shift field directly encodes the shift
21043 * amount, meaning that the supported shift values are in
21044 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
21045 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21046 extract32(ctx->opcode, 9, 2) - 1);
21047 break;
821f2008
JH
21048 case NM_EXTW:
21049 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21050 break;
64224187
YK
21051 case NM_POOL32AXF:
21052 gen_pool32axf_nanomips_insn(env, ctx);
21053 break;
21054 default:
21055 generate_exception_end(ctx, EXCP_RI);
21056 break;
21057 }
e0cf0e65
YK
21058 break;
21059 default:
21060 generate_exception_end(ctx, EXCP_RI);
21061 break;
21062 }
c0280983
YK
21063 break;
21064 case NM_P_GP_W:
21065 switch (ctx->opcode & 0x03) {
21066 case NM_ADDIUGP_W:
21067 if (rt != 0) {
21068 offset = extract32(ctx->opcode, 0, 21);
21069 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21070 }
21071 break;
21072 case NM_LWGP:
21073 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21074 break;
21075 case NM_SWGP:
21076 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21077 break;
21078 default:
21079 generate_exception_end(ctx, EXCP_RI);
21080 break;
21081 }
21082 break;
21083 case NM_P48I:
7ef009b2
YK
21084 {
21085 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21086 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21087 switch (extract32(ctx->opcode, 16, 5)) {
21088 case NM_LI48:
fb32f8c8 21089 check_nms(ctx);
7ef009b2
YK
21090 if (rt != 0) {
21091 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21092 }
21093 break;
21094 case NM_ADDIU48:
fb32f8c8 21095 check_nms(ctx);
7ef009b2
YK
21096 if (rt != 0) {
21097 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21098 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21099 }
21100 break;
21101 case NM_ADDIUGP48:
fb32f8c8 21102 check_nms(ctx);
7ef009b2
YK
21103 if (rt != 0) {
21104 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21105 }
21106 break;
21107 case NM_ADDIUPC48:
fb32f8c8 21108 check_nms(ctx);
7ef009b2
YK
21109 if (rt != 0) {
21110 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21111 addr_off);
21112
21113 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21114 }
21115 break;
21116 case NM_LWPC48:
fb32f8c8 21117 check_nms(ctx);
7ef009b2
YK
21118 if (rt != 0) {
21119 TCGv t0;
21120 t0 = tcg_temp_new();
21121
21122 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21123 addr_off);
21124
21125 tcg_gen_movi_tl(t0, addr);
21126 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21127 tcg_temp_free(t0);
21128 }
21129 break;
21130 case NM_SWPC48:
fb32f8c8 21131 check_nms(ctx);
7ef009b2
YK
21132 {
21133 TCGv t0, t1;
21134 t0 = tcg_temp_new();
21135 t1 = tcg_temp_new();
21136
21137 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21138 addr_off);
21139
21140 tcg_gen_movi_tl(t0, addr);
21141 gen_load_gpr(t1, rt);
21142
21143 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21144
21145 tcg_temp_free(t0);
21146 tcg_temp_free(t1);
21147 }
21148 break;
21149 default:
21150 generate_exception_end(ctx, EXCP_RI);
21151 break;
21152 }
21153 return 6;
21154 }
c0280983
YK
21155 case NM_P_U12:
21156 switch (extract32(ctx->opcode, 12, 4)) {
21157 case NM_ORI:
21158 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21159 break;
21160 case NM_XORI:
21161 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21162 break;
21163 case NM_ANDI:
21164 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21165 break;
21166 case NM_P_SR:
21167 switch (extract32(ctx->opcode, 20, 1)) {
21168 case NM_PP_SR:
21169 switch (ctx->opcode & 3) {
21170 case NM_SAVE:
21171 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21172 extract32(ctx->opcode, 2, 1),
21173 extract32(ctx->opcode, 3, 9) << 3);
21174 break;
21175 case NM_RESTORE:
21176 case NM_RESTORE_JRC:
21177 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21178 extract32(ctx->opcode, 2, 1),
21179 extract32(ctx->opcode, 3, 9) << 3);
21180 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21181 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21182 }
21183 break;
21184 default:
21185 generate_exception_end(ctx, EXCP_RI);
21186 break;
21187 }
21188 break;
21189 case NM_P_SR_F:
21190 generate_exception_end(ctx, EXCP_RI);
21191 break;
21192 }
21193 break;
21194 case NM_SLTI:
21195 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21196 break;
21197 case NM_SLTIU:
21198 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21199 break;
21200 case NM_SEQI:
21201 {
21202 TCGv t0 = tcg_temp_new();
21203
21204 imm = extract32(ctx->opcode, 0, 12);
21205 gen_load_gpr(t0, rs);
21206 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21207 gen_store_gpr(t0, rt);
21208
21209 tcg_temp_free(t0);
21210 }
21211 break;
21212 case NM_ADDIUNEG:
21213 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21214 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21215 break;
21216 case NM_P_SHIFT:
21217 {
21218 int shift = extract32(ctx->opcode, 0, 5);
21219 switch (extract32(ctx->opcode, 5, 4)) {
21220 case NM_P_SLL:
21221 if (rt == 0 && shift == 0) {
21222 /* NOP */
21223 } else if (rt == 0 && shift == 3) {
21224 /* EHB - treat as NOP */
21225 } else if (rt == 0 && shift == 5) {
21226 /* PAUSE - treat as NOP */
21227 } else if (rt == 0 && shift == 6) {
21228 /* SYNC */
21229 gen_sync(extract32(ctx->opcode, 16, 5));
21230 } else {
21231 /* SLL */
21232 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21233 extract32(ctx->opcode, 0, 5));
21234 }
21235 break;
21236 case NM_SRL:
21237 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21238 extract32(ctx->opcode, 0, 5));
21239 break;
21240 case NM_SRA:
21241 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21242 extract32(ctx->opcode, 0, 5));
21243 break;
21244 case NM_ROTR:
21245 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21246 extract32(ctx->opcode, 0, 5));
21247 break;
21248 }
21249 }
21250 break;
21251 case NM_P_ROTX:
fb32f8c8 21252 check_nms(ctx);
e222f506
MF
21253 if (rt != 0) {
21254 TCGv t0 = tcg_temp_new();
21255 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21256 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21257 << 1);
21258 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21259
21260 gen_load_gpr(t0, rs);
21261 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21262 tcg_temp_free(t0);
21263
21264 tcg_temp_free_i32(shift);
21265 tcg_temp_free_i32(shiftx);
21266 tcg_temp_free_i32(stripe);
21267 }
c0280983
YK
21268 break;
21269 case NM_P_INS:
21270 switch (((ctx->opcode >> 10) & 2) |
21271 (extract32(ctx->opcode, 5, 1))) {
21272 case NM_INS:
fb32f8c8 21273 check_nms(ctx);
c0280983
YK
21274 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21275 extract32(ctx->opcode, 6, 5));
21276 break;
21277 default:
21278 generate_exception_end(ctx, EXCP_RI);
21279 break;
21280 }
21281 break;
21282 case NM_P_EXT:
21283 switch (((ctx->opcode >> 10) & 2) |
21284 (extract32(ctx->opcode, 5, 1))) {
21285 case NM_EXT:
fb32f8c8 21286 check_nms(ctx);
c0280983
YK
21287 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21288 extract32(ctx->opcode, 6, 5));
21289 break;
21290 default:
21291 generate_exception_end(ctx, EXCP_RI);
21292 break;
21293 }
21294 break;
21295 default:
21296 generate_exception_end(ctx, EXCP_RI);
21297 break;
21298 }
21299 break;
21300 case NM_POOL32F:
579b8ea9 21301 gen_pool32f_nanomips_insn(ctx);
c0280983
YK
21302 break;
21303 case NM_POOL32S:
21304 break;
21305 case NM_P_LUI:
21306 switch (extract32(ctx->opcode, 1, 1)) {
21307 case NM_LUI:
21308 if (rt != 0) {
21309 tcg_gen_movi_tl(cpu_gpr[rt],
21310 sextract32(ctx->opcode, 0, 1) << 31 |
21311 extract32(ctx->opcode, 2, 10) << 21 |
21312 extract32(ctx->opcode, 12, 9) << 12);
21313 }
21314 break;
21315 case NM_ALUIPC:
21316 if (rt != 0) {
21317 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21318 extract32(ctx->opcode, 2, 10) << 21 |
21319 extract32(ctx->opcode, 12, 9) << 12;
21320 target_long addr;
21321 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21322 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21323 }
21324 break;
21325 }
21326 break;
21327 case NM_P_GP_BH:
8f1d9b6d
YK
21328 {
21329 uint32_t u = extract32(ctx->opcode, 0, 18);
21330
21331 switch (extract32(ctx->opcode, 18, 3)) {
21332 case NM_LBGP:
21333 gen_ld(ctx, OPC_LB, rt, 28, u);
21334 break;
21335 case NM_SBGP:
21336 gen_st(ctx, OPC_SB, rt, 28, u);
21337 break;
21338 case NM_LBUGP:
21339 gen_ld(ctx, OPC_LBU, rt, 28, u);
21340 break;
21341 case NM_ADDIUGP_B:
21342 if (rt != 0) {
21343 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21344 }
21345 break;
21346 case NM_P_GP_LH:
21347 u &= ~1;
21348 switch (ctx->opcode & 1) {
21349 case NM_LHGP:
21350 gen_ld(ctx, OPC_LH, rt, 28, u);
21351 break;
21352 case NM_LHUGP:
21353 gen_ld(ctx, OPC_LHU, rt, 28, u);
21354 break;
21355 }
21356 break;
21357 case NM_P_GP_SH:
21358 u &= ~1;
21359 switch (ctx->opcode & 1) {
21360 case NM_SHGP:
21361 gen_st(ctx, OPC_SH, rt, 28, u);
21362 break;
21363 default:
21364 generate_exception_end(ctx, EXCP_RI);
21365 break;
21366 }
21367 break;
21368 case NM_P_GP_CP1:
21369 u &= ~0x3;
21370 switch (ctx->opcode & 0x3) {
21371 case NM_LWC1GP:
21372 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21373 break;
21374 case NM_LDC1GP:
21375 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21376 break;
21377 case NM_SWC1GP:
21378 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21379 break;
21380 case NM_SDC1GP:
21381 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21382 break;
21383 }
21384 break;
21385 default:
21386 generate_exception_end(ctx, EXCP_RI);
21387 break;
21388 }
21389 }
c0280983
YK
21390 break;
21391 case NM_P_LS_U12:
8f1d9b6d
YK
21392 {
21393 uint32_t u = extract32(ctx->opcode, 0, 12);
21394
21395 switch (extract32(ctx->opcode, 12, 4)) {
21396 case NM_P_PREFU12:
21397 if (rt == 31) {
21398 /* SYNCI */
21399 /* Break the TB to be able to sync copied instructions
21400 immediately */
21401 ctx->base.is_jmp = DISAS_STOP;
21402 } else {
21403 /* PREF */
21404 /* Treat as NOP. */
21405 }
21406 break;
21407 case NM_LB:
21408 gen_ld(ctx, OPC_LB, rt, rs, u);
21409 break;
21410 case NM_LH:
21411 gen_ld(ctx, OPC_LH, rt, rs, u);
21412 break;
21413 case NM_LW:
21414 gen_ld(ctx, OPC_LW, rt, rs, u);
21415 break;
21416 case NM_LBU:
21417 gen_ld(ctx, OPC_LBU, rt, rs, u);
21418 break;
21419 case NM_LHU:
21420 gen_ld(ctx, OPC_LHU, rt, rs, u);
21421 break;
21422 case NM_SB:
21423 gen_st(ctx, OPC_SB, rt, rs, u);
21424 break;
21425 case NM_SH:
21426 gen_st(ctx, OPC_SH, rt, rs, u);
21427 break;
21428 case NM_SW:
21429 gen_st(ctx, OPC_SW, rt, rs, u);
21430 break;
21431 case NM_LWC1:
21432 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21433 break;
21434 case NM_LDC1:
21435 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21436 break;
21437 case NM_SWC1:
21438 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21439 break;
21440 case NM_SDC1:
21441 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21442 break;
21443 default:
21444 generate_exception_end(ctx, EXCP_RI);
21445 break;
21446 }
21447 }
c0280983
YK
21448 break;
21449 case NM_P_LS_S9:
8f1d9b6d
YK
21450 {
21451 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21452 extract32(ctx->opcode, 0, 8);
21453
21454 switch (extract32(ctx->opcode, 8, 3)) {
21455 case NM_P_LS_S0:
21456 switch (extract32(ctx->opcode, 11, 4)) {
21457 case NM_LBS9:
21458 gen_ld(ctx, OPC_LB, rt, rs, s);
21459 break;
21460 case NM_LHS9:
21461 gen_ld(ctx, OPC_LH, rt, rs, s);
21462 break;
21463 case NM_LWS9:
21464 gen_ld(ctx, OPC_LW, rt, rs, s);
21465 break;
21466 case NM_LBUS9:
21467 gen_ld(ctx, OPC_LBU, rt, rs, s);
21468 break;
21469 case NM_LHUS9:
21470 gen_ld(ctx, OPC_LHU, rt, rs, s);
21471 break;
21472 case NM_SBS9:
21473 gen_st(ctx, OPC_SB, rt, rs, s);
21474 break;
21475 case NM_SHS9:
21476 gen_st(ctx, OPC_SH, rt, rs, s);
21477 break;
21478 case NM_SWS9:
21479 gen_st(ctx, OPC_SW, rt, rs, s);
21480 break;
21481 case NM_LWC1S9:
21482 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21483 break;
21484 case NM_LDC1S9:
21485 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21486 break;
21487 case NM_SWC1S9:
21488 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21489 break;
21490 case NM_SDC1S9:
21491 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21492 break;
21493 case NM_P_PREFS9:
21494 if (rt == 31) {
21495 /* SYNCI */
21496 /* Break the TB to be able to sync copied instructions
21497 immediately */
21498 ctx->base.is_jmp = DISAS_STOP;
21499 } else {
21500 /* PREF */
21501 /* Treat as NOP. */
21502 }
21503 break;
21504 default:
21505 generate_exception_end(ctx, EXCP_RI);
21506 break;
21507 }
21508 break;
21509 case NM_P_LS_S1:
21510 switch (extract32(ctx->opcode, 11, 4)) {
21511 case NM_UALH:
21512 case NM_UASH:
fb32f8c8 21513 check_nms(ctx);
8f1d9b6d
YK
21514 {
21515 TCGv t0 = tcg_temp_new();
21516 TCGv t1 = tcg_temp_new();
21517
21518 gen_base_offset_addr(ctx, t0, rs, s);
21519
21520 switch (extract32(ctx->opcode, 11, 4)) {
21521 case NM_UALH:
21522 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21523 MO_UNALN);
21524 gen_store_gpr(t0, rt);
21525 break;
21526 case NM_UASH:
21527 gen_load_gpr(t1, rt);
21528 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21529 MO_UNALN);
21530 break;
21531 }
21532 tcg_temp_free(t0);
21533 tcg_temp_free(t1);
21534 }
21535 break;
21536 case NM_P_LL:
21537 switch (ctx->opcode & 0x03) {
21538 case NM_LL:
21539 gen_ld(ctx, OPC_LL, rt, rs, s);
21540 break;
21541 case NM_LLWP:
0b16dcd1
AR
21542 check_xnp(ctx);
21543 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
21544 break;
21545 }
21546 break;
21547 case NM_P_SC:
21548 switch (ctx->opcode & 0x03) {
21549 case NM_SC:
21550 gen_st_cond(ctx, OPC_SC, rt, rs, s);
21551 break;
21552 case NM_SCWP:
0b16dcd1
AR
21553 check_xnp(ctx);
21554 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
21555 break;
21556 }
21557 break;
21558 case NM_CACHE:
21559 check_cp0_enabled(ctx);
21560 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21561 gen_cache_operation(ctx, rt, rs, s);
21562 }
21563 break;
21564 }
21565 break;
d046a9ea
DN
21566 case NM_P_LS_E0:
21567 switch (extract32(ctx->opcode, 11, 4)) {
21568 case NM_LBE:
21569 check_eva(ctx);
21570 check_cp0_enabled(ctx);
21571 gen_ld(ctx, OPC_LBE, rt, rs, s);
21572 break;
21573 case NM_SBE:
21574 check_eva(ctx);
21575 check_cp0_enabled(ctx);
21576 gen_st(ctx, OPC_SBE, rt, rs, s);
21577 break;
21578 case NM_LBUE:
21579 check_eva(ctx);
21580 check_cp0_enabled(ctx);
21581 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21582 break;
21583 case NM_P_PREFE:
21584 if (rt == 31) {
21585 /* case NM_SYNCIE */
21586 check_eva(ctx);
21587 check_cp0_enabled(ctx);
21588 /* Break the TB to be able to sync copied instructions
21589 immediately */
21590 ctx->base.is_jmp = DISAS_STOP;
21591 } else {
21592 /* case NM_PREFE */
21593 check_eva(ctx);
21594 check_cp0_enabled(ctx);
21595 /* Treat as NOP. */
21596 }
21597 break;
21598 case NM_LHE:
21599 check_eva(ctx);
21600 check_cp0_enabled(ctx);
21601 gen_ld(ctx, OPC_LHE, rt, rs, s);
21602 break;
21603 case NM_SHE:
21604 check_eva(ctx);
21605 check_cp0_enabled(ctx);
21606 gen_st(ctx, OPC_SHE, rt, rs, s);
21607 break;
21608 case NM_LHUE:
21609 check_eva(ctx);
21610 check_cp0_enabled(ctx);
21611 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21612 break;
21613 case NM_CACHEE:
21614 check_nms_dl_il_sl_tl_l2c(ctx);
21615 gen_cache_operation(ctx, rt, rs, s);
21616 break;
21617 case NM_LWE:
21618 check_eva(ctx);
21619 check_cp0_enabled(ctx);
21620 gen_ld(ctx, OPC_LWE, rt, rs, s);
21621 break;
21622 case NM_SWE:
21623 check_eva(ctx);
21624 check_cp0_enabled(ctx);
21625 gen_st(ctx, OPC_SWE, rt, rs, s);
21626 break;
21627 case NM_P_LLE:
21628 switch (extract32(ctx->opcode, 2, 2)) {
21629 case NM_LLE:
21630 check_xnp(ctx);
21631 check_eva(ctx);
21632 check_cp0_enabled(ctx);
21633 gen_ld(ctx, OPC_LLE, rt, rs, s);
21634 break;
21635 case NM_LLWPE:
21636 check_xnp(ctx);
21637 check_eva(ctx);
21638 check_cp0_enabled(ctx);
21639 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
2431a422 21640 break;
d046a9ea
DN
21641 default:
21642 generate_exception_end(ctx, EXCP_RI);
21643 break;
21644 }
21645 break;
21646 case NM_P_SCE:
21647 switch (extract32(ctx->opcode, 2, 2)) {
21648 case NM_SCE:
21649 check_xnp(ctx);
21650 check_eva(ctx);
21651 check_cp0_enabled(ctx);
21652 gen_st_cond(ctx, OPC_SCE, rt, rs, s);
21653 break;
21654 case NM_SCWPE:
21655 check_xnp(ctx);
21656 check_eva(ctx);
21657 check_cp0_enabled(ctx);
21658 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
2431a422 21659 break;
d046a9ea
DN
21660 default:
21661 generate_exception_end(ctx, EXCP_RI);
21662 break;
21663 }
21664 break;
21665 }
21666 break;
8f1d9b6d
YK
21667 case NM_P_LS_WM:
21668 case NM_P_LS_UAWM:
fb32f8c8 21669 check_nms(ctx);
8f1d9b6d
YK
21670 {
21671 int count = extract32(ctx->opcode, 12, 3);
21672 int counter = 0;
21673
21674 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21675 extract32(ctx->opcode, 0, 8);
21676 TCGv va = tcg_temp_new();
21677 TCGv t1 = tcg_temp_new();
21678 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21679 NM_P_LS_UAWM ? MO_UNALN : 0;
21680
21681 count = (count == 0) ? 8 : count;
21682 while (counter != count) {
21683 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21684 int this_offset = offset + (counter << 2);
21685
21686 gen_base_offset_addr(ctx, va, rs, this_offset);
21687
21688 switch (extract32(ctx->opcode, 11, 1)) {
21689 case NM_LWM:
21690 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21691 memop | MO_TESL);
21692 gen_store_gpr(t1, this_rt);
21693 if ((this_rt == rs) &&
21694 (counter != (count - 1))) {
21695 /* UNPREDICTABLE */
21696 }
21697 break;
21698 case NM_SWM:
21699 this_rt = (rt == 0) ? 0 : this_rt;
21700 gen_load_gpr(t1, this_rt);
21701 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21702 memop | MO_TEUL);
21703 break;
21704 }
21705 counter++;
21706 }
21707 tcg_temp_free(va);
21708 tcg_temp_free(t1);
21709 }
21710 break;
21711 default:
21712 generate_exception_end(ctx, EXCP_RI);
21713 break;
21714 }
21715 }
c0280983
YK
21716 break;
21717 case NM_MOVE_BALC:
fb32f8c8 21718 check_nms(ctx);
11d0fc10
SM
21719 {
21720 TCGv t0 = tcg_temp_new();
21721 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21722 extract32(ctx->opcode, 1, 20) << 1;
21723 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21724 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21725 extract32(ctx->opcode, 21, 3));
21726 gen_load_gpr(t0, rt);
21727 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21728 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21729 tcg_temp_free(t0);
21730 }
c0280983
YK
21731 break;
21732 case NM_P_BAL:
11d0fc10
SM
21733 {
21734 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21735 extract32(ctx->opcode, 1, 24) << 1;
21736
21737 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21738 /* BC */
21739 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21740 } else {
21741 /* BALC */
21742 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21743 }
21744 }
c0280983
YK
21745 break;
21746 case NM_P_J:
11d0fc10
SM
21747 switch (extract32(ctx->opcode, 12, 4)) {
21748 case NM_JALRC:
21749 case NM_JALRC_HB:
21750 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21751 break;
21752 case NM_P_BALRSC:
21753 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21754 break;
21755 default:
21756 generate_exception_end(ctx, EXCP_RI);
21757 break;
21758 }
c0280983
YK
21759 break;
21760 case NM_P_BR1:
11d0fc10
SM
21761 {
21762 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21763 extract32(ctx->opcode, 1, 13) << 1;
21764 switch (extract32(ctx->opcode, 14, 2)) {
21765 case NM_BEQC:
fb32f8c8 21766 check_nms(ctx);
11d0fc10
SM
21767 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21768 break;
21769 case NM_P_BR3A:
21770 s = sextract32(ctx->opcode, 0, 1) << 14 |
21771 extract32(ctx->opcode, 1, 13) << 1;
21772 check_cp1_enabled(ctx);
21773 switch (extract32(ctx->opcode, 16, 5)) {
21774 case NM_BC1EQZC:
21775 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21776 break;
21777 case NM_BC1NEZC:
21778 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21779 break;
6d033ca7 21780 case NM_BPOSGE32C:
908f6be1 21781 check_dsp_r3(ctx);
6d033ca7
SM
21782 {
21783 int32_t imm = extract32(ctx->opcode, 1, 13) |
21784 extract32(ctx->opcode, 0, 1) << 13;
21785
21786 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21787 imm);
21788 }
21789 break;
11d0fc10
SM
21790 default:
21791 generate_exception_end(ctx, EXCP_RI);
21792 break;
21793 }
21794 break;
21795 case NM_BGEC:
21796 if (rs == rt) {
21797 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21798 } else {
21799 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21800 }
21801 break;
21802 case NM_BGEUC:
21803 if (rs == rt || rt == 0) {
21804 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21805 } else if (rs == 0) {
21806 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21807 } else {
21808 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21809 }
21810 break;
21811 }
21812 }
c0280983
YK
21813 break;
21814 case NM_P_BR2:
11d0fc10
SM
21815 {
21816 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21817 extract32(ctx->opcode, 1, 13) << 1;
21818 switch (extract32(ctx->opcode, 14, 2)) {
21819 case NM_BNEC:
fb32f8c8 21820 check_nms(ctx);
11d0fc10
SM
21821 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21822 break;
21823 case NM_BLTC:
21824 if (rs != 0 && rt != 0 && rs == rt) {
21825 /* NOP */
21826 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21827 } else {
21828 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21829 }
21830 break;
21831 case NM_BLTUC:
21832 if (rs == 0 || rs == rt) {
21833 /* NOP */
21834 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21835 } else {
21836 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21837 }
21838 break;
21839 default:
21840 generate_exception_end(ctx, EXCP_RI);
21841 break;
21842 }
21843 }
c0280983
YK
21844 break;
21845 case NM_P_BRI:
11d0fc10
SM
21846 {
21847 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21848 extract32(ctx->opcode, 1, 10) << 1;
21849 uint32_t u = extract32(ctx->opcode, 11, 7);
21850
21851 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21852 rt, u, s);
21853 }
c0280983
YK
21854 break;
21855 default:
21856 generate_exception_end(ctx, EXCP_RI);
21857 break;
21858 }
21859 return 4;
21860}
21861
c533c0f4
AM
21862static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21863{
ea4ca3c2
YK
21864 uint32_t op;
21865 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
21866 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21867 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
8bdb7029 21868 int offset;
ea4ca3c2
YK
21869 int imm;
21870
21871 /* make sure instructions are on a halfword boundary */
21872 if (ctx->base.pc_next & 0x1) {
21873 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21874 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21875 tcg_temp_free(tmp);
21876 generate_exception_end(ctx, EXCP_AdEL);
21877 return 2;
21878 }
21879
21880 op = extract32(ctx->opcode, 10, 6);
21881 switch (op) {
21882 case NM_P16_MV:
8869ad02
YK
21883 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21884 if (rt != 0) {
21885 /* MOVE */
21886 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21887 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21888 } else {
21889 /* P16.RI */
21890 switch (extract32(ctx->opcode, 3, 2)) {
21891 case NM_P16_SYSCALL:
21892 if (extract32(ctx->opcode, 2, 1) == 0) {
21893 generate_exception_end(ctx, EXCP_SYSCALL);
21894 } else {
21895 generate_exception_end(ctx, EXCP_RI);
21896 }
21897 break;
21898 case NM_BREAK16:
21899 generate_exception_end(ctx, EXCP_BREAK);
21900 break;
21901 case NM_SDBBP16:
21902 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21903 gen_helper_do_semihosting(cpu_env);
21904 } else {
21905 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21906 generate_exception_end(ctx, EXCP_RI);
21907 } else {
21908 generate_exception_end(ctx, EXCP_DBp);
21909 }
21910 }
21911 break;
21912 default:
21913 generate_exception_end(ctx, EXCP_RI);
21914 break;
21915 }
21916 }
ea4ca3c2
YK
21917 break;
21918 case NM_P16_SHIFT:
c46562fb
YK
21919 {
21920 int shift = extract32(ctx->opcode, 0, 3);
21921 uint32_t opc = 0;
21922 shift = (shift == 0) ? 8 : shift;
21923
21924 switch (extract32(ctx->opcode, 3, 1)) {
21925 case NM_SLL16:
21926 opc = OPC_SLL;
21927 break;
21928 case NM_SRL16:
21929 opc = OPC_SRL;
21930 break;
21931 }
21932 gen_shift_imm(ctx, opc, rt, rs, shift);
21933 }
ea4ca3c2
YK
21934 break;
21935 case NM_P16C:
8bdb7029
YK
21936 switch (ctx->opcode & 1) {
21937 case NM_POOL16C_0:
80845edf 21938 gen_pool16c_nanomips_insn(ctx);
8bdb7029
YK
21939 break;
21940 case NM_LWXS16:
21941 gen_ldxs(ctx, rt, rs, rd);
21942 break;
21943 }
ea4ca3c2
YK
21944 break;
21945 case NM_P16_A1:
21946 switch (extract32(ctx->opcode, 6, 1)) {
21947 case NM_ADDIUR1SP:
21948 imm = extract32(ctx->opcode, 0, 6) << 2;
21949 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21950 break;
21951 default:
21952 generate_exception_end(ctx, EXCP_RI);
21953 break;
21954 }
21955 break;
21956 case NM_P16_A2:
21957 switch (extract32(ctx->opcode, 3, 1)) {
21958 case NM_ADDIUR2:
21959 imm = extract32(ctx->opcode, 0, 3) << 2;
21960 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21961 break;
21962 case NM_P_ADDIURS5:
21963 rt = extract32(ctx->opcode, 5, 5);
21964 if (rt != 0) {
21965 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21966 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21967 (extract32(ctx->opcode, 0, 3));
21968 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21969 }
21970 break;
21971 }
21972 break;
21973 case NM_P16_ADDU:
21974 switch (ctx->opcode & 0x1) {
21975 case NM_ADDU16:
21976 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21977 break;
21978 case NM_SUBU16:
21979 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21980 break;
21981 }
21982 break;
21983 case NM_P16_4X4:
21984 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21985 extract32(ctx->opcode, 5, 3);
21986 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21987 extract32(ctx->opcode, 0, 3);
21988 rt = decode_gpr_gpr4(rt);
21989 rs = decode_gpr_gpr4(rs);
21990 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21991 (extract32(ctx->opcode, 3, 1))) {
21992 case NM_ADDU4X4:
fb32f8c8 21993 check_nms(ctx);
ea4ca3c2
YK
21994 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21995 break;
21996 case NM_MUL4X4:
fb32f8c8 21997 check_nms(ctx);
ea4ca3c2
YK
21998 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21999 break;
22000 default:
22001 generate_exception_end(ctx, EXCP_RI);
22002 break;
22003 }
22004 break;
22005 case NM_LI16:
8869ad02
YK
22006 {
22007 int imm = extract32(ctx->opcode, 0, 7);
22008 imm = (imm == 0x7f ? -1 : imm);
22009 if (rt != 0) {
22010 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22011 }
22012 }
ea4ca3c2
YK
22013 break;
22014 case NM_ANDI16:
80845edf
YK
22015 {
22016 uint32_t u = extract32(ctx->opcode, 0, 4);
22017 u = (u == 12) ? 0xff :
22018 (u == 13) ? 0xffff : u;
22019 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22020 }
ea4ca3c2
YK
22021 break;
22022 case NM_P16_LB:
8bdb7029
YK
22023 offset = extract32(ctx->opcode, 0, 2);
22024 switch (extract32(ctx->opcode, 2, 2)) {
22025 case NM_LB16:
22026 gen_ld(ctx, OPC_LB, rt, rs, offset);
22027 break;
22028 case NM_SB16:
22029 rt = decode_gpr_gpr3_src_store(
22030 NANOMIPS_EXTRACT_RD(ctx->opcode));
22031 gen_st(ctx, OPC_SB, rt, rs, offset);
22032 break;
22033 case NM_LBU16:
22034 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22035 break;
22036 default:
22037 generate_exception_end(ctx, EXCP_RI);
22038 break;
22039 }
ea4ca3c2
YK
22040 break;
22041 case NM_P16_LH:
8bdb7029
YK
22042 offset = extract32(ctx->opcode, 1, 2) << 1;
22043 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22044 case NM_LH16:
22045 gen_ld(ctx, OPC_LH, rt, rs, offset);
22046 break;
22047 case NM_SH16:
22048 rt = decode_gpr_gpr3_src_store(
22049 NANOMIPS_EXTRACT_RD(ctx->opcode));
22050 gen_st(ctx, OPC_SH, rt, rs, offset);
22051 break;
22052 case NM_LHU16:
22053 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22054 break;
22055 default:
22056 generate_exception_end(ctx, EXCP_RI);
22057 break;
22058 }
ea4ca3c2
YK
22059 break;
22060 case NM_LW16:
8bdb7029
YK
22061 offset = extract32(ctx->opcode, 0, 4) << 2;
22062 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
22063 break;
22064 case NM_LWSP16:
8bdb7029
YK
22065 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22066 offset = extract32(ctx->opcode, 0, 5) << 2;
22067 gen_ld(ctx, OPC_LW, rt, 29, offset);
ea4ca3c2
YK
22068 break;
22069 case NM_LW4X4:
fb32f8c8 22070 check_nms(ctx);
8bdb7029
YK
22071 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22072 extract32(ctx->opcode, 5, 3);
22073 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22074 extract32(ctx->opcode, 0, 3);
22075 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22076 (extract32(ctx->opcode, 8, 1) << 2);
22077 rt = decode_gpr_gpr4(rt);
22078 rs = decode_gpr_gpr4(rs);
22079 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
22080 break;
22081 case NM_SW4X4:
fb32f8c8 22082 check_nms(ctx);
8bdb7029
YK
22083 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22084 extract32(ctx->opcode, 5, 3);
22085 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22086 extract32(ctx->opcode, 0, 3);
22087 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22088 (extract32(ctx->opcode, 8, 1) << 2);
22089 rt = decode_gpr_gpr4_zero(rt);
22090 rs = decode_gpr_gpr4(rs);
22091 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
22092 break;
22093 case NM_LWGP16:
8bdb7029
YK
22094 offset = extract32(ctx->opcode, 0, 7) << 2;
22095 gen_ld(ctx, OPC_LW, rt, 28, offset);
ea4ca3c2
YK
22096 break;
22097 case NM_SWSP16:
8bdb7029
YK
22098 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22099 offset = extract32(ctx->opcode, 0, 5) << 2;
22100 gen_st(ctx, OPC_SW, rt, 29, offset);
ea4ca3c2
YK
22101 break;
22102 case NM_SW16:
8bdb7029
YK
22103 rt = decode_gpr_gpr3_src_store(
22104 NANOMIPS_EXTRACT_RD(ctx->opcode));
22105 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
22106 offset = extract32(ctx->opcode, 0, 4) << 2;
22107 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
22108 break;
22109 case NM_SWGP16:
8bdb7029
YK
22110 rt = decode_gpr_gpr3_src_store(
22111 NANOMIPS_EXTRACT_RD(ctx->opcode));
22112 offset = extract32(ctx->opcode, 0, 7) << 2;
22113 gen_st(ctx, OPC_SW, rt, 28, offset);
ea4ca3c2
YK
22114 break;
22115 case NM_BC16:
764371d2
SM
22116 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22117 (sextract32(ctx->opcode, 0, 1) << 10) |
22118 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
22119 break;
22120 case NM_BALC16:
764371d2
SM
22121 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22122 (sextract32(ctx->opcode, 0, 1) << 10) |
22123 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
22124 break;
22125 case NM_BEQZC16:
764371d2
SM
22126 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22127 (sextract32(ctx->opcode, 0, 1) << 7) |
22128 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
22129 break;
22130 case NM_BNEZC16:
764371d2
SM
22131 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22132 (sextract32(ctx->opcode, 0, 1) << 7) |
22133 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
22134 break;
22135 case NM_P16_BR:
764371d2
SM
22136 switch (ctx->opcode & 0xf) {
22137 case 0:
22138 /* P16.JRC */
22139 switch (extract32(ctx->opcode, 4, 1)) {
22140 case NM_JRC:
22141 gen_compute_branch_nm(ctx, OPC_JR, 2,
22142 extract32(ctx->opcode, 5, 5), 0, 0);
22143 break;
22144 case NM_JALRC16:
22145 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22146 extract32(ctx->opcode, 5, 5), 31, 0);
22147 break;
22148 }
22149 break;
22150 default:
22151 {
22152 /* P16.BRI */
22153 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22154 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22155 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22156 extract32(ctx->opcode, 0, 4) << 1);
22157 }
22158 break;
22159 }
ea4ca3c2
YK
22160 break;
22161 case NM_P16_SR:
bf0718c5
SM
22162 {
22163 int count = extract32(ctx->opcode, 0, 4);
22164 int u = extract32(ctx->opcode, 4, 4) << 4;
22165
22166 rt = 30 + extract32(ctx->opcode, 9, 1);
22167 switch (extract32(ctx->opcode, 8, 1)) {
22168 case NM_SAVE16:
22169 gen_save(ctx, rt, count, 0, u);
22170 break;
22171 case NM_RESTORE_JRC16:
22172 gen_restore(ctx, rt, count, 0, u);
22173 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22174 break;
22175 }
22176 }
ea4ca3c2
YK
22177 break;
22178 case NM_MOVEP:
ea4ca3c2 22179 case NM_MOVEPREV:
fb32f8c8 22180 check_nms(ctx);
4d18232c
YK
22181 {
22182 static const int gpr2reg1[] = {4, 5, 6, 7};
22183 static const int gpr2reg2[] = {5, 6, 7, 8};
22184 int re;
22185 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22186 extract32(ctx->opcode, 8, 1);
22187 int r1 = gpr2reg1[rd2];
22188 int r2 = gpr2reg2[rd2];
22189 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22190 extract32(ctx->opcode, 0, 3);
22191 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22192 extract32(ctx->opcode, 5, 3);
22193 TCGv t0 = tcg_temp_new();
22194 TCGv t1 = tcg_temp_new();
22195 if (op == NM_MOVEP) {
22196 rd = r1;
22197 re = r2;
22198 rs = decode_gpr_gpr4_zero(r3);
22199 rt = decode_gpr_gpr4_zero(r4);
22200 } else {
22201 rd = decode_gpr_gpr4(r3);
22202 re = decode_gpr_gpr4(r4);
22203 rs = r1;
22204 rt = r2;
22205 }
22206 gen_load_gpr(t0, rs);
22207 gen_load_gpr(t1, rt);
22208 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22209 tcg_gen_mov_tl(cpu_gpr[re], t1);
22210 tcg_temp_free(t0);
22211 tcg_temp_free(t1);
22212 }
ea4ca3c2
YK
22213 break;
22214 default:
c0280983 22215 return decode_nanomips_32_48_opc(env, ctx);
ea4ca3c2
YK
22216 }
22217
c533c0f4
AM
22218 return 2;
22219}
22220
22221
3c824109
NF
22222/* SmartMIPS extension to MIPS32 */
22223
22224#if defined(TARGET_MIPS64)
22225
22226/* MDMX extension to MIPS64 */
22227
22228#endif
22229
9b1a1d68 22230/* MIPSDSP functions. */
d75c135e 22231static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
9b1a1d68
JL
22232 int rd, int base, int offset)
22233{
9b1a1d68
JL
22234 TCGv t0;
22235
9b1a1d68
JL
22236 check_dsp(ctx);
22237 t0 = tcg_temp_new();
22238
22239 if (base == 0) {
22240 gen_load_gpr(t0, offset);
22241 } else if (offset == 0) {
22242 gen_load_gpr(t0, base);
22243 } else {
22244 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22245 }
22246
9b1a1d68
JL
22247 switch (opc) {
22248 case OPC_LBUX:
5f68f5ae 22249 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
9b1a1d68 22250 gen_store_gpr(t0, rd);
9b1a1d68
JL
22251 break;
22252 case OPC_LHX:
5f68f5ae 22253 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
9b1a1d68 22254 gen_store_gpr(t0, rd);
9b1a1d68
JL
22255 break;
22256 case OPC_LWX:
5f68f5ae 22257 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9b1a1d68 22258 gen_store_gpr(t0, rd);
9b1a1d68
JL
22259 break;
22260#if defined(TARGET_MIPS64)
22261 case OPC_LDX:
5f68f5ae 22262 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
9b1a1d68 22263 gen_store_gpr(t0, rd);
9b1a1d68
JL
22264 break;
22265#endif
22266 }
9b1a1d68
JL
22267 tcg_temp_free(t0);
22268}
22269
461c08df
JL
22270static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22271 int ret, int v1, int v2)
22272{
461c08df
JL
22273 TCGv v1_t;
22274 TCGv v2_t;
22275
22276 if (ret == 0) {
22277 /* Treat as NOP. */
461c08df
JL
22278 return;
22279 }
22280
22281 v1_t = tcg_temp_new();
22282 v2_t = tcg_temp_new();
22283
22284 gen_load_gpr(v1_t, v1);
22285 gen_load_gpr(v2_t, v2);
22286
22287 switch (op1) {
22288 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22289 case OPC_MULT_G_2E:
908f6be1 22290 check_dsp_r2(ctx);
461c08df
JL
22291 switch (op2) {
22292 case OPC_ADDUH_QB:
22293 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22294 break;
22295 case OPC_ADDUH_R_QB:
22296 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22297 break;
22298 case OPC_ADDQH_PH:
22299 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22300 break;
22301 case OPC_ADDQH_R_PH:
22302 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22303 break;
22304 case OPC_ADDQH_W:
22305 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22306 break;
22307 case OPC_ADDQH_R_W:
22308 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22309 break;
22310 case OPC_SUBUH_QB:
22311 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22312 break;
22313 case OPC_SUBUH_R_QB:
22314 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22315 break;
22316 case OPC_SUBQH_PH:
22317 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22318 break;
22319 case OPC_SUBQH_R_PH:
22320 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22321 break;
22322 case OPC_SUBQH_W:
22323 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22324 break;
22325 case OPC_SUBQH_R_W:
22326 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22327 break;
22328 }
22329 break;
22330 case OPC_ABSQ_S_PH_DSP:
22331 switch (op2) {
22332 case OPC_ABSQ_S_QB:
908f6be1 22333 check_dsp_r2(ctx);
461c08df
JL
22334 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22335 break;
22336 case OPC_ABSQ_S_PH:
22337 check_dsp(ctx);
22338 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22339 break;
22340 case OPC_ABSQ_S_W:
22341 check_dsp(ctx);
22342 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22343 break;
22344 case OPC_PRECEQ_W_PHL:
22345 check_dsp(ctx);
22346 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22347 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22348 break;
22349 case OPC_PRECEQ_W_PHR:
22350 check_dsp(ctx);
22351 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22352 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22353 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22354 break;
22355 case OPC_PRECEQU_PH_QBL:
22356 check_dsp(ctx);
22357 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22358 break;
22359 case OPC_PRECEQU_PH_QBR:
22360 check_dsp(ctx);
22361 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22362 break;
22363 case OPC_PRECEQU_PH_QBLA:
22364 check_dsp(ctx);
22365 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22366 break;
22367 case OPC_PRECEQU_PH_QBRA:
22368 check_dsp(ctx);
22369 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22370 break;
22371 case OPC_PRECEU_PH_QBL:
22372 check_dsp(ctx);
22373 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22374 break;
22375 case OPC_PRECEU_PH_QBR:
22376 check_dsp(ctx);
22377 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22378 break;
22379 case OPC_PRECEU_PH_QBLA:
22380 check_dsp(ctx);
22381 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22382 break;
22383 case OPC_PRECEU_PH_QBRA:
22384 check_dsp(ctx);
22385 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22386 break;
22387 }
22388 break;
22389 case OPC_ADDU_QB_DSP:
22390 switch (op2) {
22391 case OPC_ADDQ_PH:
22392 check_dsp(ctx);
22393 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22394 break;
22395 case OPC_ADDQ_S_PH:
22396 check_dsp(ctx);
22397 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22398 break;
22399 case OPC_ADDQ_S_W:
22400 check_dsp(ctx);
22401 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22402 break;
22403 case OPC_ADDU_QB:
22404 check_dsp(ctx);
22405 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22406 break;
22407 case OPC_ADDU_S_QB:
22408 check_dsp(ctx);
22409 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22410 break;
22411 case OPC_ADDU_PH:
908f6be1 22412 check_dsp_r2(ctx);
461c08df
JL
22413 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22414 break;
22415 case OPC_ADDU_S_PH:
908f6be1 22416 check_dsp_r2(ctx);
461c08df
JL
22417 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22418 break;
22419 case OPC_SUBQ_PH:
22420 check_dsp(ctx);
22421 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22422 break;
22423 case OPC_SUBQ_S_PH:
22424 check_dsp(ctx);
22425 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22426 break;
22427 case OPC_SUBQ_S_W:
22428 check_dsp(ctx);
22429 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22430 break;
22431 case OPC_SUBU_QB:
22432 check_dsp(ctx);
22433 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22434 break;
22435 case OPC_SUBU_S_QB:
22436 check_dsp(ctx);
22437 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22438 break;
22439 case OPC_SUBU_PH:
908f6be1 22440 check_dsp_r2(ctx);
461c08df
JL
22441 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22442 break;
22443 case OPC_SUBU_S_PH:
908f6be1 22444 check_dsp_r2(ctx);
461c08df
JL
22445 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22446 break;
22447 case OPC_ADDSC:
22448 check_dsp(ctx);
22449 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22450 break;
22451 case OPC_ADDWC:
22452 check_dsp(ctx);
22453 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22454 break;
22455 case OPC_MODSUB:
22456 check_dsp(ctx);
22457 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22458 break;
22459 case OPC_RADDU_W_QB:
22460 check_dsp(ctx);
22461 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22462 break;
22463 }
22464 break;
22465 case OPC_CMPU_EQ_QB_DSP:
22466 switch (op2) {
22467 case OPC_PRECR_QB_PH:
908f6be1 22468 check_dsp_r2(ctx);
461c08df
JL
22469 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22470 break;
22471 case OPC_PRECRQ_QB_PH:
22472 check_dsp(ctx);
22473 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22474 break;
22475 case OPC_PRECR_SRA_PH_W:
908f6be1 22476 check_dsp_r2(ctx);
461c08df
JL
22477 {
22478 TCGv_i32 sa_t = tcg_const_i32(v2);
22479 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22480 cpu_gpr[ret]);
22481 tcg_temp_free_i32(sa_t);
22482 break;
22483 }
22484 case OPC_PRECR_SRA_R_PH_W:
908f6be1 22485 check_dsp_r2(ctx);
461c08df
JL
22486 {
22487 TCGv_i32 sa_t = tcg_const_i32(v2);
22488 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22489 cpu_gpr[ret]);
22490 tcg_temp_free_i32(sa_t);
22491 break;
22492 }
22493 case OPC_PRECRQ_PH_W:
22494 check_dsp(ctx);
22495 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22496 break;
22497 case OPC_PRECRQ_RS_PH_W:
22498 check_dsp(ctx);
22499 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22500 break;
22501 case OPC_PRECRQU_S_QB_PH:
22502 check_dsp(ctx);
22503 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22504 break;
22505 }
22506 break;
22507#ifdef TARGET_MIPS64
22508 case OPC_ABSQ_S_QH_DSP:
22509 switch (op2) {
22510 case OPC_PRECEQ_L_PWL:
22511 check_dsp(ctx);
22512 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22513 break;
22514 case OPC_PRECEQ_L_PWR:
22515 check_dsp(ctx);
22516 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22517 break;
22518 case OPC_PRECEQ_PW_QHL:
22519 check_dsp(ctx);
22520 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22521 break;
22522 case OPC_PRECEQ_PW_QHR:
22523 check_dsp(ctx);
22524 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22525 break;
22526 case OPC_PRECEQ_PW_QHLA:
22527 check_dsp(ctx);
22528 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22529 break;
22530 case OPC_PRECEQ_PW_QHRA:
22531 check_dsp(ctx);
22532 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22533 break;
22534 case OPC_PRECEQU_QH_OBL:
22535 check_dsp(ctx);
22536 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22537 break;
22538 case OPC_PRECEQU_QH_OBR:
22539 check_dsp(ctx);
22540 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22541 break;
22542 case OPC_PRECEQU_QH_OBLA:
22543 check_dsp(ctx);
22544 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22545 break;
22546 case OPC_PRECEQU_QH_OBRA:
22547 check_dsp(ctx);
22548 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22549 break;
22550 case OPC_PRECEU_QH_OBL:
22551 check_dsp(ctx);
22552 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22553 break;
22554 case OPC_PRECEU_QH_OBR:
22555 check_dsp(ctx);
22556 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22557 break;
22558 case OPC_PRECEU_QH_OBLA:
22559 check_dsp(ctx);
22560 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22561 break;
22562 case OPC_PRECEU_QH_OBRA:
22563 check_dsp(ctx);
22564 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22565 break;
22566 case OPC_ABSQ_S_OB:
908f6be1 22567 check_dsp_r2(ctx);
461c08df
JL
22568 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22569 break;
22570 case OPC_ABSQ_S_PW:
22571 check_dsp(ctx);
22572 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22573 break;
22574 case OPC_ABSQ_S_QH:
22575 check_dsp(ctx);
22576 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22577 break;
22578 }
22579 break;
22580 case OPC_ADDU_OB_DSP:
22581 switch (op2) {
22582 case OPC_RADDU_L_OB:
22583 check_dsp(ctx);
22584 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22585 break;
22586 case OPC_SUBQ_PW:
22587 check_dsp(ctx);
22588 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22589 break;
22590 case OPC_SUBQ_S_PW:
22591 check_dsp(ctx);
22592 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22593 break;
22594 case OPC_SUBQ_QH:
22595 check_dsp(ctx);
22596 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22597 break;
22598 case OPC_SUBQ_S_QH:
22599 check_dsp(ctx);
22600 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22601 break;
22602 case OPC_SUBU_OB:
22603 check_dsp(ctx);
22604 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22605 break;
22606 case OPC_SUBU_S_OB:
22607 check_dsp(ctx);
22608 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22609 break;
22610 case OPC_SUBU_QH:
908f6be1 22611 check_dsp_r2(ctx);
461c08df
JL
22612 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22613 break;
22614 case OPC_SUBU_S_QH:
908f6be1 22615 check_dsp_r2(ctx);
461c08df
JL
22616 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22617 break;
22618 case OPC_SUBUH_OB:
908f6be1 22619 check_dsp_r2(ctx);
461c08df
JL
22620 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22621 break;
22622 case OPC_SUBUH_R_OB:
908f6be1 22623 check_dsp_r2(ctx);
461c08df
JL
22624 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22625 break;
22626 case OPC_ADDQ_PW:
22627 check_dsp(ctx);
22628 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22629 break;
22630 case OPC_ADDQ_S_PW:
22631 check_dsp(ctx);
22632 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22633 break;
22634 case OPC_ADDQ_QH:
22635 check_dsp(ctx);
22636 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22637 break;
22638 case OPC_ADDQ_S_QH:
22639 check_dsp(ctx);
22640 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22641 break;
22642 case OPC_ADDU_OB:
22643 check_dsp(ctx);
22644 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22645 break;
22646 case OPC_ADDU_S_OB:
22647 check_dsp(ctx);
22648 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22649 break;
22650 case OPC_ADDU_QH:
908f6be1 22651 check_dsp_r2(ctx);
461c08df
JL
22652 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22653 break;
22654 case OPC_ADDU_S_QH:
908f6be1 22655 check_dsp_r2(ctx);
461c08df
JL
22656 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22657 break;
22658 case OPC_ADDUH_OB:
908f6be1 22659 check_dsp_r2(ctx);
461c08df
JL
22660 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22661 break;
22662 case OPC_ADDUH_R_OB:
908f6be1 22663 check_dsp_r2(ctx);
461c08df
JL
22664 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22665 break;
22666 }
22667 break;
22668 case OPC_CMPU_EQ_OB_DSP:
22669 switch (op2) {
22670 case OPC_PRECR_OB_QH:
908f6be1 22671 check_dsp_r2(ctx);
461c08df
JL
22672 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22673 break;
22674 case OPC_PRECR_SRA_QH_PW:
908f6be1 22675 check_dsp_r2(ctx);
461c08df
JL
22676 {
22677 TCGv_i32 ret_t = tcg_const_i32(ret);
22678 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22679 tcg_temp_free_i32(ret_t);
22680 break;
22681 }
22682 case OPC_PRECR_SRA_R_QH_PW:
908f6be1 22683 check_dsp_r2(ctx);
461c08df
JL
22684 {
22685 TCGv_i32 sa_v = tcg_const_i32(ret);
22686 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22687 tcg_temp_free_i32(sa_v);
22688 break;
22689 }
22690 case OPC_PRECRQ_OB_QH:
22691 check_dsp(ctx);
22692 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22693 break;
22694 case OPC_PRECRQ_PW_L:
22695 check_dsp(ctx);
22696 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22697 break;
22698 case OPC_PRECRQ_QH_PW:
22699 check_dsp(ctx);
22700 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22701 break;
22702 case OPC_PRECRQ_RS_QH_PW:
22703 check_dsp(ctx);
22704 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22705 break;
22706 case OPC_PRECRQU_S_OB_QH:
22707 check_dsp(ctx);
22708 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22709 break;
22710 }
22711 break;
22712#endif
22713 }
22714
22715 tcg_temp_free(v1_t);
22716 tcg_temp_free(v2_t);
461c08df 22717}
9b1a1d68 22718
77c5fa8b
JL
22719static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22720 int ret, int v1, int v2)
22721{
22722 uint32_t op2;
77c5fa8b
JL
22723 TCGv t0;
22724 TCGv v1_t;
22725 TCGv v2_t;
22726
22727 if (ret == 0) {
22728 /* Treat as NOP. */
77c5fa8b
JL
22729 return;
22730 }
22731
22732 t0 = tcg_temp_new();
22733 v1_t = tcg_temp_new();
22734 v2_t = tcg_temp_new();
22735
22736 tcg_gen_movi_tl(t0, v1);
22737 gen_load_gpr(v1_t, v1);
22738 gen_load_gpr(v2_t, v2);
22739
22740 switch (opc) {
22741 case OPC_SHLL_QB_DSP:
22742 {
22743 op2 = MASK_SHLL_QB(ctx->opcode);
22744 switch (op2) {
22745 case OPC_SHLL_QB:
22746 check_dsp(ctx);
22747 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22748 break;
22749 case OPC_SHLLV_QB:
22750 check_dsp(ctx);
22751 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22752 break;
22753 case OPC_SHLL_PH:
22754 check_dsp(ctx);
22755 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22756 break;
22757 case OPC_SHLLV_PH:
22758 check_dsp(ctx);
22759 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22760 break;
22761 case OPC_SHLL_S_PH:
22762 check_dsp(ctx);
22763 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22764 break;
22765 case OPC_SHLLV_S_PH:
22766 check_dsp(ctx);
22767 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22768 break;
22769 case OPC_SHLL_S_W:
22770 check_dsp(ctx);
22771 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22772 break;
22773 case OPC_SHLLV_S_W:
22774 check_dsp(ctx);
22775 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22776 break;
22777 case OPC_SHRL_QB:
22778 check_dsp(ctx);
22779 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22780 break;
22781 case OPC_SHRLV_QB:
22782 check_dsp(ctx);
22783 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22784 break;
22785 case OPC_SHRL_PH:
908f6be1 22786 check_dsp_r2(ctx);
77c5fa8b
JL
22787 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22788 break;
22789 case OPC_SHRLV_PH:
908f6be1 22790 check_dsp_r2(ctx);
77c5fa8b
JL
22791 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22792 break;
22793 case OPC_SHRA_QB:
908f6be1 22794 check_dsp_r2(ctx);
77c5fa8b
JL
22795 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22796 break;
22797 case OPC_SHRA_R_QB:
908f6be1 22798 check_dsp_r2(ctx);
77c5fa8b
JL
22799 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22800 break;
22801 case OPC_SHRAV_QB:
908f6be1 22802 check_dsp_r2(ctx);
77c5fa8b
JL
22803 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22804 break;
22805 case OPC_SHRAV_R_QB:
908f6be1 22806 check_dsp_r2(ctx);
77c5fa8b
JL
22807 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22808 break;
22809 case OPC_SHRA_PH:
22810 check_dsp(ctx);
22811 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22812 break;
22813 case OPC_SHRA_R_PH:
22814 check_dsp(ctx);
22815 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22816 break;
22817 case OPC_SHRAV_PH:
22818 check_dsp(ctx);
22819 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22820 break;
22821 case OPC_SHRAV_R_PH:
22822 check_dsp(ctx);
22823 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22824 break;
22825 case OPC_SHRA_R_W:
22826 check_dsp(ctx);
22827 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22828 break;
22829 case OPC_SHRAV_R_W:
22830 check_dsp(ctx);
22831 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22832 break;
22833 default: /* Invalid */
22834 MIPS_INVAL("MASK SHLL.QB");
9c708c7f 22835 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
22836 break;
22837 }
22838 break;
22839 }
22840#ifdef TARGET_MIPS64
22841 case OPC_SHLL_OB_DSP:
22842 op2 = MASK_SHLL_OB(ctx->opcode);
22843 switch (op2) {
22844 case OPC_SHLL_PW:
22845 check_dsp(ctx);
22846 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22847 break;
22848 case OPC_SHLLV_PW:
22849 check_dsp(ctx);
22850 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22851 break;
22852 case OPC_SHLL_S_PW:
22853 check_dsp(ctx);
22854 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22855 break;
22856 case OPC_SHLLV_S_PW:
22857 check_dsp(ctx);
22858 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22859 break;
22860 case OPC_SHLL_OB:
22861 check_dsp(ctx);
22862 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22863 break;
22864 case OPC_SHLLV_OB:
22865 check_dsp(ctx);
22866 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22867 break;
22868 case OPC_SHLL_QH:
22869 check_dsp(ctx);
22870 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22871 break;
22872 case OPC_SHLLV_QH:
22873 check_dsp(ctx);
22874 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22875 break;
22876 case OPC_SHLL_S_QH:
22877 check_dsp(ctx);
22878 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22879 break;
22880 case OPC_SHLLV_S_QH:
22881 check_dsp(ctx);
22882 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22883 break;
22884 case OPC_SHRA_OB:
908f6be1 22885 check_dsp_r2(ctx);
77c5fa8b
JL
22886 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22887 break;
22888 case OPC_SHRAV_OB:
908f6be1 22889 check_dsp_r2(ctx);
77c5fa8b
JL
22890 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22891 break;
22892 case OPC_SHRA_R_OB:
908f6be1 22893 check_dsp_r2(ctx);
77c5fa8b
JL
22894 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22895 break;
22896 case OPC_SHRAV_R_OB:
908f6be1 22897 check_dsp_r2(ctx);
77c5fa8b
JL
22898 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22899 break;
22900 case OPC_SHRA_PW:
22901 check_dsp(ctx);
22902 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22903 break;
22904 case OPC_SHRAV_PW:
22905 check_dsp(ctx);
22906 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22907 break;
22908 case OPC_SHRA_R_PW:
22909 check_dsp(ctx);
22910 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22911 break;
22912 case OPC_SHRAV_R_PW:
22913 check_dsp(ctx);
22914 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22915 break;
22916 case OPC_SHRA_QH:
22917 check_dsp(ctx);
22918 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22919 break;
22920 case OPC_SHRAV_QH:
22921 check_dsp(ctx);
22922 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22923 break;
22924 case OPC_SHRA_R_QH:
22925 check_dsp(ctx);
22926 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22927 break;
22928 case OPC_SHRAV_R_QH:
22929 check_dsp(ctx);
22930 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22931 break;
22932 case OPC_SHRL_OB:
22933 check_dsp(ctx);
22934 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22935 break;
22936 case OPC_SHRLV_OB:
22937 check_dsp(ctx);
22938 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22939 break;
22940 case OPC_SHRL_QH:
908f6be1 22941 check_dsp_r2(ctx);
77c5fa8b
JL
22942 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22943 break;
22944 case OPC_SHRLV_QH:
908f6be1 22945 check_dsp_r2(ctx);
77c5fa8b
JL
22946 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22947 break;
22948 default: /* Invalid */
22949 MIPS_INVAL("MASK SHLL.OB");
9c708c7f 22950 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
22951 break;
22952 }
22953 break;
22954#endif
22955 }
22956
22957 tcg_temp_free(t0);
22958 tcg_temp_free(v1_t);
22959 tcg_temp_free(v2_t);
77c5fa8b
JL
22960}
22961
a22260ae
JL
22962static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22963 int ret, int v1, int v2, int check_ret)
22964{
a22260ae
JL
22965 TCGv_i32 t0;
22966 TCGv v1_t;
22967 TCGv v2_t;
22968
22969 if ((ret == 0) && (check_ret == 1)) {
22970 /* Treat as NOP. */
a22260ae
JL
22971 return;
22972 }
22973
22974 t0 = tcg_temp_new_i32();
22975 v1_t = tcg_temp_new();
22976 v2_t = tcg_temp_new();
22977
22978 tcg_gen_movi_i32(t0, ret);
22979 gen_load_gpr(v1_t, v1);
22980 gen_load_gpr(v2_t, v2);
22981
22982 switch (op1) {
22983 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22984 * the same mask and op1. */
22985 case OPC_MULT_G_2E:
908f6be1 22986 check_dsp_r2(ctx);
a22260ae
JL
22987 switch (op2) {
22988 case OPC_MUL_PH:
22989 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22990 break;
22991 case OPC_MUL_S_PH:
22992 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22993 break;
22994 case OPC_MULQ_S_W:
22995 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22996 break;
22997 case OPC_MULQ_RS_W:
22998 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22999 break;
23000 }
23001 break;
23002 case OPC_DPA_W_PH_DSP:
23003 switch (op2) {
23004 case OPC_DPAU_H_QBL:
23005 check_dsp(ctx);
23006 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23007 break;
23008 case OPC_DPAU_H_QBR:
23009 check_dsp(ctx);
23010 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23011 break;
23012 case OPC_DPSU_H_QBL:
23013 check_dsp(ctx);
23014 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23015 break;
23016 case OPC_DPSU_H_QBR:
23017 check_dsp(ctx);
23018 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23019 break;
23020 case OPC_DPA_W_PH:
908f6be1 23021 check_dsp_r2(ctx);
a22260ae
JL
23022 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23023 break;
23024 case OPC_DPAX_W_PH:
908f6be1 23025 check_dsp_r2(ctx);
a22260ae
JL
23026 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23027 break;
23028 case OPC_DPAQ_S_W_PH:
23029 check_dsp(ctx);
23030 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23031 break;
23032 case OPC_DPAQX_S_W_PH:
908f6be1 23033 check_dsp_r2(ctx);
a22260ae
JL
23034 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23035 break;
23036 case OPC_DPAQX_SA_W_PH:
908f6be1 23037 check_dsp_r2(ctx);
a22260ae
JL
23038 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23039 break;
23040 case OPC_DPS_W_PH:
908f6be1 23041 check_dsp_r2(ctx);
a22260ae
JL
23042 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23043 break;
23044 case OPC_DPSX_W_PH:
908f6be1 23045 check_dsp_r2(ctx);
a22260ae
JL
23046 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23047 break;
23048 case OPC_DPSQ_S_W_PH:
23049 check_dsp(ctx);
23050 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23051 break;
23052 case OPC_DPSQX_S_W_PH:
908f6be1 23053 check_dsp_r2(ctx);
a22260ae
JL
23054 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23055 break;
23056 case OPC_DPSQX_SA_W_PH:
908f6be1 23057 check_dsp_r2(ctx);
a22260ae
JL
23058 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23059 break;
23060 case OPC_MULSAQ_S_W_PH:
23061 check_dsp(ctx);
23062 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23063 break;
23064 case OPC_DPAQ_SA_L_W:
23065 check_dsp(ctx);
23066 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23067 break;
23068 case OPC_DPSQ_SA_L_W:
23069 check_dsp(ctx);
23070 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23071 break;
23072 case OPC_MAQ_S_W_PHL:
23073 check_dsp(ctx);
23074 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23075 break;
23076 case OPC_MAQ_S_W_PHR:
23077 check_dsp(ctx);
23078 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23079 break;
23080 case OPC_MAQ_SA_W_PHL:
23081 check_dsp(ctx);
23082 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23083 break;
23084 case OPC_MAQ_SA_W_PHR:
23085 check_dsp(ctx);
23086 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23087 break;
23088 case OPC_MULSA_W_PH:
908f6be1 23089 check_dsp_r2(ctx);
a22260ae
JL
23090 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23091 break;
23092 }
23093 break;
23094#ifdef TARGET_MIPS64
23095 case OPC_DPAQ_W_QH_DSP:
23096 {
23097 int ac = ret & 0x03;
23098 tcg_gen_movi_i32(t0, ac);
23099
23100 switch (op2) {
23101 case OPC_DMADD:
23102 check_dsp(ctx);
23103 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23104 break;
23105 case OPC_DMADDU:
23106 check_dsp(ctx);
23107 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23108 break;
23109 case OPC_DMSUB:
23110 check_dsp(ctx);
23111 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23112 break;
23113 case OPC_DMSUBU:
23114 check_dsp(ctx);
23115 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23116 break;
23117 case OPC_DPA_W_QH:
908f6be1 23118 check_dsp_r2(ctx);
a22260ae
JL
23119 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23120 break;
23121 case OPC_DPAQ_S_W_QH:
23122 check_dsp(ctx);
23123 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23124 break;
23125 case OPC_DPAQ_SA_L_PW:
23126 check_dsp(ctx);
23127 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23128 break;
23129 case OPC_DPAU_H_OBL:
23130 check_dsp(ctx);
23131 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23132 break;
23133 case OPC_DPAU_H_OBR:
23134 check_dsp(ctx);
23135 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23136 break;
23137 case OPC_DPS_W_QH:
908f6be1 23138 check_dsp_r2(ctx);
a22260ae
JL
23139 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23140 break;
23141 case OPC_DPSQ_S_W_QH:
23142 check_dsp(ctx);
23143 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23144 break;
23145 case OPC_DPSQ_SA_L_PW:
23146 check_dsp(ctx);
23147 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23148 break;
23149 case OPC_DPSU_H_OBL:
23150 check_dsp(ctx);
23151 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23152 break;
23153 case OPC_DPSU_H_OBR:
23154 check_dsp(ctx);
23155 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23156 break;
23157 case OPC_MAQ_S_L_PWL:
23158 check_dsp(ctx);
23159 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23160 break;
23161 case OPC_MAQ_S_L_PWR:
23162 check_dsp(ctx);
23163 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23164 break;
23165 case OPC_MAQ_S_W_QHLL:
23166 check_dsp(ctx);
23167 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23168 break;
23169 case OPC_MAQ_SA_W_QHLL:
23170 check_dsp(ctx);
23171 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23172 break;
23173 case OPC_MAQ_S_W_QHLR:
23174 check_dsp(ctx);
23175 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23176 break;
23177 case OPC_MAQ_SA_W_QHLR:
23178 check_dsp(ctx);
23179 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23180 break;
23181 case OPC_MAQ_S_W_QHRL:
23182 check_dsp(ctx);
23183 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23184 break;
23185 case OPC_MAQ_SA_W_QHRL:
23186 check_dsp(ctx);
23187 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23188 break;
23189 case OPC_MAQ_S_W_QHRR:
23190 check_dsp(ctx);
23191 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23192 break;
23193 case OPC_MAQ_SA_W_QHRR:
23194 check_dsp(ctx);
23195 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23196 break;
23197 case OPC_MULSAQ_S_L_PW:
23198 check_dsp(ctx);
23199 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23200 break;
23201 case OPC_MULSAQ_S_W_QH:
23202 check_dsp(ctx);
23203 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23204 break;
23205 }
23206 }
23207 break;
23208#endif
23209 case OPC_ADDU_QB_DSP:
23210 switch (op2) {
23211 case OPC_MULEU_S_PH_QBL:
23212 check_dsp(ctx);
23213 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23214 break;
23215 case OPC_MULEU_S_PH_QBR:
23216 check_dsp(ctx);
23217 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23218 break;
23219 case OPC_MULQ_RS_PH:
23220 check_dsp(ctx);
23221 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23222 break;
23223 case OPC_MULEQ_S_W_PHL:
23224 check_dsp(ctx);
23225 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23226 break;
23227 case OPC_MULEQ_S_W_PHR:
23228 check_dsp(ctx);
23229 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23230 break;
23231 case OPC_MULQ_S_PH:
908f6be1 23232 check_dsp_r2(ctx);
a22260ae
JL
23233 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23234 break;
23235 }
23236 break;
23237#ifdef TARGET_MIPS64
23238 case OPC_ADDU_OB_DSP:
23239 switch (op2) {
23240 case OPC_MULEQ_S_PW_QHL:
23241 check_dsp(ctx);
23242 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23243 break;
23244 case OPC_MULEQ_S_PW_QHR:
23245 check_dsp(ctx);
23246 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23247 break;
23248 case OPC_MULEU_S_QH_OBL:
23249 check_dsp(ctx);
23250 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23251 break;
23252 case OPC_MULEU_S_QH_OBR:
23253 check_dsp(ctx);
23254 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23255 break;
23256 case OPC_MULQ_RS_QH:
23257 check_dsp(ctx);
23258 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23259 break;
23260 }
23261 break;
23262#endif
23263 }
23264
23265 tcg_temp_free_i32(t0);
23266 tcg_temp_free(v1_t);
23267 tcg_temp_free(v2_t);
a22260ae
JL
23268}
23269
d75c135e 23270static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
1cb6686c
JL
23271 int ret, int val)
23272{
1cb6686c
JL
23273 int16_t imm;
23274 TCGv t0;
23275 TCGv val_t;
23276
23277 if (ret == 0) {
23278 /* Treat as NOP. */
1cb6686c
JL
23279 return;
23280 }
23281
23282 t0 = tcg_temp_new();
23283 val_t = tcg_temp_new();
23284 gen_load_gpr(val_t, val);
23285
23286 switch (op1) {
23287 case OPC_ABSQ_S_PH_DSP:
23288 switch (op2) {
23289 case OPC_BITREV:
23290 check_dsp(ctx);
23291 gen_helper_bitrev(cpu_gpr[ret], val_t);
23292 break;
23293 case OPC_REPL_QB:
23294 check_dsp(ctx);
23295 {
23296 target_long result;
23297 imm = (ctx->opcode >> 16) & 0xFF;
23298 result = (uint32_t)imm << 24 |
23299 (uint32_t)imm << 16 |
23300 (uint32_t)imm << 8 |
23301 (uint32_t)imm;
23302 result = (int32_t)result;
23303 tcg_gen_movi_tl(cpu_gpr[ret], result);
23304 }
23305 break;
23306 case OPC_REPLV_QB:
23307 check_dsp(ctx);
23308 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23309 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23310 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23311 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23312 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23313 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23314 break;
23315 case OPC_REPL_PH:
23316 check_dsp(ctx);
23317 {
23318 imm = (ctx->opcode >> 16) & 0x03FF;
c4aaba92 23319 imm = (int16_t)(imm << 6) >> 6;
1cb6686c
JL
23320 tcg_gen_movi_tl(cpu_gpr[ret], \
23321 (target_long)((int32_t)imm << 16 | \
c4aaba92 23322 (uint16_t)imm));
1cb6686c
JL
23323 }
23324 break;
23325 case OPC_REPLV_PH:
23326 check_dsp(ctx);
23327 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23328 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23329 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23330 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23331 break;
23332 }
23333 break;
23334#ifdef TARGET_MIPS64
23335 case OPC_ABSQ_S_QH_DSP:
23336 switch (op2) {
23337 case OPC_REPL_OB:
23338 check_dsp(ctx);
23339 {
23340 target_long temp;
23341
23342 imm = (ctx->opcode >> 16) & 0xFF;
23343 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23344 temp = (temp << 16) | temp;
23345 temp = (temp << 32) | temp;
23346 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23347 break;
23348 }
23349 case OPC_REPL_PW:
23350 check_dsp(ctx);
23351 {
23352 target_long temp;
23353
23354 imm = (ctx->opcode >> 16) & 0x03FF;
23355 imm = (int16_t)(imm << 6) >> 6;
23356 temp = ((target_long)imm << 32) \
23357 | ((target_long)imm & 0xFFFFFFFF);
23358 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23359 break;
23360 }
23361 case OPC_REPL_QH:
23362 check_dsp(ctx);
23363 {
23364 target_long temp;
23365
23366 imm = (ctx->opcode >> 16) & 0x03FF;
23367 imm = (int16_t)(imm << 6) >> 6;
23368
23369 temp = ((uint64_t)(uint16_t)imm << 48) |
23370 ((uint64_t)(uint16_t)imm << 32) |
23371 ((uint64_t)(uint16_t)imm << 16) |
23372 (uint64_t)(uint16_t)imm;
23373 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23374 break;
23375 }
23376 case OPC_REPLV_OB:
23377 check_dsp(ctx);
23378 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23379 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23380 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23381 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23382 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23383 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23384 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23385 break;
23386 case OPC_REPLV_PW:
23387 check_dsp(ctx);
23388 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23389 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23390 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23391 break;
23392 case OPC_REPLV_QH:
23393 check_dsp(ctx);
23394 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23395 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23396 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23397 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23398 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23399 break;
23400 }
23401 break;
23402#endif
23403 }
23404 tcg_temp_free(t0);
23405 tcg_temp_free(val_t);
1cb6686c
JL
23406}
23407
26690560
JL
23408static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23409 uint32_t op1, uint32_t op2,
23410 int ret, int v1, int v2, int check_ret)
23411{
26690560
JL
23412 TCGv t1;
23413 TCGv v1_t;
23414 TCGv v2_t;
23415
23416 if ((ret == 0) && (check_ret == 1)) {
23417 /* Treat as NOP. */
26690560
JL
23418 return;
23419 }
23420
26690560
JL
23421 t1 = tcg_temp_new();
23422 v1_t = tcg_temp_new();
23423 v2_t = tcg_temp_new();
23424
23425 gen_load_gpr(v1_t, v1);
23426 gen_load_gpr(v2_t, v2);
23427
23428 switch (op1) {
26690560
JL
23429 case OPC_CMPU_EQ_QB_DSP:
23430 switch (op2) {
23431 case OPC_CMPU_EQ_QB:
23432 check_dsp(ctx);
23433 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23434 break;
23435 case OPC_CMPU_LT_QB:
23436 check_dsp(ctx);
23437 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23438 break;
23439 case OPC_CMPU_LE_QB:
23440 check_dsp(ctx);
23441 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23442 break;
23443 case OPC_CMPGU_EQ_QB:
23444 check_dsp(ctx);
23445 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23446 break;
23447 case OPC_CMPGU_LT_QB:
23448 check_dsp(ctx);
23449 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23450 break;
23451 case OPC_CMPGU_LE_QB:
23452 check_dsp(ctx);
23453 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23454 break;
23455 case OPC_CMPGDU_EQ_QB:
908f6be1 23456 check_dsp_r2(ctx);
26690560
JL
23457 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23458 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23459 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23460 tcg_gen_shli_tl(t1, t1, 24);
23461 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23462 break;
23463 case OPC_CMPGDU_LT_QB:
908f6be1 23464 check_dsp_r2(ctx);
26690560
JL
23465 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23466 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23467 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23468 tcg_gen_shli_tl(t1, t1, 24);
23469 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23470 break;
23471 case OPC_CMPGDU_LE_QB:
908f6be1 23472 check_dsp_r2(ctx);
26690560
JL
23473 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23474 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23475 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23476 tcg_gen_shli_tl(t1, t1, 24);
23477 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23478 break;
23479 case OPC_CMP_EQ_PH:
23480 check_dsp(ctx);
23481 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23482 break;
23483 case OPC_CMP_LT_PH:
23484 check_dsp(ctx);
23485 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23486 break;
23487 case OPC_CMP_LE_PH:
23488 check_dsp(ctx);
23489 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23490 break;
23491 case OPC_PICK_QB:
23492 check_dsp(ctx);
23493 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23494 break;
23495 case OPC_PICK_PH:
23496 check_dsp(ctx);
23497 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23498 break;
23499 case OPC_PACKRL_PH:
23500 check_dsp(ctx);
23501 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23502 break;
23503 }
23504 break;
23505#ifdef TARGET_MIPS64
23506 case OPC_CMPU_EQ_OB_DSP:
23507 switch (op2) {
23508 case OPC_CMP_EQ_PW:
23509 check_dsp(ctx);
23510 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23511 break;
23512 case OPC_CMP_LT_PW:
23513 check_dsp(ctx);
23514 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23515 break;
23516 case OPC_CMP_LE_PW:
23517 check_dsp(ctx);
23518 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23519 break;
23520 case OPC_CMP_EQ_QH:
23521 check_dsp(ctx);
23522 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23523 break;
23524 case OPC_CMP_LT_QH:
23525 check_dsp(ctx);
23526 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23527 break;
23528 case OPC_CMP_LE_QH:
23529 check_dsp(ctx);
23530 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23531 break;
23532 case OPC_CMPGDU_EQ_OB:
908f6be1 23533 check_dsp_r2(ctx);
26690560
JL
23534 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23535 break;
23536 case OPC_CMPGDU_LT_OB:
908f6be1 23537 check_dsp_r2(ctx);
26690560
JL
23538 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23539 break;
23540 case OPC_CMPGDU_LE_OB:
908f6be1 23541 check_dsp_r2(ctx);
26690560
JL
23542 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23543 break;
23544 case OPC_CMPGU_EQ_OB:
23545 check_dsp(ctx);
23546 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23547 break;
23548 case OPC_CMPGU_LT_OB:
23549 check_dsp(ctx);
23550 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23551 break;
23552 case OPC_CMPGU_LE_OB:
23553 check_dsp(ctx);
23554 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23555 break;
23556 case OPC_CMPU_EQ_OB:
23557 check_dsp(ctx);
23558 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23559 break;
23560 case OPC_CMPU_LT_OB:
23561 check_dsp(ctx);
23562 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23563 break;
23564 case OPC_CMPU_LE_OB:
23565 check_dsp(ctx);
23566 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23567 break;
23568 case OPC_PACKRL_PW:
23569 check_dsp(ctx);
23570 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23571 break;
23572 case OPC_PICK_OB:
23573 check_dsp(ctx);
23574 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23575 break;
23576 case OPC_PICK_PW:
23577 check_dsp(ctx);
23578 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23579 break;
23580 case OPC_PICK_QH:
23581 check_dsp(ctx);
23582 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23583 break;
23584 }
23585 break;
df6126a7
AJ
23586#endif
23587 }
23588
23589 tcg_temp_free(t1);
23590 tcg_temp_free(v1_t);
23591 tcg_temp_free(v2_t);
df6126a7
AJ
23592}
23593
23594static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23595 uint32_t op1, int rt, int rs, int sa)
23596{
df6126a7
AJ
23597 TCGv t0;
23598
908f6be1 23599 check_dsp_r2(ctx);
df6126a7
AJ
23600
23601 if (rt == 0) {
23602 /* Treat as NOP. */
df6126a7
AJ
23603 return;
23604 }
23605
23606 t0 = tcg_temp_new();
23607 gen_load_gpr(t0, rs);
23608
23609 switch (op1) {
23610 case OPC_APPEND_DSP:
23611 switch (MASK_APPEND(ctx->opcode)) {
23612 case OPC_APPEND:
23613 if (sa != 0) {
23614 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23615 }
23616 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23617 break;
23618 case OPC_PREPEND:
23619 if (sa != 0) {
23620 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23621 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23622 tcg_gen_shli_tl(t0, t0, 32 - sa);
23623 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23624 }
23625 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23626 break;
23627 case OPC_BALIGN:
23628 sa &= 3;
23629 if (sa != 0 && sa != 2) {
23630 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23631 tcg_gen_ext32u_tl(t0, t0);
23632 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23633 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23634 }
23635 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23636 break;
23637 default: /* Invalid */
23638 MIPS_INVAL("MASK APPEND");
9c708c7f 23639 generate_exception_end(ctx, EXCP_RI);
df6126a7
AJ
23640 break;
23641 }
23642 break;
23643#ifdef TARGET_MIPS64
26690560 23644 case OPC_DAPPEND_DSP:
df6126a7 23645 switch (MASK_DAPPEND(ctx->opcode)) {
26690560 23646 case OPC_DAPPEND:
df6126a7
AJ
23647 if (sa != 0) {
23648 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23649 }
26690560
JL
23650 break;
23651 case OPC_PREPENDD:
df6126a7
AJ
23652 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23653 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23654 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
26690560
JL
23655 break;
23656 case OPC_PREPENDW:
df6126a7
AJ
23657 if (sa != 0) {
23658 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23659 tcg_gen_shli_tl(t0, t0, 64 - sa);
23660 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23661 }
26690560
JL
23662 break;
23663 case OPC_DBALIGN:
df6126a7
AJ
23664 sa &= 7;
23665 if (sa != 0 && sa != 2 && sa != 4) {
23666 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23667 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23668 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23669 }
26690560
JL
23670 break;
23671 default: /* Invalid */
23672 MIPS_INVAL("MASK DAPPEND");
9c708c7f 23673 generate_exception_end(ctx, EXCP_RI);
26690560
JL
23674 break;
23675 }
23676 break;
23677#endif
23678 }
df6126a7 23679 tcg_temp_free(t0);
26690560
JL
23680}
23681
b53371ed
JL
23682static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23683 int ret, int v1, int v2, int check_ret)
23684
23685{
b53371ed
JL
23686 TCGv t0;
23687 TCGv t1;
23688 TCGv v1_t;
23689 TCGv v2_t;
23690 int16_t imm;
23691
23692 if ((ret == 0) && (check_ret == 1)) {
23693 /* Treat as NOP. */
b53371ed
JL
23694 return;
23695 }
23696
23697 t0 = tcg_temp_new();
23698 t1 = tcg_temp_new();
23699 v1_t = tcg_temp_new();
23700 v2_t = tcg_temp_new();
23701
23702 gen_load_gpr(v1_t, v1);
23703 gen_load_gpr(v2_t, v2);
23704
23705 switch (op1) {
23706 case OPC_EXTR_W_DSP:
23707 check_dsp(ctx);
23708 switch (op2) {
23709 case OPC_EXTR_W:
23710 tcg_gen_movi_tl(t0, v2);
23711 tcg_gen_movi_tl(t1, v1);
23712 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23713 break;
23714 case OPC_EXTR_R_W:
23715 tcg_gen_movi_tl(t0, v2);
23716 tcg_gen_movi_tl(t1, v1);
23717 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23718 break;
23719 case OPC_EXTR_RS_W:
23720 tcg_gen_movi_tl(t0, v2);
23721 tcg_gen_movi_tl(t1, v1);
23722 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23723 break;
23724 case OPC_EXTR_S_H:
23725 tcg_gen_movi_tl(t0, v2);
23726 tcg_gen_movi_tl(t1, v1);
23727 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23728 break;
23729 case OPC_EXTRV_S_H:
23730 tcg_gen_movi_tl(t0, v2);
23731 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23732 break;
23733 case OPC_EXTRV_W:
23734 tcg_gen_movi_tl(t0, v2);
23735 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23736 break;
23737 case OPC_EXTRV_R_W:
23738 tcg_gen_movi_tl(t0, v2);
23739 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23740 break;
23741 case OPC_EXTRV_RS_W:
23742 tcg_gen_movi_tl(t0, v2);
23743 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23744 break;
23745 case OPC_EXTP:
23746 tcg_gen_movi_tl(t0, v2);
23747 tcg_gen_movi_tl(t1, v1);
23748 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23749 break;
23750 case OPC_EXTPV:
23751 tcg_gen_movi_tl(t0, v2);
23752 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23753 break;
23754 case OPC_EXTPDP:
23755 tcg_gen_movi_tl(t0, v2);
23756 tcg_gen_movi_tl(t1, v1);
23757 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23758 break;
23759 case OPC_EXTPDPV:
23760 tcg_gen_movi_tl(t0, v2);
23761 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23762 break;
23763 case OPC_SHILO:
23764 imm = (ctx->opcode >> 20) & 0x3F;
23765 tcg_gen_movi_tl(t0, ret);
23766 tcg_gen_movi_tl(t1, imm);
23767 gen_helper_shilo(t0, t1, cpu_env);
23768 break;
23769 case OPC_SHILOV:
23770 tcg_gen_movi_tl(t0, ret);
23771 gen_helper_shilo(t0, v1_t, cpu_env);
23772 break;
23773 case OPC_MTHLIP:
23774 tcg_gen_movi_tl(t0, ret);
23775 gen_helper_mthlip(t0, v1_t, cpu_env);
23776 break;
23777 case OPC_WRDSP:
23778 imm = (ctx->opcode >> 11) & 0x3FF;
23779 tcg_gen_movi_tl(t0, imm);
23780 gen_helper_wrdsp(v1_t, t0, cpu_env);
23781 break;
23782 case OPC_RDDSP:
23783 imm = (ctx->opcode >> 16) & 0x03FF;
23784 tcg_gen_movi_tl(t0, imm);
23785 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23786 break;
23787 }
23788 break;
23789#ifdef TARGET_MIPS64
23790 case OPC_DEXTR_W_DSP:
23791 check_dsp(ctx);
23792 switch (op2) {
23793 case OPC_DMTHLIP:
23794 tcg_gen_movi_tl(t0, ret);
23795 gen_helper_dmthlip(v1_t, t0, cpu_env);
23796 break;
23797 case OPC_DSHILO:
23798 {
23799 int shift = (ctx->opcode >> 19) & 0x7F;
23800 int ac = (ctx->opcode >> 11) & 0x03;
23801 tcg_gen_movi_tl(t0, shift);
23802 tcg_gen_movi_tl(t1, ac);
23803 gen_helper_dshilo(t0, t1, cpu_env);
23804 break;
23805 }
23806 case OPC_DSHILOV:
23807 {
23808 int ac = (ctx->opcode >> 11) & 0x03;
23809 tcg_gen_movi_tl(t0, ac);
23810 gen_helper_dshilo(v1_t, t0, cpu_env);
23811 break;
23812 }
23813 case OPC_DEXTP:
23814 tcg_gen_movi_tl(t0, v2);
23815 tcg_gen_movi_tl(t1, v1);
23816
23817 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23818 break;
23819 case OPC_DEXTPV:
23820 tcg_gen_movi_tl(t0, v2);
23821 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23822 break;
23823 case OPC_DEXTPDP:
23824 tcg_gen_movi_tl(t0, v2);
23825 tcg_gen_movi_tl(t1, v1);
23826 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23827 break;
23828 case OPC_DEXTPDPV:
23829 tcg_gen_movi_tl(t0, v2);
23830 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23831 break;
23832 case OPC_DEXTR_L:
23833 tcg_gen_movi_tl(t0, v2);
23834 tcg_gen_movi_tl(t1, v1);
23835 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23836 break;
23837 case OPC_DEXTR_R_L:
23838 tcg_gen_movi_tl(t0, v2);
23839 tcg_gen_movi_tl(t1, v1);
23840 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23841 break;
23842 case OPC_DEXTR_RS_L:
23843 tcg_gen_movi_tl(t0, v2);
23844 tcg_gen_movi_tl(t1, v1);
23845 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23846 break;
23847 case OPC_DEXTR_W:
23848 tcg_gen_movi_tl(t0, v2);
23849 tcg_gen_movi_tl(t1, v1);
23850 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23851 break;
23852 case OPC_DEXTR_R_W:
23853 tcg_gen_movi_tl(t0, v2);
23854 tcg_gen_movi_tl(t1, v1);
23855 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23856 break;
23857 case OPC_DEXTR_RS_W:
23858 tcg_gen_movi_tl(t0, v2);
23859 tcg_gen_movi_tl(t1, v1);
23860 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23861 break;
23862 case OPC_DEXTR_S_H:
23863 tcg_gen_movi_tl(t0, v2);
23864 tcg_gen_movi_tl(t1, v1);
23865 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23866 break;
23867 case OPC_DEXTRV_S_H:
23868 tcg_gen_movi_tl(t0, v2);
23869 tcg_gen_movi_tl(t1, v1);
23870 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23871 break;
23872 case OPC_DEXTRV_L:
23873 tcg_gen_movi_tl(t0, v2);
23874 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23875 break;
23876 case OPC_DEXTRV_R_L:
23877 tcg_gen_movi_tl(t0, v2);
23878 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23879 break;
23880 case OPC_DEXTRV_RS_L:
23881 tcg_gen_movi_tl(t0, v2);
23882 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23883 break;
23884 case OPC_DEXTRV_W:
23885 tcg_gen_movi_tl(t0, v2);
23886 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23887 break;
23888 case OPC_DEXTRV_R_W:
23889 tcg_gen_movi_tl(t0, v2);
23890 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23891 break;
23892 case OPC_DEXTRV_RS_W:
23893 tcg_gen_movi_tl(t0, v2);
23894 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23895 break;
23896 }
23897 break;
23898#endif
23899 }
23900
23901 tcg_temp_free(t0);
23902 tcg_temp_free(t1);
23903 tcg_temp_free(v1_t);
23904 tcg_temp_free(v2_t);
b53371ed
JL
23905}
23906
9b1a1d68
JL
23907/* End MIPSDSP functions. */
23908
10dc65db
LA
23909static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23910{
4267d3e6 23911 int rs, rt, rd, sa;
b42ee5e1 23912 uint32_t op1, op2;
10dc65db
LA
23913
23914 rs = (ctx->opcode >> 21) & 0x1f;
23915 rt = (ctx->opcode >> 16) & 0x1f;
23916 rd = (ctx->opcode >> 11) & 0x1f;
4267d3e6 23917 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
23918
23919 op1 = MASK_SPECIAL(ctx->opcode);
23920 switch (op1) {
d4ea6acd 23921 case OPC_LSA:
1f1b4c00 23922 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 23923 break;
c2e19f3c
AM
23924 case OPC_MULT:
23925 case OPC_MULTU:
23926 case OPC_DIV:
23927 case OPC_DIVU:
b42ee5e1
LA
23928 op2 = MASK_R6_MULDIV(ctx->opcode);
23929 switch (op2) {
23930 case R6_OPC_MUL:
23931 case R6_OPC_MUH:
23932 case R6_OPC_MULU:
23933 case R6_OPC_MUHU:
23934 case R6_OPC_DIV:
23935 case R6_OPC_MOD:
23936 case R6_OPC_DIVU:
23937 case R6_OPC_MODU:
23938 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23939 break;
23940 default:
23941 MIPS_INVAL("special_r6 muldiv");
9c708c7f 23942 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
23943 break;
23944 }
23945 break;
10dc65db
LA
23946 case OPC_SELEQZ:
23947 case OPC_SELNEZ:
23948 gen_cond_move(ctx, op1, rd, rs, rt);
23949 break;
4267d3e6
LA
23950 case R6_OPC_CLO:
23951 case R6_OPC_CLZ:
23952 if (rt == 0 && sa == 1) {
23953 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23954 We need additionally to check other fields */
23955 gen_cl(ctx, op1, rd, rs);
23956 } else {
9c708c7f 23957 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
23958 }
23959 break;
23960 case R6_OPC_SDBBP:
3b3c1694
LA
23961 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23962 gen_helper_do_semihosting(cpu_env);
faf1f68b 23963 } else {
3b3c1694 23964 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 23965 generate_exception_end(ctx, EXCP_RI);
3b3c1694 23966 } else {
9c708c7f 23967 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 23968 }
faf1f68b 23969 }
4267d3e6 23970 break;
b42ee5e1 23971#if defined(TARGET_MIPS64)
d4ea6acd
LA
23972 case OPC_DLSA:
23973 check_mips_64(ctx);
1f1b4c00 23974 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 23975 break;
4267d3e6
LA
23976 case R6_OPC_DCLO:
23977 case R6_OPC_DCLZ:
23978 if (rt == 0 && sa == 1) {
23979 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23980 We need additionally to check other fields */
23981 check_mips_64(ctx);
23982 gen_cl(ctx, op1, rd, rs);
23983 } else {
9c708c7f 23984 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
23985 }
23986 break;
c2e19f3c
AM
23987 case OPC_DMULT:
23988 case OPC_DMULTU:
23989 case OPC_DDIV:
23990 case OPC_DDIVU:
23991
b42ee5e1
LA
23992 op2 = MASK_R6_MULDIV(ctx->opcode);
23993 switch (op2) {
23994 case R6_OPC_DMUL:
23995 case R6_OPC_DMUH:
23996 case R6_OPC_DMULU:
23997 case R6_OPC_DMUHU:
23998 case R6_OPC_DDIV:
23999 case R6_OPC_DMOD:
24000 case R6_OPC_DDIVU:
24001 case R6_OPC_DMODU:
24002 check_mips_64(ctx);
24003 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24004 break;
24005 default:
24006 MIPS_INVAL("special_r6 muldiv");
9c708c7f 24007 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
24008 break;
24009 }
24010 break;
24011#endif
10dc65db
LA
24012 default: /* Invalid */
24013 MIPS_INVAL("special_r6");
9c708c7f 24014 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
24015 break;
24016 }
24017}
24018
9dc324ce
FN
24019static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24020{
24021 int rs = extract32(ctx->opcode, 21, 5);
24022 int rt = extract32(ctx->opcode, 16, 5);
24023 int rd = extract32(ctx->opcode, 11, 5);
24024 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24025
24026 switch (op1) {
24027 case OPC_MOVN: /* Conditional move */
24028 case OPC_MOVZ:
24029 gen_cond_move(ctx, op1, rd, rs, rt);
24030 break;
24031 case OPC_MFHI: /* Move from HI/LO */
24032 case OPC_MFLO:
24033 gen_HILO(ctx, op1, 0, rd);
24034 break;
24035 case OPC_MTHI:
24036 case OPC_MTLO: /* Move to HI/LO */
24037 gen_HILO(ctx, op1, 0, rs);
24038 break;
24039 case OPC_MULT:
24040 case OPC_MULTU:
24041 gen_mul_txx9(ctx, op1, rd, rs, rt);
24042 break;
24043 case OPC_DIV:
24044 case OPC_DIVU:
24045 gen_muldiv(ctx, op1, 0, rs, rt);
24046 break;
24047#if defined(TARGET_MIPS64)
24048 case OPC_DMULT:
24049 case OPC_DMULTU:
24050 case OPC_DDIV:
24051 case OPC_DDIVU:
24052 check_insn_opc_user_only(ctx, INSN_R5900);
24053 gen_muldiv(ctx, op1, 0, rs, rt);
24054 break;
24055#endif
24056 case OPC_JR:
24057 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24058 break;
24059 default: /* Invalid */
24060 MIPS_INVAL("special_tx79");
24061 generate_exception_end(ctx, EXCP_RI);
24062 break;
24063 }
24064}
24065
10dc65db
LA
24066static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24067{
b42ee5e1 24068 int rs, rt, rd, sa;
10dc65db
LA
24069 uint32_t op1;
24070
24071 rs = (ctx->opcode >> 21) & 0x1f;
24072 rt = (ctx->opcode >> 16) & 0x1f;
24073 rd = (ctx->opcode >> 11) & 0x1f;
b42ee5e1 24074 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
24075
24076 op1 = MASK_SPECIAL(ctx->opcode);
24077 switch (op1) {
24078 case OPC_MOVN: /* Conditional move */
24079 case OPC_MOVZ:
24080 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
9dc324ce 24081 INSN_LOONGSON2E | INSN_LOONGSON2F);
10dc65db
LA
24082 gen_cond_move(ctx, op1, rd, rs, rt);
24083 break;
24084 case OPC_MFHI: /* Move from HI/LO */
24085 case OPC_MFLO:
24086 gen_HILO(ctx, op1, rs & 3, rd);
24087 break;
24088 case OPC_MTHI:
24089 case OPC_MTLO: /* Move to HI/LO */
24090 gen_HILO(ctx, op1, rd & 3, rs);
24091 break;
24092 case OPC_MOVCI:
24093 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24094 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24095 check_cp1_enabled(ctx);
24096 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24097 (ctx->opcode >> 16) & 1);
24098 } else {
24099 generate_exception_err(ctx, EXCP_CpU, 1);
24100 }
24101 break;
b42ee5e1
LA
24102 case OPC_MULT:
24103 case OPC_MULTU:
24104 if (sa) {
24105 check_insn(ctx, INSN_VR54XX);
24106 op1 = MASK_MUL_VR54XX(ctx->opcode);
24107 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24108 } else {
24109 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24110 }
24111 break;
24112 case OPC_DIV:
24113 case OPC_DIVU:
24114 gen_muldiv(ctx, op1, 0, rs, rt);
24115 break;
24116#if defined(TARGET_MIPS64)
c2e19f3c
AM
24117 case OPC_DMULT:
24118 case OPC_DMULTU:
24119 case OPC_DDIV:
24120 case OPC_DDIVU:
b42ee5e1
LA
24121 check_insn(ctx, ISA_MIPS3);
24122 check_mips_64(ctx);
24123 gen_muldiv(ctx, op1, 0, rs, rt);
24124 break;
24125#endif
0aefa333 24126 case OPC_JR:
b231c103 24127 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
0aefa333 24128 break;
4267d3e6
LA
24129 case OPC_SPIM:
24130#ifdef MIPS_STRICT_STANDARD
24131 MIPS_INVAL("SPIM");
9c708c7f 24132 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24133#else
24134 /* Implemented as RI exception for now. */
24135 MIPS_INVAL("spim (unofficial)");
9c708c7f 24136 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
24137#endif
24138 break;
10dc65db
LA
24139 default: /* Invalid */
24140 MIPS_INVAL("special_legacy");
9c708c7f 24141 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
24142 break;
24143 }
24144}
24145
099e5b4d 24146static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
3c824109 24147{
3c824109 24148 int rs, rt, rd, sa;
099e5b4d 24149 uint32_t op1;
3c824109 24150
3c824109
NF
24151 rs = (ctx->opcode >> 21) & 0x1f;
24152 rt = (ctx->opcode >> 16) & 0x1f;
24153 rd = (ctx->opcode >> 11) & 0x1f;
24154 sa = (ctx->opcode >> 6) & 0x1f;
099e5b4d
LA
24155
24156 op1 = MASK_SPECIAL(ctx->opcode);
24157 switch (op1) {
24158 case OPC_SLL: /* Shift with immediate */
339cd2a8
LA
24159 if (sa == 5 && rd == 0 &&
24160 rs == 0 && rt == 0) { /* PAUSE */
24161 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24162 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 24163 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
24164 break;
24165 }
24166 }
24167 /* Fallthrough */
099e5b4d
LA
24168 case OPC_SRA:
24169 gen_shift_imm(ctx, op1, rd, rt, sa);
24170 break;
24171 case OPC_SRL:
24172 switch ((ctx->opcode >> 21) & 0x1f) {
24173 case 1:
24174 /* rotr is decoded as srl on non-R2 CPUs */
24175 if (ctx->insn_flags & ISA_MIPS32R2) {
24176 op1 = OPC_ROTR;
ea63e2c3 24177 }
099e5b4d
LA
24178 /* Fallthrough */
24179 case 0:
24180 gen_shift_imm(ctx, op1, rd, rt, sa);
ea63e2c3 24181 break;
099e5b4d 24182 default:
9c708c7f 24183 generate_exception_end(ctx, EXCP_RI);
ea63e2c3 24184 break;
099e5b4d
LA
24185 }
24186 break;
c2e19f3c
AM
24187 case OPC_ADD:
24188 case OPC_ADDU:
24189 case OPC_SUB:
24190 case OPC_SUBU:
099e5b4d
LA
24191 gen_arith(ctx, op1, rd, rs, rt);
24192 break;
24193 case OPC_SLLV: /* Shifts */
24194 case OPC_SRAV:
24195 gen_shift(ctx, op1, rd, rs, rt);
24196 break;
24197 case OPC_SRLV:
24198 switch ((ctx->opcode >> 6) & 0x1f) {
24199 case 1:
24200 /* rotrv is decoded as srlv on non-R2 CPUs */
24201 if (ctx->insn_flags & ISA_MIPS32R2) {
24202 op1 = OPC_ROTRV;
26135ead 24203 }
099e5b4d
LA
24204 /* Fallthrough */
24205 case 0:
24206 gen_shift(ctx, op1, rd, rs, rt);
26135ead 24207 break;
099e5b4d 24208 default:
9c708c7f 24209 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 24210 break;
099e5b4d
LA
24211 }
24212 break;
24213 case OPC_SLT: /* Set on less than */
24214 case OPC_SLTU:
24215 gen_slt(ctx, op1, rd, rs, rt);
24216 break;
24217 case OPC_AND: /* Logic*/
24218 case OPC_OR:
24219 case OPC_NOR:
24220 case OPC_XOR:
24221 gen_logic(ctx, op1, rd, rs, rt);
24222 break;
0aefa333 24223 case OPC_JALR:
b231c103 24224 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
099e5b4d 24225 break;
c2e19f3c
AM
24226 case OPC_TGE: /* Traps */
24227 case OPC_TGEU:
24228 case OPC_TLT:
24229 case OPC_TLTU:
24230 case OPC_TEQ:
099e5b4d 24231 case OPC_TNE:
d9224450 24232 check_insn(ctx, ISA_MIPS2);
099e5b4d
LA
24233 gen_trap(ctx, op1, rs, rt, -1);
24234 break;
d4ea6acd 24235 case OPC_LSA: /* OPC_PMON */
f7685877
YK
24236 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24237 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
d4ea6acd
LA
24238 decode_opc_special_r6(env, ctx);
24239 } else {
24240 /* Pmon entry point, also R4010 selsl */
b48cfdff 24241#ifdef MIPS_STRICT_STANDARD
d4ea6acd 24242 MIPS_INVAL("PMON / selsl");
9c708c7f 24243 generate_exception_end(ctx, EXCP_RI);
b48cfdff 24244#else
d4ea6acd 24245 gen_helper_0e0i(pmon, sa);
b48cfdff 24246#endif
d4ea6acd 24247 }
099e5b4d
LA
24248 break;
24249 case OPC_SYSCALL:
9c708c7f 24250 generate_exception_end(ctx, EXCP_SYSCALL);
099e5b4d
LA
24251 break;
24252 case OPC_BREAK:
9c708c7f 24253 generate_exception_end(ctx, EXCP_BREAK);
099e5b4d 24254 break;
099e5b4d 24255 case OPC_SYNC:
d9224450 24256 check_insn(ctx, ISA_MIPS2);
d208ac0c 24257 gen_sync(extract32(ctx->opcode, 6, 5));
099e5b4d 24258 break;
4ad40f36 24259
d26bc211 24260#if defined(TARGET_MIPS64)
099e5b4d
LA
24261 /* MIPS64 specific opcodes */
24262 case OPC_DSLL:
24263 case OPC_DSRA:
24264 case OPC_DSLL32:
24265 case OPC_DSRA32:
24266 check_insn(ctx, ISA_MIPS3);
24267 check_mips_64(ctx);
24268 gen_shift_imm(ctx, op1, rd, rt, sa);
24269 break;
24270 case OPC_DSRL:
24271 switch ((ctx->opcode >> 21) & 0x1f) {
24272 case 1:
24273 /* drotr is decoded as dsrl on non-R2 CPUs */
24274 if (ctx->insn_flags & ISA_MIPS32R2) {
24275 op1 = OPC_DROTR;
ea63e2c3 24276 }
099e5b4d
LA
24277 /* Fallthrough */
24278 case 0:
d75c135e 24279 check_insn(ctx, ISA_MIPS3);
e189e748 24280 check_mips_64(ctx);
099e5b4d 24281 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 24282 break;
099e5b4d 24283 default:
9c708c7f 24284 generate_exception_end(ctx, EXCP_RI);
460f00c4 24285 break;
099e5b4d
LA
24286 }
24287 break;
24288 case OPC_DSRL32:
24289 switch ((ctx->opcode >> 21) & 0x1f) {
24290 case 1:
24291 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24292 if (ctx->insn_flags & ISA_MIPS32R2) {
24293 op1 = OPC_DROTR32;
ea63e2c3 24294 }
099e5b4d
LA
24295 /* Fallthrough */
24296 case 0:
d75c135e 24297 check_insn(ctx, ISA_MIPS3);
e189e748 24298 check_mips_64(ctx);
099e5b4d 24299 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 24300 break;
099e5b4d 24301 default:
9c708c7f 24302 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
24303 break;
24304 }
24305 break;
c2e19f3c
AM
24306 case OPC_DADD:
24307 case OPC_DADDU:
24308 case OPC_DSUB:
24309 case OPC_DSUBU:
099e5b4d
LA
24310 check_insn(ctx, ISA_MIPS3);
24311 check_mips_64(ctx);
24312 gen_arith(ctx, op1, rd, rs, rt);
24313 break;
24314 case OPC_DSLLV:
24315 case OPC_DSRAV:
24316 check_insn(ctx, ISA_MIPS3);
24317 check_mips_64(ctx);
24318 gen_shift(ctx, op1, rd, rs, rt);
24319 break;
24320 case OPC_DSRLV:
24321 switch ((ctx->opcode >> 6) & 0x1f) {
24322 case 1:
24323 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24324 if (ctx->insn_flags & ISA_MIPS32R2) {
24325 op1 = OPC_DROTRV;
6af0bf9c 24326 }
099e5b4d
LA
24327 /* Fallthrough */
24328 case 0:
24329 check_insn(ctx, ISA_MIPS3);
e189e748 24330 check_mips_64(ctx);
099e5b4d 24331 gen_shift(ctx, op1, rd, rs, rt);
161f85e6 24332 break;
099e5b4d 24333 default:
9c708c7f 24334 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
24335 break;
24336 }
24337 break;
f7685877
YK
24338 case OPC_DLSA:
24339 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24340 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24341 decode_opc_special_r6(env, ctx);
24342 }
24343 break;
099e5b4d 24344#endif
10dc65db
LA
24345 default:
24346 if (ctx->insn_flags & ISA_MIPS32R6) {
24347 decode_opc_special_r6(env, ctx);
9dc324ce
FN
24348 } else if (ctx->insn_flags & INSN_R5900) {
24349 decode_opc_special_tx79(env, ctx);
10dc65db
LA
24350 } else {
24351 decode_opc_special_legacy(env, ctx);
24352 }
24353 }
24354}
24355
d67da337 24356
b621f018
AM
24357#if !defined(TARGET_MIPS64)
24358
d67da337
AM
24359/* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24360#define MXU_APTN1_A 0
24361#define MXU_APTN1_S 1
24362
b70bb918
CJ
24363/* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24364#define MXU_APTN2_AA 0
24365#define MXU_APTN2_AS 1
24366#define MXU_APTN2_SA 2
24367#define MXU_APTN2_SS 3
24368
5bb29992
AM
24369/* MXU execute add/subtract 2-bit pattern 'eptn2' */
24370#define MXU_EPTN2_AA 0
24371#define MXU_EPTN2_AS 1
24372#define MXU_EPTN2_SA 2
24373#define MXU_EPTN2_SS 3
24374
a35723f4 24375/* MXU operand getting pattern 'optn2' */
16fef5b2
AM
24376#define MXU_OPTN2_PTN0 0
24377#define MXU_OPTN2_PTN1 1
24378#define MXU_OPTN2_PTN2 2
24379#define MXU_OPTN2_PTN3 3
24380/* alternative naming scheme for 'optn2' */
a35723f4
CJ
24381#define MXU_OPTN2_WW 0
24382#define MXU_OPTN2_LW 1
24383#define MXU_OPTN2_HW 2
24384#define MXU_OPTN2_XW 3
24385
53f1131f
CJ
24386/* MXU operand getting pattern 'optn3' */
24387#define MXU_OPTN3_PTN0 0
24388#define MXU_OPTN3_PTN1 1
24389#define MXU_OPTN3_PTN2 2
24390#define MXU_OPTN3_PTN3 3
24391#define MXU_OPTN3_PTN4 4
24392#define MXU_OPTN3_PTN5 5
24393#define MXU_OPTN3_PTN6 6
24394#define MXU_OPTN3_PTN7 7
24395
d67da337 24396
96992d1a
CJ
24397/*
24398 * S32I2M XRa, rb - Register move from GRF to XRF
24399 */
24400static void gen_mxu_s32i2m(DisasContext *ctx)
24401{
24402 TCGv t0;
24403 uint32_t XRa, Rb;
24404
24405 t0 = tcg_temp_new();
24406
24407 XRa = extract32(ctx->opcode, 6, 5);
24408 Rb = extract32(ctx->opcode, 16, 5);
24409
24410 gen_load_gpr(t0, Rb);
24411 if (XRa <= 15) {
24412 gen_store_mxu_gpr(t0, XRa);
24413 } else if (XRa == 16) {
24414 gen_store_mxu_cr(t0);
24415 }
24416
24417 tcg_temp_free(t0);
24418}
24419
24420/*
24421 * S32M2I XRa, rb - Register move from XRF to GRF
24422 */
24423static void gen_mxu_s32m2i(DisasContext *ctx)
24424{
24425 TCGv t0;
24426 uint32_t XRa, Rb;
24427
24428 t0 = tcg_temp_new();
24429
24430 XRa = extract32(ctx->opcode, 6, 5);
24431 Rb = extract32(ctx->opcode, 16, 5);
24432
24433 if (XRa <= 15) {
24434 gen_load_mxu_gpr(t0, XRa);
24435 } else if (XRa == 16) {
24436 gen_load_mxu_cr(t0);
24437 }
24438
24439 gen_store_gpr(t0, Rb);
24440
24441 tcg_temp_free(t0);
24442}
24443
be57bcdb
CJ
24444/*
24445 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24446 */
24447static void gen_mxu_s8ldd(DisasContext *ctx)
24448{
24449 TCGv t0, t1;
be57bcdb
CJ
24450 uint32_t XRa, Rb, s8, optn3;
24451
24452 t0 = tcg_temp_new();
24453 t1 = tcg_temp_new();
24454
be57bcdb
CJ
24455 XRa = extract32(ctx->opcode, 6, 4);
24456 s8 = extract32(ctx->opcode, 10, 8);
24457 optn3 = extract32(ctx->opcode, 18, 3);
24458 Rb = extract32(ctx->opcode, 21, 5);
24459
be57bcdb
CJ
24460 gen_load_gpr(t0, Rb);
24461 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24462
24463 switch (optn3) {
24464 /* XRa[7:0] = tmp8 */
24465 case MXU_OPTN3_PTN0:
24466 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24467 gen_load_mxu_gpr(t0, XRa);
24468 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24469 break;
24470 /* XRa[15:8] = tmp8 */
24471 case MXU_OPTN3_PTN1:
24472 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24473 gen_load_mxu_gpr(t0, XRa);
24474 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24475 break;
24476 /* XRa[23:16] = tmp8 */
24477 case MXU_OPTN3_PTN2:
24478 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24479 gen_load_mxu_gpr(t0, XRa);
24480 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24481 break;
24482 /* XRa[31:24] = tmp8 */
24483 case MXU_OPTN3_PTN3:
24484 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24485 gen_load_mxu_gpr(t0, XRa);
24486 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24487 break;
24488 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24489 case MXU_OPTN3_PTN4:
24490 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24491 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24492 break;
24493 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24494 case MXU_OPTN3_PTN5:
24495 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24496 tcg_gen_shli_tl(t1, t1, 8);
24497 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24498 break;
24499 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24500 case MXU_OPTN3_PTN6:
24501 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24502 tcg_gen_mov_tl(t0, t1);
24503 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24504 tcg_gen_shli_tl(t1, t1, 16);
24505 tcg_gen_or_tl(t0, t0, t1);
24506 break;
24507 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24508 case MXU_OPTN3_PTN7:
24509 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24510 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24511 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24512 break;
24513 }
24514
24515 gen_store_mxu_gpr(t0, XRa);
24516
be57bcdb
CJ
24517 tcg_temp_free(t0);
24518 tcg_temp_free(t1);
24519}
24520
72c9bcf8
CJ
24521/*
24522 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24523 */
24524static void gen_mxu_d16mul(DisasContext *ctx)
24525{
24526 TCGv t0, t1, t2, t3;
72c9bcf8
CJ
24527 uint32_t XRa, XRb, XRc, XRd, optn2;
24528
24529 t0 = tcg_temp_new();
24530 t1 = tcg_temp_new();
24531 t2 = tcg_temp_new();
24532 t3 = tcg_temp_new();
24533
72c9bcf8
CJ
24534 XRa = extract32(ctx->opcode, 6, 4);
24535 XRb = extract32(ctx->opcode, 10, 4);
24536 XRc = extract32(ctx->opcode, 14, 4);
24537 XRd = extract32(ctx->opcode, 18, 4);
24538 optn2 = extract32(ctx->opcode, 22, 2);
24539
72c9bcf8
CJ
24540 gen_load_mxu_gpr(t1, XRb);
24541 tcg_gen_sextract_tl(t0, t1, 0, 16);
24542 tcg_gen_sextract_tl(t1, t1, 16, 16);
24543 gen_load_mxu_gpr(t3, XRc);
24544 tcg_gen_sextract_tl(t2, t3, 0, 16);
24545 tcg_gen_sextract_tl(t3, t3, 16, 16);
24546
24547 switch (optn2) {
24548 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24549 tcg_gen_mul_tl(t3, t1, t3);
24550 tcg_gen_mul_tl(t2, t0, t2);
24551 break;
24552 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24553 tcg_gen_mul_tl(t3, t0, t3);
24554 tcg_gen_mul_tl(t2, t0, t2);
24555 break;
24556 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24557 tcg_gen_mul_tl(t3, t1, t3);
24558 tcg_gen_mul_tl(t2, t1, t2);
24559 break;
24560 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24561 tcg_gen_mul_tl(t3, t0, t3);
24562 tcg_gen_mul_tl(t2, t1, t2);
24563 break;
24564 }
24565 gen_store_mxu_gpr(t3, XRa);
24566 gen_store_mxu_gpr(t2, XRd);
24567
72c9bcf8
CJ
24568 tcg_temp_free(t0);
24569 tcg_temp_free(t1);
24570 tcg_temp_free(t2);
24571 tcg_temp_free(t3);
24572}
24573
e67915b4
CJ
24574/*
24575 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
24576 * and accumulate
24577 */
24578static void gen_mxu_d16mac(DisasContext *ctx)
24579{
24580 TCGv t0, t1, t2, t3;
e67915b4
CJ
24581 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
24582
24583 t0 = tcg_temp_new();
24584 t1 = tcg_temp_new();
24585 t2 = tcg_temp_new();
24586 t3 = tcg_temp_new();
24587
e67915b4
CJ
24588 XRa = extract32(ctx->opcode, 6, 4);
24589 XRb = extract32(ctx->opcode, 10, 4);
24590 XRc = extract32(ctx->opcode, 14, 4);
24591 XRd = extract32(ctx->opcode, 18, 4);
24592 optn2 = extract32(ctx->opcode, 22, 2);
24593 aptn2 = extract32(ctx->opcode, 24, 2);
24594
e67915b4
CJ
24595 gen_load_mxu_gpr(t1, XRb);
24596 tcg_gen_sextract_tl(t0, t1, 0, 16);
24597 tcg_gen_sextract_tl(t1, t1, 16, 16);
24598
24599 gen_load_mxu_gpr(t3, XRc);
24600 tcg_gen_sextract_tl(t2, t3, 0, 16);
24601 tcg_gen_sextract_tl(t3, t3, 16, 16);
24602
24603 switch (optn2) {
24604 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24605 tcg_gen_mul_tl(t3, t1, t3);
24606 tcg_gen_mul_tl(t2, t0, t2);
24607 break;
24608 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24609 tcg_gen_mul_tl(t3, t0, t3);
24610 tcg_gen_mul_tl(t2, t0, t2);
24611 break;
24612 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24613 tcg_gen_mul_tl(t3, t1, t3);
24614 tcg_gen_mul_tl(t2, t1, t2);
24615 break;
24616 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24617 tcg_gen_mul_tl(t3, t0, t3);
24618 tcg_gen_mul_tl(t2, t1, t2);
24619 break;
24620 }
24621 gen_load_mxu_gpr(t0, XRa);
24622 gen_load_mxu_gpr(t1, XRd);
24623
24624 switch (aptn2) {
24625 case MXU_APTN2_AA:
24626 tcg_gen_add_tl(t3, t0, t3);
24627 tcg_gen_add_tl(t2, t1, t2);
24628 break;
24629 case MXU_APTN2_AS:
24630 tcg_gen_add_tl(t3, t0, t3);
24631 tcg_gen_sub_tl(t2, t1, t2);
24632 break;
24633 case MXU_APTN2_SA:
24634 tcg_gen_sub_tl(t3, t0, t3);
24635 tcg_gen_add_tl(t2, t1, t2);
24636 break;
24637 case MXU_APTN2_SS:
24638 tcg_gen_sub_tl(t3, t0, t3);
24639 tcg_gen_sub_tl(t2, t1, t2);
24640 break;
24641 }
24642 gen_store_mxu_gpr(t3, XRa);
24643 gen_store_mxu_gpr(t2, XRd);
24644
e67915b4
CJ
24645 tcg_temp_free(t0);
24646 tcg_temp_free(t1);
24647 tcg_temp_free(t2);
24648 tcg_temp_free(t3);
24649}
24650
a9a4181b
CJ
24651/*
24652 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
24653 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
24654 */
24655static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
24656{
24657 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
a9a4181b
CJ
24658 uint32_t XRa, XRb, XRc, XRd, sel;
24659
24660 t0 = tcg_temp_new();
24661 t1 = tcg_temp_new();
24662 t2 = tcg_temp_new();
24663 t3 = tcg_temp_new();
24664 t4 = tcg_temp_new();
24665 t5 = tcg_temp_new();
24666 t6 = tcg_temp_new();
24667 t7 = tcg_temp_new();
24668
a9a4181b
CJ
24669 XRa = extract32(ctx->opcode, 6, 4);
24670 XRb = extract32(ctx->opcode, 10, 4);
24671 XRc = extract32(ctx->opcode, 14, 4);
24672 XRd = extract32(ctx->opcode, 18, 4);
24673 sel = extract32(ctx->opcode, 22, 2);
24674
a9a4181b
CJ
24675 gen_load_mxu_gpr(t3, XRb);
24676 gen_load_mxu_gpr(t7, XRc);
24677
24678 if (sel == 0x2) {
24679 /* Q8MULSU */
24680 tcg_gen_ext8s_tl(t0, t3);
24681 tcg_gen_shri_tl(t3, t3, 8);
24682 tcg_gen_ext8s_tl(t1, t3);
24683 tcg_gen_shri_tl(t3, t3, 8);
24684 tcg_gen_ext8s_tl(t2, t3);
24685 tcg_gen_shri_tl(t3, t3, 8);
24686 tcg_gen_ext8s_tl(t3, t3);
24687 } else {
24688 /* Q8MUL */
24689 tcg_gen_ext8u_tl(t0, t3);
24690 tcg_gen_shri_tl(t3, t3, 8);
24691 tcg_gen_ext8u_tl(t1, t3);
24692 tcg_gen_shri_tl(t3, t3, 8);
24693 tcg_gen_ext8u_tl(t2, t3);
24694 tcg_gen_shri_tl(t3, t3, 8);
24695 tcg_gen_ext8u_tl(t3, t3);
24696 }
24697
24698 tcg_gen_ext8u_tl(t4, t7);
24699 tcg_gen_shri_tl(t7, t7, 8);
24700 tcg_gen_ext8u_tl(t5, t7);
24701 tcg_gen_shri_tl(t7, t7, 8);
24702 tcg_gen_ext8u_tl(t6, t7);
24703 tcg_gen_shri_tl(t7, t7, 8);
24704 tcg_gen_ext8u_tl(t7, t7);
24705
24706 tcg_gen_mul_tl(t0, t0, t4);
24707 tcg_gen_mul_tl(t1, t1, t5);
24708 tcg_gen_mul_tl(t2, t2, t6);
24709 tcg_gen_mul_tl(t3, t3, t7);
24710
24711 tcg_gen_andi_tl(t0, t0, 0xFFFF);
24712 tcg_gen_andi_tl(t1, t1, 0xFFFF);
24713 tcg_gen_andi_tl(t2, t2, 0xFFFF);
24714 tcg_gen_andi_tl(t3, t3, 0xFFFF);
24715
24716 tcg_gen_shli_tl(t1, t1, 16);
24717 tcg_gen_shli_tl(t3, t3, 16);
24718
24719 tcg_gen_or_tl(t0, t0, t1);
24720 tcg_gen_or_tl(t1, t2, t3);
24721
24722 gen_store_mxu_gpr(t0, XRd);
24723 gen_store_mxu_gpr(t1, XRa);
24724
a9a4181b
CJ
24725 tcg_temp_free(t0);
24726 tcg_temp_free(t1);
24727 tcg_temp_free(t2);
24728 tcg_temp_free(t3);
24729 tcg_temp_free(t4);
24730 tcg_temp_free(t5);
24731 tcg_temp_free(t6);
24732 tcg_temp_free(t7);
24733}
24734
4ca83721
CJ
24735/*
24736 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
24737 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
24738 */
24739static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
24740{
24741 TCGv t0, t1;
4ca83721
CJ
24742 uint32_t XRa, Rb, s12, sel;
24743
24744 t0 = tcg_temp_new();
24745 t1 = tcg_temp_new();
24746
4ca83721
CJ
24747 XRa = extract32(ctx->opcode, 6, 4);
24748 s12 = extract32(ctx->opcode, 10, 10);
24749 sel = extract32(ctx->opcode, 20, 1);
24750 Rb = extract32(ctx->opcode, 21, 5);
24751
4ca83721
CJ
24752 gen_load_gpr(t0, Rb);
24753
24754 tcg_gen_movi_tl(t1, s12);
24755 tcg_gen_shli_tl(t1, t1, 2);
24756 if (s12 & 0x200) {
24757 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
24758 }
24759 tcg_gen_add_tl(t1, t0, t1);
24760 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
24761
24762 if (sel == 1) {
24763 /* S32LDDR */
24764 tcg_gen_bswap32_tl(t1, t1);
24765 }
24766 gen_store_mxu_gpr(t1, XRa);
24767
4ca83721
CJ
24768 tcg_temp_free(t0);
24769 tcg_temp_free(t1);
24770}
24771
96992d1a 24772
b621f018
AM
24773/*
24774 * MXU instruction category: logic
24775 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24776 *
24777 * S32NOR S32AND S32OR S32XOR
24778 */
24779
24780/*
24781 * S32NOR XRa, XRb, XRc
24782 * Update XRa with the result of logical bitwise 'nor' operation
24783 * applied to the content of XRb and XRc.
24784 *
24785 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24786 * +-----------+---------+-----+-------+-------+-------+-----------+
24787 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24788 * +-----------+---------+-----+-------+-------+-------+-----------+
24789 */
24790static void gen_mxu_S32NOR(DisasContext *ctx)
24791{
24792 uint32_t pad, XRc, XRb, XRa;
24793
24794 pad = extract32(ctx->opcode, 21, 5);
24795 XRc = extract32(ctx->opcode, 14, 4);
24796 XRb = extract32(ctx->opcode, 10, 4);
24797 XRa = extract32(ctx->opcode, 6, 4);
24798
24799 if (unlikely(pad != 0)) {
24800 /* opcode padding incorrect -> do nothing */
24801 } else if (unlikely(XRa == 0)) {
24802 /* destination is zero register -> do nothing */
24803 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24804 /* both operands zero registers -> just set destination to all 1s */
24805 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
24806 } else if (unlikely(XRb == 0)) {
24807 /* XRb zero register -> just set destination to the negation of XRc */
24808 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
24809 } else if (unlikely(XRc == 0)) {
24810 /* XRa zero register -> just set destination to the negation of XRb */
24811 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24812 } else if (unlikely(XRb == XRc)) {
24813 /* both operands same -> just set destination to the negation of XRb */
24814 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24815 } else {
24816 /* the most general case */
24817 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24818 }
24819}
24820
24821/*
24822 * S32AND XRa, XRb, XRc
24823 * Update XRa with the result of logical bitwise 'and' operation
24824 * applied to the content of XRb and XRc.
24825 *
24826 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24827 * +-----------+---------+-----+-------+-------+-------+-----------+
24828 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24829 * +-----------+---------+-----+-------+-------+-------+-----------+
24830 */
24831static void gen_mxu_S32AND(DisasContext *ctx)
24832{
24833 uint32_t pad, XRc, XRb, XRa;
24834
24835 pad = extract32(ctx->opcode, 21, 5);
24836 XRc = extract32(ctx->opcode, 14, 4);
24837 XRb = extract32(ctx->opcode, 10, 4);
24838 XRa = extract32(ctx->opcode, 6, 4);
24839
24840 if (unlikely(pad != 0)) {
24841 /* opcode padding incorrect -> do nothing */
24842 } else if (unlikely(XRa == 0)) {
24843 /* destination is zero register -> do nothing */
24844 } else if (unlikely((XRb == 0) || (XRc == 0))) {
24845 /* one of operands zero register -> just set destination to all 0s */
24846 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24847 } else if (unlikely(XRb == XRc)) {
24848 /* both operands same -> just set destination to one of them */
24849 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24850 } else {
24851 /* the most general case */
24852 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24853 }
24854}
24855
24856/*
24857 * S32OR XRa, XRb, XRc
24858 * Update XRa with the result of logical bitwise 'or' operation
24859 * applied to the content of XRb and XRc.
24860 *
24861 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24862 * +-----------+---------+-----+-------+-------+-------+-----------+
24863 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24864 * +-----------+---------+-----+-------+-------+-------+-----------+
24865 */
24866static void gen_mxu_S32OR(DisasContext *ctx)
24867{
24868 uint32_t pad, XRc, XRb, XRa;
24869
24870 pad = extract32(ctx->opcode, 21, 5);
24871 XRc = extract32(ctx->opcode, 14, 4);
24872 XRb = extract32(ctx->opcode, 10, 4);
24873 XRa = extract32(ctx->opcode, 6, 4);
24874
24875 if (unlikely(pad != 0)) {
24876 /* opcode padding incorrect -> do nothing */
24877 } else if (unlikely(XRa == 0)) {
24878 /* destination is zero register -> do nothing */
24879 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24880 /* both operands zero registers -> just set destination to all 0s */
24881 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24882 } else if (unlikely(XRb == 0)) {
24883 /* XRb zero register -> just set destination to the content of XRc */
24884 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
24885 } else if (unlikely(XRc == 0)) {
24886 /* XRc zero register -> just set destination to the content of XRb */
24887 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24888 } else if (unlikely(XRb == XRc)) {
24889 /* both operands same -> just set destination to one of them */
24890 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24891 } else {
24892 /* the most general case */
24893 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24894 }
24895}
24896
24897/*
24898 * S32XOR XRa, XRb, XRc
24899 * Update XRa with the result of logical bitwise 'xor' operation
24900 * applied to the content of XRb and XRc.
24901 *
24902 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24903 * +-----------+---------+-----+-------+-------+-------+-----------+
24904 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24905 * +-----------+---------+-----+-------+-------+-------+-----------+
24906 */
24907static void gen_mxu_S32XOR(DisasContext *ctx)
24908{
24909 uint32_t pad, XRc, XRb, XRa;
24910
24911 pad = extract32(ctx->opcode, 21, 5);
24912 XRc = extract32(ctx->opcode, 14, 4);
24913 XRb = extract32(ctx->opcode, 10, 4);
24914 XRa = extract32(ctx->opcode, 6, 4);
24915
24916 if (unlikely(pad != 0)) {
24917 /* opcode padding incorrect -> do nothing */
24918 } else if (unlikely(XRa == 0)) {
24919 /* destination is zero register -> do nothing */
24920 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24921 /* both operands zero registers -> just set destination to all 0s */
24922 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24923 } else if (unlikely(XRb == 0)) {
24924 /* XRb zero register -> just set destination to the content of XRc */
24925 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
24926 } else if (unlikely(XRc == 0)) {
24927 /* XRc zero register -> just set destination to the content of XRb */
24928 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24929 } else if (unlikely(XRb == XRc)) {
24930 /* both operands same -> just set destination to all 0s */
24931 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24932 } else {
24933 /* the most general case */
24934 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
24935 }
24936}
24937
24938
bb84cbf3
AM
24939/*
24940 * MXU instruction category max/min
24941 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24942 *
24943 * S32MAX D16MAX Q8MAX
24944 * S32MIN D16MIN Q8MIN
24945 */
24946
24947/*
24948 * S32MAX XRa, XRb, XRc
24949 * Update XRa with the maximum of signed 32-bit integers contained
24950 * in XRb and XRc.
24951 *
24952 * S32MIN XRa, XRb, XRc
24953 * Update XRa with the minimum of signed 32-bit integers contained
24954 * in XRb and XRc.
24955 *
24956 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24957 * +-----------+---------+-----+-------+-------+-------+-----------+
24958 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
24959 * +-----------+---------+-----+-------+-------+-------+-----------+
24960 */
24961static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
24962{
24963 uint32_t pad, opc, XRc, XRb, XRa;
24964
24965 pad = extract32(ctx->opcode, 21, 5);
24966 opc = extract32(ctx->opcode, 18, 3);
24967 XRc = extract32(ctx->opcode, 14, 4);
24968 XRb = extract32(ctx->opcode, 10, 4);
24969 XRa = extract32(ctx->opcode, 6, 4);
24970
24971 if (unlikely(pad != 0)) {
24972 /* opcode padding incorrect -> do nothing */
24973 } else if (unlikely(XRa == 0)) {
24974 /* destination is zero register -> do nothing */
24975 } else if (unlikely((XRb == 0) && (XRc == 0))) {
24976 /* both operands zero registers -> just set destination to zero */
24977 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
24978 } else if (unlikely((XRb == 0) || (XRc == 0))) {
24979 /* exactly one operand is zero register - find which one is not...*/
24980 uint32_t XRx = XRb ? XRb : XRc;
24981 /* ...and do max/min operation with one operand 0 */
24982 if (opc == OPC_MXU_S32MAX) {
24983 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
24984 } else {
24985 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
24986 }
24987 } else if (unlikely(XRb == XRc)) {
24988 /* both operands same -> just set destination to one of them */
24989 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
24990 } else {
24991 /* the most general case */
24992 if (opc == OPC_MXU_S32MAX) {
24993 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
24994 mxu_gpr[XRc - 1]);
24995 } else {
24996 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
24997 mxu_gpr[XRc - 1]);
24998 }
24999 }
25000}
25001
25002/*
25003 * D16MAX
25004 * Update XRa with the 16-bit-wise maximums of signed integers
25005 * contained in XRb and XRc.
25006 *
25007 * D16MIN
25008 * Update XRa with the 16-bit-wise minimums of signed integers
25009 * contained in XRb and XRc.
25010 *
25011 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25012 * +-----------+---------+-----+-------+-------+-------+-----------+
25013 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25014 * +-----------+---------+-----+-------+-------+-------+-----------+
25015 */
25016static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25017{
25018 uint32_t pad, opc, XRc, XRb, XRa;
25019
25020 pad = extract32(ctx->opcode, 21, 5);
25021 opc = extract32(ctx->opcode, 18, 3);
25022 XRc = extract32(ctx->opcode, 14, 4);
25023 XRb = extract32(ctx->opcode, 10, 4);
25024 XRa = extract32(ctx->opcode, 6, 4);
25025
25026 if (unlikely(pad != 0)) {
25027 /* opcode padding incorrect -> do nothing */
25028 } else if (unlikely(XRc == 0)) {
25029 /* destination is zero register -> do nothing */
25030 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25031 /* both operands zero registers -> just set destination to zero */
25032 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25033 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25034 /* exactly one operand is zero register - find which one is not...*/
25035 uint32_t XRx = XRb ? XRb : XRc;
25036 /* ...and do half-word-wise max/min with one operand 0 */
25037 TCGv_i32 t0 = tcg_temp_new();
25038 TCGv_i32 t1 = tcg_const_i32(0);
25039
25040 /* the left half-word first */
25041 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25042 if (opc == OPC_MXU_D16MAX) {
25043 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25044 } else {
25045 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25046 }
25047
25048 /* the right half-word */
25049 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25050 /* move half-words to the leftmost position */
25051 tcg_gen_shli_i32(t0, t0, 16);
25052 /* t0 will be max/min of t0 and t1 */
25053 if (opc == OPC_MXU_D16MAX) {
25054 tcg_gen_smax_i32(t0, t0, t1);
25055 } else {
25056 tcg_gen_smin_i32(t0, t0, t1);
25057 }
25058 /* return resulting half-words to its original position */
25059 tcg_gen_shri_i32(t0, t0, 16);
25060 /* finaly update the destination */
25061 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25062
25063 tcg_temp_free(t1);
25064 tcg_temp_free(t0);
25065 } else if (unlikely(XRb == XRc)) {
25066 /* both operands same -> just set destination to one of them */
25067 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25068 } else {
25069 /* the most general case */
25070 TCGv_i32 t0 = tcg_temp_new();
25071 TCGv_i32 t1 = tcg_temp_new();
25072
25073 /* the left half-word first */
25074 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25075 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25076 if (opc == OPC_MXU_D16MAX) {
25077 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25078 } else {
25079 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25080 }
25081
25082 /* the right half-word */
25083 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25084 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25085 /* move half-words to the leftmost position */
25086 tcg_gen_shli_i32(t0, t0, 16);
25087 tcg_gen_shli_i32(t1, t1, 16);
25088 /* t0 will be max/min of t0 and t1 */
25089 if (opc == OPC_MXU_D16MAX) {
25090 tcg_gen_smax_i32(t0, t0, t1);
25091 } else {
25092 tcg_gen_smin_i32(t0, t0, t1);
25093 }
25094 /* return resulting half-words to its original position */
25095 tcg_gen_shri_i32(t0, t0, 16);
25096 /* finaly update the destination */
25097 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25098
25099 tcg_temp_free(t1);
25100 tcg_temp_free(t0);
25101 }
25102}
25103
25104/*
25105 * Q8MAX
25106 * Update XRa with the 8-bit-wise maximums of signed integers
25107 * contained in XRb and XRc.
25108 *
25109 * Q8MIN
25110 * Update XRa with the 8-bit-wise minimums of signed integers
25111 * contained in XRb and XRc.
25112 *
25113 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25114 * +-----------+---------+-----+-------+-------+-------+-----------+
25115 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25116 * +-----------+---------+-----+-------+-------+-------+-----------+
25117 */
25118static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25119{
25120 uint32_t pad, opc, XRc, XRb, XRa;
25121
25122 pad = extract32(ctx->opcode, 21, 5);
25123 opc = extract32(ctx->opcode, 18, 3);
25124 XRc = extract32(ctx->opcode, 14, 4);
25125 XRb = extract32(ctx->opcode, 10, 4);
25126 XRa = extract32(ctx->opcode, 6, 4);
25127
25128 if (unlikely(pad != 0)) {
25129 /* opcode padding incorrect -> do nothing */
25130 } else if (unlikely(XRa == 0)) {
25131 /* destination is zero register -> do nothing */
25132 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25133 /* both operands zero registers -> just set destination to zero */
25134 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25135 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25136 /* exactly one operand is zero register - make it be the first...*/
25137 uint32_t XRx = XRb ? XRb : XRc;
25138 /* ...and do byte-wise max/min with one operand 0 */
25139 TCGv_i32 t0 = tcg_temp_new();
25140 TCGv_i32 t1 = tcg_const_i32(0);
25141 int32_t i;
25142
25143 /* the leftmost byte (byte 3) first */
25144 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25145 if (opc == OPC_MXU_Q8MAX) {
25146 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25147 } else {
25148 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25149 }
25150
25151 /* bytes 2, 1, 0 */
25152 for (i = 2; i >= 0; i--) {
25153 /* extract the byte */
25154 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25155 /* move the byte to the leftmost position */
25156 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25157 /* t0 will be max/min of t0 and t1 */
25158 if (opc == OPC_MXU_Q8MAX) {
25159 tcg_gen_smax_i32(t0, t0, t1);
25160 } else {
25161 tcg_gen_smin_i32(t0, t0, t1);
25162 }
25163 /* return resulting byte to its original position */
25164 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25165 /* finaly update the destination */
25166 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25167 }
25168
25169 tcg_temp_free(t1);
25170 tcg_temp_free(t0);
25171 } else if (unlikely(XRb == XRc)) {
25172 /* both operands same -> just set destination to one of them */
25173 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25174 } else {
25175 /* the most general case */
25176 TCGv_i32 t0 = tcg_temp_new();
25177 TCGv_i32 t1 = tcg_temp_new();
25178 int32_t i;
25179
25180 /* the leftmost bytes (bytes 3) first */
25181 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25182 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25183 if (opc == OPC_MXU_Q8MAX) {
25184 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25185 } else {
25186 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25187 }
25188
25189 /* bytes 2, 1, 0 */
25190 for (i = 2; i >= 0; i--) {
25191 /* extract corresponding bytes */
25192 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25193 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25194 /* move the bytes to the leftmost position */
25195 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25196 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25197 /* t0 will be max/min of t0 and t1 */
25198 if (opc == OPC_MXU_Q8MAX) {
25199 tcg_gen_smax_i32(t0, t0, t1);
25200 } else {
25201 tcg_gen_smin_i32(t0, t0, t1);
25202 }
25203 /* return resulting byte to its original position */
25204 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25205 /* finaly update the destination */
25206 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25207 }
25208
25209 tcg_temp_free(t1);
25210 tcg_temp_free(t0);
25211 }
25212}
25213
25214
79f5fee7
AM
25215/*
25216 * MXU instruction category: align
25217 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25218 *
25219 * S32ALN S32ALNI
25220 */
25221
25222/*
25223 * S32ALNI XRc, XRb, XRa, optn3
25224 * Arrange bytes from XRb and XRc according to one of five sets of
25225 * rules determined by optn3, and place the result in XRa.
25226 *
25227 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25228 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25229 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25230 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25231 *
25232 */
25233static void gen_mxu_S32ALNI(DisasContext *ctx)
25234{
25235 uint32_t optn3, pad, XRc, XRb, XRa;
25236
25237 optn3 = extract32(ctx->opcode, 23, 3);
25238 pad = extract32(ctx->opcode, 21, 2);
25239 XRc = extract32(ctx->opcode, 14, 4);
25240 XRb = extract32(ctx->opcode, 10, 4);
25241 XRa = extract32(ctx->opcode, 6, 4);
25242
25243 if (unlikely(pad != 0)) {
25244 /* opcode padding incorrect -> do nothing */
25245 } else if (unlikely(XRa == 0)) {
25246 /* destination is zero register -> do nothing */
25247 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25248 /* both operands zero registers -> just set destination to all 0s */
25249 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25250 } else if (unlikely(XRb == 0)) {
25251 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25252 switch (optn3) {
25253 case MXU_OPTN3_PTN0:
25254 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25255 break;
25256 case MXU_OPTN3_PTN1:
25257 case MXU_OPTN3_PTN2:
25258 case MXU_OPTN3_PTN3:
25259 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25260 8 * (4 - optn3));
25261 break;
25262 case MXU_OPTN3_PTN4:
25263 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25264 break;
25265 }
25266 } else if (unlikely(XRc == 0)) {
25267 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25268 switch (optn3) {
25269 case MXU_OPTN3_PTN0:
25270 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25271 break;
25272 case MXU_OPTN3_PTN1:
25273 case MXU_OPTN3_PTN2:
25274 case MXU_OPTN3_PTN3:
25275 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25276 break;
25277 case MXU_OPTN3_PTN4:
25278 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25279 break;
25280 }
25281 } else if (unlikely(XRb == XRc)) {
25282 /* both operands same -> just rotation or moving from any of them */
25283 switch (optn3) {
25284 case MXU_OPTN3_PTN0:
25285 case MXU_OPTN3_PTN4:
25286 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25287 break;
25288 case MXU_OPTN3_PTN1:
25289 case MXU_OPTN3_PTN2:
25290 case MXU_OPTN3_PTN3:
25291 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25292 break;
25293 }
25294 } else {
25295 /* the most general case */
25296 switch (optn3) {
25297 case MXU_OPTN3_PTN0:
25298 {
25299 /* */
25300 /* XRb XRc */
25301 /* +---------------+ */
25302 /* | A B C D | E F G H */
25303 /* +-------+-------+ */
25304 /* | */
25305 /* XRa */
25306 /* */
25307
25308 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25309 }
25310 break;
25311 case MXU_OPTN3_PTN1:
25312 {
25313 /* */
25314 /* XRb XRc */
25315 /* +-------------------+ */
25316 /* A | B C D E | F G H */
25317 /* +---------+---------+ */
25318 /* | */
25319 /* XRa */
25320 /* */
25321
25322 TCGv_i32 t0 = tcg_temp_new();
25323 TCGv_i32 t1 = tcg_temp_new();
25324
25325 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25326 tcg_gen_shli_i32(t0, t0, 8);
25327
25328 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25329 tcg_gen_shri_i32(t1, t1, 24);
25330
25331 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25332
25333 tcg_temp_free(t1);
25334 tcg_temp_free(t0);
25335 }
25336 break;
25337 case MXU_OPTN3_PTN2:
25338 {
25339 /* */
25340 /* XRb XRc */
25341 /* +-------------------+ */
25342 /* A B | C D E F | G H */
25343 /* +---------+---------+ */
25344 /* | */
25345 /* XRa */
25346 /* */
25347
25348 TCGv_i32 t0 = tcg_temp_new();
25349 TCGv_i32 t1 = tcg_temp_new();
25350
25351 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25352 tcg_gen_shli_i32(t0, t0, 16);
25353
25354 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25355 tcg_gen_shri_i32(t1, t1, 16);
25356
25357 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25358
25359 tcg_temp_free(t1);
25360 tcg_temp_free(t0);
25361 }
25362 break;
25363 case MXU_OPTN3_PTN3:
25364 {
25365 /* */
25366 /* XRb XRc */
25367 /* +-------------------+ */
25368 /* A B C | D E F G | H */
25369 /* +---------+---------+ */
25370 /* | */
25371 /* XRa */
25372 /* */
25373
25374 TCGv_i32 t0 = tcg_temp_new();
25375 TCGv_i32 t1 = tcg_temp_new();
25376
25377 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25378 tcg_gen_shli_i32(t0, t0, 24);
25379
25380 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25381 tcg_gen_shri_i32(t1, t1, 8);
25382
25383 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25384
25385 tcg_temp_free(t1);
25386 tcg_temp_free(t0);
25387 }
25388 break;
25389 case MXU_OPTN3_PTN4:
25390 {
25391 /* */
25392 /* XRb XRc */
25393 /* +---------------+ */
25394 /* A B C D | E F G H | */
25395 /* +-------+-------+ */
25396 /* | */
25397 /* XRa */
25398 /* */
25399
25400 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25401 }
25402 break;
25403 }
25404 }
25405}
25406
25407
96992d1a
CJ
25408/*
25409 * Decoding engine for MXU
25410 * =======================
25411 */
25412
03f40088
AM
25413/*
25414 *
25415 * Decode MXU pool00
25416 *
25417 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25418 * +-----------+---------+-----+-------+-------+-------+-----------+
25419 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25420 * +-----------+---------+-----+-------+-------+-------+-----------+
25421 *
25422 */
25423static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25424{
25425 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25426
25427 switch (opcode) {
25428 case OPC_MXU_S32MAX:
03f40088 25429 case OPC_MXU_S32MIN:
bb84cbf3 25430 gen_mxu_S32MAX_S32MIN(ctx);
03f40088
AM
25431 break;
25432 case OPC_MXU_D16MAX:
03f40088 25433 case OPC_MXU_D16MIN:
bb84cbf3 25434 gen_mxu_D16MAX_D16MIN(ctx);
03f40088
AM
25435 break;
25436 case OPC_MXU_Q8MAX:
03f40088 25437 case OPC_MXU_Q8MIN:
bb84cbf3 25438 gen_mxu_Q8MAX_Q8MIN(ctx);
03f40088
AM
25439 break;
25440 case OPC_MXU_Q8SLT:
25441 /* TODO: Implement emulation of Q8SLT instruction. */
25442 MIPS_INVAL("OPC_MXU_Q8SLT");
25443 generate_exception_end(ctx, EXCP_RI);
25444 break;
25445 case OPC_MXU_Q8SLTU:
25446 /* TODO: Implement emulation of Q8SLTU instruction. */
25447 MIPS_INVAL("OPC_MXU_Q8SLTU");
25448 generate_exception_end(ctx, EXCP_RI);
25449 break;
25450 default:
25451 MIPS_INVAL("decode_opc_mxu");
25452 generate_exception_end(ctx, EXCP_RI);
25453 break;
25454 }
25455}
25456
25457/*
25458 *
25459 * Decode MXU pool01
25460 *
25461 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
25462 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25463 * +-----------+---------+-----+-------+-------+-------+-----------+
25464 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25465 * +-----------+---------+-----+-------+-------+-------+-----------+
25466 *
25467 * Q8ADD:
25468 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25469 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25470 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25471 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25472 *
25473 */
25474static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
25475{
25476 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25477
25478 switch (opcode) {
25479 case OPC_MXU_S32SLT:
25480 /* TODO: Implement emulation of S32SLT instruction. */
25481 MIPS_INVAL("OPC_MXU_S32SLT");
25482 generate_exception_end(ctx, EXCP_RI);
25483 break;
25484 case OPC_MXU_D16SLT:
25485 /* TODO: Implement emulation of D16SLT instruction. */
25486 MIPS_INVAL("OPC_MXU_D16SLT");
25487 generate_exception_end(ctx, EXCP_RI);
25488 break;
25489 case OPC_MXU_D16AVG:
25490 /* TODO: Implement emulation of D16AVG instruction. */
25491 MIPS_INVAL("OPC_MXU_D16AVG");
25492 generate_exception_end(ctx, EXCP_RI);
25493 break;
25494 case OPC_MXU_D16AVGR:
25495 /* TODO: Implement emulation of D16AVGR instruction. */
25496 MIPS_INVAL("OPC_MXU_D16AVGR");
25497 generate_exception_end(ctx, EXCP_RI);
25498 break;
25499 case OPC_MXU_Q8AVG:
25500 /* TODO: Implement emulation of Q8AVG instruction. */
25501 MIPS_INVAL("OPC_MXU_Q8AVG");
25502 generate_exception_end(ctx, EXCP_RI);
25503 break;
25504 case OPC_MXU_Q8AVGR:
25505 /* TODO: Implement emulation of Q8AVGR instruction. */
25506 MIPS_INVAL("OPC_MXU_Q8AVGR");
25507 generate_exception_end(ctx, EXCP_RI);
25508 break;
25509 case OPC_MXU_Q8ADD:
25510 /* TODO: Implement emulation of Q8ADD instruction. */
25511 MIPS_INVAL("OPC_MXU_Q8ADD");
25512 generate_exception_end(ctx, EXCP_RI);
25513 break;
25514 default:
25515 MIPS_INVAL("decode_opc_mxu");
25516 generate_exception_end(ctx, EXCP_RI);
25517 break;
25518 }
25519}
25520
25521/*
25522 *
25523 * Decode MXU pool02
25524 *
25525 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25526 * +-----------+---------+-----+-------+-------+-------+-----------+
25527 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
25528 * +-----------+---------+-----+-------+-------+-------+-----------+
25529 *
25530 */
25531static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
25532{
25533 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25534
25535 switch (opcode) {
25536 case OPC_MXU_S32CPS:
25537 /* TODO: Implement emulation of S32CPS instruction. */
25538 MIPS_INVAL("OPC_MXU_S32CPS");
25539 generate_exception_end(ctx, EXCP_RI);
25540 break;
25541 case OPC_MXU_D16CPS:
25542 /* TODO: Implement emulation of D16CPS instruction. */
25543 MIPS_INVAL("OPC_MXU_D16CPS");
25544 generate_exception_end(ctx, EXCP_RI);
25545 break;
25546 case OPC_MXU_Q8ABD:
25547 /* TODO: Implement emulation of Q8ABD instruction. */
25548 MIPS_INVAL("OPC_MXU_Q8ABD");
25549 generate_exception_end(ctx, EXCP_RI);
25550 break;
25551 case OPC_MXU_Q16SAT:
25552 /* TODO: Implement emulation of Q16SAT instruction. */
25553 MIPS_INVAL("OPC_MXU_Q16SAT");
25554 generate_exception_end(ctx, EXCP_RI);
25555 break;
25556 default:
25557 MIPS_INVAL("decode_opc_mxu");
25558 generate_exception_end(ctx, EXCP_RI);
25559 break;
25560 }
25561}
25562
25563/*
25564 *
25565 * Decode MXU pool03
25566 *
25567 * D16MULF:
25568 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25569 * +-----------+---+---+-------+-------+-------+-------+-----------+
25570 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
25571 * +-----------+---+---+-------+-------+-------+-------+-----------+
25572 *
25573 * D16MULE:
25574 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25575 * +-----------+---+---+-------+-------+-------+-------+-----------+
25576 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
25577 * +-----------+---+---+-------+-------+-------+-------+-----------+
25578 *
25579 */
25580static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
25581{
25582 uint32_t opcode = extract32(ctx->opcode, 24, 2);
25583
25584 switch (opcode) {
25585 case OPC_MXU_D16MULF:
25586 /* TODO: Implement emulation of D16MULF instruction. */
25587 MIPS_INVAL("OPC_MXU_D16MULF");
25588 generate_exception_end(ctx, EXCP_RI);
25589 break;
25590 case OPC_MXU_D16MULE:
25591 /* TODO: Implement emulation of D16MULE instruction. */
25592 MIPS_INVAL("OPC_MXU_D16MULE");
25593 generate_exception_end(ctx, EXCP_RI);
25594 break;
25595 default:
25596 MIPS_INVAL("decode_opc_mxu");
25597 generate_exception_end(ctx, EXCP_RI);
25598 break;
25599 }
25600}
25601
25602/*
25603 *
25604 * Decode MXU pool04
25605 *
25606 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25607 * +-----------+---------+-+-------------------+-------+-----------+
25608 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
25609 * +-----------+---------+-+-------------------+-------+-----------+
25610 *
25611 */
25612static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
25613{
25614 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25615
25616 switch (opcode) {
25617 case OPC_MXU_S32LDD:
03f40088 25618 case OPC_MXU_S32LDDR:
4ca83721 25619 gen_mxu_s32ldd_s32lddr(ctx);
03f40088
AM
25620 break;
25621 default:
25622 MIPS_INVAL("decode_opc_mxu");
25623 generate_exception_end(ctx, EXCP_RI);
25624 break;
25625 }
25626}
25627
25628/*
25629 *
25630 * Decode MXU pool05
25631 *
25632 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25633 * +-----------+---------+-+-------------------+-------+-----------+
25634 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
25635 * +-----------+---------+-+-------------------+-------+-----------+
25636 *
25637 */
25638static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
25639{
25640 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25641
25642 switch (opcode) {
25643 case OPC_MXU_S32STD:
25644 /* TODO: Implement emulation of S32STD instruction. */
25645 MIPS_INVAL("OPC_MXU_S32STD");
25646 generate_exception_end(ctx, EXCP_RI);
25647 break;
25648 case OPC_MXU_S32STDR:
25649 /* TODO: Implement emulation of S32STDR instruction. */
25650 MIPS_INVAL("OPC_MXU_S32STDR");
25651 generate_exception_end(ctx, EXCP_RI);
25652 break;
25653 default:
25654 MIPS_INVAL("decode_opc_mxu");
25655 generate_exception_end(ctx, EXCP_RI);
25656 break;
25657 }
25658}
25659
25660/*
25661 *
25662 * Decode MXU pool06
25663 *
25664 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25665 * +-----------+---------+---------+---+-------+-------+-----------+
25666 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
25667 * +-----------+---------+---------+---+-------+-------+-----------+
25668 *
25669 */
25670static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
25671{
25672 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25673
25674 switch (opcode) {
25675 case OPC_MXU_S32LDDV:
25676 /* TODO: Implement emulation of S32LDDV instruction. */
25677 MIPS_INVAL("OPC_MXU_S32LDDV");
25678 generate_exception_end(ctx, EXCP_RI);
25679 break;
25680 case OPC_MXU_S32LDDVR:
25681 /* TODO: Implement emulation of S32LDDVR instruction. */
25682 MIPS_INVAL("OPC_MXU_S32LDDVR");
25683 generate_exception_end(ctx, EXCP_RI);
25684 break;
25685 default:
25686 MIPS_INVAL("decode_opc_mxu");
25687 generate_exception_end(ctx, EXCP_RI);
25688 break;
25689 }
25690}
25691
25692/*
25693 *
25694 * Decode MXU pool07
25695 *
25696 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25697 * +-----------+---------+---------+---+-------+-------+-----------+
25698 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
25699 * +-----------+---------+---------+---+-------+-------+-----------+
25700 *
25701 */
25702static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
25703{
25704 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25705
25706 switch (opcode) {
25707 case OPC_MXU_S32STDV:
25708 /* TODO: Implement emulation of S32TDV instruction. */
25709 MIPS_INVAL("OPC_MXU_S32TDV");
25710 generate_exception_end(ctx, EXCP_RI);
25711 break;
25712 case OPC_MXU_S32STDVR:
25713 /* TODO: Implement emulation of S32TDVR instruction. */
25714 MIPS_INVAL("OPC_MXU_S32TDVR");
25715 generate_exception_end(ctx, EXCP_RI);
25716 break;
25717 default:
25718 MIPS_INVAL("decode_opc_mxu");
25719 generate_exception_end(ctx, EXCP_RI);
25720 break;
25721 }
25722}
25723
25724/*
25725 *
25726 * Decode MXU pool08
25727 *
25728 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25729 * +-----------+---------+-+-------------------+-------+-----------+
25730 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
25731 * +-----------+---------+-+-------------------+-------+-----------+
25732 *
25733*/
25734static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
25735{
25736 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25737
25738 switch (opcode) {
25739 case OPC_MXU_S32LDI:
25740 /* TODO: Implement emulation of S32LDI instruction. */
25741 MIPS_INVAL("OPC_MXU_S32LDI");
25742 generate_exception_end(ctx, EXCP_RI);
25743 break;
25744 case OPC_MXU_S32LDIR:
25745 /* TODO: Implement emulation of S32LDIR instruction. */
25746 MIPS_INVAL("OPC_MXU_S32LDIR");
25747 generate_exception_end(ctx, EXCP_RI);
25748 break;
25749 default:
25750 MIPS_INVAL("decode_opc_mxu");
25751 generate_exception_end(ctx, EXCP_RI);
25752 break;
25753 }
25754}
25755
25756/*
25757 *
25758 * Decode MXU pool09
25759 *
25760 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25761 * +-----------+---------+-+-------------------+-------+-----------+
25762 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
25763 * +-----------+---------+-+-------------------+-------+-----------+
25764 *
25765 */
25766static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
25767{
25768 uint32_t opcode = extract32(ctx->opcode, 5, 0);
25769
25770 switch (opcode) {
25771 case OPC_MXU_S32SDI:
25772 /* TODO: Implement emulation of S32SDI instruction. */
25773 MIPS_INVAL("OPC_MXU_S32SDI");
25774 generate_exception_end(ctx, EXCP_RI);
25775 break;
25776 case OPC_MXU_S32SDIR:
25777 /* TODO: Implement emulation of S32SDIR instruction. */
25778 MIPS_INVAL("OPC_MXU_S32SDIR");
25779 generate_exception_end(ctx, EXCP_RI);
25780 break;
25781 default:
25782 MIPS_INVAL("decode_opc_mxu");
25783 generate_exception_end(ctx, EXCP_RI);
25784 break;
25785 }
25786}
25787
25788/*
25789 *
25790 * Decode MXU pool10
25791 *
25792 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25793 * +-----------+---------+---------+---+-------+-------+-----------+
25794 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
25795 * +-----------+---------+---------+---+-------+-------+-----------+
25796 *
25797 */
25798static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
25799{
25800 uint32_t opcode = extract32(ctx->opcode, 5, 0);
25801
25802 switch (opcode) {
25803 case OPC_MXU_S32LDIV:
25804 /* TODO: Implement emulation of S32LDIV instruction. */
25805 MIPS_INVAL("OPC_MXU_S32LDIV");
25806 generate_exception_end(ctx, EXCP_RI);
25807 break;
25808 case OPC_MXU_S32LDIVR:
25809 /* TODO: Implement emulation of S32LDIVR instruction. */
25810 MIPS_INVAL("OPC_MXU_S32LDIVR");
25811 generate_exception_end(ctx, EXCP_RI);
25812 break;
25813 default:
25814 MIPS_INVAL("decode_opc_mxu");
25815 generate_exception_end(ctx, EXCP_RI);
25816 break;
25817 }
25818}
25819
25820/*
25821 *
25822 * Decode MXU pool11
25823 *
25824 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25825 * +-----------+---------+---------+---+-------+-------+-----------+
25826 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
25827 * +-----------+---------+---------+---+-------+-------+-----------+
25828 *
25829 */
25830static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
25831{
25832 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25833
25834 switch (opcode) {
25835 case OPC_MXU_S32SDIV:
25836 /* TODO: Implement emulation of S32SDIV instruction. */
25837 MIPS_INVAL("OPC_MXU_S32SDIV");
25838 generate_exception_end(ctx, EXCP_RI);
25839 break;
25840 case OPC_MXU_S32SDIVR:
25841 /* TODO: Implement emulation of S32SDIVR instruction. */
25842 MIPS_INVAL("OPC_MXU_S32SDIVR");
25843 generate_exception_end(ctx, EXCP_RI);
25844 break;
25845 default:
25846 MIPS_INVAL("decode_opc_mxu");
25847 generate_exception_end(ctx, EXCP_RI);
25848 break;
25849 }
25850}
25851
25852/*
25853 *
25854 * Decode MXU pool12
25855 *
25856 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25857 * +-----------+---+---+-------+-------+-------+-------+-----------+
25858 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
25859 * +-----------+---+---+-------+-------+-------+-------+-----------+
25860 *
25861 */
25862static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
25863{
25864 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25865
25866 switch (opcode) {
25867 case OPC_MXU_D32ACC:
25868 /* TODO: Implement emulation of D32ACC instruction. */
25869 MIPS_INVAL("OPC_MXU_D32ACC");
25870 generate_exception_end(ctx, EXCP_RI);
25871 break;
25872 case OPC_MXU_D32ACCM:
25873 /* TODO: Implement emulation of D32ACCM instruction. */
25874 MIPS_INVAL("OPC_MXU_D32ACCM");
25875 generate_exception_end(ctx, EXCP_RI);
25876 break;
25877 case OPC_MXU_D32ASUM:
25878 /* TODO: Implement emulation of D32ASUM instruction. */
25879 MIPS_INVAL("OPC_MXU_D32ASUM");
25880 generate_exception_end(ctx, EXCP_RI);
25881 break;
25882 default:
25883 MIPS_INVAL("decode_opc_mxu");
25884 generate_exception_end(ctx, EXCP_RI);
25885 break;
25886 }
25887}
25888
25889/*
25890 *
25891 * Decode MXU pool13
25892 *
25893 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25894 * +-----------+---+---+-------+-------+-------+-------+-----------+
25895 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
25896 * +-----------+---+---+-------+-------+-------+-------+-----------+
25897 *
25898 */
25899static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
25900{
25901 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25902
25903 switch (opcode) {
25904 case OPC_MXU_Q16ACC:
25905 /* TODO: Implement emulation of Q16ACC instruction. */
25906 MIPS_INVAL("OPC_MXU_Q16ACC");
25907 generate_exception_end(ctx, EXCP_RI);
25908 break;
25909 case OPC_MXU_Q16ACCM:
25910 /* TODO: Implement emulation of Q16ACCM instruction. */
25911 MIPS_INVAL("OPC_MXU_Q16ACCM");
25912 generate_exception_end(ctx, EXCP_RI);
25913 break;
25914 case OPC_MXU_Q16ASUM:
25915 /* TODO: Implement emulation of Q16ASUM instruction. */
25916 MIPS_INVAL("OPC_MXU_Q16ASUM");
25917 generate_exception_end(ctx, EXCP_RI);
25918 break;
25919 default:
25920 MIPS_INVAL("decode_opc_mxu");
25921 generate_exception_end(ctx, EXCP_RI);
25922 break;
25923 }
25924}
25925
25926/*
25927 *
25928 * Decode MXU pool14
25929 *
25930 * Q8ADDE, Q8ACCE:
25931 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25932 * +-----------+---+---+-------+-------+-------+-------+-----------+
25933 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
25934 * +-----------+---+---+-------+-------+-------+-------+-----------+
25935 *
25936 * D8SUM, D8SUMC:
25937 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25938 * +-----------+---+---+-------+-------+-------+-------+-----------+
25939 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
25940 * +-----------+---+---+-------+-------+-------+-------+-----------+
25941 *
25942 */
25943static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
25944{
25945 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25946
25947 switch (opcode) {
25948 case OPC_MXU_Q8ADDE:
25949 /* TODO: Implement emulation of Q8ADDE instruction. */
25950 MIPS_INVAL("OPC_MXU_Q8ADDE");
25951 generate_exception_end(ctx, EXCP_RI);
25952 break;
25953 case OPC_MXU_D8SUM:
25954 /* TODO: Implement emulation of D8SUM instruction. */
25955 MIPS_INVAL("OPC_MXU_D8SUM");
25956 generate_exception_end(ctx, EXCP_RI);
25957 break;
25958 case OPC_MXU_D8SUMC:
25959 /* TODO: Implement emulation of D8SUMC instruction. */
25960 MIPS_INVAL("OPC_MXU_D8SUMC");
25961 generate_exception_end(ctx, EXCP_RI);
25962 break;
25963 default:
25964 MIPS_INVAL("decode_opc_mxu");
25965 generate_exception_end(ctx, EXCP_RI);
25966 break;
25967 }
25968}
25969
25970/*
25971 *
25972 * Decode MXU pool15
25973 *
25974 * S32MUL, S32MULU, S32EXTRV:
25975 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25976 * +-----------+---------+---------+---+-------+-------+-----------+
25977 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
25978 * +-----------+---------+---------+---+-------+-------+-----------+
25979 *
25980 * S32EXTR:
25981 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25982 * +-----------+---------+---------+---+-------+-------+-----------+
25983 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
25984 * +-----------+---------+---------+---+-------+-------+-----------+
25985 *
25986 */
25987static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
25988{
25989 uint32_t opcode = extract32(ctx->opcode, 14, 2);
25990
25991 switch (opcode) {
25992 case OPC_MXU_S32MUL:
25993 /* TODO: Implement emulation of S32MUL instruction. */
25994 MIPS_INVAL("OPC_MXU_S32MUL");
25995 generate_exception_end(ctx, EXCP_RI);
25996 break;
25997 case OPC_MXU_S32MULU:
25998 /* TODO: Implement emulation of S32MULU instruction. */
25999 MIPS_INVAL("OPC_MXU_S32MULU");
26000 generate_exception_end(ctx, EXCP_RI);
26001 break;
26002 case OPC_MXU_S32EXTR:
26003 /* TODO: Implement emulation of S32EXTR instruction. */
26004 MIPS_INVAL("OPC_MXU_S32EXTR");
26005 generate_exception_end(ctx, EXCP_RI);
26006 break;
26007 case OPC_MXU_S32EXTRV:
26008 /* TODO: Implement emulation of S32EXTRV instruction. */
26009 MIPS_INVAL("OPC_MXU_S32EXTRV");
26010 generate_exception_end(ctx, EXCP_RI);
26011 break;
26012 default:
26013 MIPS_INVAL("decode_opc_mxu");
26014 generate_exception_end(ctx, EXCP_RI);
26015 break;
26016 }
26017}
26018
26019/*
26020 *
26021 * Decode MXU pool16
26022 *
26023 * D32SARW:
26024 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26025 * +-----------+---------+-----+-------+-------+-------+-----------+
26026 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26027 * +-----------+---------+-----+-------+-------+-------+-----------+
26028 *
26029 * S32ALN:
26030 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26031 * +-----------+---------+-----+-------+-------+-------+-----------+
26032 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26033 * +-----------+---------+-----+-------+-------+-------+-----------+
26034 *
26035 * S32ALNI:
26036 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26037 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26038 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26039 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26040 *
03f40088
AM
26041 * S32LUI:
26042 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26043 * +-----------+-----+---+-----+-------+---------------+-----------+
26044 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26045 * +-----------+-----+---+-----+-------+---------------+-----------+
26046 *
b621f018
AM
26047 * S32NOR, S32AND, S32OR, S32XOR:
26048 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26049 * +-----------+---------+-----+-------+-------+-------+-----------+
26050 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26051 * +-----------+---------+-----+-------+-------+-------+-----------+
26052 *
03f40088
AM
26053 */
26054static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26055{
26056 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26057
26058 switch (opcode) {
26059 case OPC_MXU_D32SARW:
26060 /* TODO: Implement emulation of D32SARW instruction. */
26061 MIPS_INVAL("OPC_MXU_D32SARW");
26062 generate_exception_end(ctx, EXCP_RI);
26063 break;
26064 case OPC_MXU_S32ALN:
26065 /* TODO: Implement emulation of S32ALN instruction. */
26066 MIPS_INVAL("OPC_MXU_S32ALN");
26067 generate_exception_end(ctx, EXCP_RI);
26068 break;
26069 case OPC_MXU_S32ALNI:
79f5fee7 26070 gen_mxu_S32ALNI(ctx);
03f40088 26071 break;
b621f018
AM
26072 case OPC_MXU_S32LUI:
26073 /* TODO: Implement emulation of S32LUI instruction. */
26074 MIPS_INVAL("OPC_MXU_S32LUI");
03f40088
AM
26075 generate_exception_end(ctx, EXCP_RI);
26076 break;
b621f018
AM
26077 case OPC_MXU_S32NOR:
26078 gen_mxu_S32NOR(ctx);
26079 break;
03f40088 26080 case OPC_MXU_S32AND:
b621f018 26081 gen_mxu_S32AND(ctx);
03f40088
AM
26082 break;
26083 case OPC_MXU_S32OR:
b621f018 26084 gen_mxu_S32OR(ctx);
03f40088
AM
26085 break;
26086 case OPC_MXU_S32XOR:
b621f018 26087 gen_mxu_S32XOR(ctx);
03f40088
AM
26088 break;
26089 default:
26090 MIPS_INVAL("decode_opc_mxu");
26091 generate_exception_end(ctx, EXCP_RI);
26092 break;
26093 }
26094}
26095
26096/*
26097 *
26098 * Decode MXU pool17
26099 *
26100 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
c233bf07
AM
26101 * +-----------+---------+---------+---+---------+-----+-----------+
26102 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26103 * +-----------+---------+---------+---+---------+-----+-----------+
26104 *
26105 */
26106static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26107{
26108 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26109
26110 switch (opcode) {
26111 case OPC_MXU_LXW:
26112 /* TODO: Implement emulation of LXW instruction. */
26113 MIPS_INVAL("OPC_MXU_LXW");
26114 generate_exception_end(ctx, EXCP_RI);
26115 break;
26116 case OPC_MXU_LXH:
26117 /* TODO: Implement emulation of LXH instruction. */
26118 MIPS_INVAL("OPC_MXU_LXH");
26119 generate_exception_end(ctx, EXCP_RI);
26120 break;
26121 case OPC_MXU_LXHU:
26122 /* TODO: Implement emulation of LXHU instruction. */
26123 MIPS_INVAL("OPC_MXU_LXHU");
26124 generate_exception_end(ctx, EXCP_RI);
26125 break;
26126 case OPC_MXU_LXB:
26127 /* TODO: Implement emulation of LXB instruction. */
26128 MIPS_INVAL("OPC_MXU_LXB");
26129 generate_exception_end(ctx, EXCP_RI);
26130 break;
26131 case OPC_MXU_LXBU:
26132 /* TODO: Implement emulation of LXBU instruction. */
26133 MIPS_INVAL("OPC_MXU_LXBU");
26134 generate_exception_end(ctx, EXCP_RI);
26135 break;
26136 default:
26137 MIPS_INVAL("decode_opc_mxu");
26138 generate_exception_end(ctx, EXCP_RI);
26139 break;
26140 }
26141}
26142/*
26143 *
26144 * Decode MXU pool18
26145 *
26146 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
03f40088 26147 * +-----------+---------+-----+-------+-------+-------+-----------+
c233bf07 26148 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
03f40088
AM
26149 * +-----------+---------+-----+-------+-------+-------+-----------+
26150 *
26151 */
c233bf07 26152static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26153{
26154 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26155
26156 switch (opcode) {
26157 case OPC_MXU_D32SLLV:
26158 /* TODO: Implement emulation of D32SLLV instruction. */
26159 MIPS_INVAL("OPC_MXU_D32SLLV");
26160 generate_exception_end(ctx, EXCP_RI);
26161 break;
26162 case OPC_MXU_D32SLRV:
26163 /* TODO: Implement emulation of D32SLRV instruction. */
26164 MIPS_INVAL("OPC_MXU_D32SLRV");
26165 generate_exception_end(ctx, EXCP_RI);
26166 break;
26167 case OPC_MXU_D32SARV:
26168 /* TODO: Implement emulation of D32SARV instruction. */
26169 MIPS_INVAL("OPC_MXU_D32SARV");
26170 generate_exception_end(ctx, EXCP_RI);
26171 break;
26172 case OPC_MXU_Q16SLLV:
26173 /* TODO: Implement emulation of Q16SLLV instruction. */
26174 MIPS_INVAL("OPC_MXU_Q16SLLV");
26175 generate_exception_end(ctx, EXCP_RI);
26176 break;
26177 case OPC_MXU_Q16SLRV:
26178 /* TODO: Implement emulation of Q16SLRV instruction. */
26179 MIPS_INVAL("OPC_MXU_Q16SLRV");
26180 generate_exception_end(ctx, EXCP_RI);
26181 break;
26182 case OPC_MXU_Q16SARV:
26183 /* TODO: Implement emulation of Q16SARV instruction. */
26184 MIPS_INVAL("OPC_MXU_Q16SARV");
26185 generate_exception_end(ctx, EXCP_RI);
26186 break;
26187 default:
26188 MIPS_INVAL("decode_opc_mxu");
26189 generate_exception_end(ctx, EXCP_RI);
26190 break;
26191 }
26192}
26193
26194/*
26195 *
c233bf07 26196 * Decode MXU pool19
03f40088
AM
26197 *
26198 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26199 * +-----------+---+---+-------+-------+-------+-------+-----------+
c233bf07 26200 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
03f40088
AM
26201 * +-----------+---+---+-------+-------+-------+-------+-----------+
26202 *
26203 */
c233bf07 26204static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26205{
26206 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26207
26208 switch (opcode) {
26209 case OPC_MXU_Q8MUL:
03f40088 26210 case OPC_MXU_Q8MULSU:
a9a4181b 26211 gen_mxu_q8mul_q8mulsu(ctx);
03f40088
AM
26212 break;
26213 default:
26214 MIPS_INVAL("decode_opc_mxu");
26215 generate_exception_end(ctx, EXCP_RI);
26216 break;
26217 }
26218}
26219
26220/*
26221 *
c233bf07 26222 * Decode MXU pool20
03f40088
AM
26223 *
26224 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26225 * +-----------+---------+-----+-------+-------+-------+-----------+
c233bf07 26226 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
03f40088
AM
26227 * +-----------+---------+-----+-------+-------+-------+-----------+
26228 *
26229 */
c233bf07 26230static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26231{
26232 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26233
26234 switch (opcode) {
26235 case OPC_MXU_Q8MOVZ:
26236 /* TODO: Implement emulation of Q8MOVZ instruction. */
26237 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26238 generate_exception_end(ctx, EXCP_RI);
26239 break;
26240 case OPC_MXU_Q8MOVN:
26241 /* TODO: Implement emulation of Q8MOVN instruction. */
26242 MIPS_INVAL("OPC_MXU_Q8MOVN");
26243 generate_exception_end(ctx, EXCP_RI);
26244 break;
26245 case OPC_MXU_D16MOVZ:
26246 /* TODO: Implement emulation of D16MOVZ instruction. */
26247 MIPS_INVAL("OPC_MXU_D16MOVZ");
26248 generate_exception_end(ctx, EXCP_RI);
26249 break;
26250 case OPC_MXU_D16MOVN:
26251 /* TODO: Implement emulation of D16MOVN instruction. */
26252 MIPS_INVAL("OPC_MXU_D16MOVN");
26253 generate_exception_end(ctx, EXCP_RI);
26254 break;
26255 case OPC_MXU_S32MOVZ:
26256 /* TODO: Implement emulation of S32MOVZ instruction. */
26257 MIPS_INVAL("OPC_MXU_S32MOVZ");
26258 generate_exception_end(ctx, EXCP_RI);
26259 break;
26260 case OPC_MXU_S32MOVN:
26261 /* TODO: Implement emulation of S32MOVN instruction. */
26262 MIPS_INVAL("OPC_MXU_S32MOVN");
26263 generate_exception_end(ctx, EXCP_RI);
26264 break;
26265 default:
26266 MIPS_INVAL("decode_opc_mxu");
26267 generate_exception_end(ctx, EXCP_RI);
26268 break;
26269 }
26270}
26271
26272/*
26273 *
c233bf07 26274 * Decode MXU pool21
03f40088
AM
26275 *
26276 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26277 * +-----------+---+---+-------+-------+-------+-------+-----------+
c233bf07 26278 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
03f40088
AM
26279 * +-----------+---+---+-------+-------+-------+-------+-----------+
26280 *
26281 */
c233bf07 26282static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
03f40088
AM
26283{
26284 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26285
26286 switch (opcode) {
26287 case OPC_MXU_Q8MAC:
26288 /* TODO: Implement emulation of Q8MAC instruction. */
26289 MIPS_INVAL("OPC_MXU_Q8MAC");
26290 generate_exception_end(ctx, EXCP_RI);
26291 break;
26292 case OPC_MXU_Q8MACSU:
26293 /* TODO: Implement emulation of Q8MACSU instruction. */
26294 MIPS_INVAL("OPC_MXU_Q8MACSU");
26295 generate_exception_end(ctx, EXCP_RI);
26296 break;
26297 default:
26298 MIPS_INVAL("decode_opc_mxu");
26299 generate_exception_end(ctx, EXCP_RI);
26300 break;
26301 }
26302}
26303
26304
26305/*
26306 * Main MXU decoding function
26307 *
26308 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26309 * +-----------+---------------------------------------+-----------+
26310 * | SPECIAL2 | |x x x x x x|
26311 * +-----------+---------------------------------------+-----------+
26312 *
26313 */
0a348b9a
AM
26314static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26315{
11d56f61
CJ
26316 /*
26317 * TODO: Investigate necessity of including handling of
26318 * CLZ, CLO, SDBB in this function, as they belong to
26319 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26320 */
03f40088
AM
26321 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26322
87860df5
AM
26323 if (opcode == OPC__MXU_MUL) {
26324 uint32_t rs, rt, rd, op1;
26325
26326 rs = extract32(ctx->opcode, 21, 5);
26327 rt = extract32(ctx->opcode, 16, 5);
26328 rd = extract32(ctx->opcode, 11, 5);
26329 op1 = MASK_SPECIAL2(ctx->opcode);
26330
26331 gen_arith(ctx, op1, rd, rs, rt);
26332
26333 return;
26334 }
26335
26336 if (opcode == OPC_MXU_S32M2I) {
26337 gen_mxu_s32m2i(ctx);
26338 return;
26339 }
26340
26341 if (opcode == OPC_MXU_S32I2M) {
26342 gen_mxu_s32i2m(ctx);
26343 return;
26344 }
26345
e5bf8a08
AM
26346 {
26347 TCGv t_mxu_cr = tcg_temp_new();
26348 TCGLabel *l_exit = gen_new_label();
26349
26350 gen_load_mxu_cr(t_mxu_cr);
26351 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26352 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26353
26354 switch (opcode) {
26355 case OPC_MXU_S32MADD:
26356 /* TODO: Implement emulation of S32MADD instruction. */
26357 MIPS_INVAL("OPC_MXU_S32MADD");
26358 generate_exception_end(ctx, EXCP_RI);
26359 break;
26360 case OPC_MXU_S32MADDU:
26361 /* TODO: Implement emulation of S32MADDU instruction. */
26362 MIPS_INVAL("OPC_MXU_S32MADDU");
26363 generate_exception_end(ctx, EXCP_RI);
26364 break;
26365 case OPC_MXU__POOL00:
26366 decode_opc_mxu__pool00(env, ctx);
26367 break;
26368 case OPC_MXU_S32MSUB:
26369 /* TODO: Implement emulation of S32MSUB instruction. */
26370 MIPS_INVAL("OPC_MXU_S32MSUB");
26371 generate_exception_end(ctx, EXCP_RI);
26372 break;
26373 case OPC_MXU_S32MSUBU:
26374 /* TODO: Implement emulation of S32MSUBU instruction. */
26375 MIPS_INVAL("OPC_MXU_S32MSUBU");
26376 generate_exception_end(ctx, EXCP_RI);
26377 break;
26378 case OPC_MXU__POOL01:
26379 decode_opc_mxu__pool01(env, ctx);
26380 break;
26381 case OPC_MXU__POOL02:
26382 decode_opc_mxu__pool02(env, ctx);
26383 break;
26384 case OPC_MXU_D16MUL:
26385 gen_mxu_d16mul(ctx);
26386 break;
26387 case OPC_MXU__POOL03:
26388 decode_opc_mxu__pool03(env, ctx);
26389 break;
26390 case OPC_MXU_D16MAC:
26391 gen_mxu_d16mac(ctx);
26392 break;
26393 case OPC_MXU_D16MACF:
26394 /* TODO: Implement emulation of D16MACF instruction. */
26395 MIPS_INVAL("OPC_MXU_D16MACF");
26396 generate_exception_end(ctx, EXCP_RI);
26397 break;
26398 case OPC_MXU_D16MADL:
26399 /* TODO: Implement emulation of D16MADL instruction. */
26400 MIPS_INVAL("OPC_MXU_D16MADL");
26401 generate_exception_end(ctx, EXCP_RI);
26402 break;
26403 case OPC_MXU_S16MAD:
26404 /* TODO: Implement emulation of S16MAD instruction. */
26405 MIPS_INVAL("OPC_MXU_S16MAD");
26406 generate_exception_end(ctx, EXCP_RI);
26407 break;
26408 case OPC_MXU_Q16ADD:
26409 /* TODO: Implement emulation of Q16ADD instruction. */
26410 MIPS_INVAL("OPC_MXU_Q16ADD");
26411 generate_exception_end(ctx, EXCP_RI);
26412 break;
26413 case OPC_MXU_D16MACE:
26414 /* TODO: Implement emulation of D16MACE instruction. */
26415 MIPS_INVAL("OPC_MXU_D16MACE");
26416 generate_exception_end(ctx, EXCP_RI);
26417 break;
26418 case OPC_MXU__POOL04:
26419 decode_opc_mxu__pool04(env, ctx);
26420 break;
26421 case OPC_MXU__POOL05:
26422 decode_opc_mxu__pool05(env, ctx);
26423 break;
26424 case OPC_MXU__POOL06:
26425 decode_opc_mxu__pool06(env, ctx);
26426 break;
26427 case OPC_MXU__POOL07:
26428 decode_opc_mxu__pool07(env, ctx);
26429 break;
26430 case OPC_MXU__POOL08:
26431 decode_opc_mxu__pool08(env, ctx);
26432 break;
26433 case OPC_MXU__POOL09:
26434 decode_opc_mxu__pool09(env, ctx);
26435 break;
26436 case OPC_MXU__POOL10:
26437 decode_opc_mxu__pool10(env, ctx);
26438 break;
26439 case OPC_MXU__POOL11:
26440 decode_opc_mxu__pool11(env, ctx);
26441 break;
26442 case OPC_MXU_D32ADD:
26443 /* TODO: Implement emulation of D32ADD instruction. */
26444 MIPS_INVAL("OPC_MXU_D32ADD");
26445 generate_exception_end(ctx, EXCP_RI);
26446 break;
26447 case OPC_MXU__POOL12:
26448 decode_opc_mxu__pool12(env, ctx);
26449 break;
26450 case OPC_MXU__POOL13:
26451 decode_opc_mxu__pool13(env, ctx);
26452 break;
26453 case OPC_MXU__POOL14:
26454 decode_opc_mxu__pool14(env, ctx);
26455 break;
26456 case OPC_MXU_Q8ACCE:
26457 /* TODO: Implement emulation of Q8ACCE instruction. */
26458 MIPS_INVAL("OPC_MXU_Q8ACCE");
26459 generate_exception_end(ctx, EXCP_RI);
26460 break;
26461 case OPC_MXU_S8LDD:
26462 gen_mxu_s8ldd(ctx);
26463 break;
26464 case OPC_MXU_S8STD:
26465 /* TODO: Implement emulation of S8STD instruction. */
26466 MIPS_INVAL("OPC_MXU_S8STD");
26467 generate_exception_end(ctx, EXCP_RI);
26468 break;
26469 case OPC_MXU_S8LDI:
26470 /* TODO: Implement emulation of S8LDI instruction. */
26471 MIPS_INVAL("OPC_MXU_S8LDI");
26472 generate_exception_end(ctx, EXCP_RI);
26473 break;
26474 case OPC_MXU_S8SDI:
26475 /* TODO: Implement emulation of S8SDI instruction. */
26476 MIPS_INVAL("OPC_MXU_S8SDI");
26477 generate_exception_end(ctx, EXCP_RI);
26478 break;
26479 case OPC_MXU__POOL15:
26480 decode_opc_mxu__pool15(env, ctx);
26481 break;
26482 case OPC_MXU__POOL16:
26483 decode_opc_mxu__pool16(env, ctx);
26484 break;
c233bf07
AM
26485 case OPC_MXU__POOL17:
26486 decode_opc_mxu__pool17(env, ctx);
e5bf8a08
AM
26487 break;
26488 case OPC_MXU_S16LDD:
26489 /* TODO: Implement emulation of S16LDD instruction. */
26490 MIPS_INVAL("OPC_MXU_S16LDD");
26491 generate_exception_end(ctx, EXCP_RI);
26492 break;
26493 case OPC_MXU_S16STD:
26494 /* TODO: Implement emulation of S16STD instruction. */
26495 MIPS_INVAL("OPC_MXU_S16STD");
26496 generate_exception_end(ctx, EXCP_RI);
26497 break;
26498 case OPC_MXU_S16LDI:
26499 /* TODO: Implement emulation of S16LDI instruction. */
26500 MIPS_INVAL("OPC_MXU_S16LDI");
26501 generate_exception_end(ctx, EXCP_RI);
26502 break;
26503 case OPC_MXU_S16SDI:
26504 /* TODO: Implement emulation of S16SDI instruction. */
26505 MIPS_INVAL("OPC_MXU_S16SDI");
26506 generate_exception_end(ctx, EXCP_RI);
26507 break;
26508 case OPC_MXU_D32SLL:
26509 /* TODO: Implement emulation of D32SLL instruction. */
26510 MIPS_INVAL("OPC_MXU_D32SLL");
26511 generate_exception_end(ctx, EXCP_RI);
26512 break;
26513 case OPC_MXU_D32SLR:
26514 /* TODO: Implement emulation of D32SLR instruction. */
26515 MIPS_INVAL("OPC_MXU_D32SLR");
26516 generate_exception_end(ctx, EXCP_RI);
26517 break;
26518 case OPC_MXU_D32SARL:
26519 /* TODO: Implement emulation of D32SARL instruction. */
26520 MIPS_INVAL("OPC_MXU_D32SARL");
26521 generate_exception_end(ctx, EXCP_RI);
26522 break;
26523 case OPC_MXU_D32SAR:
26524 /* TODO: Implement emulation of D32SAR instruction. */
26525 MIPS_INVAL("OPC_MXU_D32SAR");
26526 generate_exception_end(ctx, EXCP_RI);
26527 break;
26528 case OPC_MXU_Q16SLL:
26529 /* TODO: Implement emulation of Q16SLL instruction. */
26530 MIPS_INVAL("OPC_MXU_Q16SLL");
26531 generate_exception_end(ctx, EXCP_RI);
26532 break;
26533 case OPC_MXU_Q16SLR:
26534 /* TODO: Implement emulation of Q16SLR instruction. */
26535 MIPS_INVAL("OPC_MXU_Q16SLR");
26536 generate_exception_end(ctx, EXCP_RI);
26537 break;
c233bf07
AM
26538 case OPC_MXU__POOL18:
26539 decode_opc_mxu__pool18(env, ctx);
e5bf8a08
AM
26540 break;
26541 case OPC_MXU_Q16SAR:
26542 /* TODO: Implement emulation of Q16SAR instruction. */
26543 MIPS_INVAL("OPC_MXU_Q16SAR");
26544 generate_exception_end(ctx, EXCP_RI);
26545 break;
e5bf8a08
AM
26546 case OPC_MXU__POOL19:
26547 decode_opc_mxu__pool19(env, ctx);
26548 break;
26549 case OPC_MXU__POOL20:
26550 decode_opc_mxu__pool20(env, ctx);
26551 break;
c233bf07
AM
26552 case OPC_MXU__POOL21:
26553 decode_opc_mxu__pool21(env, ctx);
26554 break;
e5bf8a08
AM
26555 case OPC_MXU_Q16SCOP:
26556 /* TODO: Implement emulation of Q16SCOP instruction. */
26557 MIPS_INVAL("OPC_MXU_Q16SCOP");
26558 generate_exception_end(ctx, EXCP_RI);
26559 break;
26560 case OPC_MXU_Q8MADL:
26561 /* TODO: Implement emulation of Q8MADL instruction. */
26562 MIPS_INVAL("OPC_MXU_Q8MADL");
26563 generate_exception_end(ctx, EXCP_RI);
26564 break;
26565 case OPC_MXU_S32SFL:
26566 /* TODO: Implement emulation of S32SFL instruction. */
26567 MIPS_INVAL("OPC_MXU_S32SFL");
26568 generate_exception_end(ctx, EXCP_RI);
26569 break;
26570 case OPC_MXU_Q8SAD:
26571 /* TODO: Implement emulation of Q8SAD instruction. */
26572 MIPS_INVAL("OPC_MXU_Q8SAD");
26573 generate_exception_end(ctx, EXCP_RI);
26574 break;
26575 default:
26576 MIPS_INVAL("decode_opc_mxu");
26577 generate_exception_end(ctx, EXCP_RI);
26578 }
26579
26580 gen_set_label(l_exit);
26581 tcg_temp_free(t_mxu_cr);
03f40088 26582 }
0a348b9a
AM
26583}
26584
b621f018
AM
26585#endif /* !defined(TARGET_MIPS64) */
26586
03f40088 26587
10dc65db 26588static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
26589{
26590 int rs, rt, rd;
26591 uint32_t op1;
6c5c1e20 26592
4267d3e6
LA
26593 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26594
099e5b4d
LA
26595 rs = (ctx->opcode >> 21) & 0x1f;
26596 rt = (ctx->opcode >> 16) & 0x1f;
26597 rd = (ctx->opcode >> 11) & 0x1f;
26598
26599 op1 = MASK_SPECIAL2(ctx->opcode);
26600 switch (op1) {
c2e19f3c
AM
26601 case OPC_MADD: /* Multiply and add/sub */
26602 case OPC_MADDU:
26603 case OPC_MSUB:
26604 case OPC_MSUBU:
099e5b4d
LA
26605 check_insn(ctx, ISA_MIPS32);
26606 gen_muldiv(ctx, op1, rd & 3, rs, rt);
26607 break;
26608 case OPC_MUL:
099e5b4d
LA
26609 gen_arith(ctx, op1, rd, rs, rt);
26610 break;
fac5a073
LA
26611 case OPC_DIV_G_2F:
26612 case OPC_DIVU_G_2F:
26613 case OPC_MULT_G_2F:
26614 case OPC_MULTU_G_2F:
26615 case OPC_MOD_G_2F:
26616 case OPC_MODU_G_2F:
26617 check_insn(ctx, INSN_LOONGSON2F);
26618 gen_loongson_integer(ctx, op1, rd, rs, rt);
26619 break;
099e5b4d
LA
26620 case OPC_CLO:
26621 case OPC_CLZ:
26622 check_insn(ctx, ISA_MIPS32);
26623 gen_cl(ctx, op1, rd, rs);
26624 break;
26625 case OPC_SDBBP:
3b3c1694
LA
26626 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
26627 gen_helper_do_semihosting(cpu_env);
26628 } else {
26629 /* XXX: not clear which exception should be raised
26630 * when in debug mode...
26631 */
26632 check_insn(ctx, ISA_MIPS32);
9c708c7f 26633 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 26634 }
099e5b4d 26635 break;
9b1a1d68 26636#if defined(TARGET_MIPS64)
099e5b4d
LA
26637 case OPC_DCLO:
26638 case OPC_DCLZ:
26639 check_insn(ctx, ISA_MIPS64);
26640 check_mips_64(ctx);
26641 gen_cl(ctx, op1, rd, rs);
26642 break;
4267d3e6
LA
26643 case OPC_DMULT_G_2F:
26644 case OPC_DMULTU_G_2F:
26645 case OPC_DDIV_G_2F:
26646 case OPC_DDIVU_G_2F:
26647 case OPC_DMOD_G_2F:
26648 case OPC_DMODU_G_2F:
26649 check_insn(ctx, INSN_LOONGSON2F);
26650 gen_loongson_integer(ctx, op1, rd, rs, rt);
26651 break;
10dc65db 26652#endif
4267d3e6
LA
26653 default: /* Invalid */
26654 MIPS_INVAL("special2_legacy");
9c708c7f 26655 generate_exception_end(ctx, EXCP_RI);
4267d3e6 26656 break;
10dc65db
LA
26657 }
26658}
26659
26660static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
26661{
15eacb9b
YK
26662 int rs, rt, rd, sa;
26663 uint32_t op1, op2;
10dc65db
LA
26664 int16_t imm;
26665
26666 rs = (ctx->opcode >> 21) & 0x1f;
26667 rt = (ctx->opcode >> 16) & 0x1f;
15eacb9b
YK
26668 rd = (ctx->opcode >> 11) & 0x1f;
26669 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
26670 imm = (int16_t)ctx->opcode >> 7;
26671
26672 op1 = MASK_SPECIAL3(ctx->opcode);
26673 switch (op1) {
bf7910c6
LA
26674 case R6_OPC_PREF:
26675 if (rt >= 24) {
26676 /* hint codes 24-31 are reserved and signal RI */
9c708c7f 26677 generate_exception_end(ctx, EXCP_RI);
bf7910c6
LA
26678 }
26679 /* Treat as NOP. */
26680 break;
26681 case R6_OPC_CACHE:
40d48212 26682 check_cp0_enabled(ctx);
0d74a222
LA
26683 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26684 gen_cache_operation(ctx, rt, rs, imm);
26685 }
bf7910c6 26686 break;
10dc65db
LA
26687 case R6_OPC_SC:
26688 gen_st_cond(ctx, op1, rt, rs, imm);
26689 break;
26690 case R6_OPC_LL:
26691 gen_ld(ctx, op1, rt, rs, imm);
26692 break;
15eacb9b
YK
26693 case OPC_BSHFL:
26694 {
26695 if (rd == 0) {
26696 /* Treat as NOP. */
26697 break;
26698 }
15eacb9b
YK
26699 op2 = MASK_BSHFL(ctx->opcode);
26700 switch (op2) {
c2e19f3c 26701 case OPC_ALIGN:
373ecd38
AM
26702 case OPC_ALIGN_1:
26703 case OPC_ALIGN_2:
26704 case OPC_ALIGN_3:
821f2008 26705 gen_align(ctx, 32, rd, rs, rt, sa & 3);
15eacb9b
YK
26706 break;
26707 case OPC_BITSWAP:
1f1b4c00 26708 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
26709 break;
26710 }
15eacb9b
YK
26711 }
26712 break;
bf7910c6
LA
26713#if defined(TARGET_MIPS64)
26714 case R6_OPC_SCD:
26715 gen_st_cond(ctx, op1, rt, rs, imm);
26716 break;
26717 case R6_OPC_LLD:
26718 gen_ld(ctx, op1, rt, rs, imm);
26719 break;
15eacb9b
YK
26720 case OPC_DBSHFL:
26721 check_mips_64(ctx);
26722 {
26723 if (rd == 0) {
26724 /* Treat as NOP. */
26725 break;
26726 }
15eacb9b
YK
26727 op2 = MASK_DBSHFL(ctx->opcode);
26728 switch (op2) {
c2e19f3c 26729 case OPC_DALIGN:
373ecd38
AM
26730 case OPC_DALIGN_1:
26731 case OPC_DALIGN_2:
26732 case OPC_DALIGN_3:
26733 case OPC_DALIGN_4:
26734 case OPC_DALIGN_5:
26735 case OPC_DALIGN_6:
26736 case OPC_DALIGN_7:
821f2008 26737 gen_align(ctx, 64, rd, rs, rt, sa & 7);
15eacb9b
YK
26738 break;
26739 case OPC_DBITSWAP:
1f1b4c00 26740 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
26741 break;
26742 }
1f1b4c00 26743
15eacb9b
YK
26744 }
26745 break;
bf7910c6 26746#endif
10dc65db
LA
26747 default: /* Invalid */
26748 MIPS_INVAL("special3_r6");
9c708c7f 26749 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
26750 break;
26751 }
26752}
26753
26754static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
26755{
fac5a073 26756 int rs, rt, rd;
099e5b4d 26757 uint32_t op1, op2;
099e5b4d
LA
26758
26759 rs = (ctx->opcode >> 21) & 0x1f;
26760 rt = (ctx->opcode >> 16) & 0x1f;
26761 rd = (ctx->opcode >> 11) & 0x1f;
099e5b4d
LA
26762
26763 op1 = MASK_SPECIAL3(ctx->opcode);
26764 switch (op1) {
c2e19f3c
AM
26765 case OPC_DIV_G_2E:
26766 case OPC_DIVU_G_2E:
26767 case OPC_MOD_G_2E:
26768 case OPC_MODU_G_2E:
26769 case OPC_MULT_G_2E:
26770 case OPC_MULTU_G_2E:
099e5b4d
LA
26771 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
26772 * the same mask and op1. */
908f6be1 26773 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
099e5b4d 26774 op2 = MASK_ADDUH_QB(ctx->opcode);
461c08df 26775 switch (op2) {
099e5b4d
LA
26776 case OPC_ADDUH_QB:
26777 case OPC_ADDUH_R_QB:
26778 case OPC_ADDQH_PH:
26779 case OPC_ADDQH_R_PH:
26780 case OPC_ADDQH_W:
26781 case OPC_ADDQH_R_W:
26782 case OPC_SUBUH_QB:
26783 case OPC_SUBUH_R_QB:
26784 case OPC_SUBQH_PH:
26785 case OPC_SUBQH_R_PH:
26786 case OPC_SUBQH_W:
26787 case OPC_SUBQH_R_W:
461c08df
JL
26788 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26789 break;
099e5b4d
LA
26790 case OPC_MUL_PH:
26791 case OPC_MUL_S_PH:
26792 case OPC_MULQ_S_W:
26793 case OPC_MULQ_RS_W:
26794 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 26795 break;
461c08df 26796 default:
099e5b4d 26797 MIPS_INVAL("MASK ADDUH.QB");
9c708c7f 26798 generate_exception_end(ctx, EXCP_RI);
461c08df
JL
26799 break;
26800 }
099e5b4d
LA
26801 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
26802 gen_loongson_integer(ctx, op1, rd, rs, rt);
26803 } else {
9c708c7f 26804 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
26805 }
26806 break;
26807 case OPC_LX_DSP:
26808 op2 = MASK_LX(ctx->opcode);
26809 switch (op2) {
26810#if defined(TARGET_MIPS64)
26811 case OPC_LDX:
26812#endif
26813 case OPC_LBUX:
26814 case OPC_LHX:
26815 case OPC_LWX:
26816 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
26817 break;
26818 default: /* Invalid */
26819 MIPS_INVAL("MASK LX");
9c708c7f 26820 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
26821 break;
26822 }
26823 break;
26824 case OPC_ABSQ_S_PH_DSP:
26825 op2 = MASK_ABSQ_S_PH(ctx->opcode);
26826 switch (op2) {
26827 case OPC_ABSQ_S_QB:
26828 case OPC_ABSQ_S_PH:
26829 case OPC_ABSQ_S_W:
26830 case OPC_PRECEQ_W_PHL:
26831 case OPC_PRECEQ_W_PHR:
26832 case OPC_PRECEQU_PH_QBL:
26833 case OPC_PRECEQU_PH_QBR:
26834 case OPC_PRECEQU_PH_QBLA:
26835 case OPC_PRECEQU_PH_QBRA:
26836 case OPC_PRECEU_PH_QBL:
26837 case OPC_PRECEU_PH_QBR:
26838 case OPC_PRECEU_PH_QBLA:
26839 case OPC_PRECEU_PH_QBRA:
26840 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26841 break;
26842 case OPC_BITREV:
26843 case OPC_REPL_QB:
26844 case OPC_REPLV_QB:
26845 case OPC_REPL_PH:
26846 case OPC_REPLV_PH:
26847 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
26848 break;
26849 default:
26850 MIPS_INVAL("MASK ABSQ_S.PH");
9c708c7f 26851 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
26852 break;
26853 }
26854 break;
26855 case OPC_ADDU_QB_DSP:
26856 op2 = MASK_ADDU_QB(ctx->opcode);
26857 switch (op2) {
26858 case OPC_ADDQ_PH:
26859 case OPC_ADDQ_S_PH:
26860 case OPC_ADDQ_S_W:
26861 case OPC_ADDU_QB:
26862 case OPC_ADDU_S_QB:
26863 case OPC_ADDU_PH:
26864 case OPC_ADDU_S_PH:
26865 case OPC_SUBQ_PH:
26866 case OPC_SUBQ_S_PH:
26867 case OPC_SUBQ_S_W:
26868 case OPC_SUBU_QB:
26869 case OPC_SUBU_S_QB:
26870 case OPC_SUBU_PH:
26871 case OPC_SUBU_S_PH:
26872 case OPC_ADDSC:
26873 case OPC_ADDWC:
26874 case OPC_MODSUB:
26875 case OPC_RADDU_W_QB:
26876 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26877 break;
26878 case OPC_MULEU_S_PH_QBL:
26879 case OPC_MULEU_S_PH_QBR:
26880 case OPC_MULQ_RS_PH:
26881 case OPC_MULEQ_S_W_PHL:
26882 case OPC_MULEQ_S_W_PHR:
26883 case OPC_MULQ_S_PH:
26884 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26885 break;
26886 default: /* Invalid */
26887 MIPS_INVAL("MASK ADDU.QB");
9c708c7f 26888 generate_exception_end(ctx, EXCP_RI);
461c08df 26889 break;
461c08df 26890
099e5b4d
LA
26891 }
26892 break;
26893 case OPC_CMPU_EQ_QB_DSP:
26894 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
26895 switch (op2) {
26896 case OPC_PRECR_SRA_PH_W:
26897 case OPC_PRECR_SRA_R_PH_W:
26898 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
461c08df 26899 break;
099e5b4d
LA
26900 case OPC_PRECR_QB_PH:
26901 case OPC_PRECRQ_QB_PH:
26902 case OPC_PRECRQ_PH_W:
26903 case OPC_PRECRQ_RS_PH_W:
26904 case OPC_PRECRQU_S_QB_PH:
26905 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
461c08df 26906 break;
099e5b4d
LA
26907 case OPC_CMPU_EQ_QB:
26908 case OPC_CMPU_LT_QB:
26909 case OPC_CMPU_LE_QB:
26910 case OPC_CMP_EQ_PH:
26911 case OPC_CMP_LT_PH:
26912 case OPC_CMP_LE_PH:
26913 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
77c5fa8b 26914 break;
099e5b4d
LA
26915 case OPC_CMPGU_EQ_QB:
26916 case OPC_CMPGU_LT_QB:
26917 case OPC_CMPGU_LE_QB:
26918 case OPC_CMPGDU_EQ_QB:
26919 case OPC_CMPGDU_LT_QB:
26920 case OPC_CMPGDU_LE_QB:
26921 case OPC_PICK_QB:
26922 case OPC_PICK_PH:
26923 case OPC_PACKRL_PH:
26924 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
26925 break;
26926 default: /* Invalid */
26927 MIPS_INVAL("MASK CMPU.EQ.QB");
9c708c7f 26928 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
26929 break;
26930 }
26931 break;
26932 case OPC_SHLL_QB_DSP:
26933 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
26934 break;
26935 case OPC_DPA_W_PH_DSP:
26936 op2 = MASK_DPA_W_PH(ctx->opcode);
26937 switch (op2) {
26938 case OPC_DPAU_H_QBL:
26939 case OPC_DPAU_H_QBR:
26940 case OPC_DPSU_H_QBL:
26941 case OPC_DPSU_H_QBR:
26942 case OPC_DPA_W_PH:
26943 case OPC_DPAX_W_PH:
26944 case OPC_DPAQ_S_W_PH:
26945 case OPC_DPAQX_S_W_PH:
26946 case OPC_DPAQX_SA_W_PH:
26947 case OPC_DPS_W_PH:
26948 case OPC_DPSX_W_PH:
26949 case OPC_DPSQ_S_W_PH:
26950 case OPC_DPSQX_S_W_PH:
26951 case OPC_DPSQX_SA_W_PH:
26952 case OPC_MULSAQ_S_W_PH:
26953 case OPC_DPAQ_SA_L_W:
26954 case OPC_DPSQ_SA_L_W:
26955 case OPC_MAQ_S_W_PHL:
26956 case OPC_MAQ_S_W_PHR:
26957 case OPC_MAQ_SA_W_PHL:
26958 case OPC_MAQ_SA_W_PHR:
26959 case OPC_MULSA_W_PH:
26960 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26961 break;
26962 default: /* Invalid */
26963 MIPS_INVAL("MASK DPAW.PH");
9c708c7f 26964 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
26965 break;
26966 }
26967 break;
26968 case OPC_INSV_DSP:
26969 op2 = MASK_INSV(ctx->opcode);
26970 switch (op2) {
26971 case OPC_INSV:
26972 check_dsp(ctx);
26973 {
26974 TCGv t0, t1;
26975
26976 if (rt == 0) {
099e5b4d
LA
26977 break;
26978 }
26979
26980 t0 = tcg_temp_new();
26981 t1 = tcg_temp_new();
26982
26983 gen_load_gpr(t0, rt);
26984 gen_load_gpr(t1, rs);
26985
26986 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
26987
26988 tcg_temp_free(t0);
26989 tcg_temp_free(t1);
a22260ae
JL
26990 break;
26991 }
099e5b4d
LA
26992 default: /* Invalid */
26993 MIPS_INVAL("MASK INSV");
9c708c7f 26994 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
26995 break;
26996 }
26997 break;
26998 case OPC_APPEND_DSP:
26999 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27000 break;
27001 case OPC_EXTR_W_DSP:
27002 op2 = MASK_EXTR_W(ctx->opcode);
27003 switch (op2) {
27004 case OPC_EXTR_W:
27005 case OPC_EXTR_R_W:
27006 case OPC_EXTR_RS_W:
27007 case OPC_EXTR_S_H:
27008 case OPC_EXTRV_S_H:
27009 case OPC_EXTRV_W:
27010 case OPC_EXTRV_R_W:
27011 case OPC_EXTRV_RS_W:
27012 case OPC_EXTP:
27013 case OPC_EXTPV:
27014 case OPC_EXTPDP:
27015 case OPC_EXTPDPV:
27016 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27017 break;
27018 case OPC_RDDSP:
27019 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27020 break;
27021 case OPC_SHILO:
27022 case OPC_SHILOV:
27023 case OPC_MTHLIP:
27024 case OPC_WRDSP:
27025 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27026 break;
27027 default: /* Invalid */
27028 MIPS_INVAL("MASK EXTR.W");
9c708c7f 27029 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27030 break;
27031 }
27032 break;
099e5b4d 27033#if defined(TARGET_MIPS64)
c2e19f3c
AM
27034 case OPC_DDIV_G_2E:
27035 case OPC_DDIVU_G_2E:
27036 case OPC_DMULT_G_2E:
27037 case OPC_DMULTU_G_2E:
27038 case OPC_DMOD_G_2E:
27039 case OPC_DMODU_G_2E:
fac5a073
LA
27040 check_insn(ctx, INSN_LOONGSON2E);
27041 gen_loongson_integer(ctx, op1, rd, rs, rt);
099e5b4d 27042 break;
099e5b4d
LA
27043 case OPC_ABSQ_S_QH_DSP:
27044 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27045 switch (op2) {
27046 case OPC_PRECEQ_L_PWL:
27047 case OPC_PRECEQ_L_PWR:
27048 case OPC_PRECEQ_PW_QHL:
27049 case OPC_PRECEQ_PW_QHR:
27050 case OPC_PRECEQ_PW_QHLA:
27051 case OPC_PRECEQ_PW_QHRA:
27052 case OPC_PRECEQU_QH_OBL:
27053 case OPC_PRECEQU_QH_OBR:
27054 case OPC_PRECEQU_QH_OBLA:
27055 case OPC_PRECEQU_QH_OBRA:
27056 case OPC_PRECEU_QH_OBL:
27057 case OPC_PRECEU_QH_OBR:
27058 case OPC_PRECEU_QH_OBLA:
27059 case OPC_PRECEU_QH_OBRA:
27060 case OPC_ABSQ_S_OB:
27061 case OPC_ABSQ_S_PW:
27062 case OPC_ABSQ_S_QH:
27063 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27064 break;
27065 case OPC_REPL_OB:
27066 case OPC_REPL_PW:
27067 case OPC_REPL_QH:
27068 case OPC_REPLV_OB:
27069 case OPC_REPLV_PW:
27070 case OPC_REPLV_QH:
27071 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27072 break;
27073 default: /* Invalid */
27074 MIPS_INVAL("MASK ABSQ_S.QH");
9c708c7f 27075 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
27076 break;
27077 }
27078 break;
27079 case OPC_ADDU_OB_DSP:
27080 op2 = MASK_ADDU_OB(ctx->opcode);
27081 switch (op2) {
27082 case OPC_RADDU_L_OB:
27083 case OPC_SUBQ_PW:
27084 case OPC_SUBQ_S_PW:
27085 case OPC_SUBQ_QH:
27086 case OPC_SUBQ_S_QH:
27087 case OPC_SUBU_OB:
27088 case OPC_SUBU_S_OB:
27089 case OPC_SUBU_QH:
27090 case OPC_SUBU_S_QH:
27091 case OPC_SUBUH_OB:
27092 case OPC_SUBUH_R_OB:
27093 case OPC_ADDQ_PW:
27094 case OPC_ADDQ_S_PW:
27095 case OPC_ADDQ_QH:
27096 case OPC_ADDQ_S_QH:
27097 case OPC_ADDU_OB:
27098 case OPC_ADDU_S_OB:
27099 case OPC_ADDU_QH:
27100 case OPC_ADDU_S_QH:
27101 case OPC_ADDUH_OB:
27102 case OPC_ADDUH_R_OB:
27103 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
a22260ae 27104 break;
099e5b4d
LA
27105 case OPC_MULEQ_S_PW_QHL:
27106 case OPC_MULEQ_S_PW_QHR:
27107 case OPC_MULEU_S_QH_OBL:
27108 case OPC_MULEU_S_QH_OBR:
27109 case OPC_MULQ_RS_QH:
27110 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 27111 break;
099e5b4d
LA
27112 default: /* Invalid */
27113 MIPS_INVAL("MASK ADDU.OB");
9c708c7f 27114 generate_exception_end(ctx, EXCP_RI);
26690560 27115 break;
099e5b4d
LA
27116 }
27117 break;
27118 case OPC_CMPU_EQ_OB_DSP:
27119 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27120 switch (op2) {
27121 case OPC_PRECR_SRA_QH_PW:
27122 case OPC_PRECR_SRA_R_QH_PW:
27123 /* Return value is rt. */
27124 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
b53371ed 27125 break;
099e5b4d
LA
27126 case OPC_PRECR_OB_QH:
27127 case OPC_PRECRQ_OB_QH:
27128 case OPC_PRECRQ_PW_L:
27129 case OPC_PRECRQ_QH_PW:
27130 case OPC_PRECRQ_RS_QH_PW:
27131 case OPC_PRECRQU_S_OB_QH:
27132 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
4368b29a 27133 break;
099e5b4d
LA
27134 case OPC_CMPU_EQ_OB:
27135 case OPC_CMPU_LT_OB:
27136 case OPC_CMPU_LE_OB:
27137 case OPC_CMP_EQ_QH:
27138 case OPC_CMP_LT_QH:
27139 case OPC_CMP_LE_QH:
27140 case OPC_CMP_EQ_PW:
27141 case OPC_CMP_LT_PW:
27142 case OPC_CMP_LE_PW:
27143 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
7a387fff 27144 break;
099e5b4d
LA
27145 case OPC_CMPGDU_EQ_OB:
27146 case OPC_CMPGDU_LT_OB:
27147 case OPC_CMPGDU_LE_OB:
27148 case OPC_CMPGU_EQ_OB:
27149 case OPC_CMPGU_LT_OB:
27150 case OPC_CMPGU_LE_OB:
27151 case OPC_PACKRL_PW:
27152 case OPC_PICK_OB:
27153 case OPC_PICK_PW:
27154 case OPC_PICK_QH:
27155 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
c6d6dd7c 27156 break;
099e5b4d
LA
27157 default: /* Invalid */
27158 MIPS_INVAL("MASK CMPU_EQ.OB");
9c708c7f 27159 generate_exception_end(ctx, EXCP_RI);
161f85e6 27160 break;
099e5b4d
LA
27161 }
27162 break;
27163 case OPC_DAPPEND_DSP:
27164 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27165 break;
27166 case OPC_DEXTR_W_DSP:
27167 op2 = MASK_DEXTR_W(ctx->opcode);
27168 switch (op2) {
27169 case OPC_DEXTP:
27170 case OPC_DEXTPDP:
27171 case OPC_DEXTPDPV:
27172 case OPC_DEXTPV:
27173 case OPC_DEXTR_L:
27174 case OPC_DEXTR_R_L:
27175 case OPC_DEXTR_RS_L:
27176 case OPC_DEXTR_W:
27177 case OPC_DEXTR_R_W:
27178 case OPC_DEXTR_RS_W:
27179 case OPC_DEXTR_S_H:
27180 case OPC_DEXTRV_L:
27181 case OPC_DEXTRV_R_L:
27182 case OPC_DEXTRV_RS_L:
27183 case OPC_DEXTRV_S_H:
27184 case OPC_DEXTRV_W:
27185 case OPC_DEXTRV_R_W:
27186 case OPC_DEXTRV_RS_W:
27187 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
461c08df 27188 break;
099e5b4d
LA
27189 case OPC_DMTHLIP:
27190 case OPC_DSHILO:
27191 case OPC_DSHILOV:
27192 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
461c08df 27193 break;
099e5b4d
LA
27194 default: /* Invalid */
27195 MIPS_INVAL("MASK EXTR.W");
9c708c7f 27196 generate_exception_end(ctx, EXCP_RI);
461c08df 27197 break;
099e5b4d
LA
27198 }
27199 break;
27200 case OPC_DPAQ_W_QH_DSP:
27201 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27202 switch (op2) {
27203 case OPC_DPAU_H_OBL:
27204 case OPC_DPAU_H_OBR:
27205 case OPC_DPSU_H_OBL:
27206 case OPC_DPSU_H_OBR:
27207 case OPC_DPA_W_QH:
27208 case OPC_DPAQ_S_W_QH:
27209 case OPC_DPS_W_QH:
27210 case OPC_DPSQ_S_W_QH:
27211 case OPC_MULSAQ_S_W_QH:
27212 case OPC_DPAQ_SA_L_PW:
27213 case OPC_DPSQ_SA_L_PW:
27214 case OPC_MULSAQ_S_L_PW:
27215 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27216 break;
27217 case OPC_MAQ_S_W_QHLL:
27218 case OPC_MAQ_S_W_QHLR:
27219 case OPC_MAQ_S_W_QHRL:
27220 case OPC_MAQ_S_W_QHRR:
27221 case OPC_MAQ_SA_W_QHLL:
27222 case OPC_MAQ_SA_W_QHLR:
27223 case OPC_MAQ_SA_W_QHRL:
27224 case OPC_MAQ_SA_W_QHRR:
27225 case OPC_MAQ_S_L_PWL:
27226 case OPC_MAQ_S_L_PWR:
27227 case OPC_DMADD:
27228 case OPC_DMADDU:
27229 case OPC_DMSUB:
27230 case OPC_DMSUBU:
27231 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26690560 27232 break;
099e5b4d
LA
27233 default: /* Invalid */
27234 MIPS_INVAL("MASK DPAQ.W.QH");
9c708c7f 27235 generate_exception_end(ctx, EXCP_RI);
b53371ed 27236 break;
099e5b4d
LA
27237 }
27238 break;
27239 case OPC_DINSV_DSP:
27240 op2 = MASK_INSV(ctx->opcode);
27241 switch (op2) {
27242 case OPC_DINSV:
27243 {
27244 TCGv t0, t1;
27245
27246 if (rt == 0) {
a22260ae
JL
27247 break;
27248 }
099e5b4d 27249 check_dsp(ctx);
1cb6686c 27250
099e5b4d
LA
27251 t0 = tcg_temp_new();
27252 t1 = tcg_temp_new();
1cb6686c 27253
099e5b4d
LA
27254 gen_load_gpr(t0, rt);
27255 gen_load_gpr(t1, rs);
1cb6686c 27256
099e5b4d 27257 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
62eb3b9a 27258
099e5b4d
LA
27259 tcg_temp_free(t0);
27260 tcg_temp_free(t1);
77c5fa8b 27261 break;
099e5b4d 27262 }
7a387fff 27263 default: /* Invalid */
099e5b4d 27264 MIPS_INVAL("MASK DINSV");
9c708c7f 27265 generate_exception_end(ctx, EXCP_RI);
7a387fff
TS
27266 break;
27267 }
27268 break;
099e5b4d
LA
27269 case OPC_SHLL_OB_DSP:
27270 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27271 break;
27272#endif
fac5a073
LA
27273 default: /* Invalid */
27274 MIPS_INVAL("special3_legacy");
9c708c7f 27275 generate_exception_end(ctx, EXCP_RI);
fac5a073
LA
27276 break;
27277 }
27278}
27279
874b2879 27280static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
88eafe0b 27281{
c8341e00 27282 uint32_t opc = MASK_MMI0(ctx->opcode);
88eafe0b
FN
27283
27284 switch (opc) {
baa609db
AM
27285 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27286 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27287 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27288 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27289 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27290 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27291 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27292 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27293 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27294 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27295 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27296 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27297 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27298 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27299 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27300 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27301 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27302 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27303 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27304 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27305 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27306 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27307 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27308 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27309 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27310 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
88eafe0b
FN
27311 break;
27312 default:
27313 MIPS_INVAL("TX79 MMI class MMI0");
27314 generate_exception_end(ctx, EXCP_RI);
27315 break;
27316 }
27317}
27318
874b2879 27319static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
7a803ca2 27320{
c8341e00 27321 uint32_t opc = MASK_MMI1(ctx->opcode);
7a803ca2
FN
27322
27323 switch (opc) {
baa609db
AM
27324 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27325 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27326 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27327 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27328 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27329 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27330 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27331 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27332 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27333 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27334 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27335 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27336 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27337 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27338 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27339 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27340 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27341 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27342 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
7a803ca2
FN
27343 break;
27344 default:
27345 MIPS_INVAL("TX79 MMI class MMI1");
27346 generate_exception_end(ctx, EXCP_RI);
27347 break;
27348 }
27349}
27350
874b2879 27351static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
6c1e48d3 27352{
c8341e00 27353 uint32_t opc = MASK_MMI2(ctx->opcode);
6c1e48d3
FN
27354
27355 switch (opc) {
baa609db
AM
27356 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27357 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27358 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27359 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27360 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27361 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27362 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27363 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27364 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
27365 case MMI_OPC_2_PCPYLD: /* TODO: MMI_OPC_2_PCPYLD */
27366 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27367 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27368 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27369 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27370 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27371 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27372 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27373 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27374 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27375 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27376 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27377 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27378 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
6c1e48d3
FN
27379 break;
27380 default:
27381 MIPS_INVAL("TX79 MMI class MMI2");
27382 generate_exception_end(ctx, EXCP_RI);
27383 break;
27384 }
27385}
27386
874b2879 27387static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
ec1944fc 27388{
c8341e00 27389 uint32_t opc = MASK_MMI3(ctx->opcode);
ec1944fc
FN
27390
27391 switch (opc) {
baa609db
AM
27392 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27393 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27394 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27395 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27396 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27397 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27398 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
27399 case MMI_OPC_3_PCPYUD: /* TODO: MMI_OPC_3_PCPYUD */
27400 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27401 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27402 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
27403 case MMI_OPC_3_PCPYH: /* TODO: MMI_OPC_3_PCPYH */
27404 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27405 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
ec1944fc
FN
27406 break;
27407 default:
27408 MIPS_INVAL("TX79 MMI class MMI3");
27409 generate_exception_end(ctx, EXCP_RI);
27410 break;
27411 }
27412}
27413
874b2879 27414static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
71b8a6b3 27415{
c8341e00 27416 uint32_t opc = MASK_MMI(ctx->opcode);
06de726b
FN
27417 int rs = extract32(ctx->opcode, 21, 5);
27418 int rt = extract32(ctx->opcode, 16, 5);
27419 int rd = extract32(ctx->opcode, 11, 5);
71b8a6b3
FN
27420
27421 switch (opc) {
baa609db 27422 case MMI_OPC_CLASS_MMI0:
874b2879 27423 decode_mmi0(env, ctx);
88eafe0b 27424 break;
baa609db 27425 case MMI_OPC_CLASS_MMI1:
874b2879 27426 decode_mmi1(env, ctx);
7a803ca2 27427 break;
baa609db 27428 case MMI_OPC_CLASS_MMI2:
874b2879 27429 decode_mmi2(env, ctx);
6c1e48d3 27430 break;
baa609db 27431 case MMI_OPC_CLASS_MMI3:
874b2879 27432 decode_mmi3(env, ctx);
ec1944fc 27433 break;
baa609db
AM
27434 case MMI_OPC_MULT1:
27435 case MMI_OPC_MULTU1:
3b948f05
PMD
27436 case MMI_OPC_MADD:
27437 case MMI_OPC_MADDU:
a95c4c26
FN
27438 case MMI_OPC_MADD1:
27439 case MMI_OPC_MADDU1:
06de726b
FN
27440 gen_mul_txx9(ctx, opc, rd, rs, rt);
27441 break;
baa609db
AM
27442 case MMI_OPC_DIV1:
27443 case MMI_OPC_DIVU1:
c42171c3 27444 gen_div1_tx79(ctx, opc, rs, rt);
be9c42c9 27445 break;
baa609db
AM
27446 case MMI_OPC_MTLO1:
27447 case MMI_OPC_MTHI1:
86efbfb6 27448 gen_HILO1_tx79(ctx, opc, rs);
8d927f7c 27449 break;
baa609db
AM
27450 case MMI_OPC_MFLO1:
27451 case MMI_OPC_MFHI1:
86efbfb6 27452 gen_HILO1_tx79(ctx, opc, rd);
8d927f7c 27453 break;
baa609db 27454 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
baa609db
AM
27455 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
27456 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
27457 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
27458 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
27459 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
27460 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
27461 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
27462 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
27463 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
71b8a6b3
FN
27464 break;
27465 default:
27466 MIPS_INVAL("TX79 MMI class");
27467 generate_exception_end(ctx, EXCP_RI);
27468 break;
27469 }
27470}
27471
874b2879 27472static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
f08099ad 27473{
baa609db 27474 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
f08099ad
FN
27475}
27476
874b2879 27477static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
bb41e74b 27478{
baa609db 27479 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
bb41e74b
FN
27480}
27481
27482/*
27483 * The TX79-specific instruction Store Quadword
27484 *
27485 * +--------+-------+-------+------------------------+
27486 * | 011111 | base | rt | offset | SQ
27487 * +--------+-------+-------+------------------------+
27488 * 6 5 5 16
27489 *
27490 * has the same opcode as the Read Hardware Register instruction
27491 *
27492 * +--------+-------+-------+-------+-------+--------+
27493 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
27494 * +--------+-------+-------+-------+-------+--------+
27495 * 6 5 5 5 5 6
27496 *
27497 * that is required, trapped and emulated by the Linux kernel. However, all
27498 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
27499 * offset is odd. Therefore all valid SQ instructions can execute normally.
27500 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
27501 * between SQ and RDHWR, as the Linux kernel does.
27502 */
874b2879 27503static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
bb41e74b
FN
27504{
27505 int base = extract32(ctx->opcode, 21, 5);
27506 int rt = extract32(ctx->opcode, 16, 5);
27507 int offset = extract32(ctx->opcode, 0, 16);
27508
27509#ifdef CONFIG_USER_ONLY
27510 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
27511 uint32_t op2 = extract32(ctx->opcode, 6, 5);
27512
27513 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
27514 int rd = extract32(ctx->opcode, 11, 5);
27515
27516 gen_rdhwr(ctx, rt, rd, 0);
27517 return;
27518 }
27519#endif
27520
874b2879 27521 gen_mmi_sq(ctx, base, rt, offset);
bb41e74b
FN
27522}
27523
fac5a073
LA
27524static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
27525{
27526 int rs, rt, rd, sa;
27527 uint32_t op1, op2;
76964147 27528 int16_t imm;
fac5a073
LA
27529
27530 rs = (ctx->opcode >> 21) & 0x1f;
27531 rt = (ctx->opcode >> 16) & 0x1f;
27532 rd = (ctx->opcode >> 11) & 0x1f;
27533 sa = (ctx->opcode >> 6) & 0x1f;
76964147 27534 imm = sextract32(ctx->opcode, 7, 9);
fac5a073
LA
27535
27536 op1 = MASK_SPECIAL3(ctx->opcode);
76964147
JH
27537
27538 /*
27539 * EVA loads and stores overlap Loongson 2E instructions decoded by
27540 * decode_opc_special3_legacy(), so be careful to allow their decoding when
27541 * EVA is absent.
27542 */
27543 if (ctx->eva) {
27544 switch (op1) {
c2e19f3c
AM
27545 case OPC_LWLE:
27546 case OPC_LWRE:
76964147
JH
27547 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27548 /* fall through */
c2e19f3c
AM
27549 case OPC_LBUE:
27550 case OPC_LHUE:
27551 case OPC_LBE:
27552 case OPC_LHE:
27553 case OPC_LLE:
27554 case OPC_LWE:
76964147
JH
27555 check_cp0_enabled(ctx);
27556 gen_ld(ctx, op1, rt, rs, imm);
27557 return;
c2e19f3c
AM
27558 case OPC_SWLE:
27559 case OPC_SWRE:
76964147
JH
27560 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27561 /* fall through */
c2e19f3c
AM
27562 case OPC_SBE:
27563 case OPC_SHE:
76964147
JH
27564 case OPC_SWE:
27565 check_cp0_enabled(ctx);
27566 gen_st(ctx, op1, rt, rs, imm);
27567 return;
27568 case OPC_SCE:
27569 check_cp0_enabled(ctx);
27570 gen_st_cond(ctx, op1, rt, rs, imm);
27571 return;
27572 case OPC_CACHEE:
27573 check_cp0_enabled(ctx);
27574 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27575 gen_cache_operation(ctx, rt, rs, imm);
27576 }
27577 /* Treat as NOP. */
27578 return;
27579 case OPC_PREFE:
27580 check_cp0_enabled(ctx);
27581 /* Treat as NOP. */
27582 return;
27583 }
27584 }
27585
fac5a073
LA
27586 switch (op1) {
27587 case OPC_EXT:
27588 case OPC_INS:
27589 check_insn(ctx, ISA_MIPS32R2);
27590 gen_bitops(ctx, op1, rt, rs, sa, rd);
27591 break;
27592 case OPC_BSHFL:
fac5a073 27593 op2 = MASK_BSHFL(ctx->opcode);
15eacb9b 27594 switch (op2) {
c2e19f3c 27595 case OPC_ALIGN:
373ecd38
AM
27596 case OPC_ALIGN_1:
27597 case OPC_ALIGN_2:
27598 case OPC_ALIGN_3:
15eacb9b
YK
27599 case OPC_BITSWAP:
27600 check_insn(ctx, ISA_MIPS32R6);
27601 decode_opc_special3_r6(env, ctx);
27602 break;
27603 default:
27604 check_insn(ctx, ISA_MIPS32R2);
27605 gen_bshfl(ctx, op2, rt, rd);
27606 break;
27607 }
fac5a073
LA
27608 break;
27609#if defined(TARGET_MIPS64)
c2e19f3c
AM
27610 case OPC_DEXTM:
27611 case OPC_DEXTU:
27612 case OPC_DEXT:
27613 case OPC_DINSM:
27614 case OPC_DINSU:
27615 case OPC_DINS:
fac5a073
LA
27616 check_insn(ctx, ISA_MIPS64R2);
27617 check_mips_64(ctx);
27618 gen_bitops(ctx, op1, rt, rs, sa, rd);
27619 break;
27620 case OPC_DBSHFL:
fac5a073 27621 op2 = MASK_DBSHFL(ctx->opcode);
15eacb9b 27622 switch (op2) {
c2e19f3c 27623 case OPC_DALIGN:
373ecd38
AM
27624 case OPC_DALIGN_1:
27625 case OPC_DALIGN_2:
27626 case OPC_DALIGN_3:
27627 case OPC_DALIGN_4:
27628 case OPC_DALIGN_5:
27629 case OPC_DALIGN_6:
27630 case OPC_DALIGN_7:
15eacb9b
YK
27631 case OPC_DBITSWAP:
27632 check_insn(ctx, ISA_MIPS32R6);
27633 decode_opc_special3_r6(env, ctx);
27634 break;
27635 default:
27636 check_insn(ctx, ISA_MIPS64R2);
27637 check_mips_64(ctx);
27638 op2 = MASK_DBSHFL(ctx->opcode);
27639 gen_bshfl(ctx, op2, rt, rd);
27640 break;
27641 }
fac5a073
LA
27642 break;
27643#endif
27644 case OPC_RDHWR:
b00c7218 27645 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
fac5a073
LA
27646 break;
27647 case OPC_FORK:
9affc1c5 27648 check_mt(ctx);
fac5a073
LA
27649 {
27650 TCGv t0 = tcg_temp_new();
27651 TCGv t1 = tcg_temp_new();
27652
27653 gen_load_gpr(t0, rt);
27654 gen_load_gpr(t1, rs);
27655 gen_helper_fork(t0, t1);
27656 tcg_temp_free(t0);
27657 tcg_temp_free(t1);
27658 }
27659 break;
27660 case OPC_YIELD:
9affc1c5 27661 check_mt(ctx);
fac5a073
LA
27662 {
27663 TCGv t0 = tcg_temp_new();
27664
fac5a073
LA
27665 gen_load_gpr(t0, rs);
27666 gen_helper_yield(t0, cpu_env, t0);
27667 gen_store_gpr(t0, rd);
27668 tcg_temp_free(t0);
27669 }
27670 break;
10dc65db
LA
27671 default:
27672 if (ctx->insn_flags & ISA_MIPS32R6) {
27673 decode_opc_special3_r6(env, ctx);
27674 } else {
27675 decode_opc_special3_legacy(env, ctx);
27676 }
099e5b4d
LA
27677 }
27678}
27679
863f264d
YK
27680/* MIPS SIMD Architecture (MSA) */
27681static inline int check_msa_access(DisasContext *ctx)
27682{
27683 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
27684 !(ctx->hflags & MIPS_HFLAG_F64))) {
9c708c7f 27685 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
27686 return 0;
27687 }
27688
27689 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
27690 if (ctx->insn_flags & ASE_MSA) {
9c708c7f 27691 generate_exception_end(ctx, EXCP_MSADIS);
863f264d
YK
27692 return 0;
27693 } else {
9c708c7f 27694 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
27695 return 0;
27696 }
27697 }
27698 return 1;
27699}
27700
5692c6e1
YK
27701static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
27702{
27703 /* generates tcg ops to check if any element is 0 */
27704 /* Note this function only works with MSA_WRLEN = 128 */
27705 uint64_t eval_zero_or_big = 0;
27706 uint64_t eval_big = 0;
27707 TCGv_i64 t0 = tcg_temp_new_i64();
27708 TCGv_i64 t1 = tcg_temp_new_i64();
27709 switch (df) {
27710 case DF_BYTE:
27711 eval_zero_or_big = 0x0101010101010101ULL;
27712 eval_big = 0x8080808080808080ULL;
27713 break;
27714 case DF_HALF:
27715 eval_zero_or_big = 0x0001000100010001ULL;
27716 eval_big = 0x8000800080008000ULL;
27717 break;
27718 case DF_WORD:
27719 eval_zero_or_big = 0x0000000100000001ULL;
27720 eval_big = 0x8000000080000000ULL;
27721 break;
27722 case DF_DOUBLE:
27723 eval_zero_or_big = 0x0000000000000001ULL;
27724 eval_big = 0x8000000000000000ULL;
27725 break;
27726 }
27727 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
27728 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
27729 tcg_gen_andi_i64(t0, t0, eval_big);
27730 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
27731 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
27732 tcg_gen_andi_i64(t1, t1, eval_big);
27733 tcg_gen_or_i64(t0, t0, t1);
27734 /* if all bits are zero then all elements are not zero */
27735 /* if some bit is non-zero then some element is zero */
27736 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
27737 tcg_gen_trunc_i64_tl(tresult, t0);
27738 tcg_temp_free_i64(t0);
27739 tcg_temp_free_i64(t1);
27740}
27741
27742static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
27743{
27744 uint8_t df = (ctx->opcode >> 21) & 0x3;
27745 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27746 int64_t s16 = (int16_t)ctx->opcode;
27747
27748 check_msa_access(ctx);
27749
075a1fe7 27750 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 27751 generate_exception_end(ctx, EXCP_RI);
5692c6e1
YK
27752 return;
27753 }
27754 switch (op1) {
27755 case OPC_BZ_V:
27756 case OPC_BNZ_V:
27757 {
27758 TCGv_i64 t0 = tcg_temp_new_i64();
27759 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
27760 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
27761 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
27762 tcg_gen_trunc_i64_tl(bcond, t0);
27763 tcg_temp_free_i64(t0);
27764 }
27765 break;
27766 case OPC_BZ_B:
27767 case OPC_BZ_H:
27768 case OPC_BZ_W:
27769 case OPC_BZ_D:
27770 gen_check_zero_element(bcond, df, wt);
27771 break;
27772 case OPC_BNZ_B:
27773 case OPC_BNZ_H:
27774 case OPC_BNZ_W:
27775 case OPC_BNZ_D:
27776 gen_check_zero_element(bcond, df, wt);
27777 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
27778 break;
27779 }
27780
eeb3bba8 27781 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
5692c6e1
YK
27782
27783 ctx->hflags |= MIPS_HFLAG_BC;
27784 ctx->hflags |= MIPS_HFLAG_BDS32;
27785}
27786
4c789546
YK
27787static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
27788{
27789#define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
27790 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
27791 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27792 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27793
27794 TCGv_i32 twd = tcg_const_i32(wd);
27795 TCGv_i32 tws = tcg_const_i32(ws);
27796 TCGv_i32 ti8 = tcg_const_i32(i8);
27797
27798 switch (MASK_MSA_I8(ctx->opcode)) {
27799 case OPC_ANDI_B:
27800 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
27801 break;
27802 case OPC_ORI_B:
27803 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
27804 break;
27805 case OPC_NORI_B:
27806 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
27807 break;
27808 case OPC_XORI_B:
27809 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
27810 break;
27811 case OPC_BMNZI_B:
27812 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
27813 break;
27814 case OPC_BMZI_B:
27815 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
27816 break;
27817 case OPC_BSELI_B:
27818 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
27819 break;
27820 case OPC_SHF_B:
27821 case OPC_SHF_H:
27822 case OPC_SHF_W:
27823 {
27824 uint8_t df = (ctx->opcode >> 24) & 0x3;
27825 if (df == DF_DOUBLE) {
9c708c7f 27826 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
27827 } else {
27828 TCGv_i32 tdf = tcg_const_i32(df);
27829 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
27830 tcg_temp_free_i32(tdf);
27831 }
27832 }
27833 break;
27834 default:
27835 MIPS_INVAL("MSA instruction");
9c708c7f 27836 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
27837 break;
27838 }
27839
27840 tcg_temp_free_i32(twd);
27841 tcg_temp_free_i32(tws);
27842 tcg_temp_free_i32(ti8);
27843}
27844
80e71591
YK
27845static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
27846{
27847#define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
27848 uint8_t df = (ctx->opcode >> 21) & 0x3;
27849 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
27850 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
27851 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27852 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27853
27854 TCGv_i32 tdf = tcg_const_i32(df);
27855 TCGv_i32 twd = tcg_const_i32(wd);
27856 TCGv_i32 tws = tcg_const_i32(ws);
27857 TCGv_i32 timm = tcg_temp_new_i32();
27858 tcg_gen_movi_i32(timm, u5);
27859
27860 switch (MASK_MSA_I5(ctx->opcode)) {
27861 case OPC_ADDVI_df:
27862 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
27863 break;
27864 case OPC_SUBVI_df:
27865 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
27866 break;
27867 case OPC_MAXI_S_df:
27868 tcg_gen_movi_i32(timm, s5);
27869 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
27870 break;
27871 case OPC_MAXI_U_df:
27872 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
27873 break;
27874 case OPC_MINI_S_df:
27875 tcg_gen_movi_i32(timm, s5);
27876 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
27877 break;
27878 case OPC_MINI_U_df:
27879 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
27880 break;
27881 case OPC_CEQI_df:
27882 tcg_gen_movi_i32(timm, s5);
27883 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
27884 break;
27885 case OPC_CLTI_S_df:
27886 tcg_gen_movi_i32(timm, s5);
27887 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
27888 break;
27889 case OPC_CLTI_U_df:
27890 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
27891 break;
27892 case OPC_CLEI_S_df:
27893 tcg_gen_movi_i32(timm, s5);
27894 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
27895 break;
27896 case OPC_CLEI_U_df:
27897 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
27898 break;
27899 case OPC_LDI_df:
27900 {
27901 int32_t s10 = sextract32(ctx->opcode, 11, 10);
27902 tcg_gen_movi_i32(timm, s10);
27903 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
27904 }
27905 break;
27906 default:
27907 MIPS_INVAL("MSA instruction");
9c708c7f 27908 generate_exception_end(ctx, EXCP_RI);
80e71591
YK
27909 break;
27910 }
27911
27912 tcg_temp_free_i32(tdf);
27913 tcg_temp_free_i32(twd);
27914 tcg_temp_free_i32(tws);
27915 tcg_temp_free_i32(timm);
27916}
27917
d4cf28de
YK
27918static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
27919{
27920#define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
27921 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
27922 uint32_t df = 0, m = 0;
27923 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27924 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27925
27926 TCGv_i32 tdf;
27927 TCGv_i32 tm;
27928 TCGv_i32 twd;
27929 TCGv_i32 tws;
27930
27931 if ((dfm & 0x40) == 0x00) {
27932 m = dfm & 0x3f;
27933 df = DF_DOUBLE;
27934 } else if ((dfm & 0x60) == 0x40) {
27935 m = dfm & 0x1f;
27936 df = DF_WORD;
27937 } else if ((dfm & 0x70) == 0x60) {
27938 m = dfm & 0x0f;
27939 df = DF_HALF;
27940 } else if ((dfm & 0x78) == 0x70) {
27941 m = dfm & 0x7;
27942 df = DF_BYTE;
27943 } else {
9c708c7f 27944 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
27945 return;
27946 }
27947
27948 tdf = tcg_const_i32(df);
27949 tm = tcg_const_i32(m);
27950 twd = tcg_const_i32(wd);
27951 tws = tcg_const_i32(ws);
27952
27953 switch (MASK_MSA_BIT(ctx->opcode)) {
27954 case OPC_SLLI_df:
27955 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
27956 break;
27957 case OPC_SRAI_df:
27958 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
27959 break;
27960 case OPC_SRLI_df:
27961 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
27962 break;
27963 case OPC_BCLRI_df:
27964 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
27965 break;
27966 case OPC_BSETI_df:
27967 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
27968 break;
27969 case OPC_BNEGI_df:
27970 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
27971 break;
27972 case OPC_BINSLI_df:
27973 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
27974 break;
27975 case OPC_BINSRI_df:
27976 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
27977 break;
27978 case OPC_SAT_S_df:
27979 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
27980 break;
27981 case OPC_SAT_U_df:
27982 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
27983 break;
27984 case OPC_SRARI_df:
27985 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
27986 break;
27987 case OPC_SRLRI_df:
27988 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
27989 break;
27990 default:
27991 MIPS_INVAL("MSA instruction");
9c708c7f 27992 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
27993 break;
27994 }
27995
27996 tcg_temp_free_i32(tdf);
27997 tcg_temp_free_i32(tm);
27998 tcg_temp_free_i32(twd);
27999 tcg_temp_free_i32(tws);
28000}
28001
28f99f08
YK
28002static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28003{
28004#define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28005 uint8_t df = (ctx->opcode >> 21) & 0x3;
28006 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28007 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28008 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28009
28010 TCGv_i32 tdf = tcg_const_i32(df);
28011 TCGv_i32 twd = tcg_const_i32(wd);
28012 TCGv_i32 tws = tcg_const_i32(ws);
28013 TCGv_i32 twt = tcg_const_i32(wt);
28014
28015 switch (MASK_MSA_3R(ctx->opcode)) {
28016 case OPC_SLL_df:
28017 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
28018 break;
28019 case OPC_ADDV_df:
28020 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
28021 break;
28022 case OPC_CEQ_df:
28023 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
28024 break;
28025 case OPC_ADD_A_df:
28026 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
28027 break;
28028 case OPC_SUBS_S_df:
28029 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
28030 break;
28031 case OPC_MULV_df:
28032 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
28033 break;
28034 case OPC_SLD_df:
28035 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
28036 break;
28037 case OPC_VSHF_df:
28038 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
28039 break;
28040 case OPC_SRA_df:
28041 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
28042 break;
28043 case OPC_SUBV_df:
28044 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
28045 break;
28046 case OPC_ADDS_A_df:
28047 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
28048 break;
28049 case OPC_SUBS_U_df:
28050 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
28051 break;
28052 case OPC_MADDV_df:
28053 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
28054 break;
28055 case OPC_SPLAT_df:
28056 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
28057 break;
28058 case OPC_SRAR_df:
28059 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
28060 break;
28061 case OPC_SRL_df:
28062 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
28063 break;
28064 case OPC_MAX_S_df:
28065 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
28066 break;
28067 case OPC_CLT_S_df:
28068 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
28069 break;
28070 case OPC_ADDS_S_df:
28071 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
28072 break;
28073 case OPC_SUBSUS_U_df:
28074 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
28075 break;
28076 case OPC_MSUBV_df:
28077 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
28078 break;
28079 case OPC_PCKEV_df:
28080 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
28081 break;
28082 case OPC_SRLR_df:
28083 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
28084 break;
28085 case OPC_BCLR_df:
28086 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
28087 break;
28088 case OPC_MAX_U_df:
28089 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
28090 break;
28091 case OPC_CLT_U_df:
28092 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
28093 break;
28094 case OPC_ADDS_U_df:
28095 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
28096 break;
28097 case OPC_SUBSUU_S_df:
28098 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
28099 break;
28100 case OPC_PCKOD_df:
28101 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
28102 break;
28103 case OPC_BSET_df:
28104 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
28105 break;
28106 case OPC_MIN_S_df:
28107 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
28108 break;
28109 case OPC_CLE_S_df:
28110 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
28111 break;
28112 case OPC_AVE_S_df:
28113 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
28114 break;
28115 case OPC_ASUB_S_df:
28116 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
28117 break;
28118 case OPC_DIV_S_df:
28119 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
28120 break;
28121 case OPC_ILVL_df:
28122 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
28123 break;
28124 case OPC_BNEG_df:
28125 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
28126 break;
28127 case OPC_MIN_U_df:
28128 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
28129 break;
28130 case OPC_CLE_U_df:
28131 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
28132 break;
28133 case OPC_AVE_U_df:
28134 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
28135 break;
28136 case OPC_ASUB_U_df:
28137 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
28138 break;
28139 case OPC_DIV_U_df:
28140 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
28141 break;
28142 case OPC_ILVR_df:
28143 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
28144 break;
28145 case OPC_BINSL_df:
28146 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
28147 break;
28148 case OPC_MAX_A_df:
28149 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
28150 break;
28151 case OPC_AVER_S_df:
28152 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
28153 break;
28154 case OPC_MOD_S_df:
28155 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
28156 break;
28157 case OPC_ILVEV_df:
28158 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
28159 break;
28160 case OPC_BINSR_df:
28161 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
28162 break;
28163 case OPC_MIN_A_df:
28164 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
28165 break;
28166 case OPC_AVER_U_df:
28167 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
28168 break;
28169 case OPC_MOD_U_df:
28170 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
28171 break;
28172 case OPC_ILVOD_df:
28173 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
28174 break;
28175
28176 case OPC_DOTP_S_df:
28177 case OPC_DOTP_U_df:
28178 case OPC_DPADD_S_df:
28179 case OPC_DPADD_U_df:
28180 case OPC_DPSUB_S_df:
28181 case OPC_HADD_S_df:
28182 case OPC_DPSUB_U_df:
28183 case OPC_HADD_U_df:
28184 case OPC_HSUB_S_df:
28185 case OPC_HSUB_U_df:
28186 if (df == DF_BYTE) {
9c708c7f
PD
28187 generate_exception_end(ctx, EXCP_RI);
28188 break;
28f99f08
YK
28189 }
28190 switch (MASK_MSA_3R(ctx->opcode)) {
28191 case OPC_DOTP_S_df:
28192 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
28193 break;
28194 case OPC_DOTP_U_df:
28195 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
28196 break;
28197 case OPC_DPADD_S_df:
28198 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
28199 break;
28200 case OPC_DPADD_U_df:
28201 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
28202 break;
28203 case OPC_DPSUB_S_df:
28204 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
28205 break;
28206 case OPC_HADD_S_df:
28207 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
28208 break;
28209 case OPC_DPSUB_U_df:
28210 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
28211 break;
28212 case OPC_HADD_U_df:
28213 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
28214 break;
28215 case OPC_HSUB_S_df:
28216 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
28217 break;
28218 case OPC_HSUB_U_df:
28219 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
28220 break;
28221 }
28222 break;
28223 default:
28224 MIPS_INVAL("MSA instruction");
9c708c7f 28225 generate_exception_end(ctx, EXCP_RI);
28f99f08
YK
28226 break;
28227 }
28228 tcg_temp_free_i32(twd);
28229 tcg_temp_free_i32(tws);
28230 tcg_temp_free_i32(twt);
28231 tcg_temp_free_i32(tdf);
28232}
28233
1e608ec1
YK
28234static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
28235{
28236#define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
28237 uint8_t source = (ctx->opcode >> 11) & 0x1f;
28238 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
28239 TCGv telm = tcg_temp_new();
28240 TCGv_i32 tsr = tcg_const_i32(source);
28241 TCGv_i32 tdt = tcg_const_i32(dest);
28242
28243 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
28244 case OPC_CTCMSA:
28245 gen_load_gpr(telm, source);
28246 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
28247 break;
28248 case OPC_CFCMSA:
28249 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
28250 gen_store_gpr(telm, dest);
28251 break;
28252 case OPC_MOVE_V:
28253 gen_helper_msa_move_v(cpu_env, tdt, tsr);
28254 break;
28255 default:
28256 MIPS_INVAL("MSA instruction");
9c708c7f 28257 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
28258 break;
28259 }
28260
28261 tcg_temp_free(telm);
28262 tcg_temp_free_i32(tdt);
28263 tcg_temp_free_i32(tsr);
28264}
28265
28266static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
28267 uint32_t n)
28268{
28269#define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28270 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28271 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28272
28273 TCGv_i32 tws = tcg_const_i32(ws);
28274 TCGv_i32 twd = tcg_const_i32(wd);
28275 TCGv_i32 tn = tcg_const_i32(n);
28276 TCGv_i32 tdf = tcg_const_i32(df);
28277
28278 switch (MASK_MSA_ELM(ctx->opcode)) {
28279 case OPC_SLDI_df:
28280 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
28281 break;
28282 case OPC_SPLATI_df:
28283 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
28284 break;
28285 case OPC_INSVE_df:
28286 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
28287 break;
28288 case OPC_COPY_S_df:
28289 case OPC_COPY_U_df:
28290 case OPC_INSERT_df:
28291#if !defined(TARGET_MIPS64)
28292 /* Double format valid only for MIPS64 */
28293 if (df == DF_DOUBLE) {
9c708c7f 28294 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
28295 break;
28296 }
28297#endif
28298 switch (MASK_MSA_ELM(ctx->opcode)) {
28299 case OPC_COPY_S_df:
cab48881
MD
28300 if (likely(wd != 0)) {
28301 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
28302 }
1e608ec1
YK
28303 break;
28304 case OPC_COPY_U_df:
cab48881
MD
28305 if (likely(wd != 0)) {
28306 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
28307 }
1e608ec1
YK
28308 break;
28309 case OPC_INSERT_df:
28310 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
28311 break;
28312 }
28313 break;
28314 default:
28315 MIPS_INVAL("MSA instruction");
9c708c7f 28316 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
28317 }
28318 tcg_temp_free_i32(twd);
28319 tcg_temp_free_i32(tws);
28320 tcg_temp_free_i32(tn);
28321 tcg_temp_free_i32(tdf);
28322}
28323
28324static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
28325{
28326 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
28327 uint32_t df = 0, n = 0;
28328
28329 if ((dfn & 0x30) == 0x00) {
28330 n = dfn & 0x0f;
28331 df = DF_BYTE;
28332 } else if ((dfn & 0x38) == 0x20) {
28333 n = dfn & 0x07;
28334 df = DF_HALF;
28335 } else if ((dfn & 0x3c) == 0x30) {
28336 n = dfn & 0x03;
28337 df = DF_WORD;
28338 } else if ((dfn & 0x3e) == 0x38) {
28339 n = dfn & 0x01;
28340 df = DF_DOUBLE;
28341 } else if (dfn == 0x3E) {
28342 /* CTCMSA, CFCMSA, MOVE.V */
28343 gen_msa_elm_3e(env, ctx);
28344 return;
28345 } else {
9c708c7f 28346 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
28347 return;
28348 }
28349
28350 gen_msa_elm_df(env, ctx, df, n);
28351}
28352
7d05b9c8
YK
28353static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
28354{
28355#define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28356 uint8_t df = (ctx->opcode >> 21) & 0x1;
28357 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28358 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28359 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28360
28361 TCGv_i32 twd = tcg_const_i32(wd);
28362 TCGv_i32 tws = tcg_const_i32(ws);
28363 TCGv_i32 twt = tcg_const_i32(wt);
28364 TCGv_i32 tdf = tcg_temp_new_i32();
28365
28366 /* adjust df value for floating-point instruction */
28367 tcg_gen_movi_i32(tdf, df + 2);
28368
28369 switch (MASK_MSA_3RF(ctx->opcode)) {
28370 case OPC_FCAF_df:
28371 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
28372 break;
28373 case OPC_FADD_df:
28374 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
28375 break;
28376 case OPC_FCUN_df:
28377 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
28378 break;
28379 case OPC_FSUB_df:
28380 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
28381 break;
28382 case OPC_FCOR_df:
28383 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
28384 break;
28385 case OPC_FCEQ_df:
28386 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
28387 break;
28388 case OPC_FMUL_df:
28389 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
28390 break;
28391 case OPC_FCUNE_df:
28392 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
28393 break;
28394 case OPC_FCUEQ_df:
28395 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
28396 break;
28397 case OPC_FDIV_df:
28398 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
28399 break;
28400 case OPC_FCNE_df:
28401 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
28402 break;
28403 case OPC_FCLT_df:
28404 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
28405 break;
28406 case OPC_FMADD_df:
28407 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
28408 break;
28409 case OPC_MUL_Q_df:
28410 tcg_gen_movi_i32(tdf, df + 1);
28411 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
28412 break;
28413 case OPC_FCULT_df:
28414 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
28415 break;
28416 case OPC_FMSUB_df:
28417 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
28418 break;
28419 case OPC_MADD_Q_df:
28420 tcg_gen_movi_i32(tdf, df + 1);
28421 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
28422 break;
28423 case OPC_FCLE_df:
28424 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
28425 break;
28426 case OPC_MSUB_Q_df:
28427 tcg_gen_movi_i32(tdf, df + 1);
28428 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
28429 break;
28430 case OPC_FCULE_df:
28431 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
28432 break;
28433 case OPC_FEXP2_df:
28434 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
28435 break;
28436 case OPC_FSAF_df:
28437 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
28438 break;
28439 case OPC_FEXDO_df:
28440 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
28441 break;
28442 case OPC_FSUN_df:
28443 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
28444 break;
28445 case OPC_FSOR_df:
28446 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
28447 break;
28448 case OPC_FSEQ_df:
28449 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
28450 break;
28451 case OPC_FTQ_df:
28452 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
28453 break;
28454 case OPC_FSUNE_df:
28455 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
28456 break;
28457 case OPC_FSUEQ_df:
28458 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
28459 break;
28460 case OPC_FSNE_df:
28461 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
28462 break;
28463 case OPC_FSLT_df:
28464 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
28465 break;
28466 case OPC_FMIN_df:
28467 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
28468 break;
28469 case OPC_MULR_Q_df:
28470 tcg_gen_movi_i32(tdf, df + 1);
28471 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
28472 break;
28473 case OPC_FSULT_df:
28474 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
28475 break;
28476 case OPC_FMIN_A_df:
28477 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
28478 break;
28479 case OPC_MADDR_Q_df:
28480 tcg_gen_movi_i32(tdf, df + 1);
28481 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
28482 break;
28483 case OPC_FSLE_df:
28484 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
28485 break;
28486 case OPC_FMAX_df:
28487 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
28488 break;
28489 case OPC_MSUBR_Q_df:
28490 tcg_gen_movi_i32(tdf, df + 1);
28491 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
28492 break;
28493 case OPC_FSULE_df:
28494 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
28495 break;
28496 case OPC_FMAX_A_df:
28497 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
28498 break;
28499 default:
28500 MIPS_INVAL("MSA instruction");
9c708c7f 28501 generate_exception_end(ctx, EXCP_RI);
7d05b9c8
YK
28502 break;
28503 }
28504
28505 tcg_temp_free_i32(twd);
28506 tcg_temp_free_i32(tws);
28507 tcg_temp_free_i32(twt);
28508 tcg_temp_free_i32(tdf);
28509}
28510
cbe50b9a
YK
28511static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
28512{
28513#define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28514 (op & (0x7 << 18)))
28515 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28516 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28517 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28518 uint8_t df = (ctx->opcode >> 16) & 0x3;
28519 TCGv_i32 twd = tcg_const_i32(wd);
28520 TCGv_i32 tws = tcg_const_i32(ws);
28521 TCGv_i32 twt = tcg_const_i32(wt);
28522 TCGv_i32 tdf = tcg_const_i32(df);
28523
28524 switch (MASK_MSA_2R(ctx->opcode)) {
28525 case OPC_FILL_df:
28526#if !defined(TARGET_MIPS64)
28527 /* Double format valid only for MIPS64 */
28528 if (df == DF_DOUBLE) {
9c708c7f 28529 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
28530 break;
28531 }
28532#endif
28533 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
28534 break;
28535 case OPC_PCNT_df:
28536 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
28537 break;
28538 case OPC_NLOC_df:
28539 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
28540 break;
28541 case OPC_NLZC_df:
28542 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
28543 break;
28544 default:
28545 MIPS_INVAL("MSA instruction");
9c708c7f 28546 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
28547 break;
28548 }
28549
28550 tcg_temp_free_i32(twd);
28551 tcg_temp_free_i32(tws);
28552 tcg_temp_free_i32(twt);
28553 tcg_temp_free_i32(tdf);
28554}
28555
3bdeb688
YK
28556static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
28557{
28558#define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28559 (op & (0xf << 17)))
28560 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28561 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28562 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28563 uint8_t df = (ctx->opcode >> 16) & 0x1;
28564 TCGv_i32 twd = tcg_const_i32(wd);
28565 TCGv_i32 tws = tcg_const_i32(ws);
28566 TCGv_i32 twt = tcg_const_i32(wt);
28567 /* adjust df value for floating-point instruction */
28568 TCGv_i32 tdf = tcg_const_i32(df + 2);
28569
28570 switch (MASK_MSA_2RF(ctx->opcode)) {
28571 case OPC_FCLASS_df:
28572 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
28573 break;
28574 case OPC_FTRUNC_S_df:
28575 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
28576 break;
28577 case OPC_FTRUNC_U_df:
28578 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
28579 break;
28580 case OPC_FSQRT_df:
28581 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
28582 break;
28583 case OPC_FRSQRT_df:
28584 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
28585 break;
28586 case OPC_FRCP_df:
28587 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
28588 break;
28589 case OPC_FRINT_df:
28590 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
28591 break;
28592 case OPC_FLOG2_df:
28593 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
28594 break;
28595 case OPC_FEXUPL_df:
28596 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
28597 break;
28598 case OPC_FEXUPR_df:
28599 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
28600 break;
28601 case OPC_FFQL_df:
28602 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
28603 break;
28604 case OPC_FFQR_df:
28605 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
28606 break;
28607 case OPC_FTINT_S_df:
28608 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
28609 break;
28610 case OPC_FTINT_U_df:
28611 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
28612 break;
28613 case OPC_FFINT_S_df:
28614 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
28615 break;
28616 case OPC_FFINT_U_df:
28617 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
28618 break;
28619 }
28620
28621 tcg_temp_free_i32(twd);
28622 tcg_temp_free_i32(tws);
28623 tcg_temp_free_i32(twt);
28624 tcg_temp_free_i32(tdf);
28625}
28626
cbe50b9a
YK
28627static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
28628{
28629#define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
28630 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28631 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28632 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28633 TCGv_i32 twd = tcg_const_i32(wd);
28634 TCGv_i32 tws = tcg_const_i32(ws);
28635 TCGv_i32 twt = tcg_const_i32(wt);
28636
28637 switch (MASK_MSA_VEC(ctx->opcode)) {
28638 case OPC_AND_V:
28639 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
28640 break;
28641 case OPC_OR_V:
28642 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
28643 break;
28644 case OPC_NOR_V:
28645 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
28646 break;
28647 case OPC_XOR_V:
28648 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
28649 break;
28650 case OPC_BMNZ_V:
28651 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
28652 break;
28653 case OPC_BMZ_V:
28654 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
28655 break;
28656 case OPC_BSEL_V:
28657 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
28658 break;
28659 default:
28660 MIPS_INVAL("MSA instruction");
9c708c7f 28661 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
28662 break;
28663 }
28664
28665 tcg_temp_free_i32(twd);
28666 tcg_temp_free_i32(tws);
28667 tcg_temp_free_i32(twt);
28668}
28669
28670static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
28671{
28672 switch (MASK_MSA_VEC(ctx->opcode)) {
28673 case OPC_AND_V:
28674 case OPC_OR_V:
28675 case OPC_NOR_V:
28676 case OPC_XOR_V:
28677 case OPC_BMNZ_V:
28678 case OPC_BMZ_V:
28679 case OPC_BSEL_V:
28680 gen_msa_vec_v(env, ctx);
28681 break;
28682 case OPC_MSA_2R:
28683 gen_msa_2r(env, ctx);
28684 break;
3bdeb688
YK
28685 case OPC_MSA_2RF:
28686 gen_msa_2rf(env, ctx);
28687 break;
cbe50b9a
YK
28688 default:
28689 MIPS_INVAL("MSA instruction");
9c708c7f 28690 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
28691 break;
28692 }
28693}
28694
4c789546
YK
28695static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
28696{
28697 uint32_t opcode = ctx->opcode;
28698 check_insn(ctx, ASE_MSA);
28699 check_msa_access(ctx);
28700
28701 switch (MASK_MSA_MINOR(opcode)) {
28702 case OPC_MSA_I8_00:
28703 case OPC_MSA_I8_01:
28704 case OPC_MSA_I8_02:
28705 gen_msa_i8(env, ctx);
28706 break;
80e71591
YK
28707 case OPC_MSA_I5_06:
28708 case OPC_MSA_I5_07:
28709 gen_msa_i5(env, ctx);
28710 break;
d4cf28de
YK
28711 case OPC_MSA_BIT_09:
28712 case OPC_MSA_BIT_0A:
28713 gen_msa_bit(env, ctx);
28714 break;
28f99f08
YK
28715 case OPC_MSA_3R_0D:
28716 case OPC_MSA_3R_0E:
28717 case OPC_MSA_3R_0F:
28718 case OPC_MSA_3R_10:
28719 case OPC_MSA_3R_11:
28720 case OPC_MSA_3R_12:
28721 case OPC_MSA_3R_13:
28722 case OPC_MSA_3R_14:
28723 case OPC_MSA_3R_15:
28724 gen_msa_3r(env, ctx);
28725 break;
1e608ec1
YK
28726 case OPC_MSA_ELM:
28727 gen_msa_elm(env, ctx);
28728 break;
7d05b9c8
YK
28729 case OPC_MSA_3RF_1A:
28730 case OPC_MSA_3RF_1B:
28731 case OPC_MSA_3RF_1C:
28732 gen_msa_3rf(env, ctx);
28733 break;
cbe50b9a
YK
28734 case OPC_MSA_VEC:
28735 gen_msa_vec(env, ctx);
28736 break;
f7685877
YK
28737 case OPC_LD_B:
28738 case OPC_LD_H:
28739 case OPC_LD_W:
28740 case OPC_LD_D:
28741 case OPC_ST_B:
28742 case OPC_ST_H:
28743 case OPC_ST_W:
28744 case OPC_ST_D:
28745 {
28746 int32_t s10 = sextract32(ctx->opcode, 16, 10);
28747 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
28748 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28749 uint8_t df = (ctx->opcode >> 0) & 0x3;
28750
f7685877 28751 TCGv_i32 twd = tcg_const_i32(wd);
adc370a4
YK
28752 TCGv taddr = tcg_temp_new();
28753 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
f7685877
YK
28754
28755 switch (MASK_MSA_MINOR(opcode)) {
28756 case OPC_LD_B:
adc370a4
YK
28757 gen_helper_msa_ld_b(cpu_env, twd, taddr);
28758 break;
f7685877 28759 case OPC_LD_H:
adc370a4
YK
28760 gen_helper_msa_ld_h(cpu_env, twd, taddr);
28761 break;
f7685877 28762 case OPC_LD_W:
adc370a4
YK
28763 gen_helper_msa_ld_w(cpu_env, twd, taddr);
28764 break;
f7685877 28765 case OPC_LD_D:
adc370a4 28766 gen_helper_msa_ld_d(cpu_env, twd, taddr);
f7685877
YK
28767 break;
28768 case OPC_ST_B:
adc370a4
YK
28769 gen_helper_msa_st_b(cpu_env, twd, taddr);
28770 break;
f7685877 28771 case OPC_ST_H:
adc370a4
YK
28772 gen_helper_msa_st_h(cpu_env, twd, taddr);
28773 break;
f7685877 28774 case OPC_ST_W:
adc370a4
YK
28775 gen_helper_msa_st_w(cpu_env, twd, taddr);
28776 break;
f7685877 28777 case OPC_ST_D:
adc370a4 28778 gen_helper_msa_st_d(cpu_env, twd, taddr);
f7685877
YK
28779 break;
28780 }
28781
28782 tcg_temp_free_i32(twd);
adc370a4 28783 tcg_temp_free(taddr);
f7685877
YK
28784 }
28785 break;
4c789546
YK
28786 default:
28787 MIPS_INVAL("MSA instruction");
9c708c7f 28788 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
28789 break;
28790 }
28791
28792}
28793
d2bfa6e6 28794static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
28795{
28796 int32_t offset;
28797 int rs, rt, rd, sa;
28798 uint32_t op, op1;
28799 int16_t imm;
28800
28801 /* make sure instructions are on a word boundary */
eeb3bba8
EC
28802 if (ctx->base.pc_next & 0x3) {
28803 env->CP0_BadVAddr = ctx->base.pc_next;
aea14095 28804 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
099e5b4d
LA
28805 return;
28806 }
28807
28808 /* Handle blikely not taken case */
28809 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
42a268c2 28810 TCGLabel *l1 = gen_new_label();
099e5b4d 28811
099e5b4d
LA
28812 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
28813 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
eeb3bba8 28814 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
099e5b4d
LA
28815 gen_set_label(l1);
28816 }
28817
099e5b4d
LA
28818 op = MASK_OP_MAJOR(ctx->opcode);
28819 rs = (ctx->opcode >> 21) & 0x1f;
28820 rt = (ctx->opcode >> 16) & 0x1f;
28821 rd = (ctx->opcode >> 11) & 0x1f;
28822 sa = (ctx->opcode >> 6) & 0x1f;
28823 imm = (int16_t)ctx->opcode;
28824 switch (op) {
28825 case OPC_SPECIAL:
28826 decode_opc_special(env, ctx);
28827 break;
28828 case OPC_SPECIAL2:
71b8a6b3 28829 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
874b2879 28830 decode_mmi(env, ctx);
b621f018 28831#if !defined(TARGET_MIPS64)
0a348b9a
AM
28832 } else if (ctx->insn_flags & ASE_MXU) {
28833 decode_opc_mxu(env, ctx);
b621f018 28834#endif
71b8a6b3
FN
28835 } else {
28836 decode_opc_special2_legacy(env, ctx);
28837 }
099e5b4d
LA
28838 break;
28839 case OPC_SPECIAL3:
bb41e74b 28840 if (ctx->insn_flags & INSN_R5900) {
874b2879 28841 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
bb41e74b
FN
28842 } else {
28843 decode_opc_special3(env, ctx);
28844 }
099e5b4d 28845 break;
7a387fff
TS
28846 case OPC_REGIMM:
28847 op1 = MASK_REGIMM(ctx->opcode);
28848 switch (op1) {
fecd2646
LA
28849 case OPC_BLTZL: /* REGIMM branches */
28850 case OPC_BGEZL:
28851 case OPC_BLTZALL:
28852 case OPC_BGEZALL:
d9224450 28853 check_insn(ctx, ISA_MIPS2);
fecd2646 28854 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 28855 /* Fallthrough */
fecd2646
LA
28856 case OPC_BLTZ:
28857 case OPC_BGEZ:
b231c103 28858 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 28859 break;
fecd2646
LA
28860 case OPC_BLTZAL:
28861 case OPC_BGEZAL:
0aefa333
YK
28862 if (ctx->insn_flags & ISA_MIPS32R6) {
28863 if (rs == 0) {
28864 /* OPC_NAL, OPC_BAL */
b231c103 28865 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
0aefa333 28866 } else {
9c708c7f 28867 generate_exception_end(ctx, EXCP_RI);
0aefa333
YK
28868 }
28869 } else {
b231c103 28870 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 28871 }
c9602061 28872 break;
c2e19f3c
AM
28873 case OPC_TGEI: /* REGIMM traps */
28874 case OPC_TGEIU:
28875 case OPC_TLTI:
28876 case OPC_TLTIU:
28877 case OPC_TEQI:
28878
7a387fff 28879 case OPC_TNEI:
d9224450 28880 check_insn(ctx, ISA_MIPS2);
fecd2646 28881 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7a387fff
TS
28882 gen_trap(ctx, op1, rs, -1, imm);
28883 break;
bb238210
YK
28884 case OPC_SIGRIE:
28885 check_insn(ctx, ISA_MIPS32R6);
28886 generate_exception_end(ctx, EXCP_RI);
28887 break;
7a387fff 28888 case OPC_SYNCI:
d75c135e 28889 check_insn(ctx, ISA_MIPS32R2);
a83bddd6
DZ
28890 /* Break the TB to be able to sync copied instructions
28891 immediately */
eeb3bba8 28892 ctx->base.is_jmp = DISAS_STOP;
6af0bf9c 28893 break;
e45a93e2
JL
28894 case OPC_BPOSGE32: /* MIPS DSP branch */
28895#if defined(TARGET_MIPS64)
28896 case OPC_BPOSGE64:
28897#endif
28898 check_dsp(ctx);
b231c103 28899 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
e45a93e2 28900 break;
d4ea6acd
LA
28901#if defined(TARGET_MIPS64)
28902 case OPC_DAHI:
28903 check_insn(ctx, ISA_MIPS32R6);
28904 check_mips_64(ctx);
28905 if (rs != 0) {
28906 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
28907 }
d4ea6acd
LA
28908 break;
28909 case OPC_DATI:
28910 check_insn(ctx, ISA_MIPS32R6);
28911 check_mips_64(ctx);
28912 if (rs != 0) {
28913 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
28914 }
d4ea6acd
LA
28915 break;
28916#endif
6af0bf9c 28917 default: /* Invalid */
923617a3 28918 MIPS_INVAL("regimm");
9c708c7f 28919 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
28920 break;
28921 }
28922 break;
7a387fff 28923 case OPC_CP0:
387a8fe5 28924 check_cp0_enabled(ctx);
7a387fff 28925 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 28926 switch (op1) {
7a387fff
TS
28927 case OPC_MFC0:
28928 case OPC_MTC0:
ead9360e
TS
28929 case OPC_MFTR:
28930 case OPC_MTTR:
5204ea79
LA
28931 case OPC_MFHC0:
28932 case OPC_MTHC0:
d26bc211 28933#if defined(TARGET_MIPS64)
7a387fff
TS
28934 case OPC_DMFC0:
28935 case OPC_DMTC0:
28936#endif
f1aa6320 28937#ifndef CONFIG_USER_ONLY
932e71cd 28938 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 28939#endif /* !CONFIG_USER_ONLY */
7a387fff 28940 break;
c38a1d52
AR
28941 case OPC_C0:
28942 case OPC_C0_1:
28943 case OPC_C0_2:
28944 case OPC_C0_3:
28945 case OPC_C0_4:
28946 case OPC_C0_5:
28947 case OPC_C0_6:
28948 case OPC_C0_7:
28949 case OPC_C0_8:
28950 case OPC_C0_9:
28951 case OPC_C0_A:
28952 case OPC_C0_B:
28953 case OPC_C0_C:
28954 case OPC_C0_D:
28955 case OPC_C0_E:
28956 case OPC_C0_F:
f1aa6320 28957#ifndef CONFIG_USER_ONLY
932e71cd 28958 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 28959#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
28960 break;
28961 case OPC_MFMC0:
8706c382 28962#ifndef CONFIG_USER_ONLY
932e71cd 28963 {
099e5b4d 28964 uint32_t op2;
35fbce2c 28965 TCGv t0 = tcg_temp_new();
6c5c1e20 28966
0eaef5aa 28967 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
28968 switch (op2) {
28969 case OPC_DMT:
9affc1c5 28970 check_cp0_mt(ctx);
9ed5726c 28971 gen_helper_dmt(t0);
35fbce2c 28972 gen_store_gpr(t0, rt);
6c5c1e20
TS
28973 break;
28974 case OPC_EMT:
9affc1c5 28975 check_cp0_mt(ctx);
9ed5726c 28976 gen_helper_emt(t0);
35fbce2c 28977 gen_store_gpr(t0, rt);
da80682b 28978 break;
6c5c1e20 28979 case OPC_DVPE:
9affc1c5 28980 check_cp0_mt(ctx);
895c2d04 28981 gen_helper_dvpe(t0, cpu_env);
35fbce2c 28982 gen_store_gpr(t0, rt);
6c5c1e20
TS
28983 break;
28984 case OPC_EVPE:
9affc1c5 28985 check_cp0_mt(ctx);
895c2d04 28986 gen_helper_evpe(t0, cpu_env);
35fbce2c 28987 gen_store_gpr(t0, rt);
6c5c1e20 28988 break;
01bc435b
YK
28989 case OPC_DVP:
28990 check_insn(ctx, ISA_MIPS32R6);
28991 if (ctx->vp) {
28992 gen_helper_dvp(t0, cpu_env);
28993 gen_store_gpr(t0, rt);
28994 }
28995 break;
28996 case OPC_EVP:
28997 check_insn(ctx, ISA_MIPS32R6);
28998 if (ctx->vp) {
28999 gen_helper_evp(t0, cpu_env);
29000 gen_store_gpr(t0, rt);
29001 }
29002 break;
6c5c1e20 29003 case OPC_DI:
d75c135e 29004 check_insn(ctx, ISA_MIPS32R2);
867abc7e 29005 save_cpu_state(ctx, 1);
895c2d04 29006 gen_helper_di(t0, cpu_env);
35fbce2c 29007 gen_store_gpr(t0, rt);
d2bfa6e6
MR
29008 /* Stop translation as we may have switched
29009 the execution mode. */
eeb3bba8 29010 ctx->base.is_jmp = DISAS_STOP;
6c5c1e20
TS
29011 break;
29012 case OPC_EI:
d75c135e 29013 check_insn(ctx, ISA_MIPS32R2);
867abc7e 29014 save_cpu_state(ctx, 1);
895c2d04 29015 gen_helper_ei(t0, cpu_env);
35fbce2c 29016 gen_store_gpr(t0, rt);
b28425ba
EC
29017 /* DISAS_STOP isn't sufficient, we need to ensure we break
29018 out of translated code to check for pending interrupts */
eeb3bba8
EC
29019 gen_save_pc(ctx->base.pc_next + 4);
29020 ctx->base.is_jmp = DISAS_EXIT;
6c5c1e20
TS
29021 break;
29022 default: /* Invalid */
29023 MIPS_INVAL("mfmc0");
9c708c7f 29024 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
29025 break;
29026 }
6c5c1e20 29027 tcg_temp_free(t0);
7a387fff 29028 }
0eaef5aa 29029#endif /* !CONFIG_USER_ONLY */
6af0bf9c 29030 break;
7a387fff 29031 case OPC_RDPGPR:
d75c135e 29032 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 29033 gen_load_srsgpr(rt, rd);
ead9360e 29034 break;
7a387fff 29035 case OPC_WRPGPR:
d75c135e 29036 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 29037 gen_store_srsgpr(rt, rd);
38121543 29038 break;
6af0bf9c 29039 default:
923617a3 29040 MIPS_INVAL("cp0");
9c708c7f 29041 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
29042 break;
29043 }
29044 break;
31837be3
YK
29045 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
29046 if (ctx->insn_flags & ISA_MIPS32R6) {
29047 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
29048 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29049 } else {
29050 /* OPC_ADDI */
29051 /* Arithmetic with immediate opcode */
29052 gen_arith_imm(ctx, op, rt, rs, imm);
29053 }
29054 break;
324d9e32 29055 case OPC_ADDIU:
d75c135e 29056 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 29057 break;
324d9e32
AJ
29058 case OPC_SLTI: /* Set on less than with immediate opcode */
29059 case OPC_SLTIU:
d75c135e 29060 gen_slt_imm(ctx, op, rt, rs, imm);
324d9e32
AJ
29061 break;
29062 case OPC_ANDI: /* Arithmetic with immediate opcode */
d4ea6acd 29063 case OPC_LUI: /* OPC_AUI */
324d9e32
AJ
29064 case OPC_ORI:
29065 case OPC_XORI:
d75c135e 29066 gen_logic_imm(ctx, op, rt, rs, imm);
324d9e32 29067 break;
c2e19f3c
AM
29068 case OPC_J: /* Jump */
29069 case OPC_JAL:
7a387fff 29070 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 29071 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
c9602061 29072 break;
31837be3
YK
29073 /* Branch */
29074 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
29075 if (ctx->insn_flags & ISA_MIPS32R6) {
29076 if (rt == 0) {
9c708c7f 29077 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
29078 break;
29079 }
29080 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
29081 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29082 } else {
29083 /* OPC_BLEZL */
b231c103 29084 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
29085 }
29086 break;
29087 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
29088 if (ctx->insn_flags & ISA_MIPS32R6) {
29089 if (rt == 0) {
9c708c7f 29090 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
29091 break;
29092 }
29093 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
29094 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29095 } else {
29096 /* OPC_BGTZL */
b231c103 29097 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
29098 }
29099 break;
29100 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
29101 if (rt == 0) {
29102 /* OPC_BLEZ */
b231c103 29103 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
29104 } else {
29105 check_insn(ctx, ISA_MIPS32R6);
29106 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
29107 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29108 }
29109 break;
29110 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
29111 if (rt == 0) {
29112 /* OPC_BGTZ */
b231c103 29113 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
29114 } else {
29115 check_insn(ctx, ISA_MIPS32R6);
29116 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
29117 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29118 }
29119 break;
29120 case OPC_BEQL:
29121 case OPC_BNEL:
d9224450 29122 check_insn(ctx, ISA_MIPS2);
fecd2646 29123 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 29124 /* Fallthrough */
31837be3
YK
29125 case OPC_BEQ:
29126 case OPC_BNE:
b231c103 29127 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
c9602061 29128 break;
d9224450
MR
29129 case OPC_LL: /* Load and stores */
29130 check_insn(ctx, ISA_MIPS2);
55fc7a69
FN
29131 if (ctx->insn_flags & INSN_R5900) {
29132 check_insn_opc_user_only(ctx, INSN_R5900);
29133 }
d9224450
MR
29134 /* Fallthrough */
29135 case OPC_LWL:
fecd2646
LA
29136 case OPC_LWR:
29137 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 29138 /* Fallthrough */
c2e19f3c
AM
29139 case OPC_LB:
29140 case OPC_LH:
29141 case OPC_LW:
29142 case OPC_LWPC:
29143 case OPC_LBU:
29144 case OPC_LHU:
d75c135e 29145 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 29146 break;
fecd2646 29147 case OPC_SWL:
7a387fff 29148 case OPC_SWR:
fecd2646 29149 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 29150 /* fall through */
c2e19f3c
AM
29151 case OPC_SB:
29152 case OPC_SH:
fecd2646 29153 case OPC_SW:
5c13fdfd 29154 gen_st(ctx, op, rt, rs, imm);
7a387fff 29155 break;
d66c7132 29156 case OPC_SC:
d9224450 29157 check_insn(ctx, ISA_MIPS2);
4368b29a 29158 check_insn_opc_removed(ctx, ISA_MIPS32R6);
55fc7a69
FN
29159 if (ctx->insn_flags & INSN_R5900) {
29160 check_insn_opc_user_only(ctx, INSN_R5900);
29161 }
d66c7132
AJ
29162 gen_st_cond(ctx, op, rt, rs, imm);
29163 break;
7a387fff 29164 case OPC_CACHE:
bf7910c6 29165 check_insn_opc_removed(ctx, ISA_MIPS32R6);
2e15497c 29166 check_cp0_enabled(ctx);
d75c135e 29167 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
0d74a222
LA
29168 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
29169 gen_cache_operation(ctx, rt, rs, imm);
29170 }
ead9360e 29171 /* Treat as NOP. */
34ae7b51 29172 break;
7a387fff 29173 case OPC_PREF:
bf7910c6 29174 check_insn_opc_removed(ctx, ISA_MIPS32R6);
992e8176
FN
29175 if (ctx->insn_flags & INSN_R5900) {
29176 /* Treat as NOP. */
29177 } else {
29178 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
29179 /* Treat as NOP. */
29180 }
6af0bf9c 29181 break;
4ad40f36 29182
923617a3 29183 /* Floating point (COP1). */
7a387fff
TS
29184 case OPC_LWC1:
29185 case OPC_LDC1:
29186 case OPC_SWC1:
29187 case OPC_SDC1:
5ab5c041 29188 gen_cop1_ldst(ctx, op, rt, rs, imm);
6ea83fed
FB
29189 break;
29190
7a387fff 29191 case OPC_CP1:
5692c6e1
YK
29192 op1 = MASK_CP1(ctx->opcode);
29193
29194 switch (op1) {
29195 case OPC_MFHC1:
29196 case OPC_MTHC1:
5e755519 29197 check_cp1_enabled(ctx);
5692c6e1 29198 check_insn(ctx, ISA_MIPS32R2);
146dd620 29199 /* fall through */
5692c6e1
YK
29200 case OPC_MFC1:
29201 case OPC_CFC1:
29202 case OPC_MTC1:
29203 case OPC_CTC1:
29204 check_cp1_enabled(ctx);
29205 gen_cp1(ctx, op1, rt, rd);
29206 break;
d26bc211 29207#if defined(TARGET_MIPS64)
5692c6e1
YK
29208 case OPC_DMFC1:
29209 case OPC_DMTC1:
29210 check_cp1_enabled(ctx);
29211 check_insn(ctx, ISA_MIPS3);
d9224450 29212 check_mips_64(ctx);
5692c6e1
YK
29213 gen_cp1(ctx, op1, rt, rd);
29214 break;
e189e748 29215#endif
5692c6e1
YK
29216 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
29217 check_cp1_enabled(ctx);
29218 if (ctx->insn_flags & ISA_MIPS32R6) {
29219 /* OPC_BC1EQZ */
31837be3 29220 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 29221 rt, imm << 2, 4);
5692c6e1
YK
29222 } else {
29223 /* OPC_BC1ANY2 */
b8aa4598 29224 check_cop1x(ctx);
d75c135e 29225 check_insn(ctx, ASE_MIPS3D);
d75c135e 29226 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5a5012ec 29227 (rt >> 2) & 0x7, imm << 2);
5692c6e1
YK
29228 }
29229 break;
29230 case OPC_BC1NEZ:
29231 check_cp1_enabled(ctx);
29232 check_insn(ctx, ISA_MIPS32R6);
29233 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 29234 rt, imm << 2, 4);
5692c6e1
YK
29235 break;
29236 case OPC_BC1ANY4:
29237 check_cp1_enabled(ctx);
29238 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29239 check_cop1x(ctx);
29240 check_insn(ctx, ASE_MIPS3D);
29241 /* fall through */
29242 case OPC_BC1:
29243 check_cp1_enabled(ctx);
29244 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29245 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29246 (rt >> 2) & 0x7, imm << 2);
29247 break;
29248 case OPC_PS_FMT:
e29c9628 29249 check_ps(ctx);
b6f3b233 29250 /* fall through */
5692c6e1
YK
29251 case OPC_S_FMT:
29252 case OPC_D_FMT:
29253 check_cp1_enabled(ctx);
29254 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29255 (imm >> 8) & 0x7);
29256 break;
29257 case OPC_W_FMT:
29258 case OPC_L_FMT:
29259 {
29260 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
29261 check_cp1_enabled(ctx);
29262 if (ctx->insn_flags & ISA_MIPS32R6) {
29263 switch (r6_op) {
29264 case R6_OPC_CMP_AF_S:
29265 case R6_OPC_CMP_UN_S:
29266 case R6_OPC_CMP_EQ_S:
29267 case R6_OPC_CMP_UEQ_S:
29268 case R6_OPC_CMP_LT_S:
29269 case R6_OPC_CMP_ULT_S:
29270 case R6_OPC_CMP_LE_S:
29271 case R6_OPC_CMP_ULE_S:
29272 case R6_OPC_CMP_SAF_S:
29273 case R6_OPC_CMP_SUN_S:
29274 case R6_OPC_CMP_SEQ_S:
29275 case R6_OPC_CMP_SEUQ_S:
29276 case R6_OPC_CMP_SLT_S:
29277 case R6_OPC_CMP_SULT_S:
29278 case R6_OPC_CMP_SLE_S:
29279 case R6_OPC_CMP_SULE_S:
29280 case R6_OPC_CMP_OR_S:
29281 case R6_OPC_CMP_UNE_S:
29282 case R6_OPC_CMP_NE_S:
29283 case R6_OPC_CMP_SOR_S:
29284 case R6_OPC_CMP_SUNE_S:
29285 case R6_OPC_CMP_SNE_S:
29286 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29287 break;
29288 case R6_OPC_CMP_AF_D:
29289 case R6_OPC_CMP_UN_D:
29290 case R6_OPC_CMP_EQ_D:
29291 case R6_OPC_CMP_UEQ_D:
29292 case R6_OPC_CMP_LT_D:
29293 case R6_OPC_CMP_ULT_D:
29294 case R6_OPC_CMP_LE_D:
29295 case R6_OPC_CMP_ULE_D:
29296 case R6_OPC_CMP_SAF_D:
29297 case R6_OPC_CMP_SUN_D:
29298 case R6_OPC_CMP_SEQ_D:
29299 case R6_OPC_CMP_SEUQ_D:
29300 case R6_OPC_CMP_SLT_D:
29301 case R6_OPC_CMP_SULT_D:
29302 case R6_OPC_CMP_SLE_D:
29303 case R6_OPC_CMP_SULE_D:
29304 case R6_OPC_CMP_OR_D:
29305 case R6_OPC_CMP_UNE_D:
29306 case R6_OPC_CMP_NE_D:
29307 case R6_OPC_CMP_SOR_D:
29308 case R6_OPC_CMP_SUNE_D:
29309 case R6_OPC_CMP_SNE_D:
29310 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29311 break;
29312 default:
d2bfa6e6
MR
29313 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
29314 rt, rd, sa, (imm >> 8) & 0x7);
29315
5692c6e1 29316 break;
3f493883 29317 }
5692c6e1
YK
29318 } else {
29319 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29320 (imm >> 8) & 0x7);
36d23958 29321 }
5692c6e1
YK
29322 break;
29323 }
29324 case OPC_BZ_V:
29325 case OPC_BNZ_V:
29326 case OPC_BZ_B:
29327 case OPC_BZ_H:
29328 case OPC_BZ_W:
29329 case OPC_BZ_D:
29330 case OPC_BNZ_B:
29331 case OPC_BNZ_H:
29332 case OPC_BNZ_W:
29333 case OPC_BNZ_D:
29334 check_insn(ctx, ASE_MSA);
29335 gen_msa_branch(env, ctx, op1);
29336 break;
29337 default:
29338 MIPS_INVAL("cp1");
9c708c7f 29339 generate_exception_end(ctx, EXCP_RI);
5692c6e1 29340 break;
6ea83fed 29341 }
4ad40f36
FB
29342 break;
29343
31837be3
YK
29344 /* Compact branches [R6] and COP2 [non-R6] */
29345 case OPC_BC: /* OPC_LWC2 */
29346 case OPC_BALC: /* OPC_SWC2 */
29347 if (ctx->insn_flags & ISA_MIPS32R6) {
29348 /* OPC_BC, OPC_BALC */
29349 gen_compute_compact_branch(ctx, op, 0, 0,
29350 sextract32(ctx->opcode << 2, 0, 28));
29351 } else {
29352 /* OPC_LWC2, OPC_SWC2 */
29353 /* COP2: Not implemented. */
29354 generate_exception_err(ctx, EXCP_CpU, 2);
29355 }
29356 break;
29357 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
29358 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
29359 if (ctx->insn_flags & ISA_MIPS32R6) {
29360 if (rs != 0) {
29361 /* OPC_BEQZC, OPC_BNEZC */
29362 gen_compute_compact_branch(ctx, op, rs, 0,
29363 sextract32(ctx->opcode << 2, 0, 23));
29364 } else {
29365 /* OPC_JIC, OPC_JIALC */
29366 gen_compute_compact_branch(ctx, op, 0, rt, imm);
29367 }
29368 } else {
29369 /* OPC_LWC2, OPC_SWC2 */
29370 /* COP2: Not implemented. */
29371 generate_exception_err(ctx, EXCP_CpU, 2);
29372 }
4ad40f36 29373 break;
bd277fa1 29374 case OPC_CP2:
d75c135e 29375 check_insn(ctx, INSN_LOONGSON2F);
bd277fa1
RH
29376 /* Note that these instructions use different fields. */
29377 gen_loongson_multimedia(ctx, sa, rd, rt);
29378 break;
4ad40f36 29379
7a387fff 29380 case OPC_CP3:
fecd2646 29381 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5ab5c041 29382 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 29383 check_cp1_enabled(ctx);
36d23958
TS
29384 op1 = MASK_CP3(ctx->opcode);
29385 switch (op1) {
d9224450
MR
29386 case OPC_LUXC1:
29387 case OPC_SUXC1:
29388 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29389 /* Fallthrough */
5a5012ec
TS
29390 case OPC_LWXC1:
29391 case OPC_LDXC1:
5a5012ec
TS
29392 case OPC_SWXC1:
29393 case OPC_SDXC1:
d9224450 29394 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
93b12ccc 29395 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 29396 break;
e0c84da7 29397 case OPC_PREFX:
d9224450 29398 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
ead9360e 29399 /* Treat as NOP. */
e0c84da7 29400 break;
5a5012ec 29401 case OPC_ALNV_PS:
d9224450
MR
29402 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29403 /* Fallthrough */
5a5012ec
TS
29404 case OPC_MADD_S:
29405 case OPC_MADD_D:
29406 case OPC_MADD_PS:
29407 case OPC_MSUB_S:
29408 case OPC_MSUB_D:
29409 case OPC_MSUB_PS:
29410 case OPC_NMADD_S:
29411 case OPC_NMADD_D:
29412 case OPC_NMADD_PS:
29413 case OPC_NMSUB_S:
29414 case OPC_NMSUB_D:
29415 case OPC_NMSUB_PS:
d9224450 29416 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
5a5012ec
TS
29417 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
29418 break;
36d23958 29419 default:
923617a3 29420 MIPS_INVAL("cp3");
9c708c7f 29421 generate_exception_end(ctx, EXCP_RI);
36d23958
TS
29422 break;
29423 }
29424 } else {
e397ee33 29425 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 29426 }
4ad40f36
FB
29427 break;
29428
d26bc211 29429#if defined(TARGET_MIPS64)
7a387fff 29430 /* MIPS64 opcodes */
96631327 29431 case OPC_LLD:
55fc7a69
FN
29432 if (ctx->insn_flags & INSN_R5900) {
29433 check_insn_opc_user_only(ctx, INSN_R5900);
29434 }
96631327 29435 /* fall through */
c2e19f3c
AM
29436 case OPC_LDL:
29437 case OPC_LDR:
fecd2646 29438 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 29439 /* fall through */
fecd2646 29440 case OPC_LWU:
7a387fff 29441 case OPC_LD:
d75c135e 29442 check_insn(ctx, ISA_MIPS3);
5c13fdfd 29443 check_mips_64(ctx);
d75c135e 29444 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 29445 break;
c2e19f3c
AM
29446 case OPC_SDL:
29447 case OPC_SDR:
fecd2646 29448 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 29449 /* fall through */
7a387fff 29450 case OPC_SD:
d75c135e 29451 check_insn(ctx, ISA_MIPS3);
e189e748 29452 check_mips_64(ctx);
5c13fdfd 29453 gen_st(ctx, op, rt, rs, imm);
7a387fff 29454 break;
d66c7132 29455 case OPC_SCD:
bf7910c6 29456 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d75c135e 29457 check_insn(ctx, ISA_MIPS3);
55fc7a69
FN
29458 if (ctx->insn_flags & INSN_R5900) {
29459 check_insn_opc_user_only(ctx, INSN_R5900);
29460 }
d66c7132
AJ
29461 check_mips_64(ctx);
29462 gen_st_cond(ctx, op, rt, rs, imm);
29463 break;
31837be3
YK
29464 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
29465 if (ctx->insn_flags & ISA_MIPS32R6) {
29466 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
29467 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29468 } else {
29469 /* OPC_DADDI */
29470 check_insn(ctx, ISA_MIPS3);
29471 check_mips_64(ctx);
29472 gen_arith_imm(ctx, op, rt, rs, imm);
29473 }
29474 break;
324d9e32 29475 case OPC_DADDIU:
d75c135e 29476 check_insn(ctx, ISA_MIPS3);
e189e748 29477 check_mips_64(ctx);
d75c135e 29478 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 29479 break;
31837be3
YK
29480#else
29481 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
29482 if (ctx->insn_flags & ISA_MIPS32R6) {
29483 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29484 } else {
29485 MIPS_INVAL("major opcode");
9c708c7f 29486 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
29487 }
29488 break;
6af0bf9c 29489#endif
d4ea6acd
LA
29490 case OPC_DAUI: /* OPC_JALX */
29491 if (ctx->insn_flags & ISA_MIPS32R6) {
29492#if defined(TARGET_MIPS64)
29493 /* OPC_DAUI */
29494 check_mips_64(ctx);
db77d852
LA
29495 if (rs == 0) {
29496 generate_exception(ctx, EXCP_RI);
29497 } else if (rt != 0) {
d4ea6acd
LA
29498 TCGv t0 = tcg_temp_new();
29499 gen_load_gpr(t0, rs);
29500 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
29501 tcg_temp_free(t0);
29502 }
d4ea6acd 29503#else
9c708c7f 29504 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
29505 MIPS_INVAL("major opcode");
29506#endif
29507 } else {
29508 /* OPC_JALX */
29509 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
29510 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 29511 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
d4ea6acd 29512 }
364d4831 29513 break;
4c789546 29514 case OPC_MSA: /* OPC_MDMX */
f08099ad 29515 if (ctx->insn_flags & INSN_R5900) {
874b2879 29516 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
f08099ad
FN
29517 } else {
29518 /* MDMX: Not implemented. */
29519 gen_msa(env, ctx);
29520 }
d4ea6acd
LA
29521 break;
29522 case OPC_PCREL:
29523 check_insn(ctx, ISA_MIPS32R6);
eeb3bba8 29524 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
d4ea6acd 29525 break;
6af0bf9c 29526 default: /* Invalid */
923617a3 29527 MIPS_INVAL("major opcode");
9c708c7f 29528 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
29529 break;
29530 }
6af0bf9c
FB
29531}
29532
18f440ed 29533static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
6af0bf9c 29534{
18f440ed 29535 DisasContext *ctx = container_of(dcbase, DisasContext, base);
9c489ea6 29536 CPUMIPSState *env = cs->env_ptr;
12be9258 29537
18f440ed 29538 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
12be9258
EC
29539 ctx->saved_pc = -1;
29540 ctx->insn_flags = env->insn_flags;
29541 ctx->CP0_Config1 = env->CP0_Config1;
49735f76 29542 ctx->CP0_Config2 = env->CP0_Config2;
ab77fc61
DN
29543 ctx->CP0_Config3 = env->CP0_Config3;
29544 ctx->CP0_Config5 = env->CP0_Config5;
12be9258
EC
29545 ctx->btarget = 0;
29546 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
29547 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
29548 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
29549 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
29550 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
29551 ctx->PAMask = env->PAMask;
29552 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
29553 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
29554 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
29555 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
29556 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
4ad40f36 29557 /* Restore delay slot state from the tb context. */
12be9258
EC
29558 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
29559 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
29560 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
e29c9628 29561 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
12be9258
EC
29562 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
29563 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
29564 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
29565 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
29566 restore_cpu_state(env, ctx);
932e71cd 29567#ifdef CONFIG_USER_ONLY
12be9258 29568 ctx->mem_idx = MIPS_HFLAG_UM;
932e71cd 29569#else
12be9258 29570 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
932e71cd 29571#endif
12be9258
EC
29572 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
29573 MO_UNALN : MO_ALIGN;
190ce7fb 29574
18f440ed
EC
29575 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
29576 ctx->hflags);
29577}
12be9258 29578
18f440ed
EC
29579static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
29580{
29581}
b933066a 29582
18f440ed
EC
29583static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
29584{
29585 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 29586
18f440ed
EC
29587 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
29588 ctx->btarget);
29589}
31837be3 29590
18f440ed
EC
29591static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
29592 const CPUBreakpoint *bp)
29593{
29594 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 29595
18f440ed
EC
29596 save_cpu_state(ctx, 1);
29597 ctx->base.is_jmp = DISAS_NORETURN;
29598 gen_helper_raise_exception_debug(cpu_env);
29599 /* The address covered by the breakpoint must be included in
29600 [tb->pc, tb->pc + tb->size) in order to for it to be
29601 properly cleared -- thus we increment the PC here so that
29602 the logic setting tb->size below does the right thing. */
29603 ctx->base.pc_next += 4;
29604 return true;
29605}
4ad40f36 29606
18f440ed
EC
29607static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
29608{
29609 CPUMIPSState *env = cs->env_ptr;
29610 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29611 int insn_bytes;
29612 int is_slot;
4ad40f36 29613
18f440ed 29614 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
c533c0f4
AM
29615 if (ctx->insn_flags & ISA_NANOMIPS32) {
29616 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29617 insn_bytes = decode_nanomips_opc(env, ctx);
29618 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
18f440ed
EC
29619 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
29620 insn_bytes = 4;
29621 decode_opc(env, ctx);
29622 } else if (ctx->insn_flags & ASE_MICROMIPS) {
29623 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29624 insn_bytes = decode_micromips_opc(env, ctx);
29625 } else if (ctx->insn_flags & ASE_MIPS16) {
29626 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29627 insn_bytes = decode_mips16_opc(env, ctx);
29628 } else {
29629 generate_exception_end(ctx, EXCP_RI);
29630 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
29631 return;
29632 }
faf7aaa9 29633
18f440ed
EC
29634 if (ctx->hflags & MIPS_HFLAG_BMASK) {
29635 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
29636 MIPS_HFLAG_FBNSLOT))) {
29637 /* force to generate branch as there is neither delay nor
29638 forbidden slot */
29639 is_slot = 1;
29640 }
29641 if ((ctx->hflags & MIPS_HFLAG_M16) &&
29642 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
29643 /* Force to generate branch as microMIPS R6 doesn't restrict
29644 branches in the forbidden slot. */
29645 is_slot = 1;
eeb3bba8 29646 }
18f440ed
EC
29647 }
29648 if (is_slot) {
29649 gen_branch(ctx, insn_bytes);
29650 }
29651 ctx->base.pc_next += insn_bytes;
1b530a6d 29652
18f440ed
EC
29653 if (ctx->base.is_jmp != DISAS_NEXT) {
29654 return;
6af0bf9c 29655 }
18f440ed
EC
29656 /* Execute a branch and its delay slot as a single instruction.
29657 This is what GDB expects and is consistent with what the
29658 hardware does (e.g. if a delay slot instruction faults, the
29659 reported PC is the PC of the branch). */
29660 if (ctx->base.singlestep_enabled &&
29661 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
29662 ctx->base.is_jmp = DISAS_TOO_MANY;
29663 }
29664 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
29665 ctx->base.is_jmp = DISAS_TOO_MANY;
ed2803da 29666 }
18f440ed
EC
29667}
29668
29669static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
29670{
29671 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29672
12be9258
EC
29673 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
29674 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
9c708c7f 29675 gen_helper_raise_exception_debug(cpu_env);
16c00cb2 29676 } else {
12be9258 29677 switch (ctx->base.is_jmp) {
b28425ba 29678 case DISAS_STOP:
12be9258 29679 gen_save_pc(ctx->base.pc_next);
cd314a7d 29680 tcg_gen_lookup_and_goto_ptr();
df1561e2 29681 break;
b28425ba 29682 case DISAS_NEXT:
18f440ed 29683 case DISAS_TOO_MANY:
12be9258
EC
29684 save_cpu_state(ctx, 0);
29685 gen_goto_tb(ctx, 0, ctx->base.pc_next);
16c00cb2 29686 break;
b28425ba 29687 case DISAS_EXIT:
07ea28b4 29688 tcg_gen_exit_tb(NULL, 0);
16c00cb2 29689 break;
b28425ba 29690 case DISAS_NORETURN:
5a5012ec 29691 break;
18f440ed
EC
29692 default:
29693 g_assert_not_reached();
6958549d 29694 }
6af0bf9c 29695 }
18f440ed
EC
29696}
29697
29698static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
29699{
29700 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
29701 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
29702}
29703
29704static const TranslatorOps mips_tr_ops = {
29705 .init_disas_context = mips_tr_init_disas_context,
29706 .tb_start = mips_tr_tb_start,
29707 .insn_start = mips_tr_insn_start,
29708 .breakpoint_check = mips_tr_breakpoint_check,
29709 .translate_insn = mips_tr_translate_insn,
29710 .tb_stop = mips_tr_tb_stop,
29711 .disas_log = mips_tr_disas_log,
29712};
29713
29714void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
29715{
29716 DisasContext ctx;
29717
29718 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
6af0bf9c
FB
29719}
29720
7db13fae 29721static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
8706c382 29722 int flags)
6ea83fed
FB
29723{
29724 int i;
5e755519 29725 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 29726
2a5612e6
SW
29727#define printfpr(fp) \
29728 do { \
29729 if (is_fpu64) \
29730 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
29731 " fd:%13g fs:%13g psu: %13g\n", \
29732 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
29733 (double)(fp)->fd, \
29734 (double)(fp)->fs[FP_ENDIAN_IDX], \
29735 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
29736 else { \
29737 fpr_t tmp; \
29738 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
29739 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
29740 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
29741 " fd:%13g fs:%13g psu:%13g\n", \
29742 tmp.w[FP_ENDIAN_IDX], tmp.d, \
29743 (double)tmp.fd, \
29744 (double)tmp.fs[FP_ENDIAN_IDX], \
29745 (double)tmp.fs[!FP_ENDIAN_IDX]); \
29746 } \
6ea83fed
FB
29747 } while(0)
29748
5a5012ec 29749
9a78eead
SW
29750 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
29751 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
f01be154 29752 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
29753 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
29754 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 29755 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
29756 }
29757
29758#undef printfpr
29759}
29760
878096ee
AF
29761void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
29762 int flags)
6af0bf9c 29763{
878096ee
AF
29764 MIPSCPU *cpu = MIPS_CPU(cs);
29765 CPUMIPSState *env = &cpu->env;
6af0bf9c 29766 int i;
3b46e624 29767
a7200c9f
SW
29768 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
29769 " LO=0x" TARGET_FMT_lx " ds %04x "
29770 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
3d5be870
TS
29771 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
29772 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
29773 for (i = 0; i < 32; i++) {
29774 if ((i & 3) == 0)
29775 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 29776 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
29777 if ((i & 3) == 3)
29778 cpu_fprintf(f, "\n");
29779 }
568b600d 29780
3594c774 29781 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 29782 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
284b731a
LA
29783 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
29784 PRIx64 "\n",
5499b6ff 29785 env->CP0_Config0, env->CP0_Config1, env->lladdr);
27e1fb13
MR
29786 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
29787 env->CP0_Config2, env->CP0_Config3);
29788 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
29789 env->CP0_Config4, env->CP0_Config5);
1cc5af69 29790 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
7a387fff 29791 fpu_dump_state(env, f, cpu_fprintf, flags);
1cc5af69 29792 }
6af0bf9c
FB
29793}
29794
78ce64f4 29795void mips_tcg_init(void)
39454628 29796{
f01be154 29797 int i;
39454628 29798
f764718d 29799 cpu_gpr[0] = NULL;
bb928dbe 29800 for (i = 1; i < 32; i++)
e1ccc054 29801 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
7db13fae 29802 offsetof(CPUMIPSState, active_tc.gpr[i]),
4b2eb8d2 29803 regnames[i]);
d73ee8a2 29804
863f264d
YK
29805 for (i = 0; i < 32; i++) {
29806 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
29807 msa_wr_d[i * 2] =
e1ccc054 29808 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
cb269f27
YK
29809 /* The scalar floating-point unit (FPU) registers are mapped on
29810 * the MSA vector registers. */
29811 fpu_f64[i] = msa_wr_d[i * 2];
863f264d
YK
29812 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
29813 msa_wr_d[i * 2 + 1] =
e1ccc054 29814 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
863f264d
YK
29815 }
29816
e1ccc054 29817 cpu_PC = tcg_global_mem_new(cpu_env,
7db13fae 29818 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 29819 for (i = 0; i < MIPS_DSP_ACC; i++) {
e1ccc054 29820 cpu_HI[i] = tcg_global_mem_new(cpu_env,
7db13fae 29821 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 29822 regnames_HI[i]);
e1ccc054 29823 cpu_LO[i] = tcg_global_mem_new(cpu_env,
7db13fae 29824 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 29825 regnames_LO[i]);
4b2eb8d2 29826 }
e1ccc054 29827 cpu_dspctrl = tcg_global_mem_new(cpu_env,
7db13fae 29828 offsetof(CPUMIPSState, active_tc.DSPControl),
4b2eb8d2 29829 "DSPControl");
e1ccc054 29830 bcond = tcg_global_mem_new(cpu_env,
7db13fae 29831 offsetof(CPUMIPSState, bcond), "bcond");
e1ccc054 29832 btarget = tcg_global_mem_new(cpu_env,
7db13fae 29833 offsetof(CPUMIPSState, btarget), "btarget");
e1ccc054 29834 hflags = tcg_global_mem_new_i32(cpu_env,
7db13fae 29835 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 29836
e1ccc054 29837 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
7db13fae 29838 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4 29839 "fcr0");
e1ccc054 29840 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
7db13fae 29841 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 29842 "fcr31");
a168a796
FN
29843
29844#if defined(TARGET_MIPS64)
29845 cpu_mmr[0] = NULL;
29846 for (i = 1; i < 32; i++) {
29847 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
29848 offsetof(CPUMIPSState,
29849 active_tc.mmr[i]),
29850 regnames[i]);
29851 }
29852#endif
29853
b621f018 29854#if !defined(TARGET_MIPS64)
eb5559f6
CJ
29855 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
29856 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
29857 offsetof(CPUMIPSState,
29858 active_tc.mxu_gpr[i]),
29859 mxuregnames[i]);
29860 }
29861
29862 mxu_CR = tcg_global_mem_new(cpu_env,
29863 offsetof(CPUMIPSState, active_tc.mxu_cr),
29864 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
b621f018 29865#endif
39454628
TS
29866}
29867
5b27a92d 29868#include "translate_init.inc.c"
aaed909a 29869
27e38392
PMD
29870void cpu_mips_realize_env(CPUMIPSState *env)
29871{
29872 env->exception_base = (int32_t)0xBFC00000;
29873
29874#ifndef CONFIG_USER_ONLY
29875 mmu_init(env, env->cpu_model);
29876#endif
29877 fpu_init(env, env->cpu_model);
29878 mvp_init(env, env->cpu_model);
29879}
29880
a7519f2b 29881bool cpu_supports_cps_smp(const char *cpu_type)
bff384a4 29882{
a7519f2b
IM
29883 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
29884 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
bff384a4
LA
29885}
29886
a7519f2b 29887bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
bed9e5ce 29888{
a7519f2b
IM
29889 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
29890 return (mcc->cpu_def->insn_flags & isa) != 0;
bed9e5ce
PB
29891}
29892
89777fd1
LA
29893void cpu_set_exception_base(int vp_index, target_ulong address)
29894{
29895 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
29896 vp->env.exception_base = address;
29897}
29898
1bba0dc9 29899void cpu_state_reset(CPUMIPSState *env)
6ae81775 29900{
55e5c285
AF
29901 MIPSCPU *cpu = mips_env_get_cpu(env);
29902 CPUState *cs = CPU(cpu);
6ae81775 29903
51cc2e78
BS
29904 /* Reset registers to their default values */
29905 env->CP0_PRid = env->cpu_model->CP0_PRid;
29906 env->CP0_Config0 = env->cpu_model->CP0_Config0;
29907#ifdef TARGET_WORDS_BIGENDIAN
29908 env->CP0_Config0 |= (1 << CP0C0_BE);
29909#endif
29910 env->CP0_Config1 = env->cpu_model->CP0_Config1;
29911 env->CP0_Config2 = env->cpu_model->CP0_Config2;
29912 env->CP0_Config3 = env->cpu_model->CP0_Config3;
b4160af1
PJ
29913 env->CP0_Config4 = env->cpu_model->CP0_Config4;
29914 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
b4dd99a3
PJ
29915 env->CP0_Config5 = env->cpu_model->CP0_Config5;
29916 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
51cc2e78
BS
29917 env->CP0_Config6 = env->cpu_model->CP0_Config6;
29918 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
29919 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
29920 << env->cpu_model->CP0_LLAddr_shift;
29921 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
29922 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
29923 env->CCRes = env->cpu_model->CCRes;
29924 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
29925 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
29926 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
29927 env->current_tc = 0;
29928 env->SEGBITS = env->cpu_model->SEGBITS;
29929 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
29930#if defined(TARGET_MIPS64)
29931 if (env->cpu_model->insn_flags & ISA_MIPS3) {
29932 env->SEGMask |= 3ULL << 62;
29933 }
29934#endif
29935 env->PABITS = env->cpu_model->PABITS;
51cc2e78
BS
29936 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
29937 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
29938 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
29939 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
29940 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
29941 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
29942 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
29943 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
29944 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
29945 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
7207c7f9
LA
29946 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
29947 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
74dbf824 29948 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
f1cb0951 29949 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
599bc5e8 29950 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
ba5c79f2 29951 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
863f264d 29952 env->msair = env->cpu_model->MSAIR;
51cc2e78
BS
29953 env->insn_flags = env->cpu_model->insn_flags;
29954
0eaef5aa 29955#if defined(CONFIG_USER_ONLY)
03e6e501 29956 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
68473f15
RH
29957# ifdef TARGET_MIPS64
29958 /* Enable 64-bit register mode. */
29959 env->CP0_Status |= (1 << CP0St_PX);
29960# endif
29961# ifdef TARGET_ABI_MIPSN64
29962 /* Enable 64-bit address mode. */
29963 env->CP0_Status |= (1 << CP0St_UX);
29964# endif
94159135
MI
29965 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
29966 hardware registers. */
29967 env->CP0_HWREna |= 0x0000000F;
91a75935 29968 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
03e6e501 29969 env->CP0_Status |= (1 << CP0St_CU1);
91a75935 29970 }
6f0af304
PJ
29971 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
29972 env->CP0_Status |= (1 << CP0St_MX);
853c3240 29973 }
4d66261f
PJ
29974# if defined(TARGET_MIPS64)
29975 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
29976 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
29977 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
68473f15
RH
29978 env->CP0_Status |= (1 << CP0St_FR);
29979 }
4d66261f 29980# endif
932e71cd
AJ
29981#else
29982 if (env->hflags & MIPS_HFLAG_BMASK) {
29983 /* If the exception was raised from a delay slot,
29984 come back to the jump. */
c3577479
MR
29985 env->CP0_ErrorEPC = (env->active_tc.PC
29986 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
aa328add 29987 } else {
932e71cd
AJ
29988 env->CP0_ErrorEPC = env->active_tc.PC;
29989 }
89777fd1 29990 env->active_tc.PC = env->exception_base;
51cc2e78
BS
29991 env->CP0_Random = env->tlb->nb_tlb - 1;
29992 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd 29993 env->CP0_Wired = 0;
01bc435b 29994 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
0a2672b7 29995 env->CP0_EBase = (cs->cpu_index & 0x3FF);
d3d93c6c 29996 if (mips_um_ksegs_enabled()) {
0a2672b7
JH
29997 env->CP0_EBase |= 0x40000000;
29998 } else {
74dbf824 29999 env->CP0_EBase |= (int32_t)0x80000000;
0a2672b7 30000 }
c870e3f5
YK
30001 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
30002 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
30003 }
a0c80608
PB
30004 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
30005 0x3ff : 0xff;
932e71cd
AJ
30006 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
30007 /* vectored interrupts not implemented, timer on int 7,
30008 no performance counters. */
30009 env->CP0_IntCtl = 0xe0000000;
30010 {
30011 int i;
30012
30013 for (i = 0; i < 7; i++) {
30014 env->CP0_WatchLo[i] = 0;
30015 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 30016 }
932e71cd
AJ
30017 env->CP0_WatchLo[7] = 0;
30018 env->CP0_WatchHi[7] = 0;
fd88b6ab 30019 }
932e71cd
AJ
30020 /* Count register increments in debug mode, EJTAG version 1 */
30021 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9e56e756 30022
4b69c7e2
JH
30023 cpu_mips_store_count(env, 1);
30024
9e56e756
EI
30025 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
30026 int i;
30027
30028 /* Only TC0 on VPE 0 starts as active. */
30029 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
55e5c285 30030 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
9e56e756
EI
30031 env->tcs[i].CP0_TCHalt = 1;
30032 }
30033 env->active_tc.CP0_TCHalt = 1;
259186a7 30034 cs->halted = 1;
9e56e756 30035
55e5c285 30036 if (cs->cpu_index == 0) {
9e56e756
EI
30037 /* VPE0 starts up enabled. */
30038 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
30039 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
30040
30041 /* TC0 starts up unhalted. */
259186a7 30042 cs->halted = 0;
9e56e756
EI
30043 env->active_tc.CP0_TCHalt = 0;
30044 env->tcs[0].CP0_TCHalt = 0;
30045 /* With thread 0 active. */
30046 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
30047 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
30048 }
30049 }
cec56a73
JH
30050
30051 /*
30052 * Configure default legacy segmentation control. We use this regardless of
30053 * whether segmentation control is presented to the guest.
30054 */
30055 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
30056 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
30057 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
30058 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
30059 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
30060 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30061 (2 << CP0SC_C);
30062 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
30063 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30064 (3 << CP0SC_C)) << 16;
30065 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
30066 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30067 (1 << CP0SC_EU) | (2 << CP0SC_C);
30068 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
30069 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30070 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
30071 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
30072 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
51cc2e78 30073#endif
ddc584bd
LA
30074 if ((env->insn_flags & ISA_MIPS32R6) &&
30075 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
30076 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
30077 env->CP0_Status |= (1 << CP0St_FR);
30078 }
30079
63010795
YK
30080 if (env->insn_flags & ISA_MIPS32R6) {
30081 /* PTW = 1 */
30082 env->CP0_PWSize = 0x40;
30083 /* GDI = 12 */
30084 /* UDI = 12 */
30085 /* MDI = 12 */
30086 /* PRI = 12 */
30087 /* PTEI = 2 */
30088 env->CP0_PWField = 0x0C30C302;
30089 } else {
30090 /* GDI = 0 */
30091 /* UDI = 0 */
30092 /* MDI = 0 */
30093 /* PRI = 0 */
30094 /* PTEI = 2 */
30095 env->CP0_PWField = 0x02;
30096 }
30097
0bbc0396
SM
30098 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
30099 /* microMIPS on reset when Config3.ISA is 3 */
0305d194
YK
30100 env->hflags |= MIPS_HFLAG_M16;
30101 }
30102
863f264d
YK
30103 /* MSA */
30104 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
30105 msa_reset(env);
30106 }
30107
03e6e501 30108 compute_hflags(env);
599bc5e8 30109 restore_fp_status(env);
e117f526 30110 restore_pamask(env);
27103424 30111 cs->exception_index = EXCP_NONE;
3b3c1694
LA
30112
30113 if (semihosting_get_argc()) {
30114 /* UHI interface can be used to obtain argc and argv */
30115 env->active_tc.gpr[4] = -1;
30116 }
6af0bf9c 30117}
d2856f1a 30118
bad729e2
RH
30119void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
30120 target_ulong *data)
d2856f1a 30121{
bad729e2 30122 env->active_tc.PC = data[0];
d2856f1a 30123 env->hflags &= ~MIPS_HFLAG_BMASK;
bad729e2 30124 env->hflags |= data[1];
4636401d
AJ
30125 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
30126 case MIPS_HFLAG_BR:
30127 break;
30128 case MIPS_HFLAG_BC:
30129 case MIPS_HFLAG_BL:
30130 case MIPS_HFLAG_B:
bad729e2 30131 env->btarget = data[2];
4636401d
AJ
30132 break;
30133 }
d2856f1a 30134}
This page took 6.618552 seconds and 4 git commands to generate.