]> git.proxmox.com Git - mirror_qemu.git/blame - target/mips/translate.c
target/mips: Add two missing breaks for NM_LLWPE and NM_SCWPE decoder cases
[mirror_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/*
1402 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1403 * ============================================
1404 *
1405 * MXU (full name: MIPS eXtension/enhanced Unit) is an SIMD extension of MIPS32
1406 * instructions set. It is designed to fit the needs of signal, graphical and
1407 * video processing applications. MXU instruction set is used in Xburst family
1408 * of microprocessors by Ingenic.
1409 *
1410 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1411 * the control register.
1412 *
1d0e663c
AM
1413 * The notation used in MXU assembler mnemonics:
1414 *
1415 * XRa, XRb, XRc, XRd - MXU registers
1416 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1417 * s12 - a subfield of an instruction code
1418 * strd2 - a subfield of an instruction code
1419 * eptn2 - a subfield of an instruction code
1420 * eptn3 - a subfield of an instruction code
1421 * optn2 - a subfield of an instruction code
1422 * optn3 - a subfield of an instruction code
1423 * sft4 - a subfield of an instruction code
1424 *
1425 * Load/Store instructions Multiplication instructions
1426 * ----------------------- ---------------------------
1427 *
1428 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1429 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1430 * S32LDDV XRa, Rb, rc, strd2 S32SUB XRa, XRd, Rs, Rt
1431 * S32STDV XRa, Rb, rc, strd2 S32SUBU XRa, XRd, Rs, Rt
1432 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1433 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1434 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1435 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1436 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1437 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1438 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1439 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1440 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1441 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1442 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1443 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1444 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1445 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1446 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1447 * S16SDI XRa, Rb, s10, eptn2
1448 * S8LDD XRa, Rb, s8, eptn3
1449 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1450 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1451 * S8SDI XRa, Rb, s8, eptn3
1452 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1453 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1454 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1455 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1456 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1457 * S32CPS XRa, XRb, XRc
1458 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1459 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1460 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1461 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1462 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1463 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1464 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1465 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1466 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1467 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1468 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1469 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1470 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1471 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1472 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1473 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1474 * Q8SLT XRa, XRb, XRc
1475 * Q8SLTU XRa, XRb, XRc
1476 * Q8MOVZ XRa, XRb, XRc Shift instructions
1477 * Q8MOVN XRa, XRb, XRc ------------------
1478 *
1479 * D32SLL XRa, XRb, XRc, XRd, sft4
1480 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1481 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1482 * D32SARL XRa, XRb, XRc, sft4
1483 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1484 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1485 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1486 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1487 * Q16SLL XRa, XRb, XRc, XRd, sft4
1488 * Q16SLR XRa, XRb, XRc, XRd, sft4
1489 * Miscelaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1490 * ------------------------- Q16SLLV XRa, XRb, Rb
1491 * Q16SLRV XRa, XRb, Rb
1492 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1493 * S32ALN XRa, XRb, XRc, Rb
1494 * S32ALNI XRa, XRb, XRc, s3
1495 * S32LUI XRa, s8, optn3 Move instructions
1496 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1497 * S32EXTRV XRa, XRb, Rs, Rt
1498 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1499 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1500 *
9ef5bff9
AM
1501 *
1502 * bits
1503 * 05..00
1504 *
1505 * ┌─ 000000 ─ OPC_MXU_S32MADD
1506 * ├─ 000001 ─ OPC_MXU_S32MADDU
1507 * ├─ 000010 ─ <not assigned>
1508 * │ 20..18
1509 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1510 * │ ├─ 001 ─ OPC_MXU_S32MIN
1511 * │ ├─ 010 ─ OPC_MXU_D16MAX
1512 * │ ├─ 011 ─ OPC_MXU_D16MIN
1513 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1514 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1515 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1516 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1517 * ├─ 000100 ─ OPC_MXU_S32MSUB
1518 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1519 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1520 * │ ├─ 001 ─ OPC_MXU_D16SLT
1521 * │ ├─ 010 ─ OPC_MXU_D16AVG
1522 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1523 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1524 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1525 * │ └─ 111 ─ OPC_MXU_Q8ADD
1526 * │
1527 * │ 20..18
1528 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1529 * │ ├─ 010 ─ OPC_MXU_D16CPS
1530 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1531 * │ └─ 110 ─ OPC_MXU_Q16SAT
1532 * ├─ 001000 ─ OPC_MXU_D16MUL
1533 * │ 25..24
1534 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1535 * │ └─ 01 ─ OPC_MXU_D16MULE
1536 * ├─ 001010 ─ OPC_MXU_D16MAC
1537 * ├─ 001011 ─ OPC_MXU_D16MACF
1538 * ├─ 001100 ─ OPC_MXU_D16MADL
1539 * │ 25..24
1540 * ├─ 001101 ─ OPC_MXU__POOL04 ─┬─ 00 ─ OPC_MXU_S16MAD
1541 * │ └─ 01 ─ OPC_MXU_S16MAD_1
1542 * ├─ 001110 ─ OPC_MXU_Q16ADD
1543 * ├─ 001111 ─ OPC_MXU_D16MACE
1544 * │ 23
1545 * ├─ 010000 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32LDD
1546 * │ └─ 1 ─ OPC_MXU_S32LDDR
1547 * │
1548 * │ 23
1549 * ├─ 010001 ─ OPC_MXU__POOL06 ─┬─ 0 ─ OPC_MXU_S32STD
1550 * │ └─ 1 ─ OPC_MXU_S32STDR
1551 * │
1552 * │ 13..10
1553 * ├─ 010010 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1554 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1555 * │
1556 * │ 13..10
1557 * ├─ 010011 ─ OPC_MXU__POOL08 ─┬─ 0000 ─ OPC_MXU_S32STDV
1558 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1559 * │
1560 * │ 23
1561 * ├─ 010100 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32LDI
1562 * │ └─ 1 ─ OPC_MXU_S32LDIR
1563 * │
1564 * │ 23
1565 * ├─ 010101 ─ OPC_MXU__POOL10 ─┬─ 0 ─ OPC_MXU_S32SDI
1566 * │ └─ 1 ─ OPC_MXU_S32SDIR
1567 * │
1568 * │ 13..10
1569 * ├─ 010110 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1570 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1571 * │
1572 * │ 13..10
1573 * ├─ 010111 ─ OPC_MXU__POOL12 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1574 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1575 * ├─ 011000 ─ OPC_MXU_D32ADD
1576 * │ 23..22
1577 * MXU ├─ 011001 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_D32ACC
1578 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1579 * │ └─ 10 ─ OPC_MXU_D32ASUM
1580 * ├─ 011010 ─ <not assigned>
1581 * │ 23..22
1582 * ├─ 011011 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q16ACC
1583 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1584 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1585 * │
1586 * │ 23..22
1587 * ├─ 011100 ─ OPC_MXU__POOL15 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1588 * │ ├─ 01 ─ OPC_MXU_D8SUM
1589 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1590 * ├─ 011110 ─ <not assigned>
1591 * ├─ 011111 ─ <not assigned>
1592 * ├─ 100000 ─ <not assigned>
1593 * ├─ 100001 ─ <not assigned>
1594 * ├─ 100010 ─ OPC_MXU_S8LDD
1595 * ├─ 100011 ─ OPC_MXU_S8STD
1596 * ├─ 100100 ─ OPC_MXU_S8LDI
1597 * ├─ 100101 ─ OPC_MXU_S8SDI
1598 * │ 15..14
1599 * ├─ 100110 ─ OPC_MXU__POOL16 ─┬─ 00 ─ OPC_MXU_S32MUL
1600 * │ ├─ 00 ─ OPC_MXU_S32MULU
1601 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1602 * │ └─ 00 ─ OPC_MXU_S32EXTRV
1603 * │
1604 * │ 20..18
1605 * ├─ 100111 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_D32SARW
1606 * │ ├─ 001 ─ OPC_MXU_S32ALN
1607 * ├─ 101000 ─ OPC_MXU_LXB ├─ 010 ─ OPC_MXU_S32ALNI
1608 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_S32NOR
1609 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_S32AND
1610 * ├─ 101011 ─ OPC_MXU_S16STD ├─ 101 ─ OPC_MXU_S32OR
1611 * ├─ 101100 ─ OPC_MXU_S16LDI ├─ 110 ─ OPC_MXU_S32XOR
1612 * ├─ 101101 ─ OPC_MXU_S16SDI └─ 111 ─ OPC_MXU_S32LUI
1613 * ├─ 101000 ─ <not assigned>
1614 * ├─ 101001 ─ <not assigned>
1615 * ├─ 101010 ─ <not assigned>
1616 * ├─ 101011 ─ <not assigned>
1617 * ├─ 101100 ─ <not assigned>
1618 * ├─ 101101 ─ <not assigned>
1619 * ├─ 101110 ─ OPC_MXU_S32M2I
1620 * ├─ 101111 ─ OPC_MXU_S32I2M
1621 * ├─ 110000 ─ OPC_MXU_D32SLL
1622 * ├─ 110001 ─ OPC_MXU_D32SLR
1623 * ├─ 110010 ─ OPC_MXU_D32SARL
1624 * ├─ 110011 ─ OPC_MXU_D32SAR
1625 * ├─ 110100 ─ OPC_MXU_Q16SLL
1626 * ├─ 110101 ─ OPC_MXU_Q16SLR 20..18
1627 * ├─ 110110 ─ OPC_MXU__POOL18 ─┬─ 000 ─ OPC_MXU_D32SLLV
1628 * │ ├─ 001 ─ OPC_MXU_D32SLRV
1629 * │ ├─ 010 ─ OPC_MXU_D32SARV
1630 * │ ├─ 011 ─ OPC_MXU_Q16SLLV
1631 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1632 * │ └─ 101 ─ OPC_MXU_Q16SARV
1633 * ├─ 110111 ─ OPC_MXU_Q16SAR
1634 * │ 23..22
1635 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1636 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1637 * │
1638 * │ 20..18
1639 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1640 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1641 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1642 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1643 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1644 * │ └─ 101 ─ OPC_MXU_S32MOV
1645 * │
1646 * │ 23..22
1647 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1648 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1649 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1650 * ├─ 111100 ─ OPC_MXU_Q8MADL
1651 * ├─ 111101 ─ OPC_MXU_S32SFL
1652 * ├─ 111110 ─ OPC_MXU_Q8SAD
1653 * └─ 111111 ─ <not assigned>
1654 *
1655 *
b158d449
AM
1656 * Compiled after:
1657 *
1658 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1659 * Programming Manual", Ingenic Semiconductor Co, Ltd., 2017
1660 */
1661
8bacd1ff
AM
1662enum {
1663 OPC_MXU_S32MADD = 0x00,
1664 OPC_MXU_S32MADDU = 0x01,
1665 /* not assigned 0x02 */
1666 OPC_MXU__POOL00 = 0x03,
1667 OPC_MXU_S32MSUB = 0x04,
1668 OPC_MXU_S32MSUBU = 0x05,
1669 OPC_MXU__POOL01 = 0x06,
1670 OPC_MXU__POOL02 = 0x07,
1671 OPC_MXU_D16MUL = 0x08,
1672 OPC_MXU__POOL03 = 0x09,
1673 OPC_MXU_D16MAC = 0x0A,
1674 OPC_MXU_D16MACF = 0x0B,
1675 OPC_MXU_D16MADL = 0x0C,
1676 OPC_MXU__POOL04 = 0x0D,
1677 OPC_MXU_Q16ADD = 0x0E,
1678 OPC_MXU_D16MACE = 0x0F,
1679 OPC_MXU__POOL05 = 0x10,
1680 OPC_MXU__POOL06 = 0x11,
1681 OPC_MXU__POOL07 = 0x12,
1682 OPC_MXU__POOL08 = 0x13,
1683 OPC_MXU__POOL09 = 0x14,
1684 OPC_MXU__POOL10 = 0x15,
1685 OPC_MXU__POOL11 = 0x16,
1686 OPC_MXU__POOL12 = 0x17,
1687 OPC_MXU_D32ADD = 0x18,
1688 OPC_MXU__POOL13 = 0x19,
1689 /* not assigned 0x1A */
1690 OPC_MXU__POOL14 = 0x1B,
1691 OPC_MXU__POOL15 = 0x1C,
1692 OPC_MXU_Q8ACCE = 0x1D,
1693 /* not assigned 0x1E */
1694 /* not assigned 0x1F */
1695 /* not assigned 0x20 */
1696 /* not assigned 0x21 */
1697 OPC_MXU_S8LDD = 0x22,
1698 OPC_MXU_S8STD = 0x23,
1699 OPC_MXU_S8LDI = 0x24,
1700 OPC_MXU_S8SDI = 0x25,
1701 OPC_MXU__POOL16 = 0x26,
1702 OPC_MXU__POOL17 = 0x27,
1703 OPC_MXU_LXB = 0x28,
1704 /* not assigned 0x29 */
1705 OPC_MXU_S16LDD = 0x2A,
1706 OPC_MXU_S16STD = 0x2B,
1707 OPC_MXU_S16LDI = 0x2C,
1708 OPC_MXU_S16SDI = 0x2D,
1709 OPC_MXU_S32M2I = 0x2E,
1710 OPC_MXU_S32I2M = 0x2F,
1711 OPC_MXU_D32SLL = 0x30,
1712 OPC_MXU_D32SLR = 0x31,
1713 OPC_MXU_D32SARL = 0x32,
1714 OPC_MXU_D32SAR = 0x33,
1715 OPC_MXU_Q16SLL = 0x34,
1716 OPC_MXU_Q16SLR = 0x35,
1717 OPC_MXU__POOL18 = 0x36,
1718 OPC_MXU_Q16SAR = 0x37,
1719 OPC_MXU__POOL19 = 0x38,
1720 OPC_MXU__POOL20 = 0x39,
1721 OPC_MXU__POOL21 = 0x3A,
1722 OPC_MXU_Q16SCOP = 0x3B,
1723 OPC_MXU_Q8MADL = 0x3C,
1724 OPC_MXU_S32SFL = 0x3D,
1725 OPC_MXU_Q8SAD = 0x3E,
1726 /* not assigned 0x3F */
1727};
1728
1729
1730/*
1731 * MXU pool 00
1732 */
1733enum {
1734 OPC_MXU_S32MAX = 0x00,
1735 OPC_MXU_S32MIN = 0x01,
1736 OPC_MXU_D16MAX = 0x02,
1737 OPC_MXU_D16MIN = 0x03,
1738 OPC_MXU_Q8MAX = 0x04,
1739 OPC_MXU_Q8MIN = 0x05,
1740 OPC_MXU_Q8SLT = 0x06,
1741 OPC_MXU_Q8SLTU = 0x07,
1742};
1743
1744/*
1745 * MXU pool 01
1746 */
1747enum {
1748 OPC_MXU_S32SLT = 0x00,
1749 OPC_MXU_D16SLT = 0x01,
1750 OPC_MXU_D16AVG = 0x02,
1751 OPC_MXU_D16AVGR = 0x03,
1752 OPC_MXU_Q8AVG = 0x04,
1753 OPC_MXU_Q8AVGR = 0x05,
1754 OPC_MXU_Q8ADD = 0x07,
1755};
1756
1757/*
1758 * MXU pool 02
1759 */
1760enum {
1761 OPC_MXU_S32CPS = 0x00,
1762 OPC_MXU_D16CPS = 0x02,
1763 OPC_MXU_Q8ABD = 0x04,
1764 OPC_MXU_Q16SAT = 0x06,
1765};
1766
1767/*
1768 * MXU pool 03
1769 */
1770enum {
1771 OPC_MXU_D16MULF = 0x00,
1772 OPC_MXU_D16MULE = 0x01,
1773};
1774
1775/*
1776 * MXU pool 04
1777 */
1778enum {
1779 OPC_MXU_S16MAD = 0x00,
1780 OPC_MXU_S16MAD_1 = 0x01,
1781};
1782
1783/*
1784 * MXU pool 05
1785 */
1786enum {
1787 OPC_MXU_S32LDD = 0x00,
1788 OPC_MXU_S32LDDR = 0x01,
1789};
1790
1791/*
1792 * MXU pool 06
1793 */
1794enum {
1795 OPC_MXU_S32STD = 0x00,
1796 OPC_MXU_S32STDR = 0x01,
1797};
1798
1799/*
1800 * MXU pool 07
1801 */
1802enum {
1803 OPC_MXU_S32LDDV = 0x00,
1804 OPC_MXU_S32LDDVR = 0x01,
1805};
1806
1807/*
1808 * MXU pool 08
1809 */
1810enum {
1811 OPC_MXU_S32STDV = 0x00,
1812 OPC_MXU_S32STDVR = 0x01,
1813};
1814
1815/*
1816 * MXU pool 09
1817 */
1818enum {
1819 OPC_MXU_S32LDI = 0x00,
1820 OPC_MXU_S32LDIR = 0x01,
1821};
1822
1823/*
1824 * MXU pool 10
1825 */
1826enum {
1827 OPC_MXU_S32SDI = 0x00,
1828 OPC_MXU_S32SDIR = 0x01,
1829};
1830
1831/*
1832 * MXU pool 11
1833 */
1834enum {
1835 OPC_MXU_S32LDIV = 0x00,
1836 OPC_MXU_S32LDIVR = 0x01,
1837};
1838
1839/*
1840 * MXU pool 12
1841 */
1842enum {
1843 OPC_MXU_S32SDIV = 0x00,
1844 OPC_MXU_S32SDIVR = 0x01,
1845};
1846
1847/*
1848 * MXU pool 13
1849 */
1850enum {
1851 OPC_MXU_D32ACC = 0x00,
1852 OPC_MXU_D32ACCM = 0x01,
1853 OPC_MXU_D32ASUM = 0x02,
1854};
1855
1856/*
1857 * MXU pool 14
1858 */
1859enum {
1860 OPC_MXU_Q16ACC = 0x00,
1861 OPC_MXU_Q16ACCM = 0x01,
1862 OPC_MXU_Q16ASUM = 0x02,
1863};
1864
1865/*
1866 * MXU pool 15
1867 */
1868enum {
1869 OPC_MXU_Q8ADDE = 0x00,
1870 OPC_MXU_D8SUM = 0x01,
1871 OPC_MXU_D8SUMC = 0x02,
1872};
1873
1874/*
1875 * MXU pool 16
1876 */
1877enum {
1878 OPC_MXU_S32MUL = 0x00,
1879 OPC_MXU_S32MULU = 0x01,
1880 OPC_MXU_S32EXTR = 0x02,
1881 OPC_MXU_S32EXTRV = 0x03,
1882};
1883
1884/*
1885 * MXU pool 17
1886 */
1887enum {
1888 OPC_MXU_D32SARW = 0x00,
1889 OPC_MXU_S32ALN = 0x01,
1890 OPC_MXU_S32ALNI = 0x02,
1891 OPC_MXU_S32NOR = 0x03,
1892 OPC_MXU_S32AND = 0x04,
1893 OPC_MXU_S32OR = 0x05,
1894 OPC_MXU_S32XOR = 0x06,
1895 OPC_MXU_S32LUI = 0x07,
1896};
1897
1898/*
1899 * MXU pool 18
1900 */
1901enum {
1902 OPC_MXU_D32SLLV = 0x00,
1903 OPC_MXU_D32SLRV = 0x01,
1904 OPC_MXU_D32SARV = 0x03,
1905 OPC_MXU_Q16SLLV = 0x04,
1906 OPC_MXU_Q16SLRV = 0x05,
1907 OPC_MXU_Q16SARV = 0x07,
1908};
1909
1910/*
1911 * MXU pool 19
1912 */
1913enum {
1914 OPC_MXU_Q8MUL = 0x00,
1915 OPC_MXU_Q8MULSU = 0x01,
1916};
1917
1918/*
1919 * MXU pool 20
1920 */
1921enum {
1922 OPC_MXU_Q8MOVZ = 0x00,
1923 OPC_MXU_Q8MOVN = 0x01,
1924 OPC_MXU_D16MOVZ = 0x02,
1925 OPC_MXU_D16MOVN = 0x03,
1926 OPC_MXU_S32MOVZ = 0x04,
1927 OPC_MXU_S32MOVN = 0x05,
1928};
1929
1930/*
1931 * MXU pool 21
1932 */
1933enum {
1934 OPC_MXU_Q8MAC = 0x00,
1935 OPC_MXU_Q8MACSU = 0x01,
1936};
1937
497f072b
FN
1938/*
1939 * Overview of the TX79-specific instruction set
1940 * =============================================
1941 *
1942 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
1943 * are only used by the specific quadword (128-bit) LQ/SQ load/store
1944 * instructions and certain multimedia instructions (MMIs). These MMIs
1945 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
1946 * or sixteen 8-bit paths.
1947 *
1948 * Reference:
1949 *
1950 * The Toshiba TX System RISC TX79 Core Architecture manual,
1951 * https://wiki.qemu.org/File:C790.pdf
1952 *
1953 * Three-Operand Multiply and Multiply-Add (4 instructions)
1954 * --------------------------------------------------------
1955 * MADD [rd,] rs, rt Multiply/Add
1956 * MADDU [rd,] rs, rt Multiply/Add Unsigned
1957 * MULT [rd,] rs, rt Multiply (3-operand)
1958 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
1959 *
1960 * Multiply Instructions for Pipeline 1 (10 instructions)
1961 * ------------------------------------------------------
1962 * MULT1 [rd,] rs, rt Multiply Pipeline 1
1963 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
1964 * DIV1 rs, rt Divide Pipeline 1
1965 * DIVU1 rs, rt Divide Unsigned Pipeline 1
1966 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
1967 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
1968 * MFHI1 rd Move From HI1 Register
1969 * MFLO1 rd Move From LO1 Register
1970 * MTHI1 rs Move To HI1 Register
1971 * MTLO1 rs Move To LO1 Register
1972 *
1973 * Arithmetic (19 instructions)
1974 * ----------------------------
1975 * PADDB rd, rs, rt Parallel Add Byte
1976 * PSUBB rd, rs, rt Parallel Subtract Byte
1977 * PADDH rd, rs, rt Parallel Add Halfword
1978 * PSUBH rd, rs, rt Parallel Subtract Halfword
1979 * PADDW rd, rs, rt Parallel Add Word
1980 * PSUBW rd, rs, rt Parallel Subtract Word
1981 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
1982 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
1983 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
1984 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
1985 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
1986 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
1987 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
1988 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
1989 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
1990 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
1991 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
1992 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
1993 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
1994 *
1995 * Min/Max (4 instructions)
1996 * ------------------------
1997 * PMAXH rd, rs, rt Parallel Maximum Halfword
1998 * PMINH rd, rs, rt Parallel Minimum Halfword
1999 * PMAXW rd, rs, rt Parallel Maximum Word
2000 * PMINW rd, rs, rt Parallel Minimum Word
2001 *
2002 * Absolute (2 instructions)
2003 * -------------------------
2004 * PABSH rd, rt Parallel Absolute Halfword
2005 * PABSW rd, rt Parallel Absolute Word
2006 *
2007 * Logical (4 instructions)
2008 * ------------------------
2009 * PAND rd, rs, rt Parallel AND
2010 * POR rd, rs, rt Parallel OR
2011 * PXOR rd, rs, rt Parallel XOR
2012 * PNOR rd, rs, rt Parallel NOR
2013 *
2014 * Shift (9 instructions)
2015 * ----------------------
2016 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2017 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2018 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2019 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2020 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2021 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2022 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2023 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2024 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2025 *
2026 * Compare (6 instructions)
2027 * ------------------------
2028 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2029 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2030 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2031 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2032 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2033 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2034 *
2035 * LZC (1 instruction)
2036 * -------------------
2037 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2038 *
2039 * Quadword Load and Store (2 instructions)
2040 * ----------------------------------------
2041 * LQ rt, offset(base) Load Quadword
2042 * SQ rt, offset(base) Store Quadword
2043 *
2044 * Multiply and Divide (19 instructions)
2045 * -------------------------------------
2046 * PMULTW rd, rs, rt Parallel Multiply Word
2047 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2048 * PDIVW rs, rt Parallel Divide Word
2049 * PDIVUW rs, rt Parallel Divide Unsigned Word
2050 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2051 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2052 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2053 * PMULTH rd, rs, rt Parallel Multiply Halfword
2054 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2055 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2056 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2057 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2058 * PDIVBW rs, rt Parallel Divide Broadcast Word
2059 * PMFHI rd Parallel Move From HI Register
2060 * PMFLO rd Parallel Move From LO Register
2061 * PMTHI rs Parallel Move To HI Register
2062 * PMTLO rs Parallel Move To LO Register
2063 * PMFHL rd Parallel Move From HI/LO Register
2064 * PMTHL rs Parallel Move To HI/LO Register
2065 *
2066 * Pack/Extend (11 instructions)
2067 * -----------------------------
2068 * PPAC5 rd, rt Parallel Pack to 5 bits
2069 * PPACB rd, rs, rt Parallel Pack to Byte
2070 * PPACH rd, rs, rt Parallel Pack to Halfword
2071 * PPACW rd, rs, rt Parallel Pack to Word
2072 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2073 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2074 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2075 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2076 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2077 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2078 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2079 *
2080 * Others (16 instructions)
2081 * ------------------------
2082 * PCPYH rd, rt Parallel Copy Halfword
2083 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2084 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2085 * PREVH rd, rt Parallel Reverse Halfword
2086 * PINTH rd, rs, rt Parallel Interleave Halfword
2087 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2088 * PEXEH rd, rt Parallel Exchange Even Halfword
2089 * PEXCH rd, rt Parallel Exchange Center Halfword
2090 * PEXEW rd, rt Parallel Exchange Even Word
2091 * PEXCW rd, rt Parallel Exchange Center Word
2092 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2093 * MFSA rd Move from Shift Amount Register
2094 * MTSA rs Move to Shift Amount Register
2095 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2096 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2097 * PROT3W rd, rt Parallel Rotate 3 Words
f99c0d6d
FN
2098 *
2099 * The TX79-specific Multimedia Instruction encodings
2100 * ==================================================
2101 *
2102 * TX79 Multimedia Instruction encoding table keys:
2103 *
2104 * * This code is reserved for future use. An attempt to execute it
2105 * causes a Reserved Instruction exception.
2106 * % This code indicates an instruction class. The instruction word
2107 * must be further decoded by examining additional tables that show
2108 * the values for other instruction fields.
2109 * # This code is reserved for the unsupported instructions DMULT,
2110 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2111 * to execute it causes a Reserved Instruction exception.
2112 *
2113 * TX79 Multimedia Instructions encoded by opcode field (MMI, LQ, SQ):
2114 *
2115 * 31 26 0
2116 * +--------+----------------------------------------+
2117 * | opcode | |
2118 * +--------+----------------------------------------+
2119 *
2120 * opcode bits 28..26
2121 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2122 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2123 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2124 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2125 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2126 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2127 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2128 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2129 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2130 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2131 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
497f072b 2132 */
b158d449 2133
f99c0d6d
FN
2134enum {
2135 TX79_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2136 TX79_LQ = 0x1E << 26, /* Same as OPC_MSA */
2137 TX79_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2138};
2139
d3297211
FN
2140/*
2141 * TX79 Multimedia Instructions with opcode field = MMI:
2142 *
2143 * 31 26 5 0
2144 * +--------+-------------------------------+--------+
2145 * | MMI | |function|
2146 * +--------+-------------------------------+--------+
2147 *
2148 * function bits 2..0
2149 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2150 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2151 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2152 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2153 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2154 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2155 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2156 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2157 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2158 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2159 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2160 */
2161
2162#define MASK_TX79_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2163enum {
2164 TX79_MMI_MADD = 0x00 | TX79_CLASS_MMI, /* Same as OPC_MADD */
2165 TX79_MMI_MADDU = 0x01 | TX79_CLASS_MMI, /* Same as OPC_MADDU */
2166 TX79_MMI_PLZCW = 0x04 | TX79_CLASS_MMI,
2167 TX79_MMI_CLASS_MMI0 = 0x08 | TX79_CLASS_MMI,
2168 TX79_MMI_CLASS_MMI2 = 0x09 | TX79_CLASS_MMI,
2169 TX79_MMI_MFHI1 = 0x10 | TX79_CLASS_MMI, /* Same minor as OPC_MFHI */
2170 TX79_MMI_MTHI1 = 0x11 | TX79_CLASS_MMI, /* Same minor as OPC_MTHI */
2171 TX79_MMI_MFLO1 = 0x12 | TX79_CLASS_MMI, /* Same minor as OPC_MFLO */
2172 TX79_MMI_MTLO1 = 0x13 | TX79_CLASS_MMI, /* Same minor as OPC_MTLO */
2173 TX79_MMI_MULT1 = 0x18 | TX79_CLASS_MMI, /* Same minor as OPC_MULT */
2174 TX79_MMI_MULTU1 = 0x19 | TX79_CLASS_MMI, /* Same minor as OPC_MULTU */
2175 TX79_MMI_DIV1 = 0x1A | TX79_CLASS_MMI, /* Same minor as OPC_DIV */
2176 TX79_MMI_DIVU1 = 0x1B | TX79_CLASS_MMI, /* Same minor as OPC_DIVU */
2177 TX79_MMI_MADD1 = 0x20 | TX79_CLASS_MMI,
2178 TX79_MMI_MADDU1 = 0x21 | TX79_CLASS_MMI,
2179 TX79_MMI_CLASS_MMI1 = 0x28 | TX79_CLASS_MMI,
2180 TX79_MMI_CLASS_MMI3 = 0x29 | TX79_CLASS_MMI,
2181 TX79_MMI_PMFHL = 0x30 | TX79_CLASS_MMI,
2182 TX79_MMI_PMTHL = 0x31 | TX79_CLASS_MMI,
2183 TX79_MMI_PSLLH = 0x34 | TX79_CLASS_MMI,
2184 TX79_MMI_PSRLH = 0x36 | TX79_CLASS_MMI,
2185 TX79_MMI_PSRAH = 0x37 | TX79_CLASS_MMI,
2186 TX79_MMI_PSLLW = 0x3C | TX79_CLASS_MMI,
2187 TX79_MMI_PSRLW = 0x3E | TX79_CLASS_MMI,
2188 TX79_MMI_PSRAW = 0x3F | TX79_CLASS_MMI,
2189};
2190
3ef65697
FN
2191/*
2192 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI0:
2193 *
2194 * 31 26 10 6 5 0
2195 * +--------+----------------------+--------+--------+
2196 * | MMI | |function| MMI0 |
2197 * +--------+----------------------+--------+--------+
2198 *
2199 * function bits 7..6
2200 * bits | 0 | 1 | 2 | 3
2201 * 10..8 | 00 | 01 | 10 | 11
2202 * -------+-------+-------+-------+-------
2203 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2204 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2205 * 2 010 | PADDB | PSUBB | PCGTB | *
2206 * 3 011 | * | * | * | *
2207 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2208 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2209 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2210 * 7 111 | * | * | PEXT5 | PPAC5
2211 */
2212
2213#define MASK_TX79_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2214enum {
2215 TX79_MMI0_PADDW = (0x00 << 6) | TX79_MMI_CLASS_MMI0,
2216 TX79_MMI0_PSUBW = (0x01 << 6) | TX79_MMI_CLASS_MMI0,
2217 TX79_MMI0_PCGTW = (0x02 << 6) | TX79_MMI_CLASS_MMI0,
2218 TX79_MMI0_PMAXW = (0x03 << 6) | TX79_MMI_CLASS_MMI0,
2219 TX79_MMI0_PADDH = (0x04 << 6) | TX79_MMI_CLASS_MMI0,
2220 TX79_MMI0_PSUBH = (0x05 << 6) | TX79_MMI_CLASS_MMI0,
2221 TX79_MMI0_PCGTH = (0x06 << 6) | TX79_MMI_CLASS_MMI0,
2222 TX79_MMI0_PMAXH = (0x07 << 6) | TX79_MMI_CLASS_MMI0,
2223 TX79_MMI0_PADDB = (0x08 << 6) | TX79_MMI_CLASS_MMI0,
2224 TX79_MMI0_PSUBB = (0x09 << 6) | TX79_MMI_CLASS_MMI0,
2225 TX79_MMI0_PCGTB = (0x0A << 6) | TX79_MMI_CLASS_MMI0,
2226 TX79_MMI0_PADDSW = (0x10 << 6) | TX79_MMI_CLASS_MMI0,
2227 TX79_MMI0_PSUBSW = (0x11 << 6) | TX79_MMI_CLASS_MMI0,
2228 TX79_MMI0_PEXTLW = (0x12 << 6) | TX79_MMI_CLASS_MMI0,
2229 TX79_MMI0_PPACW = (0x13 << 6) | TX79_MMI_CLASS_MMI0,
2230 TX79_MMI0_PADDSH = (0x14 << 6) | TX79_MMI_CLASS_MMI0,
2231 TX79_MMI0_PSUBSH = (0x15 << 6) | TX79_MMI_CLASS_MMI0,
2232 TX79_MMI0_PEXTLH = (0x16 << 6) | TX79_MMI_CLASS_MMI0,
2233 TX79_MMI0_PPACH = (0x17 << 6) | TX79_MMI_CLASS_MMI0,
2234 TX79_MMI0_PADDSB = (0x18 << 6) | TX79_MMI_CLASS_MMI0,
2235 TX79_MMI0_PSUBSB = (0x19 << 6) | TX79_MMI_CLASS_MMI0,
2236 TX79_MMI0_PEXTLB = (0x1A << 6) | TX79_MMI_CLASS_MMI0,
2237 TX79_MMI0_PPACB = (0x1B << 6) | TX79_MMI_CLASS_MMI0,
2238 TX79_MMI0_PEXT5 = (0x1E << 6) | TX79_MMI_CLASS_MMI0,
2239 TX79_MMI0_PPAC5 = (0x1F << 6) | TX79_MMI_CLASS_MMI0,
2240};
2241
77596541
FN
2242/*
2243 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI1:
2244 *
2245 * 31 26 10 6 5 0
2246 * +--------+----------------------+--------+--------+
2247 * | MMI | |function| MMI1 |
2248 * +--------+----------------------+--------+--------+
2249 *
2250 * function bits 7..6
2251 * bits | 0 | 1 | 2 | 3
2252 * 10..8 | 00 | 01 | 10 | 11
2253 * -------+-------+-------+-------+-------
2254 * 0 000 | * | PABSW | PCEQW | PMINW
2255 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2256 * 2 010 | * | * | PCEQB | *
2257 * 3 011 | * | * | * | *
2258 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2259 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2260 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2261 * 7 111 | * | * | * | *
2262 */
2263
2264#define MASK_TX79_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2265enum {
2266 TX79_MMI1_PABSW = (0x01 << 6) | TX79_MMI_CLASS_MMI1,
2267 TX79_MMI1_PCEQW = (0x02 << 6) | TX79_MMI_CLASS_MMI1,
2268 TX79_MMI1_PMINW = (0x03 << 6) | TX79_MMI_CLASS_MMI1,
2269 TX79_MMI1_PADSBH = (0x04 << 6) | TX79_MMI_CLASS_MMI1,
2270 TX79_MMI1_PABSH = (0x05 << 6) | TX79_MMI_CLASS_MMI1,
2271 TX79_MMI1_PCEQH = (0x06 << 6) | TX79_MMI_CLASS_MMI1,
2272 TX79_MMI1_PMINH = (0x07 << 6) | TX79_MMI_CLASS_MMI1,
2273 TX79_MMI1_PCEQB = (0x0A << 6) | TX79_MMI_CLASS_MMI1,
2274 TX79_MMI1_PADDUW = (0x10 << 6) | TX79_MMI_CLASS_MMI1,
2275 TX79_MMI1_PSUBUW = (0x11 << 6) | TX79_MMI_CLASS_MMI1,
2276 TX79_MMI1_PEXTUW = (0x12 << 6) | TX79_MMI_CLASS_MMI1,
2277 TX79_MMI1_PADDUH = (0x14 << 6) | TX79_MMI_CLASS_MMI1,
2278 TX79_MMI1_PSUBUH = (0x15 << 6) | TX79_MMI_CLASS_MMI1,
2279 TX79_MMI1_PEXTUH = (0x16 << 6) | TX79_MMI_CLASS_MMI1,
2280 TX79_MMI1_PADDUB = (0x18 << 6) | TX79_MMI_CLASS_MMI1,
2281 TX79_MMI1_PSUBUB = (0x19 << 6) | TX79_MMI_CLASS_MMI1,
2282 TX79_MMI1_PEXTUB = (0x1A << 6) | TX79_MMI_CLASS_MMI1,
2283 TX79_MMI1_QFSRV = (0x1B << 6) | TX79_MMI_CLASS_MMI1,
2284};
2285
6c03ef6a
FN
2286/*
2287 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI2:
2288 *
2289 * 31 26 10 6 5 0
2290 * +--------+----------------------+--------+--------+
2291 * | MMI | |function| MMI2 |
2292 * +--------+----------------------+--------+--------+
2293 *
2294 * function bits 7..6
2295 * bits | 0 | 1 | 2 | 3
2296 * 10..8 | 00 | 01 | 10 | 11
2297 * -------+-------+-------+-------+-------
2298 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2299 * 1 001 | PMSUBW| * | * | *
2300 * 2 010 | PMFHI | PMFLO | PINTH | *
2301 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2302 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2303 * 5 101 | PMSUBH| PHMSBH| * | *
2304 * 6 110 | * | * | PEXEH | PREVH
2305 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2306 */
2307
2308#define MASK_TX79_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2309enum {
2310 TX79_MMI2_PMADDW = (0x00 << 6) | TX79_MMI_CLASS_MMI2,
2311 TX79_MMI2_PSLLVW = (0x02 << 6) | TX79_MMI_CLASS_MMI2,
2312 TX79_MMI2_PSRLVW = (0x03 << 6) | TX79_MMI_CLASS_MMI2,
2313 TX79_MMI2_PMSUBW = (0x04 << 6) | TX79_MMI_CLASS_MMI2,
2314 TX79_MMI2_PMFHI = (0x08 << 6) | TX79_MMI_CLASS_MMI2,
2315 TX79_MMI2_PMFLO = (0x09 << 6) | TX79_MMI_CLASS_MMI2,
2316 TX79_MMI2_PINTH = (0x0A << 6) | TX79_MMI_CLASS_MMI2,
2317 TX79_MMI2_PMULTW = (0x0C << 6) | TX79_MMI_CLASS_MMI2,
2318 TX79_MMI2_PDIVW = (0x0D << 6) | TX79_MMI_CLASS_MMI2,
2319 TX79_MMI2_PCPYLD = (0x0E << 6) | TX79_MMI_CLASS_MMI2,
2320 TX79_MMI2_PMADDH = (0x10 << 6) | TX79_MMI_CLASS_MMI2,
2321 TX79_MMI2_PHMADH = (0x11 << 6) | TX79_MMI_CLASS_MMI2,
2322 TX79_MMI2_PAND = (0x12 << 6) | TX79_MMI_CLASS_MMI2,
2323 TX79_MMI2_PXOR = (0x13 << 6) | TX79_MMI_CLASS_MMI2,
2324 TX79_MMI2_PMSUBH = (0x14 << 6) | TX79_MMI_CLASS_MMI2,
2325 TX79_MMI2_PHMSBH = (0x15 << 6) | TX79_MMI_CLASS_MMI2,
2326 TX79_MMI2_PEXEH = (0x1A << 6) | TX79_MMI_CLASS_MMI2,
2327 TX79_MMI2_PREVH = (0x1B << 6) | TX79_MMI_CLASS_MMI2,
2328 TX79_MMI2_PMULTH = (0x1C << 6) | TX79_MMI_CLASS_MMI2,
2329 TX79_MMI2_PDIVBW = (0x1D << 6) | TX79_MMI_CLASS_MMI2,
2330 TX79_MMI2_PEXEW = (0x1E << 6) | TX79_MMI_CLASS_MMI2,
2331 TX79_MMI2_PROT3W = (0x1F << 6) | TX79_MMI_CLASS_MMI2,
2332};
2333
dd581bf9
FN
2334/*
2335 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI3:
2336 *
2337 * 31 26 10 6 5 0
2338 * +--------+----------------------+--------+--------+
2339 * | MMI | |function| MMI3 |
2340 * +--------+----------------------+--------+--------+
2341 *
2342 * function bits 7..6
2343 * bits | 0 | 1 | 2 | 3
2344 * 10..8 | 00 | 01 | 10 | 11
2345 * -------+-------+-------+-------+-------
2346 * 0 000 |PMADDUW| * | * | PSRAVW
2347 * 1 001 | * | * | * | *
2348 * 2 010 | PMTHI | PMTLO | PINTEH| *
2349 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2350 * 4 100 | * | * | POR | PNOR
2351 * 5 101 | * | * | * | *
2352 * 6 110 | * | * | PEXCH | PCPYH
2353 * 7 111 | * | * | PEXCW | *
2354 */
2355
2356#define MASK_TX79_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2357enum {
2358 TX79_MMI3_PMADDUW = (0x00 << 6) | TX79_MMI_CLASS_MMI3,
2359 TX79_MMI3_PSRAVW = (0x03 << 6) | TX79_MMI_CLASS_MMI3,
2360 TX79_MMI3_PMTHI = (0x08 << 6) | TX79_MMI_CLASS_MMI3,
2361 TX79_MMI3_PMTLO = (0x09 << 6) | TX79_MMI_CLASS_MMI3,
2362 TX79_MMI3_PINTEH = (0x0A << 6) | TX79_MMI_CLASS_MMI3,
2363 TX79_MMI3_PMULTUW = (0x0C << 6) | TX79_MMI_CLASS_MMI3,
2364 TX79_MMI3_PDIVUW = (0x0D << 6) | TX79_MMI_CLASS_MMI3,
2365 TX79_MMI3_PCPYUD = (0x0E << 6) | TX79_MMI_CLASS_MMI3,
2366 TX79_MMI3_POR = (0x12 << 6) | TX79_MMI_CLASS_MMI3,
2367 TX79_MMI3_PNOR = (0x13 << 6) | TX79_MMI_CLASS_MMI3,
2368 TX79_MMI3_PEXCH = (0x1A << 6) | TX79_MMI_CLASS_MMI3,
2369 TX79_MMI3_PCPYH = (0x1B << 6) | TX79_MMI_CLASS_MMI3,
2370 TX79_MMI3_PEXCW = (0x1E << 6) | TX79_MMI_CLASS_MMI3,
2371};
2372
39454628 2373/* global register indices */
a7812ae4 2374static TCGv cpu_gpr[32], cpu_PC;
340fff72 2375static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
41db4607
AJ
2376static TCGv cpu_dspctrl, btarget, bcond;
2377static TCGv_i32 hflags;
a7812ae4 2378static TCGv_i32 fpu_fcr0, fpu_fcr31;
d73ee8a2 2379static TCGv_i64 fpu_f64[32];
863f264d 2380static TCGv_i64 msa_wr_d[64];
aa0bf00b 2381
022c62cb 2382#include "exec/gen-icount.h"
2e70f6ef 2383
895c2d04 2384#define gen_helper_0e0i(name, arg) do { \
a7812ae4 2385 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
895c2d04 2386 gen_helper_##name(cpu_env, helper_tmp); \
a7812ae4
PB
2387 tcg_temp_free_i32(helper_tmp); \
2388 } while(0)
be24bb4f 2389
895c2d04 2390#define gen_helper_0e1i(name, arg1, arg2) do { \
a7812ae4 2391 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
895c2d04 2392 gen_helper_##name(cpu_env, arg1, helper_tmp); \
a7812ae4
PB
2393 tcg_temp_free_i32(helper_tmp); \
2394 } while(0)
be24bb4f 2395
895c2d04
BS
2396#define gen_helper_1e0i(name, ret, arg1) do { \
2397 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2398 gen_helper_##name(ret, cpu_env, helper_tmp); \
2399 tcg_temp_free_i32(helper_tmp); \
2400 } while(0)
2401
2402#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2403 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2404 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2405 tcg_temp_free_i32(helper_tmp); \
2406 } while(0)
2407
2408#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2409 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2410 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2411 tcg_temp_free_i32(helper_tmp); \
2412 } while(0)
2413
2414#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
a7812ae4 2415 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
895c2d04 2416 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
a7812ae4
PB
2417 tcg_temp_free_i32(helper_tmp); \
2418 } while(0)
be24bb4f 2419
895c2d04 2420#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
a7812ae4 2421 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
895c2d04 2422 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
a7812ae4
PB
2423 tcg_temp_free_i32(helper_tmp); \
2424 } while(0)
c239529e 2425
8e9ade68 2426typedef struct DisasContext {
eeb3bba8
EC
2427 DisasContextBase base;
2428 target_ulong saved_pc;
18f440ed 2429 target_ulong page_start;
8e9ade68 2430 uint32_t opcode;
f9c9cd63 2431 uint64_t insn_flags;
5ab5c041 2432 int32_t CP0_Config1;
49735f76 2433 int32_t CP0_Config2;
ab77fc61
DN
2434 int32_t CP0_Config3;
2435 int32_t CP0_Config5;
8e9ade68
TS
2436 /* Routine used to access memory */
2437 int mem_idx;
be3a8c53 2438 TCGMemOp default_tcg_memop_mask;
8e9ade68 2439 uint32_t hflags, saved_hflags;
8e9ade68 2440 target_ulong btarget;
d279279e 2441 bool ulri;
e98c0d17 2442 int kscrexist;
7207c7f9 2443 bool rxi;
9456c2fb 2444 int ie;
aea14095
LA
2445 bool bi;
2446 bool bp;
5204ea79
LA
2447 uint64_t PAMask;
2448 bool mvh;
76964147 2449 bool eva;
cec56a73 2450 bool sc;
5204ea79 2451 int CP0_LLAddr_shift;
e29c9628 2452 bool ps;
01bc435b 2453 bool vp;
c870e3f5 2454 bool cmgcr;
f6d4dd81 2455 bool mrp;
87552089 2456 bool nan2008;
6be77480 2457 bool abs2008;
8e9ade68
TS
2458} DisasContext;
2459
b28425ba
EC
2460#define DISAS_STOP DISAS_TARGET_0
2461#define DISAS_EXIT DISAS_TARGET_1
8e9ade68 2462
d73ee8a2
RH
2463static const char * const regnames[] = {
2464 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2465 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2466 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2467 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2468};
6af0bf9c 2469
d73ee8a2
RH
2470static const char * const regnames_HI[] = {
2471 "HI0", "HI1", "HI2", "HI3",
2472};
4b2eb8d2 2473
d73ee8a2
RH
2474static const char * const regnames_LO[] = {
2475 "LO0", "LO1", "LO2", "LO3",
2476};
4b2eb8d2 2477
d73ee8a2
RH
2478static const char * const fregnames[] = {
2479 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2480 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2481 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2482 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2483};
958fb4a9 2484
863f264d
YK
2485static const char * const msaregnames[] = {
2486 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2487 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2488 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2489 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2490 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2491 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2492 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2493 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2494 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2495 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2496 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2497 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2498 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2499 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2500 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2501 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2502};
2503
9d68ac14 2504#define LOG_DISAS(...) \
fb7729e2
RH
2505 do { \
2506 if (MIPS_DEBUG_DISAS) { \
9d68ac14 2507 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
fb7729e2
RH
2508 } \
2509 } while (0)
2510
9d68ac14 2511#define MIPS_INVAL(op) \
fb7729e2
RH
2512 do { \
2513 if (MIPS_DEBUG_DISAS) { \
9d68ac14
AJ
2514 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2515 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
eeb3bba8
EC
2516 ctx->base.pc_next, ctx->opcode, op, \
2517 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2518 ((ctx->opcode >> 16) & 0x1F)); \
fb7729e2
RH
2519 } \
2520 } while (0)
958fb4a9 2521
8e9ade68
TS
2522/* General purpose registers moves. */
2523static inline void gen_load_gpr (TCGv t, int reg)
aaa9128a 2524{
8e9ade68
TS
2525 if (reg == 0)
2526 tcg_gen_movi_tl(t, 0);
2527 else
4b2eb8d2 2528 tcg_gen_mov_tl(t, cpu_gpr[reg]);
aaa9128a
TS
2529}
2530
8e9ade68 2531static inline void gen_store_gpr (TCGv t, int reg)
aaa9128a 2532{
8e9ade68 2533 if (reg != 0)
4b2eb8d2 2534 tcg_gen_mov_tl(cpu_gpr[reg], t);
aaa9128a
TS
2535}
2536
8e9ade68 2537/* Moves to/from shadow registers. */
be24bb4f 2538static inline void gen_load_srsgpr (int from, int to)
aaa9128a 2539{
d9bea114 2540 TCGv t0 = tcg_temp_new();
be24bb4f
TS
2541
2542 if (from == 0)
d9bea114 2543 tcg_gen_movi_tl(t0, 0);
8e9ade68 2544 else {
d9bea114 2545 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 2546 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 2547
7db13fae 2548 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
2549 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2550 tcg_gen_andi_i32(t2, t2, 0xf);
2551 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2552 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 2553 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 2554
d9bea114 2555 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 2556 tcg_temp_free_ptr(addr);
d9bea114 2557 tcg_temp_free_i32(t2);
8e9ade68 2558 }
d9bea114
AJ
2559 gen_store_gpr(t0, to);
2560 tcg_temp_free(t0);
aaa9128a
TS
2561}
2562
be24bb4f 2563static inline void gen_store_srsgpr (int from, int to)
aaa9128a 2564{
be24bb4f 2565 if (to != 0) {
d9bea114
AJ
2566 TCGv t0 = tcg_temp_new();
2567 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 2568 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 2569
d9bea114 2570 gen_load_gpr(t0, from);
7db13fae 2571 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
2572 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2573 tcg_gen_andi_i32(t2, t2, 0xf);
2574 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2575 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 2576 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 2577
d9bea114 2578 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 2579 tcg_temp_free_ptr(addr);
d9bea114
AJ
2580 tcg_temp_free_i32(t2);
2581 tcg_temp_free(t0);
8e9ade68 2582 }
aaa9128a
TS
2583}
2584
eab9944c
LA
2585/* Tests */
2586static inline void gen_save_pc(target_ulong pc)
2587{
2588 tcg_gen_movi_tl(cpu_PC, pc);
2589}
2590
2591static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2592{
2593 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
eeb3bba8
EC
2594 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2595 gen_save_pc(ctx->base.pc_next);
2596 ctx->saved_pc = ctx->base.pc_next;
eab9944c
LA
2597 }
2598 if (ctx->hflags != ctx->saved_hflags) {
2599 tcg_gen_movi_i32(hflags, ctx->hflags);
2600 ctx->saved_hflags = ctx->hflags;
2601 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2602 case MIPS_HFLAG_BR:
2603 break;
2604 case MIPS_HFLAG_BC:
2605 case MIPS_HFLAG_BL:
2606 case MIPS_HFLAG_B:
2607 tcg_gen_movi_tl(btarget, ctx->btarget);
2608 break;
2609 }
2610 }
2611}
2612
2613static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2614{
2615 ctx->saved_hflags = ctx->hflags;
2616 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2617 case MIPS_HFLAG_BR:
2618 break;
2619 case MIPS_HFLAG_BC:
2620 case MIPS_HFLAG_BL:
2621 case MIPS_HFLAG_B:
2622 ctx->btarget = env->btarget;
2623 break;
2624 }
2625}
2626
2627static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2628{
2629 TCGv_i32 texcp = tcg_const_i32(excp);
2630 TCGv_i32 terr = tcg_const_i32(err);
2631 save_cpu_state(ctx, 1);
2632 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2633 tcg_temp_free_i32(terr);
2634 tcg_temp_free_i32(texcp);
eeb3bba8 2635 ctx->base.is_jmp = DISAS_NORETURN;
eab9944c
LA
2636}
2637
2638static inline void generate_exception(DisasContext *ctx, int excp)
2639{
eab9944c
LA
2640 gen_helper_0e0i(raise_exception, excp);
2641}
2642
9c708c7f
PD
2643static inline void generate_exception_end(DisasContext *ctx, int excp)
2644{
2645 generate_exception_err(ctx, excp, 0);
2646}
2647
aaa9128a 2648/* Floating point register moves. */
7c979afd 2649static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 2650{
7c979afd
LA
2651 if (ctx->hflags & MIPS_HFLAG_FRE) {
2652 generate_exception(ctx, EXCP_RI);
2653 }
ecc7b3aa 2654 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
2655}
2656
7c979afd 2657static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 2658{
7c979afd
LA
2659 TCGv_i64 t64;
2660 if (ctx->hflags & MIPS_HFLAG_FRE) {
2661 generate_exception(ctx, EXCP_RI);
2662 }
2663 t64 = tcg_temp_new_i64();
d73ee8a2
RH
2664 tcg_gen_extu_i32_i64(t64, t);
2665 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2666 tcg_temp_free_i64(t64);
6d066274
AJ
2667}
2668
7f6613ce 2669static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 2670{
7f6613ce 2671 if (ctx->hflags & MIPS_HFLAG_F64) {
71f303cd 2672 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
7f6613ce 2673 } else {
7c979afd 2674 gen_load_fpr32(ctx, t, reg | 1);
7f6613ce 2675 }
6d066274
AJ
2676}
2677
7f6613ce 2678static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 2679{
7f6613ce
PJ
2680 if (ctx->hflags & MIPS_HFLAG_F64) {
2681 TCGv_i64 t64 = tcg_temp_new_i64();
2682 tcg_gen_extu_i32_i64(t64, t);
2683 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2684 tcg_temp_free_i64(t64);
2685 } else {
7c979afd 2686 gen_store_fpr32(ctx, t, reg | 1);
7f6613ce 2687 }
aa0bf00b 2688}
6ea83fed 2689
d73ee8a2 2690static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 2691{
f364515c 2692 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 2693 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 2694 } else {
d73ee8a2 2695 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
2696 }
2697}
6ea83fed 2698
d73ee8a2 2699static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 2700{
f364515c 2701 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 2702 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 2703 } else {
d73ee8a2
RH
2704 TCGv_i64 t0;
2705 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2706 t0 = tcg_temp_new_i64();
6d066274 2707 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 2708 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
6d066274 2709 tcg_temp_free_i64(t0);
aa0bf00b
TS
2710 }
2711}
6ea83fed 2712
d94536f4 2713static inline int get_fp_bit (int cc)
a16336e4 2714{
d94536f4
AJ
2715 if (cc)
2716 return 24 + cc;
2717 else
2718 return 23;
a16336e4
TS
2719}
2720
48d38ca5 2721/* Addresses computation */
941694d0 2722static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
4ad40f36 2723{
941694d0 2724 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
2725
2726#if defined(TARGET_MIPS64)
01f72885 2727 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
941694d0 2728 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
2729 }
2730#endif
4ad40f36
FB
2731}
2732
bf0718c5
SM
2733static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2734 target_long ofs)
2735{
2736 tcg_gen_addi_tl(ret, base, ofs);
2737
2738#if defined(TARGET_MIPS64)
2739 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2740 tcg_gen_ext32s_i64(ret, ret);
2741 }
2742#endif
2743}
2744
31837be3
YK
2745/* Addresses computation (translation time) */
2746static target_long addr_add(DisasContext *ctx, target_long base,
2747 target_long offset)
2748{
2749 target_long sum = base + offset;
2750
2751#if defined(TARGET_MIPS64)
2752 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2753 sum = (int32_t)sum;
2754 }
2755#endif
2756 return sum;
2757}
2758
71f303cd 2759/* Sign-extract the low 32-bits to a target_long. */
1f1b4c00
YK
2760static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2761{
2762#if defined(TARGET_MIPS64)
71f303cd
RH
2763 tcg_gen_ext32s_i64(ret, arg);
2764#else
2765 tcg_gen_extrl_i64_i32(ret, arg);
2766#endif
2767}
2768
2769/* Sign-extract the high 32-bits to a target_long. */
2770static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2771{
2772#if defined(TARGET_MIPS64)
2773 tcg_gen_sari_i64(ret, arg, 32);
1f1b4c00 2774#else
71f303cd 2775 tcg_gen_extrh_i64_i32(ret, arg);
1f1b4c00
YK
2776#endif
2777}
2778
356265ae 2779static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 2780{
fe253235 2781 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
c2c65dab 2782 generate_exception_err(ctx, EXCP_CpU, 0);
387a8fe5
TS
2783}
2784
356265ae 2785static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 2786{
fe253235 2787 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
5e755519
TS
2788 generate_exception_err(ctx, EXCP_CpU, 1);
2789}
2790
b8aa4598
TS
2791/* Verify that the processor is running with COP1X instructions enabled.
2792 This is associated with the nabla symbol in the MIPS32 and MIPS64
2793 opcode tables. */
2794
356265ae 2795static inline void check_cop1x(DisasContext *ctx)
b8aa4598
TS
2796{
2797 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
9c708c7f 2798 generate_exception_end(ctx, EXCP_RI);
b8aa4598
TS
2799}
2800
2801/* Verify that the processor is running with 64-bit floating-point
2802 operations enabled. */
2803
356265ae 2804static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 2805{
b8aa4598 2806 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
9c708c7f 2807 generate_exception_end(ctx, EXCP_RI);
5e755519
TS
2808}
2809
2810/*
2811 * Verify if floating point register is valid; an operation is not defined
2812 * if bit 0 of any register specification is set and the FR bit in the
2813 * Status register equals zero, since the register numbers specify an
2814 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2815 * in the Status register equals one, both even and odd register numbers
2816 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2817 *
2818 * Multiple 64 bit wide registers can be checked by calling
2819 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2820 */
356265ae 2821static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 2822{
fe253235 2823 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
9c708c7f 2824 generate_exception_end(ctx, EXCP_RI);
5e755519
TS
2825}
2826
853c3240
JL
2827/* Verify that the processor is running with DSP instructions enabled.
2828 This is enabled by CP0 Status register MX(24) bit.
2829 */
2830
2831static inline void check_dsp(DisasContext *ctx)
2832{
2833 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
ad153f15 2834 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 2835 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 2836 } else {
9c708c7f 2837 generate_exception_end(ctx, EXCP_RI);
ad153f15 2838 }
853c3240
JL
2839 }
2840}
2841
908f6be1 2842static inline void check_dsp_r2(DisasContext *ctx)
853c3240 2843{
908f6be1 2844 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
ad153f15 2845 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 2846 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 2847 } else {
9c708c7f 2848 generate_exception_end(ctx, EXCP_RI);
ad153f15 2849 }
853c3240
JL
2850 }
2851}
2852
908f6be1 2853static inline void check_dsp_r3(DisasContext *ctx)
59e781fb 2854{
908f6be1 2855 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
59e781fb
SM
2856 if (ctx->insn_flags & ASE_DSP) {
2857 generate_exception_end(ctx, EXCP_DSPDIS);
2858 } else {
2859 generate_exception_end(ctx, EXCP_RI);
2860 }
2861 }
2862}
2863
3a95e3a7 2864/* This code generates a "reserved instruction" exception if the
e189e748 2865 CPU does not support the instruction set corresponding to flags. */
f9c9cd63 2866static inline void check_insn(DisasContext *ctx, uint64_t flags)
3a95e3a7 2867{
d75c135e 2868 if (unlikely(!(ctx->insn_flags & flags))) {
9c708c7f 2869 generate_exception_end(ctx, EXCP_RI);
d75c135e 2870 }
3a95e3a7
TS
2871}
2872
fecd2646
LA
2873/* This code generates a "reserved instruction" exception if the
2874 CPU has corresponding flag set which indicates that the instruction
2875 has been removed. */
f9c9cd63 2876static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
fecd2646
LA
2877{
2878 if (unlikely(ctx->insn_flags & flags)) {
9c708c7f 2879 generate_exception_end(ctx, EXCP_RI);
fecd2646
LA
2880 }
2881}
2882
96631327
FN
2883/*
2884 * The Linux kernel traps certain reserved instruction exceptions to
2885 * emulate the corresponding instructions. QEMU is the kernel in user
2886 * mode, so those traps are emulated by accepting the instructions.
2887 *
2888 * A reserved instruction exception is generated for flagged CPUs if
2889 * QEMU runs in system mode.
2890 */
2891static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
2892{
2893#ifndef CONFIG_USER_ONLY
2894 check_insn_opc_removed(ctx, flags);
2895#endif
2896}
2897
e29c9628
YK
2898/* This code generates a "reserved instruction" exception if the
2899 CPU does not support 64-bit paired-single (PS) floating point data type */
2900static inline void check_ps(DisasContext *ctx)
2901{
2902 if (unlikely(!ctx->ps)) {
2903 generate_exception(ctx, EXCP_RI);
2904 }
2905 check_cp1_64bitmode(ctx);
2906}
2907
c7986fd6 2908#ifdef TARGET_MIPS64
e189e748
TS
2909/* This code generates a "reserved instruction" exception if 64-bit
2910 instructions are not enabled. */
356265ae 2911static inline void check_mips_64(DisasContext *ctx)
e189e748 2912{
fe253235 2913 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
9c708c7f 2914 generate_exception_end(ctx, EXCP_RI);
e189e748 2915}
c7986fd6 2916#endif
e189e748 2917
5204ea79
LA
2918#ifndef CONFIG_USER_ONLY
2919static inline void check_mvh(DisasContext *ctx)
2920{
2921 if (unlikely(!ctx->mvh)) {
2922 generate_exception(ctx, EXCP_RI);
2923 }
2924}
2925#endif
2926
0b16dcd1
AR
2927/*
2928 * This code generates a "reserved instruction" exception if the
2929 * Config5 XNP bit is set.
2930 */
2931static inline void check_xnp(DisasContext *ctx)
2932{
2933 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2934 generate_exception_end(ctx, EXCP_RI);
2935 }
2936}
2937
5e31fdd5
YK
2938#ifndef CONFIG_USER_ONLY
2939/*
2940 * This code generates a "reserved instruction" exception if the
2941 * Config3 PW bit is NOT set.
2942 */
2943static inline void check_pw(DisasContext *ctx)
2944{
2945 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2946 generate_exception_end(ctx, EXCP_RI);
2947 }
2948}
2949#endif
2950
9affc1c5
AR
2951/*
2952 * This code generates a "reserved instruction" exception if the
2953 * Config3 MT bit is NOT set.
2954 */
2955static inline void check_mt(DisasContext *ctx)
2956{
2957 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2958 generate_exception_end(ctx, EXCP_RI);
2959 }
2960}
2961
2962#ifndef CONFIG_USER_ONLY
2963/*
2964 * This code generates a "coprocessor unusable" exception if CP0 is not
2965 * available, and, if that is not the case, generates a "reserved instruction"
2966 * exception if the Config5 MT bit is NOT set. This is needed for availability
2967 * control of some of MT ASE instructions.
2968 */
2969static inline void check_cp0_mt(DisasContext *ctx)
2970{
2971 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2972 generate_exception_err(ctx, EXCP_CpU, 0);
2973 } else {
2974 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2975 generate_exception_err(ctx, EXCP_RI, 0);
2976 }
2977 }
2978}
2979#endif
2980
fb32f8c8
DN
2981/*
2982 * This code generates a "reserved instruction" exception if the
2983 * Config5 NMS bit is set.
2984 */
2985static inline void check_nms(DisasContext *ctx)
2986{
2987 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2988 generate_exception_end(ctx, EXCP_RI);
2989 }
2990}
2991
d046a9ea
DN
2992/*
2993 * This code generates a "reserved instruction" exception if the
2994 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
2995 * Config2 TL, and Config5 L2C are unset.
2996 */
2997static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
2998{
2999 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3000 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3001 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3002 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3003 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3004 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))
3005 {
3006 generate_exception_end(ctx, EXCP_RI);
3007 }
3008}
3009
3010/*
3011 * This code generates a "reserved instruction" exception if the
3012 * Config5 EVA bit is NOT set.
3013 */
3014static inline void check_eva(DisasContext *ctx)
3015{
3016 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3017 generate_exception_end(ctx, EXCP_RI);
3018 }
3019}
3020
0b16dcd1 3021
8153667c
NF
3022/* Define small wrappers for gen_load_fpr* so that we have a uniform
3023 calling interface for 32 and 64-bit FPRs. No sense in changing
3024 all callers for gen_load_fpr32 when we need the CTX parameter for
3025 this one use. */
7c979afd 3026#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
8153667c
NF
3027#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3028#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3029static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3030 int ft, int fs, int cc) \
3031{ \
3032 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
3033 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
3034 switch (ifmt) { \
3035 case FMT_PS: \
e29c9628 3036 check_ps(ctx); \
8153667c
NF
3037 break; \
3038 case FMT_D: \
3039 if (abs) { \
3040 check_cop1x(ctx); \
3041 } \
3042 check_cp1_registers(ctx, fs | ft); \
3043 break; \
3044 case FMT_S: \
3045 if (abs) { \
3046 check_cop1x(ctx); \
3047 } \
3048 break; \
3049 } \
3050 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
3051 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
3052 switch (n) { \
895c2d04
BS
3053 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
3054 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
3055 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
3056 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
3057 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
3058 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
3059 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
3060 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
3061 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
3062 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
3063 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
3064 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
3065 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
3066 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
3067 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
3068 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
8153667c
NF
3069 default: abort(); \
3070 } \
3071 tcg_temp_free_i##bits (fp0); \
3072 tcg_temp_free_i##bits (fp1); \
3073}
3074
3075FOP_CONDS(, 0, d, FMT_D, 64)
3076FOP_CONDS(abs, 1, d, FMT_D, 64)
3077FOP_CONDS(, 0, s, FMT_S, 32)
3078FOP_CONDS(abs, 1, s, FMT_S, 32)
3079FOP_CONDS(, 0, ps, FMT_PS, 64)
3080FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3081#undef FOP_CONDS
3f493883
YK
3082
3083#define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3084static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
3085 int ft, int fs, int fd) \
3086{ \
3087 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3088 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
00fb4a11 3089 if (ifmt == FMT_D) { \
3f493883 3090 check_cp1_registers(ctx, fs | ft | fd); \
3f493883
YK
3091 } \
3092 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3093 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3094 switch (n) { \
3095 case 0: \
3096 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3097 break; \
3098 case 1: \
3099 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3100 break; \
3101 case 2: \
3102 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3103 break; \
3104 case 3: \
3105 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3106 break; \
3107 case 4: \
3108 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3109 break; \
3110 case 5: \
3111 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3112 break; \
3113 case 6: \
3114 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3115 break; \
3116 case 7: \
3117 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3118 break; \
3119 case 8: \
3120 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3121 break; \
3122 case 9: \
3123 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3124 break; \
3125 case 10: \
3126 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3127 break; \
3128 case 11: \
3129 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3130 break; \
3131 case 12: \
3132 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3133 break; \
3134 case 13: \
3135 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3136 break; \
3137 case 14: \
3138 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3139 break; \
3140 case 15: \
3141 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3142 break; \
3143 case 17: \
3144 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3145 break; \
3146 case 18: \
3147 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3148 break; \
3149 case 19: \
3150 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3151 break; \
3152 case 25: \
3153 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3154 break; \
3155 case 26: \
3156 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3157 break; \
3158 case 27: \
3159 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3160 break; \
3161 default: \
3162 abort(); \
3163 } \
3164 STORE; \
3165 tcg_temp_free_i ## bits (fp0); \
3166 tcg_temp_free_i ## bits (fp1); \
3167}
3168
3169FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
7c979afd 3170FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3f493883 3171#undef FOP_CONDNS
8153667c
NF
3172#undef gen_ldcmp_fpr32
3173#undef gen_ldcmp_fpr64
3174
958fb4a9 3175/* load/store instructions. */
e7139c44 3176#ifdef CONFIG_USER_ONLY
d9bea114 3177#define OP_LD_ATOMIC(insn,fname) \
dd4096cd
JH
3178static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3179 DisasContext *ctx) \
d9bea114
AJ
3180{ \
3181 TCGv t0 = tcg_temp_new(); \
3182 tcg_gen_mov_tl(t0, arg1); \
3183 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
7db13fae
AF
3184 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3185 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 3186 tcg_temp_free(t0); \
aaa9128a 3187}
e7139c44
AJ
3188#else
3189#define OP_LD_ATOMIC(insn,fname) \
dd4096cd
JH
3190static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3191 DisasContext *ctx) \
e7139c44 3192{ \
dd4096cd 3193 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
e7139c44
AJ
3194}
3195#endif
aaa9128a
TS
3196OP_LD_ATOMIC(ll,ld32s);
3197#if defined(TARGET_MIPS64)
3198OP_LD_ATOMIC(lld,ld64);
3199#endif
3200#undef OP_LD_ATOMIC
3201
590bc601
PB
3202#ifdef CONFIG_USER_ONLY
3203#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
dd4096cd
JH
3204static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3205 DisasContext *ctx) \
590bc601
PB
3206{ \
3207 TCGv t0 = tcg_temp_new(); \
42a268c2
RH
3208 TCGLabel *l1 = gen_new_label(); \
3209 TCGLabel *l2 = gen_new_label(); \
590bc601
PB
3210 \
3211 tcg_gen_andi_tl(t0, arg2, almask); \
3212 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
7db13fae 3213 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
590bc601
PB
3214 generate_exception(ctx, EXCP_AdES); \
3215 gen_set_label(l1); \
7db13fae 3216 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
590bc601
PB
3217 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
3218 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
7db13fae
AF
3219 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
3220 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
9c708c7f 3221 generate_exception_end(ctx, EXCP_SC); \
590bc601
PB
3222 gen_set_label(l2); \
3223 tcg_gen_movi_tl(t0, 0); \
3224 gen_store_gpr(t0, rt); \
3225 tcg_temp_free(t0); \
3226}
3227#else
3228#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
dd4096cd
JH
3229static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3230 DisasContext *ctx) \
590bc601
PB
3231{ \
3232 TCGv t0 = tcg_temp_new(); \
dd4096cd 3233 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
590bc601 3234 gen_store_gpr(t0, rt); \
590bc601
PB
3235 tcg_temp_free(t0); \
3236}
3237#endif
590bc601 3238OP_ST_ATOMIC(sc,st32,ld32s,0x3);
aaa9128a 3239#if defined(TARGET_MIPS64)
590bc601 3240OP_ST_ATOMIC(scd,st64,ld64,0x7);
aaa9128a
TS
3241#endif
3242#undef OP_ST_ATOMIC
3243
662d7485 3244static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
72e1f16f 3245 int base, int offset)
662d7485
NF
3246{
3247 if (base == 0) {
3248 tcg_gen_movi_tl(addr, offset);
3249 } else if (offset == 0) {
3250 gen_load_gpr(addr, base);
3251 } else {
3252 tcg_gen_movi_tl(addr, offset);
3253 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3254 }
3255}
3256
364d4831
NF
3257static target_ulong pc_relative_pc (DisasContext *ctx)
3258{
eeb3bba8 3259 target_ulong pc = ctx->base.pc_next;
364d4831
NF
3260
3261 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3262 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3263
3264 pc -= branch_bytes;
3265 }
3266
3267 pc &= ~(target_ulong)3;
3268 return pc;
3269}
3270
5c13fdfd 3271/* Load */
d75c135e 3272static void gen_ld(DisasContext *ctx, uint32_t opc,
72e1f16f 3273 int rt, int base, int offset)
6af0bf9c 3274{
fc40787a 3275 TCGv t0, t1, t2;
dd4096cd 3276 int mem_idx = ctx->mem_idx;
afa88c3a 3277
d75c135e 3278 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
afa88c3a
AJ
3279 /* Loongson CPU uses a load to zero register for prefetch.
3280 We emulate it as a NOP. On other CPU we must perform the
3281 actual memory access. */
afa88c3a
AJ
3282 return;
3283 }
6af0bf9c 3284
afa88c3a 3285 t0 = tcg_temp_new();
662d7485 3286 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 3287
6af0bf9c 3288 switch (opc) {
d26bc211 3289#if defined(TARGET_MIPS64)
6e473128 3290 case OPC_LWU:
dd4096cd 3291 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
be3a8c53 3292 ctx->default_tcg_memop_mask);
78723684 3293 gen_store_gpr(t0, rt);
6e473128 3294 break;
6af0bf9c 3295 case OPC_LD:
dd4096cd 3296 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
be3a8c53 3297 ctx->default_tcg_memop_mask);
78723684 3298 gen_store_gpr(t0, rt);
6af0bf9c 3299 break;
7a387fff 3300 case OPC_LLD:
bf7910c6 3301 case R6_OPC_LLD:
dd4096cd 3302 op_ld_lld(t0, t0, mem_idx, ctx);
78723684 3303 gen_store_gpr(t0, rt);
7a387fff 3304 break;
6af0bf9c 3305 case OPC_LDL:
3cee3050 3306 t1 = tcg_temp_new();
908680c6
AJ
3307 /* Do a byte access to possibly trigger a page
3308 fault with the unaligned address. */
dd4096cd 3309 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3310 tcg_gen_andi_tl(t1, t0, 7);
3311#ifndef TARGET_WORDS_BIGENDIAN
3312 tcg_gen_xori_tl(t1, t1, 7);
3313#endif
3314 tcg_gen_shli_tl(t1, t1, 3);
3315 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 3316 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a 3317 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
3318 t2 = tcg_const_tl(-1);
3319 tcg_gen_shl_tl(t2, t2, t1);
78723684 3320 gen_load_gpr(t1, rt);
eb02cc3f 3321 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
3322 tcg_temp_free(t2);
3323 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3324 tcg_temp_free(t1);
fc40787a 3325 gen_store_gpr(t0, rt);
6af0bf9c 3326 break;
6af0bf9c 3327 case OPC_LDR:
3cee3050 3328 t1 = tcg_temp_new();
908680c6
AJ
3329 /* Do a byte access to possibly trigger a page
3330 fault with the unaligned address. */
dd4096cd 3331 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3332 tcg_gen_andi_tl(t1, t0, 7);
3333#ifdef TARGET_WORDS_BIGENDIAN
3334 tcg_gen_xori_tl(t1, t1, 7);
3335#endif
3336 tcg_gen_shli_tl(t1, t1, 3);
3337 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 3338 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a
AJ
3339 tcg_gen_shr_tl(t0, t0, t1);
3340 tcg_gen_xori_tl(t1, t1, 63);
3341 t2 = tcg_const_tl(0xfffffffffffffffeull);
3342 tcg_gen_shl_tl(t2, t2, t1);
78723684 3343 gen_load_gpr(t1, rt);
fc40787a
AJ
3344 tcg_gen_and_tl(t1, t1, t2);
3345 tcg_temp_free(t2);
3346 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3347 tcg_temp_free(t1);
fc40787a 3348 gen_store_gpr(t0, rt);
6af0bf9c 3349 break;
364d4831 3350 case OPC_LDPC:
3cee3050 3351 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 3352 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 3353 tcg_temp_free(t1);
dd4096cd 3354 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
364d4831
NF
3355 gen_store_gpr(t0, rt);
3356 break;
6af0bf9c 3357#endif
364d4831 3358 case OPC_LWPC:
3cee3050 3359 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 3360 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 3361 tcg_temp_free(t1);
dd4096cd 3362 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
364d4831
NF
3363 gen_store_gpr(t0, rt);
3364 break;
76964147
JH
3365 case OPC_LWE:
3366 mem_idx = MIPS_HFLAG_UM;
3367 /* fall through */
6af0bf9c 3368 case OPC_LW:
dd4096cd 3369 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
be3a8c53 3370 ctx->default_tcg_memop_mask);
78723684 3371 gen_store_gpr(t0, rt);
6af0bf9c 3372 break;
76964147
JH
3373 case OPC_LHE:
3374 mem_idx = MIPS_HFLAG_UM;
3375 /* fall through */
6af0bf9c 3376 case OPC_LH:
dd4096cd 3377 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
be3a8c53 3378 ctx->default_tcg_memop_mask);
78723684 3379 gen_store_gpr(t0, rt);
6af0bf9c 3380 break;
76964147
JH
3381 case OPC_LHUE:
3382 mem_idx = MIPS_HFLAG_UM;
3383 /* fall through */
6af0bf9c 3384 case OPC_LHU:
dd4096cd 3385 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
be3a8c53 3386 ctx->default_tcg_memop_mask);
78723684 3387 gen_store_gpr(t0, rt);
6af0bf9c 3388 break;
76964147
JH
3389 case OPC_LBE:
3390 mem_idx = MIPS_HFLAG_UM;
3391 /* fall through */
6af0bf9c 3392 case OPC_LB:
dd4096cd 3393 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
78723684 3394 gen_store_gpr(t0, rt);
6af0bf9c 3395 break;
76964147
JH
3396 case OPC_LBUE:
3397 mem_idx = MIPS_HFLAG_UM;
3398 /* fall through */
6af0bf9c 3399 case OPC_LBU:
dd4096cd 3400 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
78723684 3401 gen_store_gpr(t0, rt);
6af0bf9c 3402 break;
76964147
JH
3403 case OPC_LWLE:
3404 mem_idx = MIPS_HFLAG_UM;
3405 /* fall through */
6af0bf9c 3406 case OPC_LWL:
3cee3050 3407 t1 = tcg_temp_new();
908680c6
AJ
3408 /* Do a byte access to possibly trigger a page
3409 fault with the unaligned address. */
dd4096cd 3410 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
3411 tcg_gen_andi_tl(t1, t0, 3);
3412#ifndef TARGET_WORDS_BIGENDIAN
3413 tcg_gen_xori_tl(t1, t1, 3);
3414#endif
3415 tcg_gen_shli_tl(t1, t1, 3);
3416 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 3417 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a 3418 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
3419 t2 = tcg_const_tl(-1);
3420 tcg_gen_shl_tl(t2, t2, t1);
6958549d 3421 gen_load_gpr(t1, rt);
eb02cc3f 3422 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
3423 tcg_temp_free(t2);
3424 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3425 tcg_temp_free(t1);
fc40787a
AJ
3426 tcg_gen_ext32s_tl(t0, t0);
3427 gen_store_gpr(t0, rt);
6af0bf9c 3428 break;
76964147
JH
3429 case OPC_LWRE:
3430 mem_idx = MIPS_HFLAG_UM;
3431 /* fall through */
6af0bf9c 3432 case OPC_LWR:
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, 3);
3438#ifdef TARGET_WORDS_BIGENDIAN
3439 tcg_gen_xori_tl(t1, t1, 3);
3440#endif
3441 tcg_gen_shli_tl(t1, t1, 3);
3442 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 3443 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a
AJ
3444 tcg_gen_shr_tl(t0, t0, t1);
3445 tcg_gen_xori_tl(t1, t1, 31);
3446 t2 = tcg_const_tl(0xfffffffeull);
3447 tcg_gen_shl_tl(t2, t2, t1);
6958549d 3448 gen_load_gpr(t1, rt);
fc40787a
AJ
3449 tcg_gen_and_tl(t1, t1, t2);
3450 tcg_temp_free(t2);
3451 tcg_gen_or_tl(t0, t0, t1);
3cee3050 3452 tcg_temp_free(t1);
c728154b 3453 tcg_gen_ext32s_tl(t0, t0);
fc40787a 3454 gen_store_gpr(t0, rt);
6af0bf9c 3455 break;
76964147
JH
3456 case OPC_LLE:
3457 mem_idx = MIPS_HFLAG_UM;
3458 /* fall through */
6af0bf9c 3459 case OPC_LL:
4368b29a 3460 case R6_OPC_LL:
dd4096cd 3461 op_ld_ll(t0, t0, mem_idx, ctx);
78723684 3462 gen_store_gpr(t0, rt);
6af0bf9c 3463 break;
d66c7132 3464 }
d66c7132 3465 tcg_temp_free(t0);
d66c7132
AJ
3466}
3467
0b16dcd1
AR
3468static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3469 uint32_t reg1, uint32_t reg2)
3470{
3471 TCGv taddr = tcg_temp_new();
3472 TCGv_i64 tval = tcg_temp_new_i64();
3473 TCGv tmp1 = tcg_temp_new();
3474 TCGv tmp2 = tcg_temp_new();
3475
3476 gen_base_offset_addr(ctx, taddr, base, offset);
3477 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3478#ifdef TARGET_WORDS_BIGENDIAN
3479 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3480#else
3481 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3482#endif
3483 gen_store_gpr(tmp1, reg1);
3484 tcg_temp_free(tmp1);
3485 gen_store_gpr(tmp2, reg2);
3486 tcg_temp_free(tmp2);
3487 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3488 tcg_temp_free_i64(tval);
3489 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3490 tcg_temp_free(taddr);
3491}
3492
5c13fdfd
AJ
3493/* Store */
3494static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
72e1f16f 3495 int base, int offset)
5c13fdfd 3496{
5c13fdfd
AJ
3497 TCGv t0 = tcg_temp_new();
3498 TCGv t1 = tcg_temp_new();
dd4096cd 3499 int mem_idx = ctx->mem_idx;
5c13fdfd
AJ
3500
3501 gen_base_offset_addr(ctx, t0, base, offset);
3502 gen_load_gpr(t1, rt);
3503 switch (opc) {
3504#if defined(TARGET_MIPS64)
3505 case OPC_SD:
dd4096cd 3506 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
be3a8c53 3507 ctx->default_tcg_memop_mask);
5c13fdfd
AJ
3508 break;
3509 case OPC_SDL:
dd4096cd 3510 gen_helper_0e2i(sdl, t1, t0, mem_idx);
5c13fdfd
AJ
3511 break;
3512 case OPC_SDR:
dd4096cd 3513 gen_helper_0e2i(sdr, t1, t0, mem_idx);
5c13fdfd
AJ
3514 break;
3515#endif
76964147
JH
3516 case OPC_SWE:
3517 mem_idx = MIPS_HFLAG_UM;
3518 /* fall through */
5c13fdfd 3519 case OPC_SW:
dd4096cd 3520 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
be3a8c53 3521 ctx->default_tcg_memop_mask);
5c13fdfd 3522 break;
76964147
JH
3523 case OPC_SHE:
3524 mem_idx = MIPS_HFLAG_UM;
3525 /* fall through */
5c13fdfd 3526 case OPC_SH:
dd4096cd 3527 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
be3a8c53 3528 ctx->default_tcg_memop_mask);
5c13fdfd 3529 break;
76964147
JH
3530 case OPC_SBE:
3531 mem_idx = MIPS_HFLAG_UM;
3532 /* fall through */
5c13fdfd 3533 case OPC_SB:
dd4096cd 3534 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
5c13fdfd 3535 break;
76964147
JH
3536 case OPC_SWLE:
3537 mem_idx = MIPS_HFLAG_UM;
3538 /* fall through */
5c13fdfd 3539 case OPC_SWL:
dd4096cd 3540 gen_helper_0e2i(swl, t1, t0, mem_idx);
5c13fdfd 3541 break;
76964147
JH
3542 case OPC_SWRE:
3543 mem_idx = MIPS_HFLAG_UM;
3544 /* fall through */
5c13fdfd 3545 case OPC_SWR:
dd4096cd 3546 gen_helper_0e2i(swr, t1, t0, mem_idx);
5c13fdfd
AJ
3547 break;
3548 }
5c13fdfd
AJ
3549 tcg_temp_free(t0);
3550 tcg_temp_free(t1);
3551}
3552
3553
d66c7132
AJ
3554/* Store conditional */
3555static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
3556 int base, int16_t offset)
3557{
d66c7132 3558 TCGv t0, t1;
dd4096cd 3559 int mem_idx = ctx->mem_idx;
d66c7132 3560
2d2826b9 3561#ifdef CONFIG_USER_ONLY
d66c7132 3562 t0 = tcg_temp_local_new();
d66c7132 3563 t1 = tcg_temp_local_new();
2d2826b9
AJ
3564#else
3565 t0 = tcg_temp_new();
3566 t1 = tcg_temp_new();
3567#endif
3568 gen_base_offset_addr(ctx, t0, base, offset);
d66c7132
AJ
3569 gen_load_gpr(t1, rt);
3570 switch (opc) {
3571#if defined(TARGET_MIPS64)
3572 case OPC_SCD:
bf7910c6 3573 case R6_OPC_SCD:
dd4096cd 3574 op_st_scd(t1, t0, rt, mem_idx, ctx);
d66c7132
AJ
3575 break;
3576#endif
76964147
JH
3577 case OPC_SCE:
3578 mem_idx = MIPS_HFLAG_UM;
3579 /* fall through */
6af0bf9c 3580 case OPC_SC:
4368b29a 3581 case R6_OPC_SC:
dd4096cd 3582 op_st_sc(t1, t0, rt, mem_idx, ctx);
6af0bf9c 3583 break;
6af0bf9c 3584 }
78723684 3585 tcg_temp_free(t1);
d66c7132 3586 tcg_temp_free(t0);
6af0bf9c
FB
3587}
3588
0b16dcd1
AR
3589static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3590 uint32_t reg1, uint32_t reg2)
3591{
3592 TCGv taddr = tcg_temp_local_new();
3593 TCGv lladdr = tcg_temp_local_new();
3594 TCGv_i64 tval = tcg_temp_new_i64();
3595 TCGv_i64 llval = tcg_temp_new_i64();
3596 TCGv_i64 val = tcg_temp_new_i64();
3597 TCGv tmp1 = tcg_temp_new();
3598 TCGv tmp2 = tcg_temp_new();
3599 TCGLabel *lab_fail = gen_new_label();
3600 TCGLabel *lab_done = gen_new_label();
3601
3602 gen_base_offset_addr(ctx, taddr, base, offset);
3603
3604 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3605 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3606
3607 gen_load_gpr(tmp1, reg1);
3608 gen_load_gpr(tmp2, reg2);
3609
3610#ifdef TARGET_WORDS_BIGENDIAN
3611 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3612#else
3613 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3614#endif
3615
3616 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3617 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3618 ctx->mem_idx, MO_64);
3619 if (reg1 != 0) {
3620 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3621 }
3622 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3623
3624 gen_set_label(lab_fail);
3625
3626 if (reg1 != 0) {
3627 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3628 }
3629 gen_set_label(lab_done);
3630 tcg_gen_movi_tl(lladdr, -1);
3631 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3632}
3633
6ea83fed 3634/* Load and store */
7a387fff 3635static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
b52d3bfa 3636 TCGv t0)
6ea83fed 3637{
6ea83fed 3638 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 3639 memory access. */
6ea83fed
FB
3640 switch (opc) {
3641 case OPC_LWC1:
b6d96bed 3642 {
a7812ae4 3643 TCGv_i32 fp0 = tcg_temp_new_i32();
be3a8c53
YK
3644 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3645 ctx->default_tcg_memop_mask);
7c979afd 3646 gen_store_fpr32(ctx, fp0, ft);
a7812ae4 3647 tcg_temp_free_i32(fp0);
b6d96bed 3648 }
6ea83fed
FB
3649 break;
3650 case OPC_SWC1:
b6d96bed 3651 {
a7812ae4 3652 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 3653 gen_load_fpr32(ctx, fp0, ft);
be3a8c53
YK
3654 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3655 ctx->default_tcg_memop_mask);
a7812ae4 3656 tcg_temp_free_i32(fp0);
b6d96bed 3657 }
6ea83fed
FB
3658 break;
3659 case OPC_LDC1:
b6d96bed 3660 {
a7812ae4 3661 TCGv_i64 fp0 = tcg_temp_new_i64();
be3a8c53
YK
3662 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3663 ctx->default_tcg_memop_mask);
b6d96bed 3664 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 3665 tcg_temp_free_i64(fp0);
b6d96bed 3666 }
6ea83fed
FB
3667 break;
3668 case OPC_SDC1:
b6d96bed 3669 {
a7812ae4 3670 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 3671 gen_load_fpr64(ctx, fp0, ft);
be3a8c53
YK
3672 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3673 ctx->default_tcg_memop_mask);
a7812ae4 3674 tcg_temp_free_i64(fp0);
b6d96bed 3675 }
6ea83fed
FB
3676 break;
3677 default:
9d68ac14 3678 MIPS_INVAL("flt_ldst");
9c708c7f 3679 generate_exception_end(ctx, EXCP_RI);
b52d3bfa 3680 break;
6ea83fed 3681 }
6ea83fed 3682}
6ea83fed 3683
5ab5c041
AJ
3684static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3685 int rs, int16_t imm)
26ebe468 3686{
b52d3bfa
YK
3687 TCGv t0 = tcg_temp_new();
3688
5ab5c041 3689 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26ebe468 3690 check_cp1_enabled(ctx);
d9224450
MR
3691 switch (op) {
3692 case OPC_LDC1:
3693 case OPC_SDC1:
3694 check_insn(ctx, ISA_MIPS2);
3695 /* Fallthrough */
3696 default:
b52d3bfa
YK
3697 gen_base_offset_addr(ctx, t0, rs, imm);
3698 gen_flt_ldst(ctx, op, rt, t0);
d9224450 3699 }
26ebe468
NF
3700 } else {
3701 generate_exception_err(ctx, EXCP_CpU, 1);
3702 }
b52d3bfa 3703 tcg_temp_free(t0);
26ebe468
NF
3704}
3705
6af0bf9c 3706/* Arithmetic with immediate operand */
d75c135e 3707static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
72e1f16f 3708 int rt, int rs, int imm)
6af0bf9c 3709{
324d9e32 3710 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
6af0bf9c 3711
7a387fff 3712 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
ead9360e
TS
3713 /* If no destination, treat it as a NOP.
3714 For addi, we must generate the overflow exception when needed. */
324d9e32 3715 return;
6af0bf9c
FB
3716 }
3717 switch (opc) {
3718 case OPC_ADDI:
48d38ca5 3719 {
324d9e32
AJ
3720 TCGv t0 = tcg_temp_local_new();
3721 TCGv t1 = tcg_temp_new();
3722 TCGv t2 = tcg_temp_new();
42a268c2 3723 TCGLabel *l1 = gen_new_label();
48d38ca5 3724
324d9e32
AJ
3725 gen_load_gpr(t1, rs);
3726 tcg_gen_addi_tl(t0, t1, uimm);
3727 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 3728
324d9e32
AJ
3729 tcg_gen_xori_tl(t1, t1, ~uimm);
3730 tcg_gen_xori_tl(t2, t0, uimm);
3731 tcg_gen_and_tl(t1, t1, t2);
3732 tcg_temp_free(t2);
3733 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3734 tcg_temp_free(t1);
48d38ca5
TS
3735 /* operands of same sign, result different sign */
3736 generate_exception(ctx, EXCP_OVERFLOW);
3737 gen_set_label(l1);
78723684 3738 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
3739 gen_store_gpr(t0, rt);
3740 tcg_temp_free(t0);
48d38ca5 3741 }
6af0bf9c
FB
3742 break;
3743 case OPC_ADDIU:
324d9e32
AJ
3744 if (rs != 0) {
3745 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3746 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3747 } else {
3748 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3749 }
6af0bf9c 3750 break;
d26bc211 3751#if defined(TARGET_MIPS64)
7a387fff 3752 case OPC_DADDI:
48d38ca5 3753 {
324d9e32
AJ
3754 TCGv t0 = tcg_temp_local_new();
3755 TCGv t1 = tcg_temp_new();
3756 TCGv t2 = tcg_temp_new();
42a268c2 3757 TCGLabel *l1 = gen_new_label();
48d38ca5 3758
324d9e32
AJ
3759 gen_load_gpr(t1, rs);
3760 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 3761
324d9e32
AJ
3762 tcg_gen_xori_tl(t1, t1, ~uimm);
3763 tcg_gen_xori_tl(t2, t0, uimm);
3764 tcg_gen_and_tl(t1, t1, t2);
3765 tcg_temp_free(t2);
3766 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3767 tcg_temp_free(t1);
48d38ca5
TS
3768 /* operands of same sign, result different sign */
3769 generate_exception(ctx, EXCP_OVERFLOW);
3770 gen_set_label(l1);
324d9e32
AJ
3771 gen_store_gpr(t0, rt);
3772 tcg_temp_free(t0);
48d38ca5 3773 }
7a387fff
TS
3774 break;
3775 case OPC_DADDIU:
324d9e32
AJ
3776 if (rs != 0) {
3777 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3778 } else {
3779 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3780 }
7a387fff
TS
3781 break;
3782#endif
324d9e32 3783 }
324d9e32
AJ
3784}
3785
3786/* Logic with immediate operand */
d75c135e 3787static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3788 int rt, int rs, int16_t imm)
324d9e32
AJ
3789{
3790 target_ulong uimm;
324d9e32
AJ
3791
3792 if (rt == 0) {
3793 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3794 return;
3795 }
3796 uimm = (uint16_t)imm;
3797 switch (opc) {
6af0bf9c 3798 case OPC_ANDI:
324d9e32
AJ
3799 if (likely(rs != 0))
3800 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3801 else
3802 tcg_gen_movi_tl(cpu_gpr[rt], 0);
6af0bf9c
FB
3803 break;
3804 case OPC_ORI:
324d9e32
AJ
3805 if (rs != 0)
3806 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3807 else
3808 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
3809 break;
3810 case OPC_XORI:
324d9e32
AJ
3811 if (likely(rs != 0))
3812 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3813 else
3814 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
3815 break;
3816 case OPC_LUI:
d4ea6acd
LA
3817 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3818 /* OPC_AUI */
3819 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3820 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
d4ea6acd
LA
3821 } else {
3822 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
d4ea6acd 3823 }
7c2c3ea3
EJ
3824 break;
3825
3826 default:
6af0bf9c 3827 break;
324d9e32 3828 }
324d9e32
AJ
3829}
3830
3831/* Set on less than with immediate operand */
d75c135e 3832static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3833 int rt, int rs, int16_t imm)
324d9e32
AJ
3834{
3835 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
324d9e32
AJ
3836 TCGv t0;
3837
3838 if (rt == 0) {
3839 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3840 return;
3841 }
3842 t0 = tcg_temp_new();
3843 gen_load_gpr(t0, rs);
3844 switch (opc) {
3845 case OPC_SLTI:
e68dd28f 3846 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
3847 break;
3848 case OPC_SLTIU:
e68dd28f 3849 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
3850 break;
3851 }
324d9e32
AJ
3852 tcg_temp_free(t0);
3853}
3854
3855/* Shifts with immediate operand */
d75c135e 3856static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
324d9e32
AJ
3857 int rt, int rs, int16_t imm)
3858{
3859 target_ulong uimm = ((uint16_t)imm) & 0x1f;
324d9e32
AJ
3860 TCGv t0;
3861
3862 if (rt == 0) {
3863 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3864 return;
3865 }
3866
3867 t0 = tcg_temp_new();
3868 gen_load_gpr(t0, rs);
3869 switch (opc) {
6af0bf9c 3870 case OPC_SLL:
78723684 3871 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 3872 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
3873 break;
3874 case OPC_SRA:
324d9e32 3875 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
3876 break;
3877 case OPC_SRL:
ea63e2c3
NF
3878 if (uimm != 0) {
3879 tcg_gen_ext32u_tl(t0, t0);
3880 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3881 } else {
3882 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 3883 }
ea63e2c3
NF
3884 break;
3885 case OPC_ROTR:
3886 if (uimm != 0) {
3887 TCGv_i32 t1 = tcg_temp_new_i32();
3888
3889 tcg_gen_trunc_tl_i32(t1, t0);
3890 tcg_gen_rotri_i32(t1, t1, uimm);
3891 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3892 tcg_temp_free_i32(t1);
3399e30f
NF
3893 } else {
3894 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3 3895 }
7a387fff 3896 break;
d26bc211 3897#if defined(TARGET_MIPS64)
7a387fff 3898 case OPC_DSLL:
324d9e32 3899 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
3900 break;
3901 case OPC_DSRA:
324d9e32 3902 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
3903 break;
3904 case OPC_DSRL:
ea63e2c3 3905 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
ea63e2c3
NF
3906 break;
3907 case OPC_DROTR:
3908 if (uimm != 0) {
3909 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
3910 } else {
3911 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 3912 }
7a387fff
TS
3913 break;
3914 case OPC_DSLL32:
324d9e32 3915 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
3916 break;
3917 case OPC_DSRA32:
324d9e32 3918 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
3919 break;
3920 case OPC_DSRL32:
ea63e2c3 3921 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
ea63e2c3
NF
3922 break;
3923 case OPC_DROTR32:
3924 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
6af0bf9c 3925 break;
7a387fff 3926#endif
6af0bf9c 3927 }
78723684 3928 tcg_temp_free(t0);
6af0bf9c
FB
3929}
3930
3931/* Arithmetic */
d75c135e
AJ
3932static void gen_arith(DisasContext *ctx, uint32_t opc,
3933 int rd, int rs, int rt)
6af0bf9c 3934{
7a387fff
TS
3935 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3936 && opc != OPC_DADD && opc != OPC_DSUB) {
ead9360e
TS
3937 /* If no destination, treat it as a NOP.
3938 For add & sub, we must generate the overflow exception when needed. */
460f00c4 3939 return;
185f0762 3940 }
460f00c4 3941
6af0bf9c
FB
3942 switch (opc) {
3943 case OPC_ADD:
48d38ca5 3944 {
460f00c4
AJ
3945 TCGv t0 = tcg_temp_local_new();
3946 TCGv t1 = tcg_temp_new();
3947 TCGv t2 = tcg_temp_new();
42a268c2 3948 TCGLabel *l1 = gen_new_label();
48d38ca5 3949
460f00c4
AJ
3950 gen_load_gpr(t1, rs);
3951 gen_load_gpr(t2, rt);
3952 tcg_gen_add_tl(t0, t1, t2);
3953 tcg_gen_ext32s_tl(t0, t0);
3954 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 3955 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 3956 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
3957 tcg_temp_free(t2);
3958 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3959 tcg_temp_free(t1);
48d38ca5
TS
3960 /* operands of same sign, result different sign */
3961 generate_exception(ctx, EXCP_OVERFLOW);
3962 gen_set_label(l1);
460f00c4
AJ
3963 gen_store_gpr(t0, rd);
3964 tcg_temp_free(t0);
48d38ca5 3965 }
6af0bf9c
FB
3966 break;
3967 case OPC_ADDU:
460f00c4
AJ
3968 if (rs != 0 && rt != 0) {
3969 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3970 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3971 } else if (rs == 0 && rt != 0) {
3972 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3973 } else if (rs != 0 && rt == 0) {
3974 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3975 } else {
3976 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3977 }
6af0bf9c
FB
3978 break;
3979 case OPC_SUB:
48d38ca5 3980 {
460f00c4
AJ
3981 TCGv t0 = tcg_temp_local_new();
3982 TCGv t1 = tcg_temp_new();
3983 TCGv t2 = tcg_temp_new();
42a268c2 3984 TCGLabel *l1 = gen_new_label();
48d38ca5 3985
460f00c4
AJ
3986 gen_load_gpr(t1, rs);
3987 gen_load_gpr(t2, rt);
3988 tcg_gen_sub_tl(t0, t1, t2);
3989 tcg_gen_ext32s_tl(t0, t0);
3990 tcg_gen_xor_tl(t2, t1, t2);
3991 tcg_gen_xor_tl(t1, t0, t1);
3992 tcg_gen_and_tl(t1, t1, t2);
3993 tcg_temp_free(t2);
3994 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3995 tcg_temp_free(t1);
31e3104f 3996 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
3997 generate_exception(ctx, EXCP_OVERFLOW);
3998 gen_set_label(l1);
460f00c4
AJ
3999 gen_store_gpr(t0, rd);
4000 tcg_temp_free(t0);
48d38ca5 4001 }
6af0bf9c
FB
4002 break;
4003 case OPC_SUBU:
460f00c4
AJ
4004 if (rs != 0 && rt != 0) {
4005 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4006 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4007 } else if (rs == 0 && rt != 0) {
4008 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 4009 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
4010 } else if (rs != 0 && rt == 0) {
4011 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4012 } else {
4013 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4014 }
6af0bf9c 4015 break;
d26bc211 4016#if defined(TARGET_MIPS64)
7a387fff 4017 case OPC_DADD:
48d38ca5 4018 {
460f00c4
AJ
4019 TCGv t0 = tcg_temp_local_new();
4020 TCGv t1 = tcg_temp_new();
4021 TCGv t2 = tcg_temp_new();
42a268c2 4022 TCGLabel *l1 = gen_new_label();
48d38ca5 4023
460f00c4
AJ
4024 gen_load_gpr(t1, rs);
4025 gen_load_gpr(t2, rt);
4026 tcg_gen_add_tl(t0, t1, t2);
4027 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 4028 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 4029 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
4030 tcg_temp_free(t2);
4031 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4032 tcg_temp_free(t1);
48d38ca5
TS
4033 /* operands of same sign, result different sign */
4034 generate_exception(ctx, EXCP_OVERFLOW);
4035 gen_set_label(l1);
460f00c4
AJ
4036 gen_store_gpr(t0, rd);
4037 tcg_temp_free(t0);
48d38ca5 4038 }
7a387fff
TS
4039 break;
4040 case OPC_DADDU:
460f00c4
AJ
4041 if (rs != 0 && rt != 0) {
4042 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4043 } else if (rs == 0 && rt != 0) {
4044 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4045 } else if (rs != 0 && rt == 0) {
4046 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4047 } else {
4048 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4049 }
7a387fff
TS
4050 break;
4051 case OPC_DSUB:
48d38ca5 4052 {
460f00c4
AJ
4053 TCGv t0 = tcg_temp_local_new();
4054 TCGv t1 = tcg_temp_new();
4055 TCGv t2 = tcg_temp_new();
42a268c2 4056 TCGLabel *l1 = gen_new_label();
48d38ca5 4057
460f00c4
AJ
4058 gen_load_gpr(t1, rs);
4059 gen_load_gpr(t2, rt);
4060 tcg_gen_sub_tl(t0, t1, t2);
4061 tcg_gen_xor_tl(t2, t1, t2);
4062 tcg_gen_xor_tl(t1, t0, t1);
4063 tcg_gen_and_tl(t1, t1, t2);
4064 tcg_temp_free(t2);
4065 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4066 tcg_temp_free(t1);
31e3104f 4067 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
4068 generate_exception(ctx, EXCP_OVERFLOW);
4069 gen_set_label(l1);
460f00c4
AJ
4070 gen_store_gpr(t0, rd);
4071 tcg_temp_free(t0);
48d38ca5 4072 }
7a387fff
TS
4073 break;
4074 case OPC_DSUBU:
460f00c4
AJ
4075 if (rs != 0 && rt != 0) {
4076 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4077 } else if (rs == 0 && rt != 0) {
4078 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4079 } else if (rs != 0 && rt == 0) {
4080 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4081 } else {
4082 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4083 }
7a387fff
TS
4084 break;
4085#endif
460f00c4
AJ
4086 case OPC_MUL:
4087 if (likely(rs != 0 && rt != 0)) {
4088 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4089 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4090 } else {
4091 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4092 }
6af0bf9c 4093 break;
460f00c4 4094 }
460f00c4
AJ
4095}
4096
4097/* Conditional move */
d75c135e 4098static void gen_cond_move(DisasContext *ctx, uint32_t opc,
9fa77488 4099 int rd, int rs, int rt)
460f00c4 4100{
acf12465 4101 TCGv t0, t1, t2;
460f00c4
AJ
4102
4103 if (rd == 0) {
acf12465 4104 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4105 return;
4106 }
4107
acf12465
AJ
4108 t0 = tcg_temp_new();
4109 gen_load_gpr(t0, rt);
4110 t1 = tcg_const_tl(0);
4111 t2 = tcg_temp_new();
4112 gen_load_gpr(t2, rs);
460f00c4
AJ
4113 switch (opc) {
4114 case OPC_MOVN:
acf12465 4115 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
6af0bf9c 4116 break;
460f00c4 4117 case OPC_MOVZ:
acf12465 4118 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
460f00c4 4119 break;
b691d9d2
LA
4120 case OPC_SELNEZ:
4121 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2
LA
4122 break;
4123 case OPC_SELEQZ:
4124 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2 4125 break;
460f00c4 4126 }
acf12465
AJ
4127 tcg_temp_free(t2);
4128 tcg_temp_free(t1);
4129 tcg_temp_free(t0);
460f00c4
AJ
4130}
4131
4132/* Logic */
d75c135e 4133static void gen_logic(DisasContext *ctx, uint32_t opc,
9fa77488 4134 int rd, int rs, int rt)
460f00c4 4135{
460f00c4
AJ
4136 if (rd == 0) {
4137 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4138 return;
4139 }
4140
4141 switch (opc) {
6af0bf9c 4142 case OPC_AND:
460f00c4
AJ
4143 if (likely(rs != 0 && rt != 0)) {
4144 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4145 } else {
4146 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4147 }
6af0bf9c
FB
4148 break;
4149 case OPC_NOR:
460f00c4
AJ
4150 if (rs != 0 && rt != 0) {
4151 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4152 } else if (rs == 0 && rt != 0) {
4153 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4154 } else if (rs != 0 && rt == 0) {
4155 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4156 } else {
4157 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4158 }
6af0bf9c
FB
4159 break;
4160 case OPC_OR:
460f00c4
AJ
4161 if (likely(rs != 0 && rt != 0)) {
4162 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4163 } else if (rs == 0 && rt != 0) {
4164 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4165 } else if (rs != 0 && rt == 0) {
4166 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4167 } else {
4168 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4169 }
6af0bf9c
FB
4170 break;
4171 case OPC_XOR:
460f00c4
AJ
4172 if (likely(rs != 0 && rt != 0)) {
4173 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4174 } else if (rs == 0 && rt != 0) {
4175 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4176 } else if (rs != 0 && rt == 0) {
4177 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4178 } else {
4179 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4180 }
6af0bf9c 4181 break;
460f00c4 4182 }
460f00c4
AJ
4183}
4184
4185/* Set on lower than */
d75c135e 4186static void gen_slt(DisasContext *ctx, uint32_t opc,
9fa77488 4187 int rd, int rs, int rt)
460f00c4 4188{
460f00c4
AJ
4189 TCGv t0, t1;
4190
4191 if (rd == 0) {
4192 /* If no destination, treat it as a NOP. */
460f00c4
AJ
4193 return;
4194 }
4195
4196 t0 = tcg_temp_new();
4197 t1 = tcg_temp_new();
4198 gen_load_gpr(t0, rs);
4199 gen_load_gpr(t1, rt);
4200 switch (opc) {
4201 case OPC_SLT:
e68dd28f 4202 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
6af0bf9c 4203 break;
460f00c4 4204 case OPC_SLTU:
e68dd28f 4205 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
4206 break;
4207 }
460f00c4
AJ
4208 tcg_temp_free(t0);
4209 tcg_temp_free(t1);
4210}
20c4c97c 4211
460f00c4 4212/* Shifts */
d75c135e
AJ
4213static void gen_shift(DisasContext *ctx, uint32_t opc,
4214 int rd, int rs, int rt)
460f00c4 4215{
460f00c4 4216 TCGv t0, t1;
20c4c97c 4217
460f00c4
AJ
4218 if (rd == 0) {
4219 /* If no destination, treat it as a NOP.
4220 For add & sub, we must generate the overflow exception when needed. */
460f00c4
AJ
4221 return;
4222 }
4223
4224 t0 = tcg_temp_new();
4225 t1 = tcg_temp_new();
4226 gen_load_gpr(t0, rs);
4227 gen_load_gpr(t1, rt);
4228 switch (opc) {
6af0bf9c 4229 case OPC_SLLV:
78723684
TS
4230 tcg_gen_andi_tl(t0, t0, 0x1f);
4231 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 4232 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
4233 break;
4234 case OPC_SRAV:
78723684 4235 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 4236 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
4237 break;
4238 case OPC_SRLV:
ea63e2c3
NF
4239 tcg_gen_ext32u_tl(t1, t1);
4240 tcg_gen_andi_tl(t0, t0, 0x1f);
4241 tcg_gen_shr_tl(t0, t1, t0);
4242 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
ea63e2c3
NF
4243 break;
4244 case OPC_ROTRV:
4245 {
4246 TCGv_i32 t2 = tcg_temp_new_i32();
4247 TCGv_i32 t3 = tcg_temp_new_i32();
4248
4249 tcg_gen_trunc_tl_i32(t2, t0);
4250 tcg_gen_trunc_tl_i32(t3, t1);
4251 tcg_gen_andi_i32(t2, t2, 0x1f);
4252 tcg_gen_rotr_i32(t2, t3, t2);
4253 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4254 tcg_temp_free_i32(t2);
4255 tcg_temp_free_i32(t3);
5a63bcb2 4256 }
7a387fff 4257 break;
d26bc211 4258#if defined(TARGET_MIPS64)
7a387fff 4259 case OPC_DSLLV:
78723684 4260 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 4261 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
4262 break;
4263 case OPC_DSRAV:
78723684 4264 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 4265 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
4266 break;
4267 case OPC_DSRLV:
ea63e2c3
NF
4268 tcg_gen_andi_tl(t0, t0, 0x3f);
4269 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
ea63e2c3
NF
4270 break;
4271 case OPC_DROTRV:
4272 tcg_gen_andi_tl(t0, t0, 0x3f);
4273 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
6af0bf9c 4274 break;
7a387fff 4275#endif
6af0bf9c 4276 }
78723684
TS
4277 tcg_temp_free(t0);
4278 tcg_temp_free(t1);
6af0bf9c
FB
4279}
4280
4281/* Arithmetic on HI/LO registers */
26135ead 4282static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
6af0bf9c 4283{
8d927f7c
FN
4284 if (reg == 0 && (opc == OPC_MFHI || opc == TX79_MMI_MFHI1 ||
4285 opc == OPC_MFLO || opc == TX79_MMI_MFLO1)) {
ead9360e 4286 /* Treat as NOP. */
a1f6684d 4287 return;
6af0bf9c 4288 }
4133498f 4289
4133498f 4290 if (acc != 0) {
8d927f7c
FN
4291 if (!(ctx->insn_flags & INSN_R5900)) {
4292 check_dsp(ctx);
4293 }
4133498f
JL
4294 }
4295
6af0bf9c
FB
4296 switch (opc) {
4297 case OPC_MFHI:
8d927f7c 4298 case TX79_MMI_MFHI1:
4133498f
JL
4299#if defined(TARGET_MIPS64)
4300 if (acc != 0) {
4301 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4302 } else
4303#endif
4304 {
4305 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4306 }
6af0bf9c
FB
4307 break;
4308 case OPC_MFLO:
8d927f7c 4309 case TX79_MMI_MFLO1:
4133498f
JL
4310#if defined(TARGET_MIPS64)
4311 if (acc != 0) {
4312 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4313 } else
4314#endif
4315 {
4316 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4317 }
6af0bf9c
FB
4318 break;
4319 case OPC_MTHI:
8d927f7c 4320 case TX79_MMI_MTHI1:
4133498f
JL
4321 if (reg != 0) {
4322#if defined(TARGET_MIPS64)
4323 if (acc != 0) {
4324 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4325 } else
4326#endif
4327 {
4328 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4329 }
4330 } else {
4331 tcg_gen_movi_tl(cpu_HI[acc], 0);
4332 }
6af0bf9c
FB
4333 break;
4334 case OPC_MTLO:
8d927f7c 4335 case TX79_MMI_MTLO1:
4133498f
JL
4336 if (reg != 0) {
4337#if defined(TARGET_MIPS64)
4338 if (acc != 0) {
4339 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4340 } else
4341#endif
4342 {
4343 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4344 }
4345 } else {
4346 tcg_gen_movi_tl(cpu_LO[acc], 0);
4347 }
6af0bf9c 4348 break;
6af0bf9c 4349 }
6af0bf9c
FB
4350}
4351
d4ea6acd
LA
4352static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4353 TCGMemOp memop)
4354{
4355 TCGv t0 = tcg_const_tl(addr);
4356 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4357 gen_store_gpr(t0, reg);
4358 tcg_temp_free(t0);
4359}
4360
ab39ee45
YK
4361static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4362 int rs)
d4ea6acd
LA
4363{
4364 target_long offset;
4365 target_long addr;
4366
ab39ee45 4367 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
d4ea6acd
LA
4368 case OPC_ADDIUPC:
4369 if (rs != 0) {
4370 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4371 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4372 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4373 }
4374 break;
4375 case R6_OPC_LWPC:
4376 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4377 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4378 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4379 break;
4380#if defined(TARGET_MIPS64)
4381 case OPC_LWUPC:
4382 check_mips_64(ctx);
4383 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 4384 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4385 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4386 break;
4387#endif
4388 default:
ab39ee45 4389 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
d4ea6acd
LA
4390 case OPC_AUIPC:
4391 if (rs != 0) {
ab39ee45
YK
4392 offset = sextract32(ctx->opcode, 0, 16) << 16;
4393 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
4394 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4395 }
4396 break;
4397 case OPC_ALUIPC:
4398 if (rs != 0) {
ab39ee45
YK
4399 offset = sextract32(ctx->opcode, 0, 16) << 16;
4400 addr = ~0xFFFF & addr_add(ctx, pc, offset);
d4ea6acd
LA
4401 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4402 }
4403 break;
4404#if defined(TARGET_MIPS64)
4405 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4406 case R6_OPC_LDPC + (1 << 16):
4407 case R6_OPC_LDPC + (2 << 16):
4408 case R6_OPC_LDPC + (3 << 16):
4409 check_mips_64(ctx);
4410 offset = sextract32(ctx->opcode << 3, 0, 21);
ab39ee45 4411 addr = addr_add(ctx, (pc & ~0x7), offset);
d4ea6acd
LA
4412 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4413 break;
4414#endif
4415 default:
4416 MIPS_INVAL("OPC_PCREL");
9c708c7f 4417 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
4418 break;
4419 }
4420 break;
4421 }
4422}
4423
b42ee5e1
LA
4424static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4425{
b42ee5e1
LA
4426 TCGv t0, t1;
4427
4428 if (rd == 0) {
4429 /* Treat as NOP. */
b42ee5e1
LA
4430 return;
4431 }
4432
4433 t0 = tcg_temp_new();
4434 t1 = tcg_temp_new();
4435
4436 gen_load_gpr(t0, rs);
4437 gen_load_gpr(t1, rt);
4438
4439 switch (opc) {
4440 case R6_OPC_DIV:
4441 {
4442 TCGv t2 = tcg_temp_new();
4443 TCGv t3 = tcg_temp_new();
4444 tcg_gen_ext32s_tl(t0, t0);
4445 tcg_gen_ext32s_tl(t1, t1);
4446 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4447 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4448 tcg_gen_and_tl(t2, t2, t3);
4449 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4450 tcg_gen_or_tl(t2, t2, t3);
4451 tcg_gen_movi_tl(t3, 0);
4452 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4453 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4454 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4455 tcg_temp_free(t3);
4456 tcg_temp_free(t2);
4457 }
b42ee5e1
LA
4458 break;
4459 case R6_OPC_MOD:
4460 {
4461 TCGv t2 = tcg_temp_new();
4462 TCGv t3 = tcg_temp_new();
4463 tcg_gen_ext32s_tl(t0, t0);
4464 tcg_gen_ext32s_tl(t1, t1);
4465 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4466 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4467 tcg_gen_and_tl(t2, t2, t3);
4468 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4469 tcg_gen_or_tl(t2, t2, t3);
4470 tcg_gen_movi_tl(t3, 0);
4471 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4472 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4473 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4474 tcg_temp_free(t3);
4475 tcg_temp_free(t2);
4476 }
b42ee5e1
LA
4477 break;
4478 case R6_OPC_DIVU:
4479 {
4480 TCGv t2 = tcg_const_tl(0);
4481 TCGv t3 = tcg_const_tl(1);
4482 tcg_gen_ext32u_tl(t0, t0);
4483 tcg_gen_ext32u_tl(t1, t1);
4484 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4485 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4486 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4487 tcg_temp_free(t3);
4488 tcg_temp_free(t2);
4489 }
b42ee5e1
LA
4490 break;
4491 case R6_OPC_MODU:
4492 {
4493 TCGv t2 = tcg_const_tl(0);
4494 TCGv t3 = tcg_const_tl(1);
4495 tcg_gen_ext32u_tl(t0, t0);
4496 tcg_gen_ext32u_tl(t1, t1);
4497 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4498 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4499 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4500 tcg_temp_free(t3);
4501 tcg_temp_free(t2);
4502 }
b42ee5e1
LA
4503 break;
4504 case R6_OPC_MUL:
4505 {
4506 TCGv_i32 t2 = tcg_temp_new_i32();
4507 TCGv_i32 t3 = tcg_temp_new_i32();
4508 tcg_gen_trunc_tl_i32(t2, t0);
4509 tcg_gen_trunc_tl_i32(t3, t1);
4510 tcg_gen_mul_i32(t2, t2, t3);
4511 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4512 tcg_temp_free_i32(t2);
4513 tcg_temp_free_i32(t3);
4514 }
b42ee5e1
LA
4515 break;
4516 case R6_OPC_MUH:
4517 {
4518 TCGv_i32 t2 = tcg_temp_new_i32();
4519 TCGv_i32 t3 = tcg_temp_new_i32();
4520 tcg_gen_trunc_tl_i32(t2, t0);
4521 tcg_gen_trunc_tl_i32(t3, t1);
4522 tcg_gen_muls2_i32(t2, t3, t2, t3);
4523 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4524 tcg_temp_free_i32(t2);
4525 tcg_temp_free_i32(t3);
4526 }
b42ee5e1
LA
4527 break;
4528 case R6_OPC_MULU:
4529 {
4530 TCGv_i32 t2 = tcg_temp_new_i32();
4531 TCGv_i32 t3 = tcg_temp_new_i32();
4532 tcg_gen_trunc_tl_i32(t2, t0);
4533 tcg_gen_trunc_tl_i32(t3, t1);
4534 tcg_gen_mul_i32(t2, t2, t3);
4535 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4536 tcg_temp_free_i32(t2);
4537 tcg_temp_free_i32(t3);
4538 }
b42ee5e1
LA
4539 break;
4540 case R6_OPC_MUHU:
4541 {
4542 TCGv_i32 t2 = tcg_temp_new_i32();
4543 TCGv_i32 t3 = tcg_temp_new_i32();
4544 tcg_gen_trunc_tl_i32(t2, t0);
4545 tcg_gen_trunc_tl_i32(t3, t1);
4546 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4547 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4548 tcg_temp_free_i32(t2);
4549 tcg_temp_free_i32(t3);
4550 }
b42ee5e1
LA
4551 break;
4552#if defined(TARGET_MIPS64)
4553 case R6_OPC_DDIV:
4554 {
4555 TCGv t2 = tcg_temp_new();
4556 TCGv t3 = tcg_temp_new();
4557 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4558 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4559 tcg_gen_and_tl(t2, t2, t3);
4560 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4561 tcg_gen_or_tl(t2, t2, t3);
4562 tcg_gen_movi_tl(t3, 0);
4563 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4564 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4565 tcg_temp_free(t3);
4566 tcg_temp_free(t2);
4567 }
b42ee5e1
LA
4568 break;
4569 case R6_OPC_DMOD:
4570 {
4571 TCGv t2 = tcg_temp_new();
4572 TCGv t3 = tcg_temp_new();
4573 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4574 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4575 tcg_gen_and_tl(t2, t2, t3);
4576 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4577 tcg_gen_or_tl(t2, t2, t3);
4578 tcg_gen_movi_tl(t3, 0);
4579 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4580 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4581 tcg_temp_free(t3);
4582 tcg_temp_free(t2);
4583 }
b42ee5e1
LA
4584 break;
4585 case R6_OPC_DDIVU:
4586 {
4587 TCGv t2 = tcg_const_tl(0);
4588 TCGv t3 = tcg_const_tl(1);
4589 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4590 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4591 tcg_temp_free(t3);
4592 tcg_temp_free(t2);
4593 }
b42ee5e1
LA
4594 break;
4595 case R6_OPC_DMODU:
4596 {
4597 TCGv t2 = tcg_const_tl(0);
4598 TCGv t3 = tcg_const_tl(1);
4599 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4600 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4601 tcg_temp_free(t3);
4602 tcg_temp_free(t2);
4603 }
b42ee5e1
LA
4604 break;
4605 case R6_OPC_DMUL:
4606 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
4607 break;
4608 case R6_OPC_DMUH:
4609 {
4610 TCGv t2 = tcg_temp_new();
4611 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4612 tcg_temp_free(t2);
4613 }
b42ee5e1
LA
4614 break;
4615 case R6_OPC_DMULU:
4616 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
4617 break;
4618 case R6_OPC_DMUHU:
4619 {
4620 TCGv t2 = tcg_temp_new();
4621 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4622 tcg_temp_free(t2);
4623 }
b42ee5e1
LA
4624 break;
4625#endif
4626 default:
9d68ac14 4627 MIPS_INVAL("r6 mul/div");
9c708c7f 4628 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
4629 goto out;
4630 }
b42ee5e1
LA
4631 out:
4632 tcg_temp_free(t0);
4633 tcg_temp_free(t1);
4634}
4635
26135ead
RS
4636static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4637 int acc, int rs, int rt)
6af0bf9c 4638{
d45f89f4
AJ
4639 TCGv t0, t1;
4640
51127181
AJ
4641 t0 = tcg_temp_new();
4642 t1 = tcg_temp_new();
6af0bf9c 4643
78723684
TS
4644 gen_load_gpr(t0, rs);
4645 gen_load_gpr(t1, rt);
51127181 4646
26135ead 4647 if (acc != 0) {
be9c42c9
FN
4648 if (!(ctx->insn_flags & INSN_R5900)) {
4649 check_dsp(ctx);
4650 }
26135ead
RS
4651 }
4652
6af0bf9c
FB
4653 switch (opc) {
4654 case OPC_DIV:
be9c42c9 4655 case TX79_MMI_DIV1:
48d38ca5 4656 {
51127181
AJ
4657 TCGv t2 = tcg_temp_new();
4658 TCGv t3 = tcg_temp_new();
d45f89f4
AJ
4659 tcg_gen_ext32s_tl(t0, t0);
4660 tcg_gen_ext32s_tl(t1, t1);
51127181
AJ
4661 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4662 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4663 tcg_gen_and_tl(t2, t2, t3);
4664 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4665 tcg_gen_or_tl(t2, t2, t3);
4666 tcg_gen_movi_tl(t3, 0);
4667 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
4668 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4669 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4670 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4671 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
4672 tcg_temp_free(t3);
4673 tcg_temp_free(t2);
48d38ca5 4674 }
6af0bf9c
FB
4675 break;
4676 case OPC_DIVU:
be9c42c9 4677 case TX79_MMI_DIVU1:
48d38ca5 4678 {
51127181
AJ
4679 TCGv t2 = tcg_const_tl(0);
4680 TCGv t3 = tcg_const_tl(1);
0c0ed03b
AJ
4681 tcg_gen_ext32u_tl(t0, t0);
4682 tcg_gen_ext32u_tl(t1, t1);
51127181 4683 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
4684 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4685 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4686 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4687 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
4688 tcg_temp_free(t3);
4689 tcg_temp_free(t2);
48d38ca5 4690 }
6af0bf9c
FB
4691 break;
4692 case OPC_MULT:
214c465f 4693 {
ce1dd5d1
RH
4694 TCGv_i32 t2 = tcg_temp_new_i32();
4695 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
4696 tcg_gen_trunc_tl_i32(t2, t0);
4697 tcg_gen_trunc_tl_i32(t3, t1);
4698 tcg_gen_muls2_i32(t2, t3, t2, t3);
4699 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4700 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4701 tcg_temp_free_i32(t2);
4702 tcg_temp_free_i32(t3);
214c465f 4703 }
6af0bf9c
FB
4704 break;
4705 case OPC_MULTU:
214c465f 4706 {
ce1dd5d1
RH
4707 TCGv_i32 t2 = tcg_temp_new_i32();
4708 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
4709 tcg_gen_trunc_tl_i32(t2, t0);
4710 tcg_gen_trunc_tl_i32(t3, t1);
4711 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4712 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4713 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4714 tcg_temp_free_i32(t2);
4715 tcg_temp_free_i32(t3);
214c465f 4716 }
6af0bf9c 4717 break;
d26bc211 4718#if defined(TARGET_MIPS64)
7a387fff 4719 case OPC_DDIV:
48d38ca5 4720 {
51127181
AJ
4721 TCGv t2 = tcg_temp_new();
4722 TCGv t3 = tcg_temp_new();
4723 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4724 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4725 tcg_gen_and_tl(t2, t2, t3);
4726 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4727 tcg_gen_or_tl(t2, t2, t3);
4728 tcg_gen_movi_tl(t3, 0);
4729 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
4730 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4731 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
51127181
AJ
4732 tcg_temp_free(t3);
4733 tcg_temp_free(t2);
48d38ca5 4734 }
7a387fff
TS
4735 break;
4736 case OPC_DDIVU:
48d38ca5 4737 {
51127181
AJ
4738 TCGv t2 = tcg_const_tl(0);
4739 TCGv t3 = tcg_const_tl(1);
4740 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
4741 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4742 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
51127181
AJ
4743 tcg_temp_free(t3);
4744 tcg_temp_free(t2);
48d38ca5 4745 }
7a387fff
TS
4746 break;
4747 case OPC_DMULT:
26135ead 4748 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
4749 break;
4750 case OPC_DMULTU:
26135ead 4751 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
4752 break;
4753#endif
6af0bf9c 4754 case OPC_MADD:
214c465f 4755 {
d45f89f4
AJ
4756 TCGv_i64 t2 = tcg_temp_new_i64();
4757 TCGv_i64 t3 = tcg_temp_new_i64();
4758
4759 tcg_gen_ext_tl_i64(t2, t0);
4760 tcg_gen_ext_tl_i64(t3, t1);
4761 tcg_gen_mul_i64(t2, t2, t3);
4133498f 4762 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
4763 tcg_gen_add_i64(t2, t2, t3);
4764 tcg_temp_free_i64(t3);
71f303cd
RH
4765 gen_move_low32(cpu_LO[acc], t2);
4766 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 4767 tcg_temp_free_i64(t2);
214c465f 4768 }
6af0bf9c
FB
4769 break;
4770 case OPC_MADDU:
4133498f 4771 {
d45f89f4
AJ
4772 TCGv_i64 t2 = tcg_temp_new_i64();
4773 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 4774
78723684
TS
4775 tcg_gen_ext32u_tl(t0, t0);
4776 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
4777 tcg_gen_extu_tl_i64(t2, t0);
4778 tcg_gen_extu_tl_i64(t3, t1);
4779 tcg_gen_mul_i64(t2, t2, t3);
4133498f 4780 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
4781 tcg_gen_add_i64(t2, t2, t3);
4782 tcg_temp_free_i64(t3);
71f303cd
RH
4783 gen_move_low32(cpu_LO[acc], t2);
4784 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 4785 tcg_temp_free_i64(t2);
214c465f 4786 }
6af0bf9c
FB
4787 break;
4788 case OPC_MSUB:
214c465f 4789 {
d45f89f4
AJ
4790 TCGv_i64 t2 = tcg_temp_new_i64();
4791 TCGv_i64 t3 = tcg_temp_new_i64();
4792
4793 tcg_gen_ext_tl_i64(t2, t0);
4794 tcg_gen_ext_tl_i64(t3, t1);
4795 tcg_gen_mul_i64(t2, t2, t3);
4133498f 4796 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 4797 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 4798 tcg_temp_free_i64(t3);
71f303cd
RH
4799 gen_move_low32(cpu_LO[acc], t2);
4800 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 4801 tcg_temp_free_i64(t2);
214c465f 4802 }
6af0bf9c
FB
4803 break;
4804 case OPC_MSUBU:
214c465f 4805 {
d45f89f4
AJ
4806 TCGv_i64 t2 = tcg_temp_new_i64();
4807 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 4808
78723684
TS
4809 tcg_gen_ext32u_tl(t0, t0);
4810 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
4811 tcg_gen_extu_tl_i64(t2, t0);
4812 tcg_gen_extu_tl_i64(t3, t1);
4813 tcg_gen_mul_i64(t2, t2, t3);
4133498f 4814 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 4815 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 4816 tcg_temp_free_i64(t3);
71f303cd
RH
4817 gen_move_low32(cpu_LO[acc], t2);
4818 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 4819 tcg_temp_free_i64(t2);
214c465f 4820 }
6af0bf9c
FB
4821 break;
4822 default:
9d68ac14 4823 MIPS_INVAL("mul/div");
9c708c7f 4824 generate_exception_end(ctx, EXCP_RI);
78723684 4825 goto out;
6af0bf9c 4826 }
78723684
TS
4827 out:
4828 tcg_temp_free(t0);
4829 tcg_temp_free(t1);
6af0bf9c
FB
4830}
4831
21e8e8b2
FN
4832/*
4833 * These MULT and MULTU instructions implemented in for example the
4834 * Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
4835 * architectures are special three-operand variants with the syntax
4836 *
06de726b 4837 * MULT[U][1] rd, rs, rt
21e8e8b2
FN
4838 *
4839 * such that
4840 *
4841 * (rd, LO, HI) <- rs * rt
4842 *
4843 * where the low-order 32-bits of the result is placed into both the
4844 * GPR rd and the special register LO. The high-order 32-bits of the
4845 * result is placed into the special register HI.
4846 *
4847 * If the GPR rd is omitted in assembly language, it is taken to be 0,
4848 * which is the zero register that always reads as 0.
4849 */
4850static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
4851 int rd, int rs, int rt)
4852{
4853 TCGv t0 = tcg_temp_new();
4854 TCGv t1 = tcg_temp_new();
4855 int acc = 0;
4856
4857 gen_load_gpr(t0, rs);
4858 gen_load_gpr(t1, rt);
4859
4860 switch (opc) {
06de726b
FN
4861 case TX79_MMI_MULT1:
4862 acc = 1;
4863 /* Fall through */
21e8e8b2
FN
4864 case OPC_MULT:
4865 {
4866 TCGv_i32 t2 = tcg_temp_new_i32();
4867 TCGv_i32 t3 = tcg_temp_new_i32();
4868 tcg_gen_trunc_tl_i32(t2, t0);
4869 tcg_gen_trunc_tl_i32(t3, t1);
4870 tcg_gen_muls2_i32(t2, t3, t2, t3);
4871 if (rd) {
4872 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4873 }
4874 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4875 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4876 tcg_temp_free_i32(t2);
4877 tcg_temp_free_i32(t3);
4878 }
4879 break;
06de726b
FN
4880 case TX79_MMI_MULTU1:
4881 acc = 1;
4882 /* Fall through */
21e8e8b2
FN
4883 case OPC_MULTU:
4884 {
4885 TCGv_i32 t2 = tcg_temp_new_i32();
4886 TCGv_i32 t3 = tcg_temp_new_i32();
4887 tcg_gen_trunc_tl_i32(t2, t0);
4888 tcg_gen_trunc_tl_i32(t3, t1);
4889 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4890 if (rd) {
4891 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4892 }
4893 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4894 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4895 tcg_temp_free_i32(t2);
4896 tcg_temp_free_i32(t3);
4897 }
4898 break;
4899 default:
4900 MIPS_INVAL("mul TXx9");
4901 generate_exception_end(ctx, EXCP_RI);
4902 goto out;
4903 }
4904
4905 out:
4906 tcg_temp_free(t0);
4907 tcg_temp_free(t1);
4908}
4909
e9c71dd1
TS
4910static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
4911 int rd, int rs, int rt)
4912{
f157bfe1
AJ
4913 TCGv t0 = tcg_temp_new();
4914 TCGv t1 = tcg_temp_new();
e9c71dd1 4915
6c5c1e20
TS
4916 gen_load_gpr(t0, rs);
4917 gen_load_gpr(t1, rt);
e9c71dd1
TS
4918
4919 switch (opc) {
4920 case OPC_VR54XX_MULS:
895c2d04 4921 gen_helper_muls(t0, cpu_env, t0, t1);
6958549d 4922 break;
e9c71dd1 4923 case OPC_VR54XX_MULSU:
895c2d04 4924 gen_helper_mulsu(t0, cpu_env, t0, t1);
6958549d 4925 break;
e9c71dd1 4926 case OPC_VR54XX_MACC:
895c2d04 4927 gen_helper_macc(t0, cpu_env, t0, t1);
6958549d 4928 break;
e9c71dd1 4929 case OPC_VR54XX_MACCU:
895c2d04 4930 gen_helper_maccu(t0, cpu_env, t0, t1);
6958549d 4931 break;
e9c71dd1 4932 case OPC_VR54XX_MSAC:
895c2d04 4933 gen_helper_msac(t0, cpu_env, t0, t1);
6958549d 4934 break;
e9c71dd1 4935 case OPC_VR54XX_MSACU:
895c2d04 4936 gen_helper_msacu(t0, cpu_env, t0, t1);
6958549d 4937 break;
e9c71dd1 4938 case OPC_VR54XX_MULHI:
895c2d04 4939 gen_helper_mulhi(t0, cpu_env, t0, t1);
6958549d 4940 break;
e9c71dd1 4941 case OPC_VR54XX_MULHIU:
895c2d04 4942 gen_helper_mulhiu(t0, cpu_env, t0, t1);
6958549d 4943 break;
e9c71dd1 4944 case OPC_VR54XX_MULSHI:
895c2d04 4945 gen_helper_mulshi(t0, cpu_env, t0, t1);
6958549d 4946 break;
e9c71dd1 4947 case OPC_VR54XX_MULSHIU:
895c2d04 4948 gen_helper_mulshiu(t0, cpu_env, t0, t1);
6958549d 4949 break;
e9c71dd1 4950 case OPC_VR54XX_MACCHI:
895c2d04 4951 gen_helper_macchi(t0, cpu_env, t0, t1);
6958549d 4952 break;
e9c71dd1 4953 case OPC_VR54XX_MACCHIU:
895c2d04 4954 gen_helper_macchiu(t0, cpu_env, t0, t1);
6958549d 4955 break;
e9c71dd1 4956 case OPC_VR54XX_MSACHI:
895c2d04 4957 gen_helper_msachi(t0, cpu_env, t0, t1);
6958549d 4958 break;
e9c71dd1 4959 case OPC_VR54XX_MSACHIU:
895c2d04 4960 gen_helper_msachiu(t0, cpu_env, t0, t1);
6958549d 4961 break;
e9c71dd1
TS
4962 default:
4963 MIPS_INVAL("mul vr54xx");
9c708c7f 4964 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 4965 goto out;
e9c71dd1 4966 }
6c5c1e20 4967 gen_store_gpr(t0, rd);
6c5c1e20
TS
4968
4969 out:
4970 tcg_temp_free(t0);
4971 tcg_temp_free(t1);
e9c71dd1
TS
4972}
4973
7a387fff 4974static void gen_cl (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
4975 int rd, int rs)
4976{
20e1fb52 4977 TCGv t0;
6c5c1e20 4978
6af0bf9c 4979 if (rd == 0) {
ead9360e 4980 /* Treat as NOP. */
20e1fb52 4981 return;
6af0bf9c 4982 }
1a0196c5 4983 t0 = cpu_gpr[rd];
6c5c1e20 4984 gen_load_gpr(t0, rs);
1a0196c5 4985
6af0bf9c
FB
4986 switch (opc) {
4987 case OPC_CLO:
4267d3e6 4988 case R6_OPC_CLO:
1a0196c5
RH
4989#if defined(TARGET_MIPS64)
4990 case OPC_DCLO:
4991 case R6_OPC_DCLO:
4992#endif
4993 tcg_gen_not_tl(t0, t0);
6af0bf9c 4994 break;
1a0196c5
RH
4995 }
4996
4997 switch (opc) {
4998 case OPC_CLO:
4999 case R6_OPC_CLO:
6af0bf9c 5000 case OPC_CLZ:
4267d3e6 5001 case R6_OPC_CLZ:
1a0196c5
RH
5002 tcg_gen_ext32u_tl(t0, t0);
5003 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5004 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
6af0bf9c 5005 break;
d26bc211 5006#if defined(TARGET_MIPS64)
7a387fff 5007 case OPC_DCLO:
4267d3e6 5008 case R6_OPC_DCLO:
7a387fff 5009 case OPC_DCLZ:
4267d3e6 5010 case R6_OPC_DCLZ:
1a0196c5 5011 tcg_gen_clzi_i64(t0, t0, 64);
7a387fff
TS
5012 break;
5013#endif
6af0bf9c 5014 }
6af0bf9c
FB
5015}
5016
161f85e6 5017/* Godson integer instructions */
bd277fa1
RH
5018static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5019 int rd, int rs, int rt)
161f85e6 5020{
161f85e6
AJ
5021 TCGv t0, t1;
5022
5023 if (rd == 0) {
5024 /* Treat as NOP. */
161f85e6
AJ
5025 return;
5026 }
5027
5028 switch (opc) {
5029 case OPC_MULT_G_2E:
5030 case OPC_MULT_G_2F:
5031 case OPC_MULTU_G_2E:
5032 case OPC_MULTU_G_2F:
5033#if defined(TARGET_MIPS64)
5034 case OPC_DMULT_G_2E:
5035 case OPC_DMULT_G_2F:
5036 case OPC_DMULTU_G_2E:
5037 case OPC_DMULTU_G_2F:
5038#endif
5039 t0 = tcg_temp_new();
5040 t1 = tcg_temp_new();
5041 break;
5042 default:
5043 t0 = tcg_temp_local_new();
5044 t1 = tcg_temp_local_new();
5045 break;
5046 }
5047
5048 gen_load_gpr(t0, rs);
5049 gen_load_gpr(t1, rt);
5050
5051 switch (opc) {
5052 case OPC_MULT_G_2E:
5053 case OPC_MULT_G_2F:
5054 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5055 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
5056 break;
5057 case OPC_MULTU_G_2E:
5058 case OPC_MULTU_G_2F:
5059 tcg_gen_ext32u_tl(t0, t0);
5060 tcg_gen_ext32u_tl(t1, t1);
5061 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5062 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
5063 break;
5064 case OPC_DIV_G_2E:
5065 case OPC_DIV_G_2F:
5066 {
42a268c2
RH
5067 TCGLabel *l1 = gen_new_label();
5068 TCGLabel *l2 = gen_new_label();
5069 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5070 tcg_gen_ext32s_tl(t0, t0);
5071 tcg_gen_ext32s_tl(t1, t1);
5072 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5073 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5074 tcg_gen_br(l3);
5075 gen_set_label(l1);
5076 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5077 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5078 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5079 tcg_gen_br(l3);
5080 gen_set_label(l2);
5081 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5082 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5083 gen_set_label(l3);
5084 }
161f85e6
AJ
5085 break;
5086 case OPC_DIVU_G_2E:
5087 case OPC_DIVU_G_2F:
5088 {
42a268c2
RH
5089 TCGLabel *l1 = gen_new_label();
5090 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5091 tcg_gen_ext32u_tl(t0, t0);
5092 tcg_gen_ext32u_tl(t1, t1);
5093 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5094 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5095 tcg_gen_br(l2);
5096 gen_set_label(l1);
5097 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5098 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5099 gen_set_label(l2);
5100 }
161f85e6
AJ
5101 break;
5102 case OPC_MOD_G_2E:
5103 case OPC_MOD_G_2F:
5104 {
42a268c2
RH
5105 TCGLabel *l1 = gen_new_label();
5106 TCGLabel *l2 = gen_new_label();
5107 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5108 tcg_gen_ext32u_tl(t0, t0);
5109 tcg_gen_ext32u_tl(t1, t1);
5110 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5111 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5112 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5113 gen_set_label(l1);
5114 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5115 tcg_gen_br(l3);
5116 gen_set_label(l2);
5117 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5118 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5119 gen_set_label(l3);
5120 }
161f85e6
AJ
5121 break;
5122 case OPC_MODU_G_2E:
5123 case OPC_MODU_G_2F:
5124 {
42a268c2
RH
5125 TCGLabel *l1 = gen_new_label();
5126 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5127 tcg_gen_ext32u_tl(t0, t0);
5128 tcg_gen_ext32u_tl(t1, t1);
5129 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5130 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5131 tcg_gen_br(l2);
5132 gen_set_label(l1);
5133 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5134 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5135 gen_set_label(l2);
5136 }
161f85e6
AJ
5137 break;
5138#if defined(TARGET_MIPS64)
5139 case OPC_DMULT_G_2E:
5140 case OPC_DMULT_G_2F:
5141 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
5142 break;
5143 case OPC_DMULTU_G_2E:
5144 case OPC_DMULTU_G_2F:
5145 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
5146 break;
5147 case OPC_DDIV_G_2E:
5148 case OPC_DDIV_G_2F:
5149 {
42a268c2
RH
5150 TCGLabel *l1 = gen_new_label();
5151 TCGLabel *l2 = gen_new_label();
5152 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5153 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5154 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5155 tcg_gen_br(l3);
5156 gen_set_label(l1);
5157 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5158 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5159 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5160 tcg_gen_br(l3);
5161 gen_set_label(l2);
5162 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5163 gen_set_label(l3);
5164 }
161f85e6
AJ
5165 break;
5166 case OPC_DDIVU_G_2E:
5167 case OPC_DDIVU_G_2F:
5168 {
42a268c2
RH
5169 TCGLabel *l1 = gen_new_label();
5170 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5171 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5172 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5173 tcg_gen_br(l2);
5174 gen_set_label(l1);
5175 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5176 gen_set_label(l2);
5177 }
161f85e6
AJ
5178 break;
5179 case OPC_DMOD_G_2E:
5180 case OPC_DMOD_G_2F:
5181 {
42a268c2
RH
5182 TCGLabel *l1 = gen_new_label();
5183 TCGLabel *l2 = gen_new_label();
5184 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
5185 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5186 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5187 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5188 gen_set_label(l1);
5189 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5190 tcg_gen_br(l3);
5191 gen_set_label(l2);
5192 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5193 gen_set_label(l3);
5194 }
161f85e6
AJ
5195 break;
5196 case OPC_DMODU_G_2E:
5197 case OPC_DMODU_G_2F:
5198 {
42a268c2
RH
5199 TCGLabel *l1 = gen_new_label();
5200 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
5201 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5202 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5203 tcg_gen_br(l2);
5204 gen_set_label(l1);
5205 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5206 gen_set_label(l2);
5207 }
161f85e6
AJ
5208 break;
5209#endif
5210 }
5211
161f85e6
AJ
5212 tcg_temp_free(t0);
5213 tcg_temp_free(t1);
5214}
5215
bd277fa1
RH
5216/* Loongson multimedia instructions */
5217static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5218{
bd277fa1
RH
5219 uint32_t opc, shift_max;
5220 TCGv_i64 t0, t1;
5221
5222 opc = MASK_LMI(ctx->opcode);
5223 switch (opc) {
5224 case OPC_ADD_CP2:
5225 case OPC_SUB_CP2:
5226 case OPC_DADD_CP2:
5227 case OPC_DSUB_CP2:
5228 t0 = tcg_temp_local_new_i64();
5229 t1 = tcg_temp_local_new_i64();
5230 break;
5231 default:
5232 t0 = tcg_temp_new_i64();
5233 t1 = tcg_temp_new_i64();
5234 break;
5235 }
5236
b5a587b6 5237 check_cp1_enabled(ctx);
bd277fa1
RH
5238 gen_load_fpr64(ctx, t0, rs);
5239 gen_load_fpr64(ctx, t1, rt);
5240
5241#define LMI_HELPER(UP, LO) \
9d68ac14 5242 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
bd277fa1 5243#define LMI_HELPER_1(UP, LO) \
9d68ac14 5244 case OPC_##UP: gen_helper_##LO(t0, t0); break
bd277fa1 5245#define LMI_DIRECT(UP, LO, OP) \
9d68ac14 5246 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
bd277fa1
RH
5247
5248 switch (opc) {
5249 LMI_HELPER(PADDSH, paddsh);
5250 LMI_HELPER(PADDUSH, paddush);
5251 LMI_HELPER(PADDH, paddh);
5252 LMI_HELPER(PADDW, paddw);
5253 LMI_HELPER(PADDSB, paddsb);
5254 LMI_HELPER(PADDUSB, paddusb);
5255 LMI_HELPER(PADDB, paddb);
5256
5257 LMI_HELPER(PSUBSH, psubsh);
5258 LMI_HELPER(PSUBUSH, psubush);
5259 LMI_HELPER(PSUBH, psubh);
5260 LMI_HELPER(PSUBW, psubw);
5261 LMI_HELPER(PSUBSB, psubsb);
5262 LMI_HELPER(PSUBUSB, psubusb);
5263 LMI_HELPER(PSUBB, psubb);
5264
5265 LMI_HELPER(PSHUFH, pshufh);
5266 LMI_HELPER(PACKSSWH, packsswh);
5267 LMI_HELPER(PACKSSHB, packsshb);
5268 LMI_HELPER(PACKUSHB, packushb);
5269
5270 LMI_HELPER(PUNPCKLHW, punpcklhw);
5271 LMI_HELPER(PUNPCKHHW, punpckhhw);
5272 LMI_HELPER(PUNPCKLBH, punpcklbh);
5273 LMI_HELPER(PUNPCKHBH, punpckhbh);
5274 LMI_HELPER(PUNPCKLWD, punpcklwd);
5275 LMI_HELPER(PUNPCKHWD, punpckhwd);
5276
5277 LMI_HELPER(PAVGH, pavgh);
5278 LMI_HELPER(PAVGB, pavgb);
5279 LMI_HELPER(PMAXSH, pmaxsh);
5280 LMI_HELPER(PMINSH, pminsh);
5281 LMI_HELPER(PMAXUB, pmaxub);
5282 LMI_HELPER(PMINUB, pminub);
5283
5284 LMI_HELPER(PCMPEQW, pcmpeqw);
5285 LMI_HELPER(PCMPGTW, pcmpgtw);
5286 LMI_HELPER(PCMPEQH, pcmpeqh);
5287 LMI_HELPER(PCMPGTH, pcmpgth);
5288 LMI_HELPER(PCMPEQB, pcmpeqb);
5289 LMI_HELPER(PCMPGTB, pcmpgtb);
5290
5291 LMI_HELPER(PSLLW, psllw);
5292 LMI_HELPER(PSLLH, psllh);
5293 LMI_HELPER(PSRLW, psrlw);
5294 LMI_HELPER(PSRLH, psrlh);
5295 LMI_HELPER(PSRAW, psraw);
5296 LMI_HELPER(PSRAH, psrah);
5297
5298 LMI_HELPER(PMULLH, pmullh);
5299 LMI_HELPER(PMULHH, pmulhh);
5300 LMI_HELPER(PMULHUH, pmulhuh);
5301 LMI_HELPER(PMADDHW, pmaddhw);
5302
5303 LMI_HELPER(PASUBUB, pasubub);
5304 LMI_HELPER_1(BIADD, biadd);
5305 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5306
5307 LMI_DIRECT(PADDD, paddd, add);
5308 LMI_DIRECT(PSUBD, psubd, sub);
5309 LMI_DIRECT(XOR_CP2, xor, xor);
5310 LMI_DIRECT(NOR_CP2, nor, nor);
5311 LMI_DIRECT(AND_CP2, and, and);
bb7cab5f 5312 LMI_DIRECT(OR_CP2, or, or);
bd277fa1 5313
9099a36b
H
5314 case OPC_PANDN:
5315 tcg_gen_andc_i64(t0, t1, t0);
5316 break;
5317
bd277fa1
RH
5318 case OPC_PINSRH_0:
5319 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
bd277fa1
RH
5320 break;
5321 case OPC_PINSRH_1:
5322 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
bd277fa1
RH
5323 break;
5324 case OPC_PINSRH_2:
5325 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
bd277fa1
RH
5326 break;
5327 case OPC_PINSRH_3:
5328 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
bd277fa1
RH
5329 break;
5330
5331 case OPC_PEXTRH:
5332 tcg_gen_andi_i64(t1, t1, 3);
5333 tcg_gen_shli_i64(t1, t1, 4);
5334 tcg_gen_shr_i64(t0, t0, t1);
5335 tcg_gen_ext16u_i64(t0, t0);
bd277fa1
RH
5336 break;
5337
5338 case OPC_ADDU_CP2:
5339 tcg_gen_add_i64(t0, t0, t1);
5340 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
5341 break;
5342 case OPC_SUBU_CP2:
5343 tcg_gen_sub_i64(t0, t0, t1);
5344 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
5345 break;
5346
5347 case OPC_SLL_CP2:
bd277fa1
RH
5348 shift_max = 32;
5349 goto do_shift;
5350 case OPC_SRL_CP2:
bd277fa1
RH
5351 shift_max = 32;
5352 goto do_shift;
5353 case OPC_SRA_CP2:
bd277fa1
RH
5354 shift_max = 32;
5355 goto do_shift;
5356 case OPC_DSLL_CP2:
bd277fa1
RH
5357 shift_max = 64;
5358 goto do_shift;
5359 case OPC_DSRL_CP2:
bd277fa1
RH
5360 shift_max = 64;
5361 goto do_shift;
5362 case OPC_DSRA_CP2:
bd277fa1
RH
5363 shift_max = 64;
5364 goto do_shift;
5365 do_shift:
5366 /* Make sure shift count isn't TCG undefined behaviour. */
5367 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5368
5369 switch (opc) {
5370 case OPC_SLL_CP2:
5371 case OPC_DSLL_CP2:
5372 tcg_gen_shl_i64(t0, t0, t1);
5373 break;
5374 case OPC_SRA_CP2:
5375 case OPC_DSRA_CP2:
5376 /* Since SRA is UndefinedResult without sign-extended inputs,
5377 we can treat SRA and DSRA the same. */
5378 tcg_gen_sar_i64(t0, t0, t1);
5379 break;
5380 case OPC_SRL_CP2:
5381 /* We want to shift in zeros for SRL; zero-extend first. */
5382 tcg_gen_ext32u_i64(t0, t0);
5383 /* FALLTHRU */
5384 case OPC_DSRL_CP2:
5385 tcg_gen_shr_i64(t0, t0, t1);
5386 break;
5387 }
5388
5389 if (shift_max == 32) {
5390 tcg_gen_ext32s_i64(t0, t0);
5391 }
5392
5393 /* Shifts larger than MAX produce zero. */
5394 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5395 tcg_gen_neg_i64(t1, t1);
5396 tcg_gen_and_i64(t0, t0, t1);
5397 break;
5398
5399 case OPC_ADD_CP2:
5400 case OPC_DADD_CP2:
5401 {
5402 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 5403 TCGLabel *lab = gen_new_label();
bd277fa1
RH
5404
5405 tcg_gen_mov_i64(t2, t0);
5406 tcg_gen_add_i64(t0, t1, t2);
5407 if (opc == OPC_ADD_CP2) {
5408 tcg_gen_ext32s_i64(t0, t0);
5409 }
5410 tcg_gen_xor_i64(t1, t1, t2);
5411 tcg_gen_xor_i64(t2, t2, t0);
5412 tcg_gen_andc_i64(t1, t2, t1);
5413 tcg_temp_free_i64(t2);
5414 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5415 generate_exception(ctx, EXCP_OVERFLOW);
5416 gen_set_label(lab);
bd277fa1
RH
5417 break;
5418 }
5419
5420 case OPC_SUB_CP2:
5421 case OPC_DSUB_CP2:
5422 {
5423 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 5424 TCGLabel *lab = gen_new_label();
bd277fa1
RH
5425
5426 tcg_gen_mov_i64(t2, t0);
5427 tcg_gen_sub_i64(t0, t1, t2);
5428 if (opc == OPC_SUB_CP2) {
5429 tcg_gen_ext32s_i64(t0, t0);
5430 }
5431 tcg_gen_xor_i64(t1, t1, t2);
5432 tcg_gen_xor_i64(t2, t2, t0);
5433 tcg_gen_and_i64(t1, t1, t2);
5434 tcg_temp_free_i64(t2);
5435 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5436 generate_exception(ctx, EXCP_OVERFLOW);
5437 gen_set_label(lab);
bd277fa1
RH
5438 break;
5439 }
5440
5441 case OPC_PMULUW:
5442 tcg_gen_ext32u_i64(t0, t0);
5443 tcg_gen_ext32u_i64(t1, t1);
5444 tcg_gen_mul_i64(t0, t0, t1);
bd277fa1
RH
5445 break;
5446
5447 case OPC_SEQU_CP2:
5448 case OPC_SEQ_CP2:
5449 case OPC_SLTU_CP2:
5450 case OPC_SLT_CP2:
5451 case OPC_SLEU_CP2:
5452 case OPC_SLE_CP2:
5453 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5454 FD field is the CC field? */
5455 default:
9d68ac14 5456 MIPS_INVAL("loongson_cp2");
9c708c7f 5457 generate_exception_end(ctx, EXCP_RI);
bd277fa1
RH
5458 return;
5459 }
5460
5461#undef LMI_HELPER
5462#undef LMI_DIRECT
5463
5464 gen_store_fpr64(ctx, t0, rd);
5465
bd277fa1
RH
5466 tcg_temp_free_i64(t0);
5467 tcg_temp_free_i64(t1);
5468}
5469
6af0bf9c 5470/* Traps */
7a387fff 5471static void gen_trap (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
5472 int rs, int rt, int16_t imm)
5473{
5474 int cond;
cdc0faa6 5475 TCGv t0 = tcg_temp_new();
1ba74fb8 5476 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
5477
5478 cond = 0;
5479 /* Load needed operands */
5480 switch (opc) {
5481 case OPC_TEQ:
5482 case OPC_TGE:
5483 case OPC_TGEU:
5484 case OPC_TLT:
5485 case OPC_TLTU:
5486 case OPC_TNE:
5487 /* Compare two registers */
5488 if (rs != rt) {
be24bb4f
TS
5489 gen_load_gpr(t0, rs);
5490 gen_load_gpr(t1, rt);
6af0bf9c
FB
5491 cond = 1;
5492 }
179e32bb 5493 break;
6af0bf9c
FB
5494 case OPC_TEQI:
5495 case OPC_TGEI:
5496 case OPC_TGEIU:
5497 case OPC_TLTI:
5498 case OPC_TLTIU:
5499 case OPC_TNEI:
5500 /* Compare register to immediate */
5501 if (rs != 0 || imm != 0) {
be24bb4f
TS
5502 gen_load_gpr(t0, rs);
5503 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
5504 cond = 1;
5505 }
5506 break;
5507 }
5508 if (cond == 0) {
5509 switch (opc) {
5510 case OPC_TEQ: /* rs == rs */
5511 case OPC_TEQI: /* r0 == 0 */
5512 case OPC_TGE: /* rs >= rs */
5513 case OPC_TGEI: /* r0 >= 0 */
5514 case OPC_TGEU: /* rs >= rs unsigned */
5515 case OPC_TGEIU: /* r0 >= 0 unsigned */
5516 /* Always trap */
9c708c7f 5517 generate_exception_end(ctx, EXCP_TRAP);
6af0bf9c
FB
5518 break;
5519 case OPC_TLT: /* rs < rs */
5520 case OPC_TLTI: /* r0 < 0 */
5521 case OPC_TLTU: /* rs < rs unsigned */
5522 case OPC_TLTIU: /* r0 < 0 unsigned */
5523 case OPC_TNE: /* rs != rs */
5524 case OPC_TNEI: /* r0 != 0 */
ead9360e 5525 /* Never trap: treat as NOP. */
cdc0faa6 5526 break;
6af0bf9c
FB
5527 }
5528 } else {
42a268c2 5529 TCGLabel *l1 = gen_new_label();
cdc0faa6 5530
6af0bf9c
FB
5531 switch (opc) {
5532 case OPC_TEQ:
5533 case OPC_TEQI:
cdc0faa6 5534 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
5535 break;
5536 case OPC_TGE:
5537 case OPC_TGEI:
cdc0faa6 5538 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
5539 break;
5540 case OPC_TGEU:
5541 case OPC_TGEIU:
cdc0faa6 5542 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
5543 break;
5544 case OPC_TLT:
5545 case OPC_TLTI:
cdc0faa6 5546 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
5547 break;
5548 case OPC_TLTU:
5549 case OPC_TLTIU:
cdc0faa6 5550 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
5551 break;
5552 case OPC_TNE:
5553 case OPC_TNEI:
cdc0faa6 5554 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 5555 break;
6af0bf9c 5556 }
cdc0faa6 5557 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
5558 gen_set_label(l1);
5559 }
be24bb4f
TS
5560 tcg_temp_free(t0);
5561 tcg_temp_free(t1);
6af0bf9c
FB
5562}
5563
90aa39a1
SF
5564static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5565{
eeb3bba8 5566 if (unlikely(ctx->base.singlestep_enabled)) {
90aa39a1
SF
5567 return false;
5568 }
5569
5570#ifndef CONFIG_USER_ONLY
eeb3bba8 5571 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
90aa39a1
SF
5572#else
5573 return true;
5574#endif
5575}
5576
356265ae 5577static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 5578{
90aa39a1 5579 if (use_goto_tb(ctx, dest)) {
57fec1fe 5580 tcg_gen_goto_tb(n);
9b9e4393 5581 gen_save_pc(dest);
07ea28b4 5582 tcg_gen_exit_tb(ctx->base.tb, n);
6e256c93 5583 } else {
9b9e4393 5584 gen_save_pc(dest);
eeb3bba8 5585 if (ctx->base.singlestep_enabled) {
7b270ef2 5586 save_cpu_state(ctx, 0);
9c708c7f 5587 gen_helper_raise_exception_debug(cpu_env);
7b270ef2 5588 }
7f11636d 5589 tcg_gen_lookup_and_goto_ptr();
6e256c93 5590 }
c53be334
FB
5591}
5592
6af0bf9c 5593/* Branches (before delay slot) */
7a387fff 5594static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
7dca4ad0 5595 int insn_bytes,
b231c103
YK
5596 int rs, int rt, int32_t offset,
5597 int delayslot_size)
6af0bf9c 5598{
d077b6f7 5599 target_ulong btgt = -1;
3ad4bb2d 5600 int blink = 0;
2fdbad25 5601 int bcond_compute = 0;
1ba74fb8
AJ
5602 TCGv t0 = tcg_temp_new();
5603 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
5604
5605 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 5606#ifdef MIPS_DEBUG_DISAS
339cd2a8 5607 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
eeb3bba8 5608 TARGET_FMT_lx "\n", ctx->base.pc_next);
923617a3 5609#endif
9c708c7f 5610 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5611 goto out;
3ad4bb2d 5612 }
6af0bf9c 5613
6af0bf9c
FB
5614 /* Load needed operands */
5615 switch (opc) {
5616 case OPC_BEQ:
5617 case OPC_BEQL:
5618 case OPC_BNE:
5619 case OPC_BNEL:
5620 /* Compare two registers */
5621 if (rs != rt) {
6c5c1e20
TS
5622 gen_load_gpr(t0, rs);
5623 gen_load_gpr(t1, rt);
2fdbad25 5624 bcond_compute = 1;
6af0bf9c 5625 }
eeb3bba8 5626 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c
FB
5627 break;
5628 case OPC_BGEZ:
5629 case OPC_BGEZAL:
5630 case OPC_BGEZALL:
5631 case OPC_BGEZL:
5632 case OPC_BGTZ:
5633 case OPC_BGTZL:
5634 case OPC_BLEZ:
5635 case OPC_BLEZL:
5636 case OPC_BLTZ:
5637 case OPC_BLTZAL:
5638 case OPC_BLTZALL:
5639 case OPC_BLTZL:
5640 /* Compare to zero */
5641 if (rs != 0) {
6c5c1e20 5642 gen_load_gpr(t0, rs);
2fdbad25 5643 bcond_compute = 1;
6af0bf9c 5644 }
eeb3bba8 5645 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c 5646 break;
e45a93e2
JL
5647 case OPC_BPOSGE32:
5648#if defined(TARGET_MIPS64)
5649 case OPC_BPOSGE64:
5650 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5651#else
5652 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5653#endif
5654 bcond_compute = 1;
eeb3bba8 5655 btgt = ctx->base.pc_next + insn_bytes + offset;
e45a93e2 5656 break;
6af0bf9c
FB
5657 case OPC_J:
5658 case OPC_JAL:
364d4831 5659 case OPC_JALX:
6af0bf9c 5660 /* Jump to immediate */
eeb3bba8
EC
5661 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5662 (uint32_t)offset;
6af0bf9c
FB
5663 break;
5664 case OPC_JR:
5665 case OPC_JALR:
5666 /* Jump to register */
7a387fff
TS
5667 if (offset != 0 && offset != 16) {
5668 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
cbeb0857 5669 others are reserved. */
923617a3 5670 MIPS_INVAL("jump hint");
9c708c7f 5671 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5672 goto out;
6af0bf9c 5673 }
d077b6f7 5674 gen_load_gpr(btarget, rs);
6af0bf9c
FB
5675 break;
5676 default:
5677 MIPS_INVAL("branch/jump");
9c708c7f 5678 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5679 goto out;
6af0bf9c 5680 }
2fdbad25 5681 if (bcond_compute == 0) {
6af0bf9c
FB
5682 /* No condition to be computed */
5683 switch (opc) {
5684 case OPC_BEQ: /* rx == rx */
5685 case OPC_BEQL: /* rx == rx likely */
5686 case OPC_BGEZ: /* 0 >= 0 */
5687 case OPC_BGEZL: /* 0 >= 0 likely */
5688 case OPC_BLEZ: /* 0 <= 0 */
5689 case OPC_BLEZL: /* 0 <= 0 likely */
5690 /* Always take */
4ad40f36 5691 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
5692 break;
5693 case OPC_BGEZAL: /* 0 >= 0 */
5694 case OPC_BGEZALL: /* 0 >= 0 likely */
5695 /* Always take and link */
5696 blink = 31;
4ad40f36 5697 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
5698 break;
5699 case OPC_BNE: /* rx != rx */
5700 case OPC_BGTZ: /* 0 > 0 */
5701 case OPC_BLTZ: /* 0 < 0 */
ead9360e 5702 /* Treat as NOP. */
6c5c1e20 5703 goto out;
eeef26cd 5704 case OPC_BLTZAL: /* 0 < 0 */
3c824109
NF
5705 /* Handle as an unconditional branch to get correct delay
5706 slot checking. */
5707 blink = 31;
eeb3bba8 5708 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
3c824109 5709 ctx->hflags |= MIPS_HFLAG_B;
3c824109 5710 break;
eeef26cd 5711 case OPC_BLTZALL: /* 0 < 0 likely */
eeb3bba8 5712 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
9898128f 5713 /* Skip the instruction in the delay slot */
eeb3bba8 5714 ctx->base.pc_next += 4;
6c5c1e20 5715 goto out;
6af0bf9c
FB
5716 case OPC_BNEL: /* rx != rx likely */
5717 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
5718 case OPC_BLTZL: /* 0 < 0 likely */
5719 /* Skip the instruction in the delay slot */
eeb3bba8 5720 ctx->base.pc_next += 4;
6c5c1e20 5721 goto out;
6af0bf9c 5722 case OPC_J:
4ad40f36 5723 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c 5724 break;
364d4831
NF
5725 case OPC_JALX:
5726 ctx->hflags |= MIPS_HFLAG_BX;
5727 /* Fallthrough */
6af0bf9c
FB
5728 case OPC_JAL:
5729 blink = 31;
4ad40f36 5730 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
5731 break;
5732 case OPC_JR:
4ad40f36 5733 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
5734 break;
5735 case OPC_JALR:
5736 blink = rt;
4ad40f36 5737 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
5738 break;
5739 default:
5740 MIPS_INVAL("branch/jump");
9c708c7f 5741 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5742 goto out;
6af0bf9c
FB
5743 }
5744 } else {
5745 switch (opc) {
5746 case OPC_BEQ:
e68dd28f 5747 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
5748 goto not_likely;
5749 case OPC_BEQL:
e68dd28f 5750 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
5751 goto likely;
5752 case OPC_BNE:
e68dd28f 5753 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
5754 goto not_likely;
5755 case OPC_BNEL:
e68dd28f 5756 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
5757 goto likely;
5758 case OPC_BGEZ:
e68dd28f 5759 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
5760 goto not_likely;
5761 case OPC_BGEZL:
e68dd28f 5762 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
5763 goto likely;
5764 case OPC_BGEZAL:
e68dd28f 5765 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
5766 blink = 31;
5767 goto not_likely;
5768 case OPC_BGEZALL:
e68dd28f 5769 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 5770 blink = 31;
6af0bf9c
FB
5771 goto likely;
5772 case OPC_BGTZ:
e68dd28f 5773 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
5774 goto not_likely;
5775 case OPC_BGTZL:
e68dd28f 5776 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
5777 goto likely;
5778 case OPC_BLEZ:
e68dd28f 5779 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
5780 goto not_likely;
5781 case OPC_BLEZL:
e68dd28f 5782 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
5783 goto likely;
5784 case OPC_BLTZ:
e68dd28f 5785 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c
FB
5786 goto not_likely;
5787 case OPC_BLTZL:
e68dd28f 5788 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 5789 goto likely;
e45a93e2
JL
5790 case OPC_BPOSGE32:
5791 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
e45a93e2
JL
5792 goto not_likely;
5793#if defined(TARGET_MIPS64)
5794 case OPC_BPOSGE64:
5795 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
e45a93e2
JL
5796 goto not_likely;
5797#endif
6af0bf9c 5798 case OPC_BLTZAL:
e68dd28f 5799 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 5800 blink = 31;
6af0bf9c 5801 not_likely:
4ad40f36 5802 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
5803 break;
5804 case OPC_BLTZALL:
e68dd28f 5805 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 5806 blink = 31;
6af0bf9c 5807 likely:
4ad40f36 5808 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 5809 break;
c53f4a62
TS
5810 default:
5811 MIPS_INVAL("conditional branch/jump");
9c708c7f 5812 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 5813 goto out;
6af0bf9c 5814 }
6af0bf9c 5815 }
9b9e4393 5816
d077b6f7 5817 ctx->btarget = btgt;
b231c103
YK
5818
5819 switch (delayslot_size) {
5820 case 2:
5821 ctx->hflags |= MIPS_HFLAG_BDS16;
5822 break;
5823 case 4:
5824 ctx->hflags |= MIPS_HFLAG_BDS32;
5825 break;
5826 }
5827
6af0bf9c 5828 if (blink > 0) {
b231c103 5829 int post_delay = insn_bytes + delayslot_size;
364d4831
NF
5830 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5831
eeb3bba8
EC
5832 tcg_gen_movi_tl(cpu_gpr[blink],
5833 ctx->base.pc_next + post_delay + lowbit);
6af0bf9c 5834 }
6c5c1e20
TS
5835
5836 out:
364d4831
NF
5837 if (insn_bytes == 2)
5838 ctx->hflags |= MIPS_HFLAG_B16;
6c5c1e20
TS
5839 tcg_temp_free(t0);
5840 tcg_temp_free(t1);
6af0bf9c
FB
5841}
5842
764371d2
SM
5843
5844/* nanoMIPS Branches */
5845static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5846 int insn_bytes,
5847 int rs, int rt, int32_t offset)
5848{
5849 target_ulong btgt = -1;
5850 int bcond_compute = 0;
5851 TCGv t0 = tcg_temp_new();
5852 TCGv t1 = tcg_temp_new();
5853
5854 /* Load needed operands */
5855 switch (opc) {
5856 case OPC_BEQ:
5857 case OPC_BNE:
5858 /* Compare two registers */
5859 if (rs != rt) {
5860 gen_load_gpr(t0, rs);
5861 gen_load_gpr(t1, rt);
5862 bcond_compute = 1;
5863 }
5864 btgt = ctx->base.pc_next + insn_bytes + offset;
5865 break;
5866 case OPC_BGEZAL:
5867 /* Compare to zero */
5868 if (rs != 0) {
5869 gen_load_gpr(t0, rs);
5870 bcond_compute = 1;
5871 }
5872 btgt = ctx->base.pc_next + insn_bytes + offset;
5873 break;
5874 case OPC_BPOSGE32:
5875 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5876 bcond_compute = 1;
5877 btgt = ctx->base.pc_next + insn_bytes + offset;
5878 break;
5879 case OPC_JR:
5880 case OPC_JALR:
5881 /* Jump to register */
5882 if (offset != 0 && offset != 16) {
5883 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5884 others are reserved. */
5885 MIPS_INVAL("jump hint");
5886 generate_exception_end(ctx, EXCP_RI);
5887 goto out;
5888 }
5889 gen_load_gpr(btarget, rs);
5890 break;
5891 default:
5892 MIPS_INVAL("branch/jump");
5893 generate_exception_end(ctx, EXCP_RI);
5894 goto out;
5895 }
5896 if (bcond_compute == 0) {
5897 /* No condition to be computed */
5898 switch (opc) {
5899 case OPC_BEQ: /* rx == rx */
5900 /* Always take */
5901 ctx->hflags |= MIPS_HFLAG_B;
5902 break;
5903 case OPC_BGEZAL: /* 0 >= 0 */
5904 /* Always take and link */
5905 tcg_gen_movi_tl(cpu_gpr[31],
5906 ctx->base.pc_next + insn_bytes);
5907 ctx->hflags |= MIPS_HFLAG_B;
5908 break;
5909 case OPC_BNE: /* rx != rx */
5910 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5911 /* Skip the instruction in the delay slot */
5912 ctx->base.pc_next += 4;
5913 goto out;
5914 case OPC_JR:
5915 ctx->hflags |= MIPS_HFLAG_BR;
5916 break;
5917 case OPC_JALR:
5918 if (rt > 0) {
5919 tcg_gen_movi_tl(cpu_gpr[rt],
5920 ctx->base.pc_next + insn_bytes);
5921 }
5922 ctx->hflags |= MIPS_HFLAG_BR;
5923 break;
5924 default:
5925 MIPS_INVAL("branch/jump");
5926 generate_exception_end(ctx, EXCP_RI);
5927 goto out;
5928 }
5929 } else {
5930 switch (opc) {
5931 case OPC_BEQ:
5932 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5933 goto not_likely;
5934 case OPC_BNE:
5935 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5936 goto not_likely;
5937 case OPC_BGEZAL:
5938 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5939 tcg_gen_movi_tl(cpu_gpr[31],
5940 ctx->base.pc_next + insn_bytes);
5941 goto not_likely;
5942 case OPC_BPOSGE32:
5943 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5944 not_likely:
5945 ctx->hflags |= MIPS_HFLAG_BC;
5946 break;
5947 default:
5948 MIPS_INVAL("conditional branch/jump");
5949 generate_exception_end(ctx, EXCP_RI);
5950 goto out;
5951 }
5952 }
5953
5954 ctx->btarget = btgt;
5955
5956 out:
5957 if (insn_bytes == 2) {
5958 ctx->hflags |= MIPS_HFLAG_B16;
5959 }
5960 tcg_temp_free(t0);
5961 tcg_temp_free(t1);
5962}
5963
5964
7a387fff
TS
5965/* special3 bitfield operations */
5966static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
356265ae 5967 int rs, int lsb, int msb)
7a387fff 5968{
a7812ae4
PB
5969 TCGv t0 = tcg_temp_new();
5970 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
5971
5972 gen_load_gpr(t1, rs);
7a387fff
TS
5973 switch (opc) {
5974 case OPC_EXT:
b7f26e52 5975 if (lsb + msb > 31) {
7a387fff 5976 goto fail;
b7f26e52 5977 }
505ad7c2 5978 if (msb != 31) {
6eebb7a4 5979 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
505ad7c2 5980 } else {
6eebb7a4
RH
5981 /* The two checks together imply that lsb == 0,
5982 so this is a simple sign-extension. */
5983 tcg_gen_ext32s_tl(t0, t1);
505ad7c2 5984 }
7a387fff 5985 break;
c6d6dd7c 5986#if defined(TARGET_MIPS64)
7a387fff 5987 case OPC_DEXTU:
b7f26e52
RH
5988 lsb += 32;
5989 goto do_dext;
5990 case OPC_DEXTM:
5991 msb += 32;
5992 goto do_dext;
7a387fff 5993 case OPC_DEXT:
b7f26e52
RH
5994 do_dext:
5995 if (lsb + msb > 63) {
5996 goto fail;
5997 }
6eebb7a4 5998 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
7a387fff 5999 break;
c6d6dd7c 6000#endif
7a387fff 6001 case OPC_INS:
b7f26e52 6002 if (lsb > msb) {
7a387fff 6003 goto fail;
b7f26e52 6004 }
6c5c1e20 6005 gen_load_gpr(t0, rt);
e0d002f1 6006 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
505ad7c2 6007 tcg_gen_ext32s_tl(t0, t0);
7a387fff 6008 break;
c6d6dd7c 6009#if defined(TARGET_MIPS64)
7a387fff 6010 case OPC_DINSU:
b7f26e52
RH
6011 lsb += 32;
6012 /* FALLTHRU */
6013 case OPC_DINSM:
6014 msb += 32;
6015 /* FALLTHRU */
7a387fff 6016 case OPC_DINS:
b7f26e52
RH
6017 if (lsb > msb) {
6018 goto fail;
6019 }
6c5c1e20 6020 gen_load_gpr(t0, rt);
e0d002f1 6021 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
7a387fff 6022 break;
c6d6dd7c 6023#endif
7a387fff
TS
6024 default:
6025fail:
6026 MIPS_INVAL("bitops");
9c708c7f 6027 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
6028 tcg_temp_free(t0);
6029 tcg_temp_free(t1);
7a387fff
TS
6030 return;
6031 }
6c5c1e20
TS
6032 gen_store_gpr(t0, rt);
6033 tcg_temp_free(t0);
6034 tcg_temp_free(t1);
7a387fff
TS
6035}
6036
49bcf33c
AJ
6037static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
6038{
3a55fa47 6039 TCGv t0;
49bcf33c 6040
3a55fa47
AJ
6041 if (rd == 0) {
6042 /* If no destination, treat it as a NOP. */
3a55fa47
AJ
6043 return;
6044 }
6045
6046 t0 = tcg_temp_new();
6047 gen_load_gpr(t0, rt);
49bcf33c
AJ
6048 switch (op2) {
6049 case OPC_WSBH:
3a55fa47
AJ
6050 {
6051 TCGv t1 = tcg_temp_new();
06a57e5c 6052 TCGv t2 = tcg_const_tl(0x00FF00FF);
3a55fa47
AJ
6053
6054 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
6055 tcg_gen_and_tl(t1, t1, t2);
6056 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6057 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 6058 tcg_gen_or_tl(t0, t0, t1);
06a57e5c 6059 tcg_temp_free(t2);
3a55fa47
AJ
6060 tcg_temp_free(t1);
6061 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6062 }
49bcf33c
AJ
6063 break;
6064 case OPC_SEB:
3a55fa47 6065 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
6066 break;
6067 case OPC_SEH:
3a55fa47 6068 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
6069 break;
6070#if defined(TARGET_MIPS64)
6071 case OPC_DSBH:
3a55fa47
AJ
6072 {
6073 TCGv t1 = tcg_temp_new();
06a57e5c 6074 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
3a55fa47
AJ
6075
6076 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
6077 tcg_gen_and_tl(t1, t1, t2);
6078 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6079 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 6080 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 6081 tcg_temp_free(t2);
3a55fa47
AJ
6082 tcg_temp_free(t1);
6083 }
49bcf33c
AJ
6084 break;
6085 case OPC_DSHD:
3a55fa47
AJ
6086 {
6087 TCGv t1 = tcg_temp_new();
06a57e5c 6088 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
3a55fa47
AJ
6089
6090 tcg_gen_shri_tl(t1, t0, 16);
06a57e5c
AJ
6091 tcg_gen_and_tl(t1, t1, t2);
6092 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 6093 tcg_gen_shli_tl(t0, t0, 16);
3a55fa47
AJ
6094 tcg_gen_or_tl(t0, t0, t1);
6095 tcg_gen_shri_tl(t1, t0, 32);
6096 tcg_gen_shli_tl(t0, t0, 32);
6097 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 6098 tcg_temp_free(t2);
3a55fa47
AJ
6099 tcg_temp_free(t1);
6100 }
49bcf33c
AJ
6101 break;
6102#endif
6103 default:
6104 MIPS_INVAL("bsfhl");
9c708c7f 6105 generate_exception_end(ctx, EXCP_RI);
49bcf33c 6106 tcg_temp_free(t0);
49bcf33c
AJ
6107 return;
6108 }
49bcf33c 6109 tcg_temp_free(t0);
49bcf33c
AJ
6110}
6111
1f1b4c00
YK
6112static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6113 int imm2)
6114{
6115 TCGv t0;
6116 TCGv t1;
6117 if (rd == 0) {
6118 /* Treat as NOP. */
6119 return;
6120 }
6121 t0 = tcg_temp_new();
6122 t1 = tcg_temp_new();
6123 gen_load_gpr(t0, rs);
6124 gen_load_gpr(t1, rt);
6125 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6126 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6127 if (opc == OPC_LSA) {
6128 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6129 }
6130
6131 tcg_temp_free(t1);
6132 tcg_temp_free(t0);
6133
6134 return;
6135}
6136
821f2008
JH
6137static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6138 int rt, int bits)
284b731a 6139{
1f1b4c00
YK
6140 TCGv t0;
6141 if (rd == 0) {
6142 /* Treat as NOP. */
6143 return;
6144 }
6145 t0 = tcg_temp_new();
821f2008
JH
6146 if (bits == 0 || bits == wordsz) {
6147 if (bits == 0) {
6148 gen_load_gpr(t0, rt);
6149 } else {
6150 gen_load_gpr(t0, rs);
6151 }
6152 switch (wordsz) {
6153 case 32:
51243852
MD
6154 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6155 break;
6156#if defined(TARGET_MIPS64)
821f2008 6157 case 64:
51243852
MD
6158 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6159 break;
6160#endif
6161 }
1f1b4c00
YK
6162 } else {
6163 TCGv t1 = tcg_temp_new();
821f2008 6164 gen_load_gpr(t0, rt);
1f1b4c00 6165 gen_load_gpr(t1, rs);
821f2008
JH
6166 switch (wordsz) {
6167 case 32:
1f1b4c00
YK
6168 {
6169 TCGv_i64 t2 = tcg_temp_new_i64();
6170 tcg_gen_concat_tl_i64(t2, t1, t0);
821f2008 6171 tcg_gen_shri_i64(t2, t2, 32 - bits);
1f1b4c00
YK
6172 gen_move_low32(cpu_gpr[rd], t2);
6173 tcg_temp_free_i64(t2);
6174 }
6175 break;
284b731a 6176#if defined(TARGET_MIPS64)
821f2008
JH
6177 case 64:
6178 tcg_gen_shli_tl(t0, t0, bits);
6179 tcg_gen_shri_tl(t1, t1, 64 - bits);
1f1b4c00
YK
6180 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6181 break;
284b731a 6182#endif
1f1b4c00
YK
6183 }
6184 tcg_temp_free(t1);
6185 }
6186
6187 tcg_temp_free(t0);
6188}
6189
821f2008
JH
6190static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6191 int bp)
6192{
6193 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6194}
6195
6196static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6197 int shift)
6198{
6199 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6200}
6201
1f1b4c00
YK
6202static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6203{
6204 TCGv t0;
6205 if (rd == 0) {
6206 /* Treat as NOP. */
6207 return;
6208 }
6209 t0 = tcg_temp_new();
6210 gen_load_gpr(t0, rt);
6211 switch (opc) {
6212 case OPC_BITSWAP:
6213 gen_helper_bitswap(cpu_gpr[rd], t0);
6214 break;
6215#if defined(TARGET_MIPS64)
6216 case OPC_DBITSWAP:
6217 gen_helper_dbitswap(cpu_gpr[rd], t0);
6218 break;
6219#endif
6220 }
6221 tcg_temp_free(t0);
284b731a
LA
6222}
6223
1f1b4c00
YK
6224#ifndef CONFIG_USER_ONLY
6225/* CP0 (MMU and control) */
5204ea79
LA
6226static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6227{
6228 TCGv_i64 t0 = tcg_temp_new_i64();
6229 TCGv_i64 t1 = tcg_temp_new_i64();
6230
6231 tcg_gen_ext_tl_i64(t0, arg);
6232 tcg_gen_ld_i64(t1, cpu_env, off);
6233#if defined(TARGET_MIPS64)
6234 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6235#else
6236 tcg_gen_concat32_i64(t1, t1, t0);
6237#endif
6238 tcg_gen_st_i64(t1, cpu_env, off);
6239 tcg_temp_free_i64(t1);
6240 tcg_temp_free_i64(t0);
6241}
6242
6243static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6244{
6245 TCGv_i64 t0 = tcg_temp_new_i64();
6246 TCGv_i64 t1 = tcg_temp_new_i64();
6247
6248 tcg_gen_ext_tl_i64(t0, arg);
6249 tcg_gen_ld_i64(t1, cpu_env, off);
6250 tcg_gen_concat32_i64(t1, t1, t0);
6251 tcg_gen_st_i64(t1, cpu_env, off);
6252 tcg_temp_free_i64(t1);
6253 tcg_temp_free_i64(t0);
6254}
6255
6256static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6257{
6258 TCGv_i64 t0 = tcg_temp_new_i64();
6259
6260 tcg_gen_ld_i64(t0, cpu_env, off);
6261#if defined(TARGET_MIPS64)
6262 tcg_gen_shri_i64(t0, t0, 30);
6263#else
6264 tcg_gen_shri_i64(t0, t0, 32);
6265#endif
6266 gen_move_low32(arg, t0);
6267 tcg_temp_free_i64(t0);
6268}
6269
6270static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6271{
6272 TCGv_i64 t0 = tcg_temp_new_i64();
6273
6274 tcg_gen_ld_i64(t0, cpu_env, off);
6275 tcg_gen_shri_i64(t0, t0, 32 + shift);
6276 gen_move_low32(arg, t0);
6277 tcg_temp_free_i64(t0);
6278}
6279
d9bea114 6280static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4f57689a 6281{
d9bea114 6282 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 6283
d9bea114
AJ
6284 tcg_gen_ld_i32(t0, cpu_env, off);
6285 tcg_gen_ext_i32_tl(arg, t0);
6286 tcg_temp_free_i32(t0);
4f57689a
TS
6287}
6288
d9bea114 6289static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4f57689a 6290{
d9bea114
AJ
6291 tcg_gen_ld_tl(arg, cpu_env, off);
6292 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
6293}
6294
d9bea114 6295static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
f1aa6320 6296{
d9bea114 6297 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 6298
d9bea114
AJ
6299 tcg_gen_trunc_tl_i32(t0, arg);
6300 tcg_gen_st_i32(t0, cpu_env, off);
6301 tcg_temp_free_i32(t0);
f1aa6320
TS
6302}
6303
c98d3d79
YK
6304#define CP0_CHECK(c) \
6305 do { \
6306 if (!(c)) { \
6307 goto cp0_unimplemented; \
6308 } \
6309 } while (0)
6310
5204ea79
LA
6311static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6312{
6313 const char *rn = "invalid";
6314
5204ea79
LA
6315 switch (reg) {
6316 case 2:
6317 switch (sel) {
6318 case 0:
59488dda 6319 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
6320 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6321 rn = "EntryLo0";
6322 break;
6323 default:
c98d3d79 6324 goto cp0_unimplemented;
5204ea79
LA
6325 }
6326 break;
6327 case 3:
6328 switch (sel) {
6329 case 0:
59488dda 6330 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
6331 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6332 rn = "EntryLo1";
6333 break;
6334 default:
c98d3d79 6335 goto cp0_unimplemented;
5204ea79
LA
6336 }
6337 break;
6338 case 17:
6339 switch (sel) {
6340 case 0:
6341 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
6342 ctx->CP0_LLAddr_shift);
6343 rn = "LLAddr";
6344 break;
f6d4dd81
YK
6345 case 1:
6346 CP0_CHECK(ctx->mrp);
6347 gen_helper_mfhc0_maar(arg, cpu_env);
6348 rn = "MAAR";
6349 break;
5204ea79 6350 default:
c98d3d79 6351 goto cp0_unimplemented;
5204ea79
LA
6352 }
6353 break;
6354 case 28:
6355 switch (sel) {
6356 case 0:
6357 case 2:
6358 case 4:
6359 case 6:
6360 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6361 rn = "TagLo";
6362 break;
6363 default:
c98d3d79 6364 goto cp0_unimplemented;
5204ea79
LA
6365 }
6366 break;
6367 default:
c98d3d79 6368 goto cp0_unimplemented;
5204ea79 6369 }
b44a7fb1 6370 trace_mips_translate_c0("mfhc0", rn, reg, sel);
5204ea79
LA
6371 return;
6372
c98d3d79 6373cp0_unimplemented:
965447ee 6374 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5204ea79
LA
6375 tcg_gen_movi_tl(arg, 0);
6376}
6377
6378static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6379{
6380 const char *rn = "invalid";
6381 uint64_t mask = ctx->PAMask >> 36;
6382
5204ea79
LA
6383 switch (reg) {
6384 case 2:
6385 switch (sel) {
6386 case 0:
59488dda 6387 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
6388 tcg_gen_andi_tl(arg, arg, mask);
6389 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6390 rn = "EntryLo0";
6391 break;
6392 default:
c98d3d79 6393 goto cp0_unimplemented;
5204ea79
LA
6394 }
6395 break;
6396 case 3:
6397 switch (sel) {
6398 case 0:
59488dda 6399 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
6400 tcg_gen_andi_tl(arg, arg, mask);
6401 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6402 rn = "EntryLo1";
6403 break;
6404 default:
c98d3d79 6405 goto cp0_unimplemented;
5204ea79
LA
6406 }
6407 break;
6408 case 17:
6409 switch (sel) {
6410 case 0:
6411 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6412 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6413 relevant for modern MIPS cores supporting MTHC0, therefore
6414 treating MTHC0 to LLAddr as NOP. */
6415 rn = "LLAddr";
6416 break;
f6d4dd81
YK
6417 case 1:
6418 CP0_CHECK(ctx->mrp);
6419 gen_helper_mthc0_maar(cpu_env, arg);
6420 rn = "MAAR";
6421 break;
5204ea79 6422 default:
c98d3d79 6423 goto cp0_unimplemented;
5204ea79
LA
6424 }
6425 break;
6426 case 28:
6427 switch (sel) {
6428 case 0:
6429 case 2:
6430 case 4:
6431 case 6:
6432 tcg_gen_andi_tl(arg, arg, mask);
6433 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6434 rn = "TagLo";
6435 break;
6436 default:
c98d3d79 6437 goto cp0_unimplemented;
5204ea79
LA
6438 }
6439 break;
6440 default:
c98d3d79 6441 goto cp0_unimplemented;
5204ea79 6442 }
b44a7fb1 6443 trace_mips_translate_c0("mthc0", rn, reg, sel);
5204ea79 6444
c98d3d79 6445cp0_unimplemented:
965447ee 6446 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
5204ea79
LA
6447}
6448
e98c0d17
LA
6449static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6450{
6451 if (ctx->insn_flags & ISA_MIPS32R6) {
6452 tcg_gen_movi_tl(arg, 0);
6453 } else {
6454 tcg_gen_movi_tl(arg, ~0);
6455 }
6456}
6457
d75c135e 6458static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 6459{
7a387fff 6460 const char *rn = "invalid";
873eb012 6461
e189e748 6462 if (sel != 0)
d75c135e 6463 check_insn(ctx, ISA_MIPS32);
e189e748 6464
873eb012
TS
6465 switch (reg) {
6466 case 0:
7a387fff
TS
6467 switch (sel) {
6468 case 0:
7db13fae 6469 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7a387fff
TS
6470 rn = "Index";
6471 break;
6472 case 1:
f31b035a 6473 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6474 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7a387fff 6475 rn = "MVPControl";
ead9360e 6476 break;
7a387fff 6477 case 2:
f31b035a 6478 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6479 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7a387fff 6480 rn = "MVPConf0";
ead9360e 6481 break;
7a387fff 6482 case 3:
f31b035a 6483 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6484 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7a387fff 6485 rn = "MVPConf1";
ead9360e 6486 break;
01bc435b
YK
6487 case 4:
6488 CP0_CHECK(ctx->vp);
6489 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6490 rn = "VPControl";
6491 break;
7a387fff 6492 default:
f31b035a 6493 goto cp0_unimplemented;
7a387fff 6494 }
873eb012
TS
6495 break;
6496 case 1:
7a387fff
TS
6497 switch (sel) {
6498 case 0:
f31b035a 6499 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 6500 gen_helper_mfc0_random(arg, cpu_env);
7a387fff 6501 rn = "Random";
2423f660 6502 break;
7a387fff 6503 case 1:
f31b035a 6504 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6505 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7a387fff 6506 rn = "VPEControl";
ead9360e 6507 break;
7a387fff 6508 case 2:
f31b035a 6509 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6510 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7a387fff 6511 rn = "VPEConf0";
ead9360e 6512 break;
7a387fff 6513 case 3:
f31b035a 6514 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6515 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7a387fff 6516 rn = "VPEConf1";
ead9360e 6517 break;
7a387fff 6518 case 4:
f31b035a 6519 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6520 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7a387fff 6521 rn = "YQMask";
ead9360e 6522 break;
7a387fff 6523 case 5:
f31b035a 6524 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6525 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 6526 rn = "VPESchedule";
ead9360e 6527 break;
7a387fff 6528 case 6:
f31b035a 6529 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6530 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 6531 rn = "VPEScheFBack";
ead9360e 6532 break;
7a387fff 6533 case 7:
f31b035a 6534 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6535 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7a387fff 6536 rn = "VPEOpt";
ead9360e 6537 break;
7a387fff 6538 default:
f31b035a 6539 goto cp0_unimplemented;
7a387fff 6540 }
873eb012
TS
6541 break;
6542 case 2:
7a387fff
TS
6543 switch (sel) {
6544 case 0:
284b731a
LA
6545 {
6546 TCGv_i64 tmp = tcg_temp_new_i64();
6547 tcg_gen_ld_i64(tmp, cpu_env,
6548 offsetof(CPUMIPSState, CP0_EntryLo0));
7207c7f9 6549#if defined(TARGET_MIPS64)
284b731a
LA
6550 if (ctx->rxi) {
6551 /* Move RI/XI fields to bits 31:30 */
6552 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6553 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6554 }
7207c7f9 6555#endif
284b731a
LA
6556 gen_move_low32(arg, tmp);
6557 tcg_temp_free_i64(tmp);
6558 }
2423f660
TS
6559 rn = "EntryLo0";
6560 break;
7a387fff 6561 case 1:
f31b035a 6562 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6563 gen_helper_mfc0_tcstatus(arg, cpu_env);
2423f660 6564 rn = "TCStatus";
ead9360e 6565 break;
7a387fff 6566 case 2:
f31b035a 6567 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6568 gen_helper_mfc0_tcbind(arg, cpu_env);
2423f660 6569 rn = "TCBind";
ead9360e 6570 break;
7a387fff 6571 case 3:
f31b035a 6572 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6573 gen_helper_mfc0_tcrestart(arg, cpu_env);
2423f660 6574 rn = "TCRestart";
ead9360e 6575 break;
7a387fff 6576 case 4:
f31b035a 6577 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6578 gen_helper_mfc0_tchalt(arg, cpu_env);
2423f660 6579 rn = "TCHalt";
ead9360e 6580 break;
7a387fff 6581 case 5:
f31b035a 6582 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6583 gen_helper_mfc0_tccontext(arg, cpu_env);
2423f660 6584 rn = "TCContext";
ead9360e 6585 break;
7a387fff 6586 case 6:
f31b035a 6587 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6588 gen_helper_mfc0_tcschedule(arg, cpu_env);
2423f660 6589 rn = "TCSchedule";
ead9360e 6590 break;
7a387fff 6591 case 7:
f31b035a 6592 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6593 gen_helper_mfc0_tcschefback(arg, cpu_env);
2423f660 6594 rn = "TCScheFBack";
ead9360e 6595 break;
7a387fff 6596 default:
f31b035a 6597 goto cp0_unimplemented;
7a387fff 6598 }
873eb012
TS
6599 break;
6600 case 3:
7a387fff
TS
6601 switch (sel) {
6602 case 0:
284b731a
LA
6603 {
6604 TCGv_i64 tmp = tcg_temp_new_i64();
6605 tcg_gen_ld_i64(tmp, cpu_env,
6606 offsetof(CPUMIPSState, CP0_EntryLo1));
7207c7f9 6607#if defined(TARGET_MIPS64)
284b731a
LA
6608 if (ctx->rxi) {
6609 /* Move RI/XI fields to bits 31:30 */
6610 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6611 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6612 }
7207c7f9 6613#endif
284b731a
LA
6614 gen_move_low32(arg, tmp);
6615 tcg_temp_free_i64(tmp);
6616 }
2423f660
TS
6617 rn = "EntryLo1";
6618 break;
01bc435b
YK
6619 case 1:
6620 CP0_CHECK(ctx->vp);
6621 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6622 rn = "GlobalNumber";
6623 break;
7a387fff 6624 default:
f31b035a 6625 goto cp0_unimplemented;
1579a72e 6626 }
873eb012
TS
6627 break;
6628 case 4:
7a387fff
TS
6629 switch (sel) {
6630 case 0:
7db13fae 6631 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 6632 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
6633 rn = "Context";
6634 break;
7a387fff 6635 case 1:
d9bea114 6636// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660 6637 rn = "ContextConfig";
f31b035a 6638 goto cp0_unimplemented;
d279279e 6639 case 2:
f31b035a 6640 CP0_CHECK(ctx->ulri);
e40df9a8
JH
6641 tcg_gen_ld_tl(arg, cpu_env,
6642 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6643 tcg_gen_ext32s_tl(arg, arg);
f31b035a 6644 rn = "UserLocal";
d279279e 6645 break;
7a387fff 6646 default:
f31b035a 6647 goto cp0_unimplemented;
1579a72e 6648 }
873eb012
TS
6649 break;
6650 case 5:
7a387fff
TS
6651 switch (sel) {
6652 case 0:
7db13fae 6653 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
6654 rn = "PageMask";
6655 break;
7a387fff 6656 case 1:
d75c135e 6657 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6658 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
6659 rn = "PageGrain";
6660 break;
cec56a73
JH
6661 case 2:
6662 CP0_CHECK(ctx->sc);
6663 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6664 tcg_gen_ext32s_tl(arg, arg);
6665 rn = "SegCtl0";
6666 break;
6667 case 3:
6668 CP0_CHECK(ctx->sc);
6669 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6670 tcg_gen_ext32s_tl(arg, arg);
6671 rn = "SegCtl1";
6672 break;
6673 case 4:
6674 CP0_CHECK(ctx->sc);
6675 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6676 tcg_gen_ext32s_tl(arg, arg);
6677 rn = "SegCtl2";
6678 break;
5e31fdd5
YK
6679 case 5:
6680 check_pw(ctx);
6681 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6682 rn = "PWBase";
6683 break;
fa75ad14
YK
6684 case 6:
6685 check_pw(ctx);
6686 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6687 rn = "PWField";
6688 break;
20b28ebc
YK
6689 case 7:
6690 check_pw(ctx);
6691 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6692 rn = "PWSize";
6693 break;
7a387fff 6694 default:
f31b035a 6695 goto cp0_unimplemented;
1579a72e 6696 }
873eb012
TS
6697 break;
6698 case 6:
7a387fff
TS
6699 switch (sel) {
6700 case 0:
7db13fae 6701 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
6702 rn = "Wired";
6703 break;
7a387fff 6704 case 1:
d75c135e 6705 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6706 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 6707 rn = "SRSConf0";
ead9360e 6708 break;
7a387fff 6709 case 2:
d75c135e 6710 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6711 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 6712 rn = "SRSConf1";
ead9360e 6713 break;
7a387fff 6714 case 3:
d75c135e 6715 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6716 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 6717 rn = "SRSConf2";
ead9360e 6718 break;
7a387fff 6719 case 4:
d75c135e 6720 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6721 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 6722 rn = "SRSConf3";
ead9360e 6723 break;
7a387fff 6724 case 5:
d75c135e 6725 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6726 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 6727 rn = "SRSConf4";
ead9360e 6728 break;
103be64c
YK
6729 case 6:
6730 check_pw(ctx);
6731 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6732 rn = "PWCtl";
6733 break;
7a387fff 6734 default:
f31b035a 6735 goto cp0_unimplemented;
1579a72e 6736 }
873eb012 6737 break;
8c0fdd85 6738 case 7:
7a387fff
TS
6739 switch (sel) {
6740 case 0:
d75c135e 6741 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6742 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
6743 rn = "HWREna";
6744 break;
7a387fff 6745 default:
f31b035a 6746 goto cp0_unimplemented;
1579a72e 6747 }
8c0fdd85 6748 break;
873eb012 6749 case 8:
7a387fff
TS
6750 switch (sel) {
6751 case 0:
7db13fae 6752 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 6753 tcg_gen_ext32s_tl(arg, arg);
f0b3f3ae 6754 rn = "BadVAddr";
2423f660 6755 break;
aea14095 6756 case 1:
f31b035a
LA
6757 CP0_CHECK(ctx->bi);
6758 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6759 rn = "BadInstr";
aea14095
LA
6760 break;
6761 case 2:
f31b035a
LA
6762 CP0_CHECK(ctx->bp);
6763 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6764 rn = "BadInstrP";
aea14095 6765 break;
25beba9b
SM
6766 case 3:
6767 CP0_CHECK(ctx->bi);
6768 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6769 tcg_gen_andi_tl(arg, arg, ~0xffff);
6770 rn = "BadInstrX";
6771 break;
6772 default:
f31b035a 6773 goto cp0_unimplemented;
aea14095 6774 }
873eb012
TS
6775 break;
6776 case 9:
7a387fff
TS
6777 switch (sel) {
6778 case 0:
2e70f6ef 6779 /* Mark as an IO operation because we read the time. */
eeb3bba8 6780 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6781 gen_io_start();
bd79255d 6782 }
895c2d04 6783 gen_helper_mfc0_count(arg, cpu_env);
eeb3bba8 6784 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6785 gen_io_end();
2e70f6ef 6786 }
55807224 6787 /* Break the TB to be able to take timer interrupts immediately
b28425ba
EC
6788 after reading count. DISAS_STOP isn't sufficient, we need to
6789 ensure we break completely out of translated code. */
eeb3bba8
EC
6790 gen_save_pc(ctx->base.pc_next + 4);
6791 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
6792 rn = "Count";
6793 break;
6794 /* 6,7 are implementation dependent */
7a387fff 6795 default:
f31b035a 6796 goto cp0_unimplemented;
2423f660 6797 }
873eb012
TS
6798 break;
6799 case 10:
7a387fff
TS
6800 switch (sel) {
6801 case 0:
7db13fae 6802 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 6803 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
6804 rn = "EntryHi";
6805 break;
7a387fff 6806 default:
f31b035a 6807 goto cp0_unimplemented;
1579a72e 6808 }
873eb012
TS
6809 break;
6810 case 11:
7a387fff
TS
6811 switch (sel) {
6812 case 0:
7db13fae 6813 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
6814 rn = "Compare";
6815 break;
6816 /* 6,7 are implementation dependent */
7a387fff 6817 default:
f31b035a 6818 goto cp0_unimplemented;
2423f660 6819 }
873eb012
TS
6820 break;
6821 case 12:
7a387fff
TS
6822 switch (sel) {
6823 case 0:
7db13fae 6824 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
6825 rn = "Status";
6826 break;
7a387fff 6827 case 1:
d75c135e 6828 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6829 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
6830 rn = "IntCtl";
6831 break;
7a387fff 6832 case 2:
d75c135e 6833 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6834 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
6835 rn = "SRSCtl";
6836 break;
7a387fff 6837 case 3:
d75c135e 6838 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6839 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660 6840 rn = "SRSMap";
fd88b6ab 6841 break;
7a387fff 6842 default:
f31b035a 6843 goto cp0_unimplemented;
7a387fff 6844 }
873eb012
TS
6845 break;
6846 case 13:
7a387fff
TS
6847 switch (sel) {
6848 case 0:
7db13fae 6849 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
6850 rn = "Cause";
6851 break;
7a387fff 6852 default:
f31b035a 6853 goto cp0_unimplemented;
7a387fff 6854 }
873eb012
TS
6855 break;
6856 case 14:
7a387fff
TS
6857 switch (sel) {
6858 case 0:
7db13fae 6859 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 6860 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
6861 rn = "EPC";
6862 break;
7a387fff 6863 default:
f31b035a 6864 goto cp0_unimplemented;
1579a72e 6865 }
873eb012
TS
6866 break;
6867 case 15:
7a387fff
TS
6868 switch (sel) {
6869 case 0:
7db13fae 6870 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
6871 rn = "PRid";
6872 break;
7a387fff 6873 case 1:
d75c135e 6874 check_insn(ctx, ISA_MIPS32R2);
74dbf824
JH
6875 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6876 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
6877 rn = "EBase";
6878 break;
c870e3f5
YK
6879 case 3:
6880 check_insn(ctx, ISA_MIPS32R2);
6881 CP0_CHECK(ctx->cmgcr);
6882 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6883 tcg_gen_ext32s_tl(arg, arg);
6884 rn = "CMGCRBase";
6885 break;
7a387fff 6886 default:
f31b035a 6887 goto cp0_unimplemented;
7a387fff 6888 }
873eb012
TS
6889 break;
6890 case 16:
6891 switch (sel) {
6892 case 0:
7db13fae 6893 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
873eb012
TS
6894 rn = "Config";
6895 break;
6896 case 1:
7db13fae 6897 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
873eb012
TS
6898 rn = "Config1";
6899 break;
7a387fff 6900 case 2:
7db13fae 6901 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7a387fff
TS
6902 rn = "Config2";
6903 break;
6904 case 3:
7db13fae 6905 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7a387fff
TS
6906 rn = "Config3";
6907 break;
b4160af1
PJ
6908 case 4:
6909 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6910 rn = "Config4";
6911 break;
b4dd99a3
PJ
6912 case 5:
6913 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6914 rn = "Config5";
6915 break;
e397ee33
TS
6916 /* 6,7 are implementation dependent */
6917 case 6:
7db13fae 6918 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
e397ee33
TS
6919 rn = "Config6";
6920 break;
6921 case 7:
7db13fae 6922 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
e397ee33
TS
6923 rn = "Config7";
6924 break;
873eb012 6925 default:
f31b035a 6926 goto cp0_unimplemented;
873eb012
TS
6927 }
6928 break;
6929 case 17:
7a387fff
TS
6930 switch (sel) {
6931 case 0:
895c2d04 6932 gen_helper_mfc0_lladdr(arg, cpu_env);
2423f660
TS
6933 rn = "LLAddr";
6934 break;
f6d4dd81
YK
6935 case 1:
6936 CP0_CHECK(ctx->mrp);
6937 gen_helper_mfc0_maar(arg, cpu_env);
6938 rn = "MAAR";
6939 break;
6940 case 2:
6941 CP0_CHECK(ctx->mrp);
6942 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6943 rn = "MAARI";
6944 break;
7a387fff 6945 default:
f31b035a 6946 goto cp0_unimplemented;
7a387fff 6947 }
873eb012
TS
6948 break;
6949 case 18:
7a387fff 6950 switch (sel) {
c2e19f3c
AM
6951 case 0:
6952 case 1:
6953 case 2:
6954 case 3:
6955 case 4:
6956 case 5:
6957 case 6:
6958 case 7:
fa192d49 6959 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 6960 gen_helper_1e0i(mfc0_watchlo, arg, sel);
2423f660
TS
6961 rn = "WatchLo";
6962 break;
7a387fff 6963 default:
f31b035a 6964 goto cp0_unimplemented;
7a387fff 6965 }
873eb012
TS
6966 break;
6967 case 19:
7a387fff 6968 switch (sel) {
c2e19f3c
AM
6969 case 0:
6970 case 1:
6971 case 2:
6972 case 3:
6973 case 4:
6974 case 5:
6975 case 6:
6976 case 7:
fa192d49 6977 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 6978 gen_helper_1e0i(mfc0_watchhi, arg, sel);
2423f660
TS
6979 rn = "WatchHi";
6980 break;
7a387fff 6981 default:
f31b035a 6982 goto cp0_unimplemented;
7a387fff 6983 }
873eb012 6984 break;
8c0fdd85 6985 case 20:
7a387fff
TS
6986 switch (sel) {
6987 case 0:
d26bc211 6988#if defined(TARGET_MIPS64)
d75c135e 6989 check_insn(ctx, ISA_MIPS3);
7db13fae 6990 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 6991 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
6992 rn = "XContext";
6993 break;
703eaf37 6994#endif
7a387fff 6995 default:
f31b035a 6996 goto cp0_unimplemented;
7a387fff 6997 }
8c0fdd85
TS
6998 break;
6999 case 21:
7a387fff 7000 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 7001 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
7002 switch (sel) {
7003 case 0:
7db13fae 7004 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
7005 rn = "Framemask";
7006 break;
7a387fff 7007 default:
f31b035a 7008 goto cp0_unimplemented;
7a387fff 7009 }
8c0fdd85
TS
7010 break;
7011 case 22:
d9bea114 7012 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
7013 rn = "'Diagnostic"; /* implementation dependent */
7014 break;
873eb012 7015 case 23:
7a387fff
TS
7016 switch (sel) {
7017 case 0:
895c2d04 7018 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
2423f660
TS
7019 rn = "Debug";
7020 break;
7a387fff 7021 case 1:
d9bea114 7022// gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
2423f660 7023 rn = "TraceControl";
3570d7f6 7024 goto cp0_unimplemented;
7a387fff 7025 case 2:
d9bea114 7026// gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
2423f660 7027 rn = "TraceControl2";
3570d7f6 7028 goto cp0_unimplemented;
7a387fff 7029 case 3:
d9bea114 7030// gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
2423f660 7031 rn = "UserTraceData";
3570d7f6 7032 goto cp0_unimplemented;
7a387fff 7033 case 4:
d9bea114 7034// gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
2423f660 7035 rn = "TraceBPC";
3570d7f6 7036 goto cp0_unimplemented;
7a387fff 7037 default:
f31b035a 7038 goto cp0_unimplemented;
7a387fff 7039 }
873eb012
TS
7040 break;
7041 case 24:
7a387fff
TS
7042 switch (sel) {
7043 case 0:
f0b3f3ae 7044 /* EJTAG support */
7db13fae 7045 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 7046 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
7047 rn = "DEPC";
7048 break;
7a387fff 7049 default:
f31b035a 7050 goto cp0_unimplemented;
7a387fff 7051 }
873eb012 7052 break;
8c0fdd85 7053 case 25:
7a387fff
TS
7054 switch (sel) {
7055 case 0:
7db13fae 7056 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 7057 rn = "Performance0";
7a387fff
TS
7058 break;
7059 case 1:
d9bea114 7060// gen_helper_mfc0_performance1(arg);
2423f660 7061 rn = "Performance1";
3570d7f6 7062 goto cp0_unimplemented;
7a387fff 7063 case 2:
d9bea114 7064// gen_helper_mfc0_performance2(arg);
2423f660 7065 rn = "Performance2";
3570d7f6 7066 goto cp0_unimplemented;
7a387fff 7067 case 3:
d9bea114 7068// gen_helper_mfc0_performance3(arg);
2423f660 7069 rn = "Performance3";
3570d7f6 7070 goto cp0_unimplemented;
7a387fff 7071 case 4:
d9bea114 7072// gen_helper_mfc0_performance4(arg);
2423f660 7073 rn = "Performance4";
3570d7f6 7074 goto cp0_unimplemented;
7a387fff 7075 case 5:
d9bea114 7076// gen_helper_mfc0_performance5(arg);
2423f660 7077 rn = "Performance5";
3570d7f6 7078 goto cp0_unimplemented;
7a387fff 7079 case 6:
d9bea114 7080// gen_helper_mfc0_performance6(arg);
2423f660 7081 rn = "Performance6";
3570d7f6 7082 goto cp0_unimplemented;
7a387fff 7083 case 7:
d9bea114 7084// gen_helper_mfc0_performance7(arg);
2423f660 7085 rn = "Performance7";
3570d7f6 7086 goto cp0_unimplemented;
7a387fff 7087 default:
f31b035a 7088 goto cp0_unimplemented;
7a387fff 7089 }
8c0fdd85
TS
7090 break;
7091 case 26:
0d74a222
LA
7092 switch (sel) {
7093 case 0:
7094 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7095 rn = "ErrCtl";
7096 break;
7097 default:
7098 goto cp0_unimplemented;
7099 }
da80682b 7100 break;
8c0fdd85 7101 case 27:
7a387fff 7102 switch (sel) {
c2e19f3c
AM
7103 case 0:
7104 case 1:
7105 case 2:
7106 case 3:
d9bea114 7107 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
7108 rn = "CacheErr";
7109 break;
7a387fff 7110 default:
f31b035a 7111 goto cp0_unimplemented;
7a387fff 7112 }
8c0fdd85 7113 break;
873eb012
TS
7114 case 28:
7115 switch (sel) {
7116 case 0:
7a387fff
TS
7117 case 2:
7118 case 4:
7119 case 6:
284b731a
LA
7120 {
7121 TCGv_i64 tmp = tcg_temp_new_i64();
7122 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7123 gen_move_low32(arg, tmp);
7124 tcg_temp_free_i64(tmp);
7125 }
873eb012
TS
7126 rn = "TagLo";
7127 break;
7128 case 1:
7a387fff
TS
7129 case 3:
7130 case 5:
7131 case 7:
7db13fae 7132 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
873eb012
TS
7133 rn = "DataLo";
7134 break;
7135 default:
f31b035a 7136 goto cp0_unimplemented;
873eb012
TS
7137 }
7138 break;
8c0fdd85 7139 case 29:
7a387fff
TS
7140 switch (sel) {
7141 case 0:
7142 case 2:
7143 case 4:
7144 case 6:
7db13fae 7145 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7a387fff
TS
7146 rn = "TagHi";
7147 break;
7148 case 1:
7149 case 3:
7150 case 5:
7151 case 7:
7db13fae 7152 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7a387fff
TS
7153 rn = "DataHi";
7154 break;
7155 default:
f31b035a 7156 goto cp0_unimplemented;
7a387fff 7157 }
8c0fdd85 7158 break;
873eb012 7159 case 30:
7a387fff
TS
7160 switch (sel) {
7161 case 0:
7db13fae 7162 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 7163 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
7164 rn = "ErrorEPC";
7165 break;
7a387fff 7166 default:
f31b035a 7167 goto cp0_unimplemented;
7a387fff 7168 }
873eb012
TS
7169 break;
7170 case 31:
7a387fff
TS
7171 switch (sel) {
7172 case 0:
f0b3f3ae 7173 /* EJTAG support */
7db13fae 7174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
7175 rn = "DESAVE";
7176 break;
c2e19f3c
AM
7177 case 2:
7178 case 3:
7179 case 4:
7180 case 5:
7181 case 6:
7182 case 7:
f31b035a
LA
7183 CP0_CHECK(ctx->kscrexist & (1 << sel));
7184 tcg_gen_ld_tl(arg, cpu_env,
7185 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7186 tcg_gen_ext32s_tl(arg, arg);
7187 rn = "KScratch";
e98c0d17 7188 break;
7a387fff 7189 default:
f31b035a 7190 goto cp0_unimplemented;
7a387fff 7191 }
873eb012
TS
7192 break;
7193 default:
f31b035a 7194 goto cp0_unimplemented;
873eb012 7195 }
b44a7fb1 7196 trace_mips_translate_c0("mfc0", rn, reg, sel);
873eb012
TS
7197 return;
7198
f31b035a 7199cp0_unimplemented:
965447ee 7200 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
f31b035a 7201 gen_mfc0_unimplemented(ctx, arg);
873eb012
TS
7202}
7203
d75c135e 7204static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 7205{
7a387fff
TS
7206 const char *rn = "invalid";
7207
e189e748 7208 if (sel != 0)
d75c135e 7209 check_insn(ctx, ISA_MIPS32);
e189e748 7210
eeb3bba8 7211 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7212 gen_io_start();
bd79255d 7213 }
2e70f6ef 7214
8c0fdd85
TS
7215 switch (reg) {
7216 case 0:
7a387fff
TS
7217 switch (sel) {
7218 case 0:
895c2d04 7219 gen_helper_mtc0_index(cpu_env, arg);
7a387fff
TS
7220 rn = "Index";
7221 break;
7222 case 1:
f31b035a 7223 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7224 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7a387fff 7225 rn = "MVPControl";
ead9360e 7226 break;
7a387fff 7227 case 2:
f31b035a 7228 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7229 /* ignored */
7a387fff 7230 rn = "MVPConf0";
ead9360e 7231 break;
7a387fff 7232 case 3:
f31b035a 7233 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7234 /* ignored */
7a387fff 7235 rn = "MVPConf1";
ead9360e 7236 break;
01bc435b
YK
7237 case 4:
7238 CP0_CHECK(ctx->vp);
7239 /* ignored */
7240 rn = "VPControl";
7241 break;
7a387fff 7242 default:
f31b035a 7243 goto cp0_unimplemented;
7a387fff 7244 }
8c0fdd85
TS
7245 break;
7246 case 1:
7a387fff
TS
7247 switch (sel) {
7248 case 0:
2423f660 7249 /* ignored */
7a387fff 7250 rn = "Random";
2423f660 7251 break;
7a387fff 7252 case 1:
f31b035a 7253 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7254 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7a387fff 7255 rn = "VPEControl";
ead9360e 7256 break;
7a387fff 7257 case 2:
f31b035a 7258 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7259 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7a387fff 7260 rn = "VPEConf0";
ead9360e 7261 break;
7a387fff 7262 case 3:
f31b035a 7263 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7264 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7a387fff 7265 rn = "VPEConf1";
ead9360e 7266 break;
7a387fff 7267 case 4:
f31b035a 7268 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7269 gen_helper_mtc0_yqmask(cpu_env, arg);
7a387fff 7270 rn = "YQMask";
ead9360e 7271 break;
7a387fff 7272 case 5:
f31b035a 7273 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
7274 tcg_gen_st_tl(arg, cpu_env,
7275 offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 7276 rn = "VPESchedule";
ead9360e 7277 break;
7a387fff 7278 case 6:
f31b035a 7279 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
7280 tcg_gen_st_tl(arg, cpu_env,
7281 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 7282 rn = "VPEScheFBack";
ead9360e 7283 break;
7a387fff 7284 case 7:
f31b035a 7285 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7286 gen_helper_mtc0_vpeopt(cpu_env, arg);
7a387fff 7287 rn = "VPEOpt";
ead9360e 7288 break;
7a387fff 7289 default:
f31b035a 7290 goto cp0_unimplemented;
7a387fff 7291 }
8c0fdd85
TS
7292 break;
7293 case 2:
7a387fff
TS
7294 switch (sel) {
7295 case 0:
895c2d04 7296 gen_helper_mtc0_entrylo0(cpu_env, arg);
2423f660
TS
7297 rn = "EntryLo0";
7298 break;
7a387fff 7299 case 1:
f31b035a 7300 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7301 gen_helper_mtc0_tcstatus(cpu_env, arg);
2423f660 7302 rn = "TCStatus";
ead9360e 7303 break;
7a387fff 7304 case 2:
f31b035a 7305 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7306 gen_helper_mtc0_tcbind(cpu_env, arg);
2423f660 7307 rn = "TCBind";
ead9360e 7308 break;
7a387fff 7309 case 3:
f31b035a 7310 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7311 gen_helper_mtc0_tcrestart(cpu_env, arg);
2423f660 7312 rn = "TCRestart";
ead9360e 7313 break;
7a387fff 7314 case 4:
f31b035a 7315 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7316 gen_helper_mtc0_tchalt(cpu_env, arg);
2423f660 7317 rn = "TCHalt";
ead9360e 7318 break;
7a387fff 7319 case 5:
f31b035a 7320 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7321 gen_helper_mtc0_tccontext(cpu_env, arg);
2423f660 7322 rn = "TCContext";
ead9360e 7323 break;
7a387fff 7324 case 6:
f31b035a 7325 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7326 gen_helper_mtc0_tcschedule(cpu_env, arg);
2423f660 7327 rn = "TCSchedule";
ead9360e 7328 break;
7a387fff 7329 case 7:
f31b035a 7330 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7331 gen_helper_mtc0_tcschefback(cpu_env, arg);
2423f660 7332 rn = "TCScheFBack";
ead9360e 7333 break;
7a387fff 7334 default:
f31b035a 7335 goto cp0_unimplemented;
7a387fff 7336 }
8c0fdd85
TS
7337 break;
7338 case 3:
7a387fff
TS
7339 switch (sel) {
7340 case 0:
895c2d04 7341 gen_helper_mtc0_entrylo1(cpu_env, arg);
2423f660
TS
7342 rn = "EntryLo1";
7343 break;
01bc435b
YK
7344 case 1:
7345 CP0_CHECK(ctx->vp);
7346 /* ignored */
7347 rn = "GlobalNumber";
7348 break;
7a387fff 7349 default:
f31b035a 7350 goto cp0_unimplemented;
876d4b07 7351 }
8c0fdd85
TS
7352 break;
7353 case 4:
7a387fff
TS
7354 switch (sel) {
7355 case 0:
895c2d04 7356 gen_helper_mtc0_context(cpu_env, arg);
2423f660
TS
7357 rn = "Context";
7358 break;
7a387fff 7359 case 1:
895c2d04 7360// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
2423f660 7361 rn = "ContextConfig";
f31b035a 7362 goto cp0_unimplemented;
d279279e 7363 case 2:
f31b035a
LA
7364 CP0_CHECK(ctx->ulri);
7365 tcg_gen_st_tl(arg, cpu_env,
7366 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7367 rn = "UserLocal";
d279279e 7368 break;
7a387fff 7369 default:
f31b035a 7370 goto cp0_unimplemented;
876d4b07 7371 }
8c0fdd85
TS
7372 break;
7373 case 5:
7a387fff
TS
7374 switch (sel) {
7375 case 0:
895c2d04 7376 gen_helper_mtc0_pagemask(cpu_env, arg);
2423f660
TS
7377 rn = "PageMask";
7378 break;
7a387fff 7379 case 1:
d75c135e 7380 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7381 gen_helper_mtc0_pagegrain(cpu_env, arg);
2423f660 7382 rn = "PageGrain";
eeb3bba8 7383 ctx->base.is_jmp = DISAS_STOP;
2423f660 7384 break;
cec56a73
JH
7385 case 2:
7386 CP0_CHECK(ctx->sc);
7387 gen_helper_mtc0_segctl0(cpu_env, arg);
7388 rn = "SegCtl0";
7389 break;
7390 case 3:
7391 CP0_CHECK(ctx->sc);
7392 gen_helper_mtc0_segctl1(cpu_env, arg);
7393 rn = "SegCtl1";
7394 break;
7395 case 4:
7396 CP0_CHECK(ctx->sc);
7397 gen_helper_mtc0_segctl2(cpu_env, arg);
7398 rn = "SegCtl2";
7399 break;
5e31fdd5
YK
7400 case 5:
7401 check_pw(ctx);
7402 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7403 rn = "PWBase";
7404 break;
fa75ad14
YK
7405 case 6:
7406 check_pw(ctx);
7407 gen_helper_mtc0_pwfield(cpu_env, arg);
7408 rn = "PWField";
7409 break;
20b28ebc
YK
7410 case 7:
7411 check_pw(ctx);
7412 gen_helper_mtc0_pwsize(cpu_env, arg);
7413 rn = "PWSize";
7414 break;
7a387fff 7415 default:
f31b035a 7416 goto cp0_unimplemented;
876d4b07 7417 }
8c0fdd85
TS
7418 break;
7419 case 6:
7a387fff
TS
7420 switch (sel) {
7421 case 0:
895c2d04 7422 gen_helper_mtc0_wired(cpu_env, arg);
2423f660
TS
7423 rn = "Wired";
7424 break;
7a387fff 7425 case 1:
d75c135e 7426 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7427 gen_helper_mtc0_srsconf0(cpu_env, arg);
2423f660 7428 rn = "SRSConf0";
ead9360e 7429 break;
7a387fff 7430 case 2:
d75c135e 7431 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7432 gen_helper_mtc0_srsconf1(cpu_env, arg);
2423f660 7433 rn = "SRSConf1";
ead9360e 7434 break;
7a387fff 7435 case 3:
d75c135e 7436 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7437 gen_helper_mtc0_srsconf2(cpu_env, arg);
2423f660 7438 rn = "SRSConf2";
ead9360e 7439 break;
7a387fff 7440 case 4:
d75c135e 7441 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7442 gen_helper_mtc0_srsconf3(cpu_env, arg);
2423f660 7443 rn = "SRSConf3";
ead9360e 7444 break;
7a387fff 7445 case 5:
d75c135e 7446 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7447 gen_helper_mtc0_srsconf4(cpu_env, arg);
2423f660 7448 rn = "SRSConf4";
ead9360e 7449 break;
103be64c
YK
7450 case 6:
7451 check_pw(ctx);
7452 gen_helper_mtc0_pwctl(cpu_env, arg);
7453 rn = "PWCtl";
7454 break;
7a387fff 7455 default:
f31b035a 7456 goto cp0_unimplemented;
876d4b07 7457 }
8c0fdd85
TS
7458 break;
7459 case 7:
7a387fff
TS
7460 switch (sel) {
7461 case 0:
d75c135e 7462 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7463 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 7464 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
7465 rn = "HWREna";
7466 break;
7a387fff 7467 default:
f31b035a 7468 goto cp0_unimplemented;
876d4b07 7469 }
8c0fdd85
TS
7470 break;
7471 case 8:
aea14095
LA
7472 switch (sel) {
7473 case 0:
7474 /* ignored */
7475 rn = "BadVAddr";
7476 break;
7477 case 1:
7478 /* ignored */
7479 rn = "BadInstr";
7480 break;
7481 case 2:
7482 /* ignored */
7483 rn = "BadInstrP";
7484 break;
25beba9b
SM
7485 case 3:
7486 /* ignored */
7487 rn = "BadInstrX";
7488 break;
aea14095 7489 default:
f31b035a 7490 goto cp0_unimplemented;
aea14095 7491 }
8c0fdd85
TS
7492 break;
7493 case 9:
7a387fff
TS
7494 switch (sel) {
7495 case 0:
895c2d04 7496 gen_helper_mtc0_count(cpu_env, arg);
2423f660
TS
7497 rn = "Count";
7498 break;
876d4b07 7499 /* 6,7 are implementation dependent */
7a387fff 7500 default:
f31b035a 7501 goto cp0_unimplemented;
876d4b07 7502 }
8c0fdd85
TS
7503 break;
7504 case 10:
7a387fff
TS
7505 switch (sel) {
7506 case 0:
895c2d04 7507 gen_helper_mtc0_entryhi(cpu_env, arg);
2423f660
TS
7508 rn = "EntryHi";
7509 break;
7a387fff 7510 default:
f31b035a 7511 goto cp0_unimplemented;
876d4b07 7512 }
8c0fdd85
TS
7513 break;
7514 case 11:
7a387fff
TS
7515 switch (sel) {
7516 case 0:
895c2d04 7517 gen_helper_mtc0_compare(cpu_env, arg);
2423f660
TS
7518 rn = "Compare";
7519 break;
7520 /* 6,7 are implementation dependent */
7a387fff 7521 default:
f31b035a 7522 goto cp0_unimplemented;
876d4b07 7523 }
8c0fdd85
TS
7524 break;
7525 case 12:
7a387fff
TS
7526 switch (sel) {
7527 case 0:
867abc7e 7528 save_cpu_state(ctx, 1);
895c2d04 7529 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 7530 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
7531 gen_save_pc(ctx->base.pc_next + 4);
7532 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
7533 rn = "Status";
7534 break;
7a387fff 7535 case 1:
d75c135e 7536 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7537 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 7538 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7539 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
7540 rn = "IntCtl";
7541 break;
7a387fff 7542 case 2:
d75c135e 7543 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7544 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 7545 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7546 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
7547 rn = "SRSCtl";
7548 break;
7a387fff 7549 case 3:
d75c135e 7550 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7551 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 7552 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7553 ctx->base.is_jmp = DISAS_STOP;
2423f660 7554 rn = "SRSMap";
fd88b6ab 7555 break;
7a387fff 7556 default:
f31b035a 7557 goto cp0_unimplemented;
876d4b07 7558 }
8c0fdd85
TS
7559 break;
7560 case 13:
7a387fff
TS
7561 switch (sel) {
7562 case 0:
867abc7e 7563 save_cpu_state(ctx, 1);
895c2d04 7564 gen_helper_mtc0_cause(cpu_env, arg);
b28425ba
EC
7565 /* Stop translation as we may have triggered an interrupt.
7566 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7567 * translated code to check for pending interrupts. */
eeb3bba8
EC
7568 gen_save_pc(ctx->base.pc_next + 4);
7569 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
7570 rn = "Cause";
7571 break;
7a387fff 7572 default:
f31b035a 7573 goto cp0_unimplemented;
876d4b07 7574 }
8c0fdd85
TS
7575 break;
7576 case 14:
7a387fff
TS
7577 switch (sel) {
7578 case 0:
d54a299b 7579 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
7580 rn = "EPC";
7581 break;
7a387fff 7582 default:
f31b035a 7583 goto cp0_unimplemented;
876d4b07 7584 }
8c0fdd85
TS
7585 break;
7586 case 15:
7a387fff
TS
7587 switch (sel) {
7588 case 0:
2423f660
TS
7589 /* ignored */
7590 rn = "PRid";
7591 break;
7a387fff 7592 case 1:
d75c135e 7593 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7594 gen_helper_mtc0_ebase(cpu_env, arg);
2423f660
TS
7595 rn = "EBase";
7596 break;
7a387fff 7597 default:
f31b035a 7598 goto cp0_unimplemented;
1579a72e 7599 }
8c0fdd85
TS
7600 break;
7601 case 16:
7602 switch (sel) {
7603 case 0:
895c2d04 7604 gen_helper_mtc0_config0(cpu_env, arg);
7a387fff 7605 rn = "Config";
2423f660 7606 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7607 ctx->base.is_jmp = DISAS_STOP;
7a387fff
TS
7608 break;
7609 case 1:
e397ee33 7610 /* ignored, read only */
7a387fff
TS
7611 rn = "Config1";
7612 break;
7613 case 2:
895c2d04 7614 gen_helper_mtc0_config2(cpu_env, arg);
7a387fff 7615 rn = "Config2";
2423f660 7616 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7617 ctx->base.is_jmp = DISAS_STOP;
8c0fdd85 7618 break;
7a387fff 7619 case 3:
90f12d73 7620 gen_helper_mtc0_config3(cpu_env, arg);
7a387fff 7621 rn = "Config3";
90f12d73 7622 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7623 ctx->base.is_jmp = DISAS_STOP;
7a387fff 7624 break;
b4160af1
PJ
7625 case 4:
7626 gen_helper_mtc0_config4(cpu_env, arg);
7627 rn = "Config4";
eeb3bba8 7628 ctx->base.is_jmp = DISAS_STOP;
b4160af1 7629 break;
b4dd99a3
PJ
7630 case 5:
7631 gen_helper_mtc0_config5(cpu_env, arg);
7632 rn = "Config5";
7633 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7634 ctx->base.is_jmp = DISAS_STOP;
b4dd99a3 7635 break;
e397ee33
TS
7636 /* 6,7 are implementation dependent */
7637 case 6:
7638 /* ignored */
7639 rn = "Config6";
7640 break;
7641 case 7:
7642 /* ignored */
7643 rn = "Config7";
7644 break;
8c0fdd85
TS
7645 default:
7646 rn = "Invalid config selector";
f31b035a 7647 goto cp0_unimplemented;
8c0fdd85
TS
7648 }
7649 break;
7650 case 17:
7a387fff
TS
7651 switch (sel) {
7652 case 0:
895c2d04 7653 gen_helper_mtc0_lladdr(cpu_env, arg);
2423f660
TS
7654 rn = "LLAddr";
7655 break;
f6d4dd81
YK
7656 case 1:
7657 CP0_CHECK(ctx->mrp);
7658 gen_helper_mtc0_maar(cpu_env, arg);
7659 rn = "MAAR";
7660 break;
7661 case 2:
7662 CP0_CHECK(ctx->mrp);
7663 gen_helper_mtc0_maari(cpu_env, arg);
7664 rn = "MAARI";
7665 break;
7a387fff 7666 default:
f31b035a 7667 goto cp0_unimplemented;
7a387fff 7668 }
8c0fdd85
TS
7669 break;
7670 case 18:
7a387fff 7671 switch (sel) {
c2e19f3c
AM
7672 case 0:
7673 case 1:
7674 case 2:
7675 case 3:
7676 case 4:
7677 case 5:
7678 case 6:
7679 case 7:
fa192d49 7680 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7681 gen_helper_0e1i(mtc0_watchlo, arg, sel);
2423f660
TS
7682 rn = "WatchLo";
7683 break;
7a387fff 7684 default:
f31b035a 7685 goto cp0_unimplemented;
7a387fff 7686 }
8c0fdd85
TS
7687 break;
7688 case 19:
7a387fff 7689 switch (sel) {
c2e19f3c
AM
7690 case 0:
7691 case 1:
7692 case 2:
7693 case 3:
7694 case 4:
7695 case 5:
7696 case 6:
7697 case 7:
fa192d49 7698 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7699 gen_helper_0e1i(mtc0_watchhi, arg, sel);
2423f660
TS
7700 rn = "WatchHi";
7701 break;
7a387fff 7702 default:
f31b035a 7703 goto cp0_unimplemented;
7a387fff 7704 }
8c0fdd85
TS
7705 break;
7706 case 20:
7a387fff
TS
7707 switch (sel) {
7708 case 0:
d26bc211 7709#if defined(TARGET_MIPS64)
d75c135e 7710 check_insn(ctx, ISA_MIPS3);
895c2d04 7711 gen_helper_mtc0_xcontext(cpu_env, arg);
2423f660
TS
7712 rn = "XContext";
7713 break;
703eaf37 7714#endif
7a387fff 7715 default:
f31b035a 7716 goto cp0_unimplemented;
7a387fff 7717 }
8c0fdd85
TS
7718 break;
7719 case 21:
7a387fff 7720 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 7721 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
7722 switch (sel) {
7723 case 0:
895c2d04 7724 gen_helper_mtc0_framemask(cpu_env, arg);
2423f660
TS
7725 rn = "Framemask";
7726 break;
7a387fff 7727 default:
f31b035a 7728 goto cp0_unimplemented;
7a387fff
TS
7729 }
7730 break;
8c0fdd85 7731 case 22:
7a387fff
TS
7732 /* ignored */
7733 rn = "Diagnostic"; /* implementation dependent */
2423f660 7734 break;
8c0fdd85 7735 case 23:
7a387fff
TS
7736 switch (sel) {
7737 case 0:
895c2d04 7738 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 7739 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
7740 gen_save_pc(ctx->base.pc_next + 4);
7741 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
7742 rn = "Debug";
7743 break;
7a387fff 7744 case 1:
895c2d04 7745// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
2423f660 7746 rn = "TraceControl";
8487327a 7747 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7748 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 7749 goto cp0_unimplemented;
7a387fff 7750 case 2:
895c2d04 7751// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
2423f660 7752 rn = "TraceControl2";
8487327a 7753 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7754 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 7755 goto cp0_unimplemented;
7a387fff 7756 case 3:
8487327a 7757 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7758 ctx->base.is_jmp = DISAS_STOP;
895c2d04 7759// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
2423f660 7760 rn = "UserTraceData";
8487327a 7761 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7762 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 7763 goto cp0_unimplemented;
7a387fff 7764 case 4:
895c2d04 7765// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a 7766 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7767 ctx->base.is_jmp = DISAS_STOP;
2423f660 7768 rn = "TraceBPC";
3570d7f6 7769 goto cp0_unimplemented;
7a387fff 7770 default:
f31b035a 7771 goto cp0_unimplemented;
7a387fff 7772 }
8c0fdd85
TS
7773 break;
7774 case 24:
7a387fff
TS
7775 switch (sel) {
7776 case 0:
f1aa6320 7777 /* EJTAG support */
d54a299b 7778 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
7779 rn = "DEPC";
7780 break;
7a387fff 7781 default:
f31b035a 7782 goto cp0_unimplemented;
7a387fff 7783 }
8c0fdd85
TS
7784 break;
7785 case 25:
7a387fff
TS
7786 switch (sel) {
7787 case 0:
895c2d04 7788 gen_helper_mtc0_performance0(cpu_env, arg);
2423f660
TS
7789 rn = "Performance0";
7790 break;
7a387fff 7791 case 1:
d9bea114 7792// gen_helper_mtc0_performance1(arg);
2423f660 7793 rn = "Performance1";
3570d7f6 7794 goto cp0_unimplemented;
7a387fff 7795 case 2:
d9bea114 7796// gen_helper_mtc0_performance2(arg);
2423f660 7797 rn = "Performance2";
3570d7f6 7798 goto cp0_unimplemented;
7a387fff 7799 case 3:
d9bea114 7800// gen_helper_mtc0_performance3(arg);
2423f660 7801 rn = "Performance3";
3570d7f6 7802 goto cp0_unimplemented;
7a387fff 7803 case 4:
d9bea114 7804// gen_helper_mtc0_performance4(arg);
2423f660 7805 rn = "Performance4";
3570d7f6 7806 goto cp0_unimplemented;
7a387fff 7807 case 5:
d9bea114 7808// gen_helper_mtc0_performance5(arg);
2423f660 7809 rn = "Performance5";
3570d7f6 7810 goto cp0_unimplemented;
7a387fff 7811 case 6:
d9bea114 7812// gen_helper_mtc0_performance6(arg);
2423f660 7813 rn = "Performance6";
3570d7f6 7814 goto cp0_unimplemented;
7a387fff 7815 case 7:
d9bea114 7816// gen_helper_mtc0_performance7(arg);
2423f660 7817 rn = "Performance7";
3570d7f6 7818 goto cp0_unimplemented;
7a387fff 7819 default:
f31b035a 7820 goto cp0_unimplemented;
7a387fff 7821 }
8c0fdd85
TS
7822 break;
7823 case 26:
0d74a222
LA
7824 switch (sel) {
7825 case 0:
7826 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 7827 ctx->base.is_jmp = DISAS_STOP;
0d74a222
LA
7828 rn = "ErrCtl";
7829 break;
7830 default:
7831 goto cp0_unimplemented;
7832 }
2423f660 7833 break;
8c0fdd85 7834 case 27:
7a387fff 7835 switch (sel) {
c2e19f3c
AM
7836 case 0:
7837 case 1:
7838 case 2:
7839 case 3:
2423f660
TS
7840 /* ignored */
7841 rn = "CacheErr";
7842 break;
7a387fff 7843 default:
f31b035a 7844 goto cp0_unimplemented;
7a387fff 7845 }
8c0fdd85
TS
7846 break;
7847 case 28:
7848 switch (sel) {
7849 case 0:
7a387fff
TS
7850 case 2:
7851 case 4:
7852 case 6:
895c2d04 7853 gen_helper_mtc0_taglo(cpu_env, arg);
8c0fdd85
TS
7854 rn = "TagLo";
7855 break;
7a387fff
TS
7856 case 1:
7857 case 3:
7858 case 5:
7859 case 7:
895c2d04 7860 gen_helper_mtc0_datalo(cpu_env, arg);
7a387fff
TS
7861 rn = "DataLo";
7862 break;
8c0fdd85 7863 default:
f31b035a 7864 goto cp0_unimplemented;
8c0fdd85
TS
7865 }
7866 break;
7867 case 29:
7a387fff
TS
7868 switch (sel) {
7869 case 0:
7870 case 2:
7871 case 4:
7872 case 6:
895c2d04 7873 gen_helper_mtc0_taghi(cpu_env, arg);
7a387fff
TS
7874 rn = "TagHi";
7875 break;
7876 case 1:
7877 case 3:
7878 case 5:
7879 case 7:
895c2d04 7880 gen_helper_mtc0_datahi(cpu_env, arg);
7a387fff
TS
7881 rn = "DataHi";
7882 break;
7883 default:
7884 rn = "invalid sel";
f31b035a 7885 goto cp0_unimplemented;
7a387fff 7886 }
8c0fdd85
TS
7887 break;
7888 case 30:
7a387fff
TS
7889 switch (sel) {
7890 case 0:
d54a299b 7891 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
7892 rn = "ErrorEPC";
7893 break;
7a387fff 7894 default:
f31b035a 7895 goto cp0_unimplemented;
7a387fff 7896 }
8c0fdd85
TS
7897 break;
7898 case 31:
7a387fff
TS
7899 switch (sel) {
7900 case 0:
f1aa6320 7901 /* EJTAG support */
7db13fae 7902 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
7903 rn = "DESAVE";
7904 break;
c2e19f3c
AM
7905 case 2:
7906 case 3:
7907 case 4:
7908 case 5:
7909 case 6:
7910 case 7:
f31b035a
LA
7911 CP0_CHECK(ctx->kscrexist & (1 << sel));
7912 tcg_gen_st_tl(arg, cpu_env,
7913 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7914 rn = "KScratch";
e98c0d17 7915 break;
7a387fff 7916 default:
f31b035a 7917 goto cp0_unimplemented;
7a387fff 7918 }
8c0fdd85
TS
7919 break;
7920 default:
f31b035a 7921 goto cp0_unimplemented;
8c0fdd85 7922 }
b44a7fb1
PMD
7923 trace_mips_translate_c0("mtc0", rn, reg, sel);
7924
bf20dc07 7925 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 7926 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7927 gen_io_end();
b28425ba 7928 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
b74cddcb 7929 * translated code to check for pending interrupts. */
eeb3bba8
EC
7930 gen_save_pc(ctx->base.pc_next + 4);
7931 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 7932 }
8c0fdd85
TS
7933 return;
7934
f31b035a 7935cp0_unimplemented:
965447ee 7936 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8c0fdd85
TS
7937}
7938
d26bc211 7939#if defined(TARGET_MIPS64)
d75c135e 7940static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
7941{
7942 const char *rn = "invalid";
7943
e189e748 7944 if (sel != 0)
d75c135e 7945 check_insn(ctx, ISA_MIPS64);
e189e748 7946
9c2149c8
TS
7947 switch (reg) {
7948 case 0:
7949 switch (sel) {
7950 case 0:
7db13fae 7951 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
9c2149c8
TS
7952 rn = "Index";
7953 break;
7954 case 1:
f31b035a 7955 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7956 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
9c2149c8 7957 rn = "MVPControl";
ead9360e 7958 break;
9c2149c8 7959 case 2:
f31b035a 7960 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7961 gen_helper_mfc0_mvpconf0(arg, cpu_env);
9c2149c8 7962 rn = "MVPConf0";
ead9360e 7963 break;
9c2149c8 7964 case 3:
f31b035a 7965 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7966 gen_helper_mfc0_mvpconf1(arg, cpu_env);
9c2149c8 7967 rn = "MVPConf1";
ead9360e 7968 break;
01bc435b
YK
7969 case 4:
7970 CP0_CHECK(ctx->vp);
7971 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7972 rn = "VPControl";
7973 break;
9c2149c8 7974 default:
f31b035a 7975 goto cp0_unimplemented;
9c2149c8
TS
7976 }
7977 break;
7978 case 1:
7979 switch (sel) {
7980 case 0:
f31b035a 7981 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 7982 gen_helper_mfc0_random(arg, cpu_env);
9c2149c8 7983 rn = "Random";
2423f660 7984 break;
9c2149c8 7985 case 1:
f31b035a 7986 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7987 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
9c2149c8 7988 rn = "VPEControl";
ead9360e 7989 break;
9c2149c8 7990 case 2:
f31b035a 7991 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7992 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
9c2149c8 7993 rn = "VPEConf0";
ead9360e 7994 break;
9c2149c8 7995 case 3:
f31b035a 7996 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7997 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
9c2149c8 7998 rn = "VPEConf1";
ead9360e 7999 break;
9c2149c8 8000 case 4:
f31b035a 8001 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8002 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
9c2149c8 8003 rn = "YQMask";
ead9360e 8004 break;
9c2149c8 8005 case 5:
f31b035a 8006 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8007 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 8008 rn = "VPESchedule";
ead9360e 8009 break;
9c2149c8 8010 case 6:
f31b035a 8011 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8012 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 8013 rn = "VPEScheFBack";
ead9360e 8014 break;
9c2149c8 8015 case 7:
f31b035a 8016 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8017 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
9c2149c8 8018 rn = "VPEOpt";
ead9360e 8019 break;
9c2149c8 8020 default:
f31b035a 8021 goto cp0_unimplemented;
9c2149c8
TS
8022 }
8023 break;
8024 case 2:
8025 switch (sel) {
8026 case 0:
7db13fae 8027 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
2423f660
TS
8028 rn = "EntryLo0";
8029 break;
9c2149c8 8030 case 1:
f31b035a 8031 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8032 gen_helper_mfc0_tcstatus(arg, cpu_env);
2423f660 8033 rn = "TCStatus";
ead9360e 8034 break;
9c2149c8 8035 case 2:
f31b035a 8036 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8037 gen_helper_mfc0_tcbind(arg, cpu_env);
2423f660 8038 rn = "TCBind";
ead9360e 8039 break;
9c2149c8 8040 case 3:
f31b035a 8041 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8042 gen_helper_dmfc0_tcrestart(arg, cpu_env);
2423f660 8043 rn = "TCRestart";
ead9360e 8044 break;
9c2149c8 8045 case 4:
f31b035a 8046 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8047 gen_helper_dmfc0_tchalt(arg, cpu_env);
2423f660 8048 rn = "TCHalt";
ead9360e 8049 break;
9c2149c8 8050 case 5:
f31b035a 8051 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8052 gen_helper_dmfc0_tccontext(arg, cpu_env);
2423f660 8053 rn = "TCContext";
ead9360e 8054 break;
9c2149c8 8055 case 6:
f31b035a 8056 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8057 gen_helper_dmfc0_tcschedule(arg, cpu_env);
2423f660 8058 rn = "TCSchedule";
ead9360e 8059 break;
9c2149c8 8060 case 7:
f31b035a 8061 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8062 gen_helper_dmfc0_tcschefback(arg, cpu_env);
2423f660 8063 rn = "TCScheFBack";
ead9360e 8064 break;
9c2149c8 8065 default:
f31b035a 8066 goto cp0_unimplemented;
9c2149c8
TS
8067 }
8068 break;
8069 case 3:
8070 switch (sel) {
8071 case 0:
7db13fae 8072 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
2423f660
TS
8073 rn = "EntryLo1";
8074 break;
01bc435b
YK
8075 case 1:
8076 CP0_CHECK(ctx->vp);
8077 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8078 rn = "GlobalNumber";
8079 break;
9c2149c8 8080 default:
f31b035a 8081 goto cp0_unimplemented;
1579a72e 8082 }
9c2149c8
TS
8083 break;
8084 case 4:
8085 switch (sel) {
8086 case 0:
7db13fae 8087 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
2423f660
TS
8088 rn = "Context";
8089 break;
9c2149c8 8090 case 1:
d9bea114 8091// gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660 8092 rn = "ContextConfig";
f31b035a 8093 goto cp0_unimplemented;
d279279e 8094 case 2:
f31b035a
LA
8095 CP0_CHECK(ctx->ulri);
8096 tcg_gen_ld_tl(arg, cpu_env,
8097 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8098 rn = "UserLocal";
d279279e 8099 break;
9c2149c8 8100 default:
f31b035a 8101 goto cp0_unimplemented;
876d4b07 8102 }
9c2149c8
TS
8103 break;
8104 case 5:
8105 switch (sel) {
8106 case 0:
7db13fae 8107 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
8108 rn = "PageMask";
8109 break;
9c2149c8 8110 case 1:
d75c135e 8111 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8112 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
8113 rn = "PageGrain";
8114 break;
cec56a73
JH
8115 case 2:
8116 CP0_CHECK(ctx->sc);
8117 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8118 rn = "SegCtl0";
8119 break;
8120 case 3:
8121 CP0_CHECK(ctx->sc);
8122 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8123 rn = "SegCtl1";
8124 break;
8125 case 4:
8126 CP0_CHECK(ctx->sc);
8127 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8128 rn = "SegCtl2";
8129 break;
5e31fdd5
YK
8130 case 5:
8131 check_pw(ctx);
8132 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8133 rn = "PWBase";
8134 break;
fa75ad14
YK
8135 case 6:
8136 check_pw(ctx);
8137 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8138 rn = "PWField";
8139 break;
20b28ebc
YK
8140 case 7:
8141 check_pw(ctx);
8142 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8143 rn = "PWSize";
8144 break;
9c2149c8 8145 default:
f31b035a 8146 goto cp0_unimplemented;
876d4b07 8147 }
9c2149c8
TS
8148 break;
8149 case 6:
8150 switch (sel) {
8151 case 0:
7db13fae 8152 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
8153 rn = "Wired";
8154 break;
9c2149c8 8155 case 1:
d75c135e 8156 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8157 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 8158 rn = "SRSConf0";
ead9360e 8159 break;
9c2149c8 8160 case 2:
d75c135e 8161 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8162 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 8163 rn = "SRSConf1";
ead9360e 8164 break;
9c2149c8 8165 case 3:
d75c135e 8166 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8167 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 8168 rn = "SRSConf2";
ead9360e 8169 break;
9c2149c8 8170 case 4:
d75c135e 8171 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8172 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 8173 rn = "SRSConf3";
ead9360e 8174 break;
9c2149c8 8175 case 5:
d75c135e 8176 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8177 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 8178 rn = "SRSConf4";
ead9360e 8179 break;
103be64c
YK
8180 case 6:
8181 check_pw(ctx);
8182 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8183 rn = "PWCtl";
8184 break;
9c2149c8 8185 default:
f31b035a 8186 goto cp0_unimplemented;
876d4b07 8187 }
9c2149c8
TS
8188 break;
8189 case 7:
8190 switch (sel) {
8191 case 0:
d75c135e 8192 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8193 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
8194 rn = "HWREna";
8195 break;
9c2149c8 8196 default:
f31b035a 8197 goto cp0_unimplemented;
876d4b07 8198 }
9c2149c8
TS
8199 break;
8200 case 8:
8201 switch (sel) {
8202 case 0:
7db13fae 8203 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
f0b3f3ae 8204 rn = "BadVAddr";
2423f660 8205 break;
aea14095 8206 case 1:
f31b035a
LA
8207 CP0_CHECK(ctx->bi);
8208 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8209 rn = "BadInstr";
aea14095
LA
8210 break;
8211 case 2:
f31b035a
LA
8212 CP0_CHECK(ctx->bp);
8213 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8214 rn = "BadInstrP";
aea14095 8215 break;
25beba9b
SM
8216 case 3:
8217 CP0_CHECK(ctx->bi);
8218 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8219 tcg_gen_andi_tl(arg, arg, ~0xffff);
8220 rn = "BadInstrX";
8221 break;
9c2149c8 8222 default:
f31b035a 8223 goto cp0_unimplemented;
876d4b07 8224 }
9c2149c8
TS
8225 break;
8226 case 9:
8227 switch (sel) {
8228 case 0:
2e70f6ef 8229 /* Mark as an IO operation because we read the time. */
eeb3bba8 8230 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8231 gen_io_start();
bd79255d 8232 }
895c2d04 8233 gen_helper_mfc0_count(arg, cpu_env);
eeb3bba8 8234 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8235 gen_io_end();
2e70f6ef 8236 }
55807224 8237 /* Break the TB to be able to take timer interrupts immediately
b28425ba
EC
8238 after reading count. DISAS_STOP isn't sufficient, we need to
8239 ensure we break completely out of translated code. */
eeb3bba8
EC
8240 gen_save_pc(ctx->base.pc_next + 4);
8241 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
8242 rn = "Count";
8243 break;
8244 /* 6,7 are implementation dependent */
9c2149c8 8245 default:
f31b035a 8246 goto cp0_unimplemented;
876d4b07 8247 }
9c2149c8
TS
8248 break;
8249 case 10:
8250 switch (sel) {
8251 case 0:
7db13fae 8252 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
2423f660
TS
8253 rn = "EntryHi";
8254 break;
9c2149c8 8255 default:
f31b035a 8256 goto cp0_unimplemented;
876d4b07 8257 }
9c2149c8
TS
8258 break;
8259 case 11:
8260 switch (sel) {
8261 case 0:
7db13fae 8262 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
8263 rn = "Compare";
8264 break;
876d4b07 8265 /* 6,7 are implementation dependent */
9c2149c8 8266 default:
f31b035a 8267 goto cp0_unimplemented;
876d4b07 8268 }
9c2149c8
TS
8269 break;
8270 case 12:
8271 switch (sel) {
8272 case 0:
7db13fae 8273 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
8274 rn = "Status";
8275 break;
9c2149c8 8276 case 1:
d75c135e 8277 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8278 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
8279 rn = "IntCtl";
8280 break;
9c2149c8 8281 case 2:
d75c135e 8282 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8283 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
8284 rn = "SRSCtl";
8285 break;
9c2149c8 8286 case 3:
d75c135e 8287 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8288 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660
TS
8289 rn = "SRSMap";
8290 break;
9c2149c8 8291 default:
f31b035a 8292 goto cp0_unimplemented;
876d4b07 8293 }
9c2149c8
TS
8294 break;
8295 case 13:
8296 switch (sel) {
8297 case 0:
7db13fae 8298 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
8299 rn = "Cause";
8300 break;
9c2149c8 8301 default:
f31b035a 8302 goto cp0_unimplemented;
876d4b07 8303 }
9c2149c8
TS
8304 break;
8305 case 14:
8306 switch (sel) {
8307 case 0:
7db13fae 8308 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
8309 rn = "EPC";
8310 break;
9c2149c8 8311 default:
f31b035a 8312 goto cp0_unimplemented;
876d4b07 8313 }
9c2149c8
TS
8314 break;
8315 case 15:
8316 switch (sel) {
8317 case 0:
7db13fae 8318 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
8319 rn = "PRid";
8320 break;
9c2149c8 8321 case 1:
d75c135e 8322 check_insn(ctx, ISA_MIPS32R2);
74dbf824 8323 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
2423f660
TS
8324 rn = "EBase";
8325 break;
c870e3f5
YK
8326 case 3:
8327 check_insn(ctx, ISA_MIPS32R2);
8328 CP0_CHECK(ctx->cmgcr);
8329 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8330 rn = "CMGCRBase";
8331 break;
9c2149c8 8332 default:
f31b035a 8333 goto cp0_unimplemented;
876d4b07 8334 }
9c2149c8
TS
8335 break;
8336 case 16:
8337 switch (sel) {
8338 case 0:
7db13fae 8339 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
9c2149c8
TS
8340 rn = "Config";
8341 break;
8342 case 1:
7db13fae 8343 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
9c2149c8
TS
8344 rn = "Config1";
8345 break;
8346 case 2:
7db13fae 8347 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
9c2149c8
TS
8348 rn = "Config2";
8349 break;
8350 case 3:
7db13fae 8351 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
9c2149c8
TS
8352 rn = "Config3";
8353 break;
faf1f68b
LA
8354 case 4:
8355 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8356 rn = "Config4";
8357 break;
8358 case 5:
8359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8360 rn = "Config5";
8361 break;
9c2149c8 8362 /* 6,7 are implementation dependent */
f0b3f3ae 8363 case 6:
7db13fae 8364 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
f0b3f3ae
TS
8365 rn = "Config6";
8366 break;
8367 case 7:
7db13fae 8368 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
f0b3f3ae
TS
8369 rn = "Config7";
8370 break;
9c2149c8 8371 default:
f31b035a 8372 goto cp0_unimplemented;
9c2149c8
TS
8373 }
8374 break;
8375 case 17:
8376 switch (sel) {
8377 case 0:
895c2d04 8378 gen_helper_dmfc0_lladdr(arg, cpu_env);
2423f660
TS
8379 rn = "LLAddr";
8380 break;
f6d4dd81
YK
8381 case 1:
8382 CP0_CHECK(ctx->mrp);
8383 gen_helper_dmfc0_maar(arg, cpu_env);
8384 rn = "MAAR";
8385 break;
8386 case 2:
8387 CP0_CHECK(ctx->mrp);
8388 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8389 rn = "MAARI";
8390 break;
9c2149c8 8391 default:
f31b035a 8392 goto cp0_unimplemented;
9c2149c8
TS
8393 }
8394 break;
8395 case 18:
8396 switch (sel) {
c2e19f3c
AM
8397 case 0:
8398 case 1:
8399 case 2:
8400 case 3:
8401 case 4:
8402 case 5:
8403 case 6:
8404 case 7:
fa192d49 8405 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8406 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
2423f660
TS
8407 rn = "WatchLo";
8408 break;
9c2149c8 8409 default:
f31b035a 8410 goto cp0_unimplemented;
9c2149c8
TS
8411 }
8412 break;
8413 case 19:
8414 switch (sel) {
c2e19f3c
AM
8415 case 0:
8416 case 1:
8417 case 2:
8418 case 3:
8419 case 4:
8420 case 5:
8421 case 6:
8422 case 7:
fa192d49 8423 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8424 gen_helper_1e0i(mfc0_watchhi, arg, sel);
2423f660
TS
8425 rn = "WatchHi";
8426 break;
9c2149c8 8427 default:
f31b035a 8428 goto cp0_unimplemented;
9c2149c8
TS
8429 }
8430 break;
8431 case 20:
8432 switch (sel) {
8433 case 0:
d75c135e 8434 check_insn(ctx, ISA_MIPS3);
7db13fae 8435 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
2423f660
TS
8436 rn = "XContext";
8437 break;
9c2149c8 8438 default:
f31b035a 8439 goto cp0_unimplemented;
9c2149c8
TS
8440 }
8441 break;
8442 case 21:
8443 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 8444 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
8445 switch (sel) {
8446 case 0:
7db13fae 8447 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
8448 rn = "Framemask";
8449 break;
9c2149c8 8450 default:
f31b035a 8451 goto cp0_unimplemented;
9c2149c8
TS
8452 }
8453 break;
8454 case 22:
d9bea114 8455 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
8456 rn = "'Diagnostic"; /* implementation dependent */
8457 break;
9c2149c8
TS
8458 case 23:
8459 switch (sel) {
8460 case 0:
895c2d04 8461 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
2423f660
TS
8462 rn = "Debug";
8463 break;
9c2149c8 8464 case 1:
895c2d04 8465// gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
2423f660 8466 rn = "TraceControl";
3570d7f6 8467 goto cp0_unimplemented;
9c2149c8 8468 case 2:
895c2d04 8469// gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
2423f660 8470 rn = "TraceControl2";
3570d7f6 8471 goto cp0_unimplemented;
9c2149c8 8472 case 3:
895c2d04 8473// gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
2423f660 8474 rn = "UserTraceData";
3570d7f6 8475 goto cp0_unimplemented;
9c2149c8 8476 case 4:
895c2d04 8477// gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
2423f660 8478 rn = "TraceBPC";
3570d7f6 8479 goto cp0_unimplemented;
9c2149c8 8480 default:
f31b035a 8481 goto cp0_unimplemented;
9c2149c8
TS
8482 }
8483 break;
8484 case 24:
8485 switch (sel) {
8486 case 0:
f0b3f3ae 8487 /* EJTAG support */
7db13fae 8488 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
8489 rn = "DEPC";
8490 break;
9c2149c8 8491 default:
f31b035a 8492 goto cp0_unimplemented;
9c2149c8
TS
8493 }
8494 break;
8495 case 25:
8496 switch (sel) {
8497 case 0:
7db13fae 8498 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 8499 rn = "Performance0";
9c2149c8
TS
8500 break;
8501 case 1:
d9bea114 8502// gen_helper_dmfc0_performance1(arg);
2423f660 8503 rn = "Performance1";
3570d7f6 8504 goto cp0_unimplemented;
9c2149c8 8505 case 2:
d9bea114 8506// gen_helper_dmfc0_performance2(arg);
2423f660 8507 rn = "Performance2";
3570d7f6 8508 goto cp0_unimplemented;
9c2149c8 8509 case 3:
d9bea114 8510// gen_helper_dmfc0_performance3(arg);
2423f660 8511 rn = "Performance3";
3570d7f6 8512 goto cp0_unimplemented;
9c2149c8 8513 case 4:
d9bea114 8514// gen_helper_dmfc0_performance4(arg);
2423f660 8515 rn = "Performance4";
3570d7f6 8516 goto cp0_unimplemented;
9c2149c8 8517 case 5:
d9bea114 8518// gen_helper_dmfc0_performance5(arg);
2423f660 8519 rn = "Performance5";
3570d7f6 8520 goto cp0_unimplemented;
9c2149c8 8521 case 6:
d9bea114 8522// gen_helper_dmfc0_performance6(arg);
2423f660 8523 rn = "Performance6";
3570d7f6 8524 goto cp0_unimplemented;
9c2149c8 8525 case 7:
d9bea114 8526// gen_helper_dmfc0_performance7(arg);
2423f660 8527 rn = "Performance7";
3570d7f6 8528 goto cp0_unimplemented;
9c2149c8 8529 default:
f31b035a 8530 goto cp0_unimplemented;
9c2149c8
TS
8531 }
8532 break;
8533 case 26:
0d74a222
LA
8534 switch (sel) {
8535 case 0:
8536 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8537 rn = "ErrCtl";
8538 break;
8539 default:
8540 goto cp0_unimplemented;
8541 }
da80682b 8542 break;
9c2149c8
TS
8543 case 27:
8544 switch (sel) {
8545 /* ignored */
c2e19f3c
AM
8546 case 0:
8547 case 1:
8548 case 2:
8549 case 3:
d9bea114 8550 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
8551 rn = "CacheErr";
8552 break;
9c2149c8 8553 default:
f31b035a 8554 goto cp0_unimplemented;
9c2149c8
TS
8555 }
8556 break;
8557 case 28:
8558 switch (sel) {
8559 case 0:
8560 case 2:
8561 case 4:
8562 case 6:
7db13fae 8563 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9c2149c8
TS
8564 rn = "TagLo";
8565 break;
8566 case 1:
8567 case 3:
8568 case 5:
8569 case 7:
7db13fae 8570 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9c2149c8
TS
8571 rn = "DataLo";
8572 break;
8573 default:
f31b035a 8574 goto cp0_unimplemented;
9c2149c8
TS
8575 }
8576 break;
8577 case 29:
8578 switch (sel) {
8579 case 0:
8580 case 2:
8581 case 4:
8582 case 6:
7db13fae 8583 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9c2149c8
TS
8584 rn = "TagHi";
8585 break;
8586 case 1:
8587 case 3:
8588 case 5:
8589 case 7:
7db13fae 8590 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9c2149c8
TS
8591 rn = "DataHi";
8592 break;
8593 default:
f31b035a 8594 goto cp0_unimplemented;
9c2149c8
TS
8595 }
8596 break;
8597 case 30:
8598 switch (sel) {
8599 case 0:
7db13fae 8600 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
8601 rn = "ErrorEPC";
8602 break;
9c2149c8 8603 default:
f31b035a 8604 goto cp0_unimplemented;
9c2149c8
TS
8605 }
8606 break;
8607 case 31:
8608 switch (sel) {
8609 case 0:
f0b3f3ae 8610 /* EJTAG support */
7db13fae 8611 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
8612 rn = "DESAVE";
8613 break;
c2e19f3c
AM
8614 case 2:
8615 case 3:
8616 case 4:
8617 case 5:
8618 case 6:
8619 case 7:
f31b035a
LA
8620 CP0_CHECK(ctx->kscrexist & (1 << sel));
8621 tcg_gen_ld_tl(arg, cpu_env,
8622 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8623 rn = "KScratch";
e98c0d17 8624 break;
9c2149c8 8625 default:
f31b035a 8626 goto cp0_unimplemented;
9c2149c8
TS
8627 }
8628 break;
8629 default:
f31b035a 8630 goto cp0_unimplemented;
9c2149c8 8631 }
b44a7fb1 8632 trace_mips_translate_c0("dmfc0", rn, reg, sel);
9c2149c8
TS
8633 return;
8634
f31b035a 8635cp0_unimplemented:
965447ee 8636 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
f31b035a 8637 gen_mfc0_unimplemented(ctx, arg);
9c2149c8
TS
8638}
8639
d75c135e 8640static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
8641{
8642 const char *rn = "invalid";
8643
e189e748 8644 if (sel != 0)
d75c135e 8645 check_insn(ctx, ISA_MIPS64);
e189e748 8646
eeb3bba8 8647 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8648 gen_io_start();
bd79255d 8649 }
2e70f6ef 8650
9c2149c8
TS
8651 switch (reg) {
8652 case 0:
8653 switch (sel) {
8654 case 0:
895c2d04 8655 gen_helper_mtc0_index(cpu_env, arg);
9c2149c8
TS
8656 rn = "Index";
8657 break;
8658 case 1:
f31b035a 8659 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8660 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9c2149c8 8661 rn = "MVPControl";
ead9360e 8662 break;
9c2149c8 8663 case 2:
f31b035a 8664 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 8665 /* ignored */
9c2149c8 8666 rn = "MVPConf0";
ead9360e 8667 break;
9c2149c8 8668 case 3:
f31b035a 8669 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 8670 /* ignored */
9c2149c8 8671 rn = "MVPConf1";
ead9360e 8672 break;
01bc435b
YK
8673 case 4:
8674 CP0_CHECK(ctx->vp);
8675 /* ignored */
8676 rn = "VPControl";
8677 break;
9c2149c8 8678 default:
f31b035a 8679 goto cp0_unimplemented;
9c2149c8
TS
8680 }
8681 break;
8682 case 1:
8683 switch (sel) {
8684 case 0:
2423f660 8685 /* ignored */
9c2149c8 8686 rn = "Random";
2423f660 8687 break;
9c2149c8 8688 case 1:
f31b035a 8689 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8690 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9c2149c8 8691 rn = "VPEControl";
ead9360e 8692 break;
9c2149c8 8693 case 2:
f31b035a 8694 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8695 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9c2149c8 8696 rn = "VPEConf0";
ead9360e 8697 break;
9c2149c8 8698 case 3:
f31b035a 8699 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8700 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9c2149c8 8701 rn = "VPEConf1";
ead9360e 8702 break;
9c2149c8 8703 case 4:
f31b035a 8704 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8705 gen_helper_mtc0_yqmask(cpu_env, arg);
9c2149c8 8706 rn = "YQMask";
ead9360e 8707 break;
9c2149c8 8708 case 5:
f31b035a 8709 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8710 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 8711 rn = "VPESchedule";
ead9360e 8712 break;
9c2149c8 8713 case 6:
f31b035a 8714 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 8715 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 8716 rn = "VPEScheFBack";
ead9360e 8717 break;
9c2149c8 8718 case 7:
f31b035a 8719 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8720 gen_helper_mtc0_vpeopt(cpu_env, arg);
9c2149c8 8721 rn = "VPEOpt";
ead9360e 8722 break;
9c2149c8 8723 default:
f31b035a 8724 goto cp0_unimplemented;
9c2149c8
TS
8725 }
8726 break;
8727 case 2:
8728 switch (sel) {
8729 case 0:
7207c7f9 8730 gen_helper_dmtc0_entrylo0(cpu_env, arg);
2423f660
TS
8731 rn = "EntryLo0";
8732 break;
9c2149c8 8733 case 1:
f31b035a 8734 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8735 gen_helper_mtc0_tcstatus(cpu_env, arg);
2423f660 8736 rn = "TCStatus";
ead9360e 8737 break;
9c2149c8 8738 case 2:
f31b035a 8739 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8740 gen_helper_mtc0_tcbind(cpu_env, arg);
2423f660 8741 rn = "TCBind";
ead9360e 8742 break;
9c2149c8 8743 case 3:
f31b035a 8744 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8745 gen_helper_mtc0_tcrestart(cpu_env, arg);
2423f660 8746 rn = "TCRestart";
ead9360e 8747 break;
9c2149c8 8748 case 4:
f31b035a 8749 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8750 gen_helper_mtc0_tchalt(cpu_env, arg);
2423f660 8751 rn = "TCHalt";
ead9360e 8752 break;
9c2149c8 8753 case 5:
f31b035a 8754 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8755 gen_helper_mtc0_tccontext(cpu_env, arg);
2423f660 8756 rn = "TCContext";
ead9360e 8757 break;
9c2149c8 8758 case 6:
f31b035a 8759 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8760 gen_helper_mtc0_tcschedule(cpu_env, arg);
2423f660 8761 rn = "TCSchedule";
ead9360e 8762 break;
9c2149c8 8763 case 7:
f31b035a 8764 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 8765 gen_helper_mtc0_tcschefback(cpu_env, arg);
2423f660 8766 rn = "TCScheFBack";
ead9360e 8767 break;
9c2149c8 8768 default:
f31b035a 8769 goto cp0_unimplemented;
9c2149c8
TS
8770 }
8771 break;
8772 case 3:
8773 switch (sel) {
8774 case 0:
7207c7f9 8775 gen_helper_dmtc0_entrylo1(cpu_env, arg);
2423f660
TS
8776 rn = "EntryLo1";
8777 break;
01bc435b
YK
8778 case 1:
8779 CP0_CHECK(ctx->vp);
8780 /* ignored */
8781 rn = "GlobalNumber";
8782 break;
9c2149c8 8783 default:
f31b035a 8784 goto cp0_unimplemented;
876d4b07 8785 }
9c2149c8
TS
8786 break;
8787 case 4:
8788 switch (sel) {
8789 case 0:
895c2d04 8790 gen_helper_mtc0_context(cpu_env, arg);
2423f660
TS
8791 rn = "Context";
8792 break;
9c2149c8 8793 case 1:
895c2d04 8794// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
2423f660 8795 rn = "ContextConfig";
f31b035a 8796 goto cp0_unimplemented;
d279279e 8797 case 2:
f31b035a
LA
8798 CP0_CHECK(ctx->ulri);
8799 tcg_gen_st_tl(arg, cpu_env,
8800 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8801 rn = "UserLocal";
d279279e 8802 break;
9c2149c8 8803 default:
f31b035a 8804 goto cp0_unimplemented;
876d4b07 8805 }
9c2149c8
TS
8806 break;
8807 case 5:
8808 switch (sel) {
8809 case 0:
895c2d04 8810 gen_helper_mtc0_pagemask(cpu_env, arg);
2423f660
TS
8811 rn = "PageMask";
8812 break;
9c2149c8 8813 case 1:
d75c135e 8814 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8815 gen_helper_mtc0_pagegrain(cpu_env, arg);
2423f660
TS
8816 rn = "PageGrain";
8817 break;
cec56a73
JH
8818 case 2:
8819 CP0_CHECK(ctx->sc);
8820 gen_helper_mtc0_segctl0(cpu_env, arg);
8821 rn = "SegCtl0";
8822 break;
8823 case 3:
8824 CP0_CHECK(ctx->sc);
8825 gen_helper_mtc0_segctl1(cpu_env, arg);
8826 rn = "SegCtl1";
8827 break;
8828 case 4:
8829 CP0_CHECK(ctx->sc);
8830 gen_helper_mtc0_segctl2(cpu_env, arg);
8831 rn = "SegCtl2";
8832 break;
5e31fdd5
YK
8833 case 5:
8834 check_pw(ctx);
8835 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8836 rn = "PWBase";
8837 break;
fa75ad14
YK
8838 case 6:
8839 check_pw(ctx);
8840 gen_helper_mtc0_pwfield(cpu_env, arg);
8841 rn = "PWField";
8842 break;
20b28ebc
YK
8843 case 7:
8844 check_pw(ctx);
8845 gen_helper_mtc0_pwsize(cpu_env, arg);
8846 rn = "PWSize";
8847 break;
9c2149c8 8848 default:
f31b035a 8849 goto cp0_unimplemented;
876d4b07 8850 }
9c2149c8
TS
8851 break;
8852 case 6:
8853 switch (sel) {
8854 case 0:
895c2d04 8855 gen_helper_mtc0_wired(cpu_env, arg);
2423f660
TS
8856 rn = "Wired";
8857 break;
9c2149c8 8858 case 1:
d75c135e 8859 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8860 gen_helper_mtc0_srsconf0(cpu_env, arg);
2423f660 8861 rn = "SRSConf0";
ead9360e 8862 break;
9c2149c8 8863 case 2:
d75c135e 8864 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8865 gen_helper_mtc0_srsconf1(cpu_env, arg);
2423f660 8866 rn = "SRSConf1";
ead9360e 8867 break;
9c2149c8 8868 case 3:
d75c135e 8869 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8870 gen_helper_mtc0_srsconf2(cpu_env, arg);
2423f660 8871 rn = "SRSConf2";
ead9360e 8872 break;
9c2149c8 8873 case 4:
d75c135e 8874 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8875 gen_helper_mtc0_srsconf3(cpu_env, arg);
2423f660 8876 rn = "SRSConf3";
ead9360e 8877 break;
9c2149c8 8878 case 5:
d75c135e 8879 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8880 gen_helper_mtc0_srsconf4(cpu_env, arg);
2423f660 8881 rn = "SRSConf4";
ead9360e 8882 break;
103be64c
YK
8883 case 6:
8884 check_pw(ctx);
8885 gen_helper_mtc0_pwctl(cpu_env, arg);
8886 rn = "PWCtl";
8887 break;
9c2149c8 8888 default:
f31b035a 8889 goto cp0_unimplemented;
876d4b07 8890 }
9c2149c8
TS
8891 break;
8892 case 7:
8893 switch (sel) {
8894 case 0:
d75c135e 8895 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8896 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 8897 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
8898 rn = "HWREna";
8899 break;
9c2149c8 8900 default:
f31b035a 8901 goto cp0_unimplemented;
876d4b07 8902 }
9c2149c8
TS
8903 break;
8904 case 8:
aea14095
LA
8905 switch (sel) {
8906 case 0:
8907 /* ignored */
8908 rn = "BadVAddr";
8909 break;
8910 case 1:
8911 /* ignored */
8912 rn = "BadInstr";
8913 break;
8914 case 2:
8915 /* ignored */
8916 rn = "BadInstrP";
8917 break;
25beba9b
SM
8918 case 3:
8919 /* ignored */
8920 rn = "BadInstrX";
8921 break;
aea14095 8922 default:
f31b035a 8923 goto cp0_unimplemented;
aea14095 8924 }
9c2149c8
TS
8925 break;
8926 case 9:
8927 switch (sel) {
8928 case 0:
895c2d04 8929 gen_helper_mtc0_count(cpu_env, arg);
2423f660
TS
8930 rn = "Count";
8931 break;
876d4b07 8932 /* 6,7 are implementation dependent */
9c2149c8 8933 default:
f31b035a 8934 goto cp0_unimplemented;
876d4b07
TS
8935 }
8936 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8937 ctx->base.is_jmp = DISAS_STOP;
9c2149c8
TS
8938 break;
8939 case 10:
8940 switch (sel) {
8941 case 0:
895c2d04 8942 gen_helper_mtc0_entryhi(cpu_env, arg);
2423f660
TS
8943 rn = "EntryHi";
8944 break;
9c2149c8 8945 default:
f31b035a 8946 goto cp0_unimplemented;
876d4b07 8947 }
9c2149c8
TS
8948 break;
8949 case 11:
8950 switch (sel) {
8951 case 0:
895c2d04 8952 gen_helper_mtc0_compare(cpu_env, arg);
2423f660
TS
8953 rn = "Compare";
8954 break;
876d4b07 8955 /* 6,7 are implementation dependent */
9c2149c8 8956 default:
f31b035a 8957 goto cp0_unimplemented;
876d4b07 8958 }
de9a95f0 8959 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8960 ctx->base.is_jmp = DISAS_STOP;
9c2149c8
TS
8961 break;
8962 case 12:
8963 switch (sel) {
8964 case 0:
867abc7e 8965 save_cpu_state(ctx, 1);
895c2d04 8966 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 8967 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8968 gen_save_pc(ctx->base.pc_next + 4);
8969 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
8970 rn = "Status";
8971 break;
9c2149c8 8972 case 1:
d75c135e 8973 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8974 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 8975 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8976 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
8977 rn = "IntCtl";
8978 break;
9c2149c8 8979 case 2:
d75c135e 8980 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8981 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 8982 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8983 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
8984 rn = "SRSCtl";
8985 break;
9c2149c8 8986 case 3:
d75c135e 8987 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8988 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 8989 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8990 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
8991 rn = "SRSMap";
8992 break;
8993 default:
f31b035a 8994 goto cp0_unimplemented;
876d4b07 8995 }
9c2149c8
TS
8996 break;
8997 case 13:
8998 switch (sel) {
8999 case 0:
867abc7e 9000 save_cpu_state(ctx, 1);
895c2d04 9001 gen_helper_mtc0_cause(cpu_env, arg);
b28425ba
EC
9002 /* Stop translation as we may have triggered an interrupt.
9003 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9004 * translated code to check for pending interrupts. */
eeb3bba8
EC
9005 gen_save_pc(ctx->base.pc_next + 4);
9006 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
9007 rn = "Cause";
9008 break;
9c2149c8 9009 default:
f31b035a 9010 goto cp0_unimplemented;
876d4b07 9011 }
9c2149c8
TS
9012 break;
9013 case 14:
9014 switch (sel) {
9015 case 0:
7db13fae 9016 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
9017 rn = "EPC";
9018 break;
9c2149c8 9019 default:
f31b035a 9020 goto cp0_unimplemented;
876d4b07 9021 }
9c2149c8
TS
9022 break;
9023 case 15:
9024 switch (sel) {
9025 case 0:
2423f660
TS
9026 /* ignored */
9027 rn = "PRid";
9028 break;
9c2149c8 9029 case 1:
d75c135e 9030 check_insn(ctx, ISA_MIPS32R2);
895c2d04 9031 gen_helper_mtc0_ebase(cpu_env, arg);
2423f660
TS
9032 rn = "EBase";
9033 break;
9c2149c8 9034 default:
f31b035a 9035 goto cp0_unimplemented;
876d4b07 9036 }
9c2149c8
TS
9037 break;
9038 case 16:
9039 switch (sel) {
9040 case 0:
895c2d04 9041 gen_helper_mtc0_config0(cpu_env, arg);
9c2149c8 9042 rn = "Config";
2423f660 9043 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9044 ctx->base.is_jmp = DISAS_STOP;
9c2149c8
TS
9045 break;
9046 case 1:
1fc7bf6e 9047 /* ignored, read only */
9c2149c8
TS
9048 rn = "Config1";
9049 break;
9050 case 2:
895c2d04 9051 gen_helper_mtc0_config2(cpu_env, arg);
9c2149c8 9052 rn = "Config2";
2423f660 9053 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9054 ctx->base.is_jmp = DISAS_STOP;
9c2149c8
TS
9055 break;
9056 case 3:
90f12d73 9057 gen_helper_mtc0_config3(cpu_env, arg);
9c2149c8 9058 rn = "Config3";
90f12d73 9059 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9060 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 9061 break;
faf1f68b
LA
9062 case 4:
9063 /* currently ignored */
9064 rn = "Config4";
9065 break;
9066 case 5:
9067 gen_helper_mtc0_config5(cpu_env, arg);
9068 rn = "Config5";
9069 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9070 ctx->base.is_jmp = DISAS_STOP;
faf1f68b 9071 break;
9c2149c8
TS
9072 /* 6,7 are implementation dependent */
9073 default:
9074 rn = "Invalid config selector";
f31b035a 9075 goto cp0_unimplemented;
9c2149c8 9076 }
9c2149c8
TS
9077 break;
9078 case 17:
9079 switch (sel) {
9080 case 0:
895c2d04 9081 gen_helper_mtc0_lladdr(cpu_env, arg);
2423f660
TS
9082 rn = "LLAddr";
9083 break;
f6d4dd81
YK
9084 case 1:
9085 CP0_CHECK(ctx->mrp);
9086 gen_helper_mtc0_maar(cpu_env, arg);
9087 rn = "MAAR";
9088 break;
9089 case 2:
9090 CP0_CHECK(ctx->mrp);
9091 gen_helper_mtc0_maari(cpu_env, arg);
9092 rn = "MAARI";
9093 break;
9c2149c8 9094 default:
f31b035a 9095 goto cp0_unimplemented;
9c2149c8
TS
9096 }
9097 break;
9098 case 18:
9099 switch (sel) {
c2e19f3c
AM
9100 case 0:
9101 case 1:
9102 case 2:
9103 case 3:
9104 case 4:
9105 case 5:
9106 case 6:
9107 case 7:
fa192d49 9108 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 9109 gen_helper_0e1i(mtc0_watchlo, arg, sel);
2423f660
TS
9110 rn = "WatchLo";
9111 break;
9c2149c8 9112 default:
f31b035a 9113 goto cp0_unimplemented;
9c2149c8
TS
9114 }
9115 break;
9116 case 19:
9117 switch (sel) {
c2e19f3c
AM
9118 case 0:
9119 case 1:
9120 case 2:
9121 case 3:
9122 case 4:
9123 case 5:
9124 case 6:
9125 case 7:
fa192d49 9126 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 9127 gen_helper_0e1i(mtc0_watchhi, arg, sel);
2423f660
TS
9128 rn = "WatchHi";
9129 break;
9c2149c8 9130 default:
f31b035a 9131 goto cp0_unimplemented;
9c2149c8
TS
9132 }
9133 break;
9134 case 20:
9135 switch (sel) {
9136 case 0:
d75c135e 9137 check_insn(ctx, ISA_MIPS3);
895c2d04 9138 gen_helper_mtc0_xcontext(cpu_env, arg);
2423f660
TS
9139 rn = "XContext";
9140 break;
9c2149c8 9141 default:
f31b035a 9142 goto cp0_unimplemented;
9c2149c8
TS
9143 }
9144 break;
9145 case 21:
9146 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 9147 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
9148 switch (sel) {
9149 case 0:
895c2d04 9150 gen_helper_mtc0_framemask(cpu_env, arg);
2423f660
TS
9151 rn = "Framemask";
9152 break;
9c2149c8 9153 default:
f31b035a 9154 goto cp0_unimplemented;
9c2149c8
TS
9155 }
9156 break;
9157 case 22:
9158 /* ignored */
9159 rn = "Diagnostic"; /* implementation dependent */
876d4b07 9160 break;
9c2149c8
TS
9161 case 23:
9162 switch (sel) {
9163 case 0:
895c2d04 9164 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 9165 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
9166 gen_save_pc(ctx->base.pc_next + 4);
9167 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
9168 rn = "Debug";
9169 break;
9c2149c8 9170 case 1:
895c2d04 9171// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8487327a 9172 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9173 ctx->base.is_jmp = DISAS_STOP;
2423f660 9174 rn = "TraceControl";
3570d7f6 9175 goto cp0_unimplemented;
9c2149c8 9176 case 2:
895c2d04 9177// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8487327a 9178 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9179 ctx->base.is_jmp = DISAS_STOP;
2423f660 9180 rn = "TraceControl2";
3570d7f6 9181 goto cp0_unimplemented;
9c2149c8 9182 case 3:
895c2d04 9183// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8487327a 9184 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9185 ctx->base.is_jmp = DISAS_STOP;
2423f660 9186 rn = "UserTraceData";
3570d7f6 9187 goto cp0_unimplemented;
9c2149c8 9188 case 4:
895c2d04 9189// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a 9190 /* Stop translation as we may have switched the execution mode */
eeb3bba8 9191 ctx->base.is_jmp = DISAS_STOP;
2423f660 9192 rn = "TraceBPC";
3570d7f6 9193 goto cp0_unimplemented;
9c2149c8 9194 default:
f31b035a 9195 goto cp0_unimplemented;
9c2149c8 9196 }
9c2149c8
TS
9197 break;
9198 case 24:
9199 switch (sel) {
9200 case 0:
f1aa6320 9201 /* EJTAG support */
7db13fae 9202 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
9203 rn = "DEPC";
9204 break;
9c2149c8 9205 default:
f31b035a 9206 goto cp0_unimplemented;
9c2149c8
TS
9207 }
9208 break;
9209 case 25:
9210 switch (sel) {
9211 case 0:
895c2d04 9212 gen_helper_mtc0_performance0(cpu_env, arg);
2423f660
TS
9213 rn = "Performance0";
9214 break;
9c2149c8 9215 case 1:
895c2d04 9216// gen_helper_mtc0_performance1(cpu_env, arg);
2423f660 9217 rn = "Performance1";
3570d7f6 9218 goto cp0_unimplemented;
9c2149c8 9219 case 2:
895c2d04 9220// gen_helper_mtc0_performance2(cpu_env, arg);
2423f660 9221 rn = "Performance2";
3570d7f6 9222 goto cp0_unimplemented;
9c2149c8 9223 case 3:
895c2d04 9224// gen_helper_mtc0_performance3(cpu_env, arg);
2423f660 9225 rn = "Performance3";
3570d7f6 9226 goto cp0_unimplemented;
9c2149c8 9227 case 4:
895c2d04 9228// gen_helper_mtc0_performance4(cpu_env, arg);
2423f660 9229 rn = "Performance4";
3570d7f6 9230 goto cp0_unimplemented;
9c2149c8 9231 case 5:
895c2d04 9232// gen_helper_mtc0_performance5(cpu_env, arg);
2423f660 9233 rn = "Performance5";
3570d7f6 9234 goto cp0_unimplemented;
9c2149c8 9235 case 6:
895c2d04 9236// gen_helper_mtc0_performance6(cpu_env, arg);
2423f660 9237 rn = "Performance6";
3570d7f6 9238 goto cp0_unimplemented;
9c2149c8 9239 case 7:
895c2d04 9240// gen_helper_mtc0_performance7(cpu_env, arg);
2423f660 9241 rn = "Performance7";
3570d7f6 9242 goto cp0_unimplemented;
9c2149c8 9243 default:
f31b035a 9244 goto cp0_unimplemented;
9c2149c8 9245 }
876d4b07 9246 break;
9c2149c8 9247 case 26:
0d74a222
LA
9248 switch (sel) {
9249 case 0:
9250 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 9251 ctx->base.is_jmp = DISAS_STOP;
0d74a222
LA
9252 rn = "ErrCtl";
9253 break;
9254 default:
9255 goto cp0_unimplemented;
9256 }
876d4b07 9257 break;
9c2149c8
TS
9258 case 27:
9259 switch (sel) {
c2e19f3c
AM
9260 case 0:
9261 case 1:
9262 case 2:
9263 case 3:
2423f660
TS
9264 /* ignored */
9265 rn = "CacheErr";
9266 break;
9c2149c8 9267 default:
f31b035a 9268 goto cp0_unimplemented;
9c2149c8 9269 }
876d4b07 9270 break;
9c2149c8
TS
9271 case 28:
9272 switch (sel) {
9273 case 0:
9274 case 2:
9275 case 4:
9276 case 6:
895c2d04 9277 gen_helper_mtc0_taglo(cpu_env, arg);
9c2149c8
TS
9278 rn = "TagLo";
9279 break;
9280 case 1:
9281 case 3:
9282 case 5:
9283 case 7:
895c2d04 9284 gen_helper_mtc0_datalo(cpu_env, arg);
9c2149c8
TS
9285 rn = "DataLo";
9286 break;
9287 default:
f31b035a 9288 goto cp0_unimplemented;
9c2149c8
TS
9289 }
9290 break;
9291 case 29:
9292 switch (sel) {
9293 case 0:
9294 case 2:
9295 case 4:
9296 case 6:
895c2d04 9297 gen_helper_mtc0_taghi(cpu_env, arg);
9c2149c8
TS
9298 rn = "TagHi";
9299 break;
9300 case 1:
9301 case 3:
9302 case 5:
9303 case 7:
895c2d04 9304 gen_helper_mtc0_datahi(cpu_env, arg);
9c2149c8
TS
9305 rn = "DataHi";
9306 break;
9307 default:
9308 rn = "invalid sel";
f31b035a 9309 goto cp0_unimplemented;
9c2149c8 9310 }
876d4b07 9311 break;
9c2149c8
TS
9312 case 30:
9313 switch (sel) {
9314 case 0:
7db13fae 9315 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
9316 rn = "ErrorEPC";
9317 break;
9c2149c8 9318 default:
f31b035a 9319 goto cp0_unimplemented;
9c2149c8
TS
9320 }
9321 break;
9322 case 31:
9323 switch (sel) {
9324 case 0:
f1aa6320 9325 /* EJTAG support */
7db13fae 9326 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
9327 rn = "DESAVE";
9328 break;
c2e19f3c
AM
9329 case 2:
9330 case 3:
9331 case 4:
9332 case 5:
9333 case 6:
9334 case 7:
f31b035a
LA
9335 CP0_CHECK(ctx->kscrexist & (1 << sel));
9336 tcg_gen_st_tl(arg, cpu_env,
9337 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9338 rn = "KScratch";
e98c0d17 9339 break;
9c2149c8 9340 default:
f31b035a 9341 goto cp0_unimplemented;
9c2149c8 9342 }
9c2149c8
TS
9343 break;
9344 default:
f31b035a 9345 goto cp0_unimplemented;
9c2149c8 9346 }
b44a7fb1
PMD
9347 trace_mips_translate_c0("dmtc0", rn, reg, sel);
9348
bf20dc07 9349 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 9350 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 9351 gen_io_end();
b28425ba 9352 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
b74cddcb 9353 * translated code to check for pending interrupts. */
eeb3bba8
EC
9354 gen_save_pc(ctx->base.pc_next + 4);
9355 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 9356 }
9c2149c8
TS
9357 return;
9358
f31b035a 9359cp0_unimplemented:
965447ee 9360 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8 9361}
d26bc211 9362#endif /* TARGET_MIPS64 */
9c2149c8 9363
7db13fae 9364static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
9365 int u, int sel, int h)
9366{
9367 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 9368 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
9369
9370 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
9371 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9372 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 9373 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
9374 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9375 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 9376 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
9377 else if (u == 0) {
9378 switch (rt) {
5a25ce94
EI
9379 case 1:
9380 switch (sel) {
9381 case 1:
895c2d04 9382 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
9383 break;
9384 case 2:
895c2d04 9385 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
9386 break;
9387 default:
9388 goto die;
9389 break;
9390 }
9391 break;
ead9360e
TS
9392 case 2:
9393 switch (sel) {
9394 case 1:
895c2d04 9395 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
9396 break;
9397 case 2:
895c2d04 9398 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
9399 break;
9400 case 3:
895c2d04 9401 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
9402 break;
9403 case 4:
895c2d04 9404 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
9405 break;
9406 case 5:
895c2d04 9407 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
9408 break;
9409 case 6:
895c2d04 9410 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
9411 break;
9412 case 7:
895c2d04 9413 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
9414 break;
9415 default:
d75c135e 9416 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9417 break;
9418 }
9419 break;
9420 case 10:
9421 switch (sel) {
9422 case 0:
895c2d04 9423 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
9424 break;
9425 default:
d75c135e 9426 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9427 break;
9428 }
9429 case 12:
9430 switch (sel) {
9431 case 0:
895c2d04 9432 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
9433 break;
9434 default:
d75c135e 9435 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9436 break;
9437 }
5a25ce94
EI
9438 case 13:
9439 switch (sel) {
9440 case 0:
895c2d04 9441 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
9442 break;
9443 default:
9444 goto die;
9445 break;
9446 }
9447 break;
9448 case 14:
9449 switch (sel) {
9450 case 0:
895c2d04 9451 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
9452 break;
9453 default:
9454 goto die;
9455 break;
9456 }
9457 break;
9458 case 15:
9459 switch (sel) {
9460 case 1:
895c2d04 9461 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
9462 break;
9463 default:
9464 goto die;
9465 break;
9466 }
9467 break;
9468 case 16:
9469 switch (sel) {
c2e19f3c
AM
9470 case 0:
9471 case 1:
9472 case 2:
9473 case 3:
9474 case 4:
9475 case 5:
9476 case 6:
9477 case 7:
895c2d04 9478 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
9479 break;
9480 default:
9481 goto die;
9482 break;
9483 }
9484 break;
ead9360e
TS
9485 case 23:
9486 switch (sel) {
9487 case 0:
895c2d04 9488 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
9489 break;
9490 default:
d75c135e 9491 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9492 break;
9493 }
9494 break;
9495 default:
d75c135e 9496 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
9497 }
9498 } else switch (sel) {
9499 /* GPR registers. */
9500 case 0:
895c2d04 9501 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e
TS
9502 break;
9503 /* Auxiliary CPU registers */
9504 case 1:
9505 switch (rt) {
9506 case 0:
895c2d04 9507 gen_helper_1e0i(mftlo, t0, 0);
ead9360e
TS
9508 break;
9509 case 1:
895c2d04 9510 gen_helper_1e0i(mfthi, t0, 0);
ead9360e
TS
9511 break;
9512 case 2:
895c2d04 9513 gen_helper_1e0i(mftacx, t0, 0);
ead9360e
TS
9514 break;
9515 case 4:
895c2d04 9516 gen_helper_1e0i(mftlo, t0, 1);
ead9360e
TS
9517 break;
9518 case 5:
895c2d04 9519 gen_helper_1e0i(mfthi, t0, 1);
ead9360e
TS
9520 break;
9521 case 6:
895c2d04 9522 gen_helper_1e0i(mftacx, t0, 1);
ead9360e
TS
9523 break;
9524 case 8:
895c2d04 9525 gen_helper_1e0i(mftlo, t0, 2);
ead9360e
TS
9526 break;
9527 case 9:
895c2d04 9528 gen_helper_1e0i(mfthi, t0, 2);
ead9360e
TS
9529 break;
9530 case 10:
895c2d04 9531 gen_helper_1e0i(mftacx, t0, 2);
ead9360e
TS
9532 break;
9533 case 12:
895c2d04 9534 gen_helper_1e0i(mftlo, t0, 3);
ead9360e
TS
9535 break;
9536 case 13:
895c2d04 9537 gen_helper_1e0i(mfthi, t0, 3);
ead9360e
TS
9538 break;
9539 case 14:
895c2d04 9540 gen_helper_1e0i(mftacx, t0, 3);
ead9360e
TS
9541 break;
9542 case 16:
895c2d04 9543 gen_helper_mftdsp(t0, cpu_env);
ead9360e
TS
9544 break;
9545 default:
9546 goto die;
9547 }
9548 break;
9549 /* Floating point (COP1). */
9550 case 2:
9551 /* XXX: For now we support only a single FPU context. */
9552 if (h == 0) {
a7812ae4 9553 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9554
7c979afd 9555 gen_load_fpr32(ctx, fp0, rt);
b6d96bed 9556 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 9557 tcg_temp_free_i32(fp0);
ead9360e 9558 } else {
a7812ae4 9559 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9560
7f6613ce 9561 gen_load_fpr32h(ctx, fp0, rt);
b6d96bed 9562 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 9563 tcg_temp_free_i32(fp0);
ead9360e
TS
9564 }
9565 break;
9566 case 3:
9567 /* XXX: For now we support only a single FPU context. */
895c2d04 9568 gen_helper_1e0i(cfc1, t0, rt);
ead9360e
TS
9569 break;
9570 /* COP2: Not implemented. */
9571 case 4:
9572 case 5:
9573 /* fall through */
9574 default:
9575 goto die;
9576 }
b44a7fb1 9577 trace_mips_translate_tr("mftr", rt, u, sel, h);
1a3fd9c3
TS
9578 gen_store_gpr(t0, rd);
9579 tcg_temp_free(t0);
ead9360e
TS
9580 return;
9581
9582die:
1a3fd9c3 9583 tcg_temp_free(t0);
d12d51d5 9584 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9c708c7f 9585 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
9586}
9587
7db13fae 9588static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
9589 int u, int sel, int h)
9590{
9591 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 9592 TCGv t0 = tcg_temp_local_new();
ead9360e 9593
1a3fd9c3 9594 gen_load_gpr(t0, rt);
ead9360e 9595 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
9596 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9597 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
9598 /* NOP */ ;
9599 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9600 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9601 /* NOP */ ;
9602 else if (u == 0) {
9603 switch (rd) {
5a25ce94
EI
9604 case 1:
9605 switch (sel) {
9606 case 1:
895c2d04 9607 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
9608 break;
9609 case 2:
895c2d04 9610 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
9611 break;
9612 default:
9613 goto die;
9614 break;
9615 }
9616 break;
ead9360e
TS
9617 case 2:
9618 switch (sel) {
9619 case 1:
895c2d04 9620 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
9621 break;
9622 case 2:
895c2d04 9623 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
9624 break;
9625 case 3:
895c2d04 9626 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
9627 break;
9628 case 4:
895c2d04 9629 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
9630 break;
9631 case 5:
895c2d04 9632 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
9633 break;
9634 case 6:
895c2d04 9635 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
9636 break;
9637 case 7:
895c2d04 9638 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
9639 break;
9640 default:
d75c135e 9641 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9642 break;
9643 }
9644 break;
9645 case 10:
9646 switch (sel) {
9647 case 0:
895c2d04 9648 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
9649 break;
9650 default:
d75c135e 9651 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9652 break;
9653 }
9654 case 12:
9655 switch (sel) {
9656 case 0:
895c2d04 9657 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
9658 break;
9659 default:
d75c135e 9660 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9661 break;
9662 }
5a25ce94
EI
9663 case 13:
9664 switch (sel) {
9665 case 0:
895c2d04 9666 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
9667 break;
9668 default:
9669 goto die;
9670 break;
9671 }
9672 break;
9673 case 15:
9674 switch (sel) {
9675 case 1:
895c2d04 9676 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
9677 break;
9678 default:
9679 goto die;
9680 break;
9681 }
9682 break;
ead9360e
TS
9683 case 23:
9684 switch (sel) {
9685 case 0:
895c2d04 9686 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
9687 break;
9688 default:
d75c135e 9689 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9690 break;
9691 }
9692 break;
9693 default:
d75c135e 9694 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
9695 }
9696 } else switch (sel) {
9697 /* GPR registers. */
9698 case 0:
895c2d04 9699 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e
TS
9700 break;
9701 /* Auxiliary CPU registers */
9702 case 1:
9703 switch (rd) {
9704 case 0:
895c2d04 9705 gen_helper_0e1i(mttlo, t0, 0);
ead9360e
TS
9706 break;
9707 case 1:
895c2d04 9708 gen_helper_0e1i(mtthi, t0, 0);
ead9360e
TS
9709 break;
9710 case 2:
895c2d04 9711 gen_helper_0e1i(mttacx, t0, 0);
ead9360e
TS
9712 break;
9713 case 4:
895c2d04 9714 gen_helper_0e1i(mttlo, t0, 1);
ead9360e
TS
9715 break;
9716 case 5:
895c2d04 9717 gen_helper_0e1i(mtthi, t0, 1);
ead9360e
TS
9718 break;
9719 case 6:
895c2d04 9720 gen_helper_0e1i(mttacx, t0, 1);
ead9360e
TS
9721 break;
9722 case 8:
895c2d04 9723 gen_helper_0e1i(mttlo, t0, 2);
ead9360e
TS
9724 break;
9725 case 9:
895c2d04 9726 gen_helper_0e1i(mtthi, t0, 2);
ead9360e
TS
9727 break;
9728 case 10:
895c2d04 9729 gen_helper_0e1i(mttacx, t0, 2);
ead9360e
TS
9730 break;
9731 case 12:
895c2d04 9732 gen_helper_0e1i(mttlo, t0, 3);
ead9360e
TS
9733 break;
9734 case 13:
895c2d04 9735 gen_helper_0e1i(mtthi, t0, 3);
ead9360e
TS
9736 break;
9737 case 14:
895c2d04 9738 gen_helper_0e1i(mttacx, t0, 3);
ead9360e
TS
9739 break;
9740 case 16:
895c2d04 9741 gen_helper_mttdsp(cpu_env, t0);
ead9360e
TS
9742 break;
9743 default:
9744 goto die;
9745 }
9746 break;
9747 /* Floating point (COP1). */
9748 case 2:
9749 /* XXX: For now we support only a single FPU context. */
9750 if (h == 0) {
a7812ae4 9751 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
9752
9753 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 9754 gen_store_fpr32(ctx, fp0, rd);
a7812ae4 9755 tcg_temp_free_i32(fp0);
ead9360e 9756 } else {
a7812ae4 9757 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
9758
9759 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 9760 gen_store_fpr32h(ctx, fp0, rd);
a7812ae4 9761 tcg_temp_free_i32(fp0);
ead9360e
TS
9762 }
9763 break;
9764 case 3:
9765 /* XXX: For now we support only a single FPU context. */
736d120a
PJ
9766 {
9767 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9768
9769 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9770 tcg_temp_free_i32(fs_tmp);
9771 }
4cf8a45f 9772 /* Stop translation as we may have changed hflags */
eeb3bba8 9773 ctx->base.is_jmp = DISAS_STOP;
ead9360e
TS
9774 break;
9775 /* COP2: Not implemented. */
9776 case 4:
9777 case 5:
9778 /* fall through */
9779 default:
9780 goto die;
9781 }
b44a7fb1 9782 trace_mips_translate_tr("mttr", rd, u, sel, h);
1a3fd9c3 9783 tcg_temp_free(t0);
ead9360e
TS
9784 return;
9785
9786die:
1a3fd9c3 9787 tcg_temp_free(t0);
d12d51d5 9788 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9c708c7f 9789 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
9790}
9791
7db13fae 9792static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 9793{
287c4b84 9794 const char *opn = "ldst";
6af0bf9c 9795
2e15497c 9796 check_cp0_enabled(ctx);
6af0bf9c
FB
9797 switch (opc) {
9798 case OPC_MFC0:
9799 if (rt == 0) {
ead9360e 9800 /* Treat as NOP. */
6af0bf9c
FB
9801 return;
9802 }
d75c135e 9803 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
9804 opn = "mfc0";
9805 break;
9806 case OPC_MTC0:
1a3fd9c3 9807 {
1fc7bf6e 9808 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
9809
9810 gen_load_gpr(t0, rt);
d75c135e 9811 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
9812 tcg_temp_free(t0);
9813 }
6af0bf9c
FB
9814 opn = "mtc0";
9815 break;
d26bc211 9816#if defined(TARGET_MIPS64)
9c2149c8 9817 case OPC_DMFC0:
d75c135e 9818 check_insn(ctx, ISA_MIPS3);
9c2149c8 9819 if (rt == 0) {
ead9360e 9820 /* Treat as NOP. */
9c2149c8
TS
9821 return;
9822 }
d75c135e 9823 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
9824 opn = "dmfc0";
9825 break;
9826 case OPC_DMTC0:
d75c135e 9827 check_insn(ctx, ISA_MIPS3);
1a3fd9c3 9828 {
1fc7bf6e 9829 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
9830
9831 gen_load_gpr(t0, rt);
d75c135e 9832 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
9833 tcg_temp_free(t0);
9834 }
9c2149c8
TS
9835 opn = "dmtc0";
9836 break;
534ce69f 9837#endif
5204ea79
LA
9838 case OPC_MFHC0:
9839 check_mvh(ctx);
9840 if (rt == 0) {
9841 /* Treat as NOP. */
9842 return;
9843 }
9844 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9845 opn = "mfhc0";
9846 break;
9847 case OPC_MTHC0:
9848 check_mvh(ctx);
9849 {
9850 TCGv t0 = tcg_temp_new();
9851 gen_load_gpr(t0, rt);
9852 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9853 tcg_temp_free(t0);
9854 }
9855 opn = "mthc0";
9856 break;
ead9360e 9857 case OPC_MFTR:
9affc1c5 9858 check_cp0_enabled(ctx);
ead9360e
TS
9859 if (rd == 0) {
9860 /* Treat as NOP. */
9861 return;
9862 }
6c5c1e20 9863 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 9864 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
9865 opn = "mftr";
9866 break;
9867 case OPC_MTTR:
9affc1c5 9868 check_cp0_enabled(ctx);
6c5c1e20 9869 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
9870 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9871 opn = "mttr";
9872 break;
6af0bf9c 9873 case OPC_TLBWI:
6af0bf9c 9874 opn = "tlbwi";
c01fccd2 9875 if (!env->tlb->helper_tlbwi)
29929e34 9876 goto die;
895c2d04 9877 gen_helper_tlbwi(cpu_env);
6af0bf9c 9878 break;
9456c2fb
LA
9879 case OPC_TLBINV:
9880 opn = "tlbinv";
9881 if (ctx->ie >= 2) {
9882 if (!env->tlb->helper_tlbinv) {
9883 goto die;
9884 }
9885 gen_helper_tlbinv(cpu_env);
9886 } /* treat as nop if TLBINV not supported */
9887 break;
9888 case OPC_TLBINVF:
9889 opn = "tlbinvf";
9890 if (ctx->ie >= 2) {
9891 if (!env->tlb->helper_tlbinvf) {
9892 goto die;
9893 }
9894 gen_helper_tlbinvf(cpu_env);
9895 } /* treat as nop if TLBINV not supported */
9896 break;
6af0bf9c 9897 case OPC_TLBWR:
6af0bf9c 9898 opn = "tlbwr";
c01fccd2 9899 if (!env->tlb->helper_tlbwr)
29929e34 9900 goto die;
895c2d04 9901 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
9902 break;
9903 case OPC_TLBP:
6af0bf9c 9904 opn = "tlbp";
c01fccd2 9905 if (!env->tlb->helper_tlbp)
29929e34 9906 goto die;
895c2d04 9907 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
9908 break;
9909 case OPC_TLBR:
6af0bf9c 9910 opn = "tlbr";
c01fccd2 9911 if (!env->tlb->helper_tlbr)
29929e34 9912 goto die;
895c2d04 9913 gen_helper_tlbr(cpu_env);
6af0bf9c 9914 break;
ce9782f4 9915 case OPC_ERET: /* OPC_ERETNC */
339cd2a8
LA
9916 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9917 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8 9918 goto die;
ce9782f4
LA
9919 } else {
9920 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9921 if (ctx->opcode & (1 << bit_shift)) {
9922 /* OPC_ERETNC */
9923 opn = "eretnc";
9924 check_insn(ctx, ISA_MIPS32R5);
9925 gen_helper_eretnc(cpu_env);
9926 } else {
9927 /* OPC_ERET */
9928 opn = "eret";
9929 check_insn(ctx, ISA_MIPS2);
9930 gen_helper_eret(cpu_env);
9931 }
eeb3bba8 9932 ctx->base.is_jmp = DISAS_EXIT;
339cd2a8 9933 }
6af0bf9c
FB
9934 break;
9935 case OPC_DERET:
9936 opn = "deret";
d75c135e 9937 check_insn(ctx, ISA_MIPS32);
339cd2a8
LA
9938 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9939 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
9940 goto die;
9941 }
6af0bf9c 9942 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 9943 MIPS_INVAL(opn);
9c708c7f 9944 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 9945 } else {
895c2d04 9946 gen_helper_deret(cpu_env);
eeb3bba8 9947 ctx->base.is_jmp = DISAS_EXIT;
6af0bf9c
FB
9948 }
9949 break;
4ad40f36
FB
9950 case OPC_WAIT:
9951 opn = "wait";
d75c135e 9952 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
339cd2a8
LA
9953 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9954 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
9955 goto die;
9956 }
4ad40f36 9957 /* If we get an exception, we want to restart at next instruction */
eeb3bba8 9958 ctx->base.pc_next += 4;
4ad40f36 9959 save_cpu_state(ctx, 1);
eeb3bba8 9960 ctx->base.pc_next -= 4;
895c2d04 9961 gen_helper_wait(cpu_env);
eeb3bba8 9962 ctx->base.is_jmp = DISAS_NORETURN;
4ad40f36 9963 break;
6af0bf9c 9964 default:
29929e34 9965 die:
923617a3 9966 MIPS_INVAL(opn);
9c708c7f 9967 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
9968 return;
9969 }
2abf314d 9970 (void)opn; /* avoid a compiler warning */
6af0bf9c 9971}
f1aa6320 9972#endif /* !CONFIG_USER_ONLY */
6af0bf9c 9973
6ea83fed 9974/* CP1 Branches (before delay slot) */
d75c135e
AJ
9975static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9976 int32_t cc, int32_t offset)
6ea83fed
FB
9977{
9978 target_ulong btarget;
a7812ae4 9979 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 9980
339cd2a8 9981 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 9982 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
9983 goto out;
9984 }
9985
e189e748 9986 if (cc != 0)
d75c135e 9987 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
e189e748 9988
eeb3bba8 9989 btarget = ctx->base.pc_next + 4 + offset;
6ea83fed 9990
7a387fff
TS
9991 switch (op) {
9992 case OPC_BC1F:
d94536f4
AJ
9993 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9994 tcg_gen_not_i32(t0, t0);
9995 tcg_gen_andi_i32(t0, t0, 1);
9996 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 9997 goto not_likely;
7a387fff 9998 case OPC_BC1FL:
d94536f4
AJ
9999 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10000 tcg_gen_not_i32(t0, t0);
10001 tcg_gen_andi_i32(t0, t0, 1);
10002 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 10003 goto likely;
7a387fff 10004 case OPC_BC1T:
d94536f4
AJ
10005 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10006 tcg_gen_andi_i32(t0, t0, 1);
10007 tcg_gen_extu_i32_tl(bcond, t0);
5a5012ec 10008 goto not_likely;
7a387fff 10009 case OPC_BC1TL:
d94536f4
AJ
10010 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10011 tcg_gen_andi_i32(t0, t0, 1);
10012 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed
FB
10013 likely:
10014 ctx->hflags |= MIPS_HFLAG_BL;
10015 break;
5a5012ec 10016 case OPC_BC1FANY2:
a16336e4 10017 {
d94536f4
AJ
10018 TCGv_i32 t1 = tcg_temp_new_i32();
10019 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10020 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 10021 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 10022 tcg_temp_free_i32(t1);
d94536f4
AJ
10023 tcg_gen_andi_i32(t0, t0, 1);
10024 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10025 }
5a5012ec
TS
10026 goto not_likely;
10027 case OPC_BC1TANY2:
a16336e4 10028 {
d94536f4
AJ
10029 TCGv_i32 t1 = tcg_temp_new_i32();
10030 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10031 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10032 tcg_gen_or_i32(t0, t0, t1);
10033 tcg_temp_free_i32(t1);
10034 tcg_gen_andi_i32(t0, t0, 1);
10035 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10036 }
5a5012ec
TS
10037 goto not_likely;
10038 case OPC_BC1FANY4:
a16336e4 10039 {
d94536f4
AJ
10040 TCGv_i32 t1 = tcg_temp_new_i32();
10041 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10042 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 10043 tcg_gen_and_i32(t0, t0, t1);
d94536f4 10044 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
d7f66b52 10045 tcg_gen_and_i32(t0, t0, t1);
d94536f4 10046 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
d7f66b52 10047 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 10048 tcg_temp_free_i32(t1);
d94536f4
AJ
10049 tcg_gen_andi_i32(t0, t0, 1);
10050 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10051 }
5a5012ec
TS
10052 goto not_likely;
10053 case OPC_BC1TANY4:
a16336e4 10054 {
d94536f4
AJ
10055 TCGv_i32 t1 = tcg_temp_new_i32();
10056 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10057 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10058 tcg_gen_or_i32(t0, t0, t1);
10059 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10060 tcg_gen_or_i32(t0, t0, t1);
10061 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10062 tcg_gen_or_i32(t0, t0, t1);
10063 tcg_temp_free_i32(t1);
10064 tcg_gen_andi_i32(t0, t0, 1);
10065 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 10066 }
5a5012ec
TS
10067 not_likely:
10068 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
10069 break;
10070 default:
9d68ac14 10071 MIPS_INVAL("cp1 cond branch");
9c708c7f 10072 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 10073 goto out;
6ea83fed 10074 }
6ea83fed 10075 ctx->btarget = btarget;
b231c103 10076 ctx->hflags |= MIPS_HFLAG_BDS32;
6c5c1e20 10077 out:
a7812ae4 10078 tcg_temp_free_i32(t0);
6ea83fed
FB
10079}
10080
31837be3
YK
10081/* R6 CP1 Branches */
10082static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
65935f07
YK
10083 int32_t ft, int32_t offset,
10084 int delayslot_size)
31837be3
YK
10085{
10086 target_ulong btarget;
31837be3
YK
10087 TCGv_i64 t0 = tcg_temp_new_i64();
10088
10089 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10090#ifdef MIPS_DEBUG_DISAS
339cd2a8 10091 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 10092 "\n", ctx->base.pc_next);
31837be3 10093#endif
9c708c7f 10094 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
10095 goto out;
10096 }
10097
10098 gen_load_fpr64(ctx, t0, ft);
10099 tcg_gen_andi_i64(t0, t0, 1);
10100
eeb3bba8 10101 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
31837be3
YK
10102
10103 switch (op) {
10104 case OPC_BC1EQZ:
10105 tcg_gen_xori_i64(t0, t0, 1);
31837be3
YK
10106 ctx->hflags |= MIPS_HFLAG_BC;
10107 break;
10108 case OPC_BC1NEZ:
10109 /* t0 already set */
31837be3
YK
10110 ctx->hflags |= MIPS_HFLAG_BC;
10111 break;
10112 default:
9d68ac14 10113 MIPS_INVAL("cp1 cond branch");
9c708c7f 10114 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
10115 goto out;
10116 }
10117
10118 tcg_gen_trunc_i64_tl(bcond, t0);
10119
31837be3 10120 ctx->btarget = btarget;
65935f07
YK
10121
10122 switch (delayslot_size) {
10123 case 2:
10124 ctx->hflags |= MIPS_HFLAG_BDS16;
10125 break;
10126 case 4:
10127 ctx->hflags |= MIPS_HFLAG_BDS32;
10128 break;
10129 }
31837be3
YK
10130
10131out:
10132 tcg_temp_free_i64(t0);
10133}
10134
6af0bf9c 10135/* Coprocessor 1 (FPU) */
5a5012ec 10136
5a5012ec
TS
10137#define FOP(func, fmt) (((fmt) << 21) | (func))
10138
bf4120ad
NF
10139enum fopcode {
10140 OPC_ADD_S = FOP(0, FMT_S),
10141 OPC_SUB_S = FOP(1, FMT_S),
10142 OPC_MUL_S = FOP(2, FMT_S),
10143 OPC_DIV_S = FOP(3, FMT_S),
10144 OPC_SQRT_S = FOP(4, FMT_S),
10145 OPC_ABS_S = FOP(5, FMT_S),
10146 OPC_MOV_S = FOP(6, FMT_S),
10147 OPC_NEG_S = FOP(7, FMT_S),
10148 OPC_ROUND_L_S = FOP(8, FMT_S),
10149 OPC_TRUNC_L_S = FOP(9, FMT_S),
10150 OPC_CEIL_L_S = FOP(10, FMT_S),
10151 OPC_FLOOR_L_S = FOP(11, FMT_S),
10152 OPC_ROUND_W_S = FOP(12, FMT_S),
10153 OPC_TRUNC_W_S = FOP(13, FMT_S),
10154 OPC_CEIL_W_S = FOP(14, FMT_S),
10155 OPC_FLOOR_W_S = FOP(15, FMT_S),
e7f16abb 10156 OPC_SEL_S = FOP(16, FMT_S),
bf4120ad
NF
10157 OPC_MOVCF_S = FOP(17, FMT_S),
10158 OPC_MOVZ_S = FOP(18, FMT_S),
10159 OPC_MOVN_S = FOP(19, FMT_S),
e7f16abb 10160 OPC_SELEQZ_S = FOP(20, FMT_S),
bf4120ad
NF
10161 OPC_RECIP_S = FOP(21, FMT_S),
10162 OPC_RSQRT_S = FOP(22, FMT_S),
e7f16abb
LA
10163 OPC_SELNEZ_S = FOP(23, FMT_S),
10164 OPC_MADDF_S = FOP(24, FMT_S),
10165 OPC_MSUBF_S = FOP(25, FMT_S),
10166 OPC_RINT_S = FOP(26, FMT_S),
10167 OPC_CLASS_S = FOP(27, FMT_S),
10168 OPC_MIN_S = FOP(28, FMT_S),
bf4120ad 10169 OPC_RECIP2_S = FOP(28, FMT_S),
e7f16abb 10170 OPC_MINA_S = FOP(29, FMT_S),
bf4120ad 10171 OPC_RECIP1_S = FOP(29, FMT_S),
e7f16abb 10172 OPC_MAX_S = FOP(30, FMT_S),
bf4120ad 10173 OPC_RSQRT1_S = FOP(30, FMT_S),
e7f16abb 10174 OPC_MAXA_S = FOP(31, FMT_S),
bf4120ad
NF
10175 OPC_RSQRT2_S = FOP(31, FMT_S),
10176 OPC_CVT_D_S = FOP(33, FMT_S),
10177 OPC_CVT_W_S = FOP(36, FMT_S),
10178 OPC_CVT_L_S = FOP(37, FMT_S),
10179 OPC_CVT_PS_S = FOP(38, FMT_S),
10180 OPC_CMP_F_S = FOP (48, FMT_S),
10181 OPC_CMP_UN_S = FOP (49, FMT_S),
10182 OPC_CMP_EQ_S = FOP (50, FMT_S),
10183 OPC_CMP_UEQ_S = FOP (51, FMT_S),
10184 OPC_CMP_OLT_S = FOP (52, FMT_S),
10185 OPC_CMP_ULT_S = FOP (53, FMT_S),
10186 OPC_CMP_OLE_S = FOP (54, FMT_S),
10187 OPC_CMP_ULE_S = FOP (55, FMT_S),
10188 OPC_CMP_SF_S = FOP (56, FMT_S),
10189 OPC_CMP_NGLE_S = FOP (57, FMT_S),
10190 OPC_CMP_SEQ_S = FOP (58, FMT_S),
10191 OPC_CMP_NGL_S = FOP (59, FMT_S),
10192 OPC_CMP_LT_S = FOP (60, FMT_S),
10193 OPC_CMP_NGE_S = FOP (61, FMT_S),
10194 OPC_CMP_LE_S = FOP (62, FMT_S),
10195 OPC_CMP_NGT_S = FOP (63, FMT_S),
10196
10197 OPC_ADD_D = FOP(0, FMT_D),
10198 OPC_SUB_D = FOP(1, FMT_D),
10199 OPC_MUL_D = FOP(2, FMT_D),
10200 OPC_DIV_D = FOP(3, FMT_D),
10201 OPC_SQRT_D = FOP(4, FMT_D),
10202 OPC_ABS_D = FOP(5, FMT_D),
10203 OPC_MOV_D = FOP(6, FMT_D),
10204 OPC_NEG_D = FOP(7, FMT_D),
10205 OPC_ROUND_L_D = FOP(8, FMT_D),
10206 OPC_TRUNC_L_D = FOP(9, FMT_D),
10207 OPC_CEIL_L_D = FOP(10, FMT_D),
10208 OPC_FLOOR_L_D = FOP(11, FMT_D),
10209 OPC_ROUND_W_D = FOP(12, FMT_D),
10210 OPC_TRUNC_W_D = FOP(13, FMT_D),
10211 OPC_CEIL_W_D = FOP(14, FMT_D),
10212 OPC_FLOOR_W_D = FOP(15, FMT_D),
e7f16abb 10213 OPC_SEL_D = FOP(16, FMT_D),
bf4120ad
NF
10214 OPC_MOVCF_D = FOP(17, FMT_D),
10215 OPC_MOVZ_D = FOP(18, FMT_D),
10216 OPC_MOVN_D = FOP(19, FMT_D),
e7f16abb 10217 OPC_SELEQZ_D = FOP(20, FMT_D),
bf4120ad
NF
10218 OPC_RECIP_D = FOP(21, FMT_D),
10219 OPC_RSQRT_D = FOP(22, FMT_D),
e7f16abb
LA
10220 OPC_SELNEZ_D = FOP(23, FMT_D),
10221 OPC_MADDF_D = FOP(24, FMT_D),
10222 OPC_MSUBF_D = FOP(25, FMT_D),
10223 OPC_RINT_D = FOP(26, FMT_D),
10224 OPC_CLASS_D = FOP(27, FMT_D),
10225 OPC_MIN_D = FOP(28, FMT_D),
bf4120ad 10226 OPC_RECIP2_D = FOP(28, FMT_D),
e7f16abb 10227 OPC_MINA_D = FOP(29, FMT_D),
bf4120ad 10228 OPC_RECIP1_D = FOP(29, FMT_D),
e7f16abb 10229 OPC_MAX_D = FOP(30, FMT_D),
bf4120ad 10230 OPC_RSQRT1_D = FOP(30, FMT_D),
e7f16abb 10231 OPC_MAXA_D = FOP(31, FMT_D),
bf4120ad
NF
10232 OPC_RSQRT2_D = FOP(31, FMT_D),
10233 OPC_CVT_S_D = FOP(32, FMT_D),
10234 OPC_CVT_W_D = FOP(36, FMT_D),
10235 OPC_CVT_L_D = FOP(37, FMT_D),
10236 OPC_CMP_F_D = FOP (48, FMT_D),
10237 OPC_CMP_UN_D = FOP (49, FMT_D),
10238 OPC_CMP_EQ_D = FOP (50, FMT_D),
10239 OPC_CMP_UEQ_D = FOP (51, FMT_D),
10240 OPC_CMP_OLT_D = FOP (52, FMT_D),
10241 OPC_CMP_ULT_D = FOP (53, FMT_D),
10242 OPC_CMP_OLE_D = FOP (54, FMT_D),
10243 OPC_CMP_ULE_D = FOP (55, FMT_D),
10244 OPC_CMP_SF_D = FOP (56, FMT_D),
10245 OPC_CMP_NGLE_D = FOP (57, FMT_D),
10246 OPC_CMP_SEQ_D = FOP (58, FMT_D),
10247 OPC_CMP_NGL_D = FOP (59, FMT_D),
10248 OPC_CMP_LT_D = FOP (60, FMT_D),
10249 OPC_CMP_NGE_D = FOP (61, FMT_D),
10250 OPC_CMP_LE_D = FOP (62, FMT_D),
10251 OPC_CMP_NGT_D = FOP (63, FMT_D),
10252
10253 OPC_CVT_S_W = FOP(32, FMT_W),
10254 OPC_CVT_D_W = FOP(33, FMT_W),
10255 OPC_CVT_S_L = FOP(32, FMT_L),
10256 OPC_CVT_D_L = FOP(33, FMT_L),
10257 OPC_CVT_PS_PW = FOP(38, FMT_W),
10258
10259 OPC_ADD_PS = FOP(0, FMT_PS),
10260 OPC_SUB_PS = FOP(1, FMT_PS),
10261 OPC_MUL_PS = FOP(2, FMT_PS),
10262 OPC_DIV_PS = FOP(3, FMT_PS),
10263 OPC_ABS_PS = FOP(5, FMT_PS),
10264 OPC_MOV_PS = FOP(6, FMT_PS),
10265 OPC_NEG_PS = FOP(7, FMT_PS),
10266 OPC_MOVCF_PS = FOP(17, FMT_PS),
10267 OPC_MOVZ_PS = FOP(18, FMT_PS),
10268 OPC_MOVN_PS = FOP(19, FMT_PS),
10269 OPC_ADDR_PS = FOP(24, FMT_PS),
10270 OPC_MULR_PS = FOP(26, FMT_PS),
10271 OPC_RECIP2_PS = FOP(28, FMT_PS),
10272 OPC_RECIP1_PS = FOP(29, FMT_PS),
10273 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10274 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10275
10276 OPC_CVT_S_PU = FOP(32, FMT_PS),
10277 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10278 OPC_CVT_S_PL = FOP(40, FMT_PS),
10279 OPC_PLL_PS = FOP(44, FMT_PS),
10280 OPC_PLU_PS = FOP(45, FMT_PS),
10281 OPC_PUL_PS = FOP(46, FMT_PS),
10282 OPC_PUU_PS = FOP(47, FMT_PS),
10283 OPC_CMP_F_PS = FOP (48, FMT_PS),
10284 OPC_CMP_UN_PS = FOP (49, FMT_PS),
10285 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
10286 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
10287 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
10288 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
10289 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
10290 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
10291 OPC_CMP_SF_PS = FOP (56, FMT_PS),
10292 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
10293 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
10294 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
10295 OPC_CMP_LT_PS = FOP (60, FMT_PS),
10296 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
10297 OPC_CMP_LE_PS = FOP (62, FMT_PS),
10298 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
10299};
10300
3f493883
YK
10301enum r6_f_cmp_op {
10302 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10303 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10304 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10305 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10306 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10307 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10308 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10309 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10310 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10311 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10312 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10313 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10314 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10315 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10316 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10317 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10318 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10319 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10320 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10321 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10322 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10323 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10324
10325 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10326 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10327 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10328 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10329 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10330 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10331 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10332 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10333 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10334 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10335 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10336 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10337 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10338 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10339 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10340 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10341 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10342 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10343 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10344 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10345 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10346 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10347};
7a387fff 10348static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 10349{
72c3a3ee 10350 TCGv t0 = tcg_temp_new();
6ea83fed
FB
10351
10352 switch (opc) {
10353 case OPC_MFC1:
b6d96bed 10354 {
a7812ae4 10355 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10356
7c979afd 10357 gen_load_fpr32(ctx, fp0, fs);
b6d96bed 10358 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 10359 tcg_temp_free_i32(fp0);
6958549d 10360 }
6c5c1e20 10361 gen_store_gpr(t0, rt);
6ea83fed
FB
10362 break;
10363 case OPC_MTC1:
6c5c1e20 10364 gen_load_gpr(t0, rt);
b6d96bed 10365 {
a7812ae4 10366 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
10367
10368 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 10369 gen_store_fpr32(ctx, fp0, fs);
a7812ae4 10370 tcg_temp_free_i32(fp0);
6958549d 10371 }
6ea83fed
FB
10372 break;
10373 case OPC_CFC1:
895c2d04 10374 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 10375 gen_store_gpr(t0, rt);
6ea83fed
FB
10376 break;
10377 case OPC_CTC1:
6c5c1e20 10378 gen_load_gpr(t0, rt);
9c708c7f 10379 save_cpu_state(ctx, 0);
736d120a
PJ
10380 {
10381 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10382
10383 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10384 tcg_temp_free_i32(fs_tmp);
10385 }
4cf8a45f 10386 /* Stop translation as we may have changed hflags */
eeb3bba8 10387 ctx->base.is_jmp = DISAS_STOP;
6ea83fed 10388 break;
72c3a3ee 10389#if defined(TARGET_MIPS64)
9c2149c8 10390 case OPC_DMFC1:
72c3a3ee 10391 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 10392 gen_store_gpr(t0, rt);
5a5012ec 10393 break;
9c2149c8 10394 case OPC_DMTC1:
6c5c1e20 10395 gen_load_gpr(t0, rt);
72c3a3ee 10396 gen_store_fpr64(ctx, t0, fs);
5a5012ec 10397 break;
72c3a3ee 10398#endif
5a5012ec 10399 case OPC_MFHC1:
b6d96bed 10400 {
a7812ae4 10401 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10402
7f6613ce 10403 gen_load_fpr32h(ctx, fp0, fs);
b6d96bed 10404 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 10405 tcg_temp_free_i32(fp0);
6958549d 10406 }
6c5c1e20 10407 gen_store_gpr(t0, rt);
5a5012ec
TS
10408 break;
10409 case OPC_MTHC1:
6c5c1e20 10410 gen_load_gpr(t0, rt);
b6d96bed 10411 {
a7812ae4 10412 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
10413
10414 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 10415 gen_store_fpr32h(ctx, fp0, fs);
a7812ae4 10416 tcg_temp_free_i32(fp0);
6958549d 10417 }
5a5012ec 10418 break;
6ea83fed 10419 default:
9d68ac14 10420 MIPS_INVAL("cp1 move");
9c708c7f 10421 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 10422 goto out;
6ea83fed 10423 }
6c5c1e20
TS
10424
10425 out:
10426 tcg_temp_free(t0);
6ea83fed
FB
10427}
10428
5a5012ec
TS
10429static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
10430{
42a268c2 10431 TCGLabel *l1;
e214b9bb 10432 TCGCond cond;
af58f9ca
AJ
10433 TCGv_i32 t0;
10434
10435 if (rd == 0) {
10436 /* Treat as NOP. */
10437 return;
10438 }
6ea83fed 10439
e214b9bb 10440 if (tf)
e214b9bb 10441 cond = TCG_COND_EQ;
27848470
TS
10442 else
10443 cond = TCG_COND_NE;
10444
af58f9ca
AJ
10445 l1 = gen_new_label();
10446 t0 = tcg_temp_new_i32();
fa31af0e 10447 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 10448 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 10449 tcg_temp_free_i32(t0);
af58f9ca
AJ
10450 if (rs == 0) {
10451 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10452 } else {
10453 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10454 }
e214b9bb 10455 gen_set_label(l1);
5a5012ec
TS
10456}
10457
7c979afd
LA
10458static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10459 int tf)
a16336e4 10460{
a16336e4 10461 int cond;
cbc37b28 10462 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2 10463 TCGLabel *l1 = gen_new_label();
a16336e4 10464
a16336e4
TS
10465 if (tf)
10466 cond = TCG_COND_EQ;
10467 else
10468 cond = TCG_COND_NE;
10469
fa31af0e 10470 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10471 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
10472 gen_load_fpr32(ctx, t0, fs);
10473 gen_store_fpr32(ctx, t0, fd);
a16336e4 10474 gen_set_label(l1);
cbc37b28 10475 tcg_temp_free_i32(t0);
5a5012ec 10476}
a16336e4 10477
b6d96bed 10478static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4 10479{
a16336e4 10480 int cond;
cbc37b28
AJ
10481 TCGv_i32 t0 = tcg_temp_new_i32();
10482 TCGv_i64 fp0;
42a268c2 10483 TCGLabel *l1 = gen_new_label();
a16336e4 10484
a16336e4
TS
10485 if (tf)
10486 cond = TCG_COND_EQ;
10487 else
10488 cond = TCG_COND_NE;
10489
fa31af0e 10490 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10491 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 10492 tcg_temp_free_i32(t0);
11f94258 10493 fp0 = tcg_temp_new_i64();
9bf3eb2c 10494 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 10495 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10496 tcg_temp_free_i64(fp0);
cbc37b28 10497 gen_set_label(l1);
a16336e4
TS
10498}
10499
7f6613ce
PJ
10500static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10501 int cc, int tf)
a16336e4
TS
10502{
10503 int cond;
cbc37b28 10504 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2
RH
10505 TCGLabel *l1 = gen_new_label();
10506 TCGLabel *l2 = gen_new_label();
a16336e4
TS
10507
10508 if (tf)
10509 cond = TCG_COND_EQ;
10510 else
10511 cond = TCG_COND_NE;
10512
fa31af0e 10513 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 10514 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
10515 gen_load_fpr32(ctx, t0, fs);
10516 gen_store_fpr32(ctx, t0, fd);
a16336e4 10517 gen_set_label(l1);
9bf3eb2c 10518
fa31af0e 10519 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
cbc37b28 10520 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7f6613ce
PJ
10521 gen_load_fpr32h(ctx, t0, fs);
10522 gen_store_fpr32h(ctx, t0, fd);
52a0e9eb 10523 tcg_temp_free_i32(t0);
a16336e4 10524 gen_set_label(l2);
a16336e4
TS
10525}
10526
e7f16abb
LA
10527static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10528 int fs)
10529{
10530 TCGv_i32 t1 = tcg_const_i32(0);
10531 TCGv_i32 fp0 = tcg_temp_new_i32();
10532 TCGv_i32 fp1 = tcg_temp_new_i32();
10533 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10534 gen_load_fpr32(ctx, fp0, fd);
10535 gen_load_fpr32(ctx, fp1, ft);
10536 gen_load_fpr32(ctx, fp2, fs);
e7f16abb
LA
10537
10538 switch (op1) {
10539 case OPC_SEL_S:
10540 tcg_gen_andi_i32(fp0, fp0, 1);
10541 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10542 break;
10543 case OPC_SELEQZ_S:
10544 tcg_gen_andi_i32(fp1, fp1, 1);
10545 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10546 break;
10547 case OPC_SELNEZ_S:
10548 tcg_gen_andi_i32(fp1, fp1, 1);
10549 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10550 break;
10551 default:
10552 MIPS_INVAL("gen_sel_s");
9c708c7f 10553 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
10554 break;
10555 }
10556
7c979afd 10557 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10558 tcg_temp_free_i32(fp2);
10559 tcg_temp_free_i32(fp1);
10560 tcg_temp_free_i32(fp0);
10561 tcg_temp_free_i32(t1);
10562}
10563
10564static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10565 int fs)
10566{
10567 TCGv_i64 t1 = tcg_const_i64(0);
10568 TCGv_i64 fp0 = tcg_temp_new_i64();
10569 TCGv_i64 fp1 = tcg_temp_new_i64();
10570 TCGv_i64 fp2 = tcg_temp_new_i64();
10571 gen_load_fpr64(ctx, fp0, fd);
10572 gen_load_fpr64(ctx, fp1, ft);
10573 gen_load_fpr64(ctx, fp2, fs);
10574
10575 switch (op1) {
10576 case OPC_SEL_D:
10577 tcg_gen_andi_i64(fp0, fp0, 1);
10578 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10579 break;
10580 case OPC_SELEQZ_D:
10581 tcg_gen_andi_i64(fp1, fp1, 1);
10582 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10583 break;
10584 case OPC_SELNEZ_D:
10585 tcg_gen_andi_i64(fp1, fp1, 1);
10586 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10587 break;
10588 default:
10589 MIPS_INVAL("gen_sel_d");
9c708c7f 10590 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
10591 break;
10592 }
10593
10594 gen_store_fpr64(ctx, fp0, fd);
10595 tcg_temp_free_i64(fp2);
10596 tcg_temp_free_i64(fp1);
10597 tcg_temp_free_i64(fp0);
10598 tcg_temp_free_i64(t1);
10599}
6ea83fed 10600
bf4120ad 10601static void gen_farith (DisasContext *ctx, enum fopcode op1,
5e755519 10602 int ft, int fs, int fd, int cc)
6ea83fed 10603{
7a387fff 10604 uint32_t func = ctx->opcode & 0x3f;
bf4120ad
NF
10605 switch (op1) {
10606 case OPC_ADD_S:
b6d96bed 10607 {
a7812ae4
PB
10608 TCGv_i32 fp0 = tcg_temp_new_i32();
10609 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10610
7c979afd
LA
10611 gen_load_fpr32(ctx, fp0, fs);
10612 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10613 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10614 tcg_temp_free_i32(fp1);
7c979afd 10615 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10616 tcg_temp_free_i32(fp0);
b6d96bed 10617 }
5a5012ec 10618 break;
bf4120ad 10619 case OPC_SUB_S:
b6d96bed 10620 {
a7812ae4
PB
10621 TCGv_i32 fp0 = tcg_temp_new_i32();
10622 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10623
7c979afd
LA
10624 gen_load_fpr32(ctx, fp0, fs);
10625 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10626 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10627 tcg_temp_free_i32(fp1);
7c979afd 10628 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10629 tcg_temp_free_i32(fp0);
b6d96bed 10630 }
5a5012ec 10631 break;
bf4120ad 10632 case OPC_MUL_S:
b6d96bed 10633 {
a7812ae4
PB
10634 TCGv_i32 fp0 = tcg_temp_new_i32();
10635 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10636
7c979afd
LA
10637 gen_load_fpr32(ctx, fp0, fs);
10638 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10639 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10640 tcg_temp_free_i32(fp1);
7c979afd 10641 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10642 tcg_temp_free_i32(fp0);
b6d96bed 10643 }
5a5012ec 10644 break;
bf4120ad 10645 case OPC_DIV_S:
b6d96bed 10646 {
a7812ae4
PB
10647 TCGv_i32 fp0 = tcg_temp_new_i32();
10648 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10649
7c979afd
LA
10650 gen_load_fpr32(ctx, fp0, fs);
10651 gen_load_fpr32(ctx, fp1, ft);
895c2d04 10652 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 10653 tcg_temp_free_i32(fp1);
7c979afd 10654 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10655 tcg_temp_free_i32(fp0);
b6d96bed 10656 }
5a5012ec 10657 break;
bf4120ad 10658 case OPC_SQRT_S:
b6d96bed 10659 {
a7812ae4 10660 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10661
7c979afd 10662 gen_load_fpr32(ctx, fp0, fs);
895c2d04 10663 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
7c979afd 10664 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10665 tcg_temp_free_i32(fp0);
b6d96bed 10666 }
5a5012ec 10667 break;
bf4120ad 10668 case OPC_ABS_S:
b6d96bed 10669 {
a7812ae4 10670 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10671
7c979afd 10672 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
10673 if (ctx->abs2008) {
10674 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10675 } else {
10676 gen_helper_float_abs_s(fp0, fp0);
10677 }
7c979afd 10678 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10679 tcg_temp_free_i32(fp0);
b6d96bed 10680 }
5a5012ec 10681 break;
bf4120ad 10682 case OPC_MOV_S:
b6d96bed 10683 {
a7812ae4 10684 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10685
7c979afd
LA
10686 gen_load_fpr32(ctx, fp0, fs);
10687 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10688 tcg_temp_free_i32(fp0);
b6d96bed 10689 }
5a5012ec 10690 break;
bf4120ad 10691 case OPC_NEG_S:
b6d96bed 10692 {
a7812ae4 10693 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10694
7c979afd 10695 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
10696 if (ctx->abs2008) {
10697 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10698 } else {
10699 gen_helper_float_chs_s(fp0, fp0);
10700 }
7c979afd 10701 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10702 tcg_temp_free_i32(fp0);
b6d96bed 10703 }
5a5012ec 10704 break;
bf4120ad 10705 case OPC_ROUND_L_S:
5e755519 10706 check_cp1_64bitmode(ctx);
b6d96bed 10707 {
a7812ae4
PB
10708 TCGv_i32 fp32 = tcg_temp_new_i32();
10709 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10710
7c979afd 10711 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10712 if (ctx->nan2008) {
10713 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10714 } else {
10715 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10716 }
a7812ae4 10717 tcg_temp_free_i32(fp32);
b6d96bed 10718 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10719 tcg_temp_free_i64(fp64);
b6d96bed 10720 }
5a5012ec 10721 break;
bf4120ad 10722 case OPC_TRUNC_L_S:
5e755519 10723 check_cp1_64bitmode(ctx);
b6d96bed 10724 {
a7812ae4
PB
10725 TCGv_i32 fp32 = tcg_temp_new_i32();
10726 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10727
7c979afd 10728 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10729 if (ctx->nan2008) {
10730 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10731 } else {
10732 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10733 }
a7812ae4 10734 tcg_temp_free_i32(fp32);
b6d96bed 10735 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10736 tcg_temp_free_i64(fp64);
b6d96bed 10737 }
5a5012ec 10738 break;
bf4120ad 10739 case OPC_CEIL_L_S:
5e755519 10740 check_cp1_64bitmode(ctx);
b6d96bed 10741 {
a7812ae4
PB
10742 TCGv_i32 fp32 = tcg_temp_new_i32();
10743 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10744
7c979afd 10745 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10746 if (ctx->nan2008) {
10747 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10748 } else {
10749 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10750 }
a7812ae4 10751 tcg_temp_free_i32(fp32);
b6d96bed 10752 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10753 tcg_temp_free_i64(fp64);
b6d96bed 10754 }
5a5012ec 10755 break;
bf4120ad 10756 case OPC_FLOOR_L_S:
5e755519 10757 check_cp1_64bitmode(ctx);
b6d96bed 10758 {
a7812ae4
PB
10759 TCGv_i32 fp32 = tcg_temp_new_i32();
10760 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10761
7c979afd 10762 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10763 if (ctx->nan2008) {
10764 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10765 } else {
10766 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10767 }
a7812ae4 10768 tcg_temp_free_i32(fp32);
b6d96bed 10769 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10770 tcg_temp_free_i64(fp64);
b6d96bed 10771 }
5a5012ec 10772 break;
bf4120ad 10773 case OPC_ROUND_W_S:
b6d96bed 10774 {
a7812ae4 10775 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10776
7c979afd 10777 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10778 if (ctx->nan2008) {
10779 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10780 } else {
10781 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10782 }
7c979afd 10783 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10784 tcg_temp_free_i32(fp0);
b6d96bed 10785 }
5a5012ec 10786 break;
bf4120ad 10787 case OPC_TRUNC_W_S:
b6d96bed 10788 {
a7812ae4 10789 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10790
7c979afd 10791 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10792 if (ctx->nan2008) {
10793 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10794 } else {
10795 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10796 }
7c979afd 10797 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10798 tcg_temp_free_i32(fp0);
b6d96bed 10799 }
5a5012ec 10800 break;
bf4120ad 10801 case OPC_CEIL_W_S:
b6d96bed 10802 {
a7812ae4 10803 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10804
7c979afd 10805 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10806 if (ctx->nan2008) {
10807 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10808 } else {
10809 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10810 }
7c979afd 10811 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10812 tcg_temp_free_i32(fp0);
b6d96bed 10813 }
5a5012ec 10814 break;
bf4120ad 10815 case OPC_FLOOR_W_S:
b6d96bed 10816 {
a7812ae4 10817 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10818
7c979afd 10819 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10820 if (ctx->nan2008) {
10821 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10822 } else {
10823 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10824 }
7c979afd 10825 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10826 tcg_temp_free_i32(fp0);
b6d96bed 10827 }
5a5012ec 10828 break;
e7f16abb
LA
10829 case OPC_SEL_S:
10830 check_insn(ctx, ISA_MIPS32R6);
10831 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
10832 break;
10833 case OPC_SELEQZ_S:
10834 check_insn(ctx, ISA_MIPS32R6);
10835 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
10836 break;
10837 case OPC_SELNEZ_S:
10838 check_insn(ctx, ISA_MIPS32R6);
10839 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb 10840 break;
bf4120ad 10841 case OPC_MOVCF_S:
fecd2646 10842 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7c979afd 10843 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 10844 break;
bf4120ad 10845 case OPC_MOVZ_S:
fecd2646 10846 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 10847 {
42a268c2 10848 TCGLabel *l1 = gen_new_label();
c9297f4d 10849 TCGv_i32 fp0;
a16336e4 10850
c9297f4d
AJ
10851 if (ft != 0) {
10852 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10853 }
10854 fp0 = tcg_temp_new_i32();
7c979afd
LA
10855 gen_load_fpr32(ctx, fp0, fs);
10856 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10857 tcg_temp_free_i32(fp0);
a16336e4
TS
10858 gen_set_label(l1);
10859 }
5a5012ec 10860 break;
bf4120ad 10861 case OPC_MOVN_S:
fecd2646 10862 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 10863 {
42a268c2 10864 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
10865 TCGv_i32 fp0;
10866
10867 if (ft != 0) {
10868 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10869 fp0 = tcg_temp_new_i32();
7c979afd
LA
10870 gen_load_fpr32(ctx, fp0, fs);
10871 gen_store_fpr32(ctx, fp0, fd);
c9297f4d
AJ
10872 tcg_temp_free_i32(fp0);
10873 gen_set_label(l1);
10874 }
a16336e4 10875 }
5a5012ec 10876 break;
bf4120ad 10877 case OPC_RECIP_S:
b6d96bed 10878 {
a7812ae4 10879 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10880
7c979afd 10881 gen_load_fpr32(ctx, fp0, fs);
895c2d04 10882 gen_helper_float_recip_s(fp0, cpu_env, fp0);
7c979afd 10883 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10884 tcg_temp_free_i32(fp0);
b6d96bed 10885 }
57fa1fb3 10886 break;
bf4120ad 10887 case OPC_RSQRT_S:
b6d96bed 10888 {
a7812ae4 10889 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10890
7c979afd 10891 gen_load_fpr32(ctx, fp0, fs);
895c2d04 10892 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
7c979afd 10893 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10894 tcg_temp_free_i32(fp0);
b6d96bed 10895 }
57fa1fb3 10896 break;
e7f16abb
LA
10897 case OPC_MADDF_S:
10898 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 10899 {
a7812ae4
PB
10900 TCGv_i32 fp0 = tcg_temp_new_i32();
10901 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 10902 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10903 gen_load_fpr32(ctx, fp0, fs);
10904 gen_load_fpr32(ctx, fp1, ft);
10905 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 10906 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 10907 gen_store_fpr32(ctx, fp2, fd);
e7f16abb 10908 tcg_temp_free_i32(fp2);
a7812ae4 10909 tcg_temp_free_i32(fp1);
a7812ae4 10910 tcg_temp_free_i32(fp0);
b6d96bed 10911 }
57fa1fb3 10912 break;
e7f16abb
LA
10913 case OPC_MSUBF_S:
10914 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 10915 {
a7812ae4 10916 TCGv_i32 fp0 = tcg_temp_new_i32();
e7f16abb
LA
10917 TCGv_i32 fp1 = tcg_temp_new_i32();
10918 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10919 gen_load_fpr32(ctx, fp0, fs);
10920 gen_load_fpr32(ctx, fp1, ft);
10921 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 10922 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 10923 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
10924 tcg_temp_free_i32(fp2);
10925 tcg_temp_free_i32(fp1);
a7812ae4 10926 tcg_temp_free_i32(fp0);
b6d96bed 10927 }
57fa1fb3 10928 break;
e7f16abb
LA
10929 case OPC_RINT_S:
10930 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 10931 {
a7812ae4 10932 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 10933 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 10934 gen_helper_float_rint_s(fp0, cpu_env, fp0);
7c979afd 10935 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10936 tcg_temp_free_i32(fp0);
b6d96bed 10937 }
57fa1fb3 10938 break;
e7f16abb
LA
10939 case OPC_CLASS_S:
10940 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 10941 {
e7f16abb 10942 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 10943 gen_load_fpr32(ctx, fp0, fs);
af39bc8c 10944 gen_helper_float_class_s(fp0, cpu_env, fp0);
7c979afd 10945 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 10946 tcg_temp_free_i32(fp0);
e7f16abb
LA
10947 }
10948 break;
10949 case OPC_MIN_S: /* OPC_RECIP2_S */
10950 if (ctx->insn_flags & ISA_MIPS32R6) {
10951 /* OPC_MIN_S */
a7812ae4
PB
10952 TCGv_i32 fp0 = tcg_temp_new_i32();
10953 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 10954 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10955 gen_load_fpr32(ctx, fp0, fs);
10956 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 10957 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
7c979afd 10958 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
10959 tcg_temp_free_i32(fp2);
10960 tcg_temp_free_i32(fp1);
10961 tcg_temp_free_i32(fp0);
e7f16abb
LA
10962 } else {
10963 /* OPC_RECIP2_S */
10964 check_cp1_64bitmode(ctx);
10965 {
10966 TCGv_i32 fp0 = tcg_temp_new_i32();
10967 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10968
7c979afd
LA
10969 gen_load_fpr32(ctx, fp0, fs);
10970 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
10971 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10972 tcg_temp_free_i32(fp1);
7c979afd 10973 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10974 tcg_temp_free_i32(fp0);
10975 }
e7f16abb
LA
10976 }
10977 break;
10978 case OPC_MINA_S: /* OPC_RECIP1_S */
10979 if (ctx->insn_flags & ISA_MIPS32R6) {
10980 /* OPC_MINA_S */
10981 TCGv_i32 fp0 = tcg_temp_new_i32();
10982 TCGv_i32 fp1 = tcg_temp_new_i32();
10983 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10984 gen_load_fpr32(ctx, fp0, fs);
10985 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 10986 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
7c979afd 10987 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
10988 tcg_temp_free_i32(fp2);
10989 tcg_temp_free_i32(fp1);
10990 tcg_temp_free_i32(fp0);
e7f16abb
LA
10991 } else {
10992 /* OPC_RECIP1_S */
10993 check_cp1_64bitmode(ctx);
10994 {
10995 TCGv_i32 fp0 = tcg_temp_new_i32();
10996
7c979afd 10997 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 10998 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
7c979afd 10999 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11000 tcg_temp_free_i32(fp0);
11001 }
e7f16abb
LA
11002 }
11003 break;
11004 case OPC_MAX_S: /* OPC_RSQRT1_S */
11005 if (ctx->insn_flags & ISA_MIPS32R6) {
11006 /* OPC_MAX_S */
11007 TCGv_i32 fp0 = tcg_temp_new_i32();
11008 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
11009 gen_load_fpr32(ctx, fp0, fs);
11010 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11011 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
7c979afd 11012 gen_store_fpr32(ctx, fp1, fd);
e7f16abb
LA
11013 tcg_temp_free_i32(fp1);
11014 tcg_temp_free_i32(fp0);
e7f16abb
LA
11015 } else {
11016 /* OPC_RSQRT1_S */
11017 check_cp1_64bitmode(ctx);
11018 {
11019 TCGv_i32 fp0 = tcg_temp_new_i32();
11020
7c979afd 11021 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 11022 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
7c979afd 11023 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11024 tcg_temp_free_i32(fp0);
11025 }
e7f16abb
LA
11026 }
11027 break;
11028 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11029 if (ctx->insn_flags & ISA_MIPS32R6) {
11030 /* OPC_MAXA_S */
11031 TCGv_i32 fp0 = tcg_temp_new_i32();
11032 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
11033 gen_load_fpr32(ctx, fp0, fs);
11034 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 11035 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
7c979afd 11036 gen_store_fpr32(ctx, fp1, fd);
a7812ae4 11037 tcg_temp_free_i32(fp1);
a7812ae4 11038 tcg_temp_free_i32(fp0);
e7f16abb
LA
11039 } else {
11040 /* OPC_RSQRT2_S */
11041 check_cp1_64bitmode(ctx);
11042 {
11043 TCGv_i32 fp0 = tcg_temp_new_i32();
11044 TCGv_i32 fp1 = tcg_temp_new_i32();
11045
7c979afd
LA
11046 gen_load_fpr32(ctx, fp0, fs);
11047 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
11048 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11049 tcg_temp_free_i32(fp1);
7c979afd 11050 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
11051 tcg_temp_free_i32(fp0);
11052 }
b6d96bed 11053 }
57fa1fb3 11054 break;
bf4120ad 11055 case OPC_CVT_D_S:
5e755519 11056 check_cp1_registers(ctx, fd);
b6d96bed 11057 {
a7812ae4
PB
11058 TCGv_i32 fp32 = tcg_temp_new_i32();
11059 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11060
7c979afd 11061 gen_load_fpr32(ctx, fp32, fs);
895c2d04 11062 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 11063 tcg_temp_free_i32(fp32);
b6d96bed 11064 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11065 tcg_temp_free_i64(fp64);
b6d96bed 11066 }
5a5012ec 11067 break;
bf4120ad 11068 case OPC_CVT_W_S:
b6d96bed 11069 {
a7812ae4 11070 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11071
7c979afd 11072 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
11073 if (ctx->nan2008) {
11074 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11075 } else {
11076 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11077 }
7c979afd 11078 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11079 tcg_temp_free_i32(fp0);
b6d96bed 11080 }
5a5012ec 11081 break;
bf4120ad 11082 case OPC_CVT_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_cvt_2008_l_s(fp64, cpu_env, fp32);
11091 } else {
11092 gen_helper_float_cvt_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_CVT_PS_S:
e29c9628 11100 check_ps(ctx);
b6d96bed 11101 {
a7812ae4
PB
11102 TCGv_i64 fp64 = tcg_temp_new_i64();
11103 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11104 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed 11105
7c979afd
LA
11106 gen_load_fpr32(ctx, fp32_0, fs);
11107 gen_load_fpr32(ctx, fp32_1, ft);
13d24f49 11108 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
11109 tcg_temp_free_i32(fp32_1);
11110 tcg_temp_free_i32(fp32_0);
36aa55dc 11111 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11112 tcg_temp_free_i64(fp64);
b6d96bed 11113 }
5a5012ec 11114 break;
bf4120ad
NF
11115 case OPC_CMP_F_S:
11116 case OPC_CMP_UN_S:
11117 case OPC_CMP_EQ_S:
11118 case OPC_CMP_UEQ_S:
11119 case OPC_CMP_OLT_S:
11120 case OPC_CMP_ULT_S:
11121 case OPC_CMP_OLE_S:
11122 case OPC_CMP_ULE_S:
11123 case OPC_CMP_SF_S:
11124 case OPC_CMP_NGLE_S:
11125 case OPC_CMP_SEQ_S:
11126 case OPC_CMP_NGL_S:
11127 case OPC_CMP_LT_S:
11128 case OPC_CMP_NGE_S:
11129 case OPC_CMP_LE_S:
11130 case OPC_CMP_NGT_S:
fecd2646 11131 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c
NF
11132 if (ctx->opcode & (1 << 6)) {
11133 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
8153667c
NF
11134 } else {
11135 gen_cmp_s(ctx, func-48, ft, fs, cc);
5a1e8ffb 11136 }
5a5012ec 11137 break;
bf4120ad 11138 case OPC_ADD_D:
5e755519 11139 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11140 {
a7812ae4
PB
11141 TCGv_i64 fp0 = tcg_temp_new_i64();
11142 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11143
11144 gen_load_fpr64(ctx, fp0, fs);
11145 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11146 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11147 tcg_temp_free_i64(fp1);
b6d96bed 11148 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11149 tcg_temp_free_i64(fp0);
b6d96bed 11150 }
6ea83fed 11151 break;
bf4120ad 11152 case OPC_SUB_D:
5e755519 11153 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11154 {
a7812ae4
PB
11155 TCGv_i64 fp0 = tcg_temp_new_i64();
11156 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11157
11158 gen_load_fpr64(ctx, fp0, fs);
11159 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11160 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11161 tcg_temp_free_i64(fp1);
b6d96bed 11162 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11163 tcg_temp_free_i64(fp0);
b6d96bed 11164 }
6ea83fed 11165 break;
bf4120ad 11166 case OPC_MUL_D:
5e755519 11167 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11168 {
a7812ae4
PB
11169 TCGv_i64 fp0 = tcg_temp_new_i64();
11170 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11171
11172 gen_load_fpr64(ctx, fp0, fs);
11173 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11174 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11175 tcg_temp_free_i64(fp1);
b6d96bed 11176 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11177 tcg_temp_free_i64(fp0);
b6d96bed 11178 }
6ea83fed 11179 break;
bf4120ad 11180 case OPC_DIV_D:
5e755519 11181 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 11182 {
a7812ae4
PB
11183 TCGv_i64 fp0 = tcg_temp_new_i64();
11184 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11185
11186 gen_load_fpr64(ctx, fp0, fs);
11187 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11188 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 11189 tcg_temp_free_i64(fp1);
b6d96bed 11190 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11191 tcg_temp_free_i64(fp0);
b6d96bed 11192 }
6ea83fed 11193 break;
bf4120ad 11194 case OPC_SQRT_D:
5e755519 11195 check_cp1_registers(ctx, fs | fd);
b6d96bed 11196 {
a7812ae4 11197 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11198
11199 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11200 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 11201 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11202 tcg_temp_free_i64(fp0);
b6d96bed 11203 }
6ea83fed 11204 break;
bf4120ad 11205 case OPC_ABS_D:
5e755519 11206 check_cp1_registers(ctx, fs | fd);
b6d96bed 11207 {
a7812ae4 11208 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11209
11210 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
11211 if (ctx->abs2008) {
11212 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11213 } else {
11214 gen_helper_float_abs_d(fp0, fp0);
11215 }
b6d96bed 11216 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11217 tcg_temp_free_i64(fp0);
b6d96bed 11218 }
6ea83fed 11219 break;
bf4120ad 11220 case OPC_MOV_D:
5e755519 11221 check_cp1_registers(ctx, fs | fd);
b6d96bed 11222 {
a7812ae4 11223 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11224
11225 gen_load_fpr64(ctx, fp0, fs);
11226 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11227 tcg_temp_free_i64(fp0);
b6d96bed 11228 }
6ea83fed 11229 break;
bf4120ad 11230 case OPC_NEG_D:
5e755519 11231 check_cp1_registers(ctx, fs | fd);
b6d96bed 11232 {
a7812ae4 11233 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11234
11235 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
11236 if (ctx->abs2008) {
11237 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11238 } else {
11239 gen_helper_float_chs_d(fp0, fp0);
11240 }
b6d96bed 11241 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11242 tcg_temp_free_i64(fp0);
b6d96bed 11243 }
6ea83fed 11244 break;
bf4120ad 11245 case OPC_ROUND_L_D:
5e755519 11246 check_cp1_64bitmode(ctx);
b6d96bed 11247 {
a7812ae4 11248 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11249
11250 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11251 if (ctx->nan2008) {
11252 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11253 } else {
11254 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11255 }
b6d96bed 11256 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11257 tcg_temp_free_i64(fp0);
b6d96bed 11258 }
5a5012ec 11259 break;
bf4120ad 11260 case OPC_TRUNC_L_D:
5e755519 11261 check_cp1_64bitmode(ctx);
b6d96bed 11262 {
a7812ae4 11263 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11264
11265 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11266 if (ctx->nan2008) {
11267 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11268 } else {
11269 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11270 }
b6d96bed 11271 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11272 tcg_temp_free_i64(fp0);
b6d96bed 11273 }
5a5012ec 11274 break;
bf4120ad 11275 case OPC_CEIL_L_D:
5e755519 11276 check_cp1_64bitmode(ctx);
b6d96bed 11277 {
a7812ae4 11278 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11279
11280 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11281 if (ctx->nan2008) {
11282 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11283 } else {
11284 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11285 }
b6d96bed 11286 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11287 tcg_temp_free_i64(fp0);
b6d96bed 11288 }
5a5012ec 11289 break;
bf4120ad 11290 case OPC_FLOOR_L_D:
5e755519 11291 check_cp1_64bitmode(ctx);
b6d96bed 11292 {
a7812ae4 11293 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11294
11295 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11296 if (ctx->nan2008) {
11297 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11298 } else {
11299 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11300 }
b6d96bed 11301 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11302 tcg_temp_free_i64(fp0);
b6d96bed 11303 }
5a5012ec 11304 break;
bf4120ad 11305 case OPC_ROUND_W_D:
5e755519 11306 check_cp1_registers(ctx, fs);
b6d96bed 11307 {
a7812ae4
PB
11308 TCGv_i32 fp32 = tcg_temp_new_i32();
11309 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11310
11311 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11312 if (ctx->nan2008) {
11313 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11314 } else {
11315 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11316 }
a7812ae4 11317 tcg_temp_free_i64(fp64);
7c979afd 11318 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11319 tcg_temp_free_i32(fp32);
b6d96bed 11320 }
6ea83fed 11321 break;
bf4120ad 11322 case OPC_TRUNC_W_D:
5e755519 11323 check_cp1_registers(ctx, fs);
b6d96bed 11324 {
a7812ae4
PB
11325 TCGv_i32 fp32 = tcg_temp_new_i32();
11326 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11327
11328 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11329 if (ctx->nan2008) {
11330 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11331 } else {
11332 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11333 }
a7812ae4 11334 tcg_temp_free_i64(fp64);
7c979afd 11335 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11336 tcg_temp_free_i32(fp32);
b6d96bed 11337 }
6ea83fed 11338 break;
bf4120ad 11339 case OPC_CEIL_W_D:
5e755519 11340 check_cp1_registers(ctx, fs);
b6d96bed 11341 {
a7812ae4
PB
11342 TCGv_i32 fp32 = tcg_temp_new_i32();
11343 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11344
11345 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11346 if (ctx->nan2008) {
11347 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11348 } else {
11349 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11350 }
a7812ae4 11351 tcg_temp_free_i64(fp64);
7c979afd 11352 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11353 tcg_temp_free_i32(fp32);
b6d96bed 11354 }
6ea83fed 11355 break;
bf4120ad 11356 case OPC_FLOOR_W_D:
5e755519 11357 check_cp1_registers(ctx, fs);
b6d96bed 11358 {
a7812ae4
PB
11359 TCGv_i32 fp32 = tcg_temp_new_i32();
11360 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11361
11362 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11363 if (ctx->nan2008) {
11364 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11365 } else {
11366 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11367 }
a7812ae4 11368 tcg_temp_free_i64(fp64);
7c979afd 11369 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11370 tcg_temp_free_i32(fp32);
b6d96bed 11371 }
6ea83fed 11372 break;
e7f16abb
LA
11373 case OPC_SEL_D:
11374 check_insn(ctx, ISA_MIPS32R6);
11375 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
11376 break;
11377 case OPC_SELEQZ_D:
11378 check_insn(ctx, ISA_MIPS32R6);
11379 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
11380 break;
11381 case OPC_SELNEZ_D:
11382 check_insn(ctx, ISA_MIPS32R6);
11383 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb 11384 break;
bf4120ad 11385 case OPC_MOVCF_D:
fecd2646 11386 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6d96bed 11387 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
dd016883 11388 break;
bf4120ad 11389 case OPC_MOVZ_D:
fecd2646 11390 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11391 {
42a268c2 11392 TCGLabel *l1 = gen_new_label();
c9297f4d 11393 TCGv_i64 fp0;
a16336e4 11394
c9297f4d
AJ
11395 if (ft != 0) {
11396 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11397 }
11398 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11399 gen_load_fpr64(ctx, fp0, fs);
11400 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11401 tcg_temp_free_i64(fp0);
a16336e4
TS
11402 gen_set_label(l1);
11403 }
5a5012ec 11404 break;
bf4120ad 11405 case OPC_MOVN_D:
fecd2646 11406 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 11407 {
42a268c2 11408 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
11409 TCGv_i64 fp0;
11410
11411 if (ft != 0) {
11412 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11413 fp0 = tcg_temp_new_i64();
11414 gen_load_fpr64(ctx, fp0, fs);
11415 gen_store_fpr64(ctx, fp0, fd);
11416 tcg_temp_free_i64(fp0);
11417 gen_set_label(l1);
11418 }
a16336e4 11419 }
6ea83fed 11420 break;
bf4120ad 11421 case OPC_RECIP_D:
ca6c7803 11422 check_cp1_registers(ctx, fs | fd);
b6d96bed 11423 {
a7812ae4 11424 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11425
11426 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11427 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 11428 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11429 tcg_temp_free_i64(fp0);
b6d96bed 11430 }
57fa1fb3 11431 break;
bf4120ad 11432 case OPC_RSQRT_D:
ca6c7803 11433 check_cp1_registers(ctx, fs | fd);
b6d96bed 11434 {
a7812ae4 11435 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11436
11437 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11438 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 11439 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11440 tcg_temp_free_i64(fp0);
b6d96bed 11441 }
57fa1fb3 11442 break;
e7f16abb
LA
11443 case OPC_MADDF_D:
11444 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11445 {
a7812ae4
PB
11446 TCGv_i64 fp0 = tcg_temp_new_i64();
11447 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb 11448 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11449 gen_load_fpr64(ctx, fp0, fs);
11450 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
11451 gen_load_fpr64(ctx, fp2, fd);
11452 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11453 gen_store_fpr64(ctx, fp2, fd);
11454 tcg_temp_free_i64(fp2);
a7812ae4 11455 tcg_temp_free_i64(fp1);
a7812ae4 11456 tcg_temp_free_i64(fp0);
b6d96bed 11457 }
57fa1fb3 11458 break;
e7f16abb
LA
11459 case OPC_MSUBF_D:
11460 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11461 {
a7812ae4 11462 TCGv_i64 fp0 = tcg_temp_new_i64();
e7f16abb
LA
11463 TCGv_i64 fp1 = tcg_temp_new_i64();
11464 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed 11465 gen_load_fpr64(ctx, fp0, fs);
e7f16abb
LA
11466 gen_load_fpr64(ctx, fp1, ft);
11467 gen_load_fpr64(ctx, fp2, fd);
11468 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11469 gen_store_fpr64(ctx, fp2, fd);
11470 tcg_temp_free_i64(fp2);
11471 tcg_temp_free_i64(fp1);
a7812ae4 11472 tcg_temp_free_i64(fp0);
b6d96bed 11473 }
57fa1fb3 11474 break;
e7f16abb
LA
11475 case OPC_RINT_D:
11476 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11477 {
a7812ae4 11478 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11479 gen_load_fpr64(ctx, fp0, fs);
e7f16abb 11480 gen_helper_float_rint_d(fp0, cpu_env, fp0);
b6d96bed 11481 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11482 tcg_temp_free_i64(fp0);
b6d96bed 11483 }
57fa1fb3 11484 break;
e7f16abb
LA
11485 case OPC_CLASS_D:
11486 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 11487 {
e7f16abb
LA
11488 TCGv_i64 fp0 = tcg_temp_new_i64();
11489 gen_load_fpr64(ctx, fp0, fs);
af39bc8c 11490 gen_helper_float_class_d(fp0, cpu_env, fp0);
e7f16abb
LA
11491 gen_store_fpr64(ctx, fp0, fd);
11492 tcg_temp_free_i64(fp0);
e7f16abb
LA
11493 }
11494 break;
11495 case OPC_MIN_D: /* OPC_RECIP2_D */
11496 if (ctx->insn_flags & ISA_MIPS32R6) {
11497 /* OPC_MIN_D */
a7812ae4
PB
11498 TCGv_i64 fp0 = tcg_temp_new_i64();
11499 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb
LA
11500 gen_load_fpr64(ctx, fp0, fs);
11501 gen_load_fpr64(ctx, fp1, ft);
11502 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11503 gen_store_fpr64(ctx, fp1, fd);
11504 tcg_temp_free_i64(fp1);
11505 tcg_temp_free_i64(fp0);
e7f16abb
LA
11506 } else {
11507 /* OPC_RECIP2_D */
11508 check_cp1_64bitmode(ctx);
11509 {
11510 TCGv_i64 fp0 = tcg_temp_new_i64();
11511 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed 11512
e7f16abb
LA
11513 gen_load_fpr64(ctx, fp0, fs);
11514 gen_load_fpr64(ctx, fp1, ft);
11515 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11516 tcg_temp_free_i64(fp1);
11517 gen_store_fpr64(ctx, fp0, fd);
11518 tcg_temp_free_i64(fp0);
11519 }
e7f16abb
LA
11520 }
11521 break;
11522 case OPC_MINA_D: /* OPC_RECIP1_D */
11523 if (ctx->insn_flags & ISA_MIPS32R6) {
11524 /* OPC_MINA_D */
11525 TCGv_i64 fp0 = tcg_temp_new_i64();
11526 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11527 gen_load_fpr64(ctx, fp0, fs);
11528 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
11529 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11530 gen_store_fpr64(ctx, fp1, fd);
11531 tcg_temp_free_i64(fp1);
11532 tcg_temp_free_i64(fp0);
e7f16abb
LA
11533 } else {
11534 /* OPC_RECIP1_D */
11535 check_cp1_64bitmode(ctx);
11536 {
11537 TCGv_i64 fp0 = tcg_temp_new_i64();
11538
11539 gen_load_fpr64(ctx, fp0, fs);
11540 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11541 gen_store_fpr64(ctx, fp0, fd);
11542 tcg_temp_free_i64(fp0);
11543 }
e7f16abb
LA
11544 }
11545 break;
11546 case OPC_MAX_D: /* OPC_RSQRT1_D */
11547 if (ctx->insn_flags & ISA_MIPS32R6) {
11548 /* OPC_MAX_D */
11549 TCGv_i64 fp0 = tcg_temp_new_i64();
11550 TCGv_i64 fp1 = tcg_temp_new_i64();
11551 gen_load_fpr64(ctx, fp0, fs);
11552 gen_load_fpr64(ctx, fp1, ft);
11553 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11554 gen_store_fpr64(ctx, fp1, fd);
a7812ae4 11555 tcg_temp_free_i64(fp1);
a7812ae4 11556 tcg_temp_free_i64(fp0);
e7f16abb
LA
11557 } else {
11558 /* OPC_RSQRT1_D */
11559 check_cp1_64bitmode(ctx);
11560 {
11561 TCGv_i64 fp0 = tcg_temp_new_i64();
11562
11563 gen_load_fpr64(ctx, fp0, fs);
11564 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11565 gen_store_fpr64(ctx, fp0, fd);
11566 tcg_temp_free_i64(fp0);
11567 }
e7f16abb
LA
11568 }
11569 break;
11570 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11571 if (ctx->insn_flags & ISA_MIPS32R6) {
11572 /* OPC_MAXA_D */
11573 TCGv_i64 fp0 = tcg_temp_new_i64();
11574 TCGv_i64 fp1 = tcg_temp_new_i64();
11575 gen_load_fpr64(ctx, fp0, fs);
11576 gen_load_fpr64(ctx, fp1, ft);
11577 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11578 gen_store_fpr64(ctx, fp1, fd);
11579 tcg_temp_free_i64(fp1);
11580 tcg_temp_free_i64(fp0);
e7f16abb
LA
11581 } else {
11582 /* OPC_RSQRT2_D */
11583 check_cp1_64bitmode(ctx);
11584 {
11585 TCGv_i64 fp0 = tcg_temp_new_i64();
11586 TCGv_i64 fp1 = tcg_temp_new_i64();
11587
11588 gen_load_fpr64(ctx, fp0, fs);
11589 gen_load_fpr64(ctx, fp1, ft);
11590 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11591 tcg_temp_free_i64(fp1);
11592 gen_store_fpr64(ctx, fp0, fd);
11593 tcg_temp_free_i64(fp0);
11594 }
b6d96bed 11595 }
57fa1fb3 11596 break;
bf4120ad
NF
11597 case OPC_CMP_F_D:
11598 case OPC_CMP_UN_D:
11599 case OPC_CMP_EQ_D:
11600 case OPC_CMP_UEQ_D:
11601 case OPC_CMP_OLT_D:
11602 case OPC_CMP_ULT_D:
11603 case OPC_CMP_OLE_D:
11604 case OPC_CMP_ULE_D:
11605 case OPC_CMP_SF_D:
11606 case OPC_CMP_NGLE_D:
11607 case OPC_CMP_SEQ_D:
11608 case OPC_CMP_NGL_D:
11609 case OPC_CMP_LT_D:
11610 case OPC_CMP_NGE_D:
11611 case OPC_CMP_LE_D:
11612 case OPC_CMP_NGT_D:
fecd2646 11613 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c
NF
11614 if (ctx->opcode & (1 << 6)) {
11615 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
8153667c
NF
11616 } else {
11617 gen_cmp_d(ctx, func-48, ft, fs, cc);
5a1e8ffb 11618 }
6ea83fed 11619 break;
bf4120ad 11620 case OPC_CVT_S_D:
5e755519 11621 check_cp1_registers(ctx, fs);
b6d96bed 11622 {
a7812ae4
PB
11623 TCGv_i32 fp32 = tcg_temp_new_i32();
11624 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11625
11626 gen_load_fpr64(ctx, fp64, fs);
895c2d04 11627 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 11628 tcg_temp_free_i64(fp64);
7c979afd 11629 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11630 tcg_temp_free_i32(fp32);
b6d96bed 11631 }
5a5012ec 11632 break;
bf4120ad 11633 case OPC_CVT_W_D:
5e755519 11634 check_cp1_registers(ctx, fs);
b6d96bed 11635 {
a7812ae4
PB
11636 TCGv_i32 fp32 = tcg_temp_new_i32();
11637 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11638
11639 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
11640 if (ctx->nan2008) {
11641 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11642 } else {
11643 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11644 }
a7812ae4 11645 tcg_temp_free_i64(fp64);
7c979afd 11646 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11647 tcg_temp_free_i32(fp32);
b6d96bed 11648 }
5a5012ec 11649 break;
bf4120ad 11650 case OPC_CVT_L_D:
5e755519 11651 check_cp1_64bitmode(ctx);
b6d96bed 11652 {
a7812ae4 11653 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11654
11655 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
11656 if (ctx->nan2008) {
11657 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11658 } else {
11659 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11660 }
b6d96bed 11661 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11662 tcg_temp_free_i64(fp0);
b6d96bed 11663 }
5a5012ec 11664 break;
bf4120ad 11665 case OPC_CVT_S_W:
b6d96bed 11666 {
a7812ae4 11667 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11668
7c979afd 11669 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11670 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
7c979afd 11671 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11672 tcg_temp_free_i32(fp0);
b6d96bed 11673 }
6ea83fed 11674 break;
bf4120ad 11675 case OPC_CVT_D_W:
5e755519 11676 check_cp1_registers(ctx, fd);
b6d96bed 11677 {
a7812ae4
PB
11678 TCGv_i32 fp32 = tcg_temp_new_i32();
11679 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 11680
7c979afd 11681 gen_load_fpr32(ctx, fp32, fs);
895c2d04 11682 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 11683 tcg_temp_free_i32(fp32);
b6d96bed 11684 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 11685 tcg_temp_free_i64(fp64);
b6d96bed 11686 }
5a5012ec 11687 break;
bf4120ad 11688 case OPC_CVT_S_L:
5e755519 11689 check_cp1_64bitmode(ctx);
b6d96bed 11690 {
a7812ae4
PB
11691 TCGv_i32 fp32 = tcg_temp_new_i32();
11692 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
11693
11694 gen_load_fpr64(ctx, fp64, fs);
895c2d04 11695 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 11696 tcg_temp_free_i64(fp64);
7c979afd 11697 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 11698 tcg_temp_free_i32(fp32);
b6d96bed 11699 }
5a5012ec 11700 break;
bf4120ad 11701 case OPC_CVT_D_L:
5e755519 11702 check_cp1_64bitmode(ctx);
b6d96bed 11703 {
a7812ae4 11704 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11705
11706 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11707 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 11708 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11709 tcg_temp_free_i64(fp0);
b6d96bed 11710 }
5a5012ec 11711 break;
bf4120ad 11712 case OPC_CVT_PS_PW:
e29c9628 11713 check_ps(ctx);
b6d96bed 11714 {
a7812ae4 11715 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11716
11717 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11718 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 11719 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11720 tcg_temp_free_i64(fp0);
b6d96bed 11721 }
5a5012ec 11722 break;
bf4120ad 11723 case OPC_ADD_PS:
e29c9628 11724 check_ps(ctx);
b6d96bed 11725 {
a7812ae4
PB
11726 TCGv_i64 fp0 = tcg_temp_new_i64();
11727 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11728
11729 gen_load_fpr64(ctx, fp0, fs);
11730 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11731 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11732 tcg_temp_free_i64(fp1);
b6d96bed 11733 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11734 tcg_temp_free_i64(fp0);
b6d96bed 11735 }
6ea83fed 11736 break;
bf4120ad 11737 case OPC_SUB_PS:
e29c9628 11738 check_ps(ctx);
b6d96bed 11739 {
a7812ae4
PB
11740 TCGv_i64 fp0 = tcg_temp_new_i64();
11741 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11742
11743 gen_load_fpr64(ctx, fp0, fs);
11744 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11745 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11746 tcg_temp_free_i64(fp1);
b6d96bed 11747 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11748 tcg_temp_free_i64(fp0);
b6d96bed 11749 }
6ea83fed 11750 break;
bf4120ad 11751 case OPC_MUL_PS:
e29c9628 11752 check_ps(ctx);
b6d96bed 11753 {
a7812ae4
PB
11754 TCGv_i64 fp0 = tcg_temp_new_i64();
11755 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11756
11757 gen_load_fpr64(ctx, fp0, fs);
11758 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11759 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11760 tcg_temp_free_i64(fp1);
b6d96bed 11761 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11762 tcg_temp_free_i64(fp0);
b6d96bed 11763 }
6ea83fed 11764 break;
bf4120ad 11765 case OPC_ABS_PS:
e29c9628 11766 check_ps(ctx);
b6d96bed 11767 {
a7812ae4 11768 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11769
11770 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 11771 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 11772 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11773 tcg_temp_free_i64(fp0);
b6d96bed 11774 }
6ea83fed 11775 break;
bf4120ad 11776 case OPC_MOV_PS:
e29c9628 11777 check_ps(ctx);
b6d96bed 11778 {
a7812ae4 11779 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11780
11781 gen_load_fpr64(ctx, fp0, fs);
11782 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11783 tcg_temp_free_i64(fp0);
b6d96bed 11784 }
6ea83fed 11785 break;
bf4120ad 11786 case OPC_NEG_PS:
e29c9628 11787 check_ps(ctx);
b6d96bed 11788 {
a7812ae4 11789 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11790
11791 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 11792 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 11793 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11794 tcg_temp_free_i64(fp0);
b6d96bed 11795 }
6ea83fed 11796 break;
bf4120ad 11797 case OPC_MOVCF_PS:
e29c9628 11798 check_ps(ctx);
7f6613ce 11799 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6ea83fed 11800 break;
bf4120ad 11801 case OPC_MOVZ_PS:
e29c9628 11802 check_ps(ctx);
a16336e4 11803 {
42a268c2 11804 TCGLabel *l1 = gen_new_label();
30a3848b 11805 TCGv_i64 fp0;
a16336e4 11806
c9297f4d
AJ
11807 if (ft != 0)
11808 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11809 fp0 = tcg_temp_new_i64();
11810 gen_load_fpr64(ctx, fp0, fs);
11811 gen_store_fpr64(ctx, fp0, fd);
11812 tcg_temp_free_i64(fp0);
a16336e4
TS
11813 gen_set_label(l1);
11814 }
6ea83fed 11815 break;
bf4120ad 11816 case OPC_MOVN_PS:
e29c9628 11817 check_ps(ctx);
a16336e4 11818 {
42a268c2 11819 TCGLabel *l1 = gen_new_label();
30a3848b 11820 TCGv_i64 fp0;
c9297f4d
AJ
11821
11822 if (ft != 0) {
11823 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11824 fp0 = tcg_temp_new_i64();
11825 gen_load_fpr64(ctx, fp0, fs);
11826 gen_store_fpr64(ctx, fp0, fd);
11827 tcg_temp_free_i64(fp0);
11828 gen_set_label(l1);
11829 }
a16336e4 11830 }
6ea83fed 11831 break;
bf4120ad 11832 case OPC_ADDR_PS:
e29c9628 11833 check_ps(ctx);
b6d96bed 11834 {
a7812ae4
PB
11835 TCGv_i64 fp0 = tcg_temp_new_i64();
11836 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11837
11838 gen_load_fpr64(ctx, fp0, ft);
11839 gen_load_fpr64(ctx, fp1, fs);
895c2d04 11840 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11841 tcg_temp_free_i64(fp1);
b6d96bed 11842 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11843 tcg_temp_free_i64(fp0);
b6d96bed 11844 }
fbcc6828 11845 break;
bf4120ad 11846 case OPC_MULR_PS:
e29c9628 11847 check_ps(ctx);
b6d96bed 11848 {
a7812ae4
PB
11849 TCGv_i64 fp0 = tcg_temp_new_i64();
11850 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11851
11852 gen_load_fpr64(ctx, fp0, ft);
11853 gen_load_fpr64(ctx, fp1, fs);
895c2d04 11854 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11855 tcg_temp_free_i64(fp1);
b6d96bed 11856 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11857 tcg_temp_free_i64(fp0);
b6d96bed 11858 }
57fa1fb3 11859 break;
bf4120ad 11860 case OPC_RECIP2_PS:
e29c9628 11861 check_ps(ctx);
b6d96bed 11862 {
a7812ae4
PB
11863 TCGv_i64 fp0 = tcg_temp_new_i64();
11864 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11865
11866 gen_load_fpr64(ctx, fp0, fs);
d22d7289 11867 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11868 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11869 tcg_temp_free_i64(fp1);
b6d96bed 11870 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11871 tcg_temp_free_i64(fp0);
b6d96bed 11872 }
57fa1fb3 11873 break;
bf4120ad 11874 case OPC_RECIP1_PS:
e29c9628 11875 check_ps(ctx);
b6d96bed 11876 {
a7812ae4 11877 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11878
11879 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11880 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 11881 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11882 tcg_temp_free_i64(fp0);
b6d96bed 11883 }
57fa1fb3 11884 break;
bf4120ad 11885 case OPC_RSQRT1_PS:
e29c9628 11886 check_ps(ctx);
b6d96bed 11887 {
a7812ae4 11888 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11889
11890 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11891 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 11892 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11893 tcg_temp_free_i64(fp0);
b6d96bed 11894 }
57fa1fb3 11895 break;
bf4120ad 11896 case OPC_RSQRT2_PS:
e29c9628 11897 check_ps(ctx);
b6d96bed 11898 {
a7812ae4
PB
11899 TCGv_i64 fp0 = tcg_temp_new_i64();
11900 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
11901
11902 gen_load_fpr64(ctx, fp0, fs);
11903 gen_load_fpr64(ctx, fp1, ft);
895c2d04 11904 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 11905 tcg_temp_free_i64(fp1);
b6d96bed 11906 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11907 tcg_temp_free_i64(fp0);
b6d96bed 11908 }
57fa1fb3 11909 break;
bf4120ad 11910 case OPC_CVT_S_PU:
5e755519 11911 check_cp1_64bitmode(ctx);
b6d96bed 11912 {
a7812ae4 11913 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11914
7f6613ce 11915 gen_load_fpr32h(ctx, fp0, fs);
895c2d04 11916 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
7c979afd 11917 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11918 tcg_temp_free_i32(fp0);
b6d96bed 11919 }
dd016883 11920 break;
bf4120ad 11921 case OPC_CVT_PW_PS:
e29c9628 11922 check_ps(ctx);
b6d96bed 11923 {
a7812ae4 11924 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
11925
11926 gen_load_fpr64(ctx, fp0, fs);
895c2d04 11927 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 11928 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11929 tcg_temp_free_i64(fp0);
b6d96bed 11930 }
6ea83fed 11931 break;
bf4120ad 11932 case OPC_CVT_S_PL:
5e755519 11933 check_cp1_64bitmode(ctx);
b6d96bed 11934 {
a7812ae4 11935 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11936
7c979afd 11937 gen_load_fpr32(ctx, fp0, fs);
895c2d04 11938 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
7c979afd 11939 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11940 tcg_temp_free_i32(fp0);
b6d96bed 11941 }
6ea83fed 11942 break;
bf4120ad 11943 case OPC_PLL_PS:
e29c9628 11944 check_ps(ctx);
b6d96bed 11945 {
a7812ae4
PB
11946 TCGv_i32 fp0 = tcg_temp_new_i32();
11947 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11948
7c979afd
LA
11949 gen_load_fpr32(ctx, fp0, fs);
11950 gen_load_fpr32(ctx, fp1, ft);
7f6613ce 11951 gen_store_fpr32h(ctx, fp0, fd);
7c979afd 11952 gen_store_fpr32(ctx, fp1, fd);
a7812ae4
PB
11953 tcg_temp_free_i32(fp0);
11954 tcg_temp_free_i32(fp1);
b6d96bed 11955 }
6ea83fed 11956 break;
bf4120ad 11957 case OPC_PLU_PS:
e29c9628 11958 check_ps(ctx);
b6d96bed 11959 {
a7812ae4
PB
11960 TCGv_i32 fp0 = tcg_temp_new_i32();
11961 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11962
7c979afd 11963 gen_load_fpr32(ctx, fp0, fs);
7f6613ce 11964 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 11965 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 11966 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
11967 tcg_temp_free_i32(fp0);
11968 tcg_temp_free_i32(fp1);
b6d96bed 11969 }
5a5012ec 11970 break;
bf4120ad 11971 case OPC_PUL_PS:
e29c9628 11972 check_ps(ctx);
b6d96bed 11973 {
a7812ae4
PB
11974 TCGv_i32 fp0 = tcg_temp_new_i32();
11975 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11976
7f6613ce 11977 gen_load_fpr32h(ctx, fp0, fs);
7c979afd
LA
11978 gen_load_fpr32(ctx, fp1, ft);
11979 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 11980 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
11981 tcg_temp_free_i32(fp0);
11982 tcg_temp_free_i32(fp1);
b6d96bed 11983 }
5a5012ec 11984 break;
bf4120ad 11985 case OPC_PUU_PS:
e29c9628 11986 check_ps(ctx);
b6d96bed 11987 {
a7812ae4
PB
11988 TCGv_i32 fp0 = tcg_temp_new_i32();
11989 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11990
7f6613ce
PJ
11991 gen_load_fpr32h(ctx, fp0, fs);
11992 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 11993 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 11994 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
11995 tcg_temp_free_i32(fp0);
11996 tcg_temp_free_i32(fp1);
b6d96bed 11997 }
5a5012ec 11998 break;
bf4120ad
NF
11999 case OPC_CMP_F_PS:
12000 case OPC_CMP_UN_PS:
12001 case OPC_CMP_EQ_PS:
12002 case OPC_CMP_UEQ_PS:
12003 case OPC_CMP_OLT_PS:
12004 case OPC_CMP_ULT_PS:
12005 case OPC_CMP_OLE_PS:
12006 case OPC_CMP_ULE_PS:
12007 case OPC_CMP_SF_PS:
12008 case OPC_CMP_NGLE_PS:
12009 case OPC_CMP_SEQ_PS:
12010 case OPC_CMP_NGL_PS:
12011 case OPC_CMP_LT_PS:
12012 case OPC_CMP_NGE_PS:
12013 case OPC_CMP_LE_PS:
12014 case OPC_CMP_NGT_PS:
8153667c
NF
12015 if (ctx->opcode & (1 << 6)) {
12016 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
8153667c
NF
12017 } else {
12018 gen_cmp_ps(ctx, func-48, ft, fs, cc);
5a1e8ffb 12019 }
6ea83fed 12020 break;
5a5012ec 12021 default:
9d68ac14 12022 MIPS_INVAL("farith");
9c708c7f 12023 generate_exception_end(ctx, EXCP_RI);
6ea83fed
FB
12024 return;
12025 }
6ea83fed 12026}
6af0bf9c 12027
5a5012ec 12028/* Coprocessor 3 (FPU) */
5e755519
TS
12029static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
12030 int fd, int fs, int base, int index)
7a387fff 12031{
4e2474d6 12032 TCGv t0 = tcg_temp_new();
7a387fff 12033
93b12ccc 12034 if (base == 0) {
6c5c1e20 12035 gen_load_gpr(t0, index);
93b12ccc 12036 } else if (index == 0) {
6c5c1e20 12037 gen_load_gpr(t0, base);
93b12ccc 12038 } else {
05168674 12039 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 12040 }
5a5012ec 12041 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 12042 memory access. */
5a5012ec
TS
12043 switch (opc) {
12044 case OPC_LWXC1:
8c0ab41f 12045 check_cop1x(ctx);
b6d96bed 12046 {
a7812ae4 12047 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 12048
5f68f5ae 12049 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
585c88d5 12050 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 12051 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 12052 tcg_temp_free_i32(fp0);
b6d96bed 12053 }
5a5012ec
TS
12054 break;
12055 case OPC_LDXC1:
8c0ab41f
AJ
12056 check_cop1x(ctx);
12057 check_cp1_registers(ctx, fd);
b6d96bed 12058 {
a7812ae4 12059 TCGv_i64 fp0 = tcg_temp_new_i64();
5f68f5ae 12060 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 12061 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12062 tcg_temp_free_i64(fp0);
b6d96bed 12063 }
5a5012ec
TS
12064 break;
12065 case OPC_LUXC1:
8c0ab41f 12066 check_cp1_64bitmode(ctx);
6c5c1e20 12067 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 12068 {
a7812ae4 12069 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12070
5f68f5ae 12071 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 12072 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 12073 tcg_temp_free_i64(fp0);
b6d96bed 12074 }
5a5012ec
TS
12075 break;
12076 case OPC_SWXC1:
8c0ab41f 12077 check_cop1x(ctx);
b6d96bed 12078 {
a7812ae4 12079 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 12080 gen_load_fpr32(ctx, fp0, fs);
5f68f5ae 12081 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
a7812ae4 12082 tcg_temp_free_i32(fp0);
b6d96bed 12083 }
5a5012ec
TS
12084 break;
12085 case OPC_SDXC1:
8c0ab41f
AJ
12086 check_cop1x(ctx);
12087 check_cp1_registers(ctx, fs);
b6d96bed 12088 {
a7812ae4 12089 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12090 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 12091 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 12092 tcg_temp_free_i64(fp0);
b6d96bed 12093 }
5a5012ec
TS
12094 break;
12095 case OPC_SUXC1:
8c0ab41f 12096 check_cp1_64bitmode(ctx);
6c5c1e20 12097 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 12098 {
a7812ae4 12099 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 12100 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 12101 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 12102 tcg_temp_free_i64(fp0);
b6d96bed 12103 }
5a5012ec 12104 break;
5a5012ec 12105 }
6c5c1e20 12106 tcg_temp_free(t0);
5a5012ec
TS
12107}
12108
5e755519
TS
12109static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
12110 int fd, int fr, int fs, int ft)
5a5012ec 12111{
5a5012ec
TS
12112 switch (opc) {
12113 case OPC_ALNV_PS:
e29c9628 12114 check_ps(ctx);
a16336e4 12115 {
a7812ae4 12116 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
12117 TCGv_i32 fp = tcg_temp_new_i32();
12118 TCGv_i32 fph = tcg_temp_new_i32();
42a268c2
RH
12119 TCGLabel *l1 = gen_new_label();
12120 TCGLabel *l2 = gen_new_label();
a16336e4 12121
6c5c1e20
TS
12122 gen_load_gpr(t0, fr);
12123 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
12124
12125 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7c979afd 12126 gen_load_fpr32(ctx, fp, fs);
7f6613ce 12127 gen_load_fpr32h(ctx, fph, fs);
7c979afd 12128 gen_store_fpr32(ctx, fp, fd);
7f6613ce 12129 gen_store_fpr32h(ctx, fph, fd);
a16336e4
TS
12130 tcg_gen_br(l2);
12131 gen_set_label(l1);
6c5c1e20
TS
12132 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12133 tcg_temp_free(t0);
a16336e4 12134#ifdef TARGET_WORDS_BIGENDIAN
7c979afd 12135 gen_load_fpr32(ctx, fp, fs);
7f6613ce
PJ
12136 gen_load_fpr32h(ctx, fph, ft);
12137 gen_store_fpr32h(ctx, fp, fd);
7c979afd 12138 gen_store_fpr32(ctx, fph, fd);
a16336e4 12139#else
7f6613ce 12140 gen_load_fpr32h(ctx, fph, fs);
7c979afd
LA
12141 gen_load_fpr32(ctx, fp, ft);
12142 gen_store_fpr32(ctx, fph, fd);
7f6613ce 12143 gen_store_fpr32h(ctx, fp, fd);
a16336e4
TS
12144#endif
12145 gen_set_label(l2);
c905fdac
AJ
12146 tcg_temp_free_i32(fp);
12147 tcg_temp_free_i32(fph);
a16336e4 12148 }
5a5012ec
TS
12149 break;
12150 case OPC_MADD_S:
b8aa4598 12151 check_cop1x(ctx);
b6d96bed 12152 {
a7812ae4
PB
12153 TCGv_i32 fp0 = tcg_temp_new_i32();
12154 TCGv_i32 fp1 = tcg_temp_new_i32();
12155 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12156
7c979afd
LA
12157 gen_load_fpr32(ctx, fp0, fs);
12158 gen_load_fpr32(ctx, fp1, ft);
12159 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12160 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12161 tcg_temp_free_i32(fp0);
12162 tcg_temp_free_i32(fp1);
7c979afd 12163 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12164 tcg_temp_free_i32(fp2);
b6d96bed 12165 }
5a5012ec
TS
12166 break;
12167 case OPC_MADD_D:
b8aa4598
TS
12168 check_cop1x(ctx);
12169 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12170 {
a7812ae4
PB
12171 TCGv_i64 fp0 = tcg_temp_new_i64();
12172 TCGv_i64 fp1 = tcg_temp_new_i64();
12173 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12174
12175 gen_load_fpr64(ctx, fp0, fs);
12176 gen_load_fpr64(ctx, fp1, ft);
12177 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12178 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12179 tcg_temp_free_i64(fp0);
12180 tcg_temp_free_i64(fp1);
b6d96bed 12181 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12182 tcg_temp_free_i64(fp2);
b6d96bed 12183 }
5a5012ec
TS
12184 break;
12185 case OPC_MADD_PS:
e29c9628 12186 check_ps(ctx);
b6d96bed 12187 {
a7812ae4
PB
12188 TCGv_i64 fp0 = tcg_temp_new_i64();
12189 TCGv_i64 fp1 = tcg_temp_new_i64();
12190 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12191
12192 gen_load_fpr64(ctx, fp0, fs);
12193 gen_load_fpr64(ctx, fp1, ft);
12194 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12195 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12196 tcg_temp_free_i64(fp0);
12197 tcg_temp_free_i64(fp1);
b6d96bed 12198 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12199 tcg_temp_free_i64(fp2);
b6d96bed 12200 }
5a5012ec
TS
12201 break;
12202 case OPC_MSUB_S:
b8aa4598 12203 check_cop1x(ctx);
b6d96bed 12204 {
a7812ae4
PB
12205 TCGv_i32 fp0 = tcg_temp_new_i32();
12206 TCGv_i32 fp1 = tcg_temp_new_i32();
12207 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12208
7c979afd
LA
12209 gen_load_fpr32(ctx, fp0, fs);
12210 gen_load_fpr32(ctx, fp1, ft);
12211 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12212 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12213 tcg_temp_free_i32(fp0);
12214 tcg_temp_free_i32(fp1);
7c979afd 12215 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12216 tcg_temp_free_i32(fp2);
b6d96bed 12217 }
5a5012ec
TS
12218 break;
12219 case OPC_MSUB_D:
b8aa4598
TS
12220 check_cop1x(ctx);
12221 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12222 {
a7812ae4
PB
12223 TCGv_i64 fp0 = tcg_temp_new_i64();
12224 TCGv_i64 fp1 = tcg_temp_new_i64();
12225 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12226
12227 gen_load_fpr64(ctx, fp0, fs);
12228 gen_load_fpr64(ctx, fp1, ft);
12229 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12230 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12231 tcg_temp_free_i64(fp0);
12232 tcg_temp_free_i64(fp1);
b6d96bed 12233 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12234 tcg_temp_free_i64(fp2);
b6d96bed 12235 }
5a5012ec
TS
12236 break;
12237 case OPC_MSUB_PS:
e29c9628 12238 check_ps(ctx);
b6d96bed 12239 {
a7812ae4
PB
12240 TCGv_i64 fp0 = tcg_temp_new_i64();
12241 TCGv_i64 fp1 = tcg_temp_new_i64();
12242 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12243
12244 gen_load_fpr64(ctx, fp0, fs);
12245 gen_load_fpr64(ctx, fp1, ft);
12246 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12247 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12248 tcg_temp_free_i64(fp0);
12249 tcg_temp_free_i64(fp1);
b6d96bed 12250 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12251 tcg_temp_free_i64(fp2);
b6d96bed 12252 }
5a5012ec
TS
12253 break;
12254 case OPC_NMADD_S:
b8aa4598 12255 check_cop1x(ctx);
b6d96bed 12256 {
a7812ae4
PB
12257 TCGv_i32 fp0 = tcg_temp_new_i32();
12258 TCGv_i32 fp1 = tcg_temp_new_i32();
12259 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12260
7c979afd
LA
12261 gen_load_fpr32(ctx, fp0, fs);
12262 gen_load_fpr32(ctx, fp1, ft);
12263 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12264 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12265 tcg_temp_free_i32(fp0);
12266 tcg_temp_free_i32(fp1);
7c979afd 12267 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12268 tcg_temp_free_i32(fp2);
b6d96bed 12269 }
5a5012ec
TS
12270 break;
12271 case OPC_NMADD_D:
b8aa4598
TS
12272 check_cop1x(ctx);
12273 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12274 {
a7812ae4
PB
12275 TCGv_i64 fp0 = tcg_temp_new_i64();
12276 TCGv_i64 fp1 = tcg_temp_new_i64();
12277 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12278
12279 gen_load_fpr64(ctx, fp0, fs);
12280 gen_load_fpr64(ctx, fp1, ft);
12281 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12282 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12283 tcg_temp_free_i64(fp0);
12284 tcg_temp_free_i64(fp1);
b6d96bed 12285 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12286 tcg_temp_free_i64(fp2);
b6d96bed 12287 }
5a5012ec
TS
12288 break;
12289 case OPC_NMADD_PS:
e29c9628 12290 check_ps(ctx);
b6d96bed 12291 {
a7812ae4
PB
12292 TCGv_i64 fp0 = tcg_temp_new_i64();
12293 TCGv_i64 fp1 = tcg_temp_new_i64();
12294 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12295
12296 gen_load_fpr64(ctx, fp0, fs);
12297 gen_load_fpr64(ctx, fp1, ft);
12298 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12299 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12300 tcg_temp_free_i64(fp0);
12301 tcg_temp_free_i64(fp1);
b6d96bed 12302 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12303 tcg_temp_free_i64(fp2);
b6d96bed 12304 }
5a5012ec
TS
12305 break;
12306 case OPC_NMSUB_S:
b8aa4598 12307 check_cop1x(ctx);
b6d96bed 12308 {
a7812ae4
PB
12309 TCGv_i32 fp0 = tcg_temp_new_i32();
12310 TCGv_i32 fp1 = tcg_temp_new_i32();
12311 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 12312
7c979afd
LA
12313 gen_load_fpr32(ctx, fp0, fs);
12314 gen_load_fpr32(ctx, fp1, ft);
12315 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 12316 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12317 tcg_temp_free_i32(fp0);
12318 tcg_temp_free_i32(fp1);
7c979afd 12319 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 12320 tcg_temp_free_i32(fp2);
b6d96bed 12321 }
5a5012ec
TS
12322 break;
12323 case OPC_NMSUB_D:
b8aa4598
TS
12324 check_cop1x(ctx);
12325 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 12326 {
a7812ae4
PB
12327 TCGv_i64 fp0 = tcg_temp_new_i64();
12328 TCGv_i64 fp1 = tcg_temp_new_i64();
12329 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12330
12331 gen_load_fpr64(ctx, fp0, fs);
12332 gen_load_fpr64(ctx, fp1, ft);
12333 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12334 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12335 tcg_temp_free_i64(fp0);
12336 tcg_temp_free_i64(fp1);
b6d96bed 12337 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12338 tcg_temp_free_i64(fp2);
b6d96bed 12339 }
5a5012ec
TS
12340 break;
12341 case OPC_NMSUB_PS:
e29c9628 12342 check_ps(ctx);
b6d96bed 12343 {
a7812ae4
PB
12344 TCGv_i64 fp0 = tcg_temp_new_i64();
12345 TCGv_i64 fp1 = tcg_temp_new_i64();
12346 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
12347
12348 gen_load_fpr64(ctx, fp0, fs);
12349 gen_load_fpr64(ctx, fp1, ft);
12350 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 12351 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
12352 tcg_temp_free_i64(fp0);
12353 tcg_temp_free_i64(fp1);
b6d96bed 12354 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 12355 tcg_temp_free_i64(fp2);
b6d96bed 12356 }
5a5012ec 12357 break;
923617a3 12358 default:
9d68ac14 12359 MIPS_INVAL("flt3_arith");
9c708c7f 12360 generate_exception_end(ctx, EXCP_RI);
5a5012ec
TS
12361 return;
12362 }
7a387fff
TS
12363}
12364
b00c7218 12365static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
26ebe468
NF
12366{
12367 TCGv t0;
12368
b3167288
RH
12369#if !defined(CONFIG_USER_ONLY)
12370 /* The Linux kernel will emulate rdhwr if it's not supported natively.
12371 Therefore only check the ISA in system mode. */
d75c135e 12372 check_insn(ctx, ISA_MIPS32R2);
b3167288 12373#endif
26ebe468
NF
12374 t0 = tcg_temp_new();
12375
12376 switch (rd) {
12377 case 0:
895c2d04 12378 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
12379 gen_store_gpr(t0, rt);
12380 break;
12381 case 1:
895c2d04 12382 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
12383 gen_store_gpr(t0, rt);
12384 break;
12385 case 2:
eeb3bba8 12386 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
12387 gen_io_start();
12388 }
895c2d04 12389 gen_helper_rdhwr_cc(t0, cpu_env);
eeb3bba8 12390 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
12391 gen_io_end();
12392 }
26ebe468 12393 gen_store_gpr(t0, rt);
d673a68d 12394 /* Break the TB to be able to take timer interrupts immediately
b28425ba 12395 after reading count. DISAS_STOP isn't sufficient, we need to ensure
d673a68d 12396 we break completely out of translated code. */
eeb3bba8
EC
12397 gen_save_pc(ctx->base.pc_next + 4);
12398 ctx->base.is_jmp = DISAS_EXIT;
26ebe468
NF
12399 break;
12400 case 3:
895c2d04 12401 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
12402 gen_store_gpr(t0, rt);
12403 break;
b00c7218
YK
12404 case 4:
12405 check_insn(ctx, ISA_MIPS32R6);
12406 if (sel != 0) {
12407 /* Performance counter registers are not implemented other than
12408 * control register 0.
12409 */
12410 generate_exception(ctx, EXCP_RI);
12411 }
12412 gen_helper_rdhwr_performance(t0, cpu_env);
12413 gen_store_gpr(t0, rt);
12414 break;
12415 case 5:
12416 check_insn(ctx, ISA_MIPS32R6);
12417 gen_helper_rdhwr_xnp(t0, cpu_env);
12418 gen_store_gpr(t0, rt);
12419 break;
26ebe468
NF
12420 case 29:
12421#if defined(CONFIG_USER_ONLY)
d279279e
PJ
12422 tcg_gen_ld_tl(t0, cpu_env,
12423 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
26ebe468
NF
12424 gen_store_gpr(t0, rt);
12425 break;
12426#else
d279279e
PJ
12427 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12428 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12429 tcg_gen_ld_tl(t0, cpu_env,
12430 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12431 gen_store_gpr(t0, rt);
12432 } else {
9c708c7f 12433 generate_exception_end(ctx, EXCP_RI);
d279279e
PJ
12434 }
12435 break;
26ebe468
NF
12436#endif
12437 default: /* Invalid */
12438 MIPS_INVAL("rdhwr");
9c708c7f 12439 generate_exception_end(ctx, EXCP_RI);
26ebe468
NF
12440 break;
12441 }
12442 tcg_temp_free(t0);
12443}
12444
a5f53390
LA
12445static inline void clear_branch_hflags(DisasContext *ctx)
12446{
12447 ctx->hflags &= ~MIPS_HFLAG_BMASK;
eeb3bba8 12448 if (ctx->base.is_jmp == DISAS_NEXT) {
a5f53390
LA
12449 save_cpu_state(ctx, 0);
12450 } else {
12451 /* it is not safe to save ctx->hflags as hflags may be changed
12452 in execution time by the instruction in delay / forbidden slot. */
12453 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12454 }
12455}
12456
31837be3 12457static void gen_branch(DisasContext *ctx, int insn_bytes)
c9602061
NF
12458{
12459 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 12460 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061 12461 /* Branches completion */
a5f53390 12462 clear_branch_hflags(ctx);
eeb3bba8 12463 ctx->base.is_jmp = DISAS_NORETURN;
c9602061 12464 /* FIXME: Need to clear can_do_io. */
364d4831 12465 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
339cd2a8 12466 case MIPS_HFLAG_FBNSLOT:
eeb3bba8 12467 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
339cd2a8 12468 break;
c9602061
NF
12469 case MIPS_HFLAG_B:
12470 /* unconditional branch */
364d4831
NF
12471 if (proc_hflags & MIPS_HFLAG_BX) {
12472 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12473 }
c9602061
NF
12474 gen_goto_tb(ctx, 0, ctx->btarget);
12475 break;
12476 case MIPS_HFLAG_BL:
12477 /* blikely taken case */
c9602061
NF
12478 gen_goto_tb(ctx, 0, ctx->btarget);
12479 break;
12480 case MIPS_HFLAG_BC:
12481 /* Conditional branch */
c9602061 12482 {
42a268c2 12483 TCGLabel *l1 = gen_new_label();
c9602061
NF
12484
12485 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
eeb3bba8 12486 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
c9602061
NF
12487 gen_set_label(l1);
12488 gen_goto_tb(ctx, 0, ctx->btarget);
12489 }
12490 break;
12491 case MIPS_HFLAG_BR:
12492 /* unconditional branch to register */
d75c135e 12493 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
12494 TCGv t0 = tcg_temp_new();
12495 TCGv_i32 t1 = tcg_temp_new_i32();
12496
12497 tcg_gen_andi_tl(t0, btarget, 0x1);
12498 tcg_gen_trunc_tl_i32(t1, t0);
12499 tcg_temp_free(t0);
12500 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12501 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12502 tcg_gen_or_i32(hflags, hflags, t1);
12503 tcg_temp_free_i32(t1);
12504
12505 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12506 } else {
12507 tcg_gen_mov_tl(cpu_PC, btarget);
12508 }
eeb3bba8 12509 if (ctx->base.singlestep_enabled) {
c9602061 12510 save_cpu_state(ctx, 0);
9c708c7f 12511 gen_helper_raise_exception_debug(cpu_env);
c9602061 12512 }
7f11636d 12513 tcg_gen_lookup_and_goto_ptr();
c9602061
NF
12514 break;
12515 default:
a5f53390
LA
12516 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12517 abort();
c9602061
NF
12518 }
12519 }
12520}
12521
6893f074
YK
12522/* Compact Branches */
12523static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12524 int rs, int rt, int32_t offset)
12525{
12526 int bcond_compute = 0;
12527 TCGv t0 = tcg_temp_new();
12528 TCGv t1 = tcg_temp_new();
65935f07 12529 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
6893f074
YK
12530
12531 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12532#ifdef MIPS_DEBUG_DISAS
12533 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 12534 "\n", ctx->base.pc_next);
6893f074 12535#endif
9c708c7f 12536 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
12537 goto out;
12538 }
12539
12540 /* Load needed operands and calculate btarget */
12541 switch (opc) {
12542 /* compact branch */
12543 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12544 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12545 gen_load_gpr(t0, rs);
12546 gen_load_gpr(t1, rt);
12547 bcond_compute = 1;
eeb3bba8 12548 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12549 if (rs <= rt && rs == 0) {
12550 /* OPC_BEQZALC, OPC_BNEZALC */
eeb3bba8 12551 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12552 }
12553 break;
12554 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12555 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12556 gen_load_gpr(t0, rs);
12557 gen_load_gpr(t1, rt);
12558 bcond_compute = 1;
eeb3bba8 12559 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12560 break;
12561 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12562 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12563 if (rs == 0 || rs == rt) {
12564 /* OPC_BLEZALC, OPC_BGEZALC */
12565 /* OPC_BGTZALC, OPC_BLTZALC */
eeb3bba8 12566 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12567 }
12568 gen_load_gpr(t0, rs);
12569 gen_load_gpr(t1, rt);
12570 bcond_compute = 1;
eeb3bba8 12571 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12572 break;
12573 case OPC_BC:
12574 case OPC_BALC:
eeb3bba8 12575 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12576 break;
12577 case OPC_BEQZC:
12578 case OPC_BNEZC:
12579 if (rs != 0) {
12580 /* OPC_BEQZC, OPC_BNEZC */
12581 gen_load_gpr(t0, rs);
12582 bcond_compute = 1;
eeb3bba8 12583 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
12584 } else {
12585 /* OPC_JIC, OPC_JIALC */
12586 TCGv tbase = tcg_temp_new();
12587 TCGv toffset = tcg_temp_new();
12588
12589 gen_load_gpr(tbase, rt);
12590 tcg_gen_movi_tl(toffset, offset);
12591 gen_op_addr_add(ctx, btarget, tbase, toffset);
12592 tcg_temp_free(tbase);
12593 tcg_temp_free(toffset);
12594 }
12595 break;
12596 default:
12597 MIPS_INVAL("Compact branch/jump");
9c708c7f 12598 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
12599 goto out;
12600 }
12601
12602 if (bcond_compute == 0) {
12603 /* Uncoditional compact branch */
12604 switch (opc) {
12605 case OPC_JIALC:
eeb3bba8 12606 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12607 /* Fallthrough */
12608 case OPC_JIC:
12609 ctx->hflags |= MIPS_HFLAG_BR;
12610 break;
12611 case OPC_BALC:
eeb3bba8 12612 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
12613 /* Fallthrough */
12614 case OPC_BC:
12615 ctx->hflags |= MIPS_HFLAG_B;
12616 break;
12617 default:
12618 MIPS_INVAL("Compact branch/jump");
9c708c7f 12619 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
12620 goto out;
12621 }
12622
12623 /* Generating branch here as compact branches don't have delay slot */
12624 gen_branch(ctx, 4);
12625 } else {
12626 /* Conditional compact branch */
12627 TCGLabel *fs = gen_new_label();
12628 save_cpu_state(ctx, 0);
12629
12630 switch (opc) {
12631 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12632 if (rs == 0 && rt != 0) {
12633 /* OPC_BLEZALC */
12634 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12635 } else if (rs != 0 && rt != 0 && rs == rt) {
12636 /* OPC_BGEZALC */
12637 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12638 } else {
12639 /* OPC_BGEUC */
12640 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12641 }
12642 break;
12643 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12644 if (rs == 0 && rt != 0) {
12645 /* OPC_BGTZALC */
12646 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12647 } else if (rs != 0 && rt != 0 && rs == rt) {
12648 /* OPC_BLTZALC */
12649 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12650 } else {
12651 /* OPC_BLTUC */
12652 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12653 }
12654 break;
12655 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12656 if (rs == 0 && rt != 0) {
12657 /* OPC_BLEZC */
12658 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12659 } else if (rs != 0 && rt != 0 && rs == rt) {
12660 /* OPC_BGEZC */
12661 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12662 } else {
12663 /* OPC_BGEC */
12664 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12665 }
12666 break;
12667 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12668 if (rs == 0 && rt != 0) {
12669 /* OPC_BGTZC */
12670 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12671 } else if (rs != 0 && rt != 0 && rs == rt) {
12672 /* OPC_BLTZC */
12673 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12674 } else {
12675 /* OPC_BLTC */
12676 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12677 }
12678 break;
12679 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12680 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12681 if (rs >= rt) {
12682 /* OPC_BOVC, OPC_BNVC */
12683 TCGv t2 = tcg_temp_new();
12684 TCGv t3 = tcg_temp_new();
12685 TCGv t4 = tcg_temp_new();
12686 TCGv input_overflow = tcg_temp_new();
12687
12688 gen_load_gpr(t0, rs);
12689 gen_load_gpr(t1, rt);
12690 tcg_gen_ext32s_tl(t2, t0);
12691 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12692 tcg_gen_ext32s_tl(t3, t1);
12693 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12694 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12695
12696 tcg_gen_add_tl(t4, t2, t3);
12697 tcg_gen_ext32s_tl(t4, t4);
12698 tcg_gen_xor_tl(t2, t2, t3);
12699 tcg_gen_xor_tl(t3, t4, t3);
12700 tcg_gen_andc_tl(t2, t3, t2);
12701 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12702 tcg_gen_or_tl(t4, t4, input_overflow);
12703 if (opc == OPC_BOVC) {
12704 /* OPC_BOVC */
12705 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12706 } else {
12707 /* OPC_BNVC */
12708 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12709 }
12710 tcg_temp_free(input_overflow);
12711 tcg_temp_free(t4);
12712 tcg_temp_free(t3);
12713 tcg_temp_free(t2);
12714 } else if (rs < rt && rs == 0) {
12715 /* OPC_BEQZALC, OPC_BNEZALC */
12716 if (opc == OPC_BEQZALC) {
12717 /* OPC_BEQZALC */
12718 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12719 } else {
12720 /* OPC_BNEZALC */
12721 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12722 }
12723 } else {
12724 /* OPC_BEQC, OPC_BNEC */
12725 if (opc == OPC_BEQC) {
12726 /* OPC_BEQC */
12727 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12728 } else {
12729 /* OPC_BNEC */
12730 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12731 }
12732 }
12733 break;
12734 case OPC_BEQZC:
12735 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12736 break;
12737 case OPC_BNEZC:
12738 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12739 break;
12740 default:
12741 MIPS_INVAL("Compact conditional branch/jump");
9c708c7f 12742 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
12743 goto out;
12744 }
12745
12746 /* Generating branch here as compact branches don't have delay slot */
12747 gen_goto_tb(ctx, 1, ctx->btarget);
12748 gen_set_label(fs);
12749
12750 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
6893f074
YK
12751 }
12752
12753out:
12754 tcg_temp_free(t0);
12755 tcg_temp_free(t1);
12756}
12757
7a387fff 12758/* ISA extensions (ASEs) */
6af0bf9c 12759/* MIPS16 extension to MIPS32 */
6ea219d0
NF
12760
12761/* MIPS16 major opcodes */
12762enum {
12763 M16_OPC_ADDIUSP = 0x00,
12764 M16_OPC_ADDIUPC = 0x01,
12765 M16_OPC_B = 0x02,
12766 M16_OPC_JAL = 0x03,
12767 M16_OPC_BEQZ = 0x04,
12768 M16_OPC_BNEQZ = 0x05,
12769 M16_OPC_SHIFT = 0x06,
12770 M16_OPC_LD = 0x07,
12771 M16_OPC_RRIA = 0x08,
12772 M16_OPC_ADDIU8 = 0x09,
12773 M16_OPC_SLTI = 0x0a,
12774 M16_OPC_SLTIU = 0x0b,
12775 M16_OPC_I8 = 0x0c,
12776 M16_OPC_LI = 0x0d,
12777 M16_OPC_CMPI = 0x0e,
12778 M16_OPC_SD = 0x0f,
12779 M16_OPC_LB = 0x10,
12780 M16_OPC_LH = 0x11,
12781 M16_OPC_LWSP = 0x12,
12782 M16_OPC_LW = 0x13,
12783 M16_OPC_LBU = 0x14,
12784 M16_OPC_LHU = 0x15,
12785 M16_OPC_LWPC = 0x16,
12786 M16_OPC_LWU = 0x17,
12787 M16_OPC_SB = 0x18,
12788 M16_OPC_SH = 0x19,
12789 M16_OPC_SWSP = 0x1a,
12790 M16_OPC_SW = 0x1b,
12791 M16_OPC_RRR = 0x1c,
12792 M16_OPC_RR = 0x1d,
12793 M16_OPC_EXTEND = 0x1e,
12794 M16_OPC_I64 = 0x1f
12795};
12796
12797/* I8 funct field */
12798enum {
12799 I8_BTEQZ = 0x0,
12800 I8_BTNEZ = 0x1,
12801 I8_SWRASP = 0x2,
12802 I8_ADJSP = 0x3,
12803 I8_SVRS = 0x4,
12804 I8_MOV32R = 0x5,
12805 I8_MOVR32 = 0x7
12806};
12807
12808/* RRR f field */
12809enum {
12810 RRR_DADDU = 0x0,
12811 RRR_ADDU = 0x1,
12812 RRR_DSUBU = 0x2,
12813 RRR_SUBU = 0x3
12814};
12815
12816/* RR funct field */
12817enum {
12818 RR_JR = 0x00,
12819 RR_SDBBP = 0x01,
12820 RR_SLT = 0x02,
12821 RR_SLTU = 0x03,
12822 RR_SLLV = 0x04,
12823 RR_BREAK = 0x05,
12824 RR_SRLV = 0x06,
12825 RR_SRAV = 0x07,
12826 RR_DSRL = 0x08,
12827 RR_CMP = 0x0a,
12828 RR_NEG = 0x0b,
12829 RR_AND = 0x0c,
12830 RR_OR = 0x0d,
12831 RR_XOR = 0x0e,
12832 RR_NOT = 0x0f,
12833 RR_MFHI = 0x10,
12834 RR_CNVT = 0x11,
12835 RR_MFLO = 0x12,
12836 RR_DSRA = 0x13,
12837 RR_DSLLV = 0x14,
12838 RR_DSRLV = 0x16,
12839 RR_DSRAV = 0x17,
12840 RR_MULT = 0x18,
12841 RR_MULTU = 0x19,
12842 RR_DIV = 0x1a,
12843 RR_DIVU = 0x1b,
12844 RR_DMULT = 0x1c,
12845 RR_DMULTU = 0x1d,
12846 RR_DDIV = 0x1e,
12847 RR_DDIVU = 0x1f
12848};
12849
12850/* I64 funct field */
12851enum {
12852 I64_LDSP = 0x0,
12853 I64_SDSP = 0x1,
12854 I64_SDRASP = 0x2,
12855 I64_DADJSP = 0x3,
12856 I64_LDPC = 0x4,
364d4831 12857 I64_DADDIU5 = 0x5,
6ea219d0
NF
12858 I64_DADDIUPC = 0x6,
12859 I64_DADDIUSP = 0x7
12860};
12861
12862/* RR ry field for CNVT */
12863enum {
12864 RR_RY_CNVT_ZEB = 0x0,
12865 RR_RY_CNVT_ZEH = 0x1,
12866 RR_RY_CNVT_ZEW = 0x2,
12867 RR_RY_CNVT_SEB = 0x4,
12868 RR_RY_CNVT_SEH = 0x5,
12869 RR_RY_CNVT_SEW = 0x6,
12870};
12871
364d4831
NF
12872static int xlat (int r)
12873{
12874 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12875
12876 return map[r];
12877}
12878
12879static void gen_mips16_save (DisasContext *ctx,
12880 int xsregs, int aregs,
12881 int do_ra, int do_s0, int do_s1,
12882 int framesize)
12883{
12884 TCGv t0 = tcg_temp_new();
12885 TCGv t1 = tcg_temp_new();
c48245f0 12886 TCGv t2 = tcg_temp_new();
364d4831
NF
12887 int args, astatic;
12888
12889 switch (aregs) {
12890 case 0:
12891 case 1:
12892 case 2:
12893 case 3:
12894 case 11:
12895 args = 0;
12896 break;
12897 case 4:
12898 case 5:
12899 case 6:
12900 case 7:
12901 args = 1;
12902 break;
12903 case 8:
12904 case 9:
12905 case 10:
12906 args = 2;
12907 break;
12908 case 12:
12909 case 13:
12910 args = 3;
12911 break;
12912 case 14:
12913 args = 4;
12914 break;
12915 default:
9c708c7f 12916 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12917 return;
12918 }
12919
12920 switch (args) {
12921 case 4:
12922 gen_base_offset_addr(ctx, t0, 29, 12);
12923 gen_load_gpr(t1, 7);
5f68f5ae 12924 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
12925 /* Fall through */
12926 case 3:
12927 gen_base_offset_addr(ctx, t0, 29, 8);
12928 gen_load_gpr(t1, 6);
5f68f5ae 12929 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
12930 /* Fall through */
12931 case 2:
12932 gen_base_offset_addr(ctx, t0, 29, 4);
12933 gen_load_gpr(t1, 5);
5f68f5ae 12934 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
12935 /* Fall through */
12936 case 1:
12937 gen_base_offset_addr(ctx, t0, 29, 0);
12938 gen_load_gpr(t1, 4);
5f68f5ae 12939 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
12940 }
12941
12942 gen_load_gpr(t0, 29);
12943
5f68f5ae 12944#define DECR_AND_STORE(reg) do { \
c48245f0
MR
12945 tcg_gen_movi_tl(t2, -4); \
12946 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
12947 gen_load_gpr(t1, reg); \
12948 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
364d4831
NF
12949 } while (0)
12950
12951 if (do_ra) {
12952 DECR_AND_STORE(31);
12953 }
12954
12955 switch (xsregs) {
12956 case 7:
12957 DECR_AND_STORE(30);
12958 /* Fall through */
12959 case 6:
12960 DECR_AND_STORE(23);
12961 /* Fall through */
12962 case 5:
12963 DECR_AND_STORE(22);
12964 /* Fall through */
12965 case 4:
12966 DECR_AND_STORE(21);
12967 /* Fall through */
12968 case 3:
12969 DECR_AND_STORE(20);
12970 /* Fall through */
12971 case 2:
12972 DECR_AND_STORE(19);
12973 /* Fall through */
12974 case 1:
12975 DECR_AND_STORE(18);
12976 }
12977
12978 if (do_s1) {
12979 DECR_AND_STORE(17);
12980 }
12981 if (do_s0) {
12982 DECR_AND_STORE(16);
12983 }
12984
12985 switch (aregs) {
12986 case 0:
12987 case 4:
12988 case 8:
12989 case 12:
12990 case 14:
12991 astatic = 0;
12992 break;
12993 case 1:
12994 case 5:
12995 case 9:
12996 case 13:
12997 astatic = 1;
12998 break;
12999 case 2:
13000 case 6:
13001 case 10:
13002 astatic = 2;
13003 break;
13004 case 3:
13005 case 7:
13006 astatic = 3;
13007 break;
13008 case 11:
13009 astatic = 4;
13010 break;
13011 default:
9c708c7f 13012 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13013 return;
13014 }
13015
13016 if (astatic > 0) {
13017 DECR_AND_STORE(7);
13018 if (astatic > 1) {
13019 DECR_AND_STORE(6);
13020 if (astatic > 2) {
13021 DECR_AND_STORE(5);
13022 if (astatic > 3) {
13023 DECR_AND_STORE(4);
13024 }
13025 }
13026 }
13027 }
13028#undef DECR_AND_STORE
13029
c48245f0
MR
13030 tcg_gen_movi_tl(t2, -framesize);
13031 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
13032 tcg_temp_free(t0);
13033 tcg_temp_free(t1);
c48245f0 13034 tcg_temp_free(t2);
364d4831
NF
13035}
13036
13037static void gen_mips16_restore (DisasContext *ctx,
13038 int xsregs, int aregs,
13039 int do_ra, int do_s0, int do_s1,
13040 int framesize)
13041{
13042 int astatic;
13043 TCGv t0 = tcg_temp_new();
13044 TCGv t1 = tcg_temp_new();
c48245f0 13045 TCGv t2 = tcg_temp_new();
364d4831 13046
c48245f0
MR
13047 tcg_gen_movi_tl(t2, framesize);
13048 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
364d4831 13049
5f68f5ae 13050#define DECR_AND_LOAD(reg) do { \
c48245f0
MR
13051 tcg_gen_movi_tl(t2, -4); \
13052 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
13053 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13054 gen_store_gpr(t1, reg); \
364d4831
NF
13055 } while (0)
13056
13057 if (do_ra) {
13058 DECR_AND_LOAD(31);
13059 }
13060
13061 switch (xsregs) {
13062 case 7:
13063 DECR_AND_LOAD(30);
13064 /* Fall through */
13065 case 6:
13066 DECR_AND_LOAD(23);
13067 /* Fall through */
13068 case 5:
13069 DECR_AND_LOAD(22);
13070 /* Fall through */
13071 case 4:
13072 DECR_AND_LOAD(21);
13073 /* Fall through */
13074 case 3:
13075 DECR_AND_LOAD(20);
13076 /* Fall through */
13077 case 2:
13078 DECR_AND_LOAD(19);
13079 /* Fall through */
13080 case 1:
13081 DECR_AND_LOAD(18);
13082 }
13083
13084 if (do_s1) {
13085 DECR_AND_LOAD(17);
13086 }
13087 if (do_s0) {
13088 DECR_AND_LOAD(16);
13089 }
13090
13091 switch (aregs) {
13092 case 0:
13093 case 4:
13094 case 8:
13095 case 12:
13096 case 14:
13097 astatic = 0;
13098 break;
13099 case 1:
13100 case 5:
13101 case 9:
13102 case 13:
13103 astatic = 1;
13104 break;
13105 case 2:
13106 case 6:
13107 case 10:
13108 astatic = 2;
13109 break;
13110 case 3:
13111 case 7:
13112 astatic = 3;
13113 break;
13114 case 11:
13115 astatic = 4;
13116 break;
13117 default:
9c708c7f 13118 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13119 return;
13120 }
13121
13122 if (astatic > 0) {
13123 DECR_AND_LOAD(7);
13124 if (astatic > 1) {
13125 DECR_AND_LOAD(6);
13126 if (astatic > 2) {
13127 DECR_AND_LOAD(5);
13128 if (astatic > 3) {
13129 DECR_AND_LOAD(4);
13130 }
13131 }
13132 }
13133 }
13134#undef DECR_AND_LOAD
13135
c48245f0
MR
13136 tcg_gen_movi_tl(t2, framesize);
13137 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
13138 tcg_temp_free(t0);
13139 tcg_temp_free(t1);
c48245f0 13140 tcg_temp_free(t2);
364d4831
NF
13141}
13142
13143static void gen_addiupc (DisasContext *ctx, int rx, int imm,
13144 int is_64_bit, int extended)
13145{
13146 TCGv t0;
13147
13148 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 13149 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13150 return;
13151 }
13152
13153 t0 = tcg_temp_new();
13154
13155 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13156 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13157 if (!is_64_bit) {
13158 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13159 }
13160
13161 tcg_temp_free(t0);
13162}
13163
0d74a222
LA
13164static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13165 int16_t offset)
13166{
13167 TCGv_i32 t0 = tcg_const_i32(op);
13168 TCGv t1 = tcg_temp_new();
13169 gen_base_offset_addr(ctx, t1, base, offset);
13170 gen_helper_cache(cpu_env, t1, t0);
13171}
13172
364d4831 13173#if defined(TARGET_MIPS64)
d75c135e 13174static void decode_i64_mips16 (DisasContext *ctx,
364d4831
NF
13175 int ry, int funct, int16_t offset,
13176 int extended)
13177{
13178 switch (funct) {
13179 case I64_LDSP:
d9224450 13180 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13181 check_mips_64(ctx);
13182 offset = extended ? offset : offset << 3;
d75c135e 13183 gen_ld(ctx, OPC_LD, ry, 29, offset);
364d4831
NF
13184 break;
13185 case I64_SDSP:
d9224450 13186 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13187 check_mips_64(ctx);
13188 offset = extended ? offset : offset << 3;
5c13fdfd 13189 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
13190 break;
13191 case I64_SDRASP:
d9224450 13192 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13193 check_mips_64(ctx);
13194 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 13195 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
13196 break;
13197 case I64_DADJSP:
d9224450 13198 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13199 check_mips_64(ctx);
13200 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
d75c135e 13201 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
364d4831
NF
13202 break;
13203 case I64_LDPC:
d9224450
MR
13204 check_insn(ctx, ISA_MIPS3);
13205 check_mips_64(ctx);
364d4831 13206 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 13207 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13208 } else {
13209 offset = extended ? offset : offset << 3;
d75c135e 13210 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
13211 }
13212 break;
13213 case I64_DADDIU5:
d9224450 13214 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13215 check_mips_64(ctx);
13216 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
d75c135e 13217 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
364d4831
NF
13218 break;
13219 case I64_DADDIUPC:
d9224450 13220 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13221 check_mips_64(ctx);
13222 offset = extended ? offset : offset << 2;
13223 gen_addiupc(ctx, ry, offset, 1, extended);
13224 break;
13225 case I64_DADDIUSP:
d9224450 13226 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13227 check_mips_64(ctx);
13228 offset = extended ? offset : offset << 2;
d75c135e 13229 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
364d4831
NF
13230 break;
13231 }
13232}
13233#endif
13234
240ce26a 13235static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
364d4831 13236{
eeb3bba8 13237 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
13238 int op, rx, ry, funct, sa;
13239 int16_t imm, offset;
13240
13241 ctx->opcode = (ctx->opcode << 16) | extend;
13242 op = (ctx->opcode >> 11) & 0x1f;
13243 sa = (ctx->opcode >> 22) & 0x1f;
13244 funct = (ctx->opcode >> 8) & 0x7;
13245 rx = xlat((ctx->opcode >> 8) & 0x7);
13246 ry = xlat((ctx->opcode >> 5) & 0x7);
13247 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13248 | ((ctx->opcode >> 21) & 0x3f) << 5
13249 | (ctx->opcode & 0x1f));
13250
13251 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
13252 counterparts. */
13253 switch (op) {
13254 case M16_OPC_ADDIUSP:
d75c135e 13255 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
13256 break;
13257 case M16_OPC_ADDIUPC:
13258 gen_addiupc(ctx, rx, imm, 0, 1);
13259 break;
13260 case M16_OPC_B:
b231c103 13261 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
364d4831
NF
13262 /* No delay slot, so just process as a normal instruction */
13263 break;
13264 case M16_OPC_BEQZ:
b231c103 13265 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
364d4831
NF
13266 /* No delay slot, so just process as a normal instruction */
13267 break;
13268 case M16_OPC_BNEQZ:
b231c103 13269 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
364d4831
NF
13270 /* No delay slot, so just process as a normal instruction */
13271 break;
13272 case M16_OPC_SHIFT:
13273 switch (ctx->opcode & 0x3) {
13274 case 0x0:
d75c135e 13275 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
13276 break;
13277 case 0x1:
13278#if defined(TARGET_MIPS64)
13279 check_mips_64(ctx);
d75c135e 13280 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 13281#else
9c708c7f 13282 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13283#endif
13284 break;
13285 case 0x2:
d75c135e 13286 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
13287 break;
13288 case 0x3:
d75c135e 13289 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
13290 break;
13291 }
13292 break;
13293#if defined(TARGET_MIPS64)
13294 case M16_OPC_LD:
d9224450 13295 check_insn(ctx, ISA_MIPS3);
d75de749 13296 check_mips_64(ctx);
d75c135e 13297 gen_ld(ctx, OPC_LD, ry, rx, offset);
364d4831
NF
13298 break;
13299#endif
13300 case M16_OPC_RRIA:
13301 imm = ctx->opcode & 0xf;
13302 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13303 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13304 imm = (int16_t) (imm << 1) >> 1;
13305 if ((ctx->opcode >> 4) & 0x1) {
13306#if defined(TARGET_MIPS64)
13307 check_mips_64(ctx);
d75c135e 13308 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 13309#else
9c708c7f 13310 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13311#endif
13312 } else {
d75c135e 13313 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
13314 }
13315 break;
13316 case M16_OPC_ADDIU8:
d75c135e 13317 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
13318 break;
13319 case M16_OPC_SLTI:
d75c135e 13320 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
13321 break;
13322 case M16_OPC_SLTIU:
d75c135e 13323 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
13324 break;
13325 case M16_OPC_I8:
13326 switch (funct) {
13327 case I8_BTEQZ:
b231c103 13328 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
364d4831
NF
13329 break;
13330 case I8_BTNEZ:
b231c103 13331 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
364d4831
NF
13332 break;
13333 case I8_SWRASP:
5c13fdfd 13334 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
13335 break;
13336 case I8_ADJSP:
d75c135e 13337 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
364d4831
NF
13338 break;
13339 case I8_SVRS:
d9224450 13340 check_insn(ctx, ISA_MIPS32);
364d4831
NF
13341 {
13342 int xsregs = (ctx->opcode >> 24) & 0x7;
13343 int aregs = (ctx->opcode >> 16) & 0xf;
13344 int do_ra = (ctx->opcode >> 6) & 0x1;
13345 int do_s0 = (ctx->opcode >> 5) & 0x1;
13346 int do_s1 = (ctx->opcode >> 4) & 0x1;
13347 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13348 | (ctx->opcode & 0xf)) << 3;
13349
13350 if (ctx->opcode & (1 << 7)) {
13351 gen_mips16_save(ctx, xsregs, aregs,
13352 do_ra, do_s0, do_s1,
13353 framesize);
13354 } else {
13355 gen_mips16_restore(ctx, xsregs, aregs,
13356 do_ra, do_s0, do_s1,
13357 framesize);
13358 }
13359 }
13360 break;
13361 default:
9c708c7f 13362 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13363 break;
13364 }
13365 break;
13366 case M16_OPC_LI:
13367 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13368 break;
13369 case M16_OPC_CMPI:
13370 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13371 break;
13372#if defined(TARGET_MIPS64)
13373 case M16_OPC_SD:
d9224450
MR
13374 check_insn(ctx, ISA_MIPS3);
13375 check_mips_64(ctx);
5c13fdfd 13376 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
13377 break;
13378#endif
13379 case M16_OPC_LB:
d75c135e 13380 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
13381 break;
13382 case M16_OPC_LH:
d75c135e 13383 gen_ld(ctx, OPC_LH, ry, rx, offset);
364d4831
NF
13384 break;
13385 case M16_OPC_LWSP:
d75c135e 13386 gen_ld(ctx, OPC_LW, rx, 29, offset);
364d4831
NF
13387 break;
13388 case M16_OPC_LW:
d75c135e 13389 gen_ld(ctx, OPC_LW, ry, rx, offset);
364d4831
NF
13390 break;
13391 case M16_OPC_LBU:
d75c135e 13392 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
13393 break;
13394 case M16_OPC_LHU:
d75c135e 13395 gen_ld(ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
13396 break;
13397 case M16_OPC_LWPC:
d75c135e 13398 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
13399 break;
13400#if defined(TARGET_MIPS64)
13401 case M16_OPC_LWU:
d9224450
MR
13402 check_insn(ctx, ISA_MIPS3);
13403 check_mips_64(ctx);
d75c135e 13404 gen_ld(ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
13405 break;
13406#endif
13407 case M16_OPC_SB:
5c13fdfd 13408 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
13409 break;
13410 case M16_OPC_SH:
5c13fdfd 13411 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
13412 break;
13413 case M16_OPC_SWSP:
5c13fdfd 13414 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
13415 break;
13416 case M16_OPC_SW:
5c13fdfd 13417 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
13418 break;
13419#if defined(TARGET_MIPS64)
13420 case M16_OPC_I64:
d75c135e 13421 decode_i64_mips16(ctx, ry, funct, offset, 1);
364d4831
NF
13422 break;
13423#endif
13424 default:
9c708c7f 13425 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13426 break;
13427 }
13428
13429 return 4;
13430}
13431
3b3c1694
LA
13432static inline bool is_uhi(int sdbbp_code)
13433{
13434#ifdef CONFIG_USER_ONLY
13435 return false;
13436#else
13437 return semihosting_enabled() && sdbbp_code == 1;
13438#endif
13439}
13440
240ce26a 13441static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
364d4831
NF
13442{
13443 int rx, ry;
13444 int sa;
13445 int op, cnvt_op, op1, offset;
13446 int funct;
13447 int n_bytes;
13448
13449 op = (ctx->opcode >> 11) & 0x1f;
13450 sa = (ctx->opcode >> 2) & 0x7;
13451 sa = sa == 0 ? 8 : sa;
13452 rx = xlat((ctx->opcode >> 8) & 0x7);
13453 cnvt_op = (ctx->opcode >> 5) & 0x7;
13454 ry = xlat((ctx->opcode >> 5) & 0x7);
13455 op1 = offset = ctx->opcode & 0x1f;
13456
13457 n_bytes = 2;
13458
13459 switch (op) {
13460 case M16_OPC_ADDIUSP:
13461 {
13462 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13463
d75c135e 13464 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
13465 }
13466 break;
13467 case M16_OPC_ADDIUPC:
13468 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13469 break;
13470 case M16_OPC_B:
13471 offset = (ctx->opcode & 0x7ff) << 1;
13472 offset = (int16_t)(offset << 4) >> 4;
b231c103 13473 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
364d4831
NF
13474 /* No delay slot, so just process as a normal instruction */
13475 break;
13476 case M16_OPC_JAL:
eeb3bba8 13477 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
13478 offset = (((ctx->opcode & 0x1f) << 21)
13479 | ((ctx->opcode >> 5) & 0x1f) << 16
13480 | offset) << 2;
b231c103
YK
13481 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13482 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
364d4831 13483 n_bytes = 4;
364d4831
NF
13484 break;
13485 case M16_OPC_BEQZ:
b231c103
YK
13486 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13487 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13488 /* No delay slot, so just process as a normal instruction */
13489 break;
13490 case M16_OPC_BNEQZ:
b231c103
YK
13491 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13492 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13493 /* No delay slot, so just process as a normal instruction */
13494 break;
13495 case M16_OPC_SHIFT:
13496 switch (ctx->opcode & 0x3) {
13497 case 0x0:
d75c135e 13498 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
13499 break;
13500 case 0x1:
13501#if defined(TARGET_MIPS64)
d9224450 13502 check_insn(ctx, ISA_MIPS3);
364d4831 13503 check_mips_64(ctx);
d75c135e 13504 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 13505#else
9c708c7f 13506 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13507#endif
13508 break;
13509 case 0x2:
d75c135e 13510 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
13511 break;
13512 case 0x3:
d75c135e 13513 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
13514 break;
13515 }
13516 break;
13517#if defined(TARGET_MIPS64)
13518 case M16_OPC_LD:
d9224450 13519 check_insn(ctx, ISA_MIPS3);
364d4831 13520 check_mips_64(ctx);
d75c135e 13521 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
13522 break;
13523#endif
13524 case M16_OPC_RRIA:
13525 {
13526 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13527
13528 if ((ctx->opcode >> 4) & 1) {
13529#if defined(TARGET_MIPS64)
d9224450 13530 check_insn(ctx, ISA_MIPS3);
364d4831 13531 check_mips_64(ctx);
d75c135e 13532 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 13533#else
9c708c7f 13534 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13535#endif
13536 } else {
d75c135e 13537 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
13538 }
13539 }
13540 break;
13541 case M16_OPC_ADDIU8:
13542 {
13543 int16_t imm = (int8_t) ctx->opcode;
13544
d75c135e 13545 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
13546 }
13547 break;
13548 case M16_OPC_SLTI:
13549 {
13550 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 13551 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
13552 }
13553 break;
13554 case M16_OPC_SLTIU:
13555 {
13556 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 13557 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
13558 }
13559 break;
13560 case M16_OPC_I8:
13561 {
13562 int reg32;
13563
13564 funct = (ctx->opcode >> 8) & 0x7;
13565 switch (funct) {
13566 case I8_BTEQZ:
13567 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
b231c103 13568 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13569 break;
13570 case I8_BTNEZ:
13571 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
b231c103 13572 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
13573 break;
13574 case I8_SWRASP:
5c13fdfd 13575 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
13576 break;
13577 case I8_ADJSP:
d75c135e 13578 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
364d4831
NF
13579 ((int8_t)ctx->opcode) << 3);
13580 break;
13581 case I8_SVRS:
d9224450 13582 check_insn(ctx, ISA_MIPS32);
364d4831
NF
13583 {
13584 int do_ra = ctx->opcode & (1 << 6);
13585 int do_s0 = ctx->opcode & (1 << 5);
13586 int do_s1 = ctx->opcode & (1 << 4);
13587 int framesize = ctx->opcode & 0xf;
13588
13589 if (framesize == 0) {
13590 framesize = 128;
13591 } else {
13592 framesize = framesize << 3;
13593 }
13594
13595 if (ctx->opcode & (1 << 7)) {
13596 gen_mips16_save(ctx, 0, 0,
13597 do_ra, do_s0, do_s1, framesize);
13598 } else {
13599 gen_mips16_restore(ctx, 0, 0,
13600 do_ra, do_s0, do_s1, framesize);
13601 }
13602 }
13603 break;
13604 case I8_MOV32R:
13605 {
13606 int rz = xlat(ctx->opcode & 0x7);
13607
13608 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13609 ((ctx->opcode >> 5) & 0x7);
d75c135e 13610 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
364d4831
NF
13611 }
13612 break;
13613 case I8_MOVR32:
13614 reg32 = ctx->opcode & 0x1f;
d75c135e 13615 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
364d4831
NF
13616 break;
13617 default:
9c708c7f 13618 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13619 break;
13620 }
13621 }
13622 break;
13623 case M16_OPC_LI:
13624 {
13625 int16_t imm = (uint8_t) ctx->opcode;
13626
d75c135e 13627 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
364d4831
NF
13628 }
13629 break;
13630 case M16_OPC_CMPI:
13631 {
13632 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 13633 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
13634 }
13635 break;
13636#if defined(TARGET_MIPS64)
13637 case M16_OPC_SD:
d9224450 13638 check_insn(ctx, ISA_MIPS3);
364d4831 13639 check_mips_64(ctx);
5c13fdfd 13640 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
13641 break;
13642#endif
13643 case M16_OPC_LB:
d75c135e 13644 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
13645 break;
13646 case M16_OPC_LH:
d75c135e 13647 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
13648 break;
13649 case M16_OPC_LWSP:
d75c135e 13650 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
13651 break;
13652 case M16_OPC_LW:
d75c135e 13653 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
13654 break;
13655 case M16_OPC_LBU:
d75c135e 13656 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
13657 break;
13658 case M16_OPC_LHU:
d75c135e 13659 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
13660 break;
13661 case M16_OPC_LWPC:
d75c135e 13662 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
13663 break;
13664#if defined (TARGET_MIPS64)
13665 case M16_OPC_LWU:
d9224450 13666 check_insn(ctx, ISA_MIPS3);
364d4831 13667 check_mips_64(ctx);
d75c135e 13668 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
13669 break;
13670#endif
13671 case M16_OPC_SB:
5c13fdfd 13672 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
13673 break;
13674 case M16_OPC_SH:
5c13fdfd 13675 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
13676 break;
13677 case M16_OPC_SWSP:
5c13fdfd 13678 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
13679 break;
13680 case M16_OPC_SW:
5c13fdfd 13681 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
13682 break;
13683 case M16_OPC_RRR:
13684 {
13685 int rz = xlat((ctx->opcode >> 2) & 0x7);
13686 int mips32_op;
13687
13688 switch (ctx->opcode & 0x3) {
13689 case RRR_ADDU:
13690 mips32_op = OPC_ADDU;
13691 break;
13692 case RRR_SUBU:
13693 mips32_op = OPC_SUBU;
13694 break;
13695#if defined(TARGET_MIPS64)
13696 case RRR_DADDU:
13697 mips32_op = OPC_DADDU;
d9224450 13698 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13699 check_mips_64(ctx);
13700 break;
13701 case RRR_DSUBU:
13702 mips32_op = OPC_DSUBU;
d9224450 13703 check_insn(ctx, ISA_MIPS3);
364d4831
NF
13704 check_mips_64(ctx);
13705 break;
13706#endif
13707 default:
9c708c7f 13708 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13709 goto done;
13710 }
13711
d75c135e 13712 gen_arith(ctx, mips32_op, rz, rx, ry);
364d4831
NF
13713 done:
13714 ;
13715 }
13716 break;
13717 case M16_OPC_RR:
13718 switch (op1) {
13719 case RR_JR:
13720 {
13721 int nd = (ctx->opcode >> 7) & 0x1;
13722 int link = (ctx->opcode >> 6) & 0x1;
13723 int ra = (ctx->opcode >> 5) & 0x1;
13724
d9224450
MR
13725 if (nd) {
13726 check_insn(ctx, ISA_MIPS32);
13727 }
13728
364d4831 13729 if (link) {
b231c103 13730 op = OPC_JALR;
364d4831
NF
13731 } else {
13732 op = OPC_JR;
13733 }
13734
b231c103
YK
13735 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13736 (nd ? 0 : 2));
364d4831
NF
13737 }
13738 break;
13739 case RR_SDBBP:
3b3c1694
LA
13740 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13741 gen_helper_do_semihosting(cpu_env);
13742 } else {
13743 /* XXX: not clear which exception should be raised
13744 * when in debug mode...
13745 */
13746 check_insn(ctx, ISA_MIPS32);
9c708c7f 13747 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 13748 }
364d4831
NF
13749 break;
13750 case RR_SLT:
d75c135e 13751 gen_slt(ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
13752 break;
13753 case RR_SLTU:
d75c135e 13754 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
13755 break;
13756 case RR_BREAK:
9c708c7f 13757 generate_exception_end(ctx, EXCP_BREAK);
364d4831
NF
13758 break;
13759 case RR_SLLV:
d75c135e 13760 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
364d4831
NF
13761 break;
13762 case RR_SRLV:
d75c135e 13763 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
364d4831
NF
13764 break;
13765 case RR_SRAV:
d75c135e 13766 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
364d4831
NF
13767 break;
13768#if defined (TARGET_MIPS64)
13769 case RR_DSRL:
d9224450 13770 check_insn(ctx, ISA_MIPS3);
364d4831 13771 check_mips_64(ctx);
d75c135e 13772 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
364d4831
NF
13773 break;
13774#endif
13775 case RR_CMP:
d75c135e 13776 gen_logic(ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
13777 break;
13778 case RR_NEG:
d75c135e 13779 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
364d4831
NF
13780 break;
13781 case RR_AND:
d75c135e 13782 gen_logic(ctx, OPC_AND, rx, rx, ry);
364d4831
NF
13783 break;
13784 case RR_OR:
d75c135e 13785 gen_logic(ctx, OPC_OR, rx, rx, ry);
364d4831
NF
13786 break;
13787 case RR_XOR:
d75c135e 13788 gen_logic(ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
13789 break;
13790 case RR_NOT:
d75c135e 13791 gen_logic(ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
13792 break;
13793 case RR_MFHI:
26135ead 13794 gen_HILO(ctx, OPC_MFHI, 0, rx);
364d4831
NF
13795 break;
13796 case RR_CNVT:
d9224450 13797 check_insn(ctx, ISA_MIPS32);
364d4831
NF
13798 switch (cnvt_op) {
13799 case RR_RY_CNVT_ZEB:
13800 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13801 break;
13802 case RR_RY_CNVT_ZEH:
13803 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13804 break;
13805 case RR_RY_CNVT_SEB:
13806 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13807 break;
13808 case RR_RY_CNVT_SEH:
13809 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13810 break;
13811#if defined (TARGET_MIPS64)
13812 case RR_RY_CNVT_ZEW:
d9224450 13813 check_insn(ctx, ISA_MIPS64);
364d4831
NF
13814 check_mips_64(ctx);
13815 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13816 break;
13817 case RR_RY_CNVT_SEW:
d9224450 13818 check_insn(ctx, ISA_MIPS64);
364d4831
NF
13819 check_mips_64(ctx);
13820 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13821 break;
13822#endif
13823 default:
9c708c7f 13824 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13825 break;
13826 }
13827 break;
13828 case RR_MFLO:
26135ead 13829 gen_HILO(ctx, OPC_MFLO, 0, rx);
364d4831
NF
13830 break;
13831#if defined (TARGET_MIPS64)
13832 case RR_DSRA:
d9224450 13833 check_insn(ctx, ISA_MIPS3);
364d4831 13834 check_mips_64(ctx);
d75c135e 13835 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
364d4831
NF
13836 break;
13837 case RR_DSLLV:
d9224450 13838 check_insn(ctx, ISA_MIPS3);
364d4831 13839 check_mips_64(ctx);
d75c135e 13840 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
364d4831
NF
13841 break;
13842 case RR_DSRLV:
d9224450 13843 check_insn(ctx, ISA_MIPS3);
364d4831 13844 check_mips_64(ctx);
d75c135e 13845 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
364d4831
NF
13846 break;
13847 case RR_DSRAV:
d9224450 13848 check_insn(ctx, ISA_MIPS3);
364d4831 13849 check_mips_64(ctx);
d75c135e 13850 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
364d4831
NF
13851 break;
13852#endif
13853 case RR_MULT:
26135ead 13854 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
364d4831
NF
13855 break;
13856 case RR_MULTU:
26135ead 13857 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
364d4831
NF
13858 break;
13859 case RR_DIV:
26135ead 13860 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
364d4831
NF
13861 break;
13862 case RR_DIVU:
26135ead 13863 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
364d4831
NF
13864 break;
13865#if defined (TARGET_MIPS64)
13866 case RR_DMULT:
d9224450 13867 check_insn(ctx, ISA_MIPS3);
364d4831 13868 check_mips_64(ctx);
26135ead 13869 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
364d4831
NF
13870 break;
13871 case RR_DMULTU:
d9224450 13872 check_insn(ctx, ISA_MIPS3);
364d4831 13873 check_mips_64(ctx);
26135ead 13874 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
364d4831
NF
13875 break;
13876 case RR_DDIV:
d9224450 13877 check_insn(ctx, ISA_MIPS3);
364d4831 13878 check_mips_64(ctx);
26135ead 13879 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
364d4831
NF
13880 break;
13881 case RR_DDIVU:
d9224450 13882 check_insn(ctx, ISA_MIPS3);
364d4831 13883 check_mips_64(ctx);
26135ead 13884 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
364d4831
NF
13885 break;
13886#endif
13887 default:
9c708c7f 13888 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13889 break;
13890 }
13891 break;
13892 case M16_OPC_EXTEND:
240ce26a 13893 decode_extended_mips16_opc(env, ctx);
364d4831
NF
13894 n_bytes = 4;
13895 break;
13896#if defined(TARGET_MIPS64)
13897 case M16_OPC_I64:
13898 funct = (ctx->opcode >> 8) & 0x7;
d75c135e 13899 decode_i64_mips16(ctx, ry, funct, offset, 0);
364d4831
NF
13900 break;
13901#endif
13902 default:
9c708c7f 13903 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
13904 break;
13905 }
13906
13907 return n_bytes;
13908}
13909
211da992 13910/* microMIPS extension to MIPS32/MIPS64 */
6af0bf9c 13911
211da992
CWR
13912/*
13913 * microMIPS32/microMIPS64 major opcodes
13914 *
13915 * 1. MIPS Architecture for Programmers Volume II-B:
13916 * The microMIPS32 Instruction Set (Revision 3.05)
13917 *
13918 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13919 *
13920 * 2. MIPS Architecture For Programmers Volume II-A:
13921 * The MIPS64 Instruction Set (Revision 3.51)
13922 */
6af0bf9c 13923
3c824109
NF
13924enum {
13925 POOL32A = 0x00,
13926 POOL16A = 0x01,
13927 LBU16 = 0x02,
13928 MOVE16 = 0x03,
13929 ADDI32 = 0x04,
3a1f4268
YK
13930 R6_LUI = 0x04,
13931 AUI = 0x04,
3c824109
NF
13932 LBU32 = 0x05,
13933 SB32 = 0x06,
13934 LB32 = 0x07,
13935
13936 POOL32B = 0x08,
13937 POOL16B = 0x09,
13938 LHU16 = 0x0a,
13939 ANDI16 = 0x0b,
13940 ADDIU32 = 0x0c,
13941 LHU32 = 0x0d,
13942 SH32 = 0x0e,
13943 LH32 = 0x0f,
13944
13945 POOL32I = 0x10,
13946 POOL16C = 0x11,
13947 LWSP16 = 0x12,
13948 POOL16D = 0x13,
13949 ORI32 = 0x14,
13950 POOL32F = 0x15,
211da992
CWR
13951 POOL32S = 0x16, /* MIPS64 */
13952 DADDIU32 = 0x17, /* MIPS64 */
3c824109
NF
13953
13954 POOL32C = 0x18,
13955 LWGP16 = 0x19,
13956 LW16 = 0x1a,
13957 POOL16E = 0x1b,
13958 XORI32 = 0x1c,
13959 JALS32 = 0x1d,
3a1f4268
YK
13960 BOVC = 0x1d,
13961 BEQC = 0x1d,
13962 BEQZALC = 0x1d,
3c824109 13963 ADDIUPC = 0x1e,
3a1f4268
YK
13964 PCREL = 0x1e,
13965 BNVC = 0x1f,
13966 BNEC = 0x1f,
13967 BNEZALC = 0x1f,
3c824109 13968
3a1f4268
YK
13969 R6_BEQZC = 0x20,
13970 JIC = 0x20,
3c824109
NF
13971 POOL16F = 0x21,
13972 SB16 = 0x22,
13973 BEQZ16 = 0x23,
3a1f4268 13974 BEQZC16 = 0x23,
3c824109
NF
13975 SLTI32 = 0x24,
13976 BEQ32 = 0x25,
3a1f4268 13977 BC = 0x25,
3c824109
NF
13978 SWC132 = 0x26,
13979 LWC132 = 0x27,
13980
3a1f4268 13981 /* 0x29 is reserved */
3c824109 13982 RES_29 = 0x29,
3a1f4268
YK
13983 R6_BNEZC = 0x28,
13984 JIALC = 0x28,
3c824109
NF
13985 SH16 = 0x2a,
13986 BNEZ16 = 0x2b,
3a1f4268 13987 BNEZC16 = 0x2b,
3c824109
NF
13988 SLTIU32 = 0x2c,
13989 BNE32 = 0x2d,
3a1f4268 13990 BALC = 0x2d,
3c824109
NF
13991 SDC132 = 0x2e,
13992 LDC132 = 0x2f,
13993
3a1f4268 13994 /* 0x31 is reserved */
3c824109 13995 RES_31 = 0x31,
3a1f4268
YK
13996 BLEZALC = 0x30,
13997 BGEZALC = 0x30,
13998 BGEUC = 0x30,
3c824109
NF
13999 SWSP16 = 0x32,
14000 B16 = 0x33,
3a1f4268 14001 BC16 = 0x33,
3c824109
NF
14002 ANDI32 = 0x34,
14003 J32 = 0x35,
3a1f4268
YK
14004 BGTZC = 0x35,
14005 BLTZC = 0x35,
14006 BLTC = 0x35,
211da992
CWR
14007 SD32 = 0x36, /* MIPS64 */
14008 LD32 = 0x37, /* MIPS64 */
3c824109 14009
3a1f4268 14010 /* 0x39 is reserved */
3c824109 14011 RES_39 = 0x39,
3a1f4268
YK
14012 BGTZALC = 0x38,
14013 BLTZALC = 0x38,
14014 BLTUC = 0x38,
3c824109
NF
14015 SW16 = 0x3a,
14016 LI16 = 0x3b,
14017 JALX32 = 0x3c,
14018 JAL32 = 0x3d,
3a1f4268
YK
14019 BLEZC = 0x3d,
14020 BGEZC = 0x3d,
14021 BGEC = 0x3d,
3c824109
NF
14022 SW32 = 0x3e,
14023 LW32 = 0x3f
14024};
14025
3a1f4268
YK
14026/* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14027enum {
14028 ADDIUPC_00 = 0x00,
c38a1d52
AR
14029 ADDIUPC_01 = 0x01,
14030 ADDIUPC_02 = 0x02,
14031 ADDIUPC_03 = 0x03,
14032 ADDIUPC_04 = 0x04,
14033 ADDIUPC_05 = 0x05,
14034 ADDIUPC_06 = 0x06,
3a1f4268
YK
14035 ADDIUPC_07 = 0x07,
14036 AUIPC = 0x1e,
14037 ALUIPC = 0x1f,
14038 LWPC_08 = 0x08,
c38a1d52
AR
14039 LWPC_09 = 0x09,
14040 LWPC_0A = 0x0A,
14041 LWPC_0B = 0x0B,
14042 LWPC_0C = 0x0C,
14043 LWPC_0D = 0x0D,
14044 LWPC_0E = 0x0E,
3a1f4268
YK
14045 LWPC_0F = 0x0F,
14046};
14047
3c824109
NF
14048/* POOL32A encoding of minor opcode field */
14049
14050enum {
14051 /* These opcodes are distinguished only by bits 9..6; those bits are
14052 * what are recorded below. */
14053 SLL32 = 0x0,
14054 SRL32 = 0x1,
14055 SRA = 0x2,
14056 ROTR = 0x3,
3a1f4268
YK
14057 SELEQZ = 0x5,
14058 SELNEZ = 0x6,
b00c7218 14059 R6_RDHWR = 0x7,
3c824109
NF
14060
14061 SLLV = 0x0,
14062 SRLV = 0x1,
14063 SRAV = 0x2,
14064 ROTRV = 0x3,
14065 ADD = 0x4,
14066 ADDU32 = 0x5,
14067 SUB = 0x6,
14068 SUBU32 = 0x7,
14069 MUL = 0x8,
14070 AND = 0x9,
14071 OR32 = 0xa,
14072 NOR = 0xb,
14073 XOR32 = 0xc,
14074 SLT = 0xd,
14075 SLTU = 0xe,
14076
14077 MOVN = 0x0,
3a1f4268 14078 R6_MUL = 0x0,
3c824109 14079 MOVZ = 0x1,
3a1f4268
YK
14080 MUH = 0x1,
14081 MULU = 0x2,
14082 MUHU = 0x3,
3c824109 14083 LWXS = 0x4,
3a1f4268
YK
14084 R6_DIV = 0x4,
14085 MOD = 0x5,
14086 R6_DIVU = 0x6,
14087 MODU = 0x7,
3c824109
NF
14088
14089 /* The following can be distinguished by their lower 6 bits. */
dbd8af98 14090 BREAK32 = 0x07,
3c824109 14091 INS = 0x0c,
3a1f4268
YK
14092 LSA = 0x0f,
14093 ALIGN = 0x1f,
3c824109 14094 EXT = 0x2c,
bb238210
YK
14095 POOL32AXF = 0x3c,
14096 SIGRIE = 0x3f
3c824109
NF
14097};
14098
14099/* POOL32AXF encoding of minor opcode field extension */
14100
d132c79f
CWR
14101/*
14102 * 1. MIPS Architecture for Programmers Volume II-B:
14103 * The microMIPS32 Instruction Set (Revision 3.05)
14104 *
14105 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14106 *
14107 * 2. MIPS Architecture for Programmers VolumeIV-e:
14108 * The MIPS DSP Application-Specific Extension
14109 * to the microMIPS32 Architecture (Revision 2.34)
14110 *
14111 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14112 */
14113
3c824109
NF
14114enum {
14115 /* bits 11..6 */
14116 TEQ = 0x00,
14117 TGE = 0x08,
14118 TGEU = 0x10,
14119 TLT = 0x20,
14120 TLTU = 0x28,
14121 TNE = 0x30,
14122
14123 MFC0 = 0x03,
14124 MTC0 = 0x0b,
14125
d132c79f
CWR
14126 /* begin of microMIPS32 DSP */
14127
3c824109
NF
14128 /* bits 13..12 for 0x01 */
14129 MFHI_ACC = 0x0,
14130 MFLO_ACC = 0x1,
14131 MTHI_ACC = 0x2,
14132 MTLO_ACC = 0x3,
14133
14134 /* bits 13..12 for 0x2a */
14135 MADD_ACC = 0x0,
14136 MADDU_ACC = 0x1,
14137 MSUB_ACC = 0x2,
14138 MSUBU_ACC = 0x3,
14139
14140 /* bits 13..12 for 0x32 */
14141 MULT_ACC = 0x0,
6801038b 14142 MULTU_ACC = 0x1,
3c824109 14143
d132c79f
CWR
14144 /* end of microMIPS32 DSP */
14145
3c824109 14146 /* bits 15..12 for 0x2c */
3a1f4268 14147 BITSWAP = 0x0,
3c824109
NF
14148 SEB = 0x2,
14149 SEH = 0x3,
14150 CLO = 0x4,
14151 CLZ = 0x5,
14152 RDHWR = 0x6,
14153 WSBH = 0x7,
14154 MULT = 0x8,
14155 MULTU = 0x9,
14156 DIV = 0xa,
14157 DIVU = 0xb,
14158 MADD = 0xc,
14159 MADDU = 0xd,
14160 MSUB = 0xe,
14161 MSUBU = 0xf,
14162
14163 /* bits 15..12 for 0x34 */
14164 MFC2 = 0x4,
14165 MTC2 = 0x5,
14166 MFHC2 = 0x8,
14167 MTHC2 = 0x9,
14168 CFC2 = 0xc,
14169 CTC2 = 0xd,
14170
14171 /* bits 15..12 for 0x3c */
14172 JALR = 0x0,
14173 JR = 0x0, /* alias */
3a1f4268
YK
14174 JALRC = 0x0,
14175 JRC = 0x0,
3c824109 14176 JALR_HB = 0x1,
3a1f4268 14177 JALRC_HB = 0x1,
3c824109
NF
14178 JALRS = 0x4,
14179 JALRS_HB = 0x5,
14180
14181 /* bits 15..12 for 0x05 */
14182 RDPGPR = 0xe,
14183 WRPGPR = 0xf,
14184
14185 /* bits 15..12 for 0x0d */
14186 TLBP = 0x0,
14187 TLBR = 0x1,
14188 TLBWI = 0x2,
14189 TLBWR = 0x3,
e60ec063
YK
14190 TLBINV = 0x4,
14191 TLBINVF = 0x5,
3c824109
NF
14192 WAIT = 0x9,
14193 IRET = 0xd,
14194 DERET = 0xe,
14195 ERET = 0xf,
14196
14197 /* bits 15..12 for 0x15 */
14198 DMT = 0x0,
14199 DVPE = 0x1,
14200 EMT = 0x2,
14201 EVPE = 0x3,
14202
14203 /* bits 15..12 for 0x1d */
14204 DI = 0x4,
14205 EI = 0x5,
14206
14207 /* bits 15..12 for 0x2d */
14208 SYNC = 0x6,
14209 SYSCALL = 0x8,
14210 SDBBP = 0xd,
14211
14212 /* bits 15..12 for 0x35 */
14213 MFHI32 = 0x0,
14214 MFLO32 = 0x1,
14215 MTHI32 = 0x2,
14216 MTLO32 = 0x3,
14217};
14218
14219/* POOL32B encoding of minor opcode field (bits 15..12) */
14220
14221enum {
14222 LWC2 = 0x0,
14223 LWP = 0x1,
14224 LDP = 0x4,
14225 LWM32 = 0x5,
14226 CACHE = 0x6,
14227 LDM = 0x7,
14228 SWC2 = 0x8,
14229 SWP = 0x9,
14230 SDP = 0xc,
14231 SWM32 = 0xd,
14232 SDM = 0xf
14233};
14234
14235/* POOL32C encoding of minor opcode field (bits 15..12) */
14236
14237enum {
14238 LWL = 0x0,
14239 SWL = 0x8,
14240 LWR = 0x1,
14241 SWR = 0x9,
14242 PREF = 0x2,
8fffc646 14243 ST_EVA = 0xa,
3c824109
NF
14244 LL = 0x3,
14245 SC = 0xb,
14246 LDL = 0x4,
14247 SDL = 0xc,
14248 LDR = 0x5,
14249 SDR = 0xd,
8fffc646 14250 LD_EVA = 0x6,
3c824109
NF
14251 LWU = 0xe,
14252 LLD = 0x7,
14253 SCD = 0xf
14254};
14255
8fffc646
JH
14256/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14257
14258enum {
14259 LBUE = 0x0,
14260 LHUE = 0x1,
14261 LWLE = 0x2,
14262 LWRE = 0x3,
14263 LBE = 0x4,
14264 LHE = 0x5,
14265 LLE = 0x6,
14266 LWE = 0x7,
14267};
14268
14269/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14270
14271enum {
14272 SWLE = 0x0,
14273 SWRE = 0x1,
14274 PREFE = 0x2,
14275 CACHEE = 0x3,
14276 SBE = 0x4,
14277 SHE = 0x5,
14278 SCE = 0x6,
14279 SWE = 0x7,
14280};
14281
3c824109
NF
14282/* POOL32F encoding of minor opcode field (bits 5..0) */
14283
14284enum {
14285 /* These are the bit 7..6 values */
14286 ADD_FMT = 0x0,
3c824109
NF
14287
14288 SUB_FMT = 0x1,
3c824109
NF
14289
14290 MUL_FMT = 0x2,
14291
14292 DIV_FMT = 0x3,
14293
14294 /* These are the bit 8..6 values */
3a1f4268 14295 MOVN_FMT = 0x0,
3c824109
NF
14296 RSQRT2_FMT = 0x0,
14297 MOVF_FMT = 0x0,
3a1f4268
YK
14298 RINT_FMT = 0x0,
14299 SELNEZ_FMT = 0x0,
3c824109 14300
3a1f4268 14301 MOVZ_FMT = 0x1,
3c824109
NF
14302 LWXC1 = 0x1,
14303 MOVT_FMT = 0x1,
3a1f4268
YK
14304 CLASS_FMT = 0x1,
14305 SELEQZ_FMT = 0x1,
3c824109
NF
14306
14307 PLL_PS = 0x2,
14308 SWXC1 = 0x2,
3a1f4268 14309 SEL_FMT = 0x2,
3c824109
NF
14310
14311 PLU_PS = 0x3,
14312 LDXC1 = 0x3,
14313
3a1f4268 14314 MOVN_FMT_04 = 0x4,
3c824109
NF
14315 PUL_PS = 0x4,
14316 SDXC1 = 0x4,
14317 RECIP2_FMT = 0x4,
14318
3a1f4268 14319 MOVZ_FMT_05 = 0x05,
3c824109
NF
14320 PUU_PS = 0x5,
14321 LUXC1 = 0x5,
14322
14323 CVT_PS_S = 0x6,
14324 SUXC1 = 0x6,
14325 ADDR_PS = 0x6,
14326 PREFX = 0x6,
3a1f4268 14327 MADDF_FMT = 0x6,
3c824109
NF
14328
14329 MULR_PS = 0x7,
3a1f4268 14330 MSUBF_FMT = 0x7,
3c824109
NF
14331
14332 MADD_S = 0x01,
14333 MADD_D = 0x09,
14334 MADD_PS = 0x11,
14335 ALNV_PS = 0x19,
14336 MSUB_S = 0x21,
14337 MSUB_D = 0x29,
14338 MSUB_PS = 0x31,
14339
14340 NMADD_S = 0x02,
14341 NMADD_D = 0x0a,
14342 NMADD_PS = 0x12,
14343 NMSUB_S = 0x22,
14344 NMSUB_D = 0x2a,
14345 NMSUB_PS = 0x32,
14346
3a1f4268
YK
14347 MIN_FMT = 0x3,
14348 MAX_FMT = 0xb,
14349 MINA_FMT = 0x23,
14350 MAXA_FMT = 0x2b,
3c824109
NF
14351 POOL32FXF = 0x3b,
14352
14353 CABS_COND_FMT = 0x1c, /* MIPS3D */
3a1f4268
YK
14354 C_COND_FMT = 0x3c,
14355
14356 CMP_CONDN_S = 0x5,
14357 CMP_CONDN_D = 0x15
3c824109
NF
14358};
14359
14360/* POOL32Fxf encoding of minor opcode extension field */
14361
14362enum {
14363 CVT_L = 0x04,
14364 RSQRT_FMT = 0x08,
14365 FLOOR_L = 0x0c,
14366 CVT_PW_PS = 0x1c,
14367 CVT_W = 0x24,
14368 SQRT_FMT = 0x28,
14369 FLOOR_W = 0x2c,
14370 CVT_PS_PW = 0x3c,
14371 CFC1 = 0x40,
14372 RECIP_FMT = 0x48,
14373 CEIL_L = 0x4c,
14374 CTC1 = 0x60,
14375 CEIL_W = 0x6c,
14376 MFC1 = 0x80,
14377 CVT_S_PL = 0x84,
14378 TRUNC_L = 0x8c,
14379 MTC1 = 0xa0,
14380 CVT_S_PU = 0xa4,
14381 TRUNC_W = 0xac,
14382 MFHC1 = 0xc0,
14383 ROUND_L = 0xcc,
14384 MTHC1 = 0xe0,
14385 ROUND_W = 0xec,
14386
14387 MOV_FMT = 0x01,
14388 MOVF = 0x05,
14389 ABS_FMT = 0x0d,
14390 RSQRT1_FMT = 0x1d,
14391 MOVT = 0x25,
14392 NEG_FMT = 0x2d,
14393 CVT_D = 0x4d,
14394 RECIP1_FMT = 0x5d,
14395 CVT_S = 0x6d
14396};
14397
14398/* POOL32I encoding of minor opcode field (bits 25..21) */
14399
14400enum {
14401 BLTZ = 0x00,
14402 BLTZAL = 0x01,
14403 BGEZ = 0x02,
14404 BGEZAL = 0x03,
14405 BLEZ = 0x04,
14406 BNEZC = 0x05,
14407 BGTZ = 0x06,
14408 BEQZC = 0x07,
14409 TLTI = 0x08,
3a1f4268 14410 BC1EQZC = 0x08,
3c824109 14411 TGEI = 0x09,
3a1f4268 14412 BC1NEZC = 0x09,
3c824109 14413 TLTIU = 0x0a,
3a1f4268 14414 BC2EQZC = 0x0a,
3c824109 14415 TGEIU = 0x0b,
3a1f4268 14416 BC2NEZC = 0x0a,
3c824109 14417 TNEI = 0x0c,
3a1f4268 14418 R6_SYNCI = 0x0c,
3c824109
NF
14419 LUI = 0x0d,
14420 TEQI = 0x0e,
14421 SYNCI = 0x10,
14422 BLTZALS = 0x11,
14423 BGEZALS = 0x13,
14424 BC2F = 0x14,
14425 BC2T = 0x15,
14426 BPOSGE64 = 0x1a,
14427 BPOSGE32 = 0x1b,
14428 /* These overlap and are distinguished by bit16 of the instruction */
14429 BC1F = 0x1c,
14430 BC1T = 0x1d,
14431 BC1ANY2F = 0x1c,
14432 BC1ANY2T = 0x1d,
14433 BC1ANY4F = 0x1e,
14434 BC1ANY4T = 0x1f
14435};
14436
14437/* POOL16A encoding of minor opcode field */
14438
14439enum {
14440 ADDU16 = 0x0,
14441 SUBU16 = 0x1
14442};
14443
14444/* POOL16B encoding of minor opcode field */
14445
14446enum {
14447 SLL16 = 0x0,
14448 SRL16 = 0x1
14449};
14450
14451/* POOL16C encoding of minor opcode field */
14452
14453enum {
14454 NOT16 = 0x00,
14455 XOR16 = 0x04,
14456 AND16 = 0x08,
14457 OR16 = 0x0c,
14458 LWM16 = 0x10,
14459 SWM16 = 0x14,
14460 JR16 = 0x18,
14461 JRC16 = 0x1a,
14462 JALR16 = 0x1c,
14463 JALR16S = 0x1e,
14464 MFHI16 = 0x20,
14465 MFLO16 = 0x24,
14466 BREAK16 = 0x28,
14467 SDBBP16 = 0x2c,
14468 JRADDIUSP = 0x30
14469};
14470
3a1f4268
YK
14471/* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14472
14473enum {
14474 R6_NOT16 = 0x00,
14475 R6_AND16 = 0x01,
14476 R6_LWM16 = 0x02,
14477 R6_JRC16 = 0x03,
14478 MOVEP = 0x04,
c38a1d52
AR
14479 MOVEP_05 = 0x05,
14480 MOVEP_06 = 0x06,
3a1f4268
YK
14481 MOVEP_07 = 0x07,
14482 R6_XOR16 = 0x08,
14483 R6_OR16 = 0x09,
14484 R6_SWM16 = 0x0a,
14485 JALRC16 = 0x0b,
14486 MOVEP_0C = 0x0c,
c38a1d52
AR
14487 MOVEP_0D = 0x0d,
14488 MOVEP_0E = 0x0e,
3a1f4268
YK
14489 MOVEP_0F = 0x0f,
14490 JRCADDIUSP = 0x13,
14491 R6_BREAK16 = 0x1b,
14492 R6_SDBBP16 = 0x3b
14493};
14494
3c824109
NF
14495/* POOL16D encoding of minor opcode field */
14496
14497enum {
14498 ADDIUS5 = 0x0,
14499 ADDIUSP = 0x1
14500};
14501
14502/* POOL16E encoding of minor opcode field */
14503
14504enum {
14505 ADDIUR2 = 0x0,
14506 ADDIUR1SP = 0x1
14507};
14508
14509static int mmreg (int r)
14510{
14511 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14512
14513 return map[r];
14514}
14515
14516/* Used for 16-bit store instructions. */
14517static int mmreg2 (int r)
14518{
14519 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14520
14521 return map[r];
14522}
14523
14524#define uMIPS_RD(op) ((op >> 7) & 0x7)
14525#define uMIPS_RS(op) ((op >> 4) & 0x7)
14526#define uMIPS_RS2(op) uMIPS_RS(op)
14527#define uMIPS_RS1(op) ((op >> 1) & 0x7)
14528#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14529#define uMIPS_RS5(op) (op & 0x1f)
14530
14531/* Signed immediate */
14532#define SIMM(op, start, width) \
14533 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14534 << (32-width)) \
14535 >> (32-width))
14536/* Zero-extended immediate */
14537#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14538
d75c135e 14539static void gen_addiur1sp(DisasContext *ctx)
3c824109
NF
14540{
14541 int rd = mmreg(uMIPS_RD(ctx->opcode));
14542
d75c135e 14543 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
3c824109
NF
14544}
14545
d75c135e 14546static void gen_addiur2(DisasContext *ctx)
3c824109
NF
14547{
14548 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14549 int rd = mmreg(uMIPS_RD(ctx->opcode));
14550 int rs = mmreg(uMIPS_RS(ctx->opcode));
14551
d75c135e 14552 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
3c824109
NF
14553}
14554
d75c135e 14555static void gen_addiusp(DisasContext *ctx)
3c824109
NF
14556{
14557 int encoded = ZIMM(ctx->opcode, 1, 9);
14558 int decoded;
14559
14560 if (encoded <= 1) {
14561 decoded = 256 + encoded;
14562 } else if (encoded <= 255) {
14563 decoded = encoded;
14564 } else if (encoded <= 509) {
14565 decoded = encoded - 512;
14566 } else {
14567 decoded = encoded - 768;
14568 }
14569
d75c135e 14570 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
3c824109
NF
14571}
14572
d75c135e 14573static void gen_addius5(DisasContext *ctx)
3c824109
NF
14574{
14575 int imm = SIMM(ctx->opcode, 1, 4);
14576 int rd = (ctx->opcode >> 5) & 0x1f;
14577
d75c135e 14578 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
3c824109
NF
14579}
14580
d75c135e 14581static void gen_andi16(DisasContext *ctx)
3c824109
NF
14582{
14583 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14584 31, 32, 63, 64, 255, 32768, 65535 };
14585 int rd = mmreg(uMIPS_RD(ctx->opcode));
14586 int rs = mmreg(uMIPS_RS(ctx->opcode));
14587 int encoded = ZIMM(ctx->opcode, 0, 4);
14588
d75c135e 14589 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
14590}
14591
14592static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14593 int base, int16_t offset)
14594{
14595 TCGv t0, t1;
14596 TCGv_i32 t2;
14597
14598 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 14599 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
14600 return;
14601 }
14602
14603 t0 = tcg_temp_new();
14604
14605 gen_base_offset_addr(ctx, t0, base, offset);
14606
14607 t1 = tcg_const_tl(reglist);
14608 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 14609
3c824109
NF
14610 save_cpu_state(ctx, 1);
14611 switch (opc) {
14612 case LWM32:
895c2d04 14613 gen_helper_lwm(cpu_env, t0, t1, t2);
3c824109
NF
14614 break;
14615 case SWM32:
895c2d04 14616 gen_helper_swm(cpu_env, t0, t1, t2);
3c824109
NF
14617 break;
14618#ifdef TARGET_MIPS64
14619 case LDM:
895c2d04 14620 gen_helper_ldm(cpu_env, t0, t1, t2);
3c824109
NF
14621 break;
14622 case SDM:
895c2d04 14623 gen_helper_sdm(cpu_env, t0, t1, t2);
3c824109 14624 break;
6af0bf9c 14625#endif
3c824109 14626 }
3c824109 14627 tcg_temp_free(t0);
33087598 14628 tcg_temp_free(t1);
3c824109
NF
14629 tcg_temp_free_i32(t2);
14630}
6af0bf9c 14631
3c824109 14632
240ce26a 14633static void gen_pool16c_insn(DisasContext *ctx)
6af0bf9c 14634{
3c824109
NF
14635 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14636 int rs = mmreg(ctx->opcode & 0x7);
6af0bf9c 14637
3c824109
NF
14638 switch (((ctx->opcode) >> 4) & 0x3f) {
14639 case NOT16 + 0:
14640 case NOT16 + 1:
14641 case NOT16 + 2:
14642 case NOT16 + 3:
d75c135e 14643 gen_logic(ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
14644 break;
14645 case XOR16 + 0:
14646 case XOR16 + 1:
14647 case XOR16 + 2:
14648 case XOR16 + 3:
d75c135e 14649 gen_logic(ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
14650 break;
14651 case AND16 + 0:
14652 case AND16 + 1:
14653 case AND16 + 2:
14654 case AND16 + 3:
d75c135e 14655 gen_logic(ctx, OPC_AND, rd, rd, rs);
3c824109
NF
14656 break;
14657 case OR16 + 0:
14658 case OR16 + 1:
14659 case OR16 + 2:
14660 case OR16 + 3:
d75c135e 14661 gen_logic(ctx, OPC_OR, rd, rd, rs);
3c824109
NF
14662 break;
14663 case LWM16 + 0:
14664 case LWM16 + 1:
14665 case LWM16 + 2:
14666 case LWM16 + 3:
14667 {
14668 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14669 int offset = ZIMM(ctx->opcode, 0, 4);
14670
14671 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14672 29, offset << 2);
14673 }
14674 break;
14675 case SWM16 + 0:
14676 case SWM16 + 1:
14677 case SWM16 + 2:
14678 case SWM16 + 3:
14679 {
14680 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14681 int offset = ZIMM(ctx->opcode, 0, 4);
14682
14683 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14684 29, offset << 2);
14685 }
14686 break;
14687 case JR16 + 0:
14688 case JR16 + 1:
14689 {
14690 int reg = ctx->opcode & 0x1f;
14691
b231c103 14692 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
3c824109 14693 }
3c824109
NF
14694 break;
14695 case JRC16 + 0:
14696 case JRC16 + 1:
14697 {
14698 int reg = ctx->opcode & 0x1f;
b231c103 14699 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
3c824109
NF
14700 /* Let normal delay slot handling in our caller take us
14701 to the branch target. */
14702 }
14703 break;
14704 case JALR16 + 0:
14705 case JALR16 + 1:
b231c103
YK
14706 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14707 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14708 break;
3c824109
NF
14709 case JALR16S + 0:
14710 case JALR16S + 1:
b231c103
YK
14711 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14712 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
14713 break;
14714 case MFHI16 + 0:
14715 case MFHI16 + 1:
26135ead 14716 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
14717 break;
14718 case MFLO16 + 0:
14719 case MFLO16 + 1:
26135ead 14720 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
14721 break;
14722 case BREAK16:
9c708c7f 14723 generate_exception_end(ctx, EXCP_BREAK);
3c824109
NF
14724 break;
14725 case SDBBP16:
3b3c1694
LA
14726 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14727 gen_helper_do_semihosting(cpu_env);
14728 } else {
14729 /* XXX: not clear which exception should be raised
14730 * when in debug mode...
14731 */
14732 check_insn(ctx, ISA_MIPS32);
9c708c7f 14733 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 14734 }
3c824109
NF
14735 break;
14736 case JRADDIUSP + 0:
14737 case JRADDIUSP + 1:
14738 {
14739 int imm = ZIMM(ctx->opcode, 0, 5);
b231c103 14740 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
d75c135e 14741 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
3c824109
NF
14742 /* Let normal delay slot handling in our caller take us
14743 to the branch target. */
14744 }
14745 break;
14746 default:
9c708c7f 14747 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
14748 break;
14749 }
14750}
14751
ed7ce6c0
YK
14752static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14753 int enc_rs)
14754{
14755 int rd, rs, re, rt;
14756 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14757 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14758 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14759 rd = rd_enc[enc_dest];
14760 re = re_enc[enc_dest];
14761 rs = rs_rt_enc[enc_rs];
14762 rt = rs_rt_enc[enc_rt];
14763 if (rs) {
14764 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
14765 } else {
14766 tcg_gen_movi_tl(cpu_gpr[rd], 0);
14767 }
14768 if (rt) {
14769 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
14770 } else {
14771 tcg_gen_movi_tl(cpu_gpr[re], 0);
14772 }
14773}
14774
14775static void gen_pool16c_r6_insn(DisasContext *ctx)
14776{
14777 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14778 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14779
14780 switch (ctx->opcode & 0xf) {
14781 case R6_NOT16:
14782 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14783 break;
14784 case R6_AND16:
14785 gen_logic(ctx, OPC_AND, rt, rt, rs);
14786 break;
14787 case R6_LWM16:
14788 {
14789 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14790 int offset = extract32(ctx->opcode, 4, 4);
14791 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14792 }
14793 break;
14794 case R6_JRC16: /* JRCADDIUSP */
14795 if ((ctx->opcode >> 4) & 1) {
14796 /* JRCADDIUSP */
14797 int imm = extract32(ctx->opcode, 5, 5);
14798 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14799 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14800 } else {
14801 /* JRC16 */
e1555d7d 14802 rs = extract32(ctx->opcode, 5, 5);
ed7ce6c0
YK
14803 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14804 }
14805 break;
c38a1d52
AR
14806 case MOVEP:
14807 case MOVEP_05:
14808 case MOVEP_06:
14809 case MOVEP_07:
14810 case MOVEP_0C:
14811 case MOVEP_0D:
14812 case MOVEP_0E:
14813 case MOVEP_0F:
ed7ce6c0
YK
14814 {
14815 int enc_dest = uMIPS_RD(ctx->opcode);
14816 int enc_rt = uMIPS_RS2(ctx->opcode);
14817 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14818 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14819 }
14820 break;
14821 case R6_XOR16:
14822 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14823 break;
14824 case R6_OR16:
14825 gen_logic(ctx, OPC_OR, rt, rt, rs);
14826 break;
14827 case R6_SWM16:
14828 {
14829 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14830 int offset = extract32(ctx->opcode, 4, 4);
14831 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14832 }
14833 break;
14834 case JALRC16: /* BREAK16, SDBBP16 */
14835 switch (ctx->opcode & 0x3f) {
14836 case JALRC16:
14837 case JALRC16 + 0x20:
14838 /* JALRC16 */
14839 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14840 31, 0, 0);
14841 break;
14842 case R6_BREAK16:
14843 /* BREAK16 */
14844 generate_exception(ctx, EXCP_BREAK);
14845 break;
14846 case R6_SDBBP16:
14847 /* SDBBP16 */
060ebfef
LA
14848 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14849 gen_helper_do_semihosting(cpu_env);
ed7ce6c0 14850 } else {
060ebfef
LA
14851 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14852 generate_exception(ctx, EXCP_RI);
14853 } else {
14854 generate_exception(ctx, EXCP_DBp);
14855 }
ed7ce6c0
YK
14856 }
14857 break;
14858 }
14859 break;
14860 default:
14861 generate_exception(ctx, EXCP_RI);
14862 break;
14863 }
14864}
14865
3c824109
NF
14866static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
14867{
14868 TCGv t0 = tcg_temp_new();
14869 TCGv t1 = tcg_temp_new();
14870
14871 gen_load_gpr(t0, base);
14872
14873 if (index != 0) {
14874 gen_load_gpr(t1, index);
14875 tcg_gen_shli_tl(t1, t1, 2);
14876 gen_op_addr_add(ctx, t0, t1, t0);
14877 }
14878
5f68f5ae 14879 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
14880 gen_store_gpr(t1, rd);
14881
14882 tcg_temp_free(t0);
14883 tcg_temp_free(t1);
14884}
14885
14886static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
14887 int base, int16_t offset)
14888{
3c824109
NF
14889 TCGv t0, t1;
14890
36c6711b 14891 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
9c708c7f 14892 generate_exception_end(ctx, EXCP_RI);
d796321b
FB
14893 return;
14894 }
14895
3c824109
NF
14896 t0 = tcg_temp_new();
14897 t1 = tcg_temp_new();
8e9ade68 14898
3c824109
NF
14899 gen_base_offset_addr(ctx, t0, base, offset);
14900
14901 switch (opc) {
14902 case LWP:
36c6711b 14903 if (rd == base) {
9c708c7f 14904 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
14905 return;
14906 }
5f68f5ae 14907 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
14908 gen_store_gpr(t1, rd);
14909 tcg_gen_movi_tl(t1, 4);
14910 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 14911 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109 14912 gen_store_gpr(t1, rd+1);
3c824109
NF
14913 break;
14914 case SWP:
3c824109 14915 gen_load_gpr(t1, rd);
5f68f5ae 14916 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
14917 tcg_gen_movi_tl(t1, 4);
14918 gen_op_addr_add(ctx, t0, t0, t1);
14919 gen_load_gpr(t1, rd+1);
5f68f5ae 14920 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
14921 break;
14922#ifdef TARGET_MIPS64
14923 case LDP:
36c6711b 14924 if (rd == base) {
9c708c7f 14925 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
14926 return;
14927 }
5f68f5ae 14928 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
14929 gen_store_gpr(t1, rd);
14930 tcg_gen_movi_tl(t1, 8);
14931 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 14932 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109 14933 gen_store_gpr(t1, rd+1);
3c824109
NF
14934 break;
14935 case SDP:
3c824109 14936 gen_load_gpr(t1, rd);
5f68f5ae 14937 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
14938 tcg_gen_movi_tl(t1, 8);
14939 gen_op_addr_add(ctx, t0, t0, t1);
14940 gen_load_gpr(t1, rd+1);
5f68f5ae 14941 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
14942 break;
14943#endif
6af0bf9c 14944 }
3c824109
NF
14945 tcg_temp_free(t0);
14946 tcg_temp_free(t1);
14947}
618b0fe9 14948
d208ac0c
LA
14949static void gen_sync(int stype)
14950{
14951 TCGBar tcg_mo = TCG_BAR_SC;
14952
14953 switch (stype) {
14954 case 0x4: /* SYNC_WMB */
14955 tcg_mo |= TCG_MO_ST_ST;
14956 break;
14957 case 0x10: /* SYNC_MB */
14958 tcg_mo |= TCG_MO_ALL;
14959 break;
14960 case 0x11: /* SYNC_ACQUIRE */
14961 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14962 break;
14963 case 0x12: /* SYNC_RELEASE */
14964 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14965 break;
14966 case 0x13: /* SYNC_RMB */
14967 tcg_mo |= TCG_MO_LD_LD;
14968 break;
14969 default:
14970 tcg_mo |= TCG_MO_ALL;
14971 break;
14972 }
14973
14974 tcg_gen_mb(tcg_mo);
14975}
14976
240ce26a 14977static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
14978{
14979 int extension = (ctx->opcode >> 6) & 0x3f;
14980 int minor = (ctx->opcode >> 12) & 0xf;
14981 uint32_t mips32_op;
14982
14983 switch (extension) {
14984 case TEQ:
14985 mips32_op = OPC_TEQ;
14986 goto do_trap;
14987 case TGE:
14988 mips32_op = OPC_TGE;
14989 goto do_trap;
14990 case TGEU:
14991 mips32_op = OPC_TGEU;
14992 goto do_trap;
14993 case TLT:
14994 mips32_op = OPC_TLT;
14995 goto do_trap;
14996 case TLTU:
14997 mips32_op = OPC_TLTU;
14998 goto do_trap;
14999 case TNE:
15000 mips32_op = OPC_TNE;
15001 do_trap:
15002 gen_trap(ctx, mips32_op, rs, rt, -1);
15003 break;
15004#ifndef CONFIG_USER_ONLY
15005 case MFC0:
15006 case MFC0 + 32:
2e15497c 15007 check_cp0_enabled(ctx);
3c824109
NF
15008 if (rt == 0) {
15009 /* Treat as NOP. */
15010 break;
15011 }
d75c135e 15012 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
15013 break;
15014 case MTC0:
15015 case MTC0 + 32:
2e15497c 15016 check_cp0_enabled(ctx);
3c824109
NF
15017 {
15018 TCGv t0 = tcg_temp_new();
618b0fe9 15019
3c824109 15020 gen_load_gpr(t0, rt);
d75c135e 15021 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
15022 tcg_temp_free(t0);
15023 }
15024 break;
15025#endif
a1fc6246
LA
15026 case 0x2a:
15027 switch (minor & 3) {
15028 case MADD_ACC:
15029 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15030 break;
15031 case MADDU_ACC:
15032 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15033 break;
15034 case MSUB_ACC:
15035 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15036 break;
15037 case MSUBU_ACC:
15038 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15039 break;
15040 default:
15041 goto pool32axf_invalid;
15042 }
15043 break;
15044 case 0x32:
15045 switch (minor & 3) {
15046 case MULT_ACC:
15047 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15048 break;
15049 case MULTU_ACC:
15050 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15051 break;
15052 default:
15053 goto pool32axf_invalid;
15054 }
15055 break;
3c824109
NF
15056 case 0x2c:
15057 switch (minor) {
e0332095
YK
15058 case BITSWAP:
15059 check_insn(ctx, ISA_MIPS32R6);
15060 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15061 break;
3c824109
NF
15062 case SEB:
15063 gen_bshfl(ctx, OPC_SEB, rs, rt);
15064 break;
15065 case SEH:
15066 gen_bshfl(ctx, OPC_SEH, rs, rt);
15067 break;
15068 case CLO:
15069 mips32_op = OPC_CLO;
15070 goto do_cl;
15071 case CLZ:
15072 mips32_op = OPC_CLZ;
15073 do_cl:
d75c135e 15074 check_insn(ctx, ISA_MIPS32);
3c824109
NF
15075 gen_cl(ctx, mips32_op, rt, rs);
15076 break;
15077 case RDHWR:
b00c7218
YK
15078 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15079 gen_rdhwr(ctx, rt, rs, 0);
3c824109
NF
15080 break;
15081 case WSBH:
15082 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15083 break;
15084 case MULT:
9e8f441a 15085 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15086 mips32_op = OPC_MULT;
26135ead 15087 goto do_mul;
3c824109 15088 case MULTU:
9e8f441a 15089 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15090 mips32_op = OPC_MULTU;
26135ead 15091 goto do_mul;
3c824109 15092 case DIV:
9e8f441a 15093 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15094 mips32_op = OPC_DIV;
26135ead 15095 goto do_div;
3c824109 15096 case DIVU:
9e8f441a 15097 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15098 mips32_op = OPC_DIVU;
26135ead
RS
15099 goto do_div;
15100 do_div:
15101 check_insn(ctx, ISA_MIPS32);
15102 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15103 break;
3c824109 15104 case MADD:
9e8f441a 15105 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15106 mips32_op = OPC_MADD;
26135ead 15107 goto do_mul;
3c824109 15108 case MADDU:
9e8f441a 15109 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15110 mips32_op = OPC_MADDU;
26135ead 15111 goto do_mul;
3c824109 15112 case MSUB:
9e8f441a 15113 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15114 mips32_op = OPC_MSUB;
26135ead 15115 goto do_mul;
3c824109 15116 case MSUBU:
9e8f441a 15117 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15118 mips32_op = OPC_MSUBU;
26135ead 15119 do_mul:
d75c135e 15120 check_insn(ctx, ISA_MIPS32);
a1fc6246 15121 gen_muldiv(ctx, mips32_op, 0, rs, rt);
3c824109
NF
15122 break;
15123 default:
15124 goto pool32axf_invalid;
15125 }
15126 break;
15127 case 0x34:
15128 switch (minor) {
15129 case MFC2:
15130 case MTC2:
15131 case MFHC2:
15132 case MTHC2:
15133 case CFC2:
15134 case CTC2:
15135 generate_exception_err(ctx, EXCP_CpU, 2);
15136 break;
15137 default:
15138 goto pool32axf_invalid;
15139 }
15140 break;
15141 case 0x3c:
15142 switch (minor) {
65935f07
YK
15143 case JALR: /* JALRC */
15144 case JALR_HB: /* JALRC_HB */
15145 if (ctx->insn_flags & ISA_MIPS32R6) {
15146 /* JALRC, JALRC_HB */
15147 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15148 } else {
15149 /* JALR, JALR_HB */
15150 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15151 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15152 }
3c824109
NF
15153 break;
15154 case JALRS:
15155 case JALRS_HB:
9e8f441a 15156 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15157 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15158 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
15159 break;
15160 default:
15161 goto pool32axf_invalid;
15162 }
15163 break;
15164 case 0x05:
15165 switch (minor) {
15166 case RDPGPR:
2e15497c 15167 check_cp0_enabled(ctx);
d75c135e 15168 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 15169 gen_load_srsgpr(rs, rt);
3c824109
NF
15170 break;
15171 case WRPGPR:
2e15497c 15172 check_cp0_enabled(ctx);
d75c135e 15173 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 15174 gen_store_srsgpr(rs, rt);
3c824109
NF
15175 break;
15176 default:
15177 goto pool32axf_invalid;
15178 }
15179 break;
15180#ifndef CONFIG_USER_ONLY
15181 case 0x0d:
15182 switch (minor) {
15183 case TLBP:
15184 mips32_op = OPC_TLBP;
15185 goto do_cp0;
15186 case TLBR:
15187 mips32_op = OPC_TLBR;
15188 goto do_cp0;
15189 case TLBWI:
15190 mips32_op = OPC_TLBWI;
15191 goto do_cp0;
15192 case TLBWR:
15193 mips32_op = OPC_TLBWR;
15194 goto do_cp0;
e60ec063
YK
15195 case TLBINV:
15196 mips32_op = OPC_TLBINV;
15197 goto do_cp0;
15198 case TLBINVF:
15199 mips32_op = OPC_TLBINVF;
15200 goto do_cp0;
3c824109
NF
15201 case WAIT:
15202 mips32_op = OPC_WAIT;
15203 goto do_cp0;
15204 case DERET:
15205 mips32_op = OPC_DERET;
15206 goto do_cp0;
15207 case ERET:
15208 mips32_op = OPC_ERET;
15209 do_cp0:
15210 gen_cp0(env, ctx, mips32_op, rt, rs);
15211 break;
15212 default:
15213 goto pool32axf_invalid;
15214 }
15215 break;
15216 case 0x1d:
15217 switch (minor) {
15218 case DI:
2e15497c 15219 check_cp0_enabled(ctx);
3c824109
NF
15220 {
15221 TCGv t0 = tcg_temp_new();
15222
15223 save_cpu_state(ctx, 1);
895c2d04 15224 gen_helper_di(t0, cpu_env);
3c824109
NF
15225 gen_store_gpr(t0, rs);
15226 /* Stop translation as we may have switched the execution mode */
eeb3bba8 15227 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
15228 tcg_temp_free(t0);
15229 }
15230 break;
15231 case EI:
2e15497c 15232 check_cp0_enabled(ctx);
3c824109
NF
15233 {
15234 TCGv t0 = tcg_temp_new();
15235
15236 save_cpu_state(ctx, 1);
895c2d04 15237 gen_helper_ei(t0, cpu_env);
3c824109 15238 gen_store_gpr(t0, rs);
b28425ba 15239 /* DISAS_STOP isn't sufficient, we need to ensure we break out
b74cddcb 15240 of translated code to check for pending interrupts. */
eeb3bba8
EC
15241 gen_save_pc(ctx->base.pc_next + 4);
15242 ctx->base.is_jmp = DISAS_EXIT;
3c824109
NF
15243 tcg_temp_free(t0);
15244 }
15245 break;
15246 default:
15247 goto pool32axf_invalid;
15248 }
15249 break;
15250#endif
15251 case 0x2d:
15252 switch (minor) {
15253 case SYNC:
d208ac0c 15254 gen_sync(extract32(ctx->opcode, 16, 5));
3c824109
NF
15255 break;
15256 case SYSCALL:
9c708c7f 15257 generate_exception_end(ctx, EXCP_SYSCALL);
3c824109
NF
15258 break;
15259 case SDBBP:
3b3c1694
LA
15260 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15261 gen_helper_do_semihosting(cpu_env);
15262 } else {
15263 check_insn(ctx, ISA_MIPS32);
e0332095 15264 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 15265 generate_exception_end(ctx, EXCP_RI);
e0332095 15266 } else {
9c708c7f 15267 generate_exception_end(ctx, EXCP_DBp);
e0332095 15268 }
3b3c1694 15269 }
3c824109
NF
15270 break;
15271 default:
15272 goto pool32axf_invalid;
15273 }
15274 break;
a1fc6246 15275 case 0x01:
26135ead 15276 switch (minor & 3) {
a1fc6246 15277 case MFHI_ACC:
26135ead 15278 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
3c824109 15279 break;
a1fc6246 15280 case MFLO_ACC:
26135ead 15281 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
3c824109 15282 break;
a1fc6246 15283 case MTHI_ACC:
26135ead 15284 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
3c824109 15285 break;
a1fc6246 15286 case MTLO_ACC:
26135ead 15287 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
3c824109
NF
15288 break;
15289 default:
15290 goto pool32axf_invalid;
15291 }
15292 break;
a1fc6246 15293 case 0x35:
9e8f441a 15294 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a1fc6246
LA
15295 switch (minor) {
15296 case MFHI32:
15297 gen_HILO(ctx, OPC_MFHI, 0, rs);
15298 break;
15299 case MFLO32:
15300 gen_HILO(ctx, OPC_MFLO, 0, rs);
15301 break;
15302 case MTHI32:
15303 gen_HILO(ctx, OPC_MTHI, 0, rs);
15304 break;
15305 case MTLO32:
15306 gen_HILO(ctx, OPC_MTLO, 0, rs);
15307 break;
15308 default:
15309 goto pool32axf_invalid;
15310 }
15311 break;
3c824109
NF
15312 default:
15313 pool32axf_invalid:
15314 MIPS_INVAL("pool32axf");
9c708c7f 15315 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15316 break;
15317 }
15318}
15319
15320/* Values for microMIPS fmt field. Variable-width, depending on which
15321 formats the instruction supports. */
15322
15323enum {
15324 FMT_SD_S = 0,
15325 FMT_SD_D = 1,
15326
15327 FMT_SDPS_S = 0,
15328 FMT_SDPS_D = 1,
15329 FMT_SDPS_PS = 2,
15330
15331 FMT_SWL_S = 0,
15332 FMT_SWL_W = 1,
15333 FMT_SWL_L = 2,
15334
15335 FMT_DWL_D = 0,
15336 FMT_DWL_W = 1,
15337 FMT_DWL_L = 2
15338};
15339
d75c135e 15340static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
3c824109
NF
15341{
15342 int extension = (ctx->opcode >> 6) & 0x3ff;
15343 uint32_t mips32_op;
15344
15345#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
15346#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
15347#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
15348
15349 switch (extension) {
15350 case FLOAT_1BIT_FMT(CFC1, 0):
15351 mips32_op = OPC_CFC1;
15352 goto do_cp1;
15353 case FLOAT_1BIT_FMT(CTC1, 0):
15354 mips32_op = OPC_CTC1;
15355 goto do_cp1;
15356 case FLOAT_1BIT_FMT(MFC1, 0):
15357 mips32_op = OPC_MFC1;
15358 goto do_cp1;
15359 case FLOAT_1BIT_FMT(MTC1, 0):
15360 mips32_op = OPC_MTC1;
15361 goto do_cp1;
15362 case FLOAT_1BIT_FMT(MFHC1, 0):
15363 mips32_op = OPC_MFHC1;
15364 goto do_cp1;
15365 case FLOAT_1BIT_FMT(MTHC1, 0):
15366 mips32_op = OPC_MTHC1;
15367 do_cp1:
15368 gen_cp1(ctx, mips32_op, rt, rs);
15369 break;
15370
15371 /* Reciprocal square root */
15372 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15373 mips32_op = OPC_RSQRT_S;
15374 goto do_unaryfp;
15375 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15376 mips32_op = OPC_RSQRT_D;
15377 goto do_unaryfp;
15378
15379 /* Square root */
15380 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15381 mips32_op = OPC_SQRT_S;
15382 goto do_unaryfp;
15383 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15384 mips32_op = OPC_SQRT_D;
15385 goto do_unaryfp;
15386
15387 /* Reciprocal */
15388 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15389 mips32_op = OPC_RECIP_S;
15390 goto do_unaryfp;
15391 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15392 mips32_op = OPC_RECIP_D;
15393 goto do_unaryfp;
15394
15395 /* Floor */
15396 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15397 mips32_op = OPC_FLOOR_L_S;
15398 goto do_unaryfp;
15399 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15400 mips32_op = OPC_FLOOR_L_D;
15401 goto do_unaryfp;
15402 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15403 mips32_op = OPC_FLOOR_W_S;
15404 goto do_unaryfp;
15405 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15406 mips32_op = OPC_FLOOR_W_D;
15407 goto do_unaryfp;
15408
15409 /* Ceiling */
15410 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15411 mips32_op = OPC_CEIL_L_S;
15412 goto do_unaryfp;
15413 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15414 mips32_op = OPC_CEIL_L_D;
15415 goto do_unaryfp;
15416 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15417 mips32_op = OPC_CEIL_W_S;
15418 goto do_unaryfp;
15419 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15420 mips32_op = OPC_CEIL_W_D;
15421 goto do_unaryfp;
15422
15423 /* Truncation */
15424 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15425 mips32_op = OPC_TRUNC_L_S;
15426 goto do_unaryfp;
15427 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15428 mips32_op = OPC_TRUNC_L_D;
15429 goto do_unaryfp;
15430 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15431 mips32_op = OPC_TRUNC_W_S;
15432 goto do_unaryfp;
15433 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15434 mips32_op = OPC_TRUNC_W_D;
15435 goto do_unaryfp;
15436
15437 /* Round */
15438 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15439 mips32_op = OPC_ROUND_L_S;
15440 goto do_unaryfp;
15441 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15442 mips32_op = OPC_ROUND_L_D;
15443 goto do_unaryfp;
15444 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15445 mips32_op = OPC_ROUND_W_S;
15446 goto do_unaryfp;
15447 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15448 mips32_op = OPC_ROUND_W_D;
15449 goto do_unaryfp;
15450
15451 /* Integer to floating-point conversion */
15452 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15453 mips32_op = OPC_CVT_L_S;
15454 goto do_unaryfp;
15455 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15456 mips32_op = OPC_CVT_L_D;
15457 goto do_unaryfp;
15458 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15459 mips32_op = OPC_CVT_W_S;
15460 goto do_unaryfp;
15461 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15462 mips32_op = OPC_CVT_W_D;
15463 goto do_unaryfp;
15464
15465 /* Paired-foo conversions */
15466 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15467 mips32_op = OPC_CVT_S_PL;
15468 goto do_unaryfp;
15469 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15470 mips32_op = OPC_CVT_S_PU;
15471 goto do_unaryfp;
15472 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15473 mips32_op = OPC_CVT_PW_PS;
15474 goto do_unaryfp;
15475 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15476 mips32_op = OPC_CVT_PS_PW;
15477 goto do_unaryfp;
15478
15479 /* Floating-point moves */
15480 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15481 mips32_op = OPC_MOV_S;
15482 goto do_unaryfp;
15483 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15484 mips32_op = OPC_MOV_D;
15485 goto do_unaryfp;
15486 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15487 mips32_op = OPC_MOV_PS;
15488 goto do_unaryfp;
15489
15490 /* Absolute value */
15491 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15492 mips32_op = OPC_ABS_S;
15493 goto do_unaryfp;
15494 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15495 mips32_op = OPC_ABS_D;
15496 goto do_unaryfp;
15497 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15498 mips32_op = OPC_ABS_PS;
15499 goto do_unaryfp;
15500
15501 /* Negation */
15502 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15503 mips32_op = OPC_NEG_S;
15504 goto do_unaryfp;
15505 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15506 mips32_op = OPC_NEG_D;
15507 goto do_unaryfp;
15508 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15509 mips32_op = OPC_NEG_PS;
15510 goto do_unaryfp;
15511
15512 /* Reciprocal square root step */
15513 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15514 mips32_op = OPC_RSQRT1_S;
15515 goto do_unaryfp;
15516 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15517 mips32_op = OPC_RSQRT1_D;
15518 goto do_unaryfp;
15519 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15520 mips32_op = OPC_RSQRT1_PS;
15521 goto do_unaryfp;
15522
15523 /* Reciprocal step */
15524 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15525 mips32_op = OPC_RECIP1_S;
15526 goto do_unaryfp;
15527 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15528 mips32_op = OPC_RECIP1_S;
15529 goto do_unaryfp;
15530 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15531 mips32_op = OPC_RECIP1_PS;
15532 goto do_unaryfp;
15533
15534 /* Conversions from double */
15535 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15536 mips32_op = OPC_CVT_D_S;
15537 goto do_unaryfp;
15538 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15539 mips32_op = OPC_CVT_D_W;
15540 goto do_unaryfp;
15541 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15542 mips32_op = OPC_CVT_D_L;
15543 goto do_unaryfp;
15544
15545 /* Conversions from single */
15546 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15547 mips32_op = OPC_CVT_S_D;
15548 goto do_unaryfp;
15549 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15550 mips32_op = OPC_CVT_S_W;
15551 goto do_unaryfp;
15552 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15553 mips32_op = OPC_CVT_S_L;
15554 do_unaryfp:
15555 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15556 break;
15557
15558 /* Conditional moves on floating-point codes */
15559 case COND_FLOAT_MOV(MOVT, 0):
15560 case COND_FLOAT_MOV(MOVT, 1):
15561 case COND_FLOAT_MOV(MOVT, 2):
15562 case COND_FLOAT_MOV(MOVT, 3):
15563 case COND_FLOAT_MOV(MOVT, 4):
15564 case COND_FLOAT_MOV(MOVT, 5):
15565 case COND_FLOAT_MOV(MOVT, 6):
15566 case COND_FLOAT_MOV(MOVT, 7):
9e8f441a 15567 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15568 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15569 break;
15570 case COND_FLOAT_MOV(MOVF, 0):
15571 case COND_FLOAT_MOV(MOVF, 1):
15572 case COND_FLOAT_MOV(MOVF, 2):
15573 case COND_FLOAT_MOV(MOVF, 3):
15574 case COND_FLOAT_MOV(MOVF, 4):
15575 case COND_FLOAT_MOV(MOVF, 5):
15576 case COND_FLOAT_MOV(MOVF, 6):
15577 case COND_FLOAT_MOV(MOVF, 7):
9e8f441a 15578 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15579 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15580 break;
15581 default:
15582 MIPS_INVAL("pool32fxf");
9c708c7f 15583 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15584 break;
15585 }
15586}
15587
f60eeb0c 15588static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
15589{
15590 int32_t offset;
15591 uint16_t insn;
15592 int rt, rs, rd, rr;
15593 int16_t imm;
8fffc646 15594 uint32_t op, minor, minor2, mips32_op;
3c824109
NF
15595 uint32_t cond, fmt, cc;
15596
eeb3bba8 15597 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
3c824109
NF
15598 ctx->opcode = (ctx->opcode << 16) | insn;
15599
15600 rt = (ctx->opcode >> 21) & 0x1f;
15601 rs = (ctx->opcode >> 16) & 0x1f;
15602 rd = (ctx->opcode >> 11) & 0x1f;
15603 rr = (ctx->opcode >> 6) & 0x1f;
15604 imm = (int16_t) ctx->opcode;
15605
15606 op = (ctx->opcode >> 26) & 0x3f;
15607 switch (op) {
15608 case POOL32A:
15609 minor = ctx->opcode & 0x3f;
15610 switch (minor) {
15611 case 0x00:
15612 minor = (ctx->opcode >> 6) & 0xf;
15613 switch (minor) {
15614 case SLL32:
15615 mips32_op = OPC_SLL;
15616 goto do_shifti;
15617 case SRA:
15618 mips32_op = OPC_SRA;
15619 goto do_shifti;
15620 case SRL32:
15621 mips32_op = OPC_SRL;
15622 goto do_shifti;
15623 case ROTR:
15624 mips32_op = OPC_ROTR;
15625 do_shifti:
d75c135e 15626 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
3c824109 15627 break;
e0332095
YK
15628 case SELEQZ:
15629 check_insn(ctx, ISA_MIPS32R6);
15630 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15631 break;
15632 case SELNEZ:
15633 check_insn(ctx, ISA_MIPS32R6);
15634 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15635 break;
b00c7218
YK
15636 case R6_RDHWR:
15637 check_insn(ctx, ISA_MIPS32R6);
15638 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15639 break;
3c824109
NF
15640 default:
15641 goto pool32a_invalid;
15642 }
15643 break;
15644 case 0x10:
15645 minor = (ctx->opcode >> 6) & 0xf;
15646 switch (minor) {
15647 /* Arithmetic */
15648 case ADD:
15649 mips32_op = OPC_ADD;
15650 goto do_arith;
15651 case ADDU32:
15652 mips32_op = OPC_ADDU;
15653 goto do_arith;
15654 case SUB:
15655 mips32_op = OPC_SUB;
15656 goto do_arith;
15657 case SUBU32:
15658 mips32_op = OPC_SUBU;
15659 goto do_arith;
15660 case MUL:
9e8f441a 15661 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15662 mips32_op = OPC_MUL;
15663 do_arith:
d75c135e 15664 gen_arith(ctx, mips32_op, rd, rs, rt);
3c824109
NF
15665 break;
15666 /* Shifts */
15667 case SLLV:
15668 mips32_op = OPC_SLLV;
15669 goto do_shift;
15670 case SRLV:
15671 mips32_op = OPC_SRLV;
15672 goto do_shift;
15673 case SRAV:
15674 mips32_op = OPC_SRAV;
15675 goto do_shift;
15676 case ROTRV:
15677 mips32_op = OPC_ROTRV;
15678 do_shift:
d75c135e 15679 gen_shift(ctx, mips32_op, rd, rs, rt);
3c824109
NF
15680 break;
15681 /* Logical operations */
15682 case AND:
15683 mips32_op = OPC_AND;
15684 goto do_logic;
15685 case OR32:
15686 mips32_op = OPC_OR;
15687 goto do_logic;
15688 case NOR:
15689 mips32_op = OPC_NOR;
15690 goto do_logic;
15691 case XOR32:
15692 mips32_op = OPC_XOR;
15693 do_logic:
d75c135e 15694 gen_logic(ctx, mips32_op, rd, rs, rt);
3c824109
NF
15695 break;
15696 /* Set less than */
15697 case SLT:
15698 mips32_op = OPC_SLT;
15699 goto do_slt;
15700 case SLTU:
15701 mips32_op = OPC_SLTU;
15702 do_slt:
d75c135e 15703 gen_slt(ctx, mips32_op, rd, rs, rt);
3c824109
NF
15704 break;
15705 default:
15706 goto pool32a_invalid;
15707 }
15708 break;
15709 case 0x18:
15710 minor = (ctx->opcode >> 6) & 0xf;
15711 switch (minor) {
15712 /* Conditional moves */
e0332095
YK
15713 case MOVN: /* MUL */
15714 if (ctx->insn_flags & ISA_MIPS32R6) {
15715 /* MUL */
15716 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15717 } else {
15718 /* MOVN */
15719 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15720 }
15721 break;
15722 case MOVZ: /* MUH */
15723 if (ctx->insn_flags & ISA_MIPS32R6) {
15724 /* MUH */
15725 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15726 } else {
15727 /* MOVZ */
15728 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15729 }
15730 break;
15731 case MULU:
15732 check_insn(ctx, ISA_MIPS32R6);
15733 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15734 break;
15735 case MUHU:
15736 check_insn(ctx, ISA_MIPS32R6);
15737 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15738 break;
15739 case LWXS: /* DIV */
15740 if (ctx->insn_flags & ISA_MIPS32R6) {
15741 /* DIV */
15742 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15743 } else {
15744 /* LWXS */
15745 gen_ldxs(ctx, rs, rt, rd);
15746 }
15747 break;
15748 case MOD:
15749 check_insn(ctx, ISA_MIPS32R6);
15750 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15751 break;
15752 case R6_DIVU:
15753 check_insn(ctx, ISA_MIPS32R6);
15754 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
3c824109 15755 break;
e0332095
YK
15756 case MODU:
15757 check_insn(ctx, ISA_MIPS32R6);
15758 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
3c824109
NF
15759 break;
15760 default:
15761 goto pool32a_invalid;
15762 }
15763 break;
15764 case INS:
15765 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15766 return;
e0332095
YK
15767 case LSA:
15768 check_insn(ctx, ISA_MIPS32R6);
15769 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
15770 extract32(ctx->opcode, 9, 2));
15771 break;
15772 case ALIGN:
15773 check_insn(ctx, ISA_MIPS32R6);
821f2008 15774 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
e0332095 15775 break;
3c824109
NF
15776 case EXT:
15777 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15778 return;
15779 case POOL32AXF:
240ce26a 15780 gen_pool32axf(env, ctx, rt, rs);
3c824109 15781 break;
dbd8af98 15782 case BREAK32:
9c708c7f 15783 generate_exception_end(ctx, EXCP_BREAK);
3c824109 15784 break;
bb238210
YK
15785 case SIGRIE:
15786 check_insn(ctx, ISA_MIPS32R6);
15787 generate_exception_end(ctx, EXCP_RI);
15788 break;
3c824109
NF
15789 default:
15790 pool32a_invalid:
15791 MIPS_INVAL("pool32a");
9c708c7f 15792 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15793 break;
15794 }
15795 break;
15796 case POOL32B:
15797 minor = (ctx->opcode >> 12) & 0xf;
15798 switch (minor) {
15799 case CACHE:
2e15497c 15800 check_cp0_enabled(ctx);
0d74a222
LA
15801 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15802 gen_cache_operation(ctx, rt, rs, imm);
15803 }
3c824109
NF
15804 break;
15805 case LWC2:
15806 case SWC2:
15807 /* COP2: Not implemented. */
15808 generate_exception_err(ctx, EXCP_CpU, 2);
15809 break;
3c824109
NF
15810#ifdef TARGET_MIPS64
15811 case LDP:
15812 case SDP:
d9224450
MR
15813 check_insn(ctx, ISA_MIPS3);
15814 check_mips_64(ctx);
3c824109 15815#endif
146dd620 15816 /* fall through */
d9224450
MR
15817 case LWP:
15818 case SWP:
3c824109
NF
15819 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15820 break;
3c824109
NF
15821#ifdef TARGET_MIPS64
15822 case LDM:
15823 case SDM:
d9224450
MR
15824 check_insn(ctx, ISA_MIPS3);
15825 check_mips_64(ctx);
3c824109 15826#endif
146dd620 15827 /* fall through */
d9224450
MR
15828 case LWM32:
15829 case SWM32:
3c824109
NF
15830 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15831 break;
15832 default:
15833 MIPS_INVAL("pool32b");
9c708c7f 15834 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15835 break;
15836 }
15837 break;
15838 case POOL32F:
5ab5c041 15839 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3c824109
NF
15840 minor = ctx->opcode & 0x3f;
15841 check_cp1_enabled(ctx);
15842 switch (minor) {
15843 case ALNV_PS:
9e8f441a 15844 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15845 mips32_op = OPC_ALNV_PS;
15846 goto do_madd;
15847 case MADD_S:
9e8f441a 15848 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15849 mips32_op = OPC_MADD_S;
15850 goto do_madd;
15851 case MADD_D:
9e8f441a 15852 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15853 mips32_op = OPC_MADD_D;
15854 goto do_madd;
15855 case MADD_PS:
9e8f441a 15856 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15857 mips32_op = OPC_MADD_PS;
15858 goto do_madd;
15859 case MSUB_S:
9e8f441a 15860 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15861 mips32_op = OPC_MSUB_S;
15862 goto do_madd;
15863 case MSUB_D:
9e8f441a 15864 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15865 mips32_op = OPC_MSUB_D;
15866 goto do_madd;
15867 case MSUB_PS:
9e8f441a 15868 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15869 mips32_op = OPC_MSUB_PS;
15870 goto do_madd;
15871 case NMADD_S:
9e8f441a 15872 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15873 mips32_op = OPC_NMADD_S;
15874 goto do_madd;
15875 case NMADD_D:
9e8f441a 15876 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15877 mips32_op = OPC_NMADD_D;
15878 goto do_madd;
15879 case NMADD_PS:
9e8f441a 15880 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15881 mips32_op = OPC_NMADD_PS;
15882 goto do_madd;
15883 case NMSUB_S:
9e8f441a 15884 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15885 mips32_op = OPC_NMSUB_S;
15886 goto do_madd;
15887 case NMSUB_D:
9e8f441a 15888 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15889 mips32_op = OPC_NMSUB_D;
15890 goto do_madd;
15891 case NMSUB_PS:
9e8f441a 15892 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15893 mips32_op = OPC_NMSUB_PS;
15894 do_madd:
15895 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15896 break;
15897 case CABS_COND_FMT:
9e8f441a 15898 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15899 cond = (ctx->opcode >> 6) & 0xf;
15900 cc = (ctx->opcode >> 13) & 0x7;
15901 fmt = (ctx->opcode >> 10) & 0x3;
15902 switch (fmt) {
15903 case 0x0:
15904 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15905 break;
15906 case 0x1:
15907 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15908 break;
15909 case 0x2:
15910 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15911 break;
15912 default:
15913 goto pool32f_invalid;
15914 }
15915 break;
15916 case C_COND_FMT:
9e8f441a 15917 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15918 cond = (ctx->opcode >> 6) & 0xf;
15919 cc = (ctx->opcode >> 13) & 0x7;
15920 fmt = (ctx->opcode >> 10) & 0x3;
15921 switch (fmt) {
15922 case 0x0:
15923 gen_cmp_s(ctx, cond, rt, rs, cc);
15924 break;
15925 case 0x1:
15926 gen_cmp_d(ctx, cond, rt, rs, cc);
15927 break;
15928 case 0x2:
15929 gen_cmp_ps(ctx, cond, rt, rs, cc);
15930 break;
15931 default:
15932 goto pool32f_invalid;
15933 }
15934 break;
2a24a7ba
YK
15935 case CMP_CONDN_S:
15936 check_insn(ctx, ISA_MIPS32R6);
15937 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15938 break;
15939 case CMP_CONDN_D:
15940 check_insn(ctx, ISA_MIPS32R6);
15941 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15942 break;
3c824109 15943 case POOL32FXF:
d75c135e 15944 gen_pool32fxf(ctx, rt, rs);
3c824109
NF
15945 break;
15946 case 0x00:
15947 /* PLL foo */
15948 switch ((ctx->opcode >> 6) & 0x7) {
15949 case PLL_PS:
15950 mips32_op = OPC_PLL_PS;
15951 goto do_ps;
15952 case PLU_PS:
15953 mips32_op = OPC_PLU_PS;
15954 goto do_ps;
15955 case PUL_PS:
15956 mips32_op = OPC_PUL_PS;
15957 goto do_ps;
15958 case PUU_PS:
15959 mips32_op = OPC_PUU_PS;
15960 goto do_ps;
15961 case CVT_PS_S:
9e8f441a 15962 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15963 mips32_op = OPC_CVT_PS_S;
15964 do_ps:
15965 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15966 break;
15967 default:
15968 goto pool32f_invalid;
15969 }
15970 break;
2a24a7ba
YK
15971 case MIN_FMT:
15972 check_insn(ctx, ISA_MIPS32R6);
15973 switch ((ctx->opcode >> 9) & 0x3) {
15974 case FMT_SDPS_S:
15975 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15976 break;
15977 case FMT_SDPS_D:
15978 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15979 break;
15980 default:
15981 goto pool32f_invalid;
15982 }
15983 break;
3c824109
NF
15984 case 0x08:
15985 /* [LS][WDU]XC1 */
15986 switch ((ctx->opcode >> 6) & 0x7) {
15987 case LWXC1:
9e8f441a 15988 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15989 mips32_op = OPC_LWXC1;
15990 goto do_ldst_cp1;
15991 case SWXC1:
9e8f441a 15992 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15993 mips32_op = OPC_SWXC1;
15994 goto do_ldst_cp1;
15995 case LDXC1:
9e8f441a 15996 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15997 mips32_op = OPC_LDXC1;
15998 goto do_ldst_cp1;
15999 case SDXC1:
9e8f441a 16000 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16001 mips32_op = OPC_SDXC1;
16002 goto do_ldst_cp1;
16003 case LUXC1:
9e8f441a 16004 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16005 mips32_op = OPC_LUXC1;
16006 goto do_ldst_cp1;
16007 case SUXC1:
9e8f441a 16008 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16009 mips32_op = OPC_SUXC1;
16010 do_ldst_cp1:
16011 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16012 break;
16013 default:
16014 goto pool32f_invalid;
16015 }
16016 break;
2a24a7ba
YK
16017 case MAX_FMT:
16018 check_insn(ctx, ISA_MIPS32R6);
16019 switch ((ctx->opcode >> 9) & 0x3) {
16020 case FMT_SDPS_S:
16021 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16022 break;
16023 case FMT_SDPS_D:
16024 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16025 break;
16026 default:
16027 goto pool32f_invalid;
16028 }
16029 break;
3c824109
NF
16030 case 0x18:
16031 /* 3D insns */
9e8f441a 16032 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16033 fmt = (ctx->opcode >> 9) & 0x3;
16034 switch ((ctx->opcode >> 6) & 0x7) {
16035 case RSQRT2_FMT:
16036 switch (fmt) {
16037 case FMT_SDPS_S:
16038 mips32_op = OPC_RSQRT2_S;
16039 goto do_3d;
16040 case FMT_SDPS_D:
16041 mips32_op = OPC_RSQRT2_D;
16042 goto do_3d;
16043 case FMT_SDPS_PS:
16044 mips32_op = OPC_RSQRT2_PS;
16045 goto do_3d;
16046 default:
16047 goto pool32f_invalid;
16048 }
16049 break;
16050 case RECIP2_FMT:
16051 switch (fmt) {
16052 case FMT_SDPS_S:
16053 mips32_op = OPC_RECIP2_S;
16054 goto do_3d;
16055 case FMT_SDPS_D:
16056 mips32_op = OPC_RECIP2_D;
16057 goto do_3d;
16058 case FMT_SDPS_PS:
16059 mips32_op = OPC_RECIP2_PS;
16060 goto do_3d;
16061 default:
16062 goto pool32f_invalid;
16063 }
16064 break;
16065 case ADDR_PS:
16066 mips32_op = OPC_ADDR_PS;
16067 goto do_3d;
16068 case MULR_PS:
16069 mips32_op = OPC_MULR_PS;
16070 do_3d:
16071 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16072 break;
16073 default:
16074 goto pool32f_invalid;
16075 }
16076 break;
16077 case 0x20:
2a24a7ba 16078 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
3c824109
NF
16079 cc = (ctx->opcode >> 13) & 0x7;
16080 fmt = (ctx->opcode >> 9) & 0x3;
16081 switch ((ctx->opcode >> 6) & 0x7) {
2a24a7ba
YK
16082 case MOVF_FMT: /* RINT_FMT */
16083 if (ctx->insn_flags & ISA_MIPS32R6) {
16084 /* RINT_FMT */
16085 switch (fmt) {
16086 case FMT_SDPS_S:
16087 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16088 break;
16089 case FMT_SDPS_D:
16090 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16091 break;
16092 default:
16093 goto pool32f_invalid;
16094 }
16095 } else {
16096 /* MOVF_FMT */
16097 switch (fmt) {
16098 case FMT_SDPS_S:
16099 gen_movcf_s(ctx, rs, rt, cc, 0);
16100 break;
16101 case FMT_SDPS_D:
16102 gen_movcf_d(ctx, rs, rt, cc, 0);
16103 break;
16104 case FMT_SDPS_PS:
16105 check_ps(ctx);
16106 gen_movcf_ps(ctx, rs, rt, cc, 0);
16107 break;
16108 default:
16109 goto pool32f_invalid;
16110 }
3c824109
NF
16111 }
16112 break;
2a24a7ba
YK
16113 case MOVT_FMT: /* CLASS_FMT */
16114 if (ctx->insn_flags & ISA_MIPS32R6) {
16115 /* CLASS_FMT */
16116 switch (fmt) {
16117 case FMT_SDPS_S:
16118 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16119 break;
16120 case FMT_SDPS_D:
16121 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16122 break;
16123 default:
16124 goto pool32f_invalid;
16125 }
16126 } else {
16127 /* MOVT_FMT */
16128 switch (fmt) {
16129 case FMT_SDPS_S:
16130 gen_movcf_s(ctx, rs, rt, cc, 1);
16131 break;
16132 case FMT_SDPS_D:
16133 gen_movcf_d(ctx, rs, rt, cc, 1);
16134 break;
16135 case FMT_SDPS_PS:
16136 check_ps(ctx);
16137 gen_movcf_ps(ctx, rs, rt, cc, 1);
16138 break;
16139 default:
16140 goto pool32f_invalid;
16141 }
3c824109
NF
16142 }
16143 break;
16144 case PREFX:
9e8f441a 16145 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16146 break;
16147 default:
16148 goto pool32f_invalid;
16149 }
16150 break;
16151#define FINSN_3ARG_SDPS(prfx) \
16152 switch ((ctx->opcode >> 8) & 0x3) { \
16153 case FMT_SDPS_S: \
16154 mips32_op = OPC_##prfx##_S; \
16155 goto do_fpop; \
16156 case FMT_SDPS_D: \
16157 mips32_op = OPC_##prfx##_D; \
16158 goto do_fpop; \
16159 case FMT_SDPS_PS: \
e29c9628 16160 check_ps(ctx); \
3c824109
NF
16161 mips32_op = OPC_##prfx##_PS; \
16162 goto do_fpop; \
16163 default: \
16164 goto pool32f_invalid; \
16165 }
2a24a7ba
YK
16166 case MINA_FMT:
16167 check_insn(ctx, ISA_MIPS32R6);
16168 switch ((ctx->opcode >> 9) & 0x3) {
16169 case FMT_SDPS_S:
16170 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16171 break;
16172 case FMT_SDPS_D:
16173 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16174 break;
16175 default:
16176 goto pool32f_invalid;
16177 }
16178 break;
16179 case MAXA_FMT:
16180 check_insn(ctx, ISA_MIPS32R6);
16181 switch ((ctx->opcode >> 9) & 0x3) {
16182 case FMT_SDPS_S:
16183 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16184 break;
16185 case FMT_SDPS_D:
16186 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16187 break;
16188 default:
16189 goto pool32f_invalid;
16190 }
16191 break;
3c824109
NF
16192 case 0x30:
16193 /* regular FP ops */
16194 switch ((ctx->opcode >> 6) & 0x3) {
16195 case ADD_FMT:
16196 FINSN_3ARG_SDPS(ADD);
16197 break;
16198 case SUB_FMT:
16199 FINSN_3ARG_SDPS(SUB);
16200 break;
16201 case MUL_FMT:
16202 FINSN_3ARG_SDPS(MUL);
16203 break;
16204 case DIV_FMT:
16205 fmt = (ctx->opcode >> 8) & 0x3;
16206 if (fmt == 1) {
16207 mips32_op = OPC_DIV_D;
16208 } else if (fmt == 0) {
16209 mips32_op = OPC_DIV_S;
16210 } else {
16211 goto pool32f_invalid;
16212 }
16213 goto do_fpop;
16214 default:
16215 goto pool32f_invalid;
16216 }
16217 break;
16218 case 0x38:
16219 /* cmovs */
2a24a7ba 16220 switch ((ctx->opcode >> 6) & 0x7) {
fdac60cd 16221 case MOVN_FMT: /* SELEQZ_FMT */
2a24a7ba 16222 if (ctx->insn_flags & ISA_MIPS32R6) {
fdac60cd 16223 /* SELEQZ_FMT */
2a24a7ba
YK
16224 switch ((ctx->opcode >> 9) & 0x3) {
16225 case FMT_SDPS_S:
fdac60cd 16226 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
2a24a7ba
YK
16227 break;
16228 case FMT_SDPS_D:
fdac60cd 16229 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
2a24a7ba
YK
16230 break;
16231 default:
16232 goto pool32f_invalid;
16233 }
16234 } else {
16235 /* MOVN_FMT */
16236 FINSN_3ARG_SDPS(MOVN);
16237 }
16238 break;
16239 case MOVN_FMT_04:
16240 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16241 FINSN_3ARG_SDPS(MOVN);
16242 break;
fdac60cd 16243 case MOVZ_FMT: /* SELNEZ_FMT */
2a24a7ba 16244 if (ctx->insn_flags & ISA_MIPS32R6) {
fdac60cd 16245 /* SELNEZ_FMT */
2a24a7ba
YK
16246 switch ((ctx->opcode >> 9) & 0x3) {
16247 case FMT_SDPS_S:
fdac60cd 16248 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
2a24a7ba
YK
16249 break;
16250 case FMT_SDPS_D:
fdac60cd 16251 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
2a24a7ba
YK
16252 break;
16253 default:
16254 goto pool32f_invalid;
16255 }
16256 } else {
16257 /* MOVZ_FMT */
16258 FINSN_3ARG_SDPS(MOVZ);
16259 }
16260 break;
16261 case MOVZ_FMT_05:
16262 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16263 FINSN_3ARG_SDPS(MOVZ);
16264 break;
2a24a7ba
YK
16265 case SEL_FMT:
16266 check_insn(ctx, ISA_MIPS32R6);
16267 switch ((ctx->opcode >> 9) & 0x3) {
16268 case FMT_SDPS_S:
16269 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16270 break;
16271 case FMT_SDPS_D:
16272 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16273 break;
16274 default:
16275 goto pool32f_invalid;
16276 }
16277 break;
16278 case MADDF_FMT:
16279 check_insn(ctx, ISA_MIPS32R6);
16280 switch ((ctx->opcode >> 9) & 0x3) {
16281 case FMT_SDPS_S:
16282 mips32_op = OPC_MADDF_S;
16283 goto do_fpop;
16284 case FMT_SDPS_D:
16285 mips32_op = OPC_MADDF_D;
16286 goto do_fpop;
16287 default:
16288 goto pool32f_invalid;
16289 }
16290 break;
16291 case MSUBF_FMT:
16292 check_insn(ctx, ISA_MIPS32R6);
16293 switch ((ctx->opcode >> 9) & 0x3) {
16294 case FMT_SDPS_S:
16295 mips32_op = OPC_MSUBF_S;
16296 goto do_fpop;
16297 case FMT_SDPS_D:
16298 mips32_op = OPC_MSUBF_D;
16299 goto do_fpop;
16300 default:
16301 goto pool32f_invalid;
16302 }
16303 break;
3c824109
NF
16304 default:
16305 goto pool32f_invalid;
16306 }
16307 break;
16308 do_fpop:
16309 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16310 break;
16311 default:
16312 pool32f_invalid:
16313 MIPS_INVAL("pool32f");
9c708c7f 16314 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16315 break;
16316 }
16317 } else {
16318 generate_exception_err(ctx, EXCP_CpU, 1);
16319 }
16320 break;
16321 case POOL32I:
16322 minor = (ctx->opcode >> 21) & 0x1f;
16323 switch (minor) {
16324 case BLTZ:
9e8f441a 16325 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16326 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16327 break;
3c824109 16328 case BLTZAL:
9e8f441a 16329 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16330 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16331 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16332 break;
3c824109 16333 case BLTZALS:
9e8f441a 16334 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16335 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16336 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16337 break;
3c824109 16338 case BGEZ:
9e8f441a 16339 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16340 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16341 break;
3c824109 16342 case BGEZAL:
9e8f441a 16343 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16344 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16345 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16346 break;
3c824109 16347 case BGEZALS:
9e8f441a 16348 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16349 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16350 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16351 break;
3c824109 16352 case BLEZ:
9e8f441a 16353 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
16354 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16355 break;
3c824109 16356 case BGTZ:
9e8f441a 16357 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103 16358 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
3c824109
NF
16359 break;
16360
16361 /* Traps */
65935f07
YK
16362 case TLTI: /* BC1EQZC */
16363 if (ctx->insn_flags & ISA_MIPS32R6) {
16364 /* BC1EQZC */
16365 check_cp1_enabled(ctx);
16366 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16367 } else {
16368 /* TLTI */
16369 mips32_op = OPC_TLTI;
16370 goto do_trapi;
16371 }
16372 break;
16373 case TGEI: /* BC1NEZC */
16374 if (ctx->insn_flags & ISA_MIPS32R6) {
16375 /* BC1NEZC */
16376 check_cp1_enabled(ctx);
16377 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16378 } else {
16379 /* TGEI */
16380 mips32_op = OPC_TGEI;
16381 goto do_trapi;
16382 }
16383 break;
3c824109 16384 case TLTIU:
9e8f441a 16385 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16386 mips32_op = OPC_TLTIU;
16387 goto do_trapi;
16388 case TGEIU:
9e8f441a 16389 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16390 mips32_op = OPC_TGEIU;
16391 goto do_trapi;
3b4a5489
YK
16392 case TNEI: /* SYNCI */
16393 if (ctx->insn_flags & ISA_MIPS32R6) {
16394 /* SYNCI */
16395 /* Break the TB to be able to sync copied instructions
16396 immediately */
eeb3bba8 16397 ctx->base.is_jmp = DISAS_STOP;
3b4a5489
YK
16398 } else {
16399 /* TNEI */
16400 mips32_op = OPC_TNEI;
16401 goto do_trapi;
16402 }
16403 break;
3c824109 16404 case TEQI:
9e8f441a 16405 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16406 mips32_op = OPC_TEQI;
16407 do_trapi:
16408 gen_trap(ctx, mips32_op, rs, -1, imm);
16409 break;
16410
16411 case BNEZC:
16412 case BEQZC:
9e8f441a 16413 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16414 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
b231c103 16415 4, rs, 0, imm << 1, 0);
3c824109
NF
16416 /* Compact branches don't have a delay slot, so just let
16417 the normal delay slot handling take us to the branch
16418 target. */
16419 break;
16420 case LUI:
9e8f441a 16421 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5e88759a 16422 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
3c824109
NF
16423 break;
16424 case SYNCI:
9e8f441a 16425 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a83bddd6
DZ
16426 /* Break the TB to be able to sync copied instructions
16427 immediately */
eeb3bba8 16428 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
16429 break;
16430 case BC2F:
16431 case BC2T:
9e8f441a 16432 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16433 /* COP2: Not implemented. */
16434 generate_exception_err(ctx, EXCP_CpU, 2);
16435 break;
16436 case BC1F:
9e8f441a 16437 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16438 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16439 goto do_cp1branch;
16440 case BC1T:
9e8f441a 16441 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16442 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16443 goto do_cp1branch;
16444 case BC1ANY4F:
9e8f441a 16445 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16446 mips32_op = OPC_BC1FANY4;
16447 goto do_cp1mips3d;
16448 case BC1ANY4T:
9e8f441a 16449 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
16450 mips32_op = OPC_BC1TANY4;
16451 do_cp1mips3d:
16452 check_cop1x(ctx);
d75c135e 16453 check_insn(ctx, ASE_MIPS3D);
3c824109
NF
16454 /* Fall through */
16455 do_cp1branch:
272f458d
MR
16456 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16457 check_cp1_enabled(ctx);
16458 gen_compute_branch1(ctx, mips32_op,
16459 (ctx->opcode >> 18) & 0x7, imm << 1);
16460 } else {
16461 generate_exception_err(ctx, EXCP_CpU, 1);
16462 }
3c824109
NF
16463 break;
16464 case BPOSGE64:
16465 case BPOSGE32:
16466 /* MIPS DSP: not implemented */
16467 /* Fall through */
16468 default:
16469 MIPS_INVAL("pool32i");
9c708c7f 16470 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16471 break;
16472 }
16473 break;
16474 case POOL32C:
16475 minor = (ctx->opcode >> 12) & 0xf;
3b4a5489
YK
16476 offset = sextract32(ctx->opcode, 0,
16477 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
3c824109
NF
16478 switch (minor) {
16479 case LWL:
9e8f441a 16480 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16481 mips32_op = OPC_LWL;
5c13fdfd 16482 goto do_ld_lr;
3c824109 16483 case SWL:
9e8f441a 16484 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16485 mips32_op = OPC_SWL;
5c13fdfd 16486 goto do_st_lr;
3c824109 16487 case LWR:
9e8f441a 16488 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16489 mips32_op = OPC_LWR;
5c13fdfd 16490 goto do_ld_lr;
3c824109 16491 case SWR:
9e8f441a 16492 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16493 mips32_op = OPC_SWR;
5c13fdfd 16494 goto do_st_lr;
3c824109
NF
16495#if defined(TARGET_MIPS64)
16496 case LDL:
d9224450
MR
16497 check_insn(ctx, ISA_MIPS3);
16498 check_mips_64(ctx);
9e8f441a 16499 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16500 mips32_op = OPC_LDL;
5c13fdfd 16501 goto do_ld_lr;
3c824109 16502 case SDL:
d9224450
MR
16503 check_insn(ctx, ISA_MIPS3);
16504 check_mips_64(ctx);
9e8f441a 16505 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16506 mips32_op = OPC_SDL;
5c13fdfd 16507 goto do_st_lr;
3c824109 16508 case LDR:
d9224450
MR
16509 check_insn(ctx, ISA_MIPS3);
16510 check_mips_64(ctx);
9e8f441a 16511 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16512 mips32_op = OPC_LDR;
5c13fdfd 16513 goto do_ld_lr;
3c824109 16514 case SDR:
d9224450
MR
16515 check_insn(ctx, ISA_MIPS3);
16516 check_mips_64(ctx);
9e8f441a 16517 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16518 mips32_op = OPC_SDR;
5c13fdfd 16519 goto do_st_lr;
3c824109 16520 case LWU:
d9224450
MR
16521 check_insn(ctx, ISA_MIPS3);
16522 check_mips_64(ctx);
3c824109 16523 mips32_op = OPC_LWU;
5c13fdfd 16524 goto do_ld_lr;
3c824109 16525 case LLD:
d9224450
MR
16526 check_insn(ctx, ISA_MIPS3);
16527 check_mips_64(ctx);
3c824109 16528 mips32_op = OPC_LLD;
5c13fdfd 16529 goto do_ld_lr;
3c824109
NF
16530#endif
16531 case LL:
16532 mips32_op = OPC_LL;
5c13fdfd
AJ
16533 goto do_ld_lr;
16534 do_ld_lr:
3b4a5489 16535 gen_ld(ctx, mips32_op, rt, rs, offset);
5c13fdfd
AJ
16536 break;
16537 do_st_lr:
8fffc646 16538 gen_st(ctx, mips32_op, rt, rs, offset);
3c824109
NF
16539 break;
16540 case SC:
3b4a5489 16541 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
3c824109
NF
16542 break;
16543#if defined(TARGET_MIPS64)
16544 case SCD:
d9224450
MR
16545 check_insn(ctx, ISA_MIPS3);
16546 check_mips_64(ctx);
3b4a5489 16547 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
3c824109
NF
16548 break;
16549#endif
8fffc646
JH
16550 case LD_EVA:
16551 if (!ctx->eva) {
16552 MIPS_INVAL("pool32c ld-eva");
16553 generate_exception_end(ctx, EXCP_RI);
16554 break;
16555 }
16556 check_cp0_enabled(ctx);
16557
16558 minor2 = (ctx->opcode >> 9) & 0x7;
16559 offset = sextract32(ctx->opcode, 0, 9);
16560 switch (minor2) {
16561 case LBUE:
16562 mips32_op = OPC_LBUE;
16563 goto do_ld_lr;
16564 case LHUE:
16565 mips32_op = OPC_LHUE;
16566 goto do_ld_lr;
16567 case LWLE:
16568 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16569 mips32_op = OPC_LWLE;
16570 goto do_ld_lr;
16571 case LWRE:
16572 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16573 mips32_op = OPC_LWRE;
16574 goto do_ld_lr;
16575 case LBE:
16576 mips32_op = OPC_LBE;
16577 goto do_ld_lr;
16578 case LHE:
16579 mips32_op = OPC_LHE;
16580 goto do_ld_lr;
16581 case LLE:
16582 mips32_op = OPC_LLE;
16583 goto do_ld_lr;
16584 case LWE:
16585 mips32_op = OPC_LWE;
16586 goto do_ld_lr;
16587 };
16588 break;
16589 case ST_EVA:
16590 if (!ctx->eva) {
16591 MIPS_INVAL("pool32c st-eva");
16592 generate_exception_end(ctx, EXCP_RI);
16593 break;
16594 }
16595 check_cp0_enabled(ctx);
16596
16597 minor2 = (ctx->opcode >> 9) & 0x7;
16598 offset = sextract32(ctx->opcode, 0, 9);
16599 switch (minor2) {
16600 case SWLE:
16601 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16602 mips32_op = OPC_SWLE;
16603 goto do_st_lr;
16604 case SWRE:
16605 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16606 mips32_op = OPC_SWRE;
16607 goto do_st_lr;
16608 case PREFE:
16609 /* Treat as no-op */
16610 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16611 /* hint codes 24-31 are reserved and signal RI */
16612 generate_exception(ctx, EXCP_RI);
16613 }
16614 break;
16615 case CACHEE:
16616 /* Treat as no-op */
16617 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16618 gen_cache_operation(ctx, rt, rs, offset);
16619 }
16620 break;
16621 case SBE:
16622 mips32_op = OPC_SBE;
16623 goto do_st_lr;
16624 case SHE:
16625 mips32_op = OPC_SHE;
16626 goto do_st_lr;
16627 case SCE:
16628 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
16629 break;
16630 case SWE:
16631 mips32_op = OPC_SWE;
16632 goto do_st_lr;
16633 };
16634 break;
3c824109
NF
16635 case PREF:
16636 /* Treat as no-op */
3b4a5489
YK
16637 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16638 /* hint codes 24-31 are reserved and signal RI */
16639 generate_exception(ctx, EXCP_RI);
16640 }
3c824109
NF
16641 break;
16642 default:
16643 MIPS_INVAL("pool32c");
9c708c7f 16644 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16645 break;
16646 }
16647 break;
ab39ee45
YK
16648 case ADDI32: /* AUI, LUI */
16649 if (ctx->insn_flags & ISA_MIPS32R6) {
16650 /* AUI, LUI */
16651 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16652 } else {
16653 /* ADDI32 */
16654 mips32_op = OPC_ADDI;
16655 goto do_addi;
16656 }
16657 break;
3c824109
NF
16658 case ADDIU32:
16659 mips32_op = OPC_ADDIU;
16660 do_addi:
d75c135e 16661 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
16662 break;
16663
16664 /* Logical operations */
16665 case ORI32:
16666 mips32_op = OPC_ORI;
16667 goto do_logici;
16668 case XORI32:
16669 mips32_op = OPC_XORI;
16670 goto do_logici;
16671 case ANDI32:
16672 mips32_op = OPC_ANDI;
16673 do_logici:
d75c135e 16674 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
16675 break;
16676
16677 /* Set less than immediate */
16678 case SLTI32:
16679 mips32_op = OPC_SLTI;
16680 goto do_slti;
16681 case SLTIU32:
16682 mips32_op = OPC_SLTIU;
16683 do_slti:
d75c135e 16684 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
16685 break;
16686 case JALX32:
9e8f441a 16687 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16688 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103
YK
16689 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16690 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109 16691 break;
65935f07
YK
16692 case JALS32: /* BOVC, BEQC, BEQZALC */
16693 if (ctx->insn_flags & ISA_MIPS32R6) {
16694 if (rs >= rt) {
16695 /* BOVC */
16696 mips32_op = OPC_BOVC;
16697 } else if (rs < rt && rs == 0) {
16698 /* BEQZALC */
16699 mips32_op = OPC_BEQZALC;
16700 } else {
16701 /* BEQC */
16702 mips32_op = OPC_BEQC;
16703 }
16704 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16705 } else {
16706 /* JALS32 */
16707 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16708 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16709 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16710 }
3c824109 16711 break;
65935f07
YK
16712 case BEQ32: /* BC */
16713 if (ctx->insn_flags & ISA_MIPS32R6) {
16714 /* BC */
16715 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16716 sextract32(ctx->opcode << 1, 0, 27));
16717 } else {
16718 /* BEQ32 */
16719 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16720 }
3c824109 16721 break;
65935f07
YK
16722 case BNE32: /* BALC */
16723 if (ctx->insn_flags & ISA_MIPS32R6) {
16724 /* BALC */
16725 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16726 sextract32(ctx->opcode << 1, 0, 27));
16727 } else {
16728 /* BNE32 */
16729 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16730 }
3c824109 16731 break;
65935f07
YK
16732 case J32: /* BGTZC, BLTZC, BLTC */
16733 if (ctx->insn_flags & ISA_MIPS32R6) {
16734 if (rs == 0 && rt != 0) {
16735 /* BGTZC */
16736 mips32_op = OPC_BGTZC;
16737 } else if (rs != 0 && rt != 0 && rs == rt) {
16738 /* BLTZC */
16739 mips32_op = OPC_BLTZC;
16740 } else {
16741 /* BLTC */
16742 mips32_op = OPC_BLTC;
16743 }
16744 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16745 } else {
16746 /* J32 */
16747 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16748 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16749 }
3c824109 16750 break;
65935f07
YK
16751 case JAL32: /* BLEZC, BGEZC, BGEC */
16752 if (ctx->insn_flags & ISA_MIPS32R6) {
16753 if (rs == 0 && rt != 0) {
16754 /* BLEZC */
16755 mips32_op = OPC_BLEZC;
16756 } else if (rs != 0 && rt != 0 && rs == rt) {
16757 /* BGEZC */
16758 mips32_op = OPC_BGEZC;
16759 } else {
16760 /* BGEC */
16761 mips32_op = OPC_BGEC;
16762 }
16763 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16764 } else {
16765 /* JAL32 */
16766 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16767 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16768 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16769 }
3c824109
NF
16770 break;
16771 /* Floating point (COP1) */
16772 case LWC132:
16773 mips32_op = OPC_LWC1;
16774 goto do_cop1;
16775 case LDC132:
16776 mips32_op = OPC_LDC1;
16777 goto do_cop1;
16778 case SWC132:
16779 mips32_op = OPC_SWC1;
16780 goto do_cop1;
16781 case SDC132:
16782 mips32_op = OPC_SDC1;
16783 do_cop1:
5ab5c041 16784 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
3c824109 16785 break;
ab39ee45
YK
16786 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16787 if (ctx->insn_flags & ISA_MIPS32R6) {
16788 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16789 switch ((ctx->opcode >> 16) & 0x1f) {
c38a1d52
AR
16790 case ADDIUPC_00:
16791 case ADDIUPC_01:
16792 case ADDIUPC_02:
16793 case ADDIUPC_03:
16794 case ADDIUPC_04:
16795 case ADDIUPC_05:
16796 case ADDIUPC_06:
16797 case ADDIUPC_07:
eeb3bba8 16798 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
16799 break;
16800 case AUIPC:
eeb3bba8 16801 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
ab39ee45
YK
16802 break;
16803 case ALUIPC:
eeb3bba8 16804 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
ab39ee45 16805 break;
c38a1d52
AR
16806 case LWPC_08:
16807 case LWPC_09:
16808 case LWPC_0A:
16809 case LWPC_0B:
16810 case LWPC_0C:
16811 case LWPC_0D:
16812 case LWPC_0E:
16813 case LWPC_0F:
eeb3bba8 16814 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
16815 break;
16816 default:
16817 generate_exception(ctx, EXCP_RI);
16818 break;
16819 }
16820 } else {
16821 /* ADDIUPC */
3c824109 16822 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
e1555d7d 16823 offset = SIMM(ctx->opcode, 0, 23) << 2;
3c824109
NF
16824
16825 gen_addiupc(ctx, reg, offset, 0, 0);
16826 }
16827 break;
65935f07
YK
16828 case BNVC: /* BNEC, BNEZALC */
16829 check_insn(ctx, ISA_MIPS32R6);
16830 if (rs >= rt) {
16831 /* BNVC */
16832 mips32_op = OPC_BNVC;
16833 } else if (rs < rt && rs == 0) {
16834 /* BNEZALC */
16835 mips32_op = OPC_BNEZALC;
16836 } else {
16837 /* BNEC */
16838 mips32_op = OPC_BNEC;
16839 }
16840 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16841 break;
16842 case R6_BNEZC: /* JIALC */
16843 check_insn(ctx, ISA_MIPS32R6);
16844 if (rt != 0) {
16845 /* BNEZC */
16846 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16847 sextract32(ctx->opcode << 1, 0, 22));
16848 } else {
16849 /* JIALC */
16850 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16851 }
16852 break;
16853 case R6_BEQZC: /* JIC */
16854 check_insn(ctx, ISA_MIPS32R6);
16855 if (rt != 0) {
16856 /* BEQZC */
16857 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16858 sextract32(ctx->opcode << 1, 0, 22));
16859 } else {
16860 /* JIC */
16861 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16862 }
16863 break;
16864 case BLEZALC: /* BGEZALC, BGEUC */
16865 check_insn(ctx, ISA_MIPS32R6);
16866 if (rs == 0 && rt != 0) {
16867 /* BLEZALC */
16868 mips32_op = OPC_BLEZALC;
16869 } else if (rs != 0 && rt != 0 && rs == rt) {
16870 /* BGEZALC */
16871 mips32_op = OPC_BGEZALC;
16872 } else {
16873 /* BGEUC */
16874 mips32_op = OPC_BGEUC;
16875 }
16876 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16877 break;
16878 case BGTZALC: /* BLTZALC, BLTUC */
16879 check_insn(ctx, ISA_MIPS32R6);
16880 if (rs == 0 && rt != 0) {
16881 /* BGTZALC */
16882 mips32_op = OPC_BGTZALC;
16883 } else if (rs != 0 && rt != 0 && rs == rt) {
16884 /* BLTZALC */
16885 mips32_op = OPC_BLTZALC;
16886 } else {
16887 /* BLTUC */
16888 mips32_op = OPC_BLTUC;
16889 }
16890 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16891 break;
3c824109
NF
16892 /* Loads and stores */
16893 case LB32:
16894 mips32_op = OPC_LB;
5c13fdfd 16895 goto do_ld;
3c824109
NF
16896 case LBU32:
16897 mips32_op = OPC_LBU;
5c13fdfd 16898 goto do_ld;
3c824109
NF
16899 case LH32:
16900 mips32_op = OPC_LH;
5c13fdfd 16901 goto do_ld;
3c824109
NF
16902 case LHU32:
16903 mips32_op = OPC_LHU;
5c13fdfd 16904 goto do_ld;
3c824109
NF
16905 case LW32:
16906 mips32_op = OPC_LW;
5c13fdfd 16907 goto do_ld;
3c824109
NF
16908#ifdef TARGET_MIPS64
16909 case LD32:
d9224450
MR
16910 check_insn(ctx, ISA_MIPS3);
16911 check_mips_64(ctx);
3c824109 16912 mips32_op = OPC_LD;
5c13fdfd 16913 goto do_ld;
3c824109 16914 case SD32:
d9224450
MR
16915 check_insn(ctx, ISA_MIPS3);
16916 check_mips_64(ctx);
3c824109 16917 mips32_op = OPC_SD;
5c13fdfd 16918 goto do_st;
3c824109
NF
16919#endif
16920 case SB32:
16921 mips32_op = OPC_SB;
5c13fdfd 16922 goto do_st;
3c824109
NF
16923 case SH32:
16924 mips32_op = OPC_SH;
5c13fdfd 16925 goto do_st;
3c824109
NF
16926 case SW32:
16927 mips32_op = OPC_SW;
5c13fdfd
AJ
16928 goto do_st;
16929 do_ld:
d75c135e 16930 gen_ld(ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
16931 break;
16932 do_st:
16933 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
16934 break;
16935 default:
9c708c7f 16936 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16937 break;
16938 }
16939}
16940
240ce26a 16941static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
16942{
16943 uint32_t op;
16944
16945 /* make sure instructions are on a halfword boundary */
eeb3bba8
EC
16946 if (ctx->base.pc_next & 0x1) {
16947 env->CP0_BadVAddr = ctx->base.pc_next;
9c708c7f 16948 generate_exception_end(ctx, EXCP_AdEL);
3c824109
NF
16949 return 2;
16950 }
16951
16952 op = (ctx->opcode >> 10) & 0x3f;
16953 /* Enforce properly-sized instructions in a delay slot */
b231c103
YK
16954 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16955 switch (op & 0x7) { /* MSB-3..MSB-5 */
16956 case 0:
16957 /* POOL32A, POOL32B, POOL32I, POOL32C */
16958 case 4:
16959 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16960 case 5:
16961 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16962 case 6:
16963 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16964 case 7:
16965 /* LB32, LH32, LWC132, LDC132, LW32 */
16966 if (ctx->hflags & MIPS_HFLAG_BDS16) {
9c708c7f 16967 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16968 return 2;
16969 }
16970 break;
b231c103
YK
16971 case 1:
16972 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16973 case 2:
16974 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16975 case 3:
16976 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16977 if (ctx->hflags & MIPS_HFLAG_BDS32) {
9c708c7f 16978 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16979 return 2;
16980 }
16981 break;
3c824109
NF
16982 }
16983 }
b231c103 16984
3c824109
NF
16985 switch (op) {
16986 case POOL16A:
16987 {
16988 int rd = mmreg(uMIPS_RD(ctx->opcode));
16989 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16990 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16991 uint32_t opc = 0;
16992
16993 switch (ctx->opcode & 0x1) {
16994 case ADDU16:
16995 opc = OPC_ADDU;
16996 break;
16997 case SUBU16:
16998 opc = OPC_SUBU;
16999 break;
17000 }
ed7ce6c0
YK
17001 if (ctx->insn_flags & ISA_MIPS32R6) {
17002 /* In the Release 6 the register number location in
17003 * the instruction encoding has changed.
17004 */
17005 gen_arith(ctx, opc, rs1, rd, rs2);
17006 } else {
17007 gen_arith(ctx, opc, rd, rs1, rs2);
17008 }
3c824109
NF
17009 }
17010 break;
17011 case POOL16B:
17012 {
17013 int rd = mmreg(uMIPS_RD(ctx->opcode));
17014 int rs = mmreg(uMIPS_RS(ctx->opcode));
17015 int amount = (ctx->opcode >> 1) & 0x7;
17016 uint32_t opc = 0;
17017 amount = amount == 0 ? 8 : amount;
17018
17019 switch (ctx->opcode & 0x1) {
17020 case SLL16:
17021 opc = OPC_SLL;
17022 break;
17023 case SRL16:
17024 opc = OPC_SRL;
17025 break;
17026 }
17027
d75c135e 17028 gen_shift_imm(ctx, opc, rd, rs, amount);
3c824109
NF
17029 }
17030 break;
17031 case POOL16C:
ed7ce6c0
YK
17032 if (ctx->insn_flags & ISA_MIPS32R6) {
17033 gen_pool16c_r6_insn(ctx);
17034 } else {
17035 gen_pool16c_insn(ctx);
17036 }
3c824109
NF
17037 break;
17038 case LWGP16:
17039 {
17040 int rd = mmreg(uMIPS_RD(ctx->opcode));
17041 int rb = 28; /* GP */
17042 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17043
d75c135e 17044 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17045 }
17046 break;
17047 case POOL16F:
9e8f441a 17048 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 17049 if (ctx->opcode & 1) {
9c708c7f 17050 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17051 } else {
17052 /* MOVEP */
17053 int enc_dest = uMIPS_RD(ctx->opcode);
17054 int enc_rt = uMIPS_RS2(ctx->opcode);
17055 int enc_rs = uMIPS_RS1(ctx->opcode);
ed7ce6c0 17056 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
3c824109
NF
17057 }
17058 break;
17059 case LBU16:
17060 {
17061 int rd = mmreg(uMIPS_RD(ctx->opcode));
17062 int rb = mmreg(uMIPS_RS(ctx->opcode));
17063 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17064 offset = (offset == 0xf ? -1 : offset);
17065
d75c135e 17066 gen_ld(ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
17067 }
17068 break;
17069 case LHU16:
17070 {
17071 int rd = mmreg(uMIPS_RD(ctx->opcode));
17072 int rb = mmreg(uMIPS_RS(ctx->opcode));
17073 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17074
d75c135e 17075 gen_ld(ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
17076 }
17077 break;
17078 case LWSP16:
17079 {
17080 int rd = (ctx->opcode >> 5) & 0x1f;
17081 int rb = 29; /* SP */
17082 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17083
d75c135e 17084 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17085 }
17086 break;
17087 case LW16:
17088 {
17089 int rd = mmreg(uMIPS_RD(ctx->opcode));
17090 int rb = mmreg(uMIPS_RS(ctx->opcode));
17091 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17092
d75c135e 17093 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
17094 }
17095 break;
17096 case SB16:
17097 {
17098 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17099 int rb = mmreg(uMIPS_RS(ctx->opcode));
17100 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17101
5c13fdfd 17102 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
17103 }
17104 break;
17105 case SH16:
17106 {
17107 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17108 int rb = mmreg(uMIPS_RS(ctx->opcode));
17109 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17110
5c13fdfd 17111 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
17112 }
17113 break;
17114 case SWSP16:
17115 {
17116 int rd = (ctx->opcode >> 5) & 0x1f;
17117 int rb = 29; /* SP */
17118 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17119
5c13fdfd 17120 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
17121 }
17122 break;
17123 case SW16:
17124 {
17125 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17126 int rb = mmreg(uMIPS_RS(ctx->opcode));
17127 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17128
5c13fdfd 17129 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
17130 }
17131 break;
17132 case MOVE16:
17133 {
17134 int rd = uMIPS_RD5(ctx->opcode);
17135 int rs = uMIPS_RS5(ctx->opcode);
17136
7215d7e7 17137 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
3c824109
NF
17138 }
17139 break;
17140 case ANDI16:
d75c135e 17141 gen_andi16(ctx);
3c824109
NF
17142 break;
17143 case POOL16D:
17144 switch (ctx->opcode & 0x1) {
17145 case ADDIUS5:
d75c135e 17146 gen_addius5(ctx);
3c824109
NF
17147 break;
17148 case ADDIUSP:
d75c135e 17149 gen_addiusp(ctx);
3c824109
NF
17150 break;
17151 }
17152 break;
17153 case POOL16E:
17154 switch (ctx->opcode & 0x1) {
17155 case ADDIUR2:
d75c135e 17156 gen_addiur2(ctx);
3c824109
NF
17157 break;
17158 case ADDIUR1SP:
d75c135e 17159 gen_addiur1sp(ctx);
3c824109
NF
17160 break;
17161 }
17162 break;
65935f07 17163 case B16: /* BC16 */
3c824109 17164 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
65935f07
YK
17165 sextract32(ctx->opcode, 0, 10) << 1,
17166 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
3c824109 17167 break;
65935f07
YK
17168 case BNEZ16: /* BNEZC16 */
17169 case BEQZ16: /* BEQZC16 */
3c824109
NF
17170 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17171 mmreg(uMIPS_RD(ctx->opcode)),
65935f07
YK
17172 0, sextract32(ctx->opcode, 0, 7) << 1,
17173 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17174
3c824109
NF
17175 break;
17176 case LI16:
17177 {
17178 int reg = mmreg(uMIPS_RD(ctx->opcode));
17179 int imm = ZIMM(ctx->opcode, 0, 7);
17180
17181 imm = (imm == 0x7f ? -1 : imm);
17182 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17183 }
17184 break;
3c824109 17185 case RES_29:
3c824109 17186 case RES_31:
3c824109 17187 case RES_39:
9c708c7f 17188 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
17189 break;
17190 default:
f60eeb0c 17191 decode_micromips32_opc(env, ctx);
3c824109
NF
17192 return 4;
17193 }
17194
17195 return 2;
17196}
17197
261c95a0
YK
17198/*
17199 *
17200 * nanoMIPS opcodes
17201 *
17202 */
17203
17204/* MAJOR, P16, and P32 pools opcodes */
17205enum {
17206 NM_P_ADDIU = 0x00,
17207 NM_ADDIUPC = 0x01,
17208 NM_MOVE_BALC = 0x02,
17209 NM_P16_MV = 0x04,
17210 NM_LW16 = 0x05,
17211 NM_BC16 = 0x06,
17212 NM_P16_SR = 0x07,
17213
17214 NM_POOL32A = 0x08,
17215 NM_P_BAL = 0x0a,
17216 NM_P16_SHIFT = 0x0c,
17217 NM_LWSP16 = 0x0d,
17218 NM_BALC16 = 0x0e,
17219 NM_P16_4X4 = 0x0f,
17220
17221 NM_P_GP_W = 0x10,
17222 NM_P_GP_BH = 0x11,
17223 NM_P_J = 0x12,
17224 NM_P16C = 0x14,
17225 NM_LWGP16 = 0x15,
17226 NM_P16_LB = 0x17,
17227
17228 NM_P48I = 0x18,
17229 NM_P16_A1 = 0x1c,
17230 NM_LW4X4 = 0x1d,
17231 NM_P16_LH = 0x1f,
17232
17233 NM_P_U12 = 0x20,
17234 NM_P_LS_U12 = 0x21,
17235 NM_P_BR1 = 0x22,
17236 NM_P16_A2 = 0x24,
17237 NM_SW16 = 0x25,
17238 NM_BEQZC16 = 0x26,
17239
17240 NM_POOL32F = 0x28,
17241 NM_P_LS_S9 = 0x29,
17242 NM_P_BR2 = 0x2a,
17243
17244 NM_P16_ADDU = 0x2c,
17245 NM_SWSP16 = 0x2d,
17246 NM_BNEZC16 = 0x2e,
17247 NM_MOVEP = 0x2f,
17248
17249 NM_POOL32S = 0x30,
17250 NM_P_BRI = 0x32,
17251 NM_LI16 = 0x34,
17252 NM_SWGP16 = 0x35,
17253 NM_P16_BR = 0x36,
17254
17255 NM_P_LUI = 0x38,
17256 NM_ANDI16 = 0x3c,
17257 NM_SW4X4 = 0x3d,
17258 NM_MOVEPREV = 0x3f,
17259};
17260
17261/* POOL32A instruction pool */
17262enum {
17263 NM_POOL32A0 = 0x00,
17264 NM_SPECIAL2 = 0x01,
17265 NM_COP2_1 = 0x02,
17266 NM_UDI = 0x03,
17267 NM_POOL32A5 = 0x05,
17268 NM_POOL32A7 = 0x07,
17269};
17270
17271/* P.GP.W instruction pool */
17272enum {
17273 NM_ADDIUGP_W = 0x00,
17274 NM_LWGP = 0x02,
17275 NM_SWGP = 0x03,
17276};
17277
17278/* P48I instruction pool */
17279enum {
17280 NM_LI48 = 0x00,
17281 NM_ADDIU48 = 0x01,
17282 NM_ADDIUGP48 = 0x02,
17283 NM_ADDIUPC48 = 0x03,
17284 NM_LWPC48 = 0x0b,
17285 NM_SWPC48 = 0x0f,
17286};
17287
17288/* P.U12 instruction pool */
17289enum {
17290 NM_ORI = 0x00,
17291 NM_XORI = 0x01,
17292 NM_ANDI = 0x02,
17293 NM_P_SR = 0x03,
17294 NM_SLTI = 0x04,
17295 NM_SLTIU = 0x05,
17296 NM_SEQI = 0x06,
17297 NM_ADDIUNEG = 0x08,
17298 NM_P_SHIFT = 0x0c,
17299 NM_P_ROTX = 0x0d,
17300 NM_P_INS = 0x0e,
17301 NM_P_EXT = 0x0f,
17302};
17303
17304/* POOL32F instruction pool */
17305enum {
17306 NM_POOL32F_0 = 0x00,
17307 NM_POOL32F_3 = 0x03,
17308 NM_POOL32F_5 = 0x05,
17309};
17310
17311/* POOL32S instruction pool */
17312enum {
17313 NM_POOL32S_0 = 0x00,
17314 NM_POOL32S_4 = 0x04,
17315};
17316
17317/* P.LUI instruction pool */
17318enum {
17319 NM_LUI = 0x00,
17320 NM_ALUIPC = 0x01,
17321};
17322
17323/* P.GP.BH instruction pool */
17324enum {
17325 NM_LBGP = 0x00,
17326 NM_SBGP = 0x01,
17327 NM_LBUGP = 0x02,
17328 NM_ADDIUGP_B = 0x03,
17329 NM_P_GP_LH = 0x04,
17330 NM_P_GP_SH = 0x05,
17331 NM_P_GP_CP1 = 0x06,
17332};
17333
17334/* P.LS.U12 instruction pool */
17335enum {
17336 NM_LB = 0x00,
17337 NM_SB = 0x01,
17338 NM_LBU = 0x02,
17339 NM_P_PREFU12 = 0x03,
17340 NM_LH = 0x04,
17341 NM_SH = 0x05,
17342 NM_LHU = 0x06,
17343 NM_LWU = 0x07,
17344 NM_LW = 0x08,
17345 NM_SW = 0x09,
17346 NM_LWC1 = 0x0a,
17347 NM_SWC1 = 0x0b,
17348 NM_LDC1 = 0x0e,
17349 NM_SDC1 = 0x0f,
17350};
17351
17352/* P.LS.S9 instruction pool */
17353enum {
17354 NM_P_LS_S0 = 0x00,
17355 NM_P_LS_S1 = 0x01,
17356 NM_P_LS_E0 = 0x02,
17357 NM_P_LS_WM = 0x04,
17358 NM_P_LS_UAWM = 0x05,
17359};
17360
17361/* P.BAL instruction pool */
17362enum {
17363 NM_BC = 0x00,
17364 NM_BALC = 0x01,
17365};
17366
17367/* P.J instruction pool */
17368enum {
17369 NM_JALRC = 0x00,
17370 NM_JALRC_HB = 0x01,
17371 NM_P_BALRSC = 0x08,
17372};
17373
17374/* P.BR1 instruction pool */
17375enum {
17376 NM_BEQC = 0x00,
17377 NM_P_BR3A = 0x01,
17378 NM_BGEC = 0x02,
17379 NM_BGEUC = 0x03,
17380};
17381
17382/* P.BR2 instruction pool */
17383enum {
17384 NM_BNEC = 0x00,
17385 NM_BLTC = 0x02,
17386 NM_BLTUC = 0x03,
17387};
17388
17389/* P.BRI instruction pool */
17390enum {
17391 NM_BEQIC = 0x00,
17392 NM_BBEQZC = 0x01,
17393 NM_BGEIC = 0x02,
17394 NM_BGEIUC = 0x03,
17395 NM_BNEIC = 0x04,
17396 NM_BBNEZC = 0x05,
17397 NM_BLTIC = 0x06,
17398 NM_BLTIUC = 0x07,
17399};
17400
17401/* P16.SHIFT instruction pool */
17402enum {
17403 NM_SLL16 = 0x00,
17404 NM_SRL16 = 0x01,
17405};
17406
17407/* POOL16C instruction pool */
17408enum {
17409 NM_POOL16C_0 = 0x00,
17410 NM_LWXS16 = 0x01,
17411};
17412
17413/* P16.A1 instruction pool */
17414enum {
17415 NM_ADDIUR1SP = 0x01,
17416};
17417
17418/* P16.A2 instruction pool */
17419enum {
17420 NM_ADDIUR2 = 0x00,
17421 NM_P_ADDIURS5 = 0x01,
17422};
17423
17424/* P16.ADDU instruction pool */
17425enum {
17426 NM_ADDU16 = 0x00,
17427 NM_SUBU16 = 0x01,
17428};
17429
17430/* P16.SR instruction pool */
17431enum {
17432 NM_SAVE16 = 0x00,
17433 NM_RESTORE_JRC16 = 0x01,
17434};
17435
17436/* P16.4X4 instruction pool */
17437enum {
17438 NM_ADDU4X4 = 0x00,
17439 NM_MUL4X4 = 0x01,
17440};
17441
17442/* P16.LB instruction pool */
17443enum {
17444 NM_LB16 = 0x00,
17445 NM_SB16 = 0x01,
17446 NM_LBU16 = 0x02,
17447};
17448
17449/* P16.LH instruction pool */
17450enum {
17451 NM_LH16 = 0x00,
17452 NM_SH16 = 0x01,
17453 NM_LHU16 = 0x02,
17454};
17455
17456/* P.RI instruction pool */
17457enum {
17458 NM_SIGRIE = 0x00,
17459 NM_P_SYSCALL = 0x01,
17460 NM_BREAK = 0x02,
17461 NM_SDBBP = 0x03,
17462};
17463
17464/* POOL32A0 instruction pool */
17465enum {
17466 NM_P_TRAP = 0x00,
17467 NM_SEB = 0x01,
17468 NM_SLLV = 0x02,
17469 NM_MUL = 0x03,
17470 NM_MFC0 = 0x06,
17471 NM_MFHC0 = 0x07,
17472 NM_SEH = 0x09,
17473 NM_SRLV = 0x0a,
17474 NM_MUH = 0x0b,
17475 NM_MTC0 = 0x0e,
17476 NM_MTHC0 = 0x0f,
17477 NM_SRAV = 0x12,
17478 NM_MULU = 0x13,
17479 NM_ROTRV = 0x1a,
17480 NM_MUHU = 0x1b,
17481 NM_ADD = 0x22,
17482 NM_DIV = 0x23,
17483 NM_ADDU = 0x2a,
17484 NM_MOD = 0x2b,
17485 NM_SUB = 0x32,
17486 NM_DIVU = 0x33,
17487 NM_RDHWR = 0x38,
17488 NM_SUBU = 0x3a,
17489 NM_MODU = 0x3b,
17490 NM_P_CMOVE = 0x42,
17491 NM_FORK = 0x45,
17492 NM_MFTR = 0x46,
17493 NM_MFHTR = 0x47,
17494 NM_AND = 0x4a,
17495 NM_YIELD = 0x4d,
17496 NM_MTTR = 0x4e,
17497 NM_MTHTR = 0x4f,
17498 NM_OR = 0x52,
17499 NM_D_E_MT_VPE = 0x56,
17500 NM_NOR = 0x5a,
17501 NM_XOR = 0x62,
17502 NM_SLT = 0x6a,
17503 NM_P_SLTU = 0x72,
17504 NM_SOV = 0x7a,
17505};
17506
ba1e8117
AM
17507/* CRC32 instruction pool */
17508enum {
17509 NM_CRC32B = 0x00,
17510 NM_CRC32H = 0x01,
17511 NM_CRC32W = 0x02,
17512 NM_CRC32CB = 0x04,
17513 NM_CRC32CH = 0x05,
17514 NM_CRC32CW = 0x06,
17515};
17516
b3979b6f
SM
17517/* POOL32A5 instruction pool */
17518enum {
17519 NM_CMP_EQ_PH = 0x00,
17520 NM_CMP_LT_PH = 0x08,
17521 NM_CMP_LE_PH = 0x10,
17522 NM_CMPGU_EQ_QB = 0x18,
17523 NM_CMPGU_LT_QB = 0x20,
17524 NM_CMPGU_LE_QB = 0x28,
17525 NM_CMPGDU_EQ_QB = 0x30,
17526 NM_CMPGDU_LT_QB = 0x38,
17527 NM_CMPGDU_LE_QB = 0x40,
17528 NM_CMPU_EQ_QB = 0x48,
17529 NM_CMPU_LT_QB = 0x50,
17530 NM_CMPU_LE_QB = 0x58,
17531 NM_ADDQ_S_W = 0x60,
17532 NM_SUBQ_S_W = 0x68,
17533 NM_ADDSC = 0x70,
17534 NM_ADDWC = 0x78,
17535
17536 NM_ADDQ_S_PH = 0x01,
17537 NM_ADDQH_R_PH = 0x09,
17538 NM_ADDQH_R_W = 0x11,
17539 NM_ADDU_S_QB = 0x19,
17540 NM_ADDU_S_PH = 0x21,
17541 NM_ADDUH_R_QB = 0x29,
17542 NM_SHRAV_R_PH = 0x31,
17543 NM_SHRAV_R_QB = 0x39,
17544 NM_SUBQ_S_PH = 0x41,
17545 NM_SUBQH_R_PH = 0x49,
17546 NM_SUBQH_R_W = 0x51,
17547 NM_SUBU_S_QB = 0x59,
17548 NM_SUBU_S_PH = 0x61,
17549 NM_SUBUH_R_QB = 0x69,
17550 NM_SHLLV_S_PH = 0x71,
17551 NM_PRECR_SRA_R_PH_W = 0x79,
17552
17553 NM_MULEU_S_PH_QBL = 0x12,
17554 NM_MULEU_S_PH_QBR = 0x1a,
17555 NM_MULQ_RS_PH = 0x22,
17556 NM_MULQ_S_PH = 0x2a,
17557 NM_MULQ_RS_W = 0x32,
17558 NM_MULQ_S_W = 0x3a,
17559 NM_APPEND = 0x42,
17560 NM_MODSUB = 0x52,
17561 NM_SHRAV_R_W = 0x5a,
17562 NM_SHRLV_PH = 0x62,
17563 NM_SHRLV_QB = 0x6a,
17564 NM_SHLLV_QB = 0x72,
17565 NM_SHLLV_S_W = 0x7a,
17566
17567 NM_SHILO = 0x03,
17568
17569 NM_MULEQ_S_W_PHL = 0x04,
17570 NM_MULEQ_S_W_PHR = 0x0c,
17571
17572 NM_MUL_S_PH = 0x05,
17573 NM_PRECR_QB_PH = 0x0d,
17574 NM_PRECRQ_QB_PH = 0x15,
17575 NM_PRECRQ_PH_W = 0x1d,
17576 NM_PRECRQ_RS_PH_W = 0x25,
17577 NM_PRECRQU_S_QB_PH = 0x2d,
17578 NM_PACKRL_PH = 0x35,
17579 NM_PICK_QB = 0x3d,
17580 NM_PICK_PH = 0x45,
17581
17582 NM_SHRA_R_W = 0x5e,
17583 NM_SHRA_R_PH = 0x66,
17584 NM_SHLL_S_PH = 0x76,
17585 NM_SHLL_S_W = 0x7e,
17586
17587 NM_REPL_PH = 0x07
17588};
17589
261c95a0
YK
17590/* POOL32A7 instruction pool */
17591enum {
17592 NM_P_LSX = 0x00,
17593 NM_LSA = 0x01,
17594 NM_EXTW = 0x03,
17595 NM_POOL32AXF = 0x07,
17596};
17597
17598/* P.SR instruction pool */
17599enum {
17600 NM_PP_SR = 0x00,
17601 NM_P_SR_F = 0x01,
17602};
17603
17604/* P.SHIFT instruction pool */
17605enum {
17606 NM_P_SLL = 0x00,
17607 NM_SRL = 0x02,
17608 NM_SRA = 0x04,
17609 NM_ROTR = 0x06,
17610};
17611
17612/* P.ROTX instruction pool */
17613enum {
17614 NM_ROTX = 0x00,
17615};
17616
17617/* P.INS instruction pool */
17618enum {
17619 NM_INS = 0x00,
17620};
17621
17622/* P.EXT instruction pool */
17623enum {
17624 NM_EXT = 0x00,
17625};
17626
17627/* POOL32F_0 (fmt) instruction pool */
17628enum {
17629 NM_RINT_S = 0x04,
17630 NM_RINT_D = 0x44,
17631 NM_ADD_S = 0x06,
17632 NM_SELEQZ_S = 0x07,
17633 NM_SELEQZ_D = 0x47,
17634 NM_CLASS_S = 0x0c,
17635 NM_CLASS_D = 0x4c,
17636 NM_SUB_S = 0x0e,
17637 NM_SELNEZ_S = 0x0f,
17638 NM_SELNEZ_D = 0x4f,
17639 NM_MUL_S = 0x16,
17640 NM_SEL_S = 0x17,
17641 NM_SEL_D = 0x57,
17642 NM_DIV_S = 0x1e,
17643 NM_ADD_D = 0x26,
17644 NM_SUB_D = 0x2e,
17645 NM_MUL_D = 0x36,
17646 NM_MADDF_S = 0x37,
17647 NM_MADDF_D = 0x77,
17648 NM_DIV_D = 0x3e,
17649 NM_MSUBF_S = 0x3f,
17650 NM_MSUBF_D = 0x7f,
17651};
17652
17653/* POOL32F_3 instruction pool */
17654enum {
17655 NM_MIN_FMT = 0x00,
17656 NM_MAX_FMT = 0x01,
17657 NM_MINA_FMT = 0x04,
17658 NM_MAXA_FMT = 0x05,
17659 NM_POOL32FXF = 0x07,
17660};
17661
17662/* POOL32F_5 instruction pool */
17663enum {
17664 NM_CMP_CONDN_S = 0x00,
17665 NM_CMP_CONDN_D = 0x02,
17666};
17667
17668/* P.GP.LH instruction pool */
17669enum {
17670 NM_LHGP = 0x00,
17671 NM_LHUGP = 0x01,
17672};
17673
17674/* P.GP.SH instruction pool */
17675enum {
17676 NM_SHGP = 0x00,
17677};
17678
17679/* P.GP.CP1 instruction pool */
17680enum {
17681 NM_LWC1GP = 0x00,
17682 NM_SWC1GP = 0x01,
17683 NM_LDC1GP = 0x02,
17684 NM_SDC1GP = 0x03,
17685};
17686
17687/* P.LS.S0 instruction pool */
17688enum {
17689 NM_LBS9 = 0x00,
17690 NM_LHS9 = 0x04,
17691 NM_LWS9 = 0x08,
17692 NM_LDS9 = 0x0c,
17693
17694 NM_SBS9 = 0x01,
17695 NM_SHS9 = 0x05,
17696 NM_SWS9 = 0x09,
17697 NM_SDS9 = 0x0d,
17698
17699 NM_LBUS9 = 0x02,
17700 NM_LHUS9 = 0x06,
17701 NM_LWC1S9 = 0x0a,
17702 NM_LDC1S9 = 0x0e,
17703
17704 NM_P_PREFS9 = 0x03,
17705 NM_LWUS9 = 0x07,
17706 NM_SWC1S9 = 0x0b,
17707 NM_SDC1S9 = 0x0f,
17708};
17709
17710/* P.LS.S1 instruction pool */
17711enum {
17712 NM_ASET_ACLR = 0x02,
17713 NM_UALH = 0x04,
17714 NM_UASH = 0x05,
17715 NM_CACHE = 0x07,
17716 NM_P_LL = 0x0a,
17717 NM_P_SC = 0x0b,
17718};
17719
0d30b3bb
DN
17720/* P.LS.E0 instruction pool */
17721enum {
17722 NM_LBE = 0x00,
17723 NM_SBE = 0x01,
17724 NM_LBUE = 0x02,
17725 NM_P_PREFE = 0x03,
17726 NM_LHE = 0x04,
17727 NM_SHE = 0x05,
17728 NM_LHUE = 0x06,
17729 NM_CACHEE = 0x07,
17730 NM_LWE = 0x08,
17731 NM_SWE = 0x09,
17732 NM_P_LLE = 0x0a,
17733 NM_P_SCE = 0x0b,
17734};
17735
17736/* P.PREFE instruction pool */
17737enum {
17738 NM_SYNCIE = 0x00,
17739 NM_PREFE = 0x01,
17740};
17741
17742/* P.LLE instruction pool */
17743enum {
17744 NM_LLE = 0x00,
17745 NM_LLWPE = 0x01,
17746};
17747
17748/* P.SCE instruction pool */
17749enum {
17750 NM_SCE = 0x00,
17751 NM_SCWPE = 0x01,
17752};
17753
261c95a0
YK
17754/* P.LS.WM instruction pool */
17755enum {
17756 NM_LWM = 0x00,
17757 NM_SWM = 0x01,
17758};
17759
17760/* P.LS.UAWM instruction pool */
17761enum {
17762 NM_UALWM = 0x00,
17763 NM_UASWM = 0x01,
17764};
17765
17766/* P.BR3A instruction pool */
17767enum {
17768 NM_BC1EQZC = 0x00,
17769 NM_BC1NEZC = 0x01,
17770 NM_BC2EQZC = 0x02,
17771 NM_BC2NEZC = 0x03,
17772 NM_BPOSGE32C = 0x04,
17773};
17774
17775/* P16.RI instruction pool */
17776enum {
17777 NM_P16_SYSCALL = 0x01,
17778 NM_BREAK16 = 0x02,
17779 NM_SDBBP16 = 0x03,
17780};
17781
17782/* POOL16C_0 instruction pool */
17783enum {
17784 NM_POOL16C_00 = 0x00,
17785};
17786
17787/* P16.JRC instruction pool */
17788enum {
17789 NM_JRC = 0x00,
17790 NM_JALRC16 = 0x01,
17791};
17792
17793/* P.SYSCALL instruction pool */
17794enum {
17795 NM_SYSCALL = 0x00,
17796 NM_HYPCALL = 0x01,
17797};
17798
17799/* P.TRAP instruction pool */
17800enum {
17801 NM_TEQ = 0x00,
17802 NM_TNE = 0x01,
17803};
17804
17805/* P.CMOVE instruction pool */
17806enum {
17807 NM_MOVZ = 0x00,
17808 NM_MOVN = 0x01,
17809};
17810
17811/* POOL32Axf instruction pool */
17812enum {
b3979b6f
SM
17813 NM_POOL32AXF_1 = 0x01,
17814 NM_POOL32AXF_2 = 0x02,
261c95a0
YK
17815 NM_POOL32AXF_4 = 0x04,
17816 NM_POOL32AXF_5 = 0x05,
b3979b6f
SM
17817 NM_POOL32AXF_7 = 0x07,
17818};
17819
17820/* POOL32Axf_1 instruction pool */
17821enum {
17822 NM_POOL32AXF_1_0 = 0x00,
17823 NM_POOL32AXF_1_1 = 0x01,
17824 NM_POOL32AXF_1_3 = 0x03,
17825 NM_POOL32AXF_1_4 = 0x04,
17826 NM_POOL32AXF_1_5 = 0x05,
17827 NM_POOL32AXF_1_7 = 0x07,
17828};
17829
17830/* POOL32Axf_2 instruction pool */
17831enum {
17832 NM_POOL32AXF_2_0_7 = 0x00,
17833 NM_POOL32AXF_2_8_15 = 0x01,
17834 NM_POOL32AXF_2_16_23 = 0x02,
17835 NM_POOL32AXF_2_24_31 = 0x03,
17836};
17837
17838/* POOL32Axf_7 instruction pool */
17839enum {
17840 NM_SHRA_R_QB = 0x0,
17841 NM_SHRL_PH = 0x1,
17842 NM_REPL_QB = 0x2,
17843};
17844
17845/* POOL32Axf_1_0 instruction pool */
17846enum {
17847 NM_MFHI = 0x0,
17848 NM_MFLO = 0x1,
17849 NM_MTHI = 0x2,
17850 NM_MTLO = 0x3,
17851};
17852
17853/* POOL32Axf_1_1 instruction pool */
17854enum {
17855 NM_MTHLIP = 0x0,
17856 NM_SHILOV = 0x1,
17857};
17858
17859/* POOL32Axf_1_3 instruction pool */
17860enum {
17861 NM_RDDSP = 0x0,
17862 NM_WRDSP = 0x1,
17863 NM_EXTP = 0x2,
17864 NM_EXTPDP = 0x3,
17865};
17866
17867/* POOL32Axf_1_4 instruction pool */
17868enum {
17869 NM_SHLL_QB = 0x0,
17870 NM_SHRL_QB = 0x1,
17871};
17872
17873/* POOL32Axf_1_5 instruction pool */
17874enum {
17875 NM_MAQ_S_W_PHR = 0x0,
17876 NM_MAQ_S_W_PHL = 0x1,
17877 NM_MAQ_SA_W_PHR = 0x2,
17878 NM_MAQ_SA_W_PHL = 0x3,
17879};
17880
17881/* POOL32Axf_1_7 instruction pool */
17882enum {
17883 NM_EXTR_W = 0x0,
17884 NM_EXTR_R_W = 0x1,
17885 NM_EXTR_RS_W = 0x2,
17886 NM_EXTR_S_H = 0x3,
17887};
17888
17889/* POOL32Axf_2_0_7 instruction pool */
17890enum {
17891 NM_DPA_W_PH = 0x0,
17892 NM_DPAQ_S_W_PH = 0x1,
17893 NM_DPS_W_PH = 0x2,
17894 NM_DPSQ_S_W_PH = 0x3,
17895 NM_BALIGN = 0x4,
17896 NM_MADD = 0x5,
17897 NM_MULT = 0x6,
17898 NM_EXTRV_W = 0x7,
17899};
17900
17901/* POOL32Axf_2_8_15 instruction pool */
17902enum {
17903 NM_DPAX_W_PH = 0x0,
17904 NM_DPAQ_SA_L_W = 0x1,
17905 NM_DPSX_W_PH = 0x2,
17906 NM_DPSQ_SA_L_W = 0x3,
17907 NM_MADDU = 0x5,
17908 NM_MULTU = 0x6,
17909 NM_EXTRV_R_W = 0x7,
17910};
17911
17912/* POOL32Axf_2_16_23 instruction pool */
17913enum {
17914 NM_DPAU_H_QBL = 0x0,
17915 NM_DPAQX_S_W_PH = 0x1,
17916 NM_DPSU_H_QBL = 0x2,
17917 NM_DPSQX_S_W_PH = 0x3,
17918 NM_EXTPV = 0x4,
17919 NM_MSUB = 0x5,
17920 NM_MULSA_W_PH = 0x6,
17921 NM_EXTRV_RS_W = 0x7,
17922};
17923
17924/* POOL32Axf_2_24_31 instruction pool */
17925enum {
17926 NM_DPAU_H_QBR = 0x0,
17927 NM_DPAQX_SA_W_PH = 0x1,
17928 NM_DPSU_H_QBR = 0x2,
17929 NM_DPSQX_SA_W_PH = 0x3,
17930 NM_EXTPDPV = 0x4,
17931 NM_MSUBU = 0x5,
17932 NM_MULSAQ_S_W_PH = 0x6,
17933 NM_EXTRV_S_H = 0x7,
261c95a0
YK
17934};
17935
17936/* POOL32Axf_{4, 5} instruction pool */
17937enum {
17938 NM_CLO = 0x25,
17939 NM_CLZ = 0x2d,
17940
17941 NM_TLBP = 0x01,
17942 NM_TLBR = 0x09,
17943 NM_TLBWI = 0x11,
17944 NM_TLBWR = 0x19,
17945 NM_TLBINV = 0x03,
17946 NM_TLBINVF = 0x0b,
17947 NM_DI = 0x23,
17948 NM_EI = 0x2b,
17949 NM_RDPGPR = 0x70,
17950 NM_WRPGPR = 0x78,
17951 NM_WAIT = 0x61,
17952 NM_DERET = 0x71,
17953 NM_ERETX = 0x79,
b3979b6f
SM
17954
17955 /* nanoMIPS DSP instructions */
17956 NM_ABSQ_S_QB = 0x00,
17957 NM_ABSQ_S_PH = 0x08,
17958 NM_ABSQ_S_W = 0x10,
17959 NM_PRECEQ_W_PHL = 0x28,
17960 NM_PRECEQ_W_PHR = 0x30,
17961 NM_PRECEQU_PH_QBL = 0x38,
17962 NM_PRECEQU_PH_QBR = 0x48,
17963 NM_PRECEU_PH_QBL = 0x58,
17964 NM_PRECEU_PH_QBR = 0x68,
17965 NM_PRECEQU_PH_QBLA = 0x39,
17966 NM_PRECEQU_PH_QBRA = 0x49,
17967 NM_PRECEU_PH_QBLA = 0x59,
17968 NM_PRECEU_PH_QBRA = 0x69,
17969 NM_REPLV_PH = 0x01,
17970 NM_REPLV_QB = 0x09,
17971 NM_BITREV = 0x18,
17972 NM_INSV = 0x20,
17973 NM_RADDU_W_QB = 0x78,
17974
17975 NM_BITSWAP = 0x05,
17976 NM_WSBH = 0x3d,
261c95a0
YK
17977};
17978
17979/* PP.SR instruction pool */
17980enum {
17981 NM_SAVE = 0x00,
17982 NM_RESTORE = 0x02,
17983 NM_RESTORE_JRC = 0x03,
17984};
17985
17986/* P.SR.F instruction pool */
17987enum {
17988 NM_SAVEF = 0x00,
17989 NM_RESTOREF = 0x01,
17990};
17991
17992/* P16.SYSCALL instruction pool */
17993enum {
17994 NM_SYSCALL16 = 0x00,
17995 NM_HYPCALL16 = 0x01,
17996};
17997
17998/* POOL16C_00 instruction pool */
17999enum {
18000 NM_NOT16 = 0x00,
18001 NM_XOR16 = 0x01,
18002 NM_AND16 = 0x02,
18003 NM_OR16 = 0x03,
18004};
18005
18006/* PP.LSX and PP.LSXS instruction pool */
18007enum {
18008 NM_LBX = 0x00,
18009 NM_LHX = 0x04,
18010 NM_LWX = 0x08,
18011 NM_LDX = 0x0c,
18012
18013 NM_SBX = 0x01,
18014 NM_SHX = 0x05,
18015 NM_SWX = 0x09,
18016 NM_SDX = 0x0d,
18017
18018 NM_LBUX = 0x02,
18019 NM_LHUX = 0x06,
18020 NM_LWC1X = 0x0a,
18021 NM_LDC1X = 0x0e,
18022
18023 NM_LWUX = 0x07,
18024 NM_SWC1X = 0x0b,
18025 NM_SDC1X = 0x0f,
18026
18027 NM_LHXS = 0x04,
18028 NM_LWXS = 0x08,
18029 NM_LDXS = 0x0c,
18030
18031 NM_SHXS = 0x05,
18032 NM_SWXS = 0x09,
18033 NM_SDXS = 0x0d,
18034
18035 NM_LHUXS = 0x06,
18036 NM_LWC1XS = 0x0a,
18037 NM_LDC1XS = 0x0e,
18038
18039 NM_LWUXS = 0x07,
18040 NM_SWC1XS = 0x0b,
18041 NM_SDC1XS = 0x0f,
18042};
18043
18044/* ERETx instruction pool */
18045enum {
18046 NM_ERET = 0x00,
18047 NM_ERETNC = 0x01,
18048};
18049
18050/* POOL32FxF_{0, 1} insturction pool */
18051enum {
18052 NM_CFC1 = 0x40,
18053 NM_CTC1 = 0x60,
18054 NM_MFC1 = 0x80,
18055 NM_MTC1 = 0xa0,
18056 NM_MFHC1 = 0xc0,
18057 NM_MTHC1 = 0xe0,
18058
18059 NM_CVT_S_PL = 0x84,
18060 NM_CVT_S_PU = 0xa4,
18061
18062 NM_CVT_L_S = 0x004,
18063 NM_CVT_L_D = 0x104,
18064 NM_CVT_W_S = 0x024,
18065 NM_CVT_W_D = 0x124,
18066
18067 NM_RSQRT_S = 0x008,
18068 NM_RSQRT_D = 0x108,
18069
18070 NM_SQRT_S = 0x028,
18071 NM_SQRT_D = 0x128,
18072
18073 NM_RECIP_S = 0x048,
18074 NM_RECIP_D = 0x148,
18075
18076 NM_FLOOR_L_S = 0x00c,
18077 NM_FLOOR_L_D = 0x10c,
18078
18079 NM_FLOOR_W_S = 0x02c,
18080 NM_FLOOR_W_D = 0x12c,
18081
18082 NM_CEIL_L_S = 0x04c,
18083 NM_CEIL_L_D = 0x14c,
18084 NM_CEIL_W_S = 0x06c,
18085 NM_CEIL_W_D = 0x16c,
18086 NM_TRUNC_L_S = 0x08c,
18087 NM_TRUNC_L_D = 0x18c,
18088 NM_TRUNC_W_S = 0x0ac,
18089 NM_TRUNC_W_D = 0x1ac,
18090 NM_ROUND_L_S = 0x0cc,
18091 NM_ROUND_L_D = 0x1cc,
18092 NM_ROUND_W_S = 0x0ec,
18093 NM_ROUND_W_D = 0x1ec,
18094
18095 NM_MOV_S = 0x01,
18096 NM_MOV_D = 0x81,
18097 NM_ABS_S = 0x0d,
18098 NM_ABS_D = 0x8d,
18099 NM_NEG_S = 0x2d,
18100 NM_NEG_D = 0xad,
18101 NM_CVT_D_S = 0x04d,
18102 NM_CVT_D_W = 0x0cd,
18103 NM_CVT_D_L = 0x14d,
18104 NM_CVT_S_D = 0x06d,
18105 NM_CVT_S_W = 0x0ed,
18106 NM_CVT_S_L = 0x16d,
18107};
18108
18109/* P.LL instruction pool */
18110enum {
18111 NM_LL = 0x00,
18112 NM_LLWP = 0x01,
18113};
18114
18115/* P.SC instruction pool */
18116enum {
18117 NM_SC = 0x00,
18118 NM_SCWP = 0x01,
18119};
18120
18121/* P.DVP instruction pool */
18122enum {
18123 NM_DVP = 0x00,
18124 NM_EVP = 0x01,
18125};
18126
c533c0f4
AM
18127
18128/*
18129 *
18130 * nanoMIPS decoding engine
18131 *
18132 */
18133
6bfa9f4c
AM
18134
18135/* extraction utilities */
18136
18137#define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18138#define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18139#define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18140#define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18141#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18142#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18143
ea4ca3c2
YK
18144/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18145static inline int decode_gpr_gpr3(int r)
18146{
18147 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18148
18149 return map[r & 0x7];
18150}
18151
8bdb7029
YK
18152/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18153static inline int decode_gpr_gpr3_src_store(int r)
18154{
18155 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18156
18157 return map[r & 0x7];
18158}
18159
ea4ca3c2
YK
18160/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18161static inline int decode_gpr_gpr4(int r)
18162{
18163 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18164 16, 17, 18, 19, 20, 21, 22, 23 };
18165
18166 return map[r & 0xf];
18167}
18168
8bdb7029
YK
18169/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18170static inline int decode_gpr_gpr4_zero(int r)
18171{
18172 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18173 16, 17, 18, 19, 20, 21, 22, 23 };
18174
18175 return map[r & 0xf];
18176}
18177
6bfa9f4c 18178
80845edf
YK
18179/* extraction utilities */
18180
18181#define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18182#define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18183#define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18184#define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18185#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18186#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18187
18188
bf0718c5
SM
18189static void gen_adjust_sp(DisasContext *ctx, int u)
18190{
18191 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18192}
18193
18194static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18195 uint8_t gp, uint16_t u)
18196{
18197 int counter = 0;
18198 TCGv va = tcg_temp_new();
18199 TCGv t0 = tcg_temp_new();
18200
18201 while (counter != count) {
18202 bool use_gp = gp && (counter == count - 1);
18203 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18204 int this_offset = -((counter + 1) << 2);
18205 gen_base_offset_addr(ctx, va, 29, this_offset);
18206 gen_load_gpr(t0, this_rt);
18207 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18208 (MO_TEUL | ctx->default_tcg_memop_mask));
18209 counter++;
18210 }
18211
18212 /* adjust stack pointer */
18213 gen_adjust_sp(ctx, -u);
18214
18215 tcg_temp_free(t0);
18216 tcg_temp_free(va);
18217}
18218
18219static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18220 uint8_t gp, uint16_t u)
18221{
18222 int counter = 0;
18223 TCGv va = tcg_temp_new();
18224 TCGv t0 = tcg_temp_new();
18225
18226 while (counter != count) {
18227 bool use_gp = gp && (counter == count - 1);
18228 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18229 int this_offset = u - ((counter + 1) << 2);
18230 gen_base_offset_addr(ctx, va, 29, this_offset);
18231 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18232 ctx->default_tcg_memop_mask);
18233 tcg_gen_ext32s_tl(t0, t0);
18234 gen_store_gpr(t0, this_rt);
18235 counter++;
18236 }
18237
18238 /* adjust stack pointer */
18239 gen_adjust_sp(ctx, u);
18240
18241 tcg_temp_free(t0);
18242 tcg_temp_free(va);
18243}
18244
80845edf
YK
18245static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18246{
18247 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
18248 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
18249
18250 switch (extract32(ctx->opcode, 2, 2)) {
18251 case NM_NOT16:
18252 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18253 break;
18254 case NM_AND16:
18255 gen_logic(ctx, OPC_AND, rt, rt, rs);
18256 break;
18257 case NM_XOR16:
18258 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18259 break;
18260 case NM_OR16:
18261 gen_logic(ctx, OPC_OR, rt, rt, rs);
18262 break;
18263 }
18264}
18265
0a1a6ed7 18266static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
e0cf0e65
YK
18267{
18268 int rt = extract32(ctx->opcode, 21, 5);
18269 int rs = extract32(ctx->opcode, 16, 5);
18270 int rd = extract32(ctx->opcode, 11, 5);
18271
18272 switch (extract32(ctx->opcode, 3, 7)) {
18273 case NM_P_TRAP:
18274 switch (extract32(ctx->opcode, 10, 1)) {
18275 case NM_TEQ:
fb32f8c8 18276 check_nms(ctx);
e0cf0e65
YK
18277 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18278 break;
18279 case NM_TNE:
fb32f8c8 18280 check_nms(ctx);
e0cf0e65
YK
18281 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18282 break;
18283 }
18284 break;
18285 case NM_RDHWR:
fb32f8c8 18286 check_nms(ctx);
e0cf0e65
YK
18287 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18288 break;
18289 case NM_SEB:
fb32f8c8 18290 check_nms(ctx);
e0cf0e65
YK
18291 gen_bshfl(ctx, OPC_SEB, rs, rt);
18292 break;
18293 case NM_SEH:
18294 gen_bshfl(ctx, OPC_SEH, rs, rt);
18295 break;
18296 case NM_SLLV:
18297 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18298 break;
18299 case NM_SRLV:
18300 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18301 break;
18302 case NM_SRAV:
18303 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18304 break;
18305 case NM_ROTRV:
18306 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18307 break;
18308 case NM_ADD:
18309 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18310 break;
18311 case NM_ADDU:
18312 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18313 break;
18314 case NM_SUB:
fb32f8c8 18315 check_nms(ctx);
e0cf0e65
YK
18316 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18317 break;
18318 case NM_SUBU:
18319 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18320 break;
18321 case NM_P_CMOVE:
18322 switch (extract32(ctx->opcode, 10, 1)) {
18323 case NM_MOVZ:
18324 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18325 break;
18326 case NM_MOVN:
18327 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18328 break;
18329 }
18330 break;
18331 case NM_AND:
18332 gen_logic(ctx, OPC_AND, rd, rs, rt);
18333 break;
18334 case NM_OR:
18335 gen_logic(ctx, OPC_OR, rd, rs, rt);
18336 break;
18337 case NM_NOR:
18338 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18339 break;
18340 case NM_XOR:
18341 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18342 break;
18343 case NM_SLT:
18344 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18345 break;
18346 case NM_P_SLTU:
18347 if (rd == 0) {
18348 /* P_DVP */
18349#ifndef CONFIG_USER_ONLY
18350 TCGv t0 = tcg_temp_new();
18351 switch (extract32(ctx->opcode, 10, 1)) {
18352 case NM_DVP:
18353 if (ctx->vp) {
18354 check_cp0_enabled(ctx);
18355 gen_helper_dvp(t0, cpu_env);
18356 gen_store_gpr(t0, rt);
18357 }
18358 break;
18359 case NM_EVP:
18360 if (ctx->vp) {
18361 check_cp0_enabled(ctx);
18362 gen_helper_evp(t0, cpu_env);
18363 gen_store_gpr(t0, rt);
18364 }
18365 break;
18366 }
18367 tcg_temp_free(t0);
18368#endif
18369 } else {
18370 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18371 }
18372 break;
18373 case NM_SOV:
18374 {
18375 TCGv t0 = tcg_temp_new();
18376 TCGv t1 = tcg_temp_new();
18377 TCGv t2 = tcg_temp_new();
18378
18379 gen_load_gpr(t1, rs);
18380 gen_load_gpr(t2, rt);
18381 tcg_gen_add_tl(t0, t1, t2);
18382 tcg_gen_ext32s_tl(t0, t0);
18383 tcg_gen_xor_tl(t1, t1, t2);
18384 tcg_gen_xor_tl(t2, t0, t2);
18385 tcg_gen_andc_tl(t1, t2, t1);
18386
18387 /* operands of same sign, result different sign */
18388 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18389 gen_store_gpr(t0, rd);
18390
18391 tcg_temp_free(t0);
18392 tcg_temp_free(t1);
18393 tcg_temp_free(t2);
18394 }
18395 break;
18396 case NM_MUL:
18397 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18398 break;
18399 case NM_MUH:
18400 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18401 break;
18402 case NM_MULU:
18403 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18404 break;
18405 case NM_MUHU:
18406 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18407 break;
18408 case NM_DIV:
18409 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18410 break;
18411 case NM_MOD:
18412 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18413 break;
18414 case NM_DIVU:
18415 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18416 break;
18417 case NM_MODU:
18418 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18419 break;
18420#ifndef CONFIG_USER_ONLY
18421 case NM_MFC0:
18422 check_cp0_enabled(ctx);
18423 if (rt == 0) {
18424 /* Treat as NOP. */
18425 break;
18426 }
18427 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18428 break;
18429 case NM_MTC0:
18430 check_cp0_enabled(ctx);
18431 {
18432 TCGv t0 = tcg_temp_new();
18433
18434 gen_load_gpr(t0, rt);
18435 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18436 tcg_temp_free(t0);
18437 }
18438 break;
0a1a6ed7
SM
18439 case NM_D_E_MT_VPE:
18440 {
18441 uint8_t sc = extract32(ctx->opcode, 10, 1);
18442 TCGv t0 = tcg_temp_new();
18443
18444 switch (sc) {
18445 case 0:
18446 if (rs == 1) {
18447 /* DMT */
18448 check_cp0_mt(ctx);
18449 gen_helper_dmt(t0);
18450 gen_store_gpr(t0, rt);
18451 } else if (rs == 0) {
18452 /* DVPE */
18453 check_cp0_mt(ctx);
18454 gen_helper_dvpe(t0, cpu_env);
18455 gen_store_gpr(t0, rt);
18456 } else {
18457 generate_exception_end(ctx, EXCP_RI);
18458 }
18459 break;
18460 case 1:
18461 if (rs == 1) {
18462 /* EMT */
18463 check_cp0_mt(ctx);
18464 gen_helper_emt(t0);
18465 gen_store_gpr(t0, rt);
18466 } else if (rs == 0) {
18467 /* EVPE */
18468 check_cp0_mt(ctx);
18469 gen_helper_evpe(t0, cpu_env);
18470 gen_store_gpr(t0, rt);
18471 } else {
18472 generate_exception_end(ctx, EXCP_RI);
18473 }
18474 break;
18475 }
18476
18477 tcg_temp_free(t0);
18478 }
18479 break;
18480 case NM_FORK:
18481 check_mt(ctx);
18482 {
18483 TCGv t0 = tcg_temp_new();
18484 TCGv t1 = tcg_temp_new();
18485
18486 gen_load_gpr(t0, rt);
18487 gen_load_gpr(t1, rs);
18488 gen_helper_fork(t0, t1);
18489 tcg_temp_free(t0);
18490 tcg_temp_free(t1);
18491 }
18492 break;
18493 case NM_MFTR:
18494 case NM_MFHTR:
18495 check_cp0_enabled(ctx);
18496 if (rd == 0) {
18497 /* Treat as NOP. */
18498 return;
18499 }
18500 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18501 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18502 break;
18503 case NM_MTTR:
18504 case NM_MTHTR:
18505 check_cp0_enabled(ctx);
18506 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18507 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18508 break;
18509 case NM_YIELD:
18510 check_mt(ctx);
18511 {
18512 TCGv t0 = tcg_temp_new();
18513
18514 gen_load_gpr(t0, rs);
18515 gen_helper_yield(t0, cpu_env, t0);
18516 gen_store_gpr(t0, rt);
18517 tcg_temp_free(t0);
18518 }
18519 break;
e0cf0e65
YK
18520#endif
18521 default:
18522 generate_exception_end(ctx, EXCP_RI);
18523 break;
18524 }
18525}
18526
2ed42efa
SM
18527/* dsp */
18528static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18529 int ret, int v1, int v2)
18530{
18531 TCGv_i32 t0;
18532 TCGv v0_t;
18533 TCGv v1_t;
18534
18535 t0 = tcg_temp_new_i32();
18536
18537 v0_t = tcg_temp_new();
18538 v1_t = tcg_temp_new();
18539
18540 tcg_gen_movi_i32(t0, v2 >> 3);
18541
18542 gen_load_gpr(v0_t, ret);
18543 gen_load_gpr(v1_t, v1);
18544
18545 switch (opc) {
18546 case NM_MAQ_S_W_PHR:
18547 check_dsp(ctx);
18548 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18549 break;
18550 case NM_MAQ_S_W_PHL:
18551 check_dsp(ctx);
18552 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18553 break;
18554 case NM_MAQ_SA_W_PHR:
18555 check_dsp(ctx);
18556 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18557 break;
18558 case NM_MAQ_SA_W_PHL:
18559 check_dsp(ctx);
18560 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18561 break;
18562 default:
18563 generate_exception_end(ctx, EXCP_RI);
18564 break;
18565 }
18566
18567 tcg_temp_free_i32(t0);
18568
18569 tcg_temp_free(v0_t);
18570 tcg_temp_free(v1_t);
18571}
18572
18573
18574static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18575 int ret, int v1, int v2)
18576{
18577 int16_t imm;
18578 TCGv t0 = tcg_temp_new();
18579 TCGv t1 = tcg_temp_new();
18580 TCGv v0_t = tcg_temp_new();
18581
18582 gen_load_gpr(v0_t, v1);
18583
18584 switch (opc) {
18585 case NM_POOL32AXF_1_0:
18586 check_dsp(ctx);
18587 switch (extract32(ctx->opcode, 12, 2)) {
18588 case NM_MFHI:
18589 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18590 break;
18591 case NM_MFLO:
18592 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18593 break;
18594 case NM_MTHI:
18595 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18596 break;
18597 case NM_MTLO:
18598 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18599 break;
18600 }
18601 break;
18602 case NM_POOL32AXF_1_1:
18603 check_dsp(ctx);
18604 switch (extract32(ctx->opcode, 12, 2)) {
18605 case NM_MTHLIP:
18606 tcg_gen_movi_tl(t0, v2);
18607 gen_helper_mthlip(t0, v0_t, cpu_env);
18608 break;
18609 case NM_SHILOV:
18610 tcg_gen_movi_tl(t0, v2 >> 3);
18611 gen_helper_shilo(t0, v0_t, cpu_env);
18612 break;
18613 default:
18614 generate_exception_end(ctx, EXCP_RI);
18615 break;
18616 }
18617 break;
18618 case NM_POOL32AXF_1_3:
18619 check_dsp(ctx);
18620 imm = extract32(ctx->opcode, 14, 7);
18621 switch (extract32(ctx->opcode, 12, 2)) {
18622 case NM_RDDSP:
18623 tcg_gen_movi_tl(t0, imm);
18624 gen_helper_rddsp(t0, t0, cpu_env);
18625 gen_store_gpr(t0, ret);
18626 break;
18627 case NM_WRDSP:
18628 gen_load_gpr(t0, ret);
18629 tcg_gen_movi_tl(t1, imm);
18630 gen_helper_wrdsp(t0, t1, cpu_env);
18631 break;
18632 case NM_EXTP:
18633 tcg_gen_movi_tl(t0, v2 >> 3);
18634 tcg_gen_movi_tl(t1, v1);
18635 gen_helper_extp(t0, t0, t1, cpu_env);
18636 gen_store_gpr(t0, ret);
18637 break;
18638 case NM_EXTPDP:
18639 tcg_gen_movi_tl(t0, v2 >> 3);
18640 tcg_gen_movi_tl(t1, v1);
18641 gen_helper_extpdp(t0, t0, t1, cpu_env);
18642 gen_store_gpr(t0, ret);
18643 break;
18644 }
18645 break;
18646 case NM_POOL32AXF_1_4:
18647 check_dsp(ctx);
18648 tcg_gen_movi_tl(t0, v2 >> 2);
18649 switch (extract32(ctx->opcode, 12, 1)) {
18650 case NM_SHLL_QB:
18651 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18652 gen_store_gpr(t0, ret);
18653 break;
18654 case NM_SHRL_QB:
18655 gen_helper_shrl_qb(t0, t0, v0_t);
18656 gen_store_gpr(t0, ret);
18657 break;
18658 }
18659 break;
18660 case NM_POOL32AXF_1_5:
18661 opc = extract32(ctx->opcode, 12, 2);
18662 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18663 break;
18664 case NM_POOL32AXF_1_7:
18665 check_dsp(ctx);
18666 tcg_gen_movi_tl(t0, v2 >> 3);
18667 tcg_gen_movi_tl(t1, v1);
18668 switch (extract32(ctx->opcode, 12, 2)) {
18669 case NM_EXTR_W:
18670 gen_helper_extr_w(t0, t0, t1, cpu_env);
18671 gen_store_gpr(t0, ret);
18672 break;
18673 case NM_EXTR_R_W:
18674 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18675 gen_store_gpr(t0, ret);
18676 break;
18677 case NM_EXTR_RS_W:
18678 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18679 gen_store_gpr(t0, ret);
18680 break;
18681 case NM_EXTR_S_H:
18682 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18683 gen_store_gpr(t0, ret);
18684 break;
18685 }
18686 break;
18687 default:
18688 generate_exception_end(ctx, EXCP_RI);
18689 break;
18690 }
18691
18692 tcg_temp_free(t0);
18693 tcg_temp_free(t1);
18694 tcg_temp_free(v0_t);
18695}
18696
8b3698b2
SM
18697static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18698 TCGv v0, TCGv v1, int rd)
18699{
18700 TCGv_i32 t0;
18701
18702 t0 = tcg_temp_new_i32();
18703
18704 tcg_gen_movi_i32(t0, rd >> 3);
18705
18706 switch (opc) {
18707 case NM_POOL32AXF_2_0_7:
18708 switch (extract32(ctx->opcode, 9, 3)) {
18709 case NM_DPA_W_PH:
908f6be1 18710 check_dsp_r2(ctx);
8b3698b2
SM
18711 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18712 break;
18713 case NM_DPAQ_S_W_PH:
18714 check_dsp(ctx);
18715 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18716 break;
18717 case NM_DPS_W_PH:
908f6be1 18718 check_dsp_r2(ctx);
8b3698b2
SM
18719 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18720 break;
18721 case NM_DPSQ_S_W_PH:
18722 check_dsp(ctx);
18723 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18724 break;
18725 default:
18726 generate_exception_end(ctx, EXCP_RI);
18727 break;
18728 }
18729 break;
18730 case NM_POOL32AXF_2_8_15:
18731 switch (extract32(ctx->opcode, 9, 3)) {
18732 case NM_DPAX_W_PH:
908f6be1 18733 check_dsp_r2(ctx);
8b3698b2
SM
18734 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18735 break;
18736 case NM_DPAQ_SA_L_W:
18737 check_dsp(ctx);
18738 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18739 break;
18740 case NM_DPSX_W_PH:
908f6be1 18741 check_dsp_r2(ctx);
8b3698b2
SM
18742 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18743 break;
18744 case NM_DPSQ_SA_L_W:
18745 check_dsp(ctx);
18746 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18747 break;
18748 default:
18749 generate_exception_end(ctx, EXCP_RI);
18750 break;
18751 }
18752 break;
18753 case NM_POOL32AXF_2_16_23:
18754 switch (extract32(ctx->opcode, 9, 3)) {
18755 case NM_DPAU_H_QBL:
18756 check_dsp(ctx);
18757 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18758 break;
18759 case NM_DPAQX_S_W_PH:
908f6be1 18760 check_dsp_r2(ctx);
8b3698b2
SM
18761 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18762 break;
18763 case NM_DPSU_H_QBL:
18764 check_dsp(ctx);
18765 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18766 break;
18767 case NM_DPSQX_S_W_PH:
908f6be1 18768 check_dsp_r2(ctx);
8b3698b2
SM
18769 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18770 break;
18771 case NM_MULSA_W_PH:
908f6be1 18772 check_dsp_r2(ctx);
8b3698b2
SM
18773 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18774 break;
18775 default:
18776 generate_exception_end(ctx, EXCP_RI);
18777 break;
18778 }
18779 break;
18780 case NM_POOL32AXF_2_24_31:
18781 switch (extract32(ctx->opcode, 9, 3)) {
18782 case NM_DPAU_H_QBR:
18783 check_dsp(ctx);
18784 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18785 break;
18786 case NM_DPAQX_SA_W_PH:
908f6be1 18787 check_dsp_r2(ctx);
8b3698b2
SM
18788 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18789 break;
18790 case NM_DPSU_H_QBR:
18791 check_dsp(ctx);
18792 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18793 break;
18794 case NM_DPSQX_SA_W_PH:
908f6be1 18795 check_dsp_r2(ctx);
8b3698b2
SM
18796 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18797 break;
18798 case NM_MULSAQ_S_W_PH:
18799 check_dsp(ctx);
18800 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18801 break;
18802 default:
18803 generate_exception_end(ctx, EXCP_RI);
18804 break;
18805 }
18806 break;
18807 default:
18808 generate_exception_end(ctx, EXCP_RI);
18809 break;
18810 }
18811
18812 tcg_temp_free_i32(t0);
18813}
18814
18815static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18816 int rt, int rs, int rd)
18817{
18818 int ret = rt;
18819 TCGv t0 = tcg_temp_new();
18820 TCGv t1 = tcg_temp_new();
18821 TCGv v0_t = tcg_temp_new();
18822 TCGv v1_t = tcg_temp_new();
18823
18824 gen_load_gpr(v0_t, rt);
18825 gen_load_gpr(v1_t, rs);
18826
18827 switch (opc) {
18828 case NM_POOL32AXF_2_0_7:
18829 switch (extract32(ctx->opcode, 9, 3)) {
18830 case NM_DPA_W_PH:
18831 case NM_DPAQ_S_W_PH:
18832 case NM_DPS_W_PH:
18833 case NM_DPSQ_S_W_PH:
18834 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18835 break;
18836 case NM_BALIGN:
908f6be1 18837 check_dsp_r2(ctx);
8b3698b2
SM
18838 if (rt != 0) {
18839 gen_load_gpr(t0, rs);
18840 rd &= 3;
18841 if (rd != 0 && rd != 2) {
18842 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18843 tcg_gen_ext32u_tl(t0, t0);
18844 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18845 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18846 }
18847 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18848 }
18849 break;
18850 case NM_MADD:
18851 check_dsp(ctx);
18852 {
18853 int acc = extract32(ctx->opcode, 14, 2);
18854 TCGv_i64 t2 = tcg_temp_new_i64();
18855 TCGv_i64 t3 = tcg_temp_new_i64();
18856
18857 gen_load_gpr(t0, rt);
18858 gen_load_gpr(t1, rs);
18859 tcg_gen_ext_tl_i64(t2, t0);
18860 tcg_gen_ext_tl_i64(t3, t1);
18861 tcg_gen_mul_i64(t2, t2, t3);
18862 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18863 tcg_gen_add_i64(t2, t2, t3);
18864 tcg_temp_free_i64(t3);
18865 gen_move_low32(cpu_LO[acc], t2);
18866 gen_move_high32(cpu_HI[acc], t2);
18867 tcg_temp_free_i64(t2);
18868 }
18869 break;
18870 case NM_MULT:
18871 check_dsp(ctx);
18872 {
18873 int acc = extract32(ctx->opcode, 14, 2);
18874 TCGv_i32 t2 = tcg_temp_new_i32();
18875 TCGv_i32 t3 = tcg_temp_new_i32();
18876
18877 gen_load_gpr(t0, rs);
18878 gen_load_gpr(t1, rt);
18879 tcg_gen_trunc_tl_i32(t2, t0);
18880 tcg_gen_trunc_tl_i32(t3, t1);
18881 tcg_gen_muls2_i32(t2, t3, t2, t3);
18882 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18883 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18884 tcg_temp_free_i32(t2);
18885 tcg_temp_free_i32(t3);
18886 }
18887 break;
18888 case NM_EXTRV_W:
18889 check_dsp(ctx);
18890 gen_load_gpr(v1_t, rs);
18891 tcg_gen_movi_tl(t0, rd >> 3);
18892 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18893 gen_store_gpr(t0, ret);
18894 break;
18895 }
18896 break;
18897 case NM_POOL32AXF_2_8_15:
18898 switch (extract32(ctx->opcode, 9, 3)) {
18899 case NM_DPAX_W_PH:
18900 case NM_DPAQ_SA_L_W:
18901 case NM_DPSX_W_PH:
18902 case NM_DPSQ_SA_L_W:
18903 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18904 break;
18905 case NM_MADDU:
18906 check_dsp(ctx);
18907 {
18908 int acc = extract32(ctx->opcode, 14, 2);
18909 TCGv_i64 t2 = tcg_temp_new_i64();
18910 TCGv_i64 t3 = tcg_temp_new_i64();
18911
18912 gen_load_gpr(t0, rs);
18913 gen_load_gpr(t1, rt);
18914 tcg_gen_ext32u_tl(t0, t0);
18915 tcg_gen_ext32u_tl(t1, t1);
18916 tcg_gen_extu_tl_i64(t2, t0);
18917 tcg_gen_extu_tl_i64(t3, t1);
18918 tcg_gen_mul_i64(t2, t2, t3);
18919 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18920 tcg_gen_add_i64(t2, t2, t3);
18921 tcg_temp_free_i64(t3);
18922 gen_move_low32(cpu_LO[acc], t2);
18923 gen_move_high32(cpu_HI[acc], t2);
18924 tcg_temp_free_i64(t2);
18925 }
18926 break;
18927 case NM_MULTU:
18928 check_dsp(ctx);
18929 {
18930 int acc = extract32(ctx->opcode, 14, 2);
18931 TCGv_i32 t2 = tcg_temp_new_i32();
18932 TCGv_i32 t3 = tcg_temp_new_i32();
18933
18934 gen_load_gpr(t0, rs);
18935 gen_load_gpr(t1, rt);
18936 tcg_gen_trunc_tl_i32(t2, t0);
18937 tcg_gen_trunc_tl_i32(t3, t1);
18938 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18939 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18940 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18941 tcg_temp_free_i32(t2);
18942 tcg_temp_free_i32(t3);
18943 }
18944 break;
18945 case NM_EXTRV_R_W:
18946 check_dsp(ctx);
18947 tcg_gen_movi_tl(t0, rd >> 3);
18948 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18949 gen_store_gpr(t0, ret);
18950 break;
18951 default:
18952 generate_exception_end(ctx, EXCP_RI);
18953 break;
18954 }
18955 break;
18956 case NM_POOL32AXF_2_16_23:
18957 switch (extract32(ctx->opcode, 9, 3)) {
18958 case NM_DPAU_H_QBL:
18959 case NM_DPAQX_S_W_PH:
18960 case NM_DPSU_H_QBL:
18961 case NM_DPSQX_S_W_PH:
18962 case NM_MULSA_W_PH:
18963 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18964 break;
18965 case NM_EXTPV:
18966 check_dsp(ctx);
18967 tcg_gen_movi_tl(t0, rd >> 3);
18968 gen_helper_extp(t0, t0, v1_t, cpu_env);
18969 gen_store_gpr(t0, ret);
18970 break;
18971 case NM_MSUB:
18972 check_dsp(ctx);
18973 {
18974 int acc = extract32(ctx->opcode, 14, 2);
18975 TCGv_i64 t2 = tcg_temp_new_i64();
18976 TCGv_i64 t3 = tcg_temp_new_i64();
18977
18978 gen_load_gpr(t0, rs);
18979 gen_load_gpr(t1, rt);
18980 tcg_gen_ext_tl_i64(t2, t0);
18981 tcg_gen_ext_tl_i64(t3, t1);
18982 tcg_gen_mul_i64(t2, t2, t3);
18983 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18984 tcg_gen_sub_i64(t2, t3, t2);
18985 tcg_temp_free_i64(t3);
18986 gen_move_low32(cpu_LO[acc], t2);
18987 gen_move_high32(cpu_HI[acc], t2);
18988 tcg_temp_free_i64(t2);
18989 }
18990 break;
18991 case NM_EXTRV_RS_W:
18992 check_dsp(ctx);
18993 tcg_gen_movi_tl(t0, rd >> 3);
18994 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18995 gen_store_gpr(t0, ret);
18996 break;
18997 }
18998 break;
18999 case NM_POOL32AXF_2_24_31:
19000 switch (extract32(ctx->opcode, 9, 3)) {
19001 case NM_DPAU_H_QBR:
19002 case NM_DPAQX_SA_W_PH:
19003 case NM_DPSU_H_QBR:
19004 case NM_DPSQX_SA_W_PH:
19005 case NM_MULSAQ_S_W_PH:
19006 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19007 break;
19008 case NM_EXTPDPV:
19009 check_dsp(ctx);
19010 tcg_gen_movi_tl(t0, rd >> 3);
19011 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19012 gen_store_gpr(t0, ret);
19013 break;
19014 case NM_MSUBU:
19015 check_dsp(ctx);
19016 {
19017 int acc = extract32(ctx->opcode, 14, 2);
19018 TCGv_i64 t2 = tcg_temp_new_i64();
19019 TCGv_i64 t3 = tcg_temp_new_i64();
19020
19021 gen_load_gpr(t0, rs);
19022 gen_load_gpr(t1, rt);
19023 tcg_gen_ext32u_tl(t0, t0);
19024 tcg_gen_ext32u_tl(t1, t1);
19025 tcg_gen_extu_tl_i64(t2, t0);
19026 tcg_gen_extu_tl_i64(t3, t1);
19027 tcg_gen_mul_i64(t2, t2, t3);
19028 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19029 tcg_gen_sub_i64(t2, t3, t2);
19030 tcg_temp_free_i64(t3);
19031 gen_move_low32(cpu_LO[acc], t2);
19032 gen_move_high32(cpu_HI[acc], t2);
19033 tcg_temp_free_i64(t2);
19034 }
19035 break;
19036 case NM_EXTRV_S_H:
19037 check_dsp(ctx);
19038 tcg_gen_movi_tl(t0, rd >> 3);
19039 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19040 gen_store_gpr(t0, ret);
19041 break;
19042 }
19043 break;
19044 default:
19045 generate_exception_end(ctx, EXCP_RI);
19046 break;
19047 }
19048
19049 tcg_temp_free(t0);
19050 tcg_temp_free(t1);
19051
19052 tcg_temp_free(v0_t);
19053 tcg_temp_free(v1_t);
19054}
19055
4c75c985
SM
19056static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19057 int rt, int rs)
19058{
19059 int ret = rt;
19060 TCGv t0 = tcg_temp_new();
19061 TCGv v0_t = tcg_temp_new();
19062
19063 gen_load_gpr(v0_t, rs);
19064
19065 switch (opc) {
19066 case NM_ABSQ_S_QB:
908f6be1 19067 check_dsp_r2(ctx);
4c75c985
SM
19068 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19069 gen_store_gpr(v0_t, ret);
19070 break;
19071 case NM_ABSQ_S_PH:
19072 check_dsp(ctx);
19073 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19074 gen_store_gpr(v0_t, ret);
19075 break;
19076 case NM_ABSQ_S_W:
19077 check_dsp(ctx);
19078 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19079 gen_store_gpr(v0_t, ret);
19080 break;
19081 case NM_PRECEQ_W_PHL:
19082 check_dsp(ctx);
19083 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19084 tcg_gen_ext32s_tl(v0_t, v0_t);
19085 gen_store_gpr(v0_t, ret);
19086 break;
19087 case NM_PRECEQ_W_PHR:
19088 check_dsp(ctx);
19089 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19090 tcg_gen_shli_tl(v0_t, v0_t, 16);
19091 tcg_gen_ext32s_tl(v0_t, v0_t);
19092 gen_store_gpr(v0_t, ret);
19093 break;
19094 case NM_PRECEQU_PH_QBL:
19095 check_dsp(ctx);
19096 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19097 gen_store_gpr(v0_t, ret);
19098 break;
19099 case NM_PRECEQU_PH_QBR:
19100 check_dsp(ctx);
19101 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19102 gen_store_gpr(v0_t, ret);
19103 break;
19104 case NM_PRECEQU_PH_QBLA:
19105 check_dsp(ctx);
19106 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19107 gen_store_gpr(v0_t, ret);
19108 break;
19109 case NM_PRECEQU_PH_QBRA:
19110 check_dsp(ctx);
19111 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19112 gen_store_gpr(v0_t, ret);
19113 break;
19114 case NM_PRECEU_PH_QBL:
19115 check_dsp(ctx);
19116 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19117 gen_store_gpr(v0_t, ret);
19118 break;
19119 case NM_PRECEU_PH_QBR:
19120 check_dsp(ctx);
19121 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19122 gen_store_gpr(v0_t, ret);
19123 break;
19124 case NM_PRECEU_PH_QBLA:
19125 check_dsp(ctx);
19126 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19127 gen_store_gpr(v0_t, ret);
19128 break;
19129 case NM_PRECEU_PH_QBRA:
19130 check_dsp(ctx);
19131 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19132 gen_store_gpr(v0_t, ret);
19133 break;
19134 case NM_REPLV_PH:
19135 check_dsp(ctx);
19136 tcg_gen_ext16u_tl(v0_t, v0_t);
19137 tcg_gen_shli_tl(t0, v0_t, 16);
19138 tcg_gen_or_tl(v0_t, v0_t, t0);
19139 tcg_gen_ext32s_tl(v0_t, v0_t);
19140 gen_store_gpr(v0_t, ret);
19141 break;
19142 case NM_REPLV_QB:
19143 check_dsp(ctx);
19144 tcg_gen_ext8u_tl(v0_t, v0_t);
19145 tcg_gen_shli_tl(t0, v0_t, 8);
19146 tcg_gen_or_tl(v0_t, v0_t, t0);
19147 tcg_gen_shli_tl(t0, v0_t, 16);
19148 tcg_gen_or_tl(v0_t, v0_t, t0);
19149 tcg_gen_ext32s_tl(v0_t, v0_t);
19150 gen_store_gpr(v0_t, ret);
19151 break;
19152 case NM_BITREV:
19153 check_dsp(ctx);
19154 gen_helper_bitrev(v0_t, v0_t);
19155 gen_store_gpr(v0_t, ret);
19156 break;
19157 case NM_INSV:
19158 check_dsp(ctx);
19159 {
19160 TCGv tv0 = tcg_temp_new();
19161
19162 gen_load_gpr(tv0, rt);
19163 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19164 gen_store_gpr(v0_t, ret);
19165 tcg_temp_free(tv0);
19166 }
19167 break;
19168 case NM_RADDU_W_QB:
19169 check_dsp(ctx);
19170 gen_helper_raddu_w_qb(v0_t, v0_t);
19171 gen_store_gpr(v0_t, ret);
19172 break;
19173 case NM_BITSWAP:
19174 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19175 break;
19176 case NM_CLO:
fb32f8c8 19177 check_nms(ctx);
4c75c985
SM
19178 gen_cl(ctx, OPC_CLO, ret, rs);
19179 break;
19180 case NM_CLZ:
fb32f8c8 19181 check_nms(ctx);
4c75c985
SM
19182 gen_cl(ctx, OPC_CLZ, ret, rs);
19183 break;
19184 case NM_WSBH:
19185 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19186 break;
19187 default:
19188 generate_exception_end(ctx, EXCP_RI);
19189 break;
19190 }
19191
19192 tcg_temp_free(v0_t);
19193 tcg_temp_free(t0);
19194}
19195
0b591184
SM
19196static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19197 int rt, int rs, int rd)
19198{
19199 TCGv t0 = tcg_temp_new();
19200 TCGv rs_t = tcg_temp_new();
19201
19202 gen_load_gpr(rs_t, rs);
19203
19204 switch (opc) {
19205 case NM_SHRA_R_QB:
908f6be1 19206 check_dsp_r2(ctx);
0b591184
SM
19207 tcg_gen_movi_tl(t0, rd >> 2);
19208 switch (extract32(ctx->opcode, 12, 1)) {
19209 case 0:
19210 /* NM_SHRA_QB */
19211 gen_helper_shra_qb(t0, t0, rs_t);
19212 gen_store_gpr(t0, rt);
19213 break;
19214 case 1:
19215 /* NM_SHRA_R_QB */
19216 gen_helper_shra_r_qb(t0, t0, rs_t);
19217 gen_store_gpr(t0, rt);
19218 break;
19219 }
19220 break;
19221 case NM_SHRL_PH:
908f6be1 19222 check_dsp_r2(ctx);
0b591184
SM
19223 tcg_gen_movi_tl(t0, rd >> 1);
19224 gen_helper_shrl_ph(t0, t0, rs_t);
19225 gen_store_gpr(t0, rt);
19226 break;
19227 case NM_REPL_QB:
19228 check_dsp(ctx);
19229 {
19230 int16_t imm;
19231 target_long result;
19232 imm = extract32(ctx->opcode, 13, 8);
19233 result = (uint32_t)imm << 24 |
19234 (uint32_t)imm << 16 |
19235 (uint32_t)imm << 8 |
19236 (uint32_t)imm;
19237 result = (int32_t)result;
19238 tcg_gen_movi_tl(t0, result);
19239 gen_store_gpr(t0, rt);
19240 }
19241 break;
19242 default:
19243 generate_exception_end(ctx, EXCP_RI);
19244 break;
19245 }
19246 tcg_temp_free(t0);
19247 tcg_temp_free(rs_t);
19248}
19249
2ed42efa 19250
64224187
YK
19251static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19252{
64224187
YK
19253 int rt = extract32(ctx->opcode, 21, 5);
19254 int rs = extract32(ctx->opcode, 16, 5);
2ed42efa 19255 int rd = extract32(ctx->opcode, 11, 5);
64224187
YK
19256
19257 switch (extract32(ctx->opcode, 6, 3)) {
2ed42efa
SM
19258 case NM_POOL32AXF_1:
19259 {
19260 int32_t op1 = extract32(ctx->opcode, 9, 3);
19261 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19262 }
19263 break;
19264 case NM_POOL32AXF_2:
8b3698b2
SM
19265 {
19266 int32_t op1 = extract32(ctx->opcode, 12, 2);
19267 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19268 }
2ed42efa 19269 break;
64224187 19270 case NM_POOL32AXF_4:
4c75c985
SM
19271 {
19272 int32_t op1 = extract32(ctx->opcode, 9, 7);
19273 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19274 }
2ed42efa 19275 break;
64224187
YK
19276 case NM_POOL32AXF_5:
19277 switch (extract32(ctx->opcode, 9, 7)) {
19278#ifndef CONFIG_USER_ONLY
19279 case NM_TLBP:
19280 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19281 break;
19282 case NM_TLBR:
19283 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19284 break;
19285 case NM_TLBWI:
19286 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19287 break;
19288 case NM_TLBWR:
19289 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19290 break;
19291 case NM_TLBINV:
19292 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19293 break;
19294 case NM_TLBINVF:
19295 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19296 break;
19297 case NM_DI:
19298 check_cp0_enabled(ctx);
19299 {
19300 TCGv t0 = tcg_temp_new();
19301
19302 save_cpu_state(ctx, 1);
19303 gen_helper_di(t0, cpu_env);
19304 gen_store_gpr(t0, rt);
19305 /* Stop translation as we may have switched the execution mode */
19306 ctx->base.is_jmp = DISAS_STOP;
19307 tcg_temp_free(t0);
19308 }
19309 break;
19310 case NM_EI:
19311 check_cp0_enabled(ctx);
19312 {
19313 TCGv t0 = tcg_temp_new();
19314
19315 save_cpu_state(ctx, 1);
19316 gen_helper_ei(t0, cpu_env);
19317 gen_store_gpr(t0, rt);
19318 /* Stop translation as we may have switched the execution mode */
19319 ctx->base.is_jmp = DISAS_STOP;
19320 tcg_temp_free(t0);
19321 }
19322 break;
19323 case NM_RDPGPR:
19324 gen_load_srsgpr(rs, rt);
19325 break;
19326 case NM_WRPGPR:
19327 gen_store_srsgpr(rs, rt);
19328 break;
19329 case NM_WAIT:
19330 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19331 break;
19332 case NM_DERET:
19333 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19334 break;
19335 case NM_ERETX:
19336 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19337 break;
19338#endif
19339 default:
19340 generate_exception_end(ctx, EXCP_RI);
19341 break;
19342 }
19343 break;
2ed42efa 19344 case NM_POOL32AXF_7:
0b591184
SM
19345 {
19346 int32_t op1 = extract32(ctx->opcode, 9, 3);
19347 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19348 }
2ed42efa 19349 break;
64224187
YK
19350 default:
19351 generate_exception_end(ctx, EXCP_RI);
19352 break;
19353 }
19354}
19355
11d0fc10
SM
19356/* Immediate Value Compact Branches */
19357static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19358 int rt, int32_t imm, int32_t offset)
19359{
19360 TCGCond cond;
19361 int bcond_compute = 0;
19362 TCGv t0 = tcg_temp_new();
19363 TCGv t1 = tcg_temp_new();
19364
19365 gen_load_gpr(t0, rt);
19366 tcg_gen_movi_tl(t1, imm);
19367 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19368
19369 /* Load needed operands and calculate btarget */
19370 switch (opc) {
19371 case NM_BEQIC:
19372 if (rt == 0 && imm == 0) {
19373 /* Unconditional branch */
19374 } else if (rt == 0 && imm != 0) {
19375 /* Treat as NOP */
19376 goto out;
19377 } else {
19378 bcond_compute = 1;
19379 cond = TCG_COND_EQ;
19380 }
19381 break;
19382 case NM_BBEQZC:
19383 case NM_BBNEZC:
fb32f8c8 19384 check_nms(ctx);
11d0fc10
SM
19385 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19386 generate_exception_end(ctx, EXCP_RI);
19387 goto out;
19388 } else if (rt == 0 && opc == NM_BBEQZC) {
19389 /* Unconditional branch */
19390 } else if (rt == 0 && opc == NM_BBNEZC) {
19391 /* Treat as NOP */
19392 goto out;
19393 } else {
19394 tcg_gen_shri_tl(t0, t0, imm);
19395 tcg_gen_andi_tl(t0, t0, 1);
19396 tcg_gen_movi_tl(t1, 0);
19397 bcond_compute = 1;
19398 if (opc == NM_BBEQZC) {
19399 cond = TCG_COND_EQ;
19400 } else {
19401 cond = TCG_COND_NE;
19402 }
19403 }
19404 break;
19405 case NM_BNEIC:
19406 if (rt == 0 && imm == 0) {
19407 /* Treat as NOP */
19408 goto out;
19409 } else if (rt == 0 && imm != 0) {
19410 /* Unconditional branch */
19411 } else {
19412 bcond_compute = 1;
19413 cond = TCG_COND_NE;
19414 }
19415 break;
19416 case NM_BGEIC:
19417 if (rt == 0 && imm == 0) {
19418 /* Unconditional branch */
19419 } else {
19420 bcond_compute = 1;
19421 cond = TCG_COND_GE;
19422 }
19423 break;
19424 case NM_BLTIC:
19425 bcond_compute = 1;
19426 cond = TCG_COND_LT;
19427 break;
19428 case NM_BGEIUC:
19429 if (rt == 0 && imm == 0) {
19430 /* Unconditional branch */
19431 } else {
19432 bcond_compute = 1;
19433 cond = TCG_COND_GEU;
19434 }
19435 break;
19436 case NM_BLTIUC:
19437 bcond_compute = 1;
19438 cond = TCG_COND_LTU;
19439 break;
19440 default:
19441 MIPS_INVAL("Immediate Value Compact branch");
19442 generate_exception_end(ctx, EXCP_RI);
19443 goto out;
19444 }
19445
19446 if (bcond_compute == 0) {
19447 /* Uncoditional compact branch */
19448 gen_goto_tb(ctx, 0, ctx->btarget);
19449 } else {
19450 /* Conditional compact branch */
19451 TCGLabel *fs = gen_new_label();
19452
19453 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19454
19455 gen_goto_tb(ctx, 1, ctx->btarget);
19456 gen_set_label(fs);
19457
19458 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19459 }
19460
19461out:
19462 tcg_temp_free(t0);
19463 tcg_temp_free(t1);
19464}
19465
19466/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19467static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19468 int rt)
19469{
19470 TCGv t0 = tcg_temp_new();
19471 TCGv t1 = tcg_temp_new();
19472
19473 /* load rs */
19474 gen_load_gpr(t0, rs);
19475
19476 /* link */
19477 if (rt != 0) {
19478 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19479 }
19480
19481 /* calculate btarget */
19482 tcg_gen_shli_tl(t0, t0, 1);
19483 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19484 gen_op_addr_add(ctx, btarget, t1, t0);
19485
19486 /* unconditional branch to register */
19487 tcg_gen_mov_tl(cpu_PC, btarget);
19488 tcg_gen_lookup_and_goto_ptr();
19489
19490 tcg_temp_free(t0);
19491 tcg_temp_free(t1);
19492}
19493
19494/* nanoMIPS Branches */
19495static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19496 int rs, int rt, int32_t offset)
19497{
19498 int bcond_compute = 0;
19499 TCGv t0 = tcg_temp_new();
19500 TCGv t1 = tcg_temp_new();
19501
19502 /* Load needed operands and calculate btarget */
19503 switch (opc) {
19504 /* compact branch */
19505 case OPC_BGEC:
19506 case OPC_BLTC:
19507 gen_load_gpr(t0, rs);
19508 gen_load_gpr(t1, rt);
19509 bcond_compute = 1;
19510 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19511 break;
19512 case OPC_BGEUC:
19513 case OPC_BLTUC:
19514 if (rs == 0 || rs == rt) {
19515 /* OPC_BLEZALC, OPC_BGEZALC */
19516 /* OPC_BGTZALC, OPC_BLTZALC */
19517 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19518 }
19519 gen_load_gpr(t0, rs);
19520 gen_load_gpr(t1, rt);
19521 bcond_compute = 1;
19522 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19523 break;
19524 case OPC_BC:
19525 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19526 break;
19527 case OPC_BEQZC:
19528 if (rs != 0) {
19529 /* OPC_BEQZC, OPC_BNEZC */
19530 gen_load_gpr(t0, rs);
19531 bcond_compute = 1;
19532 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19533 } else {
19534 /* OPC_JIC, OPC_JIALC */
19535 TCGv tbase = tcg_temp_new();
19536 TCGv toffset = tcg_temp_new();
19537
19538 gen_load_gpr(tbase, rt);
19539 tcg_gen_movi_tl(toffset, offset);
19540 gen_op_addr_add(ctx, btarget, tbase, toffset);
19541 tcg_temp_free(tbase);
19542 tcg_temp_free(toffset);
19543 }
19544 break;
19545 default:
19546 MIPS_INVAL("Compact branch/jump");
19547 generate_exception_end(ctx, EXCP_RI);
19548 goto out;
19549 }
19550
19551 if (bcond_compute == 0) {
19552 /* Uncoditional compact branch */
19553 switch (opc) {
19554 case OPC_BC:
19555 gen_goto_tb(ctx, 0, ctx->btarget);
19556 break;
19557 default:
19558 MIPS_INVAL("Compact branch/jump");
19559 generate_exception_end(ctx, EXCP_RI);
19560 goto out;
19561 }
19562 } else {
19563 /* Conditional compact branch */
19564 TCGLabel *fs = gen_new_label();
19565
19566 switch (opc) {
19567 case OPC_BGEUC:
19568 if (rs == 0 && rt != 0) {
19569 /* OPC_BLEZALC */
19570 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19571 } else if (rs != 0 && rt != 0 && rs == rt) {
19572 /* OPC_BGEZALC */
19573 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19574 } else {
19575 /* OPC_BGEUC */
19576 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19577 }
19578 break;
19579 case OPC_BLTUC:
19580 if (rs == 0 && rt != 0) {
19581 /* OPC_BGTZALC */
19582 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19583 } else if (rs != 0 && rt != 0 && rs == rt) {
19584 /* OPC_BLTZALC */
19585 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19586 } else {
19587 /* OPC_BLTUC */
19588 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19589 }
19590 break;
19591 case OPC_BGEC:
19592 if (rs == 0 && rt != 0) {
19593 /* OPC_BLEZC */
19594 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19595 } else if (rs != 0 && rt != 0 && rs == rt) {
19596 /* OPC_BGEZC */
19597 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19598 } else {
19599 /* OPC_BGEC */
19600 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19601 }
19602 break;
19603 case OPC_BLTC:
19604 if (rs == 0 && rt != 0) {
19605 /* OPC_BGTZC */
19606 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19607 } else if (rs != 0 && rt != 0 && rs == rt) {
19608 /* OPC_BLTZC */
19609 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19610 } else {
19611 /* OPC_BLTC */
19612 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19613 }
19614 break;
19615 case OPC_BEQZC:
19616 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19617 break;
19618 default:
19619 MIPS_INVAL("Compact conditional branch/jump");
19620 generate_exception_end(ctx, EXCP_RI);
19621 goto out;
19622 }
19623
19624 /* Generating branch here as compact branches don't have delay slot */
19625 gen_goto_tb(ctx, 1, ctx->btarget);
19626 gen_set_label(fs);
19627
19628 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19629 }
19630
19631out:
19632 tcg_temp_free(t0);
19633 tcg_temp_free(t1);
19634}
19635
19636
19637/* nanoMIPS CP1 Branches */
19638static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19639 int32_t ft, int32_t offset)
19640{
19641 target_ulong btarget;
19642 TCGv_i64 t0 = tcg_temp_new_i64();
19643
19644 gen_load_fpr64(ctx, t0, ft);
19645 tcg_gen_andi_i64(t0, t0, 1);
19646
19647 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19648
19649 switch (op) {
19650 case NM_BC1EQZC:
19651 tcg_gen_xori_i64(t0, t0, 1);
19652 ctx->hflags |= MIPS_HFLAG_BC;
19653 break;
19654 case NM_BC1NEZC:
19655 /* t0 already set */
19656 ctx->hflags |= MIPS_HFLAG_BC;
19657 break;
19658 default:
19659 MIPS_INVAL("cp1 cond branch");
19660 generate_exception_end(ctx, EXCP_RI);
19661 goto out;
19662 }
19663
19664 tcg_gen_trunc_i64_tl(bcond, t0);
19665
19666 ctx->btarget = btarget;
19667
19668out:
19669 tcg_temp_free_i64(t0);
19670}
19671
eac52664
YK
19672
19673static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19674{
19675 TCGv t0, t1;
19676 t0 = tcg_temp_new();
19677 t1 = tcg_temp_new();
19678
19679 gen_load_gpr(t0, rs);
19680 gen_load_gpr(t1, rt);
19681
19682 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19683 /* PP.LSXS instructions require shifting */
19684 switch (extract32(ctx->opcode, 7, 4)) {
eac52664 19685 case NM_SHXS:
fb32f8c8
DN
19686 check_nms(ctx);
19687 case NM_LHXS:
eac52664
YK
19688 case NM_LHUXS:
19689 tcg_gen_shli_tl(t0, t0, 1);
19690 break;
eac52664 19691 case NM_SWXS:
fb32f8c8
DN
19692 check_nms(ctx);
19693 case NM_LWXS:
eac52664
YK
19694 case NM_LWC1XS:
19695 case NM_SWC1XS:
19696 tcg_gen_shli_tl(t0, t0, 2);
19697 break;
19698 case NM_LDC1XS:
19699 case NM_SDC1XS:
19700 tcg_gen_shli_tl(t0, t0, 3);
19701 break;
19702 }
19703 }
19704 gen_op_addr_add(ctx, t0, t0, t1);
19705
19706 switch (extract32(ctx->opcode, 7, 4)) {
19707 case NM_LBX:
19708 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19709 MO_SB);
19710 gen_store_gpr(t0, rd);
19711 break;
19712 case NM_LHX:
19713 /*case NM_LHXS:*/
19714 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19715 MO_TESW);
19716 gen_store_gpr(t0, rd);
19717 break;
19718 case NM_LWX:
19719 /*case NM_LWXS:*/
19720 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19721 MO_TESL);
19722 gen_store_gpr(t0, rd);
19723 break;
19724 case NM_LBUX:
19725 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19726 MO_UB);
19727 gen_store_gpr(t0, rd);
19728 break;
19729 case NM_LHUX:
19730 /*case NM_LHUXS:*/
19731 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19732 MO_TEUW);
19733 gen_store_gpr(t0, rd);
19734 break;
19735 case NM_SBX:
fb32f8c8 19736 check_nms(ctx);
eac52664
YK
19737 gen_load_gpr(t1, rd);
19738 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19739 MO_8);
19740 break;
19741 case NM_SHX:
19742 /*case NM_SHXS:*/
fb32f8c8 19743 check_nms(ctx);
eac52664
YK
19744 gen_load_gpr(t1, rd);
19745 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19746 MO_TEUW);
19747 break;
19748 case NM_SWX:
19749 /*case NM_SWXS:*/
fb32f8c8 19750 check_nms(ctx);
eac52664
YK
19751 gen_load_gpr(t1, rd);
19752 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19753 MO_TEUL);
19754 break;
19755 case NM_LWC1X:
19756 /*case NM_LWC1XS:*/
19757 case NM_LDC1X:
19758 /*case NM_LDC1XS:*/
19759 case NM_SWC1X:
19760 /*case NM_SWC1XS:*/
19761 case NM_SDC1X:
19762 /*case NM_SDC1XS:*/
19763 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19764 check_cp1_enabled(ctx);
19765 switch (extract32(ctx->opcode, 7, 4)) {
19766 case NM_LWC1X:
19767 /*case NM_LWC1XS:*/
19768 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19769 break;
19770 case NM_LDC1X:
19771 /*case NM_LDC1XS:*/
19772 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19773 break;
19774 case NM_SWC1X:
19775 /*case NM_SWC1XS:*/
19776 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19777 break;
19778 case NM_SDC1X:
19779 /*case NM_SDC1XS:*/
19780 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19781 break;
19782 }
19783 } else {
19784 generate_exception_err(ctx, EXCP_CpU, 1);
19785 }
19786 break;
19787 default:
19788 generate_exception_end(ctx, EXCP_RI);
19789 break;
19790 }
19791
19792 tcg_temp_free(t0);
19793 tcg_temp_free(t1);
19794}
19795
579b8ea9
YK
19796static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19797{
19798 int rt, rs, rd;
19799
19800 rt = extract32(ctx->opcode, 21, 5);
19801 rs = extract32(ctx->opcode, 16, 5);
19802 rd = extract32(ctx->opcode, 11, 5);
19803
19804 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19805 generate_exception_end(ctx, EXCP_RI);
19806 return;
19807 }
19808 check_cp1_enabled(ctx);
19809 switch (extract32(ctx->opcode, 0, 3)) {
19810 case NM_POOL32F_0:
19811 switch (extract32(ctx->opcode, 3, 7)) {
19812 case NM_RINT_S:
19813 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19814 break;
19815 case NM_RINT_D:
19816 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19817 break;
19818 case NM_CLASS_S:
19819 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19820 break;
19821 case NM_CLASS_D:
19822 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19823 break;
19824 case NM_ADD_S:
19825 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19826 break;
19827 case NM_ADD_D:
19828 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19829 break;
19830 case NM_SUB_S:
19831 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19832 break;
19833 case NM_SUB_D:
19834 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19835 break;
19836 case NM_MUL_S:
19837 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19838 break;
19839 case NM_MUL_D:
19840 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19841 break;
19842 case NM_DIV_S:
19843 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19844 break;
19845 case NM_DIV_D:
19846 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19847 break;
19848 case NM_SELEQZ_S:
19849 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19850 break;
19851 case NM_SELEQZ_D:
19852 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19853 break;
19854 case NM_SELNEZ_S:
19855 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19856 break;
19857 case NM_SELNEZ_D:
19858 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19859 break;
19860 case NM_SEL_S:
19861 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19862 break;
19863 case NM_SEL_D:
19864 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19865 break;
19866 case NM_MADDF_S:
19867 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19868 break;
19869 case NM_MADDF_D:
19870 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19871 break;
19872 case NM_MSUBF_S:
19873 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19874 break;
19875 case NM_MSUBF_D:
19876 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19877 break;
19878 default:
19879 generate_exception_end(ctx, EXCP_RI);
19880 break;
19881 }
19882 break;
19883 case NM_POOL32F_3:
19884 switch (extract32(ctx->opcode, 3, 3)) {
19885 case NM_MIN_FMT:
19886 switch (extract32(ctx->opcode, 9, 1)) {
19887 case FMT_SDPS_S:
19888 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19889 break;
19890 case FMT_SDPS_D:
19891 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19892 break;
19893 }
19894 break;
19895 case NM_MAX_FMT:
19896 switch (extract32(ctx->opcode, 9, 1)) {
19897 case FMT_SDPS_S:
19898 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19899 break;
19900 case FMT_SDPS_D:
19901 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19902 break;
19903 }
19904 break;
19905 case NM_MINA_FMT:
19906 switch (extract32(ctx->opcode, 9, 1)) {
19907 case FMT_SDPS_S:
19908 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19909 break;
19910 case FMT_SDPS_D:
19911 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19912 break;
19913 }
19914 break;
19915 case NM_MAXA_FMT:
19916 switch (extract32(ctx->opcode, 9, 1)) {
19917 case FMT_SDPS_S:
19918 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19919 break;
19920 case FMT_SDPS_D:
19921 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19922 break;
19923 }
19924 break;
19925 case NM_POOL32FXF:
19926 switch (extract32(ctx->opcode, 6, 8)) {
19927 case NM_CFC1:
19928 gen_cp1(ctx, OPC_CFC1, rt, rs);
19929 break;
19930 case NM_CTC1:
19931 gen_cp1(ctx, OPC_CTC1, rt, rs);
19932 break;
19933 case NM_MFC1:
19934 gen_cp1(ctx, OPC_MFC1, rt, rs);
19935 break;
19936 case NM_MTC1:
19937 gen_cp1(ctx, OPC_MTC1, rt, rs);
19938 break;
19939 case NM_MFHC1:
19940 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19941 break;
19942 case NM_MTHC1:
19943 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19944 break;
19945 case NM_CVT_S_PL:
19946 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19947 break;
19948 case NM_CVT_S_PU:
19949 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19950 break;
19951 default:
19952 switch (extract32(ctx->opcode, 6, 9)) {
19953 case NM_CVT_L_S:
19954 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19955 break;
19956 case NM_CVT_L_D:
19957 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19958 break;
19959 case NM_CVT_W_S:
19960 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19961 break;
19962 case NM_CVT_W_D:
19963 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19964 break;
19965 case NM_RSQRT_S:
19966 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19967 break;
19968 case NM_RSQRT_D:
19969 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19970 break;
19971 case NM_SQRT_S:
19972 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19973 break;
19974 case NM_SQRT_D:
19975 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19976 break;
19977 case NM_RECIP_S:
19978 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19979 break;
19980 case NM_RECIP_D:
19981 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19982 break;
19983 case NM_FLOOR_L_S:
19984 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19985 break;
19986 case NM_FLOOR_L_D:
19987 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19988 break;
19989 case NM_FLOOR_W_S:
19990 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19991 break;
19992 case NM_FLOOR_W_D:
19993 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19994 break;
19995 case NM_CEIL_L_S:
19996 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19997 break;
19998 case NM_CEIL_L_D:
19999 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20000 break;
20001 case NM_CEIL_W_S:
20002 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20003 break;
20004 case NM_CEIL_W_D:
20005 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20006 break;
20007 case NM_TRUNC_L_S:
20008 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20009 break;
20010 case NM_TRUNC_L_D:
20011 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20012 break;
20013 case NM_TRUNC_W_S:
20014 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20015 break;
20016 case NM_TRUNC_W_D:
20017 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20018 break;
20019 case NM_ROUND_L_S:
20020 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20021 break;
20022 case NM_ROUND_L_D:
20023 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20024 break;
20025 case NM_ROUND_W_S:
20026 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20027 break;
20028 case NM_ROUND_W_D:
20029 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20030 break;
20031 case NM_MOV_S:
20032 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20033 break;
20034 case NM_MOV_D:
20035 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20036 break;
20037 case NM_ABS_S:
20038 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20039 break;
20040 case NM_ABS_D:
20041 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20042 break;
20043 case NM_NEG_S:
20044 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20045 break;
20046 case NM_NEG_D:
20047 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20048 break;
20049 case NM_CVT_D_S:
20050 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20051 break;
20052 case NM_CVT_D_W:
20053 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20054 break;
20055 case NM_CVT_D_L:
20056 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20057 break;
20058 case NM_CVT_S_D:
20059 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20060 break;
20061 case NM_CVT_S_W:
20062 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20063 break;
20064 case NM_CVT_S_L:
20065 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20066 break;
20067 default:
20068 generate_exception_end(ctx, EXCP_RI);
20069 break;
20070 }
20071 break;
20072 }
20073 break;
20074 }
20075 break;
20076 case NM_POOL32F_5:
20077 switch (extract32(ctx->opcode, 3, 3)) {
20078 case NM_CMP_CONDN_S:
20079 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20080 break;
20081 case NM_CMP_CONDN_D:
20082 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20083 break;
20084 default:
20085 generate_exception_end(ctx, EXCP_RI);
20086 break;
20087 }
20088 break;
20089 default:
20090 generate_exception_end(ctx, EXCP_RI);
20091 break;
20092 }
20093}
20094
3285a3e4
SM
20095static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20096 int rd, int rs, int rt)
20097{
20098 int ret = rd;
20099 TCGv t0 = tcg_temp_new();
20100 TCGv v1_t = tcg_temp_new();
20101 TCGv v2_t = tcg_temp_new();
20102
20103 gen_load_gpr(v1_t, rs);
20104 gen_load_gpr(v2_t, rt);
20105
20106 switch (opc) {
20107 case NM_CMP_EQ_PH:
20108 check_dsp(ctx);
20109 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20110 break;
20111 case NM_CMP_LT_PH:
20112 check_dsp(ctx);
20113 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20114 break;
20115 case NM_CMP_LE_PH:
20116 check_dsp(ctx);
20117 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20118 break;
20119 case NM_CMPU_EQ_QB:
20120 check_dsp(ctx);
20121 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20122 break;
20123 case NM_CMPU_LT_QB:
20124 check_dsp(ctx);
20125 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20126 break;
20127 case NM_CMPU_LE_QB:
20128 check_dsp(ctx);
20129 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20130 break;
20131 case NM_CMPGU_EQ_QB:
20132 check_dsp(ctx);
20133 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20134 gen_store_gpr(v1_t, ret);
20135 break;
20136 case NM_CMPGU_LT_QB:
20137 check_dsp(ctx);
20138 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20139 gen_store_gpr(v1_t, ret);
20140 break;
20141 case NM_CMPGU_LE_QB:
20142 check_dsp(ctx);
20143 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20144 gen_store_gpr(v1_t, ret);
20145 break;
20146 case NM_CMPGDU_EQ_QB:
908f6be1 20147 check_dsp_r2(ctx);
3285a3e4
SM
20148 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20149 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20150 gen_store_gpr(v1_t, ret);
20151 break;
20152 case NM_CMPGDU_LT_QB:
908f6be1 20153 check_dsp_r2(ctx);
3285a3e4
SM
20154 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20155 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20156 gen_store_gpr(v1_t, ret);
20157 break;
20158 case NM_CMPGDU_LE_QB:
908f6be1 20159 check_dsp_r2(ctx);
3285a3e4
SM
20160 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20161 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20162 gen_store_gpr(v1_t, ret);
20163 break;
20164 case NM_PACKRL_PH:
20165 check_dsp(ctx);
20166 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20167 gen_store_gpr(v1_t, ret);
20168 break;
20169 case NM_PICK_QB:
20170 check_dsp(ctx);
20171 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20172 gen_store_gpr(v1_t, ret);
20173 break;
20174 case NM_PICK_PH:
20175 check_dsp(ctx);
20176 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20177 gen_store_gpr(v1_t, ret);
20178 break;
20179 case NM_ADDQ_S_W:
20180 check_dsp(ctx);
20181 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20182 gen_store_gpr(v1_t, ret);
20183 break;
20184 case NM_SUBQ_S_W:
20185 check_dsp(ctx);
20186 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20187 gen_store_gpr(v1_t, ret);
20188 break;
20189 case NM_ADDSC:
20190 check_dsp(ctx);
20191 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20192 gen_store_gpr(v1_t, ret);
20193 break;
20194 case NM_ADDWC:
20195 check_dsp(ctx);
20196 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20197 gen_store_gpr(v1_t, ret);
20198 break;
20199 case NM_ADDQ_S_PH:
20200 check_dsp(ctx);
20201 switch (extract32(ctx->opcode, 10, 1)) {
20202 case 0:
20203 /* ADDQ_PH */
20204 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20205 gen_store_gpr(v1_t, ret);
20206 break;
20207 case 1:
20208 /* ADDQ_S_PH */
20209 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20210 gen_store_gpr(v1_t, ret);
20211 break;
20212 }
20213 break;
20214 case NM_ADDQH_R_PH:
908f6be1 20215 check_dsp_r2(ctx);
3285a3e4
SM
20216 switch (extract32(ctx->opcode, 10, 1)) {
20217 case 0:
20218 /* ADDQH_PH */
20219 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20220 gen_store_gpr(v1_t, ret);
20221 break;
20222 case 1:
20223 /* ADDQH_R_PH */
20224 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20225 gen_store_gpr(v1_t, ret);
20226 break;
20227 }
20228 break;
20229 case NM_ADDQH_R_W:
908f6be1 20230 check_dsp_r2(ctx);
3285a3e4
SM
20231 switch (extract32(ctx->opcode, 10, 1)) {
20232 case 0:
20233 /* ADDQH_W */
20234 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20235 gen_store_gpr(v1_t, ret);
20236 break;
20237 case 1:
20238 /* ADDQH_R_W */
20239 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20240 gen_store_gpr(v1_t, ret);
20241 break;
20242 }
20243 break;
20244 case NM_ADDU_S_QB:
20245 check_dsp(ctx);
20246 switch (extract32(ctx->opcode, 10, 1)) {
20247 case 0:
20248 /* ADDU_QB */
20249 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20250 gen_store_gpr(v1_t, ret);
20251 break;
20252 case 1:
20253 /* ADDU_S_QB */
20254 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20255 gen_store_gpr(v1_t, ret);
20256 break;
20257 }
20258 break;
20259 case NM_ADDU_S_PH:
908f6be1 20260 check_dsp_r2(ctx);
3285a3e4
SM
20261 switch (extract32(ctx->opcode, 10, 1)) {
20262 case 0:
20263 /* ADDU_PH */
20264 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20265 gen_store_gpr(v1_t, ret);
20266 break;
20267 case 1:
20268 /* ADDU_S_PH */
20269 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20270 gen_store_gpr(v1_t, ret);
20271 break;
20272 }
20273 break;
20274 case NM_ADDUH_R_QB:
908f6be1 20275 check_dsp_r2(ctx);
3285a3e4
SM
20276 switch (extract32(ctx->opcode, 10, 1)) {
20277 case 0:
20278 /* ADDUH_QB */
20279 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20280 gen_store_gpr(v1_t, ret);
20281 break;
20282 case 1:
20283 /* ADDUH_R_QB */
20284 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20285 gen_store_gpr(v1_t, ret);
20286 break;
20287 }
20288 break;
20289 case NM_SHRAV_R_PH:
20290 check_dsp(ctx);
20291 switch (extract32(ctx->opcode, 10, 1)) {
20292 case 0:
20293 /* SHRAV_PH */
20294 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20295 gen_store_gpr(v1_t, ret);
20296 break;
20297 case 1:
20298 /* SHRAV_R_PH */
20299 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20300 gen_store_gpr(v1_t, ret);
20301 break;
20302 }
20303 break;
20304 case NM_SHRAV_R_QB:
908f6be1 20305 check_dsp_r2(ctx);
3285a3e4
SM
20306 switch (extract32(ctx->opcode, 10, 1)) {
20307 case 0:
20308 /* SHRAV_QB */
20309 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20310 gen_store_gpr(v1_t, ret);
20311 break;
20312 case 1:
20313 /* SHRAV_R_QB */
20314 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20315 gen_store_gpr(v1_t, ret);
20316 break;
20317 }
20318 break;
20319 case NM_SUBQ_S_PH:
20320 check_dsp(ctx);
20321 switch (extract32(ctx->opcode, 10, 1)) {
20322 case 0:
20323 /* SUBQ_PH */
20324 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20325 gen_store_gpr(v1_t, ret);
20326 break;
20327 case 1:
20328 /* SUBQ_S_PH */
20329 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20330 gen_store_gpr(v1_t, ret);
20331 break;
20332 }
20333 break;
20334 case NM_SUBQH_R_PH:
908f6be1 20335 check_dsp_r2(ctx);
3285a3e4
SM
20336 switch (extract32(ctx->opcode, 10, 1)) {
20337 case 0:
20338 /* SUBQH_PH */
20339 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20340 gen_store_gpr(v1_t, ret);
20341 break;
20342 case 1:
20343 /* SUBQH_R_PH */
20344 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20345 gen_store_gpr(v1_t, ret);
20346 break;
20347 }
20348 break;
20349 case NM_SUBQH_R_W:
908f6be1 20350 check_dsp_r2(ctx);
3285a3e4
SM
20351 switch (extract32(ctx->opcode, 10, 1)) {
20352 case 0:
20353 /* SUBQH_W */
20354 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20355 gen_store_gpr(v1_t, ret);
20356 break;
20357 case 1:
20358 /* SUBQH_R_W */
20359 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20360 gen_store_gpr(v1_t, ret);
20361 break;
20362 }
20363 break;
20364 case NM_SUBU_S_QB:
20365 check_dsp(ctx);
20366 switch (extract32(ctx->opcode, 10, 1)) {
20367 case 0:
20368 /* SUBU_QB */
20369 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20370 gen_store_gpr(v1_t, ret);
20371 break;
20372 case 1:
20373 /* SUBU_S_QB */
20374 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20375 gen_store_gpr(v1_t, ret);
20376 break;
20377 }
20378 break;
20379 case NM_SUBU_S_PH:
908f6be1 20380 check_dsp_r2(ctx);
3285a3e4
SM
20381 switch (extract32(ctx->opcode, 10, 1)) {
20382 case 0:
20383 /* SUBU_PH */
20384 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20385 gen_store_gpr(v1_t, ret);
20386 break;
20387 case 1:
20388 /* SUBU_S_PH */
20389 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20390 gen_store_gpr(v1_t, ret);
20391 break;
20392 }
20393 break;
20394 case NM_SUBUH_R_QB:
908f6be1 20395 check_dsp_r2(ctx);
3285a3e4
SM
20396 switch (extract32(ctx->opcode, 10, 1)) {
20397 case 0:
20398 /* SUBUH_QB */
20399 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20400 gen_store_gpr(v1_t, ret);
20401 break;
20402 case 1:
20403 /* SUBUH_R_QB */
20404 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20405 gen_store_gpr(v1_t, ret);
20406 break;
20407 }
20408 break;
20409 case NM_SHLLV_S_PH:
20410 check_dsp(ctx);
20411 switch (extract32(ctx->opcode, 10, 1)) {
20412 case 0:
20413 /* SHLLV_PH */
20414 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20415 gen_store_gpr(v1_t, ret);
20416 break;
20417 case 1:
20418 /* SHLLV_S_PH */
20419 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20420 gen_store_gpr(v1_t, ret);
20421 break;
20422 }
20423 break;
20424 case NM_PRECR_SRA_R_PH_W:
908f6be1 20425 check_dsp_r2(ctx);
3285a3e4
SM
20426 switch (extract32(ctx->opcode, 10, 1)) {
20427 case 0:
20428 /* PRECR_SRA_PH_W */
20429 {
20430 TCGv_i32 sa_t = tcg_const_i32(rd);
20431 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20432 cpu_gpr[rt]);
20433 gen_store_gpr(v1_t, rt);
20434 tcg_temp_free_i32(sa_t);
20435 }
20436 break;
20437 case 1:
20438 /* PRECR_SRA_R_PH_W */
20439 {
20440 TCGv_i32 sa_t = tcg_const_i32(rd);
20441 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20442 cpu_gpr[rt]);
20443 gen_store_gpr(v1_t, rt);
20444 tcg_temp_free_i32(sa_t);
20445 }
20446 break;
20447 }
20448 break;
20449 case NM_MULEU_S_PH_QBL:
20450 check_dsp(ctx);
20451 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20452 gen_store_gpr(v1_t, ret);
20453 break;
20454 case NM_MULEU_S_PH_QBR:
20455 check_dsp(ctx);
20456 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20457 gen_store_gpr(v1_t, ret);
20458 break;
20459 case NM_MULQ_RS_PH:
20460 check_dsp(ctx);
20461 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20462 gen_store_gpr(v1_t, ret);
20463 break;
20464 case NM_MULQ_S_PH:
908f6be1 20465 check_dsp_r2(ctx);
3285a3e4
SM
20466 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20467 gen_store_gpr(v1_t, ret);
20468 break;
20469 case NM_MULQ_RS_W:
908f6be1 20470 check_dsp_r2(ctx);
3285a3e4
SM
20471 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20472 gen_store_gpr(v1_t, ret);
20473 break;
20474 case NM_MULQ_S_W:
908f6be1 20475 check_dsp_r2(ctx);
3285a3e4
SM
20476 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20477 gen_store_gpr(v1_t, ret);
20478 break;
20479 case NM_APPEND:
908f6be1 20480 check_dsp_r2(ctx);
3285a3e4
SM
20481 gen_load_gpr(t0, rs);
20482 if (rd != 0) {
20483 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20484 }
20485 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20486 break;
20487 case NM_MODSUB:
20488 check_dsp(ctx);
20489 gen_helper_modsub(v1_t, v1_t, v2_t);
20490 gen_store_gpr(v1_t, ret);
20491 break;
20492 case NM_SHRAV_R_W:
20493 check_dsp(ctx);
20494 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20495 gen_store_gpr(v1_t, ret);
20496 break;
20497 case NM_SHRLV_PH:
908f6be1 20498 check_dsp_r2(ctx);
3285a3e4
SM
20499 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20500 gen_store_gpr(v1_t, ret);
20501 break;
20502 case NM_SHRLV_QB:
20503 check_dsp(ctx);
20504 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20505 gen_store_gpr(v1_t, ret);
20506 break;
20507 case NM_SHLLV_QB:
20508 check_dsp(ctx);
20509 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20510 gen_store_gpr(v1_t, ret);
20511 break;
20512 case NM_SHLLV_S_W:
20513 check_dsp(ctx);
20514 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20515 gen_store_gpr(v1_t, ret);
20516 break;
20517 case NM_SHILO:
20518 check_dsp(ctx);
20519 {
20520 TCGv tv0 = tcg_temp_new();
20521 TCGv tv1 = tcg_temp_new();
20522 int16_t imm = extract32(ctx->opcode, 16, 7);
20523
20524 tcg_gen_movi_tl(tv0, rd >> 3);
20525 tcg_gen_movi_tl(tv1, imm);
20526 gen_helper_shilo(tv0, tv1, cpu_env);
20527 }
20528 break;
20529 case NM_MULEQ_S_W_PHL:
20530 check_dsp(ctx);
20531 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20532 gen_store_gpr(v1_t, ret);
20533 break;
20534 case NM_MULEQ_S_W_PHR:
20535 check_dsp(ctx);
20536 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20537 gen_store_gpr(v1_t, ret);
20538 break;
20539 case NM_MUL_S_PH:
908f6be1 20540 check_dsp_r2(ctx);
3285a3e4
SM
20541 switch (extract32(ctx->opcode, 10, 1)) {
20542 case 0:
20543 /* MUL_PH */
20544 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20545 gen_store_gpr(v1_t, ret);
20546 break;
20547 case 1:
20548 /* MUL_S_PH */
20549 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20550 gen_store_gpr(v1_t, ret);
20551 break;
20552 }
20553 break;
20554 case NM_PRECR_QB_PH:
908f6be1 20555 check_dsp_r2(ctx);
3285a3e4
SM
20556 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20557 gen_store_gpr(v1_t, ret);
20558 break;
20559 case NM_PRECRQ_QB_PH:
20560 check_dsp(ctx);
20561 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20562 gen_store_gpr(v1_t, ret);
20563 break;
20564 case NM_PRECRQ_PH_W:
20565 check_dsp(ctx);
20566 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20567 gen_store_gpr(v1_t, ret);
20568 break;
20569 case NM_PRECRQ_RS_PH_W:
20570 check_dsp(ctx);
20571 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20572 gen_store_gpr(v1_t, ret);
20573 break;
20574 case NM_PRECRQU_S_QB_PH:
20575 check_dsp(ctx);
20576 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20577 gen_store_gpr(v1_t, ret);
20578 break;
20579 case NM_SHRA_R_W:
20580 check_dsp(ctx);
20581 tcg_gen_movi_tl(t0, rd);
20582 gen_helper_shra_r_w(v1_t, t0, v1_t);
20583 gen_store_gpr(v1_t, rt);
20584 break;
20585 case NM_SHRA_R_PH:
20586 check_dsp(ctx);
20587 tcg_gen_movi_tl(t0, rd >> 1);
20588 switch (extract32(ctx->opcode, 10, 1)) {
20589 case 0:
20590 /* SHRA_PH */
20591 gen_helper_shra_ph(v1_t, t0, v1_t);
3285a3e4 20592 gen_store_gpr(v1_t, rt);
d5ebcbaf 20593 break;
3285a3e4
SM
20594 case 1:
20595 /* SHRA_R_PH */
20596 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20597 gen_store_gpr(v1_t, rt);
20598 break;
20599 }
20600 break;
20601 case NM_SHLL_S_PH:
20602 check_dsp(ctx);
20603 tcg_gen_movi_tl(t0, rd >> 1);
20604 switch (extract32(ctx->opcode, 10, 2)) {
20605 case 0:
20606 /* SHLL_PH */
20607 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20608 gen_store_gpr(v1_t, rt);
20609 break;
20610 case 2:
20611 /* SHLL_S_PH */
20612 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20613 gen_store_gpr(v1_t, rt);
20614 break;
20615 default:
20616 generate_exception_end(ctx, EXCP_RI);
20617 break;
20618 }
20619 break;
20620 case NM_SHLL_S_W:
20621 check_dsp(ctx);
20622 tcg_gen_movi_tl(t0, rd);
20623 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20624 gen_store_gpr(v1_t, rt);
20625 break;
20626 case NM_REPL_PH:
20627 check_dsp(ctx);
20628 {
20629 int16_t imm;
20630 imm = sextract32(ctx->opcode, 11, 11);
20631 imm = (int16_t)(imm << 6) >> 6;
20632 if (rt != 0) {
20633 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20634 }
20635 }
20636 break;
20637 default:
20638 generate_exception_end(ctx, EXCP_RI);
20639 break;
20640 }
20641}
20642
c0280983
YK
20643static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20644{
20645 uint16_t insn;
20646 uint32_t op;
eac52664 20647 int rt, rs, rd;
c0280983
YK
20648 int offset;
20649 int imm;
20650
20651 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20652 ctx->opcode = (ctx->opcode << 16) | insn;
20653
20654 rt = extract32(ctx->opcode, 21, 5);
20655 rs = extract32(ctx->opcode, 16, 5);
eac52664 20656 rd = extract32(ctx->opcode, 11, 5);
c0280983
YK
20657
20658 op = extract32(ctx->opcode, 26, 6);
20659 switch (op) {
20660 case NM_P_ADDIU:
20661 if (rt == 0) {
20662 /* P.RI */
20663 switch (extract32(ctx->opcode, 19, 2)) {
20664 case NM_SIGRIE:
20665 default:
20666 generate_exception_end(ctx, EXCP_RI);
20667 break;
20668 case NM_P_SYSCALL:
20669 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20670 generate_exception_end(ctx, EXCP_SYSCALL);
20671 } else {
20672 generate_exception_end(ctx, EXCP_RI);
20673 }
20674 break;
20675 case NM_BREAK:
20676 generate_exception_end(ctx, EXCP_BREAK);
20677 break;
20678 case NM_SDBBP:
20679 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20680 gen_helper_do_semihosting(cpu_env);
20681 } else {
20682 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20683 generate_exception_end(ctx, EXCP_RI);
20684 } else {
20685 generate_exception_end(ctx, EXCP_DBp);
20686 }
20687 }
20688 break;
20689 }
20690 } else {
20691 /* NM_ADDIU */
20692 imm = extract32(ctx->opcode, 0, 16);
20693 if (rs != 0) {
20694 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20695 } else {
20696 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20697 }
20698 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20699 }
20700 break;
20701 case NM_ADDIUPC:
20702 if (rt != 0) {
20703 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20704 extract32(ctx->opcode, 1, 20) << 1;
20705 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20706 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20707 }
20708 break;
20709 case NM_POOL32A:
e0cf0e65
YK
20710 switch (ctx->opcode & 0x07) {
20711 case NM_POOL32A0:
0a1a6ed7 20712 gen_pool32a0_nanomips_insn(env, ctx);
e0cf0e65 20713 break;
3285a3e4
SM
20714 case NM_POOL32A5:
20715 {
20716 int32_t op1 = extract32(ctx->opcode, 3, 7);
20717 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20718 }
20719 break;
e0cf0e65 20720 case NM_POOL32A7:
64224187 20721 switch (extract32(ctx->opcode, 3, 3)) {
eac52664
YK
20722 case NM_P_LSX:
20723 gen_p_lsx(ctx, rd, rs, rt);
20724 break;
20725 case NM_LSA:
20726 /* In nanoMIPS, the shift field directly encodes the shift
20727 * amount, meaning that the supported shift values are in
20728 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
20729 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
20730 extract32(ctx->opcode, 9, 2) - 1);
20731 break;
821f2008
JH
20732 case NM_EXTW:
20733 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20734 break;
64224187
YK
20735 case NM_POOL32AXF:
20736 gen_pool32axf_nanomips_insn(env, ctx);
20737 break;
20738 default:
20739 generate_exception_end(ctx, EXCP_RI);
20740 break;
20741 }
e0cf0e65
YK
20742 break;
20743 default:
20744 generate_exception_end(ctx, EXCP_RI);
20745 break;
20746 }
c0280983
YK
20747 break;
20748 case NM_P_GP_W:
20749 switch (ctx->opcode & 0x03) {
20750 case NM_ADDIUGP_W:
20751 if (rt != 0) {
20752 offset = extract32(ctx->opcode, 0, 21);
20753 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20754 }
20755 break;
20756 case NM_LWGP:
20757 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20758 break;
20759 case NM_SWGP:
20760 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20761 break;
20762 default:
20763 generate_exception_end(ctx, EXCP_RI);
20764 break;
20765 }
20766 break;
20767 case NM_P48I:
7ef009b2
YK
20768 {
20769 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
20770 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20771 switch (extract32(ctx->opcode, 16, 5)) {
20772 case NM_LI48:
fb32f8c8 20773 check_nms(ctx);
7ef009b2
YK
20774 if (rt != 0) {
20775 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20776 }
20777 break;
20778 case NM_ADDIU48:
fb32f8c8 20779 check_nms(ctx);
7ef009b2
YK
20780 if (rt != 0) {
20781 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20782 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20783 }
20784 break;
20785 case NM_ADDIUGP48:
fb32f8c8 20786 check_nms(ctx);
7ef009b2
YK
20787 if (rt != 0) {
20788 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20789 }
20790 break;
20791 case NM_ADDIUPC48:
fb32f8c8 20792 check_nms(ctx);
7ef009b2
YK
20793 if (rt != 0) {
20794 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20795 addr_off);
20796
20797 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20798 }
20799 break;
20800 case NM_LWPC48:
fb32f8c8 20801 check_nms(ctx);
7ef009b2
YK
20802 if (rt != 0) {
20803 TCGv t0;
20804 t0 = tcg_temp_new();
20805
20806 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20807 addr_off);
20808
20809 tcg_gen_movi_tl(t0, addr);
20810 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20811 tcg_temp_free(t0);
20812 }
20813 break;
20814 case NM_SWPC48:
fb32f8c8 20815 check_nms(ctx);
7ef009b2
YK
20816 {
20817 TCGv t0, t1;
20818 t0 = tcg_temp_new();
20819 t1 = tcg_temp_new();
20820
20821 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20822 addr_off);
20823
20824 tcg_gen_movi_tl(t0, addr);
20825 gen_load_gpr(t1, rt);
20826
20827 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20828
20829 tcg_temp_free(t0);
20830 tcg_temp_free(t1);
20831 }
20832 break;
20833 default:
20834 generate_exception_end(ctx, EXCP_RI);
20835 break;
20836 }
20837 return 6;
20838 }
c0280983
YK
20839 case NM_P_U12:
20840 switch (extract32(ctx->opcode, 12, 4)) {
20841 case NM_ORI:
20842 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20843 break;
20844 case NM_XORI:
20845 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20846 break;
20847 case NM_ANDI:
20848 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20849 break;
20850 case NM_P_SR:
20851 switch (extract32(ctx->opcode, 20, 1)) {
20852 case NM_PP_SR:
20853 switch (ctx->opcode & 3) {
20854 case NM_SAVE:
20855 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20856 extract32(ctx->opcode, 2, 1),
20857 extract32(ctx->opcode, 3, 9) << 3);
20858 break;
20859 case NM_RESTORE:
20860 case NM_RESTORE_JRC:
20861 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20862 extract32(ctx->opcode, 2, 1),
20863 extract32(ctx->opcode, 3, 9) << 3);
20864 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20865 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20866 }
20867 break;
20868 default:
20869 generate_exception_end(ctx, EXCP_RI);
20870 break;
20871 }
20872 break;
20873 case NM_P_SR_F:
20874 generate_exception_end(ctx, EXCP_RI);
20875 break;
20876 }
20877 break;
20878 case NM_SLTI:
20879 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20880 break;
20881 case NM_SLTIU:
20882 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20883 break;
20884 case NM_SEQI:
20885 {
20886 TCGv t0 = tcg_temp_new();
20887
20888 imm = extract32(ctx->opcode, 0, 12);
20889 gen_load_gpr(t0, rs);
20890 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20891 gen_store_gpr(t0, rt);
20892
20893 tcg_temp_free(t0);
20894 }
20895 break;
20896 case NM_ADDIUNEG:
20897 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20898 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20899 break;
20900 case NM_P_SHIFT:
20901 {
20902 int shift = extract32(ctx->opcode, 0, 5);
20903 switch (extract32(ctx->opcode, 5, 4)) {
20904 case NM_P_SLL:
20905 if (rt == 0 && shift == 0) {
20906 /* NOP */
20907 } else if (rt == 0 && shift == 3) {
20908 /* EHB - treat as NOP */
20909 } else if (rt == 0 && shift == 5) {
20910 /* PAUSE - treat as NOP */
20911 } else if (rt == 0 && shift == 6) {
20912 /* SYNC */
20913 gen_sync(extract32(ctx->opcode, 16, 5));
20914 } else {
20915 /* SLL */
20916 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20917 extract32(ctx->opcode, 0, 5));
20918 }
20919 break;
20920 case NM_SRL:
20921 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20922 extract32(ctx->opcode, 0, 5));
20923 break;
20924 case NM_SRA:
20925 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20926 extract32(ctx->opcode, 0, 5));
20927 break;
20928 case NM_ROTR:
20929 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20930 extract32(ctx->opcode, 0, 5));
20931 break;
20932 }
20933 }
20934 break;
20935 case NM_P_ROTX:
fb32f8c8 20936 check_nms(ctx);
e222f506
MF
20937 if (rt != 0) {
20938 TCGv t0 = tcg_temp_new();
20939 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20940 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20941 << 1);
20942 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20943
20944 gen_load_gpr(t0, rs);
20945 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20946 tcg_temp_free(t0);
20947
20948 tcg_temp_free_i32(shift);
20949 tcg_temp_free_i32(shiftx);
20950 tcg_temp_free_i32(stripe);
20951 }
c0280983
YK
20952 break;
20953 case NM_P_INS:
20954 switch (((ctx->opcode >> 10) & 2) |
20955 (extract32(ctx->opcode, 5, 1))) {
20956 case NM_INS:
fb32f8c8 20957 check_nms(ctx);
c0280983
YK
20958 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20959 extract32(ctx->opcode, 6, 5));
20960 break;
20961 default:
20962 generate_exception_end(ctx, EXCP_RI);
20963 break;
20964 }
20965 break;
20966 case NM_P_EXT:
20967 switch (((ctx->opcode >> 10) & 2) |
20968 (extract32(ctx->opcode, 5, 1))) {
20969 case NM_EXT:
fb32f8c8 20970 check_nms(ctx);
c0280983
YK
20971 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20972 extract32(ctx->opcode, 6, 5));
20973 break;
20974 default:
20975 generate_exception_end(ctx, EXCP_RI);
20976 break;
20977 }
20978 break;
20979 default:
20980 generate_exception_end(ctx, EXCP_RI);
20981 break;
20982 }
20983 break;
20984 case NM_POOL32F:
579b8ea9 20985 gen_pool32f_nanomips_insn(ctx);
c0280983
YK
20986 break;
20987 case NM_POOL32S:
20988 break;
20989 case NM_P_LUI:
20990 switch (extract32(ctx->opcode, 1, 1)) {
20991 case NM_LUI:
20992 if (rt != 0) {
20993 tcg_gen_movi_tl(cpu_gpr[rt],
20994 sextract32(ctx->opcode, 0, 1) << 31 |
20995 extract32(ctx->opcode, 2, 10) << 21 |
20996 extract32(ctx->opcode, 12, 9) << 12);
20997 }
20998 break;
20999 case NM_ALUIPC:
21000 if (rt != 0) {
21001 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21002 extract32(ctx->opcode, 2, 10) << 21 |
21003 extract32(ctx->opcode, 12, 9) << 12;
21004 target_long addr;
21005 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21006 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21007 }
21008 break;
21009 }
21010 break;
21011 case NM_P_GP_BH:
8f1d9b6d
YK
21012 {
21013 uint32_t u = extract32(ctx->opcode, 0, 18);
21014
21015 switch (extract32(ctx->opcode, 18, 3)) {
21016 case NM_LBGP:
21017 gen_ld(ctx, OPC_LB, rt, 28, u);
21018 break;
21019 case NM_SBGP:
21020 gen_st(ctx, OPC_SB, rt, 28, u);
21021 break;
21022 case NM_LBUGP:
21023 gen_ld(ctx, OPC_LBU, rt, 28, u);
21024 break;
21025 case NM_ADDIUGP_B:
21026 if (rt != 0) {
21027 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21028 }
21029 break;
21030 case NM_P_GP_LH:
21031 u &= ~1;
21032 switch (ctx->opcode & 1) {
21033 case NM_LHGP:
21034 gen_ld(ctx, OPC_LH, rt, 28, u);
21035 break;
21036 case NM_LHUGP:
21037 gen_ld(ctx, OPC_LHU, rt, 28, u);
21038 break;
21039 }
21040 break;
21041 case NM_P_GP_SH:
21042 u &= ~1;
21043 switch (ctx->opcode & 1) {
21044 case NM_SHGP:
21045 gen_st(ctx, OPC_SH, rt, 28, u);
21046 break;
21047 default:
21048 generate_exception_end(ctx, EXCP_RI);
21049 break;
21050 }
21051 break;
21052 case NM_P_GP_CP1:
21053 u &= ~0x3;
21054 switch (ctx->opcode & 0x3) {
21055 case NM_LWC1GP:
21056 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21057 break;
21058 case NM_LDC1GP:
21059 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21060 break;
21061 case NM_SWC1GP:
21062 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21063 break;
21064 case NM_SDC1GP:
21065 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21066 break;
21067 }
21068 break;
21069 default:
21070 generate_exception_end(ctx, EXCP_RI);
21071 break;
21072 }
21073 }
c0280983
YK
21074 break;
21075 case NM_P_LS_U12:
8f1d9b6d
YK
21076 {
21077 uint32_t u = extract32(ctx->opcode, 0, 12);
21078
21079 switch (extract32(ctx->opcode, 12, 4)) {
21080 case NM_P_PREFU12:
21081 if (rt == 31) {
21082 /* SYNCI */
21083 /* Break the TB to be able to sync copied instructions
21084 immediately */
21085 ctx->base.is_jmp = DISAS_STOP;
21086 } else {
21087 /* PREF */
21088 /* Treat as NOP. */
21089 }
21090 break;
21091 case NM_LB:
21092 gen_ld(ctx, OPC_LB, rt, rs, u);
21093 break;
21094 case NM_LH:
21095 gen_ld(ctx, OPC_LH, rt, rs, u);
21096 break;
21097 case NM_LW:
21098 gen_ld(ctx, OPC_LW, rt, rs, u);
21099 break;
21100 case NM_LBU:
21101 gen_ld(ctx, OPC_LBU, rt, rs, u);
21102 break;
21103 case NM_LHU:
21104 gen_ld(ctx, OPC_LHU, rt, rs, u);
21105 break;
21106 case NM_SB:
21107 gen_st(ctx, OPC_SB, rt, rs, u);
21108 break;
21109 case NM_SH:
21110 gen_st(ctx, OPC_SH, rt, rs, u);
21111 break;
21112 case NM_SW:
21113 gen_st(ctx, OPC_SW, rt, rs, u);
21114 break;
21115 case NM_LWC1:
21116 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21117 break;
21118 case NM_LDC1:
21119 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21120 break;
21121 case NM_SWC1:
21122 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21123 break;
21124 case NM_SDC1:
21125 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21126 break;
21127 default:
21128 generate_exception_end(ctx, EXCP_RI);
21129 break;
21130 }
21131 }
c0280983
YK
21132 break;
21133 case NM_P_LS_S9:
8f1d9b6d
YK
21134 {
21135 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21136 extract32(ctx->opcode, 0, 8);
21137
21138 switch (extract32(ctx->opcode, 8, 3)) {
21139 case NM_P_LS_S0:
21140 switch (extract32(ctx->opcode, 11, 4)) {
21141 case NM_LBS9:
21142 gen_ld(ctx, OPC_LB, rt, rs, s);
21143 break;
21144 case NM_LHS9:
21145 gen_ld(ctx, OPC_LH, rt, rs, s);
21146 break;
21147 case NM_LWS9:
21148 gen_ld(ctx, OPC_LW, rt, rs, s);
21149 break;
21150 case NM_LBUS9:
21151 gen_ld(ctx, OPC_LBU, rt, rs, s);
21152 break;
21153 case NM_LHUS9:
21154 gen_ld(ctx, OPC_LHU, rt, rs, s);
21155 break;
21156 case NM_SBS9:
21157 gen_st(ctx, OPC_SB, rt, rs, s);
21158 break;
21159 case NM_SHS9:
21160 gen_st(ctx, OPC_SH, rt, rs, s);
21161 break;
21162 case NM_SWS9:
21163 gen_st(ctx, OPC_SW, rt, rs, s);
21164 break;
21165 case NM_LWC1S9:
21166 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21167 break;
21168 case NM_LDC1S9:
21169 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21170 break;
21171 case NM_SWC1S9:
21172 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21173 break;
21174 case NM_SDC1S9:
21175 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21176 break;
21177 case NM_P_PREFS9:
21178 if (rt == 31) {
21179 /* SYNCI */
21180 /* Break the TB to be able to sync copied instructions
21181 immediately */
21182 ctx->base.is_jmp = DISAS_STOP;
21183 } else {
21184 /* PREF */
21185 /* Treat as NOP. */
21186 }
21187 break;
21188 default:
21189 generate_exception_end(ctx, EXCP_RI);
21190 break;
21191 }
21192 break;
21193 case NM_P_LS_S1:
21194 switch (extract32(ctx->opcode, 11, 4)) {
21195 case NM_UALH:
21196 case NM_UASH:
fb32f8c8 21197 check_nms(ctx);
8f1d9b6d
YK
21198 {
21199 TCGv t0 = tcg_temp_new();
21200 TCGv t1 = tcg_temp_new();
21201
21202 gen_base_offset_addr(ctx, t0, rs, s);
21203
21204 switch (extract32(ctx->opcode, 11, 4)) {
21205 case NM_UALH:
21206 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21207 MO_UNALN);
21208 gen_store_gpr(t0, rt);
21209 break;
21210 case NM_UASH:
21211 gen_load_gpr(t1, rt);
21212 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21213 MO_UNALN);
21214 break;
21215 }
21216 tcg_temp_free(t0);
21217 tcg_temp_free(t1);
21218 }
21219 break;
21220 case NM_P_LL:
21221 switch (ctx->opcode & 0x03) {
21222 case NM_LL:
21223 gen_ld(ctx, OPC_LL, rt, rs, s);
21224 break;
21225 case NM_LLWP:
0b16dcd1
AR
21226 check_xnp(ctx);
21227 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
21228 break;
21229 }
21230 break;
21231 case NM_P_SC:
21232 switch (ctx->opcode & 0x03) {
21233 case NM_SC:
21234 gen_st_cond(ctx, OPC_SC, rt, rs, s);
21235 break;
21236 case NM_SCWP:
0b16dcd1
AR
21237 check_xnp(ctx);
21238 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
21239 break;
21240 }
21241 break;
21242 case NM_CACHE:
21243 check_cp0_enabled(ctx);
21244 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21245 gen_cache_operation(ctx, rt, rs, s);
21246 }
21247 break;
21248 }
21249 break;
d046a9ea
DN
21250 case NM_P_LS_E0:
21251 switch (extract32(ctx->opcode, 11, 4)) {
21252 case NM_LBE:
21253 check_eva(ctx);
21254 check_cp0_enabled(ctx);
21255 gen_ld(ctx, OPC_LBE, rt, rs, s);
21256 break;
21257 case NM_SBE:
21258 check_eva(ctx);
21259 check_cp0_enabled(ctx);
21260 gen_st(ctx, OPC_SBE, rt, rs, s);
21261 break;
21262 case NM_LBUE:
21263 check_eva(ctx);
21264 check_cp0_enabled(ctx);
21265 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21266 break;
21267 case NM_P_PREFE:
21268 if (rt == 31) {
21269 /* case NM_SYNCIE */
21270 check_eva(ctx);
21271 check_cp0_enabled(ctx);
21272 /* Break the TB to be able to sync copied instructions
21273 immediately */
21274 ctx->base.is_jmp = DISAS_STOP;
21275 } else {
21276 /* case NM_PREFE */
21277 check_eva(ctx);
21278 check_cp0_enabled(ctx);
21279 /* Treat as NOP. */
21280 }
21281 break;
21282 case NM_LHE:
21283 check_eva(ctx);
21284 check_cp0_enabled(ctx);
21285 gen_ld(ctx, OPC_LHE, rt, rs, s);
21286 break;
21287 case NM_SHE:
21288 check_eva(ctx);
21289 check_cp0_enabled(ctx);
21290 gen_st(ctx, OPC_SHE, rt, rs, s);
21291 break;
21292 case NM_LHUE:
21293 check_eva(ctx);
21294 check_cp0_enabled(ctx);
21295 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21296 break;
21297 case NM_CACHEE:
21298 check_nms_dl_il_sl_tl_l2c(ctx);
21299 gen_cache_operation(ctx, rt, rs, s);
21300 break;
21301 case NM_LWE:
21302 check_eva(ctx);
21303 check_cp0_enabled(ctx);
21304 gen_ld(ctx, OPC_LWE, rt, rs, s);
21305 break;
21306 case NM_SWE:
21307 check_eva(ctx);
21308 check_cp0_enabled(ctx);
21309 gen_st(ctx, OPC_SWE, rt, rs, s);
21310 break;
21311 case NM_P_LLE:
21312 switch (extract32(ctx->opcode, 2, 2)) {
21313 case NM_LLE:
21314 check_xnp(ctx);
21315 check_eva(ctx);
21316 check_cp0_enabled(ctx);
21317 gen_ld(ctx, OPC_LLE, rt, rs, s);
21318 break;
21319 case NM_LLWPE:
21320 check_xnp(ctx);
21321 check_eva(ctx);
21322 check_cp0_enabled(ctx);
21323 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
2431a422 21324 break;
d046a9ea
DN
21325 default:
21326 generate_exception_end(ctx, EXCP_RI);
21327 break;
21328 }
21329 break;
21330 case NM_P_SCE:
21331 switch (extract32(ctx->opcode, 2, 2)) {
21332 case NM_SCE:
21333 check_xnp(ctx);
21334 check_eva(ctx);
21335 check_cp0_enabled(ctx);
21336 gen_st_cond(ctx, OPC_SCE, rt, rs, s);
21337 break;
21338 case NM_SCWPE:
21339 check_xnp(ctx);
21340 check_eva(ctx);
21341 check_cp0_enabled(ctx);
21342 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
2431a422 21343 break;
d046a9ea
DN
21344 default:
21345 generate_exception_end(ctx, EXCP_RI);
21346 break;
21347 }
21348 break;
21349 }
21350 break;
8f1d9b6d
YK
21351 case NM_P_LS_WM:
21352 case NM_P_LS_UAWM:
fb32f8c8 21353 check_nms(ctx);
8f1d9b6d
YK
21354 {
21355 int count = extract32(ctx->opcode, 12, 3);
21356 int counter = 0;
21357
21358 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21359 extract32(ctx->opcode, 0, 8);
21360 TCGv va = tcg_temp_new();
21361 TCGv t1 = tcg_temp_new();
21362 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21363 NM_P_LS_UAWM ? MO_UNALN : 0;
21364
21365 count = (count == 0) ? 8 : count;
21366 while (counter != count) {
21367 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21368 int this_offset = offset + (counter << 2);
21369
21370 gen_base_offset_addr(ctx, va, rs, this_offset);
21371
21372 switch (extract32(ctx->opcode, 11, 1)) {
21373 case NM_LWM:
21374 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21375 memop | MO_TESL);
21376 gen_store_gpr(t1, this_rt);
21377 if ((this_rt == rs) &&
21378 (counter != (count - 1))) {
21379 /* UNPREDICTABLE */
21380 }
21381 break;
21382 case NM_SWM:
21383 this_rt = (rt == 0) ? 0 : this_rt;
21384 gen_load_gpr(t1, this_rt);
21385 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21386 memop | MO_TEUL);
21387 break;
21388 }
21389 counter++;
21390 }
21391 tcg_temp_free(va);
21392 tcg_temp_free(t1);
21393 }
21394 break;
21395 default:
21396 generate_exception_end(ctx, EXCP_RI);
21397 break;
21398 }
21399 }
c0280983
YK
21400 break;
21401 case NM_MOVE_BALC:
fb32f8c8 21402 check_nms(ctx);
11d0fc10
SM
21403 {
21404 TCGv t0 = tcg_temp_new();
21405 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21406 extract32(ctx->opcode, 1, 20) << 1;
21407 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21408 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21409 extract32(ctx->opcode, 21, 3));
21410 gen_load_gpr(t0, rt);
21411 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21412 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21413 tcg_temp_free(t0);
21414 }
c0280983
YK
21415 break;
21416 case NM_P_BAL:
11d0fc10
SM
21417 {
21418 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21419 extract32(ctx->opcode, 1, 24) << 1;
21420
21421 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21422 /* BC */
21423 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21424 } else {
21425 /* BALC */
21426 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21427 }
21428 }
c0280983
YK
21429 break;
21430 case NM_P_J:
11d0fc10
SM
21431 switch (extract32(ctx->opcode, 12, 4)) {
21432 case NM_JALRC:
21433 case NM_JALRC_HB:
21434 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21435 break;
21436 case NM_P_BALRSC:
21437 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21438 break;
21439 default:
21440 generate_exception_end(ctx, EXCP_RI);
21441 break;
21442 }
c0280983
YK
21443 break;
21444 case NM_P_BR1:
11d0fc10
SM
21445 {
21446 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21447 extract32(ctx->opcode, 1, 13) << 1;
21448 switch (extract32(ctx->opcode, 14, 2)) {
21449 case NM_BEQC:
fb32f8c8 21450 check_nms(ctx);
11d0fc10
SM
21451 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21452 break;
21453 case NM_P_BR3A:
21454 s = sextract32(ctx->opcode, 0, 1) << 14 |
21455 extract32(ctx->opcode, 1, 13) << 1;
21456 check_cp1_enabled(ctx);
21457 switch (extract32(ctx->opcode, 16, 5)) {
21458 case NM_BC1EQZC:
21459 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21460 break;
21461 case NM_BC1NEZC:
21462 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21463 break;
6d033ca7 21464 case NM_BPOSGE32C:
908f6be1 21465 check_dsp_r3(ctx);
6d033ca7
SM
21466 {
21467 int32_t imm = extract32(ctx->opcode, 1, 13) |
21468 extract32(ctx->opcode, 0, 1) << 13;
21469
21470 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21471 imm);
21472 }
21473 break;
11d0fc10
SM
21474 default:
21475 generate_exception_end(ctx, EXCP_RI);
21476 break;
21477 }
21478 break;
21479 case NM_BGEC:
21480 if (rs == rt) {
21481 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21482 } else {
21483 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21484 }
21485 break;
21486 case NM_BGEUC:
21487 if (rs == rt || rt == 0) {
21488 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21489 } else if (rs == 0) {
21490 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21491 } else {
21492 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21493 }
21494 break;
21495 }
21496 }
c0280983
YK
21497 break;
21498 case NM_P_BR2:
11d0fc10
SM
21499 {
21500 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21501 extract32(ctx->opcode, 1, 13) << 1;
21502 switch (extract32(ctx->opcode, 14, 2)) {
21503 case NM_BNEC:
fb32f8c8 21504 check_nms(ctx);
11d0fc10
SM
21505 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21506 break;
21507 case NM_BLTC:
21508 if (rs != 0 && rt != 0 && rs == rt) {
21509 /* NOP */
21510 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21511 } else {
21512 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21513 }
21514 break;
21515 case NM_BLTUC:
21516 if (rs == 0 || rs == rt) {
21517 /* NOP */
21518 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21519 } else {
21520 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21521 }
21522 break;
21523 default:
21524 generate_exception_end(ctx, EXCP_RI);
21525 break;
21526 }
21527 }
c0280983
YK
21528 break;
21529 case NM_P_BRI:
11d0fc10
SM
21530 {
21531 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21532 extract32(ctx->opcode, 1, 10) << 1;
21533 uint32_t u = extract32(ctx->opcode, 11, 7);
21534
21535 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21536 rt, u, s);
21537 }
c0280983
YK
21538 break;
21539 default:
21540 generate_exception_end(ctx, EXCP_RI);
21541 break;
21542 }
21543 return 4;
21544}
21545
c533c0f4
AM
21546static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21547{
ea4ca3c2
YK
21548 uint32_t op;
21549 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
21550 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21551 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
8bdb7029 21552 int offset;
ea4ca3c2
YK
21553 int imm;
21554
21555 /* make sure instructions are on a halfword boundary */
21556 if (ctx->base.pc_next & 0x1) {
21557 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21558 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21559 tcg_temp_free(tmp);
21560 generate_exception_end(ctx, EXCP_AdEL);
21561 return 2;
21562 }
21563
21564 op = extract32(ctx->opcode, 10, 6);
21565 switch (op) {
21566 case NM_P16_MV:
8869ad02
YK
21567 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21568 if (rt != 0) {
21569 /* MOVE */
21570 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21571 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21572 } else {
21573 /* P16.RI */
21574 switch (extract32(ctx->opcode, 3, 2)) {
21575 case NM_P16_SYSCALL:
21576 if (extract32(ctx->opcode, 2, 1) == 0) {
21577 generate_exception_end(ctx, EXCP_SYSCALL);
21578 } else {
21579 generate_exception_end(ctx, EXCP_RI);
21580 }
21581 break;
21582 case NM_BREAK16:
21583 generate_exception_end(ctx, EXCP_BREAK);
21584 break;
21585 case NM_SDBBP16:
21586 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21587 gen_helper_do_semihosting(cpu_env);
21588 } else {
21589 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21590 generate_exception_end(ctx, EXCP_RI);
21591 } else {
21592 generate_exception_end(ctx, EXCP_DBp);
21593 }
21594 }
21595 break;
21596 default:
21597 generate_exception_end(ctx, EXCP_RI);
21598 break;
21599 }
21600 }
ea4ca3c2
YK
21601 break;
21602 case NM_P16_SHIFT:
c46562fb
YK
21603 {
21604 int shift = extract32(ctx->opcode, 0, 3);
21605 uint32_t opc = 0;
21606 shift = (shift == 0) ? 8 : shift;
21607
21608 switch (extract32(ctx->opcode, 3, 1)) {
21609 case NM_SLL16:
21610 opc = OPC_SLL;
21611 break;
21612 case NM_SRL16:
21613 opc = OPC_SRL;
21614 break;
21615 }
21616 gen_shift_imm(ctx, opc, rt, rs, shift);
21617 }
ea4ca3c2
YK
21618 break;
21619 case NM_P16C:
8bdb7029
YK
21620 switch (ctx->opcode & 1) {
21621 case NM_POOL16C_0:
80845edf 21622 gen_pool16c_nanomips_insn(ctx);
8bdb7029
YK
21623 break;
21624 case NM_LWXS16:
21625 gen_ldxs(ctx, rt, rs, rd);
21626 break;
21627 }
ea4ca3c2
YK
21628 break;
21629 case NM_P16_A1:
21630 switch (extract32(ctx->opcode, 6, 1)) {
21631 case NM_ADDIUR1SP:
21632 imm = extract32(ctx->opcode, 0, 6) << 2;
21633 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21634 break;
21635 default:
21636 generate_exception_end(ctx, EXCP_RI);
21637 break;
21638 }
21639 break;
21640 case NM_P16_A2:
21641 switch (extract32(ctx->opcode, 3, 1)) {
21642 case NM_ADDIUR2:
21643 imm = extract32(ctx->opcode, 0, 3) << 2;
21644 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21645 break;
21646 case NM_P_ADDIURS5:
21647 rt = extract32(ctx->opcode, 5, 5);
21648 if (rt != 0) {
21649 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21650 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21651 (extract32(ctx->opcode, 0, 3));
21652 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21653 }
21654 break;
21655 }
21656 break;
21657 case NM_P16_ADDU:
21658 switch (ctx->opcode & 0x1) {
21659 case NM_ADDU16:
21660 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21661 break;
21662 case NM_SUBU16:
21663 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21664 break;
21665 }
21666 break;
21667 case NM_P16_4X4:
21668 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21669 extract32(ctx->opcode, 5, 3);
21670 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21671 extract32(ctx->opcode, 0, 3);
21672 rt = decode_gpr_gpr4(rt);
21673 rs = decode_gpr_gpr4(rs);
21674 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21675 (extract32(ctx->opcode, 3, 1))) {
21676 case NM_ADDU4X4:
fb32f8c8 21677 check_nms(ctx);
ea4ca3c2
YK
21678 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21679 break;
21680 case NM_MUL4X4:
fb32f8c8 21681 check_nms(ctx);
ea4ca3c2
YK
21682 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21683 break;
21684 default:
21685 generate_exception_end(ctx, EXCP_RI);
21686 break;
21687 }
21688 break;
21689 case NM_LI16:
8869ad02
YK
21690 {
21691 int imm = extract32(ctx->opcode, 0, 7);
21692 imm = (imm == 0x7f ? -1 : imm);
21693 if (rt != 0) {
21694 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21695 }
21696 }
ea4ca3c2
YK
21697 break;
21698 case NM_ANDI16:
80845edf
YK
21699 {
21700 uint32_t u = extract32(ctx->opcode, 0, 4);
21701 u = (u == 12) ? 0xff :
21702 (u == 13) ? 0xffff : u;
21703 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21704 }
ea4ca3c2
YK
21705 break;
21706 case NM_P16_LB:
8bdb7029
YK
21707 offset = extract32(ctx->opcode, 0, 2);
21708 switch (extract32(ctx->opcode, 2, 2)) {
21709 case NM_LB16:
21710 gen_ld(ctx, OPC_LB, rt, rs, offset);
21711 break;
21712 case NM_SB16:
21713 rt = decode_gpr_gpr3_src_store(
21714 NANOMIPS_EXTRACT_RD(ctx->opcode));
21715 gen_st(ctx, OPC_SB, rt, rs, offset);
21716 break;
21717 case NM_LBU16:
21718 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21719 break;
21720 default:
21721 generate_exception_end(ctx, EXCP_RI);
21722 break;
21723 }
ea4ca3c2
YK
21724 break;
21725 case NM_P16_LH:
8bdb7029
YK
21726 offset = extract32(ctx->opcode, 1, 2) << 1;
21727 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21728 case NM_LH16:
21729 gen_ld(ctx, OPC_LH, rt, rs, offset);
21730 break;
21731 case NM_SH16:
21732 rt = decode_gpr_gpr3_src_store(
21733 NANOMIPS_EXTRACT_RD(ctx->opcode));
21734 gen_st(ctx, OPC_SH, rt, rs, offset);
21735 break;
21736 case NM_LHU16:
21737 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21738 break;
21739 default:
21740 generate_exception_end(ctx, EXCP_RI);
21741 break;
21742 }
ea4ca3c2
YK
21743 break;
21744 case NM_LW16:
8bdb7029
YK
21745 offset = extract32(ctx->opcode, 0, 4) << 2;
21746 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
21747 break;
21748 case NM_LWSP16:
8bdb7029
YK
21749 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21750 offset = extract32(ctx->opcode, 0, 5) << 2;
21751 gen_ld(ctx, OPC_LW, rt, 29, offset);
ea4ca3c2
YK
21752 break;
21753 case NM_LW4X4:
fb32f8c8 21754 check_nms(ctx);
8bdb7029
YK
21755 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21756 extract32(ctx->opcode, 5, 3);
21757 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21758 extract32(ctx->opcode, 0, 3);
21759 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21760 (extract32(ctx->opcode, 8, 1) << 2);
21761 rt = decode_gpr_gpr4(rt);
21762 rs = decode_gpr_gpr4(rs);
21763 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
21764 break;
21765 case NM_SW4X4:
fb32f8c8 21766 check_nms(ctx);
8bdb7029
YK
21767 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21768 extract32(ctx->opcode, 5, 3);
21769 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21770 extract32(ctx->opcode, 0, 3);
21771 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21772 (extract32(ctx->opcode, 8, 1) << 2);
21773 rt = decode_gpr_gpr4_zero(rt);
21774 rs = decode_gpr_gpr4(rs);
21775 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
21776 break;
21777 case NM_LWGP16:
8bdb7029
YK
21778 offset = extract32(ctx->opcode, 0, 7) << 2;
21779 gen_ld(ctx, OPC_LW, rt, 28, offset);
ea4ca3c2
YK
21780 break;
21781 case NM_SWSP16:
8bdb7029
YK
21782 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21783 offset = extract32(ctx->opcode, 0, 5) << 2;
21784 gen_st(ctx, OPC_SW, rt, 29, offset);
ea4ca3c2
YK
21785 break;
21786 case NM_SW16:
8bdb7029
YK
21787 rt = decode_gpr_gpr3_src_store(
21788 NANOMIPS_EXTRACT_RD(ctx->opcode));
21789 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21790 offset = extract32(ctx->opcode, 0, 4) << 2;
21791 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
21792 break;
21793 case NM_SWGP16:
8bdb7029
YK
21794 rt = decode_gpr_gpr3_src_store(
21795 NANOMIPS_EXTRACT_RD(ctx->opcode));
21796 offset = extract32(ctx->opcode, 0, 7) << 2;
21797 gen_st(ctx, OPC_SW, rt, 28, offset);
ea4ca3c2
YK
21798 break;
21799 case NM_BC16:
764371d2
SM
21800 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21801 (sextract32(ctx->opcode, 0, 1) << 10) |
21802 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
21803 break;
21804 case NM_BALC16:
764371d2
SM
21805 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21806 (sextract32(ctx->opcode, 0, 1) << 10) |
21807 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
21808 break;
21809 case NM_BEQZC16:
764371d2
SM
21810 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21811 (sextract32(ctx->opcode, 0, 1) << 7) |
21812 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
21813 break;
21814 case NM_BNEZC16:
764371d2
SM
21815 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21816 (sextract32(ctx->opcode, 0, 1) << 7) |
21817 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
21818 break;
21819 case NM_P16_BR:
764371d2
SM
21820 switch (ctx->opcode & 0xf) {
21821 case 0:
21822 /* P16.JRC */
21823 switch (extract32(ctx->opcode, 4, 1)) {
21824 case NM_JRC:
21825 gen_compute_branch_nm(ctx, OPC_JR, 2,
21826 extract32(ctx->opcode, 5, 5), 0, 0);
21827 break;
21828 case NM_JALRC16:
21829 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21830 extract32(ctx->opcode, 5, 5), 31, 0);
21831 break;
21832 }
21833 break;
21834 default:
21835 {
21836 /* P16.BRI */
21837 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21838 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21839 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21840 extract32(ctx->opcode, 0, 4) << 1);
21841 }
21842 break;
21843 }
ea4ca3c2
YK
21844 break;
21845 case NM_P16_SR:
bf0718c5
SM
21846 {
21847 int count = extract32(ctx->opcode, 0, 4);
21848 int u = extract32(ctx->opcode, 4, 4) << 4;
21849
21850 rt = 30 + extract32(ctx->opcode, 9, 1);
21851 switch (extract32(ctx->opcode, 8, 1)) {
21852 case NM_SAVE16:
21853 gen_save(ctx, rt, count, 0, u);
21854 break;
21855 case NM_RESTORE_JRC16:
21856 gen_restore(ctx, rt, count, 0, u);
21857 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21858 break;
21859 }
21860 }
ea4ca3c2
YK
21861 break;
21862 case NM_MOVEP:
ea4ca3c2 21863 case NM_MOVEPREV:
fb32f8c8 21864 check_nms(ctx);
4d18232c
YK
21865 {
21866 static const int gpr2reg1[] = {4, 5, 6, 7};
21867 static const int gpr2reg2[] = {5, 6, 7, 8};
21868 int re;
21869 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21870 extract32(ctx->opcode, 8, 1);
21871 int r1 = gpr2reg1[rd2];
21872 int r2 = gpr2reg2[rd2];
21873 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21874 extract32(ctx->opcode, 0, 3);
21875 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21876 extract32(ctx->opcode, 5, 3);
21877 TCGv t0 = tcg_temp_new();
21878 TCGv t1 = tcg_temp_new();
21879 if (op == NM_MOVEP) {
21880 rd = r1;
21881 re = r2;
21882 rs = decode_gpr_gpr4_zero(r3);
21883 rt = decode_gpr_gpr4_zero(r4);
21884 } else {
21885 rd = decode_gpr_gpr4(r3);
21886 re = decode_gpr_gpr4(r4);
21887 rs = r1;
21888 rt = r2;
21889 }
21890 gen_load_gpr(t0, rs);
21891 gen_load_gpr(t1, rt);
21892 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21893 tcg_gen_mov_tl(cpu_gpr[re], t1);
21894 tcg_temp_free(t0);
21895 tcg_temp_free(t1);
21896 }
ea4ca3c2
YK
21897 break;
21898 default:
c0280983 21899 return decode_nanomips_32_48_opc(env, ctx);
ea4ca3c2
YK
21900 }
21901
c533c0f4
AM
21902 return 2;
21903}
21904
21905
3c824109
NF
21906/* SmartMIPS extension to MIPS32 */
21907
21908#if defined(TARGET_MIPS64)
21909
21910/* MDMX extension to MIPS64 */
21911
21912#endif
21913
9b1a1d68 21914/* MIPSDSP functions. */
d75c135e 21915static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
9b1a1d68
JL
21916 int rd, int base, int offset)
21917{
9b1a1d68
JL
21918 TCGv t0;
21919
9b1a1d68
JL
21920 check_dsp(ctx);
21921 t0 = tcg_temp_new();
21922
21923 if (base == 0) {
21924 gen_load_gpr(t0, offset);
21925 } else if (offset == 0) {
21926 gen_load_gpr(t0, base);
21927 } else {
21928 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21929 }
21930
9b1a1d68
JL
21931 switch (opc) {
21932 case OPC_LBUX:
5f68f5ae 21933 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
9b1a1d68 21934 gen_store_gpr(t0, rd);
9b1a1d68
JL
21935 break;
21936 case OPC_LHX:
5f68f5ae 21937 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
9b1a1d68 21938 gen_store_gpr(t0, rd);
9b1a1d68
JL
21939 break;
21940 case OPC_LWX:
5f68f5ae 21941 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9b1a1d68 21942 gen_store_gpr(t0, rd);
9b1a1d68
JL
21943 break;
21944#if defined(TARGET_MIPS64)
21945 case OPC_LDX:
5f68f5ae 21946 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
9b1a1d68 21947 gen_store_gpr(t0, rd);
9b1a1d68
JL
21948 break;
21949#endif
21950 }
9b1a1d68
JL
21951 tcg_temp_free(t0);
21952}
21953
461c08df
JL
21954static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21955 int ret, int v1, int v2)
21956{
461c08df
JL
21957 TCGv v1_t;
21958 TCGv v2_t;
21959
21960 if (ret == 0) {
21961 /* Treat as NOP. */
461c08df
JL
21962 return;
21963 }
21964
21965 v1_t = tcg_temp_new();
21966 v2_t = tcg_temp_new();
21967
21968 gen_load_gpr(v1_t, v1);
21969 gen_load_gpr(v2_t, v2);
21970
21971 switch (op1) {
21972 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21973 case OPC_MULT_G_2E:
908f6be1 21974 check_dsp_r2(ctx);
461c08df
JL
21975 switch (op2) {
21976 case OPC_ADDUH_QB:
21977 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21978 break;
21979 case OPC_ADDUH_R_QB:
21980 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21981 break;
21982 case OPC_ADDQH_PH:
21983 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21984 break;
21985 case OPC_ADDQH_R_PH:
21986 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21987 break;
21988 case OPC_ADDQH_W:
21989 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21990 break;
21991 case OPC_ADDQH_R_W:
21992 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21993 break;
21994 case OPC_SUBUH_QB:
21995 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21996 break;
21997 case OPC_SUBUH_R_QB:
21998 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21999 break;
22000 case OPC_SUBQH_PH:
22001 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22002 break;
22003 case OPC_SUBQH_R_PH:
22004 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22005 break;
22006 case OPC_SUBQH_W:
22007 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22008 break;
22009 case OPC_SUBQH_R_W:
22010 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22011 break;
22012 }
22013 break;
22014 case OPC_ABSQ_S_PH_DSP:
22015 switch (op2) {
22016 case OPC_ABSQ_S_QB:
908f6be1 22017 check_dsp_r2(ctx);
461c08df
JL
22018 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22019 break;
22020 case OPC_ABSQ_S_PH:
22021 check_dsp(ctx);
22022 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22023 break;
22024 case OPC_ABSQ_S_W:
22025 check_dsp(ctx);
22026 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22027 break;
22028 case OPC_PRECEQ_W_PHL:
22029 check_dsp(ctx);
22030 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22031 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22032 break;
22033 case OPC_PRECEQ_W_PHR:
22034 check_dsp(ctx);
22035 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22036 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22037 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22038 break;
22039 case OPC_PRECEQU_PH_QBL:
22040 check_dsp(ctx);
22041 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22042 break;
22043 case OPC_PRECEQU_PH_QBR:
22044 check_dsp(ctx);
22045 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22046 break;
22047 case OPC_PRECEQU_PH_QBLA:
22048 check_dsp(ctx);
22049 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22050 break;
22051 case OPC_PRECEQU_PH_QBRA:
22052 check_dsp(ctx);
22053 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22054 break;
22055 case OPC_PRECEU_PH_QBL:
22056 check_dsp(ctx);
22057 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22058 break;
22059 case OPC_PRECEU_PH_QBR:
22060 check_dsp(ctx);
22061 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22062 break;
22063 case OPC_PRECEU_PH_QBLA:
22064 check_dsp(ctx);
22065 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22066 break;
22067 case OPC_PRECEU_PH_QBRA:
22068 check_dsp(ctx);
22069 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22070 break;
22071 }
22072 break;
22073 case OPC_ADDU_QB_DSP:
22074 switch (op2) {
22075 case OPC_ADDQ_PH:
22076 check_dsp(ctx);
22077 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22078 break;
22079 case OPC_ADDQ_S_PH:
22080 check_dsp(ctx);
22081 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22082 break;
22083 case OPC_ADDQ_S_W:
22084 check_dsp(ctx);
22085 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22086 break;
22087 case OPC_ADDU_QB:
22088 check_dsp(ctx);
22089 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22090 break;
22091 case OPC_ADDU_S_QB:
22092 check_dsp(ctx);
22093 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22094 break;
22095 case OPC_ADDU_PH:
908f6be1 22096 check_dsp_r2(ctx);
461c08df
JL
22097 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22098 break;
22099 case OPC_ADDU_S_PH:
908f6be1 22100 check_dsp_r2(ctx);
461c08df
JL
22101 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22102 break;
22103 case OPC_SUBQ_PH:
22104 check_dsp(ctx);
22105 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22106 break;
22107 case OPC_SUBQ_S_PH:
22108 check_dsp(ctx);
22109 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22110 break;
22111 case OPC_SUBQ_S_W:
22112 check_dsp(ctx);
22113 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22114 break;
22115 case OPC_SUBU_QB:
22116 check_dsp(ctx);
22117 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22118 break;
22119 case OPC_SUBU_S_QB:
22120 check_dsp(ctx);
22121 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22122 break;
22123 case OPC_SUBU_PH:
908f6be1 22124 check_dsp_r2(ctx);
461c08df
JL
22125 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22126 break;
22127 case OPC_SUBU_S_PH:
908f6be1 22128 check_dsp_r2(ctx);
461c08df
JL
22129 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22130 break;
22131 case OPC_ADDSC:
22132 check_dsp(ctx);
22133 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22134 break;
22135 case OPC_ADDWC:
22136 check_dsp(ctx);
22137 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22138 break;
22139 case OPC_MODSUB:
22140 check_dsp(ctx);
22141 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22142 break;
22143 case OPC_RADDU_W_QB:
22144 check_dsp(ctx);
22145 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22146 break;
22147 }
22148 break;
22149 case OPC_CMPU_EQ_QB_DSP:
22150 switch (op2) {
22151 case OPC_PRECR_QB_PH:
908f6be1 22152 check_dsp_r2(ctx);
461c08df
JL
22153 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22154 break;
22155 case OPC_PRECRQ_QB_PH:
22156 check_dsp(ctx);
22157 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22158 break;
22159 case OPC_PRECR_SRA_PH_W:
908f6be1 22160 check_dsp_r2(ctx);
461c08df
JL
22161 {
22162 TCGv_i32 sa_t = tcg_const_i32(v2);
22163 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22164 cpu_gpr[ret]);
22165 tcg_temp_free_i32(sa_t);
22166 break;
22167 }
22168 case OPC_PRECR_SRA_R_PH_W:
908f6be1 22169 check_dsp_r2(ctx);
461c08df
JL
22170 {
22171 TCGv_i32 sa_t = tcg_const_i32(v2);
22172 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22173 cpu_gpr[ret]);
22174 tcg_temp_free_i32(sa_t);
22175 break;
22176 }
22177 case OPC_PRECRQ_PH_W:
22178 check_dsp(ctx);
22179 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22180 break;
22181 case OPC_PRECRQ_RS_PH_W:
22182 check_dsp(ctx);
22183 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22184 break;
22185 case OPC_PRECRQU_S_QB_PH:
22186 check_dsp(ctx);
22187 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22188 break;
22189 }
22190 break;
22191#ifdef TARGET_MIPS64
22192 case OPC_ABSQ_S_QH_DSP:
22193 switch (op2) {
22194 case OPC_PRECEQ_L_PWL:
22195 check_dsp(ctx);
22196 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22197 break;
22198 case OPC_PRECEQ_L_PWR:
22199 check_dsp(ctx);
22200 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22201 break;
22202 case OPC_PRECEQ_PW_QHL:
22203 check_dsp(ctx);
22204 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22205 break;
22206 case OPC_PRECEQ_PW_QHR:
22207 check_dsp(ctx);
22208 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22209 break;
22210 case OPC_PRECEQ_PW_QHLA:
22211 check_dsp(ctx);
22212 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22213 break;
22214 case OPC_PRECEQ_PW_QHRA:
22215 check_dsp(ctx);
22216 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22217 break;
22218 case OPC_PRECEQU_QH_OBL:
22219 check_dsp(ctx);
22220 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22221 break;
22222 case OPC_PRECEQU_QH_OBR:
22223 check_dsp(ctx);
22224 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22225 break;
22226 case OPC_PRECEQU_QH_OBLA:
22227 check_dsp(ctx);
22228 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22229 break;
22230 case OPC_PRECEQU_QH_OBRA:
22231 check_dsp(ctx);
22232 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22233 break;
22234 case OPC_PRECEU_QH_OBL:
22235 check_dsp(ctx);
22236 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22237 break;
22238 case OPC_PRECEU_QH_OBR:
22239 check_dsp(ctx);
22240 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22241 break;
22242 case OPC_PRECEU_QH_OBLA:
22243 check_dsp(ctx);
22244 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22245 break;
22246 case OPC_PRECEU_QH_OBRA:
22247 check_dsp(ctx);
22248 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22249 break;
22250 case OPC_ABSQ_S_OB:
908f6be1 22251 check_dsp_r2(ctx);
461c08df
JL
22252 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22253 break;
22254 case OPC_ABSQ_S_PW:
22255 check_dsp(ctx);
22256 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22257 break;
22258 case OPC_ABSQ_S_QH:
22259 check_dsp(ctx);
22260 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22261 break;
22262 }
22263 break;
22264 case OPC_ADDU_OB_DSP:
22265 switch (op2) {
22266 case OPC_RADDU_L_OB:
22267 check_dsp(ctx);
22268 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22269 break;
22270 case OPC_SUBQ_PW:
22271 check_dsp(ctx);
22272 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22273 break;
22274 case OPC_SUBQ_S_PW:
22275 check_dsp(ctx);
22276 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22277 break;
22278 case OPC_SUBQ_QH:
22279 check_dsp(ctx);
22280 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22281 break;
22282 case OPC_SUBQ_S_QH:
22283 check_dsp(ctx);
22284 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22285 break;
22286 case OPC_SUBU_OB:
22287 check_dsp(ctx);
22288 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22289 break;
22290 case OPC_SUBU_S_OB:
22291 check_dsp(ctx);
22292 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22293 break;
22294 case OPC_SUBU_QH:
908f6be1 22295 check_dsp_r2(ctx);
461c08df
JL
22296 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22297 break;
22298 case OPC_SUBU_S_QH:
908f6be1 22299 check_dsp_r2(ctx);
461c08df
JL
22300 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22301 break;
22302 case OPC_SUBUH_OB:
908f6be1 22303 check_dsp_r2(ctx);
461c08df
JL
22304 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22305 break;
22306 case OPC_SUBUH_R_OB:
908f6be1 22307 check_dsp_r2(ctx);
461c08df
JL
22308 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22309 break;
22310 case OPC_ADDQ_PW:
22311 check_dsp(ctx);
22312 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22313 break;
22314 case OPC_ADDQ_S_PW:
22315 check_dsp(ctx);
22316 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22317 break;
22318 case OPC_ADDQ_QH:
22319 check_dsp(ctx);
22320 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22321 break;
22322 case OPC_ADDQ_S_QH:
22323 check_dsp(ctx);
22324 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22325 break;
22326 case OPC_ADDU_OB:
22327 check_dsp(ctx);
22328 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22329 break;
22330 case OPC_ADDU_S_OB:
22331 check_dsp(ctx);
22332 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22333 break;
22334 case OPC_ADDU_QH:
908f6be1 22335 check_dsp_r2(ctx);
461c08df
JL
22336 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22337 break;
22338 case OPC_ADDU_S_QH:
908f6be1 22339 check_dsp_r2(ctx);
461c08df
JL
22340 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22341 break;
22342 case OPC_ADDUH_OB:
908f6be1 22343 check_dsp_r2(ctx);
461c08df
JL
22344 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22345 break;
22346 case OPC_ADDUH_R_OB:
908f6be1 22347 check_dsp_r2(ctx);
461c08df
JL
22348 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22349 break;
22350 }
22351 break;
22352 case OPC_CMPU_EQ_OB_DSP:
22353 switch (op2) {
22354 case OPC_PRECR_OB_QH:
908f6be1 22355 check_dsp_r2(ctx);
461c08df
JL
22356 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22357 break;
22358 case OPC_PRECR_SRA_QH_PW:
908f6be1 22359 check_dsp_r2(ctx);
461c08df
JL
22360 {
22361 TCGv_i32 ret_t = tcg_const_i32(ret);
22362 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22363 tcg_temp_free_i32(ret_t);
22364 break;
22365 }
22366 case OPC_PRECR_SRA_R_QH_PW:
908f6be1 22367 check_dsp_r2(ctx);
461c08df
JL
22368 {
22369 TCGv_i32 sa_v = tcg_const_i32(ret);
22370 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22371 tcg_temp_free_i32(sa_v);
22372 break;
22373 }
22374 case OPC_PRECRQ_OB_QH:
22375 check_dsp(ctx);
22376 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22377 break;
22378 case OPC_PRECRQ_PW_L:
22379 check_dsp(ctx);
22380 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22381 break;
22382 case OPC_PRECRQ_QH_PW:
22383 check_dsp(ctx);
22384 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22385 break;
22386 case OPC_PRECRQ_RS_QH_PW:
22387 check_dsp(ctx);
22388 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22389 break;
22390 case OPC_PRECRQU_S_OB_QH:
22391 check_dsp(ctx);
22392 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22393 break;
22394 }
22395 break;
22396#endif
22397 }
22398
22399 tcg_temp_free(v1_t);
22400 tcg_temp_free(v2_t);
461c08df 22401}
9b1a1d68 22402
77c5fa8b
JL
22403static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22404 int ret, int v1, int v2)
22405{
22406 uint32_t op2;
77c5fa8b
JL
22407 TCGv t0;
22408 TCGv v1_t;
22409 TCGv v2_t;
22410
22411 if (ret == 0) {
22412 /* Treat as NOP. */
77c5fa8b
JL
22413 return;
22414 }
22415
22416 t0 = tcg_temp_new();
22417 v1_t = tcg_temp_new();
22418 v2_t = tcg_temp_new();
22419
22420 tcg_gen_movi_tl(t0, v1);
22421 gen_load_gpr(v1_t, v1);
22422 gen_load_gpr(v2_t, v2);
22423
22424 switch (opc) {
22425 case OPC_SHLL_QB_DSP:
22426 {
22427 op2 = MASK_SHLL_QB(ctx->opcode);
22428 switch (op2) {
22429 case OPC_SHLL_QB:
22430 check_dsp(ctx);
22431 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22432 break;
22433 case OPC_SHLLV_QB:
22434 check_dsp(ctx);
22435 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22436 break;
22437 case OPC_SHLL_PH:
22438 check_dsp(ctx);
22439 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22440 break;
22441 case OPC_SHLLV_PH:
22442 check_dsp(ctx);
22443 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22444 break;
22445 case OPC_SHLL_S_PH:
22446 check_dsp(ctx);
22447 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22448 break;
22449 case OPC_SHLLV_S_PH:
22450 check_dsp(ctx);
22451 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22452 break;
22453 case OPC_SHLL_S_W:
22454 check_dsp(ctx);
22455 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22456 break;
22457 case OPC_SHLLV_S_W:
22458 check_dsp(ctx);
22459 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22460 break;
22461 case OPC_SHRL_QB:
22462 check_dsp(ctx);
22463 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22464 break;
22465 case OPC_SHRLV_QB:
22466 check_dsp(ctx);
22467 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22468 break;
22469 case OPC_SHRL_PH:
908f6be1 22470 check_dsp_r2(ctx);
77c5fa8b
JL
22471 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22472 break;
22473 case OPC_SHRLV_PH:
908f6be1 22474 check_dsp_r2(ctx);
77c5fa8b
JL
22475 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22476 break;
22477 case OPC_SHRA_QB:
908f6be1 22478 check_dsp_r2(ctx);
77c5fa8b
JL
22479 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22480 break;
22481 case OPC_SHRA_R_QB:
908f6be1 22482 check_dsp_r2(ctx);
77c5fa8b
JL
22483 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22484 break;
22485 case OPC_SHRAV_QB:
908f6be1 22486 check_dsp_r2(ctx);
77c5fa8b
JL
22487 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22488 break;
22489 case OPC_SHRAV_R_QB:
908f6be1 22490 check_dsp_r2(ctx);
77c5fa8b
JL
22491 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22492 break;
22493 case OPC_SHRA_PH:
22494 check_dsp(ctx);
22495 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22496 break;
22497 case OPC_SHRA_R_PH:
22498 check_dsp(ctx);
22499 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22500 break;
22501 case OPC_SHRAV_PH:
22502 check_dsp(ctx);
22503 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22504 break;
22505 case OPC_SHRAV_R_PH:
22506 check_dsp(ctx);
22507 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22508 break;
22509 case OPC_SHRA_R_W:
22510 check_dsp(ctx);
22511 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22512 break;
22513 case OPC_SHRAV_R_W:
22514 check_dsp(ctx);
22515 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22516 break;
22517 default: /* Invalid */
22518 MIPS_INVAL("MASK SHLL.QB");
9c708c7f 22519 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
22520 break;
22521 }
22522 break;
22523 }
22524#ifdef TARGET_MIPS64
22525 case OPC_SHLL_OB_DSP:
22526 op2 = MASK_SHLL_OB(ctx->opcode);
22527 switch (op2) {
22528 case OPC_SHLL_PW:
22529 check_dsp(ctx);
22530 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22531 break;
22532 case OPC_SHLLV_PW:
22533 check_dsp(ctx);
22534 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22535 break;
22536 case OPC_SHLL_S_PW:
22537 check_dsp(ctx);
22538 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22539 break;
22540 case OPC_SHLLV_S_PW:
22541 check_dsp(ctx);
22542 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22543 break;
22544 case OPC_SHLL_OB:
22545 check_dsp(ctx);
22546 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22547 break;
22548 case OPC_SHLLV_OB:
22549 check_dsp(ctx);
22550 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22551 break;
22552 case OPC_SHLL_QH:
22553 check_dsp(ctx);
22554 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22555 break;
22556 case OPC_SHLLV_QH:
22557 check_dsp(ctx);
22558 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22559 break;
22560 case OPC_SHLL_S_QH:
22561 check_dsp(ctx);
22562 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22563 break;
22564 case OPC_SHLLV_S_QH:
22565 check_dsp(ctx);
22566 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22567 break;
22568 case OPC_SHRA_OB:
908f6be1 22569 check_dsp_r2(ctx);
77c5fa8b
JL
22570 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22571 break;
22572 case OPC_SHRAV_OB:
908f6be1 22573 check_dsp_r2(ctx);
77c5fa8b
JL
22574 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22575 break;
22576 case OPC_SHRA_R_OB:
908f6be1 22577 check_dsp_r2(ctx);
77c5fa8b
JL
22578 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22579 break;
22580 case OPC_SHRAV_R_OB:
908f6be1 22581 check_dsp_r2(ctx);
77c5fa8b
JL
22582 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22583 break;
22584 case OPC_SHRA_PW:
22585 check_dsp(ctx);
22586 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22587 break;
22588 case OPC_SHRAV_PW:
22589 check_dsp(ctx);
22590 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22591 break;
22592 case OPC_SHRA_R_PW:
22593 check_dsp(ctx);
22594 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22595 break;
22596 case OPC_SHRAV_R_PW:
22597 check_dsp(ctx);
22598 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22599 break;
22600 case OPC_SHRA_QH:
22601 check_dsp(ctx);
22602 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22603 break;
22604 case OPC_SHRAV_QH:
22605 check_dsp(ctx);
22606 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22607 break;
22608 case OPC_SHRA_R_QH:
22609 check_dsp(ctx);
22610 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22611 break;
22612 case OPC_SHRAV_R_QH:
22613 check_dsp(ctx);
22614 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22615 break;
22616 case OPC_SHRL_OB:
22617 check_dsp(ctx);
22618 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22619 break;
22620 case OPC_SHRLV_OB:
22621 check_dsp(ctx);
22622 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22623 break;
22624 case OPC_SHRL_QH:
908f6be1 22625 check_dsp_r2(ctx);
77c5fa8b
JL
22626 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22627 break;
22628 case OPC_SHRLV_QH:
908f6be1 22629 check_dsp_r2(ctx);
77c5fa8b
JL
22630 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22631 break;
22632 default: /* Invalid */
22633 MIPS_INVAL("MASK SHLL.OB");
9c708c7f 22634 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
22635 break;
22636 }
22637 break;
22638#endif
22639 }
22640
22641 tcg_temp_free(t0);
22642 tcg_temp_free(v1_t);
22643 tcg_temp_free(v2_t);
77c5fa8b
JL
22644}
22645
a22260ae
JL
22646static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22647 int ret, int v1, int v2, int check_ret)
22648{
a22260ae
JL
22649 TCGv_i32 t0;
22650 TCGv v1_t;
22651 TCGv v2_t;
22652
22653 if ((ret == 0) && (check_ret == 1)) {
22654 /* Treat as NOP. */
a22260ae
JL
22655 return;
22656 }
22657
22658 t0 = tcg_temp_new_i32();
22659 v1_t = tcg_temp_new();
22660 v2_t = tcg_temp_new();
22661
22662 tcg_gen_movi_i32(t0, ret);
22663 gen_load_gpr(v1_t, v1);
22664 gen_load_gpr(v2_t, v2);
22665
22666 switch (op1) {
22667 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22668 * the same mask and op1. */
22669 case OPC_MULT_G_2E:
908f6be1 22670 check_dsp_r2(ctx);
a22260ae
JL
22671 switch (op2) {
22672 case OPC_MUL_PH:
22673 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22674 break;
22675 case OPC_MUL_S_PH:
22676 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22677 break;
22678 case OPC_MULQ_S_W:
22679 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22680 break;
22681 case OPC_MULQ_RS_W:
22682 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22683 break;
22684 }
22685 break;
22686 case OPC_DPA_W_PH_DSP:
22687 switch (op2) {
22688 case OPC_DPAU_H_QBL:
22689 check_dsp(ctx);
22690 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22691 break;
22692 case OPC_DPAU_H_QBR:
22693 check_dsp(ctx);
22694 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22695 break;
22696 case OPC_DPSU_H_QBL:
22697 check_dsp(ctx);
22698 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22699 break;
22700 case OPC_DPSU_H_QBR:
22701 check_dsp(ctx);
22702 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22703 break;
22704 case OPC_DPA_W_PH:
908f6be1 22705 check_dsp_r2(ctx);
a22260ae
JL
22706 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22707 break;
22708 case OPC_DPAX_W_PH:
908f6be1 22709 check_dsp_r2(ctx);
a22260ae
JL
22710 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22711 break;
22712 case OPC_DPAQ_S_W_PH:
22713 check_dsp(ctx);
22714 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22715 break;
22716 case OPC_DPAQX_S_W_PH:
908f6be1 22717 check_dsp_r2(ctx);
a22260ae
JL
22718 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22719 break;
22720 case OPC_DPAQX_SA_W_PH:
908f6be1 22721 check_dsp_r2(ctx);
a22260ae
JL
22722 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22723 break;
22724 case OPC_DPS_W_PH:
908f6be1 22725 check_dsp_r2(ctx);
a22260ae
JL
22726 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22727 break;
22728 case OPC_DPSX_W_PH:
908f6be1 22729 check_dsp_r2(ctx);
a22260ae
JL
22730 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22731 break;
22732 case OPC_DPSQ_S_W_PH:
22733 check_dsp(ctx);
22734 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22735 break;
22736 case OPC_DPSQX_S_W_PH:
908f6be1 22737 check_dsp_r2(ctx);
a22260ae
JL
22738 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22739 break;
22740 case OPC_DPSQX_SA_W_PH:
908f6be1 22741 check_dsp_r2(ctx);
a22260ae
JL
22742 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22743 break;
22744 case OPC_MULSAQ_S_W_PH:
22745 check_dsp(ctx);
22746 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22747 break;
22748 case OPC_DPAQ_SA_L_W:
22749 check_dsp(ctx);
22750 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22751 break;
22752 case OPC_DPSQ_SA_L_W:
22753 check_dsp(ctx);
22754 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22755 break;
22756 case OPC_MAQ_S_W_PHL:
22757 check_dsp(ctx);
22758 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22759 break;
22760 case OPC_MAQ_S_W_PHR:
22761 check_dsp(ctx);
22762 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22763 break;
22764 case OPC_MAQ_SA_W_PHL:
22765 check_dsp(ctx);
22766 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22767 break;
22768 case OPC_MAQ_SA_W_PHR:
22769 check_dsp(ctx);
22770 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22771 break;
22772 case OPC_MULSA_W_PH:
908f6be1 22773 check_dsp_r2(ctx);
a22260ae
JL
22774 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22775 break;
22776 }
22777 break;
22778#ifdef TARGET_MIPS64
22779 case OPC_DPAQ_W_QH_DSP:
22780 {
22781 int ac = ret & 0x03;
22782 tcg_gen_movi_i32(t0, ac);
22783
22784 switch (op2) {
22785 case OPC_DMADD:
22786 check_dsp(ctx);
22787 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22788 break;
22789 case OPC_DMADDU:
22790 check_dsp(ctx);
22791 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22792 break;
22793 case OPC_DMSUB:
22794 check_dsp(ctx);
22795 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22796 break;
22797 case OPC_DMSUBU:
22798 check_dsp(ctx);
22799 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22800 break;
22801 case OPC_DPA_W_QH:
908f6be1 22802 check_dsp_r2(ctx);
a22260ae
JL
22803 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22804 break;
22805 case OPC_DPAQ_S_W_QH:
22806 check_dsp(ctx);
22807 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22808 break;
22809 case OPC_DPAQ_SA_L_PW:
22810 check_dsp(ctx);
22811 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22812 break;
22813 case OPC_DPAU_H_OBL:
22814 check_dsp(ctx);
22815 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22816 break;
22817 case OPC_DPAU_H_OBR:
22818 check_dsp(ctx);
22819 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22820 break;
22821 case OPC_DPS_W_QH:
908f6be1 22822 check_dsp_r2(ctx);
a22260ae
JL
22823 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22824 break;
22825 case OPC_DPSQ_S_W_QH:
22826 check_dsp(ctx);
22827 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22828 break;
22829 case OPC_DPSQ_SA_L_PW:
22830 check_dsp(ctx);
22831 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22832 break;
22833 case OPC_DPSU_H_OBL:
22834 check_dsp(ctx);
22835 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22836 break;
22837 case OPC_DPSU_H_OBR:
22838 check_dsp(ctx);
22839 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22840 break;
22841 case OPC_MAQ_S_L_PWL:
22842 check_dsp(ctx);
22843 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22844 break;
22845 case OPC_MAQ_S_L_PWR:
22846 check_dsp(ctx);
22847 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22848 break;
22849 case OPC_MAQ_S_W_QHLL:
22850 check_dsp(ctx);
22851 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22852 break;
22853 case OPC_MAQ_SA_W_QHLL:
22854 check_dsp(ctx);
22855 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22856 break;
22857 case OPC_MAQ_S_W_QHLR:
22858 check_dsp(ctx);
22859 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22860 break;
22861 case OPC_MAQ_SA_W_QHLR:
22862 check_dsp(ctx);
22863 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22864 break;
22865 case OPC_MAQ_S_W_QHRL:
22866 check_dsp(ctx);
22867 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22868 break;
22869 case OPC_MAQ_SA_W_QHRL:
22870 check_dsp(ctx);
22871 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22872 break;
22873 case OPC_MAQ_S_W_QHRR:
22874 check_dsp(ctx);
22875 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22876 break;
22877 case OPC_MAQ_SA_W_QHRR:
22878 check_dsp(ctx);
22879 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22880 break;
22881 case OPC_MULSAQ_S_L_PW:
22882 check_dsp(ctx);
22883 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22884 break;
22885 case OPC_MULSAQ_S_W_QH:
22886 check_dsp(ctx);
22887 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22888 break;
22889 }
22890 }
22891 break;
22892#endif
22893 case OPC_ADDU_QB_DSP:
22894 switch (op2) {
22895 case OPC_MULEU_S_PH_QBL:
22896 check_dsp(ctx);
22897 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22898 break;
22899 case OPC_MULEU_S_PH_QBR:
22900 check_dsp(ctx);
22901 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22902 break;
22903 case OPC_MULQ_RS_PH:
22904 check_dsp(ctx);
22905 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22906 break;
22907 case OPC_MULEQ_S_W_PHL:
22908 check_dsp(ctx);
22909 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22910 break;
22911 case OPC_MULEQ_S_W_PHR:
22912 check_dsp(ctx);
22913 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22914 break;
22915 case OPC_MULQ_S_PH:
908f6be1 22916 check_dsp_r2(ctx);
a22260ae
JL
22917 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22918 break;
22919 }
22920 break;
22921#ifdef TARGET_MIPS64
22922 case OPC_ADDU_OB_DSP:
22923 switch (op2) {
22924 case OPC_MULEQ_S_PW_QHL:
22925 check_dsp(ctx);
22926 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22927 break;
22928 case OPC_MULEQ_S_PW_QHR:
22929 check_dsp(ctx);
22930 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22931 break;
22932 case OPC_MULEU_S_QH_OBL:
22933 check_dsp(ctx);
22934 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22935 break;
22936 case OPC_MULEU_S_QH_OBR:
22937 check_dsp(ctx);
22938 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22939 break;
22940 case OPC_MULQ_RS_QH:
22941 check_dsp(ctx);
22942 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22943 break;
22944 }
22945 break;
22946#endif
22947 }
22948
22949 tcg_temp_free_i32(t0);
22950 tcg_temp_free(v1_t);
22951 tcg_temp_free(v2_t);
a22260ae
JL
22952}
22953
d75c135e 22954static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
1cb6686c
JL
22955 int ret, int val)
22956{
1cb6686c
JL
22957 int16_t imm;
22958 TCGv t0;
22959 TCGv val_t;
22960
22961 if (ret == 0) {
22962 /* Treat as NOP. */
1cb6686c
JL
22963 return;
22964 }
22965
22966 t0 = tcg_temp_new();
22967 val_t = tcg_temp_new();
22968 gen_load_gpr(val_t, val);
22969
22970 switch (op1) {
22971 case OPC_ABSQ_S_PH_DSP:
22972 switch (op2) {
22973 case OPC_BITREV:
22974 check_dsp(ctx);
22975 gen_helper_bitrev(cpu_gpr[ret], val_t);
22976 break;
22977 case OPC_REPL_QB:
22978 check_dsp(ctx);
22979 {
22980 target_long result;
22981 imm = (ctx->opcode >> 16) & 0xFF;
22982 result = (uint32_t)imm << 24 |
22983 (uint32_t)imm << 16 |
22984 (uint32_t)imm << 8 |
22985 (uint32_t)imm;
22986 result = (int32_t)result;
22987 tcg_gen_movi_tl(cpu_gpr[ret], result);
22988 }
22989 break;
22990 case OPC_REPLV_QB:
22991 check_dsp(ctx);
22992 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22993 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22994 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22995 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22996 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22997 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22998 break;
22999 case OPC_REPL_PH:
23000 check_dsp(ctx);
23001 {
23002 imm = (ctx->opcode >> 16) & 0x03FF;
c4aaba92 23003 imm = (int16_t)(imm << 6) >> 6;
1cb6686c
JL
23004 tcg_gen_movi_tl(cpu_gpr[ret], \
23005 (target_long)((int32_t)imm << 16 | \
c4aaba92 23006 (uint16_t)imm));
1cb6686c
JL
23007 }
23008 break;
23009 case OPC_REPLV_PH:
23010 check_dsp(ctx);
23011 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23012 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23013 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23014 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23015 break;
23016 }
23017 break;
23018#ifdef TARGET_MIPS64
23019 case OPC_ABSQ_S_QH_DSP:
23020 switch (op2) {
23021 case OPC_REPL_OB:
23022 check_dsp(ctx);
23023 {
23024 target_long temp;
23025
23026 imm = (ctx->opcode >> 16) & 0xFF;
23027 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23028 temp = (temp << 16) | temp;
23029 temp = (temp << 32) | temp;
23030 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23031 break;
23032 }
23033 case OPC_REPL_PW:
23034 check_dsp(ctx);
23035 {
23036 target_long temp;
23037
23038 imm = (ctx->opcode >> 16) & 0x03FF;
23039 imm = (int16_t)(imm << 6) >> 6;
23040 temp = ((target_long)imm << 32) \
23041 | ((target_long)imm & 0xFFFFFFFF);
23042 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23043 break;
23044 }
23045 case OPC_REPL_QH:
23046 check_dsp(ctx);
23047 {
23048 target_long temp;
23049
23050 imm = (ctx->opcode >> 16) & 0x03FF;
23051 imm = (int16_t)(imm << 6) >> 6;
23052
23053 temp = ((uint64_t)(uint16_t)imm << 48) |
23054 ((uint64_t)(uint16_t)imm << 32) |
23055 ((uint64_t)(uint16_t)imm << 16) |
23056 (uint64_t)(uint16_t)imm;
23057 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23058 break;
23059 }
23060 case OPC_REPLV_OB:
23061 check_dsp(ctx);
23062 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23063 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23064 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23065 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23066 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23067 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23068 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23069 break;
23070 case OPC_REPLV_PW:
23071 check_dsp(ctx);
23072 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23073 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23074 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23075 break;
23076 case OPC_REPLV_QH:
23077 check_dsp(ctx);
23078 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23079 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23080 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23081 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23082 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23083 break;
23084 }
23085 break;
23086#endif
23087 }
23088 tcg_temp_free(t0);
23089 tcg_temp_free(val_t);
1cb6686c
JL
23090}
23091
26690560
JL
23092static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23093 uint32_t op1, uint32_t op2,
23094 int ret, int v1, int v2, int check_ret)
23095{
26690560
JL
23096 TCGv t1;
23097 TCGv v1_t;
23098 TCGv v2_t;
23099
23100 if ((ret == 0) && (check_ret == 1)) {
23101 /* Treat as NOP. */
26690560
JL
23102 return;
23103 }
23104
26690560
JL
23105 t1 = tcg_temp_new();
23106 v1_t = tcg_temp_new();
23107 v2_t = tcg_temp_new();
23108
23109 gen_load_gpr(v1_t, v1);
23110 gen_load_gpr(v2_t, v2);
23111
23112 switch (op1) {
26690560
JL
23113 case OPC_CMPU_EQ_QB_DSP:
23114 switch (op2) {
23115 case OPC_CMPU_EQ_QB:
23116 check_dsp(ctx);
23117 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23118 break;
23119 case OPC_CMPU_LT_QB:
23120 check_dsp(ctx);
23121 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23122 break;
23123 case OPC_CMPU_LE_QB:
23124 check_dsp(ctx);
23125 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23126 break;
23127 case OPC_CMPGU_EQ_QB:
23128 check_dsp(ctx);
23129 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23130 break;
23131 case OPC_CMPGU_LT_QB:
23132 check_dsp(ctx);
23133 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23134 break;
23135 case OPC_CMPGU_LE_QB:
23136 check_dsp(ctx);
23137 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23138 break;
23139 case OPC_CMPGDU_EQ_QB:
908f6be1 23140 check_dsp_r2(ctx);
26690560
JL
23141 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23142 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23143 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23144 tcg_gen_shli_tl(t1, t1, 24);
23145 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23146 break;
23147 case OPC_CMPGDU_LT_QB:
908f6be1 23148 check_dsp_r2(ctx);
26690560
JL
23149 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23150 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23151 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23152 tcg_gen_shli_tl(t1, t1, 24);
23153 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23154 break;
23155 case OPC_CMPGDU_LE_QB:
908f6be1 23156 check_dsp_r2(ctx);
26690560
JL
23157 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23158 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23159 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23160 tcg_gen_shli_tl(t1, t1, 24);
23161 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23162 break;
23163 case OPC_CMP_EQ_PH:
23164 check_dsp(ctx);
23165 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23166 break;
23167 case OPC_CMP_LT_PH:
23168 check_dsp(ctx);
23169 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23170 break;
23171 case OPC_CMP_LE_PH:
23172 check_dsp(ctx);
23173 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23174 break;
23175 case OPC_PICK_QB:
23176 check_dsp(ctx);
23177 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23178 break;
23179 case OPC_PICK_PH:
23180 check_dsp(ctx);
23181 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23182 break;
23183 case OPC_PACKRL_PH:
23184 check_dsp(ctx);
23185 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23186 break;
23187 }
23188 break;
23189#ifdef TARGET_MIPS64
23190 case OPC_CMPU_EQ_OB_DSP:
23191 switch (op2) {
23192 case OPC_CMP_EQ_PW:
23193 check_dsp(ctx);
23194 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23195 break;
23196 case OPC_CMP_LT_PW:
23197 check_dsp(ctx);
23198 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23199 break;
23200 case OPC_CMP_LE_PW:
23201 check_dsp(ctx);
23202 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23203 break;
23204 case OPC_CMP_EQ_QH:
23205 check_dsp(ctx);
23206 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23207 break;
23208 case OPC_CMP_LT_QH:
23209 check_dsp(ctx);
23210 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23211 break;
23212 case OPC_CMP_LE_QH:
23213 check_dsp(ctx);
23214 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23215 break;
23216 case OPC_CMPGDU_EQ_OB:
908f6be1 23217 check_dsp_r2(ctx);
26690560
JL
23218 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23219 break;
23220 case OPC_CMPGDU_LT_OB:
908f6be1 23221 check_dsp_r2(ctx);
26690560
JL
23222 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23223 break;
23224 case OPC_CMPGDU_LE_OB:
908f6be1 23225 check_dsp_r2(ctx);
26690560
JL
23226 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23227 break;
23228 case OPC_CMPGU_EQ_OB:
23229 check_dsp(ctx);
23230 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23231 break;
23232 case OPC_CMPGU_LT_OB:
23233 check_dsp(ctx);
23234 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23235 break;
23236 case OPC_CMPGU_LE_OB:
23237 check_dsp(ctx);
23238 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23239 break;
23240 case OPC_CMPU_EQ_OB:
23241 check_dsp(ctx);
23242 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23243 break;
23244 case OPC_CMPU_LT_OB:
23245 check_dsp(ctx);
23246 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23247 break;
23248 case OPC_CMPU_LE_OB:
23249 check_dsp(ctx);
23250 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23251 break;
23252 case OPC_PACKRL_PW:
23253 check_dsp(ctx);
23254 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23255 break;
23256 case OPC_PICK_OB:
23257 check_dsp(ctx);
23258 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23259 break;
23260 case OPC_PICK_PW:
23261 check_dsp(ctx);
23262 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23263 break;
23264 case OPC_PICK_QH:
23265 check_dsp(ctx);
23266 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23267 break;
23268 }
23269 break;
df6126a7
AJ
23270#endif
23271 }
23272
23273 tcg_temp_free(t1);
23274 tcg_temp_free(v1_t);
23275 tcg_temp_free(v2_t);
df6126a7
AJ
23276}
23277
23278static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23279 uint32_t op1, int rt, int rs, int sa)
23280{
df6126a7
AJ
23281 TCGv t0;
23282
908f6be1 23283 check_dsp_r2(ctx);
df6126a7
AJ
23284
23285 if (rt == 0) {
23286 /* Treat as NOP. */
df6126a7
AJ
23287 return;
23288 }
23289
23290 t0 = tcg_temp_new();
23291 gen_load_gpr(t0, rs);
23292
23293 switch (op1) {
23294 case OPC_APPEND_DSP:
23295 switch (MASK_APPEND(ctx->opcode)) {
23296 case OPC_APPEND:
23297 if (sa != 0) {
23298 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23299 }
23300 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23301 break;
23302 case OPC_PREPEND:
23303 if (sa != 0) {
23304 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23305 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23306 tcg_gen_shli_tl(t0, t0, 32 - sa);
23307 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23308 }
23309 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23310 break;
23311 case OPC_BALIGN:
23312 sa &= 3;
23313 if (sa != 0 && sa != 2) {
23314 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23315 tcg_gen_ext32u_tl(t0, t0);
23316 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23317 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23318 }
23319 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23320 break;
23321 default: /* Invalid */
23322 MIPS_INVAL("MASK APPEND");
9c708c7f 23323 generate_exception_end(ctx, EXCP_RI);
df6126a7
AJ
23324 break;
23325 }
23326 break;
23327#ifdef TARGET_MIPS64
26690560 23328 case OPC_DAPPEND_DSP:
df6126a7 23329 switch (MASK_DAPPEND(ctx->opcode)) {
26690560 23330 case OPC_DAPPEND:
df6126a7
AJ
23331 if (sa != 0) {
23332 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23333 }
26690560
JL
23334 break;
23335 case OPC_PREPENDD:
df6126a7
AJ
23336 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23337 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23338 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
26690560
JL
23339 break;
23340 case OPC_PREPENDW:
df6126a7
AJ
23341 if (sa != 0) {
23342 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23343 tcg_gen_shli_tl(t0, t0, 64 - sa);
23344 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23345 }
26690560
JL
23346 break;
23347 case OPC_DBALIGN:
df6126a7
AJ
23348 sa &= 7;
23349 if (sa != 0 && sa != 2 && sa != 4) {
23350 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23351 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23352 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23353 }
26690560
JL
23354 break;
23355 default: /* Invalid */
23356 MIPS_INVAL("MASK DAPPEND");
9c708c7f 23357 generate_exception_end(ctx, EXCP_RI);
26690560
JL
23358 break;
23359 }
23360 break;
23361#endif
23362 }
df6126a7 23363 tcg_temp_free(t0);
26690560
JL
23364}
23365
b53371ed
JL
23366static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23367 int ret, int v1, int v2, int check_ret)
23368
23369{
b53371ed
JL
23370 TCGv t0;
23371 TCGv t1;
23372 TCGv v1_t;
23373 TCGv v2_t;
23374 int16_t imm;
23375
23376 if ((ret == 0) && (check_ret == 1)) {
23377 /* Treat as NOP. */
b53371ed
JL
23378 return;
23379 }
23380
23381 t0 = tcg_temp_new();
23382 t1 = tcg_temp_new();
23383 v1_t = tcg_temp_new();
23384 v2_t = tcg_temp_new();
23385
23386 gen_load_gpr(v1_t, v1);
23387 gen_load_gpr(v2_t, v2);
23388
23389 switch (op1) {
23390 case OPC_EXTR_W_DSP:
23391 check_dsp(ctx);
23392 switch (op2) {
23393 case OPC_EXTR_W:
23394 tcg_gen_movi_tl(t0, v2);
23395 tcg_gen_movi_tl(t1, v1);
23396 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23397 break;
23398 case OPC_EXTR_R_W:
23399 tcg_gen_movi_tl(t0, v2);
23400 tcg_gen_movi_tl(t1, v1);
23401 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23402 break;
23403 case OPC_EXTR_RS_W:
23404 tcg_gen_movi_tl(t0, v2);
23405 tcg_gen_movi_tl(t1, v1);
23406 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23407 break;
23408 case OPC_EXTR_S_H:
23409 tcg_gen_movi_tl(t0, v2);
23410 tcg_gen_movi_tl(t1, v1);
23411 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23412 break;
23413 case OPC_EXTRV_S_H:
23414 tcg_gen_movi_tl(t0, v2);
23415 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23416 break;
23417 case OPC_EXTRV_W:
23418 tcg_gen_movi_tl(t0, v2);
23419 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23420 break;
23421 case OPC_EXTRV_R_W:
23422 tcg_gen_movi_tl(t0, v2);
23423 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23424 break;
23425 case OPC_EXTRV_RS_W:
23426 tcg_gen_movi_tl(t0, v2);
23427 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23428 break;
23429 case OPC_EXTP:
23430 tcg_gen_movi_tl(t0, v2);
23431 tcg_gen_movi_tl(t1, v1);
23432 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23433 break;
23434 case OPC_EXTPV:
23435 tcg_gen_movi_tl(t0, v2);
23436 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23437 break;
23438 case OPC_EXTPDP:
23439 tcg_gen_movi_tl(t0, v2);
23440 tcg_gen_movi_tl(t1, v1);
23441 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23442 break;
23443 case OPC_EXTPDPV:
23444 tcg_gen_movi_tl(t0, v2);
23445 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23446 break;
23447 case OPC_SHILO:
23448 imm = (ctx->opcode >> 20) & 0x3F;
23449 tcg_gen_movi_tl(t0, ret);
23450 tcg_gen_movi_tl(t1, imm);
23451 gen_helper_shilo(t0, t1, cpu_env);
23452 break;
23453 case OPC_SHILOV:
23454 tcg_gen_movi_tl(t0, ret);
23455 gen_helper_shilo(t0, v1_t, cpu_env);
23456 break;
23457 case OPC_MTHLIP:
23458 tcg_gen_movi_tl(t0, ret);
23459 gen_helper_mthlip(t0, v1_t, cpu_env);
23460 break;
23461 case OPC_WRDSP:
23462 imm = (ctx->opcode >> 11) & 0x3FF;
23463 tcg_gen_movi_tl(t0, imm);
23464 gen_helper_wrdsp(v1_t, t0, cpu_env);
23465 break;
23466 case OPC_RDDSP:
23467 imm = (ctx->opcode >> 16) & 0x03FF;
23468 tcg_gen_movi_tl(t0, imm);
23469 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23470 break;
23471 }
23472 break;
23473#ifdef TARGET_MIPS64
23474 case OPC_DEXTR_W_DSP:
23475 check_dsp(ctx);
23476 switch (op2) {
23477 case OPC_DMTHLIP:
23478 tcg_gen_movi_tl(t0, ret);
23479 gen_helper_dmthlip(v1_t, t0, cpu_env);
23480 break;
23481 case OPC_DSHILO:
23482 {
23483 int shift = (ctx->opcode >> 19) & 0x7F;
23484 int ac = (ctx->opcode >> 11) & 0x03;
23485 tcg_gen_movi_tl(t0, shift);
23486 tcg_gen_movi_tl(t1, ac);
23487 gen_helper_dshilo(t0, t1, cpu_env);
23488 break;
23489 }
23490 case OPC_DSHILOV:
23491 {
23492 int ac = (ctx->opcode >> 11) & 0x03;
23493 tcg_gen_movi_tl(t0, ac);
23494 gen_helper_dshilo(v1_t, t0, cpu_env);
23495 break;
23496 }
23497 case OPC_DEXTP:
23498 tcg_gen_movi_tl(t0, v2);
23499 tcg_gen_movi_tl(t1, v1);
23500
23501 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23502 break;
23503 case OPC_DEXTPV:
23504 tcg_gen_movi_tl(t0, v2);
23505 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23506 break;
23507 case OPC_DEXTPDP:
23508 tcg_gen_movi_tl(t0, v2);
23509 tcg_gen_movi_tl(t1, v1);
23510 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23511 break;
23512 case OPC_DEXTPDPV:
23513 tcg_gen_movi_tl(t0, v2);
23514 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23515 break;
23516 case OPC_DEXTR_L:
23517 tcg_gen_movi_tl(t0, v2);
23518 tcg_gen_movi_tl(t1, v1);
23519 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23520 break;
23521 case OPC_DEXTR_R_L:
23522 tcg_gen_movi_tl(t0, v2);
23523 tcg_gen_movi_tl(t1, v1);
23524 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23525 break;
23526 case OPC_DEXTR_RS_L:
23527 tcg_gen_movi_tl(t0, v2);
23528 tcg_gen_movi_tl(t1, v1);
23529 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23530 break;
23531 case OPC_DEXTR_W:
23532 tcg_gen_movi_tl(t0, v2);
23533 tcg_gen_movi_tl(t1, v1);
23534 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23535 break;
23536 case OPC_DEXTR_R_W:
23537 tcg_gen_movi_tl(t0, v2);
23538 tcg_gen_movi_tl(t1, v1);
23539 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23540 break;
23541 case OPC_DEXTR_RS_W:
23542 tcg_gen_movi_tl(t0, v2);
23543 tcg_gen_movi_tl(t1, v1);
23544 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23545 break;
23546 case OPC_DEXTR_S_H:
23547 tcg_gen_movi_tl(t0, v2);
23548 tcg_gen_movi_tl(t1, v1);
23549 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23550 break;
23551 case OPC_DEXTRV_S_H:
23552 tcg_gen_movi_tl(t0, v2);
23553 tcg_gen_movi_tl(t1, v1);
23554 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23555 break;
23556 case OPC_DEXTRV_L:
23557 tcg_gen_movi_tl(t0, v2);
23558 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23559 break;
23560 case OPC_DEXTRV_R_L:
23561 tcg_gen_movi_tl(t0, v2);
23562 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23563 break;
23564 case OPC_DEXTRV_RS_L:
23565 tcg_gen_movi_tl(t0, v2);
23566 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23567 break;
23568 case OPC_DEXTRV_W:
23569 tcg_gen_movi_tl(t0, v2);
23570 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23571 break;
23572 case OPC_DEXTRV_R_W:
23573 tcg_gen_movi_tl(t0, v2);
23574 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23575 break;
23576 case OPC_DEXTRV_RS_W:
23577 tcg_gen_movi_tl(t0, v2);
23578 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23579 break;
23580 }
23581 break;
23582#endif
23583 }
23584
23585 tcg_temp_free(t0);
23586 tcg_temp_free(t1);
23587 tcg_temp_free(v1_t);
23588 tcg_temp_free(v2_t);
b53371ed
JL
23589}
23590
9b1a1d68
JL
23591/* End MIPSDSP functions. */
23592
10dc65db
LA
23593static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23594{
4267d3e6 23595 int rs, rt, rd, sa;
b42ee5e1 23596 uint32_t op1, op2;
10dc65db
LA
23597
23598 rs = (ctx->opcode >> 21) & 0x1f;
23599 rt = (ctx->opcode >> 16) & 0x1f;
23600 rd = (ctx->opcode >> 11) & 0x1f;
4267d3e6 23601 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
23602
23603 op1 = MASK_SPECIAL(ctx->opcode);
23604 switch (op1) {
d4ea6acd 23605 case OPC_LSA:
1f1b4c00 23606 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 23607 break;
c2e19f3c
AM
23608 case OPC_MULT:
23609 case OPC_MULTU:
23610 case OPC_DIV:
23611 case OPC_DIVU:
b42ee5e1
LA
23612 op2 = MASK_R6_MULDIV(ctx->opcode);
23613 switch (op2) {
23614 case R6_OPC_MUL:
23615 case R6_OPC_MUH:
23616 case R6_OPC_MULU:
23617 case R6_OPC_MUHU:
23618 case R6_OPC_DIV:
23619 case R6_OPC_MOD:
23620 case R6_OPC_DIVU:
23621 case R6_OPC_MODU:
23622 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23623 break;
23624 default:
23625 MIPS_INVAL("special_r6 muldiv");
9c708c7f 23626 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
23627 break;
23628 }
23629 break;
10dc65db
LA
23630 case OPC_SELEQZ:
23631 case OPC_SELNEZ:
23632 gen_cond_move(ctx, op1, rd, rs, rt);
23633 break;
4267d3e6
LA
23634 case R6_OPC_CLO:
23635 case R6_OPC_CLZ:
23636 if (rt == 0 && sa == 1) {
23637 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23638 We need additionally to check other fields */
23639 gen_cl(ctx, op1, rd, rs);
23640 } else {
9c708c7f 23641 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
23642 }
23643 break;
23644 case R6_OPC_SDBBP:
3b3c1694
LA
23645 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23646 gen_helper_do_semihosting(cpu_env);
faf1f68b 23647 } else {
3b3c1694 23648 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 23649 generate_exception_end(ctx, EXCP_RI);
3b3c1694 23650 } else {
9c708c7f 23651 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 23652 }
faf1f68b 23653 }
4267d3e6 23654 break;
b42ee5e1 23655#if defined(TARGET_MIPS64)
d4ea6acd
LA
23656 case OPC_DLSA:
23657 check_mips_64(ctx);
1f1b4c00 23658 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 23659 break;
4267d3e6
LA
23660 case R6_OPC_DCLO:
23661 case R6_OPC_DCLZ:
23662 if (rt == 0 && sa == 1) {
23663 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23664 We need additionally to check other fields */
23665 check_mips_64(ctx);
23666 gen_cl(ctx, op1, rd, rs);
23667 } else {
9c708c7f 23668 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
23669 }
23670 break;
c2e19f3c
AM
23671 case OPC_DMULT:
23672 case OPC_DMULTU:
23673 case OPC_DDIV:
23674 case OPC_DDIVU:
23675
b42ee5e1
LA
23676 op2 = MASK_R6_MULDIV(ctx->opcode);
23677 switch (op2) {
23678 case R6_OPC_DMUL:
23679 case R6_OPC_DMUH:
23680 case R6_OPC_DMULU:
23681 case R6_OPC_DMUHU:
23682 case R6_OPC_DDIV:
23683 case R6_OPC_DMOD:
23684 case R6_OPC_DDIVU:
23685 case R6_OPC_DMODU:
23686 check_mips_64(ctx);
23687 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23688 break;
23689 default:
23690 MIPS_INVAL("special_r6 muldiv");
9c708c7f 23691 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
23692 break;
23693 }
23694 break;
23695#endif
10dc65db
LA
23696 default: /* Invalid */
23697 MIPS_INVAL("special_r6");
9c708c7f 23698 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
23699 break;
23700 }
23701}
23702
23703static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23704{
b42ee5e1 23705 int rs, rt, rd, sa;
10dc65db
LA
23706 uint32_t op1;
23707
23708 rs = (ctx->opcode >> 21) & 0x1f;
23709 rt = (ctx->opcode >> 16) & 0x1f;
23710 rd = (ctx->opcode >> 11) & 0x1f;
b42ee5e1 23711 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
23712
23713 op1 = MASK_SPECIAL(ctx->opcode);
23714 switch (op1) {
23715 case OPC_MOVN: /* Conditional move */
23716 case OPC_MOVZ:
23717 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
5601e621 23718 INSN_LOONGSON2E | INSN_LOONGSON2F | INSN_R5900);
10dc65db
LA
23719 gen_cond_move(ctx, op1, rd, rs, rt);
23720 break;
23721 case OPC_MFHI: /* Move from HI/LO */
23722 case OPC_MFLO:
23723 gen_HILO(ctx, op1, rs & 3, rd);
23724 break;
23725 case OPC_MTHI:
23726 case OPC_MTLO: /* Move to HI/LO */
23727 gen_HILO(ctx, op1, rd & 3, rs);
23728 break;
23729 case OPC_MOVCI:
23730 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
23731 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23732 check_cp1_enabled(ctx);
23733 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23734 (ctx->opcode >> 16) & 1);
23735 } else {
23736 generate_exception_err(ctx, EXCP_CpU, 1);
23737 }
23738 break;
b42ee5e1
LA
23739 case OPC_MULT:
23740 case OPC_MULTU:
23741 if (sa) {
23742 check_insn(ctx, INSN_VR54XX);
23743 op1 = MASK_MUL_VR54XX(ctx->opcode);
23744 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
21e8e8b2
FN
23745 } else if (ctx->insn_flags & INSN_R5900) {
23746 gen_mul_txx9(ctx, op1, rd, rs, rt);
b42ee5e1
LA
23747 } else {
23748 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23749 }
23750 break;
23751 case OPC_DIV:
23752 case OPC_DIVU:
23753 gen_muldiv(ctx, op1, 0, rs, rt);
23754 break;
23755#if defined(TARGET_MIPS64)
c2e19f3c
AM
23756 case OPC_DMULT:
23757 case OPC_DMULTU:
23758 case OPC_DDIV:
23759 case OPC_DDIVU:
b42ee5e1 23760 check_insn(ctx, ISA_MIPS3);
96631327 23761 check_insn_opc_user_only(ctx, INSN_R5900);
b42ee5e1
LA
23762 check_mips_64(ctx);
23763 gen_muldiv(ctx, op1, 0, rs, rt);
23764 break;
23765#endif
0aefa333 23766 case OPC_JR:
b231c103 23767 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
0aefa333 23768 break;
4267d3e6
LA
23769 case OPC_SPIM:
23770#ifdef MIPS_STRICT_STANDARD
23771 MIPS_INVAL("SPIM");
9c708c7f 23772 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
23773#else
23774 /* Implemented as RI exception for now. */
23775 MIPS_INVAL("spim (unofficial)");
9c708c7f 23776 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
23777#endif
23778 break;
10dc65db
LA
23779 default: /* Invalid */
23780 MIPS_INVAL("special_legacy");
9c708c7f 23781 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
23782 break;
23783 }
23784}
23785
099e5b4d 23786static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
3c824109 23787{
3c824109 23788 int rs, rt, rd, sa;
099e5b4d 23789 uint32_t op1;
3c824109 23790
3c824109
NF
23791 rs = (ctx->opcode >> 21) & 0x1f;
23792 rt = (ctx->opcode >> 16) & 0x1f;
23793 rd = (ctx->opcode >> 11) & 0x1f;
23794 sa = (ctx->opcode >> 6) & 0x1f;
099e5b4d
LA
23795
23796 op1 = MASK_SPECIAL(ctx->opcode);
23797 switch (op1) {
23798 case OPC_SLL: /* Shift with immediate */
339cd2a8
LA
23799 if (sa == 5 && rd == 0 &&
23800 rs == 0 && rt == 0) { /* PAUSE */
23801 if ((ctx->insn_flags & ISA_MIPS32R6) &&
23802 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 23803 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
23804 break;
23805 }
23806 }
23807 /* Fallthrough */
099e5b4d
LA
23808 case OPC_SRA:
23809 gen_shift_imm(ctx, op1, rd, rt, sa);
23810 break;
23811 case OPC_SRL:
23812 switch ((ctx->opcode >> 21) & 0x1f) {
23813 case 1:
23814 /* rotr is decoded as srl on non-R2 CPUs */
23815 if (ctx->insn_flags & ISA_MIPS32R2) {
23816 op1 = OPC_ROTR;
ea63e2c3 23817 }
099e5b4d
LA
23818 /* Fallthrough */
23819 case 0:
23820 gen_shift_imm(ctx, op1, rd, rt, sa);
ea63e2c3 23821 break;
099e5b4d 23822 default:
9c708c7f 23823 generate_exception_end(ctx, EXCP_RI);
ea63e2c3 23824 break;
099e5b4d
LA
23825 }
23826 break;
c2e19f3c
AM
23827 case OPC_ADD:
23828 case OPC_ADDU:
23829 case OPC_SUB:
23830 case OPC_SUBU:
099e5b4d
LA
23831 gen_arith(ctx, op1, rd, rs, rt);
23832 break;
23833 case OPC_SLLV: /* Shifts */
23834 case OPC_SRAV:
23835 gen_shift(ctx, op1, rd, rs, rt);
23836 break;
23837 case OPC_SRLV:
23838 switch ((ctx->opcode >> 6) & 0x1f) {
23839 case 1:
23840 /* rotrv is decoded as srlv on non-R2 CPUs */
23841 if (ctx->insn_flags & ISA_MIPS32R2) {
23842 op1 = OPC_ROTRV;
26135ead 23843 }
099e5b4d
LA
23844 /* Fallthrough */
23845 case 0:
23846 gen_shift(ctx, op1, rd, rs, rt);
26135ead 23847 break;
099e5b4d 23848 default:
9c708c7f 23849 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 23850 break;
099e5b4d
LA
23851 }
23852 break;
23853 case OPC_SLT: /* Set on less than */
23854 case OPC_SLTU:
23855 gen_slt(ctx, op1, rd, rs, rt);
23856 break;
23857 case OPC_AND: /* Logic*/
23858 case OPC_OR:
23859 case OPC_NOR:
23860 case OPC_XOR:
23861 gen_logic(ctx, op1, rd, rs, rt);
23862 break;
0aefa333 23863 case OPC_JALR:
b231c103 23864 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
099e5b4d 23865 break;
c2e19f3c
AM
23866 case OPC_TGE: /* Traps */
23867 case OPC_TGEU:
23868 case OPC_TLT:
23869 case OPC_TLTU:
23870 case OPC_TEQ:
099e5b4d 23871 case OPC_TNE:
d9224450 23872 check_insn(ctx, ISA_MIPS2);
099e5b4d
LA
23873 gen_trap(ctx, op1, rs, rt, -1);
23874 break;
d4ea6acd 23875 case OPC_LSA: /* OPC_PMON */
f7685877
YK
23876 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23877 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
d4ea6acd
LA
23878 decode_opc_special_r6(env, ctx);
23879 } else {
23880 /* Pmon entry point, also R4010 selsl */
b48cfdff 23881#ifdef MIPS_STRICT_STANDARD
d4ea6acd 23882 MIPS_INVAL("PMON / selsl");
9c708c7f 23883 generate_exception_end(ctx, EXCP_RI);
b48cfdff 23884#else
d4ea6acd 23885 gen_helper_0e0i(pmon, sa);
b48cfdff 23886#endif
d4ea6acd 23887 }
099e5b4d
LA
23888 break;
23889 case OPC_SYSCALL:
9c708c7f 23890 generate_exception_end(ctx, EXCP_SYSCALL);
099e5b4d
LA
23891 break;
23892 case OPC_BREAK:
9c708c7f 23893 generate_exception_end(ctx, EXCP_BREAK);
099e5b4d 23894 break;
099e5b4d 23895 case OPC_SYNC:
d9224450 23896 check_insn(ctx, ISA_MIPS2);
d208ac0c 23897 gen_sync(extract32(ctx->opcode, 6, 5));
099e5b4d 23898 break;
4ad40f36 23899
d26bc211 23900#if defined(TARGET_MIPS64)
099e5b4d
LA
23901 /* MIPS64 specific opcodes */
23902 case OPC_DSLL:
23903 case OPC_DSRA:
23904 case OPC_DSLL32:
23905 case OPC_DSRA32:
23906 check_insn(ctx, ISA_MIPS3);
23907 check_mips_64(ctx);
23908 gen_shift_imm(ctx, op1, rd, rt, sa);
23909 break;
23910 case OPC_DSRL:
23911 switch ((ctx->opcode >> 21) & 0x1f) {
23912 case 1:
23913 /* drotr is decoded as dsrl on non-R2 CPUs */
23914 if (ctx->insn_flags & ISA_MIPS32R2) {
23915 op1 = OPC_DROTR;
ea63e2c3 23916 }
099e5b4d
LA
23917 /* Fallthrough */
23918 case 0:
d75c135e 23919 check_insn(ctx, ISA_MIPS3);
e189e748 23920 check_mips_64(ctx);
099e5b4d 23921 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 23922 break;
099e5b4d 23923 default:
9c708c7f 23924 generate_exception_end(ctx, EXCP_RI);
460f00c4 23925 break;
099e5b4d
LA
23926 }
23927 break;
23928 case OPC_DSRL32:
23929 switch ((ctx->opcode >> 21) & 0x1f) {
23930 case 1:
23931 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23932 if (ctx->insn_flags & ISA_MIPS32R2) {
23933 op1 = OPC_DROTR32;
ea63e2c3 23934 }
099e5b4d
LA
23935 /* Fallthrough */
23936 case 0:
d75c135e 23937 check_insn(ctx, ISA_MIPS3);
e189e748 23938 check_mips_64(ctx);
099e5b4d 23939 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 23940 break;
099e5b4d 23941 default:
9c708c7f 23942 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
23943 break;
23944 }
23945 break;
c2e19f3c
AM
23946 case OPC_DADD:
23947 case OPC_DADDU:
23948 case OPC_DSUB:
23949 case OPC_DSUBU:
099e5b4d
LA
23950 check_insn(ctx, ISA_MIPS3);
23951 check_mips_64(ctx);
23952 gen_arith(ctx, op1, rd, rs, rt);
23953 break;
23954 case OPC_DSLLV:
23955 case OPC_DSRAV:
23956 check_insn(ctx, ISA_MIPS3);
23957 check_mips_64(ctx);
23958 gen_shift(ctx, op1, rd, rs, rt);
23959 break;
23960 case OPC_DSRLV:
23961 switch ((ctx->opcode >> 6) & 0x1f) {
23962 case 1:
23963 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23964 if (ctx->insn_flags & ISA_MIPS32R2) {
23965 op1 = OPC_DROTRV;
6af0bf9c 23966 }
099e5b4d
LA
23967 /* Fallthrough */
23968 case 0:
23969 check_insn(ctx, ISA_MIPS3);
e189e748 23970 check_mips_64(ctx);
099e5b4d 23971 gen_shift(ctx, op1, rd, rs, rt);
161f85e6 23972 break;
099e5b4d 23973 default:
9c708c7f 23974 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
23975 break;
23976 }
23977 break;
f7685877
YK
23978 case OPC_DLSA:
23979 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23980 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23981 decode_opc_special_r6(env, ctx);
23982 }
23983 break;
099e5b4d 23984#endif
10dc65db
LA
23985 default:
23986 if (ctx->insn_flags & ISA_MIPS32R6) {
23987 decode_opc_special_r6(env, ctx);
23988 } else {
23989 decode_opc_special_legacy(env, ctx);
23990 }
23991 }
23992}
23993
10dc65db 23994static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
23995{
23996 int rs, rt, rd;
23997 uint32_t op1;
6c5c1e20 23998
4267d3e6
LA
23999 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24000
099e5b4d
LA
24001 rs = (ctx->opcode >> 21) & 0x1f;
24002 rt = (ctx->opcode >> 16) & 0x1f;
24003 rd = (ctx->opcode >> 11) & 0x1f;
24004
24005 op1 = MASK_SPECIAL2(ctx->opcode);
24006 switch (op1) {
c2e19f3c
AM
24007 case OPC_MADD: /* Multiply and add/sub */
24008 case OPC_MADDU:
24009 case OPC_MSUB:
24010 case OPC_MSUBU:
099e5b4d
LA
24011 check_insn(ctx, ISA_MIPS32);
24012 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24013 break;
24014 case OPC_MUL:
099e5b4d
LA
24015 gen_arith(ctx, op1, rd, rs, rt);
24016 break;
fac5a073
LA
24017 case OPC_DIV_G_2F:
24018 case OPC_DIVU_G_2F:
24019 case OPC_MULT_G_2F:
24020 case OPC_MULTU_G_2F:
24021 case OPC_MOD_G_2F:
24022 case OPC_MODU_G_2F:
24023 check_insn(ctx, INSN_LOONGSON2F);
24024 gen_loongson_integer(ctx, op1, rd, rs, rt);
24025 break;
099e5b4d
LA
24026 case OPC_CLO:
24027 case OPC_CLZ:
24028 check_insn(ctx, ISA_MIPS32);
24029 gen_cl(ctx, op1, rd, rs);
24030 break;
24031 case OPC_SDBBP:
3b3c1694
LA
24032 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24033 gen_helper_do_semihosting(cpu_env);
24034 } else {
24035 /* XXX: not clear which exception should be raised
24036 * when in debug mode...
24037 */
24038 check_insn(ctx, ISA_MIPS32);
9c708c7f 24039 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 24040 }
099e5b4d 24041 break;
9b1a1d68 24042#if defined(TARGET_MIPS64)
099e5b4d
LA
24043 case OPC_DCLO:
24044 case OPC_DCLZ:
24045 check_insn(ctx, ISA_MIPS64);
24046 check_mips_64(ctx);
24047 gen_cl(ctx, op1, rd, rs);
24048 break;
4267d3e6
LA
24049 case OPC_DMULT_G_2F:
24050 case OPC_DMULTU_G_2F:
24051 case OPC_DDIV_G_2F:
24052 case OPC_DDIVU_G_2F:
24053 case OPC_DMOD_G_2F:
24054 case OPC_DMODU_G_2F:
24055 check_insn(ctx, INSN_LOONGSON2F);
24056 gen_loongson_integer(ctx, op1, rd, rs, rt);
24057 break;
10dc65db 24058#endif
4267d3e6
LA
24059 default: /* Invalid */
24060 MIPS_INVAL("special2_legacy");
9c708c7f 24061 generate_exception_end(ctx, EXCP_RI);
4267d3e6 24062 break;
10dc65db
LA
24063 }
24064}
24065
24066static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
24067{
15eacb9b
YK
24068 int rs, rt, rd, sa;
24069 uint32_t op1, op2;
10dc65db
LA
24070 int16_t imm;
24071
24072 rs = (ctx->opcode >> 21) & 0x1f;
24073 rt = (ctx->opcode >> 16) & 0x1f;
15eacb9b
YK
24074 rd = (ctx->opcode >> 11) & 0x1f;
24075 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
24076 imm = (int16_t)ctx->opcode >> 7;
24077
24078 op1 = MASK_SPECIAL3(ctx->opcode);
24079 switch (op1) {
bf7910c6
LA
24080 case R6_OPC_PREF:
24081 if (rt >= 24) {
24082 /* hint codes 24-31 are reserved and signal RI */
9c708c7f 24083 generate_exception_end(ctx, EXCP_RI);
bf7910c6
LA
24084 }
24085 /* Treat as NOP. */
24086 break;
24087 case R6_OPC_CACHE:
40d48212 24088 check_cp0_enabled(ctx);
0d74a222
LA
24089 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24090 gen_cache_operation(ctx, rt, rs, imm);
24091 }
bf7910c6 24092 break;
10dc65db
LA
24093 case R6_OPC_SC:
24094 gen_st_cond(ctx, op1, rt, rs, imm);
24095 break;
24096 case R6_OPC_LL:
24097 gen_ld(ctx, op1, rt, rs, imm);
24098 break;
15eacb9b
YK
24099 case OPC_BSHFL:
24100 {
24101 if (rd == 0) {
24102 /* Treat as NOP. */
24103 break;
24104 }
15eacb9b
YK
24105 op2 = MASK_BSHFL(ctx->opcode);
24106 switch (op2) {
c2e19f3c 24107 case OPC_ALIGN:
373ecd38
AM
24108 case OPC_ALIGN_1:
24109 case OPC_ALIGN_2:
24110 case OPC_ALIGN_3:
821f2008 24111 gen_align(ctx, 32, rd, rs, rt, sa & 3);
15eacb9b
YK
24112 break;
24113 case OPC_BITSWAP:
1f1b4c00 24114 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
24115 break;
24116 }
15eacb9b
YK
24117 }
24118 break;
bf7910c6
LA
24119#if defined(TARGET_MIPS64)
24120 case R6_OPC_SCD:
24121 gen_st_cond(ctx, op1, rt, rs, imm);
24122 break;
24123 case R6_OPC_LLD:
24124 gen_ld(ctx, op1, rt, rs, imm);
24125 break;
15eacb9b
YK
24126 case OPC_DBSHFL:
24127 check_mips_64(ctx);
24128 {
24129 if (rd == 0) {
24130 /* Treat as NOP. */
24131 break;
24132 }
15eacb9b
YK
24133 op2 = MASK_DBSHFL(ctx->opcode);
24134 switch (op2) {
c2e19f3c 24135 case OPC_DALIGN:
373ecd38
AM
24136 case OPC_DALIGN_1:
24137 case OPC_DALIGN_2:
24138 case OPC_DALIGN_3:
24139 case OPC_DALIGN_4:
24140 case OPC_DALIGN_5:
24141 case OPC_DALIGN_6:
24142 case OPC_DALIGN_7:
821f2008 24143 gen_align(ctx, 64, rd, rs, rt, sa & 7);
15eacb9b
YK
24144 break;
24145 case OPC_DBITSWAP:
1f1b4c00 24146 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
24147 break;
24148 }
1f1b4c00 24149
15eacb9b
YK
24150 }
24151 break;
bf7910c6 24152#endif
10dc65db
LA
24153 default: /* Invalid */
24154 MIPS_INVAL("special3_r6");
9c708c7f 24155 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
24156 break;
24157 }
24158}
24159
24160static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
24161{
fac5a073 24162 int rs, rt, rd;
099e5b4d 24163 uint32_t op1, op2;
099e5b4d
LA
24164
24165 rs = (ctx->opcode >> 21) & 0x1f;
24166 rt = (ctx->opcode >> 16) & 0x1f;
24167 rd = (ctx->opcode >> 11) & 0x1f;
099e5b4d
LA
24168
24169 op1 = MASK_SPECIAL3(ctx->opcode);
24170 switch (op1) {
c2e19f3c
AM
24171 case OPC_DIV_G_2E:
24172 case OPC_DIVU_G_2E:
24173 case OPC_MOD_G_2E:
24174 case OPC_MODU_G_2E:
24175 case OPC_MULT_G_2E:
24176 case OPC_MULTU_G_2E:
099e5b4d
LA
24177 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
24178 * the same mask and op1. */
908f6be1 24179 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
099e5b4d 24180 op2 = MASK_ADDUH_QB(ctx->opcode);
461c08df 24181 switch (op2) {
099e5b4d
LA
24182 case OPC_ADDUH_QB:
24183 case OPC_ADDUH_R_QB:
24184 case OPC_ADDQH_PH:
24185 case OPC_ADDQH_R_PH:
24186 case OPC_ADDQH_W:
24187 case OPC_ADDQH_R_W:
24188 case OPC_SUBUH_QB:
24189 case OPC_SUBUH_R_QB:
24190 case OPC_SUBQH_PH:
24191 case OPC_SUBQH_R_PH:
24192 case OPC_SUBQH_W:
24193 case OPC_SUBQH_R_W:
461c08df
JL
24194 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24195 break;
099e5b4d
LA
24196 case OPC_MUL_PH:
24197 case OPC_MUL_S_PH:
24198 case OPC_MULQ_S_W:
24199 case OPC_MULQ_RS_W:
24200 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 24201 break;
461c08df 24202 default:
099e5b4d 24203 MIPS_INVAL("MASK ADDUH.QB");
9c708c7f 24204 generate_exception_end(ctx, EXCP_RI);
461c08df
JL
24205 break;
24206 }
099e5b4d
LA
24207 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
24208 gen_loongson_integer(ctx, op1, rd, rs, rt);
24209 } else {
9c708c7f 24210 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
24211 }
24212 break;
24213 case OPC_LX_DSP:
24214 op2 = MASK_LX(ctx->opcode);
24215 switch (op2) {
24216#if defined(TARGET_MIPS64)
24217 case OPC_LDX:
24218#endif
24219 case OPC_LBUX:
24220 case OPC_LHX:
24221 case OPC_LWX:
24222 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
24223 break;
24224 default: /* Invalid */
24225 MIPS_INVAL("MASK LX");
9c708c7f 24226 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
24227 break;
24228 }
24229 break;
24230 case OPC_ABSQ_S_PH_DSP:
24231 op2 = MASK_ABSQ_S_PH(ctx->opcode);
24232 switch (op2) {
24233 case OPC_ABSQ_S_QB:
24234 case OPC_ABSQ_S_PH:
24235 case OPC_ABSQ_S_W:
24236 case OPC_PRECEQ_W_PHL:
24237 case OPC_PRECEQ_W_PHR:
24238 case OPC_PRECEQU_PH_QBL:
24239 case OPC_PRECEQU_PH_QBR:
24240 case OPC_PRECEQU_PH_QBLA:
24241 case OPC_PRECEQU_PH_QBRA:
24242 case OPC_PRECEU_PH_QBL:
24243 case OPC_PRECEU_PH_QBR:
24244 case OPC_PRECEU_PH_QBLA:
24245 case OPC_PRECEU_PH_QBRA:
24246 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24247 break;
24248 case OPC_BITREV:
24249 case OPC_REPL_QB:
24250 case OPC_REPLV_QB:
24251 case OPC_REPL_PH:
24252 case OPC_REPLV_PH:
24253 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24254 break;
24255 default:
24256 MIPS_INVAL("MASK ABSQ_S.PH");
9c708c7f 24257 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
24258 break;
24259 }
24260 break;
24261 case OPC_ADDU_QB_DSP:
24262 op2 = MASK_ADDU_QB(ctx->opcode);
24263 switch (op2) {
24264 case OPC_ADDQ_PH:
24265 case OPC_ADDQ_S_PH:
24266 case OPC_ADDQ_S_W:
24267 case OPC_ADDU_QB:
24268 case OPC_ADDU_S_QB:
24269 case OPC_ADDU_PH:
24270 case OPC_ADDU_S_PH:
24271 case OPC_SUBQ_PH:
24272 case OPC_SUBQ_S_PH:
24273 case OPC_SUBQ_S_W:
24274 case OPC_SUBU_QB:
24275 case OPC_SUBU_S_QB:
24276 case OPC_SUBU_PH:
24277 case OPC_SUBU_S_PH:
24278 case OPC_ADDSC:
24279 case OPC_ADDWC:
24280 case OPC_MODSUB:
24281 case OPC_RADDU_W_QB:
24282 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24283 break;
24284 case OPC_MULEU_S_PH_QBL:
24285 case OPC_MULEU_S_PH_QBR:
24286 case OPC_MULQ_RS_PH:
24287 case OPC_MULEQ_S_W_PHL:
24288 case OPC_MULEQ_S_W_PHR:
24289 case OPC_MULQ_S_PH:
24290 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24291 break;
24292 default: /* Invalid */
24293 MIPS_INVAL("MASK ADDU.QB");
9c708c7f 24294 generate_exception_end(ctx, EXCP_RI);
461c08df 24295 break;
461c08df 24296
099e5b4d
LA
24297 }
24298 break;
24299 case OPC_CMPU_EQ_QB_DSP:
24300 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
24301 switch (op2) {
24302 case OPC_PRECR_SRA_PH_W:
24303 case OPC_PRECR_SRA_R_PH_W:
24304 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
461c08df 24305 break;
099e5b4d
LA
24306 case OPC_PRECR_QB_PH:
24307 case OPC_PRECRQ_QB_PH:
24308 case OPC_PRECRQ_PH_W:
24309 case OPC_PRECRQ_RS_PH_W:
24310 case OPC_PRECRQU_S_QB_PH:
24311 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
461c08df 24312 break;
099e5b4d
LA
24313 case OPC_CMPU_EQ_QB:
24314 case OPC_CMPU_LT_QB:
24315 case OPC_CMPU_LE_QB:
24316 case OPC_CMP_EQ_PH:
24317 case OPC_CMP_LT_PH:
24318 case OPC_CMP_LE_PH:
24319 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
77c5fa8b 24320 break;
099e5b4d
LA
24321 case OPC_CMPGU_EQ_QB:
24322 case OPC_CMPGU_LT_QB:
24323 case OPC_CMPGU_LE_QB:
24324 case OPC_CMPGDU_EQ_QB:
24325 case OPC_CMPGDU_LT_QB:
24326 case OPC_CMPGDU_LE_QB:
24327 case OPC_PICK_QB:
24328 case OPC_PICK_PH:
24329 case OPC_PACKRL_PH:
24330 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24331 break;
24332 default: /* Invalid */
24333 MIPS_INVAL("MASK CMPU.EQ.QB");
9c708c7f 24334 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
24335 break;
24336 }
24337 break;
24338 case OPC_SHLL_QB_DSP:
24339 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24340 break;
24341 case OPC_DPA_W_PH_DSP:
24342 op2 = MASK_DPA_W_PH(ctx->opcode);
24343 switch (op2) {
24344 case OPC_DPAU_H_QBL:
24345 case OPC_DPAU_H_QBR:
24346 case OPC_DPSU_H_QBL:
24347 case OPC_DPSU_H_QBR:
24348 case OPC_DPA_W_PH:
24349 case OPC_DPAX_W_PH:
24350 case OPC_DPAQ_S_W_PH:
24351 case OPC_DPAQX_S_W_PH:
24352 case OPC_DPAQX_SA_W_PH:
24353 case OPC_DPS_W_PH:
24354 case OPC_DPSX_W_PH:
24355 case OPC_DPSQ_S_W_PH:
24356 case OPC_DPSQX_S_W_PH:
24357 case OPC_DPSQX_SA_W_PH:
24358 case OPC_MULSAQ_S_W_PH:
24359 case OPC_DPAQ_SA_L_W:
24360 case OPC_DPSQ_SA_L_W:
24361 case OPC_MAQ_S_W_PHL:
24362 case OPC_MAQ_S_W_PHR:
24363 case OPC_MAQ_SA_W_PHL:
24364 case OPC_MAQ_SA_W_PHR:
24365 case OPC_MULSA_W_PH:
24366 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24367 break;
24368 default: /* Invalid */
24369 MIPS_INVAL("MASK DPAW.PH");
9c708c7f 24370 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
24371 break;
24372 }
24373 break;
24374 case OPC_INSV_DSP:
24375 op2 = MASK_INSV(ctx->opcode);
24376 switch (op2) {
24377 case OPC_INSV:
24378 check_dsp(ctx);
24379 {
24380 TCGv t0, t1;
24381
24382 if (rt == 0) {
099e5b4d
LA
24383 break;
24384 }
24385
24386 t0 = tcg_temp_new();
24387 t1 = tcg_temp_new();
24388
24389 gen_load_gpr(t0, rt);
24390 gen_load_gpr(t1, rs);
24391
24392 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
24393
24394 tcg_temp_free(t0);
24395 tcg_temp_free(t1);
a22260ae
JL
24396 break;
24397 }
099e5b4d
LA
24398 default: /* Invalid */
24399 MIPS_INVAL("MASK INSV");
9c708c7f 24400 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
24401 break;
24402 }
24403 break;
24404 case OPC_APPEND_DSP:
24405 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24406 break;
24407 case OPC_EXTR_W_DSP:
24408 op2 = MASK_EXTR_W(ctx->opcode);
24409 switch (op2) {
24410 case OPC_EXTR_W:
24411 case OPC_EXTR_R_W:
24412 case OPC_EXTR_RS_W:
24413 case OPC_EXTR_S_H:
24414 case OPC_EXTRV_S_H:
24415 case OPC_EXTRV_W:
24416 case OPC_EXTRV_R_W:
24417 case OPC_EXTRV_RS_W:
24418 case OPC_EXTP:
24419 case OPC_EXTPV:
24420 case OPC_EXTPDP:
24421 case OPC_EXTPDPV:
24422 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24423 break;
24424 case OPC_RDDSP:
24425 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
24426 break;
24427 case OPC_SHILO:
24428 case OPC_SHILOV:
24429 case OPC_MTHLIP:
24430 case OPC_WRDSP:
24431 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24432 break;
24433 default: /* Invalid */
24434 MIPS_INVAL("MASK EXTR.W");
9c708c7f 24435 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
24436 break;
24437 }
24438 break;
099e5b4d 24439#if defined(TARGET_MIPS64)
c2e19f3c
AM
24440 case OPC_DDIV_G_2E:
24441 case OPC_DDIVU_G_2E:
24442 case OPC_DMULT_G_2E:
24443 case OPC_DMULTU_G_2E:
24444 case OPC_DMOD_G_2E:
24445 case OPC_DMODU_G_2E:
fac5a073
LA
24446 check_insn(ctx, INSN_LOONGSON2E);
24447 gen_loongson_integer(ctx, op1, rd, rs, rt);
099e5b4d 24448 break;
099e5b4d
LA
24449 case OPC_ABSQ_S_QH_DSP:
24450 op2 = MASK_ABSQ_S_QH(ctx->opcode);
24451 switch (op2) {
24452 case OPC_PRECEQ_L_PWL:
24453 case OPC_PRECEQ_L_PWR:
24454 case OPC_PRECEQ_PW_QHL:
24455 case OPC_PRECEQ_PW_QHR:
24456 case OPC_PRECEQ_PW_QHLA:
24457 case OPC_PRECEQ_PW_QHRA:
24458 case OPC_PRECEQU_QH_OBL:
24459 case OPC_PRECEQU_QH_OBR:
24460 case OPC_PRECEQU_QH_OBLA:
24461 case OPC_PRECEQU_QH_OBRA:
24462 case OPC_PRECEU_QH_OBL:
24463 case OPC_PRECEU_QH_OBR:
24464 case OPC_PRECEU_QH_OBLA:
24465 case OPC_PRECEU_QH_OBRA:
24466 case OPC_ABSQ_S_OB:
24467 case OPC_ABSQ_S_PW:
24468 case OPC_ABSQ_S_QH:
24469 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24470 break;
24471 case OPC_REPL_OB:
24472 case OPC_REPL_PW:
24473 case OPC_REPL_QH:
24474 case OPC_REPLV_OB:
24475 case OPC_REPLV_PW:
24476 case OPC_REPLV_QH:
24477 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24478 break;
24479 default: /* Invalid */
24480 MIPS_INVAL("MASK ABSQ_S.QH");
9c708c7f 24481 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
24482 break;
24483 }
24484 break;
24485 case OPC_ADDU_OB_DSP:
24486 op2 = MASK_ADDU_OB(ctx->opcode);
24487 switch (op2) {
24488 case OPC_RADDU_L_OB:
24489 case OPC_SUBQ_PW:
24490 case OPC_SUBQ_S_PW:
24491 case OPC_SUBQ_QH:
24492 case OPC_SUBQ_S_QH:
24493 case OPC_SUBU_OB:
24494 case OPC_SUBU_S_OB:
24495 case OPC_SUBU_QH:
24496 case OPC_SUBU_S_QH:
24497 case OPC_SUBUH_OB:
24498 case OPC_SUBUH_R_OB:
24499 case OPC_ADDQ_PW:
24500 case OPC_ADDQ_S_PW:
24501 case OPC_ADDQ_QH:
24502 case OPC_ADDQ_S_QH:
24503 case OPC_ADDU_OB:
24504 case OPC_ADDU_S_OB:
24505 case OPC_ADDU_QH:
24506 case OPC_ADDU_S_QH:
24507 case OPC_ADDUH_OB:
24508 case OPC_ADDUH_R_OB:
24509 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
a22260ae 24510 break;
099e5b4d
LA
24511 case OPC_MULEQ_S_PW_QHL:
24512 case OPC_MULEQ_S_PW_QHR:
24513 case OPC_MULEU_S_QH_OBL:
24514 case OPC_MULEU_S_QH_OBR:
24515 case OPC_MULQ_RS_QH:
24516 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 24517 break;
099e5b4d
LA
24518 default: /* Invalid */
24519 MIPS_INVAL("MASK ADDU.OB");
9c708c7f 24520 generate_exception_end(ctx, EXCP_RI);
26690560 24521 break;
099e5b4d
LA
24522 }
24523 break;
24524 case OPC_CMPU_EQ_OB_DSP:
24525 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
24526 switch (op2) {
24527 case OPC_PRECR_SRA_QH_PW:
24528 case OPC_PRECR_SRA_R_QH_PW:
24529 /* Return value is rt. */
24530 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
b53371ed 24531 break;
099e5b4d
LA
24532 case OPC_PRECR_OB_QH:
24533 case OPC_PRECRQ_OB_QH:
24534 case OPC_PRECRQ_PW_L:
24535 case OPC_PRECRQ_QH_PW:
24536 case OPC_PRECRQ_RS_QH_PW:
24537 case OPC_PRECRQU_S_OB_QH:
24538 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
4368b29a 24539 break;
099e5b4d
LA
24540 case OPC_CMPU_EQ_OB:
24541 case OPC_CMPU_LT_OB:
24542 case OPC_CMPU_LE_OB:
24543 case OPC_CMP_EQ_QH:
24544 case OPC_CMP_LT_QH:
24545 case OPC_CMP_LE_QH:
24546 case OPC_CMP_EQ_PW:
24547 case OPC_CMP_LT_PW:
24548 case OPC_CMP_LE_PW:
24549 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
7a387fff 24550 break;
099e5b4d
LA
24551 case OPC_CMPGDU_EQ_OB:
24552 case OPC_CMPGDU_LT_OB:
24553 case OPC_CMPGDU_LE_OB:
24554 case OPC_CMPGU_EQ_OB:
24555 case OPC_CMPGU_LT_OB:
24556 case OPC_CMPGU_LE_OB:
24557 case OPC_PACKRL_PW:
24558 case OPC_PICK_OB:
24559 case OPC_PICK_PW:
24560 case OPC_PICK_QH:
24561 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
c6d6dd7c 24562 break;
099e5b4d
LA
24563 default: /* Invalid */
24564 MIPS_INVAL("MASK CMPU_EQ.OB");
9c708c7f 24565 generate_exception_end(ctx, EXCP_RI);
161f85e6 24566 break;
099e5b4d
LA
24567 }
24568 break;
24569 case OPC_DAPPEND_DSP:
24570 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24571 break;
24572 case OPC_DEXTR_W_DSP:
24573 op2 = MASK_DEXTR_W(ctx->opcode);
24574 switch (op2) {
24575 case OPC_DEXTP:
24576 case OPC_DEXTPDP:
24577 case OPC_DEXTPDPV:
24578 case OPC_DEXTPV:
24579 case OPC_DEXTR_L:
24580 case OPC_DEXTR_R_L:
24581 case OPC_DEXTR_RS_L:
24582 case OPC_DEXTR_W:
24583 case OPC_DEXTR_R_W:
24584 case OPC_DEXTR_RS_W:
24585 case OPC_DEXTR_S_H:
24586 case OPC_DEXTRV_L:
24587 case OPC_DEXTRV_R_L:
24588 case OPC_DEXTRV_RS_L:
24589 case OPC_DEXTRV_S_H:
24590 case OPC_DEXTRV_W:
24591 case OPC_DEXTRV_R_W:
24592 case OPC_DEXTRV_RS_W:
24593 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
461c08df 24594 break;
099e5b4d
LA
24595 case OPC_DMTHLIP:
24596 case OPC_DSHILO:
24597 case OPC_DSHILOV:
24598 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
461c08df 24599 break;
099e5b4d
LA
24600 default: /* Invalid */
24601 MIPS_INVAL("MASK EXTR.W");
9c708c7f 24602 generate_exception_end(ctx, EXCP_RI);
461c08df 24603 break;
099e5b4d
LA
24604 }
24605 break;
24606 case OPC_DPAQ_W_QH_DSP:
24607 op2 = MASK_DPAQ_W_QH(ctx->opcode);
24608 switch (op2) {
24609 case OPC_DPAU_H_OBL:
24610 case OPC_DPAU_H_OBR:
24611 case OPC_DPSU_H_OBL:
24612 case OPC_DPSU_H_OBR:
24613 case OPC_DPA_W_QH:
24614 case OPC_DPAQ_S_W_QH:
24615 case OPC_DPS_W_QH:
24616 case OPC_DPSQ_S_W_QH:
24617 case OPC_MULSAQ_S_W_QH:
24618 case OPC_DPAQ_SA_L_PW:
24619 case OPC_DPSQ_SA_L_PW:
24620 case OPC_MULSAQ_S_L_PW:
24621 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24622 break;
24623 case OPC_MAQ_S_W_QHLL:
24624 case OPC_MAQ_S_W_QHLR:
24625 case OPC_MAQ_S_W_QHRL:
24626 case OPC_MAQ_S_W_QHRR:
24627 case OPC_MAQ_SA_W_QHLL:
24628 case OPC_MAQ_SA_W_QHLR:
24629 case OPC_MAQ_SA_W_QHRL:
24630 case OPC_MAQ_SA_W_QHRR:
24631 case OPC_MAQ_S_L_PWL:
24632 case OPC_MAQ_S_L_PWR:
24633 case OPC_DMADD:
24634 case OPC_DMADDU:
24635 case OPC_DMSUB:
24636 case OPC_DMSUBU:
24637 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26690560 24638 break;
099e5b4d
LA
24639 default: /* Invalid */
24640 MIPS_INVAL("MASK DPAQ.W.QH");
9c708c7f 24641 generate_exception_end(ctx, EXCP_RI);
b53371ed 24642 break;
099e5b4d
LA
24643 }
24644 break;
24645 case OPC_DINSV_DSP:
24646 op2 = MASK_INSV(ctx->opcode);
24647 switch (op2) {
24648 case OPC_DINSV:
24649 {
24650 TCGv t0, t1;
24651
24652 if (rt == 0) {
a22260ae
JL
24653 break;
24654 }
099e5b4d 24655 check_dsp(ctx);
1cb6686c 24656
099e5b4d
LA
24657 t0 = tcg_temp_new();
24658 t1 = tcg_temp_new();
1cb6686c 24659
099e5b4d
LA
24660 gen_load_gpr(t0, rt);
24661 gen_load_gpr(t1, rs);
1cb6686c 24662
099e5b4d 24663 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
62eb3b9a 24664
099e5b4d
LA
24665 tcg_temp_free(t0);
24666 tcg_temp_free(t1);
77c5fa8b 24667 break;
099e5b4d 24668 }
7a387fff 24669 default: /* Invalid */
099e5b4d 24670 MIPS_INVAL("MASK DINSV");
9c708c7f 24671 generate_exception_end(ctx, EXCP_RI);
7a387fff
TS
24672 break;
24673 }
24674 break;
099e5b4d
LA
24675 case OPC_SHLL_OB_DSP:
24676 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24677 break;
24678#endif
fac5a073
LA
24679 default: /* Invalid */
24680 MIPS_INVAL("special3_legacy");
9c708c7f 24681 generate_exception_end(ctx, EXCP_RI);
fac5a073
LA
24682 break;
24683 }
24684}
24685
88eafe0b
FN
24686static void decode_tx79_mmi0(CPUMIPSState *env, DisasContext *ctx)
24687{
24688 uint32_t opc = MASK_TX79_MMI0(ctx->opcode);
24689
24690 switch (opc) {
24691 case TX79_MMI0_PADDW: /* TODO: TX79_MMI0_PADDW */
24692 case TX79_MMI0_PSUBW: /* TODO: TX79_MMI0_PSUBW */
24693 case TX79_MMI0_PCGTW: /* TODO: TX79_MMI0_PCGTW */
24694 case TX79_MMI0_PMAXW: /* TODO: TX79_MMI0_PMAXW */
24695 case TX79_MMI0_PADDH: /* TODO: TX79_MMI0_PADDH */
24696 case TX79_MMI0_PSUBH: /* TODO: TX79_MMI0_PSUBH */
24697 case TX79_MMI0_PCGTH: /* TODO: TX79_MMI0_PCGTH */
24698 case TX79_MMI0_PMAXH: /* TODO: TX79_MMI0_PMAXH */
24699 case TX79_MMI0_PADDB: /* TODO: TX79_MMI0_PADDB */
24700 case TX79_MMI0_PSUBB: /* TODO: TX79_MMI0_PSUBB */
24701 case TX79_MMI0_PCGTB: /* TODO: TX79_MMI0_PCGTB */
24702 case TX79_MMI0_PADDSW: /* TODO: TX79_MMI0_PADDSW */
24703 case TX79_MMI0_PSUBSW: /* TODO: TX79_MMI0_PSUBSW */
24704 case TX79_MMI0_PEXTLW: /* TODO: TX79_MMI0_PEXTLW */
24705 case TX79_MMI0_PPACW: /* TODO: TX79_MMI0_PPACW */
24706 case TX79_MMI0_PADDSH: /* TODO: TX79_MMI0_PADDSH */
24707 case TX79_MMI0_PSUBSH: /* TODO: TX79_MMI0_PSUBSH */
24708 case TX79_MMI0_PEXTLH: /* TODO: TX79_MMI0_PEXTLH */
24709 case TX79_MMI0_PPACH: /* TODO: TX79_MMI0_PPACH */
24710 case TX79_MMI0_PADDSB: /* TODO: TX79_MMI0_PADDSB */
24711 case TX79_MMI0_PSUBSB: /* TODO: TX79_MMI0_PSUBSB */
24712 case TX79_MMI0_PEXTLB: /* TODO: TX79_MMI0_PEXTLB */
24713 case TX79_MMI0_PPACB: /* TODO: TX79_MMI0_PPACB */
24714 case TX79_MMI0_PEXT5: /* TODO: TX79_MMI0_PEXT5 */
24715 case TX79_MMI0_PPAC5: /* TODO: TX79_MMI0_PPAC5 */
24716 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI0 */
24717 break;
24718 default:
24719 MIPS_INVAL("TX79 MMI class MMI0");
24720 generate_exception_end(ctx, EXCP_RI);
24721 break;
24722 }
24723}
24724
7a803ca2
FN
24725static void decode_tx79_mmi1(CPUMIPSState *env, DisasContext *ctx)
24726{
24727 uint32_t opc = MASK_TX79_MMI1(ctx->opcode);
24728
24729 switch (opc) {
24730 case TX79_MMI1_PABSW: /* TODO: TX79_MMI1_PABSW */
24731 case TX79_MMI1_PCEQW: /* TODO: TX79_MMI1_PCEQW */
24732 case TX79_MMI1_PMINW: /* TODO: TX79_MMI1_PMINW */
24733 case TX79_MMI1_PADSBH: /* TODO: TX79_MMI1_PADSBH */
24734 case TX79_MMI1_PABSH: /* TODO: TX79_MMI1_PABSH */
24735 case TX79_MMI1_PCEQH: /* TODO: TX79_MMI1_PCEQH */
24736 case TX79_MMI1_PMINH: /* TODO: TX79_MMI1_PMINH */
24737 case TX79_MMI1_PCEQB: /* TODO: TX79_MMI1_PCEQB */
24738 case TX79_MMI1_PADDUW: /* TODO: TX79_MMI1_PADDUW */
24739 case TX79_MMI1_PSUBUW: /* TODO: TX79_MMI1_PSUBUW */
24740 case TX79_MMI1_PEXTUW: /* TODO: TX79_MMI1_PEXTUW */
24741 case TX79_MMI1_PADDUH: /* TODO: TX79_MMI1_PADDUH */
24742 case TX79_MMI1_PSUBUH: /* TODO: TX79_MMI1_PSUBUH */
24743 case TX79_MMI1_PEXTUH: /* TODO: TX79_MMI1_PEXTUH */
24744 case TX79_MMI1_PADDUB: /* TODO: TX79_MMI1_PADDUB */
24745 case TX79_MMI1_PSUBUB: /* TODO: TX79_MMI1_PSUBUB */
24746 case TX79_MMI1_PEXTUB: /* TODO: TX79_MMI1_PEXTUB */
24747 case TX79_MMI1_QFSRV: /* TODO: TX79_MMI1_QFSRV */
24748 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI1 */
24749 break;
24750 default:
24751 MIPS_INVAL("TX79 MMI class MMI1");
24752 generate_exception_end(ctx, EXCP_RI);
24753 break;
24754 }
24755}
24756
6c1e48d3
FN
24757static void decode_tx79_mmi2(CPUMIPSState *env, DisasContext *ctx)
24758{
24759 uint32_t opc = MASK_TX79_MMI2(ctx->opcode);
24760
24761 switch (opc) {
24762 case TX79_MMI2_PMADDW: /* TODO: TX79_MMI2_PMADDW */
24763 case TX79_MMI2_PSLLVW: /* TODO: TX79_MMI2_PSLLVW */
24764 case TX79_MMI2_PSRLVW: /* TODO: TX79_MMI2_PSRLVW */
24765 case TX79_MMI2_PMSUBW: /* TODO: TX79_MMI2_PMSUBW */
24766 case TX79_MMI2_PMFHI: /* TODO: TX79_MMI2_PMFHI */
24767 case TX79_MMI2_PMFLO: /* TODO: TX79_MMI2_PMFLO */
24768 case TX79_MMI2_PINTH: /* TODO: TX79_MMI2_PINTH */
24769 case TX79_MMI2_PMULTW: /* TODO: TX79_MMI2_PMULTW */
24770 case TX79_MMI2_PDIVW: /* TODO: TX79_MMI2_PDIVW */
24771 case TX79_MMI2_PCPYLD: /* TODO: TX79_MMI2_PCPYLD */
24772 case TX79_MMI2_PMADDH: /* TODO: TX79_MMI2_PMADDH */
24773 case TX79_MMI2_PHMADH: /* TODO: TX79_MMI2_PHMADH */
24774 case TX79_MMI2_PAND: /* TODO: TX79_MMI2_PAND */
24775 case TX79_MMI2_PXOR: /* TODO: TX79_MMI2_PXOR */
24776 case TX79_MMI2_PMSUBH: /* TODO: TX79_MMI2_PMSUBH */
24777 case TX79_MMI2_PHMSBH: /* TODO: TX79_MMI2_PHMSBH */
24778 case TX79_MMI2_PEXEH: /* TODO: TX79_MMI2_PEXEH */
24779 case TX79_MMI2_PREVH: /* TODO: TX79_MMI2_PREVH */
24780 case TX79_MMI2_PMULTH: /* TODO: TX79_MMI2_PMULTH */
24781 case TX79_MMI2_PDIVBW: /* TODO: TX79_MMI2_PDIVBW */
24782 case TX79_MMI2_PEXEW: /* TODO: TX79_MMI2_PEXEW */
24783 case TX79_MMI2_PROT3W: /* TODO: TX79_MMI2_PROT3W */
24784 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI2 */
24785 break;
24786 default:
24787 MIPS_INVAL("TX79 MMI class MMI2");
24788 generate_exception_end(ctx, EXCP_RI);
24789 break;
24790 }
24791}
24792
ec1944fc
FN
24793static void decode_tx79_mmi3(CPUMIPSState *env, DisasContext *ctx)
24794{
24795 uint32_t opc = MASK_TX79_MMI3(ctx->opcode);
24796
24797 switch (opc) {
24798 case TX79_MMI3_PMADDUW: /* TODO: TX79_MMI3_PMADDUW */
24799 case TX79_MMI3_PSRAVW: /* TODO: TX79_MMI3_PSRAVW */
24800 case TX79_MMI3_PMTHI: /* TODO: TX79_MMI3_PMTHI */
24801 case TX79_MMI3_PMTLO: /* TODO: TX79_MMI3_PMTLO */
24802 case TX79_MMI3_PINTEH: /* TODO: TX79_MMI3_PINTEH */
24803 case TX79_MMI3_PMULTUW: /* TODO: TX79_MMI3_PMULTUW */
24804 case TX79_MMI3_PDIVUW: /* TODO: TX79_MMI3_PDIVUW */
24805 case TX79_MMI3_PCPYUD: /* TODO: TX79_MMI3_PCPYUD */
24806 case TX79_MMI3_POR: /* TODO: TX79_MMI3_POR */
24807 case TX79_MMI3_PNOR: /* TODO: TX79_MMI3_PNOR */
24808 case TX79_MMI3_PEXCH: /* TODO: TX79_MMI3_PEXCH */
24809 case TX79_MMI3_PCPYH: /* TODO: TX79_MMI3_PCPYH */
24810 case TX79_MMI3_PEXCW: /* TODO: TX79_MMI3_PEXCW */
24811 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI3 */
24812 break;
24813 default:
24814 MIPS_INVAL("TX79 MMI class MMI3");
24815 generate_exception_end(ctx, EXCP_RI);
24816 break;
24817 }
24818}
24819
71b8a6b3
FN
24820static void decode_tx79_mmi(CPUMIPSState *env, DisasContext *ctx)
24821{
24822 uint32_t opc = MASK_TX79_MMI(ctx->opcode);
06de726b
FN
24823 int rs = extract32(ctx->opcode, 21, 5);
24824 int rt = extract32(ctx->opcode, 16, 5);
24825 int rd = extract32(ctx->opcode, 11, 5);
71b8a6b3
FN
24826
24827 switch (opc) {
88eafe0b
FN
24828 case TX79_MMI_CLASS_MMI0:
24829 decode_tx79_mmi0(env, ctx);
24830 break;
7a803ca2
FN
24831 case TX79_MMI_CLASS_MMI1:
24832 decode_tx79_mmi1(env, ctx);
24833 break;
6c1e48d3
FN
24834 case TX79_MMI_CLASS_MMI2:
24835 decode_tx79_mmi2(env, ctx);
24836 break;
ec1944fc
FN
24837 case TX79_MMI_CLASS_MMI3:
24838 decode_tx79_mmi3(env, ctx);
24839 break;
06de726b
FN
24840 case TX79_MMI_MULT1:
24841 case TX79_MMI_MULTU1:
24842 gen_mul_txx9(ctx, opc, rd, rs, rt);
24843 break;
be9c42c9
FN
24844 case TX79_MMI_DIV1:
24845 case TX79_MMI_DIVU1:
24846 gen_muldiv(ctx, opc, 1, rs, rt);
24847 break;
8d927f7c
FN
24848 case TX79_MMI_MTLO1:
24849 case TX79_MMI_MTHI1:
24850 gen_HILO(ctx, opc, 1, rs);
24851 break;
24852 case TX79_MMI_MFLO1:
24853 case TX79_MMI_MFHI1:
24854 gen_HILO(ctx, opc, 1, rd);
24855 break;
71b8a6b3
FN
24856 case TX79_MMI_MADD: /* TODO: TX79_MMI_MADD */
24857 case TX79_MMI_MADDU: /* TODO: TX79_MMI_MADDU */
24858 case TX79_MMI_PLZCW: /* TODO: TX79_MMI_PLZCW */
71b8a6b3
FN
24859 case TX79_MMI_MADD1: /* TODO: TX79_MMI_MADD1 */
24860 case TX79_MMI_MADDU1: /* TODO: TX79_MMI_MADDU1 */
71b8a6b3
FN
24861 case TX79_MMI_PMFHL: /* TODO: TX79_MMI_PMFHL */
24862 case TX79_MMI_PMTHL: /* TODO: TX79_MMI_PMTHL */
24863 case TX79_MMI_PSLLH: /* TODO: TX79_MMI_PSLLH */
24864 case TX79_MMI_PSRLH: /* TODO: TX79_MMI_PSRLH */
24865 case TX79_MMI_PSRAH: /* TODO: TX79_MMI_PSRAH */
24866 case TX79_MMI_PSLLW: /* TODO: TX79_MMI_PSLLW */
24867 case TX79_MMI_PSRLW: /* TODO: TX79_MMI_PSRLW */
24868 case TX79_MMI_PSRAW: /* TODO: TX79_MMI_PSRAW */
24869 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_CLASS_MMI */
24870 break;
24871 default:
24872 MIPS_INVAL("TX79 MMI class");
24873 generate_exception_end(ctx, EXCP_RI);
24874 break;
24875 }
24876}
24877
f08099ad
FN
24878static void decode_tx79_lq(CPUMIPSState *env, DisasContext *ctx)
24879{
24880 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_LQ */
24881}
24882
bb41e74b
FN
24883static void gen_tx79_sq(DisasContext *ctx, int base, int rt, int offset)
24884{
24885 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_SQ */
24886}
24887
24888/*
24889 * The TX79-specific instruction Store Quadword
24890 *
24891 * +--------+-------+-------+------------------------+
24892 * | 011111 | base | rt | offset | SQ
24893 * +--------+-------+-------+------------------------+
24894 * 6 5 5 16
24895 *
24896 * has the same opcode as the Read Hardware Register instruction
24897 *
24898 * +--------+-------+-------+-------+-------+--------+
24899 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
24900 * +--------+-------+-------+-------+-------+--------+
24901 * 6 5 5 5 5 6
24902 *
24903 * that is required, trapped and emulated by the Linux kernel. However, all
24904 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
24905 * offset is odd. Therefore all valid SQ instructions can execute normally.
24906 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
24907 * between SQ and RDHWR, as the Linux kernel does.
24908 */
24909static void decode_tx79_sq(CPUMIPSState *env, DisasContext *ctx)
24910{
24911 int base = extract32(ctx->opcode, 21, 5);
24912 int rt = extract32(ctx->opcode, 16, 5);
24913 int offset = extract32(ctx->opcode, 0, 16);
24914
24915#ifdef CONFIG_USER_ONLY
24916 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
24917 uint32_t op2 = extract32(ctx->opcode, 6, 5);
24918
24919 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
24920 int rd = extract32(ctx->opcode, 11, 5);
24921
24922 gen_rdhwr(ctx, rt, rd, 0);
24923 return;
24924 }
24925#endif
24926
24927 gen_tx79_sq(ctx, base, rt, offset);
24928}
24929
fac5a073
LA
24930static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
24931{
24932 int rs, rt, rd, sa;
24933 uint32_t op1, op2;
76964147 24934 int16_t imm;
fac5a073
LA
24935
24936 rs = (ctx->opcode >> 21) & 0x1f;
24937 rt = (ctx->opcode >> 16) & 0x1f;
24938 rd = (ctx->opcode >> 11) & 0x1f;
24939 sa = (ctx->opcode >> 6) & 0x1f;
76964147 24940 imm = sextract32(ctx->opcode, 7, 9);
fac5a073
LA
24941
24942 op1 = MASK_SPECIAL3(ctx->opcode);
76964147
JH
24943
24944 /*
24945 * EVA loads and stores overlap Loongson 2E instructions decoded by
24946 * decode_opc_special3_legacy(), so be careful to allow their decoding when
24947 * EVA is absent.
24948 */
24949 if (ctx->eva) {
24950 switch (op1) {
c2e19f3c
AM
24951 case OPC_LWLE:
24952 case OPC_LWRE:
76964147
JH
24953 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24954 /* fall through */
c2e19f3c
AM
24955 case OPC_LBUE:
24956 case OPC_LHUE:
24957 case OPC_LBE:
24958 case OPC_LHE:
24959 case OPC_LLE:
24960 case OPC_LWE:
76964147
JH
24961 check_cp0_enabled(ctx);
24962 gen_ld(ctx, op1, rt, rs, imm);
24963 return;
c2e19f3c
AM
24964 case OPC_SWLE:
24965 case OPC_SWRE:
76964147
JH
24966 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24967 /* fall through */
c2e19f3c
AM
24968 case OPC_SBE:
24969 case OPC_SHE:
76964147
JH
24970 case OPC_SWE:
24971 check_cp0_enabled(ctx);
24972 gen_st(ctx, op1, rt, rs, imm);
24973 return;
24974 case OPC_SCE:
24975 check_cp0_enabled(ctx);
24976 gen_st_cond(ctx, op1, rt, rs, imm);
24977 return;
24978 case OPC_CACHEE:
24979 check_cp0_enabled(ctx);
24980 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24981 gen_cache_operation(ctx, rt, rs, imm);
24982 }
24983 /* Treat as NOP. */
24984 return;
24985 case OPC_PREFE:
24986 check_cp0_enabled(ctx);
24987 /* Treat as NOP. */
24988 return;
24989 }
24990 }
24991
fac5a073
LA
24992 switch (op1) {
24993 case OPC_EXT:
24994 case OPC_INS:
24995 check_insn(ctx, ISA_MIPS32R2);
24996 gen_bitops(ctx, op1, rt, rs, sa, rd);
24997 break;
24998 case OPC_BSHFL:
fac5a073 24999 op2 = MASK_BSHFL(ctx->opcode);
15eacb9b 25000 switch (op2) {
c2e19f3c 25001 case OPC_ALIGN:
373ecd38
AM
25002 case OPC_ALIGN_1:
25003 case OPC_ALIGN_2:
25004 case OPC_ALIGN_3:
15eacb9b
YK
25005 case OPC_BITSWAP:
25006 check_insn(ctx, ISA_MIPS32R6);
25007 decode_opc_special3_r6(env, ctx);
25008 break;
25009 default:
25010 check_insn(ctx, ISA_MIPS32R2);
25011 gen_bshfl(ctx, op2, rt, rd);
25012 break;
25013 }
fac5a073
LA
25014 break;
25015#if defined(TARGET_MIPS64)
c2e19f3c
AM
25016 case OPC_DEXTM:
25017 case OPC_DEXTU:
25018 case OPC_DEXT:
25019 case OPC_DINSM:
25020 case OPC_DINSU:
25021 case OPC_DINS:
fac5a073
LA
25022 check_insn(ctx, ISA_MIPS64R2);
25023 check_mips_64(ctx);
25024 gen_bitops(ctx, op1, rt, rs, sa, rd);
25025 break;
25026 case OPC_DBSHFL:
fac5a073 25027 op2 = MASK_DBSHFL(ctx->opcode);
15eacb9b 25028 switch (op2) {
c2e19f3c 25029 case OPC_DALIGN:
373ecd38
AM
25030 case OPC_DALIGN_1:
25031 case OPC_DALIGN_2:
25032 case OPC_DALIGN_3:
25033 case OPC_DALIGN_4:
25034 case OPC_DALIGN_5:
25035 case OPC_DALIGN_6:
25036 case OPC_DALIGN_7:
15eacb9b
YK
25037 case OPC_DBITSWAP:
25038 check_insn(ctx, ISA_MIPS32R6);
25039 decode_opc_special3_r6(env, ctx);
25040 break;
25041 default:
25042 check_insn(ctx, ISA_MIPS64R2);
25043 check_mips_64(ctx);
25044 op2 = MASK_DBSHFL(ctx->opcode);
25045 gen_bshfl(ctx, op2, rt, rd);
25046 break;
25047 }
fac5a073
LA
25048 break;
25049#endif
25050 case OPC_RDHWR:
b00c7218 25051 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
fac5a073
LA
25052 break;
25053 case OPC_FORK:
9affc1c5 25054 check_mt(ctx);
fac5a073
LA
25055 {
25056 TCGv t0 = tcg_temp_new();
25057 TCGv t1 = tcg_temp_new();
25058
25059 gen_load_gpr(t0, rt);
25060 gen_load_gpr(t1, rs);
25061 gen_helper_fork(t0, t1);
25062 tcg_temp_free(t0);
25063 tcg_temp_free(t1);
25064 }
25065 break;
25066 case OPC_YIELD:
9affc1c5 25067 check_mt(ctx);
fac5a073
LA
25068 {
25069 TCGv t0 = tcg_temp_new();
25070
fac5a073
LA
25071 gen_load_gpr(t0, rs);
25072 gen_helper_yield(t0, cpu_env, t0);
25073 gen_store_gpr(t0, rd);
25074 tcg_temp_free(t0);
25075 }
25076 break;
10dc65db
LA
25077 default:
25078 if (ctx->insn_flags & ISA_MIPS32R6) {
25079 decode_opc_special3_r6(env, ctx);
25080 } else {
25081 decode_opc_special3_legacy(env, ctx);
25082 }
099e5b4d
LA
25083 }
25084}
25085
863f264d
YK
25086/* MIPS SIMD Architecture (MSA) */
25087static inline int check_msa_access(DisasContext *ctx)
25088{
25089 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
25090 !(ctx->hflags & MIPS_HFLAG_F64))) {
9c708c7f 25091 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
25092 return 0;
25093 }
25094
25095 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
25096 if (ctx->insn_flags & ASE_MSA) {
9c708c7f 25097 generate_exception_end(ctx, EXCP_MSADIS);
863f264d
YK
25098 return 0;
25099 } else {
9c708c7f 25100 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
25101 return 0;
25102 }
25103 }
25104 return 1;
25105}
25106
5692c6e1
YK
25107static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
25108{
25109 /* generates tcg ops to check if any element is 0 */
25110 /* Note this function only works with MSA_WRLEN = 128 */
25111 uint64_t eval_zero_or_big = 0;
25112 uint64_t eval_big = 0;
25113 TCGv_i64 t0 = tcg_temp_new_i64();
25114 TCGv_i64 t1 = tcg_temp_new_i64();
25115 switch (df) {
25116 case DF_BYTE:
25117 eval_zero_or_big = 0x0101010101010101ULL;
25118 eval_big = 0x8080808080808080ULL;
25119 break;
25120 case DF_HALF:
25121 eval_zero_or_big = 0x0001000100010001ULL;
25122 eval_big = 0x8000800080008000ULL;
25123 break;
25124 case DF_WORD:
25125 eval_zero_or_big = 0x0000000100000001ULL;
25126 eval_big = 0x8000000080000000ULL;
25127 break;
25128 case DF_DOUBLE:
25129 eval_zero_or_big = 0x0000000000000001ULL;
25130 eval_big = 0x8000000000000000ULL;
25131 break;
25132 }
25133 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
25134 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
25135 tcg_gen_andi_i64(t0, t0, eval_big);
25136 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
25137 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
25138 tcg_gen_andi_i64(t1, t1, eval_big);
25139 tcg_gen_or_i64(t0, t0, t1);
25140 /* if all bits are zero then all elements are not zero */
25141 /* if some bit is non-zero then some element is zero */
25142 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
25143 tcg_gen_trunc_i64_tl(tresult, t0);
25144 tcg_temp_free_i64(t0);
25145 tcg_temp_free_i64(t1);
25146}
25147
25148static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
25149{
25150 uint8_t df = (ctx->opcode >> 21) & 0x3;
25151 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25152 int64_t s16 = (int16_t)ctx->opcode;
25153
25154 check_msa_access(ctx);
25155
075a1fe7 25156 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 25157 generate_exception_end(ctx, EXCP_RI);
5692c6e1
YK
25158 return;
25159 }
25160 switch (op1) {
25161 case OPC_BZ_V:
25162 case OPC_BNZ_V:
25163 {
25164 TCGv_i64 t0 = tcg_temp_new_i64();
25165 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
25166 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
25167 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
25168 tcg_gen_trunc_i64_tl(bcond, t0);
25169 tcg_temp_free_i64(t0);
25170 }
25171 break;
25172 case OPC_BZ_B:
25173 case OPC_BZ_H:
25174 case OPC_BZ_W:
25175 case OPC_BZ_D:
25176 gen_check_zero_element(bcond, df, wt);
25177 break;
25178 case OPC_BNZ_B:
25179 case OPC_BNZ_H:
25180 case OPC_BNZ_W:
25181 case OPC_BNZ_D:
25182 gen_check_zero_element(bcond, df, wt);
25183 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
25184 break;
25185 }
25186
eeb3bba8 25187 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
5692c6e1
YK
25188
25189 ctx->hflags |= MIPS_HFLAG_BC;
25190 ctx->hflags |= MIPS_HFLAG_BDS32;
25191}
25192
4c789546
YK
25193static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
25194{
25195#define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
25196 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
25197 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25198 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25199
25200 TCGv_i32 twd = tcg_const_i32(wd);
25201 TCGv_i32 tws = tcg_const_i32(ws);
25202 TCGv_i32 ti8 = tcg_const_i32(i8);
25203
25204 switch (MASK_MSA_I8(ctx->opcode)) {
25205 case OPC_ANDI_B:
25206 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
25207 break;
25208 case OPC_ORI_B:
25209 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
25210 break;
25211 case OPC_NORI_B:
25212 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
25213 break;
25214 case OPC_XORI_B:
25215 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
25216 break;
25217 case OPC_BMNZI_B:
25218 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
25219 break;
25220 case OPC_BMZI_B:
25221 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
25222 break;
25223 case OPC_BSELI_B:
25224 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
25225 break;
25226 case OPC_SHF_B:
25227 case OPC_SHF_H:
25228 case OPC_SHF_W:
25229 {
25230 uint8_t df = (ctx->opcode >> 24) & 0x3;
25231 if (df == DF_DOUBLE) {
9c708c7f 25232 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
25233 } else {
25234 TCGv_i32 tdf = tcg_const_i32(df);
25235 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
25236 tcg_temp_free_i32(tdf);
25237 }
25238 }
25239 break;
25240 default:
25241 MIPS_INVAL("MSA instruction");
9c708c7f 25242 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
25243 break;
25244 }
25245
25246 tcg_temp_free_i32(twd);
25247 tcg_temp_free_i32(tws);
25248 tcg_temp_free_i32(ti8);
25249}
25250
80e71591
YK
25251static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
25252{
25253#define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25254 uint8_t df = (ctx->opcode >> 21) & 0x3;
25255 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
25256 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
25257 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25258 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25259
25260 TCGv_i32 tdf = tcg_const_i32(df);
25261 TCGv_i32 twd = tcg_const_i32(wd);
25262 TCGv_i32 tws = tcg_const_i32(ws);
25263 TCGv_i32 timm = tcg_temp_new_i32();
25264 tcg_gen_movi_i32(timm, u5);
25265
25266 switch (MASK_MSA_I5(ctx->opcode)) {
25267 case OPC_ADDVI_df:
25268 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
25269 break;
25270 case OPC_SUBVI_df:
25271 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
25272 break;
25273 case OPC_MAXI_S_df:
25274 tcg_gen_movi_i32(timm, s5);
25275 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
25276 break;
25277 case OPC_MAXI_U_df:
25278 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
25279 break;
25280 case OPC_MINI_S_df:
25281 tcg_gen_movi_i32(timm, s5);
25282 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
25283 break;
25284 case OPC_MINI_U_df:
25285 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
25286 break;
25287 case OPC_CEQI_df:
25288 tcg_gen_movi_i32(timm, s5);
25289 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
25290 break;
25291 case OPC_CLTI_S_df:
25292 tcg_gen_movi_i32(timm, s5);
25293 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
25294 break;
25295 case OPC_CLTI_U_df:
25296 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
25297 break;
25298 case OPC_CLEI_S_df:
25299 tcg_gen_movi_i32(timm, s5);
25300 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
25301 break;
25302 case OPC_CLEI_U_df:
25303 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
25304 break;
25305 case OPC_LDI_df:
25306 {
25307 int32_t s10 = sextract32(ctx->opcode, 11, 10);
25308 tcg_gen_movi_i32(timm, s10);
25309 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
25310 }
25311 break;
25312 default:
25313 MIPS_INVAL("MSA instruction");
9c708c7f 25314 generate_exception_end(ctx, EXCP_RI);
80e71591
YK
25315 break;
25316 }
25317
25318 tcg_temp_free_i32(tdf);
25319 tcg_temp_free_i32(twd);
25320 tcg_temp_free_i32(tws);
25321 tcg_temp_free_i32(timm);
25322}
25323
d4cf28de
YK
25324static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
25325{
25326#define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25327 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
25328 uint32_t df = 0, m = 0;
25329 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25330 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25331
25332 TCGv_i32 tdf;
25333 TCGv_i32 tm;
25334 TCGv_i32 twd;
25335 TCGv_i32 tws;
25336
25337 if ((dfm & 0x40) == 0x00) {
25338 m = dfm & 0x3f;
25339 df = DF_DOUBLE;
25340 } else if ((dfm & 0x60) == 0x40) {
25341 m = dfm & 0x1f;
25342 df = DF_WORD;
25343 } else if ((dfm & 0x70) == 0x60) {
25344 m = dfm & 0x0f;
25345 df = DF_HALF;
25346 } else if ((dfm & 0x78) == 0x70) {
25347 m = dfm & 0x7;
25348 df = DF_BYTE;
25349 } else {
9c708c7f 25350 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
25351 return;
25352 }
25353
25354 tdf = tcg_const_i32(df);
25355 tm = tcg_const_i32(m);
25356 twd = tcg_const_i32(wd);
25357 tws = tcg_const_i32(ws);
25358
25359 switch (MASK_MSA_BIT(ctx->opcode)) {
25360 case OPC_SLLI_df:
25361 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
25362 break;
25363 case OPC_SRAI_df:
25364 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
25365 break;
25366 case OPC_SRLI_df:
25367 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
25368 break;
25369 case OPC_BCLRI_df:
25370 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
25371 break;
25372 case OPC_BSETI_df:
25373 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
25374 break;
25375 case OPC_BNEGI_df:
25376 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
25377 break;
25378 case OPC_BINSLI_df:
25379 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
25380 break;
25381 case OPC_BINSRI_df:
25382 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
25383 break;
25384 case OPC_SAT_S_df:
25385 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
25386 break;
25387 case OPC_SAT_U_df:
25388 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
25389 break;
25390 case OPC_SRARI_df:
25391 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
25392 break;
25393 case OPC_SRLRI_df:
25394 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
25395 break;
25396 default:
25397 MIPS_INVAL("MSA instruction");
9c708c7f 25398 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
25399 break;
25400 }
25401
25402 tcg_temp_free_i32(tdf);
25403 tcg_temp_free_i32(tm);
25404 tcg_temp_free_i32(twd);
25405 tcg_temp_free_i32(tws);
25406}
25407
28f99f08
YK
25408static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
25409{
25410#define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25411 uint8_t df = (ctx->opcode >> 21) & 0x3;
25412 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25413 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25414 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25415
25416 TCGv_i32 tdf = tcg_const_i32(df);
25417 TCGv_i32 twd = tcg_const_i32(wd);
25418 TCGv_i32 tws = tcg_const_i32(ws);
25419 TCGv_i32 twt = tcg_const_i32(wt);
25420
25421 switch (MASK_MSA_3R(ctx->opcode)) {
25422 case OPC_SLL_df:
25423 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
25424 break;
25425 case OPC_ADDV_df:
25426 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
25427 break;
25428 case OPC_CEQ_df:
25429 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
25430 break;
25431 case OPC_ADD_A_df:
25432 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
25433 break;
25434 case OPC_SUBS_S_df:
25435 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
25436 break;
25437 case OPC_MULV_df:
25438 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
25439 break;
25440 case OPC_SLD_df:
25441 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
25442 break;
25443 case OPC_VSHF_df:
25444 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
25445 break;
25446 case OPC_SRA_df:
25447 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
25448 break;
25449 case OPC_SUBV_df:
25450 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
25451 break;
25452 case OPC_ADDS_A_df:
25453 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
25454 break;
25455 case OPC_SUBS_U_df:
25456 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
25457 break;
25458 case OPC_MADDV_df:
25459 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
25460 break;
25461 case OPC_SPLAT_df:
25462 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
25463 break;
25464 case OPC_SRAR_df:
25465 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
25466 break;
25467 case OPC_SRL_df:
25468 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
25469 break;
25470 case OPC_MAX_S_df:
25471 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
25472 break;
25473 case OPC_CLT_S_df:
25474 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
25475 break;
25476 case OPC_ADDS_S_df:
25477 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
25478 break;
25479 case OPC_SUBSUS_U_df:
25480 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
25481 break;
25482 case OPC_MSUBV_df:
25483 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
25484 break;
25485 case OPC_PCKEV_df:
25486 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
25487 break;
25488 case OPC_SRLR_df:
25489 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
25490 break;
25491 case OPC_BCLR_df:
25492 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
25493 break;
25494 case OPC_MAX_U_df:
25495 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
25496 break;
25497 case OPC_CLT_U_df:
25498 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
25499 break;
25500 case OPC_ADDS_U_df:
25501 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
25502 break;
25503 case OPC_SUBSUU_S_df:
25504 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
25505 break;
25506 case OPC_PCKOD_df:
25507 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
25508 break;
25509 case OPC_BSET_df:
25510 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
25511 break;
25512 case OPC_MIN_S_df:
25513 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
25514 break;
25515 case OPC_CLE_S_df:
25516 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
25517 break;
25518 case OPC_AVE_S_df:
25519 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
25520 break;
25521 case OPC_ASUB_S_df:
25522 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
25523 break;
25524 case OPC_DIV_S_df:
25525 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
25526 break;
25527 case OPC_ILVL_df:
25528 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
25529 break;
25530 case OPC_BNEG_df:
25531 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
25532 break;
25533 case OPC_MIN_U_df:
25534 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
25535 break;
25536 case OPC_CLE_U_df:
25537 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
25538 break;
25539 case OPC_AVE_U_df:
25540 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
25541 break;
25542 case OPC_ASUB_U_df:
25543 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
25544 break;
25545 case OPC_DIV_U_df:
25546 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
25547 break;
25548 case OPC_ILVR_df:
25549 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
25550 break;
25551 case OPC_BINSL_df:
25552 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
25553 break;
25554 case OPC_MAX_A_df:
25555 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
25556 break;
25557 case OPC_AVER_S_df:
25558 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
25559 break;
25560 case OPC_MOD_S_df:
25561 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
25562 break;
25563 case OPC_ILVEV_df:
25564 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
25565 break;
25566 case OPC_BINSR_df:
25567 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
25568 break;
25569 case OPC_MIN_A_df:
25570 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
25571 break;
25572 case OPC_AVER_U_df:
25573 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
25574 break;
25575 case OPC_MOD_U_df:
25576 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
25577 break;
25578 case OPC_ILVOD_df:
25579 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
25580 break;
25581
25582 case OPC_DOTP_S_df:
25583 case OPC_DOTP_U_df:
25584 case OPC_DPADD_S_df:
25585 case OPC_DPADD_U_df:
25586 case OPC_DPSUB_S_df:
25587 case OPC_HADD_S_df:
25588 case OPC_DPSUB_U_df:
25589 case OPC_HADD_U_df:
25590 case OPC_HSUB_S_df:
25591 case OPC_HSUB_U_df:
25592 if (df == DF_BYTE) {
9c708c7f
PD
25593 generate_exception_end(ctx, EXCP_RI);
25594 break;
28f99f08
YK
25595 }
25596 switch (MASK_MSA_3R(ctx->opcode)) {
25597 case OPC_DOTP_S_df:
25598 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
25599 break;
25600 case OPC_DOTP_U_df:
25601 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
25602 break;
25603 case OPC_DPADD_S_df:
25604 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
25605 break;
25606 case OPC_DPADD_U_df:
25607 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
25608 break;
25609 case OPC_DPSUB_S_df:
25610 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
25611 break;
25612 case OPC_HADD_S_df:
25613 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
25614 break;
25615 case OPC_DPSUB_U_df:
25616 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
25617 break;
25618 case OPC_HADD_U_df:
25619 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
25620 break;
25621 case OPC_HSUB_S_df:
25622 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
25623 break;
25624 case OPC_HSUB_U_df:
25625 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
25626 break;
25627 }
25628 break;
25629 default:
25630 MIPS_INVAL("MSA instruction");
9c708c7f 25631 generate_exception_end(ctx, EXCP_RI);
28f99f08
YK
25632 break;
25633 }
25634 tcg_temp_free_i32(twd);
25635 tcg_temp_free_i32(tws);
25636 tcg_temp_free_i32(twt);
25637 tcg_temp_free_i32(tdf);
25638}
25639
1e608ec1
YK
25640static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
25641{
25642#define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
25643 uint8_t source = (ctx->opcode >> 11) & 0x1f;
25644 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
25645 TCGv telm = tcg_temp_new();
25646 TCGv_i32 tsr = tcg_const_i32(source);
25647 TCGv_i32 tdt = tcg_const_i32(dest);
25648
25649 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
25650 case OPC_CTCMSA:
25651 gen_load_gpr(telm, source);
25652 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
25653 break;
25654 case OPC_CFCMSA:
25655 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
25656 gen_store_gpr(telm, dest);
25657 break;
25658 case OPC_MOVE_V:
25659 gen_helper_msa_move_v(cpu_env, tdt, tsr);
25660 break;
25661 default:
25662 MIPS_INVAL("MSA instruction");
9c708c7f 25663 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
25664 break;
25665 }
25666
25667 tcg_temp_free(telm);
25668 tcg_temp_free_i32(tdt);
25669 tcg_temp_free_i32(tsr);
25670}
25671
25672static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
25673 uint32_t n)
25674{
25675#define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
25676 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25677 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25678
25679 TCGv_i32 tws = tcg_const_i32(ws);
25680 TCGv_i32 twd = tcg_const_i32(wd);
25681 TCGv_i32 tn = tcg_const_i32(n);
25682 TCGv_i32 tdf = tcg_const_i32(df);
25683
25684 switch (MASK_MSA_ELM(ctx->opcode)) {
25685 case OPC_SLDI_df:
25686 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
25687 break;
25688 case OPC_SPLATI_df:
25689 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
25690 break;
25691 case OPC_INSVE_df:
25692 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
25693 break;
25694 case OPC_COPY_S_df:
25695 case OPC_COPY_U_df:
25696 case OPC_INSERT_df:
25697#if !defined(TARGET_MIPS64)
25698 /* Double format valid only for MIPS64 */
25699 if (df == DF_DOUBLE) {
9c708c7f 25700 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
25701 break;
25702 }
25703#endif
25704 switch (MASK_MSA_ELM(ctx->opcode)) {
25705 case OPC_COPY_S_df:
cab48881
MD
25706 if (likely(wd != 0)) {
25707 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
25708 }
1e608ec1
YK
25709 break;
25710 case OPC_COPY_U_df:
cab48881
MD
25711 if (likely(wd != 0)) {
25712 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
25713 }
1e608ec1
YK
25714 break;
25715 case OPC_INSERT_df:
25716 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
25717 break;
25718 }
25719 break;
25720 default:
25721 MIPS_INVAL("MSA instruction");
9c708c7f 25722 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
25723 }
25724 tcg_temp_free_i32(twd);
25725 tcg_temp_free_i32(tws);
25726 tcg_temp_free_i32(tn);
25727 tcg_temp_free_i32(tdf);
25728}
25729
25730static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
25731{
25732 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
25733 uint32_t df = 0, n = 0;
25734
25735 if ((dfn & 0x30) == 0x00) {
25736 n = dfn & 0x0f;
25737 df = DF_BYTE;
25738 } else if ((dfn & 0x38) == 0x20) {
25739 n = dfn & 0x07;
25740 df = DF_HALF;
25741 } else if ((dfn & 0x3c) == 0x30) {
25742 n = dfn & 0x03;
25743 df = DF_WORD;
25744 } else if ((dfn & 0x3e) == 0x38) {
25745 n = dfn & 0x01;
25746 df = DF_DOUBLE;
25747 } else if (dfn == 0x3E) {
25748 /* CTCMSA, CFCMSA, MOVE.V */
25749 gen_msa_elm_3e(env, ctx);
25750 return;
25751 } else {
9c708c7f 25752 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
25753 return;
25754 }
25755
25756 gen_msa_elm_df(env, ctx, df, n);
25757}
25758
7d05b9c8
YK
25759static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
25760{
25761#define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
25762 uint8_t df = (ctx->opcode >> 21) & 0x1;
25763 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25764 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25765 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25766
25767 TCGv_i32 twd = tcg_const_i32(wd);
25768 TCGv_i32 tws = tcg_const_i32(ws);
25769 TCGv_i32 twt = tcg_const_i32(wt);
25770 TCGv_i32 tdf = tcg_temp_new_i32();
25771
25772 /* adjust df value for floating-point instruction */
25773 tcg_gen_movi_i32(tdf, df + 2);
25774
25775 switch (MASK_MSA_3RF(ctx->opcode)) {
25776 case OPC_FCAF_df:
25777 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
25778 break;
25779 case OPC_FADD_df:
25780 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
25781 break;
25782 case OPC_FCUN_df:
25783 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
25784 break;
25785 case OPC_FSUB_df:
25786 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
25787 break;
25788 case OPC_FCOR_df:
25789 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
25790 break;
25791 case OPC_FCEQ_df:
25792 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
25793 break;
25794 case OPC_FMUL_df:
25795 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
25796 break;
25797 case OPC_FCUNE_df:
25798 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
25799 break;
25800 case OPC_FCUEQ_df:
25801 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
25802 break;
25803 case OPC_FDIV_df:
25804 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
25805 break;
25806 case OPC_FCNE_df:
25807 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
25808 break;
25809 case OPC_FCLT_df:
25810 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
25811 break;
25812 case OPC_FMADD_df:
25813 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
25814 break;
25815 case OPC_MUL_Q_df:
25816 tcg_gen_movi_i32(tdf, df + 1);
25817 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
25818 break;
25819 case OPC_FCULT_df:
25820 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
25821 break;
25822 case OPC_FMSUB_df:
25823 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
25824 break;
25825 case OPC_MADD_Q_df:
25826 tcg_gen_movi_i32(tdf, df + 1);
25827 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
25828 break;
25829 case OPC_FCLE_df:
25830 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
25831 break;
25832 case OPC_MSUB_Q_df:
25833 tcg_gen_movi_i32(tdf, df + 1);
25834 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
25835 break;
25836 case OPC_FCULE_df:
25837 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
25838 break;
25839 case OPC_FEXP2_df:
25840 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
25841 break;
25842 case OPC_FSAF_df:
25843 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
25844 break;
25845 case OPC_FEXDO_df:
25846 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
25847 break;
25848 case OPC_FSUN_df:
25849 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
25850 break;
25851 case OPC_FSOR_df:
25852 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
25853 break;
25854 case OPC_FSEQ_df:
25855 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
25856 break;
25857 case OPC_FTQ_df:
25858 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
25859 break;
25860 case OPC_FSUNE_df:
25861 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
25862 break;
25863 case OPC_FSUEQ_df:
25864 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
25865 break;
25866 case OPC_FSNE_df:
25867 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
25868 break;
25869 case OPC_FSLT_df:
25870 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
25871 break;
25872 case OPC_FMIN_df:
25873 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
25874 break;
25875 case OPC_MULR_Q_df:
25876 tcg_gen_movi_i32(tdf, df + 1);
25877 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
25878 break;
25879 case OPC_FSULT_df:
25880 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
25881 break;
25882 case OPC_FMIN_A_df:
25883 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
25884 break;
25885 case OPC_MADDR_Q_df:
25886 tcg_gen_movi_i32(tdf, df + 1);
25887 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
25888 break;
25889 case OPC_FSLE_df:
25890 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
25891 break;
25892 case OPC_FMAX_df:
25893 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
25894 break;
25895 case OPC_MSUBR_Q_df:
25896 tcg_gen_movi_i32(tdf, df + 1);
25897 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
25898 break;
25899 case OPC_FSULE_df:
25900 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
25901 break;
25902 case OPC_FMAX_A_df:
25903 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
25904 break;
25905 default:
25906 MIPS_INVAL("MSA instruction");
9c708c7f 25907 generate_exception_end(ctx, EXCP_RI);
7d05b9c8
YK
25908 break;
25909 }
25910
25911 tcg_temp_free_i32(twd);
25912 tcg_temp_free_i32(tws);
25913 tcg_temp_free_i32(twt);
25914 tcg_temp_free_i32(tdf);
25915}
25916
cbe50b9a
YK
25917static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
25918{
25919#define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25920 (op & (0x7 << 18)))
25921 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25922 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25923 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25924 uint8_t df = (ctx->opcode >> 16) & 0x3;
25925 TCGv_i32 twd = tcg_const_i32(wd);
25926 TCGv_i32 tws = tcg_const_i32(ws);
25927 TCGv_i32 twt = tcg_const_i32(wt);
25928 TCGv_i32 tdf = tcg_const_i32(df);
25929
25930 switch (MASK_MSA_2R(ctx->opcode)) {
25931 case OPC_FILL_df:
25932#if !defined(TARGET_MIPS64)
25933 /* Double format valid only for MIPS64 */
25934 if (df == DF_DOUBLE) {
9c708c7f 25935 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
25936 break;
25937 }
25938#endif
25939 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
25940 break;
25941 case OPC_PCNT_df:
25942 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
25943 break;
25944 case OPC_NLOC_df:
25945 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
25946 break;
25947 case OPC_NLZC_df:
25948 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
25949 break;
25950 default:
25951 MIPS_INVAL("MSA instruction");
9c708c7f 25952 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
25953 break;
25954 }
25955
25956 tcg_temp_free_i32(twd);
25957 tcg_temp_free_i32(tws);
25958 tcg_temp_free_i32(twt);
25959 tcg_temp_free_i32(tdf);
25960}
25961
3bdeb688
YK
25962static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
25963{
25964#define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25965 (op & (0xf << 17)))
25966 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25967 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25968 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25969 uint8_t df = (ctx->opcode >> 16) & 0x1;
25970 TCGv_i32 twd = tcg_const_i32(wd);
25971 TCGv_i32 tws = tcg_const_i32(ws);
25972 TCGv_i32 twt = tcg_const_i32(wt);
25973 /* adjust df value for floating-point instruction */
25974 TCGv_i32 tdf = tcg_const_i32(df + 2);
25975
25976 switch (MASK_MSA_2RF(ctx->opcode)) {
25977 case OPC_FCLASS_df:
25978 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
25979 break;
25980 case OPC_FTRUNC_S_df:
25981 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
25982 break;
25983 case OPC_FTRUNC_U_df:
25984 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
25985 break;
25986 case OPC_FSQRT_df:
25987 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
25988 break;
25989 case OPC_FRSQRT_df:
25990 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
25991 break;
25992 case OPC_FRCP_df:
25993 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
25994 break;
25995 case OPC_FRINT_df:
25996 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
25997 break;
25998 case OPC_FLOG2_df:
25999 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
26000 break;
26001 case OPC_FEXUPL_df:
26002 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
26003 break;
26004 case OPC_FEXUPR_df:
26005 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
26006 break;
26007 case OPC_FFQL_df:
26008 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
26009 break;
26010 case OPC_FFQR_df:
26011 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
26012 break;
26013 case OPC_FTINT_S_df:
26014 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
26015 break;
26016 case OPC_FTINT_U_df:
26017 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
26018 break;
26019 case OPC_FFINT_S_df:
26020 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
26021 break;
26022 case OPC_FFINT_U_df:
26023 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
26024 break;
26025 }
26026
26027 tcg_temp_free_i32(twd);
26028 tcg_temp_free_i32(tws);
26029 tcg_temp_free_i32(twt);
26030 tcg_temp_free_i32(tdf);
26031}
26032
cbe50b9a
YK
26033static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
26034{
26035#define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
26036 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
26037 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
26038 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26039 TCGv_i32 twd = tcg_const_i32(wd);
26040 TCGv_i32 tws = tcg_const_i32(ws);
26041 TCGv_i32 twt = tcg_const_i32(wt);
26042
26043 switch (MASK_MSA_VEC(ctx->opcode)) {
26044 case OPC_AND_V:
26045 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
26046 break;
26047 case OPC_OR_V:
26048 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
26049 break;
26050 case OPC_NOR_V:
26051 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
26052 break;
26053 case OPC_XOR_V:
26054 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
26055 break;
26056 case OPC_BMNZ_V:
26057 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
26058 break;
26059 case OPC_BMZ_V:
26060 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
26061 break;
26062 case OPC_BSEL_V:
26063 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
26064 break;
26065 default:
26066 MIPS_INVAL("MSA instruction");
9c708c7f 26067 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
26068 break;
26069 }
26070
26071 tcg_temp_free_i32(twd);
26072 tcg_temp_free_i32(tws);
26073 tcg_temp_free_i32(twt);
26074}
26075
26076static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
26077{
26078 switch (MASK_MSA_VEC(ctx->opcode)) {
26079 case OPC_AND_V:
26080 case OPC_OR_V:
26081 case OPC_NOR_V:
26082 case OPC_XOR_V:
26083 case OPC_BMNZ_V:
26084 case OPC_BMZ_V:
26085 case OPC_BSEL_V:
26086 gen_msa_vec_v(env, ctx);
26087 break;
26088 case OPC_MSA_2R:
26089 gen_msa_2r(env, ctx);
26090 break;
3bdeb688
YK
26091 case OPC_MSA_2RF:
26092 gen_msa_2rf(env, ctx);
26093 break;
cbe50b9a
YK
26094 default:
26095 MIPS_INVAL("MSA instruction");
9c708c7f 26096 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
26097 break;
26098 }
26099}
26100
4c789546
YK
26101static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
26102{
26103 uint32_t opcode = ctx->opcode;
26104 check_insn(ctx, ASE_MSA);
26105 check_msa_access(ctx);
26106
26107 switch (MASK_MSA_MINOR(opcode)) {
26108 case OPC_MSA_I8_00:
26109 case OPC_MSA_I8_01:
26110 case OPC_MSA_I8_02:
26111 gen_msa_i8(env, ctx);
26112 break;
80e71591
YK
26113 case OPC_MSA_I5_06:
26114 case OPC_MSA_I5_07:
26115 gen_msa_i5(env, ctx);
26116 break;
d4cf28de
YK
26117 case OPC_MSA_BIT_09:
26118 case OPC_MSA_BIT_0A:
26119 gen_msa_bit(env, ctx);
26120 break;
28f99f08
YK
26121 case OPC_MSA_3R_0D:
26122 case OPC_MSA_3R_0E:
26123 case OPC_MSA_3R_0F:
26124 case OPC_MSA_3R_10:
26125 case OPC_MSA_3R_11:
26126 case OPC_MSA_3R_12:
26127 case OPC_MSA_3R_13:
26128 case OPC_MSA_3R_14:
26129 case OPC_MSA_3R_15:
26130 gen_msa_3r(env, ctx);
26131 break;
1e608ec1
YK
26132 case OPC_MSA_ELM:
26133 gen_msa_elm(env, ctx);
26134 break;
7d05b9c8
YK
26135 case OPC_MSA_3RF_1A:
26136 case OPC_MSA_3RF_1B:
26137 case OPC_MSA_3RF_1C:
26138 gen_msa_3rf(env, ctx);
26139 break;
cbe50b9a
YK
26140 case OPC_MSA_VEC:
26141 gen_msa_vec(env, ctx);
26142 break;
f7685877
YK
26143 case OPC_LD_B:
26144 case OPC_LD_H:
26145 case OPC_LD_W:
26146 case OPC_LD_D:
26147 case OPC_ST_B:
26148 case OPC_ST_H:
26149 case OPC_ST_W:
26150 case OPC_ST_D:
26151 {
26152 int32_t s10 = sextract32(ctx->opcode, 16, 10);
26153 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
26154 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26155 uint8_t df = (ctx->opcode >> 0) & 0x3;
26156
f7685877 26157 TCGv_i32 twd = tcg_const_i32(wd);
adc370a4
YK
26158 TCGv taddr = tcg_temp_new();
26159 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
f7685877
YK
26160
26161 switch (MASK_MSA_MINOR(opcode)) {
26162 case OPC_LD_B:
adc370a4
YK
26163 gen_helper_msa_ld_b(cpu_env, twd, taddr);
26164 break;
f7685877 26165 case OPC_LD_H:
adc370a4
YK
26166 gen_helper_msa_ld_h(cpu_env, twd, taddr);
26167 break;
f7685877 26168 case OPC_LD_W:
adc370a4
YK
26169 gen_helper_msa_ld_w(cpu_env, twd, taddr);
26170 break;
f7685877 26171 case OPC_LD_D:
adc370a4 26172 gen_helper_msa_ld_d(cpu_env, twd, taddr);
f7685877
YK
26173 break;
26174 case OPC_ST_B:
adc370a4
YK
26175 gen_helper_msa_st_b(cpu_env, twd, taddr);
26176 break;
f7685877 26177 case OPC_ST_H:
adc370a4
YK
26178 gen_helper_msa_st_h(cpu_env, twd, taddr);
26179 break;
f7685877 26180 case OPC_ST_W:
adc370a4
YK
26181 gen_helper_msa_st_w(cpu_env, twd, taddr);
26182 break;
f7685877 26183 case OPC_ST_D:
adc370a4 26184 gen_helper_msa_st_d(cpu_env, twd, taddr);
f7685877
YK
26185 break;
26186 }
26187
26188 tcg_temp_free_i32(twd);
adc370a4 26189 tcg_temp_free(taddr);
f7685877
YK
26190 }
26191 break;
4c789546
YK
26192 default:
26193 MIPS_INVAL("MSA instruction");
9c708c7f 26194 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
26195 break;
26196 }
26197
26198}
26199
d2bfa6e6 26200static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
26201{
26202 int32_t offset;
26203 int rs, rt, rd, sa;
26204 uint32_t op, op1;
26205 int16_t imm;
26206
26207 /* make sure instructions are on a word boundary */
eeb3bba8
EC
26208 if (ctx->base.pc_next & 0x3) {
26209 env->CP0_BadVAddr = ctx->base.pc_next;
aea14095 26210 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
099e5b4d
LA
26211 return;
26212 }
26213
26214 /* Handle blikely not taken case */
26215 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
42a268c2 26216 TCGLabel *l1 = gen_new_label();
099e5b4d 26217
099e5b4d
LA
26218 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
26219 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
eeb3bba8 26220 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
099e5b4d
LA
26221 gen_set_label(l1);
26222 }
26223
099e5b4d
LA
26224 op = MASK_OP_MAJOR(ctx->opcode);
26225 rs = (ctx->opcode >> 21) & 0x1f;
26226 rt = (ctx->opcode >> 16) & 0x1f;
26227 rd = (ctx->opcode >> 11) & 0x1f;
26228 sa = (ctx->opcode >> 6) & 0x1f;
26229 imm = (int16_t)ctx->opcode;
26230 switch (op) {
26231 case OPC_SPECIAL:
26232 decode_opc_special(env, ctx);
26233 break;
26234 case OPC_SPECIAL2:
71b8a6b3
FN
26235 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
26236 decode_tx79_mmi(env, ctx);
26237 } else {
26238 decode_opc_special2_legacy(env, ctx);
26239 }
099e5b4d
LA
26240 break;
26241 case OPC_SPECIAL3:
bb41e74b
FN
26242 if (ctx->insn_flags & INSN_R5900) {
26243 decode_tx79_sq(env, ctx); /* TX79_SQ */
26244 } else {
26245 decode_opc_special3(env, ctx);
26246 }
099e5b4d 26247 break;
7a387fff
TS
26248 case OPC_REGIMM:
26249 op1 = MASK_REGIMM(ctx->opcode);
26250 switch (op1) {
fecd2646
LA
26251 case OPC_BLTZL: /* REGIMM branches */
26252 case OPC_BGEZL:
26253 case OPC_BLTZALL:
26254 case OPC_BGEZALL:
d9224450 26255 check_insn(ctx, ISA_MIPS2);
fecd2646 26256 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 26257 /* Fallthrough */
fecd2646
LA
26258 case OPC_BLTZ:
26259 case OPC_BGEZ:
b231c103 26260 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 26261 break;
fecd2646
LA
26262 case OPC_BLTZAL:
26263 case OPC_BGEZAL:
0aefa333
YK
26264 if (ctx->insn_flags & ISA_MIPS32R6) {
26265 if (rs == 0) {
26266 /* OPC_NAL, OPC_BAL */
b231c103 26267 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
0aefa333 26268 } else {
9c708c7f 26269 generate_exception_end(ctx, EXCP_RI);
0aefa333
YK
26270 }
26271 } else {
b231c103 26272 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 26273 }
c9602061 26274 break;
c2e19f3c
AM
26275 case OPC_TGEI: /* REGIMM traps */
26276 case OPC_TGEIU:
26277 case OPC_TLTI:
26278 case OPC_TLTIU:
26279 case OPC_TEQI:
26280
7a387fff 26281 case OPC_TNEI:
d9224450 26282 check_insn(ctx, ISA_MIPS2);
fecd2646 26283 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7a387fff
TS
26284 gen_trap(ctx, op1, rs, -1, imm);
26285 break;
bb238210
YK
26286 case OPC_SIGRIE:
26287 check_insn(ctx, ISA_MIPS32R6);
26288 generate_exception_end(ctx, EXCP_RI);
26289 break;
7a387fff 26290 case OPC_SYNCI:
d75c135e 26291 check_insn(ctx, ISA_MIPS32R2);
a83bddd6
DZ
26292 /* Break the TB to be able to sync copied instructions
26293 immediately */
eeb3bba8 26294 ctx->base.is_jmp = DISAS_STOP;
6af0bf9c 26295 break;
e45a93e2
JL
26296 case OPC_BPOSGE32: /* MIPS DSP branch */
26297#if defined(TARGET_MIPS64)
26298 case OPC_BPOSGE64:
26299#endif
26300 check_dsp(ctx);
b231c103 26301 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
e45a93e2 26302 break;
d4ea6acd
LA
26303#if defined(TARGET_MIPS64)
26304 case OPC_DAHI:
26305 check_insn(ctx, ISA_MIPS32R6);
26306 check_mips_64(ctx);
26307 if (rs != 0) {
26308 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
26309 }
d4ea6acd
LA
26310 break;
26311 case OPC_DATI:
26312 check_insn(ctx, ISA_MIPS32R6);
26313 check_mips_64(ctx);
26314 if (rs != 0) {
26315 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
26316 }
d4ea6acd
LA
26317 break;
26318#endif
6af0bf9c 26319 default: /* Invalid */
923617a3 26320 MIPS_INVAL("regimm");
9c708c7f 26321 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
26322 break;
26323 }
26324 break;
7a387fff 26325 case OPC_CP0:
387a8fe5 26326 check_cp0_enabled(ctx);
7a387fff 26327 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 26328 switch (op1) {
7a387fff
TS
26329 case OPC_MFC0:
26330 case OPC_MTC0:
ead9360e
TS
26331 case OPC_MFTR:
26332 case OPC_MTTR:
5204ea79
LA
26333 case OPC_MFHC0:
26334 case OPC_MTHC0:
d26bc211 26335#if defined(TARGET_MIPS64)
7a387fff
TS
26336 case OPC_DMFC0:
26337 case OPC_DMTC0:
26338#endif
f1aa6320 26339#ifndef CONFIG_USER_ONLY
932e71cd 26340 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 26341#endif /* !CONFIG_USER_ONLY */
7a387fff 26342 break;
c38a1d52
AR
26343 case OPC_C0:
26344 case OPC_C0_1:
26345 case OPC_C0_2:
26346 case OPC_C0_3:
26347 case OPC_C0_4:
26348 case OPC_C0_5:
26349 case OPC_C0_6:
26350 case OPC_C0_7:
26351 case OPC_C0_8:
26352 case OPC_C0_9:
26353 case OPC_C0_A:
26354 case OPC_C0_B:
26355 case OPC_C0_C:
26356 case OPC_C0_D:
26357 case OPC_C0_E:
26358 case OPC_C0_F:
f1aa6320 26359#ifndef CONFIG_USER_ONLY
932e71cd 26360 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 26361#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
26362 break;
26363 case OPC_MFMC0:
8706c382 26364#ifndef CONFIG_USER_ONLY
932e71cd 26365 {
099e5b4d 26366 uint32_t op2;
35fbce2c 26367 TCGv t0 = tcg_temp_new();
6c5c1e20 26368
0eaef5aa 26369 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
26370 switch (op2) {
26371 case OPC_DMT:
9affc1c5 26372 check_cp0_mt(ctx);
9ed5726c 26373 gen_helper_dmt(t0);
35fbce2c 26374 gen_store_gpr(t0, rt);
6c5c1e20
TS
26375 break;
26376 case OPC_EMT:
9affc1c5 26377 check_cp0_mt(ctx);
9ed5726c 26378 gen_helper_emt(t0);
35fbce2c 26379 gen_store_gpr(t0, rt);
da80682b 26380 break;
6c5c1e20 26381 case OPC_DVPE:
9affc1c5 26382 check_cp0_mt(ctx);
895c2d04 26383 gen_helper_dvpe(t0, cpu_env);
35fbce2c 26384 gen_store_gpr(t0, rt);
6c5c1e20
TS
26385 break;
26386 case OPC_EVPE:
9affc1c5 26387 check_cp0_mt(ctx);
895c2d04 26388 gen_helper_evpe(t0, cpu_env);
35fbce2c 26389 gen_store_gpr(t0, rt);
6c5c1e20 26390 break;
01bc435b
YK
26391 case OPC_DVP:
26392 check_insn(ctx, ISA_MIPS32R6);
26393 if (ctx->vp) {
26394 gen_helper_dvp(t0, cpu_env);
26395 gen_store_gpr(t0, rt);
26396 }
26397 break;
26398 case OPC_EVP:
26399 check_insn(ctx, ISA_MIPS32R6);
26400 if (ctx->vp) {
26401 gen_helper_evp(t0, cpu_env);
26402 gen_store_gpr(t0, rt);
26403 }
26404 break;
6c5c1e20 26405 case OPC_DI:
d75c135e 26406 check_insn(ctx, ISA_MIPS32R2);
867abc7e 26407 save_cpu_state(ctx, 1);
895c2d04 26408 gen_helper_di(t0, cpu_env);
35fbce2c 26409 gen_store_gpr(t0, rt);
d2bfa6e6
MR
26410 /* Stop translation as we may have switched
26411 the execution mode. */
eeb3bba8 26412 ctx->base.is_jmp = DISAS_STOP;
6c5c1e20
TS
26413 break;
26414 case OPC_EI:
d75c135e 26415 check_insn(ctx, ISA_MIPS32R2);
867abc7e 26416 save_cpu_state(ctx, 1);
895c2d04 26417 gen_helper_ei(t0, cpu_env);
35fbce2c 26418 gen_store_gpr(t0, rt);
b28425ba
EC
26419 /* DISAS_STOP isn't sufficient, we need to ensure we break
26420 out of translated code to check for pending interrupts */
eeb3bba8
EC
26421 gen_save_pc(ctx->base.pc_next + 4);
26422 ctx->base.is_jmp = DISAS_EXIT;
6c5c1e20
TS
26423 break;
26424 default: /* Invalid */
26425 MIPS_INVAL("mfmc0");
9c708c7f 26426 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
26427 break;
26428 }
6c5c1e20 26429 tcg_temp_free(t0);
7a387fff 26430 }
0eaef5aa 26431#endif /* !CONFIG_USER_ONLY */
6af0bf9c 26432 break;
7a387fff 26433 case OPC_RDPGPR:
d75c135e 26434 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 26435 gen_load_srsgpr(rt, rd);
ead9360e 26436 break;
7a387fff 26437 case OPC_WRPGPR:
d75c135e 26438 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 26439 gen_store_srsgpr(rt, rd);
38121543 26440 break;
6af0bf9c 26441 default:
923617a3 26442 MIPS_INVAL("cp0");
9c708c7f 26443 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
26444 break;
26445 }
26446 break;
31837be3
YK
26447 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
26448 if (ctx->insn_flags & ISA_MIPS32R6) {
26449 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
26450 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26451 } else {
26452 /* OPC_ADDI */
26453 /* Arithmetic with immediate opcode */
26454 gen_arith_imm(ctx, op, rt, rs, imm);
26455 }
26456 break;
324d9e32 26457 case OPC_ADDIU:
d75c135e 26458 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 26459 break;
324d9e32
AJ
26460 case OPC_SLTI: /* Set on less than with immediate opcode */
26461 case OPC_SLTIU:
d75c135e 26462 gen_slt_imm(ctx, op, rt, rs, imm);
324d9e32
AJ
26463 break;
26464 case OPC_ANDI: /* Arithmetic with immediate opcode */
d4ea6acd 26465 case OPC_LUI: /* OPC_AUI */
324d9e32
AJ
26466 case OPC_ORI:
26467 case OPC_XORI:
d75c135e 26468 gen_logic_imm(ctx, op, rt, rs, imm);
324d9e32 26469 break;
c2e19f3c
AM
26470 case OPC_J: /* Jump */
26471 case OPC_JAL:
7a387fff 26472 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 26473 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
c9602061 26474 break;
31837be3
YK
26475 /* Branch */
26476 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
26477 if (ctx->insn_flags & ISA_MIPS32R6) {
26478 if (rt == 0) {
9c708c7f 26479 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
26480 break;
26481 }
26482 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
26483 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26484 } else {
26485 /* OPC_BLEZL */
b231c103 26486 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
26487 }
26488 break;
26489 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
26490 if (ctx->insn_flags & ISA_MIPS32R6) {
26491 if (rt == 0) {
9c708c7f 26492 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
26493 break;
26494 }
26495 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
26496 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26497 } else {
26498 /* OPC_BGTZL */
b231c103 26499 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
26500 }
26501 break;
26502 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
26503 if (rt == 0) {
26504 /* OPC_BLEZ */
b231c103 26505 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
26506 } else {
26507 check_insn(ctx, ISA_MIPS32R6);
26508 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
26509 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26510 }
26511 break;
26512 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
26513 if (rt == 0) {
26514 /* OPC_BGTZ */
b231c103 26515 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
26516 } else {
26517 check_insn(ctx, ISA_MIPS32R6);
26518 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
26519 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26520 }
26521 break;
26522 case OPC_BEQL:
26523 case OPC_BNEL:
d9224450 26524 check_insn(ctx, ISA_MIPS2);
fecd2646 26525 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 26526 /* Fallthrough */
31837be3
YK
26527 case OPC_BEQ:
26528 case OPC_BNE:
b231c103 26529 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
c9602061 26530 break;
d9224450
MR
26531 case OPC_LL: /* Load and stores */
26532 check_insn(ctx, ISA_MIPS2);
96631327 26533 check_insn_opc_user_only(ctx, INSN_R5900);
d9224450
MR
26534 /* Fallthrough */
26535 case OPC_LWL:
fecd2646
LA
26536 case OPC_LWR:
26537 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 26538 /* Fallthrough */
c2e19f3c
AM
26539 case OPC_LB:
26540 case OPC_LH:
26541 case OPC_LW:
26542 case OPC_LWPC:
26543 case OPC_LBU:
26544 case OPC_LHU:
d75c135e 26545 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 26546 break;
fecd2646 26547 case OPC_SWL:
7a387fff 26548 case OPC_SWR:
fecd2646 26549 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 26550 /* fall through */
c2e19f3c
AM
26551 case OPC_SB:
26552 case OPC_SH:
fecd2646 26553 case OPC_SW:
5c13fdfd 26554 gen_st(ctx, op, rt, rs, imm);
7a387fff 26555 break;
d66c7132 26556 case OPC_SC:
d9224450 26557 check_insn(ctx, ISA_MIPS2);
4368b29a 26558 check_insn_opc_removed(ctx, ISA_MIPS32R6);
96631327 26559 check_insn_opc_user_only(ctx, INSN_R5900);
d66c7132
AJ
26560 gen_st_cond(ctx, op, rt, rs, imm);
26561 break;
7a387fff 26562 case OPC_CACHE:
bf7910c6 26563 check_insn_opc_removed(ctx, ISA_MIPS32R6);
2e15497c 26564 check_cp0_enabled(ctx);
d75c135e 26565 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
0d74a222
LA
26566 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26567 gen_cache_operation(ctx, rt, rs, imm);
26568 }
ead9360e 26569 /* Treat as NOP. */
34ae7b51 26570 break;
7a387fff 26571 case OPC_PREF:
bf7910c6 26572 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5601e621
FN
26573 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
26574 INSN_R5900);
ead9360e 26575 /* Treat as NOP. */
6af0bf9c 26576 break;
4ad40f36 26577
923617a3 26578 /* Floating point (COP1). */
7a387fff
TS
26579 case OPC_LWC1:
26580 case OPC_LDC1:
26581 case OPC_SWC1:
26582 case OPC_SDC1:
5ab5c041 26583 gen_cop1_ldst(ctx, op, rt, rs, imm);
6ea83fed
FB
26584 break;
26585
7a387fff 26586 case OPC_CP1:
5692c6e1
YK
26587 op1 = MASK_CP1(ctx->opcode);
26588
26589 switch (op1) {
26590 case OPC_MFHC1:
26591 case OPC_MTHC1:
5e755519 26592 check_cp1_enabled(ctx);
5692c6e1 26593 check_insn(ctx, ISA_MIPS32R2);
146dd620 26594 /* fall through */
5692c6e1
YK
26595 case OPC_MFC1:
26596 case OPC_CFC1:
26597 case OPC_MTC1:
26598 case OPC_CTC1:
26599 check_cp1_enabled(ctx);
26600 gen_cp1(ctx, op1, rt, rd);
26601 break;
d26bc211 26602#if defined(TARGET_MIPS64)
5692c6e1
YK
26603 case OPC_DMFC1:
26604 case OPC_DMTC1:
26605 check_cp1_enabled(ctx);
26606 check_insn(ctx, ISA_MIPS3);
d9224450 26607 check_mips_64(ctx);
5692c6e1
YK
26608 gen_cp1(ctx, op1, rt, rd);
26609 break;
e189e748 26610#endif
5692c6e1
YK
26611 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
26612 check_cp1_enabled(ctx);
26613 if (ctx->insn_flags & ISA_MIPS32R6) {
26614 /* OPC_BC1EQZ */
31837be3 26615 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 26616 rt, imm << 2, 4);
5692c6e1
YK
26617 } else {
26618 /* OPC_BC1ANY2 */
b8aa4598 26619 check_cop1x(ctx);
d75c135e 26620 check_insn(ctx, ASE_MIPS3D);
d75c135e 26621 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5a5012ec 26622 (rt >> 2) & 0x7, imm << 2);
5692c6e1
YK
26623 }
26624 break;
26625 case OPC_BC1NEZ:
26626 check_cp1_enabled(ctx);
26627 check_insn(ctx, ISA_MIPS32R6);
26628 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 26629 rt, imm << 2, 4);
5692c6e1
YK
26630 break;
26631 case OPC_BC1ANY4:
26632 check_cp1_enabled(ctx);
26633 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26634 check_cop1x(ctx);
26635 check_insn(ctx, ASE_MIPS3D);
26636 /* fall through */
26637 case OPC_BC1:
26638 check_cp1_enabled(ctx);
26639 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26640 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
26641 (rt >> 2) & 0x7, imm << 2);
26642 break;
26643 case OPC_PS_FMT:
e29c9628 26644 check_ps(ctx);
b6f3b233 26645 /* fall through */
5692c6e1
YK
26646 case OPC_S_FMT:
26647 case OPC_D_FMT:
26648 check_cp1_enabled(ctx);
26649 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
26650 (imm >> 8) & 0x7);
26651 break;
26652 case OPC_W_FMT:
26653 case OPC_L_FMT:
26654 {
26655 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
26656 check_cp1_enabled(ctx);
26657 if (ctx->insn_flags & ISA_MIPS32R6) {
26658 switch (r6_op) {
26659 case R6_OPC_CMP_AF_S:
26660 case R6_OPC_CMP_UN_S:
26661 case R6_OPC_CMP_EQ_S:
26662 case R6_OPC_CMP_UEQ_S:
26663 case R6_OPC_CMP_LT_S:
26664 case R6_OPC_CMP_ULT_S:
26665 case R6_OPC_CMP_LE_S:
26666 case R6_OPC_CMP_ULE_S:
26667 case R6_OPC_CMP_SAF_S:
26668 case R6_OPC_CMP_SUN_S:
26669 case R6_OPC_CMP_SEQ_S:
26670 case R6_OPC_CMP_SEUQ_S:
26671 case R6_OPC_CMP_SLT_S:
26672 case R6_OPC_CMP_SULT_S:
26673 case R6_OPC_CMP_SLE_S:
26674 case R6_OPC_CMP_SULE_S:
26675 case R6_OPC_CMP_OR_S:
26676 case R6_OPC_CMP_UNE_S:
26677 case R6_OPC_CMP_NE_S:
26678 case R6_OPC_CMP_SOR_S:
26679 case R6_OPC_CMP_SUNE_S:
26680 case R6_OPC_CMP_SNE_S:
26681 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
26682 break;
26683 case R6_OPC_CMP_AF_D:
26684 case R6_OPC_CMP_UN_D:
26685 case R6_OPC_CMP_EQ_D:
26686 case R6_OPC_CMP_UEQ_D:
26687 case R6_OPC_CMP_LT_D:
26688 case R6_OPC_CMP_ULT_D:
26689 case R6_OPC_CMP_LE_D:
26690 case R6_OPC_CMP_ULE_D:
26691 case R6_OPC_CMP_SAF_D:
26692 case R6_OPC_CMP_SUN_D:
26693 case R6_OPC_CMP_SEQ_D:
26694 case R6_OPC_CMP_SEUQ_D:
26695 case R6_OPC_CMP_SLT_D:
26696 case R6_OPC_CMP_SULT_D:
26697 case R6_OPC_CMP_SLE_D:
26698 case R6_OPC_CMP_SULE_D:
26699 case R6_OPC_CMP_OR_D:
26700 case R6_OPC_CMP_UNE_D:
26701 case R6_OPC_CMP_NE_D:
26702 case R6_OPC_CMP_SOR_D:
26703 case R6_OPC_CMP_SUNE_D:
26704 case R6_OPC_CMP_SNE_D:
26705 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
26706 break;
26707 default:
d2bfa6e6
MR
26708 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
26709 rt, rd, sa, (imm >> 8) & 0x7);
26710
5692c6e1 26711 break;
3f493883 26712 }
5692c6e1
YK
26713 } else {
26714 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
26715 (imm >> 8) & 0x7);
36d23958 26716 }
5692c6e1
YK
26717 break;
26718 }
26719 case OPC_BZ_V:
26720 case OPC_BNZ_V:
26721 case OPC_BZ_B:
26722 case OPC_BZ_H:
26723 case OPC_BZ_W:
26724 case OPC_BZ_D:
26725 case OPC_BNZ_B:
26726 case OPC_BNZ_H:
26727 case OPC_BNZ_W:
26728 case OPC_BNZ_D:
26729 check_insn(ctx, ASE_MSA);
26730 gen_msa_branch(env, ctx, op1);
26731 break;
26732 default:
26733 MIPS_INVAL("cp1");
9c708c7f 26734 generate_exception_end(ctx, EXCP_RI);
5692c6e1 26735 break;
6ea83fed 26736 }
4ad40f36
FB
26737 break;
26738
31837be3
YK
26739 /* Compact branches [R6] and COP2 [non-R6] */
26740 case OPC_BC: /* OPC_LWC2 */
26741 case OPC_BALC: /* OPC_SWC2 */
26742 if (ctx->insn_flags & ISA_MIPS32R6) {
26743 /* OPC_BC, OPC_BALC */
26744 gen_compute_compact_branch(ctx, op, 0, 0,
26745 sextract32(ctx->opcode << 2, 0, 28));
26746 } else {
26747 /* OPC_LWC2, OPC_SWC2 */
26748 /* COP2: Not implemented. */
26749 generate_exception_err(ctx, EXCP_CpU, 2);
26750 }
26751 break;
26752 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
26753 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
26754 if (ctx->insn_flags & ISA_MIPS32R6) {
26755 if (rs != 0) {
26756 /* OPC_BEQZC, OPC_BNEZC */
26757 gen_compute_compact_branch(ctx, op, rs, 0,
26758 sextract32(ctx->opcode << 2, 0, 23));
26759 } else {
26760 /* OPC_JIC, OPC_JIALC */
26761 gen_compute_compact_branch(ctx, op, 0, rt, imm);
26762 }
26763 } else {
26764 /* OPC_LWC2, OPC_SWC2 */
26765 /* COP2: Not implemented. */
26766 generate_exception_err(ctx, EXCP_CpU, 2);
26767 }
4ad40f36 26768 break;
bd277fa1 26769 case OPC_CP2:
d75c135e 26770 check_insn(ctx, INSN_LOONGSON2F);
bd277fa1
RH
26771 /* Note that these instructions use different fields. */
26772 gen_loongson_multimedia(ctx, sa, rd, rt);
26773 break;
4ad40f36 26774
7a387fff 26775 case OPC_CP3:
fecd2646 26776 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5ab5c041 26777 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 26778 check_cp1_enabled(ctx);
36d23958
TS
26779 op1 = MASK_CP3(ctx->opcode);
26780 switch (op1) {
d9224450
MR
26781 case OPC_LUXC1:
26782 case OPC_SUXC1:
26783 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
26784 /* Fallthrough */
5a5012ec
TS
26785 case OPC_LWXC1:
26786 case OPC_LDXC1:
5a5012ec
TS
26787 case OPC_SWXC1:
26788 case OPC_SDXC1:
d9224450 26789 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
93b12ccc 26790 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 26791 break;
e0c84da7 26792 case OPC_PREFX:
d9224450 26793 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
ead9360e 26794 /* Treat as NOP. */
e0c84da7 26795 break;
5a5012ec 26796 case OPC_ALNV_PS:
d9224450
MR
26797 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
26798 /* Fallthrough */
5a5012ec
TS
26799 case OPC_MADD_S:
26800 case OPC_MADD_D:
26801 case OPC_MADD_PS:
26802 case OPC_MSUB_S:
26803 case OPC_MSUB_D:
26804 case OPC_MSUB_PS:
26805 case OPC_NMADD_S:
26806 case OPC_NMADD_D:
26807 case OPC_NMADD_PS:
26808 case OPC_NMSUB_S:
26809 case OPC_NMSUB_D:
26810 case OPC_NMSUB_PS:
d9224450 26811 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
5a5012ec
TS
26812 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
26813 break;
36d23958 26814 default:
923617a3 26815 MIPS_INVAL("cp3");
9c708c7f 26816 generate_exception_end(ctx, EXCP_RI);
36d23958
TS
26817 break;
26818 }
26819 } else {
e397ee33 26820 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 26821 }
4ad40f36
FB
26822 break;
26823
d26bc211 26824#if defined(TARGET_MIPS64)
7a387fff 26825 /* MIPS64 opcodes */
96631327
FN
26826 case OPC_LLD:
26827 check_insn_opc_user_only(ctx, INSN_R5900);
26828 /* fall through */
c2e19f3c
AM
26829 case OPC_LDL:
26830 case OPC_LDR:
fecd2646 26831 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 26832 /* fall through */
fecd2646 26833 case OPC_LWU:
7a387fff 26834 case OPC_LD:
d75c135e 26835 check_insn(ctx, ISA_MIPS3);
5c13fdfd 26836 check_mips_64(ctx);
d75c135e 26837 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 26838 break;
c2e19f3c
AM
26839 case OPC_SDL:
26840 case OPC_SDR:
fecd2646 26841 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 26842 /* fall through */
7a387fff 26843 case OPC_SD:
d75c135e 26844 check_insn(ctx, ISA_MIPS3);
e189e748 26845 check_mips_64(ctx);
5c13fdfd 26846 gen_st(ctx, op, rt, rs, imm);
7a387fff 26847 break;
d66c7132 26848 case OPC_SCD:
bf7910c6 26849 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d75c135e 26850 check_insn(ctx, ISA_MIPS3);
96631327 26851 check_insn_opc_user_only(ctx, INSN_R5900);
d66c7132
AJ
26852 check_mips_64(ctx);
26853 gen_st_cond(ctx, op, rt, rs, imm);
26854 break;
31837be3
YK
26855 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
26856 if (ctx->insn_flags & ISA_MIPS32R6) {
26857 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
26858 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26859 } else {
26860 /* OPC_DADDI */
26861 check_insn(ctx, ISA_MIPS3);
26862 check_mips_64(ctx);
26863 gen_arith_imm(ctx, op, rt, rs, imm);
26864 }
26865 break;
324d9e32 26866 case OPC_DADDIU:
d75c135e 26867 check_insn(ctx, ISA_MIPS3);
e189e748 26868 check_mips_64(ctx);
d75c135e 26869 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 26870 break;
31837be3
YK
26871#else
26872 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
26873 if (ctx->insn_flags & ISA_MIPS32R6) {
26874 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26875 } else {
26876 MIPS_INVAL("major opcode");
9c708c7f 26877 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
26878 }
26879 break;
6af0bf9c 26880#endif
d4ea6acd
LA
26881 case OPC_DAUI: /* OPC_JALX */
26882 if (ctx->insn_flags & ISA_MIPS32R6) {
26883#if defined(TARGET_MIPS64)
26884 /* OPC_DAUI */
26885 check_mips_64(ctx);
db77d852
LA
26886 if (rs == 0) {
26887 generate_exception(ctx, EXCP_RI);
26888 } else if (rt != 0) {
d4ea6acd
LA
26889 TCGv t0 = tcg_temp_new();
26890 gen_load_gpr(t0, rs);
26891 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
26892 tcg_temp_free(t0);
26893 }
d4ea6acd 26894#else
9c708c7f 26895 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
26896 MIPS_INVAL("major opcode");
26897#endif
26898 } else {
26899 /* OPC_JALX */
26900 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
26901 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 26902 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
d4ea6acd 26903 }
364d4831 26904 break;
4c789546 26905 case OPC_MSA: /* OPC_MDMX */
f08099ad
FN
26906 if (ctx->insn_flags & INSN_R5900) {
26907 decode_tx79_lq(env, ctx); /* TX79_LQ */
26908 } else {
26909 /* MDMX: Not implemented. */
26910 gen_msa(env, ctx);
26911 }
d4ea6acd
LA
26912 break;
26913 case OPC_PCREL:
26914 check_insn(ctx, ISA_MIPS32R6);
eeb3bba8 26915 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
d4ea6acd 26916 break;
6af0bf9c 26917 default: /* Invalid */
923617a3 26918 MIPS_INVAL("major opcode");
9c708c7f 26919 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
26920 break;
26921 }
6af0bf9c
FB
26922}
26923
18f440ed 26924static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
6af0bf9c 26925{
18f440ed 26926 DisasContext *ctx = container_of(dcbase, DisasContext, base);
9c489ea6 26927 CPUMIPSState *env = cs->env_ptr;
12be9258 26928
18f440ed 26929 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
12be9258
EC
26930 ctx->saved_pc = -1;
26931 ctx->insn_flags = env->insn_flags;
26932 ctx->CP0_Config1 = env->CP0_Config1;
49735f76 26933 ctx->CP0_Config2 = env->CP0_Config2;
ab77fc61
DN
26934 ctx->CP0_Config3 = env->CP0_Config3;
26935 ctx->CP0_Config5 = env->CP0_Config5;
12be9258
EC
26936 ctx->btarget = 0;
26937 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
26938 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
26939 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
26940 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
26941 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
26942 ctx->PAMask = env->PAMask;
26943 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
26944 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
26945 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
26946 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
26947 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
4ad40f36 26948 /* Restore delay slot state from the tb context. */
12be9258
EC
26949 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
26950 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
26951 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
e29c9628 26952 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
12be9258
EC
26953 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
26954 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
26955 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
26956 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
26957 restore_cpu_state(env, ctx);
932e71cd 26958#ifdef CONFIG_USER_ONLY
12be9258 26959 ctx->mem_idx = MIPS_HFLAG_UM;
932e71cd 26960#else
12be9258 26961 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
932e71cd 26962#endif
12be9258
EC
26963 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
26964 MO_UNALN : MO_ALIGN;
190ce7fb 26965
18f440ed
EC
26966 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
26967 ctx->hflags);
26968}
12be9258 26969
18f440ed
EC
26970static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
26971{
26972}
b933066a 26973
18f440ed
EC
26974static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
26975{
26976 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 26977
18f440ed
EC
26978 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
26979 ctx->btarget);
26980}
31837be3 26981
18f440ed
EC
26982static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
26983 const CPUBreakpoint *bp)
26984{
26985 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 26986
18f440ed
EC
26987 save_cpu_state(ctx, 1);
26988 ctx->base.is_jmp = DISAS_NORETURN;
26989 gen_helper_raise_exception_debug(cpu_env);
26990 /* The address covered by the breakpoint must be included in
26991 [tb->pc, tb->pc + tb->size) in order to for it to be
26992 properly cleared -- thus we increment the PC here so that
26993 the logic setting tb->size below does the right thing. */
26994 ctx->base.pc_next += 4;
26995 return true;
26996}
4ad40f36 26997
18f440ed
EC
26998static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
26999{
27000 CPUMIPSState *env = cs->env_ptr;
27001 DisasContext *ctx = container_of(dcbase, DisasContext, base);
27002 int insn_bytes;
27003 int is_slot;
4ad40f36 27004
18f440ed 27005 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
c533c0f4
AM
27006 if (ctx->insn_flags & ISA_NANOMIPS32) {
27007 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
27008 insn_bytes = decode_nanomips_opc(env, ctx);
27009 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
18f440ed
EC
27010 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
27011 insn_bytes = 4;
27012 decode_opc(env, ctx);
27013 } else if (ctx->insn_flags & ASE_MICROMIPS) {
27014 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
27015 insn_bytes = decode_micromips_opc(env, ctx);
27016 } else if (ctx->insn_flags & ASE_MIPS16) {
27017 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
27018 insn_bytes = decode_mips16_opc(env, ctx);
27019 } else {
27020 generate_exception_end(ctx, EXCP_RI);
27021 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
27022 return;
27023 }
faf7aaa9 27024
18f440ed
EC
27025 if (ctx->hflags & MIPS_HFLAG_BMASK) {
27026 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
27027 MIPS_HFLAG_FBNSLOT))) {
27028 /* force to generate branch as there is neither delay nor
27029 forbidden slot */
27030 is_slot = 1;
27031 }
27032 if ((ctx->hflags & MIPS_HFLAG_M16) &&
27033 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
27034 /* Force to generate branch as microMIPS R6 doesn't restrict
27035 branches in the forbidden slot. */
27036 is_slot = 1;
eeb3bba8 27037 }
18f440ed
EC
27038 }
27039 if (is_slot) {
27040 gen_branch(ctx, insn_bytes);
27041 }
27042 ctx->base.pc_next += insn_bytes;
1b530a6d 27043
18f440ed
EC
27044 if (ctx->base.is_jmp != DISAS_NEXT) {
27045 return;
6af0bf9c 27046 }
18f440ed
EC
27047 /* Execute a branch and its delay slot as a single instruction.
27048 This is what GDB expects and is consistent with what the
27049 hardware does (e.g. if a delay slot instruction faults, the
27050 reported PC is the PC of the branch). */
27051 if (ctx->base.singlestep_enabled &&
27052 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
27053 ctx->base.is_jmp = DISAS_TOO_MANY;
27054 }
27055 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
27056 ctx->base.is_jmp = DISAS_TOO_MANY;
ed2803da 27057 }
18f440ed
EC
27058}
27059
27060static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
27061{
27062 DisasContext *ctx = container_of(dcbase, DisasContext, base);
27063
12be9258
EC
27064 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
27065 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
9c708c7f 27066 gen_helper_raise_exception_debug(cpu_env);
16c00cb2 27067 } else {
12be9258 27068 switch (ctx->base.is_jmp) {
b28425ba 27069 case DISAS_STOP:
12be9258 27070 gen_save_pc(ctx->base.pc_next);
cd314a7d 27071 tcg_gen_lookup_and_goto_ptr();
df1561e2 27072 break;
b28425ba 27073 case DISAS_NEXT:
18f440ed 27074 case DISAS_TOO_MANY:
12be9258
EC
27075 save_cpu_state(ctx, 0);
27076 gen_goto_tb(ctx, 0, ctx->base.pc_next);
16c00cb2 27077 break;
b28425ba 27078 case DISAS_EXIT:
07ea28b4 27079 tcg_gen_exit_tb(NULL, 0);
16c00cb2 27080 break;
b28425ba 27081 case DISAS_NORETURN:
5a5012ec 27082 break;
18f440ed
EC
27083 default:
27084 g_assert_not_reached();
6958549d 27085 }
6af0bf9c 27086 }
18f440ed
EC
27087}
27088
27089static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
27090{
27091 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
27092 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
27093}
27094
27095static const TranslatorOps mips_tr_ops = {
27096 .init_disas_context = mips_tr_init_disas_context,
27097 .tb_start = mips_tr_tb_start,
27098 .insn_start = mips_tr_insn_start,
27099 .breakpoint_check = mips_tr_breakpoint_check,
27100 .translate_insn = mips_tr_translate_insn,
27101 .tb_stop = mips_tr_tb_stop,
27102 .disas_log = mips_tr_disas_log,
27103};
27104
27105void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
27106{
27107 DisasContext ctx;
27108
27109 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
6af0bf9c
FB
27110}
27111
7db13fae 27112static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
8706c382 27113 int flags)
6ea83fed
FB
27114{
27115 int i;
5e755519 27116 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 27117
2a5612e6
SW
27118#define printfpr(fp) \
27119 do { \
27120 if (is_fpu64) \
27121 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
27122 " fd:%13g fs:%13g psu: %13g\n", \
27123 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
27124 (double)(fp)->fd, \
27125 (double)(fp)->fs[FP_ENDIAN_IDX], \
27126 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
27127 else { \
27128 fpr_t tmp; \
27129 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
27130 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
27131 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
27132 " fd:%13g fs:%13g psu:%13g\n", \
27133 tmp.w[FP_ENDIAN_IDX], tmp.d, \
27134 (double)tmp.fd, \
27135 (double)tmp.fs[FP_ENDIAN_IDX], \
27136 (double)tmp.fs[!FP_ENDIAN_IDX]); \
27137 } \
6ea83fed
FB
27138 } while(0)
27139
5a5012ec 27140
9a78eead
SW
27141 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
27142 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
f01be154 27143 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
27144 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
27145 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 27146 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
27147 }
27148
27149#undef printfpr
27150}
27151
878096ee
AF
27152void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
27153 int flags)
6af0bf9c 27154{
878096ee
AF
27155 MIPSCPU *cpu = MIPS_CPU(cs);
27156 CPUMIPSState *env = &cpu->env;
6af0bf9c 27157 int i;
3b46e624 27158
a7200c9f
SW
27159 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
27160 " LO=0x" TARGET_FMT_lx " ds %04x "
27161 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
3d5be870
TS
27162 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
27163 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
27164 for (i = 0; i < 32; i++) {
27165 if ((i & 3) == 0)
27166 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 27167 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
27168 if ((i & 3) == 3)
27169 cpu_fprintf(f, "\n");
27170 }
568b600d 27171
3594c774 27172 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 27173 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
284b731a
LA
27174 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
27175 PRIx64 "\n",
5499b6ff 27176 env->CP0_Config0, env->CP0_Config1, env->lladdr);
27e1fb13
MR
27177 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
27178 env->CP0_Config2, env->CP0_Config3);
27179 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
27180 env->CP0_Config4, env->CP0_Config5);
1cc5af69 27181 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
7a387fff 27182 fpu_dump_state(env, f, cpu_fprintf, flags);
1cc5af69 27183 }
6af0bf9c
FB
27184}
27185
78ce64f4 27186void mips_tcg_init(void)
39454628 27187{
f01be154 27188 int i;
39454628 27189
f764718d 27190 cpu_gpr[0] = NULL;
bb928dbe 27191 for (i = 1; i < 32; i++)
e1ccc054 27192 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
7db13fae 27193 offsetof(CPUMIPSState, active_tc.gpr[i]),
4b2eb8d2 27194 regnames[i]);
d73ee8a2 27195
863f264d
YK
27196 for (i = 0; i < 32; i++) {
27197 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
27198 msa_wr_d[i * 2] =
e1ccc054 27199 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
cb269f27
YK
27200 /* The scalar floating-point unit (FPU) registers are mapped on
27201 * the MSA vector registers. */
27202 fpu_f64[i] = msa_wr_d[i * 2];
863f264d
YK
27203 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
27204 msa_wr_d[i * 2 + 1] =
e1ccc054 27205 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
863f264d
YK
27206 }
27207
e1ccc054 27208 cpu_PC = tcg_global_mem_new(cpu_env,
7db13fae 27209 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 27210 for (i = 0; i < MIPS_DSP_ACC; i++) {
e1ccc054 27211 cpu_HI[i] = tcg_global_mem_new(cpu_env,
7db13fae 27212 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 27213 regnames_HI[i]);
e1ccc054 27214 cpu_LO[i] = tcg_global_mem_new(cpu_env,
7db13fae 27215 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 27216 regnames_LO[i]);
4b2eb8d2 27217 }
e1ccc054 27218 cpu_dspctrl = tcg_global_mem_new(cpu_env,
7db13fae 27219 offsetof(CPUMIPSState, active_tc.DSPControl),
4b2eb8d2 27220 "DSPControl");
e1ccc054 27221 bcond = tcg_global_mem_new(cpu_env,
7db13fae 27222 offsetof(CPUMIPSState, bcond), "bcond");
e1ccc054 27223 btarget = tcg_global_mem_new(cpu_env,
7db13fae 27224 offsetof(CPUMIPSState, btarget), "btarget");
e1ccc054 27225 hflags = tcg_global_mem_new_i32(cpu_env,
7db13fae 27226 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 27227
e1ccc054 27228 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
7db13fae 27229 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4 27230 "fcr0");
e1ccc054 27231 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
7db13fae 27232 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 27233 "fcr31");
39454628
TS
27234}
27235
5b27a92d 27236#include "translate_init.inc.c"
aaed909a 27237
27e38392
PMD
27238void cpu_mips_realize_env(CPUMIPSState *env)
27239{
27240 env->exception_base = (int32_t)0xBFC00000;
27241
27242#ifndef CONFIG_USER_ONLY
27243 mmu_init(env, env->cpu_model);
27244#endif
27245 fpu_init(env, env->cpu_model);
27246 mvp_init(env, env->cpu_model);
27247}
27248
a7519f2b 27249bool cpu_supports_cps_smp(const char *cpu_type)
bff384a4 27250{
a7519f2b
IM
27251 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
27252 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
bff384a4
LA
27253}
27254
a7519f2b 27255bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
bed9e5ce 27256{
a7519f2b
IM
27257 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
27258 return (mcc->cpu_def->insn_flags & isa) != 0;
bed9e5ce
PB
27259}
27260
89777fd1
LA
27261void cpu_set_exception_base(int vp_index, target_ulong address)
27262{
27263 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
27264 vp->env.exception_base = address;
27265}
27266
1bba0dc9 27267void cpu_state_reset(CPUMIPSState *env)
6ae81775 27268{
55e5c285
AF
27269 MIPSCPU *cpu = mips_env_get_cpu(env);
27270 CPUState *cs = CPU(cpu);
6ae81775 27271
51cc2e78
BS
27272 /* Reset registers to their default values */
27273 env->CP0_PRid = env->cpu_model->CP0_PRid;
27274 env->CP0_Config0 = env->cpu_model->CP0_Config0;
27275#ifdef TARGET_WORDS_BIGENDIAN
27276 env->CP0_Config0 |= (1 << CP0C0_BE);
27277#endif
27278 env->CP0_Config1 = env->cpu_model->CP0_Config1;
27279 env->CP0_Config2 = env->cpu_model->CP0_Config2;
27280 env->CP0_Config3 = env->cpu_model->CP0_Config3;
b4160af1
PJ
27281 env->CP0_Config4 = env->cpu_model->CP0_Config4;
27282 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
b4dd99a3
PJ
27283 env->CP0_Config5 = env->cpu_model->CP0_Config5;
27284 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
51cc2e78
BS
27285 env->CP0_Config6 = env->cpu_model->CP0_Config6;
27286 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
27287 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
27288 << env->cpu_model->CP0_LLAddr_shift;
27289 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
27290 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
27291 env->CCRes = env->cpu_model->CCRes;
27292 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
27293 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
27294 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
27295 env->current_tc = 0;
27296 env->SEGBITS = env->cpu_model->SEGBITS;
27297 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
27298#if defined(TARGET_MIPS64)
27299 if (env->cpu_model->insn_flags & ISA_MIPS3) {
27300 env->SEGMask |= 3ULL << 62;
27301 }
27302#endif
27303 env->PABITS = env->cpu_model->PABITS;
51cc2e78
BS
27304 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
27305 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
27306 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
27307 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
27308 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
27309 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
27310 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
27311 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
27312 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
27313 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
7207c7f9
LA
27314 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
27315 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
74dbf824 27316 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
f1cb0951 27317 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
599bc5e8 27318 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
ba5c79f2 27319 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
863f264d 27320 env->msair = env->cpu_model->MSAIR;
51cc2e78
BS
27321 env->insn_flags = env->cpu_model->insn_flags;
27322
0eaef5aa 27323#if defined(CONFIG_USER_ONLY)
03e6e501 27324 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
68473f15
RH
27325# ifdef TARGET_MIPS64
27326 /* Enable 64-bit register mode. */
27327 env->CP0_Status |= (1 << CP0St_PX);
27328# endif
27329# ifdef TARGET_ABI_MIPSN64
27330 /* Enable 64-bit address mode. */
27331 env->CP0_Status |= (1 << CP0St_UX);
27332# endif
94159135
MI
27333 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
27334 hardware registers. */
27335 env->CP0_HWREna |= 0x0000000F;
91a75935 27336 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
03e6e501 27337 env->CP0_Status |= (1 << CP0St_CU1);
91a75935 27338 }
6f0af304
PJ
27339 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
27340 env->CP0_Status |= (1 << CP0St_MX);
853c3240 27341 }
4d66261f
PJ
27342# if defined(TARGET_MIPS64)
27343 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
27344 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
27345 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
68473f15
RH
27346 env->CP0_Status |= (1 << CP0St_FR);
27347 }
4d66261f 27348# endif
932e71cd
AJ
27349#else
27350 if (env->hflags & MIPS_HFLAG_BMASK) {
27351 /* If the exception was raised from a delay slot,
27352 come back to the jump. */
c3577479
MR
27353 env->CP0_ErrorEPC = (env->active_tc.PC
27354 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
aa328add 27355 } else {
932e71cd
AJ
27356 env->CP0_ErrorEPC = env->active_tc.PC;
27357 }
89777fd1 27358 env->active_tc.PC = env->exception_base;
51cc2e78
BS
27359 env->CP0_Random = env->tlb->nb_tlb - 1;
27360 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd 27361 env->CP0_Wired = 0;
01bc435b 27362 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
0a2672b7 27363 env->CP0_EBase = (cs->cpu_index & 0x3FF);
d3d93c6c 27364 if (mips_um_ksegs_enabled()) {
0a2672b7
JH
27365 env->CP0_EBase |= 0x40000000;
27366 } else {
74dbf824 27367 env->CP0_EBase |= (int32_t)0x80000000;
0a2672b7 27368 }
c870e3f5
YK
27369 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
27370 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
27371 }
a0c80608
PB
27372 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
27373 0x3ff : 0xff;
932e71cd
AJ
27374 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
27375 /* vectored interrupts not implemented, timer on int 7,
27376 no performance counters. */
27377 env->CP0_IntCtl = 0xe0000000;
27378 {
27379 int i;
27380
27381 for (i = 0; i < 7; i++) {
27382 env->CP0_WatchLo[i] = 0;
27383 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 27384 }
932e71cd
AJ
27385 env->CP0_WatchLo[7] = 0;
27386 env->CP0_WatchHi[7] = 0;
fd88b6ab 27387 }
932e71cd
AJ
27388 /* Count register increments in debug mode, EJTAG version 1 */
27389 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9e56e756 27390
4b69c7e2
JH
27391 cpu_mips_store_count(env, 1);
27392
9e56e756
EI
27393 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
27394 int i;
27395
27396 /* Only TC0 on VPE 0 starts as active. */
27397 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
55e5c285 27398 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
9e56e756
EI
27399 env->tcs[i].CP0_TCHalt = 1;
27400 }
27401 env->active_tc.CP0_TCHalt = 1;
259186a7 27402 cs->halted = 1;
9e56e756 27403
55e5c285 27404 if (cs->cpu_index == 0) {
9e56e756
EI
27405 /* VPE0 starts up enabled. */
27406 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
27407 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
27408
27409 /* TC0 starts up unhalted. */
259186a7 27410 cs->halted = 0;
9e56e756
EI
27411 env->active_tc.CP0_TCHalt = 0;
27412 env->tcs[0].CP0_TCHalt = 0;
27413 /* With thread 0 active. */
27414 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
27415 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
27416 }
27417 }
cec56a73
JH
27418
27419 /*
27420 * Configure default legacy segmentation control. We use this regardless of
27421 * whether segmentation control is presented to the guest.
27422 */
27423 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
27424 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
27425 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
27426 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
27427 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
27428 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
27429 (2 << CP0SC_C);
27430 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
27431 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
27432 (3 << CP0SC_C)) << 16;
27433 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
27434 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
27435 (1 << CP0SC_EU) | (2 << CP0SC_C);
27436 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
27437 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
27438 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
27439 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
27440 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
51cc2e78 27441#endif
ddc584bd
LA
27442 if ((env->insn_flags & ISA_MIPS32R6) &&
27443 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
27444 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
27445 env->CP0_Status |= (1 << CP0St_FR);
27446 }
27447
63010795
YK
27448 if (env->insn_flags & ISA_MIPS32R6) {
27449 /* PTW = 1 */
27450 env->CP0_PWSize = 0x40;
27451 /* GDI = 12 */
27452 /* UDI = 12 */
27453 /* MDI = 12 */
27454 /* PRI = 12 */
27455 /* PTEI = 2 */
27456 env->CP0_PWField = 0x0C30C302;
27457 } else {
27458 /* GDI = 0 */
27459 /* UDI = 0 */
27460 /* MDI = 0 */
27461 /* PRI = 0 */
27462 /* PTEI = 2 */
27463 env->CP0_PWField = 0x02;
27464 }
27465
0bbc0396
SM
27466 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
27467 /* microMIPS on reset when Config3.ISA is 3 */
0305d194
YK
27468 env->hflags |= MIPS_HFLAG_M16;
27469 }
27470
863f264d
YK
27471 /* MSA */
27472 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
27473 msa_reset(env);
27474 }
27475
03e6e501 27476 compute_hflags(env);
599bc5e8 27477 restore_fp_status(env);
e117f526 27478 restore_pamask(env);
27103424 27479 cs->exception_index = EXCP_NONE;
3b3c1694
LA
27480
27481 if (semihosting_get_argc()) {
27482 /* UHI interface can be used to obtain argc and argv */
27483 env->active_tc.gpr[4] = -1;
27484 }
6af0bf9c 27485}
d2856f1a 27486
bad729e2
RH
27487void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
27488 target_ulong *data)
d2856f1a 27489{
bad729e2 27490 env->active_tc.PC = data[0];
d2856f1a 27491 env->hflags &= ~MIPS_HFLAG_BMASK;
bad729e2 27492 env->hflags |= data[1];
4636401d
AJ
27493 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
27494 case MIPS_HFLAG_BR:
27495 break;
27496 case MIPS_HFLAG_BC:
27497 case MIPS_HFLAG_BL:
27498 case MIPS_HFLAG_B:
bad729e2 27499 env->btarget = data[2];
4636401d
AJ
27500 break;
27501 }
d2856f1a 27502}