]> Git Repo - qemu.git/blame - target/mips/translate.c
target/mips: Add organizational chart of MXU ASE
[qemu.git] / target / mips / translate.c
CommitLineData
6af0bf9c
FB
1/*
2 * MIPS32 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,
466 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
467 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
468 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
e37e863f
FB
469};
470
7a387fff
TS
471/* DBSHFL opcodes */
472#define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
473
e37e863f 474enum {
15eacb9b
YK
475 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
476 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
477 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
478 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
479 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
e37e863f
FB
480};
481
e45a93e2
JL
482/* MIPS DSP REGIMM opcodes */
483enum {
484 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
e45a93e2 485 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
e45a93e2
JL
486};
487
9b1a1d68
JL
488#define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
489/* MIPS DSP Load */
490enum {
491 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
492 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
493 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
9b1a1d68 494 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
9b1a1d68
JL
495};
496
461c08df
JL
497#define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
498enum {
499 /* MIPS DSP Arithmetic Sub-class */
500 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
501 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
502 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
503 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
504 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
505 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
506 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
507 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
508 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
509 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
510 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
511 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
512 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
513 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
516 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
517 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
a22260ae
JL
518 /* MIPS DSP Multiply Sub-class insns */
519 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
520 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
521 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
522 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
523 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
524 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
461c08df
JL
525};
526
527#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
528#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
529enum {
530 /* MIPS DSP Arithmetic Sub-class */
531 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
532 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
533 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
534 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
535 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
536 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
537 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
538 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
539 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
541 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
a22260ae
JL
543 /* MIPS DSP Multiply Sub-class insns */
544 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
545 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
546 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
461c08df
JL
548};
549
550#define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
551enum {
552 /* MIPS DSP Arithmetic Sub-class */
553 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
554 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
555 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
556 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
557 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
558 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
559 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
560 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
561 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
1cb6686c
JL
566 /* DSP Bit/Manipulation Sub-class */
567 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
461c08df
JL
572};
573
574#define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
575enum {
576 /* MIPS DSP Arithmetic Sub-class */
577 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
578 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
579 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
580 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
581 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
582 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
583 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
26690560
JL
584 /* DSP Compare-Pick Sub-class */
585 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
461c08df 600};
a22260ae 601
77c5fa8b
JL
602#define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
603enum {
604 /* MIPS DSP GPR-Based Shift Sub-class */
605 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
606 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
607 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
608 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
609 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
610 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
611 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
612 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
613 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
627};
461c08df 628
a22260ae
JL
629#define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
630enum {
631 /* MIPS DSP Multiply Sub-class insns */
632 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
633 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
634 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
635 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
636 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
637 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
638 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
639 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
640 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
646 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
649 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
654};
655
1cb6686c
JL
656#define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
657enum {
658 /* DSP Bit/Manipulation Sub-class */
659 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
660};
661
26690560
JL
662#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
663enum {
df6126a7 664 /* MIPS DSP Append Sub-class */
26690560
JL
665 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
666 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
667 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
668};
669
b53371ed
JL
670#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671enum {
672 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
673 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
674 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
675 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
676 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
677 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
678 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
679 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
680 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
681 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
685 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
686 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
687 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
688 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
689 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
690};
691
461c08df
JL
692#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
693enum {
694 /* MIPS DSP Arithmetic Sub-class */
695 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
697 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
698 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
699 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
700 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
701 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
702 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
703 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
1cb6686c
JL
712 /* DSP Bit/Manipulation Sub-class */
713 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
461c08df 719};
461c08df 720
461c08df
JL
721#define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
722enum {
a22260ae
JL
723 /* MIPS DSP Multiply Sub-class insns */
724 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
725 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
726 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
727 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
728 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
461c08df
JL
729 /* MIPS DSP Arithmetic Sub-class */
730 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
731 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
732 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
733 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
734 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
735 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
736 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
737 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
738 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
741 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
742 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
743 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
744 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
745 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
746 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
747 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
748 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
751};
461c08df 752
461c08df
JL
753#define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
754enum {
26690560
JL
755 /* DSP Compare-Pick Sub-class */
756 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
762 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
763 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
764 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
461c08df
JL
775 /* MIPS DSP Arithmetic Sub-class */
776 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
784};
461c08df 785
26690560
JL
786#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
787enum {
df6126a7 788 /* DSP Append Sub-class */
26690560
JL
789 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
790 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
791 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
792 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
793};
26690560 794
b53371ed
JL
795#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796enum {
797 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
798 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
799 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
800 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
801 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
802 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
803 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
804 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
805 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
806 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
807 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
819};
820
1cb6686c
JL
821#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
822enum {
823 /* DSP Bit/Manipulation Sub-class */
824 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
825};
1cb6686c 826
a22260ae
JL
827#define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
828enum {
829 /* MIPS DSP Multiply Sub-class insns */
830 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
834 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
835 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
836 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
837 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
838 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
856};
a22260ae 857
77c5fa8b
JL
858#define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
859enum {
860 /* MIPS DSP GPR-Based Shift Sub-class */
861 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
865 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
866 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
867 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
868 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
869 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
887};
77c5fa8b 888
7a387fff
TS
889/* Coprocessor 0 (rs field) */
890#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
891
6ea83fed 892enum {
7a387fff
TS
893 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
894 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
5204ea79 895 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
7a387fff
TS
896 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
897 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
5204ea79 898 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
ead9360e 899 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
900 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
901 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 902 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
903 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
904 OPC_C0 = (0x10 << 21) | OPC_CP0,
c38a1d52
AR
905 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
906 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
907 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
908 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
909 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
910 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
911 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
912 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
913 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
914 OPC_C0_A = (0x1A << 21) | OPC_CP0,
915 OPC_C0_B = (0x1B << 21) | OPC_CP0,
916 OPC_C0_C = (0x1C << 21) | OPC_CP0,
917 OPC_C0_D = (0x1D << 21) | OPC_CP0,
918 OPC_C0_E = (0x1E << 21) | OPC_CP0,
919 OPC_C0_F = (0x1F << 21) | OPC_CP0,
6ea83fed 920};
7a387fff
TS
921
922/* MFMC0 opcodes */
b48cfdff 923#define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
7a387fff
TS
924
925enum {
ead9360e
TS
926 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
927 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
928 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
929 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
930 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
931 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
01bc435b
YK
932 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
933 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
7a387fff
TS
934};
935
936/* Coprocessor 0 (with rs == C0) */
937#define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
938
939enum {
940 OPC_TLBR = 0x01 | OPC_C0,
941 OPC_TLBWI = 0x02 | OPC_C0,
9456c2fb
LA
942 OPC_TLBINV = 0x03 | OPC_C0,
943 OPC_TLBINVF = 0x04 | OPC_C0,
7a387fff
TS
944 OPC_TLBWR = 0x06 | OPC_C0,
945 OPC_TLBP = 0x08 | OPC_C0,
946 OPC_RFE = 0x10 | OPC_C0,
947 OPC_ERET = 0x18 | OPC_C0,
948 OPC_DERET = 0x1F | OPC_C0,
949 OPC_WAIT = 0x20 | OPC_C0,
950};
951
952/* Coprocessor 1 (rs field) */
953#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
954
bf4120ad
NF
955/* Values for the fmt field in FP instructions */
956enum {
957 /* 0 - 15 are reserved */
e459440a
AJ
958 FMT_S = 16, /* single fp */
959 FMT_D = 17, /* double fp */
960 FMT_E = 18, /* extended fp */
961 FMT_Q = 19, /* quad fp */
962 FMT_W = 20, /* 32-bit fixed */
963 FMT_L = 21, /* 64-bit fixed */
964 FMT_PS = 22, /* paired single fp */
bf4120ad
NF
965 /* 23 - 31 are reserved */
966};
967
7a387fff
TS
968enum {
969 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
970 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
971 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
5a5012ec 972 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
7a387fff
TS
973 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
974 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
975 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
5a5012ec 976 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
7a387fff 977 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
5a5012ec
TS
978 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
979 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
239dfebe
YK
980 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
981 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
e459440a
AJ
982 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
983 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
984 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
985 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
986 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
987 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
988 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
31837be3
YK
989 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
990 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
239dfebe
YK
991 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
992 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
993 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
994 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
995 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
996 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
997 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
998 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
7a387fff
TS
999};
1000
5a5012ec
TS
1001#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1002#define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1003
7a387fff
TS
1004enum {
1005 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1006 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1007 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1008 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1009};
1010
5a5012ec
TS
1011enum {
1012 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1013 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1014};
1015
1016enum {
1017 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1018 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1019};
7a387fff
TS
1020
1021#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
e0c84da7
TS
1022
1023enum {
1024 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1025 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1026 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1027 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1028 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1029 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1030 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1031 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1032 OPC_BC2 = (0x08 << 21) | OPC_CP2,
31837be3
YK
1033 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1034 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
e0c84da7
TS
1035};
1036
bd277fa1
RH
1037#define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1038
1039enum {
1040 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1041 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1042 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1043 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1044 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1045 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1046 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1047 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1048
1049 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1050 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1051 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1052 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1053 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1054 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1055 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1056 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1057
1058 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1059 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1060 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1061 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1062 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1063 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1064 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1065 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1066
1067 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1068 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1069 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1070 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1071 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1072 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1073 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1074 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1075
1076 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1077 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1078 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1079 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1080 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1081 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1082
1083 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1084 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1085 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1086 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1087 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1088 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1089
1090 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1091 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1092 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1093 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1094 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1095 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1096
1097 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1098 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1099 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1100 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1101 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1102 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1103
1104 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1105 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1106 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1107 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1108 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1109 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1110
1111 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1112 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1113 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1114 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1115 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1116 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1117
1118 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1119 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1120 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1121 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1122 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1123 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1124
1125 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1126 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1127 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1128 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1129 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1130 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1131};
1132
1133
e0c84da7
TS
1134#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1135
1136enum {
1137 OPC_LWXC1 = 0x00 | OPC_CP3,
1138 OPC_LDXC1 = 0x01 | OPC_CP3,
1139 OPC_LUXC1 = 0x05 | OPC_CP3,
1140 OPC_SWXC1 = 0x08 | OPC_CP3,
1141 OPC_SDXC1 = 0x09 | OPC_CP3,
1142 OPC_SUXC1 = 0x0D | OPC_CP3,
1143 OPC_PREFX = 0x0F | OPC_CP3,
1144 OPC_ALNV_PS = 0x1E | OPC_CP3,
1145 OPC_MADD_S = 0x20 | OPC_CP3,
1146 OPC_MADD_D = 0x21 | OPC_CP3,
1147 OPC_MADD_PS = 0x26 | OPC_CP3,
1148 OPC_MSUB_S = 0x28 | OPC_CP3,
1149 OPC_MSUB_D = 0x29 | OPC_CP3,
1150 OPC_MSUB_PS = 0x2E | OPC_CP3,
1151 OPC_NMADD_S = 0x30 | OPC_CP3,
fbcc6828 1152 OPC_NMADD_D = 0x31 | OPC_CP3,
e0c84da7
TS
1153 OPC_NMADD_PS= 0x36 | OPC_CP3,
1154 OPC_NMSUB_S = 0x38 | OPC_CP3,
1155 OPC_NMSUB_D = 0x39 | OPC_CP3,
1156 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1157};
1158
239dfebe
YK
1159/* MSA Opcodes */
1160#define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1161enum {
1162 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1163 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1164 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1165 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1166 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1167 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1168 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1169 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1170 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1171 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1172 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1173 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1174 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1175 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1176 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1177 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1178 OPC_MSA_ELM = 0x19 | OPC_MSA,
1179 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1180 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1181 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1182 OPC_MSA_VEC = 0x1E | OPC_MSA,
1183
1184 /* MI10 instruction */
1185 OPC_LD_B = (0x20) | OPC_MSA,
1186 OPC_LD_H = (0x21) | OPC_MSA,
1187 OPC_LD_W = (0x22) | OPC_MSA,
1188 OPC_LD_D = (0x23) | OPC_MSA,
1189 OPC_ST_B = (0x24) | OPC_MSA,
1190 OPC_ST_H = (0x25) | OPC_MSA,
1191 OPC_ST_W = (0x26) | OPC_MSA,
1192 OPC_ST_D = (0x27) | OPC_MSA,
1193};
1194
1195enum {
1196 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1197 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1198 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1199 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1200 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1201 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1202 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1203 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1204 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1205 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1206 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1207 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1208 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1209
1210 /* I8 instruction */
1211 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1212 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1213 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1214 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1215 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1216 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1217 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1218 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1219 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1220 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1221
1222 /* VEC/2R/2RF instruction */
1223 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1224 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1225 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1226 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1227 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1228 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1229 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1230
1231 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1232 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1233
1234 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1235 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1236 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1237 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1238 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1239
1240 /* 2RF instruction df(bit 16) = _w, _d */
1241 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1242 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1243 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1244 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1245 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1246 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1247 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1248 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1249 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1250 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1251 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1252 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1253 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1254 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1255 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1256 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1257
1258 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1259 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1260 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1261 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1262 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1263 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1264 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1265 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1266 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1267 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1268 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1269 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1270 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1271 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1272 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1273 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1274 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1275 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1276 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1277 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1278 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1279 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1280 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1281 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1282 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1283 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1284 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1285 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1286 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1287 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1288 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1289 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1290 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1291 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1292 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1293 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1294 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1295 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1296 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1297 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1298 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1299 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1300 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1301 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1302 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1303 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1304 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1305 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1306 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1307 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1308 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1309 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1310 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1311 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1312 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1313 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1314 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1315 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1316 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1317 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1318 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1319 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1320 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1321 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1322
1323 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1324 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1325 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1326 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1327 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1328 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1329 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1330 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1331 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1332 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1333
1334 /* 3RF instruction _df(bit 21) = _w, _d */
1335 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1336 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1337 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1338 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1339 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1340 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1341 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1342 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1343 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1344 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1345 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1346 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1347 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1348 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1349 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1350 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1351 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1352 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1353 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1356 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1357 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1358 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1359 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1361 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1362 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1363 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1364 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1365 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1366 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1367 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1368 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1369 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1370 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1372 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1373 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1374 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1375 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1376
1377 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1378 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1379 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1380 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1381 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1382 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1383 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1384 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1385 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1386 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1387 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1388 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1389 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1390};
1391
b158d449
AM
1392
1393/*
1394 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1395 * ============================================
1396 *
1397 * MXU (full name: MIPS eXtension/enhanced Unit) is an SIMD extension of MIPS32
1398 * instructions set. It is designed to fit the needs of signal, graphical and
1399 * video processing applications. MXU instruction set is used in Xburst family
1400 * of microprocessors by Ingenic.
1401 *
1402 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1403 * the control register.
1404 *
1d0e663c
AM
1405 * The notation used in MXU assembler mnemonics:
1406 *
1407 * XRa, XRb, XRc, XRd - MXU registers
1408 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1409 * s12 - a subfield of an instruction code
1410 * strd2 - a subfield of an instruction code
1411 * eptn2 - a subfield of an instruction code
1412 * eptn3 - a subfield of an instruction code
1413 * optn2 - a subfield of an instruction code
1414 * optn3 - a subfield of an instruction code
1415 * sft4 - a subfield of an instruction code
1416 *
1417 * Load/Store instructions Multiplication instructions
1418 * ----------------------- ---------------------------
1419 *
1420 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1421 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1422 * S32LDDV XRa, Rb, rc, strd2 S32SUB XRa, XRd, Rs, Rt
1423 * S32STDV XRa, Rb, rc, strd2 S32SUBU XRa, XRd, Rs, Rt
1424 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1425 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1426 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1427 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1428 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1429 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1430 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1431 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1432 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1433 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1434 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1435 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1436 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1437 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1438 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1439 * S16SDI XRa, Rb, s10, eptn2
1440 * S8LDD XRa, Rb, s8, eptn3
1441 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1442 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1443 * S8SDI XRa, Rb, s8, eptn3
1444 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1445 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1446 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1447 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1448 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1449 * S32CPS XRa, XRb, XRc
1450 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1451 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1452 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1453 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1454 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1455 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1456 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1457 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1458 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1459 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1460 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1461 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1462 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1463 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1464 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1465 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1466 * Q8SLT XRa, XRb, XRc
1467 * Q8SLTU XRa, XRb, XRc
1468 * Q8MOVZ XRa, XRb, XRc Shift instructions
1469 * Q8MOVN XRa, XRb, XRc ------------------
1470 *
1471 * D32SLL XRa, XRb, XRc, XRd, sft4
1472 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1473 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1474 * D32SARL XRa, XRb, XRc, sft4
1475 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1476 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1477 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1478 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1479 * Q16SLL XRa, XRb, XRc, XRd, sft4
1480 * Q16SLR XRa, XRb, XRc, XRd, sft4
1481 * Miscelaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1482 * ------------------------- Q16SLLV XRa, XRb, Rb
1483 * Q16SLRV XRa, XRb, Rb
1484 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1485 * S32ALN XRa, XRb, XRc, Rb
1486 * S32ALNI XRa, XRb, XRc, s3
1487 * S32LUI XRa, s8, optn3 Move instructions
1488 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1489 * S32EXTRV XRa, XRb, Rs, Rt
1490 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1491 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1492 *
9ef5bff9
AM
1493 *
1494 * bits
1495 * 05..00
1496 *
1497 * ┌─ 000000 ─ OPC_MXU_S32MADD
1498 * ├─ 000001 ─ OPC_MXU_S32MADDU
1499 * ├─ 000010 ─ <not assigned>
1500 * │ 20..18
1501 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1502 * │ ├─ 001 ─ OPC_MXU_S32MIN
1503 * │ ├─ 010 ─ OPC_MXU_D16MAX
1504 * │ ├─ 011 ─ OPC_MXU_D16MIN
1505 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1506 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1507 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1508 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1509 * ├─ 000100 ─ OPC_MXU_S32MSUB
1510 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1511 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1512 * │ ├─ 001 ─ OPC_MXU_D16SLT
1513 * │ ├─ 010 ─ OPC_MXU_D16AVG
1514 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1515 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1516 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1517 * │ └─ 111 ─ OPC_MXU_Q8ADD
1518 * │
1519 * │ 20..18
1520 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1521 * │ ├─ 010 ─ OPC_MXU_D16CPS
1522 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1523 * │ └─ 110 ─ OPC_MXU_Q16SAT
1524 * ├─ 001000 ─ OPC_MXU_D16MUL
1525 * │ 25..24
1526 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1527 * │ └─ 01 ─ OPC_MXU_D16MULE
1528 * ├─ 001010 ─ OPC_MXU_D16MAC
1529 * ├─ 001011 ─ OPC_MXU_D16MACF
1530 * ├─ 001100 ─ OPC_MXU_D16MADL
1531 * │ 25..24
1532 * ├─ 001101 ─ OPC_MXU__POOL04 ─┬─ 00 ─ OPC_MXU_S16MAD
1533 * │ └─ 01 ─ OPC_MXU_S16MAD_1
1534 * ├─ 001110 ─ OPC_MXU_Q16ADD
1535 * ├─ 001111 ─ OPC_MXU_D16MACE
1536 * │ 23
1537 * ├─ 010000 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32LDD
1538 * │ └─ 1 ─ OPC_MXU_S32LDDR
1539 * │
1540 * │ 23
1541 * ├─ 010001 ─ OPC_MXU__POOL06 ─┬─ 0 ─ OPC_MXU_S32STD
1542 * │ └─ 1 ─ OPC_MXU_S32STDR
1543 * │
1544 * │ 13..10
1545 * ├─ 010010 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1546 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1547 * │
1548 * │ 13..10
1549 * ├─ 010011 ─ OPC_MXU__POOL08 ─┬─ 0000 ─ OPC_MXU_S32STDV
1550 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1551 * │
1552 * │ 23
1553 * ├─ 010100 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32LDI
1554 * │ └─ 1 ─ OPC_MXU_S32LDIR
1555 * │
1556 * │ 23
1557 * ├─ 010101 ─ OPC_MXU__POOL10 ─┬─ 0 ─ OPC_MXU_S32SDI
1558 * │ └─ 1 ─ OPC_MXU_S32SDIR
1559 * │
1560 * │ 13..10
1561 * ├─ 010110 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1562 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1563 * │
1564 * │ 13..10
1565 * ├─ 010111 ─ OPC_MXU__POOL12 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1566 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1567 * ├─ 011000 ─ OPC_MXU_D32ADD
1568 * │ 23..22
1569 * MXU ├─ 011001 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_D32ACC
1570 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1571 * │ └─ 10 ─ OPC_MXU_D32ASUM
1572 * ├─ 011010 ─ <not assigned>
1573 * │ 23..22
1574 * ├─ 011011 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q16ACC
1575 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1576 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1577 * │
1578 * │ 23..22
1579 * ├─ 011100 ─ OPC_MXU__POOL15 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1580 * │ ├─ 01 ─ OPC_MXU_D8SUM
1581 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1582 * ├─ 011110 ─ <not assigned>
1583 * ├─ 011111 ─ <not assigned>
1584 * ├─ 100000 ─ <not assigned>
1585 * ├─ 100001 ─ <not assigned>
1586 * ├─ 100010 ─ OPC_MXU_S8LDD
1587 * ├─ 100011 ─ OPC_MXU_S8STD
1588 * ├─ 100100 ─ OPC_MXU_S8LDI
1589 * ├─ 100101 ─ OPC_MXU_S8SDI
1590 * │ 15..14
1591 * ├─ 100110 ─ OPC_MXU__POOL16 ─┬─ 00 ─ OPC_MXU_S32MUL
1592 * │ ├─ 00 ─ OPC_MXU_S32MULU
1593 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1594 * │ └─ 00 ─ OPC_MXU_S32EXTRV
1595 * │
1596 * │ 20..18
1597 * ├─ 100111 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_D32SARW
1598 * │ ├─ 001 ─ OPC_MXU_S32ALN
1599 * ├─ 101000 ─ OPC_MXU_LXB ├─ 010 ─ OPC_MXU_S32ALNI
1600 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_S32NOR
1601 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_S32AND
1602 * ├─ 101011 ─ OPC_MXU_S16STD ├─ 101 ─ OPC_MXU_S32OR
1603 * ├─ 101100 ─ OPC_MXU_S16LDI ├─ 110 ─ OPC_MXU_S32XOR
1604 * ├─ 101101 ─ OPC_MXU_S16SDI └─ 111 ─ OPC_MXU_S32LUI
1605 * ├─ 101000 ─ <not assigned>
1606 * ├─ 101001 ─ <not assigned>
1607 * ├─ 101010 ─ <not assigned>
1608 * ├─ 101011 ─ <not assigned>
1609 * ├─ 101100 ─ <not assigned>
1610 * ├─ 101101 ─ <not assigned>
1611 * ├─ 101110 ─ OPC_MXU_S32M2I
1612 * ├─ 101111 ─ OPC_MXU_S32I2M
1613 * ├─ 110000 ─ OPC_MXU_D32SLL
1614 * ├─ 110001 ─ OPC_MXU_D32SLR
1615 * ├─ 110010 ─ OPC_MXU_D32SARL
1616 * ├─ 110011 ─ OPC_MXU_D32SAR
1617 * ├─ 110100 ─ OPC_MXU_Q16SLL
1618 * ├─ 110101 ─ OPC_MXU_Q16SLR 20..18
1619 * ├─ 110110 ─ OPC_MXU__POOL18 ─┬─ 000 ─ OPC_MXU_D32SLLV
1620 * │ ├─ 001 ─ OPC_MXU_D32SLRV
1621 * │ ├─ 010 ─ OPC_MXU_D32SARV
1622 * │ ├─ 011 ─ OPC_MXU_Q16SLLV
1623 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1624 * │ └─ 101 ─ OPC_MXU_Q16SARV
1625 * ├─ 110111 ─ OPC_MXU_Q16SAR
1626 * │ 23..22
1627 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1628 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1629 * │
1630 * │ 20..18
1631 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1632 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1633 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1634 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1635 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1636 * │ └─ 101 ─ OPC_MXU_S32MOV
1637 * │
1638 * │ 23..22
1639 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1640 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1641 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1642 * ├─ 111100 ─ OPC_MXU_Q8MADL
1643 * ├─ 111101 ─ OPC_MXU_S32SFL
1644 * ├─ 111110 ─ OPC_MXU_Q8SAD
1645 * └─ 111111 ─ <not assigned>
1646 *
1647 *
b158d449
AM
1648 * Compiled after:
1649 *
1650 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1651 * Programming Manual", Ingenic Semiconductor Co, Ltd., 2017
1652 */
1653
1654
39454628 1655/* global register indices */
a7812ae4 1656static TCGv cpu_gpr[32], cpu_PC;
340fff72 1657static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
41db4607
AJ
1658static TCGv cpu_dspctrl, btarget, bcond;
1659static TCGv_i32 hflags;
a7812ae4 1660static TCGv_i32 fpu_fcr0, fpu_fcr31;
d73ee8a2 1661static TCGv_i64 fpu_f64[32];
863f264d 1662static TCGv_i64 msa_wr_d[64];
aa0bf00b 1663
022c62cb 1664#include "exec/gen-icount.h"
2e70f6ef 1665
895c2d04 1666#define gen_helper_0e0i(name, arg) do { \
a7812ae4 1667 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
895c2d04 1668 gen_helper_##name(cpu_env, helper_tmp); \
a7812ae4
PB
1669 tcg_temp_free_i32(helper_tmp); \
1670 } while(0)
be24bb4f 1671
895c2d04 1672#define gen_helper_0e1i(name, arg1, arg2) do { \
a7812ae4 1673 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
895c2d04 1674 gen_helper_##name(cpu_env, arg1, helper_tmp); \
a7812ae4
PB
1675 tcg_temp_free_i32(helper_tmp); \
1676 } while(0)
be24bb4f 1677
895c2d04
BS
1678#define gen_helper_1e0i(name, ret, arg1) do { \
1679 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1680 gen_helper_##name(ret, cpu_env, helper_tmp); \
1681 tcg_temp_free_i32(helper_tmp); \
1682 } while(0)
1683
1684#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1685 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1686 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1687 tcg_temp_free_i32(helper_tmp); \
1688 } while(0)
1689
1690#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1691 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1692 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1693 tcg_temp_free_i32(helper_tmp); \
1694 } while(0)
1695
1696#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
a7812ae4 1697 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
895c2d04 1698 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
a7812ae4
PB
1699 tcg_temp_free_i32(helper_tmp); \
1700 } while(0)
be24bb4f 1701
895c2d04 1702#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
a7812ae4 1703 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
895c2d04 1704 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
a7812ae4
PB
1705 tcg_temp_free_i32(helper_tmp); \
1706 } while(0)
c239529e 1707
8e9ade68 1708typedef struct DisasContext {
eeb3bba8
EC
1709 DisasContextBase base;
1710 target_ulong saved_pc;
18f440ed 1711 target_ulong page_start;
8e9ade68 1712 uint32_t opcode;
d75c135e 1713 int insn_flags;
5ab5c041 1714 int32_t CP0_Config1;
ab77fc61
DN
1715 int32_t CP0_Config3;
1716 int32_t CP0_Config5;
8e9ade68
TS
1717 /* Routine used to access memory */
1718 int mem_idx;
be3a8c53 1719 TCGMemOp default_tcg_memop_mask;
8e9ade68 1720 uint32_t hflags, saved_hflags;
8e9ade68 1721 target_ulong btarget;
d279279e 1722 bool ulri;
e98c0d17 1723 int kscrexist;
7207c7f9 1724 bool rxi;
9456c2fb 1725 int ie;
aea14095
LA
1726 bool bi;
1727 bool bp;
5204ea79
LA
1728 uint64_t PAMask;
1729 bool mvh;
76964147 1730 bool eva;
cec56a73 1731 bool sc;
5204ea79 1732 int CP0_LLAddr_shift;
e29c9628 1733 bool ps;
01bc435b 1734 bool vp;
c870e3f5 1735 bool cmgcr;
f6d4dd81 1736 bool mrp;
87552089 1737 bool nan2008;
6be77480 1738 bool abs2008;
8e9ade68
TS
1739} DisasContext;
1740
b28425ba
EC
1741#define DISAS_STOP DISAS_TARGET_0
1742#define DISAS_EXIT DISAS_TARGET_1
8e9ade68 1743
d73ee8a2
RH
1744static const char * const regnames[] = {
1745 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1746 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1747 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1748 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1749};
6af0bf9c 1750
d73ee8a2
RH
1751static const char * const regnames_HI[] = {
1752 "HI0", "HI1", "HI2", "HI3",
1753};
4b2eb8d2 1754
d73ee8a2
RH
1755static const char * const regnames_LO[] = {
1756 "LO0", "LO1", "LO2", "LO3",
1757};
4b2eb8d2 1758
d73ee8a2
RH
1759static const char * const fregnames[] = {
1760 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1761 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1762 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1763 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1764};
958fb4a9 1765
863f264d
YK
1766static const char * const msaregnames[] = {
1767 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1768 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1769 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1770 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1771 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1772 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1773 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1774 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1775 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1776 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1777 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1778 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1779 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1780 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1781 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1782 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1783};
1784
9d68ac14 1785#define LOG_DISAS(...) \
fb7729e2
RH
1786 do { \
1787 if (MIPS_DEBUG_DISAS) { \
9d68ac14 1788 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
fb7729e2
RH
1789 } \
1790 } while (0)
1791
9d68ac14 1792#define MIPS_INVAL(op) \
fb7729e2
RH
1793 do { \
1794 if (MIPS_DEBUG_DISAS) { \
9d68ac14
AJ
1795 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1796 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
eeb3bba8
EC
1797 ctx->base.pc_next, ctx->opcode, op, \
1798 ctx->opcode >> 26, ctx->opcode & 0x3F, \
1799 ((ctx->opcode >> 16) & 0x1F)); \
fb7729e2
RH
1800 } \
1801 } while (0)
958fb4a9 1802
8e9ade68
TS
1803/* General purpose registers moves. */
1804static inline void gen_load_gpr (TCGv t, int reg)
aaa9128a 1805{
8e9ade68
TS
1806 if (reg == 0)
1807 tcg_gen_movi_tl(t, 0);
1808 else
4b2eb8d2 1809 tcg_gen_mov_tl(t, cpu_gpr[reg]);
aaa9128a
TS
1810}
1811
8e9ade68 1812static inline void gen_store_gpr (TCGv t, int reg)
aaa9128a 1813{
8e9ade68 1814 if (reg != 0)
4b2eb8d2 1815 tcg_gen_mov_tl(cpu_gpr[reg], t);
aaa9128a
TS
1816}
1817
8e9ade68 1818/* Moves to/from shadow registers. */
be24bb4f 1819static inline void gen_load_srsgpr (int from, int to)
aaa9128a 1820{
d9bea114 1821 TCGv t0 = tcg_temp_new();
be24bb4f
TS
1822
1823 if (from == 0)
d9bea114 1824 tcg_gen_movi_tl(t0, 0);
8e9ade68 1825 else {
d9bea114 1826 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 1827 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 1828
7db13fae 1829 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
1830 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1831 tcg_gen_andi_i32(t2, t2, 0xf);
1832 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1833 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 1834 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 1835
d9bea114 1836 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 1837 tcg_temp_free_ptr(addr);
d9bea114 1838 tcg_temp_free_i32(t2);
8e9ade68 1839 }
d9bea114
AJ
1840 gen_store_gpr(t0, to);
1841 tcg_temp_free(t0);
aaa9128a
TS
1842}
1843
be24bb4f 1844static inline void gen_store_srsgpr (int from, int to)
aaa9128a 1845{
be24bb4f 1846 if (to != 0) {
d9bea114
AJ
1847 TCGv t0 = tcg_temp_new();
1848 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 1849 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 1850
d9bea114 1851 gen_load_gpr(t0, from);
7db13fae 1852 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
1853 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1854 tcg_gen_andi_i32(t2, t2, 0xf);
1855 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1856 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 1857 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 1858
d9bea114 1859 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 1860 tcg_temp_free_ptr(addr);
d9bea114
AJ
1861 tcg_temp_free_i32(t2);
1862 tcg_temp_free(t0);
8e9ade68 1863 }
aaa9128a
TS
1864}
1865
eab9944c
LA
1866/* Tests */
1867static inline void gen_save_pc(target_ulong pc)
1868{
1869 tcg_gen_movi_tl(cpu_PC, pc);
1870}
1871
1872static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1873{
1874 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
eeb3bba8
EC
1875 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1876 gen_save_pc(ctx->base.pc_next);
1877 ctx->saved_pc = ctx->base.pc_next;
eab9944c
LA
1878 }
1879 if (ctx->hflags != ctx->saved_hflags) {
1880 tcg_gen_movi_i32(hflags, ctx->hflags);
1881 ctx->saved_hflags = ctx->hflags;
1882 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1883 case MIPS_HFLAG_BR:
1884 break;
1885 case MIPS_HFLAG_BC:
1886 case MIPS_HFLAG_BL:
1887 case MIPS_HFLAG_B:
1888 tcg_gen_movi_tl(btarget, ctx->btarget);
1889 break;
1890 }
1891 }
1892}
1893
1894static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1895{
1896 ctx->saved_hflags = ctx->hflags;
1897 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1898 case MIPS_HFLAG_BR:
1899 break;
1900 case MIPS_HFLAG_BC:
1901 case MIPS_HFLAG_BL:
1902 case MIPS_HFLAG_B:
1903 ctx->btarget = env->btarget;
1904 break;
1905 }
1906}
1907
1908static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1909{
1910 TCGv_i32 texcp = tcg_const_i32(excp);
1911 TCGv_i32 terr = tcg_const_i32(err);
1912 save_cpu_state(ctx, 1);
1913 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1914 tcg_temp_free_i32(terr);
1915 tcg_temp_free_i32(texcp);
eeb3bba8 1916 ctx->base.is_jmp = DISAS_NORETURN;
eab9944c
LA
1917}
1918
1919static inline void generate_exception(DisasContext *ctx, int excp)
1920{
eab9944c
LA
1921 gen_helper_0e0i(raise_exception, excp);
1922}
1923
9c708c7f
PD
1924static inline void generate_exception_end(DisasContext *ctx, int excp)
1925{
1926 generate_exception_err(ctx, excp, 0);
1927}
1928
aaa9128a 1929/* Floating point register moves. */
7c979afd 1930static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 1931{
7c979afd
LA
1932 if (ctx->hflags & MIPS_HFLAG_FRE) {
1933 generate_exception(ctx, EXCP_RI);
1934 }
ecc7b3aa 1935 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
1936}
1937
7c979afd 1938static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 1939{
7c979afd
LA
1940 TCGv_i64 t64;
1941 if (ctx->hflags & MIPS_HFLAG_FRE) {
1942 generate_exception(ctx, EXCP_RI);
1943 }
1944 t64 = tcg_temp_new_i64();
d73ee8a2
RH
1945 tcg_gen_extu_i32_i64(t64, t);
1946 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1947 tcg_temp_free_i64(t64);
6d066274
AJ
1948}
1949
7f6613ce 1950static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 1951{
7f6613ce 1952 if (ctx->hflags & MIPS_HFLAG_F64) {
71f303cd 1953 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
7f6613ce 1954 } else {
7c979afd 1955 gen_load_fpr32(ctx, t, reg | 1);
7f6613ce 1956 }
6d066274
AJ
1957}
1958
7f6613ce 1959static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 1960{
7f6613ce
PJ
1961 if (ctx->hflags & MIPS_HFLAG_F64) {
1962 TCGv_i64 t64 = tcg_temp_new_i64();
1963 tcg_gen_extu_i32_i64(t64, t);
1964 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1965 tcg_temp_free_i64(t64);
1966 } else {
7c979afd 1967 gen_store_fpr32(ctx, t, reg | 1);
7f6613ce 1968 }
aa0bf00b 1969}
6ea83fed 1970
d73ee8a2 1971static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 1972{
f364515c 1973 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 1974 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 1975 } else {
d73ee8a2 1976 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
1977 }
1978}
6ea83fed 1979
d73ee8a2 1980static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 1981{
f364515c 1982 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 1983 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 1984 } else {
d73ee8a2
RH
1985 TCGv_i64 t0;
1986 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1987 t0 = tcg_temp_new_i64();
6d066274 1988 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 1989 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
6d066274 1990 tcg_temp_free_i64(t0);
aa0bf00b
TS
1991 }
1992}
6ea83fed 1993
d94536f4 1994static inline int get_fp_bit (int cc)
a16336e4 1995{
d94536f4
AJ
1996 if (cc)
1997 return 24 + cc;
1998 else
1999 return 23;
a16336e4
TS
2000}
2001
48d38ca5 2002/* Addresses computation */
941694d0 2003static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
4ad40f36 2004{
941694d0 2005 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
2006
2007#if defined(TARGET_MIPS64)
01f72885 2008 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
941694d0 2009 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
2010 }
2011#endif
4ad40f36
FB
2012}
2013
bf0718c5
SM
2014static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2015 target_long ofs)
2016{
2017 tcg_gen_addi_tl(ret, base, ofs);
2018
2019#if defined(TARGET_MIPS64)
2020 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2021 tcg_gen_ext32s_i64(ret, ret);
2022 }
2023#endif
2024}
2025
31837be3
YK
2026/* Addresses computation (translation time) */
2027static target_long addr_add(DisasContext *ctx, target_long base,
2028 target_long offset)
2029{
2030 target_long sum = base + offset;
2031
2032#if defined(TARGET_MIPS64)
2033 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2034 sum = (int32_t)sum;
2035 }
2036#endif
2037 return sum;
2038}
2039
71f303cd 2040/* Sign-extract the low 32-bits to a target_long. */
1f1b4c00
YK
2041static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2042{
2043#if defined(TARGET_MIPS64)
71f303cd
RH
2044 tcg_gen_ext32s_i64(ret, arg);
2045#else
2046 tcg_gen_extrl_i64_i32(ret, arg);
2047#endif
2048}
2049
2050/* Sign-extract the high 32-bits to a target_long. */
2051static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2052{
2053#if defined(TARGET_MIPS64)
2054 tcg_gen_sari_i64(ret, arg, 32);
1f1b4c00 2055#else
71f303cd 2056 tcg_gen_extrh_i64_i32(ret, arg);
1f1b4c00
YK
2057#endif
2058}
2059
356265ae 2060static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 2061{
fe253235 2062 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
c2c65dab 2063 generate_exception_err(ctx, EXCP_CpU, 0);
387a8fe5
TS
2064}
2065
356265ae 2066static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 2067{
fe253235 2068 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
5e755519
TS
2069 generate_exception_err(ctx, EXCP_CpU, 1);
2070}
2071
b8aa4598
TS
2072/* Verify that the processor is running with COP1X instructions enabled.
2073 This is associated with the nabla symbol in the MIPS32 and MIPS64
2074 opcode tables. */
2075
356265ae 2076static inline void check_cop1x(DisasContext *ctx)
b8aa4598
TS
2077{
2078 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
9c708c7f 2079 generate_exception_end(ctx, EXCP_RI);
b8aa4598
TS
2080}
2081
2082/* Verify that the processor is running with 64-bit floating-point
2083 operations enabled. */
2084
356265ae 2085static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 2086{
b8aa4598 2087 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
9c708c7f 2088 generate_exception_end(ctx, EXCP_RI);
5e755519
TS
2089}
2090
2091/*
2092 * Verify if floating point register is valid; an operation is not defined
2093 * if bit 0 of any register specification is set and the FR bit in the
2094 * Status register equals zero, since the register numbers specify an
2095 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2096 * in the Status register equals one, both even and odd register numbers
2097 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2098 *
2099 * Multiple 64 bit wide registers can be checked by calling
2100 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2101 */
356265ae 2102static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 2103{
fe253235 2104 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
9c708c7f 2105 generate_exception_end(ctx, EXCP_RI);
5e755519
TS
2106}
2107
853c3240
JL
2108/* Verify that the processor is running with DSP instructions enabled.
2109 This is enabled by CP0 Status register MX(24) bit.
2110 */
2111
2112static inline void check_dsp(DisasContext *ctx)
2113{
2114 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
ad153f15 2115 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 2116 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 2117 } else {
9c708c7f 2118 generate_exception_end(ctx, EXCP_RI);
ad153f15 2119 }
853c3240
JL
2120 }
2121}
2122
2123static inline void check_dspr2(DisasContext *ctx)
2124{
2125 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
ad153f15 2126 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 2127 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 2128 } else {
9c708c7f 2129 generate_exception_end(ctx, EXCP_RI);
ad153f15 2130 }
853c3240
JL
2131 }
2132}
2133
3a95e3a7 2134/* This code generates a "reserved instruction" exception if the
e189e748 2135 CPU does not support the instruction set corresponding to flags. */
d75c135e 2136static inline void check_insn(DisasContext *ctx, int flags)
3a95e3a7 2137{
d75c135e 2138 if (unlikely(!(ctx->insn_flags & flags))) {
9c708c7f 2139 generate_exception_end(ctx, EXCP_RI);
d75c135e 2140 }
3a95e3a7
TS
2141}
2142
fecd2646
LA
2143/* This code generates a "reserved instruction" exception if the
2144 CPU has corresponding flag set which indicates that the instruction
2145 has been removed. */
2146static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
2147{
2148 if (unlikely(ctx->insn_flags & flags)) {
9c708c7f 2149 generate_exception_end(ctx, EXCP_RI);
fecd2646
LA
2150 }
2151}
2152
e29c9628
YK
2153/* This code generates a "reserved instruction" exception if the
2154 CPU does not support 64-bit paired-single (PS) floating point data type */
2155static inline void check_ps(DisasContext *ctx)
2156{
2157 if (unlikely(!ctx->ps)) {
2158 generate_exception(ctx, EXCP_RI);
2159 }
2160 check_cp1_64bitmode(ctx);
2161}
2162
c7986fd6 2163#ifdef TARGET_MIPS64
e189e748
TS
2164/* This code generates a "reserved instruction" exception if 64-bit
2165 instructions are not enabled. */
356265ae 2166static inline void check_mips_64(DisasContext *ctx)
e189e748 2167{
fe253235 2168 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
9c708c7f 2169 generate_exception_end(ctx, EXCP_RI);
e189e748 2170}
c7986fd6 2171#endif
e189e748 2172
5204ea79
LA
2173#ifndef CONFIG_USER_ONLY
2174static inline void check_mvh(DisasContext *ctx)
2175{
2176 if (unlikely(!ctx->mvh)) {
2177 generate_exception(ctx, EXCP_RI);
2178 }
2179}
2180#endif
2181
0b16dcd1
AR
2182/*
2183 * This code generates a "reserved instruction" exception if the
2184 * Config5 XNP bit is set.
2185 */
2186static inline void check_xnp(DisasContext *ctx)
2187{
2188 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2189 generate_exception_end(ctx, EXCP_RI);
2190 }
2191}
2192
9affc1c5
AR
2193/*
2194 * This code generates a "reserved instruction" exception if the
2195 * Config3 MT bit is NOT set.
2196 */
2197static inline void check_mt(DisasContext *ctx)
2198{
2199 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2200 generate_exception_end(ctx, EXCP_RI);
2201 }
2202}
2203
2204#ifndef CONFIG_USER_ONLY
2205/*
2206 * This code generates a "coprocessor unusable" exception if CP0 is not
2207 * available, and, if that is not the case, generates a "reserved instruction"
2208 * exception if the Config5 MT bit is NOT set. This is needed for availability
2209 * control of some of MT ASE instructions.
2210 */
2211static inline void check_cp0_mt(DisasContext *ctx)
2212{
2213 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2214 generate_exception_err(ctx, EXCP_CpU, 0);
2215 } else {
2216 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2217 generate_exception_err(ctx, EXCP_RI, 0);
2218 }
2219 }
2220}
2221#endif
2222
fb32f8c8
DN
2223/*
2224 * This code generates a "reserved instruction" exception if the
2225 * Config5 NMS bit is set.
2226 */
2227static inline void check_nms(DisasContext *ctx)
2228{
2229 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2230 generate_exception_end(ctx, EXCP_RI);
2231 }
2232}
2233
0b16dcd1 2234
8153667c
NF
2235/* Define small wrappers for gen_load_fpr* so that we have a uniform
2236 calling interface for 32 and 64-bit FPRs. No sense in changing
2237 all callers for gen_load_fpr32 when we need the CTX parameter for
2238 this one use. */
7c979afd 2239#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
8153667c
NF
2240#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
2241#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
2242static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
2243 int ft, int fs, int cc) \
2244{ \
2245 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
2246 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
2247 switch (ifmt) { \
2248 case FMT_PS: \
e29c9628 2249 check_ps(ctx); \
8153667c
NF
2250 break; \
2251 case FMT_D: \
2252 if (abs) { \
2253 check_cop1x(ctx); \
2254 } \
2255 check_cp1_registers(ctx, fs | ft); \
2256 break; \
2257 case FMT_S: \
2258 if (abs) { \
2259 check_cop1x(ctx); \
2260 } \
2261 break; \
2262 } \
2263 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
2264 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
2265 switch (n) { \
895c2d04
BS
2266 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
2267 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
2268 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
2269 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
2270 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
2271 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
2272 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
2273 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
2274 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
2275 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
2276 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
2277 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
2278 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
2279 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
2280 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
2281 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
8153667c
NF
2282 default: abort(); \
2283 } \
2284 tcg_temp_free_i##bits (fp0); \
2285 tcg_temp_free_i##bits (fp1); \
2286}
2287
2288FOP_CONDS(, 0, d, FMT_D, 64)
2289FOP_CONDS(abs, 1, d, FMT_D, 64)
2290FOP_CONDS(, 0, s, FMT_S, 32)
2291FOP_CONDS(abs, 1, s, FMT_S, 32)
2292FOP_CONDS(, 0, ps, FMT_PS, 64)
2293FOP_CONDS(abs, 1, ps, FMT_PS, 64)
2294#undef FOP_CONDS
3f493883
YK
2295
2296#define FOP_CONDNS(fmt, ifmt, bits, STORE) \
2297static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
2298 int ft, int fs, int fd) \
2299{ \
2300 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
2301 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
00fb4a11 2302 if (ifmt == FMT_D) { \
3f493883 2303 check_cp1_registers(ctx, fs | ft | fd); \
3f493883
YK
2304 } \
2305 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
2306 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
2307 switch (n) { \
2308 case 0: \
2309 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
2310 break; \
2311 case 1: \
2312 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
2313 break; \
2314 case 2: \
2315 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
2316 break; \
2317 case 3: \
2318 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
2319 break; \
2320 case 4: \
2321 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
2322 break; \
2323 case 5: \
2324 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
2325 break; \
2326 case 6: \
2327 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
2328 break; \
2329 case 7: \
2330 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
2331 break; \
2332 case 8: \
2333 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
2334 break; \
2335 case 9: \
2336 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
2337 break; \
2338 case 10: \
2339 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2340 break; \
2341 case 11: \
2342 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2343 break; \
2344 case 12: \
2345 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2346 break; \
2347 case 13: \
2348 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2349 break; \
2350 case 14: \
2351 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
2352 break; \
2353 case 15: \
2354 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
2355 break; \
2356 case 17: \
2357 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
2358 break; \
2359 case 18: \
2360 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2361 break; \
2362 case 19: \
2363 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2364 break; \
2365 case 25: \
2366 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2367 break; \
2368 case 26: \
2369 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2370 break; \
2371 case 27: \
2372 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2373 break; \
2374 default: \
2375 abort(); \
2376 } \
2377 STORE; \
2378 tcg_temp_free_i ## bits (fp0); \
2379 tcg_temp_free_i ## bits (fp1); \
2380}
2381
2382FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
7c979afd 2383FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3f493883 2384#undef FOP_CONDNS
8153667c
NF
2385#undef gen_ldcmp_fpr32
2386#undef gen_ldcmp_fpr64
2387
958fb4a9 2388/* load/store instructions. */
e7139c44 2389#ifdef CONFIG_USER_ONLY
d9bea114 2390#define OP_LD_ATOMIC(insn,fname) \
dd4096cd
JH
2391static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2392 DisasContext *ctx) \
d9bea114
AJ
2393{ \
2394 TCGv t0 = tcg_temp_new(); \
2395 tcg_gen_mov_tl(t0, arg1); \
2396 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
7db13fae
AF
2397 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2398 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 2399 tcg_temp_free(t0); \
aaa9128a 2400}
e7139c44
AJ
2401#else
2402#define OP_LD_ATOMIC(insn,fname) \
dd4096cd
JH
2403static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2404 DisasContext *ctx) \
e7139c44 2405{ \
dd4096cd 2406 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
e7139c44
AJ
2407}
2408#endif
aaa9128a
TS
2409OP_LD_ATOMIC(ll,ld32s);
2410#if defined(TARGET_MIPS64)
2411OP_LD_ATOMIC(lld,ld64);
2412#endif
2413#undef OP_LD_ATOMIC
2414
590bc601
PB
2415#ifdef CONFIG_USER_ONLY
2416#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
dd4096cd
JH
2417static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2418 DisasContext *ctx) \
590bc601
PB
2419{ \
2420 TCGv t0 = tcg_temp_new(); \
42a268c2
RH
2421 TCGLabel *l1 = gen_new_label(); \
2422 TCGLabel *l2 = gen_new_label(); \
590bc601
PB
2423 \
2424 tcg_gen_andi_tl(t0, arg2, almask); \
2425 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
7db13fae 2426 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
590bc601
PB
2427 generate_exception(ctx, EXCP_AdES); \
2428 gen_set_label(l1); \
7db13fae 2429 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
590bc601
PB
2430 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2431 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
7db13fae
AF
2432 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2433 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
9c708c7f 2434 generate_exception_end(ctx, EXCP_SC); \
590bc601
PB
2435 gen_set_label(l2); \
2436 tcg_gen_movi_tl(t0, 0); \
2437 gen_store_gpr(t0, rt); \
2438 tcg_temp_free(t0); \
2439}
2440#else
2441#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
dd4096cd
JH
2442static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2443 DisasContext *ctx) \
590bc601
PB
2444{ \
2445 TCGv t0 = tcg_temp_new(); \
dd4096cd 2446 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
590bc601 2447 gen_store_gpr(t0, rt); \
590bc601
PB
2448 tcg_temp_free(t0); \
2449}
2450#endif
590bc601 2451OP_ST_ATOMIC(sc,st32,ld32s,0x3);
aaa9128a 2452#if defined(TARGET_MIPS64)
590bc601 2453OP_ST_ATOMIC(scd,st64,ld64,0x7);
aaa9128a
TS
2454#endif
2455#undef OP_ST_ATOMIC
2456
662d7485 2457static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
72e1f16f 2458 int base, int offset)
662d7485
NF
2459{
2460 if (base == 0) {
2461 tcg_gen_movi_tl(addr, offset);
2462 } else if (offset == 0) {
2463 gen_load_gpr(addr, base);
2464 } else {
2465 tcg_gen_movi_tl(addr, offset);
2466 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2467 }
2468}
2469
364d4831
NF
2470static target_ulong pc_relative_pc (DisasContext *ctx)
2471{
eeb3bba8 2472 target_ulong pc = ctx->base.pc_next;
364d4831
NF
2473
2474 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2475 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2476
2477 pc -= branch_bytes;
2478 }
2479
2480 pc &= ~(target_ulong)3;
2481 return pc;
2482}
2483
5c13fdfd 2484/* Load */
d75c135e 2485static void gen_ld(DisasContext *ctx, uint32_t opc,
72e1f16f 2486 int rt, int base, int offset)
6af0bf9c 2487{
fc40787a 2488 TCGv t0, t1, t2;
dd4096cd 2489 int mem_idx = ctx->mem_idx;
afa88c3a 2490
d75c135e 2491 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
afa88c3a
AJ
2492 /* Loongson CPU uses a load to zero register for prefetch.
2493 We emulate it as a NOP. On other CPU we must perform the
2494 actual memory access. */
afa88c3a
AJ
2495 return;
2496 }
6af0bf9c 2497
afa88c3a 2498 t0 = tcg_temp_new();
662d7485 2499 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 2500
6af0bf9c 2501 switch (opc) {
d26bc211 2502#if defined(TARGET_MIPS64)
6e473128 2503 case OPC_LWU:
dd4096cd 2504 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
be3a8c53 2505 ctx->default_tcg_memop_mask);
78723684 2506 gen_store_gpr(t0, rt);
6e473128 2507 break;
6af0bf9c 2508 case OPC_LD:
dd4096cd 2509 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
be3a8c53 2510 ctx->default_tcg_memop_mask);
78723684 2511 gen_store_gpr(t0, rt);
6af0bf9c 2512 break;
7a387fff 2513 case OPC_LLD:
bf7910c6 2514 case R6_OPC_LLD:
dd4096cd 2515 op_ld_lld(t0, t0, mem_idx, ctx);
78723684 2516 gen_store_gpr(t0, rt);
7a387fff 2517 break;
6af0bf9c 2518 case OPC_LDL:
3cee3050 2519 t1 = tcg_temp_new();
908680c6
AJ
2520 /* Do a byte access to possibly trigger a page
2521 fault with the unaligned address. */
dd4096cd 2522 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2523 tcg_gen_andi_tl(t1, t0, 7);
2524#ifndef TARGET_WORDS_BIGENDIAN
2525 tcg_gen_xori_tl(t1, t1, 7);
2526#endif
2527 tcg_gen_shli_tl(t1, t1, 3);
2528 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 2529 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a 2530 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
2531 t2 = tcg_const_tl(-1);
2532 tcg_gen_shl_tl(t2, t2, t1);
78723684 2533 gen_load_gpr(t1, rt);
eb02cc3f 2534 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
2535 tcg_temp_free(t2);
2536 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2537 tcg_temp_free(t1);
fc40787a 2538 gen_store_gpr(t0, rt);
6af0bf9c 2539 break;
6af0bf9c 2540 case OPC_LDR:
3cee3050 2541 t1 = tcg_temp_new();
908680c6
AJ
2542 /* Do a byte access to possibly trigger a page
2543 fault with the unaligned address. */
dd4096cd 2544 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2545 tcg_gen_andi_tl(t1, t0, 7);
2546#ifdef TARGET_WORDS_BIGENDIAN
2547 tcg_gen_xori_tl(t1, t1, 7);
2548#endif
2549 tcg_gen_shli_tl(t1, t1, 3);
2550 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 2551 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a
AJ
2552 tcg_gen_shr_tl(t0, t0, t1);
2553 tcg_gen_xori_tl(t1, t1, 63);
2554 t2 = tcg_const_tl(0xfffffffffffffffeull);
2555 tcg_gen_shl_tl(t2, t2, t1);
78723684 2556 gen_load_gpr(t1, rt);
fc40787a
AJ
2557 tcg_gen_and_tl(t1, t1, t2);
2558 tcg_temp_free(t2);
2559 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2560 tcg_temp_free(t1);
fc40787a 2561 gen_store_gpr(t0, rt);
6af0bf9c 2562 break;
364d4831 2563 case OPC_LDPC:
3cee3050 2564 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 2565 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 2566 tcg_temp_free(t1);
dd4096cd 2567 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
364d4831
NF
2568 gen_store_gpr(t0, rt);
2569 break;
6af0bf9c 2570#endif
364d4831 2571 case OPC_LWPC:
3cee3050 2572 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 2573 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 2574 tcg_temp_free(t1);
dd4096cd 2575 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
364d4831
NF
2576 gen_store_gpr(t0, rt);
2577 break;
76964147
JH
2578 case OPC_LWE:
2579 mem_idx = MIPS_HFLAG_UM;
2580 /* fall through */
6af0bf9c 2581 case OPC_LW:
dd4096cd 2582 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
be3a8c53 2583 ctx->default_tcg_memop_mask);
78723684 2584 gen_store_gpr(t0, rt);
6af0bf9c 2585 break;
76964147
JH
2586 case OPC_LHE:
2587 mem_idx = MIPS_HFLAG_UM;
2588 /* fall through */
6af0bf9c 2589 case OPC_LH:
dd4096cd 2590 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
be3a8c53 2591 ctx->default_tcg_memop_mask);
78723684 2592 gen_store_gpr(t0, rt);
6af0bf9c 2593 break;
76964147
JH
2594 case OPC_LHUE:
2595 mem_idx = MIPS_HFLAG_UM;
2596 /* fall through */
6af0bf9c 2597 case OPC_LHU:
dd4096cd 2598 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
be3a8c53 2599 ctx->default_tcg_memop_mask);
78723684 2600 gen_store_gpr(t0, rt);
6af0bf9c 2601 break;
76964147
JH
2602 case OPC_LBE:
2603 mem_idx = MIPS_HFLAG_UM;
2604 /* fall through */
6af0bf9c 2605 case OPC_LB:
dd4096cd 2606 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
78723684 2607 gen_store_gpr(t0, rt);
6af0bf9c 2608 break;
76964147
JH
2609 case OPC_LBUE:
2610 mem_idx = MIPS_HFLAG_UM;
2611 /* fall through */
6af0bf9c 2612 case OPC_LBU:
dd4096cd 2613 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
78723684 2614 gen_store_gpr(t0, rt);
6af0bf9c 2615 break;
76964147
JH
2616 case OPC_LWLE:
2617 mem_idx = MIPS_HFLAG_UM;
2618 /* fall through */
6af0bf9c 2619 case OPC_LWL:
3cee3050 2620 t1 = tcg_temp_new();
908680c6
AJ
2621 /* Do a byte access to possibly trigger a page
2622 fault with the unaligned address. */
dd4096cd 2623 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2624 tcg_gen_andi_tl(t1, t0, 3);
2625#ifndef TARGET_WORDS_BIGENDIAN
2626 tcg_gen_xori_tl(t1, t1, 3);
2627#endif
2628 tcg_gen_shli_tl(t1, t1, 3);
2629 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 2630 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a 2631 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
2632 t2 = tcg_const_tl(-1);
2633 tcg_gen_shl_tl(t2, t2, t1);
6958549d 2634 gen_load_gpr(t1, rt);
eb02cc3f 2635 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
2636 tcg_temp_free(t2);
2637 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2638 tcg_temp_free(t1);
fc40787a
AJ
2639 tcg_gen_ext32s_tl(t0, t0);
2640 gen_store_gpr(t0, rt);
6af0bf9c 2641 break;
76964147
JH
2642 case OPC_LWRE:
2643 mem_idx = MIPS_HFLAG_UM;
2644 /* fall through */
6af0bf9c 2645 case OPC_LWR:
3cee3050 2646 t1 = tcg_temp_new();
908680c6
AJ
2647 /* Do a byte access to possibly trigger a page
2648 fault with the unaligned address. */
dd4096cd 2649 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2650 tcg_gen_andi_tl(t1, t0, 3);
2651#ifdef TARGET_WORDS_BIGENDIAN
2652 tcg_gen_xori_tl(t1, t1, 3);
2653#endif
2654 tcg_gen_shli_tl(t1, t1, 3);
2655 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 2656 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a
AJ
2657 tcg_gen_shr_tl(t0, t0, t1);
2658 tcg_gen_xori_tl(t1, t1, 31);
2659 t2 = tcg_const_tl(0xfffffffeull);
2660 tcg_gen_shl_tl(t2, t2, t1);
6958549d 2661 gen_load_gpr(t1, rt);
fc40787a
AJ
2662 tcg_gen_and_tl(t1, t1, t2);
2663 tcg_temp_free(t2);
2664 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2665 tcg_temp_free(t1);
c728154b 2666 tcg_gen_ext32s_tl(t0, t0);
fc40787a 2667 gen_store_gpr(t0, rt);
6af0bf9c 2668 break;
76964147
JH
2669 case OPC_LLE:
2670 mem_idx = MIPS_HFLAG_UM;
2671 /* fall through */
6af0bf9c 2672 case OPC_LL:
4368b29a 2673 case R6_OPC_LL:
dd4096cd 2674 op_ld_ll(t0, t0, mem_idx, ctx);
78723684 2675 gen_store_gpr(t0, rt);
6af0bf9c 2676 break;
d66c7132 2677 }
d66c7132 2678 tcg_temp_free(t0);
d66c7132
AJ
2679}
2680
0b16dcd1
AR
2681static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
2682 uint32_t reg1, uint32_t reg2)
2683{
2684 TCGv taddr = tcg_temp_new();
2685 TCGv_i64 tval = tcg_temp_new_i64();
2686 TCGv tmp1 = tcg_temp_new();
2687 TCGv tmp2 = tcg_temp_new();
2688
2689 gen_base_offset_addr(ctx, taddr, base, offset);
2690 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
2691#ifdef TARGET_WORDS_BIGENDIAN
2692 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
2693#else
2694 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
2695#endif
2696 gen_store_gpr(tmp1, reg1);
2697 tcg_temp_free(tmp1);
2698 gen_store_gpr(tmp2, reg2);
2699 tcg_temp_free(tmp2);
2700 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2701 tcg_temp_free_i64(tval);
2702 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
2703 tcg_temp_free(taddr);
2704}
2705
5c13fdfd
AJ
2706/* Store */
2707static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
72e1f16f 2708 int base, int offset)
5c13fdfd 2709{
5c13fdfd
AJ
2710 TCGv t0 = tcg_temp_new();
2711 TCGv t1 = tcg_temp_new();
dd4096cd 2712 int mem_idx = ctx->mem_idx;
5c13fdfd
AJ
2713
2714 gen_base_offset_addr(ctx, t0, base, offset);
2715 gen_load_gpr(t1, rt);
2716 switch (opc) {
2717#if defined(TARGET_MIPS64)
2718 case OPC_SD:
dd4096cd 2719 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
be3a8c53 2720 ctx->default_tcg_memop_mask);
5c13fdfd
AJ
2721 break;
2722 case OPC_SDL:
dd4096cd 2723 gen_helper_0e2i(sdl, t1, t0, mem_idx);
5c13fdfd
AJ
2724 break;
2725 case OPC_SDR:
dd4096cd 2726 gen_helper_0e2i(sdr, t1, t0, mem_idx);
5c13fdfd
AJ
2727 break;
2728#endif
76964147
JH
2729 case OPC_SWE:
2730 mem_idx = MIPS_HFLAG_UM;
2731 /* fall through */
5c13fdfd 2732 case OPC_SW:
dd4096cd 2733 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
be3a8c53 2734 ctx->default_tcg_memop_mask);
5c13fdfd 2735 break;
76964147
JH
2736 case OPC_SHE:
2737 mem_idx = MIPS_HFLAG_UM;
2738 /* fall through */
5c13fdfd 2739 case OPC_SH:
dd4096cd 2740 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
be3a8c53 2741 ctx->default_tcg_memop_mask);
5c13fdfd 2742 break;
76964147
JH
2743 case OPC_SBE:
2744 mem_idx = MIPS_HFLAG_UM;
2745 /* fall through */
5c13fdfd 2746 case OPC_SB:
dd4096cd 2747 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
5c13fdfd 2748 break;
76964147
JH
2749 case OPC_SWLE:
2750 mem_idx = MIPS_HFLAG_UM;
2751 /* fall through */
5c13fdfd 2752 case OPC_SWL:
dd4096cd 2753 gen_helper_0e2i(swl, t1, t0, mem_idx);
5c13fdfd 2754 break;
76964147
JH
2755 case OPC_SWRE:
2756 mem_idx = MIPS_HFLAG_UM;
2757 /* fall through */
5c13fdfd 2758 case OPC_SWR:
dd4096cd 2759 gen_helper_0e2i(swr, t1, t0, mem_idx);
5c13fdfd
AJ
2760 break;
2761 }
5c13fdfd
AJ
2762 tcg_temp_free(t0);
2763 tcg_temp_free(t1);
2764}
2765
2766
d66c7132
AJ
2767/* Store conditional */
2768static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2769 int base, int16_t offset)
2770{
d66c7132 2771 TCGv t0, t1;
dd4096cd 2772 int mem_idx = ctx->mem_idx;
d66c7132 2773
2d2826b9 2774#ifdef CONFIG_USER_ONLY
d66c7132 2775 t0 = tcg_temp_local_new();
d66c7132 2776 t1 = tcg_temp_local_new();
2d2826b9
AJ
2777#else
2778 t0 = tcg_temp_new();
2779 t1 = tcg_temp_new();
2780#endif
2781 gen_base_offset_addr(ctx, t0, base, offset);
d66c7132
AJ
2782 gen_load_gpr(t1, rt);
2783 switch (opc) {
2784#if defined(TARGET_MIPS64)
2785 case OPC_SCD:
bf7910c6 2786 case R6_OPC_SCD:
dd4096cd 2787 op_st_scd(t1, t0, rt, mem_idx, ctx);
d66c7132
AJ
2788 break;
2789#endif
76964147
JH
2790 case OPC_SCE:
2791 mem_idx = MIPS_HFLAG_UM;
2792 /* fall through */
6af0bf9c 2793 case OPC_SC:
4368b29a 2794 case R6_OPC_SC:
dd4096cd 2795 op_st_sc(t1, t0, rt, mem_idx, ctx);
6af0bf9c 2796 break;
6af0bf9c 2797 }
78723684 2798 tcg_temp_free(t1);
d66c7132 2799 tcg_temp_free(t0);
6af0bf9c
FB
2800}
2801
0b16dcd1
AR
2802static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
2803 uint32_t reg1, uint32_t reg2)
2804{
2805 TCGv taddr = tcg_temp_local_new();
2806 TCGv lladdr = tcg_temp_local_new();
2807 TCGv_i64 tval = tcg_temp_new_i64();
2808 TCGv_i64 llval = tcg_temp_new_i64();
2809 TCGv_i64 val = tcg_temp_new_i64();
2810 TCGv tmp1 = tcg_temp_new();
2811 TCGv tmp2 = tcg_temp_new();
2812 TCGLabel *lab_fail = gen_new_label();
2813 TCGLabel *lab_done = gen_new_label();
2814
2815 gen_base_offset_addr(ctx, taddr, base, offset);
2816
2817 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2818 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
2819
2820 gen_load_gpr(tmp1, reg1);
2821 gen_load_gpr(tmp2, reg2);
2822
2823#ifdef TARGET_WORDS_BIGENDIAN
2824 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
2825#else
2826 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
2827#endif
2828
2829 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2830 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
2831 ctx->mem_idx, MO_64);
2832 if (reg1 != 0) {
2833 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
2834 }
2835 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
2836
2837 gen_set_label(lab_fail);
2838
2839 if (reg1 != 0) {
2840 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
2841 }
2842 gen_set_label(lab_done);
2843 tcg_gen_movi_tl(lladdr, -1);
2844 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2845}
2846
6ea83fed 2847/* Load and store */
7a387fff 2848static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
b52d3bfa 2849 TCGv t0)
6ea83fed 2850{
6ea83fed 2851 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 2852 memory access. */
6ea83fed
FB
2853 switch (opc) {
2854 case OPC_LWC1:
b6d96bed 2855 {
a7812ae4 2856 TCGv_i32 fp0 = tcg_temp_new_i32();
be3a8c53
YK
2857 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2858 ctx->default_tcg_memop_mask);
7c979afd 2859 gen_store_fpr32(ctx, fp0, ft);
a7812ae4 2860 tcg_temp_free_i32(fp0);
b6d96bed 2861 }
6ea83fed
FB
2862 break;
2863 case OPC_SWC1:
b6d96bed 2864 {
a7812ae4 2865 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 2866 gen_load_fpr32(ctx, fp0, ft);
be3a8c53
YK
2867 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2868 ctx->default_tcg_memop_mask);
a7812ae4 2869 tcg_temp_free_i32(fp0);
b6d96bed 2870 }
6ea83fed
FB
2871 break;
2872 case OPC_LDC1:
b6d96bed 2873 {
a7812ae4 2874 TCGv_i64 fp0 = tcg_temp_new_i64();
be3a8c53
YK
2875 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2876 ctx->default_tcg_memop_mask);
b6d96bed 2877 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 2878 tcg_temp_free_i64(fp0);
b6d96bed 2879 }
6ea83fed
FB
2880 break;
2881 case OPC_SDC1:
b6d96bed 2882 {
a7812ae4 2883 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 2884 gen_load_fpr64(ctx, fp0, ft);
be3a8c53
YK
2885 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2886 ctx->default_tcg_memop_mask);
a7812ae4 2887 tcg_temp_free_i64(fp0);
b6d96bed 2888 }
6ea83fed
FB
2889 break;
2890 default:
9d68ac14 2891 MIPS_INVAL("flt_ldst");
9c708c7f 2892 generate_exception_end(ctx, EXCP_RI);
b52d3bfa 2893 break;
6ea83fed 2894 }
6ea83fed 2895}
6ea83fed 2896
5ab5c041
AJ
2897static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2898 int rs, int16_t imm)
26ebe468 2899{
b52d3bfa
YK
2900 TCGv t0 = tcg_temp_new();
2901
5ab5c041 2902 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26ebe468 2903 check_cp1_enabled(ctx);
d9224450
MR
2904 switch (op) {
2905 case OPC_LDC1:
2906 case OPC_SDC1:
2907 check_insn(ctx, ISA_MIPS2);
2908 /* Fallthrough */
2909 default:
b52d3bfa
YK
2910 gen_base_offset_addr(ctx, t0, rs, imm);
2911 gen_flt_ldst(ctx, op, rt, t0);
d9224450 2912 }
26ebe468
NF
2913 } else {
2914 generate_exception_err(ctx, EXCP_CpU, 1);
2915 }
b52d3bfa 2916 tcg_temp_free(t0);
26ebe468
NF
2917}
2918
6af0bf9c 2919/* Arithmetic with immediate operand */
d75c135e 2920static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
72e1f16f 2921 int rt, int rs, int imm)
6af0bf9c 2922{
324d9e32 2923 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
6af0bf9c 2924
7a387fff 2925 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
ead9360e
TS
2926 /* If no destination, treat it as a NOP.
2927 For addi, we must generate the overflow exception when needed. */
324d9e32 2928 return;
6af0bf9c
FB
2929 }
2930 switch (opc) {
2931 case OPC_ADDI:
48d38ca5 2932 {
324d9e32
AJ
2933 TCGv t0 = tcg_temp_local_new();
2934 TCGv t1 = tcg_temp_new();
2935 TCGv t2 = tcg_temp_new();
42a268c2 2936 TCGLabel *l1 = gen_new_label();
48d38ca5 2937
324d9e32
AJ
2938 gen_load_gpr(t1, rs);
2939 tcg_gen_addi_tl(t0, t1, uimm);
2940 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 2941
324d9e32
AJ
2942 tcg_gen_xori_tl(t1, t1, ~uimm);
2943 tcg_gen_xori_tl(t2, t0, uimm);
2944 tcg_gen_and_tl(t1, t1, t2);
2945 tcg_temp_free(t2);
2946 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2947 tcg_temp_free(t1);
48d38ca5
TS
2948 /* operands of same sign, result different sign */
2949 generate_exception(ctx, EXCP_OVERFLOW);
2950 gen_set_label(l1);
78723684 2951 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
2952 gen_store_gpr(t0, rt);
2953 tcg_temp_free(t0);
48d38ca5 2954 }
6af0bf9c
FB
2955 break;
2956 case OPC_ADDIU:
324d9e32
AJ
2957 if (rs != 0) {
2958 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2959 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2960 } else {
2961 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2962 }
6af0bf9c 2963 break;
d26bc211 2964#if defined(TARGET_MIPS64)
7a387fff 2965 case OPC_DADDI:
48d38ca5 2966 {
324d9e32
AJ
2967 TCGv t0 = tcg_temp_local_new();
2968 TCGv t1 = tcg_temp_new();
2969 TCGv t2 = tcg_temp_new();
42a268c2 2970 TCGLabel *l1 = gen_new_label();
48d38ca5 2971
324d9e32
AJ
2972 gen_load_gpr(t1, rs);
2973 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 2974
324d9e32
AJ
2975 tcg_gen_xori_tl(t1, t1, ~uimm);
2976 tcg_gen_xori_tl(t2, t0, uimm);
2977 tcg_gen_and_tl(t1, t1, t2);
2978 tcg_temp_free(t2);
2979 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2980 tcg_temp_free(t1);
48d38ca5
TS
2981 /* operands of same sign, result different sign */
2982 generate_exception(ctx, EXCP_OVERFLOW);
2983 gen_set_label(l1);
324d9e32
AJ
2984 gen_store_gpr(t0, rt);
2985 tcg_temp_free(t0);
48d38ca5 2986 }
7a387fff
TS
2987 break;
2988 case OPC_DADDIU:
324d9e32
AJ
2989 if (rs != 0) {
2990 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2991 } else {
2992 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2993 }
7a387fff
TS
2994 break;
2995#endif
324d9e32 2996 }
324d9e32
AJ
2997}
2998
2999/* Logic with immediate operand */
d75c135e 3000static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3001 int rt, int rs, int16_t imm)
324d9e32
AJ
3002{
3003 target_ulong uimm;
324d9e32
AJ
3004
3005 if (rt == 0) {
3006 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3007 return;
3008 }
3009 uimm = (uint16_t)imm;
3010 switch (opc) {
6af0bf9c 3011 case OPC_ANDI:
324d9e32
AJ
3012 if (likely(rs != 0))
3013 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3014 else
3015 tcg_gen_movi_tl(cpu_gpr[rt], 0);
6af0bf9c
FB
3016 break;
3017 case OPC_ORI:
324d9e32
AJ
3018 if (rs != 0)
3019 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3020 else
3021 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
3022 break;
3023 case OPC_XORI:
324d9e32
AJ
3024 if (likely(rs != 0))
3025 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3026 else
3027 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
3028 break;
3029 case OPC_LUI:
d4ea6acd
LA
3030 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3031 /* OPC_AUI */
3032 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3033 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
d4ea6acd
LA
3034 } else {
3035 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
d4ea6acd 3036 }
7c2c3ea3
EJ
3037 break;
3038
3039 default:
6af0bf9c 3040 break;
324d9e32 3041 }
324d9e32
AJ
3042}
3043
3044/* Set on less than with immediate operand */
d75c135e 3045static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
9fa77488 3046 int rt, int rs, int16_t imm)
324d9e32
AJ
3047{
3048 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
324d9e32
AJ
3049 TCGv t0;
3050
3051 if (rt == 0) {
3052 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3053 return;
3054 }
3055 t0 = tcg_temp_new();
3056 gen_load_gpr(t0, rs);
3057 switch (opc) {
3058 case OPC_SLTI:
e68dd28f 3059 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
3060 break;
3061 case OPC_SLTIU:
e68dd28f 3062 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
3063 break;
3064 }
324d9e32
AJ
3065 tcg_temp_free(t0);
3066}
3067
3068/* Shifts with immediate operand */
d75c135e 3069static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
324d9e32
AJ
3070 int rt, int rs, int16_t imm)
3071{
3072 target_ulong uimm = ((uint16_t)imm) & 0x1f;
324d9e32
AJ
3073 TCGv t0;
3074
3075 if (rt == 0) {
3076 /* If no destination, treat it as a NOP. */
324d9e32
AJ
3077 return;
3078 }
3079
3080 t0 = tcg_temp_new();
3081 gen_load_gpr(t0, rs);
3082 switch (opc) {
6af0bf9c 3083 case OPC_SLL:
78723684 3084 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 3085 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
3086 break;
3087 case OPC_SRA:
324d9e32 3088 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
3089 break;
3090 case OPC_SRL:
ea63e2c3
NF
3091 if (uimm != 0) {
3092 tcg_gen_ext32u_tl(t0, t0);
3093 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3094 } else {
3095 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 3096 }
ea63e2c3
NF
3097 break;
3098 case OPC_ROTR:
3099 if (uimm != 0) {
3100 TCGv_i32 t1 = tcg_temp_new_i32();
3101
3102 tcg_gen_trunc_tl_i32(t1, t0);
3103 tcg_gen_rotri_i32(t1, t1, uimm);
3104 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3105 tcg_temp_free_i32(t1);
3399e30f
NF
3106 } else {
3107 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3 3108 }
7a387fff 3109 break;
d26bc211 3110#if defined(TARGET_MIPS64)
7a387fff 3111 case OPC_DSLL:
324d9e32 3112 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
3113 break;
3114 case OPC_DSRA:
324d9e32 3115 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
3116 break;
3117 case OPC_DSRL:
ea63e2c3 3118 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
ea63e2c3
NF
3119 break;
3120 case OPC_DROTR:
3121 if (uimm != 0) {
3122 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
3123 } else {
3124 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 3125 }
7a387fff
TS
3126 break;
3127 case OPC_DSLL32:
324d9e32 3128 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
3129 break;
3130 case OPC_DSRA32:
324d9e32 3131 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
3132 break;
3133 case OPC_DSRL32:
ea63e2c3 3134 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
ea63e2c3
NF
3135 break;
3136 case OPC_DROTR32:
3137 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
6af0bf9c 3138 break;
7a387fff 3139#endif
6af0bf9c 3140 }
78723684 3141 tcg_temp_free(t0);
6af0bf9c
FB
3142}
3143
3144/* Arithmetic */
d75c135e
AJ
3145static void gen_arith(DisasContext *ctx, uint32_t opc,
3146 int rd, int rs, int rt)
6af0bf9c 3147{
7a387fff
TS
3148 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3149 && opc != OPC_DADD && opc != OPC_DSUB) {
ead9360e
TS
3150 /* If no destination, treat it as a NOP.
3151 For add & sub, we must generate the overflow exception when needed. */
460f00c4 3152 return;
185f0762 3153 }
460f00c4 3154
6af0bf9c
FB
3155 switch (opc) {
3156 case OPC_ADD:
48d38ca5 3157 {
460f00c4
AJ
3158 TCGv t0 = tcg_temp_local_new();
3159 TCGv t1 = tcg_temp_new();
3160 TCGv t2 = tcg_temp_new();
42a268c2 3161 TCGLabel *l1 = gen_new_label();
48d38ca5 3162
460f00c4
AJ
3163 gen_load_gpr(t1, rs);
3164 gen_load_gpr(t2, rt);
3165 tcg_gen_add_tl(t0, t1, t2);
3166 tcg_gen_ext32s_tl(t0, t0);
3167 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 3168 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 3169 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
3170 tcg_temp_free(t2);
3171 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3172 tcg_temp_free(t1);
48d38ca5
TS
3173 /* operands of same sign, result different sign */
3174 generate_exception(ctx, EXCP_OVERFLOW);
3175 gen_set_label(l1);
460f00c4
AJ
3176 gen_store_gpr(t0, rd);
3177 tcg_temp_free(t0);
48d38ca5 3178 }
6af0bf9c
FB
3179 break;
3180 case OPC_ADDU:
460f00c4
AJ
3181 if (rs != 0 && rt != 0) {
3182 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3183 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3184 } else if (rs == 0 && rt != 0) {
3185 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3186 } else if (rs != 0 && rt == 0) {
3187 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3188 } else {
3189 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3190 }
6af0bf9c
FB
3191 break;
3192 case OPC_SUB:
48d38ca5 3193 {
460f00c4
AJ
3194 TCGv t0 = tcg_temp_local_new();
3195 TCGv t1 = tcg_temp_new();
3196 TCGv t2 = tcg_temp_new();
42a268c2 3197 TCGLabel *l1 = gen_new_label();
48d38ca5 3198
460f00c4
AJ
3199 gen_load_gpr(t1, rs);
3200 gen_load_gpr(t2, rt);
3201 tcg_gen_sub_tl(t0, t1, t2);
3202 tcg_gen_ext32s_tl(t0, t0);
3203 tcg_gen_xor_tl(t2, t1, t2);
3204 tcg_gen_xor_tl(t1, t0, t1);
3205 tcg_gen_and_tl(t1, t1, t2);
3206 tcg_temp_free(t2);
3207 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3208 tcg_temp_free(t1);
31e3104f 3209 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
3210 generate_exception(ctx, EXCP_OVERFLOW);
3211 gen_set_label(l1);
460f00c4
AJ
3212 gen_store_gpr(t0, rd);
3213 tcg_temp_free(t0);
48d38ca5 3214 }
6af0bf9c
FB
3215 break;
3216 case OPC_SUBU:
460f00c4
AJ
3217 if (rs != 0 && rt != 0) {
3218 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3219 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3220 } else if (rs == 0 && rt != 0) {
3221 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 3222 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
3223 } else if (rs != 0 && rt == 0) {
3224 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3225 } else {
3226 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3227 }
6af0bf9c 3228 break;
d26bc211 3229#if defined(TARGET_MIPS64)
7a387fff 3230 case OPC_DADD:
48d38ca5 3231 {
460f00c4
AJ
3232 TCGv t0 = tcg_temp_local_new();
3233 TCGv t1 = tcg_temp_new();
3234 TCGv t2 = tcg_temp_new();
42a268c2 3235 TCGLabel *l1 = gen_new_label();
48d38ca5 3236
460f00c4
AJ
3237 gen_load_gpr(t1, rs);
3238 gen_load_gpr(t2, rt);
3239 tcg_gen_add_tl(t0, t1, t2);
3240 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 3241 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 3242 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
3243 tcg_temp_free(t2);
3244 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3245 tcg_temp_free(t1);
48d38ca5
TS
3246 /* operands of same sign, result different sign */
3247 generate_exception(ctx, EXCP_OVERFLOW);
3248 gen_set_label(l1);
460f00c4
AJ
3249 gen_store_gpr(t0, rd);
3250 tcg_temp_free(t0);
48d38ca5 3251 }
7a387fff
TS
3252 break;
3253 case OPC_DADDU:
460f00c4
AJ
3254 if (rs != 0 && rt != 0) {
3255 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3256 } else if (rs == 0 && rt != 0) {
3257 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3258 } else if (rs != 0 && rt == 0) {
3259 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3260 } else {
3261 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3262 }
7a387fff
TS
3263 break;
3264 case OPC_DSUB:
48d38ca5 3265 {
460f00c4
AJ
3266 TCGv t0 = tcg_temp_local_new();
3267 TCGv t1 = tcg_temp_new();
3268 TCGv t2 = tcg_temp_new();
42a268c2 3269 TCGLabel *l1 = gen_new_label();
48d38ca5 3270
460f00c4
AJ
3271 gen_load_gpr(t1, rs);
3272 gen_load_gpr(t2, rt);
3273 tcg_gen_sub_tl(t0, t1, t2);
3274 tcg_gen_xor_tl(t2, t1, t2);
3275 tcg_gen_xor_tl(t1, t0, t1);
3276 tcg_gen_and_tl(t1, t1, t2);
3277 tcg_temp_free(t2);
3278 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3279 tcg_temp_free(t1);
31e3104f 3280 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
3281 generate_exception(ctx, EXCP_OVERFLOW);
3282 gen_set_label(l1);
460f00c4
AJ
3283 gen_store_gpr(t0, rd);
3284 tcg_temp_free(t0);
48d38ca5 3285 }
7a387fff
TS
3286 break;
3287 case OPC_DSUBU:
460f00c4
AJ
3288 if (rs != 0 && rt != 0) {
3289 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3290 } else if (rs == 0 && rt != 0) {
3291 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3292 } else if (rs != 0 && rt == 0) {
3293 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3294 } else {
3295 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3296 }
7a387fff
TS
3297 break;
3298#endif
460f00c4
AJ
3299 case OPC_MUL:
3300 if (likely(rs != 0 && rt != 0)) {
3301 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3302 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3303 } else {
3304 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3305 }
6af0bf9c 3306 break;
460f00c4 3307 }
460f00c4
AJ
3308}
3309
3310/* Conditional move */
d75c135e 3311static void gen_cond_move(DisasContext *ctx, uint32_t opc,
9fa77488 3312 int rd, int rs, int rt)
460f00c4 3313{
acf12465 3314 TCGv t0, t1, t2;
460f00c4
AJ
3315
3316 if (rd == 0) {
acf12465 3317 /* If no destination, treat it as a NOP. */
460f00c4
AJ
3318 return;
3319 }
3320
acf12465
AJ
3321 t0 = tcg_temp_new();
3322 gen_load_gpr(t0, rt);
3323 t1 = tcg_const_tl(0);
3324 t2 = tcg_temp_new();
3325 gen_load_gpr(t2, rs);
460f00c4
AJ
3326 switch (opc) {
3327 case OPC_MOVN:
acf12465 3328 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
6af0bf9c 3329 break;
460f00c4 3330 case OPC_MOVZ:
acf12465 3331 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
460f00c4 3332 break;
b691d9d2
LA
3333 case OPC_SELNEZ:
3334 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2
LA
3335 break;
3336 case OPC_SELEQZ:
3337 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2 3338 break;
460f00c4 3339 }
acf12465
AJ
3340 tcg_temp_free(t2);
3341 tcg_temp_free(t1);
3342 tcg_temp_free(t0);
460f00c4
AJ
3343}
3344
3345/* Logic */
d75c135e 3346static void gen_logic(DisasContext *ctx, uint32_t opc,
9fa77488 3347 int rd, int rs, int rt)
460f00c4 3348{
460f00c4
AJ
3349 if (rd == 0) {
3350 /* If no destination, treat it as a NOP. */
460f00c4
AJ
3351 return;
3352 }
3353
3354 switch (opc) {
6af0bf9c 3355 case OPC_AND:
460f00c4
AJ
3356 if (likely(rs != 0 && rt != 0)) {
3357 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3358 } else {
3359 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3360 }
6af0bf9c
FB
3361 break;
3362 case OPC_NOR:
460f00c4
AJ
3363 if (rs != 0 && rt != 0) {
3364 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3365 } else if (rs == 0 && rt != 0) {
3366 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
3367 } else if (rs != 0 && rt == 0) {
3368 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
3369 } else {
3370 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
3371 }
6af0bf9c
FB
3372 break;
3373 case OPC_OR:
460f00c4
AJ
3374 if (likely(rs != 0 && rt != 0)) {
3375 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3376 } else if (rs == 0 && rt != 0) {
3377 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3378 } else if (rs != 0 && rt == 0) {
3379 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3380 } else {
3381 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3382 }
6af0bf9c
FB
3383 break;
3384 case OPC_XOR:
460f00c4
AJ
3385 if (likely(rs != 0 && rt != 0)) {
3386 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3387 } else if (rs == 0 && rt != 0) {
3388 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3389 } else if (rs != 0 && rt == 0) {
3390 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3391 } else {
3392 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3393 }
6af0bf9c 3394 break;
460f00c4 3395 }
460f00c4
AJ
3396}
3397
3398/* Set on lower than */
d75c135e 3399static void gen_slt(DisasContext *ctx, uint32_t opc,
9fa77488 3400 int rd, int rs, int rt)
460f00c4 3401{
460f00c4
AJ
3402 TCGv t0, t1;
3403
3404 if (rd == 0) {
3405 /* If no destination, treat it as a NOP. */
460f00c4
AJ
3406 return;
3407 }
3408
3409 t0 = tcg_temp_new();
3410 t1 = tcg_temp_new();
3411 gen_load_gpr(t0, rs);
3412 gen_load_gpr(t1, rt);
3413 switch (opc) {
3414 case OPC_SLT:
e68dd28f 3415 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
6af0bf9c 3416 break;
460f00c4 3417 case OPC_SLTU:
e68dd28f 3418 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
3419 break;
3420 }
460f00c4
AJ
3421 tcg_temp_free(t0);
3422 tcg_temp_free(t1);
3423}
20c4c97c 3424
460f00c4 3425/* Shifts */
d75c135e
AJ
3426static void gen_shift(DisasContext *ctx, uint32_t opc,
3427 int rd, int rs, int rt)
460f00c4 3428{
460f00c4 3429 TCGv t0, t1;
20c4c97c 3430
460f00c4
AJ
3431 if (rd == 0) {
3432 /* If no destination, treat it as a NOP.
3433 For add & sub, we must generate the overflow exception when needed. */
460f00c4
AJ
3434 return;
3435 }
3436
3437 t0 = tcg_temp_new();
3438 t1 = tcg_temp_new();
3439 gen_load_gpr(t0, rs);
3440 gen_load_gpr(t1, rt);
3441 switch (opc) {
6af0bf9c 3442 case OPC_SLLV:
78723684
TS
3443 tcg_gen_andi_tl(t0, t0, 0x1f);
3444 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 3445 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
3446 break;
3447 case OPC_SRAV:
78723684 3448 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 3449 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
3450 break;
3451 case OPC_SRLV:
ea63e2c3
NF
3452 tcg_gen_ext32u_tl(t1, t1);
3453 tcg_gen_andi_tl(t0, t0, 0x1f);
3454 tcg_gen_shr_tl(t0, t1, t0);
3455 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
ea63e2c3
NF
3456 break;
3457 case OPC_ROTRV:
3458 {
3459 TCGv_i32 t2 = tcg_temp_new_i32();
3460 TCGv_i32 t3 = tcg_temp_new_i32();
3461
3462 tcg_gen_trunc_tl_i32(t2, t0);
3463 tcg_gen_trunc_tl_i32(t3, t1);
3464 tcg_gen_andi_i32(t2, t2, 0x1f);
3465 tcg_gen_rotr_i32(t2, t3, t2);
3466 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3467 tcg_temp_free_i32(t2);
3468 tcg_temp_free_i32(t3);
5a63bcb2 3469 }
7a387fff 3470 break;
d26bc211 3471#if defined(TARGET_MIPS64)
7a387fff 3472 case OPC_DSLLV:
78723684 3473 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 3474 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
3475 break;
3476 case OPC_DSRAV:
78723684 3477 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 3478 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
3479 break;
3480 case OPC_DSRLV:
ea63e2c3
NF
3481 tcg_gen_andi_tl(t0, t0, 0x3f);
3482 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
ea63e2c3
NF
3483 break;
3484 case OPC_DROTRV:
3485 tcg_gen_andi_tl(t0, t0, 0x3f);
3486 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
6af0bf9c 3487 break;
7a387fff 3488#endif
6af0bf9c 3489 }
78723684
TS
3490 tcg_temp_free(t0);
3491 tcg_temp_free(t1);
6af0bf9c
FB
3492}
3493
3494/* Arithmetic on HI/LO registers */
26135ead 3495static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
6af0bf9c 3496{
6af0bf9c 3497 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 3498 /* Treat as NOP. */
a1f6684d 3499 return;
6af0bf9c 3500 }
4133498f 3501
4133498f
JL
3502 if (acc != 0) {
3503 check_dsp(ctx);
3504 }
3505
6af0bf9c
FB
3506 switch (opc) {
3507 case OPC_MFHI:
4133498f
JL
3508#if defined(TARGET_MIPS64)
3509 if (acc != 0) {
3510 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3511 } else
3512#endif
3513 {
3514 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3515 }
6af0bf9c
FB
3516 break;
3517 case OPC_MFLO:
4133498f
JL
3518#if defined(TARGET_MIPS64)
3519 if (acc != 0) {
3520 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3521 } else
3522#endif
3523 {
3524 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3525 }
6af0bf9c
FB
3526 break;
3527 case OPC_MTHI:
4133498f
JL
3528 if (reg != 0) {
3529#if defined(TARGET_MIPS64)
3530 if (acc != 0) {
3531 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3532 } else
3533#endif
3534 {
3535 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3536 }
3537 } else {
3538 tcg_gen_movi_tl(cpu_HI[acc], 0);
3539 }
6af0bf9c
FB
3540 break;
3541 case OPC_MTLO:
4133498f
JL
3542 if (reg != 0) {
3543#if defined(TARGET_MIPS64)
3544 if (acc != 0) {
3545 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3546 } else
3547#endif
3548 {
3549 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3550 }
3551 } else {
3552 tcg_gen_movi_tl(cpu_LO[acc], 0);
3553 }
6af0bf9c 3554 break;
6af0bf9c 3555 }
6af0bf9c
FB
3556}
3557
d4ea6acd
LA
3558static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3559 TCGMemOp memop)
3560{
3561 TCGv t0 = tcg_const_tl(addr);
3562 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3563 gen_store_gpr(t0, reg);
3564 tcg_temp_free(t0);
3565}
3566
ab39ee45
YK
3567static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3568 int rs)
d4ea6acd
LA
3569{
3570 target_long offset;
3571 target_long addr;
3572
ab39ee45 3573 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
d4ea6acd
LA
3574 case OPC_ADDIUPC:
3575 if (rs != 0) {
3576 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 3577 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3578 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3579 }
3580 break;
3581 case R6_OPC_LWPC:
3582 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 3583 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3584 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3585 break;
3586#if defined(TARGET_MIPS64)
3587 case OPC_LWUPC:
3588 check_mips_64(ctx);
3589 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 3590 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3591 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3592 break;
3593#endif
3594 default:
ab39ee45 3595 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
d4ea6acd
LA
3596 case OPC_AUIPC:
3597 if (rs != 0) {
ab39ee45
YK
3598 offset = sextract32(ctx->opcode, 0, 16) << 16;
3599 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3600 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3601 }
3602 break;
3603 case OPC_ALUIPC:
3604 if (rs != 0) {
ab39ee45
YK
3605 offset = sextract32(ctx->opcode, 0, 16) << 16;
3606 addr = ~0xFFFF & addr_add(ctx, pc, offset);
d4ea6acd
LA
3607 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3608 }
3609 break;
3610#if defined(TARGET_MIPS64)
3611 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3612 case R6_OPC_LDPC + (1 << 16):
3613 case R6_OPC_LDPC + (2 << 16):
3614 case R6_OPC_LDPC + (3 << 16):
3615 check_mips_64(ctx);
3616 offset = sextract32(ctx->opcode << 3, 0, 21);
ab39ee45 3617 addr = addr_add(ctx, (pc & ~0x7), offset);
d4ea6acd
LA
3618 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3619 break;
3620#endif
3621 default:
3622 MIPS_INVAL("OPC_PCREL");
9c708c7f 3623 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
3624 break;
3625 }
3626 break;
3627 }
3628}
3629
b42ee5e1
LA
3630static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3631{
b42ee5e1
LA
3632 TCGv t0, t1;
3633
3634 if (rd == 0) {
3635 /* Treat as NOP. */
b42ee5e1
LA
3636 return;
3637 }
3638
3639 t0 = tcg_temp_new();
3640 t1 = tcg_temp_new();
3641
3642 gen_load_gpr(t0, rs);
3643 gen_load_gpr(t1, rt);
3644
3645 switch (opc) {
3646 case R6_OPC_DIV:
3647 {
3648 TCGv t2 = tcg_temp_new();
3649 TCGv t3 = tcg_temp_new();
3650 tcg_gen_ext32s_tl(t0, t0);
3651 tcg_gen_ext32s_tl(t1, t1);
3652 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3653 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3654 tcg_gen_and_tl(t2, t2, t3);
3655 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3656 tcg_gen_or_tl(t2, t2, t3);
3657 tcg_gen_movi_tl(t3, 0);
3658 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3659 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3660 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3661 tcg_temp_free(t3);
3662 tcg_temp_free(t2);
3663 }
b42ee5e1
LA
3664 break;
3665 case R6_OPC_MOD:
3666 {
3667 TCGv t2 = tcg_temp_new();
3668 TCGv t3 = tcg_temp_new();
3669 tcg_gen_ext32s_tl(t0, t0);
3670 tcg_gen_ext32s_tl(t1, t1);
3671 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3672 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3673 tcg_gen_and_tl(t2, t2, t3);
3674 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3675 tcg_gen_or_tl(t2, t2, t3);
3676 tcg_gen_movi_tl(t3, 0);
3677 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3678 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3679 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3680 tcg_temp_free(t3);
3681 tcg_temp_free(t2);
3682 }
b42ee5e1
LA
3683 break;
3684 case R6_OPC_DIVU:
3685 {
3686 TCGv t2 = tcg_const_tl(0);
3687 TCGv t3 = tcg_const_tl(1);
3688 tcg_gen_ext32u_tl(t0, t0);
3689 tcg_gen_ext32u_tl(t1, t1);
3690 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3691 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3692 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3693 tcg_temp_free(t3);
3694 tcg_temp_free(t2);
3695 }
b42ee5e1
LA
3696 break;
3697 case R6_OPC_MODU:
3698 {
3699 TCGv t2 = tcg_const_tl(0);
3700 TCGv t3 = tcg_const_tl(1);
3701 tcg_gen_ext32u_tl(t0, t0);
3702 tcg_gen_ext32u_tl(t1, t1);
3703 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3704 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3705 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3706 tcg_temp_free(t3);
3707 tcg_temp_free(t2);
3708 }
b42ee5e1
LA
3709 break;
3710 case R6_OPC_MUL:
3711 {
3712 TCGv_i32 t2 = tcg_temp_new_i32();
3713 TCGv_i32 t3 = tcg_temp_new_i32();
3714 tcg_gen_trunc_tl_i32(t2, t0);
3715 tcg_gen_trunc_tl_i32(t3, t1);
3716 tcg_gen_mul_i32(t2, t2, t3);
3717 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3718 tcg_temp_free_i32(t2);
3719 tcg_temp_free_i32(t3);
3720 }
b42ee5e1
LA
3721 break;
3722 case R6_OPC_MUH:
3723 {
3724 TCGv_i32 t2 = tcg_temp_new_i32();
3725 TCGv_i32 t3 = tcg_temp_new_i32();
3726 tcg_gen_trunc_tl_i32(t2, t0);
3727 tcg_gen_trunc_tl_i32(t3, t1);
3728 tcg_gen_muls2_i32(t2, t3, t2, t3);
3729 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3730 tcg_temp_free_i32(t2);
3731 tcg_temp_free_i32(t3);
3732 }
b42ee5e1
LA
3733 break;
3734 case R6_OPC_MULU:
3735 {
3736 TCGv_i32 t2 = tcg_temp_new_i32();
3737 TCGv_i32 t3 = tcg_temp_new_i32();
3738 tcg_gen_trunc_tl_i32(t2, t0);
3739 tcg_gen_trunc_tl_i32(t3, t1);
3740 tcg_gen_mul_i32(t2, t2, t3);
3741 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3742 tcg_temp_free_i32(t2);
3743 tcg_temp_free_i32(t3);
3744 }
b42ee5e1
LA
3745 break;
3746 case R6_OPC_MUHU:
3747 {
3748 TCGv_i32 t2 = tcg_temp_new_i32();
3749 TCGv_i32 t3 = tcg_temp_new_i32();
3750 tcg_gen_trunc_tl_i32(t2, t0);
3751 tcg_gen_trunc_tl_i32(t3, t1);
3752 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3753 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3754 tcg_temp_free_i32(t2);
3755 tcg_temp_free_i32(t3);
3756 }
b42ee5e1
LA
3757 break;
3758#if defined(TARGET_MIPS64)
3759 case R6_OPC_DDIV:
3760 {
3761 TCGv t2 = tcg_temp_new();
3762 TCGv t3 = tcg_temp_new();
3763 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3764 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3765 tcg_gen_and_tl(t2, t2, t3);
3766 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3767 tcg_gen_or_tl(t2, t2, t3);
3768 tcg_gen_movi_tl(t3, 0);
3769 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3770 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3771 tcg_temp_free(t3);
3772 tcg_temp_free(t2);
3773 }
b42ee5e1
LA
3774 break;
3775 case R6_OPC_DMOD:
3776 {
3777 TCGv t2 = tcg_temp_new();
3778 TCGv t3 = tcg_temp_new();
3779 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3780 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3781 tcg_gen_and_tl(t2, t2, t3);
3782 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3783 tcg_gen_or_tl(t2, t2, t3);
3784 tcg_gen_movi_tl(t3, 0);
3785 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3786 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3787 tcg_temp_free(t3);
3788 tcg_temp_free(t2);
3789 }
b42ee5e1
LA
3790 break;
3791 case R6_OPC_DDIVU:
3792 {
3793 TCGv t2 = tcg_const_tl(0);
3794 TCGv t3 = tcg_const_tl(1);
3795 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3796 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3797 tcg_temp_free(t3);
3798 tcg_temp_free(t2);
3799 }
b42ee5e1
LA
3800 break;
3801 case R6_OPC_DMODU:
3802 {
3803 TCGv t2 = tcg_const_tl(0);
3804 TCGv t3 = tcg_const_tl(1);
3805 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3806 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3807 tcg_temp_free(t3);
3808 tcg_temp_free(t2);
3809 }
b42ee5e1
LA
3810 break;
3811 case R6_OPC_DMUL:
3812 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
3813 break;
3814 case R6_OPC_DMUH:
3815 {
3816 TCGv t2 = tcg_temp_new();
3817 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3818 tcg_temp_free(t2);
3819 }
b42ee5e1
LA
3820 break;
3821 case R6_OPC_DMULU:
3822 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
3823 break;
3824 case R6_OPC_DMUHU:
3825 {
3826 TCGv t2 = tcg_temp_new();
3827 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3828 tcg_temp_free(t2);
3829 }
b42ee5e1
LA
3830 break;
3831#endif
3832 default:
9d68ac14 3833 MIPS_INVAL("r6 mul/div");
9c708c7f 3834 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
3835 goto out;
3836 }
b42ee5e1
LA
3837 out:
3838 tcg_temp_free(t0);
3839 tcg_temp_free(t1);
3840}
3841
26135ead
RS
3842static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3843 int acc, int rs, int rt)
6af0bf9c 3844{
d45f89f4
AJ
3845 TCGv t0, t1;
3846
51127181
AJ
3847 t0 = tcg_temp_new();
3848 t1 = tcg_temp_new();
6af0bf9c 3849
78723684
TS
3850 gen_load_gpr(t0, rs);
3851 gen_load_gpr(t1, rt);
51127181 3852
26135ead
RS
3853 if (acc != 0) {
3854 check_dsp(ctx);
3855 }
3856
6af0bf9c
FB
3857 switch (opc) {
3858 case OPC_DIV:
48d38ca5 3859 {
51127181
AJ
3860 TCGv t2 = tcg_temp_new();
3861 TCGv t3 = tcg_temp_new();
d45f89f4
AJ
3862 tcg_gen_ext32s_tl(t0, t0);
3863 tcg_gen_ext32s_tl(t1, t1);
51127181
AJ
3864 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3865 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3866 tcg_gen_and_tl(t2, t2, t3);
3867 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3868 tcg_gen_or_tl(t2, t2, t3);
3869 tcg_gen_movi_tl(t3, 0);
3870 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
3871 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3872 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3873 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3874 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
3875 tcg_temp_free(t3);
3876 tcg_temp_free(t2);
48d38ca5 3877 }
6af0bf9c
FB
3878 break;
3879 case OPC_DIVU:
48d38ca5 3880 {
51127181
AJ
3881 TCGv t2 = tcg_const_tl(0);
3882 TCGv t3 = tcg_const_tl(1);
0c0ed03b
AJ
3883 tcg_gen_ext32u_tl(t0, t0);
3884 tcg_gen_ext32u_tl(t1, t1);
51127181 3885 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
3886 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3887 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3888 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3889 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
3890 tcg_temp_free(t3);
3891 tcg_temp_free(t2);
48d38ca5 3892 }
6af0bf9c
FB
3893 break;
3894 case OPC_MULT:
214c465f 3895 {
ce1dd5d1
RH
3896 TCGv_i32 t2 = tcg_temp_new_i32();
3897 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
3898 tcg_gen_trunc_tl_i32(t2, t0);
3899 tcg_gen_trunc_tl_i32(t3, t1);
3900 tcg_gen_muls2_i32(t2, t3, t2, t3);
3901 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3902 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3903 tcg_temp_free_i32(t2);
3904 tcg_temp_free_i32(t3);
214c465f 3905 }
6af0bf9c
FB
3906 break;
3907 case OPC_MULTU:
214c465f 3908 {
ce1dd5d1
RH
3909 TCGv_i32 t2 = tcg_temp_new_i32();
3910 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
3911 tcg_gen_trunc_tl_i32(t2, t0);
3912 tcg_gen_trunc_tl_i32(t3, t1);
3913 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3914 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3915 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3916 tcg_temp_free_i32(t2);
3917 tcg_temp_free_i32(t3);
214c465f 3918 }
6af0bf9c 3919 break;
d26bc211 3920#if defined(TARGET_MIPS64)
7a387fff 3921 case OPC_DDIV:
48d38ca5 3922 {
51127181
AJ
3923 TCGv t2 = tcg_temp_new();
3924 TCGv t3 = tcg_temp_new();
3925 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3926 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3927 tcg_gen_and_tl(t2, t2, t3);
3928 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3929 tcg_gen_or_tl(t2, t2, t3);
3930 tcg_gen_movi_tl(t3, 0);
3931 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
3932 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3933 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
51127181
AJ
3934 tcg_temp_free(t3);
3935 tcg_temp_free(t2);
48d38ca5 3936 }
7a387fff
TS
3937 break;
3938 case OPC_DDIVU:
48d38ca5 3939 {
51127181
AJ
3940 TCGv t2 = tcg_const_tl(0);
3941 TCGv t3 = tcg_const_tl(1);
3942 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
3943 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3944 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
51127181
AJ
3945 tcg_temp_free(t3);
3946 tcg_temp_free(t2);
48d38ca5 3947 }
7a387fff
TS
3948 break;
3949 case OPC_DMULT:
26135ead 3950 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
3951 break;
3952 case OPC_DMULTU:
26135ead 3953 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
3954 break;
3955#endif
6af0bf9c 3956 case OPC_MADD:
214c465f 3957 {
d45f89f4
AJ
3958 TCGv_i64 t2 = tcg_temp_new_i64();
3959 TCGv_i64 t3 = tcg_temp_new_i64();
3960
3961 tcg_gen_ext_tl_i64(t2, t0);
3962 tcg_gen_ext_tl_i64(t3, t1);
3963 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3964 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
3965 tcg_gen_add_i64(t2, t2, t3);
3966 tcg_temp_free_i64(t3);
71f303cd
RH
3967 gen_move_low32(cpu_LO[acc], t2);
3968 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 3969 tcg_temp_free_i64(t2);
214c465f 3970 }
6af0bf9c
FB
3971 break;
3972 case OPC_MADDU:
4133498f 3973 {
d45f89f4
AJ
3974 TCGv_i64 t2 = tcg_temp_new_i64();
3975 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 3976
78723684
TS
3977 tcg_gen_ext32u_tl(t0, t0);
3978 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
3979 tcg_gen_extu_tl_i64(t2, t0);
3980 tcg_gen_extu_tl_i64(t3, t1);
3981 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3982 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
3983 tcg_gen_add_i64(t2, t2, t3);
3984 tcg_temp_free_i64(t3);
71f303cd
RH
3985 gen_move_low32(cpu_LO[acc], t2);
3986 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 3987 tcg_temp_free_i64(t2);
214c465f 3988 }
6af0bf9c
FB
3989 break;
3990 case OPC_MSUB:
214c465f 3991 {
d45f89f4
AJ
3992 TCGv_i64 t2 = tcg_temp_new_i64();
3993 TCGv_i64 t3 = tcg_temp_new_i64();
3994
3995 tcg_gen_ext_tl_i64(t2, t0);
3996 tcg_gen_ext_tl_i64(t3, t1);
3997 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3998 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 3999 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 4000 tcg_temp_free_i64(t3);
71f303cd
RH
4001 gen_move_low32(cpu_LO[acc], t2);
4002 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 4003 tcg_temp_free_i64(t2);
214c465f 4004 }
6af0bf9c
FB
4005 break;
4006 case OPC_MSUBU:
214c465f 4007 {
d45f89f4
AJ
4008 TCGv_i64 t2 = tcg_temp_new_i64();
4009 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 4010
78723684
TS
4011 tcg_gen_ext32u_tl(t0, t0);
4012 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
4013 tcg_gen_extu_tl_i64(t2, t0);
4014 tcg_gen_extu_tl_i64(t3, t1);
4015 tcg_gen_mul_i64(t2, t2, t3);
4133498f 4016 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 4017 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 4018 tcg_temp_free_i64(t3);
71f303cd
RH
4019 gen_move_low32(cpu_LO[acc], t2);
4020 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 4021 tcg_temp_free_i64(t2);
214c465f 4022 }
6af0bf9c
FB
4023 break;
4024 default:
9d68ac14 4025 MIPS_INVAL("mul/div");
9c708c7f 4026 generate_exception_end(ctx, EXCP_RI);
78723684 4027 goto out;
6af0bf9c 4028 }
78723684
TS
4029 out:
4030 tcg_temp_free(t0);
4031 tcg_temp_free(t1);
6af0bf9c
FB
4032}
4033
e9c71dd1
TS
4034static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
4035 int rd, int rs, int rt)
4036{
f157bfe1
AJ
4037 TCGv t0 = tcg_temp_new();
4038 TCGv t1 = tcg_temp_new();
e9c71dd1 4039
6c5c1e20
TS
4040 gen_load_gpr(t0, rs);
4041 gen_load_gpr(t1, rt);
e9c71dd1
TS
4042
4043 switch (opc) {
4044 case OPC_VR54XX_MULS:
895c2d04 4045 gen_helper_muls(t0, cpu_env, t0, t1);
6958549d 4046 break;
e9c71dd1 4047 case OPC_VR54XX_MULSU:
895c2d04 4048 gen_helper_mulsu(t0, cpu_env, t0, t1);
6958549d 4049 break;
e9c71dd1 4050 case OPC_VR54XX_MACC:
895c2d04 4051 gen_helper_macc(t0, cpu_env, t0, t1);
6958549d 4052 break;
e9c71dd1 4053 case OPC_VR54XX_MACCU:
895c2d04 4054 gen_helper_maccu(t0, cpu_env, t0, t1);
6958549d 4055 break;
e9c71dd1 4056 case OPC_VR54XX_MSAC:
895c2d04 4057 gen_helper_msac(t0, cpu_env, t0, t1);
6958549d 4058 break;
e9c71dd1 4059 case OPC_VR54XX_MSACU:
895c2d04 4060 gen_helper_msacu(t0, cpu_env, t0, t1);
6958549d 4061 break;
e9c71dd1 4062 case OPC_VR54XX_MULHI:
895c2d04 4063 gen_helper_mulhi(t0, cpu_env, t0, t1);
6958549d 4064 break;
e9c71dd1 4065 case OPC_VR54XX_MULHIU:
895c2d04 4066 gen_helper_mulhiu(t0, cpu_env, t0, t1);
6958549d 4067 break;
e9c71dd1 4068 case OPC_VR54XX_MULSHI:
895c2d04 4069 gen_helper_mulshi(t0, cpu_env, t0, t1);
6958549d 4070 break;
e9c71dd1 4071 case OPC_VR54XX_MULSHIU:
895c2d04 4072 gen_helper_mulshiu(t0, cpu_env, t0, t1);
6958549d 4073 break;
e9c71dd1 4074 case OPC_VR54XX_MACCHI:
895c2d04 4075 gen_helper_macchi(t0, cpu_env, t0, t1);
6958549d 4076 break;
e9c71dd1 4077 case OPC_VR54XX_MACCHIU:
895c2d04 4078 gen_helper_macchiu(t0, cpu_env, t0, t1);
6958549d 4079 break;
e9c71dd1 4080 case OPC_VR54XX_MSACHI:
895c2d04 4081 gen_helper_msachi(t0, cpu_env, t0, t1);
6958549d 4082 break;
e9c71dd1 4083 case OPC_VR54XX_MSACHIU:
895c2d04 4084 gen_helper_msachiu(t0, cpu_env, t0, t1);
6958549d 4085 break;
e9c71dd1
TS
4086 default:
4087 MIPS_INVAL("mul vr54xx");
9c708c7f 4088 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 4089 goto out;
e9c71dd1 4090 }
6c5c1e20 4091 gen_store_gpr(t0, rd);
6c5c1e20
TS
4092
4093 out:
4094 tcg_temp_free(t0);
4095 tcg_temp_free(t1);
e9c71dd1
TS
4096}
4097
7a387fff 4098static void gen_cl (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
4099 int rd, int rs)
4100{
20e1fb52 4101 TCGv t0;
6c5c1e20 4102
6af0bf9c 4103 if (rd == 0) {
ead9360e 4104 /* Treat as NOP. */
20e1fb52 4105 return;
6af0bf9c 4106 }
1a0196c5 4107 t0 = cpu_gpr[rd];
6c5c1e20 4108 gen_load_gpr(t0, rs);
1a0196c5 4109
6af0bf9c
FB
4110 switch (opc) {
4111 case OPC_CLO:
4267d3e6 4112 case R6_OPC_CLO:
1a0196c5
RH
4113#if defined(TARGET_MIPS64)
4114 case OPC_DCLO:
4115 case R6_OPC_DCLO:
4116#endif
4117 tcg_gen_not_tl(t0, t0);
6af0bf9c 4118 break;
1a0196c5
RH
4119 }
4120
4121 switch (opc) {
4122 case OPC_CLO:
4123 case R6_OPC_CLO:
6af0bf9c 4124 case OPC_CLZ:
4267d3e6 4125 case R6_OPC_CLZ:
1a0196c5
RH
4126 tcg_gen_ext32u_tl(t0, t0);
4127 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4128 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
6af0bf9c 4129 break;
d26bc211 4130#if defined(TARGET_MIPS64)
7a387fff 4131 case OPC_DCLO:
4267d3e6 4132 case R6_OPC_DCLO:
7a387fff 4133 case OPC_DCLZ:
4267d3e6 4134 case R6_OPC_DCLZ:
1a0196c5 4135 tcg_gen_clzi_i64(t0, t0, 64);
7a387fff
TS
4136 break;
4137#endif
6af0bf9c 4138 }
6af0bf9c
FB
4139}
4140
161f85e6 4141/* Godson integer instructions */
bd277fa1
RH
4142static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
4143 int rd, int rs, int rt)
161f85e6 4144{
161f85e6
AJ
4145 TCGv t0, t1;
4146
4147 if (rd == 0) {
4148 /* Treat as NOP. */
161f85e6
AJ
4149 return;
4150 }
4151
4152 switch (opc) {
4153 case OPC_MULT_G_2E:
4154 case OPC_MULT_G_2F:
4155 case OPC_MULTU_G_2E:
4156 case OPC_MULTU_G_2F:
4157#if defined(TARGET_MIPS64)
4158 case OPC_DMULT_G_2E:
4159 case OPC_DMULT_G_2F:
4160 case OPC_DMULTU_G_2E:
4161 case OPC_DMULTU_G_2F:
4162#endif
4163 t0 = tcg_temp_new();
4164 t1 = tcg_temp_new();
4165 break;
4166 default:
4167 t0 = tcg_temp_local_new();
4168 t1 = tcg_temp_local_new();
4169 break;
4170 }
4171
4172 gen_load_gpr(t0, rs);
4173 gen_load_gpr(t1, rt);
4174
4175 switch (opc) {
4176 case OPC_MULT_G_2E:
4177 case OPC_MULT_G_2F:
4178 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4179 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
4180 break;
4181 case OPC_MULTU_G_2E:
4182 case OPC_MULTU_G_2F:
4183 tcg_gen_ext32u_tl(t0, t0);
4184 tcg_gen_ext32u_tl(t1, t1);
4185 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4186 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
4187 break;
4188 case OPC_DIV_G_2E:
4189 case OPC_DIV_G_2F:
4190 {
42a268c2
RH
4191 TCGLabel *l1 = gen_new_label();
4192 TCGLabel *l2 = gen_new_label();
4193 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
4194 tcg_gen_ext32s_tl(t0, t0);
4195 tcg_gen_ext32s_tl(t1, t1);
4196 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4197 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4198 tcg_gen_br(l3);
4199 gen_set_label(l1);
4200 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4201 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4202 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4203 tcg_gen_br(l3);
4204 gen_set_label(l2);
4205 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4206 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4207 gen_set_label(l3);
4208 }
161f85e6
AJ
4209 break;
4210 case OPC_DIVU_G_2E:
4211 case OPC_DIVU_G_2F:
4212 {
42a268c2
RH
4213 TCGLabel *l1 = gen_new_label();
4214 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
4215 tcg_gen_ext32u_tl(t0, t0);
4216 tcg_gen_ext32u_tl(t1, t1);
4217 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4218 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4219 tcg_gen_br(l2);
4220 gen_set_label(l1);
4221 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4222 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4223 gen_set_label(l2);
4224 }
161f85e6
AJ
4225 break;
4226 case OPC_MOD_G_2E:
4227 case OPC_MOD_G_2F:
4228 {
42a268c2
RH
4229 TCGLabel *l1 = gen_new_label();
4230 TCGLabel *l2 = gen_new_label();
4231 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
4232 tcg_gen_ext32u_tl(t0, t0);
4233 tcg_gen_ext32u_tl(t1, t1);
4234 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4235 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4236 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4237 gen_set_label(l1);
4238 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4239 tcg_gen_br(l3);
4240 gen_set_label(l2);
4241 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4242 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4243 gen_set_label(l3);
4244 }
161f85e6
AJ
4245 break;
4246 case OPC_MODU_G_2E:
4247 case OPC_MODU_G_2F:
4248 {
42a268c2
RH
4249 TCGLabel *l1 = gen_new_label();
4250 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
4251 tcg_gen_ext32u_tl(t0, t0);
4252 tcg_gen_ext32u_tl(t1, t1);
4253 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4254 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4255 tcg_gen_br(l2);
4256 gen_set_label(l1);
4257 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4258 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4259 gen_set_label(l2);
4260 }
161f85e6
AJ
4261 break;
4262#if defined(TARGET_MIPS64)
4263 case OPC_DMULT_G_2E:
4264 case OPC_DMULT_G_2F:
4265 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
4266 break;
4267 case OPC_DMULTU_G_2E:
4268 case OPC_DMULTU_G_2F:
4269 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
4270 break;
4271 case OPC_DDIV_G_2E:
4272 case OPC_DDIV_G_2F:
4273 {
42a268c2
RH
4274 TCGLabel *l1 = gen_new_label();
4275 TCGLabel *l2 = gen_new_label();
4276 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
4277 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4278 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4279 tcg_gen_br(l3);
4280 gen_set_label(l1);
4281 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4282 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4283 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4284 tcg_gen_br(l3);
4285 gen_set_label(l2);
4286 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4287 gen_set_label(l3);
4288 }
161f85e6
AJ
4289 break;
4290 case OPC_DDIVU_G_2E:
4291 case OPC_DDIVU_G_2F:
4292 {
42a268c2
RH
4293 TCGLabel *l1 = gen_new_label();
4294 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
4295 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4296 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4297 tcg_gen_br(l2);
4298 gen_set_label(l1);
4299 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4300 gen_set_label(l2);
4301 }
161f85e6
AJ
4302 break;
4303 case OPC_DMOD_G_2E:
4304 case OPC_DMOD_G_2F:
4305 {
42a268c2
RH
4306 TCGLabel *l1 = gen_new_label();
4307 TCGLabel *l2 = gen_new_label();
4308 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
4309 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4310 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4311 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4312 gen_set_label(l1);
4313 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4314 tcg_gen_br(l3);
4315 gen_set_label(l2);
4316 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4317 gen_set_label(l3);
4318 }
161f85e6
AJ
4319 break;
4320 case OPC_DMODU_G_2E:
4321 case OPC_DMODU_G_2F:
4322 {
42a268c2
RH
4323 TCGLabel *l1 = gen_new_label();
4324 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
4325 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4326 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4327 tcg_gen_br(l2);
4328 gen_set_label(l1);
4329 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4330 gen_set_label(l2);
4331 }
161f85e6
AJ
4332 break;
4333#endif
4334 }
4335
161f85e6
AJ
4336 tcg_temp_free(t0);
4337 tcg_temp_free(t1);
4338}
4339
bd277fa1
RH
4340/* Loongson multimedia instructions */
4341static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4342{
bd277fa1
RH
4343 uint32_t opc, shift_max;
4344 TCGv_i64 t0, t1;
4345
4346 opc = MASK_LMI(ctx->opcode);
4347 switch (opc) {
4348 case OPC_ADD_CP2:
4349 case OPC_SUB_CP2:
4350 case OPC_DADD_CP2:
4351 case OPC_DSUB_CP2:
4352 t0 = tcg_temp_local_new_i64();
4353 t1 = tcg_temp_local_new_i64();
4354 break;
4355 default:
4356 t0 = tcg_temp_new_i64();
4357 t1 = tcg_temp_new_i64();
4358 break;
4359 }
4360
b5a587b6 4361 check_cp1_enabled(ctx);
bd277fa1
RH
4362 gen_load_fpr64(ctx, t0, rs);
4363 gen_load_fpr64(ctx, t1, rt);
4364
4365#define LMI_HELPER(UP, LO) \
9d68ac14 4366 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
bd277fa1 4367#define LMI_HELPER_1(UP, LO) \
9d68ac14 4368 case OPC_##UP: gen_helper_##LO(t0, t0); break
bd277fa1 4369#define LMI_DIRECT(UP, LO, OP) \
9d68ac14 4370 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
bd277fa1
RH
4371
4372 switch (opc) {
4373 LMI_HELPER(PADDSH, paddsh);
4374 LMI_HELPER(PADDUSH, paddush);
4375 LMI_HELPER(PADDH, paddh);
4376 LMI_HELPER(PADDW, paddw);
4377 LMI_HELPER(PADDSB, paddsb);
4378 LMI_HELPER(PADDUSB, paddusb);
4379 LMI_HELPER(PADDB, paddb);
4380
4381 LMI_HELPER(PSUBSH, psubsh);
4382 LMI_HELPER(PSUBUSH, psubush);
4383 LMI_HELPER(PSUBH, psubh);
4384 LMI_HELPER(PSUBW, psubw);
4385 LMI_HELPER(PSUBSB, psubsb);
4386 LMI_HELPER(PSUBUSB, psubusb);
4387 LMI_HELPER(PSUBB, psubb);
4388
4389 LMI_HELPER(PSHUFH, pshufh);
4390 LMI_HELPER(PACKSSWH, packsswh);
4391 LMI_HELPER(PACKSSHB, packsshb);
4392 LMI_HELPER(PACKUSHB, packushb);
4393
4394 LMI_HELPER(PUNPCKLHW, punpcklhw);
4395 LMI_HELPER(PUNPCKHHW, punpckhhw);
4396 LMI_HELPER(PUNPCKLBH, punpcklbh);
4397 LMI_HELPER(PUNPCKHBH, punpckhbh);
4398 LMI_HELPER(PUNPCKLWD, punpcklwd);
4399 LMI_HELPER(PUNPCKHWD, punpckhwd);
4400
4401 LMI_HELPER(PAVGH, pavgh);
4402 LMI_HELPER(PAVGB, pavgb);
4403 LMI_HELPER(PMAXSH, pmaxsh);
4404 LMI_HELPER(PMINSH, pminsh);
4405 LMI_HELPER(PMAXUB, pmaxub);
4406 LMI_HELPER(PMINUB, pminub);
4407
4408 LMI_HELPER(PCMPEQW, pcmpeqw);
4409 LMI_HELPER(PCMPGTW, pcmpgtw);
4410 LMI_HELPER(PCMPEQH, pcmpeqh);
4411 LMI_HELPER(PCMPGTH, pcmpgth);
4412 LMI_HELPER(PCMPEQB, pcmpeqb);
4413 LMI_HELPER(PCMPGTB, pcmpgtb);
4414
4415 LMI_HELPER(PSLLW, psllw);
4416 LMI_HELPER(PSLLH, psllh);
4417 LMI_HELPER(PSRLW, psrlw);
4418 LMI_HELPER(PSRLH, psrlh);
4419 LMI_HELPER(PSRAW, psraw);
4420 LMI_HELPER(PSRAH, psrah);
4421
4422 LMI_HELPER(PMULLH, pmullh);
4423 LMI_HELPER(PMULHH, pmulhh);
4424 LMI_HELPER(PMULHUH, pmulhuh);
4425 LMI_HELPER(PMADDHW, pmaddhw);
4426
4427 LMI_HELPER(PASUBUB, pasubub);
4428 LMI_HELPER_1(BIADD, biadd);
4429 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4430
4431 LMI_DIRECT(PADDD, paddd, add);
4432 LMI_DIRECT(PSUBD, psubd, sub);
4433 LMI_DIRECT(XOR_CP2, xor, xor);
4434 LMI_DIRECT(NOR_CP2, nor, nor);
4435 LMI_DIRECT(AND_CP2, and, and);
bb7cab5f 4436 LMI_DIRECT(OR_CP2, or, or);
bd277fa1 4437
9099a36b
H
4438 case OPC_PANDN:
4439 tcg_gen_andc_i64(t0, t1, t0);
4440 break;
4441
bd277fa1
RH
4442 case OPC_PINSRH_0:
4443 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
bd277fa1
RH
4444 break;
4445 case OPC_PINSRH_1:
4446 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
bd277fa1
RH
4447 break;
4448 case OPC_PINSRH_2:
4449 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
bd277fa1
RH
4450 break;
4451 case OPC_PINSRH_3:
4452 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
bd277fa1
RH
4453 break;
4454
4455 case OPC_PEXTRH:
4456 tcg_gen_andi_i64(t1, t1, 3);
4457 tcg_gen_shli_i64(t1, t1, 4);
4458 tcg_gen_shr_i64(t0, t0, t1);
4459 tcg_gen_ext16u_i64(t0, t0);
bd277fa1
RH
4460 break;
4461
4462 case OPC_ADDU_CP2:
4463 tcg_gen_add_i64(t0, t0, t1);
4464 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
4465 break;
4466 case OPC_SUBU_CP2:
4467 tcg_gen_sub_i64(t0, t0, t1);
4468 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
4469 break;
4470
4471 case OPC_SLL_CP2:
bd277fa1
RH
4472 shift_max = 32;
4473 goto do_shift;
4474 case OPC_SRL_CP2:
bd277fa1
RH
4475 shift_max = 32;
4476 goto do_shift;
4477 case OPC_SRA_CP2:
bd277fa1
RH
4478 shift_max = 32;
4479 goto do_shift;
4480 case OPC_DSLL_CP2:
bd277fa1
RH
4481 shift_max = 64;
4482 goto do_shift;
4483 case OPC_DSRL_CP2:
bd277fa1
RH
4484 shift_max = 64;
4485 goto do_shift;
4486 case OPC_DSRA_CP2:
bd277fa1
RH
4487 shift_max = 64;
4488 goto do_shift;
4489 do_shift:
4490 /* Make sure shift count isn't TCG undefined behaviour. */
4491 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4492
4493 switch (opc) {
4494 case OPC_SLL_CP2:
4495 case OPC_DSLL_CP2:
4496 tcg_gen_shl_i64(t0, t0, t1);
4497 break;
4498 case OPC_SRA_CP2:
4499 case OPC_DSRA_CP2:
4500 /* Since SRA is UndefinedResult without sign-extended inputs,
4501 we can treat SRA and DSRA the same. */
4502 tcg_gen_sar_i64(t0, t0, t1);
4503 break;
4504 case OPC_SRL_CP2:
4505 /* We want to shift in zeros for SRL; zero-extend first. */
4506 tcg_gen_ext32u_i64(t0, t0);
4507 /* FALLTHRU */
4508 case OPC_DSRL_CP2:
4509 tcg_gen_shr_i64(t0, t0, t1);
4510 break;
4511 }
4512
4513 if (shift_max == 32) {
4514 tcg_gen_ext32s_i64(t0, t0);
4515 }
4516
4517 /* Shifts larger than MAX produce zero. */
4518 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4519 tcg_gen_neg_i64(t1, t1);
4520 tcg_gen_and_i64(t0, t0, t1);
4521 break;
4522
4523 case OPC_ADD_CP2:
4524 case OPC_DADD_CP2:
4525 {
4526 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 4527 TCGLabel *lab = gen_new_label();
bd277fa1
RH
4528
4529 tcg_gen_mov_i64(t2, t0);
4530 tcg_gen_add_i64(t0, t1, t2);
4531 if (opc == OPC_ADD_CP2) {
4532 tcg_gen_ext32s_i64(t0, t0);
4533 }
4534 tcg_gen_xor_i64(t1, t1, t2);
4535 tcg_gen_xor_i64(t2, t2, t0);
4536 tcg_gen_andc_i64(t1, t2, t1);
4537 tcg_temp_free_i64(t2);
4538 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4539 generate_exception(ctx, EXCP_OVERFLOW);
4540 gen_set_label(lab);
bd277fa1
RH
4541 break;
4542 }
4543
4544 case OPC_SUB_CP2:
4545 case OPC_DSUB_CP2:
4546 {
4547 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 4548 TCGLabel *lab = gen_new_label();
bd277fa1
RH
4549
4550 tcg_gen_mov_i64(t2, t0);
4551 tcg_gen_sub_i64(t0, t1, t2);
4552 if (opc == OPC_SUB_CP2) {
4553 tcg_gen_ext32s_i64(t0, t0);
4554 }
4555 tcg_gen_xor_i64(t1, t1, t2);
4556 tcg_gen_xor_i64(t2, t2, t0);
4557 tcg_gen_and_i64(t1, t1, t2);
4558 tcg_temp_free_i64(t2);
4559 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4560 generate_exception(ctx, EXCP_OVERFLOW);
4561 gen_set_label(lab);
bd277fa1
RH
4562 break;
4563 }
4564
4565 case OPC_PMULUW:
4566 tcg_gen_ext32u_i64(t0, t0);
4567 tcg_gen_ext32u_i64(t1, t1);
4568 tcg_gen_mul_i64(t0, t0, t1);
bd277fa1
RH
4569 break;
4570
4571 case OPC_SEQU_CP2:
4572 case OPC_SEQ_CP2:
4573 case OPC_SLTU_CP2:
4574 case OPC_SLT_CP2:
4575 case OPC_SLEU_CP2:
4576 case OPC_SLE_CP2:
4577 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4578 FD field is the CC field? */
4579 default:
9d68ac14 4580 MIPS_INVAL("loongson_cp2");
9c708c7f 4581 generate_exception_end(ctx, EXCP_RI);
bd277fa1
RH
4582 return;
4583 }
4584
4585#undef LMI_HELPER
4586#undef LMI_DIRECT
4587
4588 gen_store_fpr64(ctx, t0, rd);
4589
bd277fa1
RH
4590 tcg_temp_free_i64(t0);
4591 tcg_temp_free_i64(t1);
4592}
4593
6af0bf9c 4594/* Traps */
7a387fff 4595static void gen_trap (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
4596 int rs, int rt, int16_t imm)
4597{
4598 int cond;
cdc0faa6 4599 TCGv t0 = tcg_temp_new();
1ba74fb8 4600 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
4601
4602 cond = 0;
4603 /* Load needed operands */
4604 switch (opc) {
4605 case OPC_TEQ:
4606 case OPC_TGE:
4607 case OPC_TGEU:
4608 case OPC_TLT:
4609 case OPC_TLTU:
4610 case OPC_TNE:
4611 /* Compare two registers */
4612 if (rs != rt) {
be24bb4f
TS
4613 gen_load_gpr(t0, rs);
4614 gen_load_gpr(t1, rt);
6af0bf9c
FB
4615 cond = 1;
4616 }
179e32bb 4617 break;
6af0bf9c
FB
4618 case OPC_TEQI:
4619 case OPC_TGEI:
4620 case OPC_TGEIU:
4621 case OPC_TLTI:
4622 case OPC_TLTIU:
4623 case OPC_TNEI:
4624 /* Compare register to immediate */
4625 if (rs != 0 || imm != 0) {
be24bb4f
TS
4626 gen_load_gpr(t0, rs);
4627 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
4628 cond = 1;
4629 }
4630 break;
4631 }
4632 if (cond == 0) {
4633 switch (opc) {
4634 case OPC_TEQ: /* rs == rs */
4635 case OPC_TEQI: /* r0 == 0 */
4636 case OPC_TGE: /* rs >= rs */
4637 case OPC_TGEI: /* r0 >= 0 */
4638 case OPC_TGEU: /* rs >= rs unsigned */
4639 case OPC_TGEIU: /* r0 >= 0 unsigned */
4640 /* Always trap */
9c708c7f 4641 generate_exception_end(ctx, EXCP_TRAP);
6af0bf9c
FB
4642 break;
4643 case OPC_TLT: /* rs < rs */
4644 case OPC_TLTI: /* r0 < 0 */
4645 case OPC_TLTU: /* rs < rs unsigned */
4646 case OPC_TLTIU: /* r0 < 0 unsigned */
4647 case OPC_TNE: /* rs != rs */
4648 case OPC_TNEI: /* r0 != 0 */
ead9360e 4649 /* Never trap: treat as NOP. */
cdc0faa6 4650 break;
6af0bf9c
FB
4651 }
4652 } else {
42a268c2 4653 TCGLabel *l1 = gen_new_label();
cdc0faa6 4654
6af0bf9c
FB
4655 switch (opc) {
4656 case OPC_TEQ:
4657 case OPC_TEQI:
cdc0faa6 4658 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
4659 break;
4660 case OPC_TGE:
4661 case OPC_TGEI:
cdc0faa6 4662 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
4663 break;
4664 case OPC_TGEU:
4665 case OPC_TGEIU:
cdc0faa6 4666 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
4667 break;
4668 case OPC_TLT:
4669 case OPC_TLTI:
cdc0faa6 4670 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
4671 break;
4672 case OPC_TLTU:
4673 case OPC_TLTIU:
cdc0faa6 4674 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
4675 break;
4676 case OPC_TNE:
4677 case OPC_TNEI:
cdc0faa6 4678 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 4679 break;
6af0bf9c 4680 }
cdc0faa6 4681 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
4682 gen_set_label(l1);
4683 }
be24bb4f
TS
4684 tcg_temp_free(t0);
4685 tcg_temp_free(t1);
6af0bf9c
FB
4686}
4687
90aa39a1
SF
4688static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
4689{
eeb3bba8 4690 if (unlikely(ctx->base.singlestep_enabled)) {
90aa39a1
SF
4691 return false;
4692 }
4693
4694#ifndef CONFIG_USER_ONLY
eeb3bba8 4695 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
90aa39a1
SF
4696#else
4697 return true;
4698#endif
4699}
4700
356265ae 4701static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 4702{
90aa39a1 4703 if (use_goto_tb(ctx, dest)) {
57fec1fe 4704 tcg_gen_goto_tb(n);
9b9e4393 4705 gen_save_pc(dest);
07ea28b4 4706 tcg_gen_exit_tb(ctx->base.tb, n);
6e256c93 4707 } else {
9b9e4393 4708 gen_save_pc(dest);
eeb3bba8 4709 if (ctx->base.singlestep_enabled) {
7b270ef2 4710 save_cpu_state(ctx, 0);
9c708c7f 4711 gen_helper_raise_exception_debug(cpu_env);
7b270ef2 4712 }
7f11636d 4713 tcg_gen_lookup_and_goto_ptr();
6e256c93 4714 }
c53be334
FB
4715}
4716
6af0bf9c 4717/* Branches (before delay slot) */
7a387fff 4718static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
7dca4ad0 4719 int insn_bytes,
b231c103
YK
4720 int rs, int rt, int32_t offset,
4721 int delayslot_size)
6af0bf9c 4722{
d077b6f7 4723 target_ulong btgt = -1;
3ad4bb2d 4724 int blink = 0;
2fdbad25 4725 int bcond_compute = 0;
1ba74fb8
AJ
4726 TCGv t0 = tcg_temp_new();
4727 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
4728
4729 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 4730#ifdef MIPS_DEBUG_DISAS
339cd2a8 4731 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
eeb3bba8 4732 TARGET_FMT_lx "\n", ctx->base.pc_next);
923617a3 4733#endif
9c708c7f 4734 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 4735 goto out;
3ad4bb2d 4736 }
6af0bf9c 4737
6af0bf9c
FB
4738 /* Load needed operands */
4739 switch (opc) {
4740 case OPC_BEQ:
4741 case OPC_BEQL:
4742 case OPC_BNE:
4743 case OPC_BNEL:
4744 /* Compare two registers */
4745 if (rs != rt) {
6c5c1e20
TS
4746 gen_load_gpr(t0, rs);
4747 gen_load_gpr(t1, rt);
2fdbad25 4748 bcond_compute = 1;
6af0bf9c 4749 }
eeb3bba8 4750 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c
FB
4751 break;
4752 case OPC_BGEZ:
4753 case OPC_BGEZAL:
4754 case OPC_BGEZALL:
4755 case OPC_BGEZL:
4756 case OPC_BGTZ:
4757 case OPC_BGTZL:
4758 case OPC_BLEZ:
4759 case OPC_BLEZL:
4760 case OPC_BLTZ:
4761 case OPC_BLTZAL:
4762 case OPC_BLTZALL:
4763 case OPC_BLTZL:
4764 /* Compare to zero */
4765 if (rs != 0) {
6c5c1e20 4766 gen_load_gpr(t0, rs);
2fdbad25 4767 bcond_compute = 1;
6af0bf9c 4768 }
eeb3bba8 4769 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c 4770 break;
e45a93e2
JL
4771 case OPC_BPOSGE32:
4772#if defined(TARGET_MIPS64)
4773 case OPC_BPOSGE64:
4774 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4775#else
4776 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4777#endif
4778 bcond_compute = 1;
eeb3bba8 4779 btgt = ctx->base.pc_next + insn_bytes + offset;
e45a93e2 4780 break;
6af0bf9c
FB
4781 case OPC_J:
4782 case OPC_JAL:
364d4831 4783 case OPC_JALX:
6af0bf9c 4784 /* Jump to immediate */
eeb3bba8
EC
4785 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
4786 (uint32_t)offset;
6af0bf9c
FB
4787 break;
4788 case OPC_JR:
4789 case OPC_JALR:
4790 /* Jump to register */
7a387fff
TS
4791 if (offset != 0 && offset != 16) {
4792 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
cbeb0857 4793 others are reserved. */
923617a3 4794 MIPS_INVAL("jump hint");
9c708c7f 4795 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 4796 goto out;
6af0bf9c 4797 }
d077b6f7 4798 gen_load_gpr(btarget, rs);
6af0bf9c
FB
4799 break;
4800 default:
4801 MIPS_INVAL("branch/jump");
9c708c7f 4802 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 4803 goto out;
6af0bf9c 4804 }
2fdbad25 4805 if (bcond_compute == 0) {
6af0bf9c
FB
4806 /* No condition to be computed */
4807 switch (opc) {
4808 case OPC_BEQ: /* rx == rx */
4809 case OPC_BEQL: /* rx == rx likely */
4810 case OPC_BGEZ: /* 0 >= 0 */
4811 case OPC_BGEZL: /* 0 >= 0 likely */
4812 case OPC_BLEZ: /* 0 <= 0 */
4813 case OPC_BLEZL: /* 0 <= 0 likely */
4814 /* Always take */
4ad40f36 4815 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
4816 break;
4817 case OPC_BGEZAL: /* 0 >= 0 */
4818 case OPC_BGEZALL: /* 0 >= 0 likely */
4819 /* Always take and link */
4820 blink = 31;
4ad40f36 4821 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
4822 break;
4823 case OPC_BNE: /* rx != rx */
4824 case OPC_BGTZ: /* 0 > 0 */
4825 case OPC_BLTZ: /* 0 < 0 */
ead9360e 4826 /* Treat as NOP. */
6c5c1e20 4827 goto out;
eeef26cd 4828 case OPC_BLTZAL: /* 0 < 0 */
3c824109
NF
4829 /* Handle as an unconditional branch to get correct delay
4830 slot checking. */
4831 blink = 31;
eeb3bba8 4832 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
3c824109 4833 ctx->hflags |= MIPS_HFLAG_B;
3c824109 4834 break;
eeef26cd 4835 case OPC_BLTZALL: /* 0 < 0 likely */
eeb3bba8 4836 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
9898128f 4837 /* Skip the instruction in the delay slot */
eeb3bba8 4838 ctx->base.pc_next += 4;
6c5c1e20 4839 goto out;
6af0bf9c
FB
4840 case OPC_BNEL: /* rx != rx likely */
4841 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
4842 case OPC_BLTZL: /* 0 < 0 likely */
4843 /* Skip the instruction in the delay slot */
eeb3bba8 4844 ctx->base.pc_next += 4;
6c5c1e20 4845 goto out;
6af0bf9c 4846 case OPC_J:
4ad40f36 4847 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c 4848 break;
364d4831
NF
4849 case OPC_JALX:
4850 ctx->hflags |= MIPS_HFLAG_BX;
4851 /* Fallthrough */
6af0bf9c
FB
4852 case OPC_JAL:
4853 blink = 31;
4ad40f36 4854 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
4855 break;
4856 case OPC_JR:
4ad40f36 4857 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
4858 break;
4859 case OPC_JALR:
4860 blink = rt;
4ad40f36 4861 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
4862 break;
4863 default:
4864 MIPS_INVAL("branch/jump");
9c708c7f 4865 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 4866 goto out;
6af0bf9c
FB
4867 }
4868 } else {
4869 switch (opc) {
4870 case OPC_BEQ:
e68dd28f 4871 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
4872 goto not_likely;
4873 case OPC_BEQL:
e68dd28f 4874 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
4875 goto likely;
4876 case OPC_BNE:
e68dd28f 4877 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
4878 goto not_likely;
4879 case OPC_BNEL:
e68dd28f 4880 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
4881 goto likely;
4882 case OPC_BGEZ:
e68dd28f 4883 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
4884 goto not_likely;
4885 case OPC_BGEZL:
e68dd28f 4886 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
4887 goto likely;
4888 case OPC_BGEZAL:
e68dd28f 4889 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
4890 blink = 31;
4891 goto not_likely;
4892 case OPC_BGEZALL:
e68dd28f 4893 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 4894 blink = 31;
6af0bf9c
FB
4895 goto likely;
4896 case OPC_BGTZ:
e68dd28f 4897 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
4898 goto not_likely;
4899 case OPC_BGTZL:
e68dd28f 4900 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
4901 goto likely;
4902 case OPC_BLEZ:
e68dd28f 4903 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
4904 goto not_likely;
4905 case OPC_BLEZL:
e68dd28f 4906 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
4907 goto likely;
4908 case OPC_BLTZ:
e68dd28f 4909 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c
FB
4910 goto not_likely;
4911 case OPC_BLTZL:
e68dd28f 4912 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 4913 goto likely;
e45a93e2
JL
4914 case OPC_BPOSGE32:
4915 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
e45a93e2
JL
4916 goto not_likely;
4917#if defined(TARGET_MIPS64)
4918 case OPC_BPOSGE64:
4919 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
e45a93e2
JL
4920 goto not_likely;
4921#endif
6af0bf9c 4922 case OPC_BLTZAL:
e68dd28f 4923 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 4924 blink = 31;
6af0bf9c 4925 not_likely:
4ad40f36 4926 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
4927 break;
4928 case OPC_BLTZALL:
e68dd28f 4929 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 4930 blink = 31;
6af0bf9c 4931 likely:
4ad40f36 4932 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 4933 break;
c53f4a62
TS
4934 default:
4935 MIPS_INVAL("conditional branch/jump");
9c708c7f 4936 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 4937 goto out;
6af0bf9c 4938 }
6af0bf9c 4939 }
9b9e4393 4940
d077b6f7 4941 ctx->btarget = btgt;
b231c103
YK
4942
4943 switch (delayslot_size) {
4944 case 2:
4945 ctx->hflags |= MIPS_HFLAG_BDS16;
4946 break;
4947 case 4:
4948 ctx->hflags |= MIPS_HFLAG_BDS32;
4949 break;
4950 }
4951
6af0bf9c 4952 if (blink > 0) {
b231c103 4953 int post_delay = insn_bytes + delayslot_size;
364d4831
NF
4954 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4955
eeb3bba8
EC
4956 tcg_gen_movi_tl(cpu_gpr[blink],
4957 ctx->base.pc_next + post_delay + lowbit);
6af0bf9c 4958 }
6c5c1e20
TS
4959
4960 out:
364d4831
NF
4961 if (insn_bytes == 2)
4962 ctx->hflags |= MIPS_HFLAG_B16;
6c5c1e20
TS
4963 tcg_temp_free(t0);
4964 tcg_temp_free(t1);
6af0bf9c
FB
4965}
4966
764371d2
SM
4967
4968/* nanoMIPS Branches */
4969static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
4970 int insn_bytes,
4971 int rs, int rt, int32_t offset)
4972{
4973 target_ulong btgt = -1;
4974 int bcond_compute = 0;
4975 TCGv t0 = tcg_temp_new();
4976 TCGv t1 = tcg_temp_new();
4977
4978 /* Load needed operands */
4979 switch (opc) {
4980 case OPC_BEQ:
4981 case OPC_BNE:
4982 /* Compare two registers */
4983 if (rs != rt) {
4984 gen_load_gpr(t0, rs);
4985 gen_load_gpr(t1, rt);
4986 bcond_compute = 1;
4987 }
4988 btgt = ctx->base.pc_next + insn_bytes + offset;
4989 break;
4990 case OPC_BGEZAL:
4991 /* Compare to zero */
4992 if (rs != 0) {
4993 gen_load_gpr(t0, rs);
4994 bcond_compute = 1;
4995 }
4996 btgt = ctx->base.pc_next + insn_bytes + offset;
4997 break;
4998 case OPC_BPOSGE32:
4999 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5000 bcond_compute = 1;
5001 btgt = ctx->base.pc_next + insn_bytes + offset;
5002 break;
5003 case OPC_JR:
5004 case OPC_JALR:
5005 /* Jump to register */
5006 if (offset != 0 && offset != 16) {
5007 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5008 others are reserved. */
5009 MIPS_INVAL("jump hint");
5010 generate_exception_end(ctx, EXCP_RI);
5011 goto out;
5012 }
5013 gen_load_gpr(btarget, rs);
5014 break;
5015 default:
5016 MIPS_INVAL("branch/jump");
5017 generate_exception_end(ctx, EXCP_RI);
5018 goto out;
5019 }
5020 if (bcond_compute == 0) {
5021 /* No condition to be computed */
5022 switch (opc) {
5023 case OPC_BEQ: /* rx == rx */
5024 /* Always take */
5025 ctx->hflags |= MIPS_HFLAG_B;
5026 break;
5027 case OPC_BGEZAL: /* 0 >= 0 */
5028 /* Always take and link */
5029 tcg_gen_movi_tl(cpu_gpr[31],
5030 ctx->base.pc_next + insn_bytes);
5031 ctx->hflags |= MIPS_HFLAG_B;
5032 break;
5033 case OPC_BNE: /* rx != rx */
5034 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5035 /* Skip the instruction in the delay slot */
5036 ctx->base.pc_next += 4;
5037 goto out;
5038 case OPC_JR:
5039 ctx->hflags |= MIPS_HFLAG_BR;
5040 break;
5041 case OPC_JALR:
5042 if (rt > 0) {
5043 tcg_gen_movi_tl(cpu_gpr[rt],
5044 ctx->base.pc_next + insn_bytes);
5045 }
5046 ctx->hflags |= MIPS_HFLAG_BR;
5047 break;
5048 default:
5049 MIPS_INVAL("branch/jump");
5050 generate_exception_end(ctx, EXCP_RI);
5051 goto out;
5052 }
5053 } else {
5054 switch (opc) {
5055 case OPC_BEQ:
5056 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5057 goto not_likely;
5058 case OPC_BNE:
5059 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5060 goto not_likely;
5061 case OPC_BGEZAL:
5062 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5063 tcg_gen_movi_tl(cpu_gpr[31],
5064 ctx->base.pc_next + insn_bytes);
5065 goto not_likely;
5066 case OPC_BPOSGE32:
5067 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5068 not_likely:
5069 ctx->hflags |= MIPS_HFLAG_BC;
5070 break;
5071 default:
5072 MIPS_INVAL("conditional branch/jump");
5073 generate_exception_end(ctx, EXCP_RI);
5074 goto out;
5075 }
5076 }
5077
5078 ctx->btarget = btgt;
5079
5080 out:
5081 if (insn_bytes == 2) {
5082 ctx->hflags |= MIPS_HFLAG_B16;
5083 }
5084 tcg_temp_free(t0);
5085 tcg_temp_free(t1);
5086}
5087
5088
7a387fff
TS
5089/* special3 bitfield operations */
5090static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
356265ae 5091 int rs, int lsb, int msb)
7a387fff 5092{
a7812ae4
PB
5093 TCGv t0 = tcg_temp_new();
5094 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
5095
5096 gen_load_gpr(t1, rs);
7a387fff
TS
5097 switch (opc) {
5098 case OPC_EXT:
b7f26e52 5099 if (lsb + msb > 31) {
7a387fff 5100 goto fail;
b7f26e52 5101 }
505ad7c2 5102 if (msb != 31) {
6eebb7a4 5103 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
505ad7c2 5104 } else {
6eebb7a4
RH
5105 /* The two checks together imply that lsb == 0,
5106 so this is a simple sign-extension. */
5107 tcg_gen_ext32s_tl(t0, t1);
505ad7c2 5108 }
7a387fff 5109 break;
c6d6dd7c 5110#if defined(TARGET_MIPS64)
7a387fff 5111 case OPC_DEXTU:
b7f26e52
RH
5112 lsb += 32;
5113 goto do_dext;
5114 case OPC_DEXTM:
5115 msb += 32;
5116 goto do_dext;
7a387fff 5117 case OPC_DEXT:
b7f26e52
RH
5118 do_dext:
5119 if (lsb + msb > 63) {
5120 goto fail;
5121 }
6eebb7a4 5122 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
7a387fff 5123 break;
c6d6dd7c 5124#endif
7a387fff 5125 case OPC_INS:
b7f26e52 5126 if (lsb > msb) {
7a387fff 5127 goto fail;
b7f26e52 5128 }
6c5c1e20 5129 gen_load_gpr(t0, rt);
e0d002f1 5130 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
505ad7c2 5131 tcg_gen_ext32s_tl(t0, t0);
7a387fff 5132 break;
c6d6dd7c 5133#if defined(TARGET_MIPS64)
7a387fff 5134 case OPC_DINSU:
b7f26e52
RH
5135 lsb += 32;
5136 /* FALLTHRU */
5137 case OPC_DINSM:
5138 msb += 32;
5139 /* FALLTHRU */
7a387fff 5140 case OPC_DINS:
b7f26e52
RH
5141 if (lsb > msb) {
5142 goto fail;
5143 }
6c5c1e20 5144 gen_load_gpr(t0, rt);
e0d002f1 5145 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
7a387fff 5146 break;
c6d6dd7c 5147#endif
7a387fff
TS
5148 default:
5149fail:
5150 MIPS_INVAL("bitops");
9c708c7f 5151 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
5152 tcg_temp_free(t0);
5153 tcg_temp_free(t1);
7a387fff
TS
5154 return;
5155 }
6c5c1e20
TS
5156 gen_store_gpr(t0, rt);
5157 tcg_temp_free(t0);
5158 tcg_temp_free(t1);
7a387fff
TS
5159}
5160
49bcf33c
AJ
5161static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
5162{
3a55fa47 5163 TCGv t0;
49bcf33c 5164
3a55fa47
AJ
5165 if (rd == 0) {
5166 /* If no destination, treat it as a NOP. */
3a55fa47
AJ
5167 return;
5168 }
5169
5170 t0 = tcg_temp_new();
5171 gen_load_gpr(t0, rt);
49bcf33c
AJ
5172 switch (op2) {
5173 case OPC_WSBH:
3a55fa47
AJ
5174 {
5175 TCGv t1 = tcg_temp_new();
06a57e5c 5176 TCGv t2 = tcg_const_tl(0x00FF00FF);
3a55fa47
AJ
5177
5178 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
5179 tcg_gen_and_tl(t1, t1, t2);
5180 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 5181 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 5182 tcg_gen_or_tl(t0, t0, t1);
06a57e5c 5183 tcg_temp_free(t2);
3a55fa47
AJ
5184 tcg_temp_free(t1);
5185 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5186 }
49bcf33c
AJ
5187 break;
5188 case OPC_SEB:
3a55fa47 5189 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
5190 break;
5191 case OPC_SEH:
3a55fa47 5192 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
5193 break;
5194#if defined(TARGET_MIPS64)
5195 case OPC_DSBH:
3a55fa47
AJ
5196 {
5197 TCGv t1 = tcg_temp_new();
06a57e5c 5198 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
3a55fa47
AJ
5199
5200 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
5201 tcg_gen_and_tl(t1, t1, t2);
5202 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 5203 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 5204 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 5205 tcg_temp_free(t2);
3a55fa47
AJ
5206 tcg_temp_free(t1);
5207 }
49bcf33c
AJ
5208 break;
5209 case OPC_DSHD:
3a55fa47
AJ
5210 {
5211 TCGv t1 = tcg_temp_new();
06a57e5c 5212 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
3a55fa47
AJ
5213
5214 tcg_gen_shri_tl(t1, t0, 16);
06a57e5c
AJ
5215 tcg_gen_and_tl(t1, t1, t2);
5216 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 5217 tcg_gen_shli_tl(t0, t0, 16);
3a55fa47
AJ
5218 tcg_gen_or_tl(t0, t0, t1);
5219 tcg_gen_shri_tl(t1, t0, 32);
5220 tcg_gen_shli_tl(t0, t0, 32);
5221 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 5222 tcg_temp_free(t2);
3a55fa47
AJ
5223 tcg_temp_free(t1);
5224 }
49bcf33c
AJ
5225 break;
5226#endif
5227 default:
5228 MIPS_INVAL("bsfhl");
9c708c7f 5229 generate_exception_end(ctx, EXCP_RI);
49bcf33c 5230 tcg_temp_free(t0);
49bcf33c
AJ
5231 return;
5232 }
49bcf33c 5233 tcg_temp_free(t0);
49bcf33c
AJ
5234}
5235
1f1b4c00
YK
5236static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
5237 int imm2)
5238{
5239 TCGv t0;
5240 TCGv t1;
5241 if (rd == 0) {
5242 /* Treat as NOP. */
5243 return;
5244 }
5245 t0 = tcg_temp_new();
5246 t1 = tcg_temp_new();
5247 gen_load_gpr(t0, rs);
5248 gen_load_gpr(t1, rt);
5249 tcg_gen_shli_tl(t0, t0, imm2 + 1);
5250 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
5251 if (opc == OPC_LSA) {
5252 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5253 }
5254
5255 tcg_temp_free(t1);
5256 tcg_temp_free(t0);
5257
5258 return;
5259}
5260
821f2008
JH
5261static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
5262 int rt, int bits)
284b731a 5263{
1f1b4c00
YK
5264 TCGv t0;
5265 if (rd == 0) {
5266 /* Treat as NOP. */
5267 return;
5268 }
5269 t0 = tcg_temp_new();
821f2008
JH
5270 if (bits == 0 || bits == wordsz) {
5271 if (bits == 0) {
5272 gen_load_gpr(t0, rt);
5273 } else {
5274 gen_load_gpr(t0, rs);
5275 }
5276 switch (wordsz) {
5277 case 32:
51243852
MD
5278 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5279 break;
5280#if defined(TARGET_MIPS64)
821f2008 5281 case 64:
51243852
MD
5282 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5283 break;
5284#endif
5285 }
1f1b4c00
YK
5286 } else {
5287 TCGv t1 = tcg_temp_new();
821f2008 5288 gen_load_gpr(t0, rt);
1f1b4c00 5289 gen_load_gpr(t1, rs);
821f2008
JH
5290 switch (wordsz) {
5291 case 32:
1f1b4c00
YK
5292 {
5293 TCGv_i64 t2 = tcg_temp_new_i64();
5294 tcg_gen_concat_tl_i64(t2, t1, t0);
821f2008 5295 tcg_gen_shri_i64(t2, t2, 32 - bits);
1f1b4c00
YK
5296 gen_move_low32(cpu_gpr[rd], t2);
5297 tcg_temp_free_i64(t2);
5298 }
5299 break;
284b731a 5300#if defined(TARGET_MIPS64)
821f2008
JH
5301 case 64:
5302 tcg_gen_shli_tl(t0, t0, bits);
5303 tcg_gen_shri_tl(t1, t1, 64 - bits);
1f1b4c00
YK
5304 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5305 break;
284b731a 5306#endif
1f1b4c00
YK
5307 }
5308 tcg_temp_free(t1);
5309 }
5310
5311 tcg_temp_free(t0);
5312}
5313
821f2008
JH
5314static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5315 int bp)
5316{
5317 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5318}
5319
5320static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5321 int shift)
5322{
5323 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5324}
5325
1f1b4c00
YK
5326static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5327{
5328 TCGv t0;
5329 if (rd == 0) {
5330 /* Treat as NOP. */
5331 return;
5332 }
5333 t0 = tcg_temp_new();
5334 gen_load_gpr(t0, rt);
5335 switch (opc) {
5336 case OPC_BITSWAP:
5337 gen_helper_bitswap(cpu_gpr[rd], t0);
5338 break;
5339#if defined(TARGET_MIPS64)
5340 case OPC_DBITSWAP:
5341 gen_helper_dbitswap(cpu_gpr[rd], t0);
5342 break;
5343#endif
5344 }
5345 tcg_temp_free(t0);
284b731a
LA
5346}
5347
1f1b4c00
YK
5348#ifndef CONFIG_USER_ONLY
5349/* CP0 (MMU and control) */
5204ea79
LA
5350static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5351{
5352 TCGv_i64 t0 = tcg_temp_new_i64();
5353 TCGv_i64 t1 = tcg_temp_new_i64();
5354
5355 tcg_gen_ext_tl_i64(t0, arg);
5356 tcg_gen_ld_i64(t1, cpu_env, off);
5357#if defined(TARGET_MIPS64)
5358 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5359#else
5360 tcg_gen_concat32_i64(t1, t1, t0);
5361#endif
5362 tcg_gen_st_i64(t1, cpu_env, off);
5363 tcg_temp_free_i64(t1);
5364 tcg_temp_free_i64(t0);
5365}
5366
5367static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5368{
5369 TCGv_i64 t0 = tcg_temp_new_i64();
5370 TCGv_i64 t1 = tcg_temp_new_i64();
5371
5372 tcg_gen_ext_tl_i64(t0, arg);
5373 tcg_gen_ld_i64(t1, cpu_env, off);
5374 tcg_gen_concat32_i64(t1, t1, t0);
5375 tcg_gen_st_i64(t1, cpu_env, off);
5376 tcg_temp_free_i64(t1);
5377 tcg_temp_free_i64(t0);
5378}
5379
5380static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5381{
5382 TCGv_i64 t0 = tcg_temp_new_i64();
5383
5384 tcg_gen_ld_i64(t0, cpu_env, off);
5385#if defined(TARGET_MIPS64)
5386 tcg_gen_shri_i64(t0, t0, 30);
5387#else
5388 tcg_gen_shri_i64(t0, t0, 32);
5389#endif
5390 gen_move_low32(arg, t0);
5391 tcg_temp_free_i64(t0);
5392}
5393
5394static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5395{
5396 TCGv_i64 t0 = tcg_temp_new_i64();
5397
5398 tcg_gen_ld_i64(t0, cpu_env, off);
5399 tcg_gen_shri_i64(t0, t0, 32 + shift);
5400 gen_move_low32(arg, t0);
5401 tcg_temp_free_i64(t0);
5402}
5403
d9bea114 5404static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4f57689a 5405{
d9bea114 5406 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 5407
d9bea114
AJ
5408 tcg_gen_ld_i32(t0, cpu_env, off);
5409 tcg_gen_ext_i32_tl(arg, t0);
5410 tcg_temp_free_i32(t0);
4f57689a
TS
5411}
5412
d9bea114 5413static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4f57689a 5414{
d9bea114
AJ
5415 tcg_gen_ld_tl(arg, cpu_env, off);
5416 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
5417}
5418
d9bea114 5419static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
f1aa6320 5420{
d9bea114 5421 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 5422
d9bea114
AJ
5423 tcg_gen_trunc_tl_i32(t0, arg);
5424 tcg_gen_st_i32(t0, cpu_env, off);
5425 tcg_temp_free_i32(t0);
f1aa6320
TS
5426}
5427
c98d3d79
YK
5428#define CP0_CHECK(c) \
5429 do { \
5430 if (!(c)) { \
5431 goto cp0_unimplemented; \
5432 } \
5433 } while (0)
5434
5204ea79
LA
5435static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5436{
5437 const char *rn = "invalid";
5438
5204ea79
LA
5439 switch (reg) {
5440 case 2:
5441 switch (sel) {
5442 case 0:
59488dda 5443 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
5444 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5445 rn = "EntryLo0";
5446 break;
5447 default:
c98d3d79 5448 goto cp0_unimplemented;
5204ea79
LA
5449 }
5450 break;
5451 case 3:
5452 switch (sel) {
5453 case 0:
59488dda 5454 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
5455 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5456 rn = "EntryLo1";
5457 break;
5458 default:
c98d3d79 5459 goto cp0_unimplemented;
5204ea79
LA
5460 }
5461 break;
5462 case 17:
5463 switch (sel) {
5464 case 0:
5465 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
5466 ctx->CP0_LLAddr_shift);
5467 rn = "LLAddr";
5468 break;
f6d4dd81
YK
5469 case 1:
5470 CP0_CHECK(ctx->mrp);
5471 gen_helper_mfhc0_maar(arg, cpu_env);
5472 rn = "MAAR";
5473 break;
5204ea79 5474 default:
c98d3d79 5475 goto cp0_unimplemented;
5204ea79
LA
5476 }
5477 break;
5478 case 28:
5479 switch (sel) {
5480 case 0:
5481 case 2:
5482 case 4:
5483 case 6:
5484 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5485 rn = "TagLo";
5486 break;
5487 default:
c98d3d79 5488 goto cp0_unimplemented;
5204ea79
LA
5489 }
5490 break;
5491 default:
c98d3d79 5492 goto cp0_unimplemented;
5204ea79 5493 }
b44a7fb1 5494 trace_mips_translate_c0("mfhc0", rn, reg, sel);
5204ea79
LA
5495 return;
5496
c98d3d79 5497cp0_unimplemented:
965447ee 5498 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5204ea79
LA
5499 tcg_gen_movi_tl(arg, 0);
5500}
5501
5502static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5503{
5504 const char *rn = "invalid";
5505 uint64_t mask = ctx->PAMask >> 36;
5506
5204ea79
LA
5507 switch (reg) {
5508 case 2:
5509 switch (sel) {
5510 case 0:
59488dda 5511 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
5512 tcg_gen_andi_tl(arg, arg, mask);
5513 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5514 rn = "EntryLo0";
5515 break;
5516 default:
c98d3d79 5517 goto cp0_unimplemented;
5204ea79
LA
5518 }
5519 break;
5520 case 3:
5521 switch (sel) {
5522 case 0:
59488dda 5523 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
5524 tcg_gen_andi_tl(arg, arg, mask);
5525 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5526 rn = "EntryLo1";
5527 break;
5528 default:
c98d3d79 5529 goto cp0_unimplemented;
5204ea79
LA
5530 }
5531 break;
5532 case 17:
5533 switch (sel) {
5534 case 0:
5535 /* LLAddr is read-only (the only exception is bit 0 if LLB is
5536 supported); the CP0_LLAddr_rw_bitmask does not seem to be
5537 relevant for modern MIPS cores supporting MTHC0, therefore
5538 treating MTHC0 to LLAddr as NOP. */
5539 rn = "LLAddr";
5540 break;
f6d4dd81
YK
5541 case 1:
5542 CP0_CHECK(ctx->mrp);
5543 gen_helper_mthc0_maar(cpu_env, arg);
5544 rn = "MAAR";
5545 break;
5204ea79 5546 default:
c98d3d79 5547 goto cp0_unimplemented;
5204ea79
LA
5548 }
5549 break;
5550 case 28:
5551 switch (sel) {
5552 case 0:
5553 case 2:
5554 case 4:
5555 case 6:
5556 tcg_gen_andi_tl(arg, arg, mask);
5557 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5558 rn = "TagLo";
5559 break;
5560 default:
c98d3d79 5561 goto cp0_unimplemented;
5204ea79
LA
5562 }
5563 break;
5564 default:
c98d3d79 5565 goto cp0_unimplemented;
5204ea79 5566 }
b44a7fb1 5567 trace_mips_translate_c0("mthc0", rn, reg, sel);
5204ea79 5568
c98d3d79 5569cp0_unimplemented:
965447ee 5570 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
5204ea79
LA
5571}
5572
e98c0d17
LA
5573static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5574{
5575 if (ctx->insn_flags & ISA_MIPS32R6) {
5576 tcg_gen_movi_tl(arg, 0);
5577 } else {
5578 tcg_gen_movi_tl(arg, ~0);
5579 }
5580}
5581
d75c135e 5582static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 5583{
7a387fff 5584 const char *rn = "invalid";
873eb012 5585
e189e748 5586 if (sel != 0)
d75c135e 5587 check_insn(ctx, ISA_MIPS32);
e189e748 5588
873eb012
TS
5589 switch (reg) {
5590 case 0:
7a387fff
TS
5591 switch (sel) {
5592 case 0:
7db13fae 5593 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7a387fff
TS
5594 rn = "Index";
5595 break;
5596 case 1:
f31b035a 5597 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5598 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7a387fff 5599 rn = "MVPControl";
ead9360e 5600 break;
7a387fff 5601 case 2:
f31b035a 5602 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5603 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7a387fff 5604 rn = "MVPConf0";
ead9360e 5605 break;
7a387fff 5606 case 3:
f31b035a 5607 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5608 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7a387fff 5609 rn = "MVPConf1";
ead9360e 5610 break;
01bc435b
YK
5611 case 4:
5612 CP0_CHECK(ctx->vp);
5613 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
5614 rn = "VPControl";
5615 break;
7a387fff 5616 default:
f31b035a 5617 goto cp0_unimplemented;
7a387fff 5618 }
873eb012
TS
5619 break;
5620 case 1:
7a387fff
TS
5621 switch (sel) {
5622 case 0:
f31b035a 5623 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 5624 gen_helper_mfc0_random(arg, cpu_env);
7a387fff 5625 rn = "Random";
2423f660 5626 break;
7a387fff 5627 case 1:
f31b035a 5628 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5629 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7a387fff 5630 rn = "VPEControl";
ead9360e 5631 break;
7a387fff 5632 case 2:
f31b035a 5633 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5634 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7a387fff 5635 rn = "VPEConf0";
ead9360e 5636 break;
7a387fff 5637 case 3:
f31b035a 5638 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5639 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7a387fff 5640 rn = "VPEConf1";
ead9360e 5641 break;
7a387fff 5642 case 4:
f31b035a 5643 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5644 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7a387fff 5645 rn = "YQMask";
ead9360e 5646 break;
7a387fff 5647 case 5:
f31b035a 5648 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5649 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 5650 rn = "VPESchedule";
ead9360e 5651 break;
7a387fff 5652 case 6:
f31b035a 5653 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5654 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 5655 rn = "VPEScheFBack";
ead9360e 5656 break;
7a387fff 5657 case 7:
f31b035a 5658 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5659 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7a387fff 5660 rn = "VPEOpt";
ead9360e 5661 break;
7a387fff 5662 default:
f31b035a 5663 goto cp0_unimplemented;
7a387fff 5664 }
873eb012
TS
5665 break;
5666 case 2:
7a387fff
TS
5667 switch (sel) {
5668 case 0:
284b731a
LA
5669 {
5670 TCGv_i64 tmp = tcg_temp_new_i64();
5671 tcg_gen_ld_i64(tmp, cpu_env,
5672 offsetof(CPUMIPSState, CP0_EntryLo0));
7207c7f9 5673#if defined(TARGET_MIPS64)
284b731a
LA
5674 if (ctx->rxi) {
5675 /* Move RI/XI fields to bits 31:30 */
5676 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5677 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5678 }
7207c7f9 5679#endif
284b731a
LA
5680 gen_move_low32(arg, tmp);
5681 tcg_temp_free_i64(tmp);
5682 }
2423f660
TS
5683 rn = "EntryLo0";
5684 break;
7a387fff 5685 case 1:
f31b035a 5686 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5687 gen_helper_mfc0_tcstatus(arg, cpu_env);
2423f660 5688 rn = "TCStatus";
ead9360e 5689 break;
7a387fff 5690 case 2:
f31b035a 5691 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5692 gen_helper_mfc0_tcbind(arg, cpu_env);
2423f660 5693 rn = "TCBind";
ead9360e 5694 break;
7a387fff 5695 case 3:
f31b035a 5696 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5697 gen_helper_mfc0_tcrestart(arg, cpu_env);
2423f660 5698 rn = "TCRestart";
ead9360e 5699 break;
7a387fff 5700 case 4:
f31b035a 5701 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5702 gen_helper_mfc0_tchalt(arg, cpu_env);
2423f660 5703 rn = "TCHalt";
ead9360e 5704 break;
7a387fff 5705 case 5:
f31b035a 5706 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5707 gen_helper_mfc0_tccontext(arg, cpu_env);
2423f660 5708 rn = "TCContext";
ead9360e 5709 break;
7a387fff 5710 case 6:
f31b035a 5711 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5712 gen_helper_mfc0_tcschedule(arg, cpu_env);
2423f660 5713 rn = "TCSchedule";
ead9360e 5714 break;
7a387fff 5715 case 7:
f31b035a 5716 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5717 gen_helper_mfc0_tcschefback(arg, cpu_env);
2423f660 5718 rn = "TCScheFBack";
ead9360e 5719 break;
7a387fff 5720 default:
f31b035a 5721 goto cp0_unimplemented;
7a387fff 5722 }
873eb012
TS
5723 break;
5724 case 3:
7a387fff
TS
5725 switch (sel) {
5726 case 0:
284b731a
LA
5727 {
5728 TCGv_i64 tmp = tcg_temp_new_i64();
5729 tcg_gen_ld_i64(tmp, cpu_env,
5730 offsetof(CPUMIPSState, CP0_EntryLo1));
7207c7f9 5731#if defined(TARGET_MIPS64)
284b731a
LA
5732 if (ctx->rxi) {
5733 /* Move RI/XI fields to bits 31:30 */
5734 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5735 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5736 }
7207c7f9 5737#endif
284b731a
LA
5738 gen_move_low32(arg, tmp);
5739 tcg_temp_free_i64(tmp);
5740 }
2423f660
TS
5741 rn = "EntryLo1";
5742 break;
01bc435b
YK
5743 case 1:
5744 CP0_CHECK(ctx->vp);
5745 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5746 rn = "GlobalNumber";
5747 break;
7a387fff 5748 default:
f31b035a 5749 goto cp0_unimplemented;
1579a72e 5750 }
873eb012
TS
5751 break;
5752 case 4:
7a387fff
TS
5753 switch (sel) {
5754 case 0:
7db13fae 5755 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 5756 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
5757 rn = "Context";
5758 break;
7a387fff 5759 case 1:
d9bea114 5760// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660 5761 rn = "ContextConfig";
f31b035a 5762 goto cp0_unimplemented;
d279279e 5763 case 2:
f31b035a 5764 CP0_CHECK(ctx->ulri);
e40df9a8
JH
5765 tcg_gen_ld_tl(arg, cpu_env,
5766 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5767 tcg_gen_ext32s_tl(arg, arg);
f31b035a 5768 rn = "UserLocal";
d279279e 5769 break;
7a387fff 5770 default:
f31b035a 5771 goto cp0_unimplemented;
1579a72e 5772 }
873eb012
TS
5773 break;
5774 case 5:
7a387fff
TS
5775 switch (sel) {
5776 case 0:
7db13fae 5777 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
5778 rn = "PageMask";
5779 break;
7a387fff 5780 case 1:
d75c135e 5781 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5782 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
5783 rn = "PageGrain";
5784 break;
cec56a73
JH
5785 case 2:
5786 CP0_CHECK(ctx->sc);
5787 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
5788 tcg_gen_ext32s_tl(arg, arg);
5789 rn = "SegCtl0";
5790 break;
5791 case 3:
5792 CP0_CHECK(ctx->sc);
5793 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
5794 tcg_gen_ext32s_tl(arg, arg);
5795 rn = "SegCtl1";
5796 break;
5797 case 4:
5798 CP0_CHECK(ctx->sc);
5799 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
5800 tcg_gen_ext32s_tl(arg, arg);
5801 rn = "SegCtl2";
5802 break;
7a387fff 5803 default:
f31b035a 5804 goto cp0_unimplemented;
1579a72e 5805 }
873eb012
TS
5806 break;
5807 case 6:
7a387fff
TS
5808 switch (sel) {
5809 case 0:
7db13fae 5810 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
5811 rn = "Wired";
5812 break;
7a387fff 5813 case 1:
d75c135e 5814 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5815 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 5816 rn = "SRSConf0";
ead9360e 5817 break;
7a387fff 5818 case 2:
d75c135e 5819 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5820 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 5821 rn = "SRSConf1";
ead9360e 5822 break;
7a387fff 5823 case 3:
d75c135e 5824 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5825 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 5826 rn = "SRSConf2";
ead9360e 5827 break;
7a387fff 5828 case 4:
d75c135e 5829 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5830 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 5831 rn = "SRSConf3";
ead9360e 5832 break;
7a387fff 5833 case 5:
d75c135e 5834 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5835 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 5836 rn = "SRSConf4";
ead9360e 5837 break;
7a387fff 5838 default:
f31b035a 5839 goto cp0_unimplemented;
1579a72e 5840 }
873eb012 5841 break;
8c0fdd85 5842 case 7:
7a387fff
TS
5843 switch (sel) {
5844 case 0:
d75c135e 5845 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5846 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
5847 rn = "HWREna";
5848 break;
7a387fff 5849 default:
f31b035a 5850 goto cp0_unimplemented;
1579a72e 5851 }
8c0fdd85 5852 break;
873eb012 5853 case 8:
7a387fff
TS
5854 switch (sel) {
5855 case 0:
7db13fae 5856 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 5857 tcg_gen_ext32s_tl(arg, arg);
f0b3f3ae 5858 rn = "BadVAddr";
2423f660 5859 break;
aea14095 5860 case 1:
f31b035a
LA
5861 CP0_CHECK(ctx->bi);
5862 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5863 rn = "BadInstr";
aea14095
LA
5864 break;
5865 case 2:
f31b035a
LA
5866 CP0_CHECK(ctx->bp);
5867 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5868 rn = "BadInstrP";
aea14095 5869 break;
25beba9b
SM
5870 case 3:
5871 CP0_CHECK(ctx->bi);
5872 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
5873 tcg_gen_andi_tl(arg, arg, ~0xffff);
5874 rn = "BadInstrX";
5875 break;
5876 default:
f31b035a 5877 goto cp0_unimplemented;
aea14095 5878 }
873eb012
TS
5879 break;
5880 case 9:
7a387fff
TS
5881 switch (sel) {
5882 case 0:
2e70f6ef 5883 /* Mark as an IO operation because we read the time. */
eeb3bba8 5884 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 5885 gen_io_start();
bd79255d 5886 }
895c2d04 5887 gen_helper_mfc0_count(arg, cpu_env);
eeb3bba8 5888 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 5889 gen_io_end();
2e70f6ef 5890 }
55807224 5891 /* Break the TB to be able to take timer interrupts immediately
b28425ba
EC
5892 after reading count. DISAS_STOP isn't sufficient, we need to
5893 ensure we break completely out of translated code. */
eeb3bba8
EC
5894 gen_save_pc(ctx->base.pc_next + 4);
5895 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
5896 rn = "Count";
5897 break;
5898 /* 6,7 are implementation dependent */
7a387fff 5899 default:
f31b035a 5900 goto cp0_unimplemented;
2423f660 5901 }
873eb012
TS
5902 break;
5903 case 10:
7a387fff
TS
5904 switch (sel) {
5905 case 0:
7db13fae 5906 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 5907 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
5908 rn = "EntryHi";
5909 break;
7a387fff 5910 default:
f31b035a 5911 goto cp0_unimplemented;
1579a72e 5912 }
873eb012
TS
5913 break;
5914 case 11:
7a387fff
TS
5915 switch (sel) {
5916 case 0:
7db13fae 5917 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
5918 rn = "Compare";
5919 break;
5920 /* 6,7 are implementation dependent */
7a387fff 5921 default:
f31b035a 5922 goto cp0_unimplemented;
2423f660 5923 }
873eb012
TS
5924 break;
5925 case 12:
7a387fff
TS
5926 switch (sel) {
5927 case 0:
7db13fae 5928 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
5929 rn = "Status";
5930 break;
7a387fff 5931 case 1:
d75c135e 5932 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5933 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
5934 rn = "IntCtl";
5935 break;
7a387fff 5936 case 2:
d75c135e 5937 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5938 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
5939 rn = "SRSCtl";
5940 break;
7a387fff 5941 case 3:
d75c135e 5942 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5943 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660 5944 rn = "SRSMap";
fd88b6ab 5945 break;
7a387fff 5946 default:
f31b035a 5947 goto cp0_unimplemented;
7a387fff 5948 }
873eb012
TS
5949 break;
5950 case 13:
7a387fff
TS
5951 switch (sel) {
5952 case 0:
7db13fae 5953 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
5954 rn = "Cause";
5955 break;
7a387fff 5956 default:
f31b035a 5957 goto cp0_unimplemented;
7a387fff 5958 }
873eb012
TS
5959 break;
5960 case 14:
7a387fff
TS
5961 switch (sel) {
5962 case 0:
7db13fae 5963 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 5964 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
5965 rn = "EPC";
5966 break;
7a387fff 5967 default:
f31b035a 5968 goto cp0_unimplemented;
1579a72e 5969 }
873eb012
TS
5970 break;
5971 case 15:
7a387fff
TS
5972 switch (sel) {
5973 case 0:
7db13fae 5974 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
5975 rn = "PRid";
5976 break;
7a387fff 5977 case 1:
d75c135e 5978 check_insn(ctx, ISA_MIPS32R2);
74dbf824
JH
5979 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
5980 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
5981 rn = "EBase";
5982 break;
c870e3f5
YK
5983 case 3:
5984 check_insn(ctx, ISA_MIPS32R2);
5985 CP0_CHECK(ctx->cmgcr);
5986 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
5987 tcg_gen_ext32s_tl(arg, arg);
5988 rn = "CMGCRBase";
5989 break;
7a387fff 5990 default:
f31b035a 5991 goto cp0_unimplemented;
7a387fff 5992 }
873eb012
TS
5993 break;
5994 case 16:
5995 switch (sel) {
5996 case 0:
7db13fae 5997 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
873eb012
TS
5998 rn = "Config";
5999 break;
6000 case 1:
7db13fae 6001 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
873eb012
TS
6002 rn = "Config1";
6003 break;
7a387fff 6004 case 2:
7db13fae 6005 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7a387fff
TS
6006 rn = "Config2";
6007 break;
6008 case 3:
7db13fae 6009 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7a387fff
TS
6010 rn = "Config3";
6011 break;
b4160af1
PJ
6012 case 4:
6013 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6014 rn = "Config4";
6015 break;
b4dd99a3
PJ
6016 case 5:
6017 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6018 rn = "Config5";
6019 break;
e397ee33
TS
6020 /* 6,7 are implementation dependent */
6021 case 6:
7db13fae 6022 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
e397ee33
TS
6023 rn = "Config6";
6024 break;
6025 case 7:
7db13fae 6026 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
e397ee33
TS
6027 rn = "Config7";
6028 break;
873eb012 6029 default:
f31b035a 6030 goto cp0_unimplemented;
873eb012
TS
6031 }
6032 break;
6033 case 17:
7a387fff
TS
6034 switch (sel) {
6035 case 0:
895c2d04 6036 gen_helper_mfc0_lladdr(arg, cpu_env);
2423f660
TS
6037 rn = "LLAddr";
6038 break;
f6d4dd81
YK
6039 case 1:
6040 CP0_CHECK(ctx->mrp);
6041 gen_helper_mfc0_maar(arg, cpu_env);
6042 rn = "MAAR";
6043 break;
6044 case 2:
6045 CP0_CHECK(ctx->mrp);
6046 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6047 rn = "MAARI";
6048 break;
7a387fff 6049 default:
f31b035a 6050 goto cp0_unimplemented;
7a387fff 6051 }
873eb012
TS
6052 break;
6053 case 18:
7a387fff 6054 switch (sel) {
c2e19f3c
AM
6055 case 0:
6056 case 1:
6057 case 2:
6058 case 3:
6059 case 4:
6060 case 5:
6061 case 6:
6062 case 7:
fa192d49 6063 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 6064 gen_helper_1e0i(mfc0_watchlo, arg, sel);
2423f660
TS
6065 rn = "WatchLo";
6066 break;
7a387fff 6067 default:
f31b035a 6068 goto cp0_unimplemented;
7a387fff 6069 }
873eb012
TS
6070 break;
6071 case 19:
7a387fff 6072 switch (sel) {
c2e19f3c
AM
6073 case 0:
6074 case 1:
6075 case 2:
6076 case 3:
6077 case 4:
6078 case 5:
6079 case 6:
6080 case 7:
fa192d49 6081 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 6082 gen_helper_1e0i(mfc0_watchhi, arg, sel);
2423f660
TS
6083 rn = "WatchHi";
6084 break;
7a387fff 6085 default:
f31b035a 6086 goto cp0_unimplemented;
7a387fff 6087 }
873eb012 6088 break;
8c0fdd85 6089 case 20:
7a387fff
TS
6090 switch (sel) {
6091 case 0:
d26bc211 6092#if defined(TARGET_MIPS64)
d75c135e 6093 check_insn(ctx, ISA_MIPS3);
7db13fae 6094 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 6095 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
6096 rn = "XContext";
6097 break;
703eaf37 6098#endif
7a387fff 6099 default:
f31b035a 6100 goto cp0_unimplemented;
7a387fff 6101 }
8c0fdd85
TS
6102 break;
6103 case 21:
7a387fff 6104 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 6105 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
6106 switch (sel) {
6107 case 0:
7db13fae 6108 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
6109 rn = "Framemask";
6110 break;
7a387fff 6111 default:
f31b035a 6112 goto cp0_unimplemented;
7a387fff 6113 }
8c0fdd85
TS
6114 break;
6115 case 22:
d9bea114 6116 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
6117 rn = "'Diagnostic"; /* implementation dependent */
6118 break;
873eb012 6119 case 23:
7a387fff
TS
6120 switch (sel) {
6121 case 0:
895c2d04 6122 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
2423f660
TS
6123 rn = "Debug";
6124 break;
7a387fff 6125 case 1:
d9bea114 6126// gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
2423f660 6127 rn = "TraceControl";
3570d7f6 6128 goto cp0_unimplemented;
7a387fff 6129 case 2:
d9bea114 6130// gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
2423f660 6131 rn = "TraceControl2";
3570d7f6 6132 goto cp0_unimplemented;
7a387fff 6133 case 3:
d9bea114 6134// gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
2423f660 6135 rn = "UserTraceData";
3570d7f6 6136 goto cp0_unimplemented;
7a387fff 6137 case 4:
d9bea114 6138// gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
2423f660 6139 rn = "TraceBPC";
3570d7f6 6140 goto cp0_unimplemented;
7a387fff 6141 default:
f31b035a 6142 goto cp0_unimplemented;
7a387fff 6143 }
873eb012
TS
6144 break;
6145 case 24:
7a387fff
TS
6146 switch (sel) {
6147 case 0:
f0b3f3ae 6148 /* EJTAG support */
7db13fae 6149 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 6150 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
6151 rn = "DEPC";
6152 break;
7a387fff 6153 default:
f31b035a 6154 goto cp0_unimplemented;
7a387fff 6155 }
873eb012 6156 break;
8c0fdd85 6157 case 25:
7a387fff
TS
6158 switch (sel) {
6159 case 0:
7db13fae 6160 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 6161 rn = "Performance0";
7a387fff
TS
6162 break;
6163 case 1:
d9bea114 6164// gen_helper_mfc0_performance1(arg);
2423f660 6165 rn = "Performance1";
3570d7f6 6166 goto cp0_unimplemented;
7a387fff 6167 case 2:
d9bea114 6168// gen_helper_mfc0_performance2(arg);
2423f660 6169 rn = "Performance2";
3570d7f6 6170 goto cp0_unimplemented;
7a387fff 6171 case 3:
d9bea114 6172// gen_helper_mfc0_performance3(arg);
2423f660 6173 rn = "Performance3";
3570d7f6 6174 goto cp0_unimplemented;
7a387fff 6175 case 4:
d9bea114 6176// gen_helper_mfc0_performance4(arg);
2423f660 6177 rn = "Performance4";
3570d7f6 6178 goto cp0_unimplemented;
7a387fff 6179 case 5:
d9bea114 6180// gen_helper_mfc0_performance5(arg);
2423f660 6181 rn = "Performance5";
3570d7f6 6182 goto cp0_unimplemented;
7a387fff 6183 case 6:
d9bea114 6184// gen_helper_mfc0_performance6(arg);
2423f660 6185 rn = "Performance6";
3570d7f6 6186 goto cp0_unimplemented;
7a387fff 6187 case 7:
d9bea114 6188// gen_helper_mfc0_performance7(arg);
2423f660 6189 rn = "Performance7";
3570d7f6 6190 goto cp0_unimplemented;
7a387fff 6191 default:
f31b035a 6192 goto cp0_unimplemented;
7a387fff 6193 }
8c0fdd85
TS
6194 break;
6195 case 26:
0d74a222
LA
6196 switch (sel) {
6197 case 0:
6198 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6199 rn = "ErrCtl";
6200 break;
6201 default:
6202 goto cp0_unimplemented;
6203 }
da80682b 6204 break;
8c0fdd85 6205 case 27:
7a387fff 6206 switch (sel) {
c2e19f3c
AM
6207 case 0:
6208 case 1:
6209 case 2:
6210 case 3:
d9bea114 6211 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
6212 rn = "CacheErr";
6213 break;
7a387fff 6214 default:
f31b035a 6215 goto cp0_unimplemented;
7a387fff 6216 }
8c0fdd85 6217 break;
873eb012
TS
6218 case 28:
6219 switch (sel) {
6220 case 0:
7a387fff
TS
6221 case 2:
6222 case 4:
6223 case 6:
284b731a
LA
6224 {
6225 TCGv_i64 tmp = tcg_temp_new_i64();
6226 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
6227 gen_move_low32(arg, tmp);
6228 tcg_temp_free_i64(tmp);
6229 }
873eb012
TS
6230 rn = "TagLo";
6231 break;
6232 case 1:
7a387fff
TS
6233 case 3:
6234 case 5:
6235 case 7:
7db13fae 6236 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
873eb012
TS
6237 rn = "DataLo";
6238 break;
6239 default:
f31b035a 6240 goto cp0_unimplemented;
873eb012
TS
6241 }
6242 break;
8c0fdd85 6243 case 29:
7a387fff
TS
6244 switch (sel) {
6245 case 0:
6246 case 2:
6247 case 4:
6248 case 6:
7db13fae 6249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7a387fff
TS
6250 rn = "TagHi";
6251 break;
6252 case 1:
6253 case 3:
6254 case 5:
6255 case 7:
7db13fae 6256 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7a387fff
TS
6257 rn = "DataHi";
6258 break;
6259 default:
f31b035a 6260 goto cp0_unimplemented;
7a387fff 6261 }
8c0fdd85 6262 break;
873eb012 6263 case 30:
7a387fff
TS
6264 switch (sel) {
6265 case 0:
7db13fae 6266 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 6267 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
6268 rn = "ErrorEPC";
6269 break;
7a387fff 6270 default:
f31b035a 6271 goto cp0_unimplemented;
7a387fff 6272 }
873eb012
TS
6273 break;
6274 case 31:
7a387fff
TS
6275 switch (sel) {
6276 case 0:
f0b3f3ae 6277 /* EJTAG support */
7db13fae 6278 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
6279 rn = "DESAVE";
6280 break;
c2e19f3c
AM
6281 case 2:
6282 case 3:
6283 case 4:
6284 case 5:
6285 case 6:
6286 case 7:
f31b035a
LA
6287 CP0_CHECK(ctx->kscrexist & (1 << sel));
6288 tcg_gen_ld_tl(arg, cpu_env,
6289 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6290 tcg_gen_ext32s_tl(arg, arg);
6291 rn = "KScratch";
e98c0d17 6292 break;
7a387fff 6293 default:
f31b035a 6294 goto cp0_unimplemented;
7a387fff 6295 }
873eb012
TS
6296 break;
6297 default:
f31b035a 6298 goto cp0_unimplemented;
873eb012 6299 }
b44a7fb1 6300 trace_mips_translate_c0("mfc0", rn, reg, sel);
873eb012
TS
6301 return;
6302
f31b035a 6303cp0_unimplemented:
965447ee 6304 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
f31b035a 6305 gen_mfc0_unimplemented(ctx, arg);
873eb012
TS
6306}
6307
d75c135e 6308static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 6309{
7a387fff
TS
6310 const char *rn = "invalid";
6311
e189e748 6312 if (sel != 0)
d75c135e 6313 check_insn(ctx, ISA_MIPS32);
e189e748 6314
eeb3bba8 6315 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6316 gen_io_start();
bd79255d 6317 }
2e70f6ef 6318
8c0fdd85
TS
6319 switch (reg) {
6320 case 0:
7a387fff
TS
6321 switch (sel) {
6322 case 0:
895c2d04 6323 gen_helper_mtc0_index(cpu_env, arg);
7a387fff
TS
6324 rn = "Index";
6325 break;
6326 case 1:
f31b035a 6327 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6328 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7a387fff 6329 rn = "MVPControl";
ead9360e 6330 break;
7a387fff 6331 case 2:
f31b035a 6332 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 6333 /* ignored */
7a387fff 6334 rn = "MVPConf0";
ead9360e 6335 break;
7a387fff 6336 case 3:
f31b035a 6337 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 6338 /* ignored */
7a387fff 6339 rn = "MVPConf1";
ead9360e 6340 break;
01bc435b
YK
6341 case 4:
6342 CP0_CHECK(ctx->vp);
6343 /* ignored */
6344 rn = "VPControl";
6345 break;
7a387fff 6346 default:
f31b035a 6347 goto cp0_unimplemented;
7a387fff 6348 }
8c0fdd85
TS
6349 break;
6350 case 1:
7a387fff
TS
6351 switch (sel) {
6352 case 0:
2423f660 6353 /* ignored */
7a387fff 6354 rn = "Random";
2423f660 6355 break;
7a387fff 6356 case 1:
f31b035a 6357 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6358 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7a387fff 6359 rn = "VPEControl";
ead9360e 6360 break;
7a387fff 6361 case 2:
f31b035a 6362 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6363 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7a387fff 6364 rn = "VPEConf0";
ead9360e 6365 break;
7a387fff 6366 case 3:
f31b035a 6367 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6368 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7a387fff 6369 rn = "VPEConf1";
ead9360e 6370 break;
7a387fff 6371 case 4:
f31b035a 6372 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6373 gen_helper_mtc0_yqmask(cpu_env, arg);
7a387fff 6374 rn = "YQMask";
ead9360e 6375 break;
7a387fff 6376 case 5:
f31b035a 6377 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
6378 tcg_gen_st_tl(arg, cpu_env,
6379 offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 6380 rn = "VPESchedule";
ead9360e 6381 break;
7a387fff 6382 case 6:
f31b035a 6383 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
6384 tcg_gen_st_tl(arg, cpu_env,
6385 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 6386 rn = "VPEScheFBack";
ead9360e 6387 break;
7a387fff 6388 case 7:
f31b035a 6389 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6390 gen_helper_mtc0_vpeopt(cpu_env, arg);
7a387fff 6391 rn = "VPEOpt";
ead9360e 6392 break;
7a387fff 6393 default:
f31b035a 6394 goto cp0_unimplemented;
7a387fff 6395 }
8c0fdd85
TS
6396 break;
6397 case 2:
7a387fff
TS
6398 switch (sel) {
6399 case 0:
895c2d04 6400 gen_helper_mtc0_entrylo0(cpu_env, arg);
2423f660
TS
6401 rn = "EntryLo0";
6402 break;
7a387fff 6403 case 1:
f31b035a 6404 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6405 gen_helper_mtc0_tcstatus(cpu_env, arg);
2423f660 6406 rn = "TCStatus";
ead9360e 6407 break;
7a387fff 6408 case 2:
f31b035a 6409 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6410 gen_helper_mtc0_tcbind(cpu_env, arg);
2423f660 6411 rn = "TCBind";
ead9360e 6412 break;
7a387fff 6413 case 3:
f31b035a 6414 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6415 gen_helper_mtc0_tcrestart(cpu_env, arg);
2423f660 6416 rn = "TCRestart";
ead9360e 6417 break;
7a387fff 6418 case 4:
f31b035a 6419 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6420 gen_helper_mtc0_tchalt(cpu_env, arg);
2423f660 6421 rn = "TCHalt";
ead9360e 6422 break;
7a387fff 6423 case 5:
f31b035a 6424 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6425 gen_helper_mtc0_tccontext(cpu_env, arg);
2423f660 6426 rn = "TCContext";
ead9360e 6427 break;
7a387fff 6428 case 6:
f31b035a 6429 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6430 gen_helper_mtc0_tcschedule(cpu_env, arg);
2423f660 6431 rn = "TCSchedule";
ead9360e 6432 break;
7a387fff 6433 case 7:
f31b035a 6434 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6435 gen_helper_mtc0_tcschefback(cpu_env, arg);
2423f660 6436 rn = "TCScheFBack";
ead9360e 6437 break;
7a387fff 6438 default:
f31b035a 6439 goto cp0_unimplemented;
7a387fff 6440 }
8c0fdd85
TS
6441 break;
6442 case 3:
7a387fff
TS
6443 switch (sel) {
6444 case 0:
895c2d04 6445 gen_helper_mtc0_entrylo1(cpu_env, arg);
2423f660
TS
6446 rn = "EntryLo1";
6447 break;
01bc435b
YK
6448 case 1:
6449 CP0_CHECK(ctx->vp);
6450 /* ignored */
6451 rn = "GlobalNumber";
6452 break;
7a387fff 6453 default:
f31b035a 6454 goto cp0_unimplemented;
876d4b07 6455 }
8c0fdd85
TS
6456 break;
6457 case 4:
7a387fff
TS
6458 switch (sel) {
6459 case 0:
895c2d04 6460 gen_helper_mtc0_context(cpu_env, arg);
2423f660
TS
6461 rn = "Context";
6462 break;
7a387fff 6463 case 1:
895c2d04 6464// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
2423f660 6465 rn = "ContextConfig";
f31b035a 6466 goto cp0_unimplemented;
d279279e 6467 case 2:
f31b035a
LA
6468 CP0_CHECK(ctx->ulri);
6469 tcg_gen_st_tl(arg, cpu_env,
6470 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6471 rn = "UserLocal";
d279279e 6472 break;
7a387fff 6473 default:
f31b035a 6474 goto cp0_unimplemented;
876d4b07 6475 }
8c0fdd85
TS
6476 break;
6477 case 5:
7a387fff
TS
6478 switch (sel) {
6479 case 0:
895c2d04 6480 gen_helper_mtc0_pagemask(cpu_env, arg);
2423f660
TS
6481 rn = "PageMask";
6482 break;
7a387fff 6483 case 1:
d75c135e 6484 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6485 gen_helper_mtc0_pagegrain(cpu_env, arg);
2423f660 6486 rn = "PageGrain";
eeb3bba8 6487 ctx->base.is_jmp = DISAS_STOP;
2423f660 6488 break;
cec56a73
JH
6489 case 2:
6490 CP0_CHECK(ctx->sc);
6491 gen_helper_mtc0_segctl0(cpu_env, arg);
6492 rn = "SegCtl0";
6493 break;
6494 case 3:
6495 CP0_CHECK(ctx->sc);
6496 gen_helper_mtc0_segctl1(cpu_env, arg);
6497 rn = "SegCtl1";
6498 break;
6499 case 4:
6500 CP0_CHECK(ctx->sc);
6501 gen_helper_mtc0_segctl2(cpu_env, arg);
6502 rn = "SegCtl2";
6503 break;
7a387fff 6504 default:
f31b035a 6505 goto cp0_unimplemented;
876d4b07 6506 }
8c0fdd85
TS
6507 break;
6508 case 6:
7a387fff
TS
6509 switch (sel) {
6510 case 0:
895c2d04 6511 gen_helper_mtc0_wired(cpu_env, arg);
2423f660
TS
6512 rn = "Wired";
6513 break;
7a387fff 6514 case 1:
d75c135e 6515 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6516 gen_helper_mtc0_srsconf0(cpu_env, arg);
2423f660 6517 rn = "SRSConf0";
ead9360e 6518 break;
7a387fff 6519 case 2:
d75c135e 6520 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6521 gen_helper_mtc0_srsconf1(cpu_env, arg);
2423f660 6522 rn = "SRSConf1";
ead9360e 6523 break;
7a387fff 6524 case 3:
d75c135e 6525 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6526 gen_helper_mtc0_srsconf2(cpu_env, arg);
2423f660 6527 rn = "SRSConf2";
ead9360e 6528 break;
7a387fff 6529 case 4:
d75c135e 6530 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6531 gen_helper_mtc0_srsconf3(cpu_env, arg);
2423f660 6532 rn = "SRSConf3";
ead9360e 6533 break;
7a387fff 6534 case 5:
d75c135e 6535 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6536 gen_helper_mtc0_srsconf4(cpu_env, arg);
2423f660 6537 rn = "SRSConf4";
ead9360e 6538 break;
7a387fff 6539 default:
f31b035a 6540 goto cp0_unimplemented;
876d4b07 6541 }
8c0fdd85
TS
6542 break;
6543 case 7:
7a387fff
TS
6544 switch (sel) {
6545 case 0:
d75c135e 6546 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6547 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 6548 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
6549 rn = "HWREna";
6550 break;
7a387fff 6551 default:
f31b035a 6552 goto cp0_unimplemented;
876d4b07 6553 }
8c0fdd85
TS
6554 break;
6555 case 8:
aea14095
LA
6556 switch (sel) {
6557 case 0:
6558 /* ignored */
6559 rn = "BadVAddr";
6560 break;
6561 case 1:
6562 /* ignored */
6563 rn = "BadInstr";
6564 break;
6565 case 2:
6566 /* ignored */
6567 rn = "BadInstrP";
6568 break;
25beba9b
SM
6569 case 3:
6570 /* ignored */
6571 rn = "BadInstrX";
6572 break;
aea14095 6573 default:
f31b035a 6574 goto cp0_unimplemented;
aea14095 6575 }
8c0fdd85
TS
6576 break;
6577 case 9:
7a387fff
TS
6578 switch (sel) {
6579 case 0:
895c2d04 6580 gen_helper_mtc0_count(cpu_env, arg);
2423f660
TS
6581 rn = "Count";
6582 break;
876d4b07 6583 /* 6,7 are implementation dependent */
7a387fff 6584 default:
f31b035a 6585 goto cp0_unimplemented;
876d4b07 6586 }
8c0fdd85
TS
6587 break;
6588 case 10:
7a387fff
TS
6589 switch (sel) {
6590 case 0:
895c2d04 6591 gen_helper_mtc0_entryhi(cpu_env, arg);
2423f660
TS
6592 rn = "EntryHi";
6593 break;
7a387fff 6594 default:
f31b035a 6595 goto cp0_unimplemented;
876d4b07 6596 }
8c0fdd85
TS
6597 break;
6598 case 11:
7a387fff
TS
6599 switch (sel) {
6600 case 0:
895c2d04 6601 gen_helper_mtc0_compare(cpu_env, arg);
2423f660
TS
6602 rn = "Compare";
6603 break;
6604 /* 6,7 are implementation dependent */
7a387fff 6605 default:
f31b035a 6606 goto cp0_unimplemented;
876d4b07 6607 }
8c0fdd85
TS
6608 break;
6609 case 12:
7a387fff
TS
6610 switch (sel) {
6611 case 0:
867abc7e 6612 save_cpu_state(ctx, 1);
895c2d04 6613 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 6614 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
6615 gen_save_pc(ctx->base.pc_next + 4);
6616 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
6617 rn = "Status";
6618 break;
7a387fff 6619 case 1:
d75c135e 6620 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6621 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 6622 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6623 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
6624 rn = "IntCtl";
6625 break;
7a387fff 6626 case 2:
d75c135e 6627 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6628 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 6629 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6630 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
6631 rn = "SRSCtl";
6632 break;
7a387fff 6633 case 3:
d75c135e 6634 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6635 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 6636 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6637 ctx->base.is_jmp = DISAS_STOP;
2423f660 6638 rn = "SRSMap";
fd88b6ab 6639 break;
7a387fff 6640 default:
f31b035a 6641 goto cp0_unimplemented;
876d4b07 6642 }
8c0fdd85
TS
6643 break;
6644 case 13:
7a387fff
TS
6645 switch (sel) {
6646 case 0:
867abc7e 6647 save_cpu_state(ctx, 1);
895c2d04 6648 gen_helper_mtc0_cause(cpu_env, arg);
b28425ba
EC
6649 /* Stop translation as we may have triggered an interrupt.
6650 * DISAS_STOP isn't sufficient, we need to ensure we break out of
6651 * translated code to check for pending interrupts. */
eeb3bba8
EC
6652 gen_save_pc(ctx->base.pc_next + 4);
6653 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
6654 rn = "Cause";
6655 break;
7a387fff 6656 default:
f31b035a 6657 goto cp0_unimplemented;
876d4b07 6658 }
8c0fdd85
TS
6659 break;
6660 case 14:
7a387fff
TS
6661 switch (sel) {
6662 case 0:
d54a299b 6663 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
6664 rn = "EPC";
6665 break;
7a387fff 6666 default:
f31b035a 6667 goto cp0_unimplemented;
876d4b07 6668 }
8c0fdd85
TS
6669 break;
6670 case 15:
7a387fff
TS
6671 switch (sel) {
6672 case 0:
2423f660
TS
6673 /* ignored */
6674 rn = "PRid";
6675 break;
7a387fff 6676 case 1:
d75c135e 6677 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6678 gen_helper_mtc0_ebase(cpu_env, arg);
2423f660
TS
6679 rn = "EBase";
6680 break;
7a387fff 6681 default:
f31b035a 6682 goto cp0_unimplemented;
1579a72e 6683 }
8c0fdd85
TS
6684 break;
6685 case 16:
6686 switch (sel) {
6687 case 0:
895c2d04 6688 gen_helper_mtc0_config0(cpu_env, arg);
7a387fff 6689 rn = "Config";
2423f660 6690 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6691 ctx->base.is_jmp = DISAS_STOP;
7a387fff
TS
6692 break;
6693 case 1:
e397ee33 6694 /* ignored, read only */
7a387fff
TS
6695 rn = "Config1";
6696 break;
6697 case 2:
895c2d04 6698 gen_helper_mtc0_config2(cpu_env, arg);
7a387fff 6699 rn = "Config2";
2423f660 6700 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6701 ctx->base.is_jmp = DISAS_STOP;
8c0fdd85 6702 break;
7a387fff 6703 case 3:
90f12d73 6704 gen_helper_mtc0_config3(cpu_env, arg);
7a387fff 6705 rn = "Config3";
90f12d73 6706 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6707 ctx->base.is_jmp = DISAS_STOP;
7a387fff 6708 break;
b4160af1
PJ
6709 case 4:
6710 gen_helper_mtc0_config4(cpu_env, arg);
6711 rn = "Config4";
eeb3bba8 6712 ctx->base.is_jmp = DISAS_STOP;
b4160af1 6713 break;
b4dd99a3
PJ
6714 case 5:
6715 gen_helper_mtc0_config5(cpu_env, arg);
6716 rn = "Config5";
6717 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6718 ctx->base.is_jmp = DISAS_STOP;
b4dd99a3 6719 break;
e397ee33
TS
6720 /* 6,7 are implementation dependent */
6721 case 6:
6722 /* ignored */
6723 rn = "Config6";
6724 break;
6725 case 7:
6726 /* ignored */
6727 rn = "Config7";
6728 break;
8c0fdd85
TS
6729 default:
6730 rn = "Invalid config selector";
f31b035a 6731 goto cp0_unimplemented;
8c0fdd85
TS
6732 }
6733 break;
6734 case 17:
7a387fff
TS
6735 switch (sel) {
6736 case 0:
895c2d04 6737 gen_helper_mtc0_lladdr(cpu_env, arg);
2423f660
TS
6738 rn = "LLAddr";
6739 break;
f6d4dd81
YK
6740 case 1:
6741 CP0_CHECK(ctx->mrp);
6742 gen_helper_mtc0_maar(cpu_env, arg);
6743 rn = "MAAR";
6744 break;
6745 case 2:
6746 CP0_CHECK(ctx->mrp);
6747 gen_helper_mtc0_maari(cpu_env, arg);
6748 rn = "MAARI";
6749 break;
7a387fff 6750 default:
f31b035a 6751 goto cp0_unimplemented;
7a387fff 6752 }
8c0fdd85
TS
6753 break;
6754 case 18:
7a387fff 6755 switch (sel) {
c2e19f3c
AM
6756 case 0:
6757 case 1:
6758 case 2:
6759 case 3:
6760 case 4:
6761 case 5:
6762 case 6:
6763 case 7:
fa192d49 6764 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 6765 gen_helper_0e1i(mtc0_watchlo, arg, sel);
2423f660
TS
6766 rn = "WatchLo";
6767 break;
7a387fff 6768 default:
f31b035a 6769 goto cp0_unimplemented;
7a387fff 6770 }
8c0fdd85
TS
6771 break;
6772 case 19:
7a387fff 6773 switch (sel) {
c2e19f3c
AM
6774 case 0:
6775 case 1:
6776 case 2:
6777 case 3:
6778 case 4:
6779 case 5:
6780 case 6:
6781 case 7:
fa192d49 6782 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 6783 gen_helper_0e1i(mtc0_watchhi, arg, sel);
2423f660
TS
6784 rn = "WatchHi";
6785 break;
7a387fff 6786 default:
f31b035a 6787 goto cp0_unimplemented;
7a387fff 6788 }
8c0fdd85
TS
6789 break;
6790 case 20:
7a387fff
TS
6791 switch (sel) {
6792 case 0:
d26bc211 6793#if defined(TARGET_MIPS64)
d75c135e 6794 check_insn(ctx, ISA_MIPS3);
895c2d04 6795 gen_helper_mtc0_xcontext(cpu_env, arg);
2423f660
TS
6796 rn = "XContext";
6797 break;
703eaf37 6798#endif
7a387fff 6799 default:
f31b035a 6800 goto cp0_unimplemented;
7a387fff 6801 }
8c0fdd85
TS
6802 break;
6803 case 21:
7a387fff 6804 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 6805 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
6806 switch (sel) {
6807 case 0:
895c2d04 6808 gen_helper_mtc0_framemask(cpu_env, arg);
2423f660
TS
6809 rn = "Framemask";
6810 break;
7a387fff 6811 default:
f31b035a 6812 goto cp0_unimplemented;
7a387fff
TS
6813 }
6814 break;
8c0fdd85 6815 case 22:
7a387fff
TS
6816 /* ignored */
6817 rn = "Diagnostic"; /* implementation dependent */
2423f660 6818 break;
8c0fdd85 6819 case 23:
7a387fff
TS
6820 switch (sel) {
6821 case 0:
895c2d04 6822 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 6823 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
6824 gen_save_pc(ctx->base.pc_next + 4);
6825 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
6826 rn = "Debug";
6827 break;
7a387fff 6828 case 1:
895c2d04 6829// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
2423f660 6830 rn = "TraceControl";
8487327a 6831 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6832 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 6833 goto cp0_unimplemented;
7a387fff 6834 case 2:
895c2d04 6835// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
2423f660 6836 rn = "TraceControl2";
8487327a 6837 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6838 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 6839 goto cp0_unimplemented;
7a387fff 6840 case 3:
8487327a 6841 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6842 ctx->base.is_jmp = DISAS_STOP;
895c2d04 6843// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
2423f660 6844 rn = "UserTraceData";
8487327a 6845 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6846 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 6847 goto cp0_unimplemented;
7a387fff 6848 case 4:
895c2d04 6849// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a 6850 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6851 ctx->base.is_jmp = DISAS_STOP;
2423f660 6852 rn = "TraceBPC";
3570d7f6 6853 goto cp0_unimplemented;
7a387fff 6854 default:
f31b035a 6855 goto cp0_unimplemented;
7a387fff 6856 }
8c0fdd85
TS
6857 break;
6858 case 24:
7a387fff
TS
6859 switch (sel) {
6860 case 0:
f1aa6320 6861 /* EJTAG support */
d54a299b 6862 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
6863 rn = "DEPC";
6864 break;
7a387fff 6865 default:
f31b035a 6866 goto cp0_unimplemented;
7a387fff 6867 }
8c0fdd85
TS
6868 break;
6869 case 25:
7a387fff
TS
6870 switch (sel) {
6871 case 0:
895c2d04 6872 gen_helper_mtc0_performance0(cpu_env, arg);
2423f660
TS
6873 rn = "Performance0";
6874 break;
7a387fff 6875 case 1:
d9bea114 6876// gen_helper_mtc0_performance1(arg);
2423f660 6877 rn = "Performance1";
3570d7f6 6878 goto cp0_unimplemented;
7a387fff 6879 case 2:
d9bea114 6880// gen_helper_mtc0_performance2(arg);
2423f660 6881 rn = "Performance2";
3570d7f6 6882 goto cp0_unimplemented;
7a387fff 6883 case 3:
d9bea114 6884// gen_helper_mtc0_performance3(arg);
2423f660 6885 rn = "Performance3";
3570d7f6 6886 goto cp0_unimplemented;
7a387fff 6887 case 4:
d9bea114 6888// gen_helper_mtc0_performance4(arg);
2423f660 6889 rn = "Performance4";
3570d7f6 6890 goto cp0_unimplemented;
7a387fff 6891 case 5:
d9bea114 6892// gen_helper_mtc0_performance5(arg);
2423f660 6893 rn = "Performance5";
3570d7f6 6894 goto cp0_unimplemented;
7a387fff 6895 case 6:
d9bea114 6896// gen_helper_mtc0_performance6(arg);
2423f660 6897 rn = "Performance6";
3570d7f6 6898 goto cp0_unimplemented;
7a387fff 6899 case 7:
d9bea114 6900// gen_helper_mtc0_performance7(arg);
2423f660 6901 rn = "Performance7";
3570d7f6 6902 goto cp0_unimplemented;
7a387fff 6903 default:
f31b035a 6904 goto cp0_unimplemented;
7a387fff 6905 }
8c0fdd85
TS
6906 break;
6907 case 26:
0d74a222
LA
6908 switch (sel) {
6909 case 0:
6910 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 6911 ctx->base.is_jmp = DISAS_STOP;
0d74a222
LA
6912 rn = "ErrCtl";
6913 break;
6914 default:
6915 goto cp0_unimplemented;
6916 }
2423f660 6917 break;
8c0fdd85 6918 case 27:
7a387fff 6919 switch (sel) {
c2e19f3c
AM
6920 case 0:
6921 case 1:
6922 case 2:
6923 case 3:
2423f660
TS
6924 /* ignored */
6925 rn = "CacheErr";
6926 break;
7a387fff 6927 default:
f31b035a 6928 goto cp0_unimplemented;
7a387fff 6929 }
8c0fdd85
TS
6930 break;
6931 case 28:
6932 switch (sel) {
6933 case 0:
7a387fff
TS
6934 case 2:
6935 case 4:
6936 case 6:
895c2d04 6937 gen_helper_mtc0_taglo(cpu_env, arg);
8c0fdd85
TS
6938 rn = "TagLo";
6939 break;
7a387fff
TS
6940 case 1:
6941 case 3:
6942 case 5:
6943 case 7:
895c2d04 6944 gen_helper_mtc0_datalo(cpu_env, arg);
7a387fff
TS
6945 rn = "DataLo";
6946 break;
8c0fdd85 6947 default:
f31b035a 6948 goto cp0_unimplemented;
8c0fdd85
TS
6949 }
6950 break;
6951 case 29:
7a387fff
TS
6952 switch (sel) {
6953 case 0:
6954 case 2:
6955 case 4:
6956 case 6:
895c2d04 6957 gen_helper_mtc0_taghi(cpu_env, arg);
7a387fff
TS
6958 rn = "TagHi";
6959 break;
6960 case 1:
6961 case 3:
6962 case 5:
6963 case 7:
895c2d04 6964 gen_helper_mtc0_datahi(cpu_env, arg);
7a387fff
TS
6965 rn = "DataHi";
6966 break;
6967 default:
6968 rn = "invalid sel";
f31b035a 6969 goto cp0_unimplemented;
7a387fff 6970 }
8c0fdd85
TS
6971 break;
6972 case 30:
7a387fff
TS
6973 switch (sel) {
6974 case 0:
d54a299b 6975 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
6976 rn = "ErrorEPC";
6977 break;
7a387fff 6978 default:
f31b035a 6979 goto cp0_unimplemented;
7a387fff 6980 }
8c0fdd85
TS
6981 break;
6982 case 31:
7a387fff
TS
6983 switch (sel) {
6984 case 0:
f1aa6320 6985 /* EJTAG support */
7db13fae 6986 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
6987 rn = "DESAVE";
6988 break;
c2e19f3c
AM
6989 case 2:
6990 case 3:
6991 case 4:
6992 case 5:
6993 case 6:
6994 case 7:
f31b035a
LA
6995 CP0_CHECK(ctx->kscrexist & (1 << sel));
6996 tcg_gen_st_tl(arg, cpu_env,
6997 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6998 rn = "KScratch";
e98c0d17 6999 break;
7a387fff 7000 default:
f31b035a 7001 goto cp0_unimplemented;
7a387fff 7002 }
8c0fdd85
TS
7003 break;
7004 default:
f31b035a 7005 goto cp0_unimplemented;
8c0fdd85 7006 }
b44a7fb1
PMD
7007 trace_mips_translate_c0("mtc0", rn, reg, sel);
7008
bf20dc07 7009 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 7010 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7011 gen_io_end();
b28425ba 7012 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
b74cddcb 7013 * translated code to check for pending interrupts. */
eeb3bba8
EC
7014 gen_save_pc(ctx->base.pc_next + 4);
7015 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 7016 }
8c0fdd85
TS
7017 return;
7018
f31b035a 7019cp0_unimplemented:
965447ee 7020 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8c0fdd85
TS
7021}
7022
d26bc211 7023#if defined(TARGET_MIPS64)
d75c135e 7024static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
7025{
7026 const char *rn = "invalid";
7027
e189e748 7028 if (sel != 0)
d75c135e 7029 check_insn(ctx, ISA_MIPS64);
e189e748 7030
9c2149c8
TS
7031 switch (reg) {
7032 case 0:
7033 switch (sel) {
7034 case 0:
7db13fae 7035 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
9c2149c8
TS
7036 rn = "Index";
7037 break;
7038 case 1:
f31b035a 7039 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7040 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
9c2149c8 7041 rn = "MVPControl";
ead9360e 7042 break;
9c2149c8 7043 case 2:
f31b035a 7044 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7045 gen_helper_mfc0_mvpconf0(arg, cpu_env);
9c2149c8 7046 rn = "MVPConf0";
ead9360e 7047 break;
9c2149c8 7048 case 3:
f31b035a 7049 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7050 gen_helper_mfc0_mvpconf1(arg, cpu_env);
9c2149c8 7051 rn = "MVPConf1";
ead9360e 7052 break;
01bc435b
YK
7053 case 4:
7054 CP0_CHECK(ctx->vp);
7055 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7056 rn = "VPControl";
7057 break;
9c2149c8 7058 default:
f31b035a 7059 goto cp0_unimplemented;
9c2149c8
TS
7060 }
7061 break;
7062 case 1:
7063 switch (sel) {
7064 case 0:
f31b035a 7065 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 7066 gen_helper_mfc0_random(arg, cpu_env);
9c2149c8 7067 rn = "Random";
2423f660 7068 break;
9c2149c8 7069 case 1:
f31b035a 7070 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7071 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
9c2149c8 7072 rn = "VPEControl";
ead9360e 7073 break;
9c2149c8 7074 case 2:
f31b035a 7075 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7076 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
9c2149c8 7077 rn = "VPEConf0";
ead9360e 7078 break;
9c2149c8 7079 case 3:
f31b035a 7080 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7081 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
9c2149c8 7082 rn = "VPEConf1";
ead9360e 7083 break;
9c2149c8 7084 case 4:
f31b035a 7085 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7086 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
9c2149c8 7087 rn = "YQMask";
ead9360e 7088 break;
9c2149c8 7089 case 5:
f31b035a 7090 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7091 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 7092 rn = "VPESchedule";
ead9360e 7093 break;
9c2149c8 7094 case 6:
f31b035a 7095 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7096 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 7097 rn = "VPEScheFBack";
ead9360e 7098 break;
9c2149c8 7099 case 7:
f31b035a 7100 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7101 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
9c2149c8 7102 rn = "VPEOpt";
ead9360e 7103 break;
9c2149c8 7104 default:
f31b035a 7105 goto cp0_unimplemented;
9c2149c8
TS
7106 }
7107 break;
7108 case 2:
7109 switch (sel) {
7110 case 0:
7db13fae 7111 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
2423f660
TS
7112 rn = "EntryLo0";
7113 break;
9c2149c8 7114 case 1:
f31b035a 7115 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7116 gen_helper_mfc0_tcstatus(arg, cpu_env);
2423f660 7117 rn = "TCStatus";
ead9360e 7118 break;
9c2149c8 7119 case 2:
f31b035a 7120 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7121 gen_helper_mfc0_tcbind(arg, cpu_env);
2423f660 7122 rn = "TCBind";
ead9360e 7123 break;
9c2149c8 7124 case 3:
f31b035a 7125 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7126 gen_helper_dmfc0_tcrestart(arg, cpu_env);
2423f660 7127 rn = "TCRestart";
ead9360e 7128 break;
9c2149c8 7129 case 4:
f31b035a 7130 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7131 gen_helper_dmfc0_tchalt(arg, cpu_env);
2423f660 7132 rn = "TCHalt";
ead9360e 7133 break;
9c2149c8 7134 case 5:
f31b035a 7135 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7136 gen_helper_dmfc0_tccontext(arg, cpu_env);
2423f660 7137 rn = "TCContext";
ead9360e 7138 break;
9c2149c8 7139 case 6:
f31b035a 7140 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7141 gen_helper_dmfc0_tcschedule(arg, cpu_env);
2423f660 7142 rn = "TCSchedule";
ead9360e 7143 break;
9c2149c8 7144 case 7:
f31b035a 7145 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7146 gen_helper_dmfc0_tcschefback(arg, cpu_env);
2423f660 7147 rn = "TCScheFBack";
ead9360e 7148 break;
9c2149c8 7149 default:
f31b035a 7150 goto cp0_unimplemented;
9c2149c8
TS
7151 }
7152 break;
7153 case 3:
7154 switch (sel) {
7155 case 0:
7db13fae 7156 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
2423f660
TS
7157 rn = "EntryLo1";
7158 break;
01bc435b
YK
7159 case 1:
7160 CP0_CHECK(ctx->vp);
7161 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7162 rn = "GlobalNumber";
7163 break;
9c2149c8 7164 default:
f31b035a 7165 goto cp0_unimplemented;
1579a72e 7166 }
9c2149c8
TS
7167 break;
7168 case 4:
7169 switch (sel) {
7170 case 0:
7db13fae 7171 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
2423f660
TS
7172 rn = "Context";
7173 break;
9c2149c8 7174 case 1:
d9bea114 7175// gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660 7176 rn = "ContextConfig";
f31b035a 7177 goto cp0_unimplemented;
d279279e 7178 case 2:
f31b035a
LA
7179 CP0_CHECK(ctx->ulri);
7180 tcg_gen_ld_tl(arg, cpu_env,
7181 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7182 rn = "UserLocal";
d279279e 7183 break;
9c2149c8 7184 default:
f31b035a 7185 goto cp0_unimplemented;
876d4b07 7186 }
9c2149c8
TS
7187 break;
7188 case 5:
7189 switch (sel) {
7190 case 0:
7db13fae 7191 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
7192 rn = "PageMask";
7193 break;
9c2149c8 7194 case 1:
d75c135e 7195 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7196 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
7197 rn = "PageGrain";
7198 break;
cec56a73
JH
7199 case 2:
7200 CP0_CHECK(ctx->sc);
7201 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7202 rn = "SegCtl0";
7203 break;
7204 case 3:
7205 CP0_CHECK(ctx->sc);
7206 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7207 rn = "SegCtl1";
7208 break;
7209 case 4:
7210 CP0_CHECK(ctx->sc);
7211 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7212 rn = "SegCtl2";
7213 break;
9c2149c8 7214 default:
f31b035a 7215 goto cp0_unimplemented;
876d4b07 7216 }
9c2149c8
TS
7217 break;
7218 case 6:
7219 switch (sel) {
7220 case 0:
7db13fae 7221 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
7222 rn = "Wired";
7223 break;
9c2149c8 7224 case 1:
d75c135e 7225 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7226 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 7227 rn = "SRSConf0";
ead9360e 7228 break;
9c2149c8 7229 case 2:
d75c135e 7230 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7231 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 7232 rn = "SRSConf1";
ead9360e 7233 break;
9c2149c8 7234 case 3:
d75c135e 7235 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7236 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 7237 rn = "SRSConf2";
ead9360e 7238 break;
9c2149c8 7239 case 4:
d75c135e 7240 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7241 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 7242 rn = "SRSConf3";
ead9360e 7243 break;
9c2149c8 7244 case 5:
d75c135e 7245 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7246 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 7247 rn = "SRSConf4";
ead9360e 7248 break;
9c2149c8 7249 default:
f31b035a 7250 goto cp0_unimplemented;
876d4b07 7251 }
9c2149c8
TS
7252 break;
7253 case 7:
7254 switch (sel) {
7255 case 0:
d75c135e 7256 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7257 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
7258 rn = "HWREna";
7259 break;
9c2149c8 7260 default:
f31b035a 7261 goto cp0_unimplemented;
876d4b07 7262 }
9c2149c8
TS
7263 break;
7264 case 8:
7265 switch (sel) {
7266 case 0:
7db13fae 7267 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
f0b3f3ae 7268 rn = "BadVAddr";
2423f660 7269 break;
aea14095 7270 case 1:
f31b035a
LA
7271 CP0_CHECK(ctx->bi);
7272 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7273 rn = "BadInstr";
aea14095
LA
7274 break;
7275 case 2:
f31b035a
LA
7276 CP0_CHECK(ctx->bp);
7277 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7278 rn = "BadInstrP";
aea14095 7279 break;
25beba9b
SM
7280 case 3:
7281 CP0_CHECK(ctx->bi);
7282 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7283 tcg_gen_andi_tl(arg, arg, ~0xffff);
7284 rn = "BadInstrX";
7285 break;
9c2149c8 7286 default:
f31b035a 7287 goto cp0_unimplemented;
876d4b07 7288 }
9c2149c8
TS
7289 break;
7290 case 9:
7291 switch (sel) {
7292 case 0:
2e70f6ef 7293 /* Mark as an IO operation because we read the time. */
eeb3bba8 7294 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7295 gen_io_start();
bd79255d 7296 }
895c2d04 7297 gen_helper_mfc0_count(arg, cpu_env);
eeb3bba8 7298 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7299 gen_io_end();
2e70f6ef 7300 }
55807224 7301 /* Break the TB to be able to take timer interrupts immediately
b28425ba
EC
7302 after reading count. DISAS_STOP isn't sufficient, we need to
7303 ensure we break completely out of translated code. */
eeb3bba8
EC
7304 gen_save_pc(ctx->base.pc_next + 4);
7305 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
7306 rn = "Count";
7307 break;
7308 /* 6,7 are implementation dependent */
9c2149c8 7309 default:
f31b035a 7310 goto cp0_unimplemented;
876d4b07 7311 }
9c2149c8
TS
7312 break;
7313 case 10:
7314 switch (sel) {
7315 case 0:
7db13fae 7316 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
2423f660
TS
7317 rn = "EntryHi";
7318 break;
9c2149c8 7319 default:
f31b035a 7320 goto cp0_unimplemented;
876d4b07 7321 }
9c2149c8
TS
7322 break;
7323 case 11:
7324 switch (sel) {
7325 case 0:
7db13fae 7326 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
7327 rn = "Compare";
7328 break;
876d4b07 7329 /* 6,7 are implementation dependent */
9c2149c8 7330 default:
f31b035a 7331 goto cp0_unimplemented;
876d4b07 7332 }
9c2149c8
TS
7333 break;
7334 case 12:
7335 switch (sel) {
7336 case 0:
7db13fae 7337 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
7338 rn = "Status";
7339 break;
9c2149c8 7340 case 1:
d75c135e 7341 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7342 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
7343 rn = "IntCtl";
7344 break;
9c2149c8 7345 case 2:
d75c135e 7346 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7347 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
7348 rn = "SRSCtl";
7349 break;
9c2149c8 7350 case 3:
d75c135e 7351 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7352 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660
TS
7353 rn = "SRSMap";
7354 break;
9c2149c8 7355 default:
f31b035a 7356 goto cp0_unimplemented;
876d4b07 7357 }
9c2149c8
TS
7358 break;
7359 case 13:
7360 switch (sel) {
7361 case 0:
7db13fae 7362 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
7363 rn = "Cause";
7364 break;
9c2149c8 7365 default:
f31b035a 7366 goto cp0_unimplemented;
876d4b07 7367 }
9c2149c8
TS
7368 break;
7369 case 14:
7370 switch (sel) {
7371 case 0:
7db13fae 7372 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
7373 rn = "EPC";
7374 break;
9c2149c8 7375 default:
f31b035a 7376 goto cp0_unimplemented;
876d4b07 7377 }
9c2149c8
TS
7378 break;
7379 case 15:
7380 switch (sel) {
7381 case 0:
7db13fae 7382 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
7383 rn = "PRid";
7384 break;
9c2149c8 7385 case 1:
d75c135e 7386 check_insn(ctx, ISA_MIPS32R2);
74dbf824 7387 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
2423f660
TS
7388 rn = "EBase";
7389 break;
c870e3f5
YK
7390 case 3:
7391 check_insn(ctx, ISA_MIPS32R2);
7392 CP0_CHECK(ctx->cmgcr);
7393 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7394 rn = "CMGCRBase";
7395 break;
9c2149c8 7396 default:
f31b035a 7397 goto cp0_unimplemented;
876d4b07 7398 }
9c2149c8
TS
7399 break;
7400 case 16:
7401 switch (sel) {
7402 case 0:
7db13fae 7403 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
9c2149c8
TS
7404 rn = "Config";
7405 break;
7406 case 1:
7db13fae 7407 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
9c2149c8
TS
7408 rn = "Config1";
7409 break;
7410 case 2:
7db13fae 7411 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
9c2149c8
TS
7412 rn = "Config2";
7413 break;
7414 case 3:
7db13fae 7415 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
9c2149c8
TS
7416 rn = "Config3";
7417 break;
faf1f68b
LA
7418 case 4:
7419 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7420 rn = "Config4";
7421 break;
7422 case 5:
7423 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7424 rn = "Config5";
7425 break;
9c2149c8 7426 /* 6,7 are implementation dependent */
f0b3f3ae 7427 case 6:
7db13fae 7428 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
f0b3f3ae
TS
7429 rn = "Config6";
7430 break;
7431 case 7:
7db13fae 7432 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
f0b3f3ae
TS
7433 rn = "Config7";
7434 break;
9c2149c8 7435 default:
f31b035a 7436 goto cp0_unimplemented;
9c2149c8
TS
7437 }
7438 break;
7439 case 17:
7440 switch (sel) {
7441 case 0:
895c2d04 7442 gen_helper_dmfc0_lladdr(arg, cpu_env);
2423f660
TS
7443 rn = "LLAddr";
7444 break;
f6d4dd81
YK
7445 case 1:
7446 CP0_CHECK(ctx->mrp);
7447 gen_helper_dmfc0_maar(arg, cpu_env);
7448 rn = "MAAR";
7449 break;
7450 case 2:
7451 CP0_CHECK(ctx->mrp);
7452 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7453 rn = "MAARI";
7454 break;
9c2149c8 7455 default:
f31b035a 7456 goto cp0_unimplemented;
9c2149c8
TS
7457 }
7458 break;
7459 case 18:
7460 switch (sel) {
c2e19f3c
AM
7461 case 0:
7462 case 1:
7463 case 2:
7464 case 3:
7465 case 4:
7466 case 5:
7467 case 6:
7468 case 7:
fa192d49 7469 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7470 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
2423f660
TS
7471 rn = "WatchLo";
7472 break;
9c2149c8 7473 default:
f31b035a 7474 goto cp0_unimplemented;
9c2149c8
TS
7475 }
7476 break;
7477 case 19:
7478 switch (sel) {
c2e19f3c
AM
7479 case 0:
7480 case 1:
7481 case 2:
7482 case 3:
7483 case 4:
7484 case 5:
7485 case 6:
7486 case 7:
fa192d49 7487 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7488 gen_helper_1e0i(mfc0_watchhi, arg, sel);
2423f660
TS
7489 rn = "WatchHi";
7490 break;
9c2149c8 7491 default:
f31b035a 7492 goto cp0_unimplemented;
9c2149c8
TS
7493 }
7494 break;
7495 case 20:
7496 switch (sel) {
7497 case 0:
d75c135e 7498 check_insn(ctx, ISA_MIPS3);
7db13fae 7499 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
2423f660
TS
7500 rn = "XContext";
7501 break;
9c2149c8 7502 default:
f31b035a 7503 goto cp0_unimplemented;
9c2149c8
TS
7504 }
7505 break;
7506 case 21:
7507 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 7508 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
7509 switch (sel) {
7510 case 0:
7db13fae 7511 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
7512 rn = "Framemask";
7513 break;
9c2149c8 7514 default:
f31b035a 7515 goto cp0_unimplemented;
9c2149c8
TS
7516 }
7517 break;
7518 case 22:
d9bea114 7519 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
7520 rn = "'Diagnostic"; /* implementation dependent */
7521 break;
9c2149c8
TS
7522 case 23:
7523 switch (sel) {
7524 case 0:
895c2d04 7525 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
2423f660
TS
7526 rn = "Debug";
7527 break;
9c2149c8 7528 case 1:
895c2d04 7529// gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
2423f660 7530 rn = "TraceControl";
3570d7f6 7531 goto cp0_unimplemented;
9c2149c8 7532 case 2:
895c2d04 7533// gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
2423f660 7534 rn = "TraceControl2";
3570d7f6 7535 goto cp0_unimplemented;
9c2149c8 7536 case 3:
895c2d04 7537// gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
2423f660 7538 rn = "UserTraceData";
3570d7f6 7539 goto cp0_unimplemented;
9c2149c8 7540 case 4:
895c2d04 7541// gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
2423f660 7542 rn = "TraceBPC";
3570d7f6 7543 goto cp0_unimplemented;
9c2149c8 7544 default:
f31b035a 7545 goto cp0_unimplemented;
9c2149c8
TS
7546 }
7547 break;
7548 case 24:
7549 switch (sel) {
7550 case 0:
f0b3f3ae 7551 /* EJTAG support */
7db13fae 7552 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
7553 rn = "DEPC";
7554 break;
9c2149c8 7555 default:
f31b035a 7556 goto cp0_unimplemented;
9c2149c8
TS
7557 }
7558 break;
7559 case 25:
7560 switch (sel) {
7561 case 0:
7db13fae 7562 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 7563 rn = "Performance0";
9c2149c8
TS
7564 break;
7565 case 1:
d9bea114 7566// gen_helper_dmfc0_performance1(arg);
2423f660 7567 rn = "Performance1";
3570d7f6 7568 goto cp0_unimplemented;
9c2149c8 7569 case 2:
d9bea114 7570// gen_helper_dmfc0_performance2(arg);
2423f660 7571 rn = "Performance2";
3570d7f6 7572 goto cp0_unimplemented;
9c2149c8 7573 case 3:
d9bea114 7574// gen_helper_dmfc0_performance3(arg);
2423f660 7575 rn = "Performance3";
3570d7f6 7576 goto cp0_unimplemented;
9c2149c8 7577 case 4:
d9bea114 7578// gen_helper_dmfc0_performance4(arg);
2423f660 7579 rn = "Performance4";
3570d7f6 7580 goto cp0_unimplemented;
9c2149c8 7581 case 5:
d9bea114 7582// gen_helper_dmfc0_performance5(arg);
2423f660 7583 rn = "Performance5";
3570d7f6 7584 goto cp0_unimplemented;
9c2149c8 7585 case 6:
d9bea114 7586// gen_helper_dmfc0_performance6(arg);
2423f660 7587 rn = "Performance6";
3570d7f6 7588 goto cp0_unimplemented;
9c2149c8 7589 case 7:
d9bea114 7590// gen_helper_dmfc0_performance7(arg);
2423f660 7591 rn = "Performance7";
3570d7f6 7592 goto cp0_unimplemented;
9c2149c8 7593 default:
f31b035a 7594 goto cp0_unimplemented;
9c2149c8
TS
7595 }
7596 break;
7597 case 26:
0d74a222
LA
7598 switch (sel) {
7599 case 0:
7600 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7601 rn = "ErrCtl";
7602 break;
7603 default:
7604 goto cp0_unimplemented;
7605 }
da80682b 7606 break;
9c2149c8
TS
7607 case 27:
7608 switch (sel) {
7609 /* ignored */
c2e19f3c
AM
7610 case 0:
7611 case 1:
7612 case 2:
7613 case 3:
d9bea114 7614 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
7615 rn = "CacheErr";
7616 break;
9c2149c8 7617 default:
f31b035a 7618 goto cp0_unimplemented;
9c2149c8
TS
7619 }
7620 break;
7621 case 28:
7622 switch (sel) {
7623 case 0:
7624 case 2:
7625 case 4:
7626 case 6:
7db13fae 7627 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9c2149c8
TS
7628 rn = "TagLo";
7629 break;
7630 case 1:
7631 case 3:
7632 case 5:
7633 case 7:
7db13fae 7634 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9c2149c8
TS
7635 rn = "DataLo";
7636 break;
7637 default:
f31b035a 7638 goto cp0_unimplemented;
9c2149c8
TS
7639 }
7640 break;
7641 case 29:
7642 switch (sel) {
7643 case 0:
7644 case 2:
7645 case 4:
7646 case 6:
7db13fae 7647 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9c2149c8
TS
7648 rn = "TagHi";
7649 break;
7650 case 1:
7651 case 3:
7652 case 5:
7653 case 7:
7db13fae 7654 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9c2149c8
TS
7655 rn = "DataHi";
7656 break;
7657 default:
f31b035a 7658 goto cp0_unimplemented;
9c2149c8
TS
7659 }
7660 break;
7661 case 30:
7662 switch (sel) {
7663 case 0:
7db13fae 7664 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
7665 rn = "ErrorEPC";
7666 break;
9c2149c8 7667 default:
f31b035a 7668 goto cp0_unimplemented;
9c2149c8
TS
7669 }
7670 break;
7671 case 31:
7672 switch (sel) {
7673 case 0:
f0b3f3ae 7674 /* EJTAG support */
7db13fae 7675 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
7676 rn = "DESAVE";
7677 break;
c2e19f3c
AM
7678 case 2:
7679 case 3:
7680 case 4:
7681 case 5:
7682 case 6:
7683 case 7:
f31b035a
LA
7684 CP0_CHECK(ctx->kscrexist & (1 << sel));
7685 tcg_gen_ld_tl(arg, cpu_env,
7686 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7687 rn = "KScratch";
e98c0d17 7688 break;
9c2149c8 7689 default:
f31b035a 7690 goto cp0_unimplemented;
9c2149c8
TS
7691 }
7692 break;
7693 default:
f31b035a 7694 goto cp0_unimplemented;
9c2149c8 7695 }
b44a7fb1 7696 trace_mips_translate_c0("dmfc0", rn, reg, sel);
9c2149c8
TS
7697 return;
7698
f31b035a 7699cp0_unimplemented:
965447ee 7700 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
f31b035a 7701 gen_mfc0_unimplemented(ctx, arg);
9c2149c8
TS
7702}
7703
d75c135e 7704static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
7705{
7706 const char *rn = "invalid";
7707
e189e748 7708 if (sel != 0)
d75c135e 7709 check_insn(ctx, ISA_MIPS64);
e189e748 7710
eeb3bba8 7711 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7712 gen_io_start();
bd79255d 7713 }
2e70f6ef 7714
9c2149c8
TS
7715 switch (reg) {
7716 case 0:
7717 switch (sel) {
7718 case 0:
895c2d04 7719 gen_helper_mtc0_index(cpu_env, arg);
9c2149c8
TS
7720 rn = "Index";
7721 break;
7722 case 1:
f31b035a 7723 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7724 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9c2149c8 7725 rn = "MVPControl";
ead9360e 7726 break;
9c2149c8 7727 case 2:
f31b035a 7728 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7729 /* ignored */
9c2149c8 7730 rn = "MVPConf0";
ead9360e 7731 break;
9c2149c8 7732 case 3:
f31b035a 7733 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7734 /* ignored */
9c2149c8 7735 rn = "MVPConf1";
ead9360e 7736 break;
01bc435b
YK
7737 case 4:
7738 CP0_CHECK(ctx->vp);
7739 /* ignored */
7740 rn = "VPControl";
7741 break;
9c2149c8 7742 default:
f31b035a 7743 goto cp0_unimplemented;
9c2149c8
TS
7744 }
7745 break;
7746 case 1:
7747 switch (sel) {
7748 case 0:
2423f660 7749 /* ignored */
9c2149c8 7750 rn = "Random";
2423f660 7751 break;
9c2149c8 7752 case 1:
f31b035a 7753 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7754 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9c2149c8 7755 rn = "VPEControl";
ead9360e 7756 break;
9c2149c8 7757 case 2:
f31b035a 7758 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7759 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9c2149c8 7760 rn = "VPEConf0";
ead9360e 7761 break;
9c2149c8 7762 case 3:
f31b035a 7763 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7764 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9c2149c8 7765 rn = "VPEConf1";
ead9360e 7766 break;
9c2149c8 7767 case 4:
f31b035a 7768 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7769 gen_helper_mtc0_yqmask(cpu_env, arg);
9c2149c8 7770 rn = "YQMask";
ead9360e 7771 break;
9c2149c8 7772 case 5:
f31b035a 7773 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7774 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 7775 rn = "VPESchedule";
ead9360e 7776 break;
9c2149c8 7777 case 6:
f31b035a 7778 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7779 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 7780 rn = "VPEScheFBack";
ead9360e 7781 break;
9c2149c8 7782 case 7:
f31b035a 7783 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7784 gen_helper_mtc0_vpeopt(cpu_env, arg);
9c2149c8 7785 rn = "VPEOpt";
ead9360e 7786 break;
9c2149c8 7787 default:
f31b035a 7788 goto cp0_unimplemented;
9c2149c8
TS
7789 }
7790 break;
7791 case 2:
7792 switch (sel) {
7793 case 0:
7207c7f9 7794 gen_helper_dmtc0_entrylo0(cpu_env, arg);
2423f660
TS
7795 rn = "EntryLo0";
7796 break;
9c2149c8 7797 case 1:
f31b035a 7798 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7799 gen_helper_mtc0_tcstatus(cpu_env, arg);
2423f660 7800 rn = "TCStatus";
ead9360e 7801 break;
9c2149c8 7802 case 2:
f31b035a 7803 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7804 gen_helper_mtc0_tcbind(cpu_env, arg);
2423f660 7805 rn = "TCBind";
ead9360e 7806 break;
9c2149c8 7807 case 3:
f31b035a 7808 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7809 gen_helper_mtc0_tcrestart(cpu_env, arg);
2423f660 7810 rn = "TCRestart";
ead9360e 7811 break;
9c2149c8 7812 case 4:
f31b035a 7813 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7814 gen_helper_mtc0_tchalt(cpu_env, arg);
2423f660 7815 rn = "TCHalt";
ead9360e 7816 break;
9c2149c8 7817 case 5:
f31b035a 7818 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7819 gen_helper_mtc0_tccontext(cpu_env, arg);
2423f660 7820 rn = "TCContext";
ead9360e 7821 break;
9c2149c8 7822 case 6:
f31b035a 7823 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7824 gen_helper_mtc0_tcschedule(cpu_env, arg);
2423f660 7825 rn = "TCSchedule";
ead9360e 7826 break;
9c2149c8 7827 case 7:
f31b035a 7828 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7829 gen_helper_mtc0_tcschefback(cpu_env, arg);
2423f660 7830 rn = "TCScheFBack";
ead9360e 7831 break;
9c2149c8 7832 default:
f31b035a 7833 goto cp0_unimplemented;
9c2149c8
TS
7834 }
7835 break;
7836 case 3:
7837 switch (sel) {
7838 case 0:
7207c7f9 7839 gen_helper_dmtc0_entrylo1(cpu_env, arg);
2423f660
TS
7840 rn = "EntryLo1";
7841 break;
01bc435b
YK
7842 case 1:
7843 CP0_CHECK(ctx->vp);
7844 /* ignored */
7845 rn = "GlobalNumber";
7846 break;
9c2149c8 7847 default:
f31b035a 7848 goto cp0_unimplemented;
876d4b07 7849 }
9c2149c8
TS
7850 break;
7851 case 4:
7852 switch (sel) {
7853 case 0:
895c2d04 7854 gen_helper_mtc0_context(cpu_env, arg);
2423f660
TS
7855 rn = "Context";
7856 break;
9c2149c8 7857 case 1:
895c2d04 7858// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
2423f660 7859 rn = "ContextConfig";
f31b035a 7860 goto cp0_unimplemented;
d279279e 7861 case 2:
f31b035a
LA
7862 CP0_CHECK(ctx->ulri);
7863 tcg_gen_st_tl(arg, cpu_env,
7864 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7865 rn = "UserLocal";
d279279e 7866 break;
9c2149c8 7867 default:
f31b035a 7868 goto cp0_unimplemented;
876d4b07 7869 }
9c2149c8
TS
7870 break;
7871 case 5:
7872 switch (sel) {
7873 case 0:
895c2d04 7874 gen_helper_mtc0_pagemask(cpu_env, arg);
2423f660
TS
7875 rn = "PageMask";
7876 break;
9c2149c8 7877 case 1:
d75c135e 7878 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7879 gen_helper_mtc0_pagegrain(cpu_env, arg);
2423f660
TS
7880 rn = "PageGrain";
7881 break;
cec56a73
JH
7882 case 2:
7883 CP0_CHECK(ctx->sc);
7884 gen_helper_mtc0_segctl0(cpu_env, arg);
7885 rn = "SegCtl0";
7886 break;
7887 case 3:
7888 CP0_CHECK(ctx->sc);
7889 gen_helper_mtc0_segctl1(cpu_env, arg);
7890 rn = "SegCtl1";
7891 break;
7892 case 4:
7893 CP0_CHECK(ctx->sc);
7894 gen_helper_mtc0_segctl2(cpu_env, arg);
7895 rn = "SegCtl2";
7896 break;
9c2149c8 7897 default:
f31b035a 7898 goto cp0_unimplemented;
876d4b07 7899 }
9c2149c8
TS
7900 break;
7901 case 6:
7902 switch (sel) {
7903 case 0:
895c2d04 7904 gen_helper_mtc0_wired(cpu_env, arg);
2423f660
TS
7905 rn = "Wired";
7906 break;
9c2149c8 7907 case 1:
d75c135e 7908 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7909 gen_helper_mtc0_srsconf0(cpu_env, arg);
2423f660 7910 rn = "SRSConf0";
ead9360e 7911 break;
9c2149c8 7912 case 2:
d75c135e 7913 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7914 gen_helper_mtc0_srsconf1(cpu_env, arg);
2423f660 7915 rn = "SRSConf1";
ead9360e 7916 break;
9c2149c8 7917 case 3:
d75c135e 7918 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7919 gen_helper_mtc0_srsconf2(cpu_env, arg);
2423f660 7920 rn = "SRSConf2";
ead9360e 7921 break;
9c2149c8 7922 case 4:
d75c135e 7923 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7924 gen_helper_mtc0_srsconf3(cpu_env, arg);
2423f660 7925 rn = "SRSConf3";
ead9360e 7926 break;
9c2149c8 7927 case 5:
d75c135e 7928 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7929 gen_helper_mtc0_srsconf4(cpu_env, arg);
2423f660 7930 rn = "SRSConf4";
ead9360e 7931 break;
9c2149c8 7932 default:
f31b035a 7933 goto cp0_unimplemented;
876d4b07 7934 }
9c2149c8
TS
7935 break;
7936 case 7:
7937 switch (sel) {
7938 case 0:
d75c135e 7939 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7940 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 7941 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
7942 rn = "HWREna";
7943 break;
9c2149c8 7944 default:
f31b035a 7945 goto cp0_unimplemented;
876d4b07 7946 }
9c2149c8
TS
7947 break;
7948 case 8:
aea14095
LA
7949 switch (sel) {
7950 case 0:
7951 /* ignored */
7952 rn = "BadVAddr";
7953 break;
7954 case 1:
7955 /* ignored */
7956 rn = "BadInstr";
7957 break;
7958 case 2:
7959 /* ignored */
7960 rn = "BadInstrP";
7961 break;
25beba9b
SM
7962 case 3:
7963 /* ignored */
7964 rn = "BadInstrX";
7965 break;
aea14095 7966 default:
f31b035a 7967 goto cp0_unimplemented;
aea14095 7968 }
9c2149c8
TS
7969 break;
7970 case 9:
7971 switch (sel) {
7972 case 0:
895c2d04 7973 gen_helper_mtc0_count(cpu_env, arg);
2423f660
TS
7974 rn = "Count";
7975 break;
876d4b07 7976 /* 6,7 are implementation dependent */
9c2149c8 7977 default:
f31b035a 7978 goto cp0_unimplemented;
876d4b07
TS
7979 }
7980 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7981 ctx->base.is_jmp = DISAS_STOP;
9c2149c8
TS
7982 break;
7983 case 10:
7984 switch (sel) {
7985 case 0:
895c2d04 7986 gen_helper_mtc0_entryhi(cpu_env, arg);
2423f660
TS
7987 rn = "EntryHi";
7988 break;
9c2149c8 7989 default:
f31b035a 7990 goto cp0_unimplemented;
876d4b07 7991 }
9c2149c8
TS
7992 break;
7993 case 11:
7994 switch (sel) {
7995 case 0:
895c2d04 7996 gen_helper_mtc0_compare(cpu_env, arg);
2423f660
TS
7997 rn = "Compare";
7998 break;
876d4b07 7999 /* 6,7 are implementation dependent */
9c2149c8 8000 default:
f31b035a 8001 goto cp0_unimplemented;
876d4b07 8002 }
de9a95f0 8003 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8004 ctx->base.is_jmp = DISAS_STOP;
9c2149c8
TS
8005 break;
8006 case 12:
8007 switch (sel) {
8008 case 0:
867abc7e 8009 save_cpu_state(ctx, 1);
895c2d04 8010 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 8011 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8012 gen_save_pc(ctx->base.pc_next + 4);
8013 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
8014 rn = "Status";
8015 break;
9c2149c8 8016 case 1:
d75c135e 8017 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8018 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 8019 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8020 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
8021 rn = "IntCtl";
8022 break;
9c2149c8 8023 case 2:
d75c135e 8024 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8025 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 8026 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8027 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
8028 rn = "SRSCtl";
8029 break;
9c2149c8 8030 case 3:
d75c135e 8031 check_insn(ctx, ISA_MIPS32R2);
7db13fae 8032 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 8033 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8034 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
8035 rn = "SRSMap";
8036 break;
8037 default:
f31b035a 8038 goto cp0_unimplemented;
876d4b07 8039 }
9c2149c8
TS
8040 break;
8041 case 13:
8042 switch (sel) {
8043 case 0:
867abc7e 8044 save_cpu_state(ctx, 1);
895c2d04 8045 gen_helper_mtc0_cause(cpu_env, arg);
b28425ba
EC
8046 /* Stop translation as we may have triggered an interrupt.
8047 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8048 * translated code to check for pending interrupts. */
eeb3bba8
EC
8049 gen_save_pc(ctx->base.pc_next + 4);
8050 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
8051 rn = "Cause";
8052 break;
9c2149c8 8053 default:
f31b035a 8054 goto cp0_unimplemented;
876d4b07 8055 }
9c2149c8
TS
8056 break;
8057 case 14:
8058 switch (sel) {
8059 case 0:
7db13fae 8060 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
8061 rn = "EPC";
8062 break;
9c2149c8 8063 default:
f31b035a 8064 goto cp0_unimplemented;
876d4b07 8065 }
9c2149c8
TS
8066 break;
8067 case 15:
8068 switch (sel) {
8069 case 0:
2423f660
TS
8070 /* ignored */
8071 rn = "PRid";
8072 break;
9c2149c8 8073 case 1:
d75c135e 8074 check_insn(ctx, ISA_MIPS32R2);
895c2d04 8075 gen_helper_mtc0_ebase(cpu_env, arg);
2423f660
TS
8076 rn = "EBase";
8077 break;
9c2149c8 8078 default:
f31b035a 8079 goto cp0_unimplemented;
876d4b07 8080 }
9c2149c8
TS
8081 break;
8082 case 16:
8083 switch (sel) {
8084 case 0:
895c2d04 8085 gen_helper_mtc0_config0(cpu_env, arg);
9c2149c8 8086 rn = "Config";
2423f660 8087 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8088 ctx->base.is_jmp = DISAS_STOP;
9c2149c8
TS
8089 break;
8090 case 1:
1fc7bf6e 8091 /* ignored, read only */
9c2149c8
TS
8092 rn = "Config1";
8093 break;
8094 case 2:
895c2d04 8095 gen_helper_mtc0_config2(cpu_env, arg);
9c2149c8 8096 rn = "Config2";
2423f660 8097 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8098 ctx->base.is_jmp = DISAS_STOP;
9c2149c8
TS
8099 break;
8100 case 3:
90f12d73 8101 gen_helper_mtc0_config3(cpu_env, arg);
9c2149c8 8102 rn = "Config3";
90f12d73 8103 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8104 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 8105 break;
faf1f68b
LA
8106 case 4:
8107 /* currently ignored */
8108 rn = "Config4";
8109 break;
8110 case 5:
8111 gen_helper_mtc0_config5(cpu_env, arg);
8112 rn = "Config5";
8113 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8114 ctx->base.is_jmp = DISAS_STOP;
faf1f68b 8115 break;
9c2149c8
TS
8116 /* 6,7 are implementation dependent */
8117 default:
8118 rn = "Invalid config selector";
f31b035a 8119 goto cp0_unimplemented;
9c2149c8 8120 }
9c2149c8
TS
8121 break;
8122 case 17:
8123 switch (sel) {
8124 case 0:
895c2d04 8125 gen_helper_mtc0_lladdr(cpu_env, arg);
2423f660
TS
8126 rn = "LLAddr";
8127 break;
f6d4dd81
YK
8128 case 1:
8129 CP0_CHECK(ctx->mrp);
8130 gen_helper_mtc0_maar(cpu_env, arg);
8131 rn = "MAAR";
8132 break;
8133 case 2:
8134 CP0_CHECK(ctx->mrp);
8135 gen_helper_mtc0_maari(cpu_env, arg);
8136 rn = "MAARI";
8137 break;
9c2149c8 8138 default:
f31b035a 8139 goto cp0_unimplemented;
9c2149c8
TS
8140 }
8141 break;
8142 case 18:
8143 switch (sel) {
c2e19f3c
AM
8144 case 0:
8145 case 1:
8146 case 2:
8147 case 3:
8148 case 4:
8149 case 5:
8150 case 6:
8151 case 7:
fa192d49 8152 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8153 gen_helper_0e1i(mtc0_watchlo, arg, sel);
2423f660
TS
8154 rn = "WatchLo";
8155 break;
9c2149c8 8156 default:
f31b035a 8157 goto cp0_unimplemented;
9c2149c8
TS
8158 }
8159 break;
8160 case 19:
8161 switch (sel) {
c2e19f3c
AM
8162 case 0:
8163 case 1:
8164 case 2:
8165 case 3:
8166 case 4:
8167 case 5:
8168 case 6:
8169 case 7:
fa192d49 8170 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 8171 gen_helper_0e1i(mtc0_watchhi, arg, sel);
2423f660
TS
8172 rn = "WatchHi";
8173 break;
9c2149c8 8174 default:
f31b035a 8175 goto cp0_unimplemented;
9c2149c8
TS
8176 }
8177 break;
8178 case 20:
8179 switch (sel) {
8180 case 0:
d75c135e 8181 check_insn(ctx, ISA_MIPS3);
895c2d04 8182 gen_helper_mtc0_xcontext(cpu_env, arg);
2423f660
TS
8183 rn = "XContext";
8184 break;
9c2149c8 8185 default:
f31b035a 8186 goto cp0_unimplemented;
9c2149c8
TS
8187 }
8188 break;
8189 case 21:
8190 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 8191 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
8192 switch (sel) {
8193 case 0:
895c2d04 8194 gen_helper_mtc0_framemask(cpu_env, arg);
2423f660
TS
8195 rn = "Framemask";
8196 break;
9c2149c8 8197 default:
f31b035a 8198 goto cp0_unimplemented;
9c2149c8
TS
8199 }
8200 break;
8201 case 22:
8202 /* ignored */
8203 rn = "Diagnostic"; /* implementation dependent */
876d4b07 8204 break;
9c2149c8
TS
8205 case 23:
8206 switch (sel) {
8207 case 0:
895c2d04 8208 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 8209 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
8210 gen_save_pc(ctx->base.pc_next + 4);
8211 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
8212 rn = "Debug";
8213 break;
9c2149c8 8214 case 1:
895c2d04 8215// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8487327a 8216 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8217 ctx->base.is_jmp = DISAS_STOP;
2423f660 8218 rn = "TraceControl";
3570d7f6 8219 goto cp0_unimplemented;
9c2149c8 8220 case 2:
895c2d04 8221// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8487327a 8222 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8223 ctx->base.is_jmp = DISAS_STOP;
2423f660 8224 rn = "TraceControl2";
3570d7f6 8225 goto cp0_unimplemented;
9c2149c8 8226 case 3:
895c2d04 8227// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8487327a 8228 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8229 ctx->base.is_jmp = DISAS_STOP;
2423f660 8230 rn = "UserTraceData";
3570d7f6 8231 goto cp0_unimplemented;
9c2149c8 8232 case 4:
895c2d04 8233// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a 8234 /* Stop translation as we may have switched the execution mode */
eeb3bba8 8235 ctx->base.is_jmp = DISAS_STOP;
2423f660 8236 rn = "TraceBPC";
3570d7f6 8237 goto cp0_unimplemented;
9c2149c8 8238 default:
f31b035a 8239 goto cp0_unimplemented;
9c2149c8 8240 }
9c2149c8
TS
8241 break;
8242 case 24:
8243 switch (sel) {
8244 case 0:
f1aa6320 8245 /* EJTAG support */
7db13fae 8246 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
8247 rn = "DEPC";
8248 break;
9c2149c8 8249 default:
f31b035a 8250 goto cp0_unimplemented;
9c2149c8
TS
8251 }
8252 break;
8253 case 25:
8254 switch (sel) {
8255 case 0:
895c2d04 8256 gen_helper_mtc0_performance0(cpu_env, arg);
2423f660
TS
8257 rn = "Performance0";
8258 break;
9c2149c8 8259 case 1:
895c2d04 8260// gen_helper_mtc0_performance1(cpu_env, arg);
2423f660 8261 rn = "Performance1";
3570d7f6 8262 goto cp0_unimplemented;
9c2149c8 8263 case 2:
895c2d04 8264// gen_helper_mtc0_performance2(cpu_env, arg);
2423f660 8265 rn = "Performance2";
3570d7f6 8266 goto cp0_unimplemented;
9c2149c8 8267 case 3:
895c2d04 8268// gen_helper_mtc0_performance3(cpu_env, arg);
2423f660 8269 rn = "Performance3";
3570d7f6 8270 goto cp0_unimplemented;
9c2149c8 8271 case 4:
895c2d04 8272// gen_helper_mtc0_performance4(cpu_env, arg);
2423f660 8273 rn = "Performance4";
3570d7f6 8274 goto cp0_unimplemented;
9c2149c8 8275 case 5:
895c2d04 8276// gen_helper_mtc0_performance5(cpu_env, arg);
2423f660 8277 rn = "Performance5";
3570d7f6 8278 goto cp0_unimplemented;
9c2149c8 8279 case 6:
895c2d04 8280// gen_helper_mtc0_performance6(cpu_env, arg);
2423f660 8281 rn = "Performance6";
3570d7f6 8282 goto cp0_unimplemented;
9c2149c8 8283 case 7:
895c2d04 8284// gen_helper_mtc0_performance7(cpu_env, arg);
2423f660 8285 rn = "Performance7";
3570d7f6 8286 goto cp0_unimplemented;
9c2149c8 8287 default:
f31b035a 8288 goto cp0_unimplemented;
9c2149c8 8289 }
876d4b07 8290 break;
9c2149c8 8291 case 26:
0d74a222
LA
8292 switch (sel) {
8293 case 0:
8294 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 8295 ctx->base.is_jmp = DISAS_STOP;
0d74a222
LA
8296 rn = "ErrCtl";
8297 break;
8298 default:
8299 goto cp0_unimplemented;
8300 }
876d4b07 8301 break;
9c2149c8
TS
8302 case 27:
8303 switch (sel) {
c2e19f3c
AM
8304 case 0:
8305 case 1:
8306 case 2:
8307 case 3:
2423f660
TS
8308 /* ignored */
8309 rn = "CacheErr";
8310 break;
9c2149c8 8311 default:
f31b035a 8312 goto cp0_unimplemented;
9c2149c8 8313 }
876d4b07 8314 break;
9c2149c8
TS
8315 case 28:
8316 switch (sel) {
8317 case 0:
8318 case 2:
8319 case 4:
8320 case 6:
895c2d04 8321 gen_helper_mtc0_taglo(cpu_env, arg);
9c2149c8
TS
8322 rn = "TagLo";
8323 break;
8324 case 1:
8325 case 3:
8326 case 5:
8327 case 7:
895c2d04 8328 gen_helper_mtc0_datalo(cpu_env, arg);
9c2149c8
TS
8329 rn = "DataLo";
8330 break;
8331 default:
f31b035a 8332 goto cp0_unimplemented;
9c2149c8
TS
8333 }
8334 break;
8335 case 29:
8336 switch (sel) {
8337 case 0:
8338 case 2:
8339 case 4:
8340 case 6:
895c2d04 8341 gen_helper_mtc0_taghi(cpu_env, arg);
9c2149c8
TS
8342 rn = "TagHi";
8343 break;
8344 case 1:
8345 case 3:
8346 case 5:
8347 case 7:
895c2d04 8348 gen_helper_mtc0_datahi(cpu_env, arg);
9c2149c8
TS
8349 rn = "DataHi";
8350 break;
8351 default:
8352 rn = "invalid sel";
f31b035a 8353 goto cp0_unimplemented;
9c2149c8 8354 }
876d4b07 8355 break;
9c2149c8
TS
8356 case 30:
8357 switch (sel) {
8358 case 0:
7db13fae 8359 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
8360 rn = "ErrorEPC";
8361 break;
9c2149c8 8362 default:
f31b035a 8363 goto cp0_unimplemented;
9c2149c8
TS
8364 }
8365 break;
8366 case 31:
8367 switch (sel) {
8368 case 0:
f1aa6320 8369 /* EJTAG support */
7db13fae 8370 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
8371 rn = "DESAVE";
8372 break;
c2e19f3c
AM
8373 case 2:
8374 case 3:
8375 case 4:
8376 case 5:
8377 case 6:
8378 case 7:
f31b035a
LA
8379 CP0_CHECK(ctx->kscrexist & (1 << sel));
8380 tcg_gen_st_tl(arg, cpu_env,
8381 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8382 rn = "KScratch";
e98c0d17 8383 break;
9c2149c8 8384 default:
f31b035a 8385 goto cp0_unimplemented;
9c2149c8 8386 }
9c2149c8
TS
8387 break;
8388 default:
f31b035a 8389 goto cp0_unimplemented;
9c2149c8 8390 }
b44a7fb1
PMD
8391 trace_mips_translate_c0("dmtc0", rn, reg, sel);
8392
bf20dc07 8393 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 8394 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8395 gen_io_end();
b28425ba 8396 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
b74cddcb 8397 * translated code to check for pending interrupts. */
eeb3bba8
EC
8398 gen_save_pc(ctx->base.pc_next + 4);
8399 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 8400 }
9c2149c8
TS
8401 return;
8402
f31b035a 8403cp0_unimplemented:
965447ee 8404 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8 8405}
d26bc211 8406#endif /* TARGET_MIPS64 */
9c2149c8 8407
7db13fae 8408static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
8409 int u, int sel, int h)
8410{
8411 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 8412 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
8413
8414 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
8415 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8416 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 8417 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
8418 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8419 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 8420 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
8421 else if (u == 0) {
8422 switch (rt) {
5a25ce94
EI
8423 case 1:
8424 switch (sel) {
8425 case 1:
895c2d04 8426 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
8427 break;
8428 case 2:
895c2d04 8429 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
8430 break;
8431 default:
8432 goto die;
8433 break;
8434 }
8435 break;
ead9360e
TS
8436 case 2:
8437 switch (sel) {
8438 case 1:
895c2d04 8439 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
8440 break;
8441 case 2:
895c2d04 8442 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
8443 break;
8444 case 3:
895c2d04 8445 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
8446 break;
8447 case 4:
895c2d04 8448 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
8449 break;
8450 case 5:
895c2d04 8451 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
8452 break;
8453 case 6:
895c2d04 8454 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
8455 break;
8456 case 7:
895c2d04 8457 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
8458 break;
8459 default:
d75c135e 8460 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
8461 break;
8462 }
8463 break;
8464 case 10:
8465 switch (sel) {
8466 case 0:
895c2d04 8467 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
8468 break;
8469 default:
d75c135e 8470 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
8471 break;
8472 }
8473 case 12:
8474 switch (sel) {
8475 case 0:
895c2d04 8476 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
8477 break;
8478 default:
d75c135e 8479 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
8480 break;
8481 }
5a25ce94
EI
8482 case 13:
8483 switch (sel) {
8484 case 0:
895c2d04 8485 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
8486 break;
8487 default:
8488 goto die;
8489 break;
8490 }
8491 break;
8492 case 14:
8493 switch (sel) {
8494 case 0:
895c2d04 8495 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
8496 break;
8497 default:
8498 goto die;
8499 break;
8500 }
8501 break;
8502 case 15:
8503 switch (sel) {
8504 case 1:
895c2d04 8505 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
8506 break;
8507 default:
8508 goto die;
8509 break;
8510 }
8511 break;
8512 case 16:
8513 switch (sel) {
c2e19f3c
AM
8514 case 0:
8515 case 1:
8516 case 2:
8517 case 3:
8518 case 4:
8519 case 5:
8520 case 6:
8521 case 7:
895c2d04 8522 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
8523 break;
8524 default:
8525 goto die;
8526 break;
8527 }
8528 break;
ead9360e
TS
8529 case 23:
8530 switch (sel) {
8531 case 0:
895c2d04 8532 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
8533 break;
8534 default:
d75c135e 8535 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
8536 break;
8537 }
8538 break;
8539 default:
d75c135e 8540 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
8541 }
8542 } else switch (sel) {
8543 /* GPR registers. */
8544 case 0:
895c2d04 8545 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e
TS
8546 break;
8547 /* Auxiliary CPU registers */
8548 case 1:
8549 switch (rt) {
8550 case 0:
895c2d04 8551 gen_helper_1e0i(mftlo, t0, 0);
ead9360e
TS
8552 break;
8553 case 1:
895c2d04 8554 gen_helper_1e0i(mfthi, t0, 0);
ead9360e
TS
8555 break;
8556 case 2:
895c2d04 8557 gen_helper_1e0i(mftacx, t0, 0);
ead9360e
TS
8558 break;
8559 case 4:
895c2d04 8560 gen_helper_1e0i(mftlo, t0, 1);
ead9360e
TS
8561 break;
8562 case 5:
895c2d04 8563 gen_helper_1e0i(mfthi, t0, 1);
ead9360e
TS
8564 break;
8565 case 6:
895c2d04 8566 gen_helper_1e0i(mftacx, t0, 1);
ead9360e
TS
8567 break;
8568 case 8:
895c2d04 8569 gen_helper_1e0i(mftlo, t0, 2);
ead9360e
TS
8570 break;
8571 case 9:
895c2d04 8572 gen_helper_1e0i(mfthi, t0, 2);
ead9360e
TS
8573 break;
8574 case 10:
895c2d04 8575 gen_helper_1e0i(mftacx, t0, 2);
ead9360e
TS
8576 break;
8577 case 12:
895c2d04 8578 gen_helper_1e0i(mftlo, t0, 3);
ead9360e
TS
8579 break;
8580 case 13:
895c2d04 8581 gen_helper_1e0i(mfthi, t0, 3);
ead9360e
TS
8582 break;
8583 case 14:
895c2d04 8584 gen_helper_1e0i(mftacx, t0, 3);
ead9360e
TS
8585 break;
8586 case 16:
895c2d04 8587 gen_helper_mftdsp(t0, cpu_env);
ead9360e
TS
8588 break;
8589 default:
8590 goto die;
8591 }
8592 break;
8593 /* Floating point (COP1). */
8594 case 2:
8595 /* XXX: For now we support only a single FPU context. */
8596 if (h == 0) {
a7812ae4 8597 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 8598
7c979afd 8599 gen_load_fpr32(ctx, fp0, rt);
b6d96bed 8600 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 8601 tcg_temp_free_i32(fp0);
ead9360e 8602 } else {
a7812ae4 8603 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 8604
7f6613ce 8605 gen_load_fpr32h(ctx, fp0, rt);
b6d96bed 8606 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 8607 tcg_temp_free_i32(fp0);
ead9360e
TS
8608 }
8609 break;
8610 case 3:
8611 /* XXX: For now we support only a single FPU context. */
895c2d04 8612 gen_helper_1e0i(cfc1, t0, rt);
ead9360e
TS
8613 break;
8614 /* COP2: Not implemented. */
8615 case 4:
8616 case 5:
8617 /* fall through */
8618 default:
8619 goto die;
8620 }
b44a7fb1 8621 trace_mips_translate_tr("mftr", rt, u, sel, h);
1a3fd9c3
TS
8622 gen_store_gpr(t0, rd);
8623 tcg_temp_free(t0);
ead9360e
TS
8624 return;
8625
8626die:
1a3fd9c3 8627 tcg_temp_free(t0);
d12d51d5 8628 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9c708c7f 8629 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
8630}
8631
7db13fae 8632static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
8633 int u, int sel, int h)
8634{
8635 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 8636 TCGv t0 = tcg_temp_local_new();
ead9360e 8637
1a3fd9c3 8638 gen_load_gpr(t0, rt);
ead9360e 8639 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
8640 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8641 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
8642 /* NOP */ ;
8643 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8644 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
8645 /* NOP */ ;
8646 else if (u == 0) {
8647 switch (rd) {
5a25ce94
EI
8648 case 1:
8649 switch (sel) {
8650 case 1:
895c2d04 8651 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
8652 break;
8653 case 2:
895c2d04 8654 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
8655 break;
8656 default:
8657 goto die;
8658 break;
8659 }
8660 break;
ead9360e
TS
8661 case 2:
8662 switch (sel) {
8663 case 1:
895c2d04 8664 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
8665 break;
8666 case 2:
895c2d04 8667 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
8668 break;
8669 case 3:
895c2d04 8670 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
8671 break;
8672 case 4:
895c2d04 8673 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
8674 break;
8675 case 5:
895c2d04 8676 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
8677 break;
8678 case 6:
895c2d04 8679 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
8680 break;
8681 case 7:
895c2d04 8682 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
8683 break;
8684 default:
d75c135e 8685 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
8686 break;
8687 }
8688 break;
8689 case 10:
8690 switch (sel) {
8691 case 0:
895c2d04 8692 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
8693 break;
8694 default:
d75c135e 8695 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
8696 break;
8697 }
8698 case 12:
8699 switch (sel) {
8700 case 0:
895c2d04 8701 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
8702 break;
8703 default:
d75c135e 8704 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
8705 break;
8706 }
5a25ce94
EI
8707 case 13:
8708 switch (sel) {
8709 case 0:
895c2d04 8710 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
8711 break;
8712 default:
8713 goto die;
8714 break;
8715 }
8716 break;
8717 case 15:
8718 switch (sel) {
8719 case 1:
895c2d04 8720 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
8721 break;
8722 default:
8723 goto die;
8724 break;
8725 }
8726 break;
ead9360e
TS
8727 case 23:
8728 switch (sel) {
8729 case 0:
895c2d04 8730 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
8731 break;
8732 default:
d75c135e 8733 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
8734 break;
8735 }
8736 break;
8737 default:
d75c135e 8738 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
8739 }
8740 } else switch (sel) {
8741 /* GPR registers. */
8742 case 0:
895c2d04 8743 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e
TS
8744 break;
8745 /* Auxiliary CPU registers */
8746 case 1:
8747 switch (rd) {
8748 case 0:
895c2d04 8749 gen_helper_0e1i(mttlo, t0, 0);
ead9360e
TS
8750 break;
8751 case 1:
895c2d04 8752 gen_helper_0e1i(mtthi, t0, 0);
ead9360e
TS
8753 break;
8754 case 2:
895c2d04 8755 gen_helper_0e1i(mttacx, t0, 0);
ead9360e
TS
8756 break;
8757 case 4:
895c2d04 8758 gen_helper_0e1i(mttlo, t0, 1);
ead9360e
TS
8759 break;
8760 case 5:
895c2d04 8761 gen_helper_0e1i(mtthi, t0, 1);
ead9360e
TS
8762 break;
8763 case 6:
895c2d04 8764 gen_helper_0e1i(mttacx, t0, 1);
ead9360e
TS
8765 break;
8766 case 8:
895c2d04 8767 gen_helper_0e1i(mttlo, t0, 2);
ead9360e
TS
8768 break;
8769 case 9:
895c2d04 8770 gen_helper_0e1i(mtthi, t0, 2);
ead9360e
TS
8771 break;
8772 case 10:
895c2d04 8773 gen_helper_0e1i(mttacx, t0, 2);
ead9360e
TS
8774 break;
8775 case 12:
895c2d04 8776 gen_helper_0e1i(mttlo, t0, 3);
ead9360e
TS
8777 break;
8778 case 13:
895c2d04 8779 gen_helper_0e1i(mtthi, t0, 3);
ead9360e
TS
8780 break;
8781 case 14:
895c2d04 8782 gen_helper_0e1i(mttacx, t0, 3);
ead9360e
TS
8783 break;
8784 case 16:
895c2d04 8785 gen_helper_mttdsp(cpu_env, t0);
ead9360e
TS
8786 break;
8787 default:
8788 goto die;
8789 }
8790 break;
8791 /* Floating point (COP1). */
8792 case 2:
8793 /* XXX: For now we support only a single FPU context. */
8794 if (h == 0) {
a7812ae4 8795 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8796
8797 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 8798 gen_store_fpr32(ctx, fp0, rd);
a7812ae4 8799 tcg_temp_free_i32(fp0);
ead9360e 8800 } else {
a7812ae4 8801 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8802
8803 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 8804 gen_store_fpr32h(ctx, fp0, rd);
a7812ae4 8805 tcg_temp_free_i32(fp0);
ead9360e
TS
8806 }
8807 break;
8808 case 3:
8809 /* XXX: For now we support only a single FPU context. */
736d120a
PJ
8810 {
8811 TCGv_i32 fs_tmp = tcg_const_i32(rd);
8812
8813 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8814 tcg_temp_free_i32(fs_tmp);
8815 }
4cf8a45f 8816 /* Stop translation as we may have changed hflags */
eeb3bba8 8817 ctx->base.is_jmp = DISAS_STOP;
ead9360e
TS
8818 break;
8819 /* COP2: Not implemented. */
8820 case 4:
8821 case 5:
8822 /* fall through */
8823 default:
8824 goto die;
8825 }
b44a7fb1 8826 trace_mips_translate_tr("mttr", rd, u, sel, h);
1a3fd9c3 8827 tcg_temp_free(t0);
ead9360e
TS
8828 return;
8829
8830die:
1a3fd9c3 8831 tcg_temp_free(t0);
d12d51d5 8832 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9c708c7f 8833 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
8834}
8835
7db13fae 8836static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 8837{
287c4b84 8838 const char *opn = "ldst";
6af0bf9c 8839
2e15497c 8840 check_cp0_enabled(ctx);
6af0bf9c
FB
8841 switch (opc) {
8842 case OPC_MFC0:
8843 if (rt == 0) {
ead9360e 8844 /* Treat as NOP. */
6af0bf9c
FB
8845 return;
8846 }
d75c135e 8847 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
8848 opn = "mfc0";
8849 break;
8850 case OPC_MTC0:
1a3fd9c3 8851 {
1fc7bf6e 8852 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
8853
8854 gen_load_gpr(t0, rt);
d75c135e 8855 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
8856 tcg_temp_free(t0);
8857 }
6af0bf9c
FB
8858 opn = "mtc0";
8859 break;
d26bc211 8860#if defined(TARGET_MIPS64)
9c2149c8 8861 case OPC_DMFC0:
d75c135e 8862 check_insn(ctx, ISA_MIPS3);
9c2149c8 8863 if (rt == 0) {
ead9360e 8864 /* Treat as NOP. */
9c2149c8
TS
8865 return;
8866 }
d75c135e 8867 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
8868 opn = "dmfc0";
8869 break;
8870 case OPC_DMTC0:
d75c135e 8871 check_insn(ctx, ISA_MIPS3);
1a3fd9c3 8872 {
1fc7bf6e 8873 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
8874
8875 gen_load_gpr(t0, rt);
d75c135e 8876 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
8877 tcg_temp_free(t0);
8878 }
9c2149c8
TS
8879 opn = "dmtc0";
8880 break;
534ce69f 8881#endif
5204ea79
LA
8882 case OPC_MFHC0:
8883 check_mvh(ctx);
8884 if (rt == 0) {
8885 /* Treat as NOP. */
8886 return;
8887 }
8888 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8889 opn = "mfhc0";
8890 break;
8891 case OPC_MTHC0:
8892 check_mvh(ctx);
8893 {
8894 TCGv t0 = tcg_temp_new();
8895 gen_load_gpr(t0, rt);
8896 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8897 tcg_temp_free(t0);
8898 }
8899 opn = "mthc0";
8900 break;
ead9360e 8901 case OPC_MFTR:
9affc1c5 8902 check_cp0_enabled(ctx);
ead9360e
TS
8903 if (rd == 0) {
8904 /* Treat as NOP. */
8905 return;
8906 }
6c5c1e20 8907 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 8908 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
8909 opn = "mftr";
8910 break;
8911 case OPC_MTTR:
9affc1c5 8912 check_cp0_enabled(ctx);
6c5c1e20 8913 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
8914 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8915 opn = "mttr";
8916 break;
6af0bf9c 8917 case OPC_TLBWI:
6af0bf9c 8918 opn = "tlbwi";
c01fccd2 8919 if (!env->tlb->helper_tlbwi)
29929e34 8920 goto die;
895c2d04 8921 gen_helper_tlbwi(cpu_env);
6af0bf9c 8922 break;
9456c2fb
LA
8923 case OPC_TLBINV:
8924 opn = "tlbinv";
8925 if (ctx->ie >= 2) {
8926 if (!env->tlb->helper_tlbinv) {
8927 goto die;
8928 }
8929 gen_helper_tlbinv(cpu_env);
8930 } /* treat as nop if TLBINV not supported */
8931 break;
8932 case OPC_TLBINVF:
8933 opn = "tlbinvf";
8934 if (ctx->ie >= 2) {
8935 if (!env->tlb->helper_tlbinvf) {
8936 goto die;
8937 }
8938 gen_helper_tlbinvf(cpu_env);
8939 } /* treat as nop if TLBINV not supported */
8940 break;
6af0bf9c 8941 case OPC_TLBWR:
6af0bf9c 8942 opn = "tlbwr";
c01fccd2 8943 if (!env->tlb->helper_tlbwr)
29929e34 8944 goto die;
895c2d04 8945 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
8946 break;
8947 case OPC_TLBP:
6af0bf9c 8948 opn = "tlbp";
c01fccd2 8949 if (!env->tlb->helper_tlbp)
29929e34 8950 goto die;
895c2d04 8951 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
8952 break;
8953 case OPC_TLBR:
6af0bf9c 8954 opn = "tlbr";
c01fccd2 8955 if (!env->tlb->helper_tlbr)
29929e34 8956 goto die;
895c2d04 8957 gen_helper_tlbr(cpu_env);
6af0bf9c 8958 break;
ce9782f4 8959 case OPC_ERET: /* OPC_ERETNC */
339cd2a8
LA
8960 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8961 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8 8962 goto die;
ce9782f4
LA
8963 } else {
8964 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8965 if (ctx->opcode & (1 << bit_shift)) {
8966 /* OPC_ERETNC */
8967 opn = "eretnc";
8968 check_insn(ctx, ISA_MIPS32R5);
8969 gen_helper_eretnc(cpu_env);
8970 } else {
8971 /* OPC_ERET */
8972 opn = "eret";
8973 check_insn(ctx, ISA_MIPS2);
8974 gen_helper_eret(cpu_env);
8975 }
eeb3bba8 8976 ctx->base.is_jmp = DISAS_EXIT;
339cd2a8 8977 }
6af0bf9c
FB
8978 break;
8979 case OPC_DERET:
8980 opn = "deret";
d75c135e 8981 check_insn(ctx, ISA_MIPS32);
339cd2a8
LA
8982 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8983 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
8984 goto die;
8985 }
6af0bf9c 8986 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 8987 MIPS_INVAL(opn);
9c708c7f 8988 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 8989 } else {
895c2d04 8990 gen_helper_deret(cpu_env);
eeb3bba8 8991 ctx->base.is_jmp = DISAS_EXIT;
6af0bf9c
FB
8992 }
8993 break;
4ad40f36
FB
8994 case OPC_WAIT:
8995 opn = "wait";
d75c135e 8996 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
339cd2a8
LA
8997 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8998 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
8999 goto die;
9000 }
4ad40f36 9001 /* If we get an exception, we want to restart at next instruction */
eeb3bba8 9002 ctx->base.pc_next += 4;
4ad40f36 9003 save_cpu_state(ctx, 1);
eeb3bba8 9004 ctx->base.pc_next -= 4;
895c2d04 9005 gen_helper_wait(cpu_env);
eeb3bba8 9006 ctx->base.is_jmp = DISAS_NORETURN;
4ad40f36 9007 break;
6af0bf9c 9008 default:
29929e34 9009 die:
923617a3 9010 MIPS_INVAL(opn);
9c708c7f 9011 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
9012 return;
9013 }
2abf314d 9014 (void)opn; /* avoid a compiler warning */
6af0bf9c 9015}
f1aa6320 9016#endif /* !CONFIG_USER_ONLY */
6af0bf9c 9017
6ea83fed 9018/* CP1 Branches (before delay slot) */
d75c135e
AJ
9019static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9020 int32_t cc, int32_t offset)
6ea83fed
FB
9021{
9022 target_ulong btarget;
a7812ae4 9023 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 9024
339cd2a8 9025 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 9026 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
9027 goto out;
9028 }
9029
e189e748 9030 if (cc != 0)
d75c135e 9031 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
e189e748 9032
eeb3bba8 9033 btarget = ctx->base.pc_next + 4 + offset;
6ea83fed 9034
7a387fff
TS
9035 switch (op) {
9036 case OPC_BC1F:
d94536f4
AJ
9037 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9038 tcg_gen_not_i32(t0, t0);
9039 tcg_gen_andi_i32(t0, t0, 1);
9040 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 9041 goto not_likely;
7a387fff 9042 case OPC_BC1FL:
d94536f4
AJ
9043 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9044 tcg_gen_not_i32(t0, t0);
9045 tcg_gen_andi_i32(t0, t0, 1);
9046 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 9047 goto likely;
7a387fff 9048 case OPC_BC1T:
d94536f4
AJ
9049 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9050 tcg_gen_andi_i32(t0, t0, 1);
9051 tcg_gen_extu_i32_tl(bcond, t0);
5a5012ec 9052 goto not_likely;
7a387fff 9053 case OPC_BC1TL:
d94536f4
AJ
9054 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9055 tcg_gen_andi_i32(t0, t0, 1);
9056 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed
FB
9057 likely:
9058 ctx->hflags |= MIPS_HFLAG_BL;
9059 break;
5a5012ec 9060 case OPC_BC1FANY2:
a16336e4 9061 {
d94536f4
AJ
9062 TCGv_i32 t1 = tcg_temp_new_i32();
9063 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9064 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 9065 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 9066 tcg_temp_free_i32(t1);
d94536f4
AJ
9067 tcg_gen_andi_i32(t0, t0, 1);
9068 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9069 }
5a5012ec
TS
9070 goto not_likely;
9071 case OPC_BC1TANY2:
a16336e4 9072 {
d94536f4
AJ
9073 TCGv_i32 t1 = tcg_temp_new_i32();
9074 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9075 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9076 tcg_gen_or_i32(t0, t0, t1);
9077 tcg_temp_free_i32(t1);
9078 tcg_gen_andi_i32(t0, t0, 1);
9079 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9080 }
5a5012ec
TS
9081 goto not_likely;
9082 case OPC_BC1FANY4:
a16336e4 9083 {
d94536f4
AJ
9084 TCGv_i32 t1 = tcg_temp_new_i32();
9085 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9086 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 9087 tcg_gen_and_i32(t0, t0, t1);
d94536f4 9088 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
d7f66b52 9089 tcg_gen_and_i32(t0, t0, t1);
d94536f4 9090 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
d7f66b52 9091 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 9092 tcg_temp_free_i32(t1);
d94536f4
AJ
9093 tcg_gen_andi_i32(t0, t0, 1);
9094 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9095 }
5a5012ec
TS
9096 goto not_likely;
9097 case OPC_BC1TANY4:
a16336e4 9098 {
d94536f4
AJ
9099 TCGv_i32 t1 = tcg_temp_new_i32();
9100 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9101 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9102 tcg_gen_or_i32(t0, t0, t1);
9103 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
9104 tcg_gen_or_i32(t0, t0, t1);
9105 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
9106 tcg_gen_or_i32(t0, t0, t1);
9107 tcg_temp_free_i32(t1);
9108 tcg_gen_andi_i32(t0, t0, 1);
9109 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 9110 }
5a5012ec
TS
9111 not_likely:
9112 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
9113 break;
9114 default:
9d68ac14 9115 MIPS_INVAL("cp1 cond branch");
9c708c7f 9116 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 9117 goto out;
6ea83fed 9118 }
6ea83fed 9119 ctx->btarget = btarget;
b231c103 9120 ctx->hflags |= MIPS_HFLAG_BDS32;
6c5c1e20 9121 out:
a7812ae4 9122 tcg_temp_free_i32(t0);
6ea83fed
FB
9123}
9124
31837be3
YK
9125/* R6 CP1 Branches */
9126static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
65935f07
YK
9127 int32_t ft, int32_t offset,
9128 int delayslot_size)
31837be3
YK
9129{
9130 target_ulong btarget;
31837be3
YK
9131 TCGv_i64 t0 = tcg_temp_new_i64();
9132
9133 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9134#ifdef MIPS_DEBUG_DISAS
339cd2a8 9135 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 9136 "\n", ctx->base.pc_next);
31837be3 9137#endif
9c708c7f 9138 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
9139 goto out;
9140 }
9141
9142 gen_load_fpr64(ctx, t0, ft);
9143 tcg_gen_andi_i64(t0, t0, 1);
9144
eeb3bba8 9145 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
31837be3
YK
9146
9147 switch (op) {
9148 case OPC_BC1EQZ:
9149 tcg_gen_xori_i64(t0, t0, 1);
31837be3
YK
9150 ctx->hflags |= MIPS_HFLAG_BC;
9151 break;
9152 case OPC_BC1NEZ:
9153 /* t0 already set */
31837be3
YK
9154 ctx->hflags |= MIPS_HFLAG_BC;
9155 break;
9156 default:
9d68ac14 9157 MIPS_INVAL("cp1 cond branch");
9c708c7f 9158 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
9159 goto out;
9160 }
9161
9162 tcg_gen_trunc_i64_tl(bcond, t0);
9163
31837be3 9164 ctx->btarget = btarget;
65935f07
YK
9165
9166 switch (delayslot_size) {
9167 case 2:
9168 ctx->hflags |= MIPS_HFLAG_BDS16;
9169 break;
9170 case 4:
9171 ctx->hflags |= MIPS_HFLAG_BDS32;
9172 break;
9173 }
31837be3
YK
9174
9175out:
9176 tcg_temp_free_i64(t0);
9177}
9178
6af0bf9c 9179/* Coprocessor 1 (FPU) */
5a5012ec 9180
5a5012ec
TS
9181#define FOP(func, fmt) (((fmt) << 21) | (func))
9182
bf4120ad
NF
9183enum fopcode {
9184 OPC_ADD_S = FOP(0, FMT_S),
9185 OPC_SUB_S = FOP(1, FMT_S),
9186 OPC_MUL_S = FOP(2, FMT_S),
9187 OPC_DIV_S = FOP(3, FMT_S),
9188 OPC_SQRT_S = FOP(4, FMT_S),
9189 OPC_ABS_S = FOP(5, FMT_S),
9190 OPC_MOV_S = FOP(6, FMT_S),
9191 OPC_NEG_S = FOP(7, FMT_S),
9192 OPC_ROUND_L_S = FOP(8, FMT_S),
9193 OPC_TRUNC_L_S = FOP(9, FMT_S),
9194 OPC_CEIL_L_S = FOP(10, FMT_S),
9195 OPC_FLOOR_L_S = FOP(11, FMT_S),
9196 OPC_ROUND_W_S = FOP(12, FMT_S),
9197 OPC_TRUNC_W_S = FOP(13, FMT_S),
9198 OPC_CEIL_W_S = FOP(14, FMT_S),
9199 OPC_FLOOR_W_S = FOP(15, FMT_S),
e7f16abb 9200 OPC_SEL_S = FOP(16, FMT_S),
bf4120ad
NF
9201 OPC_MOVCF_S = FOP(17, FMT_S),
9202 OPC_MOVZ_S = FOP(18, FMT_S),
9203 OPC_MOVN_S = FOP(19, FMT_S),
e7f16abb 9204 OPC_SELEQZ_S = FOP(20, FMT_S),
bf4120ad
NF
9205 OPC_RECIP_S = FOP(21, FMT_S),
9206 OPC_RSQRT_S = FOP(22, FMT_S),
e7f16abb
LA
9207 OPC_SELNEZ_S = FOP(23, FMT_S),
9208 OPC_MADDF_S = FOP(24, FMT_S),
9209 OPC_MSUBF_S = FOP(25, FMT_S),
9210 OPC_RINT_S = FOP(26, FMT_S),
9211 OPC_CLASS_S = FOP(27, FMT_S),
9212 OPC_MIN_S = FOP(28, FMT_S),
bf4120ad 9213 OPC_RECIP2_S = FOP(28, FMT_S),
e7f16abb 9214 OPC_MINA_S = FOP(29, FMT_S),
bf4120ad 9215 OPC_RECIP1_S = FOP(29, FMT_S),
e7f16abb 9216 OPC_MAX_S = FOP(30, FMT_S),
bf4120ad 9217 OPC_RSQRT1_S = FOP(30, FMT_S),
e7f16abb 9218 OPC_MAXA_S = FOP(31, FMT_S),
bf4120ad
NF
9219 OPC_RSQRT2_S = FOP(31, FMT_S),
9220 OPC_CVT_D_S = FOP(33, FMT_S),
9221 OPC_CVT_W_S = FOP(36, FMT_S),
9222 OPC_CVT_L_S = FOP(37, FMT_S),
9223 OPC_CVT_PS_S = FOP(38, FMT_S),
9224 OPC_CMP_F_S = FOP (48, FMT_S),
9225 OPC_CMP_UN_S = FOP (49, FMT_S),
9226 OPC_CMP_EQ_S = FOP (50, FMT_S),
9227 OPC_CMP_UEQ_S = FOP (51, FMT_S),
9228 OPC_CMP_OLT_S = FOP (52, FMT_S),
9229 OPC_CMP_ULT_S = FOP (53, FMT_S),
9230 OPC_CMP_OLE_S = FOP (54, FMT_S),
9231 OPC_CMP_ULE_S = FOP (55, FMT_S),
9232 OPC_CMP_SF_S = FOP (56, FMT_S),
9233 OPC_CMP_NGLE_S = FOP (57, FMT_S),
9234 OPC_CMP_SEQ_S = FOP (58, FMT_S),
9235 OPC_CMP_NGL_S = FOP (59, FMT_S),
9236 OPC_CMP_LT_S = FOP (60, FMT_S),
9237 OPC_CMP_NGE_S = FOP (61, FMT_S),
9238 OPC_CMP_LE_S = FOP (62, FMT_S),
9239 OPC_CMP_NGT_S = FOP (63, FMT_S),
9240
9241 OPC_ADD_D = FOP(0, FMT_D),
9242 OPC_SUB_D = FOP(1, FMT_D),
9243 OPC_MUL_D = FOP(2, FMT_D),
9244 OPC_DIV_D = FOP(3, FMT_D),
9245 OPC_SQRT_D = FOP(4, FMT_D),
9246 OPC_ABS_D = FOP(5, FMT_D),
9247 OPC_MOV_D = FOP(6, FMT_D),
9248 OPC_NEG_D = FOP(7, FMT_D),
9249 OPC_ROUND_L_D = FOP(8, FMT_D),
9250 OPC_TRUNC_L_D = FOP(9, FMT_D),
9251 OPC_CEIL_L_D = FOP(10, FMT_D),
9252 OPC_FLOOR_L_D = FOP(11, FMT_D),
9253 OPC_ROUND_W_D = FOP(12, FMT_D),
9254 OPC_TRUNC_W_D = FOP(13, FMT_D),
9255 OPC_CEIL_W_D = FOP(14, FMT_D),
9256 OPC_FLOOR_W_D = FOP(15, FMT_D),
e7f16abb 9257 OPC_SEL_D = FOP(16, FMT_D),
bf4120ad
NF
9258 OPC_MOVCF_D = FOP(17, FMT_D),
9259 OPC_MOVZ_D = FOP(18, FMT_D),
9260 OPC_MOVN_D = FOP(19, FMT_D),
e7f16abb 9261 OPC_SELEQZ_D = FOP(20, FMT_D),
bf4120ad
NF
9262 OPC_RECIP_D = FOP(21, FMT_D),
9263 OPC_RSQRT_D = FOP(22, FMT_D),
e7f16abb
LA
9264 OPC_SELNEZ_D = FOP(23, FMT_D),
9265 OPC_MADDF_D = FOP(24, FMT_D),
9266 OPC_MSUBF_D = FOP(25, FMT_D),
9267 OPC_RINT_D = FOP(26, FMT_D),
9268 OPC_CLASS_D = FOP(27, FMT_D),
9269 OPC_MIN_D = FOP(28, FMT_D),
bf4120ad 9270 OPC_RECIP2_D = FOP(28, FMT_D),
e7f16abb 9271 OPC_MINA_D = FOP(29, FMT_D),
bf4120ad 9272 OPC_RECIP1_D = FOP(29, FMT_D),
e7f16abb 9273 OPC_MAX_D = FOP(30, FMT_D),
bf4120ad 9274 OPC_RSQRT1_D = FOP(30, FMT_D),
e7f16abb 9275 OPC_MAXA_D = FOP(31, FMT_D),
bf4120ad
NF
9276 OPC_RSQRT2_D = FOP(31, FMT_D),
9277 OPC_CVT_S_D = FOP(32, FMT_D),
9278 OPC_CVT_W_D = FOP(36, FMT_D),
9279 OPC_CVT_L_D = FOP(37, FMT_D),
9280 OPC_CMP_F_D = FOP (48, FMT_D),
9281 OPC_CMP_UN_D = FOP (49, FMT_D),
9282 OPC_CMP_EQ_D = FOP (50, FMT_D),
9283 OPC_CMP_UEQ_D = FOP (51, FMT_D),
9284 OPC_CMP_OLT_D = FOP (52, FMT_D),
9285 OPC_CMP_ULT_D = FOP (53, FMT_D),
9286 OPC_CMP_OLE_D = FOP (54, FMT_D),
9287 OPC_CMP_ULE_D = FOP (55, FMT_D),
9288 OPC_CMP_SF_D = FOP (56, FMT_D),
9289 OPC_CMP_NGLE_D = FOP (57, FMT_D),
9290 OPC_CMP_SEQ_D = FOP (58, FMT_D),
9291 OPC_CMP_NGL_D = FOP (59, FMT_D),
9292 OPC_CMP_LT_D = FOP (60, FMT_D),
9293 OPC_CMP_NGE_D = FOP (61, FMT_D),
9294 OPC_CMP_LE_D = FOP (62, FMT_D),
9295 OPC_CMP_NGT_D = FOP (63, FMT_D),
9296
9297 OPC_CVT_S_W = FOP(32, FMT_W),
9298 OPC_CVT_D_W = FOP(33, FMT_W),
9299 OPC_CVT_S_L = FOP(32, FMT_L),
9300 OPC_CVT_D_L = FOP(33, FMT_L),
9301 OPC_CVT_PS_PW = FOP(38, FMT_W),
9302
9303 OPC_ADD_PS = FOP(0, FMT_PS),
9304 OPC_SUB_PS = FOP(1, FMT_PS),
9305 OPC_MUL_PS = FOP(2, FMT_PS),
9306 OPC_DIV_PS = FOP(3, FMT_PS),
9307 OPC_ABS_PS = FOP(5, FMT_PS),
9308 OPC_MOV_PS = FOP(6, FMT_PS),
9309 OPC_NEG_PS = FOP(7, FMT_PS),
9310 OPC_MOVCF_PS = FOP(17, FMT_PS),
9311 OPC_MOVZ_PS = FOP(18, FMT_PS),
9312 OPC_MOVN_PS = FOP(19, FMT_PS),
9313 OPC_ADDR_PS = FOP(24, FMT_PS),
9314 OPC_MULR_PS = FOP(26, FMT_PS),
9315 OPC_RECIP2_PS = FOP(28, FMT_PS),
9316 OPC_RECIP1_PS = FOP(29, FMT_PS),
9317 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9318 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9319
9320 OPC_CVT_S_PU = FOP(32, FMT_PS),
9321 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9322 OPC_CVT_S_PL = FOP(40, FMT_PS),
9323 OPC_PLL_PS = FOP(44, FMT_PS),
9324 OPC_PLU_PS = FOP(45, FMT_PS),
9325 OPC_PUL_PS = FOP(46, FMT_PS),
9326 OPC_PUU_PS = FOP(47, FMT_PS),
9327 OPC_CMP_F_PS = FOP (48, FMT_PS),
9328 OPC_CMP_UN_PS = FOP (49, FMT_PS),
9329 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
9330 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
9331 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
9332 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
9333 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
9334 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
9335 OPC_CMP_SF_PS = FOP (56, FMT_PS),
9336 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
9337 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
9338 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
9339 OPC_CMP_LT_PS = FOP (60, FMT_PS),
9340 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
9341 OPC_CMP_LE_PS = FOP (62, FMT_PS),
9342 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
9343};
9344
3f493883
YK
9345enum r6_f_cmp_op {
9346 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9347 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9348 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9349 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9350 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9351 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9352 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9353 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9354 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9355 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9356 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9357 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9358 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9359 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9360 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9361 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9362 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9363 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9364 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9365 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9366 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9367 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9368
9369 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9370 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9371 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9372 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9373 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9374 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9375 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9376 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9377 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9378 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9379 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9380 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9381 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9382 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9383 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9384 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9385 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9386 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9387 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9388 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9389 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9390 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9391};
7a387fff 9392static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 9393{
72c3a3ee 9394 TCGv t0 = tcg_temp_new();
6ea83fed
FB
9395
9396 switch (opc) {
9397 case OPC_MFC1:
b6d96bed 9398 {
a7812ae4 9399 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9400
7c979afd 9401 gen_load_fpr32(ctx, fp0, fs);
b6d96bed 9402 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 9403 tcg_temp_free_i32(fp0);
6958549d 9404 }
6c5c1e20 9405 gen_store_gpr(t0, rt);
6ea83fed
FB
9406 break;
9407 case OPC_MTC1:
6c5c1e20 9408 gen_load_gpr(t0, rt);
b6d96bed 9409 {
a7812ae4 9410 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
9411
9412 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 9413 gen_store_fpr32(ctx, fp0, fs);
a7812ae4 9414 tcg_temp_free_i32(fp0);
6958549d 9415 }
6ea83fed
FB
9416 break;
9417 case OPC_CFC1:
895c2d04 9418 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 9419 gen_store_gpr(t0, rt);
6ea83fed
FB
9420 break;
9421 case OPC_CTC1:
6c5c1e20 9422 gen_load_gpr(t0, rt);
9c708c7f 9423 save_cpu_state(ctx, 0);
736d120a
PJ
9424 {
9425 TCGv_i32 fs_tmp = tcg_const_i32(fs);
9426
9427 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9428 tcg_temp_free_i32(fs_tmp);
9429 }
4cf8a45f 9430 /* Stop translation as we may have changed hflags */
eeb3bba8 9431 ctx->base.is_jmp = DISAS_STOP;
6ea83fed 9432 break;
72c3a3ee 9433#if defined(TARGET_MIPS64)
9c2149c8 9434 case OPC_DMFC1:
72c3a3ee 9435 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 9436 gen_store_gpr(t0, rt);
5a5012ec 9437 break;
9c2149c8 9438 case OPC_DMTC1:
6c5c1e20 9439 gen_load_gpr(t0, rt);
72c3a3ee 9440 gen_store_fpr64(ctx, t0, fs);
5a5012ec 9441 break;
72c3a3ee 9442#endif
5a5012ec 9443 case OPC_MFHC1:
b6d96bed 9444 {
a7812ae4 9445 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9446
7f6613ce 9447 gen_load_fpr32h(ctx, fp0, fs);
b6d96bed 9448 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 9449 tcg_temp_free_i32(fp0);
6958549d 9450 }
6c5c1e20 9451 gen_store_gpr(t0, rt);
5a5012ec
TS
9452 break;
9453 case OPC_MTHC1:
6c5c1e20 9454 gen_load_gpr(t0, rt);
b6d96bed 9455 {
a7812ae4 9456 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
9457
9458 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 9459 gen_store_fpr32h(ctx, fp0, fs);
a7812ae4 9460 tcg_temp_free_i32(fp0);
6958549d 9461 }
5a5012ec 9462 break;
6ea83fed 9463 default:
9d68ac14 9464 MIPS_INVAL("cp1 move");
9c708c7f 9465 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 9466 goto out;
6ea83fed 9467 }
6c5c1e20
TS
9468
9469 out:
9470 tcg_temp_free(t0);
6ea83fed
FB
9471}
9472
5a5012ec
TS
9473static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
9474{
42a268c2 9475 TCGLabel *l1;
e214b9bb 9476 TCGCond cond;
af58f9ca
AJ
9477 TCGv_i32 t0;
9478
9479 if (rd == 0) {
9480 /* Treat as NOP. */
9481 return;
9482 }
6ea83fed 9483
e214b9bb 9484 if (tf)
e214b9bb 9485 cond = TCG_COND_EQ;
27848470
TS
9486 else
9487 cond = TCG_COND_NE;
9488
af58f9ca
AJ
9489 l1 = gen_new_label();
9490 t0 = tcg_temp_new_i32();
fa31af0e 9491 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 9492 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 9493 tcg_temp_free_i32(t0);
af58f9ca
AJ
9494 if (rs == 0) {
9495 tcg_gen_movi_tl(cpu_gpr[rd], 0);
9496 } else {
9497 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
9498 }
e214b9bb 9499 gen_set_label(l1);
5a5012ec
TS
9500}
9501
7c979afd
LA
9502static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
9503 int tf)
a16336e4 9504{
a16336e4 9505 int cond;
cbc37b28 9506 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2 9507 TCGLabel *l1 = gen_new_label();
a16336e4 9508
a16336e4
TS
9509 if (tf)
9510 cond = TCG_COND_EQ;
9511 else
9512 cond = TCG_COND_NE;
9513
fa31af0e 9514 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 9515 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
9516 gen_load_fpr32(ctx, t0, fs);
9517 gen_store_fpr32(ctx, t0, fd);
a16336e4 9518 gen_set_label(l1);
cbc37b28 9519 tcg_temp_free_i32(t0);
5a5012ec 9520}
a16336e4 9521
b6d96bed 9522static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4 9523{
a16336e4 9524 int cond;
cbc37b28
AJ
9525 TCGv_i32 t0 = tcg_temp_new_i32();
9526 TCGv_i64 fp0;
42a268c2 9527 TCGLabel *l1 = gen_new_label();
a16336e4 9528
a16336e4
TS
9529 if (tf)
9530 cond = TCG_COND_EQ;
9531 else
9532 cond = TCG_COND_NE;
9533
fa31af0e 9534 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 9535 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 9536 tcg_temp_free_i32(t0);
11f94258 9537 fp0 = tcg_temp_new_i64();
9bf3eb2c 9538 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 9539 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9540 tcg_temp_free_i64(fp0);
cbc37b28 9541 gen_set_label(l1);
a16336e4
TS
9542}
9543
7f6613ce
PJ
9544static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
9545 int cc, int tf)
a16336e4
TS
9546{
9547 int cond;
cbc37b28 9548 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2
RH
9549 TCGLabel *l1 = gen_new_label();
9550 TCGLabel *l2 = gen_new_label();
a16336e4
TS
9551
9552 if (tf)
9553 cond = TCG_COND_EQ;
9554 else
9555 cond = TCG_COND_NE;
9556
fa31af0e 9557 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 9558 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
9559 gen_load_fpr32(ctx, t0, fs);
9560 gen_store_fpr32(ctx, t0, fd);
a16336e4 9561 gen_set_label(l1);
9bf3eb2c 9562
fa31af0e 9563 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
cbc37b28 9564 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7f6613ce
PJ
9565 gen_load_fpr32h(ctx, t0, fs);
9566 gen_store_fpr32h(ctx, t0, fd);
52a0e9eb 9567 tcg_temp_free_i32(t0);
a16336e4 9568 gen_set_label(l2);
a16336e4
TS
9569}
9570
e7f16abb
LA
9571static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9572 int fs)
9573{
9574 TCGv_i32 t1 = tcg_const_i32(0);
9575 TCGv_i32 fp0 = tcg_temp_new_i32();
9576 TCGv_i32 fp1 = tcg_temp_new_i32();
9577 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
9578 gen_load_fpr32(ctx, fp0, fd);
9579 gen_load_fpr32(ctx, fp1, ft);
9580 gen_load_fpr32(ctx, fp2, fs);
e7f16abb
LA
9581
9582 switch (op1) {
9583 case OPC_SEL_S:
9584 tcg_gen_andi_i32(fp0, fp0, 1);
9585 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9586 break;
9587 case OPC_SELEQZ_S:
9588 tcg_gen_andi_i32(fp1, fp1, 1);
9589 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9590 break;
9591 case OPC_SELNEZ_S:
9592 tcg_gen_andi_i32(fp1, fp1, 1);
9593 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9594 break;
9595 default:
9596 MIPS_INVAL("gen_sel_s");
9c708c7f 9597 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
9598 break;
9599 }
9600
7c979afd 9601 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
9602 tcg_temp_free_i32(fp2);
9603 tcg_temp_free_i32(fp1);
9604 tcg_temp_free_i32(fp0);
9605 tcg_temp_free_i32(t1);
9606}
9607
9608static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9609 int fs)
9610{
9611 TCGv_i64 t1 = tcg_const_i64(0);
9612 TCGv_i64 fp0 = tcg_temp_new_i64();
9613 TCGv_i64 fp1 = tcg_temp_new_i64();
9614 TCGv_i64 fp2 = tcg_temp_new_i64();
9615 gen_load_fpr64(ctx, fp0, fd);
9616 gen_load_fpr64(ctx, fp1, ft);
9617 gen_load_fpr64(ctx, fp2, fs);
9618
9619 switch (op1) {
9620 case OPC_SEL_D:
9621 tcg_gen_andi_i64(fp0, fp0, 1);
9622 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9623 break;
9624 case OPC_SELEQZ_D:
9625 tcg_gen_andi_i64(fp1, fp1, 1);
9626 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9627 break;
9628 case OPC_SELNEZ_D:
9629 tcg_gen_andi_i64(fp1, fp1, 1);
9630 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9631 break;
9632 default:
9633 MIPS_INVAL("gen_sel_d");
9c708c7f 9634 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
9635 break;
9636 }
9637
9638 gen_store_fpr64(ctx, fp0, fd);
9639 tcg_temp_free_i64(fp2);
9640 tcg_temp_free_i64(fp1);
9641 tcg_temp_free_i64(fp0);
9642 tcg_temp_free_i64(t1);
9643}
6ea83fed 9644
bf4120ad 9645static void gen_farith (DisasContext *ctx, enum fopcode op1,
5e755519 9646 int ft, int fs, int fd, int cc)
6ea83fed 9647{
7a387fff 9648 uint32_t func = ctx->opcode & 0x3f;
bf4120ad
NF
9649 switch (op1) {
9650 case OPC_ADD_S:
b6d96bed 9651 {
a7812ae4
PB
9652 TCGv_i32 fp0 = tcg_temp_new_i32();
9653 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9654
7c979afd
LA
9655 gen_load_fpr32(ctx, fp0, fs);
9656 gen_load_fpr32(ctx, fp1, ft);
895c2d04 9657 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 9658 tcg_temp_free_i32(fp1);
7c979afd 9659 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9660 tcg_temp_free_i32(fp0);
b6d96bed 9661 }
5a5012ec 9662 break;
bf4120ad 9663 case OPC_SUB_S:
b6d96bed 9664 {
a7812ae4
PB
9665 TCGv_i32 fp0 = tcg_temp_new_i32();
9666 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9667
7c979afd
LA
9668 gen_load_fpr32(ctx, fp0, fs);
9669 gen_load_fpr32(ctx, fp1, ft);
895c2d04 9670 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 9671 tcg_temp_free_i32(fp1);
7c979afd 9672 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9673 tcg_temp_free_i32(fp0);
b6d96bed 9674 }
5a5012ec 9675 break;
bf4120ad 9676 case OPC_MUL_S:
b6d96bed 9677 {
a7812ae4
PB
9678 TCGv_i32 fp0 = tcg_temp_new_i32();
9679 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9680
7c979afd
LA
9681 gen_load_fpr32(ctx, fp0, fs);
9682 gen_load_fpr32(ctx, fp1, ft);
895c2d04 9683 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 9684 tcg_temp_free_i32(fp1);
7c979afd 9685 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9686 tcg_temp_free_i32(fp0);
b6d96bed 9687 }
5a5012ec 9688 break;
bf4120ad 9689 case OPC_DIV_S:
b6d96bed 9690 {
a7812ae4
PB
9691 TCGv_i32 fp0 = tcg_temp_new_i32();
9692 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9693
7c979afd
LA
9694 gen_load_fpr32(ctx, fp0, fs);
9695 gen_load_fpr32(ctx, fp1, ft);
895c2d04 9696 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 9697 tcg_temp_free_i32(fp1);
7c979afd 9698 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9699 tcg_temp_free_i32(fp0);
b6d96bed 9700 }
5a5012ec 9701 break;
bf4120ad 9702 case OPC_SQRT_S:
b6d96bed 9703 {
a7812ae4 9704 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9705
7c979afd 9706 gen_load_fpr32(ctx, fp0, fs);
895c2d04 9707 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
7c979afd 9708 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9709 tcg_temp_free_i32(fp0);
b6d96bed 9710 }
5a5012ec 9711 break;
bf4120ad 9712 case OPC_ABS_S:
b6d96bed 9713 {
a7812ae4 9714 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9715
7c979afd 9716 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
9717 if (ctx->abs2008) {
9718 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
9719 } else {
9720 gen_helper_float_abs_s(fp0, fp0);
9721 }
7c979afd 9722 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9723 tcg_temp_free_i32(fp0);
b6d96bed 9724 }
5a5012ec 9725 break;
bf4120ad 9726 case OPC_MOV_S:
b6d96bed 9727 {
a7812ae4 9728 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9729
7c979afd
LA
9730 gen_load_fpr32(ctx, fp0, fs);
9731 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9732 tcg_temp_free_i32(fp0);
b6d96bed 9733 }
5a5012ec 9734 break;
bf4120ad 9735 case OPC_NEG_S:
b6d96bed 9736 {
a7812ae4 9737 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9738
7c979afd 9739 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
9740 if (ctx->abs2008) {
9741 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
9742 } else {
9743 gen_helper_float_chs_s(fp0, fp0);
9744 }
7c979afd 9745 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9746 tcg_temp_free_i32(fp0);
b6d96bed 9747 }
5a5012ec 9748 break;
bf4120ad 9749 case OPC_ROUND_L_S:
5e755519 9750 check_cp1_64bitmode(ctx);
b6d96bed 9751 {
a7812ae4
PB
9752 TCGv_i32 fp32 = tcg_temp_new_i32();
9753 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9754
7c979afd 9755 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
9756 if (ctx->nan2008) {
9757 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
9758 } else {
9759 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
9760 }
a7812ae4 9761 tcg_temp_free_i32(fp32);
b6d96bed 9762 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 9763 tcg_temp_free_i64(fp64);
b6d96bed 9764 }
5a5012ec 9765 break;
bf4120ad 9766 case OPC_TRUNC_L_S:
5e755519 9767 check_cp1_64bitmode(ctx);
b6d96bed 9768 {
a7812ae4
PB
9769 TCGv_i32 fp32 = tcg_temp_new_i32();
9770 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9771
7c979afd 9772 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
9773 if (ctx->nan2008) {
9774 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
9775 } else {
9776 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
9777 }
a7812ae4 9778 tcg_temp_free_i32(fp32);
b6d96bed 9779 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 9780 tcg_temp_free_i64(fp64);
b6d96bed 9781 }
5a5012ec 9782 break;
bf4120ad 9783 case OPC_CEIL_L_S:
5e755519 9784 check_cp1_64bitmode(ctx);
b6d96bed 9785 {
a7812ae4
PB
9786 TCGv_i32 fp32 = tcg_temp_new_i32();
9787 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9788
7c979afd 9789 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
9790 if (ctx->nan2008) {
9791 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
9792 } else {
9793 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
9794 }
a7812ae4 9795 tcg_temp_free_i32(fp32);
b6d96bed 9796 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 9797 tcg_temp_free_i64(fp64);
b6d96bed 9798 }
5a5012ec 9799 break;
bf4120ad 9800 case OPC_FLOOR_L_S:
5e755519 9801 check_cp1_64bitmode(ctx);
b6d96bed 9802 {
a7812ae4
PB
9803 TCGv_i32 fp32 = tcg_temp_new_i32();
9804 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9805
7c979afd 9806 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
9807 if (ctx->nan2008) {
9808 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
9809 } else {
9810 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
9811 }
a7812ae4 9812 tcg_temp_free_i32(fp32);
b6d96bed 9813 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 9814 tcg_temp_free_i64(fp64);
b6d96bed 9815 }
5a5012ec 9816 break;
bf4120ad 9817 case OPC_ROUND_W_S:
b6d96bed 9818 {
a7812ae4 9819 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9820
7c979afd 9821 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
9822 if (ctx->nan2008) {
9823 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
9824 } else {
9825 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
9826 }
7c979afd 9827 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9828 tcg_temp_free_i32(fp0);
b6d96bed 9829 }
5a5012ec 9830 break;
bf4120ad 9831 case OPC_TRUNC_W_S:
b6d96bed 9832 {
a7812ae4 9833 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9834
7c979afd 9835 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
9836 if (ctx->nan2008) {
9837 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
9838 } else {
9839 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
9840 }
7c979afd 9841 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9842 tcg_temp_free_i32(fp0);
b6d96bed 9843 }
5a5012ec 9844 break;
bf4120ad 9845 case OPC_CEIL_W_S:
b6d96bed 9846 {
a7812ae4 9847 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9848
7c979afd 9849 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
9850 if (ctx->nan2008) {
9851 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
9852 } else {
9853 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
9854 }
7c979afd 9855 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9856 tcg_temp_free_i32(fp0);
b6d96bed 9857 }
5a5012ec 9858 break;
bf4120ad 9859 case OPC_FLOOR_W_S:
b6d96bed 9860 {
a7812ae4 9861 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9862
7c979afd 9863 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
9864 if (ctx->nan2008) {
9865 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
9866 } else {
9867 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
9868 }
7c979afd 9869 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9870 tcg_temp_free_i32(fp0);
b6d96bed 9871 }
5a5012ec 9872 break;
e7f16abb
LA
9873 case OPC_SEL_S:
9874 check_insn(ctx, ISA_MIPS32R6);
9875 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
9876 break;
9877 case OPC_SELEQZ_S:
9878 check_insn(ctx, ISA_MIPS32R6);
9879 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
9880 break;
9881 case OPC_SELNEZ_S:
9882 check_insn(ctx, ISA_MIPS32R6);
9883 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb 9884 break;
bf4120ad 9885 case OPC_MOVCF_S:
fecd2646 9886 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7c979afd 9887 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 9888 break;
bf4120ad 9889 case OPC_MOVZ_S:
fecd2646 9890 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 9891 {
42a268c2 9892 TCGLabel *l1 = gen_new_label();
c9297f4d 9893 TCGv_i32 fp0;
a16336e4 9894
c9297f4d
AJ
9895 if (ft != 0) {
9896 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9897 }
9898 fp0 = tcg_temp_new_i32();
7c979afd
LA
9899 gen_load_fpr32(ctx, fp0, fs);
9900 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9901 tcg_temp_free_i32(fp0);
a16336e4
TS
9902 gen_set_label(l1);
9903 }
5a5012ec 9904 break;
bf4120ad 9905 case OPC_MOVN_S:
fecd2646 9906 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 9907 {
42a268c2 9908 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
9909 TCGv_i32 fp0;
9910
9911 if (ft != 0) {
9912 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9913 fp0 = tcg_temp_new_i32();
7c979afd
LA
9914 gen_load_fpr32(ctx, fp0, fs);
9915 gen_store_fpr32(ctx, fp0, fd);
c9297f4d
AJ
9916 tcg_temp_free_i32(fp0);
9917 gen_set_label(l1);
9918 }
a16336e4 9919 }
5a5012ec 9920 break;
bf4120ad 9921 case OPC_RECIP_S:
b6d96bed 9922 {
a7812ae4 9923 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9924
7c979afd 9925 gen_load_fpr32(ctx, fp0, fs);
895c2d04 9926 gen_helper_float_recip_s(fp0, cpu_env, fp0);
7c979afd 9927 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9928 tcg_temp_free_i32(fp0);
b6d96bed 9929 }
57fa1fb3 9930 break;
bf4120ad 9931 case OPC_RSQRT_S:
b6d96bed 9932 {
a7812ae4 9933 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9934
7c979afd 9935 gen_load_fpr32(ctx, fp0, fs);
895c2d04 9936 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
7c979afd 9937 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9938 tcg_temp_free_i32(fp0);
b6d96bed 9939 }
57fa1fb3 9940 break;
e7f16abb
LA
9941 case OPC_MADDF_S:
9942 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 9943 {
a7812ae4
PB
9944 TCGv_i32 fp0 = tcg_temp_new_i32();
9945 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 9946 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
9947 gen_load_fpr32(ctx, fp0, fs);
9948 gen_load_fpr32(ctx, fp1, ft);
9949 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 9950 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 9951 gen_store_fpr32(ctx, fp2, fd);
e7f16abb 9952 tcg_temp_free_i32(fp2);
a7812ae4 9953 tcg_temp_free_i32(fp1);
a7812ae4 9954 tcg_temp_free_i32(fp0);
b6d96bed 9955 }
57fa1fb3 9956 break;
e7f16abb
LA
9957 case OPC_MSUBF_S:
9958 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 9959 {
a7812ae4 9960 TCGv_i32 fp0 = tcg_temp_new_i32();
e7f16abb
LA
9961 TCGv_i32 fp1 = tcg_temp_new_i32();
9962 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
9963 gen_load_fpr32(ctx, fp0, fs);
9964 gen_load_fpr32(ctx, fp1, ft);
9965 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 9966 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 9967 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
9968 tcg_temp_free_i32(fp2);
9969 tcg_temp_free_i32(fp1);
a7812ae4 9970 tcg_temp_free_i32(fp0);
b6d96bed 9971 }
57fa1fb3 9972 break;
e7f16abb
LA
9973 case OPC_RINT_S:
9974 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 9975 {
a7812ae4 9976 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 9977 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 9978 gen_helper_float_rint_s(fp0, cpu_env, fp0);
7c979afd 9979 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9980 tcg_temp_free_i32(fp0);
b6d96bed 9981 }
57fa1fb3 9982 break;
e7f16abb
LA
9983 case OPC_CLASS_S:
9984 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 9985 {
e7f16abb 9986 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 9987 gen_load_fpr32(ctx, fp0, fs);
af39bc8c 9988 gen_helper_float_class_s(fp0, cpu_env, fp0);
7c979afd 9989 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 9990 tcg_temp_free_i32(fp0);
e7f16abb
LA
9991 }
9992 break;
9993 case OPC_MIN_S: /* OPC_RECIP2_S */
9994 if (ctx->insn_flags & ISA_MIPS32R6) {
9995 /* OPC_MIN_S */
a7812ae4
PB
9996 TCGv_i32 fp0 = tcg_temp_new_i32();
9997 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 9998 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
9999 gen_load_fpr32(ctx, fp0, fs);
10000 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 10001 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
7c979afd 10002 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
10003 tcg_temp_free_i32(fp2);
10004 tcg_temp_free_i32(fp1);
10005 tcg_temp_free_i32(fp0);
e7f16abb
LA
10006 } else {
10007 /* OPC_RECIP2_S */
10008 check_cp1_64bitmode(ctx);
10009 {
10010 TCGv_i32 fp0 = tcg_temp_new_i32();
10011 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10012
7c979afd
LA
10013 gen_load_fpr32(ctx, fp0, fs);
10014 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
10015 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10016 tcg_temp_free_i32(fp1);
7c979afd 10017 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10018 tcg_temp_free_i32(fp0);
10019 }
e7f16abb
LA
10020 }
10021 break;
10022 case OPC_MINA_S: /* OPC_RECIP1_S */
10023 if (ctx->insn_flags & ISA_MIPS32R6) {
10024 /* OPC_MINA_S */
10025 TCGv_i32 fp0 = tcg_temp_new_i32();
10026 TCGv_i32 fp1 = tcg_temp_new_i32();
10027 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
10028 gen_load_fpr32(ctx, fp0, fs);
10029 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 10030 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
7c979afd 10031 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
10032 tcg_temp_free_i32(fp2);
10033 tcg_temp_free_i32(fp1);
10034 tcg_temp_free_i32(fp0);
e7f16abb
LA
10035 } else {
10036 /* OPC_RECIP1_S */
10037 check_cp1_64bitmode(ctx);
10038 {
10039 TCGv_i32 fp0 = tcg_temp_new_i32();
10040
7c979afd 10041 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 10042 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
7c979afd 10043 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10044 tcg_temp_free_i32(fp0);
10045 }
e7f16abb
LA
10046 }
10047 break;
10048 case OPC_MAX_S: /* OPC_RSQRT1_S */
10049 if (ctx->insn_flags & ISA_MIPS32R6) {
10050 /* OPC_MAX_S */
10051 TCGv_i32 fp0 = tcg_temp_new_i32();
10052 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
10053 gen_load_fpr32(ctx, fp0, fs);
10054 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 10055 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
7c979afd 10056 gen_store_fpr32(ctx, fp1, fd);
e7f16abb
LA
10057 tcg_temp_free_i32(fp1);
10058 tcg_temp_free_i32(fp0);
e7f16abb
LA
10059 } else {
10060 /* OPC_RSQRT1_S */
10061 check_cp1_64bitmode(ctx);
10062 {
10063 TCGv_i32 fp0 = tcg_temp_new_i32();
10064
7c979afd 10065 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 10066 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
7c979afd 10067 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10068 tcg_temp_free_i32(fp0);
10069 }
e7f16abb
LA
10070 }
10071 break;
10072 case OPC_MAXA_S: /* OPC_RSQRT2_S */
10073 if (ctx->insn_flags & ISA_MIPS32R6) {
10074 /* OPC_MAXA_S */
10075 TCGv_i32 fp0 = tcg_temp_new_i32();
10076 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
10077 gen_load_fpr32(ctx, fp0, fs);
10078 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 10079 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
7c979afd 10080 gen_store_fpr32(ctx, fp1, fd);
a7812ae4 10081 tcg_temp_free_i32(fp1);
a7812ae4 10082 tcg_temp_free_i32(fp0);
e7f16abb
LA
10083 } else {
10084 /* OPC_RSQRT2_S */
10085 check_cp1_64bitmode(ctx);
10086 {
10087 TCGv_i32 fp0 = tcg_temp_new_i32();
10088 TCGv_i32 fp1 = tcg_temp_new_i32();
10089
7c979afd
LA
10090 gen_load_fpr32(ctx, fp0, fs);
10091 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
10092 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10093 tcg_temp_free_i32(fp1);
7c979afd 10094 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
10095 tcg_temp_free_i32(fp0);
10096 }
b6d96bed 10097 }
57fa1fb3 10098 break;
bf4120ad 10099 case OPC_CVT_D_S:
5e755519 10100 check_cp1_registers(ctx, fd);
b6d96bed 10101 {
a7812ae4
PB
10102 TCGv_i32 fp32 = tcg_temp_new_i32();
10103 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10104
7c979afd 10105 gen_load_fpr32(ctx, fp32, fs);
895c2d04 10106 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 10107 tcg_temp_free_i32(fp32);
b6d96bed 10108 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10109 tcg_temp_free_i64(fp64);
b6d96bed 10110 }
5a5012ec 10111 break;
bf4120ad 10112 case OPC_CVT_W_S:
b6d96bed 10113 {
a7812ae4 10114 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10115
7c979afd 10116 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
10117 if (ctx->nan2008) {
10118 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
10119 } else {
10120 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
10121 }
7c979afd 10122 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10123 tcg_temp_free_i32(fp0);
b6d96bed 10124 }
5a5012ec 10125 break;
bf4120ad 10126 case OPC_CVT_L_S:
5e755519 10127 check_cp1_64bitmode(ctx);
b6d96bed 10128 {
a7812ae4
PB
10129 TCGv_i32 fp32 = tcg_temp_new_i32();
10130 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10131
7c979afd 10132 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
10133 if (ctx->nan2008) {
10134 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
10135 } else {
10136 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
10137 }
a7812ae4 10138 tcg_temp_free_i32(fp32);
b6d96bed 10139 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10140 tcg_temp_free_i64(fp64);
b6d96bed 10141 }
5a5012ec 10142 break;
bf4120ad 10143 case OPC_CVT_PS_S:
e29c9628 10144 check_ps(ctx);
b6d96bed 10145 {
a7812ae4
PB
10146 TCGv_i64 fp64 = tcg_temp_new_i64();
10147 TCGv_i32 fp32_0 = tcg_temp_new_i32();
10148 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed 10149
7c979afd
LA
10150 gen_load_fpr32(ctx, fp32_0, fs);
10151 gen_load_fpr32(ctx, fp32_1, ft);
13d24f49 10152 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
10153 tcg_temp_free_i32(fp32_1);
10154 tcg_temp_free_i32(fp32_0);
36aa55dc 10155 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10156 tcg_temp_free_i64(fp64);
b6d96bed 10157 }
5a5012ec 10158 break;
bf4120ad
NF
10159 case OPC_CMP_F_S:
10160 case OPC_CMP_UN_S:
10161 case OPC_CMP_EQ_S:
10162 case OPC_CMP_UEQ_S:
10163 case OPC_CMP_OLT_S:
10164 case OPC_CMP_ULT_S:
10165 case OPC_CMP_OLE_S:
10166 case OPC_CMP_ULE_S:
10167 case OPC_CMP_SF_S:
10168 case OPC_CMP_NGLE_S:
10169 case OPC_CMP_SEQ_S:
10170 case OPC_CMP_NGL_S:
10171 case OPC_CMP_LT_S:
10172 case OPC_CMP_NGE_S:
10173 case OPC_CMP_LE_S:
10174 case OPC_CMP_NGT_S:
fecd2646 10175 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c
NF
10176 if (ctx->opcode & (1 << 6)) {
10177 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
8153667c
NF
10178 } else {
10179 gen_cmp_s(ctx, func-48, ft, fs, cc);
5a1e8ffb 10180 }
5a5012ec 10181 break;
bf4120ad 10182 case OPC_ADD_D:
5e755519 10183 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10184 {
a7812ae4
PB
10185 TCGv_i64 fp0 = tcg_temp_new_i64();
10186 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10187
10188 gen_load_fpr64(ctx, fp0, fs);
10189 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10190 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 10191 tcg_temp_free_i64(fp1);
b6d96bed 10192 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10193 tcg_temp_free_i64(fp0);
b6d96bed 10194 }
6ea83fed 10195 break;
bf4120ad 10196 case OPC_SUB_D:
5e755519 10197 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10198 {
a7812ae4
PB
10199 TCGv_i64 fp0 = tcg_temp_new_i64();
10200 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10201
10202 gen_load_fpr64(ctx, fp0, fs);
10203 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10204 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 10205 tcg_temp_free_i64(fp1);
b6d96bed 10206 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10207 tcg_temp_free_i64(fp0);
b6d96bed 10208 }
6ea83fed 10209 break;
bf4120ad 10210 case OPC_MUL_D:
5e755519 10211 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10212 {
a7812ae4
PB
10213 TCGv_i64 fp0 = tcg_temp_new_i64();
10214 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10215
10216 gen_load_fpr64(ctx, fp0, fs);
10217 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10218 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 10219 tcg_temp_free_i64(fp1);
b6d96bed 10220 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10221 tcg_temp_free_i64(fp0);
b6d96bed 10222 }
6ea83fed 10223 break;
bf4120ad 10224 case OPC_DIV_D:
5e755519 10225 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 10226 {
a7812ae4
PB
10227 TCGv_i64 fp0 = tcg_temp_new_i64();
10228 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10229
10230 gen_load_fpr64(ctx, fp0, fs);
10231 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10232 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 10233 tcg_temp_free_i64(fp1);
b6d96bed 10234 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10235 tcg_temp_free_i64(fp0);
b6d96bed 10236 }
6ea83fed 10237 break;
bf4120ad 10238 case OPC_SQRT_D:
5e755519 10239 check_cp1_registers(ctx, fs | fd);
b6d96bed 10240 {
a7812ae4 10241 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10242
10243 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10244 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 10245 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10246 tcg_temp_free_i64(fp0);
b6d96bed 10247 }
6ea83fed 10248 break;
bf4120ad 10249 case OPC_ABS_D:
5e755519 10250 check_cp1_registers(ctx, fs | fd);
b6d96bed 10251 {
a7812ae4 10252 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10253
10254 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
10255 if (ctx->abs2008) {
10256 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
10257 } else {
10258 gen_helper_float_abs_d(fp0, fp0);
10259 }
b6d96bed 10260 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10261 tcg_temp_free_i64(fp0);
b6d96bed 10262 }
6ea83fed 10263 break;
bf4120ad 10264 case OPC_MOV_D:
5e755519 10265 check_cp1_registers(ctx, fs | fd);
b6d96bed 10266 {
a7812ae4 10267 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10268
10269 gen_load_fpr64(ctx, fp0, fs);
10270 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10271 tcg_temp_free_i64(fp0);
b6d96bed 10272 }
6ea83fed 10273 break;
bf4120ad 10274 case OPC_NEG_D:
5e755519 10275 check_cp1_registers(ctx, fs | fd);
b6d96bed 10276 {
a7812ae4 10277 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10278
10279 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
10280 if (ctx->abs2008) {
10281 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10282 } else {
10283 gen_helper_float_chs_d(fp0, fp0);
10284 }
b6d96bed 10285 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10286 tcg_temp_free_i64(fp0);
b6d96bed 10287 }
6ea83fed 10288 break;
bf4120ad 10289 case OPC_ROUND_L_D:
5e755519 10290 check_cp1_64bitmode(ctx);
b6d96bed 10291 {
a7812ae4 10292 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10293
10294 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10295 if (ctx->nan2008) {
10296 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
10297 } else {
10298 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
10299 }
b6d96bed 10300 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10301 tcg_temp_free_i64(fp0);
b6d96bed 10302 }
5a5012ec 10303 break;
bf4120ad 10304 case OPC_TRUNC_L_D:
5e755519 10305 check_cp1_64bitmode(ctx);
b6d96bed 10306 {
a7812ae4 10307 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10308
10309 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10310 if (ctx->nan2008) {
10311 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10312 } else {
10313 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10314 }
b6d96bed 10315 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10316 tcg_temp_free_i64(fp0);
b6d96bed 10317 }
5a5012ec 10318 break;
bf4120ad 10319 case OPC_CEIL_L_D:
5e755519 10320 check_cp1_64bitmode(ctx);
b6d96bed 10321 {
a7812ae4 10322 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10323
10324 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10325 if (ctx->nan2008) {
10326 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10327 } else {
10328 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10329 }
b6d96bed 10330 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10331 tcg_temp_free_i64(fp0);
b6d96bed 10332 }
5a5012ec 10333 break;
bf4120ad 10334 case OPC_FLOOR_L_D:
5e755519 10335 check_cp1_64bitmode(ctx);
b6d96bed 10336 {
a7812ae4 10337 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10338
10339 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10340 if (ctx->nan2008) {
10341 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10342 } else {
10343 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10344 }
b6d96bed 10345 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10346 tcg_temp_free_i64(fp0);
b6d96bed 10347 }
5a5012ec 10348 break;
bf4120ad 10349 case OPC_ROUND_W_D:
5e755519 10350 check_cp1_registers(ctx, fs);
b6d96bed 10351 {
a7812ae4
PB
10352 TCGv_i32 fp32 = tcg_temp_new_i32();
10353 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10354
10355 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10356 if (ctx->nan2008) {
10357 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10358 } else {
10359 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10360 }
a7812ae4 10361 tcg_temp_free_i64(fp64);
7c979afd 10362 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10363 tcg_temp_free_i32(fp32);
b6d96bed 10364 }
6ea83fed 10365 break;
bf4120ad 10366 case OPC_TRUNC_W_D:
5e755519 10367 check_cp1_registers(ctx, fs);
b6d96bed 10368 {
a7812ae4
PB
10369 TCGv_i32 fp32 = tcg_temp_new_i32();
10370 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10371
10372 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10373 if (ctx->nan2008) {
10374 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
10375 } else {
10376 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
10377 }
a7812ae4 10378 tcg_temp_free_i64(fp64);
7c979afd 10379 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10380 tcg_temp_free_i32(fp32);
b6d96bed 10381 }
6ea83fed 10382 break;
bf4120ad 10383 case OPC_CEIL_W_D:
5e755519 10384 check_cp1_registers(ctx, fs);
b6d96bed 10385 {
a7812ae4
PB
10386 TCGv_i32 fp32 = tcg_temp_new_i32();
10387 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10388
10389 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10390 if (ctx->nan2008) {
10391 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
10392 } else {
10393 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
10394 }
a7812ae4 10395 tcg_temp_free_i64(fp64);
7c979afd 10396 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10397 tcg_temp_free_i32(fp32);
b6d96bed 10398 }
6ea83fed 10399 break;
bf4120ad 10400 case OPC_FLOOR_W_D:
5e755519 10401 check_cp1_registers(ctx, fs);
b6d96bed 10402 {
a7812ae4
PB
10403 TCGv_i32 fp32 = tcg_temp_new_i32();
10404 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10405
10406 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10407 if (ctx->nan2008) {
10408 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
10409 } else {
10410 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
10411 }
a7812ae4 10412 tcg_temp_free_i64(fp64);
7c979afd 10413 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10414 tcg_temp_free_i32(fp32);
b6d96bed 10415 }
6ea83fed 10416 break;
e7f16abb
LA
10417 case OPC_SEL_D:
10418 check_insn(ctx, ISA_MIPS32R6);
10419 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
10420 break;
10421 case OPC_SELEQZ_D:
10422 check_insn(ctx, ISA_MIPS32R6);
10423 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
10424 break;
10425 case OPC_SELNEZ_D:
10426 check_insn(ctx, ISA_MIPS32R6);
10427 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb 10428 break;
bf4120ad 10429 case OPC_MOVCF_D:
fecd2646 10430 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6d96bed 10431 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
dd016883 10432 break;
bf4120ad 10433 case OPC_MOVZ_D:
fecd2646 10434 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 10435 {
42a268c2 10436 TCGLabel *l1 = gen_new_label();
c9297f4d 10437 TCGv_i64 fp0;
a16336e4 10438
c9297f4d
AJ
10439 if (ft != 0) {
10440 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10441 }
10442 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10443 gen_load_fpr64(ctx, fp0, fs);
10444 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10445 tcg_temp_free_i64(fp0);
a16336e4
TS
10446 gen_set_label(l1);
10447 }
5a5012ec 10448 break;
bf4120ad 10449 case OPC_MOVN_D:
fecd2646 10450 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 10451 {
42a268c2 10452 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
10453 TCGv_i64 fp0;
10454
10455 if (ft != 0) {
10456 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10457 fp0 = tcg_temp_new_i64();
10458 gen_load_fpr64(ctx, fp0, fs);
10459 gen_store_fpr64(ctx, fp0, fd);
10460 tcg_temp_free_i64(fp0);
10461 gen_set_label(l1);
10462 }
a16336e4 10463 }
6ea83fed 10464 break;
bf4120ad 10465 case OPC_RECIP_D:
ca6c7803 10466 check_cp1_registers(ctx, fs | fd);
b6d96bed 10467 {
a7812ae4 10468 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10469
10470 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10471 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 10472 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10473 tcg_temp_free_i64(fp0);
b6d96bed 10474 }
57fa1fb3 10475 break;
bf4120ad 10476 case OPC_RSQRT_D:
ca6c7803 10477 check_cp1_registers(ctx, fs | fd);
b6d96bed 10478 {
a7812ae4 10479 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10480
10481 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10482 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 10483 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10484 tcg_temp_free_i64(fp0);
b6d96bed 10485 }
57fa1fb3 10486 break;
e7f16abb
LA
10487 case OPC_MADDF_D:
10488 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 10489 {
a7812ae4
PB
10490 TCGv_i64 fp0 = tcg_temp_new_i64();
10491 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb 10492 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
10493 gen_load_fpr64(ctx, fp0, fs);
10494 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
10495 gen_load_fpr64(ctx, fp2, fd);
10496 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
10497 gen_store_fpr64(ctx, fp2, fd);
10498 tcg_temp_free_i64(fp2);
a7812ae4 10499 tcg_temp_free_i64(fp1);
a7812ae4 10500 tcg_temp_free_i64(fp0);
b6d96bed 10501 }
57fa1fb3 10502 break;
e7f16abb
LA
10503 case OPC_MSUBF_D:
10504 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 10505 {
a7812ae4 10506 TCGv_i64 fp0 = tcg_temp_new_i64();
e7f16abb
LA
10507 TCGv_i64 fp1 = tcg_temp_new_i64();
10508 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed 10509 gen_load_fpr64(ctx, fp0, fs);
e7f16abb
LA
10510 gen_load_fpr64(ctx, fp1, ft);
10511 gen_load_fpr64(ctx, fp2, fd);
10512 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
10513 gen_store_fpr64(ctx, fp2, fd);
10514 tcg_temp_free_i64(fp2);
10515 tcg_temp_free_i64(fp1);
a7812ae4 10516 tcg_temp_free_i64(fp0);
b6d96bed 10517 }
57fa1fb3 10518 break;
e7f16abb
LA
10519 case OPC_RINT_D:
10520 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 10521 {
a7812ae4 10522 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 10523 gen_load_fpr64(ctx, fp0, fs);
e7f16abb 10524 gen_helper_float_rint_d(fp0, cpu_env, fp0);
b6d96bed 10525 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10526 tcg_temp_free_i64(fp0);
b6d96bed 10527 }
57fa1fb3 10528 break;
e7f16abb
LA
10529 case OPC_CLASS_D:
10530 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 10531 {
e7f16abb
LA
10532 TCGv_i64 fp0 = tcg_temp_new_i64();
10533 gen_load_fpr64(ctx, fp0, fs);
af39bc8c 10534 gen_helper_float_class_d(fp0, cpu_env, fp0);
e7f16abb
LA
10535 gen_store_fpr64(ctx, fp0, fd);
10536 tcg_temp_free_i64(fp0);
e7f16abb
LA
10537 }
10538 break;
10539 case OPC_MIN_D: /* OPC_RECIP2_D */
10540 if (ctx->insn_flags & ISA_MIPS32R6) {
10541 /* OPC_MIN_D */
a7812ae4
PB
10542 TCGv_i64 fp0 = tcg_temp_new_i64();
10543 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb
LA
10544 gen_load_fpr64(ctx, fp0, fs);
10545 gen_load_fpr64(ctx, fp1, ft);
10546 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
10547 gen_store_fpr64(ctx, fp1, fd);
10548 tcg_temp_free_i64(fp1);
10549 tcg_temp_free_i64(fp0);
e7f16abb
LA
10550 } else {
10551 /* OPC_RECIP2_D */
10552 check_cp1_64bitmode(ctx);
10553 {
10554 TCGv_i64 fp0 = tcg_temp_new_i64();
10555 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed 10556
e7f16abb
LA
10557 gen_load_fpr64(ctx, fp0, fs);
10558 gen_load_fpr64(ctx, fp1, ft);
10559 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
10560 tcg_temp_free_i64(fp1);
10561 gen_store_fpr64(ctx, fp0, fd);
10562 tcg_temp_free_i64(fp0);
10563 }
e7f16abb
LA
10564 }
10565 break;
10566 case OPC_MINA_D: /* OPC_RECIP1_D */
10567 if (ctx->insn_flags & ISA_MIPS32R6) {
10568 /* OPC_MINA_D */
10569 TCGv_i64 fp0 = tcg_temp_new_i64();
10570 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10571 gen_load_fpr64(ctx, fp0, fs);
10572 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
10573 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
10574 gen_store_fpr64(ctx, fp1, fd);
10575 tcg_temp_free_i64(fp1);
10576 tcg_temp_free_i64(fp0);
e7f16abb
LA
10577 } else {
10578 /* OPC_RECIP1_D */
10579 check_cp1_64bitmode(ctx);
10580 {
10581 TCGv_i64 fp0 = tcg_temp_new_i64();
10582
10583 gen_load_fpr64(ctx, fp0, fs);
10584 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
10585 gen_store_fpr64(ctx, fp0, fd);
10586 tcg_temp_free_i64(fp0);
10587 }
e7f16abb
LA
10588 }
10589 break;
10590 case OPC_MAX_D: /* OPC_RSQRT1_D */
10591 if (ctx->insn_flags & ISA_MIPS32R6) {
10592 /* OPC_MAX_D */
10593 TCGv_i64 fp0 = tcg_temp_new_i64();
10594 TCGv_i64 fp1 = tcg_temp_new_i64();
10595 gen_load_fpr64(ctx, fp0, fs);
10596 gen_load_fpr64(ctx, fp1, ft);
10597 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
10598 gen_store_fpr64(ctx, fp1, fd);
a7812ae4 10599 tcg_temp_free_i64(fp1);
a7812ae4 10600 tcg_temp_free_i64(fp0);
e7f16abb
LA
10601 } else {
10602 /* OPC_RSQRT1_D */
10603 check_cp1_64bitmode(ctx);
10604 {
10605 TCGv_i64 fp0 = tcg_temp_new_i64();
10606
10607 gen_load_fpr64(ctx, fp0, fs);
10608 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
10609 gen_store_fpr64(ctx, fp0, fd);
10610 tcg_temp_free_i64(fp0);
10611 }
e7f16abb
LA
10612 }
10613 break;
10614 case OPC_MAXA_D: /* OPC_RSQRT2_D */
10615 if (ctx->insn_flags & ISA_MIPS32R6) {
10616 /* OPC_MAXA_D */
10617 TCGv_i64 fp0 = tcg_temp_new_i64();
10618 TCGv_i64 fp1 = tcg_temp_new_i64();
10619 gen_load_fpr64(ctx, fp0, fs);
10620 gen_load_fpr64(ctx, fp1, ft);
10621 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
10622 gen_store_fpr64(ctx, fp1, fd);
10623 tcg_temp_free_i64(fp1);
10624 tcg_temp_free_i64(fp0);
e7f16abb
LA
10625 } else {
10626 /* OPC_RSQRT2_D */
10627 check_cp1_64bitmode(ctx);
10628 {
10629 TCGv_i64 fp0 = tcg_temp_new_i64();
10630 TCGv_i64 fp1 = tcg_temp_new_i64();
10631
10632 gen_load_fpr64(ctx, fp0, fs);
10633 gen_load_fpr64(ctx, fp1, ft);
10634 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
10635 tcg_temp_free_i64(fp1);
10636 gen_store_fpr64(ctx, fp0, fd);
10637 tcg_temp_free_i64(fp0);
10638 }
b6d96bed 10639 }
57fa1fb3 10640 break;
bf4120ad
NF
10641 case OPC_CMP_F_D:
10642 case OPC_CMP_UN_D:
10643 case OPC_CMP_EQ_D:
10644 case OPC_CMP_UEQ_D:
10645 case OPC_CMP_OLT_D:
10646 case OPC_CMP_ULT_D:
10647 case OPC_CMP_OLE_D:
10648 case OPC_CMP_ULE_D:
10649 case OPC_CMP_SF_D:
10650 case OPC_CMP_NGLE_D:
10651 case OPC_CMP_SEQ_D:
10652 case OPC_CMP_NGL_D:
10653 case OPC_CMP_LT_D:
10654 case OPC_CMP_NGE_D:
10655 case OPC_CMP_LE_D:
10656 case OPC_CMP_NGT_D:
fecd2646 10657 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c
NF
10658 if (ctx->opcode & (1 << 6)) {
10659 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
8153667c
NF
10660 } else {
10661 gen_cmp_d(ctx, func-48, ft, fs, cc);
5a1e8ffb 10662 }
6ea83fed 10663 break;
bf4120ad 10664 case OPC_CVT_S_D:
5e755519 10665 check_cp1_registers(ctx, fs);
b6d96bed 10666 {
a7812ae4
PB
10667 TCGv_i32 fp32 = tcg_temp_new_i32();
10668 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10669
10670 gen_load_fpr64(ctx, fp64, fs);
895c2d04 10671 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 10672 tcg_temp_free_i64(fp64);
7c979afd 10673 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10674 tcg_temp_free_i32(fp32);
b6d96bed 10675 }
5a5012ec 10676 break;
bf4120ad 10677 case OPC_CVT_W_D:
5e755519 10678 check_cp1_registers(ctx, fs);
b6d96bed 10679 {
a7812ae4
PB
10680 TCGv_i32 fp32 = tcg_temp_new_i32();
10681 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10682
10683 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10684 if (ctx->nan2008) {
10685 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
10686 } else {
10687 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
10688 }
a7812ae4 10689 tcg_temp_free_i64(fp64);
7c979afd 10690 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10691 tcg_temp_free_i32(fp32);
b6d96bed 10692 }
5a5012ec 10693 break;
bf4120ad 10694 case OPC_CVT_L_D:
5e755519 10695 check_cp1_64bitmode(ctx);
b6d96bed 10696 {
a7812ae4 10697 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10698
10699 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10700 if (ctx->nan2008) {
10701 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
10702 } else {
10703 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
10704 }
b6d96bed 10705 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10706 tcg_temp_free_i64(fp0);
b6d96bed 10707 }
5a5012ec 10708 break;
bf4120ad 10709 case OPC_CVT_S_W:
b6d96bed 10710 {
a7812ae4 10711 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10712
7c979afd 10713 gen_load_fpr32(ctx, fp0, fs);
895c2d04 10714 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
7c979afd 10715 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10716 tcg_temp_free_i32(fp0);
b6d96bed 10717 }
6ea83fed 10718 break;
bf4120ad 10719 case OPC_CVT_D_W:
5e755519 10720 check_cp1_registers(ctx, fd);
b6d96bed 10721 {
a7812ae4
PB
10722 TCGv_i32 fp32 = tcg_temp_new_i32();
10723 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10724
7c979afd 10725 gen_load_fpr32(ctx, fp32, fs);
895c2d04 10726 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 10727 tcg_temp_free_i32(fp32);
b6d96bed 10728 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10729 tcg_temp_free_i64(fp64);
b6d96bed 10730 }
5a5012ec 10731 break;
bf4120ad 10732 case OPC_CVT_S_L:
5e755519 10733 check_cp1_64bitmode(ctx);
b6d96bed 10734 {
a7812ae4
PB
10735 TCGv_i32 fp32 = tcg_temp_new_i32();
10736 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10737
10738 gen_load_fpr64(ctx, fp64, fs);
895c2d04 10739 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 10740 tcg_temp_free_i64(fp64);
7c979afd 10741 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10742 tcg_temp_free_i32(fp32);
b6d96bed 10743 }
5a5012ec 10744 break;
bf4120ad 10745 case OPC_CVT_D_L:
5e755519 10746 check_cp1_64bitmode(ctx);
b6d96bed 10747 {
a7812ae4 10748 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10749
10750 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10751 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 10752 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10753 tcg_temp_free_i64(fp0);
b6d96bed 10754 }
5a5012ec 10755 break;
bf4120ad 10756 case OPC_CVT_PS_PW:
e29c9628 10757 check_ps(ctx);
b6d96bed 10758 {
a7812ae4 10759 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10760
10761 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10762 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 10763 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10764 tcg_temp_free_i64(fp0);
b6d96bed 10765 }
5a5012ec 10766 break;
bf4120ad 10767 case OPC_ADD_PS:
e29c9628 10768 check_ps(ctx);
b6d96bed 10769 {
a7812ae4
PB
10770 TCGv_i64 fp0 = tcg_temp_new_i64();
10771 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10772
10773 gen_load_fpr64(ctx, fp0, fs);
10774 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10775 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 10776 tcg_temp_free_i64(fp1);
b6d96bed 10777 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10778 tcg_temp_free_i64(fp0);
b6d96bed 10779 }
6ea83fed 10780 break;
bf4120ad 10781 case OPC_SUB_PS:
e29c9628 10782 check_ps(ctx);
b6d96bed 10783 {
a7812ae4
PB
10784 TCGv_i64 fp0 = tcg_temp_new_i64();
10785 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10786
10787 gen_load_fpr64(ctx, fp0, fs);
10788 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10789 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 10790 tcg_temp_free_i64(fp1);
b6d96bed 10791 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10792 tcg_temp_free_i64(fp0);
b6d96bed 10793 }
6ea83fed 10794 break;
bf4120ad 10795 case OPC_MUL_PS:
e29c9628 10796 check_ps(ctx);
b6d96bed 10797 {
a7812ae4
PB
10798 TCGv_i64 fp0 = tcg_temp_new_i64();
10799 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10800
10801 gen_load_fpr64(ctx, fp0, fs);
10802 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10803 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 10804 tcg_temp_free_i64(fp1);
b6d96bed 10805 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10806 tcg_temp_free_i64(fp0);
b6d96bed 10807 }
6ea83fed 10808 break;
bf4120ad 10809 case OPC_ABS_PS:
e29c9628 10810 check_ps(ctx);
b6d96bed 10811 {
a7812ae4 10812 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10813
10814 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 10815 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 10816 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10817 tcg_temp_free_i64(fp0);
b6d96bed 10818 }
6ea83fed 10819 break;
bf4120ad 10820 case OPC_MOV_PS:
e29c9628 10821 check_ps(ctx);
b6d96bed 10822 {
a7812ae4 10823 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10824
10825 gen_load_fpr64(ctx, fp0, fs);
10826 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10827 tcg_temp_free_i64(fp0);
b6d96bed 10828 }
6ea83fed 10829 break;
bf4120ad 10830 case OPC_NEG_PS:
e29c9628 10831 check_ps(ctx);
b6d96bed 10832 {
a7812ae4 10833 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10834
10835 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 10836 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 10837 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10838 tcg_temp_free_i64(fp0);
b6d96bed 10839 }
6ea83fed 10840 break;
bf4120ad 10841 case OPC_MOVCF_PS:
e29c9628 10842 check_ps(ctx);
7f6613ce 10843 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6ea83fed 10844 break;
bf4120ad 10845 case OPC_MOVZ_PS:
e29c9628 10846 check_ps(ctx);
a16336e4 10847 {
42a268c2 10848 TCGLabel *l1 = gen_new_label();
30a3848b 10849 TCGv_i64 fp0;
a16336e4 10850
c9297f4d
AJ
10851 if (ft != 0)
10852 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10853 fp0 = tcg_temp_new_i64();
10854 gen_load_fpr64(ctx, fp0, fs);
10855 gen_store_fpr64(ctx, fp0, fd);
10856 tcg_temp_free_i64(fp0);
a16336e4
TS
10857 gen_set_label(l1);
10858 }
6ea83fed 10859 break;
bf4120ad 10860 case OPC_MOVN_PS:
e29c9628 10861 check_ps(ctx);
a16336e4 10862 {
42a268c2 10863 TCGLabel *l1 = gen_new_label();
30a3848b 10864 TCGv_i64 fp0;
c9297f4d
AJ
10865
10866 if (ft != 0) {
10867 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10868 fp0 = tcg_temp_new_i64();
10869 gen_load_fpr64(ctx, fp0, fs);
10870 gen_store_fpr64(ctx, fp0, fd);
10871 tcg_temp_free_i64(fp0);
10872 gen_set_label(l1);
10873 }
a16336e4 10874 }
6ea83fed 10875 break;
bf4120ad 10876 case OPC_ADDR_PS:
e29c9628 10877 check_ps(ctx);
b6d96bed 10878 {
a7812ae4
PB
10879 TCGv_i64 fp0 = tcg_temp_new_i64();
10880 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10881
10882 gen_load_fpr64(ctx, fp0, ft);
10883 gen_load_fpr64(ctx, fp1, fs);
895c2d04 10884 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 10885 tcg_temp_free_i64(fp1);
b6d96bed 10886 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10887 tcg_temp_free_i64(fp0);
b6d96bed 10888 }
fbcc6828 10889 break;
bf4120ad 10890 case OPC_MULR_PS:
e29c9628 10891 check_ps(ctx);
b6d96bed 10892 {
a7812ae4
PB
10893 TCGv_i64 fp0 = tcg_temp_new_i64();
10894 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10895
10896 gen_load_fpr64(ctx, fp0, ft);
10897 gen_load_fpr64(ctx, fp1, fs);
895c2d04 10898 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 10899 tcg_temp_free_i64(fp1);
b6d96bed 10900 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10901 tcg_temp_free_i64(fp0);
b6d96bed 10902 }
57fa1fb3 10903 break;
bf4120ad 10904 case OPC_RECIP2_PS:
e29c9628 10905 check_ps(ctx);
b6d96bed 10906 {
a7812ae4
PB
10907 TCGv_i64 fp0 = tcg_temp_new_i64();
10908 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10909
10910 gen_load_fpr64(ctx, fp0, fs);
d22d7289 10911 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10912 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 10913 tcg_temp_free_i64(fp1);
b6d96bed 10914 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10915 tcg_temp_free_i64(fp0);
b6d96bed 10916 }
57fa1fb3 10917 break;
bf4120ad 10918 case OPC_RECIP1_PS:
e29c9628 10919 check_ps(ctx);
b6d96bed 10920 {
a7812ae4 10921 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10922
10923 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10924 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 10925 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10926 tcg_temp_free_i64(fp0);
b6d96bed 10927 }
57fa1fb3 10928 break;
bf4120ad 10929 case OPC_RSQRT1_PS:
e29c9628 10930 check_ps(ctx);
b6d96bed 10931 {
a7812ae4 10932 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10933
10934 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10935 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 10936 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10937 tcg_temp_free_i64(fp0);
b6d96bed 10938 }
57fa1fb3 10939 break;
bf4120ad 10940 case OPC_RSQRT2_PS:
e29c9628 10941 check_ps(ctx);
b6d96bed 10942 {
a7812ae4
PB
10943 TCGv_i64 fp0 = tcg_temp_new_i64();
10944 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10945
10946 gen_load_fpr64(ctx, fp0, fs);
10947 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10948 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 10949 tcg_temp_free_i64(fp1);
b6d96bed 10950 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10951 tcg_temp_free_i64(fp0);
b6d96bed 10952 }
57fa1fb3 10953 break;
bf4120ad 10954 case OPC_CVT_S_PU:
5e755519 10955 check_cp1_64bitmode(ctx);
b6d96bed 10956 {
a7812ae4 10957 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10958
7f6613ce 10959 gen_load_fpr32h(ctx, fp0, fs);
895c2d04 10960 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
7c979afd 10961 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10962 tcg_temp_free_i32(fp0);
b6d96bed 10963 }
dd016883 10964 break;
bf4120ad 10965 case OPC_CVT_PW_PS:
e29c9628 10966 check_ps(ctx);
b6d96bed 10967 {
a7812ae4 10968 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10969
10970 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10971 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 10972 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10973 tcg_temp_free_i64(fp0);
b6d96bed 10974 }
6ea83fed 10975 break;
bf4120ad 10976 case OPC_CVT_S_PL:
5e755519 10977 check_cp1_64bitmode(ctx);
b6d96bed 10978 {
a7812ae4 10979 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10980
7c979afd 10981 gen_load_fpr32(ctx, fp0, fs);
895c2d04 10982 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
7c979afd 10983 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10984 tcg_temp_free_i32(fp0);
b6d96bed 10985 }
6ea83fed 10986 break;
bf4120ad 10987 case OPC_PLL_PS:
e29c9628 10988 check_ps(ctx);
b6d96bed 10989 {
a7812ae4
PB
10990 TCGv_i32 fp0 = tcg_temp_new_i32();
10991 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10992
7c979afd
LA
10993 gen_load_fpr32(ctx, fp0, fs);
10994 gen_load_fpr32(ctx, fp1, ft);
7f6613ce 10995 gen_store_fpr32h(ctx, fp0, fd);
7c979afd 10996 gen_store_fpr32(ctx, fp1, fd);
a7812ae4
PB
10997 tcg_temp_free_i32(fp0);
10998 tcg_temp_free_i32(fp1);
b6d96bed 10999 }
6ea83fed 11000 break;
bf4120ad 11001 case OPC_PLU_PS:
e29c9628 11002 check_ps(ctx);
b6d96bed 11003 {
a7812ae4
PB
11004 TCGv_i32 fp0 = tcg_temp_new_i32();
11005 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11006
7c979afd 11007 gen_load_fpr32(ctx, fp0, fs);
7f6613ce 11008 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 11009 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 11010 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
11011 tcg_temp_free_i32(fp0);
11012 tcg_temp_free_i32(fp1);
b6d96bed 11013 }
5a5012ec 11014 break;
bf4120ad 11015 case OPC_PUL_PS:
e29c9628 11016 check_ps(ctx);
b6d96bed 11017 {
a7812ae4
PB
11018 TCGv_i32 fp0 = tcg_temp_new_i32();
11019 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11020
7f6613ce 11021 gen_load_fpr32h(ctx, fp0, fs);
7c979afd
LA
11022 gen_load_fpr32(ctx, fp1, ft);
11023 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 11024 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
11025 tcg_temp_free_i32(fp0);
11026 tcg_temp_free_i32(fp1);
b6d96bed 11027 }
5a5012ec 11028 break;
bf4120ad 11029 case OPC_PUU_PS:
e29c9628 11030 check_ps(ctx);
b6d96bed 11031 {
a7812ae4
PB
11032 TCGv_i32 fp0 = tcg_temp_new_i32();
11033 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 11034
7f6613ce
PJ
11035 gen_load_fpr32h(ctx, fp0, fs);
11036 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 11037 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 11038 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
11039 tcg_temp_free_i32(fp0);
11040 tcg_temp_free_i32(fp1);
b6d96bed 11041 }
5a5012ec 11042 break;
bf4120ad
NF
11043 case OPC_CMP_F_PS:
11044 case OPC_CMP_UN_PS:
11045 case OPC_CMP_EQ_PS:
11046 case OPC_CMP_UEQ_PS:
11047 case OPC_CMP_OLT_PS:
11048 case OPC_CMP_ULT_PS:
11049 case OPC_CMP_OLE_PS:
11050 case OPC_CMP_ULE_PS:
11051 case OPC_CMP_SF_PS:
11052 case OPC_CMP_NGLE_PS:
11053 case OPC_CMP_SEQ_PS:
11054 case OPC_CMP_NGL_PS:
11055 case OPC_CMP_LT_PS:
11056 case OPC_CMP_NGE_PS:
11057 case OPC_CMP_LE_PS:
11058 case OPC_CMP_NGT_PS:
8153667c
NF
11059 if (ctx->opcode & (1 << 6)) {
11060 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
8153667c
NF
11061 } else {
11062 gen_cmp_ps(ctx, func-48, ft, fs, cc);
5a1e8ffb 11063 }
6ea83fed 11064 break;
5a5012ec 11065 default:
9d68ac14 11066 MIPS_INVAL("farith");
9c708c7f 11067 generate_exception_end(ctx, EXCP_RI);
6ea83fed
FB
11068 return;
11069 }
6ea83fed 11070}
6af0bf9c 11071
5a5012ec 11072/* Coprocessor 3 (FPU) */
5e755519
TS
11073static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
11074 int fd, int fs, int base, int index)
7a387fff 11075{
4e2474d6 11076 TCGv t0 = tcg_temp_new();
7a387fff 11077
93b12ccc 11078 if (base == 0) {
6c5c1e20 11079 gen_load_gpr(t0, index);
93b12ccc 11080 } else if (index == 0) {
6c5c1e20 11081 gen_load_gpr(t0, base);
93b12ccc 11082 } else {
05168674 11083 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 11084 }
5a5012ec 11085 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 11086 memory access. */
5a5012ec
TS
11087 switch (opc) {
11088 case OPC_LWXC1:
8c0ab41f 11089 check_cop1x(ctx);
b6d96bed 11090 {
a7812ae4 11091 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 11092
5f68f5ae 11093 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
585c88d5 11094 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 11095 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 11096 tcg_temp_free_i32(fp0);
b6d96bed 11097 }
5a5012ec
TS
11098 break;
11099 case OPC_LDXC1:
8c0ab41f
AJ
11100 check_cop1x(ctx);
11101 check_cp1_registers(ctx, fd);
b6d96bed 11102 {
a7812ae4 11103 TCGv_i64 fp0 = tcg_temp_new_i64();
5f68f5ae 11104 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 11105 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11106 tcg_temp_free_i64(fp0);
b6d96bed 11107 }
5a5012ec
TS
11108 break;
11109 case OPC_LUXC1:
8c0ab41f 11110 check_cp1_64bitmode(ctx);
6c5c1e20 11111 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 11112 {
a7812ae4 11113 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11114
5f68f5ae 11115 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 11116 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 11117 tcg_temp_free_i64(fp0);
b6d96bed 11118 }
5a5012ec
TS
11119 break;
11120 case OPC_SWXC1:
8c0ab41f 11121 check_cop1x(ctx);
b6d96bed 11122 {
a7812ae4 11123 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 11124 gen_load_fpr32(ctx, fp0, fs);
5f68f5ae 11125 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
a7812ae4 11126 tcg_temp_free_i32(fp0);
b6d96bed 11127 }
5a5012ec
TS
11128 break;
11129 case OPC_SDXC1:
8c0ab41f
AJ
11130 check_cop1x(ctx);
11131 check_cp1_registers(ctx, fs);
b6d96bed 11132 {
a7812ae4 11133 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11134 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 11135 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 11136 tcg_temp_free_i64(fp0);
b6d96bed 11137 }
5a5012ec
TS
11138 break;
11139 case OPC_SUXC1:
8c0ab41f 11140 check_cp1_64bitmode(ctx);
6c5c1e20 11141 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 11142 {
a7812ae4 11143 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 11144 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 11145 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 11146 tcg_temp_free_i64(fp0);
b6d96bed 11147 }
5a5012ec 11148 break;
5a5012ec 11149 }
6c5c1e20 11150 tcg_temp_free(t0);
5a5012ec
TS
11151}
11152
5e755519
TS
11153static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
11154 int fd, int fr, int fs, int ft)
5a5012ec 11155{
5a5012ec
TS
11156 switch (opc) {
11157 case OPC_ALNV_PS:
e29c9628 11158 check_ps(ctx);
a16336e4 11159 {
a7812ae4 11160 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
11161 TCGv_i32 fp = tcg_temp_new_i32();
11162 TCGv_i32 fph = tcg_temp_new_i32();
42a268c2
RH
11163 TCGLabel *l1 = gen_new_label();
11164 TCGLabel *l2 = gen_new_label();
a16336e4 11165
6c5c1e20
TS
11166 gen_load_gpr(t0, fr);
11167 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
11168
11169 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7c979afd 11170 gen_load_fpr32(ctx, fp, fs);
7f6613ce 11171 gen_load_fpr32h(ctx, fph, fs);
7c979afd 11172 gen_store_fpr32(ctx, fp, fd);
7f6613ce 11173 gen_store_fpr32h(ctx, fph, fd);
a16336e4
TS
11174 tcg_gen_br(l2);
11175 gen_set_label(l1);
6c5c1e20
TS
11176 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
11177 tcg_temp_free(t0);
a16336e4 11178#ifdef TARGET_WORDS_BIGENDIAN
7c979afd 11179 gen_load_fpr32(ctx, fp, fs);
7f6613ce
PJ
11180 gen_load_fpr32h(ctx, fph, ft);
11181 gen_store_fpr32h(ctx, fp, fd);
7c979afd 11182 gen_store_fpr32(ctx, fph, fd);
a16336e4 11183#else
7f6613ce 11184 gen_load_fpr32h(ctx, fph, fs);
7c979afd
LA
11185 gen_load_fpr32(ctx, fp, ft);
11186 gen_store_fpr32(ctx, fph, fd);
7f6613ce 11187 gen_store_fpr32h(ctx, fp, fd);
a16336e4
TS
11188#endif
11189 gen_set_label(l2);
c905fdac
AJ
11190 tcg_temp_free_i32(fp);
11191 tcg_temp_free_i32(fph);
a16336e4 11192 }
5a5012ec
TS
11193 break;
11194 case OPC_MADD_S:
b8aa4598 11195 check_cop1x(ctx);
b6d96bed 11196 {
a7812ae4
PB
11197 TCGv_i32 fp0 = tcg_temp_new_i32();
11198 TCGv_i32 fp1 = tcg_temp_new_i32();
11199 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11200
7c979afd
LA
11201 gen_load_fpr32(ctx, fp0, fs);
11202 gen_load_fpr32(ctx, fp1, ft);
11203 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 11204 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11205 tcg_temp_free_i32(fp0);
11206 tcg_temp_free_i32(fp1);
7c979afd 11207 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 11208 tcg_temp_free_i32(fp2);
b6d96bed 11209 }
5a5012ec
TS
11210 break;
11211 case OPC_MADD_D:
b8aa4598
TS
11212 check_cop1x(ctx);
11213 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11214 {
a7812ae4
PB
11215 TCGv_i64 fp0 = tcg_temp_new_i64();
11216 TCGv_i64 fp1 = tcg_temp_new_i64();
11217 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11218
11219 gen_load_fpr64(ctx, fp0, fs);
11220 gen_load_fpr64(ctx, fp1, ft);
11221 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11222 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11223 tcg_temp_free_i64(fp0);
11224 tcg_temp_free_i64(fp1);
b6d96bed 11225 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11226 tcg_temp_free_i64(fp2);
b6d96bed 11227 }
5a5012ec
TS
11228 break;
11229 case OPC_MADD_PS:
e29c9628 11230 check_ps(ctx);
b6d96bed 11231 {
a7812ae4
PB
11232 TCGv_i64 fp0 = tcg_temp_new_i64();
11233 TCGv_i64 fp1 = tcg_temp_new_i64();
11234 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11235
11236 gen_load_fpr64(ctx, fp0, fs);
11237 gen_load_fpr64(ctx, fp1, ft);
11238 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11239 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11240 tcg_temp_free_i64(fp0);
11241 tcg_temp_free_i64(fp1);
b6d96bed 11242 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11243 tcg_temp_free_i64(fp2);
b6d96bed 11244 }
5a5012ec
TS
11245 break;
11246 case OPC_MSUB_S:
b8aa4598 11247 check_cop1x(ctx);
b6d96bed 11248 {
a7812ae4
PB
11249 TCGv_i32 fp0 = tcg_temp_new_i32();
11250 TCGv_i32 fp1 = tcg_temp_new_i32();
11251 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11252
7c979afd
LA
11253 gen_load_fpr32(ctx, fp0, fs);
11254 gen_load_fpr32(ctx, fp1, ft);
11255 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 11256 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11257 tcg_temp_free_i32(fp0);
11258 tcg_temp_free_i32(fp1);
7c979afd 11259 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 11260 tcg_temp_free_i32(fp2);
b6d96bed 11261 }
5a5012ec
TS
11262 break;
11263 case OPC_MSUB_D:
b8aa4598
TS
11264 check_cop1x(ctx);
11265 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11266 {
a7812ae4
PB
11267 TCGv_i64 fp0 = tcg_temp_new_i64();
11268 TCGv_i64 fp1 = tcg_temp_new_i64();
11269 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11270
11271 gen_load_fpr64(ctx, fp0, fs);
11272 gen_load_fpr64(ctx, fp1, ft);
11273 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11274 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11275 tcg_temp_free_i64(fp0);
11276 tcg_temp_free_i64(fp1);
b6d96bed 11277 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11278 tcg_temp_free_i64(fp2);
b6d96bed 11279 }
5a5012ec
TS
11280 break;
11281 case OPC_MSUB_PS:
e29c9628 11282 check_ps(ctx);
b6d96bed 11283 {
a7812ae4
PB
11284 TCGv_i64 fp0 = tcg_temp_new_i64();
11285 TCGv_i64 fp1 = tcg_temp_new_i64();
11286 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11287
11288 gen_load_fpr64(ctx, fp0, fs);
11289 gen_load_fpr64(ctx, fp1, ft);
11290 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11291 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11292 tcg_temp_free_i64(fp0);
11293 tcg_temp_free_i64(fp1);
b6d96bed 11294 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11295 tcg_temp_free_i64(fp2);
b6d96bed 11296 }
5a5012ec
TS
11297 break;
11298 case OPC_NMADD_S:
b8aa4598 11299 check_cop1x(ctx);
b6d96bed 11300 {
a7812ae4
PB
11301 TCGv_i32 fp0 = tcg_temp_new_i32();
11302 TCGv_i32 fp1 = tcg_temp_new_i32();
11303 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11304
7c979afd
LA
11305 gen_load_fpr32(ctx, fp0, fs);
11306 gen_load_fpr32(ctx, fp1, ft);
11307 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 11308 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11309 tcg_temp_free_i32(fp0);
11310 tcg_temp_free_i32(fp1);
7c979afd 11311 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 11312 tcg_temp_free_i32(fp2);
b6d96bed 11313 }
5a5012ec
TS
11314 break;
11315 case OPC_NMADD_D:
b8aa4598
TS
11316 check_cop1x(ctx);
11317 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11318 {
a7812ae4
PB
11319 TCGv_i64 fp0 = tcg_temp_new_i64();
11320 TCGv_i64 fp1 = tcg_temp_new_i64();
11321 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11322
11323 gen_load_fpr64(ctx, fp0, fs);
11324 gen_load_fpr64(ctx, fp1, ft);
11325 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11326 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11327 tcg_temp_free_i64(fp0);
11328 tcg_temp_free_i64(fp1);
b6d96bed 11329 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11330 tcg_temp_free_i64(fp2);
b6d96bed 11331 }
5a5012ec
TS
11332 break;
11333 case OPC_NMADD_PS:
e29c9628 11334 check_ps(ctx);
b6d96bed 11335 {
a7812ae4
PB
11336 TCGv_i64 fp0 = tcg_temp_new_i64();
11337 TCGv_i64 fp1 = tcg_temp_new_i64();
11338 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11339
11340 gen_load_fpr64(ctx, fp0, fs);
11341 gen_load_fpr64(ctx, fp1, ft);
11342 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11343 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11344 tcg_temp_free_i64(fp0);
11345 tcg_temp_free_i64(fp1);
b6d96bed 11346 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11347 tcg_temp_free_i64(fp2);
b6d96bed 11348 }
5a5012ec
TS
11349 break;
11350 case OPC_NMSUB_S:
b8aa4598 11351 check_cop1x(ctx);
b6d96bed 11352 {
a7812ae4
PB
11353 TCGv_i32 fp0 = tcg_temp_new_i32();
11354 TCGv_i32 fp1 = tcg_temp_new_i32();
11355 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11356
7c979afd
LA
11357 gen_load_fpr32(ctx, fp0, fs);
11358 gen_load_fpr32(ctx, fp1, ft);
11359 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 11360 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11361 tcg_temp_free_i32(fp0);
11362 tcg_temp_free_i32(fp1);
7c979afd 11363 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 11364 tcg_temp_free_i32(fp2);
b6d96bed 11365 }
5a5012ec
TS
11366 break;
11367 case OPC_NMSUB_D:
b8aa4598
TS
11368 check_cop1x(ctx);
11369 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11370 {
a7812ae4
PB
11371 TCGv_i64 fp0 = tcg_temp_new_i64();
11372 TCGv_i64 fp1 = tcg_temp_new_i64();
11373 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11374
11375 gen_load_fpr64(ctx, fp0, fs);
11376 gen_load_fpr64(ctx, fp1, ft);
11377 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11378 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11379 tcg_temp_free_i64(fp0);
11380 tcg_temp_free_i64(fp1);
b6d96bed 11381 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11382 tcg_temp_free_i64(fp2);
b6d96bed 11383 }
5a5012ec
TS
11384 break;
11385 case OPC_NMSUB_PS:
e29c9628 11386 check_ps(ctx);
b6d96bed 11387 {
a7812ae4
PB
11388 TCGv_i64 fp0 = tcg_temp_new_i64();
11389 TCGv_i64 fp1 = tcg_temp_new_i64();
11390 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11391
11392 gen_load_fpr64(ctx, fp0, fs);
11393 gen_load_fpr64(ctx, fp1, ft);
11394 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11395 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11396 tcg_temp_free_i64(fp0);
11397 tcg_temp_free_i64(fp1);
b6d96bed 11398 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11399 tcg_temp_free_i64(fp2);
b6d96bed 11400 }
5a5012ec 11401 break;
923617a3 11402 default:
9d68ac14 11403 MIPS_INVAL("flt3_arith");
9c708c7f 11404 generate_exception_end(ctx, EXCP_RI);
5a5012ec
TS
11405 return;
11406 }
7a387fff
TS
11407}
11408
b00c7218 11409static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
26ebe468
NF
11410{
11411 TCGv t0;
11412
b3167288
RH
11413#if !defined(CONFIG_USER_ONLY)
11414 /* The Linux kernel will emulate rdhwr if it's not supported natively.
11415 Therefore only check the ISA in system mode. */
d75c135e 11416 check_insn(ctx, ISA_MIPS32R2);
b3167288 11417#endif
26ebe468
NF
11418 t0 = tcg_temp_new();
11419
11420 switch (rd) {
11421 case 0:
895c2d04 11422 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
11423 gen_store_gpr(t0, rt);
11424 break;
11425 case 1:
895c2d04 11426 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
11427 gen_store_gpr(t0, rt);
11428 break;
11429 case 2:
eeb3bba8 11430 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
11431 gen_io_start();
11432 }
895c2d04 11433 gen_helper_rdhwr_cc(t0, cpu_env);
eeb3bba8 11434 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
11435 gen_io_end();
11436 }
26ebe468 11437 gen_store_gpr(t0, rt);
d673a68d 11438 /* Break the TB to be able to take timer interrupts immediately
b28425ba 11439 after reading count. DISAS_STOP isn't sufficient, we need to ensure
d673a68d 11440 we break completely out of translated code. */
eeb3bba8
EC
11441 gen_save_pc(ctx->base.pc_next + 4);
11442 ctx->base.is_jmp = DISAS_EXIT;
26ebe468
NF
11443 break;
11444 case 3:
895c2d04 11445 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
11446 gen_store_gpr(t0, rt);
11447 break;
b00c7218
YK
11448 case 4:
11449 check_insn(ctx, ISA_MIPS32R6);
11450 if (sel != 0) {
11451 /* Performance counter registers are not implemented other than
11452 * control register 0.
11453 */
11454 generate_exception(ctx, EXCP_RI);
11455 }
11456 gen_helper_rdhwr_performance(t0, cpu_env);
11457 gen_store_gpr(t0, rt);
11458 break;
11459 case 5:
11460 check_insn(ctx, ISA_MIPS32R6);
11461 gen_helper_rdhwr_xnp(t0, cpu_env);
11462 gen_store_gpr(t0, rt);
11463 break;
26ebe468
NF
11464 case 29:
11465#if defined(CONFIG_USER_ONLY)
d279279e
PJ
11466 tcg_gen_ld_tl(t0, cpu_env,
11467 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
26ebe468
NF
11468 gen_store_gpr(t0, rt);
11469 break;
11470#else
d279279e
PJ
11471 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
11472 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
11473 tcg_gen_ld_tl(t0, cpu_env,
11474 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11475 gen_store_gpr(t0, rt);
11476 } else {
9c708c7f 11477 generate_exception_end(ctx, EXCP_RI);
d279279e
PJ
11478 }
11479 break;
26ebe468
NF
11480#endif
11481 default: /* Invalid */
11482 MIPS_INVAL("rdhwr");
9c708c7f 11483 generate_exception_end(ctx, EXCP_RI);
26ebe468
NF
11484 break;
11485 }
11486 tcg_temp_free(t0);
11487}
11488
a5f53390
LA
11489static inline void clear_branch_hflags(DisasContext *ctx)
11490{
11491 ctx->hflags &= ~MIPS_HFLAG_BMASK;
eeb3bba8 11492 if (ctx->base.is_jmp == DISAS_NEXT) {
a5f53390
LA
11493 save_cpu_state(ctx, 0);
11494 } else {
11495 /* it is not safe to save ctx->hflags as hflags may be changed
11496 in execution time by the instruction in delay / forbidden slot. */
11497 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
11498 }
11499}
11500
31837be3 11501static void gen_branch(DisasContext *ctx, int insn_bytes)
c9602061
NF
11502{
11503 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 11504 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061 11505 /* Branches completion */
a5f53390 11506 clear_branch_hflags(ctx);
eeb3bba8 11507 ctx->base.is_jmp = DISAS_NORETURN;
c9602061 11508 /* FIXME: Need to clear can_do_io. */
364d4831 11509 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
339cd2a8 11510 case MIPS_HFLAG_FBNSLOT:
eeb3bba8 11511 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
339cd2a8 11512 break;
c9602061
NF
11513 case MIPS_HFLAG_B:
11514 /* unconditional branch */
364d4831
NF
11515 if (proc_hflags & MIPS_HFLAG_BX) {
11516 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
11517 }
c9602061
NF
11518 gen_goto_tb(ctx, 0, ctx->btarget);
11519 break;
11520 case MIPS_HFLAG_BL:
11521 /* blikely taken case */
c9602061
NF
11522 gen_goto_tb(ctx, 0, ctx->btarget);
11523 break;
11524 case MIPS_HFLAG_BC:
11525 /* Conditional branch */
c9602061 11526 {
42a268c2 11527 TCGLabel *l1 = gen_new_label();
c9602061
NF
11528
11529 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
eeb3bba8 11530 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
c9602061
NF
11531 gen_set_label(l1);
11532 gen_goto_tb(ctx, 0, ctx->btarget);
11533 }
11534 break;
11535 case MIPS_HFLAG_BR:
11536 /* unconditional branch to register */
d75c135e 11537 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
11538 TCGv t0 = tcg_temp_new();
11539 TCGv_i32 t1 = tcg_temp_new_i32();
11540
11541 tcg_gen_andi_tl(t0, btarget, 0x1);
11542 tcg_gen_trunc_tl_i32(t1, t0);
11543 tcg_temp_free(t0);
11544 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
11545 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
11546 tcg_gen_or_i32(hflags, hflags, t1);
11547 tcg_temp_free_i32(t1);
11548
11549 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
11550 } else {
11551 tcg_gen_mov_tl(cpu_PC, btarget);
11552 }
eeb3bba8 11553 if (ctx->base.singlestep_enabled) {
c9602061 11554 save_cpu_state(ctx, 0);
9c708c7f 11555 gen_helper_raise_exception_debug(cpu_env);
c9602061 11556 }
7f11636d 11557 tcg_gen_lookup_and_goto_ptr();
c9602061
NF
11558 break;
11559 default:
a5f53390
LA
11560 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
11561 abort();
c9602061
NF
11562 }
11563 }
11564}
11565
6893f074
YK
11566/* Compact Branches */
11567static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
11568 int rs, int rt, int32_t offset)
11569{
11570 int bcond_compute = 0;
11571 TCGv t0 = tcg_temp_new();
11572 TCGv t1 = tcg_temp_new();
65935f07 11573 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
6893f074
YK
11574
11575 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11576#ifdef MIPS_DEBUG_DISAS
11577 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 11578 "\n", ctx->base.pc_next);
6893f074 11579#endif
9c708c7f 11580 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
11581 goto out;
11582 }
11583
11584 /* Load needed operands and calculate btarget */
11585 switch (opc) {
11586 /* compact branch */
11587 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11588 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11589 gen_load_gpr(t0, rs);
11590 gen_load_gpr(t1, rt);
11591 bcond_compute = 1;
eeb3bba8 11592 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11593 if (rs <= rt && rs == 0) {
11594 /* OPC_BEQZALC, OPC_BNEZALC */
eeb3bba8 11595 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
11596 }
11597 break;
11598 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11599 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11600 gen_load_gpr(t0, rs);
11601 gen_load_gpr(t1, rt);
11602 bcond_compute = 1;
eeb3bba8 11603 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11604 break;
11605 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11606 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11607 if (rs == 0 || rs == rt) {
11608 /* OPC_BLEZALC, OPC_BGEZALC */
11609 /* OPC_BGTZALC, OPC_BLTZALC */
eeb3bba8 11610 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
11611 }
11612 gen_load_gpr(t0, rs);
11613 gen_load_gpr(t1, rt);
11614 bcond_compute = 1;
eeb3bba8 11615 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11616 break;
11617 case OPC_BC:
11618 case OPC_BALC:
eeb3bba8 11619 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11620 break;
11621 case OPC_BEQZC:
11622 case OPC_BNEZC:
11623 if (rs != 0) {
11624 /* OPC_BEQZC, OPC_BNEZC */
11625 gen_load_gpr(t0, rs);
11626 bcond_compute = 1;
eeb3bba8 11627 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11628 } else {
11629 /* OPC_JIC, OPC_JIALC */
11630 TCGv tbase = tcg_temp_new();
11631 TCGv toffset = tcg_temp_new();
11632
11633 gen_load_gpr(tbase, rt);
11634 tcg_gen_movi_tl(toffset, offset);
11635 gen_op_addr_add(ctx, btarget, tbase, toffset);
11636 tcg_temp_free(tbase);
11637 tcg_temp_free(toffset);
11638 }
11639 break;
11640 default:
11641 MIPS_INVAL("Compact branch/jump");
9c708c7f 11642 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
11643 goto out;
11644 }
11645
11646 if (bcond_compute == 0) {
11647 /* Uncoditional compact branch */
11648 switch (opc) {
11649 case OPC_JIALC:
eeb3bba8 11650 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
11651 /* Fallthrough */
11652 case OPC_JIC:
11653 ctx->hflags |= MIPS_HFLAG_BR;
11654 break;
11655 case OPC_BALC:
eeb3bba8 11656 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
11657 /* Fallthrough */
11658 case OPC_BC:
11659 ctx->hflags |= MIPS_HFLAG_B;
11660 break;
11661 default:
11662 MIPS_INVAL("Compact branch/jump");
9c708c7f 11663 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
11664 goto out;
11665 }
11666
11667 /* Generating branch here as compact branches don't have delay slot */
11668 gen_branch(ctx, 4);
11669 } else {
11670 /* Conditional compact branch */
11671 TCGLabel *fs = gen_new_label();
11672 save_cpu_state(ctx, 0);
11673
11674 switch (opc) {
11675 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11676 if (rs == 0 && rt != 0) {
11677 /* OPC_BLEZALC */
11678 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11679 } else if (rs != 0 && rt != 0 && rs == rt) {
11680 /* OPC_BGEZALC */
11681 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11682 } else {
11683 /* OPC_BGEUC */
11684 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
11685 }
11686 break;
11687 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11688 if (rs == 0 && rt != 0) {
11689 /* OPC_BGTZALC */
11690 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11691 } else if (rs != 0 && rt != 0 && rs == rt) {
11692 /* OPC_BLTZALC */
11693 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11694 } else {
11695 /* OPC_BLTUC */
11696 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
11697 }
11698 break;
11699 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11700 if (rs == 0 && rt != 0) {
11701 /* OPC_BLEZC */
11702 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11703 } else if (rs != 0 && rt != 0 && rs == rt) {
11704 /* OPC_BGEZC */
11705 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11706 } else {
11707 /* OPC_BGEC */
11708 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
11709 }
11710 break;
11711 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11712 if (rs == 0 && rt != 0) {
11713 /* OPC_BGTZC */
11714 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11715 } else if (rs != 0 && rt != 0 && rs == rt) {
11716 /* OPC_BLTZC */
11717 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11718 } else {
11719 /* OPC_BLTC */
11720 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
11721 }
11722 break;
11723 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11724 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11725 if (rs >= rt) {
11726 /* OPC_BOVC, OPC_BNVC */
11727 TCGv t2 = tcg_temp_new();
11728 TCGv t3 = tcg_temp_new();
11729 TCGv t4 = tcg_temp_new();
11730 TCGv input_overflow = tcg_temp_new();
11731
11732 gen_load_gpr(t0, rs);
11733 gen_load_gpr(t1, rt);
11734 tcg_gen_ext32s_tl(t2, t0);
11735 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
11736 tcg_gen_ext32s_tl(t3, t1);
11737 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
11738 tcg_gen_or_tl(input_overflow, input_overflow, t4);
11739
11740 tcg_gen_add_tl(t4, t2, t3);
11741 tcg_gen_ext32s_tl(t4, t4);
11742 tcg_gen_xor_tl(t2, t2, t3);
11743 tcg_gen_xor_tl(t3, t4, t3);
11744 tcg_gen_andc_tl(t2, t3, t2);
11745 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
11746 tcg_gen_or_tl(t4, t4, input_overflow);
11747 if (opc == OPC_BOVC) {
11748 /* OPC_BOVC */
11749 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
11750 } else {
11751 /* OPC_BNVC */
11752 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
11753 }
11754 tcg_temp_free(input_overflow);
11755 tcg_temp_free(t4);
11756 tcg_temp_free(t3);
11757 tcg_temp_free(t2);
11758 } else if (rs < rt && rs == 0) {
11759 /* OPC_BEQZALC, OPC_BNEZALC */
11760 if (opc == OPC_BEQZALC) {
11761 /* OPC_BEQZALC */
11762 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
11763 } else {
11764 /* OPC_BNEZALC */
11765 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
11766 }
11767 } else {
11768 /* OPC_BEQC, OPC_BNEC */
11769 if (opc == OPC_BEQC) {
11770 /* OPC_BEQC */
11771 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
11772 } else {
11773 /* OPC_BNEC */
11774 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
11775 }
11776 }
11777 break;
11778 case OPC_BEQZC:
11779 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
11780 break;
11781 case OPC_BNEZC:
11782 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
11783 break;
11784 default:
11785 MIPS_INVAL("Compact conditional branch/jump");
9c708c7f 11786 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
11787 goto out;
11788 }
11789
11790 /* Generating branch here as compact branches don't have delay slot */
11791 gen_goto_tb(ctx, 1, ctx->btarget);
11792 gen_set_label(fs);
11793
11794 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
6893f074
YK
11795 }
11796
11797out:
11798 tcg_temp_free(t0);
11799 tcg_temp_free(t1);
11800}
11801
7a387fff 11802/* ISA extensions (ASEs) */
6af0bf9c 11803/* MIPS16 extension to MIPS32 */
6ea219d0
NF
11804
11805/* MIPS16 major opcodes */
11806enum {
11807 M16_OPC_ADDIUSP = 0x00,
11808 M16_OPC_ADDIUPC = 0x01,
11809 M16_OPC_B = 0x02,
11810 M16_OPC_JAL = 0x03,
11811 M16_OPC_BEQZ = 0x04,
11812 M16_OPC_BNEQZ = 0x05,
11813 M16_OPC_SHIFT = 0x06,
11814 M16_OPC_LD = 0x07,
11815 M16_OPC_RRIA = 0x08,
11816 M16_OPC_ADDIU8 = 0x09,
11817 M16_OPC_SLTI = 0x0a,
11818 M16_OPC_SLTIU = 0x0b,
11819 M16_OPC_I8 = 0x0c,
11820 M16_OPC_LI = 0x0d,
11821 M16_OPC_CMPI = 0x0e,
11822 M16_OPC_SD = 0x0f,
11823 M16_OPC_LB = 0x10,
11824 M16_OPC_LH = 0x11,
11825 M16_OPC_LWSP = 0x12,
11826 M16_OPC_LW = 0x13,
11827 M16_OPC_LBU = 0x14,
11828 M16_OPC_LHU = 0x15,
11829 M16_OPC_LWPC = 0x16,
11830 M16_OPC_LWU = 0x17,
11831 M16_OPC_SB = 0x18,
11832 M16_OPC_SH = 0x19,
11833 M16_OPC_SWSP = 0x1a,
11834 M16_OPC_SW = 0x1b,
11835 M16_OPC_RRR = 0x1c,
11836 M16_OPC_RR = 0x1d,
11837 M16_OPC_EXTEND = 0x1e,
11838 M16_OPC_I64 = 0x1f
11839};
11840
11841/* I8 funct field */
11842enum {
11843 I8_BTEQZ = 0x0,
11844 I8_BTNEZ = 0x1,
11845 I8_SWRASP = 0x2,
11846 I8_ADJSP = 0x3,
11847 I8_SVRS = 0x4,
11848 I8_MOV32R = 0x5,
11849 I8_MOVR32 = 0x7
11850};
11851
11852/* RRR f field */
11853enum {
11854 RRR_DADDU = 0x0,
11855 RRR_ADDU = 0x1,
11856 RRR_DSUBU = 0x2,
11857 RRR_SUBU = 0x3
11858};
11859
11860/* RR funct field */
11861enum {
11862 RR_JR = 0x00,
11863 RR_SDBBP = 0x01,
11864 RR_SLT = 0x02,
11865 RR_SLTU = 0x03,
11866 RR_SLLV = 0x04,
11867 RR_BREAK = 0x05,
11868 RR_SRLV = 0x06,
11869 RR_SRAV = 0x07,
11870 RR_DSRL = 0x08,
11871 RR_CMP = 0x0a,
11872 RR_NEG = 0x0b,
11873 RR_AND = 0x0c,
11874 RR_OR = 0x0d,
11875 RR_XOR = 0x0e,
11876 RR_NOT = 0x0f,
11877 RR_MFHI = 0x10,
11878 RR_CNVT = 0x11,
11879 RR_MFLO = 0x12,
11880 RR_DSRA = 0x13,
11881 RR_DSLLV = 0x14,
11882 RR_DSRLV = 0x16,
11883 RR_DSRAV = 0x17,
11884 RR_MULT = 0x18,
11885 RR_MULTU = 0x19,
11886 RR_DIV = 0x1a,
11887 RR_DIVU = 0x1b,
11888 RR_DMULT = 0x1c,
11889 RR_DMULTU = 0x1d,
11890 RR_DDIV = 0x1e,
11891 RR_DDIVU = 0x1f
11892};
11893
11894/* I64 funct field */
11895enum {
11896 I64_LDSP = 0x0,
11897 I64_SDSP = 0x1,
11898 I64_SDRASP = 0x2,
11899 I64_DADJSP = 0x3,
11900 I64_LDPC = 0x4,
364d4831 11901 I64_DADDIU5 = 0x5,
6ea219d0
NF
11902 I64_DADDIUPC = 0x6,
11903 I64_DADDIUSP = 0x7
11904};
11905
11906/* RR ry field for CNVT */
11907enum {
11908 RR_RY_CNVT_ZEB = 0x0,
11909 RR_RY_CNVT_ZEH = 0x1,
11910 RR_RY_CNVT_ZEW = 0x2,
11911 RR_RY_CNVT_SEB = 0x4,
11912 RR_RY_CNVT_SEH = 0x5,
11913 RR_RY_CNVT_SEW = 0x6,
11914};
11915
364d4831
NF
11916static int xlat (int r)
11917{
11918 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11919
11920 return map[r];
11921}
11922
11923static void gen_mips16_save (DisasContext *ctx,
11924 int xsregs, int aregs,
11925 int do_ra, int do_s0, int do_s1,
11926 int framesize)
11927{
11928 TCGv t0 = tcg_temp_new();
11929 TCGv t1 = tcg_temp_new();
c48245f0 11930 TCGv t2 = tcg_temp_new();
364d4831
NF
11931 int args, astatic;
11932
11933 switch (aregs) {
11934 case 0:
11935 case 1:
11936 case 2:
11937 case 3:
11938 case 11:
11939 args = 0;
11940 break;
11941 case 4:
11942 case 5:
11943 case 6:
11944 case 7:
11945 args = 1;
11946 break;
11947 case 8:
11948 case 9:
11949 case 10:
11950 args = 2;
11951 break;
11952 case 12:
11953 case 13:
11954 args = 3;
11955 break;
11956 case 14:
11957 args = 4;
11958 break;
11959 default:
9c708c7f 11960 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
11961 return;
11962 }
11963
11964 switch (args) {
11965 case 4:
11966 gen_base_offset_addr(ctx, t0, 29, 12);
11967 gen_load_gpr(t1, 7);
5f68f5ae 11968 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
11969 /* Fall through */
11970 case 3:
11971 gen_base_offset_addr(ctx, t0, 29, 8);
11972 gen_load_gpr(t1, 6);
5f68f5ae 11973 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
11974 /* Fall through */
11975 case 2:
11976 gen_base_offset_addr(ctx, t0, 29, 4);
11977 gen_load_gpr(t1, 5);
5f68f5ae 11978 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
11979 /* Fall through */
11980 case 1:
11981 gen_base_offset_addr(ctx, t0, 29, 0);
11982 gen_load_gpr(t1, 4);
5f68f5ae 11983 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
11984 }
11985
11986 gen_load_gpr(t0, 29);
11987
5f68f5ae 11988#define DECR_AND_STORE(reg) do { \
c48245f0
MR
11989 tcg_gen_movi_tl(t2, -4); \
11990 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
11991 gen_load_gpr(t1, reg); \
11992 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
364d4831
NF
11993 } while (0)
11994
11995 if (do_ra) {
11996 DECR_AND_STORE(31);
11997 }
11998
11999 switch (xsregs) {
12000 case 7:
12001 DECR_AND_STORE(30);
12002 /* Fall through */
12003 case 6:
12004 DECR_AND_STORE(23);
12005 /* Fall through */
12006 case 5:
12007 DECR_AND_STORE(22);
12008 /* Fall through */
12009 case 4:
12010 DECR_AND_STORE(21);
12011 /* Fall through */
12012 case 3:
12013 DECR_AND_STORE(20);
12014 /* Fall through */
12015 case 2:
12016 DECR_AND_STORE(19);
12017 /* Fall through */
12018 case 1:
12019 DECR_AND_STORE(18);
12020 }
12021
12022 if (do_s1) {
12023 DECR_AND_STORE(17);
12024 }
12025 if (do_s0) {
12026 DECR_AND_STORE(16);
12027 }
12028
12029 switch (aregs) {
12030 case 0:
12031 case 4:
12032 case 8:
12033 case 12:
12034 case 14:
12035 astatic = 0;
12036 break;
12037 case 1:
12038 case 5:
12039 case 9:
12040 case 13:
12041 astatic = 1;
12042 break;
12043 case 2:
12044 case 6:
12045 case 10:
12046 astatic = 2;
12047 break;
12048 case 3:
12049 case 7:
12050 astatic = 3;
12051 break;
12052 case 11:
12053 astatic = 4;
12054 break;
12055 default:
9c708c7f 12056 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12057 return;
12058 }
12059
12060 if (astatic > 0) {
12061 DECR_AND_STORE(7);
12062 if (astatic > 1) {
12063 DECR_AND_STORE(6);
12064 if (astatic > 2) {
12065 DECR_AND_STORE(5);
12066 if (astatic > 3) {
12067 DECR_AND_STORE(4);
12068 }
12069 }
12070 }
12071 }
12072#undef DECR_AND_STORE
12073
c48245f0
MR
12074 tcg_gen_movi_tl(t2, -framesize);
12075 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
12076 tcg_temp_free(t0);
12077 tcg_temp_free(t1);
c48245f0 12078 tcg_temp_free(t2);
364d4831
NF
12079}
12080
12081static void gen_mips16_restore (DisasContext *ctx,
12082 int xsregs, int aregs,
12083 int do_ra, int do_s0, int do_s1,
12084 int framesize)
12085{
12086 int astatic;
12087 TCGv t0 = tcg_temp_new();
12088 TCGv t1 = tcg_temp_new();
c48245f0 12089 TCGv t2 = tcg_temp_new();
364d4831 12090
c48245f0
MR
12091 tcg_gen_movi_tl(t2, framesize);
12092 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
364d4831 12093
5f68f5ae 12094#define DECR_AND_LOAD(reg) do { \
c48245f0
MR
12095 tcg_gen_movi_tl(t2, -4); \
12096 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
12097 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
12098 gen_store_gpr(t1, reg); \
364d4831
NF
12099 } while (0)
12100
12101 if (do_ra) {
12102 DECR_AND_LOAD(31);
12103 }
12104
12105 switch (xsregs) {
12106 case 7:
12107 DECR_AND_LOAD(30);
12108 /* Fall through */
12109 case 6:
12110 DECR_AND_LOAD(23);
12111 /* Fall through */
12112 case 5:
12113 DECR_AND_LOAD(22);
12114 /* Fall through */
12115 case 4:
12116 DECR_AND_LOAD(21);
12117 /* Fall through */
12118 case 3:
12119 DECR_AND_LOAD(20);
12120 /* Fall through */
12121 case 2:
12122 DECR_AND_LOAD(19);
12123 /* Fall through */
12124 case 1:
12125 DECR_AND_LOAD(18);
12126 }
12127
12128 if (do_s1) {
12129 DECR_AND_LOAD(17);
12130 }
12131 if (do_s0) {
12132 DECR_AND_LOAD(16);
12133 }
12134
12135 switch (aregs) {
12136 case 0:
12137 case 4:
12138 case 8:
12139 case 12:
12140 case 14:
12141 astatic = 0;
12142 break;
12143 case 1:
12144 case 5:
12145 case 9:
12146 case 13:
12147 astatic = 1;
12148 break;
12149 case 2:
12150 case 6:
12151 case 10:
12152 astatic = 2;
12153 break;
12154 case 3:
12155 case 7:
12156 astatic = 3;
12157 break;
12158 case 11:
12159 astatic = 4;
12160 break;
12161 default:
9c708c7f 12162 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12163 return;
12164 }
12165
12166 if (astatic > 0) {
12167 DECR_AND_LOAD(7);
12168 if (astatic > 1) {
12169 DECR_AND_LOAD(6);
12170 if (astatic > 2) {
12171 DECR_AND_LOAD(5);
12172 if (astatic > 3) {
12173 DECR_AND_LOAD(4);
12174 }
12175 }
12176 }
12177 }
12178#undef DECR_AND_LOAD
12179
c48245f0
MR
12180 tcg_gen_movi_tl(t2, framesize);
12181 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
12182 tcg_temp_free(t0);
12183 tcg_temp_free(t1);
c48245f0 12184 tcg_temp_free(t2);
364d4831
NF
12185}
12186
12187static void gen_addiupc (DisasContext *ctx, int rx, int imm,
12188 int is_64_bit, int extended)
12189{
12190 TCGv t0;
12191
12192 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 12193 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12194 return;
12195 }
12196
12197 t0 = tcg_temp_new();
12198
12199 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
12200 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
12201 if (!is_64_bit) {
12202 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12203 }
12204
12205 tcg_temp_free(t0);
12206}
12207
0d74a222
LA
12208static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
12209 int16_t offset)
12210{
12211 TCGv_i32 t0 = tcg_const_i32(op);
12212 TCGv t1 = tcg_temp_new();
12213 gen_base_offset_addr(ctx, t1, base, offset);
12214 gen_helper_cache(cpu_env, t1, t0);
12215}
12216
364d4831 12217#if defined(TARGET_MIPS64)
d75c135e 12218static void decode_i64_mips16 (DisasContext *ctx,
364d4831
NF
12219 int ry, int funct, int16_t offset,
12220 int extended)
12221{
12222 switch (funct) {
12223 case I64_LDSP:
d9224450 12224 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12225 check_mips_64(ctx);
12226 offset = extended ? offset : offset << 3;
d75c135e 12227 gen_ld(ctx, OPC_LD, ry, 29, offset);
364d4831
NF
12228 break;
12229 case I64_SDSP:
d9224450 12230 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12231 check_mips_64(ctx);
12232 offset = extended ? offset : offset << 3;
5c13fdfd 12233 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
12234 break;
12235 case I64_SDRASP:
d9224450 12236 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12237 check_mips_64(ctx);
12238 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 12239 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
12240 break;
12241 case I64_DADJSP:
d9224450 12242 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12243 check_mips_64(ctx);
12244 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
d75c135e 12245 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
364d4831
NF
12246 break;
12247 case I64_LDPC:
d9224450
MR
12248 check_insn(ctx, ISA_MIPS3);
12249 check_mips_64(ctx);
364d4831 12250 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 12251 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12252 } else {
12253 offset = extended ? offset : offset << 3;
d75c135e 12254 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
12255 }
12256 break;
12257 case I64_DADDIU5:
d9224450 12258 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12259 check_mips_64(ctx);
12260 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
d75c135e 12261 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
364d4831
NF
12262 break;
12263 case I64_DADDIUPC:
d9224450 12264 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12265 check_mips_64(ctx);
12266 offset = extended ? offset : offset << 2;
12267 gen_addiupc(ctx, ry, offset, 1, extended);
12268 break;
12269 case I64_DADDIUSP:
d9224450 12270 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12271 check_mips_64(ctx);
12272 offset = extended ? offset : offset << 2;
d75c135e 12273 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
364d4831
NF
12274 break;
12275 }
12276}
12277#endif
12278
240ce26a 12279static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
364d4831 12280{
eeb3bba8 12281 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
12282 int op, rx, ry, funct, sa;
12283 int16_t imm, offset;
12284
12285 ctx->opcode = (ctx->opcode << 16) | extend;
12286 op = (ctx->opcode >> 11) & 0x1f;
12287 sa = (ctx->opcode >> 22) & 0x1f;
12288 funct = (ctx->opcode >> 8) & 0x7;
12289 rx = xlat((ctx->opcode >> 8) & 0x7);
12290 ry = xlat((ctx->opcode >> 5) & 0x7);
12291 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
12292 | ((ctx->opcode >> 21) & 0x3f) << 5
12293 | (ctx->opcode & 0x1f));
12294
12295 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
12296 counterparts. */
12297 switch (op) {
12298 case M16_OPC_ADDIUSP:
d75c135e 12299 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
12300 break;
12301 case M16_OPC_ADDIUPC:
12302 gen_addiupc(ctx, rx, imm, 0, 1);
12303 break;
12304 case M16_OPC_B:
b231c103 12305 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
364d4831
NF
12306 /* No delay slot, so just process as a normal instruction */
12307 break;
12308 case M16_OPC_BEQZ:
b231c103 12309 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
364d4831
NF
12310 /* No delay slot, so just process as a normal instruction */
12311 break;
12312 case M16_OPC_BNEQZ:
b231c103 12313 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
364d4831
NF
12314 /* No delay slot, so just process as a normal instruction */
12315 break;
12316 case M16_OPC_SHIFT:
12317 switch (ctx->opcode & 0x3) {
12318 case 0x0:
d75c135e 12319 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
12320 break;
12321 case 0x1:
12322#if defined(TARGET_MIPS64)
12323 check_mips_64(ctx);
d75c135e 12324 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 12325#else
9c708c7f 12326 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12327#endif
12328 break;
12329 case 0x2:
d75c135e 12330 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
12331 break;
12332 case 0x3:
d75c135e 12333 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
12334 break;
12335 }
12336 break;
12337#if defined(TARGET_MIPS64)
12338 case M16_OPC_LD:
d9224450 12339 check_insn(ctx, ISA_MIPS3);
d75de749 12340 check_mips_64(ctx);
d75c135e 12341 gen_ld(ctx, OPC_LD, ry, rx, offset);
364d4831
NF
12342 break;
12343#endif
12344 case M16_OPC_RRIA:
12345 imm = ctx->opcode & 0xf;
12346 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
12347 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
12348 imm = (int16_t) (imm << 1) >> 1;
12349 if ((ctx->opcode >> 4) & 0x1) {
12350#if defined(TARGET_MIPS64)
12351 check_mips_64(ctx);
d75c135e 12352 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 12353#else
9c708c7f 12354 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12355#endif
12356 } else {
d75c135e 12357 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
12358 }
12359 break;
12360 case M16_OPC_ADDIU8:
d75c135e 12361 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
12362 break;
12363 case M16_OPC_SLTI:
d75c135e 12364 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
12365 break;
12366 case M16_OPC_SLTIU:
d75c135e 12367 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
12368 break;
12369 case M16_OPC_I8:
12370 switch (funct) {
12371 case I8_BTEQZ:
b231c103 12372 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
364d4831
NF
12373 break;
12374 case I8_BTNEZ:
b231c103 12375 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
364d4831
NF
12376 break;
12377 case I8_SWRASP:
5c13fdfd 12378 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
12379 break;
12380 case I8_ADJSP:
d75c135e 12381 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
364d4831
NF
12382 break;
12383 case I8_SVRS:
d9224450 12384 check_insn(ctx, ISA_MIPS32);
364d4831
NF
12385 {
12386 int xsregs = (ctx->opcode >> 24) & 0x7;
12387 int aregs = (ctx->opcode >> 16) & 0xf;
12388 int do_ra = (ctx->opcode >> 6) & 0x1;
12389 int do_s0 = (ctx->opcode >> 5) & 0x1;
12390 int do_s1 = (ctx->opcode >> 4) & 0x1;
12391 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
12392 | (ctx->opcode & 0xf)) << 3;
12393
12394 if (ctx->opcode & (1 << 7)) {
12395 gen_mips16_save(ctx, xsregs, aregs,
12396 do_ra, do_s0, do_s1,
12397 framesize);
12398 } else {
12399 gen_mips16_restore(ctx, xsregs, aregs,
12400 do_ra, do_s0, do_s1,
12401 framesize);
12402 }
12403 }
12404 break;
12405 default:
9c708c7f 12406 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12407 break;
12408 }
12409 break;
12410 case M16_OPC_LI:
12411 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
12412 break;
12413 case M16_OPC_CMPI:
12414 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
12415 break;
12416#if defined(TARGET_MIPS64)
12417 case M16_OPC_SD:
d9224450
MR
12418 check_insn(ctx, ISA_MIPS3);
12419 check_mips_64(ctx);
5c13fdfd 12420 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
12421 break;
12422#endif
12423 case M16_OPC_LB:
d75c135e 12424 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
12425 break;
12426 case M16_OPC_LH:
d75c135e 12427 gen_ld(ctx, OPC_LH, ry, rx, offset);
364d4831
NF
12428 break;
12429 case M16_OPC_LWSP:
d75c135e 12430 gen_ld(ctx, OPC_LW, rx, 29, offset);
364d4831
NF
12431 break;
12432 case M16_OPC_LW:
d75c135e 12433 gen_ld(ctx, OPC_LW, ry, rx, offset);
364d4831
NF
12434 break;
12435 case M16_OPC_LBU:
d75c135e 12436 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
12437 break;
12438 case M16_OPC_LHU:
d75c135e 12439 gen_ld(ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
12440 break;
12441 case M16_OPC_LWPC:
d75c135e 12442 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
12443 break;
12444#if defined(TARGET_MIPS64)
12445 case M16_OPC_LWU:
d9224450
MR
12446 check_insn(ctx, ISA_MIPS3);
12447 check_mips_64(ctx);
d75c135e 12448 gen_ld(ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
12449 break;
12450#endif
12451 case M16_OPC_SB:
5c13fdfd 12452 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
12453 break;
12454 case M16_OPC_SH:
5c13fdfd 12455 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
12456 break;
12457 case M16_OPC_SWSP:
5c13fdfd 12458 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
12459 break;
12460 case M16_OPC_SW:
5c13fdfd 12461 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
12462 break;
12463#if defined(TARGET_MIPS64)
12464 case M16_OPC_I64:
d75c135e 12465 decode_i64_mips16(ctx, ry, funct, offset, 1);
364d4831
NF
12466 break;
12467#endif
12468 default:
9c708c7f 12469 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12470 break;
12471 }
12472
12473 return 4;
12474}
12475
3b3c1694
LA
12476static inline bool is_uhi(int sdbbp_code)
12477{
12478#ifdef CONFIG_USER_ONLY
12479 return false;
12480#else
12481 return semihosting_enabled() && sdbbp_code == 1;
12482#endif
12483}
12484
240ce26a 12485static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
364d4831
NF
12486{
12487 int rx, ry;
12488 int sa;
12489 int op, cnvt_op, op1, offset;
12490 int funct;
12491 int n_bytes;
12492
12493 op = (ctx->opcode >> 11) & 0x1f;
12494 sa = (ctx->opcode >> 2) & 0x7;
12495 sa = sa == 0 ? 8 : sa;
12496 rx = xlat((ctx->opcode >> 8) & 0x7);
12497 cnvt_op = (ctx->opcode >> 5) & 0x7;
12498 ry = xlat((ctx->opcode >> 5) & 0x7);
12499 op1 = offset = ctx->opcode & 0x1f;
12500
12501 n_bytes = 2;
12502
12503 switch (op) {
12504 case M16_OPC_ADDIUSP:
12505 {
12506 int16_t imm = ((uint8_t) ctx->opcode) << 2;
12507
d75c135e 12508 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
12509 }
12510 break;
12511 case M16_OPC_ADDIUPC:
12512 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
12513 break;
12514 case M16_OPC_B:
12515 offset = (ctx->opcode & 0x7ff) << 1;
12516 offset = (int16_t)(offset << 4) >> 4;
b231c103 12517 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
364d4831
NF
12518 /* No delay slot, so just process as a normal instruction */
12519 break;
12520 case M16_OPC_JAL:
eeb3bba8 12521 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
12522 offset = (((ctx->opcode & 0x1f) << 21)
12523 | ((ctx->opcode >> 5) & 0x1f) << 16
12524 | offset) << 2;
b231c103
YK
12525 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
12526 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
364d4831 12527 n_bytes = 4;
364d4831
NF
12528 break;
12529 case M16_OPC_BEQZ:
b231c103
YK
12530 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
12531 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
12532 /* No delay slot, so just process as a normal instruction */
12533 break;
12534 case M16_OPC_BNEQZ:
b231c103
YK
12535 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
12536 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
12537 /* No delay slot, so just process as a normal instruction */
12538 break;
12539 case M16_OPC_SHIFT:
12540 switch (ctx->opcode & 0x3) {
12541 case 0x0:
d75c135e 12542 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
12543 break;
12544 case 0x1:
12545#if defined(TARGET_MIPS64)
d9224450 12546 check_insn(ctx, ISA_MIPS3);
364d4831 12547 check_mips_64(ctx);
d75c135e 12548 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 12549#else
9c708c7f 12550 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12551#endif
12552 break;
12553 case 0x2:
d75c135e 12554 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
12555 break;
12556 case 0x3:
d75c135e 12557 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
12558 break;
12559 }
12560 break;
12561#if defined(TARGET_MIPS64)
12562 case M16_OPC_LD:
d9224450 12563 check_insn(ctx, ISA_MIPS3);
364d4831 12564 check_mips_64(ctx);
d75c135e 12565 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
12566 break;
12567#endif
12568 case M16_OPC_RRIA:
12569 {
12570 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
12571
12572 if ((ctx->opcode >> 4) & 1) {
12573#if defined(TARGET_MIPS64)
d9224450 12574 check_insn(ctx, ISA_MIPS3);
364d4831 12575 check_mips_64(ctx);
d75c135e 12576 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 12577#else
9c708c7f 12578 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12579#endif
12580 } else {
d75c135e 12581 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
12582 }
12583 }
12584 break;
12585 case M16_OPC_ADDIU8:
12586 {
12587 int16_t imm = (int8_t) ctx->opcode;
12588
d75c135e 12589 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
12590 }
12591 break;
12592 case M16_OPC_SLTI:
12593 {
12594 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 12595 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
12596 }
12597 break;
12598 case M16_OPC_SLTIU:
12599 {
12600 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 12601 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
12602 }
12603 break;
12604 case M16_OPC_I8:
12605 {
12606 int reg32;
12607
12608 funct = (ctx->opcode >> 8) & 0x7;
12609 switch (funct) {
12610 case I8_BTEQZ:
12611 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
b231c103 12612 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
12613 break;
12614 case I8_BTNEZ:
12615 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
b231c103 12616 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
12617 break;
12618 case I8_SWRASP:
5c13fdfd 12619 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
12620 break;
12621 case I8_ADJSP:
d75c135e 12622 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
364d4831
NF
12623 ((int8_t)ctx->opcode) << 3);
12624 break;
12625 case I8_SVRS:
d9224450 12626 check_insn(ctx, ISA_MIPS32);
364d4831
NF
12627 {
12628 int do_ra = ctx->opcode & (1 << 6);
12629 int do_s0 = ctx->opcode & (1 << 5);
12630 int do_s1 = ctx->opcode & (1 << 4);
12631 int framesize = ctx->opcode & 0xf;
12632
12633 if (framesize == 0) {
12634 framesize = 128;
12635 } else {
12636 framesize = framesize << 3;
12637 }
12638
12639 if (ctx->opcode & (1 << 7)) {
12640 gen_mips16_save(ctx, 0, 0,
12641 do_ra, do_s0, do_s1, framesize);
12642 } else {
12643 gen_mips16_restore(ctx, 0, 0,
12644 do_ra, do_s0, do_s1, framesize);
12645 }
12646 }
12647 break;
12648 case I8_MOV32R:
12649 {
12650 int rz = xlat(ctx->opcode & 0x7);
12651
12652 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
12653 ((ctx->opcode >> 5) & 0x7);
d75c135e 12654 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
364d4831
NF
12655 }
12656 break;
12657 case I8_MOVR32:
12658 reg32 = ctx->opcode & 0x1f;
d75c135e 12659 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
364d4831
NF
12660 break;
12661 default:
9c708c7f 12662 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12663 break;
12664 }
12665 }
12666 break;
12667 case M16_OPC_LI:
12668 {
12669 int16_t imm = (uint8_t) ctx->opcode;
12670
d75c135e 12671 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
364d4831
NF
12672 }
12673 break;
12674 case M16_OPC_CMPI:
12675 {
12676 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 12677 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
12678 }
12679 break;
12680#if defined(TARGET_MIPS64)
12681 case M16_OPC_SD:
d9224450 12682 check_insn(ctx, ISA_MIPS3);
364d4831 12683 check_mips_64(ctx);
5c13fdfd 12684 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
12685 break;
12686#endif
12687 case M16_OPC_LB:
d75c135e 12688 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
12689 break;
12690 case M16_OPC_LH:
d75c135e 12691 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
12692 break;
12693 case M16_OPC_LWSP:
d75c135e 12694 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
12695 break;
12696 case M16_OPC_LW:
d75c135e 12697 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
12698 break;
12699 case M16_OPC_LBU:
d75c135e 12700 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
12701 break;
12702 case M16_OPC_LHU:
d75c135e 12703 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
12704 break;
12705 case M16_OPC_LWPC:
d75c135e 12706 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
12707 break;
12708#if defined (TARGET_MIPS64)
12709 case M16_OPC_LWU:
d9224450 12710 check_insn(ctx, ISA_MIPS3);
364d4831 12711 check_mips_64(ctx);
d75c135e 12712 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
12713 break;
12714#endif
12715 case M16_OPC_SB:
5c13fdfd 12716 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
12717 break;
12718 case M16_OPC_SH:
5c13fdfd 12719 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
12720 break;
12721 case M16_OPC_SWSP:
5c13fdfd 12722 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
12723 break;
12724 case M16_OPC_SW:
5c13fdfd 12725 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
12726 break;
12727 case M16_OPC_RRR:
12728 {
12729 int rz = xlat((ctx->opcode >> 2) & 0x7);
12730 int mips32_op;
12731
12732 switch (ctx->opcode & 0x3) {
12733 case RRR_ADDU:
12734 mips32_op = OPC_ADDU;
12735 break;
12736 case RRR_SUBU:
12737 mips32_op = OPC_SUBU;
12738 break;
12739#if defined(TARGET_MIPS64)
12740 case RRR_DADDU:
12741 mips32_op = OPC_DADDU;
d9224450 12742 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12743 check_mips_64(ctx);
12744 break;
12745 case RRR_DSUBU:
12746 mips32_op = OPC_DSUBU;
d9224450 12747 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12748 check_mips_64(ctx);
12749 break;
12750#endif
12751 default:
9c708c7f 12752 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12753 goto done;
12754 }
12755
d75c135e 12756 gen_arith(ctx, mips32_op, rz, rx, ry);
364d4831
NF
12757 done:
12758 ;
12759 }
12760 break;
12761 case M16_OPC_RR:
12762 switch (op1) {
12763 case RR_JR:
12764 {
12765 int nd = (ctx->opcode >> 7) & 0x1;
12766 int link = (ctx->opcode >> 6) & 0x1;
12767 int ra = (ctx->opcode >> 5) & 0x1;
12768
d9224450
MR
12769 if (nd) {
12770 check_insn(ctx, ISA_MIPS32);
12771 }
12772
364d4831 12773 if (link) {
b231c103 12774 op = OPC_JALR;
364d4831
NF
12775 } else {
12776 op = OPC_JR;
12777 }
12778
b231c103
YK
12779 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
12780 (nd ? 0 : 2));
364d4831
NF
12781 }
12782 break;
12783 case RR_SDBBP:
3b3c1694
LA
12784 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
12785 gen_helper_do_semihosting(cpu_env);
12786 } else {
12787 /* XXX: not clear which exception should be raised
12788 * when in debug mode...
12789 */
12790 check_insn(ctx, ISA_MIPS32);
9c708c7f 12791 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 12792 }
364d4831
NF
12793 break;
12794 case RR_SLT:
d75c135e 12795 gen_slt(ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
12796 break;
12797 case RR_SLTU:
d75c135e 12798 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
12799 break;
12800 case RR_BREAK:
9c708c7f 12801 generate_exception_end(ctx, EXCP_BREAK);
364d4831
NF
12802 break;
12803 case RR_SLLV:
d75c135e 12804 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
364d4831
NF
12805 break;
12806 case RR_SRLV:
d75c135e 12807 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
364d4831
NF
12808 break;
12809 case RR_SRAV:
d75c135e 12810 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
364d4831
NF
12811 break;
12812#if defined (TARGET_MIPS64)
12813 case RR_DSRL:
d9224450 12814 check_insn(ctx, ISA_MIPS3);
364d4831 12815 check_mips_64(ctx);
d75c135e 12816 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
364d4831
NF
12817 break;
12818#endif
12819 case RR_CMP:
d75c135e 12820 gen_logic(ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
12821 break;
12822 case RR_NEG:
d75c135e 12823 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
364d4831
NF
12824 break;
12825 case RR_AND:
d75c135e 12826 gen_logic(ctx, OPC_AND, rx, rx, ry);
364d4831
NF
12827 break;
12828 case RR_OR:
d75c135e 12829 gen_logic(ctx, OPC_OR, rx, rx, ry);
364d4831
NF
12830 break;
12831 case RR_XOR:
d75c135e 12832 gen_logic(ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
12833 break;
12834 case RR_NOT:
d75c135e 12835 gen_logic(ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
12836 break;
12837 case RR_MFHI:
26135ead 12838 gen_HILO(ctx, OPC_MFHI, 0, rx);
364d4831
NF
12839 break;
12840 case RR_CNVT:
d9224450 12841 check_insn(ctx, ISA_MIPS32);
364d4831
NF
12842 switch (cnvt_op) {
12843 case RR_RY_CNVT_ZEB:
12844 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12845 break;
12846 case RR_RY_CNVT_ZEH:
12847 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12848 break;
12849 case RR_RY_CNVT_SEB:
12850 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12851 break;
12852 case RR_RY_CNVT_SEH:
12853 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12854 break;
12855#if defined (TARGET_MIPS64)
12856 case RR_RY_CNVT_ZEW:
d9224450 12857 check_insn(ctx, ISA_MIPS64);
364d4831
NF
12858 check_mips_64(ctx);
12859 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12860 break;
12861 case RR_RY_CNVT_SEW:
d9224450 12862 check_insn(ctx, ISA_MIPS64);
364d4831
NF
12863 check_mips_64(ctx);
12864 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12865 break;
12866#endif
12867 default:
9c708c7f 12868 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12869 break;
12870 }
12871 break;
12872 case RR_MFLO:
26135ead 12873 gen_HILO(ctx, OPC_MFLO, 0, rx);
364d4831
NF
12874 break;
12875#if defined (TARGET_MIPS64)
12876 case RR_DSRA:
d9224450 12877 check_insn(ctx, ISA_MIPS3);
364d4831 12878 check_mips_64(ctx);
d75c135e 12879 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
364d4831
NF
12880 break;
12881 case RR_DSLLV:
d9224450 12882 check_insn(ctx, ISA_MIPS3);
364d4831 12883 check_mips_64(ctx);
d75c135e 12884 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
364d4831
NF
12885 break;
12886 case RR_DSRLV:
d9224450 12887 check_insn(ctx, ISA_MIPS3);
364d4831 12888 check_mips_64(ctx);
d75c135e 12889 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
364d4831
NF
12890 break;
12891 case RR_DSRAV:
d9224450 12892 check_insn(ctx, ISA_MIPS3);
364d4831 12893 check_mips_64(ctx);
d75c135e 12894 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
364d4831
NF
12895 break;
12896#endif
12897 case RR_MULT:
26135ead 12898 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
364d4831
NF
12899 break;
12900 case RR_MULTU:
26135ead 12901 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
364d4831
NF
12902 break;
12903 case RR_DIV:
26135ead 12904 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
364d4831
NF
12905 break;
12906 case RR_DIVU:
26135ead 12907 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
364d4831
NF
12908 break;
12909#if defined (TARGET_MIPS64)
12910 case RR_DMULT:
d9224450 12911 check_insn(ctx, ISA_MIPS3);
364d4831 12912 check_mips_64(ctx);
26135ead 12913 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
364d4831
NF
12914 break;
12915 case RR_DMULTU:
d9224450 12916 check_insn(ctx, ISA_MIPS3);
364d4831 12917 check_mips_64(ctx);
26135ead 12918 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
364d4831
NF
12919 break;
12920 case RR_DDIV:
d9224450 12921 check_insn(ctx, ISA_MIPS3);
364d4831 12922 check_mips_64(ctx);
26135ead 12923 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
364d4831
NF
12924 break;
12925 case RR_DDIVU:
d9224450 12926 check_insn(ctx, ISA_MIPS3);
364d4831 12927 check_mips_64(ctx);
26135ead 12928 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
364d4831
NF
12929 break;
12930#endif
12931 default:
9c708c7f 12932 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12933 break;
12934 }
12935 break;
12936 case M16_OPC_EXTEND:
240ce26a 12937 decode_extended_mips16_opc(env, ctx);
364d4831
NF
12938 n_bytes = 4;
12939 break;
12940#if defined(TARGET_MIPS64)
12941 case M16_OPC_I64:
12942 funct = (ctx->opcode >> 8) & 0x7;
d75c135e 12943 decode_i64_mips16(ctx, ry, funct, offset, 0);
364d4831
NF
12944 break;
12945#endif
12946 default:
9c708c7f 12947 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12948 break;
12949 }
12950
12951 return n_bytes;
12952}
12953
211da992 12954/* microMIPS extension to MIPS32/MIPS64 */
6af0bf9c 12955
211da992
CWR
12956/*
12957 * microMIPS32/microMIPS64 major opcodes
12958 *
12959 * 1. MIPS Architecture for Programmers Volume II-B:
12960 * The microMIPS32 Instruction Set (Revision 3.05)
12961 *
12962 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
12963 *
12964 * 2. MIPS Architecture For Programmers Volume II-A:
12965 * The MIPS64 Instruction Set (Revision 3.51)
12966 */
6af0bf9c 12967
3c824109
NF
12968enum {
12969 POOL32A = 0x00,
12970 POOL16A = 0x01,
12971 LBU16 = 0x02,
12972 MOVE16 = 0x03,
12973 ADDI32 = 0x04,
3a1f4268
YK
12974 R6_LUI = 0x04,
12975 AUI = 0x04,
3c824109
NF
12976 LBU32 = 0x05,
12977 SB32 = 0x06,
12978 LB32 = 0x07,
12979
12980 POOL32B = 0x08,
12981 POOL16B = 0x09,
12982 LHU16 = 0x0a,
12983 ANDI16 = 0x0b,
12984 ADDIU32 = 0x0c,
12985 LHU32 = 0x0d,
12986 SH32 = 0x0e,
12987 LH32 = 0x0f,
12988
12989 POOL32I = 0x10,
12990 POOL16C = 0x11,
12991 LWSP16 = 0x12,
12992 POOL16D = 0x13,
12993 ORI32 = 0x14,
12994 POOL32F = 0x15,
211da992
CWR
12995 POOL32S = 0x16, /* MIPS64 */
12996 DADDIU32 = 0x17, /* MIPS64 */
3c824109
NF
12997
12998 POOL32C = 0x18,
12999 LWGP16 = 0x19,
13000 LW16 = 0x1a,
13001 POOL16E = 0x1b,
13002 XORI32 = 0x1c,
13003 JALS32 = 0x1d,
3a1f4268
YK
13004 BOVC = 0x1d,
13005 BEQC = 0x1d,
13006 BEQZALC = 0x1d,
3c824109 13007 ADDIUPC = 0x1e,
3a1f4268
YK
13008 PCREL = 0x1e,
13009 BNVC = 0x1f,
13010 BNEC = 0x1f,
13011 BNEZALC = 0x1f,
3c824109 13012
3a1f4268
YK
13013 R6_BEQZC = 0x20,
13014 JIC = 0x20,
3c824109
NF
13015 POOL16F = 0x21,
13016 SB16 = 0x22,
13017 BEQZ16 = 0x23,
3a1f4268 13018 BEQZC16 = 0x23,
3c824109
NF
13019 SLTI32 = 0x24,
13020 BEQ32 = 0x25,
3a1f4268 13021 BC = 0x25,
3c824109
NF
13022 SWC132 = 0x26,
13023 LWC132 = 0x27,
13024
3a1f4268 13025 /* 0x29 is reserved */
3c824109 13026 RES_29 = 0x29,
3a1f4268
YK
13027 R6_BNEZC = 0x28,
13028 JIALC = 0x28,
3c824109
NF
13029 SH16 = 0x2a,
13030 BNEZ16 = 0x2b,
3a1f4268 13031 BNEZC16 = 0x2b,
3c824109
NF
13032 SLTIU32 = 0x2c,
13033 BNE32 = 0x2d,
3a1f4268 13034 BALC = 0x2d,
3c824109
NF
13035 SDC132 = 0x2e,
13036 LDC132 = 0x2f,
13037
3a1f4268 13038 /* 0x31 is reserved */
3c824109 13039 RES_31 = 0x31,
3a1f4268
YK
13040 BLEZALC = 0x30,
13041 BGEZALC = 0x30,
13042 BGEUC = 0x30,
3c824109
NF
13043 SWSP16 = 0x32,
13044 B16 = 0x33,
3a1f4268 13045 BC16 = 0x33,
3c824109
NF
13046 ANDI32 = 0x34,
13047 J32 = 0x35,
3a1f4268
YK
13048 BGTZC = 0x35,
13049 BLTZC = 0x35,
13050 BLTC = 0x35,
211da992
CWR
13051 SD32 = 0x36, /* MIPS64 */
13052 LD32 = 0x37, /* MIPS64 */
3c824109 13053
3a1f4268 13054 /* 0x39 is reserved */
3c824109 13055 RES_39 = 0x39,
3a1f4268
YK
13056 BGTZALC = 0x38,
13057 BLTZALC = 0x38,
13058 BLTUC = 0x38,
3c824109
NF
13059 SW16 = 0x3a,
13060 LI16 = 0x3b,
13061 JALX32 = 0x3c,
13062 JAL32 = 0x3d,
3a1f4268
YK
13063 BLEZC = 0x3d,
13064 BGEZC = 0x3d,
13065 BGEC = 0x3d,
3c824109
NF
13066 SW32 = 0x3e,
13067 LW32 = 0x3f
13068};
13069
3a1f4268
YK
13070/* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
13071enum {
13072 ADDIUPC_00 = 0x00,
c38a1d52
AR
13073 ADDIUPC_01 = 0x01,
13074 ADDIUPC_02 = 0x02,
13075 ADDIUPC_03 = 0x03,
13076 ADDIUPC_04 = 0x04,
13077 ADDIUPC_05 = 0x05,
13078 ADDIUPC_06 = 0x06,
3a1f4268
YK
13079 ADDIUPC_07 = 0x07,
13080 AUIPC = 0x1e,
13081 ALUIPC = 0x1f,
13082 LWPC_08 = 0x08,
c38a1d52
AR
13083 LWPC_09 = 0x09,
13084 LWPC_0A = 0x0A,
13085 LWPC_0B = 0x0B,
13086 LWPC_0C = 0x0C,
13087 LWPC_0D = 0x0D,
13088 LWPC_0E = 0x0E,
3a1f4268
YK
13089 LWPC_0F = 0x0F,
13090};
13091
3c824109
NF
13092/* POOL32A encoding of minor opcode field */
13093
13094enum {
13095 /* These opcodes are distinguished only by bits 9..6; those bits are
13096 * what are recorded below. */
13097 SLL32 = 0x0,
13098 SRL32 = 0x1,
13099 SRA = 0x2,
13100 ROTR = 0x3,
3a1f4268
YK
13101 SELEQZ = 0x5,
13102 SELNEZ = 0x6,
b00c7218 13103 R6_RDHWR = 0x7,
3c824109
NF
13104
13105 SLLV = 0x0,
13106 SRLV = 0x1,
13107 SRAV = 0x2,
13108 ROTRV = 0x3,
13109 ADD = 0x4,
13110 ADDU32 = 0x5,
13111 SUB = 0x6,
13112 SUBU32 = 0x7,
13113 MUL = 0x8,
13114 AND = 0x9,
13115 OR32 = 0xa,
13116 NOR = 0xb,
13117 XOR32 = 0xc,
13118 SLT = 0xd,
13119 SLTU = 0xe,
13120
13121 MOVN = 0x0,
3a1f4268 13122 R6_MUL = 0x0,
3c824109 13123 MOVZ = 0x1,
3a1f4268
YK
13124 MUH = 0x1,
13125 MULU = 0x2,
13126 MUHU = 0x3,
3c824109 13127 LWXS = 0x4,
3a1f4268
YK
13128 R6_DIV = 0x4,
13129 MOD = 0x5,
13130 R6_DIVU = 0x6,
13131 MODU = 0x7,
3c824109
NF
13132
13133 /* The following can be distinguished by their lower 6 bits. */
dbd8af98 13134 BREAK32 = 0x07,
3c824109 13135 INS = 0x0c,
3a1f4268
YK
13136 LSA = 0x0f,
13137 ALIGN = 0x1f,
3c824109 13138 EXT = 0x2c,
bb238210
YK
13139 POOL32AXF = 0x3c,
13140 SIGRIE = 0x3f
3c824109
NF
13141};
13142
13143/* POOL32AXF encoding of minor opcode field extension */
13144
d132c79f
CWR
13145/*
13146 * 1. MIPS Architecture for Programmers Volume II-B:
13147 * The microMIPS32 Instruction Set (Revision 3.05)
13148 *
13149 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
13150 *
13151 * 2. MIPS Architecture for Programmers VolumeIV-e:
13152 * The MIPS DSP Application-Specific Extension
13153 * to the microMIPS32 Architecture (Revision 2.34)
13154 *
13155 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
13156 */
13157
3c824109
NF
13158enum {
13159 /* bits 11..6 */
13160 TEQ = 0x00,
13161 TGE = 0x08,
13162 TGEU = 0x10,
13163 TLT = 0x20,
13164 TLTU = 0x28,
13165 TNE = 0x30,
13166
13167 MFC0 = 0x03,
13168 MTC0 = 0x0b,
13169
d132c79f
CWR
13170 /* begin of microMIPS32 DSP */
13171
3c824109
NF
13172 /* bits 13..12 for 0x01 */
13173 MFHI_ACC = 0x0,
13174 MFLO_ACC = 0x1,
13175 MTHI_ACC = 0x2,
13176 MTLO_ACC = 0x3,
13177
13178 /* bits 13..12 for 0x2a */
13179 MADD_ACC = 0x0,
13180 MADDU_ACC = 0x1,
13181 MSUB_ACC = 0x2,
13182 MSUBU_ACC = 0x3,
13183
13184 /* bits 13..12 for 0x32 */
13185 MULT_ACC = 0x0,
6801038b 13186 MULTU_ACC = 0x1,
3c824109 13187
d132c79f
CWR
13188 /* end of microMIPS32 DSP */
13189
3c824109 13190 /* bits 15..12 for 0x2c */
3a1f4268 13191 BITSWAP = 0x0,
3c824109
NF
13192 SEB = 0x2,
13193 SEH = 0x3,
13194 CLO = 0x4,
13195 CLZ = 0x5,
13196 RDHWR = 0x6,
13197 WSBH = 0x7,
13198 MULT = 0x8,
13199 MULTU = 0x9,
13200 DIV = 0xa,
13201 DIVU = 0xb,
13202 MADD = 0xc,
13203 MADDU = 0xd,
13204 MSUB = 0xe,
13205 MSUBU = 0xf,
13206
13207 /* bits 15..12 for 0x34 */
13208 MFC2 = 0x4,
13209 MTC2 = 0x5,
13210 MFHC2 = 0x8,
13211 MTHC2 = 0x9,
13212 CFC2 = 0xc,
13213 CTC2 = 0xd,
13214
13215 /* bits 15..12 for 0x3c */
13216 JALR = 0x0,
13217 JR = 0x0, /* alias */
3a1f4268
YK
13218 JALRC = 0x0,
13219 JRC = 0x0,
3c824109 13220 JALR_HB = 0x1,
3a1f4268 13221 JALRC_HB = 0x1,
3c824109
NF
13222 JALRS = 0x4,
13223 JALRS_HB = 0x5,
13224
13225 /* bits 15..12 for 0x05 */
13226 RDPGPR = 0xe,
13227 WRPGPR = 0xf,
13228
13229 /* bits 15..12 for 0x0d */
13230 TLBP = 0x0,
13231 TLBR = 0x1,
13232 TLBWI = 0x2,
13233 TLBWR = 0x3,
e60ec063
YK
13234 TLBINV = 0x4,
13235 TLBINVF = 0x5,
3c824109
NF
13236 WAIT = 0x9,
13237 IRET = 0xd,
13238 DERET = 0xe,
13239 ERET = 0xf,
13240
13241 /* bits 15..12 for 0x15 */
13242 DMT = 0x0,
13243 DVPE = 0x1,
13244 EMT = 0x2,
13245 EVPE = 0x3,
13246
13247 /* bits 15..12 for 0x1d */
13248 DI = 0x4,
13249 EI = 0x5,
13250
13251 /* bits 15..12 for 0x2d */
13252 SYNC = 0x6,
13253 SYSCALL = 0x8,
13254 SDBBP = 0xd,
13255
13256 /* bits 15..12 for 0x35 */
13257 MFHI32 = 0x0,
13258 MFLO32 = 0x1,
13259 MTHI32 = 0x2,
13260 MTLO32 = 0x3,
13261};
13262
13263/* POOL32B encoding of minor opcode field (bits 15..12) */
13264
13265enum {
13266 LWC2 = 0x0,
13267 LWP = 0x1,
13268 LDP = 0x4,
13269 LWM32 = 0x5,
13270 CACHE = 0x6,
13271 LDM = 0x7,
13272 SWC2 = 0x8,
13273 SWP = 0x9,
13274 SDP = 0xc,
13275 SWM32 = 0xd,
13276 SDM = 0xf
13277};
13278
13279/* POOL32C encoding of minor opcode field (bits 15..12) */
13280
13281enum {
13282 LWL = 0x0,
13283 SWL = 0x8,
13284 LWR = 0x1,
13285 SWR = 0x9,
13286 PREF = 0x2,
8fffc646 13287 ST_EVA = 0xa,
3c824109
NF
13288 LL = 0x3,
13289 SC = 0xb,
13290 LDL = 0x4,
13291 SDL = 0xc,
13292 LDR = 0x5,
13293 SDR = 0xd,
8fffc646 13294 LD_EVA = 0x6,
3c824109
NF
13295 LWU = 0xe,
13296 LLD = 0x7,
13297 SCD = 0xf
13298};
13299
8fffc646
JH
13300/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
13301
13302enum {
13303 LBUE = 0x0,
13304 LHUE = 0x1,
13305 LWLE = 0x2,
13306 LWRE = 0x3,
13307 LBE = 0x4,
13308 LHE = 0x5,
13309 LLE = 0x6,
13310 LWE = 0x7,
13311};
13312
13313/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
13314
13315enum {
13316 SWLE = 0x0,
13317 SWRE = 0x1,
13318 PREFE = 0x2,
13319 CACHEE = 0x3,
13320 SBE = 0x4,
13321 SHE = 0x5,
13322 SCE = 0x6,
13323 SWE = 0x7,
13324};
13325
3c824109
NF
13326/* POOL32F encoding of minor opcode field (bits 5..0) */
13327
13328enum {
13329 /* These are the bit 7..6 values */
13330 ADD_FMT = 0x0,
3c824109
NF
13331
13332 SUB_FMT = 0x1,
3c824109
NF
13333
13334 MUL_FMT = 0x2,
13335
13336 DIV_FMT = 0x3,
13337
13338 /* These are the bit 8..6 values */
3a1f4268 13339 MOVN_FMT = 0x0,
3c824109
NF
13340 RSQRT2_FMT = 0x0,
13341 MOVF_FMT = 0x0,
3a1f4268
YK
13342 RINT_FMT = 0x0,
13343 SELNEZ_FMT = 0x0,
3c824109 13344
3a1f4268 13345 MOVZ_FMT = 0x1,
3c824109
NF
13346 LWXC1 = 0x1,
13347 MOVT_FMT = 0x1,
3a1f4268
YK
13348 CLASS_FMT = 0x1,
13349 SELEQZ_FMT = 0x1,
3c824109
NF
13350
13351 PLL_PS = 0x2,
13352 SWXC1 = 0x2,
3a1f4268 13353 SEL_FMT = 0x2,
3c824109
NF
13354
13355 PLU_PS = 0x3,
13356 LDXC1 = 0x3,
13357
3a1f4268 13358 MOVN_FMT_04 = 0x4,
3c824109
NF
13359 PUL_PS = 0x4,
13360 SDXC1 = 0x4,
13361 RECIP2_FMT = 0x4,
13362
3a1f4268 13363 MOVZ_FMT_05 = 0x05,
3c824109
NF
13364 PUU_PS = 0x5,
13365 LUXC1 = 0x5,
13366
13367 CVT_PS_S = 0x6,
13368 SUXC1 = 0x6,
13369 ADDR_PS = 0x6,
13370 PREFX = 0x6,
3a1f4268 13371 MADDF_FMT = 0x6,
3c824109
NF
13372
13373 MULR_PS = 0x7,
3a1f4268 13374 MSUBF_FMT = 0x7,
3c824109
NF
13375
13376 MADD_S = 0x01,
13377 MADD_D = 0x09,
13378 MADD_PS = 0x11,
13379 ALNV_PS = 0x19,
13380 MSUB_S = 0x21,
13381 MSUB_D = 0x29,
13382 MSUB_PS = 0x31,
13383
13384 NMADD_S = 0x02,
13385 NMADD_D = 0x0a,
13386 NMADD_PS = 0x12,
13387 NMSUB_S = 0x22,
13388 NMSUB_D = 0x2a,
13389 NMSUB_PS = 0x32,
13390
3a1f4268
YK
13391 MIN_FMT = 0x3,
13392 MAX_FMT = 0xb,
13393 MINA_FMT = 0x23,
13394 MAXA_FMT = 0x2b,
3c824109
NF
13395 POOL32FXF = 0x3b,
13396
13397 CABS_COND_FMT = 0x1c, /* MIPS3D */
3a1f4268
YK
13398 C_COND_FMT = 0x3c,
13399
13400 CMP_CONDN_S = 0x5,
13401 CMP_CONDN_D = 0x15
3c824109
NF
13402};
13403
13404/* POOL32Fxf encoding of minor opcode extension field */
13405
13406enum {
13407 CVT_L = 0x04,
13408 RSQRT_FMT = 0x08,
13409 FLOOR_L = 0x0c,
13410 CVT_PW_PS = 0x1c,
13411 CVT_W = 0x24,
13412 SQRT_FMT = 0x28,
13413 FLOOR_W = 0x2c,
13414 CVT_PS_PW = 0x3c,
13415 CFC1 = 0x40,
13416 RECIP_FMT = 0x48,
13417 CEIL_L = 0x4c,
13418 CTC1 = 0x60,
13419 CEIL_W = 0x6c,
13420 MFC1 = 0x80,
13421 CVT_S_PL = 0x84,
13422 TRUNC_L = 0x8c,
13423 MTC1 = 0xa0,
13424 CVT_S_PU = 0xa4,
13425 TRUNC_W = 0xac,
13426 MFHC1 = 0xc0,
13427 ROUND_L = 0xcc,
13428 MTHC1 = 0xe0,
13429 ROUND_W = 0xec,
13430
13431 MOV_FMT = 0x01,
13432 MOVF = 0x05,
13433 ABS_FMT = 0x0d,
13434 RSQRT1_FMT = 0x1d,
13435 MOVT = 0x25,
13436 NEG_FMT = 0x2d,
13437 CVT_D = 0x4d,
13438 RECIP1_FMT = 0x5d,
13439 CVT_S = 0x6d
13440};
13441
13442/* POOL32I encoding of minor opcode field (bits 25..21) */
13443
13444enum {
13445 BLTZ = 0x00,
13446 BLTZAL = 0x01,
13447 BGEZ = 0x02,
13448 BGEZAL = 0x03,
13449 BLEZ = 0x04,
13450 BNEZC = 0x05,
13451 BGTZ = 0x06,
13452 BEQZC = 0x07,
13453 TLTI = 0x08,
3a1f4268 13454 BC1EQZC = 0x08,
3c824109 13455 TGEI = 0x09,
3a1f4268 13456 BC1NEZC = 0x09,
3c824109 13457 TLTIU = 0x0a,
3a1f4268 13458 BC2EQZC = 0x0a,
3c824109 13459 TGEIU = 0x0b,
3a1f4268 13460 BC2NEZC = 0x0a,
3c824109 13461 TNEI = 0x0c,
3a1f4268 13462 R6_SYNCI = 0x0c,
3c824109
NF
13463 LUI = 0x0d,
13464 TEQI = 0x0e,
13465 SYNCI = 0x10,
13466 BLTZALS = 0x11,
13467 BGEZALS = 0x13,
13468 BC2F = 0x14,
13469 BC2T = 0x15,
13470 BPOSGE64 = 0x1a,
13471 BPOSGE32 = 0x1b,
13472 /* These overlap and are distinguished by bit16 of the instruction */
13473 BC1F = 0x1c,
13474 BC1T = 0x1d,
13475 BC1ANY2F = 0x1c,
13476 BC1ANY2T = 0x1d,
13477 BC1ANY4F = 0x1e,
13478 BC1ANY4T = 0x1f
13479};
13480
13481/* POOL16A encoding of minor opcode field */
13482
13483enum {
13484 ADDU16 = 0x0,
13485 SUBU16 = 0x1
13486};
13487
13488/* POOL16B encoding of minor opcode field */
13489
13490enum {
13491 SLL16 = 0x0,
13492 SRL16 = 0x1
13493};
13494
13495/* POOL16C encoding of minor opcode field */
13496
13497enum {
13498 NOT16 = 0x00,
13499 XOR16 = 0x04,
13500 AND16 = 0x08,
13501 OR16 = 0x0c,
13502 LWM16 = 0x10,
13503 SWM16 = 0x14,
13504 JR16 = 0x18,
13505 JRC16 = 0x1a,
13506 JALR16 = 0x1c,
13507 JALR16S = 0x1e,
13508 MFHI16 = 0x20,
13509 MFLO16 = 0x24,
13510 BREAK16 = 0x28,
13511 SDBBP16 = 0x2c,
13512 JRADDIUSP = 0x30
13513};
13514
3a1f4268
YK
13515/* R6 POOL16C encoding of minor opcode field (bits 0..5) */
13516
13517enum {
13518 R6_NOT16 = 0x00,
13519 R6_AND16 = 0x01,
13520 R6_LWM16 = 0x02,
13521 R6_JRC16 = 0x03,
13522 MOVEP = 0x04,
c38a1d52
AR
13523 MOVEP_05 = 0x05,
13524 MOVEP_06 = 0x06,
3a1f4268
YK
13525 MOVEP_07 = 0x07,
13526 R6_XOR16 = 0x08,
13527 R6_OR16 = 0x09,
13528 R6_SWM16 = 0x0a,
13529 JALRC16 = 0x0b,
13530 MOVEP_0C = 0x0c,
c38a1d52
AR
13531 MOVEP_0D = 0x0d,
13532 MOVEP_0E = 0x0e,
3a1f4268
YK
13533 MOVEP_0F = 0x0f,
13534 JRCADDIUSP = 0x13,
13535 R6_BREAK16 = 0x1b,
13536 R6_SDBBP16 = 0x3b
13537};
13538
3c824109
NF
13539/* POOL16D encoding of minor opcode field */
13540
13541enum {
13542 ADDIUS5 = 0x0,
13543 ADDIUSP = 0x1
13544};
13545
13546/* POOL16E encoding of minor opcode field */
13547
13548enum {
13549 ADDIUR2 = 0x0,
13550 ADDIUR1SP = 0x1
13551};
13552
13553static int mmreg (int r)
13554{
13555 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13556
13557 return map[r];
13558}
13559
13560/* Used for 16-bit store instructions. */
13561static int mmreg2 (int r)
13562{
13563 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
13564
13565 return map[r];
13566}
13567
13568#define uMIPS_RD(op) ((op >> 7) & 0x7)
13569#define uMIPS_RS(op) ((op >> 4) & 0x7)
13570#define uMIPS_RS2(op) uMIPS_RS(op)
13571#define uMIPS_RS1(op) ((op >> 1) & 0x7)
13572#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
13573#define uMIPS_RS5(op) (op & 0x1f)
13574
13575/* Signed immediate */
13576#define SIMM(op, start, width) \
13577 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
13578 << (32-width)) \
13579 >> (32-width))
13580/* Zero-extended immediate */
13581#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
13582
d75c135e 13583static void gen_addiur1sp(DisasContext *ctx)
3c824109
NF
13584{
13585 int rd = mmreg(uMIPS_RD(ctx->opcode));
13586
d75c135e 13587 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
3c824109
NF
13588}
13589
d75c135e 13590static void gen_addiur2(DisasContext *ctx)
3c824109
NF
13591{
13592 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
13593 int rd = mmreg(uMIPS_RD(ctx->opcode));
13594 int rs = mmreg(uMIPS_RS(ctx->opcode));
13595
d75c135e 13596 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
3c824109
NF
13597}
13598
d75c135e 13599static void gen_addiusp(DisasContext *ctx)
3c824109
NF
13600{
13601 int encoded = ZIMM(ctx->opcode, 1, 9);
13602 int decoded;
13603
13604 if (encoded <= 1) {
13605 decoded = 256 + encoded;
13606 } else if (encoded <= 255) {
13607 decoded = encoded;
13608 } else if (encoded <= 509) {
13609 decoded = encoded - 512;
13610 } else {
13611 decoded = encoded - 768;
13612 }
13613
d75c135e 13614 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
3c824109
NF
13615}
13616
d75c135e 13617static void gen_addius5(DisasContext *ctx)
3c824109
NF
13618{
13619 int imm = SIMM(ctx->opcode, 1, 4);
13620 int rd = (ctx->opcode >> 5) & 0x1f;
13621
d75c135e 13622 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
3c824109
NF
13623}
13624
d75c135e 13625static void gen_andi16(DisasContext *ctx)
3c824109
NF
13626{
13627 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
13628 31, 32, 63, 64, 255, 32768, 65535 };
13629 int rd = mmreg(uMIPS_RD(ctx->opcode));
13630 int rs = mmreg(uMIPS_RS(ctx->opcode));
13631 int encoded = ZIMM(ctx->opcode, 0, 4);
13632
d75c135e 13633 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
13634}
13635
13636static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
13637 int base, int16_t offset)
13638{
13639 TCGv t0, t1;
13640 TCGv_i32 t2;
13641
13642 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 13643 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
13644 return;
13645 }
13646
13647 t0 = tcg_temp_new();
13648
13649 gen_base_offset_addr(ctx, t0, base, offset);
13650
13651 t1 = tcg_const_tl(reglist);
13652 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 13653
3c824109
NF
13654 save_cpu_state(ctx, 1);
13655 switch (opc) {
13656 case LWM32:
895c2d04 13657 gen_helper_lwm(cpu_env, t0, t1, t2);
3c824109
NF
13658 break;
13659 case SWM32:
895c2d04 13660 gen_helper_swm(cpu_env, t0, t1, t2);
3c824109
NF
13661 break;
13662#ifdef TARGET_MIPS64
13663 case LDM:
895c2d04 13664 gen_helper_ldm(cpu_env, t0, t1, t2);
3c824109
NF
13665 break;
13666 case SDM:
895c2d04 13667 gen_helper_sdm(cpu_env, t0, t1, t2);
3c824109 13668 break;
6af0bf9c 13669#endif
3c824109 13670 }
3c824109 13671 tcg_temp_free(t0);
33087598 13672 tcg_temp_free(t1);
3c824109
NF
13673 tcg_temp_free_i32(t2);
13674}
6af0bf9c 13675
3c824109 13676
240ce26a 13677static void gen_pool16c_insn(DisasContext *ctx)
6af0bf9c 13678{
3c824109
NF
13679 int rd = mmreg((ctx->opcode >> 3) & 0x7);
13680 int rs = mmreg(ctx->opcode & 0x7);
6af0bf9c 13681
3c824109
NF
13682 switch (((ctx->opcode) >> 4) & 0x3f) {
13683 case NOT16 + 0:
13684 case NOT16 + 1:
13685 case NOT16 + 2:
13686 case NOT16 + 3:
d75c135e 13687 gen_logic(ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
13688 break;
13689 case XOR16 + 0:
13690 case XOR16 + 1:
13691 case XOR16 + 2:
13692 case XOR16 + 3:
d75c135e 13693 gen_logic(ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
13694 break;
13695 case AND16 + 0:
13696 case AND16 + 1:
13697 case AND16 + 2:
13698 case AND16 + 3:
d75c135e 13699 gen_logic(ctx, OPC_AND, rd, rd, rs);
3c824109
NF
13700 break;
13701 case OR16 + 0:
13702 case OR16 + 1:
13703 case OR16 + 2:
13704 case OR16 + 3:
d75c135e 13705 gen_logic(ctx, OPC_OR, rd, rd, rs);
3c824109
NF
13706 break;
13707 case LWM16 + 0:
13708 case LWM16 + 1:
13709 case LWM16 + 2:
13710 case LWM16 + 3:
13711 {
13712 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13713 int offset = ZIMM(ctx->opcode, 0, 4);
13714
13715 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
13716 29, offset << 2);
13717 }
13718 break;
13719 case SWM16 + 0:
13720 case SWM16 + 1:
13721 case SWM16 + 2:
13722 case SWM16 + 3:
13723 {
13724 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13725 int offset = ZIMM(ctx->opcode, 0, 4);
13726
13727 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
13728 29, offset << 2);
13729 }
13730 break;
13731 case JR16 + 0:
13732 case JR16 + 1:
13733 {
13734 int reg = ctx->opcode & 0x1f;
13735
b231c103 13736 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
3c824109 13737 }
3c824109
NF
13738 break;
13739 case JRC16 + 0:
13740 case JRC16 + 1:
13741 {
13742 int reg = ctx->opcode & 0x1f;
b231c103 13743 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
3c824109
NF
13744 /* Let normal delay slot handling in our caller take us
13745 to the branch target. */
13746 }
13747 break;
13748 case JALR16 + 0:
13749 case JALR16 + 1:
b231c103
YK
13750 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
13751 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13752 break;
3c824109
NF
13753 case JALR16S + 0:
13754 case JALR16S + 1:
b231c103
YK
13755 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
13756 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
13757 break;
13758 case MFHI16 + 0:
13759 case MFHI16 + 1:
26135ead 13760 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
13761 break;
13762 case MFLO16 + 0:
13763 case MFLO16 + 1:
26135ead 13764 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
13765 break;
13766 case BREAK16:
9c708c7f 13767 generate_exception_end(ctx, EXCP_BREAK);
3c824109
NF
13768 break;
13769 case SDBBP16:
3b3c1694
LA
13770 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
13771 gen_helper_do_semihosting(cpu_env);
13772 } else {
13773 /* XXX: not clear which exception should be raised
13774 * when in debug mode...
13775 */
13776 check_insn(ctx, ISA_MIPS32);
9c708c7f 13777 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 13778 }
3c824109
NF
13779 break;
13780 case JRADDIUSP + 0:
13781 case JRADDIUSP + 1:
13782 {
13783 int imm = ZIMM(ctx->opcode, 0, 5);
b231c103 13784 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
d75c135e 13785 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
3c824109
NF
13786 /* Let normal delay slot handling in our caller take us
13787 to the branch target. */
13788 }
13789 break;
13790 default:
9c708c7f 13791 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
13792 break;
13793 }
13794}
13795
ed7ce6c0
YK
13796static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
13797 int enc_rs)
13798{
13799 int rd, rs, re, rt;
13800 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
13801 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
13802 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
13803 rd = rd_enc[enc_dest];
13804 re = re_enc[enc_dest];
13805 rs = rs_rt_enc[enc_rs];
13806 rt = rs_rt_enc[enc_rt];
13807 if (rs) {
13808 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
13809 } else {
13810 tcg_gen_movi_tl(cpu_gpr[rd], 0);
13811 }
13812 if (rt) {
13813 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
13814 } else {
13815 tcg_gen_movi_tl(cpu_gpr[re], 0);
13816 }
13817}
13818
13819static void gen_pool16c_r6_insn(DisasContext *ctx)
13820{
13821 int rt = mmreg((ctx->opcode >> 7) & 0x7);
13822 int rs = mmreg((ctx->opcode >> 4) & 0x7);
13823
13824 switch (ctx->opcode & 0xf) {
13825 case R6_NOT16:
13826 gen_logic(ctx, OPC_NOR, rt, rs, 0);
13827 break;
13828 case R6_AND16:
13829 gen_logic(ctx, OPC_AND, rt, rt, rs);
13830 break;
13831 case R6_LWM16:
13832 {
13833 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13834 int offset = extract32(ctx->opcode, 4, 4);
13835 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
13836 }
13837 break;
13838 case R6_JRC16: /* JRCADDIUSP */
13839 if ((ctx->opcode >> 4) & 1) {
13840 /* JRCADDIUSP */
13841 int imm = extract32(ctx->opcode, 5, 5);
13842 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13843 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13844 } else {
13845 /* JRC16 */
e1555d7d 13846 rs = extract32(ctx->opcode, 5, 5);
ed7ce6c0
YK
13847 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
13848 }
13849 break;
c38a1d52
AR
13850 case MOVEP:
13851 case MOVEP_05:
13852 case MOVEP_06:
13853 case MOVEP_07:
13854 case MOVEP_0C:
13855 case MOVEP_0D:
13856 case MOVEP_0E:
13857 case MOVEP_0F:
ed7ce6c0
YK
13858 {
13859 int enc_dest = uMIPS_RD(ctx->opcode);
13860 int enc_rt = uMIPS_RS2(ctx->opcode);
13861 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
13862 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
13863 }
13864 break;
13865 case R6_XOR16:
13866 gen_logic(ctx, OPC_XOR, rt, rt, rs);
13867 break;
13868 case R6_OR16:
13869 gen_logic(ctx, OPC_OR, rt, rt, rs);
13870 break;
13871 case R6_SWM16:
13872 {
13873 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13874 int offset = extract32(ctx->opcode, 4, 4);
13875 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
13876 }
13877 break;
13878 case JALRC16: /* BREAK16, SDBBP16 */
13879 switch (ctx->opcode & 0x3f) {
13880 case JALRC16:
13881 case JALRC16 + 0x20:
13882 /* JALRC16 */
13883 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
13884 31, 0, 0);
13885 break;
13886 case R6_BREAK16:
13887 /* BREAK16 */
13888 generate_exception(ctx, EXCP_BREAK);
13889 break;
13890 case R6_SDBBP16:
13891 /* SDBBP16 */
060ebfef
LA
13892 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
13893 gen_helper_do_semihosting(cpu_env);
ed7ce6c0 13894 } else {
060ebfef
LA
13895 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13896 generate_exception(ctx, EXCP_RI);
13897 } else {
13898 generate_exception(ctx, EXCP_DBp);
13899 }
ed7ce6c0
YK
13900 }
13901 break;
13902 }
13903 break;
13904 default:
13905 generate_exception(ctx, EXCP_RI);
13906 break;
13907 }
13908}
13909
3c824109
NF
13910static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
13911{
13912 TCGv t0 = tcg_temp_new();
13913 TCGv t1 = tcg_temp_new();
13914
13915 gen_load_gpr(t0, base);
13916
13917 if (index != 0) {
13918 gen_load_gpr(t1, index);
13919 tcg_gen_shli_tl(t1, t1, 2);
13920 gen_op_addr_add(ctx, t0, t1, t0);
13921 }
13922
5f68f5ae 13923 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
13924 gen_store_gpr(t1, rd);
13925
13926 tcg_temp_free(t0);
13927 tcg_temp_free(t1);
13928}
13929
13930static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
13931 int base, int16_t offset)
13932{
3c824109
NF
13933 TCGv t0, t1;
13934
36c6711b 13935 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
9c708c7f 13936 generate_exception_end(ctx, EXCP_RI);
d796321b
FB
13937 return;
13938 }
13939
3c824109
NF
13940 t0 = tcg_temp_new();
13941 t1 = tcg_temp_new();
8e9ade68 13942
3c824109
NF
13943 gen_base_offset_addr(ctx, t0, base, offset);
13944
13945 switch (opc) {
13946 case LWP:
36c6711b 13947 if (rd == base) {
9c708c7f 13948 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
13949 return;
13950 }
5f68f5ae 13951 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
13952 gen_store_gpr(t1, rd);
13953 tcg_gen_movi_tl(t1, 4);
13954 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 13955 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109 13956 gen_store_gpr(t1, rd+1);
3c824109
NF
13957 break;
13958 case SWP:
3c824109 13959 gen_load_gpr(t1, rd);
5f68f5ae 13960 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
13961 tcg_gen_movi_tl(t1, 4);
13962 gen_op_addr_add(ctx, t0, t0, t1);
13963 gen_load_gpr(t1, rd+1);
5f68f5ae 13964 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
13965 break;
13966#ifdef TARGET_MIPS64
13967 case LDP:
36c6711b 13968 if (rd == base) {
9c708c7f 13969 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
13970 return;
13971 }
5f68f5ae 13972 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
13973 gen_store_gpr(t1, rd);
13974 tcg_gen_movi_tl(t1, 8);
13975 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 13976 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109 13977 gen_store_gpr(t1, rd+1);
3c824109
NF
13978 break;
13979 case SDP:
3c824109 13980 gen_load_gpr(t1, rd);
5f68f5ae 13981 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
13982 tcg_gen_movi_tl(t1, 8);
13983 gen_op_addr_add(ctx, t0, t0, t1);
13984 gen_load_gpr(t1, rd+1);
5f68f5ae 13985 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
13986 break;
13987#endif
6af0bf9c 13988 }
3c824109
NF
13989 tcg_temp_free(t0);
13990 tcg_temp_free(t1);
13991}
618b0fe9 13992
d208ac0c
LA
13993static void gen_sync(int stype)
13994{
13995 TCGBar tcg_mo = TCG_BAR_SC;
13996
13997 switch (stype) {
13998 case 0x4: /* SYNC_WMB */
13999 tcg_mo |= TCG_MO_ST_ST;
14000 break;
14001 case 0x10: /* SYNC_MB */
14002 tcg_mo |= TCG_MO_ALL;
14003 break;
14004 case 0x11: /* SYNC_ACQUIRE */
14005 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14006 break;
14007 case 0x12: /* SYNC_RELEASE */
14008 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14009 break;
14010 case 0x13: /* SYNC_RMB */
14011 tcg_mo |= TCG_MO_LD_LD;
14012 break;
14013 default:
14014 tcg_mo |= TCG_MO_ALL;
14015 break;
14016 }
14017
14018 tcg_gen_mb(tcg_mo);
14019}
14020
240ce26a 14021static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
14022{
14023 int extension = (ctx->opcode >> 6) & 0x3f;
14024 int minor = (ctx->opcode >> 12) & 0xf;
14025 uint32_t mips32_op;
14026
14027 switch (extension) {
14028 case TEQ:
14029 mips32_op = OPC_TEQ;
14030 goto do_trap;
14031 case TGE:
14032 mips32_op = OPC_TGE;
14033 goto do_trap;
14034 case TGEU:
14035 mips32_op = OPC_TGEU;
14036 goto do_trap;
14037 case TLT:
14038 mips32_op = OPC_TLT;
14039 goto do_trap;
14040 case TLTU:
14041 mips32_op = OPC_TLTU;
14042 goto do_trap;
14043 case TNE:
14044 mips32_op = OPC_TNE;
14045 do_trap:
14046 gen_trap(ctx, mips32_op, rs, rt, -1);
14047 break;
14048#ifndef CONFIG_USER_ONLY
14049 case MFC0:
14050 case MFC0 + 32:
2e15497c 14051 check_cp0_enabled(ctx);
3c824109
NF
14052 if (rt == 0) {
14053 /* Treat as NOP. */
14054 break;
14055 }
d75c135e 14056 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
14057 break;
14058 case MTC0:
14059 case MTC0 + 32:
2e15497c 14060 check_cp0_enabled(ctx);
3c824109
NF
14061 {
14062 TCGv t0 = tcg_temp_new();
618b0fe9 14063
3c824109 14064 gen_load_gpr(t0, rt);
d75c135e 14065 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
14066 tcg_temp_free(t0);
14067 }
14068 break;
14069#endif
a1fc6246
LA
14070 case 0x2a:
14071 switch (minor & 3) {
14072 case MADD_ACC:
14073 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
14074 break;
14075 case MADDU_ACC:
14076 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
14077 break;
14078 case MSUB_ACC:
14079 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
14080 break;
14081 case MSUBU_ACC:
14082 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
14083 break;
14084 default:
14085 goto pool32axf_invalid;
14086 }
14087 break;
14088 case 0x32:
14089 switch (minor & 3) {
14090 case MULT_ACC:
14091 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
14092 break;
14093 case MULTU_ACC:
14094 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
14095 break;
14096 default:
14097 goto pool32axf_invalid;
14098 }
14099 break;
3c824109
NF
14100 case 0x2c:
14101 switch (minor) {
e0332095
YK
14102 case BITSWAP:
14103 check_insn(ctx, ISA_MIPS32R6);
14104 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
14105 break;
3c824109
NF
14106 case SEB:
14107 gen_bshfl(ctx, OPC_SEB, rs, rt);
14108 break;
14109 case SEH:
14110 gen_bshfl(ctx, OPC_SEH, rs, rt);
14111 break;
14112 case CLO:
14113 mips32_op = OPC_CLO;
14114 goto do_cl;
14115 case CLZ:
14116 mips32_op = OPC_CLZ;
14117 do_cl:
d75c135e 14118 check_insn(ctx, ISA_MIPS32);
3c824109
NF
14119 gen_cl(ctx, mips32_op, rt, rs);
14120 break;
14121 case RDHWR:
b00c7218
YK
14122 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14123 gen_rdhwr(ctx, rt, rs, 0);
3c824109
NF
14124 break;
14125 case WSBH:
14126 gen_bshfl(ctx, OPC_WSBH, rs, rt);
14127 break;
14128 case MULT:
9e8f441a 14129 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 14130 mips32_op = OPC_MULT;
26135ead 14131 goto do_mul;
3c824109 14132 case MULTU:
9e8f441a 14133 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 14134 mips32_op = OPC_MULTU;
26135ead 14135 goto do_mul;
3c824109 14136 case DIV:
9e8f441a 14137 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 14138 mips32_op = OPC_DIV;
26135ead 14139 goto do_div;
3c824109 14140 case DIVU:
9e8f441a 14141 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 14142 mips32_op = OPC_DIVU;
26135ead
RS
14143 goto do_div;
14144 do_div:
14145 check_insn(ctx, ISA_MIPS32);
14146 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14147 break;
3c824109 14148 case MADD:
9e8f441a 14149 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 14150 mips32_op = OPC_MADD;
26135ead 14151 goto do_mul;
3c824109 14152 case MADDU:
9e8f441a 14153 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 14154 mips32_op = OPC_MADDU;
26135ead 14155 goto do_mul;
3c824109 14156 case MSUB:
9e8f441a 14157 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 14158 mips32_op = OPC_MSUB;
26135ead 14159 goto do_mul;
3c824109 14160 case MSUBU:
9e8f441a 14161 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 14162 mips32_op = OPC_MSUBU;
26135ead 14163 do_mul:
d75c135e 14164 check_insn(ctx, ISA_MIPS32);
a1fc6246 14165 gen_muldiv(ctx, mips32_op, 0, rs, rt);
3c824109
NF
14166 break;
14167 default:
14168 goto pool32axf_invalid;
14169 }
14170 break;
14171 case 0x34:
14172 switch (minor) {
14173 case MFC2:
14174 case MTC2:
14175 case MFHC2:
14176 case MTHC2:
14177 case CFC2:
14178 case CTC2:
14179 generate_exception_err(ctx, EXCP_CpU, 2);
14180 break;
14181 default:
14182 goto pool32axf_invalid;
14183 }
14184 break;
14185 case 0x3c:
14186 switch (minor) {
65935f07
YK
14187 case JALR: /* JALRC */
14188 case JALR_HB: /* JALRC_HB */
14189 if (ctx->insn_flags & ISA_MIPS32R6) {
14190 /* JALRC, JALRC_HB */
14191 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
14192 } else {
14193 /* JALR, JALR_HB */
14194 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
14195 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14196 }
3c824109
NF
14197 break;
14198 case JALRS:
14199 case JALRS_HB:
9e8f441a 14200 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
14201 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
14202 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
14203 break;
14204 default:
14205 goto pool32axf_invalid;
14206 }
14207 break;
14208 case 0x05:
14209 switch (minor) {
14210 case RDPGPR:
2e15497c 14211 check_cp0_enabled(ctx);
d75c135e 14212 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 14213 gen_load_srsgpr(rs, rt);
3c824109
NF
14214 break;
14215 case WRPGPR:
2e15497c 14216 check_cp0_enabled(ctx);
d75c135e 14217 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 14218 gen_store_srsgpr(rs, rt);
3c824109
NF
14219 break;
14220 default:
14221 goto pool32axf_invalid;
14222 }
14223 break;
14224#ifndef CONFIG_USER_ONLY
14225 case 0x0d:
14226 switch (minor) {
14227 case TLBP:
14228 mips32_op = OPC_TLBP;
14229 goto do_cp0;
14230 case TLBR:
14231 mips32_op = OPC_TLBR;
14232 goto do_cp0;
14233 case TLBWI:
14234 mips32_op = OPC_TLBWI;
14235 goto do_cp0;
14236 case TLBWR:
14237 mips32_op = OPC_TLBWR;
14238 goto do_cp0;
e60ec063
YK
14239 case TLBINV:
14240 mips32_op = OPC_TLBINV;
14241 goto do_cp0;
14242 case TLBINVF:
14243 mips32_op = OPC_TLBINVF;
14244 goto do_cp0;
3c824109
NF
14245 case WAIT:
14246 mips32_op = OPC_WAIT;
14247 goto do_cp0;
14248 case DERET:
14249 mips32_op = OPC_DERET;
14250 goto do_cp0;
14251 case ERET:
14252 mips32_op = OPC_ERET;
14253 do_cp0:
14254 gen_cp0(env, ctx, mips32_op, rt, rs);
14255 break;
14256 default:
14257 goto pool32axf_invalid;
14258 }
14259 break;
14260 case 0x1d:
14261 switch (minor) {
14262 case DI:
2e15497c 14263 check_cp0_enabled(ctx);
3c824109
NF
14264 {
14265 TCGv t0 = tcg_temp_new();
14266
14267 save_cpu_state(ctx, 1);
895c2d04 14268 gen_helper_di(t0, cpu_env);
3c824109
NF
14269 gen_store_gpr(t0, rs);
14270 /* Stop translation as we may have switched the execution mode */
eeb3bba8 14271 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
14272 tcg_temp_free(t0);
14273 }
14274 break;
14275 case EI:
2e15497c 14276 check_cp0_enabled(ctx);
3c824109
NF
14277 {
14278 TCGv t0 = tcg_temp_new();
14279
14280 save_cpu_state(ctx, 1);
895c2d04 14281 gen_helper_ei(t0, cpu_env);
3c824109 14282 gen_store_gpr(t0, rs);
b28425ba 14283 /* DISAS_STOP isn't sufficient, we need to ensure we break out
b74cddcb 14284 of translated code to check for pending interrupts. */
eeb3bba8
EC
14285 gen_save_pc(ctx->base.pc_next + 4);
14286 ctx->base.is_jmp = DISAS_EXIT;
3c824109
NF
14287 tcg_temp_free(t0);
14288 }
14289 break;
14290 default:
14291 goto pool32axf_invalid;
14292 }
14293 break;
14294#endif
14295 case 0x2d:
14296 switch (minor) {
14297 case SYNC:
d208ac0c 14298 gen_sync(extract32(ctx->opcode, 16, 5));
3c824109
NF
14299 break;
14300 case SYSCALL:
9c708c7f 14301 generate_exception_end(ctx, EXCP_SYSCALL);
3c824109
NF
14302 break;
14303 case SDBBP:
3b3c1694
LA
14304 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
14305 gen_helper_do_semihosting(cpu_env);
14306 } else {
14307 check_insn(ctx, ISA_MIPS32);
e0332095 14308 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 14309 generate_exception_end(ctx, EXCP_RI);
e0332095 14310 } else {
9c708c7f 14311 generate_exception_end(ctx, EXCP_DBp);
e0332095 14312 }
3b3c1694 14313 }
3c824109
NF
14314 break;
14315 default:
14316 goto pool32axf_invalid;
14317 }
14318 break;
a1fc6246 14319 case 0x01:
26135ead 14320 switch (minor & 3) {
a1fc6246 14321 case MFHI_ACC:
26135ead 14322 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
3c824109 14323 break;
a1fc6246 14324 case MFLO_ACC:
26135ead 14325 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
3c824109 14326 break;
a1fc6246 14327 case MTHI_ACC:
26135ead 14328 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
3c824109 14329 break;
a1fc6246 14330 case MTLO_ACC:
26135ead 14331 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
3c824109
NF
14332 break;
14333 default:
14334 goto pool32axf_invalid;
14335 }
14336 break;
a1fc6246 14337 case 0x35:
9e8f441a 14338 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a1fc6246
LA
14339 switch (minor) {
14340 case MFHI32:
14341 gen_HILO(ctx, OPC_MFHI, 0, rs);
14342 break;
14343 case MFLO32:
14344 gen_HILO(ctx, OPC_MFLO, 0, rs);
14345 break;
14346 case MTHI32:
14347 gen_HILO(ctx, OPC_MTHI, 0, rs);
14348 break;
14349 case MTLO32:
14350 gen_HILO(ctx, OPC_MTLO, 0, rs);
14351 break;
14352 default:
14353 goto pool32axf_invalid;
14354 }
14355 break;
3c824109
NF
14356 default:
14357 pool32axf_invalid:
14358 MIPS_INVAL("pool32axf");
9c708c7f 14359 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
14360 break;
14361 }
14362}
14363
14364/* Values for microMIPS fmt field. Variable-width, depending on which
14365 formats the instruction supports. */
14366
14367enum {
14368 FMT_SD_S = 0,
14369 FMT_SD_D = 1,
14370
14371 FMT_SDPS_S = 0,
14372 FMT_SDPS_D = 1,
14373 FMT_SDPS_PS = 2,
14374
14375 FMT_SWL_S = 0,
14376 FMT_SWL_W = 1,
14377 FMT_SWL_L = 2,
14378
14379 FMT_DWL_D = 0,
14380 FMT_DWL_W = 1,
14381 FMT_DWL_L = 2
14382};
14383
d75c135e 14384static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
3c824109
NF
14385{
14386 int extension = (ctx->opcode >> 6) & 0x3ff;
14387 uint32_t mips32_op;
14388
14389#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
14390#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
14391#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
14392
14393 switch (extension) {
14394 case FLOAT_1BIT_FMT(CFC1, 0):
14395 mips32_op = OPC_CFC1;
14396 goto do_cp1;
14397 case FLOAT_1BIT_FMT(CTC1, 0):
14398 mips32_op = OPC_CTC1;
14399 goto do_cp1;
14400 case FLOAT_1BIT_FMT(MFC1, 0):
14401 mips32_op = OPC_MFC1;
14402 goto do_cp1;
14403 case FLOAT_1BIT_FMT(MTC1, 0):
14404 mips32_op = OPC_MTC1;
14405 goto do_cp1;
14406 case FLOAT_1BIT_FMT(MFHC1, 0):
14407 mips32_op = OPC_MFHC1;
14408 goto do_cp1;
14409 case FLOAT_1BIT_FMT(MTHC1, 0):
14410 mips32_op = OPC_MTHC1;
14411 do_cp1:
14412 gen_cp1(ctx, mips32_op, rt, rs);
14413 break;
14414
14415 /* Reciprocal square root */
14416 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
14417 mips32_op = OPC_RSQRT_S;
14418 goto do_unaryfp;
14419 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
14420 mips32_op = OPC_RSQRT_D;
14421 goto do_unaryfp;
14422
14423 /* Square root */
14424 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
14425 mips32_op = OPC_SQRT_S;
14426 goto do_unaryfp;
14427 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
14428 mips32_op = OPC_SQRT_D;
14429 goto do_unaryfp;
14430
14431 /* Reciprocal */
14432 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
14433 mips32_op = OPC_RECIP_S;
14434 goto do_unaryfp;
14435 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
14436 mips32_op = OPC_RECIP_D;
14437 goto do_unaryfp;
14438
14439 /* Floor */
14440 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
14441 mips32_op = OPC_FLOOR_L_S;
14442 goto do_unaryfp;
14443 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
14444 mips32_op = OPC_FLOOR_L_D;
14445 goto do_unaryfp;
14446 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
14447 mips32_op = OPC_FLOOR_W_S;
14448 goto do_unaryfp;
14449 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
14450 mips32_op = OPC_FLOOR_W_D;
14451 goto do_unaryfp;
14452
14453 /* Ceiling */
14454 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
14455 mips32_op = OPC_CEIL_L_S;
14456 goto do_unaryfp;
14457 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
14458 mips32_op = OPC_CEIL_L_D;
14459 goto do_unaryfp;
14460 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
14461 mips32_op = OPC_CEIL_W_S;
14462 goto do_unaryfp;
14463 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
14464 mips32_op = OPC_CEIL_W_D;
14465 goto do_unaryfp;
14466
14467 /* Truncation */
14468 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
14469 mips32_op = OPC_TRUNC_L_S;
14470 goto do_unaryfp;
14471 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
14472 mips32_op = OPC_TRUNC_L_D;
14473 goto do_unaryfp;
14474 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
14475 mips32_op = OPC_TRUNC_W_S;
14476 goto do_unaryfp;
14477 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
14478 mips32_op = OPC_TRUNC_W_D;
14479 goto do_unaryfp;
14480
14481 /* Round */
14482 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
14483 mips32_op = OPC_ROUND_L_S;
14484 goto do_unaryfp;
14485 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
14486 mips32_op = OPC_ROUND_L_D;
14487 goto do_unaryfp;
14488 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
14489 mips32_op = OPC_ROUND_W_S;
14490 goto do_unaryfp;
14491 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
14492 mips32_op = OPC_ROUND_W_D;
14493 goto do_unaryfp;
14494
14495 /* Integer to floating-point conversion */
14496 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
14497 mips32_op = OPC_CVT_L_S;
14498 goto do_unaryfp;
14499 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
14500 mips32_op = OPC_CVT_L_D;
14501 goto do_unaryfp;
14502 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
14503 mips32_op = OPC_CVT_W_S;
14504 goto do_unaryfp;
14505 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
14506 mips32_op = OPC_CVT_W_D;
14507 goto do_unaryfp;
14508
14509 /* Paired-foo conversions */
14510 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
14511 mips32_op = OPC_CVT_S_PL;
14512 goto do_unaryfp;
14513 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
14514 mips32_op = OPC_CVT_S_PU;
14515 goto do_unaryfp;
14516 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
14517 mips32_op = OPC_CVT_PW_PS;
14518 goto do_unaryfp;
14519 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
14520 mips32_op = OPC_CVT_PS_PW;
14521 goto do_unaryfp;
14522
14523 /* Floating-point moves */
14524 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
14525 mips32_op = OPC_MOV_S;
14526 goto do_unaryfp;
14527 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
14528 mips32_op = OPC_MOV_D;
14529 goto do_unaryfp;
14530 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
14531 mips32_op = OPC_MOV_PS;
14532 goto do_unaryfp;
14533
14534 /* Absolute value */
14535 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
14536 mips32_op = OPC_ABS_S;
14537 goto do_unaryfp;
14538 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
14539 mips32_op = OPC_ABS_D;
14540 goto do_unaryfp;
14541 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
14542 mips32_op = OPC_ABS_PS;
14543 goto do_unaryfp;
14544
14545 /* Negation */
14546 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
14547 mips32_op = OPC_NEG_S;
14548 goto do_unaryfp;
14549 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
14550 mips32_op = OPC_NEG_D;
14551 goto do_unaryfp;
14552 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
14553 mips32_op = OPC_NEG_PS;
14554 goto do_unaryfp;
14555
14556 /* Reciprocal square root step */
14557 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
14558 mips32_op = OPC_RSQRT1_S;
14559 goto do_unaryfp;
14560 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
14561 mips32_op = OPC_RSQRT1_D;
14562 goto do_unaryfp;
14563 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
14564 mips32_op = OPC_RSQRT1_PS;
14565 goto do_unaryfp;
14566
14567 /* Reciprocal step */
14568 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
14569 mips32_op = OPC_RECIP1_S;
14570 goto do_unaryfp;
14571 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
14572 mips32_op = OPC_RECIP1_S;
14573 goto do_unaryfp;
14574 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
14575 mips32_op = OPC_RECIP1_PS;
14576 goto do_unaryfp;
14577
14578 /* Conversions from double */
14579 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
14580 mips32_op = OPC_CVT_D_S;
14581 goto do_unaryfp;
14582 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
14583 mips32_op = OPC_CVT_D_W;
14584 goto do_unaryfp;
14585 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
14586 mips32_op = OPC_CVT_D_L;
14587 goto do_unaryfp;
14588
14589 /* Conversions from single */
14590 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
14591 mips32_op = OPC_CVT_S_D;
14592 goto do_unaryfp;
14593 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
14594 mips32_op = OPC_CVT_S_W;
14595 goto do_unaryfp;
14596 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
14597 mips32_op = OPC_CVT_S_L;
14598 do_unaryfp:
14599 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
14600 break;
14601
14602 /* Conditional moves on floating-point codes */
14603 case COND_FLOAT_MOV(MOVT, 0):
14604 case COND_FLOAT_MOV(MOVT, 1):
14605 case COND_FLOAT_MOV(MOVT, 2):
14606 case COND_FLOAT_MOV(MOVT, 3):
14607 case COND_FLOAT_MOV(MOVT, 4):
14608 case COND_FLOAT_MOV(MOVT, 5):
14609 case COND_FLOAT_MOV(MOVT, 6):
14610 case COND_FLOAT_MOV(MOVT, 7):
9e8f441a 14611 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14612 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
14613 break;
14614 case COND_FLOAT_MOV(MOVF, 0):
14615 case COND_FLOAT_MOV(MOVF, 1):
14616 case COND_FLOAT_MOV(MOVF, 2):
14617 case COND_FLOAT_MOV(MOVF, 3):
14618 case COND_FLOAT_MOV(MOVF, 4):
14619 case COND_FLOAT_MOV(MOVF, 5):
14620 case COND_FLOAT_MOV(MOVF, 6):
14621 case COND_FLOAT_MOV(MOVF, 7):
9e8f441a 14622 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14623 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
14624 break;
14625 default:
14626 MIPS_INVAL("pool32fxf");
9c708c7f 14627 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
14628 break;
14629 }
14630}
14631
f60eeb0c 14632static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
14633{
14634 int32_t offset;
14635 uint16_t insn;
14636 int rt, rs, rd, rr;
14637 int16_t imm;
8fffc646 14638 uint32_t op, minor, minor2, mips32_op;
3c824109
NF
14639 uint32_t cond, fmt, cc;
14640
eeb3bba8 14641 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
3c824109
NF
14642 ctx->opcode = (ctx->opcode << 16) | insn;
14643
14644 rt = (ctx->opcode >> 21) & 0x1f;
14645 rs = (ctx->opcode >> 16) & 0x1f;
14646 rd = (ctx->opcode >> 11) & 0x1f;
14647 rr = (ctx->opcode >> 6) & 0x1f;
14648 imm = (int16_t) ctx->opcode;
14649
14650 op = (ctx->opcode >> 26) & 0x3f;
14651 switch (op) {
14652 case POOL32A:
14653 minor = ctx->opcode & 0x3f;
14654 switch (minor) {
14655 case 0x00:
14656 minor = (ctx->opcode >> 6) & 0xf;
14657 switch (minor) {
14658 case SLL32:
14659 mips32_op = OPC_SLL;
14660 goto do_shifti;
14661 case SRA:
14662 mips32_op = OPC_SRA;
14663 goto do_shifti;
14664 case SRL32:
14665 mips32_op = OPC_SRL;
14666 goto do_shifti;
14667 case ROTR:
14668 mips32_op = OPC_ROTR;
14669 do_shifti:
d75c135e 14670 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
3c824109 14671 break;
e0332095
YK
14672 case SELEQZ:
14673 check_insn(ctx, ISA_MIPS32R6);
14674 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
14675 break;
14676 case SELNEZ:
14677 check_insn(ctx, ISA_MIPS32R6);
14678 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
14679 break;
b00c7218
YK
14680 case R6_RDHWR:
14681 check_insn(ctx, ISA_MIPS32R6);
14682 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
14683 break;
3c824109
NF
14684 default:
14685 goto pool32a_invalid;
14686 }
14687 break;
14688 case 0x10:
14689 minor = (ctx->opcode >> 6) & 0xf;
14690 switch (minor) {
14691 /* Arithmetic */
14692 case ADD:
14693 mips32_op = OPC_ADD;
14694 goto do_arith;
14695 case ADDU32:
14696 mips32_op = OPC_ADDU;
14697 goto do_arith;
14698 case SUB:
14699 mips32_op = OPC_SUB;
14700 goto do_arith;
14701 case SUBU32:
14702 mips32_op = OPC_SUBU;
14703 goto do_arith;
14704 case MUL:
9e8f441a 14705 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14706 mips32_op = OPC_MUL;
14707 do_arith:
d75c135e 14708 gen_arith(ctx, mips32_op, rd, rs, rt);
3c824109
NF
14709 break;
14710 /* Shifts */
14711 case SLLV:
14712 mips32_op = OPC_SLLV;
14713 goto do_shift;
14714 case SRLV:
14715 mips32_op = OPC_SRLV;
14716 goto do_shift;
14717 case SRAV:
14718 mips32_op = OPC_SRAV;
14719 goto do_shift;
14720 case ROTRV:
14721 mips32_op = OPC_ROTRV;
14722 do_shift:
d75c135e 14723 gen_shift(ctx, mips32_op, rd, rs, rt);
3c824109
NF
14724 break;
14725 /* Logical operations */
14726 case AND:
14727 mips32_op = OPC_AND;
14728 goto do_logic;
14729 case OR32:
14730 mips32_op = OPC_OR;
14731 goto do_logic;
14732 case NOR:
14733 mips32_op = OPC_NOR;
14734 goto do_logic;
14735 case XOR32:
14736 mips32_op = OPC_XOR;
14737 do_logic:
d75c135e 14738 gen_logic(ctx, mips32_op, rd, rs, rt);
3c824109
NF
14739 break;
14740 /* Set less than */
14741 case SLT:
14742 mips32_op = OPC_SLT;
14743 goto do_slt;
14744 case SLTU:
14745 mips32_op = OPC_SLTU;
14746 do_slt:
d75c135e 14747 gen_slt(ctx, mips32_op, rd, rs, rt);
3c824109
NF
14748 break;
14749 default:
14750 goto pool32a_invalid;
14751 }
14752 break;
14753 case 0x18:
14754 minor = (ctx->opcode >> 6) & 0xf;
14755 switch (minor) {
14756 /* Conditional moves */
e0332095
YK
14757 case MOVN: /* MUL */
14758 if (ctx->insn_flags & ISA_MIPS32R6) {
14759 /* MUL */
14760 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
14761 } else {
14762 /* MOVN */
14763 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
14764 }
14765 break;
14766 case MOVZ: /* MUH */
14767 if (ctx->insn_flags & ISA_MIPS32R6) {
14768 /* MUH */
14769 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
14770 } else {
14771 /* MOVZ */
14772 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
14773 }
14774 break;
14775 case MULU:
14776 check_insn(ctx, ISA_MIPS32R6);
14777 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
14778 break;
14779 case MUHU:
14780 check_insn(ctx, ISA_MIPS32R6);
14781 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
14782 break;
14783 case LWXS: /* DIV */
14784 if (ctx->insn_flags & ISA_MIPS32R6) {
14785 /* DIV */
14786 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
14787 } else {
14788 /* LWXS */
14789 gen_ldxs(ctx, rs, rt, rd);
14790 }
14791 break;
14792 case MOD:
14793 check_insn(ctx, ISA_MIPS32R6);
14794 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
14795 break;
14796 case R6_DIVU:
14797 check_insn(ctx, ISA_MIPS32R6);
14798 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
3c824109 14799 break;
e0332095
YK
14800 case MODU:
14801 check_insn(ctx, ISA_MIPS32R6);
14802 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
3c824109
NF
14803 break;
14804 default:
14805 goto pool32a_invalid;
14806 }
14807 break;
14808 case INS:
14809 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
14810 return;
e0332095
YK
14811 case LSA:
14812 check_insn(ctx, ISA_MIPS32R6);
14813 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
14814 extract32(ctx->opcode, 9, 2));
14815 break;
14816 case ALIGN:
14817 check_insn(ctx, ISA_MIPS32R6);
821f2008 14818 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
e0332095 14819 break;
3c824109
NF
14820 case EXT:
14821 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
14822 return;
14823 case POOL32AXF:
240ce26a 14824 gen_pool32axf(env, ctx, rt, rs);
3c824109 14825 break;
dbd8af98 14826 case BREAK32:
9c708c7f 14827 generate_exception_end(ctx, EXCP_BREAK);
3c824109 14828 break;
bb238210
YK
14829 case SIGRIE:
14830 check_insn(ctx, ISA_MIPS32R6);
14831 generate_exception_end(ctx, EXCP_RI);
14832 break;
3c824109
NF
14833 default:
14834 pool32a_invalid:
14835 MIPS_INVAL("pool32a");
9c708c7f 14836 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
14837 break;
14838 }
14839 break;
14840 case POOL32B:
14841 minor = (ctx->opcode >> 12) & 0xf;
14842 switch (minor) {
14843 case CACHE:
2e15497c 14844 check_cp0_enabled(ctx);
0d74a222
LA
14845 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
14846 gen_cache_operation(ctx, rt, rs, imm);
14847 }
3c824109
NF
14848 break;
14849 case LWC2:
14850 case SWC2:
14851 /* COP2: Not implemented. */
14852 generate_exception_err(ctx, EXCP_CpU, 2);
14853 break;
3c824109
NF
14854#ifdef TARGET_MIPS64
14855 case LDP:
14856 case SDP:
d9224450
MR
14857 check_insn(ctx, ISA_MIPS3);
14858 check_mips_64(ctx);
3c824109 14859#endif
146dd620 14860 /* fall through */
d9224450
MR
14861 case LWP:
14862 case SWP:
3c824109
NF
14863 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14864 break;
3c824109
NF
14865#ifdef TARGET_MIPS64
14866 case LDM:
14867 case SDM:
d9224450
MR
14868 check_insn(ctx, ISA_MIPS3);
14869 check_mips_64(ctx);
3c824109 14870#endif
146dd620 14871 /* fall through */
d9224450
MR
14872 case LWM32:
14873 case SWM32:
3c824109
NF
14874 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14875 break;
14876 default:
14877 MIPS_INVAL("pool32b");
9c708c7f 14878 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
14879 break;
14880 }
14881 break;
14882 case POOL32F:
5ab5c041 14883 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3c824109
NF
14884 minor = ctx->opcode & 0x3f;
14885 check_cp1_enabled(ctx);
14886 switch (minor) {
14887 case ALNV_PS:
9e8f441a 14888 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14889 mips32_op = OPC_ALNV_PS;
14890 goto do_madd;
14891 case MADD_S:
9e8f441a 14892 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14893 mips32_op = OPC_MADD_S;
14894 goto do_madd;
14895 case MADD_D:
9e8f441a 14896 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14897 mips32_op = OPC_MADD_D;
14898 goto do_madd;
14899 case MADD_PS:
9e8f441a 14900 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14901 mips32_op = OPC_MADD_PS;
14902 goto do_madd;
14903 case MSUB_S:
9e8f441a 14904 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14905 mips32_op = OPC_MSUB_S;
14906 goto do_madd;
14907 case MSUB_D:
9e8f441a 14908 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14909 mips32_op = OPC_MSUB_D;
14910 goto do_madd;
14911 case MSUB_PS:
9e8f441a 14912 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14913 mips32_op = OPC_MSUB_PS;
14914 goto do_madd;
14915 case NMADD_S:
9e8f441a 14916 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14917 mips32_op = OPC_NMADD_S;
14918 goto do_madd;
14919 case NMADD_D:
9e8f441a 14920 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14921 mips32_op = OPC_NMADD_D;
14922 goto do_madd;
14923 case NMADD_PS:
9e8f441a 14924 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14925 mips32_op = OPC_NMADD_PS;
14926 goto do_madd;
14927 case NMSUB_S:
9e8f441a 14928 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14929 mips32_op = OPC_NMSUB_S;
14930 goto do_madd;
14931 case NMSUB_D:
9e8f441a 14932 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14933 mips32_op = OPC_NMSUB_D;
14934 goto do_madd;
14935 case NMSUB_PS:
9e8f441a 14936 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14937 mips32_op = OPC_NMSUB_PS;
14938 do_madd:
14939 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
14940 break;
14941 case CABS_COND_FMT:
9e8f441a 14942 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14943 cond = (ctx->opcode >> 6) & 0xf;
14944 cc = (ctx->opcode >> 13) & 0x7;
14945 fmt = (ctx->opcode >> 10) & 0x3;
14946 switch (fmt) {
14947 case 0x0:
14948 gen_cmpabs_s(ctx, cond, rt, rs, cc);
14949 break;
14950 case 0x1:
14951 gen_cmpabs_d(ctx, cond, rt, rs, cc);
14952 break;
14953 case 0x2:
14954 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
14955 break;
14956 default:
14957 goto pool32f_invalid;
14958 }
14959 break;
14960 case C_COND_FMT:
9e8f441a 14961 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14962 cond = (ctx->opcode >> 6) & 0xf;
14963 cc = (ctx->opcode >> 13) & 0x7;
14964 fmt = (ctx->opcode >> 10) & 0x3;
14965 switch (fmt) {
14966 case 0x0:
14967 gen_cmp_s(ctx, cond, rt, rs, cc);
14968 break;
14969 case 0x1:
14970 gen_cmp_d(ctx, cond, rt, rs, cc);
14971 break;
14972 case 0x2:
14973 gen_cmp_ps(ctx, cond, rt, rs, cc);
14974 break;
14975 default:
14976 goto pool32f_invalid;
14977 }
14978 break;
2a24a7ba
YK
14979 case CMP_CONDN_S:
14980 check_insn(ctx, ISA_MIPS32R6);
14981 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14982 break;
14983 case CMP_CONDN_D:
14984 check_insn(ctx, ISA_MIPS32R6);
14985 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14986 break;
3c824109 14987 case POOL32FXF:
d75c135e 14988 gen_pool32fxf(ctx, rt, rs);
3c824109
NF
14989 break;
14990 case 0x00:
14991 /* PLL foo */
14992 switch ((ctx->opcode >> 6) & 0x7) {
14993 case PLL_PS:
14994 mips32_op = OPC_PLL_PS;
14995 goto do_ps;
14996 case PLU_PS:
14997 mips32_op = OPC_PLU_PS;
14998 goto do_ps;
14999 case PUL_PS:
15000 mips32_op = OPC_PUL_PS;
15001 goto do_ps;
15002 case PUU_PS:
15003 mips32_op = OPC_PUU_PS;
15004 goto do_ps;
15005 case CVT_PS_S:
9e8f441a 15006 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15007 mips32_op = OPC_CVT_PS_S;
15008 do_ps:
15009 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15010 break;
15011 default:
15012 goto pool32f_invalid;
15013 }
15014 break;
2a24a7ba
YK
15015 case MIN_FMT:
15016 check_insn(ctx, ISA_MIPS32R6);
15017 switch ((ctx->opcode >> 9) & 0x3) {
15018 case FMT_SDPS_S:
15019 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15020 break;
15021 case FMT_SDPS_D:
15022 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15023 break;
15024 default:
15025 goto pool32f_invalid;
15026 }
15027 break;
3c824109
NF
15028 case 0x08:
15029 /* [LS][WDU]XC1 */
15030 switch ((ctx->opcode >> 6) & 0x7) {
15031 case LWXC1:
9e8f441a 15032 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15033 mips32_op = OPC_LWXC1;
15034 goto do_ldst_cp1;
15035 case SWXC1:
9e8f441a 15036 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15037 mips32_op = OPC_SWXC1;
15038 goto do_ldst_cp1;
15039 case LDXC1:
9e8f441a 15040 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15041 mips32_op = OPC_LDXC1;
15042 goto do_ldst_cp1;
15043 case SDXC1:
9e8f441a 15044 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15045 mips32_op = OPC_SDXC1;
15046 goto do_ldst_cp1;
15047 case LUXC1:
9e8f441a 15048 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15049 mips32_op = OPC_LUXC1;
15050 goto do_ldst_cp1;
15051 case SUXC1:
9e8f441a 15052 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15053 mips32_op = OPC_SUXC1;
15054 do_ldst_cp1:
15055 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15056 break;
15057 default:
15058 goto pool32f_invalid;
15059 }
15060 break;
2a24a7ba
YK
15061 case MAX_FMT:
15062 check_insn(ctx, ISA_MIPS32R6);
15063 switch ((ctx->opcode >> 9) & 0x3) {
15064 case FMT_SDPS_S:
15065 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
15066 break;
15067 case FMT_SDPS_D:
15068 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
15069 break;
15070 default:
15071 goto pool32f_invalid;
15072 }
15073 break;
3c824109
NF
15074 case 0x18:
15075 /* 3D insns */
9e8f441a 15076 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15077 fmt = (ctx->opcode >> 9) & 0x3;
15078 switch ((ctx->opcode >> 6) & 0x7) {
15079 case RSQRT2_FMT:
15080 switch (fmt) {
15081 case FMT_SDPS_S:
15082 mips32_op = OPC_RSQRT2_S;
15083 goto do_3d;
15084 case FMT_SDPS_D:
15085 mips32_op = OPC_RSQRT2_D;
15086 goto do_3d;
15087 case FMT_SDPS_PS:
15088 mips32_op = OPC_RSQRT2_PS;
15089 goto do_3d;
15090 default:
15091 goto pool32f_invalid;
15092 }
15093 break;
15094 case RECIP2_FMT:
15095 switch (fmt) {
15096 case FMT_SDPS_S:
15097 mips32_op = OPC_RECIP2_S;
15098 goto do_3d;
15099 case FMT_SDPS_D:
15100 mips32_op = OPC_RECIP2_D;
15101 goto do_3d;
15102 case FMT_SDPS_PS:
15103 mips32_op = OPC_RECIP2_PS;
15104 goto do_3d;
15105 default:
15106 goto pool32f_invalid;
15107 }
15108 break;
15109 case ADDR_PS:
15110 mips32_op = OPC_ADDR_PS;
15111 goto do_3d;
15112 case MULR_PS:
15113 mips32_op = OPC_MULR_PS;
15114 do_3d:
15115 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15116 break;
15117 default:
15118 goto pool32f_invalid;
15119 }
15120 break;
15121 case 0x20:
2a24a7ba 15122 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
3c824109
NF
15123 cc = (ctx->opcode >> 13) & 0x7;
15124 fmt = (ctx->opcode >> 9) & 0x3;
15125 switch ((ctx->opcode >> 6) & 0x7) {
2a24a7ba
YK
15126 case MOVF_FMT: /* RINT_FMT */
15127 if (ctx->insn_flags & ISA_MIPS32R6) {
15128 /* RINT_FMT */
15129 switch (fmt) {
15130 case FMT_SDPS_S:
15131 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
15132 break;
15133 case FMT_SDPS_D:
15134 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
15135 break;
15136 default:
15137 goto pool32f_invalid;
15138 }
15139 } else {
15140 /* MOVF_FMT */
15141 switch (fmt) {
15142 case FMT_SDPS_S:
15143 gen_movcf_s(ctx, rs, rt, cc, 0);
15144 break;
15145 case FMT_SDPS_D:
15146 gen_movcf_d(ctx, rs, rt, cc, 0);
15147 break;
15148 case FMT_SDPS_PS:
15149 check_ps(ctx);
15150 gen_movcf_ps(ctx, rs, rt, cc, 0);
15151 break;
15152 default:
15153 goto pool32f_invalid;
15154 }
3c824109
NF
15155 }
15156 break;
2a24a7ba
YK
15157 case MOVT_FMT: /* CLASS_FMT */
15158 if (ctx->insn_flags & ISA_MIPS32R6) {
15159 /* CLASS_FMT */
15160 switch (fmt) {
15161 case FMT_SDPS_S:
15162 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
15163 break;
15164 case FMT_SDPS_D:
15165 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
15166 break;
15167 default:
15168 goto pool32f_invalid;
15169 }
15170 } else {
15171 /* MOVT_FMT */
15172 switch (fmt) {
15173 case FMT_SDPS_S:
15174 gen_movcf_s(ctx, rs, rt, cc, 1);
15175 break;
15176 case FMT_SDPS_D:
15177 gen_movcf_d(ctx, rs, rt, cc, 1);
15178 break;
15179 case FMT_SDPS_PS:
15180 check_ps(ctx);
15181 gen_movcf_ps(ctx, rs, rt, cc, 1);
15182 break;
15183 default:
15184 goto pool32f_invalid;
15185 }
3c824109
NF
15186 }
15187 break;
15188 case PREFX:
9e8f441a 15189 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15190 break;
15191 default:
15192 goto pool32f_invalid;
15193 }
15194 break;
15195#define FINSN_3ARG_SDPS(prfx) \
15196 switch ((ctx->opcode >> 8) & 0x3) { \
15197 case FMT_SDPS_S: \
15198 mips32_op = OPC_##prfx##_S; \
15199 goto do_fpop; \
15200 case FMT_SDPS_D: \
15201 mips32_op = OPC_##prfx##_D; \
15202 goto do_fpop; \
15203 case FMT_SDPS_PS: \
e29c9628 15204 check_ps(ctx); \
3c824109
NF
15205 mips32_op = OPC_##prfx##_PS; \
15206 goto do_fpop; \
15207 default: \
15208 goto pool32f_invalid; \
15209 }
2a24a7ba
YK
15210 case MINA_FMT:
15211 check_insn(ctx, ISA_MIPS32R6);
15212 switch ((ctx->opcode >> 9) & 0x3) {
15213 case FMT_SDPS_S:
15214 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
15215 break;
15216 case FMT_SDPS_D:
15217 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
15218 break;
15219 default:
15220 goto pool32f_invalid;
15221 }
15222 break;
15223 case MAXA_FMT:
15224 check_insn(ctx, ISA_MIPS32R6);
15225 switch ((ctx->opcode >> 9) & 0x3) {
15226 case FMT_SDPS_S:
15227 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
15228 break;
15229 case FMT_SDPS_D:
15230 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
15231 break;
15232 default:
15233 goto pool32f_invalid;
15234 }
15235 break;
3c824109
NF
15236 case 0x30:
15237 /* regular FP ops */
15238 switch ((ctx->opcode >> 6) & 0x3) {
15239 case ADD_FMT:
15240 FINSN_3ARG_SDPS(ADD);
15241 break;
15242 case SUB_FMT:
15243 FINSN_3ARG_SDPS(SUB);
15244 break;
15245 case MUL_FMT:
15246 FINSN_3ARG_SDPS(MUL);
15247 break;
15248 case DIV_FMT:
15249 fmt = (ctx->opcode >> 8) & 0x3;
15250 if (fmt == 1) {
15251 mips32_op = OPC_DIV_D;
15252 } else if (fmt == 0) {
15253 mips32_op = OPC_DIV_S;
15254 } else {
15255 goto pool32f_invalid;
15256 }
15257 goto do_fpop;
15258 default:
15259 goto pool32f_invalid;
15260 }
15261 break;
15262 case 0x38:
15263 /* cmovs */
2a24a7ba
YK
15264 switch ((ctx->opcode >> 6) & 0x7) {
15265 case MOVN_FMT: /* SELNEZ_FMT */
15266 if (ctx->insn_flags & ISA_MIPS32R6) {
15267 /* SELNEZ_FMT */
15268 switch ((ctx->opcode >> 9) & 0x3) {
15269 case FMT_SDPS_S:
15270 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
15271 break;
15272 case FMT_SDPS_D:
15273 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
15274 break;
15275 default:
15276 goto pool32f_invalid;
15277 }
15278 } else {
15279 /* MOVN_FMT */
15280 FINSN_3ARG_SDPS(MOVN);
15281 }
15282 break;
15283 case MOVN_FMT_04:
15284 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15285 FINSN_3ARG_SDPS(MOVN);
15286 break;
2a24a7ba
YK
15287 case MOVZ_FMT: /* SELEQZ_FMT */
15288 if (ctx->insn_flags & ISA_MIPS32R6) {
15289 /* SELEQZ_FMT */
15290 switch ((ctx->opcode >> 9) & 0x3) {
15291 case FMT_SDPS_S:
15292 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
15293 break;
15294 case FMT_SDPS_D:
15295 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
15296 break;
15297 default:
15298 goto pool32f_invalid;
15299 }
15300 } else {
15301 /* MOVZ_FMT */
15302 FINSN_3ARG_SDPS(MOVZ);
15303 }
15304 break;
15305 case MOVZ_FMT_05:
15306 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15307 FINSN_3ARG_SDPS(MOVZ);
15308 break;
2a24a7ba
YK
15309 case SEL_FMT:
15310 check_insn(ctx, ISA_MIPS32R6);
15311 switch ((ctx->opcode >> 9) & 0x3) {
15312 case FMT_SDPS_S:
15313 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
15314 break;
15315 case FMT_SDPS_D:
15316 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
15317 break;
15318 default:
15319 goto pool32f_invalid;
15320 }
15321 break;
15322 case MADDF_FMT:
15323 check_insn(ctx, ISA_MIPS32R6);
15324 switch ((ctx->opcode >> 9) & 0x3) {
15325 case FMT_SDPS_S:
15326 mips32_op = OPC_MADDF_S;
15327 goto do_fpop;
15328 case FMT_SDPS_D:
15329 mips32_op = OPC_MADDF_D;
15330 goto do_fpop;
15331 default:
15332 goto pool32f_invalid;
15333 }
15334 break;
15335 case MSUBF_FMT:
15336 check_insn(ctx, ISA_MIPS32R6);
15337 switch ((ctx->opcode >> 9) & 0x3) {
15338 case FMT_SDPS_S:
15339 mips32_op = OPC_MSUBF_S;
15340 goto do_fpop;
15341 case FMT_SDPS_D:
15342 mips32_op = OPC_MSUBF_D;
15343 goto do_fpop;
15344 default:
15345 goto pool32f_invalid;
15346 }
15347 break;
3c824109
NF
15348 default:
15349 goto pool32f_invalid;
15350 }
15351 break;
15352 do_fpop:
15353 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15354 break;
15355 default:
15356 pool32f_invalid:
15357 MIPS_INVAL("pool32f");
9c708c7f 15358 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15359 break;
15360 }
15361 } else {
15362 generate_exception_err(ctx, EXCP_CpU, 1);
15363 }
15364 break;
15365 case POOL32I:
15366 minor = (ctx->opcode >> 21) & 0x1f;
15367 switch (minor) {
15368 case BLTZ:
9e8f441a 15369 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15370 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
15371 break;
3c824109 15372 case BLTZAL:
9e8f441a 15373 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15374 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
15375 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15376 break;
3c824109 15377 case BLTZALS:
9e8f441a 15378 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15379 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
15380 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15381 break;
3c824109 15382 case BGEZ:
9e8f441a 15383 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15384 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
15385 break;
3c824109 15386 case BGEZAL:
9e8f441a 15387 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15388 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
15389 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15390 break;
3c824109 15391 case BGEZALS:
9e8f441a 15392 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15393 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
15394 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15395 break;
3c824109 15396 case BLEZ:
9e8f441a 15397 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15398 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
15399 break;
3c824109 15400 case BGTZ:
9e8f441a 15401 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103 15402 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
3c824109
NF
15403 break;
15404
15405 /* Traps */
65935f07
YK
15406 case TLTI: /* BC1EQZC */
15407 if (ctx->insn_flags & ISA_MIPS32R6) {
15408 /* BC1EQZC */
15409 check_cp1_enabled(ctx);
15410 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
15411 } else {
15412 /* TLTI */
15413 mips32_op = OPC_TLTI;
15414 goto do_trapi;
15415 }
15416 break;
15417 case TGEI: /* BC1NEZC */
15418 if (ctx->insn_flags & ISA_MIPS32R6) {
15419 /* BC1NEZC */
15420 check_cp1_enabled(ctx);
15421 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
15422 } else {
15423 /* TGEI */
15424 mips32_op = OPC_TGEI;
15425 goto do_trapi;
15426 }
15427 break;
3c824109 15428 case TLTIU:
9e8f441a 15429 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15430 mips32_op = OPC_TLTIU;
15431 goto do_trapi;
15432 case TGEIU:
9e8f441a 15433 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15434 mips32_op = OPC_TGEIU;
15435 goto do_trapi;
3b4a5489
YK
15436 case TNEI: /* SYNCI */
15437 if (ctx->insn_flags & ISA_MIPS32R6) {
15438 /* SYNCI */
15439 /* Break the TB to be able to sync copied instructions
15440 immediately */
eeb3bba8 15441 ctx->base.is_jmp = DISAS_STOP;
3b4a5489
YK
15442 } else {
15443 /* TNEI */
15444 mips32_op = OPC_TNEI;
15445 goto do_trapi;
15446 }
15447 break;
3c824109 15448 case TEQI:
9e8f441a 15449 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15450 mips32_op = OPC_TEQI;
15451 do_trapi:
15452 gen_trap(ctx, mips32_op, rs, -1, imm);
15453 break;
15454
15455 case BNEZC:
15456 case BEQZC:
9e8f441a 15457 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15458 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
b231c103 15459 4, rs, 0, imm << 1, 0);
3c824109
NF
15460 /* Compact branches don't have a delay slot, so just let
15461 the normal delay slot handling take us to the branch
15462 target. */
15463 break;
15464 case LUI:
9e8f441a 15465 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5e88759a 15466 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
3c824109
NF
15467 break;
15468 case SYNCI:
9e8f441a 15469 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a83bddd6
DZ
15470 /* Break the TB to be able to sync copied instructions
15471 immediately */
eeb3bba8 15472 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
15473 break;
15474 case BC2F:
15475 case BC2T:
9e8f441a 15476 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15477 /* COP2: Not implemented. */
15478 generate_exception_err(ctx, EXCP_CpU, 2);
15479 break;
15480 case BC1F:
9e8f441a 15481 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15482 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
15483 goto do_cp1branch;
15484 case BC1T:
9e8f441a 15485 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15486 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
15487 goto do_cp1branch;
15488 case BC1ANY4F:
9e8f441a 15489 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15490 mips32_op = OPC_BC1FANY4;
15491 goto do_cp1mips3d;
15492 case BC1ANY4T:
9e8f441a 15493 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15494 mips32_op = OPC_BC1TANY4;
15495 do_cp1mips3d:
15496 check_cop1x(ctx);
d75c135e 15497 check_insn(ctx, ASE_MIPS3D);
3c824109
NF
15498 /* Fall through */
15499 do_cp1branch:
272f458d
MR
15500 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
15501 check_cp1_enabled(ctx);
15502 gen_compute_branch1(ctx, mips32_op,
15503 (ctx->opcode >> 18) & 0x7, imm << 1);
15504 } else {
15505 generate_exception_err(ctx, EXCP_CpU, 1);
15506 }
3c824109
NF
15507 break;
15508 case BPOSGE64:
15509 case BPOSGE32:
15510 /* MIPS DSP: not implemented */
15511 /* Fall through */
15512 default:
15513 MIPS_INVAL("pool32i");
9c708c7f 15514 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15515 break;
15516 }
15517 break;
15518 case POOL32C:
15519 minor = (ctx->opcode >> 12) & 0xf;
3b4a5489
YK
15520 offset = sextract32(ctx->opcode, 0,
15521 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
3c824109
NF
15522 switch (minor) {
15523 case LWL:
9e8f441a 15524 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15525 mips32_op = OPC_LWL;
5c13fdfd 15526 goto do_ld_lr;
3c824109 15527 case SWL:
9e8f441a 15528 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15529 mips32_op = OPC_SWL;
5c13fdfd 15530 goto do_st_lr;
3c824109 15531 case LWR:
9e8f441a 15532 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15533 mips32_op = OPC_LWR;
5c13fdfd 15534 goto do_ld_lr;
3c824109 15535 case SWR:
9e8f441a 15536 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15537 mips32_op = OPC_SWR;
5c13fdfd 15538 goto do_st_lr;
3c824109
NF
15539#if defined(TARGET_MIPS64)
15540 case LDL:
d9224450
MR
15541 check_insn(ctx, ISA_MIPS3);
15542 check_mips_64(ctx);
9e8f441a 15543 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15544 mips32_op = OPC_LDL;
5c13fdfd 15545 goto do_ld_lr;
3c824109 15546 case SDL:
d9224450
MR
15547 check_insn(ctx, ISA_MIPS3);
15548 check_mips_64(ctx);
9e8f441a 15549 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15550 mips32_op = OPC_SDL;
5c13fdfd 15551 goto do_st_lr;
3c824109 15552 case LDR:
d9224450
MR
15553 check_insn(ctx, ISA_MIPS3);
15554 check_mips_64(ctx);
9e8f441a 15555 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15556 mips32_op = OPC_LDR;
5c13fdfd 15557 goto do_ld_lr;
3c824109 15558 case SDR:
d9224450
MR
15559 check_insn(ctx, ISA_MIPS3);
15560 check_mips_64(ctx);
9e8f441a 15561 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15562 mips32_op = OPC_SDR;
5c13fdfd 15563 goto do_st_lr;
3c824109 15564 case LWU:
d9224450
MR
15565 check_insn(ctx, ISA_MIPS3);
15566 check_mips_64(ctx);
3c824109 15567 mips32_op = OPC_LWU;
5c13fdfd 15568 goto do_ld_lr;
3c824109 15569 case LLD:
d9224450
MR
15570 check_insn(ctx, ISA_MIPS3);
15571 check_mips_64(ctx);
3c824109 15572 mips32_op = OPC_LLD;
5c13fdfd 15573 goto do_ld_lr;
3c824109
NF
15574#endif
15575 case LL:
15576 mips32_op = OPC_LL;
5c13fdfd
AJ
15577 goto do_ld_lr;
15578 do_ld_lr:
3b4a5489 15579 gen_ld(ctx, mips32_op, rt, rs, offset);
5c13fdfd
AJ
15580 break;
15581 do_st_lr:
8fffc646 15582 gen_st(ctx, mips32_op, rt, rs, offset);
3c824109
NF
15583 break;
15584 case SC:
3b4a5489 15585 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
3c824109
NF
15586 break;
15587#if defined(TARGET_MIPS64)
15588 case SCD:
d9224450
MR
15589 check_insn(ctx, ISA_MIPS3);
15590 check_mips_64(ctx);
3b4a5489 15591 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
3c824109
NF
15592 break;
15593#endif
8fffc646
JH
15594 case LD_EVA:
15595 if (!ctx->eva) {
15596 MIPS_INVAL("pool32c ld-eva");
15597 generate_exception_end(ctx, EXCP_RI);
15598 break;
15599 }
15600 check_cp0_enabled(ctx);
15601
15602 minor2 = (ctx->opcode >> 9) & 0x7;
15603 offset = sextract32(ctx->opcode, 0, 9);
15604 switch (minor2) {
15605 case LBUE:
15606 mips32_op = OPC_LBUE;
15607 goto do_ld_lr;
15608 case LHUE:
15609 mips32_op = OPC_LHUE;
15610 goto do_ld_lr;
15611 case LWLE:
15612 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15613 mips32_op = OPC_LWLE;
15614 goto do_ld_lr;
15615 case LWRE:
15616 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15617 mips32_op = OPC_LWRE;
15618 goto do_ld_lr;
15619 case LBE:
15620 mips32_op = OPC_LBE;
15621 goto do_ld_lr;
15622 case LHE:
15623 mips32_op = OPC_LHE;
15624 goto do_ld_lr;
15625 case LLE:
15626 mips32_op = OPC_LLE;
15627 goto do_ld_lr;
15628 case LWE:
15629 mips32_op = OPC_LWE;
15630 goto do_ld_lr;
15631 };
15632 break;
15633 case ST_EVA:
15634 if (!ctx->eva) {
15635 MIPS_INVAL("pool32c st-eva");
15636 generate_exception_end(ctx, EXCP_RI);
15637 break;
15638 }
15639 check_cp0_enabled(ctx);
15640
15641 minor2 = (ctx->opcode >> 9) & 0x7;
15642 offset = sextract32(ctx->opcode, 0, 9);
15643 switch (minor2) {
15644 case SWLE:
15645 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15646 mips32_op = OPC_SWLE;
15647 goto do_st_lr;
15648 case SWRE:
15649 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15650 mips32_op = OPC_SWRE;
15651 goto do_st_lr;
15652 case PREFE:
15653 /* Treat as no-op */
15654 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
15655 /* hint codes 24-31 are reserved and signal RI */
15656 generate_exception(ctx, EXCP_RI);
15657 }
15658 break;
15659 case CACHEE:
15660 /* Treat as no-op */
15661 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15662 gen_cache_operation(ctx, rt, rs, offset);
15663 }
15664 break;
15665 case SBE:
15666 mips32_op = OPC_SBE;
15667 goto do_st_lr;
15668 case SHE:
15669 mips32_op = OPC_SHE;
15670 goto do_st_lr;
15671 case SCE:
15672 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
15673 break;
15674 case SWE:
15675 mips32_op = OPC_SWE;
15676 goto do_st_lr;
15677 };
15678 break;
3c824109
NF
15679 case PREF:
15680 /* Treat as no-op */
3b4a5489
YK
15681 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
15682 /* hint codes 24-31 are reserved and signal RI */
15683 generate_exception(ctx, EXCP_RI);
15684 }
3c824109
NF
15685 break;
15686 default:
15687 MIPS_INVAL("pool32c");
9c708c7f 15688 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15689 break;
15690 }
15691 break;
ab39ee45
YK
15692 case ADDI32: /* AUI, LUI */
15693 if (ctx->insn_flags & ISA_MIPS32R6) {
15694 /* AUI, LUI */
15695 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
15696 } else {
15697 /* ADDI32 */
15698 mips32_op = OPC_ADDI;
15699 goto do_addi;
15700 }
15701 break;
3c824109
NF
15702 case ADDIU32:
15703 mips32_op = OPC_ADDIU;
15704 do_addi:
d75c135e 15705 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
15706 break;
15707
15708 /* Logical operations */
15709 case ORI32:
15710 mips32_op = OPC_ORI;
15711 goto do_logici;
15712 case XORI32:
15713 mips32_op = OPC_XORI;
15714 goto do_logici;
15715 case ANDI32:
15716 mips32_op = OPC_ANDI;
15717 do_logici:
d75c135e 15718 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
15719 break;
15720
15721 /* Set less than immediate */
15722 case SLTI32:
15723 mips32_op = OPC_SLTI;
15724 goto do_slti;
15725 case SLTIU32:
15726 mips32_op = OPC_SLTIU;
15727 do_slti:
d75c135e 15728 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
15729 break;
15730 case JALX32:
9e8f441a 15731 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15732 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103
YK
15733 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
15734 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109 15735 break;
65935f07
YK
15736 case JALS32: /* BOVC, BEQC, BEQZALC */
15737 if (ctx->insn_flags & ISA_MIPS32R6) {
15738 if (rs >= rt) {
15739 /* BOVC */
15740 mips32_op = OPC_BOVC;
15741 } else if (rs < rt && rs == 0) {
15742 /* BEQZALC */
15743 mips32_op = OPC_BEQZALC;
15744 } else {
15745 /* BEQC */
15746 mips32_op = OPC_BEQC;
15747 }
15748 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15749 } else {
15750 /* JALS32 */
15751 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
15752 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
15753 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15754 }
3c824109 15755 break;
65935f07
YK
15756 case BEQ32: /* BC */
15757 if (ctx->insn_flags & ISA_MIPS32R6) {
15758 /* BC */
15759 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
15760 sextract32(ctx->opcode << 1, 0, 27));
15761 } else {
15762 /* BEQ32 */
15763 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
15764 }
3c824109 15765 break;
65935f07
YK
15766 case BNE32: /* BALC */
15767 if (ctx->insn_flags & ISA_MIPS32R6) {
15768 /* BALC */
15769 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
15770 sextract32(ctx->opcode << 1, 0, 27));
15771 } else {
15772 /* BNE32 */
15773 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
15774 }
3c824109 15775 break;
65935f07
YK
15776 case J32: /* BGTZC, BLTZC, BLTC */
15777 if (ctx->insn_flags & ISA_MIPS32R6) {
15778 if (rs == 0 && rt != 0) {
15779 /* BGTZC */
15780 mips32_op = OPC_BGTZC;
15781 } else if (rs != 0 && rt != 0 && rs == rt) {
15782 /* BLTZC */
15783 mips32_op = OPC_BLTZC;
15784 } else {
15785 /* BLTC */
15786 mips32_op = OPC_BLTC;
15787 }
15788 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15789 } else {
15790 /* J32 */
15791 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
15792 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15793 }
3c824109 15794 break;
65935f07
YK
15795 case JAL32: /* BLEZC, BGEZC, BGEC */
15796 if (ctx->insn_flags & ISA_MIPS32R6) {
15797 if (rs == 0 && rt != 0) {
15798 /* BLEZC */
15799 mips32_op = OPC_BLEZC;
15800 } else if (rs != 0 && rt != 0 && rs == rt) {
15801 /* BGEZC */
15802 mips32_op = OPC_BGEZC;
15803 } else {
15804 /* BGEC */
15805 mips32_op = OPC_BGEC;
15806 }
15807 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15808 } else {
15809 /* JAL32 */
15810 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
15811 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15812 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15813 }
3c824109
NF
15814 break;
15815 /* Floating point (COP1) */
15816 case LWC132:
15817 mips32_op = OPC_LWC1;
15818 goto do_cop1;
15819 case LDC132:
15820 mips32_op = OPC_LDC1;
15821 goto do_cop1;
15822 case SWC132:
15823 mips32_op = OPC_SWC1;
15824 goto do_cop1;
15825 case SDC132:
15826 mips32_op = OPC_SDC1;
15827 do_cop1:
5ab5c041 15828 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
3c824109 15829 break;
ab39ee45
YK
15830 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15831 if (ctx->insn_flags & ISA_MIPS32R6) {
15832 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15833 switch ((ctx->opcode >> 16) & 0x1f) {
c38a1d52
AR
15834 case ADDIUPC_00:
15835 case ADDIUPC_01:
15836 case ADDIUPC_02:
15837 case ADDIUPC_03:
15838 case ADDIUPC_04:
15839 case ADDIUPC_05:
15840 case ADDIUPC_06:
15841 case ADDIUPC_07:
eeb3bba8 15842 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
15843 break;
15844 case AUIPC:
eeb3bba8 15845 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
ab39ee45
YK
15846 break;
15847 case ALUIPC:
eeb3bba8 15848 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
ab39ee45 15849 break;
c38a1d52
AR
15850 case LWPC_08:
15851 case LWPC_09:
15852 case LWPC_0A:
15853 case LWPC_0B:
15854 case LWPC_0C:
15855 case LWPC_0D:
15856 case LWPC_0E:
15857 case LWPC_0F:
eeb3bba8 15858 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
15859 break;
15860 default:
15861 generate_exception(ctx, EXCP_RI);
15862 break;
15863 }
15864 } else {
15865 /* ADDIUPC */
3c824109 15866 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
e1555d7d 15867 offset = SIMM(ctx->opcode, 0, 23) << 2;
3c824109
NF
15868
15869 gen_addiupc(ctx, reg, offset, 0, 0);
15870 }
15871 break;
65935f07
YK
15872 case BNVC: /* BNEC, BNEZALC */
15873 check_insn(ctx, ISA_MIPS32R6);
15874 if (rs >= rt) {
15875 /* BNVC */
15876 mips32_op = OPC_BNVC;
15877 } else if (rs < rt && rs == 0) {
15878 /* BNEZALC */
15879 mips32_op = OPC_BNEZALC;
15880 } else {
15881 /* BNEC */
15882 mips32_op = OPC_BNEC;
15883 }
15884 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15885 break;
15886 case R6_BNEZC: /* JIALC */
15887 check_insn(ctx, ISA_MIPS32R6);
15888 if (rt != 0) {
15889 /* BNEZC */
15890 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
15891 sextract32(ctx->opcode << 1, 0, 22));
15892 } else {
15893 /* JIALC */
15894 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
15895 }
15896 break;
15897 case R6_BEQZC: /* JIC */
15898 check_insn(ctx, ISA_MIPS32R6);
15899 if (rt != 0) {
15900 /* BEQZC */
15901 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
15902 sextract32(ctx->opcode << 1, 0, 22));
15903 } else {
15904 /* JIC */
15905 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
15906 }
15907 break;
15908 case BLEZALC: /* BGEZALC, BGEUC */
15909 check_insn(ctx, ISA_MIPS32R6);
15910 if (rs == 0 && rt != 0) {
15911 /* BLEZALC */
15912 mips32_op = OPC_BLEZALC;
15913 } else if (rs != 0 && rt != 0 && rs == rt) {
15914 /* BGEZALC */
15915 mips32_op = OPC_BGEZALC;
15916 } else {
15917 /* BGEUC */
15918 mips32_op = OPC_BGEUC;
15919 }
15920 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15921 break;
15922 case BGTZALC: /* BLTZALC, BLTUC */
15923 check_insn(ctx, ISA_MIPS32R6);
15924 if (rs == 0 && rt != 0) {
15925 /* BGTZALC */
15926 mips32_op = OPC_BGTZALC;
15927 } else if (rs != 0 && rt != 0 && rs == rt) {
15928 /* BLTZALC */
15929 mips32_op = OPC_BLTZALC;
15930 } else {
15931 /* BLTUC */
15932 mips32_op = OPC_BLTUC;
15933 }
15934 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15935 break;
3c824109
NF
15936 /* Loads and stores */
15937 case LB32:
15938 mips32_op = OPC_LB;
5c13fdfd 15939 goto do_ld;
3c824109
NF
15940 case LBU32:
15941 mips32_op = OPC_LBU;
5c13fdfd 15942 goto do_ld;
3c824109
NF
15943 case LH32:
15944 mips32_op = OPC_LH;
5c13fdfd 15945 goto do_ld;
3c824109
NF
15946 case LHU32:
15947 mips32_op = OPC_LHU;
5c13fdfd 15948 goto do_ld;
3c824109
NF
15949 case LW32:
15950 mips32_op = OPC_LW;
5c13fdfd 15951 goto do_ld;
3c824109
NF
15952#ifdef TARGET_MIPS64
15953 case LD32:
d9224450
MR
15954 check_insn(ctx, ISA_MIPS3);
15955 check_mips_64(ctx);
3c824109 15956 mips32_op = OPC_LD;
5c13fdfd 15957 goto do_ld;
3c824109 15958 case SD32:
d9224450
MR
15959 check_insn(ctx, ISA_MIPS3);
15960 check_mips_64(ctx);
3c824109 15961 mips32_op = OPC_SD;
5c13fdfd 15962 goto do_st;
3c824109
NF
15963#endif
15964 case SB32:
15965 mips32_op = OPC_SB;
5c13fdfd 15966 goto do_st;
3c824109
NF
15967 case SH32:
15968 mips32_op = OPC_SH;
5c13fdfd 15969 goto do_st;
3c824109
NF
15970 case SW32:
15971 mips32_op = OPC_SW;
5c13fdfd
AJ
15972 goto do_st;
15973 do_ld:
d75c135e 15974 gen_ld(ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
15975 break;
15976 do_st:
15977 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
15978 break;
15979 default:
9c708c7f 15980 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15981 break;
15982 }
15983}
15984
240ce26a 15985static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
15986{
15987 uint32_t op;
15988
15989 /* make sure instructions are on a halfword boundary */
eeb3bba8
EC
15990 if (ctx->base.pc_next & 0x1) {
15991 env->CP0_BadVAddr = ctx->base.pc_next;
9c708c7f 15992 generate_exception_end(ctx, EXCP_AdEL);
3c824109
NF
15993 return 2;
15994 }
15995
15996 op = (ctx->opcode >> 10) & 0x3f;
15997 /* Enforce properly-sized instructions in a delay slot */
b231c103
YK
15998 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
15999 switch (op & 0x7) { /* MSB-3..MSB-5 */
16000 case 0:
16001 /* POOL32A, POOL32B, POOL32I, POOL32C */
16002 case 4:
16003 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16004 case 5:
16005 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16006 case 6:
16007 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16008 case 7:
16009 /* LB32, LH32, LWC132, LDC132, LW32 */
16010 if (ctx->hflags & MIPS_HFLAG_BDS16) {
9c708c7f 16011 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16012 return 2;
16013 }
16014 break;
b231c103
YK
16015 case 1:
16016 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16017 case 2:
16018 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16019 case 3:
16020 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16021 if (ctx->hflags & MIPS_HFLAG_BDS32) {
9c708c7f 16022 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16023 return 2;
16024 }
16025 break;
3c824109
NF
16026 }
16027 }
b231c103 16028
3c824109
NF
16029 switch (op) {
16030 case POOL16A:
16031 {
16032 int rd = mmreg(uMIPS_RD(ctx->opcode));
16033 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16034 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16035 uint32_t opc = 0;
16036
16037 switch (ctx->opcode & 0x1) {
16038 case ADDU16:
16039 opc = OPC_ADDU;
16040 break;
16041 case SUBU16:
16042 opc = OPC_SUBU;
16043 break;
16044 }
ed7ce6c0
YK
16045 if (ctx->insn_flags & ISA_MIPS32R6) {
16046 /* In the Release 6 the register number location in
16047 * the instruction encoding has changed.
16048 */
16049 gen_arith(ctx, opc, rs1, rd, rs2);
16050 } else {
16051 gen_arith(ctx, opc, rd, rs1, rs2);
16052 }
3c824109
NF
16053 }
16054 break;
16055 case POOL16B:
16056 {
16057 int rd = mmreg(uMIPS_RD(ctx->opcode));
16058 int rs = mmreg(uMIPS_RS(ctx->opcode));
16059 int amount = (ctx->opcode >> 1) & 0x7;
16060 uint32_t opc = 0;
16061 amount = amount == 0 ? 8 : amount;
16062
16063 switch (ctx->opcode & 0x1) {
16064 case SLL16:
16065 opc = OPC_SLL;
16066 break;
16067 case SRL16:
16068 opc = OPC_SRL;
16069 break;
16070 }
16071
d75c135e 16072 gen_shift_imm(ctx, opc, rd, rs, amount);
3c824109
NF
16073 }
16074 break;
16075 case POOL16C:
ed7ce6c0
YK
16076 if (ctx->insn_flags & ISA_MIPS32R6) {
16077 gen_pool16c_r6_insn(ctx);
16078 } else {
16079 gen_pool16c_insn(ctx);
16080 }
3c824109
NF
16081 break;
16082 case LWGP16:
16083 {
16084 int rd = mmreg(uMIPS_RD(ctx->opcode));
16085 int rb = 28; /* GP */
16086 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
16087
d75c135e 16088 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
16089 }
16090 break;
16091 case POOL16F:
9e8f441a 16092 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 16093 if (ctx->opcode & 1) {
9c708c7f 16094 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16095 } else {
16096 /* MOVEP */
16097 int enc_dest = uMIPS_RD(ctx->opcode);
16098 int enc_rt = uMIPS_RS2(ctx->opcode);
16099 int enc_rs = uMIPS_RS1(ctx->opcode);
ed7ce6c0 16100 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
3c824109
NF
16101 }
16102 break;
16103 case LBU16:
16104 {
16105 int rd = mmreg(uMIPS_RD(ctx->opcode));
16106 int rb = mmreg(uMIPS_RS(ctx->opcode));
16107 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16108 offset = (offset == 0xf ? -1 : offset);
16109
d75c135e 16110 gen_ld(ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
16111 }
16112 break;
16113 case LHU16:
16114 {
16115 int rd = mmreg(uMIPS_RD(ctx->opcode));
16116 int rb = mmreg(uMIPS_RS(ctx->opcode));
16117 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16118
d75c135e 16119 gen_ld(ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
16120 }
16121 break;
16122 case LWSP16:
16123 {
16124 int rd = (ctx->opcode >> 5) & 0x1f;
16125 int rb = 29; /* SP */
16126 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16127
d75c135e 16128 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
16129 }
16130 break;
16131 case LW16:
16132 {
16133 int rd = mmreg(uMIPS_RD(ctx->opcode));
16134 int rb = mmreg(uMIPS_RS(ctx->opcode));
16135 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16136
d75c135e 16137 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
16138 }
16139 break;
16140 case SB16:
16141 {
16142 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16143 int rb = mmreg(uMIPS_RS(ctx->opcode));
16144 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16145
5c13fdfd 16146 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
16147 }
16148 break;
16149 case SH16:
16150 {
16151 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16152 int rb = mmreg(uMIPS_RS(ctx->opcode));
16153 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16154
5c13fdfd 16155 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
16156 }
16157 break;
16158 case SWSP16:
16159 {
16160 int rd = (ctx->opcode >> 5) & 0x1f;
16161 int rb = 29; /* SP */
16162 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16163
5c13fdfd 16164 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
16165 }
16166 break;
16167 case SW16:
16168 {
16169 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16170 int rb = mmreg(uMIPS_RS(ctx->opcode));
16171 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16172
5c13fdfd 16173 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
16174 }
16175 break;
16176 case MOVE16:
16177 {
16178 int rd = uMIPS_RD5(ctx->opcode);
16179 int rs = uMIPS_RS5(ctx->opcode);
16180
7215d7e7 16181 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
3c824109
NF
16182 }
16183 break;
16184 case ANDI16:
d75c135e 16185 gen_andi16(ctx);
3c824109
NF
16186 break;
16187 case POOL16D:
16188 switch (ctx->opcode & 0x1) {
16189 case ADDIUS5:
d75c135e 16190 gen_addius5(ctx);
3c824109
NF
16191 break;
16192 case ADDIUSP:
d75c135e 16193 gen_addiusp(ctx);
3c824109
NF
16194 break;
16195 }
16196 break;
16197 case POOL16E:
16198 switch (ctx->opcode & 0x1) {
16199 case ADDIUR2:
d75c135e 16200 gen_addiur2(ctx);
3c824109
NF
16201 break;
16202 case ADDIUR1SP:
d75c135e 16203 gen_addiur1sp(ctx);
3c824109
NF
16204 break;
16205 }
16206 break;
65935f07 16207 case B16: /* BC16 */
3c824109 16208 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
65935f07
YK
16209 sextract32(ctx->opcode, 0, 10) << 1,
16210 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
3c824109 16211 break;
65935f07
YK
16212 case BNEZ16: /* BNEZC16 */
16213 case BEQZ16: /* BEQZC16 */
3c824109
NF
16214 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
16215 mmreg(uMIPS_RD(ctx->opcode)),
65935f07
YK
16216 0, sextract32(ctx->opcode, 0, 7) << 1,
16217 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
16218
3c824109
NF
16219 break;
16220 case LI16:
16221 {
16222 int reg = mmreg(uMIPS_RD(ctx->opcode));
16223 int imm = ZIMM(ctx->opcode, 0, 7);
16224
16225 imm = (imm == 0x7f ? -1 : imm);
16226 tcg_gen_movi_tl(cpu_gpr[reg], imm);
16227 }
16228 break;
3c824109 16229 case RES_29:
3c824109 16230 case RES_31:
3c824109 16231 case RES_39:
9c708c7f 16232 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
16233 break;
16234 default:
f60eeb0c 16235 decode_micromips32_opc(env, ctx);
3c824109
NF
16236 return 4;
16237 }
16238
16239 return 2;
16240}
16241
261c95a0
YK
16242/*
16243 *
16244 * nanoMIPS opcodes
16245 *
16246 */
16247
16248/* MAJOR, P16, and P32 pools opcodes */
16249enum {
16250 NM_P_ADDIU = 0x00,
16251 NM_ADDIUPC = 0x01,
16252 NM_MOVE_BALC = 0x02,
16253 NM_P16_MV = 0x04,
16254 NM_LW16 = 0x05,
16255 NM_BC16 = 0x06,
16256 NM_P16_SR = 0x07,
16257
16258 NM_POOL32A = 0x08,
16259 NM_P_BAL = 0x0a,
16260 NM_P16_SHIFT = 0x0c,
16261 NM_LWSP16 = 0x0d,
16262 NM_BALC16 = 0x0e,
16263 NM_P16_4X4 = 0x0f,
16264
16265 NM_P_GP_W = 0x10,
16266 NM_P_GP_BH = 0x11,
16267 NM_P_J = 0x12,
16268 NM_P16C = 0x14,
16269 NM_LWGP16 = 0x15,
16270 NM_P16_LB = 0x17,
16271
16272 NM_P48I = 0x18,
16273 NM_P16_A1 = 0x1c,
16274 NM_LW4X4 = 0x1d,
16275 NM_P16_LH = 0x1f,
16276
16277 NM_P_U12 = 0x20,
16278 NM_P_LS_U12 = 0x21,
16279 NM_P_BR1 = 0x22,
16280 NM_P16_A2 = 0x24,
16281 NM_SW16 = 0x25,
16282 NM_BEQZC16 = 0x26,
16283
16284 NM_POOL32F = 0x28,
16285 NM_P_LS_S9 = 0x29,
16286 NM_P_BR2 = 0x2a,
16287
16288 NM_P16_ADDU = 0x2c,
16289 NM_SWSP16 = 0x2d,
16290 NM_BNEZC16 = 0x2e,
16291 NM_MOVEP = 0x2f,
16292
16293 NM_POOL32S = 0x30,
16294 NM_P_BRI = 0x32,
16295 NM_LI16 = 0x34,
16296 NM_SWGP16 = 0x35,
16297 NM_P16_BR = 0x36,
16298
16299 NM_P_LUI = 0x38,
16300 NM_ANDI16 = 0x3c,
16301 NM_SW4X4 = 0x3d,
16302 NM_MOVEPREV = 0x3f,
16303};
16304
16305/* POOL32A instruction pool */
16306enum {
16307 NM_POOL32A0 = 0x00,
16308 NM_SPECIAL2 = 0x01,
16309 NM_COP2_1 = 0x02,
16310 NM_UDI = 0x03,
16311 NM_POOL32A5 = 0x05,
16312 NM_POOL32A7 = 0x07,
16313};
16314
16315/* P.GP.W instruction pool */
16316enum {
16317 NM_ADDIUGP_W = 0x00,
16318 NM_LWGP = 0x02,
16319 NM_SWGP = 0x03,
16320};
16321
16322/* P48I instruction pool */
16323enum {
16324 NM_LI48 = 0x00,
16325 NM_ADDIU48 = 0x01,
16326 NM_ADDIUGP48 = 0x02,
16327 NM_ADDIUPC48 = 0x03,
16328 NM_LWPC48 = 0x0b,
16329 NM_SWPC48 = 0x0f,
16330};
16331
16332/* P.U12 instruction pool */
16333enum {
16334 NM_ORI = 0x00,
16335 NM_XORI = 0x01,
16336 NM_ANDI = 0x02,
16337 NM_P_SR = 0x03,
16338 NM_SLTI = 0x04,
16339 NM_SLTIU = 0x05,
16340 NM_SEQI = 0x06,
16341 NM_ADDIUNEG = 0x08,
16342 NM_P_SHIFT = 0x0c,
16343 NM_P_ROTX = 0x0d,
16344 NM_P_INS = 0x0e,
16345 NM_P_EXT = 0x0f,
16346};
16347
16348/* POOL32F instruction pool */
16349enum {
16350 NM_POOL32F_0 = 0x00,
16351 NM_POOL32F_3 = 0x03,
16352 NM_POOL32F_5 = 0x05,
16353};
16354
16355/* POOL32S instruction pool */
16356enum {
16357 NM_POOL32S_0 = 0x00,
16358 NM_POOL32S_4 = 0x04,
16359};
16360
16361/* P.LUI instruction pool */
16362enum {
16363 NM_LUI = 0x00,
16364 NM_ALUIPC = 0x01,
16365};
16366
16367/* P.GP.BH instruction pool */
16368enum {
16369 NM_LBGP = 0x00,
16370 NM_SBGP = 0x01,
16371 NM_LBUGP = 0x02,
16372 NM_ADDIUGP_B = 0x03,
16373 NM_P_GP_LH = 0x04,
16374 NM_P_GP_SH = 0x05,
16375 NM_P_GP_CP1 = 0x06,
16376};
16377
16378/* P.LS.U12 instruction pool */
16379enum {
16380 NM_LB = 0x00,
16381 NM_SB = 0x01,
16382 NM_LBU = 0x02,
16383 NM_P_PREFU12 = 0x03,
16384 NM_LH = 0x04,
16385 NM_SH = 0x05,
16386 NM_LHU = 0x06,
16387 NM_LWU = 0x07,
16388 NM_LW = 0x08,
16389 NM_SW = 0x09,
16390 NM_LWC1 = 0x0a,
16391 NM_SWC1 = 0x0b,
16392 NM_LDC1 = 0x0e,
16393 NM_SDC1 = 0x0f,
16394};
16395
16396/* P.LS.S9 instruction pool */
16397enum {
16398 NM_P_LS_S0 = 0x00,
16399 NM_P_LS_S1 = 0x01,
16400 NM_P_LS_E0 = 0x02,
16401 NM_P_LS_WM = 0x04,
16402 NM_P_LS_UAWM = 0x05,
16403};
16404
16405/* P.BAL instruction pool */
16406enum {
16407 NM_BC = 0x00,
16408 NM_BALC = 0x01,
16409};
16410
16411/* P.J instruction pool */
16412enum {
16413 NM_JALRC = 0x00,
16414 NM_JALRC_HB = 0x01,
16415 NM_P_BALRSC = 0x08,
16416};
16417
16418/* P.BR1 instruction pool */
16419enum {
16420 NM_BEQC = 0x00,
16421 NM_P_BR3A = 0x01,
16422 NM_BGEC = 0x02,
16423 NM_BGEUC = 0x03,
16424};
16425
16426/* P.BR2 instruction pool */
16427enum {
16428 NM_BNEC = 0x00,
16429 NM_BLTC = 0x02,
16430 NM_BLTUC = 0x03,
16431};
16432
16433/* P.BRI instruction pool */
16434enum {
16435 NM_BEQIC = 0x00,
16436 NM_BBEQZC = 0x01,
16437 NM_BGEIC = 0x02,
16438 NM_BGEIUC = 0x03,
16439 NM_BNEIC = 0x04,
16440 NM_BBNEZC = 0x05,
16441 NM_BLTIC = 0x06,
16442 NM_BLTIUC = 0x07,
16443};
16444
16445/* P16.SHIFT instruction pool */
16446enum {
16447 NM_SLL16 = 0x00,
16448 NM_SRL16 = 0x01,
16449};
16450
16451/* POOL16C instruction pool */
16452enum {
16453 NM_POOL16C_0 = 0x00,
16454 NM_LWXS16 = 0x01,
16455};
16456
16457/* P16.A1 instruction pool */
16458enum {
16459 NM_ADDIUR1SP = 0x01,
16460};
16461
16462/* P16.A2 instruction pool */
16463enum {
16464 NM_ADDIUR2 = 0x00,
16465 NM_P_ADDIURS5 = 0x01,
16466};
16467
16468/* P16.ADDU instruction pool */
16469enum {
16470 NM_ADDU16 = 0x00,
16471 NM_SUBU16 = 0x01,
16472};
16473
16474/* P16.SR instruction pool */
16475enum {
16476 NM_SAVE16 = 0x00,
16477 NM_RESTORE_JRC16 = 0x01,
16478};
16479
16480/* P16.4X4 instruction pool */
16481enum {
16482 NM_ADDU4X4 = 0x00,
16483 NM_MUL4X4 = 0x01,
16484};
16485
16486/* P16.LB instruction pool */
16487enum {
16488 NM_LB16 = 0x00,
16489 NM_SB16 = 0x01,
16490 NM_LBU16 = 0x02,
16491};
16492
16493/* P16.LH instruction pool */
16494enum {
16495 NM_LH16 = 0x00,
16496 NM_SH16 = 0x01,
16497 NM_LHU16 = 0x02,
16498};
16499
16500/* P.RI instruction pool */
16501enum {
16502 NM_SIGRIE = 0x00,
16503 NM_P_SYSCALL = 0x01,
16504 NM_BREAK = 0x02,
16505 NM_SDBBP = 0x03,
16506};
16507
16508/* POOL32A0 instruction pool */
16509enum {
16510 NM_P_TRAP = 0x00,
16511 NM_SEB = 0x01,
16512 NM_SLLV = 0x02,
16513 NM_MUL = 0x03,
16514 NM_MFC0 = 0x06,
16515 NM_MFHC0 = 0x07,
16516 NM_SEH = 0x09,
16517 NM_SRLV = 0x0a,
16518 NM_MUH = 0x0b,
16519 NM_MTC0 = 0x0e,
16520 NM_MTHC0 = 0x0f,
16521 NM_SRAV = 0x12,
16522 NM_MULU = 0x13,
16523 NM_ROTRV = 0x1a,
16524 NM_MUHU = 0x1b,
16525 NM_ADD = 0x22,
16526 NM_DIV = 0x23,
16527 NM_ADDU = 0x2a,
16528 NM_MOD = 0x2b,
16529 NM_SUB = 0x32,
16530 NM_DIVU = 0x33,
16531 NM_RDHWR = 0x38,
16532 NM_SUBU = 0x3a,
16533 NM_MODU = 0x3b,
16534 NM_P_CMOVE = 0x42,
16535 NM_FORK = 0x45,
16536 NM_MFTR = 0x46,
16537 NM_MFHTR = 0x47,
16538 NM_AND = 0x4a,
16539 NM_YIELD = 0x4d,
16540 NM_MTTR = 0x4e,
16541 NM_MTHTR = 0x4f,
16542 NM_OR = 0x52,
16543 NM_D_E_MT_VPE = 0x56,
16544 NM_NOR = 0x5a,
16545 NM_XOR = 0x62,
16546 NM_SLT = 0x6a,
16547 NM_P_SLTU = 0x72,
16548 NM_SOV = 0x7a,
16549};
16550
b3979b6f
SM
16551/* POOL32A5 instruction pool */
16552enum {
16553 NM_CMP_EQ_PH = 0x00,
16554 NM_CMP_LT_PH = 0x08,
16555 NM_CMP_LE_PH = 0x10,
16556 NM_CMPGU_EQ_QB = 0x18,
16557 NM_CMPGU_LT_QB = 0x20,
16558 NM_CMPGU_LE_QB = 0x28,
16559 NM_CMPGDU_EQ_QB = 0x30,
16560 NM_CMPGDU_LT_QB = 0x38,
16561 NM_CMPGDU_LE_QB = 0x40,
16562 NM_CMPU_EQ_QB = 0x48,
16563 NM_CMPU_LT_QB = 0x50,
16564 NM_CMPU_LE_QB = 0x58,
16565 NM_ADDQ_S_W = 0x60,
16566 NM_SUBQ_S_W = 0x68,
16567 NM_ADDSC = 0x70,
16568 NM_ADDWC = 0x78,
16569
16570 NM_ADDQ_S_PH = 0x01,
16571 NM_ADDQH_R_PH = 0x09,
16572 NM_ADDQH_R_W = 0x11,
16573 NM_ADDU_S_QB = 0x19,
16574 NM_ADDU_S_PH = 0x21,
16575 NM_ADDUH_R_QB = 0x29,
16576 NM_SHRAV_R_PH = 0x31,
16577 NM_SHRAV_R_QB = 0x39,
16578 NM_SUBQ_S_PH = 0x41,
16579 NM_SUBQH_R_PH = 0x49,
16580 NM_SUBQH_R_W = 0x51,
16581 NM_SUBU_S_QB = 0x59,
16582 NM_SUBU_S_PH = 0x61,
16583 NM_SUBUH_R_QB = 0x69,
16584 NM_SHLLV_S_PH = 0x71,
16585 NM_PRECR_SRA_R_PH_W = 0x79,
16586
16587 NM_MULEU_S_PH_QBL = 0x12,
16588 NM_MULEU_S_PH_QBR = 0x1a,
16589 NM_MULQ_RS_PH = 0x22,
16590 NM_MULQ_S_PH = 0x2a,
16591 NM_MULQ_RS_W = 0x32,
16592 NM_MULQ_S_W = 0x3a,
16593 NM_APPEND = 0x42,
16594 NM_MODSUB = 0x52,
16595 NM_SHRAV_R_W = 0x5a,
16596 NM_SHRLV_PH = 0x62,
16597 NM_SHRLV_QB = 0x6a,
16598 NM_SHLLV_QB = 0x72,
16599 NM_SHLLV_S_W = 0x7a,
16600
16601 NM_SHILO = 0x03,
16602
16603 NM_MULEQ_S_W_PHL = 0x04,
16604 NM_MULEQ_S_W_PHR = 0x0c,
16605
16606 NM_MUL_S_PH = 0x05,
16607 NM_PRECR_QB_PH = 0x0d,
16608 NM_PRECRQ_QB_PH = 0x15,
16609 NM_PRECRQ_PH_W = 0x1d,
16610 NM_PRECRQ_RS_PH_W = 0x25,
16611 NM_PRECRQU_S_QB_PH = 0x2d,
16612 NM_PACKRL_PH = 0x35,
16613 NM_PICK_QB = 0x3d,
16614 NM_PICK_PH = 0x45,
16615
16616 NM_SHRA_R_W = 0x5e,
16617 NM_SHRA_R_PH = 0x66,
16618 NM_SHLL_S_PH = 0x76,
16619 NM_SHLL_S_W = 0x7e,
16620
16621 NM_REPL_PH = 0x07
16622};
16623
261c95a0
YK
16624/* POOL32A7 instruction pool */
16625enum {
16626 NM_P_LSX = 0x00,
16627 NM_LSA = 0x01,
16628 NM_EXTW = 0x03,
16629 NM_POOL32AXF = 0x07,
16630};
16631
16632/* P.SR instruction pool */
16633enum {
16634 NM_PP_SR = 0x00,
16635 NM_P_SR_F = 0x01,
16636};
16637
16638/* P.SHIFT instruction pool */
16639enum {
16640 NM_P_SLL = 0x00,
16641 NM_SRL = 0x02,
16642 NM_SRA = 0x04,
16643 NM_ROTR = 0x06,
16644};
16645
16646/* P.ROTX instruction pool */
16647enum {
16648 NM_ROTX = 0x00,
16649};
16650
16651/* P.INS instruction pool */
16652enum {
16653 NM_INS = 0x00,
16654};
16655
16656/* P.EXT instruction pool */
16657enum {
16658 NM_EXT = 0x00,
16659};
16660
16661/* POOL32F_0 (fmt) instruction pool */
16662enum {
16663 NM_RINT_S = 0x04,
16664 NM_RINT_D = 0x44,
16665 NM_ADD_S = 0x06,
16666 NM_SELEQZ_S = 0x07,
16667 NM_SELEQZ_D = 0x47,
16668 NM_CLASS_S = 0x0c,
16669 NM_CLASS_D = 0x4c,
16670 NM_SUB_S = 0x0e,
16671 NM_SELNEZ_S = 0x0f,
16672 NM_SELNEZ_D = 0x4f,
16673 NM_MUL_S = 0x16,
16674 NM_SEL_S = 0x17,
16675 NM_SEL_D = 0x57,
16676 NM_DIV_S = 0x1e,
16677 NM_ADD_D = 0x26,
16678 NM_SUB_D = 0x2e,
16679 NM_MUL_D = 0x36,
16680 NM_MADDF_S = 0x37,
16681 NM_MADDF_D = 0x77,
16682 NM_DIV_D = 0x3e,
16683 NM_MSUBF_S = 0x3f,
16684 NM_MSUBF_D = 0x7f,
16685};
16686
16687/* POOL32F_3 instruction pool */
16688enum {
16689 NM_MIN_FMT = 0x00,
16690 NM_MAX_FMT = 0x01,
16691 NM_MINA_FMT = 0x04,
16692 NM_MAXA_FMT = 0x05,
16693 NM_POOL32FXF = 0x07,
16694};
16695
16696/* POOL32F_5 instruction pool */
16697enum {
16698 NM_CMP_CONDN_S = 0x00,
16699 NM_CMP_CONDN_D = 0x02,
16700};
16701
16702/* P.GP.LH instruction pool */
16703enum {
16704 NM_LHGP = 0x00,
16705 NM_LHUGP = 0x01,
16706};
16707
16708/* P.GP.SH instruction pool */
16709enum {
16710 NM_SHGP = 0x00,
16711};
16712
16713/* P.GP.CP1 instruction pool */
16714enum {
16715 NM_LWC1GP = 0x00,
16716 NM_SWC1GP = 0x01,
16717 NM_LDC1GP = 0x02,
16718 NM_SDC1GP = 0x03,
16719};
16720
16721/* P.LS.S0 instruction pool */
16722enum {
16723 NM_LBS9 = 0x00,
16724 NM_LHS9 = 0x04,
16725 NM_LWS9 = 0x08,
16726 NM_LDS9 = 0x0c,
16727
16728 NM_SBS9 = 0x01,
16729 NM_SHS9 = 0x05,
16730 NM_SWS9 = 0x09,
16731 NM_SDS9 = 0x0d,
16732
16733 NM_LBUS9 = 0x02,
16734 NM_LHUS9 = 0x06,
16735 NM_LWC1S9 = 0x0a,
16736 NM_LDC1S9 = 0x0e,
16737
16738 NM_P_PREFS9 = 0x03,
16739 NM_LWUS9 = 0x07,
16740 NM_SWC1S9 = 0x0b,
16741 NM_SDC1S9 = 0x0f,
16742};
16743
16744/* P.LS.S1 instruction pool */
16745enum {
16746 NM_ASET_ACLR = 0x02,
16747 NM_UALH = 0x04,
16748 NM_UASH = 0x05,
16749 NM_CACHE = 0x07,
16750 NM_P_LL = 0x0a,
16751 NM_P_SC = 0x0b,
16752};
16753
16754/* P.LS.WM instruction pool */
16755enum {
16756 NM_LWM = 0x00,
16757 NM_SWM = 0x01,
16758};
16759
16760/* P.LS.UAWM instruction pool */
16761enum {
16762 NM_UALWM = 0x00,
16763 NM_UASWM = 0x01,
16764};
16765
16766/* P.BR3A instruction pool */
16767enum {
16768 NM_BC1EQZC = 0x00,
16769 NM_BC1NEZC = 0x01,
16770 NM_BC2EQZC = 0x02,
16771 NM_BC2NEZC = 0x03,
16772 NM_BPOSGE32C = 0x04,
16773};
16774
16775/* P16.RI instruction pool */
16776enum {
16777 NM_P16_SYSCALL = 0x01,
16778 NM_BREAK16 = 0x02,
16779 NM_SDBBP16 = 0x03,
16780};
16781
16782/* POOL16C_0 instruction pool */
16783enum {
16784 NM_POOL16C_00 = 0x00,
16785};
16786
16787/* P16.JRC instruction pool */
16788enum {
16789 NM_JRC = 0x00,
16790 NM_JALRC16 = 0x01,
16791};
16792
16793/* P.SYSCALL instruction pool */
16794enum {
16795 NM_SYSCALL = 0x00,
16796 NM_HYPCALL = 0x01,
16797};
16798
16799/* P.TRAP instruction pool */
16800enum {
16801 NM_TEQ = 0x00,
16802 NM_TNE = 0x01,
16803};
16804
16805/* P.CMOVE instruction pool */
16806enum {
16807 NM_MOVZ = 0x00,
16808 NM_MOVN = 0x01,
16809};
16810
16811/* POOL32Axf instruction pool */
16812enum {
b3979b6f
SM
16813 NM_POOL32AXF_1 = 0x01,
16814 NM_POOL32AXF_2 = 0x02,
261c95a0
YK
16815 NM_POOL32AXF_4 = 0x04,
16816 NM_POOL32AXF_5 = 0x05,
b3979b6f
SM
16817 NM_POOL32AXF_7 = 0x07,
16818};
16819
16820/* POOL32Axf_1 instruction pool */
16821enum {
16822 NM_POOL32AXF_1_0 = 0x00,
16823 NM_POOL32AXF_1_1 = 0x01,
16824 NM_POOL32AXF_1_3 = 0x03,
16825 NM_POOL32AXF_1_4 = 0x04,
16826 NM_POOL32AXF_1_5 = 0x05,
16827 NM_POOL32AXF_1_7 = 0x07,
16828};
16829
16830/* POOL32Axf_2 instruction pool */
16831enum {
16832 NM_POOL32AXF_2_0_7 = 0x00,
16833 NM_POOL32AXF_2_8_15 = 0x01,
16834 NM_POOL32AXF_2_16_23 = 0x02,
16835 NM_POOL32AXF_2_24_31 = 0x03,
16836};
16837
16838/* POOL32Axf_7 instruction pool */
16839enum {
16840 NM_SHRA_R_QB = 0x0,
16841 NM_SHRL_PH = 0x1,
16842 NM_REPL_QB = 0x2,
16843};
16844
16845/* POOL32Axf_1_0 instruction pool */
16846enum {
16847 NM_MFHI = 0x0,
16848 NM_MFLO = 0x1,
16849 NM_MTHI = 0x2,
16850 NM_MTLO = 0x3,
16851};
16852
16853/* POOL32Axf_1_1 instruction pool */
16854enum {
16855 NM_MTHLIP = 0x0,
16856 NM_SHILOV = 0x1,
16857};
16858
16859/* POOL32Axf_1_3 instruction pool */
16860enum {
16861 NM_RDDSP = 0x0,
16862 NM_WRDSP = 0x1,
16863 NM_EXTP = 0x2,
16864 NM_EXTPDP = 0x3,
16865};
16866
16867/* POOL32Axf_1_4 instruction pool */
16868enum {
16869 NM_SHLL_QB = 0x0,
16870 NM_SHRL_QB = 0x1,
16871};
16872
16873/* POOL32Axf_1_5 instruction pool */
16874enum {
16875 NM_MAQ_S_W_PHR = 0x0,
16876 NM_MAQ_S_W_PHL = 0x1,
16877 NM_MAQ_SA_W_PHR = 0x2,
16878 NM_MAQ_SA_W_PHL = 0x3,
16879};
16880
16881/* POOL32Axf_1_7 instruction pool */
16882enum {
16883 NM_EXTR_W = 0x0,
16884 NM_EXTR_R_W = 0x1,
16885 NM_EXTR_RS_W = 0x2,
16886 NM_EXTR_S_H = 0x3,
16887};
16888
16889/* POOL32Axf_2_0_7 instruction pool */
16890enum {
16891 NM_DPA_W_PH = 0x0,
16892 NM_DPAQ_S_W_PH = 0x1,
16893 NM_DPS_W_PH = 0x2,
16894 NM_DPSQ_S_W_PH = 0x3,
16895 NM_BALIGN = 0x4,
16896 NM_MADD = 0x5,
16897 NM_MULT = 0x6,
16898 NM_EXTRV_W = 0x7,
16899};
16900
16901/* POOL32Axf_2_8_15 instruction pool */
16902enum {
16903 NM_DPAX_W_PH = 0x0,
16904 NM_DPAQ_SA_L_W = 0x1,
16905 NM_DPSX_W_PH = 0x2,
16906 NM_DPSQ_SA_L_W = 0x3,
16907 NM_MADDU = 0x5,
16908 NM_MULTU = 0x6,
16909 NM_EXTRV_R_W = 0x7,
16910};
16911
16912/* POOL32Axf_2_16_23 instruction pool */
16913enum {
16914 NM_DPAU_H_QBL = 0x0,
16915 NM_DPAQX_S_W_PH = 0x1,
16916 NM_DPSU_H_QBL = 0x2,
16917 NM_DPSQX_S_W_PH = 0x3,
16918 NM_EXTPV = 0x4,
16919 NM_MSUB = 0x5,
16920 NM_MULSA_W_PH = 0x6,
16921 NM_EXTRV_RS_W = 0x7,
16922};
16923
16924/* POOL32Axf_2_24_31 instruction pool */
16925enum {
16926 NM_DPAU_H_QBR = 0x0,
16927 NM_DPAQX_SA_W_PH = 0x1,
16928 NM_DPSU_H_QBR = 0x2,
16929 NM_DPSQX_SA_W_PH = 0x3,
16930 NM_EXTPDPV = 0x4,
16931 NM_MSUBU = 0x5,
16932 NM_MULSAQ_S_W_PH = 0x6,
16933 NM_EXTRV_S_H = 0x7,
261c95a0
YK
16934};
16935
16936/* POOL32Axf_{4, 5} instruction pool */
16937enum {
16938 NM_CLO = 0x25,
16939 NM_CLZ = 0x2d,
16940
16941 NM_TLBP = 0x01,
16942 NM_TLBR = 0x09,
16943 NM_TLBWI = 0x11,
16944 NM_TLBWR = 0x19,
16945 NM_TLBINV = 0x03,
16946 NM_TLBINVF = 0x0b,
16947 NM_DI = 0x23,
16948 NM_EI = 0x2b,
16949 NM_RDPGPR = 0x70,
16950 NM_WRPGPR = 0x78,
16951 NM_WAIT = 0x61,
16952 NM_DERET = 0x71,
16953 NM_ERETX = 0x79,
b3979b6f
SM
16954
16955 /* nanoMIPS DSP instructions */
16956 NM_ABSQ_S_QB = 0x00,
16957 NM_ABSQ_S_PH = 0x08,
16958 NM_ABSQ_S_W = 0x10,
16959 NM_PRECEQ_W_PHL = 0x28,
16960 NM_PRECEQ_W_PHR = 0x30,
16961 NM_PRECEQU_PH_QBL = 0x38,
16962 NM_PRECEQU_PH_QBR = 0x48,
16963 NM_PRECEU_PH_QBL = 0x58,
16964 NM_PRECEU_PH_QBR = 0x68,
16965 NM_PRECEQU_PH_QBLA = 0x39,
16966 NM_PRECEQU_PH_QBRA = 0x49,
16967 NM_PRECEU_PH_QBLA = 0x59,
16968 NM_PRECEU_PH_QBRA = 0x69,
16969 NM_REPLV_PH = 0x01,
16970 NM_REPLV_QB = 0x09,
16971 NM_BITREV = 0x18,
16972 NM_INSV = 0x20,
16973 NM_RADDU_W_QB = 0x78,
16974
16975 NM_BITSWAP = 0x05,
16976 NM_WSBH = 0x3d,
261c95a0
YK
16977};
16978
16979/* PP.SR instruction pool */
16980enum {
16981 NM_SAVE = 0x00,
16982 NM_RESTORE = 0x02,
16983 NM_RESTORE_JRC = 0x03,
16984};
16985
16986/* P.SR.F instruction pool */
16987enum {
16988 NM_SAVEF = 0x00,
16989 NM_RESTOREF = 0x01,
16990};
16991
16992/* P16.SYSCALL instruction pool */
16993enum {
16994 NM_SYSCALL16 = 0x00,
16995 NM_HYPCALL16 = 0x01,
16996};
16997
16998/* POOL16C_00 instruction pool */
16999enum {
17000 NM_NOT16 = 0x00,
17001 NM_XOR16 = 0x01,
17002 NM_AND16 = 0x02,
17003 NM_OR16 = 0x03,
17004};
17005
17006/* PP.LSX and PP.LSXS instruction pool */
17007enum {
17008 NM_LBX = 0x00,
17009 NM_LHX = 0x04,
17010 NM_LWX = 0x08,
17011 NM_LDX = 0x0c,
17012
17013 NM_SBX = 0x01,
17014 NM_SHX = 0x05,
17015 NM_SWX = 0x09,
17016 NM_SDX = 0x0d,
17017
17018 NM_LBUX = 0x02,
17019 NM_LHUX = 0x06,
17020 NM_LWC1X = 0x0a,
17021 NM_LDC1X = 0x0e,
17022
17023 NM_LWUX = 0x07,
17024 NM_SWC1X = 0x0b,
17025 NM_SDC1X = 0x0f,
17026
17027 NM_LHXS = 0x04,
17028 NM_LWXS = 0x08,
17029 NM_LDXS = 0x0c,
17030
17031 NM_SHXS = 0x05,
17032 NM_SWXS = 0x09,
17033 NM_SDXS = 0x0d,
17034
17035 NM_LHUXS = 0x06,
17036 NM_LWC1XS = 0x0a,
17037 NM_LDC1XS = 0x0e,
17038
17039 NM_LWUXS = 0x07,
17040 NM_SWC1XS = 0x0b,
17041 NM_SDC1XS = 0x0f,
17042};
17043
17044/* ERETx instruction pool */
17045enum {
17046 NM_ERET = 0x00,
17047 NM_ERETNC = 0x01,
17048};
17049
17050/* POOL32FxF_{0, 1} insturction pool */
17051enum {
17052 NM_CFC1 = 0x40,
17053 NM_CTC1 = 0x60,
17054 NM_MFC1 = 0x80,
17055 NM_MTC1 = 0xa0,
17056 NM_MFHC1 = 0xc0,
17057 NM_MTHC1 = 0xe0,
17058
17059 NM_CVT_S_PL = 0x84,
17060 NM_CVT_S_PU = 0xa4,
17061
17062 NM_CVT_L_S = 0x004,
17063 NM_CVT_L_D = 0x104,
17064 NM_CVT_W_S = 0x024,
17065 NM_CVT_W_D = 0x124,
17066
17067 NM_RSQRT_S = 0x008,
17068 NM_RSQRT_D = 0x108,
17069
17070 NM_SQRT_S = 0x028,
17071 NM_SQRT_D = 0x128,
17072
17073 NM_RECIP_S = 0x048,
17074 NM_RECIP_D = 0x148,
17075
17076 NM_FLOOR_L_S = 0x00c,
17077 NM_FLOOR_L_D = 0x10c,
17078
17079 NM_FLOOR_W_S = 0x02c,
17080 NM_FLOOR_W_D = 0x12c,
17081
17082 NM_CEIL_L_S = 0x04c,
17083 NM_CEIL_L_D = 0x14c,
17084 NM_CEIL_W_S = 0x06c,
17085 NM_CEIL_W_D = 0x16c,
17086 NM_TRUNC_L_S = 0x08c,
17087 NM_TRUNC_L_D = 0x18c,
17088 NM_TRUNC_W_S = 0x0ac,
17089 NM_TRUNC_W_D = 0x1ac,
17090 NM_ROUND_L_S = 0x0cc,
17091 NM_ROUND_L_D = 0x1cc,
17092 NM_ROUND_W_S = 0x0ec,
17093 NM_ROUND_W_D = 0x1ec,
17094
17095 NM_MOV_S = 0x01,
17096 NM_MOV_D = 0x81,
17097 NM_ABS_S = 0x0d,
17098 NM_ABS_D = 0x8d,
17099 NM_NEG_S = 0x2d,
17100 NM_NEG_D = 0xad,
17101 NM_CVT_D_S = 0x04d,
17102 NM_CVT_D_W = 0x0cd,
17103 NM_CVT_D_L = 0x14d,
17104 NM_CVT_S_D = 0x06d,
17105 NM_CVT_S_W = 0x0ed,
17106 NM_CVT_S_L = 0x16d,
17107};
17108
17109/* P.LL instruction pool */
17110enum {
17111 NM_LL = 0x00,
17112 NM_LLWP = 0x01,
17113};
17114
17115/* P.SC instruction pool */
17116enum {
17117 NM_SC = 0x00,
17118 NM_SCWP = 0x01,
17119};
17120
17121/* P.DVP instruction pool */
17122enum {
17123 NM_DVP = 0x00,
17124 NM_EVP = 0x01,
17125};
17126
c533c0f4
AM
17127
17128/*
17129 *
17130 * nanoMIPS decoding engine
17131 *
17132 */
17133
6bfa9f4c
AM
17134
17135/* extraction utilities */
17136
17137#define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
17138#define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
17139#define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
17140#define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
17141#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17142#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17143
ea4ca3c2
YK
17144/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
17145static inline int decode_gpr_gpr3(int r)
17146{
17147 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
17148
17149 return map[r & 0x7];
17150}
17151
8bdb7029
YK
17152/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
17153static inline int decode_gpr_gpr3_src_store(int r)
17154{
17155 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
17156
17157 return map[r & 0x7];
17158}
17159
ea4ca3c2
YK
17160/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
17161static inline int decode_gpr_gpr4(int r)
17162{
17163 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
17164 16, 17, 18, 19, 20, 21, 22, 23 };
17165
17166 return map[r & 0xf];
17167}
17168
8bdb7029
YK
17169/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
17170static inline int decode_gpr_gpr4_zero(int r)
17171{
17172 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
17173 16, 17, 18, 19, 20, 21, 22, 23 };
17174
17175 return map[r & 0xf];
17176}
17177
6bfa9f4c 17178
80845edf
YK
17179/* extraction utilities */
17180
17181#define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
17182#define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
17183#define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
17184#define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
17185#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17186#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17187
17188
bf0718c5
SM
17189static void gen_adjust_sp(DisasContext *ctx, int u)
17190{
17191 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
17192}
17193
17194static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
17195 uint8_t gp, uint16_t u)
17196{
17197 int counter = 0;
17198 TCGv va = tcg_temp_new();
17199 TCGv t0 = tcg_temp_new();
17200
17201 while (counter != count) {
17202 bool use_gp = gp && (counter == count - 1);
17203 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17204 int this_offset = -((counter + 1) << 2);
17205 gen_base_offset_addr(ctx, va, 29, this_offset);
17206 gen_load_gpr(t0, this_rt);
17207 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
17208 (MO_TEUL | ctx->default_tcg_memop_mask));
17209 counter++;
17210 }
17211
17212 /* adjust stack pointer */
17213 gen_adjust_sp(ctx, -u);
17214
17215 tcg_temp_free(t0);
17216 tcg_temp_free(va);
17217}
17218
17219static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
17220 uint8_t gp, uint16_t u)
17221{
17222 int counter = 0;
17223 TCGv va = tcg_temp_new();
17224 TCGv t0 = tcg_temp_new();
17225
17226 while (counter != count) {
17227 bool use_gp = gp && (counter == count - 1);
17228 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17229 int this_offset = u - ((counter + 1) << 2);
17230 gen_base_offset_addr(ctx, va, 29, this_offset);
17231 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
17232 ctx->default_tcg_memop_mask);
17233 tcg_gen_ext32s_tl(t0, t0);
17234 gen_store_gpr(t0, this_rt);
17235 counter++;
17236 }
17237
17238 /* adjust stack pointer */
17239 gen_adjust_sp(ctx, u);
17240
17241 tcg_temp_free(t0);
17242 tcg_temp_free(va);
17243}
17244
80845edf
YK
17245static void gen_pool16c_nanomips_insn(DisasContext *ctx)
17246{
17247 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
17248 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
17249
17250 switch (extract32(ctx->opcode, 2, 2)) {
17251 case NM_NOT16:
17252 gen_logic(ctx, OPC_NOR, rt, rs, 0);
17253 break;
17254 case NM_AND16:
17255 gen_logic(ctx, OPC_AND, rt, rt, rs);
17256 break;
17257 case NM_XOR16:
17258 gen_logic(ctx, OPC_XOR, rt, rt, rs);
17259 break;
17260 case NM_OR16:
17261 gen_logic(ctx, OPC_OR, rt, rt, rs);
17262 break;
17263 }
17264}
17265
0a1a6ed7 17266static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
e0cf0e65
YK
17267{
17268 int rt = extract32(ctx->opcode, 21, 5);
17269 int rs = extract32(ctx->opcode, 16, 5);
17270 int rd = extract32(ctx->opcode, 11, 5);
17271
17272 switch (extract32(ctx->opcode, 3, 7)) {
17273 case NM_P_TRAP:
17274 switch (extract32(ctx->opcode, 10, 1)) {
17275 case NM_TEQ:
fb32f8c8 17276 check_nms(ctx);
e0cf0e65
YK
17277 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
17278 break;
17279 case NM_TNE:
fb32f8c8 17280 check_nms(ctx);
e0cf0e65
YK
17281 gen_trap(ctx, OPC_TNE, rs, rt, -1);
17282 break;
17283 }
17284 break;
17285 case NM_RDHWR:
fb32f8c8 17286 check_nms(ctx);
e0cf0e65
YK
17287 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
17288 break;
17289 case NM_SEB:
fb32f8c8 17290 check_nms(ctx);
e0cf0e65
YK
17291 gen_bshfl(ctx, OPC_SEB, rs, rt);
17292 break;
17293 case NM_SEH:
17294 gen_bshfl(ctx, OPC_SEH, rs, rt);
17295 break;
17296 case NM_SLLV:
17297 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
17298 break;
17299 case NM_SRLV:
17300 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
17301 break;
17302 case NM_SRAV:
17303 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
17304 break;
17305 case NM_ROTRV:
17306 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
17307 break;
17308 case NM_ADD:
17309 gen_arith(ctx, OPC_ADD, rd, rs, rt);
17310 break;
17311 case NM_ADDU:
17312 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
17313 break;
17314 case NM_SUB:
fb32f8c8 17315 check_nms(ctx);
e0cf0e65
YK
17316 gen_arith(ctx, OPC_SUB, rd, rs, rt);
17317 break;
17318 case NM_SUBU:
17319 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
17320 break;
17321 case NM_P_CMOVE:
17322 switch (extract32(ctx->opcode, 10, 1)) {
17323 case NM_MOVZ:
17324 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
17325 break;
17326 case NM_MOVN:
17327 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
17328 break;
17329 }
17330 break;
17331 case NM_AND:
17332 gen_logic(ctx, OPC_AND, rd, rs, rt);
17333 break;
17334 case NM_OR:
17335 gen_logic(ctx, OPC_OR, rd, rs, rt);
17336 break;
17337 case NM_NOR:
17338 gen_logic(ctx, OPC_NOR, rd, rs, rt);
17339 break;
17340 case NM_XOR:
17341 gen_logic(ctx, OPC_XOR, rd, rs, rt);
17342 break;
17343 case NM_SLT:
17344 gen_slt(ctx, OPC_SLT, rd, rs, rt);
17345 break;
17346 case NM_P_SLTU:
17347 if (rd == 0) {
17348 /* P_DVP */
17349#ifndef CONFIG_USER_ONLY
17350 TCGv t0 = tcg_temp_new();
17351 switch (extract32(ctx->opcode, 10, 1)) {
17352 case NM_DVP:
17353 if (ctx->vp) {
17354 check_cp0_enabled(ctx);
17355 gen_helper_dvp(t0, cpu_env);
17356 gen_store_gpr(t0, rt);
17357 }
17358 break;
17359 case NM_EVP:
17360 if (ctx->vp) {
17361 check_cp0_enabled(ctx);
17362 gen_helper_evp(t0, cpu_env);
17363 gen_store_gpr(t0, rt);
17364 }
17365 break;
17366 }
17367 tcg_temp_free(t0);
17368#endif
17369 } else {
17370 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
17371 }
17372 break;
17373 case NM_SOV:
17374 {
17375 TCGv t0 = tcg_temp_new();
17376 TCGv t1 = tcg_temp_new();
17377 TCGv t2 = tcg_temp_new();
17378
17379 gen_load_gpr(t1, rs);
17380 gen_load_gpr(t2, rt);
17381 tcg_gen_add_tl(t0, t1, t2);
17382 tcg_gen_ext32s_tl(t0, t0);
17383 tcg_gen_xor_tl(t1, t1, t2);
17384 tcg_gen_xor_tl(t2, t0, t2);
17385 tcg_gen_andc_tl(t1, t2, t1);
17386
17387 /* operands of same sign, result different sign */
17388 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
17389 gen_store_gpr(t0, rd);
17390
17391 tcg_temp_free(t0);
17392 tcg_temp_free(t1);
17393 tcg_temp_free(t2);
17394 }
17395 break;
17396 case NM_MUL:
17397 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
17398 break;
17399 case NM_MUH:
17400 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
17401 break;
17402 case NM_MULU:
17403 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
17404 break;
17405 case NM_MUHU:
17406 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
17407 break;
17408 case NM_DIV:
17409 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
17410 break;
17411 case NM_MOD:
17412 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
17413 break;
17414 case NM_DIVU:
17415 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
17416 break;
17417 case NM_MODU:
17418 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
17419 break;
17420#ifndef CONFIG_USER_ONLY
17421 case NM_MFC0:
17422 check_cp0_enabled(ctx);
17423 if (rt == 0) {
17424 /* Treat as NOP. */
17425 break;
17426 }
17427 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
17428 break;
17429 case NM_MTC0:
17430 check_cp0_enabled(ctx);
17431 {
17432 TCGv t0 = tcg_temp_new();
17433
17434 gen_load_gpr(t0, rt);
17435 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
17436 tcg_temp_free(t0);
17437 }
17438 break;
0a1a6ed7
SM
17439 case NM_D_E_MT_VPE:
17440 {
17441 uint8_t sc = extract32(ctx->opcode, 10, 1);
17442 TCGv t0 = tcg_temp_new();
17443
17444 switch (sc) {
17445 case 0:
17446 if (rs == 1) {
17447 /* DMT */
17448 check_cp0_mt(ctx);
17449 gen_helper_dmt(t0);
17450 gen_store_gpr(t0, rt);
17451 } else if (rs == 0) {
17452 /* DVPE */
17453 check_cp0_mt(ctx);
17454 gen_helper_dvpe(t0, cpu_env);
17455 gen_store_gpr(t0, rt);
17456 } else {
17457 generate_exception_end(ctx, EXCP_RI);
17458 }
17459 break;
17460 case 1:
17461 if (rs == 1) {
17462 /* EMT */
17463 check_cp0_mt(ctx);
17464 gen_helper_emt(t0);
17465 gen_store_gpr(t0, rt);
17466 } else if (rs == 0) {
17467 /* EVPE */
17468 check_cp0_mt(ctx);
17469 gen_helper_evpe(t0, cpu_env);
17470 gen_store_gpr(t0, rt);
17471 } else {
17472 generate_exception_end(ctx, EXCP_RI);
17473 }
17474 break;
17475 }
17476
17477 tcg_temp_free(t0);
17478 }
17479 break;
17480 case NM_FORK:
17481 check_mt(ctx);
17482 {
17483 TCGv t0 = tcg_temp_new();
17484 TCGv t1 = tcg_temp_new();
17485
17486 gen_load_gpr(t0, rt);
17487 gen_load_gpr(t1, rs);
17488 gen_helper_fork(t0, t1);
17489 tcg_temp_free(t0);
17490 tcg_temp_free(t1);
17491 }
17492 break;
17493 case NM_MFTR:
17494 case NM_MFHTR:
17495 check_cp0_enabled(ctx);
17496 if (rd == 0) {
17497 /* Treat as NOP. */
17498 return;
17499 }
17500 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
17501 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
17502 break;
17503 case NM_MTTR:
17504 case NM_MTHTR:
17505 check_cp0_enabled(ctx);
17506 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
17507 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
17508 break;
17509 case NM_YIELD:
17510 check_mt(ctx);
17511 {
17512 TCGv t0 = tcg_temp_new();
17513
17514 gen_load_gpr(t0, rs);
17515 gen_helper_yield(t0, cpu_env, t0);
17516 gen_store_gpr(t0, rt);
17517 tcg_temp_free(t0);
17518 }
17519 break;
e0cf0e65
YK
17520#endif
17521 default:
17522 generate_exception_end(ctx, EXCP_RI);
17523 break;
17524 }
17525}
17526
2ed42efa
SM
17527/* dsp */
17528static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
17529 int ret, int v1, int v2)
17530{
17531 TCGv_i32 t0;
17532 TCGv v0_t;
17533 TCGv v1_t;
17534
17535 t0 = tcg_temp_new_i32();
17536
17537 v0_t = tcg_temp_new();
17538 v1_t = tcg_temp_new();
17539
17540 tcg_gen_movi_i32(t0, v2 >> 3);
17541
17542 gen_load_gpr(v0_t, ret);
17543 gen_load_gpr(v1_t, v1);
17544
17545 switch (opc) {
17546 case NM_MAQ_S_W_PHR:
17547 check_dsp(ctx);
17548 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
17549 break;
17550 case NM_MAQ_S_W_PHL:
17551 check_dsp(ctx);
17552 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
17553 break;
17554 case NM_MAQ_SA_W_PHR:
17555 check_dsp(ctx);
17556 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
17557 break;
17558 case NM_MAQ_SA_W_PHL:
17559 check_dsp(ctx);
17560 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
17561 break;
17562 default:
17563 generate_exception_end(ctx, EXCP_RI);
17564 break;
17565 }
17566
17567 tcg_temp_free_i32(t0);
17568
17569 tcg_temp_free(v0_t);
17570 tcg_temp_free(v1_t);
17571}
17572
17573
17574static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
17575 int ret, int v1, int v2)
17576{
17577 int16_t imm;
17578 TCGv t0 = tcg_temp_new();
17579 TCGv t1 = tcg_temp_new();
17580 TCGv v0_t = tcg_temp_new();
17581
17582 gen_load_gpr(v0_t, v1);
17583
17584 switch (opc) {
17585 case NM_POOL32AXF_1_0:
17586 check_dsp(ctx);
17587 switch (extract32(ctx->opcode, 12, 2)) {
17588 case NM_MFHI:
17589 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
17590 break;
17591 case NM_MFLO:
17592 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
17593 break;
17594 case NM_MTHI:
17595 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
17596 break;
17597 case NM_MTLO:
17598 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
17599 break;
17600 }
17601 break;
17602 case NM_POOL32AXF_1_1:
17603 check_dsp(ctx);
17604 switch (extract32(ctx->opcode, 12, 2)) {
17605 case NM_MTHLIP:
17606 tcg_gen_movi_tl(t0, v2);
17607 gen_helper_mthlip(t0, v0_t, cpu_env);
17608 break;
17609 case NM_SHILOV:
17610 tcg_gen_movi_tl(t0, v2 >> 3);
17611 gen_helper_shilo(t0, v0_t, cpu_env);
17612 break;
17613 default:
17614 generate_exception_end(ctx, EXCP_RI);
17615 break;
17616 }
17617 break;
17618 case NM_POOL32AXF_1_3:
17619 check_dsp(ctx);
17620 imm = extract32(ctx->opcode, 14, 7);
17621 switch (extract32(ctx->opcode, 12, 2)) {
17622 case NM_RDDSP:
17623 tcg_gen_movi_tl(t0, imm);
17624 gen_helper_rddsp(t0, t0, cpu_env);
17625 gen_store_gpr(t0, ret);
17626 break;
17627 case NM_WRDSP:
17628 gen_load_gpr(t0, ret);
17629 tcg_gen_movi_tl(t1, imm);
17630 gen_helper_wrdsp(t0, t1, cpu_env);
17631 break;
17632 case NM_EXTP:
17633 tcg_gen_movi_tl(t0, v2 >> 3);
17634 tcg_gen_movi_tl(t1, v1);
17635 gen_helper_extp(t0, t0, t1, cpu_env);
17636 gen_store_gpr(t0, ret);
17637 break;
17638 case NM_EXTPDP:
17639 tcg_gen_movi_tl(t0, v2 >> 3);
17640 tcg_gen_movi_tl(t1, v1);
17641 gen_helper_extpdp(t0, t0, t1, cpu_env);
17642 gen_store_gpr(t0, ret);
17643 break;
17644 }
17645 break;
17646 case NM_POOL32AXF_1_4:
17647 check_dsp(ctx);
17648 tcg_gen_movi_tl(t0, v2 >> 2);
17649 switch (extract32(ctx->opcode, 12, 1)) {
17650 case NM_SHLL_QB:
17651 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
17652 gen_store_gpr(t0, ret);
17653 break;
17654 case NM_SHRL_QB:
17655 gen_helper_shrl_qb(t0, t0, v0_t);
17656 gen_store_gpr(t0, ret);
17657 break;
17658 }
17659 break;
17660 case NM_POOL32AXF_1_5:
17661 opc = extract32(ctx->opcode, 12, 2);
17662 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
17663 break;
17664 case NM_POOL32AXF_1_7:
17665 check_dsp(ctx);
17666 tcg_gen_movi_tl(t0, v2 >> 3);
17667 tcg_gen_movi_tl(t1, v1);
17668 switch (extract32(ctx->opcode, 12, 2)) {
17669 case NM_EXTR_W:
17670 gen_helper_extr_w(t0, t0, t1, cpu_env);
17671 gen_store_gpr(t0, ret);
17672 break;
17673 case NM_EXTR_R_W:
17674 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
17675 gen_store_gpr(t0, ret);
17676 break;
17677 case NM_EXTR_RS_W:
17678 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
17679 gen_store_gpr(t0, ret);
17680 break;
17681 case NM_EXTR_S_H:
17682 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
17683 gen_store_gpr(t0, ret);
17684 break;
17685 }
17686 break;
17687 default:
17688 generate_exception_end(ctx, EXCP_RI);
17689 break;
17690 }
17691
17692 tcg_temp_free(t0);
17693 tcg_temp_free(t1);
17694 tcg_temp_free(v0_t);
17695}
17696
8b3698b2
SM
17697static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
17698 TCGv v0, TCGv v1, int rd)
17699{
17700 TCGv_i32 t0;
17701
17702 t0 = tcg_temp_new_i32();
17703
17704 tcg_gen_movi_i32(t0, rd >> 3);
17705
17706 switch (opc) {
17707 case NM_POOL32AXF_2_0_7:
17708 switch (extract32(ctx->opcode, 9, 3)) {
17709 case NM_DPA_W_PH:
17710 check_dspr2(ctx);
17711 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
17712 break;
17713 case NM_DPAQ_S_W_PH:
17714 check_dsp(ctx);
17715 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
17716 break;
17717 case NM_DPS_W_PH:
17718 check_dspr2(ctx);
17719 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
17720 break;
17721 case NM_DPSQ_S_W_PH:
17722 check_dsp(ctx);
17723 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
17724 break;
17725 default:
17726 generate_exception_end(ctx, EXCP_RI);
17727 break;
17728 }
17729 break;
17730 case NM_POOL32AXF_2_8_15:
17731 switch (extract32(ctx->opcode, 9, 3)) {
17732 case NM_DPAX_W_PH:
17733 check_dspr2(ctx);
17734 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
17735 break;
17736 case NM_DPAQ_SA_L_W:
17737 check_dsp(ctx);
17738 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
17739 break;
17740 case NM_DPSX_W_PH:
17741 check_dspr2(ctx);
17742 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
17743 break;
17744 case NM_DPSQ_SA_L_W:
17745 check_dsp(ctx);
17746 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
17747 break;
17748 default:
17749 generate_exception_end(ctx, EXCP_RI);
17750 break;
17751 }
17752 break;
17753 case NM_POOL32AXF_2_16_23:
17754 switch (extract32(ctx->opcode, 9, 3)) {
17755 case NM_DPAU_H_QBL:
17756 check_dsp(ctx);
17757 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
17758 break;
17759 case NM_DPAQX_S_W_PH:
17760 check_dspr2(ctx);
17761 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
17762 break;
17763 case NM_DPSU_H_QBL:
17764 check_dsp(ctx);
17765 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
17766 break;
17767 case NM_DPSQX_S_W_PH:
17768 check_dspr2(ctx);
17769 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
17770 break;
17771 case NM_MULSA_W_PH:
17772 check_dspr2(ctx);
17773 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
17774 break;
17775 default:
17776 generate_exception_end(ctx, EXCP_RI);
17777 break;
17778 }
17779 break;
17780 case NM_POOL32AXF_2_24_31:
17781 switch (extract32(ctx->opcode, 9, 3)) {
17782 case NM_DPAU_H_QBR:
17783 check_dsp(ctx);
17784 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
17785 break;
17786 case NM_DPAQX_SA_W_PH:
17787 check_dspr2(ctx);
17788 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
17789 break;
17790 case NM_DPSU_H_QBR:
17791 check_dsp(ctx);
17792 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
17793 break;
17794 case NM_DPSQX_SA_W_PH:
17795 check_dspr2(ctx);
17796 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
17797 break;
17798 case NM_MULSAQ_S_W_PH:
17799 check_dsp(ctx);
17800 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
17801 break;
17802 default:
17803 generate_exception_end(ctx, EXCP_RI);
17804 break;
17805 }
17806 break;
17807 default:
17808 generate_exception_end(ctx, EXCP_RI);
17809 break;
17810 }
17811
17812 tcg_temp_free_i32(t0);
17813}
17814
17815static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
17816 int rt, int rs, int rd)
17817{
17818 int ret = rt;
17819 TCGv t0 = tcg_temp_new();
17820 TCGv t1 = tcg_temp_new();
17821 TCGv v0_t = tcg_temp_new();
17822 TCGv v1_t = tcg_temp_new();
17823
17824 gen_load_gpr(v0_t, rt);
17825 gen_load_gpr(v1_t, rs);
17826
17827 switch (opc) {
17828 case NM_POOL32AXF_2_0_7:
17829 switch (extract32(ctx->opcode, 9, 3)) {
17830 case NM_DPA_W_PH:
17831 case NM_DPAQ_S_W_PH:
17832 case NM_DPS_W_PH:
17833 case NM_DPSQ_S_W_PH:
17834 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
17835 break;
17836 case NM_BALIGN:
17837 check_dspr2(ctx);
17838 if (rt != 0) {
17839 gen_load_gpr(t0, rs);
17840 rd &= 3;
17841 if (rd != 0 && rd != 2) {
17842 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
17843 tcg_gen_ext32u_tl(t0, t0);
17844 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
17845 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
17846 }
17847 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
17848 }
17849 break;
17850 case NM_MADD:
17851 check_dsp(ctx);
17852 {
17853 int acc = extract32(ctx->opcode, 14, 2);
17854 TCGv_i64 t2 = tcg_temp_new_i64();
17855 TCGv_i64 t3 = tcg_temp_new_i64();
17856
17857 gen_load_gpr(t0, rt);
17858 gen_load_gpr(t1, rs);
17859 tcg_gen_ext_tl_i64(t2, t0);
17860 tcg_gen_ext_tl_i64(t3, t1);
17861 tcg_gen_mul_i64(t2, t2, t3);
17862 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
17863 tcg_gen_add_i64(t2, t2, t3);
17864 tcg_temp_free_i64(t3);
17865 gen_move_low32(cpu_LO[acc], t2);
17866 gen_move_high32(cpu_HI[acc], t2);
17867 tcg_temp_free_i64(t2);
17868 }
17869 break;
17870 case NM_MULT:
17871 check_dsp(ctx);
17872 {
17873 int acc = extract32(ctx->opcode, 14, 2);
17874 TCGv_i32 t2 = tcg_temp_new_i32();
17875 TCGv_i32 t3 = tcg_temp_new_i32();
17876
17877 gen_load_gpr(t0, rs);
17878 gen_load_gpr(t1, rt);
17879 tcg_gen_trunc_tl_i32(t2, t0);
17880 tcg_gen_trunc_tl_i32(t3, t1);
17881 tcg_gen_muls2_i32(t2, t3, t2, t3);
17882 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
17883 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
17884 tcg_temp_free_i32(t2);
17885 tcg_temp_free_i32(t3);
17886 }
17887 break;
17888 case NM_EXTRV_W:
17889 check_dsp(ctx);
17890 gen_load_gpr(v1_t, rs);
17891 tcg_gen_movi_tl(t0, rd >> 3);
17892 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
17893 gen_store_gpr(t0, ret);
17894 break;
17895 }
17896 break;
17897 case NM_POOL32AXF_2_8_15:
17898 switch (extract32(ctx->opcode, 9, 3)) {
17899 case NM_DPAX_W_PH:
17900 case NM_DPAQ_SA_L_W:
17901 case NM_DPSX_W_PH:
17902 case NM_DPSQ_SA_L_W:
17903 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
17904 break;
17905 case NM_MADDU:
17906 check_dsp(ctx);
17907 {
17908 int acc = extract32(ctx->opcode, 14, 2);
17909 TCGv_i64 t2 = tcg_temp_new_i64();
17910 TCGv_i64 t3 = tcg_temp_new_i64();
17911
17912 gen_load_gpr(t0, rs);
17913 gen_load_gpr(t1, rt);
17914 tcg_gen_ext32u_tl(t0, t0);
17915 tcg_gen_ext32u_tl(t1, t1);
17916 tcg_gen_extu_tl_i64(t2, t0);
17917 tcg_gen_extu_tl_i64(t3, t1);
17918 tcg_gen_mul_i64(t2, t2, t3);
17919 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
17920 tcg_gen_add_i64(t2, t2, t3);
17921 tcg_temp_free_i64(t3);
17922 gen_move_low32(cpu_LO[acc], t2);
17923 gen_move_high32(cpu_HI[acc], t2);
17924 tcg_temp_free_i64(t2);
17925 }
17926 break;
17927 case NM_MULTU:
17928 check_dsp(ctx);
17929 {
17930 int acc = extract32(ctx->opcode, 14, 2);
17931 TCGv_i32 t2 = tcg_temp_new_i32();
17932 TCGv_i32 t3 = tcg_temp_new_i32();
17933
17934 gen_load_gpr(t0, rs);
17935 gen_load_gpr(t1, rt);
17936 tcg_gen_trunc_tl_i32(t2, t0);
17937 tcg_gen_trunc_tl_i32(t3, t1);
17938 tcg_gen_mulu2_i32(t2, t3, t2, t3);
17939 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
17940 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
17941 tcg_temp_free_i32(t2);
17942 tcg_temp_free_i32(t3);
17943 }
17944 break;
17945 case NM_EXTRV_R_W:
17946 check_dsp(ctx);
17947 tcg_gen_movi_tl(t0, rd >> 3);
17948 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
17949 gen_store_gpr(t0, ret);
17950 break;
17951 default:
17952 generate_exception_end(ctx, EXCP_RI);
17953 break;
17954 }
17955 break;
17956 case NM_POOL32AXF_2_16_23:
17957 switch (extract32(ctx->opcode, 9, 3)) {
17958 case NM_DPAU_H_QBL:
17959 case NM_DPAQX_S_W_PH:
17960 case NM_DPSU_H_QBL:
17961 case NM_DPSQX_S_W_PH:
17962 case NM_MULSA_W_PH:
17963 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
17964 break;
17965 case NM_EXTPV:
17966 check_dsp(ctx);
17967 tcg_gen_movi_tl(t0, rd >> 3);
17968 gen_helper_extp(t0, t0, v1_t, cpu_env);
17969 gen_store_gpr(t0, ret);
17970 break;
17971 case NM_MSUB:
17972 check_dsp(ctx);
17973 {
17974 int acc = extract32(ctx->opcode, 14, 2);
17975 TCGv_i64 t2 = tcg_temp_new_i64();
17976 TCGv_i64 t3 = tcg_temp_new_i64();
17977
17978 gen_load_gpr(t0, rs);
17979 gen_load_gpr(t1, rt);
17980 tcg_gen_ext_tl_i64(t2, t0);
17981 tcg_gen_ext_tl_i64(t3, t1);
17982 tcg_gen_mul_i64(t2, t2, t3);
17983 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
17984 tcg_gen_sub_i64(t2, t3, t2);
17985 tcg_temp_free_i64(t3);
17986 gen_move_low32(cpu_LO[acc], t2);
17987 gen_move_high32(cpu_HI[acc], t2);
17988 tcg_temp_free_i64(t2);
17989 }
17990 break;
17991 case NM_EXTRV_RS_W:
17992 check_dsp(ctx);
17993 tcg_gen_movi_tl(t0, rd >> 3);
17994 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
17995 gen_store_gpr(t0, ret);
17996 break;
17997 }
17998 break;
17999 case NM_POOL32AXF_2_24_31:
18000 switch (extract32(ctx->opcode, 9, 3)) {
18001 case NM_DPAU_H_QBR:
18002 case NM_DPAQX_SA_W_PH:
18003 case NM_DPSU_H_QBR:
18004 case NM_DPSQX_SA_W_PH:
18005 case NM_MULSAQ_S_W_PH:
18006 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18007 break;
18008 case NM_EXTPDPV:
18009 check_dsp(ctx);
18010 tcg_gen_movi_tl(t0, rd >> 3);
18011 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18012 gen_store_gpr(t0, ret);
18013 break;
18014 case NM_MSUBU:
18015 check_dsp(ctx);
18016 {
18017 int acc = extract32(ctx->opcode, 14, 2);
18018 TCGv_i64 t2 = tcg_temp_new_i64();
18019 TCGv_i64 t3 = tcg_temp_new_i64();
18020
18021 gen_load_gpr(t0, rs);
18022 gen_load_gpr(t1, rt);
18023 tcg_gen_ext32u_tl(t0, t0);
18024 tcg_gen_ext32u_tl(t1, t1);
18025 tcg_gen_extu_tl_i64(t2, t0);
18026 tcg_gen_extu_tl_i64(t3, t1);
18027 tcg_gen_mul_i64(t2, t2, t3);
18028 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18029 tcg_gen_sub_i64(t2, t3, t2);
18030 tcg_temp_free_i64(t3);
18031 gen_move_low32(cpu_LO[acc], t2);
18032 gen_move_high32(cpu_HI[acc], t2);
18033 tcg_temp_free_i64(t2);
18034 }
18035 break;
18036 case NM_EXTRV_S_H:
18037 check_dsp(ctx);
18038 tcg_gen_movi_tl(t0, rd >> 3);
18039 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
18040 gen_store_gpr(t0, ret);
18041 break;
18042 }
18043 break;
18044 default:
18045 generate_exception_end(ctx, EXCP_RI);
18046 break;
18047 }
18048
18049 tcg_temp_free(t0);
18050 tcg_temp_free(t1);
18051
18052 tcg_temp_free(v0_t);
18053 tcg_temp_free(v1_t);
18054}
18055
4c75c985
SM
18056static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
18057 int rt, int rs)
18058{
18059 int ret = rt;
18060 TCGv t0 = tcg_temp_new();
18061 TCGv v0_t = tcg_temp_new();
18062
18063 gen_load_gpr(v0_t, rs);
18064
18065 switch (opc) {
18066 case NM_ABSQ_S_QB:
18067 check_dspr2(ctx);
18068 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
18069 gen_store_gpr(v0_t, ret);
18070 break;
18071 case NM_ABSQ_S_PH:
18072 check_dsp(ctx);
18073 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
18074 gen_store_gpr(v0_t, ret);
18075 break;
18076 case NM_ABSQ_S_W:
18077 check_dsp(ctx);
18078 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
18079 gen_store_gpr(v0_t, ret);
18080 break;
18081 case NM_PRECEQ_W_PHL:
18082 check_dsp(ctx);
18083 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
18084 tcg_gen_ext32s_tl(v0_t, v0_t);
18085 gen_store_gpr(v0_t, ret);
18086 break;
18087 case NM_PRECEQ_W_PHR:
18088 check_dsp(ctx);
18089 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
18090 tcg_gen_shli_tl(v0_t, v0_t, 16);
18091 tcg_gen_ext32s_tl(v0_t, v0_t);
18092 gen_store_gpr(v0_t, ret);
18093 break;
18094 case NM_PRECEQU_PH_QBL:
18095 check_dsp(ctx);
18096 gen_helper_precequ_ph_qbl(v0_t, v0_t);
18097 gen_store_gpr(v0_t, ret);
18098 break;
18099 case NM_PRECEQU_PH_QBR:
18100 check_dsp(ctx);
18101 gen_helper_precequ_ph_qbr(v0_t, v0_t);
18102 gen_store_gpr(v0_t, ret);
18103 break;
18104 case NM_PRECEQU_PH_QBLA:
18105 check_dsp(ctx);
18106 gen_helper_precequ_ph_qbla(v0_t, v0_t);
18107 gen_store_gpr(v0_t, ret);
18108 break;
18109 case NM_PRECEQU_PH_QBRA:
18110 check_dsp(ctx);
18111 gen_helper_precequ_ph_qbra(v0_t, v0_t);
18112 gen_store_gpr(v0_t, ret);
18113 break;
18114 case NM_PRECEU_PH_QBL:
18115 check_dsp(ctx);
18116 gen_helper_preceu_ph_qbl(v0_t, v0_t);
18117 gen_store_gpr(v0_t, ret);
18118 break;
18119 case NM_PRECEU_PH_QBR:
18120 check_dsp(ctx);
18121 gen_helper_preceu_ph_qbr(v0_t, v0_t);
18122 gen_store_gpr(v0_t, ret);
18123 break;
18124 case NM_PRECEU_PH_QBLA:
18125 check_dsp(ctx);
18126 gen_helper_preceu_ph_qbla(v0_t, v0_t);
18127 gen_store_gpr(v0_t, ret);
18128 break;
18129 case NM_PRECEU_PH_QBRA:
18130 check_dsp(ctx);
18131 gen_helper_preceu_ph_qbra(v0_t, v0_t);
18132 gen_store_gpr(v0_t, ret);
18133 break;
18134 case NM_REPLV_PH:
18135 check_dsp(ctx);
18136 tcg_gen_ext16u_tl(v0_t, v0_t);
18137 tcg_gen_shli_tl(t0, v0_t, 16);
18138 tcg_gen_or_tl(v0_t, v0_t, t0);
18139 tcg_gen_ext32s_tl(v0_t, v0_t);
18140 gen_store_gpr(v0_t, ret);
18141 break;
18142 case NM_REPLV_QB:
18143 check_dsp(ctx);
18144 tcg_gen_ext8u_tl(v0_t, v0_t);
18145 tcg_gen_shli_tl(t0, v0_t, 8);
18146 tcg_gen_or_tl(v0_t, v0_t, t0);
18147 tcg_gen_shli_tl(t0, v0_t, 16);
18148 tcg_gen_or_tl(v0_t, v0_t, t0);
18149 tcg_gen_ext32s_tl(v0_t, v0_t);
18150 gen_store_gpr(v0_t, ret);
18151 break;
18152 case NM_BITREV:
18153 check_dsp(ctx);
18154 gen_helper_bitrev(v0_t, v0_t);
18155 gen_store_gpr(v0_t, ret);
18156 break;
18157 case NM_INSV:
18158 check_dsp(ctx);
18159 {
18160 TCGv tv0 = tcg_temp_new();
18161
18162 gen_load_gpr(tv0, rt);
18163 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
18164 gen_store_gpr(v0_t, ret);
18165 tcg_temp_free(tv0);
18166 }
18167 break;
18168 case NM_RADDU_W_QB:
18169 check_dsp(ctx);
18170 gen_helper_raddu_w_qb(v0_t, v0_t);
18171 gen_store_gpr(v0_t, ret);
18172 break;
18173 case NM_BITSWAP:
18174 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
18175 break;
18176 case NM_CLO:
fb32f8c8 18177 check_nms(ctx);
4c75c985
SM
18178 gen_cl(ctx, OPC_CLO, ret, rs);
18179 break;
18180 case NM_CLZ:
fb32f8c8 18181 check_nms(ctx);
4c75c985
SM
18182 gen_cl(ctx, OPC_CLZ, ret, rs);
18183 break;
18184 case NM_WSBH:
18185 gen_bshfl(ctx, OPC_WSBH, ret, rs);
18186 break;
18187 default:
18188 generate_exception_end(ctx, EXCP_RI);
18189 break;
18190 }
18191
18192 tcg_temp_free(v0_t);
18193 tcg_temp_free(t0);
18194}
18195
0b591184
SM
18196static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
18197 int rt, int rs, int rd)
18198{
18199 TCGv t0 = tcg_temp_new();
18200 TCGv rs_t = tcg_temp_new();
18201
18202 gen_load_gpr(rs_t, rs);
18203
18204 switch (opc) {
18205 case NM_SHRA_R_QB:
18206 check_dspr2(ctx);
18207 tcg_gen_movi_tl(t0, rd >> 2);
18208 switch (extract32(ctx->opcode, 12, 1)) {
18209 case 0:
18210 /* NM_SHRA_QB */
18211 gen_helper_shra_qb(t0, t0, rs_t);
18212 gen_store_gpr(t0, rt);
18213 break;
18214 case 1:
18215 /* NM_SHRA_R_QB */
18216 gen_helper_shra_r_qb(t0, t0, rs_t);
18217 gen_store_gpr(t0, rt);
18218 break;
18219 }
18220 break;
18221 case NM_SHRL_PH:
18222 check_dspr2(ctx);
18223 tcg_gen_movi_tl(t0, rd >> 1);
18224 gen_helper_shrl_ph(t0, t0, rs_t);
18225 gen_store_gpr(t0, rt);
18226 break;
18227 case NM_REPL_QB:
18228 check_dsp(ctx);
18229 {
18230 int16_t imm;
18231 target_long result;
18232 imm = extract32(ctx->opcode, 13, 8);
18233 result = (uint32_t)imm << 24 |
18234 (uint32_t)imm << 16 |
18235 (uint32_t)imm << 8 |
18236 (uint32_t)imm;
18237 result = (int32_t)result;
18238 tcg_gen_movi_tl(t0, result);
18239 gen_store_gpr(t0, rt);
18240 }
18241 break;
18242 default:
18243 generate_exception_end(ctx, EXCP_RI);
18244 break;
18245 }
18246 tcg_temp_free(t0);
18247 tcg_temp_free(rs_t);
18248}
18249
2ed42efa 18250
64224187
YK
18251static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18252{
64224187
YK
18253 int rt = extract32(ctx->opcode, 21, 5);
18254 int rs = extract32(ctx->opcode, 16, 5);
2ed42efa 18255 int rd = extract32(ctx->opcode, 11, 5);
64224187
YK
18256
18257 switch (extract32(ctx->opcode, 6, 3)) {
2ed42efa
SM
18258 case NM_POOL32AXF_1:
18259 {
18260 int32_t op1 = extract32(ctx->opcode, 9, 3);
18261 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
18262 }
18263 break;
18264 case NM_POOL32AXF_2:
8b3698b2
SM
18265 {
18266 int32_t op1 = extract32(ctx->opcode, 12, 2);
18267 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
18268 }
2ed42efa 18269 break;
64224187 18270 case NM_POOL32AXF_4:
4c75c985
SM
18271 {
18272 int32_t op1 = extract32(ctx->opcode, 9, 7);
18273 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
18274 }
2ed42efa 18275 break;
64224187
YK
18276 case NM_POOL32AXF_5:
18277 switch (extract32(ctx->opcode, 9, 7)) {
18278#ifndef CONFIG_USER_ONLY
18279 case NM_TLBP:
18280 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
18281 break;
18282 case NM_TLBR:
18283 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
18284 break;
18285 case NM_TLBWI:
18286 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
18287 break;
18288 case NM_TLBWR:
18289 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
18290 break;
18291 case NM_TLBINV:
18292 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
18293 break;
18294 case NM_TLBINVF:
18295 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
18296 break;
18297 case NM_DI:
18298 check_cp0_enabled(ctx);
18299 {
18300 TCGv t0 = tcg_temp_new();
18301
18302 save_cpu_state(ctx, 1);
18303 gen_helper_di(t0, cpu_env);
18304 gen_store_gpr(t0, rt);
18305 /* Stop translation as we may have switched the execution mode */
18306 ctx->base.is_jmp = DISAS_STOP;
18307 tcg_temp_free(t0);
18308 }
18309 break;
18310 case NM_EI:
18311 check_cp0_enabled(ctx);
18312 {
18313 TCGv t0 = tcg_temp_new();
18314
18315 save_cpu_state(ctx, 1);
18316 gen_helper_ei(t0, cpu_env);
18317 gen_store_gpr(t0, rt);
18318 /* Stop translation as we may have switched the execution mode */
18319 ctx->base.is_jmp = DISAS_STOP;
18320 tcg_temp_free(t0);
18321 }
18322 break;
18323 case NM_RDPGPR:
18324 gen_load_srsgpr(rs, rt);
18325 break;
18326 case NM_WRPGPR:
18327 gen_store_srsgpr(rs, rt);
18328 break;
18329 case NM_WAIT:
18330 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
18331 break;
18332 case NM_DERET:
18333 gen_cp0(env, ctx, OPC_DERET, 0, 0);
18334 break;
18335 case NM_ERETX:
18336 gen_cp0(env, ctx, OPC_ERET, 0, 0);
18337 break;
18338#endif
18339 default:
18340 generate_exception_end(ctx, EXCP_RI);
18341 break;
18342 }
18343 break;
2ed42efa 18344 case NM_POOL32AXF_7:
0b591184
SM
18345 {
18346 int32_t op1 = extract32(ctx->opcode, 9, 3);
18347 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
18348 }
2ed42efa 18349 break;
64224187
YK
18350 default:
18351 generate_exception_end(ctx, EXCP_RI);
18352 break;
18353 }
18354}
18355
11d0fc10
SM
18356/* Immediate Value Compact Branches */
18357static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
18358 int rt, int32_t imm, int32_t offset)
18359{
18360 TCGCond cond;
18361 int bcond_compute = 0;
18362 TCGv t0 = tcg_temp_new();
18363 TCGv t1 = tcg_temp_new();
18364
18365 gen_load_gpr(t0, rt);
18366 tcg_gen_movi_tl(t1, imm);
18367 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18368
18369 /* Load needed operands and calculate btarget */
18370 switch (opc) {
18371 case NM_BEQIC:
18372 if (rt == 0 && imm == 0) {
18373 /* Unconditional branch */
18374 } else if (rt == 0 && imm != 0) {
18375 /* Treat as NOP */
18376 goto out;
18377 } else {
18378 bcond_compute = 1;
18379 cond = TCG_COND_EQ;
18380 }
18381 break;
18382 case NM_BBEQZC:
18383 case NM_BBNEZC:
fb32f8c8 18384 check_nms(ctx);
11d0fc10
SM
18385 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
18386 generate_exception_end(ctx, EXCP_RI);
18387 goto out;
18388 } else if (rt == 0 && opc == NM_BBEQZC) {
18389 /* Unconditional branch */
18390 } else if (rt == 0 && opc == NM_BBNEZC) {
18391 /* Treat as NOP */
18392 goto out;
18393 } else {
18394 tcg_gen_shri_tl(t0, t0, imm);
18395 tcg_gen_andi_tl(t0, t0, 1);
18396 tcg_gen_movi_tl(t1, 0);
18397 bcond_compute = 1;
18398 if (opc == NM_BBEQZC) {
18399 cond = TCG_COND_EQ;
18400 } else {
18401 cond = TCG_COND_NE;
18402 }
18403 }
18404 break;
18405 case NM_BNEIC:
18406 if (rt == 0 && imm == 0) {
18407 /* Treat as NOP */
18408 goto out;
18409 } else if (rt == 0 && imm != 0) {
18410 /* Unconditional branch */
18411 } else {
18412 bcond_compute = 1;
18413 cond = TCG_COND_NE;
18414 }
18415 break;
18416 case NM_BGEIC:
18417 if (rt == 0 && imm == 0) {
18418 /* Unconditional branch */
18419 } else {
18420 bcond_compute = 1;
18421 cond = TCG_COND_GE;
18422 }
18423 break;
18424 case NM_BLTIC:
18425 bcond_compute = 1;
18426 cond = TCG_COND_LT;
18427 break;
18428 case NM_BGEIUC:
18429 if (rt == 0 && imm == 0) {
18430 /* Unconditional branch */
18431 } else {
18432 bcond_compute = 1;
18433 cond = TCG_COND_GEU;
18434 }
18435 break;
18436 case NM_BLTIUC:
18437 bcond_compute = 1;
18438 cond = TCG_COND_LTU;
18439 break;
18440 default:
18441 MIPS_INVAL("Immediate Value Compact branch");
18442 generate_exception_end(ctx, EXCP_RI);
18443 goto out;
18444 }
18445
18446 if (bcond_compute == 0) {
18447 /* Uncoditional compact branch */
18448 gen_goto_tb(ctx, 0, ctx->btarget);
18449 } else {
18450 /* Conditional compact branch */
18451 TCGLabel *fs = gen_new_label();
18452
18453 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
18454
18455 gen_goto_tb(ctx, 1, ctx->btarget);
18456 gen_set_label(fs);
18457
18458 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
18459 }
18460
18461out:
18462 tcg_temp_free(t0);
18463 tcg_temp_free(t1);
18464}
18465
18466/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
18467static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
18468 int rt)
18469{
18470 TCGv t0 = tcg_temp_new();
18471 TCGv t1 = tcg_temp_new();
18472
18473 /* load rs */
18474 gen_load_gpr(t0, rs);
18475
18476 /* link */
18477 if (rt != 0) {
18478 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
18479 }
18480
18481 /* calculate btarget */
18482 tcg_gen_shli_tl(t0, t0, 1);
18483 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
18484 gen_op_addr_add(ctx, btarget, t1, t0);
18485
18486 /* unconditional branch to register */
18487 tcg_gen_mov_tl(cpu_PC, btarget);
18488 tcg_gen_lookup_and_goto_ptr();
18489
18490 tcg_temp_free(t0);
18491 tcg_temp_free(t1);
18492}
18493
18494/* nanoMIPS Branches */
18495static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
18496 int rs, int rt, int32_t offset)
18497{
18498 int bcond_compute = 0;
18499 TCGv t0 = tcg_temp_new();
18500 TCGv t1 = tcg_temp_new();
18501
18502 /* Load needed operands and calculate btarget */
18503 switch (opc) {
18504 /* compact branch */
18505 case OPC_BGEC:
18506 case OPC_BLTC:
18507 gen_load_gpr(t0, rs);
18508 gen_load_gpr(t1, rt);
18509 bcond_compute = 1;
18510 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18511 break;
18512 case OPC_BGEUC:
18513 case OPC_BLTUC:
18514 if (rs == 0 || rs == rt) {
18515 /* OPC_BLEZALC, OPC_BGEZALC */
18516 /* OPC_BGTZALC, OPC_BLTZALC */
18517 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
18518 }
18519 gen_load_gpr(t0, rs);
18520 gen_load_gpr(t1, rt);
18521 bcond_compute = 1;
18522 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18523 break;
18524 case OPC_BC:
18525 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18526 break;
18527 case OPC_BEQZC:
18528 if (rs != 0) {
18529 /* OPC_BEQZC, OPC_BNEZC */
18530 gen_load_gpr(t0, rs);
18531 bcond_compute = 1;
18532 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18533 } else {
18534 /* OPC_JIC, OPC_JIALC */
18535 TCGv tbase = tcg_temp_new();
18536 TCGv toffset = tcg_temp_new();
18537
18538 gen_load_gpr(tbase, rt);
18539 tcg_gen_movi_tl(toffset, offset);
18540 gen_op_addr_add(ctx, btarget, tbase, toffset);
18541 tcg_temp_free(tbase);
18542 tcg_temp_free(toffset);
18543 }
18544 break;
18545 default:
18546 MIPS_INVAL("Compact branch/jump");
18547 generate_exception_end(ctx, EXCP_RI);
18548 goto out;
18549 }
18550
18551 if (bcond_compute == 0) {
18552 /* Uncoditional compact branch */
18553 switch (opc) {
18554 case OPC_BC:
18555 gen_goto_tb(ctx, 0, ctx->btarget);
18556 break;
18557 default:
18558 MIPS_INVAL("Compact branch/jump");
18559 generate_exception_end(ctx, EXCP_RI);
18560 goto out;
18561 }
18562 } else {
18563 /* Conditional compact branch */
18564 TCGLabel *fs = gen_new_label();
18565
18566 switch (opc) {
18567 case OPC_BGEUC:
18568 if (rs == 0 && rt != 0) {
18569 /* OPC_BLEZALC */
18570 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
18571 } else if (rs != 0 && rt != 0 && rs == rt) {
18572 /* OPC_BGEZALC */
18573 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
18574 } else {
18575 /* OPC_BGEUC */
18576 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
18577 }
18578 break;
18579 case OPC_BLTUC:
18580 if (rs == 0 && rt != 0) {
18581 /* OPC_BGTZALC */
18582 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
18583 } else if (rs != 0 && rt != 0 && rs == rt) {
18584 /* OPC_BLTZALC */
18585 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
18586 } else {
18587 /* OPC_BLTUC */
18588 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
18589 }
18590 break;
18591 case OPC_BGEC:
18592 if (rs == 0 && rt != 0) {
18593 /* OPC_BLEZC */
18594 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
18595 } else if (rs != 0 && rt != 0 && rs == rt) {
18596 /* OPC_BGEZC */
18597 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
18598 } else {
18599 /* OPC_BGEC */
18600 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
18601 }
18602 break;
18603 case OPC_BLTC:
18604 if (rs == 0 && rt != 0) {
18605 /* OPC_BGTZC */
18606 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
18607 } else if (rs != 0 && rt != 0 && rs == rt) {
18608 /* OPC_BLTZC */
18609 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
18610 } else {
18611 /* OPC_BLTC */
18612 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
18613 }
18614 break;
18615 case OPC_BEQZC:
18616 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
18617 break;
18618 default:
18619 MIPS_INVAL("Compact conditional branch/jump");
18620 generate_exception_end(ctx, EXCP_RI);
18621 goto out;
18622 }
18623
18624 /* Generating branch here as compact branches don't have delay slot */
18625 gen_goto_tb(ctx, 1, ctx->btarget);
18626 gen_set_label(fs);
18627
18628 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
18629 }
18630
18631out:
18632 tcg_temp_free(t0);
18633 tcg_temp_free(t1);
18634}
18635
18636
18637/* nanoMIPS CP1 Branches */
18638static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
18639 int32_t ft, int32_t offset)
18640{
18641 target_ulong btarget;
18642 TCGv_i64 t0 = tcg_temp_new_i64();
18643
18644 gen_load_fpr64(ctx, t0, ft);
18645 tcg_gen_andi_i64(t0, t0, 1);
18646
18647 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18648
18649 switch (op) {
18650 case NM_BC1EQZC:
18651 tcg_gen_xori_i64(t0, t0, 1);
18652 ctx->hflags |= MIPS_HFLAG_BC;
18653 break;
18654 case NM_BC1NEZC:
18655 /* t0 already set */
18656 ctx->hflags |= MIPS_HFLAG_BC;
18657 break;
18658 default:
18659 MIPS_INVAL("cp1 cond branch");
18660 generate_exception_end(ctx, EXCP_RI);
18661 goto out;
18662 }
18663
18664 tcg_gen_trunc_i64_tl(bcond, t0);
18665
18666 ctx->btarget = btarget;
18667
18668out:
18669 tcg_temp_free_i64(t0);
18670}
18671
eac52664
YK
18672
18673static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
18674{
18675 TCGv t0, t1;
18676 t0 = tcg_temp_new();
18677 t1 = tcg_temp_new();
18678
18679 gen_load_gpr(t0, rs);
18680 gen_load_gpr(t1, rt);
18681
18682 if ((extract32(ctx->opcode, 6, 1)) == 1) {
18683 /* PP.LSXS instructions require shifting */
18684 switch (extract32(ctx->opcode, 7, 4)) {
eac52664 18685 case NM_SHXS:
fb32f8c8
DN
18686 check_nms(ctx);
18687 case NM_LHXS:
eac52664
YK
18688 case NM_LHUXS:
18689 tcg_gen_shli_tl(t0, t0, 1);
18690 break;
eac52664 18691 case NM_SWXS:
fb32f8c8
DN
18692 check_nms(ctx);
18693 case NM_LWXS:
eac52664
YK
18694 case NM_LWC1XS:
18695 case NM_SWC1XS:
18696 tcg_gen_shli_tl(t0, t0, 2);
18697 break;
18698 case NM_LDC1XS:
18699 case NM_SDC1XS:
18700 tcg_gen_shli_tl(t0, t0, 3);
18701 break;
18702 }
18703 }
18704 gen_op_addr_add(ctx, t0, t0, t1);
18705
18706 switch (extract32(ctx->opcode, 7, 4)) {
18707 case NM_LBX:
18708 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18709 MO_SB);
18710 gen_store_gpr(t0, rd);
18711 break;
18712 case NM_LHX:
18713 /*case NM_LHXS:*/
18714 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18715 MO_TESW);
18716 gen_store_gpr(t0, rd);
18717 break;
18718 case NM_LWX:
18719 /*case NM_LWXS:*/
18720 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18721 MO_TESL);
18722 gen_store_gpr(t0, rd);
18723 break;
18724 case NM_LBUX:
18725 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18726 MO_UB);
18727 gen_store_gpr(t0, rd);
18728 break;
18729 case NM_LHUX:
18730 /*case NM_LHUXS:*/
18731 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18732 MO_TEUW);
18733 gen_store_gpr(t0, rd);
18734 break;
18735 case NM_SBX:
fb32f8c8 18736 check_nms(ctx);
eac52664
YK
18737 gen_load_gpr(t1, rd);
18738 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
18739 MO_8);
18740 break;
18741 case NM_SHX:
18742 /*case NM_SHXS:*/
fb32f8c8 18743 check_nms(ctx);
eac52664
YK
18744 gen_load_gpr(t1, rd);
18745 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
18746 MO_TEUW);
18747 break;
18748 case NM_SWX:
18749 /*case NM_SWXS:*/
fb32f8c8 18750 check_nms(ctx);
eac52664
YK
18751 gen_load_gpr(t1, rd);
18752 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
18753 MO_TEUL);
18754 break;
18755 case NM_LWC1X:
18756 /*case NM_LWC1XS:*/
18757 case NM_LDC1X:
18758 /*case NM_LDC1XS:*/
18759 case NM_SWC1X:
18760 /*case NM_SWC1XS:*/
18761 case NM_SDC1X:
18762 /*case NM_SDC1XS:*/
18763 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
18764 check_cp1_enabled(ctx);
18765 switch (extract32(ctx->opcode, 7, 4)) {
18766 case NM_LWC1X:
18767 /*case NM_LWC1XS:*/
18768 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
18769 break;
18770 case NM_LDC1X:
18771 /*case NM_LDC1XS:*/
18772 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
18773 break;
18774 case NM_SWC1X:
18775 /*case NM_SWC1XS:*/
18776 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
18777 break;
18778 case NM_SDC1X:
18779 /*case NM_SDC1XS:*/
18780 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
18781 break;
18782 }
18783 } else {
18784 generate_exception_err(ctx, EXCP_CpU, 1);
18785 }
18786 break;
18787 default:
18788 generate_exception_end(ctx, EXCP_RI);
18789 break;
18790 }
18791
18792 tcg_temp_free(t0);
18793 tcg_temp_free(t1);
18794}
18795
579b8ea9
YK
18796static void gen_pool32f_nanomips_insn(DisasContext *ctx)
18797{
18798 int rt, rs, rd;
18799
18800 rt = extract32(ctx->opcode, 21, 5);
18801 rs = extract32(ctx->opcode, 16, 5);
18802 rd = extract32(ctx->opcode, 11, 5);
18803
18804 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
18805 generate_exception_end(ctx, EXCP_RI);
18806 return;
18807 }
18808 check_cp1_enabled(ctx);
18809 switch (extract32(ctx->opcode, 0, 3)) {
18810 case NM_POOL32F_0:
18811 switch (extract32(ctx->opcode, 3, 7)) {
18812 case NM_RINT_S:
18813 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
18814 break;
18815 case NM_RINT_D:
18816 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
18817 break;
18818 case NM_CLASS_S:
18819 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
18820 break;
18821 case NM_CLASS_D:
18822 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
18823 break;
18824 case NM_ADD_S:
18825 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
18826 break;
18827 case NM_ADD_D:
18828 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
18829 break;
18830 case NM_SUB_S:
18831 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
18832 break;
18833 case NM_SUB_D:
18834 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
18835 break;
18836 case NM_MUL_S:
18837 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
18838 break;
18839 case NM_MUL_D:
18840 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
18841 break;
18842 case NM_DIV_S:
18843 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
18844 break;
18845 case NM_DIV_D:
18846 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
18847 break;
18848 case NM_SELEQZ_S:
18849 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
18850 break;
18851 case NM_SELEQZ_D:
18852 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
18853 break;
18854 case NM_SELNEZ_S:
18855 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
18856 break;
18857 case NM_SELNEZ_D:
18858 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
18859 break;
18860 case NM_SEL_S:
18861 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
18862 break;
18863 case NM_SEL_D:
18864 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
18865 break;
18866 case NM_MADDF_S:
18867 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
18868 break;
18869 case NM_MADDF_D:
18870 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
18871 break;
18872 case NM_MSUBF_S:
18873 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
18874 break;
18875 case NM_MSUBF_D:
18876 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
18877 break;
18878 default:
18879 generate_exception_end(ctx, EXCP_RI);
18880 break;
18881 }
18882 break;
18883 case NM_POOL32F_3:
18884 switch (extract32(ctx->opcode, 3, 3)) {
18885 case NM_MIN_FMT:
18886 switch (extract32(ctx->opcode, 9, 1)) {
18887 case FMT_SDPS_S:
18888 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
18889 break;
18890 case FMT_SDPS_D:
18891 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
18892 break;
18893 }
18894 break;
18895 case NM_MAX_FMT:
18896 switch (extract32(ctx->opcode, 9, 1)) {
18897 case FMT_SDPS_S:
18898 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
18899 break;
18900 case FMT_SDPS_D:
18901 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
18902 break;
18903 }
18904 break;
18905 case NM_MINA_FMT:
18906 switch (extract32(ctx->opcode, 9, 1)) {
18907 case FMT_SDPS_S:
18908 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
18909 break;
18910 case FMT_SDPS_D:
18911 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
18912 break;
18913 }
18914 break;
18915 case NM_MAXA_FMT:
18916 switch (extract32(ctx->opcode, 9, 1)) {
18917 case FMT_SDPS_S:
18918 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
18919 break;
18920 case FMT_SDPS_D:
18921 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
18922 break;
18923 }
18924 break;
18925 case NM_POOL32FXF:
18926 switch (extract32(ctx->opcode, 6, 8)) {
18927 case NM_CFC1:
18928 gen_cp1(ctx, OPC_CFC1, rt, rs);
18929 break;
18930 case NM_CTC1:
18931 gen_cp1(ctx, OPC_CTC1, rt, rs);
18932 break;
18933 case NM_MFC1:
18934 gen_cp1(ctx, OPC_MFC1, rt, rs);
18935 break;
18936 case NM_MTC1:
18937 gen_cp1(ctx, OPC_MTC1, rt, rs);
18938 break;
18939 case NM_MFHC1:
18940 gen_cp1(ctx, OPC_MFHC1, rt, rs);
18941 break;
18942 case NM_MTHC1:
18943 gen_cp1(ctx, OPC_MTHC1, rt, rs);
18944 break;
18945 case NM_CVT_S_PL:
18946 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
18947 break;
18948 case NM_CVT_S_PU:
18949 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
18950 break;
18951 default:
18952 switch (extract32(ctx->opcode, 6, 9)) {
18953 case NM_CVT_L_S:
18954 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
18955 break;
18956 case NM_CVT_L_D:
18957 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
18958 break;
18959 case NM_CVT_W_S:
18960 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
18961 break;
18962 case NM_CVT_W_D:
18963 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
18964 break;
18965 case NM_RSQRT_S:
18966 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
18967 break;
18968 case NM_RSQRT_D:
18969 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
18970 break;
18971 case NM_SQRT_S:
18972 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
18973 break;
18974 case NM_SQRT_D:
18975 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
18976 break;
18977 case NM_RECIP_S:
18978 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
18979 break;
18980 case NM_RECIP_D:
18981 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
18982 break;
18983 case NM_FLOOR_L_S:
18984 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
18985 break;
18986 case NM_FLOOR_L_D:
18987 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
18988 break;
18989 case NM_FLOOR_W_S:
18990 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
18991 break;
18992 case NM_FLOOR_W_D:
18993 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
18994 break;
18995 case NM_CEIL_L_S:
18996 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
18997 break;
18998 case NM_CEIL_L_D:
18999 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19000 break;
19001 case NM_CEIL_W_S:
19002 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19003 break;
19004 case NM_CEIL_W_D:
19005 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19006 break;
19007 case NM_TRUNC_L_S:
19008 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19009 break;
19010 case NM_TRUNC_L_D:
19011 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19012 break;
19013 case NM_TRUNC_W_S:
19014 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
19015 break;
19016 case NM_TRUNC_W_D:
19017 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
19018 break;
19019 case NM_ROUND_L_S:
19020 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
19021 break;
19022 case NM_ROUND_L_D:
19023 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
19024 break;
19025 case NM_ROUND_W_S:
19026 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
19027 break;
19028 case NM_ROUND_W_D:
19029 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
19030 break;
19031 case NM_MOV_S:
19032 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
19033 break;
19034 case NM_MOV_D:
19035 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
19036 break;
19037 case NM_ABS_S:
19038 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
19039 break;
19040 case NM_ABS_D:
19041 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
19042 break;
19043 case NM_NEG_S:
19044 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
19045 break;
19046 case NM_NEG_D:
19047 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
19048 break;
19049 case NM_CVT_D_S:
19050 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
19051 break;
19052 case NM_CVT_D_W:
19053 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
19054 break;
19055 case NM_CVT_D_L:
19056 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
19057 break;
19058 case NM_CVT_S_D:
19059 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
19060 break;
19061 case NM_CVT_S_W:
19062 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
19063 break;
19064 case NM_CVT_S_L:
19065 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
19066 break;
19067 default:
19068 generate_exception_end(ctx, EXCP_RI);
19069 break;
19070 }
19071 break;
19072 }
19073 break;
19074 }
19075 break;
19076 case NM_POOL32F_5:
19077 switch (extract32(ctx->opcode, 3, 3)) {
19078 case NM_CMP_CONDN_S:
19079 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19080 break;
19081 case NM_CMP_CONDN_D:
19082 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19083 break;
19084 default:
19085 generate_exception_end(ctx, EXCP_RI);
19086 break;
19087 }
19088 break;
19089 default:
19090 generate_exception_end(ctx, EXCP_RI);
19091 break;
19092 }
19093}
19094
3285a3e4
SM
19095static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
19096 int rd, int rs, int rt)
19097{
19098 int ret = rd;
19099 TCGv t0 = tcg_temp_new();
19100 TCGv v1_t = tcg_temp_new();
19101 TCGv v2_t = tcg_temp_new();
19102
19103 gen_load_gpr(v1_t, rs);
19104 gen_load_gpr(v2_t, rt);
19105
19106 switch (opc) {
19107 case NM_CMP_EQ_PH:
19108 check_dsp(ctx);
19109 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
19110 break;
19111 case NM_CMP_LT_PH:
19112 check_dsp(ctx);
19113 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
19114 break;
19115 case NM_CMP_LE_PH:
19116 check_dsp(ctx);
19117 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
19118 break;
19119 case NM_CMPU_EQ_QB:
19120 check_dsp(ctx);
19121 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
19122 break;
19123 case NM_CMPU_LT_QB:
19124 check_dsp(ctx);
19125 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
19126 break;
19127 case NM_CMPU_LE_QB:
19128 check_dsp(ctx);
19129 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
19130 break;
19131 case NM_CMPGU_EQ_QB:
19132 check_dsp(ctx);
19133 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19134 gen_store_gpr(v1_t, ret);
19135 break;
19136 case NM_CMPGU_LT_QB:
19137 check_dsp(ctx);
19138 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19139 gen_store_gpr(v1_t, ret);
19140 break;
19141 case NM_CMPGU_LE_QB:
19142 check_dsp(ctx);
19143 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19144 gen_store_gpr(v1_t, ret);
19145 break;
19146 case NM_CMPGDU_EQ_QB:
19147 check_dspr2(ctx);
19148 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19149 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19150 gen_store_gpr(v1_t, ret);
19151 break;
19152 case NM_CMPGDU_LT_QB:
19153 check_dspr2(ctx);
19154 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19155 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19156 gen_store_gpr(v1_t, ret);
19157 break;
19158 case NM_CMPGDU_LE_QB:
19159 check_dspr2(ctx);
19160 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19161 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19162 gen_store_gpr(v1_t, ret);
19163 break;
19164 case NM_PACKRL_PH:
19165 check_dsp(ctx);
19166 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
19167 gen_store_gpr(v1_t, ret);
19168 break;
19169 case NM_PICK_QB:
19170 check_dsp(ctx);
19171 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
19172 gen_store_gpr(v1_t, ret);
19173 break;
19174 case NM_PICK_PH:
19175 check_dsp(ctx);
19176 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
19177 gen_store_gpr(v1_t, ret);
19178 break;
19179 case NM_ADDQ_S_W:
19180 check_dsp(ctx);
19181 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
19182 gen_store_gpr(v1_t, ret);
19183 break;
19184 case NM_SUBQ_S_W:
19185 check_dsp(ctx);
19186 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
19187 gen_store_gpr(v1_t, ret);
19188 break;
19189 case NM_ADDSC:
19190 check_dsp(ctx);
19191 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
19192 gen_store_gpr(v1_t, ret);
19193 break;
19194 case NM_ADDWC:
19195 check_dsp(ctx);
19196 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
19197 gen_store_gpr(v1_t, ret);
19198 break;
19199 case NM_ADDQ_S_PH:
19200 check_dsp(ctx);
19201 switch (extract32(ctx->opcode, 10, 1)) {
19202 case 0:
19203 /* ADDQ_PH */
19204 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
19205 gen_store_gpr(v1_t, ret);
19206 break;
19207 case 1:
19208 /* ADDQ_S_PH */
19209 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19210 gen_store_gpr(v1_t, ret);
19211 break;
19212 }
19213 break;
19214 case NM_ADDQH_R_PH:
19215 check_dspr2(ctx);
19216 switch (extract32(ctx->opcode, 10, 1)) {
19217 case 0:
19218 /* ADDQH_PH */
19219 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
19220 gen_store_gpr(v1_t, ret);
19221 break;
19222 case 1:
19223 /* ADDQH_R_PH */
19224 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
19225 gen_store_gpr(v1_t, ret);
19226 break;
19227 }
19228 break;
19229 case NM_ADDQH_R_W:
19230 check_dspr2(ctx);
19231 switch (extract32(ctx->opcode, 10, 1)) {
19232 case 0:
19233 /* ADDQH_W */
19234 gen_helper_addqh_w(v1_t, v1_t, v2_t);
19235 gen_store_gpr(v1_t, ret);
19236 break;
19237 case 1:
19238 /* ADDQH_R_W */
19239 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
19240 gen_store_gpr(v1_t, ret);
19241 break;
19242 }
19243 break;
19244 case NM_ADDU_S_QB:
19245 check_dsp(ctx);
19246 switch (extract32(ctx->opcode, 10, 1)) {
19247 case 0:
19248 /* ADDU_QB */
19249 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
19250 gen_store_gpr(v1_t, ret);
19251 break;
19252 case 1:
19253 /* ADDU_S_QB */
19254 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19255 gen_store_gpr(v1_t, ret);
19256 break;
19257 }
19258 break;
19259 case NM_ADDU_S_PH:
19260 check_dspr2(ctx);
19261 switch (extract32(ctx->opcode, 10, 1)) {
19262 case 0:
19263 /* ADDU_PH */
19264 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
19265 gen_store_gpr(v1_t, ret);
19266 break;
19267 case 1:
19268 /* ADDU_S_PH */
19269 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19270 gen_store_gpr(v1_t, ret);
19271 break;
19272 }
19273 break;
19274 case NM_ADDUH_R_QB:
19275 check_dspr2(ctx);
19276 switch (extract32(ctx->opcode, 10, 1)) {
19277 case 0:
19278 /* ADDUH_QB */
19279 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
19280 gen_store_gpr(v1_t, ret);
19281 break;
19282 case 1:
19283 /* ADDUH_R_QB */
19284 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
19285 gen_store_gpr(v1_t, ret);
19286 break;
19287 }
19288 break;
19289 case NM_SHRAV_R_PH:
19290 check_dsp(ctx);
19291 switch (extract32(ctx->opcode, 10, 1)) {
19292 case 0:
19293 /* SHRAV_PH */
19294 gen_helper_shra_ph(v1_t, v1_t, v2_t);
19295 gen_store_gpr(v1_t, ret);
19296 break;
19297 case 1:
19298 /* SHRAV_R_PH */
19299 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
19300 gen_store_gpr(v1_t, ret);
19301 break;
19302 }
19303 break;
19304 case NM_SHRAV_R_QB:
19305 check_dspr2(ctx);
19306 switch (extract32(ctx->opcode, 10, 1)) {
19307 case 0:
19308 /* SHRAV_QB */
19309 gen_helper_shra_qb(v1_t, v1_t, v2_t);
19310 gen_store_gpr(v1_t, ret);
19311 break;
19312 case 1:
19313 /* SHRAV_R_QB */
19314 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
19315 gen_store_gpr(v1_t, ret);
19316 break;
19317 }
19318 break;
19319 case NM_SUBQ_S_PH:
19320 check_dsp(ctx);
19321 switch (extract32(ctx->opcode, 10, 1)) {
19322 case 0:
19323 /* SUBQ_PH */
19324 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
19325 gen_store_gpr(v1_t, ret);
19326 break;
19327 case 1:
19328 /* SUBQ_S_PH */
19329 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19330 gen_store_gpr(v1_t, ret);
19331 break;
19332 }
19333 break;
19334 case NM_SUBQH_R_PH:
19335 check_dspr2(ctx);
19336 switch (extract32(ctx->opcode, 10, 1)) {
19337 case 0:
19338 /* SUBQH_PH */
19339 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
19340 gen_store_gpr(v1_t, ret);
19341 break;
19342 case 1:
19343 /* SUBQH_R_PH */
19344 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
19345 gen_store_gpr(v1_t, ret);
19346 break;
19347 }
19348 break;
19349 case NM_SUBQH_R_W:
19350 check_dspr2(ctx);
19351 switch (extract32(ctx->opcode, 10, 1)) {
19352 case 0:
19353 /* SUBQH_W */
19354 gen_helper_subqh_w(v1_t, v1_t, v2_t);
19355 gen_store_gpr(v1_t, ret);
19356 break;
19357 case 1:
19358 /* SUBQH_R_W */
19359 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
19360 gen_store_gpr(v1_t, ret);
19361 break;
19362 }
19363 break;
19364 case NM_SUBU_S_QB:
19365 check_dsp(ctx);
19366 switch (extract32(ctx->opcode, 10, 1)) {
19367 case 0:
19368 /* SUBU_QB */
19369 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
19370 gen_store_gpr(v1_t, ret);
19371 break;
19372 case 1:
19373 /* SUBU_S_QB */
19374 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19375 gen_store_gpr(v1_t, ret);
19376 break;
19377 }
19378 break;
19379 case NM_SUBU_S_PH:
19380 check_dspr2(ctx);
19381 switch (extract32(ctx->opcode, 10, 1)) {
19382 case 0:
19383 /* SUBU_PH */
19384 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
19385 gen_store_gpr(v1_t, ret);
19386 break;
19387 case 1:
19388 /* SUBU_S_PH */
19389 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19390 gen_store_gpr(v1_t, ret);
19391 break;
19392 }
19393 break;
19394 case NM_SUBUH_R_QB:
19395 check_dspr2(ctx);
19396 switch (extract32(ctx->opcode, 10, 1)) {
19397 case 0:
19398 /* SUBUH_QB */
19399 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
19400 gen_store_gpr(v1_t, ret);
19401 break;
19402 case 1:
19403 /* SUBUH_R_QB */
19404 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
19405 gen_store_gpr(v1_t, ret);
19406 break;
19407 }
19408 break;
19409 case NM_SHLLV_S_PH:
19410 check_dsp(ctx);
19411 switch (extract32(ctx->opcode, 10, 1)) {
19412 case 0:
19413 /* SHLLV_PH */
19414 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
19415 gen_store_gpr(v1_t, ret);
19416 break;
19417 case 1:
19418 /* SHLLV_S_PH */
19419 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
19420 gen_store_gpr(v1_t, ret);
19421 break;
19422 }
19423 break;
19424 case NM_PRECR_SRA_R_PH_W:
19425 check_dspr2(ctx);
19426 switch (extract32(ctx->opcode, 10, 1)) {
19427 case 0:
19428 /* PRECR_SRA_PH_W */
19429 {
19430 TCGv_i32 sa_t = tcg_const_i32(rd);
19431 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
19432 cpu_gpr[rt]);
19433 gen_store_gpr(v1_t, rt);
19434 tcg_temp_free_i32(sa_t);
19435 }
19436 break;
19437 case 1:
19438 /* PRECR_SRA_R_PH_W */
19439 {
19440 TCGv_i32 sa_t = tcg_const_i32(rd);
19441 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
19442 cpu_gpr[rt]);
19443 gen_store_gpr(v1_t, rt);
19444 tcg_temp_free_i32(sa_t);
19445 }
19446 break;
19447 }
19448 break;
19449 case NM_MULEU_S_PH_QBL:
19450 check_dsp(ctx);
19451 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
19452 gen_store_gpr(v1_t, ret);
19453 break;
19454 case NM_MULEU_S_PH_QBR:
19455 check_dsp(ctx);
19456 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
19457 gen_store_gpr(v1_t, ret);
19458 break;
19459 case NM_MULQ_RS_PH:
19460 check_dsp(ctx);
19461 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
19462 gen_store_gpr(v1_t, ret);
19463 break;
19464 case NM_MULQ_S_PH:
19465 check_dspr2(ctx);
19466 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19467 gen_store_gpr(v1_t, ret);
19468 break;
19469 case NM_MULQ_RS_W:
19470 check_dspr2(ctx);
19471 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
19472 gen_store_gpr(v1_t, ret);
19473 break;
19474 case NM_MULQ_S_W:
19475 check_dspr2(ctx);
19476 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
19477 gen_store_gpr(v1_t, ret);
19478 break;
19479 case NM_APPEND:
19480 check_dspr2(ctx);
19481 gen_load_gpr(t0, rs);
19482 if (rd != 0) {
19483 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
19484 }
19485 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
19486 break;
19487 case NM_MODSUB:
19488 check_dsp(ctx);
19489 gen_helper_modsub(v1_t, v1_t, v2_t);
19490 gen_store_gpr(v1_t, ret);
19491 break;
19492 case NM_SHRAV_R_W:
19493 check_dsp(ctx);
19494 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
19495 gen_store_gpr(v1_t, ret);
19496 break;
19497 case NM_SHRLV_PH:
19498 check_dspr2(ctx);
19499 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
19500 gen_store_gpr(v1_t, ret);
19501 break;
19502 case NM_SHRLV_QB:
19503 check_dsp(ctx);
19504 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
19505 gen_store_gpr(v1_t, ret);
19506 break;
19507 case NM_SHLLV_QB:
19508 check_dsp(ctx);
19509 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
19510 gen_store_gpr(v1_t, ret);
19511 break;
19512 case NM_SHLLV_S_W:
19513 check_dsp(ctx);
19514 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
19515 gen_store_gpr(v1_t, ret);
19516 break;
19517 case NM_SHILO:
19518 check_dsp(ctx);
19519 {
19520 TCGv tv0 = tcg_temp_new();
19521 TCGv tv1 = tcg_temp_new();
19522 int16_t imm = extract32(ctx->opcode, 16, 7);
19523
19524 tcg_gen_movi_tl(tv0, rd >> 3);
19525 tcg_gen_movi_tl(tv1, imm);
19526 gen_helper_shilo(tv0, tv1, cpu_env);
19527 }
19528 break;
19529 case NM_MULEQ_S_W_PHL:
19530 check_dsp(ctx);
19531 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
19532 gen_store_gpr(v1_t, ret);
19533 break;
19534 case NM_MULEQ_S_W_PHR:
19535 check_dsp(ctx);
19536 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
19537 gen_store_gpr(v1_t, ret);
19538 break;
19539 case NM_MUL_S_PH:
19540 check_dspr2(ctx);
19541 switch (extract32(ctx->opcode, 10, 1)) {
19542 case 0:
19543 /* MUL_PH */
19544 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
19545 gen_store_gpr(v1_t, ret);
19546 break;
19547 case 1:
19548 /* MUL_S_PH */
19549 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
19550 gen_store_gpr(v1_t, ret);
19551 break;
19552 }
19553 break;
19554 case NM_PRECR_QB_PH:
19555 check_dspr2(ctx);
19556 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
19557 gen_store_gpr(v1_t, ret);
19558 break;
19559 case NM_PRECRQ_QB_PH:
19560 check_dsp(ctx);
19561 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
19562 gen_store_gpr(v1_t, ret);
19563 break;
19564 case NM_PRECRQ_PH_W:
19565 check_dsp(ctx);
19566 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
19567 gen_store_gpr(v1_t, ret);
19568 break;
19569 case NM_PRECRQ_RS_PH_W:
19570 check_dsp(ctx);
19571 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
19572 gen_store_gpr(v1_t, ret);
19573 break;
19574 case NM_PRECRQU_S_QB_PH:
19575 check_dsp(ctx);
19576 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
19577 gen_store_gpr(v1_t, ret);
19578 break;
19579 case NM_SHRA_R_W:
19580 check_dsp(ctx);
19581 tcg_gen_movi_tl(t0, rd);
19582 gen_helper_shra_r_w(v1_t, t0, v1_t);
19583 gen_store_gpr(v1_t, rt);
19584 break;
19585 case NM_SHRA_R_PH:
19586 check_dsp(ctx);
19587 tcg_gen_movi_tl(t0, rd >> 1);
19588 switch (extract32(ctx->opcode, 10, 1)) {
19589 case 0:
19590 /* SHRA_PH */
19591 gen_helper_shra_ph(v1_t, t0, v1_t);
19592 break;
19593 gen_store_gpr(v1_t, rt);
19594 case 1:
19595 /* SHRA_R_PH */
19596 gen_helper_shra_r_ph(v1_t, t0, v1_t);
19597 gen_store_gpr(v1_t, rt);
19598 break;
19599 }
19600 break;
19601 case NM_SHLL_S_PH:
19602 check_dsp(ctx);
19603 tcg_gen_movi_tl(t0, rd >> 1);
19604 switch (extract32(ctx->opcode, 10, 2)) {
19605 case 0:
19606 /* SHLL_PH */
19607 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
19608 gen_store_gpr(v1_t, rt);
19609 break;
19610 case 2:
19611 /* SHLL_S_PH */
19612 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
19613 gen_store_gpr(v1_t, rt);
19614 break;
19615 default:
19616 generate_exception_end(ctx, EXCP_RI);
19617 break;
19618 }
19619 break;
19620 case NM_SHLL_S_W:
19621 check_dsp(ctx);
19622 tcg_gen_movi_tl(t0, rd);
19623 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
19624 gen_store_gpr(v1_t, rt);
19625 break;
19626 case NM_REPL_PH:
19627 check_dsp(ctx);
19628 {
19629 int16_t imm;
19630 imm = sextract32(ctx->opcode, 11, 11);
19631 imm = (int16_t)(imm << 6) >> 6;
19632 if (rt != 0) {
19633 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
19634 }
19635 }
19636 break;
19637 default:
19638 generate_exception_end(ctx, EXCP_RI);
19639 break;
19640 }
19641}
19642
c0280983
YK
19643static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
19644{
19645 uint16_t insn;
19646 uint32_t op;
eac52664 19647 int rt, rs, rd;
c0280983
YK
19648 int offset;
19649 int imm;
19650
19651 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
19652 ctx->opcode = (ctx->opcode << 16) | insn;
19653
19654 rt = extract32(ctx->opcode, 21, 5);
19655 rs = extract32(ctx->opcode, 16, 5);
eac52664 19656 rd = extract32(ctx->opcode, 11, 5);
c0280983
YK
19657
19658 op = extract32(ctx->opcode, 26, 6);
19659 switch (op) {
19660 case NM_P_ADDIU:
19661 if (rt == 0) {
19662 /* P.RI */
19663 switch (extract32(ctx->opcode, 19, 2)) {
19664 case NM_SIGRIE:
19665 default:
19666 generate_exception_end(ctx, EXCP_RI);
19667 break;
19668 case NM_P_SYSCALL:
19669 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
19670 generate_exception_end(ctx, EXCP_SYSCALL);
19671 } else {
19672 generate_exception_end(ctx, EXCP_RI);
19673 }
19674 break;
19675 case NM_BREAK:
19676 generate_exception_end(ctx, EXCP_BREAK);
19677 break;
19678 case NM_SDBBP:
19679 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
19680 gen_helper_do_semihosting(cpu_env);
19681 } else {
19682 if (ctx->hflags & MIPS_HFLAG_SBRI) {
19683 generate_exception_end(ctx, EXCP_RI);
19684 } else {
19685 generate_exception_end(ctx, EXCP_DBp);
19686 }
19687 }
19688 break;
19689 }
19690 } else {
19691 /* NM_ADDIU */
19692 imm = extract32(ctx->opcode, 0, 16);
19693 if (rs != 0) {
19694 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
19695 } else {
19696 tcg_gen_movi_tl(cpu_gpr[rt], imm);
19697 }
19698 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
19699 }
19700 break;
19701 case NM_ADDIUPC:
19702 if (rt != 0) {
19703 offset = sextract32(ctx->opcode, 0, 1) << 21 |
19704 extract32(ctx->opcode, 1, 20) << 1;
19705 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
19706 tcg_gen_movi_tl(cpu_gpr[rt], addr);
19707 }
19708 break;
19709 case NM_POOL32A:
e0cf0e65
YK
19710 switch (ctx->opcode & 0x07) {
19711 case NM_POOL32A0:
0a1a6ed7 19712 gen_pool32a0_nanomips_insn(env, ctx);
e0cf0e65 19713 break;
3285a3e4
SM
19714 case NM_POOL32A5:
19715 {
19716 int32_t op1 = extract32(ctx->opcode, 3, 7);
19717 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
19718 }
19719 break;
e0cf0e65 19720 case NM_POOL32A7:
64224187 19721 switch (extract32(ctx->opcode, 3, 3)) {
eac52664
YK
19722 case NM_P_LSX:
19723 gen_p_lsx(ctx, rd, rs, rt);
19724 break;
19725 case NM_LSA:
19726 /* In nanoMIPS, the shift field directly encodes the shift
19727 * amount, meaning that the supported shift values are in
19728 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
19729 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
19730 extract32(ctx->opcode, 9, 2) - 1);
19731 break;
821f2008
JH
19732 case NM_EXTW:
19733 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
19734 break;
64224187
YK
19735 case NM_POOL32AXF:
19736 gen_pool32axf_nanomips_insn(env, ctx);
19737 break;
19738 default:
19739 generate_exception_end(ctx, EXCP_RI);
19740 break;
19741 }
e0cf0e65
YK
19742 break;
19743 default:
19744 generate_exception_end(ctx, EXCP_RI);
19745 break;
19746 }
c0280983
YK
19747 break;
19748 case NM_P_GP_W:
19749 switch (ctx->opcode & 0x03) {
19750 case NM_ADDIUGP_W:
19751 if (rt != 0) {
19752 offset = extract32(ctx->opcode, 0, 21);
19753 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
19754 }
19755 break;
19756 case NM_LWGP:
19757 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
19758 break;
19759 case NM_SWGP:
19760 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
19761 break;
19762 default:
19763 generate_exception_end(ctx, EXCP_RI);
19764 break;
19765 }
19766 break;
19767 case NM_P48I:
7ef009b2
YK
19768 {
19769 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
19770 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
19771 switch (extract32(ctx->opcode, 16, 5)) {
19772 case NM_LI48:
fb32f8c8 19773 check_nms(ctx);
7ef009b2
YK
19774 if (rt != 0) {
19775 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
19776 }
19777 break;
19778 case NM_ADDIU48:
fb32f8c8 19779 check_nms(ctx);
7ef009b2
YK
19780 if (rt != 0) {
19781 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
19782 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
19783 }
19784 break;
19785 case NM_ADDIUGP48:
fb32f8c8 19786 check_nms(ctx);
7ef009b2
YK
19787 if (rt != 0) {
19788 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
19789 }
19790 break;
19791 case NM_ADDIUPC48:
fb32f8c8 19792 check_nms(ctx);
7ef009b2
YK
19793 if (rt != 0) {
19794 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
19795 addr_off);
19796
19797 tcg_gen_movi_tl(cpu_gpr[rt], addr);
19798 }
19799 break;
19800 case NM_LWPC48:
fb32f8c8 19801 check_nms(ctx);
7ef009b2
YK
19802 if (rt != 0) {
19803 TCGv t0;
19804 t0 = tcg_temp_new();
19805
19806 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
19807 addr_off);
19808
19809 tcg_gen_movi_tl(t0, addr);
19810 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
19811 tcg_temp_free(t0);
19812 }
19813 break;
19814 case NM_SWPC48:
fb32f8c8 19815 check_nms(ctx);
7ef009b2
YK
19816 {
19817 TCGv t0, t1;
19818 t0 = tcg_temp_new();
19819 t1 = tcg_temp_new();
19820
19821 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
19822 addr_off);
19823
19824 tcg_gen_movi_tl(t0, addr);
19825 gen_load_gpr(t1, rt);
19826
19827 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
19828
19829 tcg_temp_free(t0);
19830 tcg_temp_free(t1);
19831 }
19832 break;
19833 default:
19834 generate_exception_end(ctx, EXCP_RI);
19835 break;
19836 }
19837 return 6;
19838 }
c0280983
YK
19839 case NM_P_U12:
19840 switch (extract32(ctx->opcode, 12, 4)) {
19841 case NM_ORI:
19842 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
19843 break;
19844 case NM_XORI:
19845 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
19846 break;
19847 case NM_ANDI:
19848 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
19849 break;
19850 case NM_P_SR:
19851 switch (extract32(ctx->opcode, 20, 1)) {
19852 case NM_PP_SR:
19853 switch (ctx->opcode & 3) {
19854 case NM_SAVE:
19855 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
19856 extract32(ctx->opcode, 2, 1),
19857 extract32(ctx->opcode, 3, 9) << 3);
19858 break;
19859 case NM_RESTORE:
19860 case NM_RESTORE_JRC:
19861 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
19862 extract32(ctx->opcode, 2, 1),
19863 extract32(ctx->opcode, 3, 9) << 3);
19864 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
19865 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
19866 }
19867 break;
19868 default:
19869 generate_exception_end(ctx, EXCP_RI);
19870 break;
19871 }
19872 break;
19873 case NM_P_SR_F:
19874 generate_exception_end(ctx, EXCP_RI);
19875 break;
19876 }
19877 break;
19878 case NM_SLTI:
19879 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
19880 break;
19881 case NM_SLTIU:
19882 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
19883 break;
19884 case NM_SEQI:
19885 {
19886 TCGv t0 = tcg_temp_new();
19887
19888 imm = extract32(ctx->opcode, 0, 12);
19889 gen_load_gpr(t0, rs);
19890 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
19891 gen_store_gpr(t0, rt);
19892
19893 tcg_temp_free(t0);
19894 }
19895 break;
19896 case NM_ADDIUNEG:
19897 imm = (int16_t) extract32(ctx->opcode, 0, 12);
19898 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
19899 break;
19900 case NM_P_SHIFT:
19901 {
19902 int shift = extract32(ctx->opcode, 0, 5);
19903 switch (extract32(ctx->opcode, 5, 4)) {
19904 case NM_P_SLL:
19905 if (rt == 0 && shift == 0) {
19906 /* NOP */
19907 } else if (rt == 0 && shift == 3) {
19908 /* EHB - treat as NOP */
19909 } else if (rt == 0 && shift == 5) {
19910 /* PAUSE - treat as NOP */
19911 } else if (rt == 0 && shift == 6) {
19912 /* SYNC */
19913 gen_sync(extract32(ctx->opcode, 16, 5));
19914 } else {
19915 /* SLL */
19916 gen_shift_imm(ctx, OPC_SLL, rt, rs,
19917 extract32(ctx->opcode, 0, 5));
19918 }
19919 break;
19920 case NM_SRL:
19921 gen_shift_imm(ctx, OPC_SRL, rt, rs,
19922 extract32(ctx->opcode, 0, 5));
19923 break;
19924 case NM_SRA:
19925 gen_shift_imm(ctx, OPC_SRA, rt, rs,
19926 extract32(ctx->opcode, 0, 5));
19927 break;
19928 case NM_ROTR:
19929 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
19930 extract32(ctx->opcode, 0, 5));
19931 break;
19932 }
19933 }
19934 break;
19935 case NM_P_ROTX:
fb32f8c8 19936 check_nms(ctx);
e222f506
MF
19937 if (rt != 0) {
19938 TCGv t0 = tcg_temp_new();
19939 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
19940 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
19941 << 1);
19942 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
19943
19944 gen_load_gpr(t0, rs);
19945 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
19946 tcg_temp_free(t0);
19947
19948 tcg_temp_free_i32(shift);
19949 tcg_temp_free_i32(shiftx);
19950 tcg_temp_free_i32(stripe);
19951 }
c0280983
YK
19952 break;
19953 case NM_P_INS:
19954 switch (((ctx->opcode >> 10) & 2) |
19955 (extract32(ctx->opcode, 5, 1))) {
19956 case NM_INS:
fb32f8c8 19957 check_nms(ctx);
c0280983
YK
19958 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
19959 extract32(ctx->opcode, 6, 5));
19960 break;
19961 default:
19962 generate_exception_end(ctx, EXCP_RI);
19963 break;
19964 }
19965 break;
19966 case NM_P_EXT:
19967 switch (((ctx->opcode >> 10) & 2) |
19968 (extract32(ctx->opcode, 5, 1))) {
19969 case NM_EXT:
fb32f8c8 19970 check_nms(ctx);
c0280983
YK
19971 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
19972 extract32(ctx->opcode, 6, 5));
19973 break;
19974 default:
19975 generate_exception_end(ctx, EXCP_RI);
19976 break;
19977 }
19978 break;
19979 default:
19980 generate_exception_end(ctx, EXCP_RI);
19981 break;
19982 }
19983 break;
19984 case NM_POOL32F:
579b8ea9 19985 gen_pool32f_nanomips_insn(ctx);
c0280983
YK
19986 break;
19987 case NM_POOL32S:
19988 break;
19989 case NM_P_LUI:
19990 switch (extract32(ctx->opcode, 1, 1)) {
19991 case NM_LUI:
19992 if (rt != 0) {
19993 tcg_gen_movi_tl(cpu_gpr[rt],
19994 sextract32(ctx->opcode, 0, 1) << 31 |
19995 extract32(ctx->opcode, 2, 10) << 21 |
19996 extract32(ctx->opcode, 12, 9) << 12);
19997 }
19998 break;
19999 case NM_ALUIPC:
20000 if (rt != 0) {
20001 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20002 extract32(ctx->opcode, 2, 10) << 21 |
20003 extract32(ctx->opcode, 12, 9) << 12;
20004 target_long addr;
20005 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20006 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20007 }
20008 break;
20009 }
20010 break;
20011 case NM_P_GP_BH:
8f1d9b6d
YK
20012 {
20013 uint32_t u = extract32(ctx->opcode, 0, 18);
20014
20015 switch (extract32(ctx->opcode, 18, 3)) {
20016 case NM_LBGP:
20017 gen_ld(ctx, OPC_LB, rt, 28, u);
20018 break;
20019 case NM_SBGP:
20020 gen_st(ctx, OPC_SB, rt, 28, u);
20021 break;
20022 case NM_LBUGP:
20023 gen_ld(ctx, OPC_LBU, rt, 28, u);
20024 break;
20025 case NM_ADDIUGP_B:
20026 if (rt != 0) {
20027 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
20028 }
20029 break;
20030 case NM_P_GP_LH:
20031 u &= ~1;
20032 switch (ctx->opcode & 1) {
20033 case NM_LHGP:
20034 gen_ld(ctx, OPC_LH, rt, 28, u);
20035 break;
20036 case NM_LHUGP:
20037 gen_ld(ctx, OPC_LHU, rt, 28, u);
20038 break;
20039 }
20040 break;
20041 case NM_P_GP_SH:
20042 u &= ~1;
20043 switch (ctx->opcode & 1) {
20044 case NM_SHGP:
20045 gen_st(ctx, OPC_SH, rt, 28, u);
20046 break;
20047 default:
20048 generate_exception_end(ctx, EXCP_RI);
20049 break;
20050 }
20051 break;
20052 case NM_P_GP_CP1:
20053 u &= ~0x3;
20054 switch (ctx->opcode & 0x3) {
20055 case NM_LWC1GP:
20056 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
20057 break;
20058 case NM_LDC1GP:
20059 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
20060 break;
20061 case NM_SWC1GP:
20062 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
20063 break;
20064 case NM_SDC1GP:
20065 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
20066 break;
20067 }
20068 break;
20069 default:
20070 generate_exception_end(ctx, EXCP_RI);
20071 break;
20072 }
20073 }
c0280983
YK
20074 break;
20075 case NM_P_LS_U12:
8f1d9b6d
YK
20076 {
20077 uint32_t u = extract32(ctx->opcode, 0, 12);
20078
20079 switch (extract32(ctx->opcode, 12, 4)) {
20080 case NM_P_PREFU12:
20081 if (rt == 31) {
20082 /* SYNCI */
20083 /* Break the TB to be able to sync copied instructions
20084 immediately */
20085 ctx->base.is_jmp = DISAS_STOP;
20086 } else {
20087 /* PREF */
20088 /* Treat as NOP. */
20089 }
20090 break;
20091 case NM_LB:
20092 gen_ld(ctx, OPC_LB, rt, rs, u);
20093 break;
20094 case NM_LH:
20095 gen_ld(ctx, OPC_LH, rt, rs, u);
20096 break;
20097 case NM_LW:
20098 gen_ld(ctx, OPC_LW, rt, rs, u);
20099 break;
20100 case NM_LBU:
20101 gen_ld(ctx, OPC_LBU, rt, rs, u);
20102 break;
20103 case NM_LHU:
20104 gen_ld(ctx, OPC_LHU, rt, rs, u);
20105 break;
20106 case NM_SB:
20107 gen_st(ctx, OPC_SB, rt, rs, u);
20108 break;
20109 case NM_SH:
20110 gen_st(ctx, OPC_SH, rt, rs, u);
20111 break;
20112 case NM_SW:
20113 gen_st(ctx, OPC_SW, rt, rs, u);
20114 break;
20115 case NM_LWC1:
20116 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
20117 break;
20118 case NM_LDC1:
20119 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
20120 break;
20121 case NM_SWC1:
20122 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
20123 break;
20124 case NM_SDC1:
20125 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
20126 break;
20127 default:
20128 generate_exception_end(ctx, EXCP_RI);
20129 break;
20130 }
20131 }
c0280983
YK
20132 break;
20133 case NM_P_LS_S9:
8f1d9b6d
YK
20134 {
20135 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
20136 extract32(ctx->opcode, 0, 8);
20137
20138 switch (extract32(ctx->opcode, 8, 3)) {
20139 case NM_P_LS_S0:
20140 switch (extract32(ctx->opcode, 11, 4)) {
20141 case NM_LBS9:
20142 gen_ld(ctx, OPC_LB, rt, rs, s);
20143 break;
20144 case NM_LHS9:
20145 gen_ld(ctx, OPC_LH, rt, rs, s);
20146 break;
20147 case NM_LWS9:
20148 gen_ld(ctx, OPC_LW, rt, rs, s);
20149 break;
20150 case NM_LBUS9:
20151 gen_ld(ctx, OPC_LBU, rt, rs, s);
20152 break;
20153 case NM_LHUS9:
20154 gen_ld(ctx, OPC_LHU, rt, rs, s);
20155 break;
20156 case NM_SBS9:
20157 gen_st(ctx, OPC_SB, rt, rs, s);
20158 break;
20159 case NM_SHS9:
20160 gen_st(ctx, OPC_SH, rt, rs, s);
20161 break;
20162 case NM_SWS9:
20163 gen_st(ctx, OPC_SW, rt, rs, s);
20164 break;
20165 case NM_LWC1S9:
20166 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
20167 break;
20168 case NM_LDC1S9:
20169 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
20170 break;
20171 case NM_SWC1S9:
20172 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
20173 break;
20174 case NM_SDC1S9:
20175 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
20176 break;
20177 case NM_P_PREFS9:
20178 if (rt == 31) {
20179 /* SYNCI */
20180 /* Break the TB to be able to sync copied instructions
20181 immediately */
20182 ctx->base.is_jmp = DISAS_STOP;
20183 } else {
20184 /* PREF */
20185 /* Treat as NOP. */
20186 }
20187 break;
20188 default:
20189 generate_exception_end(ctx, EXCP_RI);
20190 break;
20191 }
20192 break;
20193 case NM_P_LS_S1:
20194 switch (extract32(ctx->opcode, 11, 4)) {
20195 case NM_UALH:
20196 case NM_UASH:
fb32f8c8 20197 check_nms(ctx);
8f1d9b6d
YK
20198 {
20199 TCGv t0 = tcg_temp_new();
20200 TCGv t1 = tcg_temp_new();
20201
20202 gen_base_offset_addr(ctx, t0, rs, s);
20203
20204 switch (extract32(ctx->opcode, 11, 4)) {
20205 case NM_UALH:
20206 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
20207 MO_UNALN);
20208 gen_store_gpr(t0, rt);
20209 break;
20210 case NM_UASH:
20211 gen_load_gpr(t1, rt);
20212 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
20213 MO_UNALN);
20214 break;
20215 }
20216 tcg_temp_free(t0);
20217 tcg_temp_free(t1);
20218 }
20219 break;
20220 case NM_P_LL:
20221 switch (ctx->opcode & 0x03) {
20222 case NM_LL:
20223 gen_ld(ctx, OPC_LL, rt, rs, s);
20224 break;
20225 case NM_LLWP:
0b16dcd1
AR
20226 check_xnp(ctx);
20227 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
20228 break;
20229 }
20230 break;
20231 case NM_P_SC:
20232 switch (ctx->opcode & 0x03) {
20233 case NM_SC:
20234 gen_st_cond(ctx, OPC_SC, rt, rs, s);
20235 break;
20236 case NM_SCWP:
0b16dcd1
AR
20237 check_xnp(ctx);
20238 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
20239 break;
20240 }
20241 break;
20242 case NM_CACHE:
20243 check_cp0_enabled(ctx);
20244 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
20245 gen_cache_operation(ctx, rt, rs, s);
20246 }
20247 break;
20248 }
20249 break;
20250 case NM_P_LS_WM:
20251 case NM_P_LS_UAWM:
fb32f8c8 20252 check_nms(ctx);
8f1d9b6d
YK
20253 {
20254 int count = extract32(ctx->opcode, 12, 3);
20255 int counter = 0;
20256
20257 offset = sextract32(ctx->opcode, 15, 1) << 8 |
20258 extract32(ctx->opcode, 0, 8);
20259 TCGv va = tcg_temp_new();
20260 TCGv t1 = tcg_temp_new();
20261 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
20262 NM_P_LS_UAWM ? MO_UNALN : 0;
20263
20264 count = (count == 0) ? 8 : count;
20265 while (counter != count) {
20266 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
20267 int this_offset = offset + (counter << 2);
20268
20269 gen_base_offset_addr(ctx, va, rs, this_offset);
20270
20271 switch (extract32(ctx->opcode, 11, 1)) {
20272 case NM_LWM:
20273 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
20274 memop | MO_TESL);
20275 gen_store_gpr(t1, this_rt);
20276 if ((this_rt == rs) &&
20277 (counter != (count - 1))) {
20278 /* UNPREDICTABLE */
20279 }
20280 break;
20281 case NM_SWM:
20282 this_rt = (rt == 0) ? 0 : this_rt;
20283 gen_load_gpr(t1, this_rt);
20284 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
20285 memop | MO_TEUL);
20286 break;
20287 }
20288 counter++;
20289 }
20290 tcg_temp_free(va);
20291 tcg_temp_free(t1);
20292 }
20293 break;
20294 default:
20295 generate_exception_end(ctx, EXCP_RI);
20296 break;
20297 }
20298 }
c0280983
YK
20299 break;
20300 case NM_MOVE_BALC:
fb32f8c8 20301 check_nms(ctx);
11d0fc10
SM
20302 {
20303 TCGv t0 = tcg_temp_new();
20304 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
20305 extract32(ctx->opcode, 1, 20) << 1;
20306 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
20307 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
20308 extract32(ctx->opcode, 21, 3));
20309 gen_load_gpr(t0, rt);
20310 tcg_gen_mov_tl(cpu_gpr[rd], t0);
20311 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
20312 tcg_temp_free(t0);
20313 }
c0280983
YK
20314 break;
20315 case NM_P_BAL:
11d0fc10
SM
20316 {
20317 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
20318 extract32(ctx->opcode, 1, 24) << 1;
20319
20320 if ((extract32(ctx->opcode, 25, 1)) == 0) {
20321 /* BC */
20322 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
20323 } else {
20324 /* BALC */
20325 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
20326 }
20327 }
c0280983
YK
20328 break;
20329 case NM_P_J:
11d0fc10
SM
20330 switch (extract32(ctx->opcode, 12, 4)) {
20331 case NM_JALRC:
20332 case NM_JALRC_HB:
20333 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
20334 break;
20335 case NM_P_BALRSC:
20336 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
20337 break;
20338 default:
20339 generate_exception_end(ctx, EXCP_RI);
20340 break;
20341 }
c0280983
YK
20342 break;
20343 case NM_P_BR1:
11d0fc10
SM
20344 {
20345 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
20346 extract32(ctx->opcode, 1, 13) << 1;
20347 switch (extract32(ctx->opcode, 14, 2)) {
20348 case NM_BEQC:
fb32f8c8 20349 check_nms(ctx);
11d0fc10
SM
20350 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
20351 break;
20352 case NM_P_BR3A:
20353 s = sextract32(ctx->opcode, 0, 1) << 14 |
20354 extract32(ctx->opcode, 1, 13) << 1;
20355 check_cp1_enabled(ctx);
20356 switch (extract32(ctx->opcode, 16, 5)) {
20357 case NM_BC1EQZC:
20358 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
20359 break;
20360 case NM_BC1NEZC:
20361 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
20362 break;
6d033ca7
SM
20363 case NM_BPOSGE32C:
20364 check_dspr2(ctx);
20365 {
20366 int32_t imm = extract32(ctx->opcode, 1, 13) |
20367 extract32(ctx->opcode, 0, 1) << 13;
20368
20369 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
20370 imm);
20371 }
20372 break;
11d0fc10
SM
20373 default:
20374 generate_exception_end(ctx, EXCP_RI);
20375 break;
20376 }
20377 break;
20378 case NM_BGEC:
20379 if (rs == rt) {
20380 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
20381 } else {
20382 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
20383 }
20384 break;
20385 case NM_BGEUC:
20386 if (rs == rt || rt == 0) {
20387 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
20388 } else if (rs == 0) {
20389 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
20390 } else {
20391 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
20392 }
20393 break;
20394 }
20395 }
c0280983
YK
20396 break;
20397 case NM_P_BR2:
11d0fc10
SM
20398 {
20399 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
20400 extract32(ctx->opcode, 1, 13) << 1;
20401 switch (extract32(ctx->opcode, 14, 2)) {
20402 case NM_BNEC:
fb32f8c8 20403 check_nms(ctx);
11d0fc10
SM
20404 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
20405 break;
20406 case NM_BLTC:
20407 if (rs != 0 && rt != 0 && rs == rt) {
20408 /* NOP */
20409 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
20410 } else {
20411 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
20412 }
20413 break;
20414 case NM_BLTUC:
20415 if (rs == 0 || rs == rt) {
20416 /* NOP */
20417 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
20418 } else {
20419 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
20420 }
20421 break;
20422 default:
20423 generate_exception_end(ctx, EXCP_RI);
20424 break;
20425 }
20426 }
c0280983
YK
20427 break;
20428 case NM_P_BRI:
11d0fc10
SM
20429 {
20430 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
20431 extract32(ctx->opcode, 1, 10) << 1;
20432 uint32_t u = extract32(ctx->opcode, 11, 7);
20433
20434 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
20435 rt, u, s);
20436 }
c0280983
YK
20437 break;
20438 default:
20439 generate_exception_end(ctx, EXCP_RI);
20440 break;
20441 }
20442 return 4;
20443}
20444
c533c0f4
AM
20445static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
20446{
ea4ca3c2
YK
20447 uint32_t op;
20448 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
20449 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
20450 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
8bdb7029 20451 int offset;
ea4ca3c2
YK
20452 int imm;
20453
20454 /* make sure instructions are on a halfword boundary */
20455 if (ctx->base.pc_next & 0x1) {
20456 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
20457 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
20458 tcg_temp_free(tmp);
20459 generate_exception_end(ctx, EXCP_AdEL);
20460 return 2;
20461 }
20462
20463 op = extract32(ctx->opcode, 10, 6);
20464 switch (op) {
20465 case NM_P16_MV:
8869ad02
YK
20466 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
20467 if (rt != 0) {
20468 /* MOVE */
20469 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
20470 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
20471 } else {
20472 /* P16.RI */
20473 switch (extract32(ctx->opcode, 3, 2)) {
20474 case NM_P16_SYSCALL:
20475 if (extract32(ctx->opcode, 2, 1) == 0) {
20476 generate_exception_end(ctx, EXCP_SYSCALL);
20477 } else {
20478 generate_exception_end(ctx, EXCP_RI);
20479 }
20480 break;
20481 case NM_BREAK16:
20482 generate_exception_end(ctx, EXCP_BREAK);
20483 break;
20484 case NM_SDBBP16:
20485 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
20486 gen_helper_do_semihosting(cpu_env);
20487 } else {
20488 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20489 generate_exception_end(ctx, EXCP_RI);
20490 } else {
20491 generate_exception_end(ctx, EXCP_DBp);
20492 }
20493 }
20494 break;
20495 default:
20496 generate_exception_end(ctx, EXCP_RI);
20497 break;
20498 }
20499 }
ea4ca3c2
YK
20500 break;
20501 case NM_P16_SHIFT:
c46562fb
YK
20502 {
20503 int shift = extract32(ctx->opcode, 0, 3);
20504 uint32_t opc = 0;
20505 shift = (shift == 0) ? 8 : shift;
20506
20507 switch (extract32(ctx->opcode, 3, 1)) {
20508 case NM_SLL16:
20509 opc = OPC_SLL;
20510 break;
20511 case NM_SRL16:
20512 opc = OPC_SRL;
20513 break;
20514 }
20515 gen_shift_imm(ctx, opc, rt, rs, shift);
20516 }
ea4ca3c2
YK
20517 break;
20518 case NM_P16C:
8bdb7029
YK
20519 switch (ctx->opcode & 1) {
20520 case NM_POOL16C_0:
80845edf 20521 gen_pool16c_nanomips_insn(ctx);
8bdb7029
YK
20522 break;
20523 case NM_LWXS16:
20524 gen_ldxs(ctx, rt, rs, rd);
20525 break;
20526 }
ea4ca3c2
YK
20527 break;
20528 case NM_P16_A1:
20529 switch (extract32(ctx->opcode, 6, 1)) {
20530 case NM_ADDIUR1SP:
20531 imm = extract32(ctx->opcode, 0, 6) << 2;
20532 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
20533 break;
20534 default:
20535 generate_exception_end(ctx, EXCP_RI);
20536 break;
20537 }
20538 break;
20539 case NM_P16_A2:
20540 switch (extract32(ctx->opcode, 3, 1)) {
20541 case NM_ADDIUR2:
20542 imm = extract32(ctx->opcode, 0, 3) << 2;
20543 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
20544 break;
20545 case NM_P_ADDIURS5:
20546 rt = extract32(ctx->opcode, 5, 5);
20547 if (rt != 0) {
20548 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
20549 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
20550 (extract32(ctx->opcode, 0, 3));
20551 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
20552 }
20553 break;
20554 }
20555 break;
20556 case NM_P16_ADDU:
20557 switch (ctx->opcode & 0x1) {
20558 case NM_ADDU16:
20559 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
20560 break;
20561 case NM_SUBU16:
20562 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
20563 break;
20564 }
20565 break;
20566 case NM_P16_4X4:
20567 rt = (extract32(ctx->opcode, 9, 1) << 3) |
20568 extract32(ctx->opcode, 5, 3);
20569 rs = (extract32(ctx->opcode, 4, 1) << 3) |
20570 extract32(ctx->opcode, 0, 3);
20571 rt = decode_gpr_gpr4(rt);
20572 rs = decode_gpr_gpr4(rs);
20573 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
20574 (extract32(ctx->opcode, 3, 1))) {
20575 case NM_ADDU4X4:
fb32f8c8 20576 check_nms(ctx);
ea4ca3c2
YK
20577 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
20578 break;
20579 case NM_MUL4X4:
fb32f8c8 20580 check_nms(ctx);
ea4ca3c2
YK
20581 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
20582 break;
20583 default:
20584 generate_exception_end(ctx, EXCP_RI);
20585 break;
20586 }
20587 break;
20588 case NM_LI16:
8869ad02
YK
20589 {
20590 int imm = extract32(ctx->opcode, 0, 7);
20591 imm = (imm == 0x7f ? -1 : imm);
20592 if (rt != 0) {
20593 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20594 }
20595 }
ea4ca3c2
YK
20596 break;
20597 case NM_ANDI16:
80845edf
YK
20598 {
20599 uint32_t u = extract32(ctx->opcode, 0, 4);
20600 u = (u == 12) ? 0xff :
20601 (u == 13) ? 0xffff : u;
20602 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
20603 }
ea4ca3c2
YK
20604 break;
20605 case NM_P16_LB:
8bdb7029
YK
20606 offset = extract32(ctx->opcode, 0, 2);
20607 switch (extract32(ctx->opcode, 2, 2)) {
20608 case NM_LB16:
20609 gen_ld(ctx, OPC_LB, rt, rs, offset);
20610 break;
20611 case NM_SB16:
20612 rt = decode_gpr_gpr3_src_store(
20613 NANOMIPS_EXTRACT_RD(ctx->opcode));
20614 gen_st(ctx, OPC_SB, rt, rs, offset);
20615 break;
20616 case NM_LBU16:
20617 gen_ld(ctx, OPC_LBU, rt, rs, offset);
20618 break;
20619 default:
20620 generate_exception_end(ctx, EXCP_RI);
20621 break;
20622 }
ea4ca3c2
YK
20623 break;
20624 case NM_P16_LH:
8bdb7029
YK
20625 offset = extract32(ctx->opcode, 1, 2) << 1;
20626 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
20627 case NM_LH16:
20628 gen_ld(ctx, OPC_LH, rt, rs, offset);
20629 break;
20630 case NM_SH16:
20631 rt = decode_gpr_gpr3_src_store(
20632 NANOMIPS_EXTRACT_RD(ctx->opcode));
20633 gen_st(ctx, OPC_SH, rt, rs, offset);
20634 break;
20635 case NM_LHU16:
20636 gen_ld(ctx, OPC_LHU, rt, rs, offset);
20637 break;
20638 default:
20639 generate_exception_end(ctx, EXCP_RI);
20640 break;
20641 }
ea4ca3c2
YK
20642 break;
20643 case NM_LW16:
8bdb7029
YK
20644 offset = extract32(ctx->opcode, 0, 4) << 2;
20645 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
20646 break;
20647 case NM_LWSP16:
8bdb7029
YK
20648 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
20649 offset = extract32(ctx->opcode, 0, 5) << 2;
20650 gen_ld(ctx, OPC_LW, rt, 29, offset);
ea4ca3c2
YK
20651 break;
20652 case NM_LW4X4:
fb32f8c8 20653 check_nms(ctx);
8bdb7029
YK
20654 rt = (extract32(ctx->opcode, 9, 1) << 3) |
20655 extract32(ctx->opcode, 5, 3);
20656 rs = (extract32(ctx->opcode, 4, 1) << 3) |
20657 extract32(ctx->opcode, 0, 3);
20658 offset = (extract32(ctx->opcode, 3, 1) << 3) |
20659 (extract32(ctx->opcode, 8, 1) << 2);
20660 rt = decode_gpr_gpr4(rt);
20661 rs = decode_gpr_gpr4(rs);
20662 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
20663 break;
20664 case NM_SW4X4:
fb32f8c8 20665 check_nms(ctx);
8bdb7029
YK
20666 rt = (extract32(ctx->opcode, 9, 1) << 3) |
20667 extract32(ctx->opcode, 5, 3);
20668 rs = (extract32(ctx->opcode, 4, 1) << 3) |
20669 extract32(ctx->opcode, 0, 3);
20670 offset = (extract32(ctx->opcode, 3, 1) << 3) |
20671 (extract32(ctx->opcode, 8, 1) << 2);
20672 rt = decode_gpr_gpr4_zero(rt);
20673 rs = decode_gpr_gpr4(rs);
20674 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
20675 break;
20676 case NM_LWGP16:
8bdb7029
YK
20677 offset = extract32(ctx->opcode, 0, 7) << 2;
20678 gen_ld(ctx, OPC_LW, rt, 28, offset);
ea4ca3c2
YK
20679 break;
20680 case NM_SWSP16:
8bdb7029
YK
20681 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
20682 offset = extract32(ctx->opcode, 0, 5) << 2;
20683 gen_st(ctx, OPC_SW, rt, 29, offset);
ea4ca3c2
YK
20684 break;
20685 case NM_SW16:
8bdb7029
YK
20686 rt = decode_gpr_gpr3_src_store(
20687 NANOMIPS_EXTRACT_RD(ctx->opcode));
20688 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
20689 offset = extract32(ctx->opcode, 0, 4) << 2;
20690 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
20691 break;
20692 case NM_SWGP16:
8bdb7029
YK
20693 rt = decode_gpr_gpr3_src_store(
20694 NANOMIPS_EXTRACT_RD(ctx->opcode));
20695 offset = extract32(ctx->opcode, 0, 7) << 2;
20696 gen_st(ctx, OPC_SW, rt, 28, offset);
ea4ca3c2
YK
20697 break;
20698 case NM_BC16:
764371d2
SM
20699 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
20700 (sextract32(ctx->opcode, 0, 1) << 10) |
20701 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
20702 break;
20703 case NM_BALC16:
764371d2
SM
20704 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
20705 (sextract32(ctx->opcode, 0, 1) << 10) |
20706 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
20707 break;
20708 case NM_BEQZC16:
764371d2
SM
20709 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
20710 (sextract32(ctx->opcode, 0, 1) << 7) |
20711 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
20712 break;
20713 case NM_BNEZC16:
764371d2
SM
20714 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
20715 (sextract32(ctx->opcode, 0, 1) << 7) |
20716 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
20717 break;
20718 case NM_P16_BR:
764371d2
SM
20719 switch (ctx->opcode & 0xf) {
20720 case 0:
20721 /* P16.JRC */
20722 switch (extract32(ctx->opcode, 4, 1)) {
20723 case NM_JRC:
20724 gen_compute_branch_nm(ctx, OPC_JR, 2,
20725 extract32(ctx->opcode, 5, 5), 0, 0);
20726 break;
20727 case NM_JALRC16:
20728 gen_compute_branch_nm(ctx, OPC_JALR, 2,
20729 extract32(ctx->opcode, 5, 5), 31, 0);
20730 break;
20731 }
20732 break;
20733 default:
20734 {
20735 /* P16.BRI */
20736 uint32_t opc = extract32(ctx->opcode, 4, 3) <
20737 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
20738 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
20739 extract32(ctx->opcode, 0, 4) << 1);
20740 }
20741 break;
20742 }
ea4ca3c2
YK
20743 break;
20744 case NM_P16_SR:
bf0718c5
SM
20745 {
20746 int count = extract32(ctx->opcode, 0, 4);
20747 int u = extract32(ctx->opcode, 4, 4) << 4;
20748
20749 rt = 30 + extract32(ctx->opcode, 9, 1);
20750 switch (extract32(ctx->opcode, 8, 1)) {
20751 case NM_SAVE16:
20752 gen_save(ctx, rt, count, 0, u);
20753 break;
20754 case NM_RESTORE_JRC16:
20755 gen_restore(ctx, rt, count, 0, u);
20756 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20757 break;
20758 }
20759 }
ea4ca3c2
YK
20760 break;
20761 case NM_MOVEP:
ea4ca3c2 20762 case NM_MOVEPREV:
fb32f8c8 20763 check_nms(ctx);
4d18232c
YK
20764 {
20765 static const int gpr2reg1[] = {4, 5, 6, 7};
20766 static const int gpr2reg2[] = {5, 6, 7, 8};
20767 int re;
20768 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
20769 extract32(ctx->opcode, 8, 1);
20770 int r1 = gpr2reg1[rd2];
20771 int r2 = gpr2reg2[rd2];
20772 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
20773 extract32(ctx->opcode, 0, 3);
20774 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
20775 extract32(ctx->opcode, 5, 3);
20776 TCGv t0 = tcg_temp_new();
20777 TCGv t1 = tcg_temp_new();
20778 if (op == NM_MOVEP) {
20779 rd = r1;
20780 re = r2;
20781 rs = decode_gpr_gpr4_zero(r3);
20782 rt = decode_gpr_gpr4_zero(r4);
20783 } else {
20784 rd = decode_gpr_gpr4(r3);
20785 re = decode_gpr_gpr4(r4);
20786 rs = r1;
20787 rt = r2;
20788 }
20789 gen_load_gpr(t0, rs);
20790 gen_load_gpr(t1, rt);
20791 tcg_gen_mov_tl(cpu_gpr[rd], t0);
20792 tcg_gen_mov_tl(cpu_gpr[re], t1);
20793 tcg_temp_free(t0);
20794 tcg_temp_free(t1);
20795 }
ea4ca3c2
YK
20796 break;
20797 default:
c0280983 20798 return decode_nanomips_32_48_opc(env, ctx);
ea4ca3c2
YK
20799 }
20800
c533c0f4
AM
20801 return 2;
20802}
20803
20804
3c824109
NF
20805/* SmartMIPS extension to MIPS32 */
20806
20807#if defined(TARGET_MIPS64)
20808
20809/* MDMX extension to MIPS64 */
20810
20811#endif
20812
9b1a1d68 20813/* MIPSDSP functions. */
d75c135e 20814static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
9b1a1d68
JL
20815 int rd, int base, int offset)
20816{
9b1a1d68
JL
20817 TCGv t0;
20818
9b1a1d68
JL
20819 check_dsp(ctx);
20820 t0 = tcg_temp_new();
20821
20822 if (base == 0) {
20823 gen_load_gpr(t0, offset);
20824 } else if (offset == 0) {
20825 gen_load_gpr(t0, base);
20826 } else {
20827 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
20828 }
20829
9b1a1d68
JL
20830 switch (opc) {
20831 case OPC_LBUX:
5f68f5ae 20832 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
9b1a1d68 20833 gen_store_gpr(t0, rd);
9b1a1d68
JL
20834 break;
20835 case OPC_LHX:
5f68f5ae 20836 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
9b1a1d68 20837 gen_store_gpr(t0, rd);
9b1a1d68
JL
20838 break;
20839 case OPC_LWX:
5f68f5ae 20840 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9b1a1d68 20841 gen_store_gpr(t0, rd);
9b1a1d68
JL
20842 break;
20843#if defined(TARGET_MIPS64)
20844 case OPC_LDX:
5f68f5ae 20845 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
9b1a1d68 20846 gen_store_gpr(t0, rd);
9b1a1d68
JL
20847 break;
20848#endif
20849 }
9b1a1d68
JL
20850 tcg_temp_free(t0);
20851}
20852
461c08df
JL
20853static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
20854 int ret, int v1, int v2)
20855{
461c08df
JL
20856 TCGv v1_t;
20857 TCGv v2_t;
20858
20859 if (ret == 0) {
20860 /* Treat as NOP. */
461c08df
JL
20861 return;
20862 }
20863
20864 v1_t = tcg_temp_new();
20865 v2_t = tcg_temp_new();
20866
20867 gen_load_gpr(v1_t, v1);
20868 gen_load_gpr(v2_t, v2);
20869
20870 switch (op1) {
20871 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
20872 case OPC_MULT_G_2E:
20873 check_dspr2(ctx);
20874 switch (op2) {
20875 case OPC_ADDUH_QB:
20876 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
20877 break;
20878 case OPC_ADDUH_R_QB:
20879 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
20880 break;
20881 case OPC_ADDQH_PH:
20882 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
20883 break;
20884 case OPC_ADDQH_R_PH:
20885 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
20886 break;
20887 case OPC_ADDQH_W:
20888 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
20889 break;
20890 case OPC_ADDQH_R_W:
20891 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
20892 break;
20893 case OPC_SUBUH_QB:
20894 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
20895 break;
20896 case OPC_SUBUH_R_QB:
20897 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
20898 break;
20899 case OPC_SUBQH_PH:
20900 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
20901 break;
20902 case OPC_SUBQH_R_PH:
20903 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
20904 break;
20905 case OPC_SUBQH_W:
20906 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
20907 break;
20908 case OPC_SUBQH_R_W:
20909 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
20910 break;
20911 }
20912 break;
20913 case OPC_ABSQ_S_PH_DSP:
20914 switch (op2) {
20915 case OPC_ABSQ_S_QB:
20916 check_dspr2(ctx);
20917 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
20918 break;
20919 case OPC_ABSQ_S_PH:
20920 check_dsp(ctx);
20921 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
20922 break;
20923 case OPC_ABSQ_S_W:
20924 check_dsp(ctx);
20925 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
20926 break;
20927 case OPC_PRECEQ_W_PHL:
20928 check_dsp(ctx);
20929 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
20930 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
20931 break;
20932 case OPC_PRECEQ_W_PHR:
20933 check_dsp(ctx);
20934 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
20935 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
20936 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
20937 break;
20938 case OPC_PRECEQU_PH_QBL:
20939 check_dsp(ctx);
20940 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
20941 break;
20942 case OPC_PRECEQU_PH_QBR:
20943 check_dsp(ctx);
20944 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
20945 break;
20946 case OPC_PRECEQU_PH_QBLA:
20947 check_dsp(ctx);
20948 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
20949 break;
20950 case OPC_PRECEQU_PH_QBRA:
20951 check_dsp(ctx);
20952 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
20953 break;
20954 case OPC_PRECEU_PH_QBL:
20955 check_dsp(ctx);
20956 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
20957 break;
20958 case OPC_PRECEU_PH_QBR:
20959 check_dsp(ctx);
20960 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
20961 break;
20962 case OPC_PRECEU_PH_QBLA:
20963 check_dsp(ctx);
20964 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
20965 break;
20966 case OPC_PRECEU_PH_QBRA:
20967 check_dsp(ctx);
20968 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
20969 break;
20970 }
20971 break;
20972 case OPC_ADDU_QB_DSP:
20973 switch (op2) {
20974 case OPC_ADDQ_PH:
20975 check_dsp(ctx);
20976 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20977 break;
20978 case OPC_ADDQ_S_PH:
20979 check_dsp(ctx);
20980 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20981 break;
20982 case OPC_ADDQ_S_W:
20983 check_dsp(ctx);
20984 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20985 break;
20986 case OPC_ADDU_QB:
20987 check_dsp(ctx);
20988 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20989 break;
20990 case OPC_ADDU_S_QB:
20991 check_dsp(ctx);
20992 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20993 break;
20994 case OPC_ADDU_PH:
20995 check_dspr2(ctx);
20996 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20997 break;
20998 case OPC_ADDU_S_PH:
20999 check_dspr2(ctx);
21000 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21001 break;
21002 case OPC_SUBQ_PH:
21003 check_dsp(ctx);
21004 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21005 break;
21006 case OPC_SUBQ_S_PH:
21007 check_dsp(ctx);
21008 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21009 break;
21010 case OPC_SUBQ_S_W:
21011 check_dsp(ctx);
21012 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21013 break;
21014 case OPC_SUBU_QB:
21015 check_dsp(ctx);
21016 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21017 break;
21018 case OPC_SUBU_S_QB:
21019 check_dsp(ctx);
21020 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21021 break;
21022 case OPC_SUBU_PH:
21023 check_dspr2(ctx);
21024 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21025 break;
21026 case OPC_SUBU_S_PH:
21027 check_dspr2(ctx);
21028 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21029 break;
21030 case OPC_ADDSC:
21031 check_dsp(ctx);
21032 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21033 break;
21034 case OPC_ADDWC:
21035 check_dsp(ctx);
21036 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21037 break;
21038 case OPC_MODSUB:
21039 check_dsp(ctx);
21040 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
21041 break;
21042 case OPC_RADDU_W_QB:
21043 check_dsp(ctx);
21044 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
21045 break;
21046 }
21047 break;
21048 case OPC_CMPU_EQ_QB_DSP:
21049 switch (op2) {
21050 case OPC_PRECR_QB_PH:
21051 check_dspr2(ctx);
21052 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21053 break;
21054 case OPC_PRECRQ_QB_PH:
21055 check_dsp(ctx);
21056 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21057 break;
21058 case OPC_PRECR_SRA_PH_W:
21059 check_dspr2(ctx);
21060 {
21061 TCGv_i32 sa_t = tcg_const_i32(v2);
21062 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
21063 cpu_gpr[ret]);
21064 tcg_temp_free_i32(sa_t);
21065 break;
21066 }
21067 case OPC_PRECR_SRA_R_PH_W:
21068 check_dspr2(ctx);
21069 {
21070 TCGv_i32 sa_t = tcg_const_i32(v2);
21071 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
21072 cpu_gpr[ret]);
21073 tcg_temp_free_i32(sa_t);
21074 break;
21075 }
21076 case OPC_PRECRQ_PH_W:
21077 check_dsp(ctx);
21078 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
21079 break;
21080 case OPC_PRECRQ_RS_PH_W:
21081 check_dsp(ctx);
21082 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21083 break;
21084 case OPC_PRECRQU_S_QB_PH:
21085 check_dsp(ctx);
21086 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21087 break;
21088 }
21089 break;
21090#ifdef TARGET_MIPS64
21091 case OPC_ABSQ_S_QH_DSP:
21092 switch (op2) {
21093 case OPC_PRECEQ_L_PWL:
21094 check_dsp(ctx);
21095 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
21096 break;
21097 case OPC_PRECEQ_L_PWR:
21098 check_dsp(ctx);
21099 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
21100 break;
21101 case OPC_PRECEQ_PW_QHL:
21102 check_dsp(ctx);
21103 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
21104 break;
21105 case OPC_PRECEQ_PW_QHR:
21106 check_dsp(ctx);
21107 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
21108 break;
21109 case OPC_PRECEQ_PW_QHLA:
21110 check_dsp(ctx);
21111 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
21112 break;
21113 case OPC_PRECEQ_PW_QHRA:
21114 check_dsp(ctx);
21115 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
21116 break;
21117 case OPC_PRECEQU_QH_OBL:
21118 check_dsp(ctx);
21119 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
21120 break;
21121 case OPC_PRECEQU_QH_OBR:
21122 check_dsp(ctx);
21123 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
21124 break;
21125 case OPC_PRECEQU_QH_OBLA:
21126 check_dsp(ctx);
21127 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
21128 break;
21129 case OPC_PRECEQU_QH_OBRA:
21130 check_dsp(ctx);
21131 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
21132 break;
21133 case OPC_PRECEU_QH_OBL:
21134 check_dsp(ctx);
21135 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
21136 break;
21137 case OPC_PRECEU_QH_OBR:
21138 check_dsp(ctx);
21139 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
21140 break;
21141 case OPC_PRECEU_QH_OBLA:
21142 check_dsp(ctx);
21143 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
21144 break;
21145 case OPC_PRECEU_QH_OBRA:
21146 check_dsp(ctx);
21147 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
21148 break;
21149 case OPC_ABSQ_S_OB:
21150 check_dspr2(ctx);
21151 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
21152 break;
21153 case OPC_ABSQ_S_PW:
21154 check_dsp(ctx);
21155 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
21156 break;
21157 case OPC_ABSQ_S_QH:
21158 check_dsp(ctx);
21159 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
21160 break;
21161 }
21162 break;
21163 case OPC_ADDU_OB_DSP:
21164 switch (op2) {
21165 case OPC_RADDU_L_OB:
21166 check_dsp(ctx);
21167 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
21168 break;
21169 case OPC_SUBQ_PW:
21170 check_dsp(ctx);
21171 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21172 break;
21173 case OPC_SUBQ_S_PW:
21174 check_dsp(ctx);
21175 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21176 break;
21177 case OPC_SUBQ_QH:
21178 check_dsp(ctx);
21179 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21180 break;
21181 case OPC_SUBQ_S_QH:
21182 check_dsp(ctx);
21183 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21184 break;
21185 case OPC_SUBU_OB:
21186 check_dsp(ctx);
21187 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21188 break;
21189 case OPC_SUBU_S_OB:
21190 check_dsp(ctx);
21191 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21192 break;
21193 case OPC_SUBU_QH:
21194 check_dspr2(ctx);
21195 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21196 break;
21197 case OPC_SUBU_S_QH:
21198 check_dspr2(ctx);
21199 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21200 break;
21201 case OPC_SUBUH_OB:
21202 check_dspr2(ctx);
21203 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
21204 break;
21205 case OPC_SUBUH_R_OB:
21206 check_dspr2(ctx);
21207 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21208 break;
21209 case OPC_ADDQ_PW:
21210 check_dsp(ctx);
21211 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21212 break;
21213 case OPC_ADDQ_S_PW:
21214 check_dsp(ctx);
21215 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21216 break;
21217 case OPC_ADDQ_QH:
21218 check_dsp(ctx);
21219 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21220 break;
21221 case OPC_ADDQ_S_QH:
21222 check_dsp(ctx);
21223 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21224 break;
21225 case OPC_ADDU_OB:
21226 check_dsp(ctx);
21227 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21228 break;
21229 case OPC_ADDU_S_OB:
21230 check_dsp(ctx);
21231 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21232 break;
21233 case OPC_ADDU_QH:
21234 check_dspr2(ctx);
21235 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21236 break;
21237 case OPC_ADDU_S_QH:
21238 check_dspr2(ctx);
21239 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21240 break;
21241 case OPC_ADDUH_OB:
21242 check_dspr2(ctx);
21243 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
21244 break;
21245 case OPC_ADDUH_R_OB:
21246 check_dspr2(ctx);
21247 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21248 break;
21249 }
21250 break;
21251 case OPC_CMPU_EQ_OB_DSP:
21252 switch (op2) {
21253 case OPC_PRECR_OB_QH:
21254 check_dspr2(ctx);
21255 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
21256 break;
21257 case OPC_PRECR_SRA_QH_PW:
21258 check_dspr2(ctx);
21259 {
21260 TCGv_i32 ret_t = tcg_const_i32(ret);
21261 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
21262 tcg_temp_free_i32(ret_t);
21263 break;
21264 }
21265 case OPC_PRECR_SRA_R_QH_PW:
21266 check_dspr2(ctx);
21267 {
21268 TCGv_i32 sa_v = tcg_const_i32(ret);
21269 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
21270 tcg_temp_free_i32(sa_v);
21271 break;
21272 }
21273 case OPC_PRECRQ_OB_QH:
21274 check_dsp(ctx);
21275 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
21276 break;
21277 case OPC_PRECRQ_PW_L:
21278 check_dsp(ctx);
21279 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
21280 break;
21281 case OPC_PRECRQ_QH_PW:
21282 check_dsp(ctx);
21283 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
21284 break;
21285 case OPC_PRECRQ_RS_QH_PW:
21286 check_dsp(ctx);
21287 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21288 break;
21289 case OPC_PRECRQU_S_OB_QH:
21290 check_dsp(ctx);
21291 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21292 break;
21293 }
21294 break;
21295#endif
21296 }
21297
21298 tcg_temp_free(v1_t);
21299 tcg_temp_free(v2_t);
461c08df 21300}
9b1a1d68 21301
77c5fa8b
JL
21302static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
21303 int ret, int v1, int v2)
21304{
21305 uint32_t op2;
77c5fa8b
JL
21306 TCGv t0;
21307 TCGv v1_t;
21308 TCGv v2_t;
21309
21310 if (ret == 0) {
21311 /* Treat as NOP. */
77c5fa8b
JL
21312 return;
21313 }
21314
21315 t0 = tcg_temp_new();
21316 v1_t = tcg_temp_new();
21317 v2_t = tcg_temp_new();
21318
21319 tcg_gen_movi_tl(t0, v1);
21320 gen_load_gpr(v1_t, v1);
21321 gen_load_gpr(v2_t, v2);
21322
21323 switch (opc) {
21324 case OPC_SHLL_QB_DSP:
21325 {
21326 op2 = MASK_SHLL_QB(ctx->opcode);
21327 switch (op2) {
21328 case OPC_SHLL_QB:
21329 check_dsp(ctx);
21330 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
21331 break;
21332 case OPC_SHLLV_QB:
21333 check_dsp(ctx);
21334 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21335 break;
21336 case OPC_SHLL_PH:
21337 check_dsp(ctx);
21338 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
21339 break;
21340 case OPC_SHLLV_PH:
21341 check_dsp(ctx);
21342 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21343 break;
21344 case OPC_SHLL_S_PH:
21345 check_dsp(ctx);
21346 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
21347 break;
21348 case OPC_SHLLV_S_PH:
21349 check_dsp(ctx);
21350 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21351 break;
21352 case OPC_SHLL_S_W:
21353 check_dsp(ctx);
21354 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
21355 break;
21356 case OPC_SHLLV_S_W:
21357 check_dsp(ctx);
21358 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21359 break;
21360 case OPC_SHRL_QB:
21361 check_dsp(ctx);
21362 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
21363 break;
21364 case OPC_SHRLV_QB:
21365 check_dsp(ctx);
21366 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
21367 break;
21368 case OPC_SHRL_PH:
21369 check_dspr2(ctx);
21370 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
21371 break;
21372 case OPC_SHRLV_PH:
21373 check_dspr2(ctx);
21374 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
21375 break;
21376 case OPC_SHRA_QB:
21377 check_dspr2(ctx);
21378 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
21379 break;
21380 case OPC_SHRA_R_QB:
21381 check_dspr2(ctx);
21382 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
21383 break;
21384 case OPC_SHRAV_QB:
21385 check_dspr2(ctx);
21386 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
21387 break;
21388 case OPC_SHRAV_R_QB:
21389 check_dspr2(ctx);
21390 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
21391 break;
21392 case OPC_SHRA_PH:
21393 check_dsp(ctx);
21394 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
21395 break;
21396 case OPC_SHRA_R_PH:
21397 check_dsp(ctx);
21398 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
21399 break;
21400 case OPC_SHRAV_PH:
21401 check_dsp(ctx);
21402 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
21403 break;
21404 case OPC_SHRAV_R_PH:
21405 check_dsp(ctx);
21406 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
21407 break;
21408 case OPC_SHRA_R_W:
21409 check_dsp(ctx);
21410 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
21411 break;
21412 case OPC_SHRAV_R_W:
21413 check_dsp(ctx);
21414 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
21415 break;
21416 default: /* Invalid */
21417 MIPS_INVAL("MASK SHLL.QB");
9c708c7f 21418 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
21419 break;
21420 }
21421 break;
21422 }
21423#ifdef TARGET_MIPS64
21424 case OPC_SHLL_OB_DSP:
21425 op2 = MASK_SHLL_OB(ctx->opcode);
21426 switch (op2) {
21427 case OPC_SHLL_PW:
21428 check_dsp(ctx);
21429 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
21430 break;
21431 case OPC_SHLLV_PW:
21432 check_dsp(ctx);
21433 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21434 break;
21435 case OPC_SHLL_S_PW:
21436 check_dsp(ctx);
21437 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
21438 break;
21439 case OPC_SHLLV_S_PW:
21440 check_dsp(ctx);
21441 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21442 break;
21443 case OPC_SHLL_OB:
21444 check_dsp(ctx);
21445 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
21446 break;
21447 case OPC_SHLLV_OB:
21448 check_dsp(ctx);
21449 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21450 break;
21451 case OPC_SHLL_QH:
21452 check_dsp(ctx);
21453 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
21454 break;
21455 case OPC_SHLLV_QH:
21456 check_dsp(ctx);
21457 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21458 break;
21459 case OPC_SHLL_S_QH:
21460 check_dsp(ctx);
21461 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
21462 break;
21463 case OPC_SHLLV_S_QH:
21464 check_dsp(ctx);
21465 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21466 break;
21467 case OPC_SHRA_OB:
21468 check_dspr2(ctx);
21469 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
21470 break;
21471 case OPC_SHRAV_OB:
21472 check_dspr2(ctx);
21473 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
21474 break;
21475 case OPC_SHRA_R_OB:
21476 check_dspr2(ctx);
21477 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
21478 break;
21479 case OPC_SHRAV_R_OB:
21480 check_dspr2(ctx);
21481 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
21482 break;
21483 case OPC_SHRA_PW:
21484 check_dsp(ctx);
21485 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
21486 break;
21487 case OPC_SHRAV_PW:
21488 check_dsp(ctx);
21489 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
21490 break;
21491 case OPC_SHRA_R_PW:
21492 check_dsp(ctx);
21493 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
21494 break;
21495 case OPC_SHRAV_R_PW:
21496 check_dsp(ctx);
21497 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
21498 break;
21499 case OPC_SHRA_QH:
21500 check_dsp(ctx);
21501 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
21502 break;
21503 case OPC_SHRAV_QH:
21504 check_dsp(ctx);
21505 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
21506 break;
21507 case OPC_SHRA_R_QH:
21508 check_dsp(ctx);
21509 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
21510 break;
21511 case OPC_SHRAV_R_QH:
21512 check_dsp(ctx);
21513 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
21514 break;
21515 case OPC_SHRL_OB:
21516 check_dsp(ctx);
21517 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
21518 break;
21519 case OPC_SHRLV_OB:
21520 check_dsp(ctx);
21521 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
21522 break;
21523 case OPC_SHRL_QH:
21524 check_dspr2(ctx);
21525 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
21526 break;
21527 case OPC_SHRLV_QH:
21528 check_dspr2(ctx);
21529 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
21530 break;
21531 default: /* Invalid */
21532 MIPS_INVAL("MASK SHLL.OB");
9c708c7f 21533 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
21534 break;
21535 }
21536 break;
21537#endif
21538 }
21539
21540 tcg_temp_free(t0);
21541 tcg_temp_free(v1_t);
21542 tcg_temp_free(v2_t);
77c5fa8b
JL
21543}
21544
a22260ae
JL
21545static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
21546 int ret, int v1, int v2, int check_ret)
21547{
a22260ae
JL
21548 TCGv_i32 t0;
21549 TCGv v1_t;
21550 TCGv v2_t;
21551
21552 if ((ret == 0) && (check_ret == 1)) {
21553 /* Treat as NOP. */
a22260ae
JL
21554 return;
21555 }
21556
21557 t0 = tcg_temp_new_i32();
21558 v1_t = tcg_temp_new();
21559 v2_t = tcg_temp_new();
21560
21561 tcg_gen_movi_i32(t0, ret);
21562 gen_load_gpr(v1_t, v1);
21563 gen_load_gpr(v2_t, v2);
21564
21565 switch (op1) {
21566 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
21567 * the same mask and op1. */
21568 case OPC_MULT_G_2E:
639eadb9 21569 check_dspr2(ctx);
a22260ae
JL
21570 switch (op2) {
21571 case OPC_MUL_PH:
21572 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21573 break;
21574 case OPC_MUL_S_PH:
21575 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21576 break;
21577 case OPC_MULQ_S_W:
21578 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21579 break;
21580 case OPC_MULQ_RS_W:
21581 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21582 break;
21583 }
21584 break;
21585 case OPC_DPA_W_PH_DSP:
21586 switch (op2) {
21587 case OPC_DPAU_H_QBL:
21588 check_dsp(ctx);
21589 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
21590 break;
21591 case OPC_DPAU_H_QBR:
21592 check_dsp(ctx);
21593 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
21594 break;
21595 case OPC_DPSU_H_QBL:
21596 check_dsp(ctx);
21597 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
21598 break;
21599 case OPC_DPSU_H_QBR:
21600 check_dsp(ctx);
21601 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
21602 break;
21603 case OPC_DPA_W_PH:
21604 check_dspr2(ctx);
21605 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
21606 break;
21607 case OPC_DPAX_W_PH:
21608 check_dspr2(ctx);
21609 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
21610 break;
21611 case OPC_DPAQ_S_W_PH:
21612 check_dsp(ctx);
21613 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
21614 break;
21615 case OPC_DPAQX_S_W_PH:
21616 check_dspr2(ctx);
21617 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
21618 break;
21619 case OPC_DPAQX_SA_W_PH:
21620 check_dspr2(ctx);
21621 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
21622 break;
21623 case OPC_DPS_W_PH:
21624 check_dspr2(ctx);
21625 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
21626 break;
21627 case OPC_DPSX_W_PH:
21628 check_dspr2(ctx);
21629 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
21630 break;
21631 case OPC_DPSQ_S_W_PH:
21632 check_dsp(ctx);
21633 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
21634 break;
21635 case OPC_DPSQX_S_W_PH:
21636 check_dspr2(ctx);
21637 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
21638 break;
21639 case OPC_DPSQX_SA_W_PH:
21640 check_dspr2(ctx);
21641 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
21642 break;
21643 case OPC_MULSAQ_S_W_PH:
21644 check_dsp(ctx);
21645 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
21646 break;
21647 case OPC_DPAQ_SA_L_W:
21648 check_dsp(ctx);
21649 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
21650 break;
21651 case OPC_DPSQ_SA_L_W:
21652 check_dsp(ctx);
21653 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
21654 break;
21655 case OPC_MAQ_S_W_PHL:
21656 check_dsp(ctx);
21657 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
21658 break;
21659 case OPC_MAQ_S_W_PHR:
21660 check_dsp(ctx);
21661 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
21662 break;
21663 case OPC_MAQ_SA_W_PHL:
21664 check_dsp(ctx);
21665 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
21666 break;
21667 case OPC_MAQ_SA_W_PHR:
21668 check_dsp(ctx);
21669 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
21670 break;
21671 case OPC_MULSA_W_PH:
21672 check_dspr2(ctx);
21673 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
21674 break;
21675 }
21676 break;
21677#ifdef TARGET_MIPS64
21678 case OPC_DPAQ_W_QH_DSP:
21679 {
21680 int ac = ret & 0x03;
21681 tcg_gen_movi_i32(t0, ac);
21682
21683 switch (op2) {
21684 case OPC_DMADD:
21685 check_dsp(ctx);
21686 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
21687 break;
21688 case OPC_DMADDU:
21689 check_dsp(ctx);
21690 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
21691 break;
21692 case OPC_DMSUB:
21693 check_dsp(ctx);
21694 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
21695 break;
21696 case OPC_DMSUBU:
21697 check_dsp(ctx);
21698 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
21699 break;
21700 case OPC_DPA_W_QH:
21701 check_dspr2(ctx);
21702 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
21703 break;
21704 case OPC_DPAQ_S_W_QH:
21705 check_dsp(ctx);
21706 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
21707 break;
21708 case OPC_DPAQ_SA_L_PW:
21709 check_dsp(ctx);
21710 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
21711 break;
21712 case OPC_DPAU_H_OBL:
21713 check_dsp(ctx);
21714 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
21715 break;
21716 case OPC_DPAU_H_OBR:
21717 check_dsp(ctx);
21718 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
21719 break;
21720 case OPC_DPS_W_QH:
21721 check_dspr2(ctx);
21722 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
21723 break;
21724 case OPC_DPSQ_S_W_QH:
21725 check_dsp(ctx);
21726 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
21727 break;
21728 case OPC_DPSQ_SA_L_PW:
21729 check_dsp(ctx);
21730 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
21731 break;
21732 case OPC_DPSU_H_OBL:
21733 check_dsp(ctx);
21734 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
21735 break;
21736 case OPC_DPSU_H_OBR:
21737 check_dsp(ctx);
21738 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
21739 break;
21740 case OPC_MAQ_S_L_PWL:
21741 check_dsp(ctx);
21742 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
21743 break;
21744 case OPC_MAQ_S_L_PWR:
21745 check_dsp(ctx);
21746 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
21747 break;
21748 case OPC_MAQ_S_W_QHLL:
21749 check_dsp(ctx);
21750 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
21751 break;
21752 case OPC_MAQ_SA_W_QHLL:
21753 check_dsp(ctx);
21754 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
21755 break;
21756 case OPC_MAQ_S_W_QHLR:
21757 check_dsp(ctx);
21758 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
21759 break;
21760 case OPC_MAQ_SA_W_QHLR:
21761 check_dsp(ctx);
21762 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
21763 break;
21764 case OPC_MAQ_S_W_QHRL:
21765 check_dsp(ctx);
21766 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
21767 break;
21768 case OPC_MAQ_SA_W_QHRL:
21769 check_dsp(ctx);
21770 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
21771 break;
21772 case OPC_MAQ_S_W_QHRR:
21773 check_dsp(ctx);
21774 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
21775 break;
21776 case OPC_MAQ_SA_W_QHRR:
21777 check_dsp(ctx);
21778 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
21779 break;
21780 case OPC_MULSAQ_S_L_PW:
21781 check_dsp(ctx);
21782 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
21783 break;
21784 case OPC_MULSAQ_S_W_QH:
21785 check_dsp(ctx);
21786 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
21787 break;
21788 }
21789 }
21790 break;
21791#endif
21792 case OPC_ADDU_QB_DSP:
21793 switch (op2) {
21794 case OPC_MULEU_S_PH_QBL:
21795 check_dsp(ctx);
21796 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21797 break;
21798 case OPC_MULEU_S_PH_QBR:
21799 check_dsp(ctx);
21800 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21801 break;
21802 case OPC_MULQ_RS_PH:
21803 check_dsp(ctx);
21804 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21805 break;
21806 case OPC_MULEQ_S_W_PHL:
21807 check_dsp(ctx);
21808 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21809 break;
21810 case OPC_MULEQ_S_W_PHR:
21811 check_dsp(ctx);
21812 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21813 break;
21814 case OPC_MULQ_S_PH:
21815 check_dspr2(ctx);
21816 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21817 break;
21818 }
21819 break;
21820#ifdef TARGET_MIPS64
21821 case OPC_ADDU_OB_DSP:
21822 switch (op2) {
21823 case OPC_MULEQ_S_PW_QHL:
21824 check_dsp(ctx);
21825 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21826 break;
21827 case OPC_MULEQ_S_PW_QHR:
21828 check_dsp(ctx);
21829 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21830 break;
21831 case OPC_MULEU_S_QH_OBL:
21832 check_dsp(ctx);
21833 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21834 break;
21835 case OPC_MULEU_S_QH_OBR:
21836 check_dsp(ctx);
21837 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21838 break;
21839 case OPC_MULQ_RS_QH:
21840 check_dsp(ctx);
21841 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21842 break;
21843 }
21844 break;
21845#endif
21846 }
21847
21848 tcg_temp_free_i32(t0);
21849 tcg_temp_free(v1_t);
21850 tcg_temp_free(v2_t);
a22260ae
JL
21851}
21852
d75c135e 21853static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
1cb6686c
JL
21854 int ret, int val)
21855{
1cb6686c
JL
21856 int16_t imm;
21857 TCGv t0;
21858 TCGv val_t;
21859
21860 if (ret == 0) {
21861 /* Treat as NOP. */
1cb6686c
JL
21862 return;
21863 }
21864
21865 t0 = tcg_temp_new();
21866 val_t = tcg_temp_new();
21867 gen_load_gpr(val_t, val);
21868
21869 switch (op1) {
21870 case OPC_ABSQ_S_PH_DSP:
21871 switch (op2) {
21872 case OPC_BITREV:
21873 check_dsp(ctx);
21874 gen_helper_bitrev(cpu_gpr[ret], val_t);
21875 break;
21876 case OPC_REPL_QB:
21877 check_dsp(ctx);
21878 {
21879 target_long result;
21880 imm = (ctx->opcode >> 16) & 0xFF;
21881 result = (uint32_t)imm << 24 |
21882 (uint32_t)imm << 16 |
21883 (uint32_t)imm << 8 |
21884 (uint32_t)imm;
21885 result = (int32_t)result;
21886 tcg_gen_movi_tl(cpu_gpr[ret], result);
21887 }
21888 break;
21889 case OPC_REPLV_QB:
21890 check_dsp(ctx);
21891 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
21892 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
21893 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21894 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
21895 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21896 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21897 break;
21898 case OPC_REPL_PH:
21899 check_dsp(ctx);
21900 {
21901 imm = (ctx->opcode >> 16) & 0x03FF;
c4aaba92 21902 imm = (int16_t)(imm << 6) >> 6;
1cb6686c
JL
21903 tcg_gen_movi_tl(cpu_gpr[ret], \
21904 (target_long)((int32_t)imm << 16 | \
c4aaba92 21905 (uint16_t)imm));
1cb6686c
JL
21906 }
21907 break;
21908 case OPC_REPLV_PH:
21909 check_dsp(ctx);
21910 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
21911 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
21912 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21913 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21914 break;
21915 }
21916 break;
21917#ifdef TARGET_MIPS64
21918 case OPC_ABSQ_S_QH_DSP:
21919 switch (op2) {
21920 case OPC_REPL_OB:
21921 check_dsp(ctx);
21922 {
21923 target_long temp;
21924
21925 imm = (ctx->opcode >> 16) & 0xFF;
21926 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
21927 temp = (temp << 16) | temp;
21928 temp = (temp << 32) | temp;
21929 tcg_gen_movi_tl(cpu_gpr[ret], temp);
21930 break;
21931 }
21932 case OPC_REPL_PW:
21933 check_dsp(ctx);
21934 {
21935 target_long temp;
21936
21937 imm = (ctx->opcode >> 16) & 0x03FF;
21938 imm = (int16_t)(imm << 6) >> 6;
21939 temp = ((target_long)imm << 32) \
21940 | ((target_long)imm & 0xFFFFFFFF);
21941 tcg_gen_movi_tl(cpu_gpr[ret], temp);
21942 break;
21943 }
21944 case OPC_REPL_QH:
21945 check_dsp(ctx);
21946 {
21947 target_long temp;
21948
21949 imm = (ctx->opcode >> 16) & 0x03FF;
21950 imm = (int16_t)(imm << 6) >> 6;
21951
21952 temp = ((uint64_t)(uint16_t)imm << 48) |
21953 ((uint64_t)(uint16_t)imm << 32) |
21954 ((uint64_t)(uint16_t)imm << 16) |
21955 (uint64_t)(uint16_t)imm;
21956 tcg_gen_movi_tl(cpu_gpr[ret], temp);
21957 break;
21958 }
21959 case OPC_REPLV_OB:
21960 check_dsp(ctx);
21961 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
21962 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
21963 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21964 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
21965 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21966 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
21967 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21968 break;
21969 case OPC_REPLV_PW:
21970 check_dsp(ctx);
21971 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
21972 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
21973 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21974 break;
21975 case OPC_REPLV_QH:
21976 check_dsp(ctx);
21977 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
21978 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
21979 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21980 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
21981 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21982 break;
21983 }
21984 break;
21985#endif
21986 }
21987 tcg_temp_free(t0);
21988 tcg_temp_free(val_t);
1cb6686c
JL
21989}
21990
26690560
JL
21991static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
21992 uint32_t op1, uint32_t op2,
21993 int ret, int v1, int v2, int check_ret)
21994{
26690560
JL
21995 TCGv t1;
21996 TCGv v1_t;
21997 TCGv v2_t;
21998
21999 if ((ret == 0) && (check_ret == 1)) {
22000 /* Treat as NOP. */
26690560
JL
22001 return;
22002 }
22003
26690560
JL
22004 t1 = tcg_temp_new();
22005 v1_t = tcg_temp_new();
22006 v2_t = tcg_temp_new();
22007
22008 gen_load_gpr(v1_t, v1);
22009 gen_load_gpr(v2_t, v2);
22010
22011 switch (op1) {
26690560
JL
22012 case OPC_CMPU_EQ_QB_DSP:
22013 switch (op2) {
22014 case OPC_CMPU_EQ_QB:
22015 check_dsp(ctx);
22016 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
22017 break;
22018 case OPC_CMPU_LT_QB:
22019 check_dsp(ctx);
22020 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
22021 break;
22022 case OPC_CMPU_LE_QB:
22023 check_dsp(ctx);
22024 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
22025 break;
22026 case OPC_CMPGU_EQ_QB:
22027 check_dsp(ctx);
22028 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
22029 break;
22030 case OPC_CMPGU_LT_QB:
22031 check_dsp(ctx);
22032 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
22033 break;
22034 case OPC_CMPGU_LE_QB:
22035 check_dsp(ctx);
22036 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
22037 break;
22038 case OPC_CMPGDU_EQ_QB:
22039 check_dspr2(ctx);
22040 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
22041 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22042 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22043 tcg_gen_shli_tl(t1, t1, 24);
22044 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22045 break;
22046 case OPC_CMPGDU_LT_QB:
22047 check_dspr2(ctx);
22048 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
22049 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22050 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22051 tcg_gen_shli_tl(t1, t1, 24);
22052 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22053 break;
22054 case OPC_CMPGDU_LE_QB:
22055 check_dspr2(ctx);
22056 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
22057 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22058 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22059 tcg_gen_shli_tl(t1, t1, 24);
22060 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22061 break;
22062 case OPC_CMP_EQ_PH:
22063 check_dsp(ctx);
22064 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
22065 break;
22066 case OPC_CMP_LT_PH:
22067 check_dsp(ctx);
22068 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
22069 break;
22070 case OPC_CMP_LE_PH:
22071 check_dsp(ctx);
22072 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
22073 break;
22074 case OPC_PICK_QB:
22075 check_dsp(ctx);
22076 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22077 break;
22078 case OPC_PICK_PH:
22079 check_dsp(ctx);
22080 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22081 break;
22082 case OPC_PACKRL_PH:
22083 check_dsp(ctx);
22084 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
22085 break;
22086 }
22087 break;
22088#ifdef TARGET_MIPS64
22089 case OPC_CMPU_EQ_OB_DSP:
22090 switch (op2) {
22091 case OPC_CMP_EQ_PW:
22092 check_dsp(ctx);
22093 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
22094 break;
22095 case OPC_CMP_LT_PW:
22096 check_dsp(ctx);
22097 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
22098 break;
22099 case OPC_CMP_LE_PW:
22100 check_dsp(ctx);
22101 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
22102 break;
22103 case OPC_CMP_EQ_QH:
22104 check_dsp(ctx);
22105 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
22106 break;
22107 case OPC_CMP_LT_QH:
22108 check_dsp(ctx);
22109 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
22110 break;
22111 case OPC_CMP_LE_QH:
22112 check_dsp(ctx);
22113 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
22114 break;
22115 case OPC_CMPGDU_EQ_OB:
22116 check_dspr2(ctx);
22117 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22118 break;
22119 case OPC_CMPGDU_LT_OB:
22120 check_dspr2(ctx);
22121 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22122 break;
22123 case OPC_CMPGDU_LE_OB:
22124 check_dspr2(ctx);
22125 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22126 break;
22127 case OPC_CMPGU_EQ_OB:
22128 check_dsp(ctx);
22129 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
22130 break;
22131 case OPC_CMPGU_LT_OB:
22132 check_dsp(ctx);
22133 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
22134 break;
22135 case OPC_CMPGU_LE_OB:
22136 check_dsp(ctx);
22137 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
22138 break;
22139 case OPC_CMPU_EQ_OB:
22140 check_dsp(ctx);
22141 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
22142 break;
22143 case OPC_CMPU_LT_OB:
22144 check_dsp(ctx);
22145 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
22146 break;
22147 case OPC_CMPU_LE_OB:
22148 check_dsp(ctx);
22149 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
22150 break;
22151 case OPC_PACKRL_PW:
22152 check_dsp(ctx);
22153 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
22154 break;
22155 case OPC_PICK_OB:
22156 check_dsp(ctx);
22157 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22158 break;
22159 case OPC_PICK_PW:
22160 check_dsp(ctx);
22161 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22162 break;
22163 case OPC_PICK_QH:
22164 check_dsp(ctx);
22165 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22166 break;
22167 }
22168 break;
df6126a7
AJ
22169#endif
22170 }
22171
22172 tcg_temp_free(t1);
22173 tcg_temp_free(v1_t);
22174 tcg_temp_free(v2_t);
df6126a7
AJ
22175}
22176
22177static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
22178 uint32_t op1, int rt, int rs, int sa)
22179{
df6126a7
AJ
22180 TCGv t0;
22181
22182 check_dspr2(ctx);
22183
22184 if (rt == 0) {
22185 /* Treat as NOP. */
df6126a7
AJ
22186 return;
22187 }
22188
22189 t0 = tcg_temp_new();
22190 gen_load_gpr(t0, rs);
22191
22192 switch (op1) {
22193 case OPC_APPEND_DSP:
22194 switch (MASK_APPEND(ctx->opcode)) {
22195 case OPC_APPEND:
22196 if (sa != 0) {
22197 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
22198 }
22199 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22200 break;
22201 case OPC_PREPEND:
22202 if (sa != 0) {
22203 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
22204 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22205 tcg_gen_shli_tl(t0, t0, 32 - sa);
22206 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22207 }
22208 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22209 break;
22210 case OPC_BALIGN:
22211 sa &= 3;
22212 if (sa != 0 && sa != 2) {
22213 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22214 tcg_gen_ext32u_tl(t0, t0);
22215 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
22216 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22217 }
22218 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22219 break;
22220 default: /* Invalid */
22221 MIPS_INVAL("MASK APPEND");
9c708c7f 22222 generate_exception_end(ctx, EXCP_RI);
df6126a7
AJ
22223 break;
22224 }
22225 break;
22226#ifdef TARGET_MIPS64
26690560 22227 case OPC_DAPPEND_DSP:
df6126a7 22228 switch (MASK_DAPPEND(ctx->opcode)) {
26690560 22229 case OPC_DAPPEND:
df6126a7
AJ
22230 if (sa != 0) {
22231 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
22232 }
26690560
JL
22233 break;
22234 case OPC_PREPENDD:
df6126a7
AJ
22235 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
22236 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
22237 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
26690560
JL
22238 break;
22239 case OPC_PREPENDW:
df6126a7
AJ
22240 if (sa != 0) {
22241 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22242 tcg_gen_shli_tl(t0, t0, 64 - sa);
22243 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22244 }
26690560
JL
22245 break;
22246 case OPC_DBALIGN:
df6126a7
AJ
22247 sa &= 7;
22248 if (sa != 0 && sa != 2 && sa != 4) {
22249 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22250 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
22251 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22252 }
26690560
JL
22253 break;
22254 default: /* Invalid */
22255 MIPS_INVAL("MASK DAPPEND");
9c708c7f 22256 generate_exception_end(ctx, EXCP_RI);
26690560
JL
22257 break;
22258 }
22259 break;
22260#endif
22261 }
df6126a7 22262 tcg_temp_free(t0);
26690560
JL
22263}
22264
b53371ed
JL
22265static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22266 int ret, int v1, int v2, int check_ret)
22267
22268{
b53371ed
JL
22269 TCGv t0;
22270 TCGv t1;
22271 TCGv v1_t;
22272 TCGv v2_t;
22273 int16_t imm;
22274
22275 if ((ret == 0) && (check_ret == 1)) {
22276 /* Treat as NOP. */
b53371ed
JL
22277 return;
22278 }
22279
22280 t0 = tcg_temp_new();
22281 t1 = tcg_temp_new();
22282 v1_t = tcg_temp_new();
22283 v2_t = tcg_temp_new();
22284
22285 gen_load_gpr(v1_t, v1);
22286 gen_load_gpr(v2_t, v2);
22287
22288 switch (op1) {
22289 case OPC_EXTR_W_DSP:
22290 check_dsp(ctx);
22291 switch (op2) {
22292 case OPC_EXTR_W:
22293 tcg_gen_movi_tl(t0, v2);
22294 tcg_gen_movi_tl(t1, v1);
22295 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
22296 break;
22297 case OPC_EXTR_R_W:
22298 tcg_gen_movi_tl(t0, v2);
22299 tcg_gen_movi_tl(t1, v1);
22300 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
22301 break;
22302 case OPC_EXTR_RS_W:
22303 tcg_gen_movi_tl(t0, v2);
22304 tcg_gen_movi_tl(t1, v1);
22305 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
22306 break;
22307 case OPC_EXTR_S_H:
22308 tcg_gen_movi_tl(t0, v2);
22309 tcg_gen_movi_tl(t1, v1);
22310 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
22311 break;
22312 case OPC_EXTRV_S_H:
22313 tcg_gen_movi_tl(t0, v2);
22314 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
22315 break;
22316 case OPC_EXTRV_W:
22317 tcg_gen_movi_tl(t0, v2);
22318 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22319 break;
22320 case OPC_EXTRV_R_W:
22321 tcg_gen_movi_tl(t0, v2);
22322 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22323 break;
22324 case OPC_EXTRV_RS_W:
22325 tcg_gen_movi_tl(t0, v2);
22326 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22327 break;
22328 case OPC_EXTP:
22329 tcg_gen_movi_tl(t0, v2);
22330 tcg_gen_movi_tl(t1, v1);
22331 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
22332 break;
22333 case OPC_EXTPV:
22334 tcg_gen_movi_tl(t0, v2);
22335 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
22336 break;
22337 case OPC_EXTPDP:
22338 tcg_gen_movi_tl(t0, v2);
22339 tcg_gen_movi_tl(t1, v1);
22340 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
22341 break;
22342 case OPC_EXTPDPV:
22343 tcg_gen_movi_tl(t0, v2);
22344 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
22345 break;
22346 case OPC_SHILO:
22347 imm = (ctx->opcode >> 20) & 0x3F;
22348 tcg_gen_movi_tl(t0, ret);
22349 tcg_gen_movi_tl(t1, imm);
22350 gen_helper_shilo(t0, t1, cpu_env);
22351 break;
22352 case OPC_SHILOV:
22353 tcg_gen_movi_tl(t0, ret);
22354 gen_helper_shilo(t0, v1_t, cpu_env);
22355 break;
22356 case OPC_MTHLIP:
22357 tcg_gen_movi_tl(t0, ret);
22358 gen_helper_mthlip(t0, v1_t, cpu_env);
22359 break;
22360 case OPC_WRDSP:
22361 imm = (ctx->opcode >> 11) & 0x3FF;
22362 tcg_gen_movi_tl(t0, imm);
22363 gen_helper_wrdsp(v1_t, t0, cpu_env);
22364 break;
22365 case OPC_RDDSP:
22366 imm = (ctx->opcode >> 16) & 0x03FF;
22367 tcg_gen_movi_tl(t0, imm);
22368 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
22369 break;
22370 }
22371 break;
22372#ifdef TARGET_MIPS64
22373 case OPC_DEXTR_W_DSP:
22374 check_dsp(ctx);
22375 switch (op2) {
22376 case OPC_DMTHLIP:
22377 tcg_gen_movi_tl(t0, ret);
22378 gen_helper_dmthlip(v1_t, t0, cpu_env);
22379 break;
22380 case OPC_DSHILO:
22381 {
22382 int shift = (ctx->opcode >> 19) & 0x7F;
22383 int ac = (ctx->opcode >> 11) & 0x03;
22384 tcg_gen_movi_tl(t0, shift);
22385 tcg_gen_movi_tl(t1, ac);
22386 gen_helper_dshilo(t0, t1, cpu_env);
22387 break;
22388 }
22389 case OPC_DSHILOV:
22390 {
22391 int ac = (ctx->opcode >> 11) & 0x03;
22392 tcg_gen_movi_tl(t0, ac);
22393 gen_helper_dshilo(v1_t, t0, cpu_env);
22394 break;
22395 }
22396 case OPC_DEXTP:
22397 tcg_gen_movi_tl(t0, v2);
22398 tcg_gen_movi_tl(t1, v1);
22399
22400 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
22401 break;
22402 case OPC_DEXTPV:
22403 tcg_gen_movi_tl(t0, v2);
22404 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
22405 break;
22406 case OPC_DEXTPDP:
22407 tcg_gen_movi_tl(t0, v2);
22408 tcg_gen_movi_tl(t1, v1);
22409 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
22410 break;
22411 case OPC_DEXTPDPV:
22412 tcg_gen_movi_tl(t0, v2);
22413 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
22414 break;
22415 case OPC_DEXTR_L:
22416 tcg_gen_movi_tl(t0, v2);
22417 tcg_gen_movi_tl(t1, v1);
22418 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
22419 break;
22420 case OPC_DEXTR_R_L:
22421 tcg_gen_movi_tl(t0, v2);
22422 tcg_gen_movi_tl(t1, v1);
22423 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
22424 break;
22425 case OPC_DEXTR_RS_L:
22426 tcg_gen_movi_tl(t0, v2);
22427 tcg_gen_movi_tl(t1, v1);
22428 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
22429 break;
22430 case OPC_DEXTR_W:
22431 tcg_gen_movi_tl(t0, v2);
22432 tcg_gen_movi_tl(t1, v1);
22433 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
22434 break;
22435 case OPC_DEXTR_R_W:
22436 tcg_gen_movi_tl(t0, v2);
22437 tcg_gen_movi_tl(t1, v1);
22438 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
22439 break;
22440 case OPC_DEXTR_RS_W:
22441 tcg_gen_movi_tl(t0, v2);
22442 tcg_gen_movi_tl(t1, v1);
22443 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
22444 break;
22445 case OPC_DEXTR_S_H:
22446 tcg_gen_movi_tl(t0, v2);
22447 tcg_gen_movi_tl(t1, v1);
22448 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
22449 break;
22450 case OPC_DEXTRV_S_H:
22451 tcg_gen_movi_tl(t0, v2);
22452 tcg_gen_movi_tl(t1, v1);
22453 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
22454 break;
22455 case OPC_DEXTRV_L:
22456 tcg_gen_movi_tl(t0, v2);
22457 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
22458 break;
22459 case OPC_DEXTRV_R_L:
22460 tcg_gen_movi_tl(t0, v2);
22461 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
22462 break;
22463 case OPC_DEXTRV_RS_L:
22464 tcg_gen_movi_tl(t0, v2);
22465 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
22466 break;
22467 case OPC_DEXTRV_W:
22468 tcg_gen_movi_tl(t0, v2);
22469 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22470 break;
22471 case OPC_DEXTRV_R_W:
22472 tcg_gen_movi_tl(t0, v2);
22473 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22474 break;
22475 case OPC_DEXTRV_RS_W:
22476 tcg_gen_movi_tl(t0, v2);
22477 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22478 break;
22479 }
22480 break;
22481#endif
22482 }
22483
22484 tcg_temp_free(t0);
22485 tcg_temp_free(t1);
22486 tcg_temp_free(v1_t);
22487 tcg_temp_free(v2_t);
b53371ed
JL
22488}
22489
9b1a1d68
JL
22490/* End MIPSDSP functions. */
22491
10dc65db
LA
22492static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
22493{
4267d3e6 22494 int rs, rt, rd, sa;
b42ee5e1 22495 uint32_t op1, op2;
10dc65db
LA
22496
22497 rs = (ctx->opcode >> 21) & 0x1f;
22498 rt = (ctx->opcode >> 16) & 0x1f;
22499 rd = (ctx->opcode >> 11) & 0x1f;
4267d3e6 22500 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
22501
22502 op1 = MASK_SPECIAL(ctx->opcode);
22503 switch (op1) {
d4ea6acd 22504 case OPC_LSA:
1f1b4c00 22505 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 22506 break;
c2e19f3c
AM
22507 case OPC_MULT:
22508 case OPC_MULTU:
22509 case OPC_DIV:
22510 case OPC_DIVU:
b42ee5e1
LA
22511 op2 = MASK_R6_MULDIV(ctx->opcode);
22512 switch (op2) {
22513 case R6_OPC_MUL:
22514 case R6_OPC_MUH:
22515 case R6_OPC_MULU:
22516 case R6_OPC_MUHU:
22517 case R6_OPC_DIV:
22518 case R6_OPC_MOD:
22519 case R6_OPC_DIVU:
22520 case R6_OPC_MODU:
22521 gen_r6_muldiv(ctx, op2, rd, rs, rt);
22522 break;
22523 default:
22524 MIPS_INVAL("special_r6 muldiv");
9c708c7f 22525 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
22526 break;
22527 }
22528 break;
10dc65db
LA
22529 case OPC_SELEQZ:
22530 case OPC_SELNEZ:
22531 gen_cond_move(ctx, op1, rd, rs, rt);
22532 break;
4267d3e6
LA
22533 case R6_OPC_CLO:
22534 case R6_OPC_CLZ:
22535 if (rt == 0 && sa == 1) {
22536 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
22537 We need additionally to check other fields */
22538 gen_cl(ctx, op1, rd, rs);
22539 } else {
9c708c7f 22540 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
22541 }
22542 break;
22543 case R6_OPC_SDBBP:
3b3c1694
LA
22544 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
22545 gen_helper_do_semihosting(cpu_env);
faf1f68b 22546 } else {
3b3c1694 22547 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 22548 generate_exception_end(ctx, EXCP_RI);
3b3c1694 22549 } else {
9c708c7f 22550 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 22551 }
faf1f68b 22552 }
4267d3e6 22553 break;
b42ee5e1 22554#if defined(TARGET_MIPS64)
d4ea6acd
LA
22555 case OPC_DLSA:
22556 check_mips_64(ctx);
1f1b4c00 22557 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 22558 break;
4267d3e6
LA
22559 case R6_OPC_DCLO:
22560 case R6_OPC_DCLZ:
22561 if (rt == 0 && sa == 1) {
22562 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
22563 We need additionally to check other fields */
22564 check_mips_64(ctx);
22565 gen_cl(ctx, op1, rd, rs);
22566 } else {
9c708c7f 22567 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
22568 }
22569 break;
c2e19f3c
AM
22570 case OPC_DMULT:
22571 case OPC_DMULTU:
22572 case OPC_DDIV:
22573 case OPC_DDIVU:
22574
b42ee5e1
LA
22575 op2 = MASK_R6_MULDIV(ctx->opcode);
22576 switch (op2) {
22577 case R6_OPC_DMUL:
22578 case R6_OPC_DMUH:
22579 case R6_OPC_DMULU:
22580 case R6_OPC_DMUHU:
22581 case R6_OPC_DDIV:
22582 case R6_OPC_DMOD:
22583 case R6_OPC_DDIVU:
22584 case R6_OPC_DMODU:
22585 check_mips_64(ctx);
22586 gen_r6_muldiv(ctx, op2, rd, rs, rt);
22587 break;
22588 default:
22589 MIPS_INVAL("special_r6 muldiv");
9c708c7f 22590 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
22591 break;
22592 }
22593 break;
22594#endif
10dc65db
LA
22595 default: /* Invalid */
22596 MIPS_INVAL("special_r6");
9c708c7f 22597 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
22598 break;
22599 }
22600}
22601
22602static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
22603{
b42ee5e1 22604 int rs, rt, rd, sa;
10dc65db
LA
22605 uint32_t op1;
22606
22607 rs = (ctx->opcode >> 21) & 0x1f;
22608 rt = (ctx->opcode >> 16) & 0x1f;
22609 rd = (ctx->opcode >> 11) & 0x1f;
b42ee5e1 22610 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
22611
22612 op1 = MASK_SPECIAL(ctx->opcode);
22613 switch (op1) {
22614 case OPC_MOVN: /* Conditional move */
22615 case OPC_MOVZ:
22616 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
22617 INSN_LOONGSON2E | INSN_LOONGSON2F);
22618 gen_cond_move(ctx, op1, rd, rs, rt);
22619 break;
22620 case OPC_MFHI: /* Move from HI/LO */
22621 case OPC_MFLO:
22622 gen_HILO(ctx, op1, rs & 3, rd);
22623 break;
22624 case OPC_MTHI:
22625 case OPC_MTLO: /* Move to HI/LO */
22626 gen_HILO(ctx, op1, rd & 3, rs);
22627 break;
22628 case OPC_MOVCI:
22629 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
22630 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
22631 check_cp1_enabled(ctx);
22632 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
22633 (ctx->opcode >> 16) & 1);
22634 } else {
22635 generate_exception_err(ctx, EXCP_CpU, 1);
22636 }
22637 break;
b42ee5e1
LA
22638 case OPC_MULT:
22639 case OPC_MULTU:
22640 if (sa) {
22641 check_insn(ctx, INSN_VR54XX);
22642 op1 = MASK_MUL_VR54XX(ctx->opcode);
22643 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
22644 } else {
22645 gen_muldiv(ctx, op1, rd & 3, rs, rt);
22646 }
22647 break;
22648 case OPC_DIV:
22649 case OPC_DIVU:
22650 gen_muldiv(ctx, op1, 0, rs, rt);
22651 break;
22652#if defined(TARGET_MIPS64)
c2e19f3c
AM
22653 case OPC_DMULT:
22654 case OPC_DMULTU:
22655 case OPC_DDIV:
22656 case OPC_DDIVU:
b42ee5e1
LA
22657 check_insn(ctx, ISA_MIPS3);
22658 check_mips_64(ctx);
22659 gen_muldiv(ctx, op1, 0, rs, rt);
22660 break;
22661#endif
0aefa333 22662 case OPC_JR:
b231c103 22663 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
0aefa333 22664 break;
4267d3e6
LA
22665 case OPC_SPIM:
22666#ifdef MIPS_STRICT_STANDARD
22667 MIPS_INVAL("SPIM");
9c708c7f 22668 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
22669#else
22670 /* Implemented as RI exception for now. */
22671 MIPS_INVAL("spim (unofficial)");
9c708c7f 22672 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
22673#endif
22674 break;
10dc65db
LA
22675 default: /* Invalid */
22676 MIPS_INVAL("special_legacy");
9c708c7f 22677 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
22678 break;
22679 }
22680}
22681
099e5b4d 22682static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
3c824109 22683{
3c824109 22684 int rs, rt, rd, sa;
099e5b4d 22685 uint32_t op1;
3c824109 22686
3c824109
NF
22687 rs = (ctx->opcode >> 21) & 0x1f;
22688 rt = (ctx->opcode >> 16) & 0x1f;
22689 rd = (ctx->opcode >> 11) & 0x1f;
22690 sa = (ctx->opcode >> 6) & 0x1f;
099e5b4d
LA
22691
22692 op1 = MASK_SPECIAL(ctx->opcode);
22693 switch (op1) {
22694 case OPC_SLL: /* Shift with immediate */
339cd2a8
LA
22695 if (sa == 5 && rd == 0 &&
22696 rs == 0 && rt == 0) { /* PAUSE */
22697 if ((ctx->insn_flags & ISA_MIPS32R6) &&
22698 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 22699 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
22700 break;
22701 }
22702 }
22703 /* Fallthrough */
099e5b4d
LA
22704 case OPC_SRA:
22705 gen_shift_imm(ctx, op1, rd, rt, sa);
22706 break;
22707 case OPC_SRL:
22708 switch ((ctx->opcode >> 21) & 0x1f) {
22709 case 1:
22710 /* rotr is decoded as srl on non-R2 CPUs */
22711 if (ctx->insn_flags & ISA_MIPS32R2) {
22712 op1 = OPC_ROTR;
ea63e2c3 22713 }
099e5b4d
LA
22714 /* Fallthrough */
22715 case 0:
22716 gen_shift_imm(ctx, op1, rd, rt, sa);
ea63e2c3 22717 break;
099e5b4d 22718 default:
9c708c7f 22719 generate_exception_end(ctx, EXCP_RI);
ea63e2c3 22720 break;
099e5b4d
LA
22721 }
22722 break;
c2e19f3c
AM
22723 case OPC_ADD:
22724 case OPC_ADDU:
22725 case OPC_SUB:
22726 case OPC_SUBU:
099e5b4d
LA
22727 gen_arith(ctx, op1, rd, rs, rt);
22728 break;
22729 case OPC_SLLV: /* Shifts */
22730 case OPC_SRAV:
22731 gen_shift(ctx, op1, rd, rs, rt);
22732 break;
22733 case OPC_SRLV:
22734 switch ((ctx->opcode >> 6) & 0x1f) {
22735 case 1:
22736 /* rotrv is decoded as srlv on non-R2 CPUs */
22737 if (ctx->insn_flags & ISA_MIPS32R2) {
22738 op1 = OPC_ROTRV;
26135ead 22739 }
099e5b4d
LA
22740 /* Fallthrough */
22741 case 0:
22742 gen_shift(ctx, op1, rd, rs, rt);
26135ead 22743 break;
099e5b4d 22744 default:
9c708c7f 22745 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 22746 break;
099e5b4d
LA
22747 }
22748 break;
22749 case OPC_SLT: /* Set on less than */
22750 case OPC_SLTU:
22751 gen_slt(ctx, op1, rd, rs, rt);
22752 break;
22753 case OPC_AND: /* Logic*/
22754 case OPC_OR:
22755 case OPC_NOR:
22756 case OPC_XOR:
22757 gen_logic(ctx, op1, rd, rs, rt);
22758 break;
0aefa333 22759 case OPC_JALR:
b231c103 22760 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
099e5b4d 22761 break;
c2e19f3c
AM
22762 case OPC_TGE: /* Traps */
22763 case OPC_TGEU:
22764 case OPC_TLT:
22765 case OPC_TLTU:
22766 case OPC_TEQ:
099e5b4d 22767 case OPC_TNE:
d9224450 22768 check_insn(ctx, ISA_MIPS2);
099e5b4d
LA
22769 gen_trap(ctx, op1, rs, rt, -1);
22770 break;
d4ea6acd 22771 case OPC_LSA: /* OPC_PMON */
f7685877
YK
22772 if ((ctx->insn_flags & ISA_MIPS32R6) ||
22773 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
d4ea6acd
LA
22774 decode_opc_special_r6(env, ctx);
22775 } else {
22776 /* Pmon entry point, also R4010 selsl */
b48cfdff 22777#ifdef MIPS_STRICT_STANDARD
d4ea6acd 22778 MIPS_INVAL("PMON / selsl");
9c708c7f 22779 generate_exception_end(ctx, EXCP_RI);
b48cfdff 22780#else
d4ea6acd 22781 gen_helper_0e0i(pmon, sa);
b48cfdff 22782#endif
d4ea6acd 22783 }
099e5b4d
LA
22784 break;
22785 case OPC_SYSCALL:
9c708c7f 22786 generate_exception_end(ctx, EXCP_SYSCALL);
099e5b4d
LA
22787 break;
22788 case OPC_BREAK:
9c708c7f 22789 generate_exception_end(ctx, EXCP_BREAK);
099e5b4d 22790 break;
099e5b4d 22791 case OPC_SYNC:
d9224450 22792 check_insn(ctx, ISA_MIPS2);
d208ac0c 22793 gen_sync(extract32(ctx->opcode, 6, 5));
099e5b4d 22794 break;
4ad40f36 22795
d26bc211 22796#if defined(TARGET_MIPS64)
099e5b4d
LA
22797 /* MIPS64 specific opcodes */
22798 case OPC_DSLL:
22799 case OPC_DSRA:
22800 case OPC_DSLL32:
22801 case OPC_DSRA32:
22802 check_insn(ctx, ISA_MIPS3);
22803 check_mips_64(ctx);
22804 gen_shift_imm(ctx, op1, rd, rt, sa);
22805 break;
22806 case OPC_DSRL:
22807 switch ((ctx->opcode >> 21) & 0x1f) {
22808 case 1:
22809 /* drotr is decoded as dsrl on non-R2 CPUs */
22810 if (ctx->insn_flags & ISA_MIPS32R2) {
22811 op1 = OPC_DROTR;
ea63e2c3 22812 }
099e5b4d
LA
22813 /* Fallthrough */
22814 case 0:
d75c135e 22815 check_insn(ctx, ISA_MIPS3);
e189e748 22816 check_mips_64(ctx);
099e5b4d 22817 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 22818 break;
099e5b4d 22819 default:
9c708c7f 22820 generate_exception_end(ctx, EXCP_RI);
460f00c4 22821 break;
099e5b4d
LA
22822 }
22823 break;
22824 case OPC_DSRL32:
22825 switch ((ctx->opcode >> 21) & 0x1f) {
22826 case 1:
22827 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
22828 if (ctx->insn_flags & ISA_MIPS32R2) {
22829 op1 = OPC_DROTR32;
ea63e2c3 22830 }
099e5b4d
LA
22831 /* Fallthrough */
22832 case 0:
d75c135e 22833 check_insn(ctx, ISA_MIPS3);
e189e748 22834 check_mips_64(ctx);
099e5b4d 22835 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 22836 break;
099e5b4d 22837 default:
9c708c7f 22838 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
22839 break;
22840 }
22841 break;
c2e19f3c
AM
22842 case OPC_DADD:
22843 case OPC_DADDU:
22844 case OPC_DSUB:
22845 case OPC_DSUBU:
099e5b4d
LA
22846 check_insn(ctx, ISA_MIPS3);
22847 check_mips_64(ctx);
22848 gen_arith(ctx, op1, rd, rs, rt);
22849 break;
22850 case OPC_DSLLV:
22851 case OPC_DSRAV:
22852 check_insn(ctx, ISA_MIPS3);
22853 check_mips_64(ctx);
22854 gen_shift(ctx, op1, rd, rs, rt);
22855 break;
22856 case OPC_DSRLV:
22857 switch ((ctx->opcode >> 6) & 0x1f) {
22858 case 1:
22859 /* drotrv is decoded as dsrlv on non-R2 CPUs */
22860 if (ctx->insn_flags & ISA_MIPS32R2) {
22861 op1 = OPC_DROTRV;
6af0bf9c 22862 }
099e5b4d
LA
22863 /* Fallthrough */
22864 case 0:
22865 check_insn(ctx, ISA_MIPS3);
e189e748 22866 check_mips_64(ctx);
099e5b4d 22867 gen_shift(ctx, op1, rd, rs, rt);
161f85e6 22868 break;
099e5b4d 22869 default:
9c708c7f 22870 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
22871 break;
22872 }
22873 break;
f7685877
YK
22874 case OPC_DLSA:
22875 if ((ctx->insn_flags & ISA_MIPS32R6) ||
22876 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
22877 decode_opc_special_r6(env, ctx);
22878 }
22879 break;
099e5b4d 22880#endif
10dc65db
LA
22881 default:
22882 if (ctx->insn_flags & ISA_MIPS32R6) {
22883 decode_opc_special_r6(env, ctx);
22884 } else {
22885 decode_opc_special_legacy(env, ctx);
22886 }
22887 }
22888}
22889
10dc65db 22890static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
22891{
22892 int rs, rt, rd;
22893 uint32_t op1;
6c5c1e20 22894
4267d3e6
LA
22895 check_insn_opc_removed(ctx, ISA_MIPS32R6);
22896
099e5b4d
LA
22897 rs = (ctx->opcode >> 21) & 0x1f;
22898 rt = (ctx->opcode >> 16) & 0x1f;
22899 rd = (ctx->opcode >> 11) & 0x1f;
22900
22901 op1 = MASK_SPECIAL2(ctx->opcode);
22902 switch (op1) {
c2e19f3c
AM
22903 case OPC_MADD: /* Multiply and add/sub */
22904 case OPC_MADDU:
22905 case OPC_MSUB:
22906 case OPC_MSUBU:
099e5b4d
LA
22907 check_insn(ctx, ISA_MIPS32);
22908 gen_muldiv(ctx, op1, rd & 3, rs, rt);
22909 break;
22910 case OPC_MUL:
099e5b4d
LA
22911 gen_arith(ctx, op1, rd, rs, rt);
22912 break;
fac5a073
LA
22913 case OPC_DIV_G_2F:
22914 case OPC_DIVU_G_2F:
22915 case OPC_MULT_G_2F:
22916 case OPC_MULTU_G_2F:
22917 case OPC_MOD_G_2F:
22918 case OPC_MODU_G_2F:
22919 check_insn(ctx, INSN_LOONGSON2F);
22920 gen_loongson_integer(ctx, op1, rd, rs, rt);
22921 break;
099e5b4d
LA
22922 case OPC_CLO:
22923 case OPC_CLZ:
22924 check_insn(ctx, ISA_MIPS32);
22925 gen_cl(ctx, op1, rd, rs);
22926 break;
22927 case OPC_SDBBP:
3b3c1694
LA
22928 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
22929 gen_helper_do_semihosting(cpu_env);
22930 } else {
22931 /* XXX: not clear which exception should be raised
22932 * when in debug mode...
22933 */
22934 check_insn(ctx, ISA_MIPS32);
9c708c7f 22935 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 22936 }
099e5b4d 22937 break;
9b1a1d68 22938#if defined(TARGET_MIPS64)
099e5b4d
LA
22939 case OPC_DCLO:
22940 case OPC_DCLZ:
22941 check_insn(ctx, ISA_MIPS64);
22942 check_mips_64(ctx);
22943 gen_cl(ctx, op1, rd, rs);
22944 break;
4267d3e6
LA
22945 case OPC_DMULT_G_2F:
22946 case OPC_DMULTU_G_2F:
22947 case OPC_DDIV_G_2F:
22948 case OPC_DDIVU_G_2F:
22949 case OPC_DMOD_G_2F:
22950 case OPC_DMODU_G_2F:
22951 check_insn(ctx, INSN_LOONGSON2F);
22952 gen_loongson_integer(ctx, op1, rd, rs, rt);
22953 break;
10dc65db 22954#endif
4267d3e6
LA
22955 default: /* Invalid */
22956 MIPS_INVAL("special2_legacy");
9c708c7f 22957 generate_exception_end(ctx, EXCP_RI);
4267d3e6 22958 break;
10dc65db
LA
22959 }
22960}
22961
22962static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
22963{
15eacb9b
YK
22964 int rs, rt, rd, sa;
22965 uint32_t op1, op2;
10dc65db
LA
22966 int16_t imm;
22967
22968 rs = (ctx->opcode >> 21) & 0x1f;
22969 rt = (ctx->opcode >> 16) & 0x1f;
15eacb9b
YK
22970 rd = (ctx->opcode >> 11) & 0x1f;
22971 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
22972 imm = (int16_t)ctx->opcode >> 7;
22973
22974 op1 = MASK_SPECIAL3(ctx->opcode);
22975 switch (op1) {
bf7910c6
LA
22976 case R6_OPC_PREF:
22977 if (rt >= 24) {
22978 /* hint codes 24-31 are reserved and signal RI */
9c708c7f 22979 generate_exception_end(ctx, EXCP_RI);
bf7910c6
LA
22980 }
22981 /* Treat as NOP. */
22982 break;
22983 case R6_OPC_CACHE:
40d48212 22984 check_cp0_enabled(ctx);
0d74a222
LA
22985 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
22986 gen_cache_operation(ctx, rt, rs, imm);
22987 }
bf7910c6 22988 break;
10dc65db
LA
22989 case R6_OPC_SC:
22990 gen_st_cond(ctx, op1, rt, rs, imm);
22991 break;
22992 case R6_OPC_LL:
22993 gen_ld(ctx, op1, rt, rs, imm);
22994 break;
15eacb9b
YK
22995 case OPC_BSHFL:
22996 {
22997 if (rd == 0) {
22998 /* Treat as NOP. */
22999 break;
23000 }
15eacb9b
YK
23001 op2 = MASK_BSHFL(ctx->opcode);
23002 switch (op2) {
c2e19f3c
AM
23003 case OPC_ALIGN:
23004 case OPC_ALIGN_END:
821f2008 23005 gen_align(ctx, 32, rd, rs, rt, sa & 3);
15eacb9b
YK
23006 break;
23007 case OPC_BITSWAP:
1f1b4c00 23008 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
23009 break;
23010 }
15eacb9b
YK
23011 }
23012 break;
bf7910c6
LA
23013#if defined(TARGET_MIPS64)
23014 case R6_OPC_SCD:
23015 gen_st_cond(ctx, op1, rt, rs, imm);
23016 break;
23017 case R6_OPC_LLD:
23018 gen_ld(ctx, op1, rt, rs, imm);
23019 break;
15eacb9b
YK
23020 case OPC_DBSHFL:
23021 check_mips_64(ctx);
23022 {
23023 if (rd == 0) {
23024 /* Treat as NOP. */
23025 break;
23026 }
15eacb9b
YK
23027 op2 = MASK_DBSHFL(ctx->opcode);
23028 switch (op2) {
c2e19f3c
AM
23029 case OPC_DALIGN:
23030 case OPC_DALIGN_END:
821f2008 23031 gen_align(ctx, 64, rd, rs, rt, sa & 7);
15eacb9b
YK
23032 break;
23033 case OPC_DBITSWAP:
1f1b4c00 23034 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
23035 break;
23036 }
1f1b4c00 23037
15eacb9b
YK
23038 }
23039 break;
bf7910c6 23040#endif
10dc65db
LA
23041 default: /* Invalid */
23042 MIPS_INVAL("special3_r6");
9c708c7f 23043 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
23044 break;
23045 }
23046}
23047
23048static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
23049{
fac5a073 23050 int rs, rt, rd;
099e5b4d 23051 uint32_t op1, op2;
099e5b4d
LA
23052
23053 rs = (ctx->opcode >> 21) & 0x1f;
23054 rt = (ctx->opcode >> 16) & 0x1f;
23055 rd = (ctx->opcode >> 11) & 0x1f;
099e5b4d
LA
23056
23057 op1 = MASK_SPECIAL3(ctx->opcode);
23058 switch (op1) {
c2e19f3c
AM
23059 case OPC_DIV_G_2E:
23060 case OPC_DIVU_G_2E:
23061 case OPC_MOD_G_2E:
23062 case OPC_MODU_G_2E:
23063 case OPC_MULT_G_2E:
23064 case OPC_MULTU_G_2E:
099e5b4d
LA
23065 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23066 * the same mask and op1. */
23067 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
23068 op2 = MASK_ADDUH_QB(ctx->opcode);
461c08df 23069 switch (op2) {
099e5b4d
LA
23070 case OPC_ADDUH_QB:
23071 case OPC_ADDUH_R_QB:
23072 case OPC_ADDQH_PH:
23073 case OPC_ADDQH_R_PH:
23074 case OPC_ADDQH_W:
23075 case OPC_ADDQH_R_W:
23076 case OPC_SUBUH_QB:
23077 case OPC_SUBUH_R_QB:
23078 case OPC_SUBQH_PH:
23079 case OPC_SUBQH_R_PH:
23080 case OPC_SUBQH_W:
23081 case OPC_SUBQH_R_W:
461c08df
JL
23082 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23083 break;
099e5b4d
LA
23084 case OPC_MUL_PH:
23085 case OPC_MUL_S_PH:
23086 case OPC_MULQ_S_W:
23087 case OPC_MULQ_RS_W:
23088 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 23089 break;
461c08df 23090 default:
099e5b4d 23091 MIPS_INVAL("MASK ADDUH.QB");
9c708c7f 23092 generate_exception_end(ctx, EXCP_RI);
461c08df
JL
23093 break;
23094 }
099e5b4d
LA
23095 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
23096 gen_loongson_integer(ctx, op1, rd, rs, rt);
23097 } else {
9c708c7f 23098 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
23099 }
23100 break;
23101 case OPC_LX_DSP:
23102 op2 = MASK_LX(ctx->opcode);
23103 switch (op2) {
23104#if defined(TARGET_MIPS64)
23105 case OPC_LDX:
23106#endif
23107 case OPC_LBUX:
23108 case OPC_LHX:
23109 case OPC_LWX:
23110 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
23111 break;
23112 default: /* Invalid */
23113 MIPS_INVAL("MASK LX");
9c708c7f 23114 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
23115 break;
23116 }
23117 break;
23118 case OPC_ABSQ_S_PH_DSP:
23119 op2 = MASK_ABSQ_S_PH(ctx->opcode);
23120 switch (op2) {
23121 case OPC_ABSQ_S_QB:
23122 case OPC_ABSQ_S_PH:
23123 case OPC_ABSQ_S_W:
23124 case OPC_PRECEQ_W_PHL:
23125 case OPC_PRECEQ_W_PHR:
23126 case OPC_PRECEQU_PH_QBL:
23127 case OPC_PRECEQU_PH_QBR:
23128 case OPC_PRECEQU_PH_QBLA:
23129 case OPC_PRECEQU_PH_QBRA:
23130 case OPC_PRECEU_PH_QBL:
23131 case OPC_PRECEU_PH_QBR:
23132 case OPC_PRECEU_PH_QBLA:
23133 case OPC_PRECEU_PH_QBRA:
23134 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23135 break;
23136 case OPC_BITREV:
23137 case OPC_REPL_QB:
23138 case OPC_REPLV_QB:
23139 case OPC_REPL_PH:
23140 case OPC_REPLV_PH:
23141 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23142 break;
23143 default:
23144 MIPS_INVAL("MASK ABSQ_S.PH");
9c708c7f 23145 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
23146 break;
23147 }
23148 break;
23149 case OPC_ADDU_QB_DSP:
23150 op2 = MASK_ADDU_QB(ctx->opcode);
23151 switch (op2) {
23152 case OPC_ADDQ_PH:
23153 case OPC_ADDQ_S_PH:
23154 case OPC_ADDQ_S_W:
23155 case OPC_ADDU_QB:
23156 case OPC_ADDU_S_QB:
23157 case OPC_ADDU_PH:
23158 case OPC_ADDU_S_PH:
23159 case OPC_SUBQ_PH:
23160 case OPC_SUBQ_S_PH:
23161 case OPC_SUBQ_S_W:
23162 case OPC_SUBU_QB:
23163 case OPC_SUBU_S_QB:
23164 case OPC_SUBU_PH:
23165 case OPC_SUBU_S_PH:
23166 case OPC_ADDSC:
23167 case OPC_ADDWC:
23168 case OPC_MODSUB:
23169 case OPC_RADDU_W_QB:
23170 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23171 break;
23172 case OPC_MULEU_S_PH_QBL:
23173 case OPC_MULEU_S_PH_QBR:
23174 case OPC_MULQ_RS_PH:
23175 case OPC_MULEQ_S_W_PHL:
23176 case OPC_MULEQ_S_W_PHR:
23177 case OPC_MULQ_S_PH:
23178 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23179 break;
23180 default: /* Invalid */
23181 MIPS_INVAL("MASK ADDU.QB");
9c708c7f 23182 generate_exception_end(ctx, EXCP_RI);
461c08df 23183 break;
461c08df 23184
099e5b4d
LA
23185 }
23186 break;
23187 case OPC_CMPU_EQ_QB_DSP:
23188 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
23189 switch (op2) {
23190 case OPC_PRECR_SRA_PH_W:
23191 case OPC_PRECR_SRA_R_PH_W:
23192 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
461c08df 23193 break;
099e5b4d
LA
23194 case OPC_PRECR_QB_PH:
23195 case OPC_PRECRQ_QB_PH:
23196 case OPC_PRECRQ_PH_W:
23197 case OPC_PRECRQ_RS_PH_W:
23198 case OPC_PRECRQU_S_QB_PH:
23199 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
461c08df 23200 break;
099e5b4d
LA
23201 case OPC_CMPU_EQ_QB:
23202 case OPC_CMPU_LT_QB:
23203 case OPC_CMPU_LE_QB:
23204 case OPC_CMP_EQ_PH:
23205 case OPC_CMP_LT_PH:
23206 case OPC_CMP_LE_PH:
23207 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
77c5fa8b 23208 break;
099e5b4d
LA
23209 case OPC_CMPGU_EQ_QB:
23210 case OPC_CMPGU_LT_QB:
23211 case OPC_CMPGU_LE_QB:
23212 case OPC_CMPGDU_EQ_QB:
23213 case OPC_CMPGDU_LT_QB:
23214 case OPC_CMPGDU_LE_QB:
23215 case OPC_PICK_QB:
23216 case OPC_PICK_PH:
23217 case OPC_PACKRL_PH:
23218 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
23219 break;
23220 default: /* Invalid */
23221 MIPS_INVAL("MASK CMPU.EQ.QB");
9c708c7f 23222 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
23223 break;
23224 }
23225 break;
23226 case OPC_SHLL_QB_DSP:
23227 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
23228 break;
23229 case OPC_DPA_W_PH_DSP:
23230 op2 = MASK_DPA_W_PH(ctx->opcode);
23231 switch (op2) {
23232 case OPC_DPAU_H_QBL:
23233 case OPC_DPAU_H_QBR:
23234 case OPC_DPSU_H_QBL:
23235 case OPC_DPSU_H_QBR:
23236 case OPC_DPA_W_PH:
23237 case OPC_DPAX_W_PH:
23238 case OPC_DPAQ_S_W_PH:
23239 case OPC_DPAQX_S_W_PH:
23240 case OPC_DPAQX_SA_W_PH:
23241 case OPC_DPS_W_PH:
23242 case OPC_DPSX_W_PH:
23243 case OPC_DPSQ_S_W_PH:
23244 case OPC_DPSQX_S_W_PH:
23245 case OPC_DPSQX_SA_W_PH:
23246 case OPC_MULSAQ_S_W_PH:
23247 case OPC_DPAQ_SA_L_W:
23248 case OPC_DPSQ_SA_L_W:
23249 case OPC_MAQ_S_W_PHL:
23250 case OPC_MAQ_S_W_PHR:
23251 case OPC_MAQ_SA_W_PHL:
23252 case OPC_MAQ_SA_W_PHR:
23253 case OPC_MULSA_W_PH:
23254 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
23255 break;
23256 default: /* Invalid */
23257 MIPS_INVAL("MASK DPAW.PH");
9c708c7f 23258 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
23259 break;
23260 }
23261 break;
23262 case OPC_INSV_DSP:
23263 op2 = MASK_INSV(ctx->opcode);
23264 switch (op2) {
23265 case OPC_INSV:
23266 check_dsp(ctx);
23267 {
23268 TCGv t0, t1;
23269
23270 if (rt == 0) {
099e5b4d
LA
23271 break;
23272 }
23273
23274 t0 = tcg_temp_new();
23275 t1 = tcg_temp_new();
23276
23277 gen_load_gpr(t0, rt);
23278 gen_load_gpr(t1, rs);
23279
23280 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
23281
23282 tcg_temp_free(t0);
23283 tcg_temp_free(t1);
a22260ae
JL
23284 break;
23285 }
099e5b4d
LA
23286 default: /* Invalid */
23287 MIPS_INVAL("MASK INSV");
9c708c7f 23288 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
23289 break;
23290 }
23291 break;
23292 case OPC_APPEND_DSP:
23293 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
23294 break;
23295 case OPC_EXTR_W_DSP:
23296 op2 = MASK_EXTR_W(ctx->opcode);
23297 switch (op2) {
23298 case OPC_EXTR_W:
23299 case OPC_EXTR_R_W:
23300 case OPC_EXTR_RS_W:
23301 case OPC_EXTR_S_H:
23302 case OPC_EXTRV_S_H:
23303 case OPC_EXTRV_W:
23304 case OPC_EXTRV_R_W:
23305 case OPC_EXTRV_RS_W:
23306 case OPC_EXTP:
23307 case OPC_EXTPV:
23308 case OPC_EXTPDP:
23309 case OPC_EXTPDPV:
23310 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
23311 break;
23312 case OPC_RDDSP:
23313 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
23314 break;
23315 case OPC_SHILO:
23316 case OPC_SHILOV:
23317 case OPC_MTHLIP:
23318 case OPC_WRDSP:
23319 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
23320 break;
23321 default: /* Invalid */
23322 MIPS_INVAL("MASK EXTR.W");
9c708c7f 23323 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
23324 break;
23325 }
23326 break;
099e5b4d 23327#if defined(TARGET_MIPS64)
c2e19f3c
AM
23328 case OPC_DDIV_G_2E:
23329 case OPC_DDIVU_G_2E:
23330 case OPC_DMULT_G_2E:
23331 case OPC_DMULTU_G_2E:
23332 case OPC_DMOD_G_2E:
23333 case OPC_DMODU_G_2E:
fac5a073
LA
23334 check_insn(ctx, INSN_LOONGSON2E);
23335 gen_loongson_integer(ctx, op1, rd, rs, rt);
099e5b4d 23336 break;
099e5b4d
LA
23337 case OPC_ABSQ_S_QH_DSP:
23338 op2 = MASK_ABSQ_S_QH(ctx->opcode);
23339 switch (op2) {
23340 case OPC_PRECEQ_L_PWL:
23341 case OPC_PRECEQ_L_PWR:
23342 case OPC_PRECEQ_PW_QHL:
23343 case OPC_PRECEQ_PW_QHR:
23344 case OPC_PRECEQ_PW_QHLA:
23345 case OPC_PRECEQ_PW_QHRA:
23346 case OPC_PRECEQU_QH_OBL:
23347 case OPC_PRECEQU_QH_OBR:
23348 case OPC_PRECEQU_QH_OBLA:
23349 case OPC_PRECEQU_QH_OBRA:
23350 case OPC_PRECEU_QH_OBL:
23351 case OPC_PRECEU_QH_OBR:
23352 case OPC_PRECEU_QH_OBLA:
23353 case OPC_PRECEU_QH_OBRA:
23354 case OPC_ABSQ_S_OB:
23355 case OPC_ABSQ_S_PW:
23356 case OPC_ABSQ_S_QH:
23357 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23358 break;
23359 case OPC_REPL_OB:
23360 case OPC_REPL_PW:
23361 case OPC_REPL_QH:
23362 case OPC_REPLV_OB:
23363 case OPC_REPLV_PW:
23364 case OPC_REPLV_QH:
23365 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23366 break;
23367 default: /* Invalid */
23368 MIPS_INVAL("MASK ABSQ_S.QH");
9c708c7f 23369 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
23370 break;
23371 }
23372 break;
23373 case OPC_ADDU_OB_DSP:
23374 op2 = MASK_ADDU_OB(ctx->opcode);
23375 switch (op2) {
23376 case OPC_RADDU_L_OB:
23377 case OPC_SUBQ_PW:
23378 case OPC_SUBQ_S_PW:
23379 case OPC_SUBQ_QH:
23380 case OPC_SUBQ_S_QH:
23381 case OPC_SUBU_OB:
23382 case OPC_SUBU_S_OB:
23383 case OPC_SUBU_QH:
23384 case OPC_SUBU_S_QH:
23385 case OPC_SUBUH_OB:
23386 case OPC_SUBUH_R_OB:
23387 case OPC_ADDQ_PW:
23388 case OPC_ADDQ_S_PW:
23389 case OPC_ADDQ_QH:
23390 case OPC_ADDQ_S_QH:
23391 case OPC_ADDU_OB:
23392 case OPC_ADDU_S_OB:
23393 case OPC_ADDU_QH:
23394 case OPC_ADDU_S_QH:
23395 case OPC_ADDUH_OB:
23396 case OPC_ADDUH_R_OB:
23397 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
a22260ae 23398 break;
099e5b4d
LA
23399 case OPC_MULEQ_S_PW_QHL:
23400 case OPC_MULEQ_S_PW_QHR:
23401 case OPC_MULEU_S_QH_OBL:
23402 case OPC_MULEU_S_QH_OBR:
23403 case OPC_MULQ_RS_QH:
23404 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 23405 break;
099e5b4d
LA
23406 default: /* Invalid */
23407 MIPS_INVAL("MASK ADDU.OB");
9c708c7f 23408 generate_exception_end(ctx, EXCP_RI);
26690560 23409 break;
099e5b4d
LA
23410 }
23411 break;
23412 case OPC_CMPU_EQ_OB_DSP:
23413 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
23414 switch (op2) {
23415 case OPC_PRECR_SRA_QH_PW:
23416 case OPC_PRECR_SRA_R_QH_PW:
23417 /* Return value is rt. */
23418 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
b53371ed 23419 break;
099e5b4d
LA
23420 case OPC_PRECR_OB_QH:
23421 case OPC_PRECRQ_OB_QH:
23422 case OPC_PRECRQ_PW_L:
23423 case OPC_PRECRQ_QH_PW:
23424 case OPC_PRECRQ_RS_QH_PW:
23425 case OPC_PRECRQU_S_OB_QH:
23426 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
4368b29a 23427 break;
099e5b4d
LA
23428 case OPC_CMPU_EQ_OB:
23429 case OPC_CMPU_LT_OB:
23430 case OPC_CMPU_LE_OB:
23431 case OPC_CMP_EQ_QH:
23432 case OPC_CMP_LT_QH:
23433 case OPC_CMP_LE_QH:
23434 case OPC_CMP_EQ_PW:
23435 case OPC_CMP_LT_PW:
23436 case OPC_CMP_LE_PW:
23437 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
7a387fff 23438 break;
099e5b4d
LA
23439 case OPC_CMPGDU_EQ_OB:
23440 case OPC_CMPGDU_LT_OB:
23441 case OPC_CMPGDU_LE_OB:
23442 case OPC_CMPGU_EQ_OB:
23443 case OPC_CMPGU_LT_OB:
23444 case OPC_CMPGU_LE_OB:
23445 case OPC_PACKRL_PW:
23446 case OPC_PICK_OB:
23447 case OPC_PICK_PW:
23448 case OPC_PICK_QH:
23449 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
c6d6dd7c 23450 break;
099e5b4d
LA
23451 default: /* Invalid */
23452 MIPS_INVAL("MASK CMPU_EQ.OB");
9c708c7f 23453 generate_exception_end(ctx, EXCP_RI);
161f85e6 23454 break;
099e5b4d
LA
23455 }
23456 break;
23457 case OPC_DAPPEND_DSP:
23458 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
23459 break;
23460 case OPC_DEXTR_W_DSP:
23461 op2 = MASK_DEXTR_W(ctx->opcode);
23462 switch (op2) {
23463 case OPC_DEXTP:
23464 case OPC_DEXTPDP:
23465 case OPC_DEXTPDPV:
23466 case OPC_DEXTPV:
23467 case OPC_DEXTR_L:
23468 case OPC_DEXTR_R_L:
23469 case OPC_DEXTR_RS_L:
23470 case OPC_DEXTR_W:
23471 case OPC_DEXTR_R_W:
23472 case OPC_DEXTR_RS_W:
23473 case OPC_DEXTR_S_H:
23474 case OPC_DEXTRV_L:
23475 case OPC_DEXTRV_R_L:
23476 case OPC_DEXTRV_RS_L:
23477 case OPC_DEXTRV_S_H:
23478 case OPC_DEXTRV_W:
23479 case OPC_DEXTRV_R_W:
23480 case OPC_DEXTRV_RS_W:
23481 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
461c08df 23482 break;
099e5b4d
LA
23483 case OPC_DMTHLIP:
23484 case OPC_DSHILO:
23485 case OPC_DSHILOV:
23486 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
461c08df 23487 break;
099e5b4d
LA
23488 default: /* Invalid */
23489 MIPS_INVAL("MASK EXTR.W");
9c708c7f 23490 generate_exception_end(ctx, EXCP_RI);
461c08df 23491 break;
099e5b4d
LA
23492 }
23493 break;
23494 case OPC_DPAQ_W_QH_DSP:
23495 op2 = MASK_DPAQ_W_QH(ctx->opcode);
23496 switch (op2) {
23497 case OPC_DPAU_H_OBL:
23498 case OPC_DPAU_H_OBR:
23499 case OPC_DPSU_H_OBL:
23500 case OPC_DPSU_H_OBR:
23501 case OPC_DPA_W_QH:
23502 case OPC_DPAQ_S_W_QH:
23503 case OPC_DPS_W_QH:
23504 case OPC_DPSQ_S_W_QH:
23505 case OPC_MULSAQ_S_W_QH:
23506 case OPC_DPAQ_SA_L_PW:
23507 case OPC_DPSQ_SA_L_PW:
23508 case OPC_MULSAQ_S_L_PW:
23509 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
23510 break;
23511 case OPC_MAQ_S_W_QHLL:
23512 case OPC_MAQ_S_W_QHLR:
23513 case OPC_MAQ_S_W_QHRL:
23514 case OPC_MAQ_S_W_QHRR:
23515 case OPC_MAQ_SA_W_QHLL:
23516 case OPC_MAQ_SA_W_QHLR:
23517 case OPC_MAQ_SA_W_QHRL:
23518 case OPC_MAQ_SA_W_QHRR:
23519 case OPC_MAQ_S_L_PWL:
23520 case OPC_MAQ_S_L_PWR:
23521 case OPC_DMADD:
23522 case OPC_DMADDU:
23523 case OPC_DMSUB:
23524 case OPC_DMSUBU:
23525 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26690560 23526 break;
099e5b4d
LA
23527 default: /* Invalid */
23528 MIPS_INVAL("MASK DPAQ.W.QH");
9c708c7f 23529 generate_exception_end(ctx, EXCP_RI);
b53371ed 23530 break;
099e5b4d
LA
23531 }
23532 break;
23533 case OPC_DINSV_DSP:
23534 op2 = MASK_INSV(ctx->opcode);
23535 switch (op2) {
23536 case OPC_DINSV:
23537 {
23538 TCGv t0, t1;
23539
23540 if (rt == 0) {
a22260ae
JL
23541 break;
23542 }
099e5b4d 23543 check_dsp(ctx);
1cb6686c 23544
099e5b4d
LA
23545 t0 = tcg_temp_new();
23546 t1 = tcg_temp_new();
1cb6686c 23547
099e5b4d
LA
23548 gen_load_gpr(t0, rt);
23549 gen_load_gpr(t1, rs);
1cb6686c 23550
099e5b4d 23551 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
62eb3b9a 23552
099e5b4d
LA
23553 tcg_temp_free(t0);
23554 tcg_temp_free(t1);
77c5fa8b 23555 break;
099e5b4d 23556 }
7a387fff 23557 default: /* Invalid */
099e5b4d 23558 MIPS_INVAL("MASK DINSV");
9c708c7f 23559 generate_exception_end(ctx, EXCP_RI);
7a387fff
TS
23560 break;
23561 }
23562 break;
099e5b4d
LA
23563 case OPC_SHLL_OB_DSP:
23564 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
23565 break;
23566#endif
fac5a073
LA
23567 default: /* Invalid */
23568 MIPS_INVAL("special3_legacy");
9c708c7f 23569 generate_exception_end(ctx, EXCP_RI);
fac5a073
LA
23570 break;
23571 }
23572}
23573
23574static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
23575{
23576 int rs, rt, rd, sa;
23577 uint32_t op1, op2;
76964147 23578 int16_t imm;
fac5a073
LA
23579
23580 rs = (ctx->opcode >> 21) & 0x1f;
23581 rt = (ctx->opcode >> 16) & 0x1f;
23582 rd = (ctx->opcode >> 11) & 0x1f;
23583 sa = (ctx->opcode >> 6) & 0x1f;
76964147 23584 imm = sextract32(ctx->opcode, 7, 9);
fac5a073
LA
23585
23586 op1 = MASK_SPECIAL3(ctx->opcode);
76964147
JH
23587
23588 /*
23589 * EVA loads and stores overlap Loongson 2E instructions decoded by
23590 * decode_opc_special3_legacy(), so be careful to allow their decoding when
23591 * EVA is absent.
23592 */
23593 if (ctx->eva) {
23594 switch (op1) {
c2e19f3c
AM
23595 case OPC_LWLE:
23596 case OPC_LWRE:
76964147
JH
23597 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23598 /* fall through */
c2e19f3c
AM
23599 case OPC_LBUE:
23600 case OPC_LHUE:
23601 case OPC_LBE:
23602 case OPC_LHE:
23603 case OPC_LLE:
23604 case OPC_LWE:
76964147
JH
23605 check_cp0_enabled(ctx);
23606 gen_ld(ctx, op1, rt, rs, imm);
23607 return;
c2e19f3c
AM
23608 case OPC_SWLE:
23609 case OPC_SWRE:
76964147
JH
23610 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23611 /* fall through */
c2e19f3c
AM
23612 case OPC_SBE:
23613 case OPC_SHE:
76964147
JH
23614 case OPC_SWE:
23615 check_cp0_enabled(ctx);
23616 gen_st(ctx, op1, rt, rs, imm);
23617 return;
23618 case OPC_SCE:
23619 check_cp0_enabled(ctx);
23620 gen_st_cond(ctx, op1, rt, rs, imm);
23621 return;
23622 case OPC_CACHEE:
23623 check_cp0_enabled(ctx);
23624 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23625 gen_cache_operation(ctx, rt, rs, imm);
23626 }
23627 /* Treat as NOP. */
23628 return;
23629 case OPC_PREFE:
23630 check_cp0_enabled(ctx);
23631 /* Treat as NOP. */
23632 return;
23633 }
23634 }
23635
fac5a073
LA
23636 switch (op1) {
23637 case OPC_EXT:
23638 case OPC_INS:
23639 check_insn(ctx, ISA_MIPS32R2);
23640 gen_bitops(ctx, op1, rt, rs, sa, rd);
23641 break;
23642 case OPC_BSHFL:
fac5a073 23643 op2 = MASK_BSHFL(ctx->opcode);
15eacb9b 23644 switch (op2) {
c2e19f3c
AM
23645 case OPC_ALIGN:
23646 case OPC_ALIGN_END:
15eacb9b
YK
23647 case OPC_BITSWAP:
23648 check_insn(ctx, ISA_MIPS32R6);
23649 decode_opc_special3_r6(env, ctx);
23650 break;
23651 default:
23652 check_insn(ctx, ISA_MIPS32R2);
23653 gen_bshfl(ctx, op2, rt, rd);
23654 break;
23655 }
fac5a073
LA
23656 break;
23657#if defined(TARGET_MIPS64)
c2e19f3c
AM
23658 case OPC_DEXTM:
23659 case OPC_DEXTU:
23660 case OPC_DEXT:
23661 case OPC_DINSM:
23662 case OPC_DINSU:
23663 case OPC_DINS:
fac5a073
LA
23664 check_insn(ctx, ISA_MIPS64R2);
23665 check_mips_64(ctx);
23666 gen_bitops(ctx, op1, rt, rs, sa, rd);
23667 break;
23668 case OPC_DBSHFL:
fac5a073 23669 op2 = MASK_DBSHFL(ctx->opcode);
15eacb9b 23670 switch (op2) {
c2e19f3c
AM
23671 case OPC_DALIGN:
23672 case OPC_DALIGN_END:
15eacb9b
YK
23673 case OPC_DBITSWAP:
23674 check_insn(ctx, ISA_MIPS32R6);
23675 decode_opc_special3_r6(env, ctx);
23676 break;
23677 default:
23678 check_insn(ctx, ISA_MIPS64R2);
23679 check_mips_64(ctx);
23680 op2 = MASK_DBSHFL(ctx->opcode);
23681 gen_bshfl(ctx, op2, rt, rd);
23682 break;
23683 }
fac5a073
LA
23684 break;
23685#endif
23686 case OPC_RDHWR:
b00c7218 23687 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
fac5a073
LA
23688 break;
23689 case OPC_FORK:
9affc1c5 23690 check_mt(ctx);
fac5a073
LA
23691 {
23692 TCGv t0 = tcg_temp_new();
23693 TCGv t1 = tcg_temp_new();
23694
23695 gen_load_gpr(t0, rt);
23696 gen_load_gpr(t1, rs);
23697 gen_helper_fork(t0, t1);
23698 tcg_temp_free(t0);
23699 tcg_temp_free(t1);
23700 }
23701 break;
23702 case OPC_YIELD:
9affc1c5 23703 check_mt(ctx);
fac5a073
LA
23704 {
23705 TCGv t0 = tcg_temp_new();
23706
fac5a073
LA
23707 gen_load_gpr(t0, rs);
23708 gen_helper_yield(t0, cpu_env, t0);
23709 gen_store_gpr(t0, rd);
23710 tcg_temp_free(t0);
23711 }
23712 break;
10dc65db
LA
23713 default:
23714 if (ctx->insn_flags & ISA_MIPS32R6) {
23715 decode_opc_special3_r6(env, ctx);
23716 } else {
23717 decode_opc_special3_legacy(env, ctx);
23718 }
099e5b4d
LA
23719 }
23720}
23721
863f264d
YK
23722/* MIPS SIMD Architecture (MSA) */
23723static inline int check_msa_access(DisasContext *ctx)
23724{
23725 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
23726 !(ctx->hflags & MIPS_HFLAG_F64))) {
9c708c7f 23727 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
23728 return 0;
23729 }
23730
23731 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
23732 if (ctx->insn_flags & ASE_MSA) {
9c708c7f 23733 generate_exception_end(ctx, EXCP_MSADIS);
863f264d
YK
23734 return 0;
23735 } else {
9c708c7f 23736 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
23737 return 0;
23738 }
23739 }
23740 return 1;
23741}
23742
5692c6e1
YK
23743static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
23744{
23745 /* generates tcg ops to check if any element is 0 */
23746 /* Note this function only works with MSA_WRLEN = 128 */
23747 uint64_t eval_zero_or_big = 0;
23748 uint64_t eval_big = 0;
23749 TCGv_i64 t0 = tcg_temp_new_i64();
23750 TCGv_i64 t1 = tcg_temp_new_i64();
23751 switch (df) {
23752 case DF_BYTE:
23753 eval_zero_or_big = 0x0101010101010101ULL;
23754 eval_big = 0x8080808080808080ULL;
23755 break;
23756 case DF_HALF:
23757 eval_zero_or_big = 0x0001000100010001ULL;
23758 eval_big = 0x8000800080008000ULL;
23759 break;
23760 case DF_WORD:
23761 eval_zero_or_big = 0x0000000100000001ULL;
23762 eval_big = 0x8000000080000000ULL;
23763 break;
23764 case DF_DOUBLE:
23765 eval_zero_or_big = 0x0000000000000001ULL;
23766 eval_big = 0x8000000000000000ULL;
23767 break;
23768 }
23769 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
23770 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
23771 tcg_gen_andi_i64(t0, t0, eval_big);
23772 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
23773 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
23774 tcg_gen_andi_i64(t1, t1, eval_big);
23775 tcg_gen_or_i64(t0, t0, t1);
23776 /* if all bits are zero then all elements are not zero */
23777 /* if some bit is non-zero then some element is zero */
23778 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
23779 tcg_gen_trunc_i64_tl(tresult, t0);
23780 tcg_temp_free_i64(t0);
23781 tcg_temp_free_i64(t1);
23782}
23783
23784static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
23785{
23786 uint8_t df = (ctx->opcode >> 21) & 0x3;
23787 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
23788 int64_t s16 = (int16_t)ctx->opcode;
23789
23790 check_msa_access(ctx);
23791
075a1fe7 23792 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 23793 generate_exception_end(ctx, EXCP_RI);
5692c6e1
YK
23794 return;
23795 }
23796 switch (op1) {
23797 case OPC_BZ_V:
23798 case OPC_BNZ_V:
23799 {
23800 TCGv_i64 t0 = tcg_temp_new_i64();
23801 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
23802 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
23803 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
23804 tcg_gen_trunc_i64_tl(bcond, t0);
23805 tcg_temp_free_i64(t0);
23806 }
23807 break;
23808 case OPC_BZ_B:
23809 case OPC_BZ_H:
23810 case OPC_BZ_W:
23811 case OPC_BZ_D:
23812 gen_check_zero_element(bcond, df, wt);
23813 break;
23814 case OPC_BNZ_B:
23815 case OPC_BNZ_H:
23816 case OPC_BNZ_W:
23817 case OPC_BNZ_D:
23818 gen_check_zero_element(bcond, df, wt);
23819 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
23820 break;
23821 }
23822
eeb3bba8 23823 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
5692c6e1
YK
23824
23825 ctx->hflags |= MIPS_HFLAG_BC;
23826 ctx->hflags |= MIPS_HFLAG_BDS32;
23827}
23828
4c789546
YK
23829static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
23830{
23831#define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
23832 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
23833 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
23834 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
23835
23836 TCGv_i32 twd = tcg_const_i32(wd);
23837 TCGv_i32 tws = tcg_const_i32(ws);
23838 TCGv_i32 ti8 = tcg_const_i32(i8);
23839
23840 switch (MASK_MSA_I8(ctx->opcode)) {
23841 case OPC_ANDI_B:
23842 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
23843 break;
23844 case OPC_ORI_B:
23845 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
23846 break;
23847 case OPC_NORI_B:
23848 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
23849 break;
23850 case OPC_XORI_B:
23851 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
23852 break;
23853 case OPC_BMNZI_B:
23854 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
23855 break;
23856 case OPC_BMZI_B:
23857 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
23858 break;
23859 case OPC_BSELI_B:
23860 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
23861 break;
23862 case OPC_SHF_B:
23863 case OPC_SHF_H:
23864 case OPC_SHF_W:
23865 {
23866 uint8_t df = (ctx->opcode >> 24) & 0x3;
23867 if (df == DF_DOUBLE) {
9c708c7f 23868 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
23869 } else {
23870 TCGv_i32 tdf = tcg_const_i32(df);
23871 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
23872 tcg_temp_free_i32(tdf);
23873 }
23874 }
23875 break;
23876 default:
23877 MIPS_INVAL("MSA instruction");
9c708c7f 23878 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
23879 break;
23880 }
23881
23882 tcg_temp_free_i32(twd);
23883 tcg_temp_free_i32(tws);
23884 tcg_temp_free_i32(ti8);
23885}
23886
80e71591
YK
23887static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
23888{
23889#define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
23890 uint8_t df = (ctx->opcode >> 21) & 0x3;
23891 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
23892 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
23893 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
23894 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
23895
23896 TCGv_i32 tdf = tcg_const_i32(df);
23897 TCGv_i32 twd = tcg_const_i32(wd);
23898 TCGv_i32 tws = tcg_const_i32(ws);
23899 TCGv_i32 timm = tcg_temp_new_i32();
23900 tcg_gen_movi_i32(timm, u5);
23901
23902 switch (MASK_MSA_I5(ctx->opcode)) {
23903 case OPC_ADDVI_df:
23904 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
23905 break;
23906 case OPC_SUBVI_df:
23907 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
23908 break;
23909 case OPC_MAXI_S_df:
23910 tcg_gen_movi_i32(timm, s5);
23911 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
23912 break;
23913 case OPC_MAXI_U_df:
23914 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
23915 break;
23916 case OPC_MINI_S_df:
23917 tcg_gen_movi_i32(timm, s5);
23918 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
23919 break;
23920 case OPC_MINI_U_df:
23921 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
23922 break;
23923 case OPC_CEQI_df:
23924 tcg_gen_movi_i32(timm, s5);
23925 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
23926 break;
23927 case OPC_CLTI_S_df:
23928 tcg_gen_movi_i32(timm, s5);
23929 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
23930 break;
23931 case OPC_CLTI_U_df:
23932 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
23933 break;
23934 case OPC_CLEI_S_df:
23935 tcg_gen_movi_i32(timm, s5);
23936 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
23937 break;
23938 case OPC_CLEI_U_df:
23939 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
23940 break;
23941 case OPC_LDI_df:
23942 {
23943 int32_t s10 = sextract32(ctx->opcode, 11, 10);
23944 tcg_gen_movi_i32(timm, s10);
23945 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
23946 }
23947 break;
23948 default:
23949 MIPS_INVAL("MSA instruction");
9c708c7f 23950 generate_exception_end(ctx, EXCP_RI);
80e71591
YK
23951 break;
23952 }
23953
23954 tcg_temp_free_i32(tdf);
23955 tcg_temp_free_i32(twd);
23956 tcg_temp_free_i32(tws);
23957 tcg_temp_free_i32(timm);
23958}
23959
d4cf28de
YK
23960static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
23961{
23962#define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
23963 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
23964 uint32_t df = 0, m = 0;
23965 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
23966 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
23967
23968 TCGv_i32 tdf;
23969 TCGv_i32 tm;
23970 TCGv_i32 twd;
23971 TCGv_i32 tws;
23972
23973 if ((dfm & 0x40) == 0x00) {
23974 m = dfm & 0x3f;
23975 df = DF_DOUBLE;
23976 } else if ((dfm & 0x60) == 0x40) {
23977 m = dfm & 0x1f;
23978 df = DF_WORD;
23979 } else if ((dfm & 0x70) == 0x60) {
23980 m = dfm & 0x0f;
23981 df = DF_HALF;
23982 } else if ((dfm & 0x78) == 0x70) {
23983 m = dfm & 0x7;
23984 df = DF_BYTE;
23985 } else {
9c708c7f 23986 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
23987 return;
23988 }
23989
23990 tdf = tcg_const_i32(df);
23991 tm = tcg_const_i32(m);
23992 twd = tcg_const_i32(wd);
23993 tws = tcg_const_i32(ws);
23994
23995 switch (MASK_MSA_BIT(ctx->opcode)) {
23996 case OPC_SLLI_df:
23997 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
23998 break;
23999 case OPC_SRAI_df:
24000 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
24001 break;
24002 case OPC_SRLI_df:
24003 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
24004 break;
24005 case OPC_BCLRI_df:
24006 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
24007 break;
24008 case OPC_BSETI_df:
24009 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
24010 break;
24011 case OPC_BNEGI_df:
24012 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
24013 break;
24014 case OPC_BINSLI_df:
24015 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
24016 break;
24017 case OPC_BINSRI_df:
24018 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
24019 break;
24020 case OPC_SAT_S_df:
24021 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
24022 break;
24023 case OPC_SAT_U_df:
24024 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
24025 break;
24026 case OPC_SRARI_df:
24027 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
24028 break;
24029 case OPC_SRLRI_df:
24030 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
24031 break;
24032 default:
24033 MIPS_INVAL("MSA instruction");
9c708c7f 24034 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
24035 break;
24036 }
24037
24038 tcg_temp_free_i32(tdf);
24039 tcg_temp_free_i32(tm);
24040 tcg_temp_free_i32(twd);
24041 tcg_temp_free_i32(tws);
24042}
24043
28f99f08
YK
24044static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
24045{
24046#define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
24047 uint8_t df = (ctx->opcode >> 21) & 0x3;
24048 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24049 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24050 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24051
24052 TCGv_i32 tdf = tcg_const_i32(df);
24053 TCGv_i32 twd = tcg_const_i32(wd);
24054 TCGv_i32 tws = tcg_const_i32(ws);
24055 TCGv_i32 twt = tcg_const_i32(wt);
24056
24057 switch (MASK_MSA_3R(ctx->opcode)) {
24058 case OPC_SLL_df:
24059 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
24060 break;
24061 case OPC_ADDV_df:
24062 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
24063 break;
24064 case OPC_CEQ_df:
24065 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
24066 break;
24067 case OPC_ADD_A_df:
24068 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
24069 break;
24070 case OPC_SUBS_S_df:
24071 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
24072 break;
24073 case OPC_MULV_df:
24074 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
24075 break;
24076 case OPC_SLD_df:
24077 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
24078 break;
24079 case OPC_VSHF_df:
24080 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
24081 break;
24082 case OPC_SRA_df:
24083 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
24084 break;
24085 case OPC_SUBV_df:
24086 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
24087 break;
24088 case OPC_ADDS_A_df:
24089 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
24090 break;
24091 case OPC_SUBS_U_df:
24092 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
24093 break;
24094 case OPC_MADDV_df:
24095 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
24096 break;
24097 case OPC_SPLAT_df:
24098 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
24099 break;
24100 case OPC_SRAR_df:
24101 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
24102 break;
24103 case OPC_SRL_df:
24104 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
24105 break;
24106 case OPC_MAX_S_df:
24107 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
24108 break;
24109 case OPC_CLT_S_df:
24110 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
24111 break;
24112 case OPC_ADDS_S_df:
24113 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
24114 break;
24115 case OPC_SUBSUS_U_df:
24116 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
24117 break;
24118 case OPC_MSUBV_df:
24119 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
24120 break;
24121 case OPC_PCKEV_df:
24122 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
24123 break;
24124 case OPC_SRLR_df:
24125 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
24126 break;
24127 case OPC_BCLR_df:
24128 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
24129 break;
24130 case OPC_MAX_U_df:
24131 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
24132 break;
24133 case OPC_CLT_U_df:
24134 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
24135 break;
24136 case OPC_ADDS_U_df:
24137 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
24138 break;
24139 case OPC_SUBSUU_S_df:
24140 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
24141 break;
24142 case OPC_PCKOD_df:
24143 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
24144 break;
24145 case OPC_BSET_df:
24146 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
24147 break;
24148 case OPC_MIN_S_df:
24149 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
24150 break;
24151 case OPC_CLE_S_df:
24152 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
24153 break;
24154 case OPC_AVE_S_df:
24155 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
24156 break;
24157 case OPC_ASUB_S_df:
24158 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
24159 break;
24160 case OPC_DIV_S_df:
24161 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
24162 break;
24163 case OPC_ILVL_df:
24164 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
24165 break;
24166 case OPC_BNEG_df:
24167 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
24168 break;
24169 case OPC_MIN_U_df:
24170 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
24171 break;
24172 case OPC_CLE_U_df:
24173 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
24174 break;
24175 case OPC_AVE_U_df:
24176 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
24177 break;
24178 case OPC_ASUB_U_df:
24179 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
24180 break;
24181 case OPC_DIV_U_df:
24182 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
24183 break;
24184 case OPC_ILVR_df:
24185 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
24186 break;
24187 case OPC_BINSL_df:
24188 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
24189 break;
24190 case OPC_MAX_A_df:
24191 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
24192 break;
24193 case OPC_AVER_S_df:
24194 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
24195 break;
24196 case OPC_MOD_S_df:
24197 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
24198 break;
24199 case OPC_ILVEV_df:
24200 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
24201 break;
24202 case OPC_BINSR_df:
24203 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
24204 break;
24205 case OPC_MIN_A_df:
24206 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
24207 break;
24208 case OPC_AVER_U_df:
24209 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
24210 break;
24211 case OPC_MOD_U_df:
24212 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
24213 break;
24214 case OPC_ILVOD_df:
24215 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
24216 break;
24217
24218 case OPC_DOTP_S_df:
24219 case OPC_DOTP_U_df:
24220 case OPC_DPADD_S_df:
24221 case OPC_DPADD_U_df:
24222 case OPC_DPSUB_S_df:
24223 case OPC_HADD_S_df:
24224 case OPC_DPSUB_U_df:
24225 case OPC_HADD_U_df:
24226 case OPC_HSUB_S_df:
24227 case OPC_HSUB_U_df:
24228 if (df == DF_BYTE) {
9c708c7f
PD
24229 generate_exception_end(ctx, EXCP_RI);
24230 break;
28f99f08
YK
24231 }
24232 switch (MASK_MSA_3R(ctx->opcode)) {
24233 case OPC_DOTP_S_df:
24234 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
24235 break;
24236 case OPC_DOTP_U_df:
24237 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
24238 break;
24239 case OPC_DPADD_S_df:
24240 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
24241 break;
24242 case OPC_DPADD_U_df:
24243 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
24244 break;
24245 case OPC_DPSUB_S_df:
24246 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
24247 break;
24248 case OPC_HADD_S_df:
24249 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
24250 break;
24251 case OPC_DPSUB_U_df:
24252 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
24253 break;
24254 case OPC_HADD_U_df:
24255 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
24256 break;
24257 case OPC_HSUB_S_df:
24258 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
24259 break;
24260 case OPC_HSUB_U_df:
24261 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
24262 break;
24263 }
24264 break;
24265 default:
24266 MIPS_INVAL("MSA instruction");
9c708c7f 24267 generate_exception_end(ctx, EXCP_RI);
28f99f08
YK
24268 break;
24269 }
24270 tcg_temp_free_i32(twd);
24271 tcg_temp_free_i32(tws);
24272 tcg_temp_free_i32(twt);
24273 tcg_temp_free_i32(tdf);
24274}
24275
1e608ec1
YK
24276static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
24277{
24278#define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
24279 uint8_t source = (ctx->opcode >> 11) & 0x1f;
24280 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
24281 TCGv telm = tcg_temp_new();
24282 TCGv_i32 tsr = tcg_const_i32(source);
24283 TCGv_i32 tdt = tcg_const_i32(dest);
24284
24285 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
24286 case OPC_CTCMSA:
24287 gen_load_gpr(telm, source);
24288 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
24289 break;
24290 case OPC_CFCMSA:
24291 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
24292 gen_store_gpr(telm, dest);
24293 break;
24294 case OPC_MOVE_V:
24295 gen_helper_msa_move_v(cpu_env, tdt, tsr);
24296 break;
24297 default:
24298 MIPS_INVAL("MSA instruction");
9c708c7f 24299 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
24300 break;
24301 }
24302
24303 tcg_temp_free(telm);
24304 tcg_temp_free_i32(tdt);
24305 tcg_temp_free_i32(tsr);
24306}
24307
24308static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
24309 uint32_t n)
24310{
24311#define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
24312 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24313 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24314
24315 TCGv_i32 tws = tcg_const_i32(ws);
24316 TCGv_i32 twd = tcg_const_i32(wd);
24317 TCGv_i32 tn = tcg_const_i32(n);
24318 TCGv_i32 tdf = tcg_const_i32(df);
24319
24320 switch (MASK_MSA_ELM(ctx->opcode)) {
24321 case OPC_SLDI_df:
24322 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
24323 break;
24324 case OPC_SPLATI_df:
24325 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
24326 break;
24327 case OPC_INSVE_df:
24328 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
24329 break;
24330 case OPC_COPY_S_df:
24331 case OPC_COPY_U_df:
24332 case OPC_INSERT_df:
24333#if !defined(TARGET_MIPS64)
24334 /* Double format valid only for MIPS64 */
24335 if (df == DF_DOUBLE) {
9c708c7f 24336 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
24337 break;
24338 }
24339#endif
24340 switch (MASK_MSA_ELM(ctx->opcode)) {
24341 case OPC_COPY_S_df:
cab48881
MD
24342 if (likely(wd != 0)) {
24343 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
24344 }
1e608ec1
YK
24345 break;
24346 case OPC_COPY_U_df:
cab48881
MD
24347 if (likely(wd != 0)) {
24348 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
24349 }
1e608ec1
YK
24350 break;
24351 case OPC_INSERT_df:
24352 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
24353 break;
24354 }
24355 break;
24356 default:
24357 MIPS_INVAL("MSA instruction");
9c708c7f 24358 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
24359 }
24360 tcg_temp_free_i32(twd);
24361 tcg_temp_free_i32(tws);
24362 tcg_temp_free_i32(tn);
24363 tcg_temp_free_i32(tdf);
24364}
24365
24366static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
24367{
24368 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
24369 uint32_t df = 0, n = 0;
24370
24371 if ((dfn & 0x30) == 0x00) {
24372 n = dfn & 0x0f;
24373 df = DF_BYTE;
24374 } else if ((dfn & 0x38) == 0x20) {
24375 n = dfn & 0x07;
24376 df = DF_HALF;
24377 } else if ((dfn & 0x3c) == 0x30) {
24378 n = dfn & 0x03;
24379 df = DF_WORD;
24380 } else if ((dfn & 0x3e) == 0x38) {
24381 n = dfn & 0x01;
24382 df = DF_DOUBLE;
24383 } else if (dfn == 0x3E) {
24384 /* CTCMSA, CFCMSA, MOVE.V */
24385 gen_msa_elm_3e(env, ctx);
24386 return;
24387 } else {
9c708c7f 24388 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
24389 return;
24390 }
24391
24392 gen_msa_elm_df(env, ctx, df, n);
24393}
24394
7d05b9c8
YK
24395static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
24396{
24397#define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
24398 uint8_t df = (ctx->opcode >> 21) & 0x1;
24399 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24400 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24401 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24402
24403 TCGv_i32 twd = tcg_const_i32(wd);
24404 TCGv_i32 tws = tcg_const_i32(ws);
24405 TCGv_i32 twt = tcg_const_i32(wt);
24406 TCGv_i32 tdf = tcg_temp_new_i32();
24407
24408 /* adjust df value for floating-point instruction */
24409 tcg_gen_movi_i32(tdf, df + 2);
24410
24411 switch (MASK_MSA_3RF(ctx->opcode)) {
24412 case OPC_FCAF_df:
24413 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
24414 break;
24415 case OPC_FADD_df:
24416 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
24417 break;
24418 case OPC_FCUN_df:
24419 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
24420 break;
24421 case OPC_FSUB_df:
24422 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
24423 break;
24424 case OPC_FCOR_df:
24425 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
24426 break;
24427 case OPC_FCEQ_df:
24428 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
24429 break;
24430 case OPC_FMUL_df:
24431 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
24432 break;
24433 case OPC_FCUNE_df:
24434 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
24435 break;
24436 case OPC_FCUEQ_df:
24437 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
24438 break;
24439 case OPC_FDIV_df:
24440 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
24441 break;
24442 case OPC_FCNE_df:
24443 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
24444 break;
24445 case OPC_FCLT_df:
24446 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
24447 break;
24448 case OPC_FMADD_df:
24449 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
24450 break;
24451 case OPC_MUL_Q_df:
24452 tcg_gen_movi_i32(tdf, df + 1);
24453 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
24454 break;
24455 case OPC_FCULT_df:
24456 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
24457 break;
24458 case OPC_FMSUB_df:
24459 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
24460 break;
24461 case OPC_MADD_Q_df:
24462 tcg_gen_movi_i32(tdf, df + 1);
24463 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
24464 break;
24465 case OPC_FCLE_df:
24466 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
24467 break;
24468 case OPC_MSUB_Q_df:
24469 tcg_gen_movi_i32(tdf, df + 1);
24470 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
24471 break;
24472 case OPC_FCULE_df:
24473 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
24474 break;
24475 case OPC_FEXP2_df:
24476 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
24477 break;
24478 case OPC_FSAF_df:
24479 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
24480 break;
24481 case OPC_FEXDO_df:
24482 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
24483 break;
24484 case OPC_FSUN_df:
24485 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
24486 break;
24487 case OPC_FSOR_df:
24488 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
24489 break;
24490 case OPC_FSEQ_df:
24491 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
24492 break;
24493 case OPC_FTQ_df:
24494 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
24495 break;
24496 case OPC_FSUNE_df:
24497 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
24498 break;
24499 case OPC_FSUEQ_df:
24500 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
24501 break;
24502 case OPC_FSNE_df:
24503 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
24504 break;
24505 case OPC_FSLT_df:
24506 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
24507 break;
24508 case OPC_FMIN_df:
24509 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
24510 break;
24511 case OPC_MULR_Q_df:
24512 tcg_gen_movi_i32(tdf, df + 1);
24513 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
24514 break;
24515 case OPC_FSULT_df:
24516 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
24517 break;
24518 case OPC_FMIN_A_df:
24519 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
24520 break;
24521 case OPC_MADDR_Q_df:
24522 tcg_gen_movi_i32(tdf, df + 1);
24523 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
24524 break;
24525 case OPC_FSLE_df:
24526 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
24527 break;
24528 case OPC_FMAX_df:
24529 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
24530 break;
24531 case OPC_MSUBR_Q_df:
24532 tcg_gen_movi_i32(tdf, df + 1);
24533 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
24534 break;
24535 case OPC_FSULE_df:
24536 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
24537 break;
24538 case OPC_FMAX_A_df:
24539 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
24540 break;
24541 default:
24542 MIPS_INVAL("MSA instruction");
9c708c7f 24543 generate_exception_end(ctx, EXCP_RI);
7d05b9c8
YK
24544 break;
24545 }
24546
24547 tcg_temp_free_i32(twd);
24548 tcg_temp_free_i32(tws);
24549 tcg_temp_free_i32(twt);
24550 tcg_temp_free_i32(tdf);
24551}
24552
cbe50b9a
YK
24553static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
24554{
24555#define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
24556 (op & (0x7 << 18)))
24557 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24558 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24559 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24560 uint8_t df = (ctx->opcode >> 16) & 0x3;
24561 TCGv_i32 twd = tcg_const_i32(wd);
24562 TCGv_i32 tws = tcg_const_i32(ws);
24563 TCGv_i32 twt = tcg_const_i32(wt);
24564 TCGv_i32 tdf = tcg_const_i32(df);
24565
24566 switch (MASK_MSA_2R(ctx->opcode)) {
24567 case OPC_FILL_df:
24568#if !defined(TARGET_MIPS64)
24569 /* Double format valid only for MIPS64 */
24570 if (df == DF_DOUBLE) {
9c708c7f 24571 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
24572 break;
24573 }
24574#endif
24575 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
24576 break;
24577 case OPC_PCNT_df:
24578 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
24579 break;
24580 case OPC_NLOC_df:
24581 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
24582 break;
24583 case OPC_NLZC_df:
24584 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
24585 break;
24586 default:
24587 MIPS_INVAL("MSA instruction");
9c708c7f 24588 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
24589 break;
24590 }
24591
24592 tcg_temp_free_i32(twd);
24593 tcg_temp_free_i32(tws);
24594 tcg_temp_free_i32(twt);
24595 tcg_temp_free_i32(tdf);
24596}
24597
3bdeb688
YK
24598static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
24599{
24600#define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
24601 (op & (0xf << 17)))
24602 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24603 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24604 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24605 uint8_t df = (ctx->opcode >> 16) & 0x1;
24606 TCGv_i32 twd = tcg_const_i32(wd);
24607 TCGv_i32 tws = tcg_const_i32(ws);
24608 TCGv_i32 twt = tcg_const_i32(wt);
24609 /* adjust df value for floating-point instruction */
24610 TCGv_i32 tdf = tcg_const_i32(df + 2);
24611
24612 switch (MASK_MSA_2RF(ctx->opcode)) {
24613 case OPC_FCLASS_df:
24614 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
24615 break;
24616 case OPC_FTRUNC_S_df:
24617 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
24618 break;
24619 case OPC_FTRUNC_U_df:
24620 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
24621 break;
24622 case OPC_FSQRT_df:
24623 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
24624 break;
24625 case OPC_FRSQRT_df:
24626 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
24627 break;
24628 case OPC_FRCP_df:
24629 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
24630 break;
24631 case OPC_FRINT_df:
24632 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
24633 break;
24634 case OPC_FLOG2_df:
24635 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
24636 break;
24637 case OPC_FEXUPL_df:
24638 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
24639 break;
24640 case OPC_FEXUPR_df:
24641 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
24642 break;
24643 case OPC_FFQL_df:
24644 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
24645 break;
24646 case OPC_FFQR_df:
24647 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
24648 break;
24649 case OPC_FTINT_S_df:
24650 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
24651 break;
24652 case OPC_FTINT_U_df:
24653 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
24654 break;
24655 case OPC_FFINT_S_df:
24656 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
24657 break;
24658 case OPC_FFINT_U_df:
24659 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
24660 break;
24661 }
24662
24663 tcg_temp_free_i32(twd);
24664 tcg_temp_free_i32(tws);
24665 tcg_temp_free_i32(twt);
24666 tcg_temp_free_i32(tdf);
24667}
24668
cbe50b9a
YK
24669static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
24670{
24671#define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
24672 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24673 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24674 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24675 TCGv_i32 twd = tcg_const_i32(wd);
24676 TCGv_i32 tws = tcg_const_i32(ws);
24677 TCGv_i32 twt = tcg_const_i32(wt);
24678
24679 switch (MASK_MSA_VEC(ctx->opcode)) {
24680 case OPC_AND_V:
24681 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
24682 break;
24683 case OPC_OR_V:
24684 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
24685 break;
24686 case OPC_NOR_V:
24687 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
24688 break;
24689 case OPC_XOR_V:
24690 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
24691 break;
24692 case OPC_BMNZ_V:
24693 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
24694 break;
24695 case OPC_BMZ_V:
24696 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
24697 break;
24698 case OPC_BSEL_V:
24699 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
24700 break;
24701 default:
24702 MIPS_INVAL("MSA instruction");
9c708c7f 24703 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
24704 break;
24705 }
24706
24707 tcg_temp_free_i32(twd);
24708 tcg_temp_free_i32(tws);
24709 tcg_temp_free_i32(twt);
24710}
24711
24712static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
24713{
24714 switch (MASK_MSA_VEC(ctx->opcode)) {
24715 case OPC_AND_V:
24716 case OPC_OR_V:
24717 case OPC_NOR_V:
24718 case OPC_XOR_V:
24719 case OPC_BMNZ_V:
24720 case OPC_BMZ_V:
24721 case OPC_BSEL_V:
24722 gen_msa_vec_v(env, ctx);
24723 break;
24724 case OPC_MSA_2R:
24725 gen_msa_2r(env, ctx);
24726 break;
3bdeb688
YK
24727 case OPC_MSA_2RF:
24728 gen_msa_2rf(env, ctx);
24729 break;
cbe50b9a
YK
24730 default:
24731 MIPS_INVAL("MSA instruction");
9c708c7f 24732 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
24733 break;
24734 }
24735}
24736
4c789546
YK
24737static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
24738{
24739 uint32_t opcode = ctx->opcode;
24740 check_insn(ctx, ASE_MSA);
24741 check_msa_access(ctx);
24742
24743 switch (MASK_MSA_MINOR(opcode)) {
24744 case OPC_MSA_I8_00:
24745 case OPC_MSA_I8_01:
24746 case OPC_MSA_I8_02:
24747 gen_msa_i8(env, ctx);
24748 break;
80e71591
YK
24749 case OPC_MSA_I5_06:
24750 case OPC_MSA_I5_07:
24751 gen_msa_i5(env, ctx);
24752 break;
d4cf28de
YK
24753 case OPC_MSA_BIT_09:
24754 case OPC_MSA_BIT_0A:
24755 gen_msa_bit(env, ctx);
24756 break;
28f99f08
YK
24757 case OPC_MSA_3R_0D:
24758 case OPC_MSA_3R_0E:
24759 case OPC_MSA_3R_0F:
24760 case OPC_MSA_3R_10:
24761 case OPC_MSA_3R_11:
24762 case OPC_MSA_3R_12:
24763 case OPC_MSA_3R_13:
24764 case OPC_MSA_3R_14:
24765 case OPC_MSA_3R_15:
24766 gen_msa_3r(env, ctx);
24767 break;
1e608ec1
YK
24768 case OPC_MSA_ELM:
24769 gen_msa_elm(env, ctx);
24770 break;
7d05b9c8
YK
24771 case OPC_MSA_3RF_1A:
24772 case OPC_MSA_3RF_1B:
24773 case OPC_MSA_3RF_1C:
24774 gen_msa_3rf(env, ctx);
24775 break;
cbe50b9a
YK
24776 case OPC_MSA_VEC:
24777 gen_msa_vec(env, ctx);
24778 break;
f7685877
YK
24779 case OPC_LD_B:
24780 case OPC_LD_H:
24781 case OPC_LD_W:
24782 case OPC_LD_D:
24783 case OPC_ST_B:
24784 case OPC_ST_H:
24785 case OPC_ST_W:
24786 case OPC_ST_D:
24787 {
24788 int32_t s10 = sextract32(ctx->opcode, 16, 10);
24789 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
24790 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24791 uint8_t df = (ctx->opcode >> 0) & 0x3;
24792
f7685877 24793 TCGv_i32 twd = tcg_const_i32(wd);
adc370a4
YK
24794 TCGv taddr = tcg_temp_new();
24795 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
f7685877
YK
24796
24797 switch (MASK_MSA_MINOR(opcode)) {
24798 case OPC_LD_B:
adc370a4
YK
24799 gen_helper_msa_ld_b(cpu_env, twd, taddr);
24800 break;
f7685877 24801 case OPC_LD_H:
adc370a4
YK
24802 gen_helper_msa_ld_h(cpu_env, twd, taddr);
24803 break;
f7685877 24804 case OPC_LD_W:
adc370a4
YK
24805 gen_helper_msa_ld_w(cpu_env, twd, taddr);
24806 break;
f7685877 24807 case OPC_LD_D:
adc370a4 24808 gen_helper_msa_ld_d(cpu_env, twd, taddr);
f7685877
YK
24809 break;
24810 case OPC_ST_B:
adc370a4
YK
24811 gen_helper_msa_st_b(cpu_env, twd, taddr);
24812 break;
f7685877 24813 case OPC_ST_H:
adc370a4
YK
24814 gen_helper_msa_st_h(cpu_env, twd, taddr);
24815 break;
f7685877 24816 case OPC_ST_W:
adc370a4
YK
24817 gen_helper_msa_st_w(cpu_env, twd, taddr);
24818 break;
f7685877 24819 case OPC_ST_D:
adc370a4 24820 gen_helper_msa_st_d(cpu_env, twd, taddr);
f7685877
YK
24821 break;
24822 }
24823
24824 tcg_temp_free_i32(twd);
adc370a4 24825 tcg_temp_free(taddr);
f7685877
YK
24826 }
24827 break;
4c789546
YK
24828 default:
24829 MIPS_INVAL("MSA instruction");
9c708c7f 24830 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
24831 break;
24832 }
24833
24834}
24835
d2bfa6e6 24836static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
24837{
24838 int32_t offset;
24839 int rs, rt, rd, sa;
24840 uint32_t op, op1;
24841 int16_t imm;
24842
24843 /* make sure instructions are on a word boundary */
eeb3bba8
EC
24844 if (ctx->base.pc_next & 0x3) {
24845 env->CP0_BadVAddr = ctx->base.pc_next;
aea14095 24846 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
099e5b4d
LA
24847 return;
24848 }
24849
24850 /* Handle blikely not taken case */
24851 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
42a268c2 24852 TCGLabel *l1 = gen_new_label();
099e5b4d 24853
099e5b4d
LA
24854 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
24855 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
eeb3bba8 24856 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
099e5b4d
LA
24857 gen_set_label(l1);
24858 }
24859
099e5b4d
LA
24860 op = MASK_OP_MAJOR(ctx->opcode);
24861 rs = (ctx->opcode >> 21) & 0x1f;
24862 rt = (ctx->opcode >> 16) & 0x1f;
24863 rd = (ctx->opcode >> 11) & 0x1f;
24864 sa = (ctx->opcode >> 6) & 0x1f;
24865 imm = (int16_t)ctx->opcode;
24866 switch (op) {
24867 case OPC_SPECIAL:
24868 decode_opc_special(env, ctx);
24869 break;
24870 case OPC_SPECIAL2:
4267d3e6 24871 decode_opc_special2_legacy(env, ctx);
099e5b4d
LA
24872 break;
24873 case OPC_SPECIAL3:
24874 decode_opc_special3(env, ctx);
24875 break;
7a387fff
TS
24876 case OPC_REGIMM:
24877 op1 = MASK_REGIMM(ctx->opcode);
24878 switch (op1) {
fecd2646
LA
24879 case OPC_BLTZL: /* REGIMM branches */
24880 case OPC_BGEZL:
24881 case OPC_BLTZALL:
24882 case OPC_BGEZALL:
d9224450 24883 check_insn(ctx, ISA_MIPS2);
fecd2646 24884 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 24885 /* Fallthrough */
fecd2646
LA
24886 case OPC_BLTZ:
24887 case OPC_BGEZ:
b231c103 24888 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 24889 break;
fecd2646
LA
24890 case OPC_BLTZAL:
24891 case OPC_BGEZAL:
0aefa333
YK
24892 if (ctx->insn_flags & ISA_MIPS32R6) {
24893 if (rs == 0) {
24894 /* OPC_NAL, OPC_BAL */
b231c103 24895 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
0aefa333 24896 } else {
9c708c7f 24897 generate_exception_end(ctx, EXCP_RI);
0aefa333
YK
24898 }
24899 } else {
b231c103 24900 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 24901 }
c9602061 24902 break;
c2e19f3c
AM
24903 case OPC_TGEI: /* REGIMM traps */
24904 case OPC_TGEIU:
24905 case OPC_TLTI:
24906 case OPC_TLTIU:
24907 case OPC_TEQI:
24908
7a387fff 24909 case OPC_TNEI:
d9224450 24910 check_insn(ctx, ISA_MIPS2);
fecd2646 24911 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7a387fff
TS
24912 gen_trap(ctx, op1, rs, -1, imm);
24913 break;
bb238210
YK
24914 case OPC_SIGRIE:
24915 check_insn(ctx, ISA_MIPS32R6);
24916 generate_exception_end(ctx, EXCP_RI);
24917 break;
7a387fff 24918 case OPC_SYNCI:
d75c135e 24919 check_insn(ctx, ISA_MIPS32R2);
a83bddd6
DZ
24920 /* Break the TB to be able to sync copied instructions
24921 immediately */
eeb3bba8 24922 ctx->base.is_jmp = DISAS_STOP;
6af0bf9c 24923 break;
e45a93e2
JL
24924 case OPC_BPOSGE32: /* MIPS DSP branch */
24925#if defined(TARGET_MIPS64)
24926 case OPC_BPOSGE64:
24927#endif
24928 check_dsp(ctx);
b231c103 24929 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
e45a93e2 24930 break;
d4ea6acd
LA
24931#if defined(TARGET_MIPS64)
24932 case OPC_DAHI:
24933 check_insn(ctx, ISA_MIPS32R6);
24934 check_mips_64(ctx);
24935 if (rs != 0) {
24936 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
24937 }
d4ea6acd
LA
24938 break;
24939 case OPC_DATI:
24940 check_insn(ctx, ISA_MIPS32R6);
24941 check_mips_64(ctx);
24942 if (rs != 0) {
24943 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
24944 }
d4ea6acd
LA
24945 break;
24946#endif
6af0bf9c 24947 default: /* Invalid */
923617a3 24948 MIPS_INVAL("regimm");
9c708c7f 24949 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
24950 break;
24951 }
24952 break;
7a387fff 24953 case OPC_CP0:
387a8fe5 24954 check_cp0_enabled(ctx);
7a387fff 24955 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 24956 switch (op1) {
7a387fff
TS
24957 case OPC_MFC0:
24958 case OPC_MTC0:
ead9360e
TS
24959 case OPC_MFTR:
24960 case OPC_MTTR:
5204ea79
LA
24961 case OPC_MFHC0:
24962 case OPC_MTHC0:
d26bc211 24963#if defined(TARGET_MIPS64)
7a387fff
TS
24964 case OPC_DMFC0:
24965 case OPC_DMTC0:
24966#endif
f1aa6320 24967#ifndef CONFIG_USER_ONLY
932e71cd 24968 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 24969#endif /* !CONFIG_USER_ONLY */
7a387fff 24970 break;
c38a1d52
AR
24971 case OPC_C0:
24972 case OPC_C0_1:
24973 case OPC_C0_2:
24974 case OPC_C0_3:
24975 case OPC_C0_4:
24976 case OPC_C0_5:
24977 case OPC_C0_6:
24978 case OPC_C0_7:
24979 case OPC_C0_8:
24980 case OPC_C0_9:
24981 case OPC_C0_A:
24982 case OPC_C0_B:
24983 case OPC_C0_C:
24984 case OPC_C0_D:
24985 case OPC_C0_E:
24986 case OPC_C0_F:
f1aa6320 24987#ifndef CONFIG_USER_ONLY
932e71cd 24988 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 24989#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
24990 break;
24991 case OPC_MFMC0:
8706c382 24992#ifndef CONFIG_USER_ONLY
932e71cd 24993 {
099e5b4d 24994 uint32_t op2;
35fbce2c 24995 TCGv t0 = tcg_temp_new();
6c5c1e20 24996
0eaef5aa 24997 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
24998 switch (op2) {
24999 case OPC_DMT:
9affc1c5 25000 check_cp0_mt(ctx);
9ed5726c 25001 gen_helper_dmt(t0);
35fbce2c 25002 gen_store_gpr(t0, rt);
6c5c1e20
TS
25003 break;
25004 case OPC_EMT:
9affc1c5 25005 check_cp0_mt(ctx);
9ed5726c 25006 gen_helper_emt(t0);
35fbce2c 25007 gen_store_gpr(t0, rt);
da80682b 25008 break;
6c5c1e20 25009 case OPC_DVPE:
9affc1c5 25010 check_cp0_mt(ctx);
895c2d04 25011 gen_helper_dvpe(t0, cpu_env);
35fbce2c 25012 gen_store_gpr(t0, rt);
6c5c1e20
TS
25013 break;
25014 case OPC_EVPE:
9affc1c5 25015 check_cp0_mt(ctx);
895c2d04 25016 gen_helper_evpe(t0, cpu_env);
35fbce2c 25017 gen_store_gpr(t0, rt);
6c5c1e20 25018 break;
01bc435b
YK
25019 case OPC_DVP:
25020 check_insn(ctx, ISA_MIPS32R6);
25021 if (ctx->vp) {
25022 gen_helper_dvp(t0, cpu_env);
25023 gen_store_gpr(t0, rt);
25024 }
25025 break;
25026 case OPC_EVP:
25027 check_insn(ctx, ISA_MIPS32R6);
25028 if (ctx->vp) {
25029 gen_helper_evp(t0, cpu_env);
25030 gen_store_gpr(t0, rt);
25031 }
25032 break;
6c5c1e20 25033 case OPC_DI:
d75c135e 25034 check_insn(ctx, ISA_MIPS32R2);
867abc7e 25035 save_cpu_state(ctx, 1);
895c2d04 25036 gen_helper_di(t0, cpu_env);
35fbce2c 25037 gen_store_gpr(t0, rt);
d2bfa6e6
MR
25038 /* Stop translation as we may have switched
25039 the execution mode. */
eeb3bba8 25040 ctx->base.is_jmp = DISAS_STOP;
6c5c1e20
TS
25041 break;
25042 case OPC_EI:
d75c135e 25043 check_insn(ctx, ISA_MIPS32R2);
867abc7e 25044 save_cpu_state(ctx, 1);
895c2d04 25045 gen_helper_ei(t0, cpu_env);
35fbce2c 25046 gen_store_gpr(t0, rt);
b28425ba
EC
25047 /* DISAS_STOP isn't sufficient, we need to ensure we break
25048 out of translated code to check for pending interrupts */
eeb3bba8
EC
25049 gen_save_pc(ctx->base.pc_next + 4);
25050 ctx->base.is_jmp = DISAS_EXIT;
6c5c1e20
TS
25051 break;
25052 default: /* Invalid */
25053 MIPS_INVAL("mfmc0");
9c708c7f 25054 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
25055 break;
25056 }
6c5c1e20 25057 tcg_temp_free(t0);
7a387fff 25058 }
0eaef5aa 25059#endif /* !CONFIG_USER_ONLY */
6af0bf9c 25060 break;
7a387fff 25061 case OPC_RDPGPR:
d75c135e 25062 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 25063 gen_load_srsgpr(rt, rd);
ead9360e 25064 break;
7a387fff 25065 case OPC_WRPGPR:
d75c135e 25066 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 25067 gen_store_srsgpr(rt, rd);
38121543 25068 break;
6af0bf9c 25069 default:
923617a3 25070 MIPS_INVAL("cp0");
9c708c7f 25071 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
25072 break;
25073 }
25074 break;
31837be3
YK
25075 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
25076 if (ctx->insn_flags & ISA_MIPS32R6) {
25077 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
25078 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25079 } else {
25080 /* OPC_ADDI */
25081 /* Arithmetic with immediate opcode */
25082 gen_arith_imm(ctx, op, rt, rs, imm);
25083 }
25084 break;
324d9e32 25085 case OPC_ADDIU:
d75c135e 25086 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 25087 break;
324d9e32
AJ
25088 case OPC_SLTI: /* Set on less than with immediate opcode */
25089 case OPC_SLTIU:
d75c135e 25090 gen_slt_imm(ctx, op, rt, rs, imm);
324d9e32
AJ
25091 break;
25092 case OPC_ANDI: /* Arithmetic with immediate opcode */
d4ea6acd 25093 case OPC_LUI: /* OPC_AUI */
324d9e32
AJ
25094 case OPC_ORI:
25095 case OPC_XORI:
d75c135e 25096 gen_logic_imm(ctx, op, rt, rs, imm);
324d9e32 25097 break;
c2e19f3c
AM
25098 case OPC_J: /* Jump */
25099 case OPC_JAL:
7a387fff 25100 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 25101 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
c9602061 25102 break;
31837be3
YK
25103 /* Branch */
25104 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
25105 if (ctx->insn_flags & ISA_MIPS32R6) {
25106 if (rt == 0) {
9c708c7f 25107 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
25108 break;
25109 }
25110 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
25111 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25112 } else {
25113 /* OPC_BLEZL */
b231c103 25114 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
25115 }
25116 break;
25117 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
25118 if (ctx->insn_flags & ISA_MIPS32R6) {
25119 if (rt == 0) {
9c708c7f 25120 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
25121 break;
25122 }
25123 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
25124 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25125 } else {
25126 /* OPC_BGTZL */
b231c103 25127 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
25128 }
25129 break;
25130 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
25131 if (rt == 0) {
25132 /* OPC_BLEZ */
b231c103 25133 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
25134 } else {
25135 check_insn(ctx, ISA_MIPS32R6);
25136 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
25137 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25138 }
25139 break;
25140 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
25141 if (rt == 0) {
25142 /* OPC_BGTZ */
b231c103 25143 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
25144 } else {
25145 check_insn(ctx, ISA_MIPS32R6);
25146 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
25147 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25148 }
25149 break;
25150 case OPC_BEQL:
25151 case OPC_BNEL:
d9224450 25152 check_insn(ctx, ISA_MIPS2);
fecd2646 25153 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 25154 /* Fallthrough */
31837be3
YK
25155 case OPC_BEQ:
25156 case OPC_BNE:
b231c103 25157 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
c9602061 25158 break;
d9224450
MR
25159 case OPC_LL: /* Load and stores */
25160 check_insn(ctx, ISA_MIPS2);
25161 /* Fallthrough */
25162 case OPC_LWL:
fecd2646
LA
25163 case OPC_LWR:
25164 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 25165 /* Fallthrough */
c2e19f3c
AM
25166 case OPC_LB:
25167 case OPC_LH:
25168 case OPC_LW:
25169 case OPC_LWPC:
25170 case OPC_LBU:
25171 case OPC_LHU:
d75c135e 25172 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 25173 break;
fecd2646 25174 case OPC_SWL:
7a387fff 25175 case OPC_SWR:
fecd2646 25176 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 25177 /* fall through */
c2e19f3c
AM
25178 case OPC_SB:
25179 case OPC_SH:
fecd2646 25180 case OPC_SW:
5c13fdfd 25181 gen_st(ctx, op, rt, rs, imm);
7a387fff 25182 break;
d66c7132 25183 case OPC_SC:
d9224450 25184 check_insn(ctx, ISA_MIPS2);
4368b29a 25185 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d66c7132
AJ
25186 gen_st_cond(ctx, op, rt, rs, imm);
25187 break;
7a387fff 25188 case OPC_CACHE:
bf7910c6 25189 check_insn_opc_removed(ctx, ISA_MIPS32R6);
2e15497c 25190 check_cp0_enabled(ctx);
d75c135e 25191 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
0d74a222
LA
25192 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25193 gen_cache_operation(ctx, rt, rs, imm);
25194 }
ead9360e 25195 /* Treat as NOP. */
34ae7b51 25196 break;
7a387fff 25197 case OPC_PREF:
bf7910c6 25198 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d75c135e 25199 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
ead9360e 25200 /* Treat as NOP. */
6af0bf9c 25201 break;
4ad40f36 25202
923617a3 25203 /* Floating point (COP1). */
7a387fff
TS
25204 case OPC_LWC1:
25205 case OPC_LDC1:
25206 case OPC_SWC1:
25207 case OPC_SDC1:
5ab5c041 25208 gen_cop1_ldst(ctx, op, rt, rs, imm);
6ea83fed
FB
25209 break;
25210
7a387fff 25211 case OPC_CP1:
5692c6e1
YK
25212 op1 = MASK_CP1(ctx->opcode);
25213
25214 switch (op1) {
25215 case OPC_MFHC1:
25216 case OPC_MTHC1:
5e755519 25217 check_cp1_enabled(ctx);
5692c6e1 25218 check_insn(ctx, ISA_MIPS32R2);
146dd620 25219 /* fall through */
5692c6e1
YK
25220 case OPC_MFC1:
25221 case OPC_CFC1:
25222 case OPC_MTC1:
25223 case OPC_CTC1:
25224 check_cp1_enabled(ctx);
25225 gen_cp1(ctx, op1, rt, rd);
25226 break;
d26bc211 25227#if defined(TARGET_MIPS64)
5692c6e1
YK
25228 case OPC_DMFC1:
25229 case OPC_DMTC1:
25230 check_cp1_enabled(ctx);
25231 check_insn(ctx, ISA_MIPS3);
d9224450 25232 check_mips_64(ctx);
5692c6e1
YK
25233 gen_cp1(ctx, op1, rt, rd);
25234 break;
e189e748 25235#endif
5692c6e1
YK
25236 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
25237 check_cp1_enabled(ctx);
25238 if (ctx->insn_flags & ISA_MIPS32R6) {
25239 /* OPC_BC1EQZ */
31837be3 25240 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 25241 rt, imm << 2, 4);
5692c6e1
YK
25242 } else {
25243 /* OPC_BC1ANY2 */
b8aa4598 25244 check_cop1x(ctx);
d75c135e 25245 check_insn(ctx, ASE_MIPS3D);
d75c135e 25246 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5a5012ec 25247 (rt >> 2) & 0x7, imm << 2);
5692c6e1
YK
25248 }
25249 break;
25250 case OPC_BC1NEZ:
25251 check_cp1_enabled(ctx);
25252 check_insn(ctx, ISA_MIPS32R6);
25253 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 25254 rt, imm << 2, 4);
5692c6e1
YK
25255 break;
25256 case OPC_BC1ANY4:
25257 check_cp1_enabled(ctx);
25258 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25259 check_cop1x(ctx);
25260 check_insn(ctx, ASE_MIPS3D);
25261 /* fall through */
25262 case OPC_BC1:
25263 check_cp1_enabled(ctx);
25264 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25265 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25266 (rt >> 2) & 0x7, imm << 2);
25267 break;
25268 case OPC_PS_FMT:
e29c9628 25269 check_ps(ctx);
b6f3b233 25270 /* fall through */
5692c6e1
YK
25271 case OPC_S_FMT:
25272 case OPC_D_FMT:
25273 check_cp1_enabled(ctx);
25274 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25275 (imm >> 8) & 0x7);
25276 break;
25277 case OPC_W_FMT:
25278 case OPC_L_FMT:
25279 {
25280 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
25281 check_cp1_enabled(ctx);
25282 if (ctx->insn_flags & ISA_MIPS32R6) {
25283 switch (r6_op) {
25284 case R6_OPC_CMP_AF_S:
25285 case R6_OPC_CMP_UN_S:
25286 case R6_OPC_CMP_EQ_S:
25287 case R6_OPC_CMP_UEQ_S:
25288 case R6_OPC_CMP_LT_S:
25289 case R6_OPC_CMP_ULT_S:
25290 case R6_OPC_CMP_LE_S:
25291 case R6_OPC_CMP_ULE_S:
25292 case R6_OPC_CMP_SAF_S:
25293 case R6_OPC_CMP_SUN_S:
25294 case R6_OPC_CMP_SEQ_S:
25295 case R6_OPC_CMP_SEUQ_S:
25296 case R6_OPC_CMP_SLT_S:
25297 case R6_OPC_CMP_SULT_S:
25298 case R6_OPC_CMP_SLE_S:
25299 case R6_OPC_CMP_SULE_S:
25300 case R6_OPC_CMP_OR_S:
25301 case R6_OPC_CMP_UNE_S:
25302 case R6_OPC_CMP_NE_S:
25303 case R6_OPC_CMP_SOR_S:
25304 case R6_OPC_CMP_SUNE_S:
25305 case R6_OPC_CMP_SNE_S:
25306 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25307 break;
25308 case R6_OPC_CMP_AF_D:
25309 case R6_OPC_CMP_UN_D:
25310 case R6_OPC_CMP_EQ_D:
25311 case R6_OPC_CMP_UEQ_D:
25312 case R6_OPC_CMP_LT_D:
25313 case R6_OPC_CMP_ULT_D:
25314 case R6_OPC_CMP_LE_D:
25315 case R6_OPC_CMP_ULE_D:
25316 case R6_OPC_CMP_SAF_D:
25317 case R6_OPC_CMP_SUN_D:
25318 case R6_OPC_CMP_SEQ_D:
25319 case R6_OPC_CMP_SEUQ_D:
25320 case R6_OPC_CMP_SLT_D:
25321 case R6_OPC_CMP_SULT_D:
25322 case R6_OPC_CMP_SLE_D:
25323 case R6_OPC_CMP_SULE_D:
25324 case R6_OPC_CMP_OR_D:
25325 case R6_OPC_CMP_UNE_D:
25326 case R6_OPC_CMP_NE_D:
25327 case R6_OPC_CMP_SOR_D:
25328 case R6_OPC_CMP_SUNE_D:
25329 case R6_OPC_CMP_SNE_D:
25330 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25331 break;
25332 default:
d2bfa6e6
MR
25333 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
25334 rt, rd, sa, (imm >> 8) & 0x7);
25335
5692c6e1 25336 break;
3f493883 25337 }
5692c6e1
YK
25338 } else {
25339 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25340 (imm >> 8) & 0x7);
36d23958 25341 }
5692c6e1
YK
25342 break;
25343 }
25344 case OPC_BZ_V:
25345 case OPC_BNZ_V:
25346 case OPC_BZ_B:
25347 case OPC_BZ_H:
25348 case OPC_BZ_W:
25349 case OPC_BZ_D:
25350 case OPC_BNZ_B:
25351 case OPC_BNZ_H:
25352 case OPC_BNZ_W:
25353 case OPC_BNZ_D:
25354 check_insn(ctx, ASE_MSA);
25355 gen_msa_branch(env, ctx, op1);
25356 break;
25357 default:
25358 MIPS_INVAL("cp1");
9c708c7f 25359 generate_exception_end(ctx, EXCP_RI);
5692c6e1 25360 break;
6ea83fed 25361 }
4ad40f36
FB
25362 break;
25363
31837be3
YK
25364 /* Compact branches [R6] and COP2 [non-R6] */
25365 case OPC_BC: /* OPC_LWC2 */
25366 case OPC_BALC: /* OPC_SWC2 */
25367 if (ctx->insn_flags & ISA_MIPS32R6) {
25368 /* OPC_BC, OPC_BALC */
25369 gen_compute_compact_branch(ctx, op, 0, 0,
25370 sextract32(ctx->opcode << 2, 0, 28));
25371 } else {
25372 /* OPC_LWC2, OPC_SWC2 */
25373 /* COP2: Not implemented. */
25374 generate_exception_err(ctx, EXCP_CpU, 2);
25375 }
25376 break;
25377 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
25378 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
25379 if (ctx->insn_flags & ISA_MIPS32R6) {
25380 if (rs != 0) {
25381 /* OPC_BEQZC, OPC_BNEZC */
25382 gen_compute_compact_branch(ctx, op, rs, 0,
25383 sextract32(ctx->opcode << 2, 0, 23));
25384 } else {
25385 /* OPC_JIC, OPC_JIALC */
25386 gen_compute_compact_branch(ctx, op, 0, rt, imm);
25387 }
25388 } else {
25389 /* OPC_LWC2, OPC_SWC2 */
25390 /* COP2: Not implemented. */
25391 generate_exception_err(ctx, EXCP_CpU, 2);
25392 }
4ad40f36 25393 break;
bd277fa1 25394 case OPC_CP2:
d75c135e 25395 check_insn(ctx, INSN_LOONGSON2F);
bd277fa1
RH
25396 /* Note that these instructions use different fields. */
25397 gen_loongson_multimedia(ctx, sa, rd, rt);
25398 break;
4ad40f36 25399
7a387fff 25400 case OPC_CP3:
fecd2646 25401 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5ab5c041 25402 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 25403 check_cp1_enabled(ctx);
36d23958
TS
25404 op1 = MASK_CP3(ctx->opcode);
25405 switch (op1) {
d9224450
MR
25406 case OPC_LUXC1:
25407 case OPC_SUXC1:
25408 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
25409 /* Fallthrough */
5a5012ec
TS
25410 case OPC_LWXC1:
25411 case OPC_LDXC1:
5a5012ec
TS
25412 case OPC_SWXC1:
25413 case OPC_SDXC1:
d9224450 25414 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
93b12ccc 25415 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 25416 break;
e0c84da7 25417 case OPC_PREFX:
d9224450 25418 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
ead9360e 25419 /* Treat as NOP. */
e0c84da7 25420 break;
5a5012ec 25421 case OPC_ALNV_PS:
d9224450
MR
25422 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
25423 /* Fallthrough */
5a5012ec
TS
25424 case OPC_MADD_S:
25425 case OPC_MADD_D:
25426 case OPC_MADD_PS:
25427 case OPC_MSUB_S:
25428 case OPC_MSUB_D:
25429 case OPC_MSUB_PS:
25430 case OPC_NMADD_S:
25431 case OPC_NMADD_D:
25432 case OPC_NMADD_PS:
25433 case OPC_NMSUB_S:
25434 case OPC_NMSUB_D:
25435 case OPC_NMSUB_PS:
d9224450 25436 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
5a5012ec
TS
25437 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
25438 break;
36d23958 25439 default:
923617a3 25440 MIPS_INVAL("cp3");
9c708c7f 25441 generate_exception_end(ctx, EXCP_RI);
36d23958
TS
25442 break;
25443 }
25444 } else {
e397ee33 25445 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 25446 }
4ad40f36
FB
25447 break;
25448
d26bc211 25449#if defined(TARGET_MIPS64)
7a387fff 25450 /* MIPS64 opcodes */
c2e19f3c
AM
25451 case OPC_LDL:
25452 case OPC_LDR:
bf7910c6 25453 case OPC_LLD:
fecd2646 25454 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 25455 /* fall through */
fecd2646 25456 case OPC_LWU:
7a387fff 25457 case OPC_LD:
d75c135e 25458 check_insn(ctx, ISA_MIPS3);
5c13fdfd 25459 check_mips_64(ctx);
d75c135e 25460 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 25461 break;
c2e19f3c
AM
25462 case OPC_SDL:
25463 case OPC_SDR:
fecd2646 25464 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 25465 /* fall through */
7a387fff 25466 case OPC_SD:
d75c135e 25467 check_insn(ctx, ISA_MIPS3);
e189e748 25468 check_mips_64(ctx);
5c13fdfd 25469 gen_st(ctx, op, rt, rs, imm);
7a387fff 25470 break;
d66c7132 25471 case OPC_SCD:
bf7910c6 25472 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d75c135e 25473 check_insn(ctx, ISA_MIPS3);
d66c7132
AJ
25474 check_mips_64(ctx);
25475 gen_st_cond(ctx, op, rt, rs, imm);
25476 break;
31837be3
YK
25477 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
25478 if (ctx->insn_flags & ISA_MIPS32R6) {
25479 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
25480 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25481 } else {
25482 /* OPC_DADDI */
25483 check_insn(ctx, ISA_MIPS3);
25484 check_mips_64(ctx);
25485 gen_arith_imm(ctx, op, rt, rs, imm);
25486 }
25487 break;
324d9e32 25488 case OPC_DADDIU:
d75c135e 25489 check_insn(ctx, ISA_MIPS3);
e189e748 25490 check_mips_64(ctx);
d75c135e 25491 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 25492 break;
31837be3
YK
25493#else
25494 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
25495 if (ctx->insn_flags & ISA_MIPS32R6) {
25496 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25497 } else {
25498 MIPS_INVAL("major opcode");
9c708c7f 25499 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
25500 }
25501 break;
6af0bf9c 25502#endif
d4ea6acd
LA
25503 case OPC_DAUI: /* OPC_JALX */
25504 if (ctx->insn_flags & ISA_MIPS32R6) {
25505#if defined(TARGET_MIPS64)
25506 /* OPC_DAUI */
25507 check_mips_64(ctx);
db77d852
LA
25508 if (rs == 0) {
25509 generate_exception(ctx, EXCP_RI);
25510 } else if (rt != 0) {
d4ea6acd
LA
25511 TCGv t0 = tcg_temp_new();
25512 gen_load_gpr(t0, rs);
25513 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
25514 tcg_temp_free(t0);
25515 }
d4ea6acd 25516#else
9c708c7f 25517 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
25518 MIPS_INVAL("major opcode");
25519#endif
25520 } else {
25521 /* OPC_JALX */
25522 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
25523 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 25524 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
d4ea6acd 25525 }
364d4831 25526 break;
4c789546 25527 case OPC_MSA: /* OPC_MDMX */
7a387fff 25528 /* MDMX: Not implemented. */
4c789546 25529 gen_msa(env, ctx);
d4ea6acd
LA
25530 break;
25531 case OPC_PCREL:
25532 check_insn(ctx, ISA_MIPS32R6);
eeb3bba8 25533 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
d4ea6acd 25534 break;
6af0bf9c 25535 default: /* Invalid */
923617a3 25536 MIPS_INVAL("major opcode");
9c708c7f 25537 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
25538 break;
25539 }
6af0bf9c
FB
25540}
25541
18f440ed 25542static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
6af0bf9c 25543{
18f440ed 25544 DisasContext *ctx = container_of(dcbase, DisasContext, base);
9c489ea6 25545 CPUMIPSState *env = cs->env_ptr;
12be9258 25546
18f440ed 25547 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
12be9258
EC
25548 ctx->saved_pc = -1;
25549 ctx->insn_flags = env->insn_flags;
25550 ctx->CP0_Config1 = env->CP0_Config1;
ab77fc61
DN
25551 ctx->CP0_Config3 = env->CP0_Config3;
25552 ctx->CP0_Config5 = env->CP0_Config5;
12be9258
EC
25553 ctx->btarget = 0;
25554 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
25555 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
25556 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
25557 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
25558 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
25559 ctx->PAMask = env->PAMask;
25560 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
25561 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
25562 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
25563 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
25564 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
4ad40f36 25565 /* Restore delay slot state from the tb context. */
12be9258
EC
25566 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
25567 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
25568 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
e29c9628 25569 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
12be9258
EC
25570 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
25571 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
25572 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
25573 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
25574 restore_cpu_state(env, ctx);
932e71cd 25575#ifdef CONFIG_USER_ONLY
12be9258 25576 ctx->mem_idx = MIPS_HFLAG_UM;
932e71cd 25577#else
12be9258 25578 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
932e71cd 25579#endif
12be9258
EC
25580 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
25581 MO_UNALN : MO_ALIGN;
190ce7fb 25582
18f440ed
EC
25583 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
25584 ctx->hflags);
25585}
12be9258 25586
18f440ed
EC
25587static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
25588{
25589}
b933066a 25590
18f440ed
EC
25591static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
25592{
25593 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 25594
18f440ed
EC
25595 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
25596 ctx->btarget);
25597}
31837be3 25598
18f440ed
EC
25599static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
25600 const CPUBreakpoint *bp)
25601{
25602 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 25603
18f440ed
EC
25604 save_cpu_state(ctx, 1);
25605 ctx->base.is_jmp = DISAS_NORETURN;
25606 gen_helper_raise_exception_debug(cpu_env);
25607 /* The address covered by the breakpoint must be included in
25608 [tb->pc, tb->pc + tb->size) in order to for it to be
25609 properly cleared -- thus we increment the PC here so that
25610 the logic setting tb->size below does the right thing. */
25611 ctx->base.pc_next += 4;
25612 return true;
25613}
4ad40f36 25614
18f440ed
EC
25615static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
25616{
25617 CPUMIPSState *env = cs->env_ptr;
25618 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25619 int insn_bytes;
25620 int is_slot;
4ad40f36 25621
18f440ed 25622 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
c533c0f4
AM
25623 if (ctx->insn_flags & ISA_NANOMIPS32) {
25624 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
25625 insn_bytes = decode_nanomips_opc(env, ctx);
25626 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
18f440ed
EC
25627 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
25628 insn_bytes = 4;
25629 decode_opc(env, ctx);
25630 } else if (ctx->insn_flags & ASE_MICROMIPS) {
25631 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
25632 insn_bytes = decode_micromips_opc(env, ctx);
25633 } else if (ctx->insn_flags & ASE_MIPS16) {
25634 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
25635 insn_bytes = decode_mips16_opc(env, ctx);
25636 } else {
25637 generate_exception_end(ctx, EXCP_RI);
25638 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
25639 return;
25640 }
faf7aaa9 25641
18f440ed
EC
25642 if (ctx->hflags & MIPS_HFLAG_BMASK) {
25643 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
25644 MIPS_HFLAG_FBNSLOT))) {
25645 /* force to generate branch as there is neither delay nor
25646 forbidden slot */
25647 is_slot = 1;
25648 }
25649 if ((ctx->hflags & MIPS_HFLAG_M16) &&
25650 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
25651 /* Force to generate branch as microMIPS R6 doesn't restrict
25652 branches in the forbidden slot. */
25653 is_slot = 1;
eeb3bba8 25654 }
18f440ed
EC
25655 }
25656 if (is_slot) {
25657 gen_branch(ctx, insn_bytes);
25658 }
25659 ctx->base.pc_next += insn_bytes;
1b530a6d 25660
18f440ed
EC
25661 if (ctx->base.is_jmp != DISAS_NEXT) {
25662 return;
6af0bf9c 25663 }
18f440ed
EC
25664 /* Execute a branch and its delay slot as a single instruction.
25665 This is what GDB expects and is consistent with what the
25666 hardware does (e.g. if a delay slot instruction faults, the
25667 reported PC is the PC of the branch). */
25668 if (ctx->base.singlestep_enabled &&
25669 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
25670 ctx->base.is_jmp = DISAS_TOO_MANY;
25671 }
25672 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
25673 ctx->base.is_jmp = DISAS_TOO_MANY;
ed2803da 25674 }
18f440ed
EC
25675}
25676
25677static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
25678{
25679 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25680
12be9258
EC
25681 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
25682 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
9c708c7f 25683 gen_helper_raise_exception_debug(cpu_env);
16c00cb2 25684 } else {
12be9258 25685 switch (ctx->base.is_jmp) {
b28425ba 25686 case DISAS_STOP:
12be9258 25687 gen_save_pc(ctx->base.pc_next);
cd314a7d 25688 tcg_gen_lookup_and_goto_ptr();
df1561e2 25689 break;
b28425ba 25690 case DISAS_NEXT:
18f440ed 25691 case DISAS_TOO_MANY:
12be9258
EC
25692 save_cpu_state(ctx, 0);
25693 gen_goto_tb(ctx, 0, ctx->base.pc_next);
16c00cb2 25694 break;
b28425ba 25695 case DISAS_EXIT:
07ea28b4 25696 tcg_gen_exit_tb(NULL, 0);
16c00cb2 25697 break;
b28425ba 25698 case DISAS_NORETURN:
5a5012ec 25699 break;
18f440ed
EC
25700 default:
25701 g_assert_not_reached();
6958549d 25702 }
6af0bf9c 25703 }
18f440ed
EC
25704}
25705
25706static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
25707{
25708 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
25709 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
25710}
25711
25712static const TranslatorOps mips_tr_ops = {
25713 .init_disas_context = mips_tr_init_disas_context,
25714 .tb_start = mips_tr_tb_start,
25715 .insn_start = mips_tr_insn_start,
25716 .breakpoint_check = mips_tr_breakpoint_check,
25717 .translate_insn = mips_tr_translate_insn,
25718 .tb_stop = mips_tr_tb_stop,
25719 .disas_log = mips_tr_disas_log,
25720};
25721
25722void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
25723{
25724 DisasContext ctx;
25725
25726 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
6af0bf9c
FB
25727}
25728
7db13fae 25729static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
8706c382 25730 int flags)
6ea83fed
FB
25731{
25732 int i;
5e755519 25733 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 25734
2a5612e6
SW
25735#define printfpr(fp) \
25736 do { \
25737 if (is_fpu64) \
25738 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
25739 " fd:%13g fs:%13g psu: %13g\n", \
25740 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
25741 (double)(fp)->fd, \
25742 (double)(fp)->fs[FP_ENDIAN_IDX], \
25743 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
25744 else { \
25745 fpr_t tmp; \
25746 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
25747 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
25748 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
25749 " fd:%13g fs:%13g psu:%13g\n", \
25750 tmp.w[FP_ENDIAN_IDX], tmp.d, \
25751 (double)tmp.fd, \
25752 (double)tmp.fs[FP_ENDIAN_IDX], \
25753 (double)tmp.fs[!FP_ENDIAN_IDX]); \
25754 } \
6ea83fed
FB
25755 } while(0)
25756
5a5012ec 25757
9a78eead
SW
25758 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
25759 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
f01be154 25760 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
25761 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
25762 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 25763 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
25764 }
25765
25766#undef printfpr
25767}
25768
878096ee
AF
25769void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
25770 int flags)
6af0bf9c 25771{
878096ee
AF
25772 MIPSCPU *cpu = MIPS_CPU(cs);
25773 CPUMIPSState *env = &cpu->env;
6af0bf9c 25774 int i;
3b46e624 25775
a7200c9f
SW
25776 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
25777 " LO=0x" TARGET_FMT_lx " ds %04x "
25778 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
3d5be870
TS
25779 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
25780 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
25781 for (i = 0; i < 32; i++) {
25782 if ((i & 3) == 0)
25783 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 25784 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
25785 if ((i & 3) == 3)
25786 cpu_fprintf(f, "\n");
25787 }
568b600d 25788
3594c774 25789 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 25790 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
284b731a
LA
25791 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
25792 PRIx64 "\n",
5499b6ff 25793 env->CP0_Config0, env->CP0_Config1, env->lladdr);
27e1fb13
MR
25794 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
25795 env->CP0_Config2, env->CP0_Config3);
25796 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
25797 env->CP0_Config4, env->CP0_Config5);
1cc5af69 25798 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
7a387fff 25799 fpu_dump_state(env, f, cpu_fprintf, flags);
1cc5af69 25800 }
6af0bf9c
FB
25801}
25802
78ce64f4 25803void mips_tcg_init(void)
39454628 25804{
f01be154 25805 int i;
39454628 25806
f764718d 25807 cpu_gpr[0] = NULL;
bb928dbe 25808 for (i = 1; i < 32; i++)
e1ccc054 25809 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
7db13fae 25810 offsetof(CPUMIPSState, active_tc.gpr[i]),
4b2eb8d2 25811 regnames[i]);
d73ee8a2 25812
863f264d
YK
25813 for (i = 0; i < 32; i++) {
25814 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
25815 msa_wr_d[i * 2] =
e1ccc054 25816 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
cb269f27
YK
25817 /* The scalar floating-point unit (FPU) registers are mapped on
25818 * the MSA vector registers. */
25819 fpu_f64[i] = msa_wr_d[i * 2];
863f264d
YK
25820 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
25821 msa_wr_d[i * 2 + 1] =
e1ccc054 25822 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
863f264d
YK
25823 }
25824
e1ccc054 25825 cpu_PC = tcg_global_mem_new(cpu_env,
7db13fae 25826 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 25827 for (i = 0; i < MIPS_DSP_ACC; i++) {
e1ccc054 25828 cpu_HI[i] = tcg_global_mem_new(cpu_env,
7db13fae 25829 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 25830 regnames_HI[i]);
e1ccc054 25831 cpu_LO[i] = tcg_global_mem_new(cpu_env,
7db13fae 25832 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 25833 regnames_LO[i]);
4b2eb8d2 25834 }
e1ccc054 25835 cpu_dspctrl = tcg_global_mem_new(cpu_env,
7db13fae 25836 offsetof(CPUMIPSState, active_tc.DSPControl),
4b2eb8d2 25837 "DSPControl");
e1ccc054 25838 bcond = tcg_global_mem_new(cpu_env,
7db13fae 25839 offsetof(CPUMIPSState, bcond), "bcond");
e1ccc054 25840 btarget = tcg_global_mem_new(cpu_env,
7db13fae 25841 offsetof(CPUMIPSState, btarget), "btarget");
e1ccc054 25842 hflags = tcg_global_mem_new_i32(cpu_env,
7db13fae 25843 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 25844
e1ccc054 25845 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
7db13fae 25846 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4 25847 "fcr0");
e1ccc054 25848 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
7db13fae 25849 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 25850 "fcr31");
39454628
TS
25851}
25852
5b27a92d 25853#include "translate_init.inc.c"
aaed909a 25854
27e38392
PMD
25855void cpu_mips_realize_env(CPUMIPSState *env)
25856{
25857 env->exception_base = (int32_t)0xBFC00000;
25858
25859#ifndef CONFIG_USER_ONLY
25860 mmu_init(env, env->cpu_model);
25861#endif
25862 fpu_init(env, env->cpu_model);
25863 mvp_init(env, env->cpu_model);
25864}
25865
a7519f2b 25866bool cpu_supports_cps_smp(const char *cpu_type)
bff384a4 25867{
a7519f2b
IM
25868 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
25869 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
bff384a4
LA
25870}
25871
a7519f2b 25872bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
bed9e5ce 25873{
a7519f2b
IM
25874 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
25875 return (mcc->cpu_def->insn_flags & isa) != 0;
bed9e5ce
PB
25876}
25877
89777fd1
LA
25878void cpu_set_exception_base(int vp_index, target_ulong address)
25879{
25880 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
25881 vp->env.exception_base = address;
25882}
25883
1bba0dc9 25884void cpu_state_reset(CPUMIPSState *env)
6ae81775 25885{
55e5c285
AF
25886 MIPSCPU *cpu = mips_env_get_cpu(env);
25887 CPUState *cs = CPU(cpu);
6ae81775 25888
51cc2e78
BS
25889 /* Reset registers to their default values */
25890 env->CP0_PRid = env->cpu_model->CP0_PRid;
25891 env->CP0_Config0 = env->cpu_model->CP0_Config0;
25892#ifdef TARGET_WORDS_BIGENDIAN
25893 env->CP0_Config0 |= (1 << CP0C0_BE);
25894#endif
25895 env->CP0_Config1 = env->cpu_model->CP0_Config1;
25896 env->CP0_Config2 = env->cpu_model->CP0_Config2;
25897 env->CP0_Config3 = env->cpu_model->CP0_Config3;
b4160af1
PJ
25898 env->CP0_Config4 = env->cpu_model->CP0_Config4;
25899 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
b4dd99a3
PJ
25900 env->CP0_Config5 = env->cpu_model->CP0_Config5;
25901 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
51cc2e78
BS
25902 env->CP0_Config6 = env->cpu_model->CP0_Config6;
25903 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
25904 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
25905 << env->cpu_model->CP0_LLAddr_shift;
25906 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
25907 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
25908 env->CCRes = env->cpu_model->CCRes;
25909 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
25910 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
25911 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
25912 env->current_tc = 0;
25913 env->SEGBITS = env->cpu_model->SEGBITS;
25914 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
25915#if defined(TARGET_MIPS64)
25916 if (env->cpu_model->insn_flags & ISA_MIPS3) {
25917 env->SEGMask |= 3ULL << 62;
25918 }
25919#endif
25920 env->PABITS = env->cpu_model->PABITS;
51cc2e78
BS
25921 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
25922 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
25923 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
25924 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
25925 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
25926 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
25927 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
25928 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
25929 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
25930 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
7207c7f9
LA
25931 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
25932 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
74dbf824 25933 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
f1cb0951 25934 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
599bc5e8 25935 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
ba5c79f2 25936 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
863f264d 25937 env->msair = env->cpu_model->MSAIR;
51cc2e78
BS
25938 env->insn_flags = env->cpu_model->insn_flags;
25939
0eaef5aa 25940#if defined(CONFIG_USER_ONLY)
03e6e501 25941 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
68473f15
RH
25942# ifdef TARGET_MIPS64
25943 /* Enable 64-bit register mode. */
25944 env->CP0_Status |= (1 << CP0St_PX);
25945# endif
25946# ifdef TARGET_ABI_MIPSN64
25947 /* Enable 64-bit address mode. */
25948 env->CP0_Status |= (1 << CP0St_UX);
25949# endif
94159135
MI
25950 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
25951 hardware registers. */
25952 env->CP0_HWREna |= 0x0000000F;
91a75935 25953 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
03e6e501 25954 env->CP0_Status |= (1 << CP0St_CU1);
91a75935 25955 }
6f0af304
PJ
25956 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
25957 env->CP0_Status |= (1 << CP0St_MX);
853c3240 25958 }
4d66261f
PJ
25959# if defined(TARGET_MIPS64)
25960 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
25961 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
25962 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
68473f15
RH
25963 env->CP0_Status |= (1 << CP0St_FR);
25964 }
4d66261f 25965# endif
932e71cd
AJ
25966#else
25967 if (env->hflags & MIPS_HFLAG_BMASK) {
25968 /* If the exception was raised from a delay slot,
25969 come back to the jump. */
c3577479
MR
25970 env->CP0_ErrorEPC = (env->active_tc.PC
25971 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
aa328add 25972 } else {
932e71cd
AJ
25973 env->CP0_ErrorEPC = env->active_tc.PC;
25974 }
89777fd1 25975 env->active_tc.PC = env->exception_base;
51cc2e78
BS
25976 env->CP0_Random = env->tlb->nb_tlb - 1;
25977 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd 25978 env->CP0_Wired = 0;
01bc435b 25979 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
0a2672b7 25980 env->CP0_EBase = (cs->cpu_index & 0x3FF);
d3d93c6c 25981 if (mips_um_ksegs_enabled()) {
0a2672b7
JH
25982 env->CP0_EBase |= 0x40000000;
25983 } else {
74dbf824 25984 env->CP0_EBase |= (int32_t)0x80000000;
0a2672b7 25985 }
c870e3f5
YK
25986 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
25987 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
25988 }
a0c80608
PB
25989 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
25990 0x3ff : 0xff;
932e71cd
AJ
25991 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
25992 /* vectored interrupts not implemented, timer on int 7,
25993 no performance counters. */
25994 env->CP0_IntCtl = 0xe0000000;
25995 {
25996 int i;
25997
25998 for (i = 0; i < 7; i++) {
25999 env->CP0_WatchLo[i] = 0;
26000 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 26001 }
932e71cd
AJ
26002 env->CP0_WatchLo[7] = 0;
26003 env->CP0_WatchHi[7] = 0;
fd88b6ab 26004 }
932e71cd
AJ
26005 /* Count register increments in debug mode, EJTAG version 1 */
26006 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9e56e756 26007
4b69c7e2
JH
26008 cpu_mips_store_count(env, 1);
26009
9e56e756
EI
26010 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
26011 int i;
26012
26013 /* Only TC0 on VPE 0 starts as active. */
26014 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
55e5c285 26015 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
9e56e756
EI
26016 env->tcs[i].CP0_TCHalt = 1;
26017 }
26018 env->active_tc.CP0_TCHalt = 1;
259186a7 26019 cs->halted = 1;
9e56e756 26020
55e5c285 26021 if (cs->cpu_index == 0) {
9e56e756
EI
26022 /* VPE0 starts up enabled. */
26023 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
26024 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
26025
26026 /* TC0 starts up unhalted. */
259186a7 26027 cs->halted = 0;
9e56e756
EI
26028 env->active_tc.CP0_TCHalt = 0;
26029 env->tcs[0].CP0_TCHalt = 0;
26030 /* With thread 0 active. */
26031 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
26032 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
26033 }
26034 }
cec56a73
JH
26035
26036 /*
26037 * Configure default legacy segmentation control. We use this regardless of
26038 * whether segmentation control is presented to the guest.
26039 */
26040 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
26041 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
26042 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
26043 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
26044 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
26045 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
26046 (2 << CP0SC_C);
26047 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
26048 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
26049 (3 << CP0SC_C)) << 16;
26050 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
26051 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
26052 (1 << CP0SC_EU) | (2 << CP0SC_C);
26053 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
26054 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
26055 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
26056 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
26057 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
51cc2e78 26058#endif
ddc584bd
LA
26059 if ((env->insn_flags & ISA_MIPS32R6) &&
26060 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
26061 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
26062 env->CP0_Status |= (1 << CP0St_FR);
26063 }
26064
0bbc0396
SM
26065 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
26066 /* microMIPS on reset when Config3.ISA is 3 */
0305d194
YK
26067 env->hflags |= MIPS_HFLAG_M16;
26068 }
26069
863f264d
YK
26070 /* MSA */
26071 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
26072 msa_reset(env);
26073 }
26074
03e6e501 26075 compute_hflags(env);
599bc5e8 26076 restore_fp_status(env);
e117f526 26077 restore_pamask(env);
27103424 26078 cs->exception_index = EXCP_NONE;
3b3c1694
LA
26079
26080 if (semihosting_get_argc()) {
26081 /* UHI interface can be used to obtain argc and argv */
26082 env->active_tc.gpr[4] = -1;
26083 }
6af0bf9c 26084}
d2856f1a 26085
bad729e2
RH
26086void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
26087 target_ulong *data)
d2856f1a 26088{
bad729e2 26089 env->active_tc.PC = data[0];
d2856f1a 26090 env->hflags &= ~MIPS_HFLAG_BMASK;
bad729e2 26091 env->hflags |= data[1];
4636401d
AJ
26092 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
26093 case MIPS_HFLAG_BR:
26094 break;
26095 case MIPS_HFLAG_BC:
26096 case MIPS_HFLAG_BL:
26097 case MIPS_HFLAG_B:
bad729e2 26098 env->btarget = data[2];
4636401d
AJ
26099 break;
26100 }
d2856f1a 26101}
This page took 5.610492 seconds and 4 git commands to generate.