]> git.proxmox.com Git - mirror_qemu.git/blame - target/mips/translate.c
target/mips: Implement emulation of nanoMIPS LLWP/SCWP pair
[mirror_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
39454628 1392/* global register indices */
a7812ae4 1393static TCGv cpu_gpr[32], cpu_PC;
340fff72 1394static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
41db4607
AJ
1395static TCGv cpu_dspctrl, btarget, bcond;
1396static TCGv_i32 hflags;
a7812ae4 1397static TCGv_i32 fpu_fcr0, fpu_fcr31;
d73ee8a2 1398static TCGv_i64 fpu_f64[32];
863f264d 1399static TCGv_i64 msa_wr_d[64];
aa0bf00b 1400
022c62cb 1401#include "exec/gen-icount.h"
2e70f6ef 1402
895c2d04 1403#define gen_helper_0e0i(name, arg) do { \
a7812ae4 1404 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
895c2d04 1405 gen_helper_##name(cpu_env, helper_tmp); \
a7812ae4
PB
1406 tcg_temp_free_i32(helper_tmp); \
1407 } while(0)
be24bb4f 1408
895c2d04 1409#define gen_helper_0e1i(name, arg1, arg2) do { \
a7812ae4 1410 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
895c2d04 1411 gen_helper_##name(cpu_env, arg1, helper_tmp); \
a7812ae4
PB
1412 tcg_temp_free_i32(helper_tmp); \
1413 } while(0)
be24bb4f 1414
895c2d04
BS
1415#define gen_helper_1e0i(name, ret, arg1) do { \
1416 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1417 gen_helper_##name(ret, cpu_env, helper_tmp); \
1418 tcg_temp_free_i32(helper_tmp); \
1419 } while(0)
1420
1421#define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1422 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1423 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1424 tcg_temp_free_i32(helper_tmp); \
1425 } while(0)
1426
1427#define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1428 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1429 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1430 tcg_temp_free_i32(helper_tmp); \
1431 } while(0)
1432
1433#define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
a7812ae4 1434 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
895c2d04 1435 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
a7812ae4
PB
1436 tcg_temp_free_i32(helper_tmp); \
1437 } while(0)
be24bb4f 1438
895c2d04 1439#define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
a7812ae4 1440 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
895c2d04 1441 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
a7812ae4
PB
1442 tcg_temp_free_i32(helper_tmp); \
1443 } while(0)
c239529e 1444
8e9ade68 1445typedef struct DisasContext {
eeb3bba8
EC
1446 DisasContextBase base;
1447 target_ulong saved_pc;
18f440ed 1448 target_ulong page_start;
8e9ade68 1449 uint32_t opcode;
d75c135e 1450 int insn_flags;
5ab5c041 1451 int32_t CP0_Config1;
ab77fc61
DN
1452 int32_t CP0_Config3;
1453 int32_t CP0_Config5;
8e9ade68
TS
1454 /* Routine used to access memory */
1455 int mem_idx;
be3a8c53 1456 TCGMemOp default_tcg_memop_mask;
8e9ade68 1457 uint32_t hflags, saved_hflags;
8e9ade68 1458 target_ulong btarget;
d279279e 1459 bool ulri;
e98c0d17 1460 int kscrexist;
7207c7f9 1461 bool rxi;
9456c2fb 1462 int ie;
aea14095
LA
1463 bool bi;
1464 bool bp;
5204ea79
LA
1465 uint64_t PAMask;
1466 bool mvh;
76964147 1467 bool eva;
cec56a73 1468 bool sc;
5204ea79 1469 int CP0_LLAddr_shift;
e29c9628 1470 bool ps;
01bc435b 1471 bool vp;
c870e3f5 1472 bool cmgcr;
f6d4dd81 1473 bool mrp;
87552089 1474 bool nan2008;
6be77480 1475 bool abs2008;
8e9ade68
TS
1476} DisasContext;
1477
b28425ba
EC
1478#define DISAS_STOP DISAS_TARGET_0
1479#define DISAS_EXIT DISAS_TARGET_1
8e9ade68 1480
d73ee8a2
RH
1481static const char * const regnames[] = {
1482 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1483 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1484 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1485 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1486};
6af0bf9c 1487
d73ee8a2
RH
1488static const char * const regnames_HI[] = {
1489 "HI0", "HI1", "HI2", "HI3",
1490};
4b2eb8d2 1491
d73ee8a2
RH
1492static const char * const regnames_LO[] = {
1493 "LO0", "LO1", "LO2", "LO3",
1494};
4b2eb8d2 1495
d73ee8a2
RH
1496static const char * const fregnames[] = {
1497 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1498 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1499 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1500 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1501};
958fb4a9 1502
863f264d
YK
1503static const char * const msaregnames[] = {
1504 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1505 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1506 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1507 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1508 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1509 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1510 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1511 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1512 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1513 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1514 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1515 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1516 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1517 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1518 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1519 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1520};
1521
9d68ac14 1522#define LOG_DISAS(...) \
fb7729e2
RH
1523 do { \
1524 if (MIPS_DEBUG_DISAS) { \
9d68ac14 1525 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
fb7729e2
RH
1526 } \
1527 } while (0)
1528
9d68ac14 1529#define MIPS_INVAL(op) \
fb7729e2
RH
1530 do { \
1531 if (MIPS_DEBUG_DISAS) { \
9d68ac14
AJ
1532 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1533 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
eeb3bba8
EC
1534 ctx->base.pc_next, ctx->opcode, op, \
1535 ctx->opcode >> 26, ctx->opcode & 0x3F, \
1536 ((ctx->opcode >> 16) & 0x1F)); \
fb7729e2
RH
1537 } \
1538 } while (0)
958fb4a9 1539
8e9ade68
TS
1540/* General purpose registers moves. */
1541static inline void gen_load_gpr (TCGv t, int reg)
aaa9128a 1542{
8e9ade68
TS
1543 if (reg == 0)
1544 tcg_gen_movi_tl(t, 0);
1545 else
4b2eb8d2 1546 tcg_gen_mov_tl(t, cpu_gpr[reg]);
aaa9128a
TS
1547}
1548
8e9ade68 1549static inline void gen_store_gpr (TCGv t, int reg)
aaa9128a 1550{
8e9ade68 1551 if (reg != 0)
4b2eb8d2 1552 tcg_gen_mov_tl(cpu_gpr[reg], t);
aaa9128a
TS
1553}
1554
8e9ade68 1555/* Moves to/from shadow registers. */
be24bb4f 1556static inline void gen_load_srsgpr (int from, int to)
aaa9128a 1557{
d9bea114 1558 TCGv t0 = tcg_temp_new();
be24bb4f
TS
1559
1560 if (from == 0)
d9bea114 1561 tcg_gen_movi_tl(t0, 0);
8e9ade68 1562 else {
d9bea114 1563 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 1564 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 1565
7db13fae 1566 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
1567 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1568 tcg_gen_andi_i32(t2, t2, 0xf);
1569 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1570 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 1571 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 1572
d9bea114 1573 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 1574 tcg_temp_free_ptr(addr);
d9bea114 1575 tcg_temp_free_i32(t2);
8e9ade68 1576 }
d9bea114
AJ
1577 gen_store_gpr(t0, to);
1578 tcg_temp_free(t0);
aaa9128a
TS
1579}
1580
be24bb4f 1581static inline void gen_store_srsgpr (int from, int to)
aaa9128a 1582{
be24bb4f 1583 if (to != 0) {
d9bea114
AJ
1584 TCGv t0 = tcg_temp_new();
1585 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 1586 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 1587
d9bea114 1588 gen_load_gpr(t0, from);
7db13fae 1589 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
d9bea114
AJ
1590 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1591 tcg_gen_andi_i32(t2, t2, 0xf);
1592 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1593 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 1594 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 1595
d9bea114 1596 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 1597 tcg_temp_free_ptr(addr);
d9bea114
AJ
1598 tcg_temp_free_i32(t2);
1599 tcg_temp_free(t0);
8e9ade68 1600 }
aaa9128a
TS
1601}
1602
eab9944c
LA
1603/* Tests */
1604static inline void gen_save_pc(target_ulong pc)
1605{
1606 tcg_gen_movi_tl(cpu_PC, pc);
1607}
1608
1609static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1610{
1611 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
eeb3bba8
EC
1612 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1613 gen_save_pc(ctx->base.pc_next);
1614 ctx->saved_pc = ctx->base.pc_next;
eab9944c
LA
1615 }
1616 if (ctx->hflags != ctx->saved_hflags) {
1617 tcg_gen_movi_i32(hflags, ctx->hflags);
1618 ctx->saved_hflags = ctx->hflags;
1619 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1620 case MIPS_HFLAG_BR:
1621 break;
1622 case MIPS_HFLAG_BC:
1623 case MIPS_HFLAG_BL:
1624 case MIPS_HFLAG_B:
1625 tcg_gen_movi_tl(btarget, ctx->btarget);
1626 break;
1627 }
1628 }
1629}
1630
1631static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1632{
1633 ctx->saved_hflags = ctx->hflags;
1634 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1635 case MIPS_HFLAG_BR:
1636 break;
1637 case MIPS_HFLAG_BC:
1638 case MIPS_HFLAG_BL:
1639 case MIPS_HFLAG_B:
1640 ctx->btarget = env->btarget;
1641 break;
1642 }
1643}
1644
1645static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1646{
1647 TCGv_i32 texcp = tcg_const_i32(excp);
1648 TCGv_i32 terr = tcg_const_i32(err);
1649 save_cpu_state(ctx, 1);
1650 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1651 tcg_temp_free_i32(terr);
1652 tcg_temp_free_i32(texcp);
eeb3bba8 1653 ctx->base.is_jmp = DISAS_NORETURN;
eab9944c
LA
1654}
1655
1656static inline void generate_exception(DisasContext *ctx, int excp)
1657{
eab9944c
LA
1658 gen_helper_0e0i(raise_exception, excp);
1659}
1660
9c708c7f
PD
1661static inline void generate_exception_end(DisasContext *ctx, int excp)
1662{
1663 generate_exception_err(ctx, excp, 0);
1664}
1665
aaa9128a 1666/* Floating point register moves. */
7c979afd 1667static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 1668{
7c979afd
LA
1669 if (ctx->hflags & MIPS_HFLAG_FRE) {
1670 generate_exception(ctx, EXCP_RI);
1671 }
ecc7b3aa 1672 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
6ea83fed
FB
1673}
1674
7c979afd 1675static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
aa0bf00b 1676{
7c979afd
LA
1677 TCGv_i64 t64;
1678 if (ctx->hflags & MIPS_HFLAG_FRE) {
1679 generate_exception(ctx, EXCP_RI);
1680 }
1681 t64 = tcg_temp_new_i64();
d73ee8a2
RH
1682 tcg_gen_extu_i32_i64(t64, t);
1683 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1684 tcg_temp_free_i64(t64);
6d066274
AJ
1685}
1686
7f6613ce 1687static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 1688{
7f6613ce 1689 if (ctx->hflags & MIPS_HFLAG_F64) {
71f303cd 1690 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
7f6613ce 1691 } else {
7c979afd 1692 gen_load_fpr32(ctx, t, reg | 1);
7f6613ce 1693 }
6d066274
AJ
1694}
1695
7f6613ce 1696static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
6d066274 1697{
7f6613ce
PJ
1698 if (ctx->hflags & MIPS_HFLAG_F64) {
1699 TCGv_i64 t64 = tcg_temp_new_i64();
1700 tcg_gen_extu_i32_i64(t64, t);
1701 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1702 tcg_temp_free_i64(t64);
1703 } else {
7c979afd 1704 gen_store_fpr32(ctx, t, reg | 1);
7f6613ce 1705 }
aa0bf00b 1706}
6ea83fed 1707
d73ee8a2 1708static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 1709{
f364515c 1710 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 1711 tcg_gen_mov_i64(t, fpu_f64[reg]);
f364515c 1712 } else {
d73ee8a2 1713 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
aa0bf00b
TS
1714 }
1715}
6ea83fed 1716
d73ee8a2 1717static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 1718{
f364515c 1719 if (ctx->hflags & MIPS_HFLAG_F64) {
d73ee8a2 1720 tcg_gen_mov_i64(fpu_f64[reg], t);
f364515c 1721 } else {
d73ee8a2
RH
1722 TCGv_i64 t0;
1723 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1724 t0 = tcg_temp_new_i64();
6d066274 1725 tcg_gen_shri_i64(t0, t, 32);
d73ee8a2 1726 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
6d066274 1727 tcg_temp_free_i64(t0);
aa0bf00b
TS
1728 }
1729}
6ea83fed 1730
d94536f4 1731static inline int get_fp_bit (int cc)
a16336e4 1732{
d94536f4
AJ
1733 if (cc)
1734 return 24 + cc;
1735 else
1736 return 23;
a16336e4
TS
1737}
1738
48d38ca5 1739/* Addresses computation */
941694d0 1740static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
4ad40f36 1741{
941694d0 1742 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
1743
1744#if defined(TARGET_MIPS64)
01f72885 1745 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
941694d0 1746 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
1747 }
1748#endif
4ad40f36
FB
1749}
1750
bf0718c5
SM
1751static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
1752 target_long ofs)
1753{
1754 tcg_gen_addi_tl(ret, base, ofs);
1755
1756#if defined(TARGET_MIPS64)
1757 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1758 tcg_gen_ext32s_i64(ret, ret);
1759 }
1760#endif
1761}
1762
31837be3
YK
1763/* Addresses computation (translation time) */
1764static target_long addr_add(DisasContext *ctx, target_long base,
1765 target_long offset)
1766{
1767 target_long sum = base + offset;
1768
1769#if defined(TARGET_MIPS64)
1770 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1771 sum = (int32_t)sum;
1772 }
1773#endif
1774 return sum;
1775}
1776
71f303cd 1777/* Sign-extract the low 32-bits to a target_long. */
1f1b4c00
YK
1778static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
1779{
1780#if defined(TARGET_MIPS64)
71f303cd
RH
1781 tcg_gen_ext32s_i64(ret, arg);
1782#else
1783 tcg_gen_extrl_i64_i32(ret, arg);
1784#endif
1785}
1786
1787/* Sign-extract the high 32-bits to a target_long. */
1788static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
1789{
1790#if defined(TARGET_MIPS64)
1791 tcg_gen_sari_i64(ret, arg, 32);
1f1b4c00 1792#else
71f303cd 1793 tcg_gen_extrh_i64_i32(ret, arg);
1f1b4c00
YK
1794#endif
1795}
1796
356265ae 1797static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 1798{
fe253235 1799 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
c2c65dab 1800 generate_exception_err(ctx, EXCP_CpU, 0);
387a8fe5
TS
1801}
1802
356265ae 1803static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 1804{
fe253235 1805 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
5e755519
TS
1806 generate_exception_err(ctx, EXCP_CpU, 1);
1807}
1808
b8aa4598
TS
1809/* Verify that the processor is running with COP1X instructions enabled.
1810 This is associated with the nabla symbol in the MIPS32 and MIPS64
1811 opcode tables. */
1812
356265ae 1813static inline void check_cop1x(DisasContext *ctx)
b8aa4598
TS
1814{
1815 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
9c708c7f 1816 generate_exception_end(ctx, EXCP_RI);
b8aa4598
TS
1817}
1818
1819/* Verify that the processor is running with 64-bit floating-point
1820 operations enabled. */
1821
356265ae 1822static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 1823{
b8aa4598 1824 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
9c708c7f 1825 generate_exception_end(ctx, EXCP_RI);
5e755519
TS
1826}
1827
1828/*
1829 * Verify if floating point register is valid; an operation is not defined
1830 * if bit 0 of any register specification is set and the FR bit in the
1831 * Status register equals zero, since the register numbers specify an
1832 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1833 * in the Status register equals one, both even and odd register numbers
1834 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1835 *
1836 * Multiple 64 bit wide registers can be checked by calling
1837 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1838 */
356265ae 1839static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 1840{
fe253235 1841 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
9c708c7f 1842 generate_exception_end(ctx, EXCP_RI);
5e755519
TS
1843}
1844
853c3240
JL
1845/* Verify that the processor is running with DSP instructions enabled.
1846 This is enabled by CP0 Status register MX(24) bit.
1847 */
1848
1849static inline void check_dsp(DisasContext *ctx)
1850{
1851 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
ad153f15 1852 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 1853 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 1854 } else {
9c708c7f 1855 generate_exception_end(ctx, EXCP_RI);
ad153f15 1856 }
853c3240
JL
1857 }
1858}
1859
1860static inline void check_dspr2(DisasContext *ctx)
1861{
1862 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
ad153f15 1863 if (ctx->insn_flags & ASE_DSP) {
9c708c7f 1864 generate_exception_end(ctx, EXCP_DSPDIS);
ad153f15 1865 } else {
9c708c7f 1866 generate_exception_end(ctx, EXCP_RI);
ad153f15 1867 }
853c3240
JL
1868 }
1869}
1870
3a95e3a7 1871/* This code generates a "reserved instruction" exception if the
e189e748 1872 CPU does not support the instruction set corresponding to flags. */
d75c135e 1873static inline void check_insn(DisasContext *ctx, int flags)
3a95e3a7 1874{
d75c135e 1875 if (unlikely(!(ctx->insn_flags & flags))) {
9c708c7f 1876 generate_exception_end(ctx, EXCP_RI);
d75c135e 1877 }
3a95e3a7
TS
1878}
1879
fecd2646
LA
1880/* This code generates a "reserved instruction" exception if the
1881 CPU has corresponding flag set which indicates that the instruction
1882 has been removed. */
1883static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1884{
1885 if (unlikely(ctx->insn_flags & flags)) {
9c708c7f 1886 generate_exception_end(ctx, EXCP_RI);
fecd2646
LA
1887 }
1888}
1889
e29c9628
YK
1890/* This code generates a "reserved instruction" exception if the
1891 CPU does not support 64-bit paired-single (PS) floating point data type */
1892static inline void check_ps(DisasContext *ctx)
1893{
1894 if (unlikely(!ctx->ps)) {
1895 generate_exception(ctx, EXCP_RI);
1896 }
1897 check_cp1_64bitmode(ctx);
1898}
1899
c7986fd6 1900#ifdef TARGET_MIPS64
e189e748
TS
1901/* This code generates a "reserved instruction" exception if 64-bit
1902 instructions are not enabled. */
356265ae 1903static inline void check_mips_64(DisasContext *ctx)
e189e748 1904{
fe253235 1905 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
9c708c7f 1906 generate_exception_end(ctx, EXCP_RI);
e189e748 1907}
c7986fd6 1908#endif
e189e748 1909
5204ea79
LA
1910#ifndef CONFIG_USER_ONLY
1911static inline void check_mvh(DisasContext *ctx)
1912{
1913 if (unlikely(!ctx->mvh)) {
1914 generate_exception(ctx, EXCP_RI);
1915 }
1916}
1917#endif
1918
0b16dcd1
AR
1919/*
1920 * This code generates a "reserved instruction" exception if the
1921 * Config5 XNP bit is set.
1922 */
1923static inline void check_xnp(DisasContext *ctx)
1924{
1925 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
1926 generate_exception_end(ctx, EXCP_RI);
1927 }
1928}
1929
1930
8153667c
NF
1931/* Define small wrappers for gen_load_fpr* so that we have a uniform
1932 calling interface for 32 and 64-bit FPRs. No sense in changing
1933 all callers for gen_load_fpr32 when we need the CTX parameter for
1934 this one use. */
7c979afd 1935#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
8153667c
NF
1936#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1937#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1938static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1939 int ft, int fs, int cc) \
1940{ \
1941 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1942 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1943 switch (ifmt) { \
1944 case FMT_PS: \
e29c9628 1945 check_ps(ctx); \
8153667c
NF
1946 break; \
1947 case FMT_D: \
1948 if (abs) { \
1949 check_cop1x(ctx); \
1950 } \
1951 check_cp1_registers(ctx, fs | ft); \
1952 break; \
1953 case FMT_S: \
1954 if (abs) { \
1955 check_cop1x(ctx); \
1956 } \
1957 break; \
1958 } \
1959 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1960 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1961 switch (n) { \
895c2d04
BS
1962 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1963 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1964 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1965 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1966 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1967 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1968 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1969 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1970 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1971 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1972 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1973 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1974 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1975 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1976 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1977 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
8153667c
NF
1978 default: abort(); \
1979 } \
1980 tcg_temp_free_i##bits (fp0); \
1981 tcg_temp_free_i##bits (fp1); \
1982}
1983
1984FOP_CONDS(, 0, d, FMT_D, 64)
1985FOP_CONDS(abs, 1, d, FMT_D, 64)
1986FOP_CONDS(, 0, s, FMT_S, 32)
1987FOP_CONDS(abs, 1, s, FMT_S, 32)
1988FOP_CONDS(, 0, ps, FMT_PS, 64)
1989FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1990#undef FOP_CONDS
3f493883
YK
1991
1992#define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1993static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1994 int ft, int fs, int fd) \
1995{ \
1996 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1997 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
00fb4a11 1998 if (ifmt == FMT_D) { \
3f493883 1999 check_cp1_registers(ctx, fs | ft | fd); \
3f493883
YK
2000 } \
2001 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
2002 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
2003 switch (n) { \
2004 case 0: \
2005 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
2006 break; \
2007 case 1: \
2008 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
2009 break; \
2010 case 2: \
2011 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
2012 break; \
2013 case 3: \
2014 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
2015 break; \
2016 case 4: \
2017 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
2018 break; \
2019 case 5: \
2020 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
2021 break; \
2022 case 6: \
2023 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
2024 break; \
2025 case 7: \
2026 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
2027 break; \
2028 case 8: \
2029 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
2030 break; \
2031 case 9: \
2032 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
2033 break; \
2034 case 10: \
2035 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2036 break; \
2037 case 11: \
2038 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2039 break; \
2040 case 12: \
2041 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2042 break; \
2043 case 13: \
2044 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2045 break; \
2046 case 14: \
2047 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
2048 break; \
2049 case 15: \
2050 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
2051 break; \
2052 case 17: \
2053 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
2054 break; \
2055 case 18: \
2056 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2057 break; \
2058 case 19: \
2059 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2060 break; \
2061 case 25: \
2062 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2063 break; \
2064 case 26: \
2065 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2066 break; \
2067 case 27: \
2068 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2069 break; \
2070 default: \
2071 abort(); \
2072 } \
2073 STORE; \
2074 tcg_temp_free_i ## bits (fp0); \
2075 tcg_temp_free_i ## bits (fp1); \
2076}
2077
2078FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
7c979afd 2079FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3f493883 2080#undef FOP_CONDNS
8153667c
NF
2081#undef gen_ldcmp_fpr32
2082#undef gen_ldcmp_fpr64
2083
958fb4a9 2084/* load/store instructions. */
e7139c44 2085#ifdef CONFIG_USER_ONLY
d9bea114 2086#define OP_LD_ATOMIC(insn,fname) \
dd4096cd
JH
2087static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2088 DisasContext *ctx) \
d9bea114
AJ
2089{ \
2090 TCGv t0 = tcg_temp_new(); \
2091 tcg_gen_mov_tl(t0, arg1); \
2092 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
7db13fae
AF
2093 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2094 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
d9bea114 2095 tcg_temp_free(t0); \
aaa9128a 2096}
e7139c44
AJ
2097#else
2098#define OP_LD_ATOMIC(insn,fname) \
dd4096cd
JH
2099static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2100 DisasContext *ctx) \
e7139c44 2101{ \
dd4096cd 2102 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
e7139c44
AJ
2103}
2104#endif
aaa9128a
TS
2105OP_LD_ATOMIC(ll,ld32s);
2106#if defined(TARGET_MIPS64)
2107OP_LD_ATOMIC(lld,ld64);
2108#endif
2109#undef OP_LD_ATOMIC
2110
590bc601
PB
2111#ifdef CONFIG_USER_ONLY
2112#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
dd4096cd
JH
2113static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2114 DisasContext *ctx) \
590bc601
PB
2115{ \
2116 TCGv t0 = tcg_temp_new(); \
42a268c2
RH
2117 TCGLabel *l1 = gen_new_label(); \
2118 TCGLabel *l2 = gen_new_label(); \
590bc601
PB
2119 \
2120 tcg_gen_andi_tl(t0, arg2, almask); \
2121 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
7db13fae 2122 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
590bc601
PB
2123 generate_exception(ctx, EXCP_AdES); \
2124 gen_set_label(l1); \
7db13fae 2125 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
590bc601
PB
2126 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2127 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
7db13fae
AF
2128 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2129 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
9c708c7f 2130 generate_exception_end(ctx, EXCP_SC); \
590bc601
PB
2131 gen_set_label(l2); \
2132 tcg_gen_movi_tl(t0, 0); \
2133 gen_store_gpr(t0, rt); \
2134 tcg_temp_free(t0); \
2135}
2136#else
2137#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
dd4096cd
JH
2138static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2139 DisasContext *ctx) \
590bc601
PB
2140{ \
2141 TCGv t0 = tcg_temp_new(); \
dd4096cd 2142 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
590bc601 2143 gen_store_gpr(t0, rt); \
590bc601
PB
2144 tcg_temp_free(t0); \
2145}
2146#endif
590bc601 2147OP_ST_ATOMIC(sc,st32,ld32s,0x3);
aaa9128a 2148#if defined(TARGET_MIPS64)
590bc601 2149OP_ST_ATOMIC(scd,st64,ld64,0x7);
aaa9128a
TS
2150#endif
2151#undef OP_ST_ATOMIC
2152
662d7485 2153static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
72e1f16f 2154 int base, int offset)
662d7485
NF
2155{
2156 if (base == 0) {
2157 tcg_gen_movi_tl(addr, offset);
2158 } else if (offset == 0) {
2159 gen_load_gpr(addr, base);
2160 } else {
2161 tcg_gen_movi_tl(addr, offset);
2162 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2163 }
2164}
2165
364d4831
NF
2166static target_ulong pc_relative_pc (DisasContext *ctx)
2167{
eeb3bba8 2168 target_ulong pc = ctx->base.pc_next;
364d4831
NF
2169
2170 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2171 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2172
2173 pc -= branch_bytes;
2174 }
2175
2176 pc &= ~(target_ulong)3;
2177 return pc;
2178}
2179
5c13fdfd 2180/* Load */
d75c135e 2181static void gen_ld(DisasContext *ctx, uint32_t opc,
72e1f16f 2182 int rt, int base, int offset)
6af0bf9c 2183{
fc40787a 2184 TCGv t0, t1, t2;
dd4096cd 2185 int mem_idx = ctx->mem_idx;
afa88c3a 2186
d75c135e 2187 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
afa88c3a
AJ
2188 /* Loongson CPU uses a load to zero register for prefetch.
2189 We emulate it as a NOP. On other CPU we must perform the
2190 actual memory access. */
afa88c3a
AJ
2191 return;
2192 }
6af0bf9c 2193
afa88c3a 2194 t0 = tcg_temp_new();
662d7485 2195 gen_base_offset_addr(ctx, t0, base, offset);
afa88c3a 2196
6af0bf9c 2197 switch (opc) {
d26bc211 2198#if defined(TARGET_MIPS64)
6e473128 2199 case OPC_LWU:
dd4096cd 2200 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
be3a8c53 2201 ctx->default_tcg_memop_mask);
78723684 2202 gen_store_gpr(t0, rt);
6e473128 2203 break;
6af0bf9c 2204 case OPC_LD:
dd4096cd 2205 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
be3a8c53 2206 ctx->default_tcg_memop_mask);
78723684 2207 gen_store_gpr(t0, rt);
6af0bf9c 2208 break;
7a387fff 2209 case OPC_LLD:
bf7910c6 2210 case R6_OPC_LLD:
dd4096cd 2211 op_ld_lld(t0, t0, mem_idx, ctx);
78723684 2212 gen_store_gpr(t0, rt);
7a387fff 2213 break;
6af0bf9c 2214 case OPC_LDL:
3cee3050 2215 t1 = tcg_temp_new();
908680c6
AJ
2216 /* Do a byte access to possibly trigger a page
2217 fault with the unaligned address. */
dd4096cd 2218 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2219 tcg_gen_andi_tl(t1, t0, 7);
2220#ifndef TARGET_WORDS_BIGENDIAN
2221 tcg_gen_xori_tl(t1, t1, 7);
2222#endif
2223 tcg_gen_shli_tl(t1, t1, 3);
2224 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 2225 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a 2226 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
2227 t2 = tcg_const_tl(-1);
2228 tcg_gen_shl_tl(t2, t2, t1);
78723684 2229 gen_load_gpr(t1, rt);
eb02cc3f 2230 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
2231 tcg_temp_free(t2);
2232 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2233 tcg_temp_free(t1);
fc40787a 2234 gen_store_gpr(t0, rt);
6af0bf9c 2235 break;
6af0bf9c 2236 case OPC_LDR:
3cee3050 2237 t1 = tcg_temp_new();
908680c6
AJ
2238 /* Do a byte access to possibly trigger a page
2239 fault with the unaligned address. */
dd4096cd 2240 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2241 tcg_gen_andi_tl(t1, t0, 7);
2242#ifdef TARGET_WORDS_BIGENDIAN
2243 tcg_gen_xori_tl(t1, t1, 7);
2244#endif
2245 tcg_gen_shli_tl(t1, t1, 3);
2246 tcg_gen_andi_tl(t0, t0, ~7);
dd4096cd 2247 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
fc40787a
AJ
2248 tcg_gen_shr_tl(t0, t0, t1);
2249 tcg_gen_xori_tl(t1, t1, 63);
2250 t2 = tcg_const_tl(0xfffffffffffffffeull);
2251 tcg_gen_shl_tl(t2, t2, t1);
78723684 2252 gen_load_gpr(t1, rt);
fc40787a
AJ
2253 tcg_gen_and_tl(t1, t1, t2);
2254 tcg_temp_free(t2);
2255 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2256 tcg_temp_free(t1);
fc40787a 2257 gen_store_gpr(t0, rt);
6af0bf9c 2258 break;
364d4831 2259 case OPC_LDPC:
3cee3050 2260 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 2261 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 2262 tcg_temp_free(t1);
dd4096cd 2263 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
364d4831
NF
2264 gen_store_gpr(t0, rt);
2265 break;
6af0bf9c 2266#endif
364d4831 2267 case OPC_LWPC:
3cee3050 2268 t1 = tcg_const_tl(pc_relative_pc(ctx));
364d4831 2269 gen_op_addr_add(ctx, t0, t0, t1);
3cee3050 2270 tcg_temp_free(t1);
dd4096cd 2271 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
364d4831
NF
2272 gen_store_gpr(t0, rt);
2273 break;
76964147
JH
2274 case OPC_LWE:
2275 mem_idx = MIPS_HFLAG_UM;
2276 /* fall through */
6af0bf9c 2277 case OPC_LW:
dd4096cd 2278 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
be3a8c53 2279 ctx->default_tcg_memop_mask);
78723684 2280 gen_store_gpr(t0, rt);
6af0bf9c 2281 break;
76964147
JH
2282 case OPC_LHE:
2283 mem_idx = MIPS_HFLAG_UM;
2284 /* fall through */
6af0bf9c 2285 case OPC_LH:
dd4096cd 2286 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
be3a8c53 2287 ctx->default_tcg_memop_mask);
78723684 2288 gen_store_gpr(t0, rt);
6af0bf9c 2289 break;
76964147
JH
2290 case OPC_LHUE:
2291 mem_idx = MIPS_HFLAG_UM;
2292 /* fall through */
6af0bf9c 2293 case OPC_LHU:
dd4096cd 2294 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
be3a8c53 2295 ctx->default_tcg_memop_mask);
78723684 2296 gen_store_gpr(t0, rt);
6af0bf9c 2297 break;
76964147
JH
2298 case OPC_LBE:
2299 mem_idx = MIPS_HFLAG_UM;
2300 /* fall through */
6af0bf9c 2301 case OPC_LB:
dd4096cd 2302 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
78723684 2303 gen_store_gpr(t0, rt);
6af0bf9c 2304 break;
76964147
JH
2305 case OPC_LBUE:
2306 mem_idx = MIPS_HFLAG_UM;
2307 /* fall through */
6af0bf9c 2308 case OPC_LBU:
dd4096cd 2309 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
78723684 2310 gen_store_gpr(t0, rt);
6af0bf9c 2311 break;
76964147
JH
2312 case OPC_LWLE:
2313 mem_idx = MIPS_HFLAG_UM;
2314 /* fall through */
6af0bf9c 2315 case OPC_LWL:
3cee3050 2316 t1 = tcg_temp_new();
908680c6
AJ
2317 /* Do a byte access to possibly trigger a page
2318 fault with the unaligned address. */
dd4096cd 2319 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2320 tcg_gen_andi_tl(t1, t0, 3);
2321#ifndef TARGET_WORDS_BIGENDIAN
2322 tcg_gen_xori_tl(t1, t1, 3);
2323#endif
2324 tcg_gen_shli_tl(t1, t1, 3);
2325 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 2326 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a 2327 tcg_gen_shl_tl(t0, t0, t1);
eb02cc3f
AJ
2328 t2 = tcg_const_tl(-1);
2329 tcg_gen_shl_tl(t2, t2, t1);
6958549d 2330 gen_load_gpr(t1, rt);
eb02cc3f 2331 tcg_gen_andc_tl(t1, t1, t2);
fc40787a
AJ
2332 tcg_temp_free(t2);
2333 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2334 tcg_temp_free(t1);
fc40787a
AJ
2335 tcg_gen_ext32s_tl(t0, t0);
2336 gen_store_gpr(t0, rt);
6af0bf9c 2337 break;
76964147
JH
2338 case OPC_LWRE:
2339 mem_idx = MIPS_HFLAG_UM;
2340 /* fall through */
6af0bf9c 2341 case OPC_LWR:
3cee3050 2342 t1 = tcg_temp_new();
908680c6
AJ
2343 /* Do a byte access to possibly trigger a page
2344 fault with the unaligned address. */
dd4096cd 2345 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
fc40787a
AJ
2346 tcg_gen_andi_tl(t1, t0, 3);
2347#ifdef TARGET_WORDS_BIGENDIAN
2348 tcg_gen_xori_tl(t1, t1, 3);
2349#endif
2350 tcg_gen_shli_tl(t1, t1, 3);
2351 tcg_gen_andi_tl(t0, t0, ~3);
dd4096cd 2352 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
fc40787a
AJ
2353 tcg_gen_shr_tl(t0, t0, t1);
2354 tcg_gen_xori_tl(t1, t1, 31);
2355 t2 = tcg_const_tl(0xfffffffeull);
2356 tcg_gen_shl_tl(t2, t2, t1);
6958549d 2357 gen_load_gpr(t1, rt);
fc40787a
AJ
2358 tcg_gen_and_tl(t1, t1, t2);
2359 tcg_temp_free(t2);
2360 tcg_gen_or_tl(t0, t0, t1);
3cee3050 2361 tcg_temp_free(t1);
c728154b 2362 tcg_gen_ext32s_tl(t0, t0);
fc40787a 2363 gen_store_gpr(t0, rt);
6af0bf9c 2364 break;
76964147
JH
2365 case OPC_LLE:
2366 mem_idx = MIPS_HFLAG_UM;
2367 /* fall through */
6af0bf9c 2368 case OPC_LL:
4368b29a 2369 case R6_OPC_LL:
dd4096cd 2370 op_ld_ll(t0, t0, mem_idx, ctx);
78723684 2371 gen_store_gpr(t0, rt);
6af0bf9c 2372 break;
d66c7132 2373 }
d66c7132 2374 tcg_temp_free(t0);
d66c7132
AJ
2375}
2376
0b16dcd1
AR
2377static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
2378 uint32_t reg1, uint32_t reg2)
2379{
2380 TCGv taddr = tcg_temp_new();
2381 TCGv_i64 tval = tcg_temp_new_i64();
2382 TCGv tmp1 = tcg_temp_new();
2383 TCGv tmp2 = tcg_temp_new();
2384
2385 gen_base_offset_addr(ctx, taddr, base, offset);
2386 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
2387#ifdef TARGET_WORDS_BIGENDIAN
2388 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
2389#else
2390 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
2391#endif
2392 gen_store_gpr(tmp1, reg1);
2393 tcg_temp_free(tmp1);
2394 gen_store_gpr(tmp2, reg2);
2395 tcg_temp_free(tmp2);
2396 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2397 tcg_temp_free_i64(tval);
2398 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
2399 tcg_temp_free(taddr);
2400}
2401
5c13fdfd
AJ
2402/* Store */
2403static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
72e1f16f 2404 int base, int offset)
5c13fdfd 2405{
5c13fdfd
AJ
2406 TCGv t0 = tcg_temp_new();
2407 TCGv t1 = tcg_temp_new();
dd4096cd 2408 int mem_idx = ctx->mem_idx;
5c13fdfd
AJ
2409
2410 gen_base_offset_addr(ctx, t0, base, offset);
2411 gen_load_gpr(t1, rt);
2412 switch (opc) {
2413#if defined(TARGET_MIPS64)
2414 case OPC_SD:
dd4096cd 2415 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
be3a8c53 2416 ctx->default_tcg_memop_mask);
5c13fdfd
AJ
2417 break;
2418 case OPC_SDL:
dd4096cd 2419 gen_helper_0e2i(sdl, t1, t0, mem_idx);
5c13fdfd
AJ
2420 break;
2421 case OPC_SDR:
dd4096cd 2422 gen_helper_0e2i(sdr, t1, t0, mem_idx);
5c13fdfd
AJ
2423 break;
2424#endif
76964147
JH
2425 case OPC_SWE:
2426 mem_idx = MIPS_HFLAG_UM;
2427 /* fall through */
5c13fdfd 2428 case OPC_SW:
dd4096cd 2429 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
be3a8c53 2430 ctx->default_tcg_memop_mask);
5c13fdfd 2431 break;
76964147
JH
2432 case OPC_SHE:
2433 mem_idx = MIPS_HFLAG_UM;
2434 /* fall through */
5c13fdfd 2435 case OPC_SH:
dd4096cd 2436 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
be3a8c53 2437 ctx->default_tcg_memop_mask);
5c13fdfd 2438 break;
76964147
JH
2439 case OPC_SBE:
2440 mem_idx = MIPS_HFLAG_UM;
2441 /* fall through */
5c13fdfd 2442 case OPC_SB:
dd4096cd 2443 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
5c13fdfd 2444 break;
76964147
JH
2445 case OPC_SWLE:
2446 mem_idx = MIPS_HFLAG_UM;
2447 /* fall through */
5c13fdfd 2448 case OPC_SWL:
dd4096cd 2449 gen_helper_0e2i(swl, t1, t0, mem_idx);
5c13fdfd 2450 break;
76964147
JH
2451 case OPC_SWRE:
2452 mem_idx = MIPS_HFLAG_UM;
2453 /* fall through */
5c13fdfd 2454 case OPC_SWR:
dd4096cd 2455 gen_helper_0e2i(swr, t1, t0, mem_idx);
5c13fdfd
AJ
2456 break;
2457 }
5c13fdfd
AJ
2458 tcg_temp_free(t0);
2459 tcg_temp_free(t1);
2460}
2461
2462
d66c7132
AJ
2463/* Store conditional */
2464static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2465 int base, int16_t offset)
2466{
d66c7132 2467 TCGv t0, t1;
dd4096cd 2468 int mem_idx = ctx->mem_idx;
d66c7132 2469
2d2826b9 2470#ifdef CONFIG_USER_ONLY
d66c7132 2471 t0 = tcg_temp_local_new();
d66c7132 2472 t1 = tcg_temp_local_new();
2d2826b9
AJ
2473#else
2474 t0 = tcg_temp_new();
2475 t1 = tcg_temp_new();
2476#endif
2477 gen_base_offset_addr(ctx, t0, base, offset);
d66c7132
AJ
2478 gen_load_gpr(t1, rt);
2479 switch (opc) {
2480#if defined(TARGET_MIPS64)
2481 case OPC_SCD:
bf7910c6 2482 case R6_OPC_SCD:
dd4096cd 2483 op_st_scd(t1, t0, rt, mem_idx, ctx);
d66c7132
AJ
2484 break;
2485#endif
76964147
JH
2486 case OPC_SCE:
2487 mem_idx = MIPS_HFLAG_UM;
2488 /* fall through */
6af0bf9c 2489 case OPC_SC:
4368b29a 2490 case R6_OPC_SC:
dd4096cd 2491 op_st_sc(t1, t0, rt, mem_idx, ctx);
6af0bf9c 2492 break;
6af0bf9c 2493 }
78723684 2494 tcg_temp_free(t1);
d66c7132 2495 tcg_temp_free(t0);
6af0bf9c
FB
2496}
2497
0b16dcd1
AR
2498static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
2499 uint32_t reg1, uint32_t reg2)
2500{
2501 TCGv taddr = tcg_temp_local_new();
2502 TCGv lladdr = tcg_temp_local_new();
2503 TCGv_i64 tval = tcg_temp_new_i64();
2504 TCGv_i64 llval = tcg_temp_new_i64();
2505 TCGv_i64 val = tcg_temp_new_i64();
2506 TCGv tmp1 = tcg_temp_new();
2507 TCGv tmp2 = tcg_temp_new();
2508 TCGLabel *lab_fail = gen_new_label();
2509 TCGLabel *lab_done = gen_new_label();
2510
2511 gen_base_offset_addr(ctx, taddr, base, offset);
2512
2513 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2514 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
2515
2516 gen_load_gpr(tmp1, reg1);
2517 gen_load_gpr(tmp2, reg2);
2518
2519#ifdef TARGET_WORDS_BIGENDIAN
2520 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
2521#else
2522 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
2523#endif
2524
2525 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2526 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
2527 ctx->mem_idx, MO_64);
2528 if (reg1 != 0) {
2529 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
2530 }
2531 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
2532
2533 gen_set_label(lab_fail);
2534
2535 if (reg1 != 0) {
2536 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
2537 }
2538 gen_set_label(lab_done);
2539 tcg_gen_movi_tl(lladdr, -1);
2540 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2541}
2542
6ea83fed 2543/* Load and store */
7a387fff 2544static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
b52d3bfa 2545 TCGv t0)
6ea83fed 2546{
6ea83fed 2547 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 2548 memory access. */
6ea83fed
FB
2549 switch (opc) {
2550 case OPC_LWC1:
b6d96bed 2551 {
a7812ae4 2552 TCGv_i32 fp0 = tcg_temp_new_i32();
be3a8c53
YK
2553 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2554 ctx->default_tcg_memop_mask);
7c979afd 2555 gen_store_fpr32(ctx, fp0, ft);
a7812ae4 2556 tcg_temp_free_i32(fp0);
b6d96bed 2557 }
6ea83fed
FB
2558 break;
2559 case OPC_SWC1:
b6d96bed 2560 {
a7812ae4 2561 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 2562 gen_load_fpr32(ctx, fp0, ft);
be3a8c53
YK
2563 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2564 ctx->default_tcg_memop_mask);
a7812ae4 2565 tcg_temp_free_i32(fp0);
b6d96bed 2566 }
6ea83fed
FB
2567 break;
2568 case OPC_LDC1:
b6d96bed 2569 {
a7812ae4 2570 TCGv_i64 fp0 = tcg_temp_new_i64();
be3a8c53
YK
2571 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2572 ctx->default_tcg_memop_mask);
b6d96bed 2573 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 2574 tcg_temp_free_i64(fp0);
b6d96bed 2575 }
6ea83fed
FB
2576 break;
2577 case OPC_SDC1:
b6d96bed 2578 {
a7812ae4 2579 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 2580 gen_load_fpr64(ctx, fp0, ft);
be3a8c53
YK
2581 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2582 ctx->default_tcg_memop_mask);
a7812ae4 2583 tcg_temp_free_i64(fp0);
b6d96bed 2584 }
6ea83fed
FB
2585 break;
2586 default:
9d68ac14 2587 MIPS_INVAL("flt_ldst");
9c708c7f 2588 generate_exception_end(ctx, EXCP_RI);
b52d3bfa 2589 break;
6ea83fed 2590 }
6ea83fed 2591}
6ea83fed 2592
5ab5c041
AJ
2593static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2594 int rs, int16_t imm)
26ebe468 2595{
b52d3bfa
YK
2596 TCGv t0 = tcg_temp_new();
2597
5ab5c041 2598 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26ebe468 2599 check_cp1_enabled(ctx);
d9224450
MR
2600 switch (op) {
2601 case OPC_LDC1:
2602 case OPC_SDC1:
2603 check_insn(ctx, ISA_MIPS2);
2604 /* Fallthrough */
2605 default:
b52d3bfa
YK
2606 gen_base_offset_addr(ctx, t0, rs, imm);
2607 gen_flt_ldst(ctx, op, rt, t0);
d9224450 2608 }
26ebe468
NF
2609 } else {
2610 generate_exception_err(ctx, EXCP_CpU, 1);
2611 }
b52d3bfa 2612 tcg_temp_free(t0);
26ebe468
NF
2613}
2614
6af0bf9c 2615/* Arithmetic with immediate operand */
d75c135e 2616static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
72e1f16f 2617 int rt, int rs, int imm)
6af0bf9c 2618{
324d9e32 2619 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
6af0bf9c 2620
7a387fff 2621 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
ead9360e
TS
2622 /* If no destination, treat it as a NOP.
2623 For addi, we must generate the overflow exception when needed. */
324d9e32 2624 return;
6af0bf9c
FB
2625 }
2626 switch (opc) {
2627 case OPC_ADDI:
48d38ca5 2628 {
324d9e32
AJ
2629 TCGv t0 = tcg_temp_local_new();
2630 TCGv t1 = tcg_temp_new();
2631 TCGv t2 = tcg_temp_new();
42a268c2 2632 TCGLabel *l1 = gen_new_label();
48d38ca5 2633
324d9e32
AJ
2634 gen_load_gpr(t1, rs);
2635 tcg_gen_addi_tl(t0, t1, uimm);
2636 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 2637
324d9e32
AJ
2638 tcg_gen_xori_tl(t1, t1, ~uimm);
2639 tcg_gen_xori_tl(t2, t0, uimm);
2640 tcg_gen_and_tl(t1, t1, t2);
2641 tcg_temp_free(t2);
2642 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2643 tcg_temp_free(t1);
48d38ca5
TS
2644 /* operands of same sign, result different sign */
2645 generate_exception(ctx, EXCP_OVERFLOW);
2646 gen_set_label(l1);
78723684 2647 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
2648 gen_store_gpr(t0, rt);
2649 tcg_temp_free(t0);
48d38ca5 2650 }
6af0bf9c
FB
2651 break;
2652 case OPC_ADDIU:
324d9e32
AJ
2653 if (rs != 0) {
2654 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2655 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2656 } else {
2657 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2658 }
6af0bf9c 2659 break;
d26bc211 2660#if defined(TARGET_MIPS64)
7a387fff 2661 case OPC_DADDI:
48d38ca5 2662 {
324d9e32
AJ
2663 TCGv t0 = tcg_temp_local_new();
2664 TCGv t1 = tcg_temp_new();
2665 TCGv t2 = tcg_temp_new();
42a268c2 2666 TCGLabel *l1 = gen_new_label();
48d38ca5 2667
324d9e32
AJ
2668 gen_load_gpr(t1, rs);
2669 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 2670
324d9e32
AJ
2671 tcg_gen_xori_tl(t1, t1, ~uimm);
2672 tcg_gen_xori_tl(t2, t0, uimm);
2673 tcg_gen_and_tl(t1, t1, t2);
2674 tcg_temp_free(t2);
2675 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2676 tcg_temp_free(t1);
48d38ca5
TS
2677 /* operands of same sign, result different sign */
2678 generate_exception(ctx, EXCP_OVERFLOW);
2679 gen_set_label(l1);
324d9e32
AJ
2680 gen_store_gpr(t0, rt);
2681 tcg_temp_free(t0);
48d38ca5 2682 }
7a387fff
TS
2683 break;
2684 case OPC_DADDIU:
324d9e32
AJ
2685 if (rs != 0) {
2686 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2687 } else {
2688 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2689 }
7a387fff
TS
2690 break;
2691#endif
324d9e32 2692 }
324d9e32
AJ
2693}
2694
2695/* Logic with immediate operand */
d75c135e 2696static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
9fa77488 2697 int rt, int rs, int16_t imm)
324d9e32
AJ
2698{
2699 target_ulong uimm;
324d9e32
AJ
2700
2701 if (rt == 0) {
2702 /* If no destination, treat it as a NOP. */
324d9e32
AJ
2703 return;
2704 }
2705 uimm = (uint16_t)imm;
2706 switch (opc) {
6af0bf9c 2707 case OPC_ANDI:
324d9e32
AJ
2708 if (likely(rs != 0))
2709 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2710 else
2711 tcg_gen_movi_tl(cpu_gpr[rt], 0);
6af0bf9c
FB
2712 break;
2713 case OPC_ORI:
324d9e32
AJ
2714 if (rs != 0)
2715 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2716 else
2717 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
2718 break;
2719 case OPC_XORI:
324d9e32
AJ
2720 if (likely(rs != 0))
2721 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2722 else
2723 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
2724 break;
2725 case OPC_LUI:
d4ea6acd
LA
2726 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2727 /* OPC_AUI */
2728 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2729 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
d4ea6acd
LA
2730 } else {
2731 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
d4ea6acd 2732 }
7c2c3ea3
EJ
2733 break;
2734
2735 default:
6af0bf9c 2736 break;
324d9e32 2737 }
324d9e32
AJ
2738}
2739
2740/* Set on less than with immediate operand */
d75c135e 2741static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
9fa77488 2742 int rt, int rs, int16_t imm)
324d9e32
AJ
2743{
2744 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
324d9e32
AJ
2745 TCGv t0;
2746
2747 if (rt == 0) {
2748 /* If no destination, treat it as a NOP. */
324d9e32
AJ
2749 return;
2750 }
2751 t0 = tcg_temp_new();
2752 gen_load_gpr(t0, rs);
2753 switch (opc) {
2754 case OPC_SLTI:
e68dd28f 2755 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
2756 break;
2757 case OPC_SLTIU:
e68dd28f 2758 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
2759 break;
2760 }
324d9e32
AJ
2761 tcg_temp_free(t0);
2762}
2763
2764/* Shifts with immediate operand */
d75c135e 2765static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
324d9e32
AJ
2766 int rt, int rs, int16_t imm)
2767{
2768 target_ulong uimm = ((uint16_t)imm) & 0x1f;
324d9e32
AJ
2769 TCGv t0;
2770
2771 if (rt == 0) {
2772 /* If no destination, treat it as a NOP. */
324d9e32
AJ
2773 return;
2774 }
2775
2776 t0 = tcg_temp_new();
2777 gen_load_gpr(t0, rs);
2778 switch (opc) {
6af0bf9c 2779 case OPC_SLL:
78723684 2780 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 2781 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
2782 break;
2783 case OPC_SRA:
324d9e32 2784 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
2785 break;
2786 case OPC_SRL:
ea63e2c3
NF
2787 if (uimm != 0) {
2788 tcg_gen_ext32u_tl(t0, t0);
2789 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2790 } else {
2791 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 2792 }
ea63e2c3
NF
2793 break;
2794 case OPC_ROTR:
2795 if (uimm != 0) {
2796 TCGv_i32 t1 = tcg_temp_new_i32();
2797
2798 tcg_gen_trunc_tl_i32(t1, t0);
2799 tcg_gen_rotri_i32(t1, t1, uimm);
2800 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2801 tcg_temp_free_i32(t1);
3399e30f
NF
2802 } else {
2803 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3 2804 }
7a387fff 2805 break;
d26bc211 2806#if defined(TARGET_MIPS64)
7a387fff 2807 case OPC_DSLL:
324d9e32 2808 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
2809 break;
2810 case OPC_DSRA:
324d9e32 2811 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
2812 break;
2813 case OPC_DSRL:
ea63e2c3 2814 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
ea63e2c3
NF
2815 break;
2816 case OPC_DROTR:
2817 if (uimm != 0) {
2818 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
2819 } else {
2820 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 2821 }
7a387fff
TS
2822 break;
2823 case OPC_DSLL32:
324d9e32 2824 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
2825 break;
2826 case OPC_DSRA32:
324d9e32 2827 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
2828 break;
2829 case OPC_DSRL32:
ea63e2c3 2830 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
ea63e2c3
NF
2831 break;
2832 case OPC_DROTR32:
2833 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
6af0bf9c 2834 break;
7a387fff 2835#endif
6af0bf9c 2836 }
78723684 2837 tcg_temp_free(t0);
6af0bf9c
FB
2838}
2839
2840/* Arithmetic */
d75c135e
AJ
2841static void gen_arith(DisasContext *ctx, uint32_t opc,
2842 int rd, int rs, int rt)
6af0bf9c 2843{
7a387fff
TS
2844 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2845 && opc != OPC_DADD && opc != OPC_DSUB) {
ead9360e
TS
2846 /* If no destination, treat it as a NOP.
2847 For add & sub, we must generate the overflow exception when needed. */
460f00c4 2848 return;
185f0762 2849 }
460f00c4 2850
6af0bf9c
FB
2851 switch (opc) {
2852 case OPC_ADD:
48d38ca5 2853 {
460f00c4
AJ
2854 TCGv t0 = tcg_temp_local_new();
2855 TCGv t1 = tcg_temp_new();
2856 TCGv t2 = tcg_temp_new();
42a268c2 2857 TCGLabel *l1 = gen_new_label();
48d38ca5 2858
460f00c4
AJ
2859 gen_load_gpr(t1, rs);
2860 gen_load_gpr(t2, rt);
2861 tcg_gen_add_tl(t0, t1, t2);
2862 tcg_gen_ext32s_tl(t0, t0);
2863 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 2864 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 2865 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
2866 tcg_temp_free(t2);
2867 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2868 tcg_temp_free(t1);
48d38ca5
TS
2869 /* operands of same sign, result different sign */
2870 generate_exception(ctx, EXCP_OVERFLOW);
2871 gen_set_label(l1);
460f00c4
AJ
2872 gen_store_gpr(t0, rd);
2873 tcg_temp_free(t0);
48d38ca5 2874 }
6af0bf9c
FB
2875 break;
2876 case OPC_ADDU:
460f00c4
AJ
2877 if (rs != 0 && rt != 0) {
2878 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2879 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2880 } else if (rs == 0 && rt != 0) {
2881 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2882 } else if (rs != 0 && rt == 0) {
2883 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2884 } else {
2885 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2886 }
6af0bf9c
FB
2887 break;
2888 case OPC_SUB:
48d38ca5 2889 {
460f00c4
AJ
2890 TCGv t0 = tcg_temp_local_new();
2891 TCGv t1 = tcg_temp_new();
2892 TCGv t2 = tcg_temp_new();
42a268c2 2893 TCGLabel *l1 = gen_new_label();
48d38ca5 2894
460f00c4
AJ
2895 gen_load_gpr(t1, rs);
2896 gen_load_gpr(t2, rt);
2897 tcg_gen_sub_tl(t0, t1, t2);
2898 tcg_gen_ext32s_tl(t0, t0);
2899 tcg_gen_xor_tl(t2, t1, t2);
2900 tcg_gen_xor_tl(t1, t0, t1);
2901 tcg_gen_and_tl(t1, t1, t2);
2902 tcg_temp_free(t2);
2903 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2904 tcg_temp_free(t1);
31e3104f 2905 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
2906 generate_exception(ctx, EXCP_OVERFLOW);
2907 gen_set_label(l1);
460f00c4
AJ
2908 gen_store_gpr(t0, rd);
2909 tcg_temp_free(t0);
48d38ca5 2910 }
6af0bf9c
FB
2911 break;
2912 case OPC_SUBU:
460f00c4
AJ
2913 if (rs != 0 && rt != 0) {
2914 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2915 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2916 } else if (rs == 0 && rt != 0) {
2917 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 2918 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
2919 } else if (rs != 0 && rt == 0) {
2920 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2921 } else {
2922 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2923 }
6af0bf9c 2924 break;
d26bc211 2925#if defined(TARGET_MIPS64)
7a387fff 2926 case OPC_DADD:
48d38ca5 2927 {
460f00c4
AJ
2928 TCGv t0 = tcg_temp_local_new();
2929 TCGv t1 = tcg_temp_new();
2930 TCGv t2 = tcg_temp_new();
42a268c2 2931 TCGLabel *l1 = gen_new_label();
48d38ca5 2932
460f00c4
AJ
2933 gen_load_gpr(t1, rs);
2934 gen_load_gpr(t2, rt);
2935 tcg_gen_add_tl(t0, t1, t2);
2936 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 2937 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 2938 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
2939 tcg_temp_free(t2);
2940 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2941 tcg_temp_free(t1);
48d38ca5
TS
2942 /* operands of same sign, result different sign */
2943 generate_exception(ctx, EXCP_OVERFLOW);
2944 gen_set_label(l1);
460f00c4
AJ
2945 gen_store_gpr(t0, rd);
2946 tcg_temp_free(t0);
48d38ca5 2947 }
7a387fff
TS
2948 break;
2949 case OPC_DADDU:
460f00c4
AJ
2950 if (rs != 0 && rt != 0) {
2951 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2952 } else if (rs == 0 && rt != 0) {
2953 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2954 } else if (rs != 0 && rt == 0) {
2955 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2956 } else {
2957 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2958 }
7a387fff
TS
2959 break;
2960 case OPC_DSUB:
48d38ca5 2961 {
460f00c4
AJ
2962 TCGv t0 = tcg_temp_local_new();
2963 TCGv t1 = tcg_temp_new();
2964 TCGv t2 = tcg_temp_new();
42a268c2 2965 TCGLabel *l1 = gen_new_label();
48d38ca5 2966
460f00c4
AJ
2967 gen_load_gpr(t1, rs);
2968 gen_load_gpr(t2, rt);
2969 tcg_gen_sub_tl(t0, t1, t2);
2970 tcg_gen_xor_tl(t2, t1, t2);
2971 tcg_gen_xor_tl(t1, t0, t1);
2972 tcg_gen_and_tl(t1, t1, t2);
2973 tcg_temp_free(t2);
2974 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2975 tcg_temp_free(t1);
31e3104f 2976 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
2977 generate_exception(ctx, EXCP_OVERFLOW);
2978 gen_set_label(l1);
460f00c4
AJ
2979 gen_store_gpr(t0, rd);
2980 tcg_temp_free(t0);
48d38ca5 2981 }
7a387fff
TS
2982 break;
2983 case OPC_DSUBU:
460f00c4
AJ
2984 if (rs != 0 && rt != 0) {
2985 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2986 } else if (rs == 0 && rt != 0) {
2987 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2988 } else if (rs != 0 && rt == 0) {
2989 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2990 } else {
2991 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2992 }
7a387fff
TS
2993 break;
2994#endif
460f00c4
AJ
2995 case OPC_MUL:
2996 if (likely(rs != 0 && rt != 0)) {
2997 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2998 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2999 } else {
3000 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3001 }
6af0bf9c 3002 break;
460f00c4 3003 }
460f00c4
AJ
3004}
3005
3006/* Conditional move */
d75c135e 3007static void gen_cond_move(DisasContext *ctx, uint32_t opc,
9fa77488 3008 int rd, int rs, int rt)
460f00c4 3009{
acf12465 3010 TCGv t0, t1, t2;
460f00c4
AJ
3011
3012 if (rd == 0) {
acf12465 3013 /* If no destination, treat it as a NOP. */
460f00c4
AJ
3014 return;
3015 }
3016
acf12465
AJ
3017 t0 = tcg_temp_new();
3018 gen_load_gpr(t0, rt);
3019 t1 = tcg_const_tl(0);
3020 t2 = tcg_temp_new();
3021 gen_load_gpr(t2, rs);
460f00c4
AJ
3022 switch (opc) {
3023 case OPC_MOVN:
acf12465 3024 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
6af0bf9c 3025 break;
460f00c4 3026 case OPC_MOVZ:
acf12465 3027 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
460f00c4 3028 break;
b691d9d2
LA
3029 case OPC_SELNEZ:
3030 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2
LA
3031 break;
3032 case OPC_SELEQZ:
3033 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
b691d9d2 3034 break;
460f00c4 3035 }
acf12465
AJ
3036 tcg_temp_free(t2);
3037 tcg_temp_free(t1);
3038 tcg_temp_free(t0);
460f00c4
AJ
3039}
3040
3041/* Logic */
d75c135e 3042static void gen_logic(DisasContext *ctx, uint32_t opc,
9fa77488 3043 int rd, int rs, int rt)
460f00c4 3044{
460f00c4
AJ
3045 if (rd == 0) {
3046 /* If no destination, treat it as a NOP. */
460f00c4
AJ
3047 return;
3048 }
3049
3050 switch (opc) {
6af0bf9c 3051 case OPC_AND:
460f00c4
AJ
3052 if (likely(rs != 0 && rt != 0)) {
3053 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3054 } else {
3055 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3056 }
6af0bf9c
FB
3057 break;
3058 case OPC_NOR:
460f00c4
AJ
3059 if (rs != 0 && rt != 0) {
3060 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3061 } else if (rs == 0 && rt != 0) {
3062 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
3063 } else if (rs != 0 && rt == 0) {
3064 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
3065 } else {
3066 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
3067 }
6af0bf9c
FB
3068 break;
3069 case OPC_OR:
460f00c4
AJ
3070 if (likely(rs != 0 && rt != 0)) {
3071 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3072 } else if (rs == 0 && rt != 0) {
3073 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3074 } else if (rs != 0 && rt == 0) {
3075 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3076 } else {
3077 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3078 }
6af0bf9c
FB
3079 break;
3080 case OPC_XOR:
460f00c4
AJ
3081 if (likely(rs != 0 && rt != 0)) {
3082 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3083 } else if (rs == 0 && rt != 0) {
3084 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3085 } else if (rs != 0 && rt == 0) {
3086 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3087 } else {
3088 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3089 }
6af0bf9c 3090 break;
460f00c4 3091 }
460f00c4
AJ
3092}
3093
3094/* Set on lower than */
d75c135e 3095static void gen_slt(DisasContext *ctx, uint32_t opc,
9fa77488 3096 int rd, int rs, int rt)
460f00c4 3097{
460f00c4
AJ
3098 TCGv t0, t1;
3099
3100 if (rd == 0) {
3101 /* If no destination, treat it as a NOP. */
460f00c4
AJ
3102 return;
3103 }
3104
3105 t0 = tcg_temp_new();
3106 t1 = tcg_temp_new();
3107 gen_load_gpr(t0, rs);
3108 gen_load_gpr(t1, rt);
3109 switch (opc) {
3110 case OPC_SLT:
e68dd28f 3111 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
6af0bf9c 3112 break;
460f00c4 3113 case OPC_SLTU:
e68dd28f 3114 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
3115 break;
3116 }
460f00c4
AJ
3117 tcg_temp_free(t0);
3118 tcg_temp_free(t1);
3119}
20c4c97c 3120
460f00c4 3121/* Shifts */
d75c135e
AJ
3122static void gen_shift(DisasContext *ctx, uint32_t opc,
3123 int rd, int rs, int rt)
460f00c4 3124{
460f00c4 3125 TCGv t0, t1;
20c4c97c 3126
460f00c4
AJ
3127 if (rd == 0) {
3128 /* If no destination, treat it as a NOP.
3129 For add & sub, we must generate the overflow exception when needed. */
460f00c4
AJ
3130 return;
3131 }
3132
3133 t0 = tcg_temp_new();
3134 t1 = tcg_temp_new();
3135 gen_load_gpr(t0, rs);
3136 gen_load_gpr(t1, rt);
3137 switch (opc) {
6af0bf9c 3138 case OPC_SLLV:
78723684
TS
3139 tcg_gen_andi_tl(t0, t0, 0x1f);
3140 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 3141 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
3142 break;
3143 case OPC_SRAV:
78723684 3144 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 3145 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
3146 break;
3147 case OPC_SRLV:
ea63e2c3
NF
3148 tcg_gen_ext32u_tl(t1, t1);
3149 tcg_gen_andi_tl(t0, t0, 0x1f);
3150 tcg_gen_shr_tl(t0, t1, t0);
3151 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
ea63e2c3
NF
3152 break;
3153 case OPC_ROTRV:
3154 {
3155 TCGv_i32 t2 = tcg_temp_new_i32();
3156 TCGv_i32 t3 = tcg_temp_new_i32();
3157
3158 tcg_gen_trunc_tl_i32(t2, t0);
3159 tcg_gen_trunc_tl_i32(t3, t1);
3160 tcg_gen_andi_i32(t2, t2, 0x1f);
3161 tcg_gen_rotr_i32(t2, t3, t2);
3162 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3163 tcg_temp_free_i32(t2);
3164 tcg_temp_free_i32(t3);
5a63bcb2 3165 }
7a387fff 3166 break;
d26bc211 3167#if defined(TARGET_MIPS64)
7a387fff 3168 case OPC_DSLLV:
78723684 3169 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 3170 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
3171 break;
3172 case OPC_DSRAV:
78723684 3173 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 3174 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
3175 break;
3176 case OPC_DSRLV:
ea63e2c3
NF
3177 tcg_gen_andi_tl(t0, t0, 0x3f);
3178 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
ea63e2c3
NF
3179 break;
3180 case OPC_DROTRV:
3181 tcg_gen_andi_tl(t0, t0, 0x3f);
3182 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
6af0bf9c 3183 break;
7a387fff 3184#endif
6af0bf9c 3185 }
78723684
TS
3186 tcg_temp_free(t0);
3187 tcg_temp_free(t1);
6af0bf9c
FB
3188}
3189
3190/* Arithmetic on HI/LO registers */
26135ead 3191static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
6af0bf9c 3192{
6af0bf9c 3193 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 3194 /* Treat as NOP. */
a1f6684d 3195 return;
6af0bf9c 3196 }
4133498f 3197
4133498f
JL
3198 if (acc != 0) {
3199 check_dsp(ctx);
3200 }
3201
6af0bf9c
FB
3202 switch (opc) {
3203 case OPC_MFHI:
4133498f
JL
3204#if defined(TARGET_MIPS64)
3205 if (acc != 0) {
3206 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3207 } else
3208#endif
3209 {
3210 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3211 }
6af0bf9c
FB
3212 break;
3213 case OPC_MFLO:
4133498f
JL
3214#if defined(TARGET_MIPS64)
3215 if (acc != 0) {
3216 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3217 } else
3218#endif
3219 {
3220 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3221 }
6af0bf9c
FB
3222 break;
3223 case OPC_MTHI:
4133498f
JL
3224 if (reg != 0) {
3225#if defined(TARGET_MIPS64)
3226 if (acc != 0) {
3227 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3228 } else
3229#endif
3230 {
3231 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3232 }
3233 } else {
3234 tcg_gen_movi_tl(cpu_HI[acc], 0);
3235 }
6af0bf9c
FB
3236 break;
3237 case OPC_MTLO:
4133498f
JL
3238 if (reg != 0) {
3239#if defined(TARGET_MIPS64)
3240 if (acc != 0) {
3241 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3242 } else
3243#endif
3244 {
3245 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3246 }
3247 } else {
3248 tcg_gen_movi_tl(cpu_LO[acc], 0);
3249 }
6af0bf9c 3250 break;
6af0bf9c 3251 }
6af0bf9c
FB
3252}
3253
d4ea6acd
LA
3254static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3255 TCGMemOp memop)
3256{
3257 TCGv t0 = tcg_const_tl(addr);
3258 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3259 gen_store_gpr(t0, reg);
3260 tcg_temp_free(t0);
3261}
3262
ab39ee45
YK
3263static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3264 int rs)
d4ea6acd
LA
3265{
3266 target_long offset;
3267 target_long addr;
3268
ab39ee45 3269 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
d4ea6acd
LA
3270 case OPC_ADDIUPC:
3271 if (rs != 0) {
3272 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 3273 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3274 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3275 }
3276 break;
3277 case R6_OPC_LWPC:
3278 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 3279 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3280 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3281 break;
3282#if defined(TARGET_MIPS64)
3283 case OPC_LWUPC:
3284 check_mips_64(ctx);
3285 offset = sextract32(ctx->opcode << 2, 0, 21);
ab39ee45 3286 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3287 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3288 break;
3289#endif
3290 default:
ab39ee45 3291 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
d4ea6acd
LA
3292 case OPC_AUIPC:
3293 if (rs != 0) {
ab39ee45
YK
3294 offset = sextract32(ctx->opcode, 0, 16) << 16;
3295 addr = addr_add(ctx, pc, offset);
d4ea6acd
LA
3296 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3297 }
3298 break;
3299 case OPC_ALUIPC:
3300 if (rs != 0) {
ab39ee45
YK
3301 offset = sextract32(ctx->opcode, 0, 16) << 16;
3302 addr = ~0xFFFF & addr_add(ctx, pc, offset);
d4ea6acd
LA
3303 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3304 }
3305 break;
3306#if defined(TARGET_MIPS64)
3307 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3308 case R6_OPC_LDPC + (1 << 16):
3309 case R6_OPC_LDPC + (2 << 16):
3310 case R6_OPC_LDPC + (3 << 16):
3311 check_mips_64(ctx);
3312 offset = sextract32(ctx->opcode << 3, 0, 21);
ab39ee45 3313 addr = addr_add(ctx, (pc & ~0x7), offset);
d4ea6acd
LA
3314 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3315 break;
3316#endif
3317 default:
3318 MIPS_INVAL("OPC_PCREL");
9c708c7f 3319 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
3320 break;
3321 }
3322 break;
3323 }
3324}
3325
b42ee5e1
LA
3326static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3327{
b42ee5e1
LA
3328 TCGv t0, t1;
3329
3330 if (rd == 0) {
3331 /* Treat as NOP. */
b42ee5e1
LA
3332 return;
3333 }
3334
3335 t0 = tcg_temp_new();
3336 t1 = tcg_temp_new();
3337
3338 gen_load_gpr(t0, rs);
3339 gen_load_gpr(t1, rt);
3340
3341 switch (opc) {
3342 case R6_OPC_DIV:
3343 {
3344 TCGv t2 = tcg_temp_new();
3345 TCGv t3 = tcg_temp_new();
3346 tcg_gen_ext32s_tl(t0, t0);
3347 tcg_gen_ext32s_tl(t1, t1);
3348 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3349 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3350 tcg_gen_and_tl(t2, t2, t3);
3351 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3352 tcg_gen_or_tl(t2, t2, t3);
3353 tcg_gen_movi_tl(t3, 0);
3354 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3355 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3356 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3357 tcg_temp_free(t3);
3358 tcg_temp_free(t2);
3359 }
b42ee5e1
LA
3360 break;
3361 case R6_OPC_MOD:
3362 {
3363 TCGv t2 = tcg_temp_new();
3364 TCGv t3 = tcg_temp_new();
3365 tcg_gen_ext32s_tl(t0, t0);
3366 tcg_gen_ext32s_tl(t1, t1);
3367 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3368 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3369 tcg_gen_and_tl(t2, t2, t3);
3370 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3371 tcg_gen_or_tl(t2, t2, t3);
3372 tcg_gen_movi_tl(t3, 0);
3373 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3374 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3375 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3376 tcg_temp_free(t3);
3377 tcg_temp_free(t2);
3378 }
b42ee5e1
LA
3379 break;
3380 case R6_OPC_DIVU:
3381 {
3382 TCGv t2 = tcg_const_tl(0);
3383 TCGv t3 = tcg_const_tl(1);
3384 tcg_gen_ext32u_tl(t0, t0);
3385 tcg_gen_ext32u_tl(t1, t1);
3386 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3387 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3388 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3389 tcg_temp_free(t3);
3390 tcg_temp_free(t2);
3391 }
b42ee5e1
LA
3392 break;
3393 case R6_OPC_MODU:
3394 {
3395 TCGv t2 = tcg_const_tl(0);
3396 TCGv t3 = tcg_const_tl(1);
3397 tcg_gen_ext32u_tl(t0, t0);
3398 tcg_gen_ext32u_tl(t1, t1);
3399 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3400 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3401 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3402 tcg_temp_free(t3);
3403 tcg_temp_free(t2);
3404 }
b42ee5e1
LA
3405 break;
3406 case R6_OPC_MUL:
3407 {
3408 TCGv_i32 t2 = tcg_temp_new_i32();
3409 TCGv_i32 t3 = tcg_temp_new_i32();
3410 tcg_gen_trunc_tl_i32(t2, t0);
3411 tcg_gen_trunc_tl_i32(t3, t1);
3412 tcg_gen_mul_i32(t2, t2, t3);
3413 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3414 tcg_temp_free_i32(t2);
3415 tcg_temp_free_i32(t3);
3416 }
b42ee5e1
LA
3417 break;
3418 case R6_OPC_MUH:
3419 {
3420 TCGv_i32 t2 = tcg_temp_new_i32();
3421 TCGv_i32 t3 = tcg_temp_new_i32();
3422 tcg_gen_trunc_tl_i32(t2, t0);
3423 tcg_gen_trunc_tl_i32(t3, t1);
3424 tcg_gen_muls2_i32(t2, t3, t2, t3);
3425 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3426 tcg_temp_free_i32(t2);
3427 tcg_temp_free_i32(t3);
3428 }
b42ee5e1
LA
3429 break;
3430 case R6_OPC_MULU:
3431 {
3432 TCGv_i32 t2 = tcg_temp_new_i32();
3433 TCGv_i32 t3 = tcg_temp_new_i32();
3434 tcg_gen_trunc_tl_i32(t2, t0);
3435 tcg_gen_trunc_tl_i32(t3, t1);
3436 tcg_gen_mul_i32(t2, t2, t3);
3437 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3438 tcg_temp_free_i32(t2);
3439 tcg_temp_free_i32(t3);
3440 }
b42ee5e1
LA
3441 break;
3442 case R6_OPC_MUHU:
3443 {
3444 TCGv_i32 t2 = tcg_temp_new_i32();
3445 TCGv_i32 t3 = tcg_temp_new_i32();
3446 tcg_gen_trunc_tl_i32(t2, t0);
3447 tcg_gen_trunc_tl_i32(t3, t1);
3448 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3449 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3450 tcg_temp_free_i32(t2);
3451 tcg_temp_free_i32(t3);
3452 }
b42ee5e1
LA
3453 break;
3454#if defined(TARGET_MIPS64)
3455 case R6_OPC_DDIV:
3456 {
3457 TCGv t2 = tcg_temp_new();
3458 TCGv t3 = tcg_temp_new();
3459 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3460 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3461 tcg_gen_and_tl(t2, t2, t3);
3462 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3463 tcg_gen_or_tl(t2, t2, t3);
3464 tcg_gen_movi_tl(t3, 0);
3465 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3466 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3467 tcg_temp_free(t3);
3468 tcg_temp_free(t2);
3469 }
b42ee5e1
LA
3470 break;
3471 case R6_OPC_DMOD:
3472 {
3473 TCGv t2 = tcg_temp_new();
3474 TCGv t3 = tcg_temp_new();
3475 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3476 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3477 tcg_gen_and_tl(t2, t2, t3);
3478 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3479 tcg_gen_or_tl(t2, t2, t3);
3480 tcg_gen_movi_tl(t3, 0);
3481 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3482 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3483 tcg_temp_free(t3);
3484 tcg_temp_free(t2);
3485 }
b42ee5e1
LA
3486 break;
3487 case R6_OPC_DDIVU:
3488 {
3489 TCGv t2 = tcg_const_tl(0);
3490 TCGv t3 = tcg_const_tl(1);
3491 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3492 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3493 tcg_temp_free(t3);
3494 tcg_temp_free(t2);
3495 }
b42ee5e1
LA
3496 break;
3497 case R6_OPC_DMODU:
3498 {
3499 TCGv t2 = tcg_const_tl(0);
3500 TCGv t3 = tcg_const_tl(1);
3501 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3502 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3503 tcg_temp_free(t3);
3504 tcg_temp_free(t2);
3505 }
b42ee5e1
LA
3506 break;
3507 case R6_OPC_DMUL:
3508 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
3509 break;
3510 case R6_OPC_DMUH:
3511 {
3512 TCGv t2 = tcg_temp_new();
3513 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3514 tcg_temp_free(t2);
3515 }
b42ee5e1
LA
3516 break;
3517 case R6_OPC_DMULU:
3518 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
b42ee5e1
LA
3519 break;
3520 case R6_OPC_DMUHU:
3521 {
3522 TCGv t2 = tcg_temp_new();
3523 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3524 tcg_temp_free(t2);
3525 }
b42ee5e1
LA
3526 break;
3527#endif
3528 default:
9d68ac14 3529 MIPS_INVAL("r6 mul/div");
9c708c7f 3530 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
3531 goto out;
3532 }
b42ee5e1
LA
3533 out:
3534 tcg_temp_free(t0);
3535 tcg_temp_free(t1);
3536}
3537
26135ead
RS
3538static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3539 int acc, int rs, int rt)
6af0bf9c 3540{
d45f89f4
AJ
3541 TCGv t0, t1;
3542
51127181
AJ
3543 t0 = tcg_temp_new();
3544 t1 = tcg_temp_new();
6af0bf9c 3545
78723684
TS
3546 gen_load_gpr(t0, rs);
3547 gen_load_gpr(t1, rt);
51127181 3548
26135ead
RS
3549 if (acc != 0) {
3550 check_dsp(ctx);
3551 }
3552
6af0bf9c
FB
3553 switch (opc) {
3554 case OPC_DIV:
48d38ca5 3555 {
51127181
AJ
3556 TCGv t2 = tcg_temp_new();
3557 TCGv t3 = tcg_temp_new();
d45f89f4
AJ
3558 tcg_gen_ext32s_tl(t0, t0);
3559 tcg_gen_ext32s_tl(t1, t1);
51127181
AJ
3560 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3561 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3562 tcg_gen_and_tl(t2, t2, t3);
3563 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3564 tcg_gen_or_tl(t2, t2, t3);
3565 tcg_gen_movi_tl(t3, 0);
3566 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
3567 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3568 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3569 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3570 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
3571 tcg_temp_free(t3);
3572 tcg_temp_free(t2);
48d38ca5 3573 }
6af0bf9c
FB
3574 break;
3575 case OPC_DIVU:
48d38ca5 3576 {
51127181
AJ
3577 TCGv t2 = tcg_const_tl(0);
3578 TCGv t3 = tcg_const_tl(1);
0c0ed03b
AJ
3579 tcg_gen_ext32u_tl(t0, t0);
3580 tcg_gen_ext32u_tl(t1, t1);
51127181 3581 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
3582 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3583 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3584 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3585 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
51127181
AJ
3586 tcg_temp_free(t3);
3587 tcg_temp_free(t2);
48d38ca5 3588 }
6af0bf9c
FB
3589 break;
3590 case OPC_MULT:
214c465f 3591 {
ce1dd5d1
RH
3592 TCGv_i32 t2 = tcg_temp_new_i32();
3593 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
3594 tcg_gen_trunc_tl_i32(t2, t0);
3595 tcg_gen_trunc_tl_i32(t3, t1);
3596 tcg_gen_muls2_i32(t2, t3, t2, t3);
3597 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3598 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3599 tcg_temp_free_i32(t2);
3600 tcg_temp_free_i32(t3);
214c465f 3601 }
6af0bf9c
FB
3602 break;
3603 case OPC_MULTU:
214c465f 3604 {
ce1dd5d1
RH
3605 TCGv_i32 t2 = tcg_temp_new_i32();
3606 TCGv_i32 t3 = tcg_temp_new_i32();
ce1dd5d1
RH
3607 tcg_gen_trunc_tl_i32(t2, t0);
3608 tcg_gen_trunc_tl_i32(t3, t1);
3609 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3610 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3611 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3612 tcg_temp_free_i32(t2);
3613 tcg_temp_free_i32(t3);
214c465f 3614 }
6af0bf9c 3615 break;
d26bc211 3616#if defined(TARGET_MIPS64)
7a387fff 3617 case OPC_DDIV:
48d38ca5 3618 {
51127181
AJ
3619 TCGv t2 = tcg_temp_new();
3620 TCGv t3 = tcg_temp_new();
3621 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3622 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3623 tcg_gen_and_tl(t2, t2, t3);
3624 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3625 tcg_gen_or_tl(t2, t2, t3);
3626 tcg_gen_movi_tl(t3, 0);
3627 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
26135ead
RS
3628 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3629 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
51127181
AJ
3630 tcg_temp_free(t3);
3631 tcg_temp_free(t2);
48d38ca5 3632 }
7a387fff
TS
3633 break;
3634 case OPC_DDIVU:
48d38ca5 3635 {
51127181
AJ
3636 TCGv t2 = tcg_const_tl(0);
3637 TCGv t3 = tcg_const_tl(1);
3638 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
26135ead
RS
3639 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3640 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
51127181
AJ
3641 tcg_temp_free(t3);
3642 tcg_temp_free(t2);
48d38ca5 3643 }
7a387fff
TS
3644 break;
3645 case OPC_DMULT:
26135ead 3646 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
3647 break;
3648 case OPC_DMULTU:
26135ead 3649 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
7a387fff
TS
3650 break;
3651#endif
6af0bf9c 3652 case OPC_MADD:
214c465f 3653 {
d45f89f4
AJ
3654 TCGv_i64 t2 = tcg_temp_new_i64();
3655 TCGv_i64 t3 = tcg_temp_new_i64();
3656
3657 tcg_gen_ext_tl_i64(t2, t0);
3658 tcg_gen_ext_tl_i64(t3, t1);
3659 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3660 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
3661 tcg_gen_add_i64(t2, t2, t3);
3662 tcg_temp_free_i64(t3);
71f303cd
RH
3663 gen_move_low32(cpu_LO[acc], t2);
3664 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 3665 tcg_temp_free_i64(t2);
214c465f 3666 }
6af0bf9c
FB
3667 break;
3668 case OPC_MADDU:
4133498f 3669 {
d45f89f4
AJ
3670 TCGv_i64 t2 = tcg_temp_new_i64();
3671 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 3672
78723684
TS
3673 tcg_gen_ext32u_tl(t0, t0);
3674 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
3675 tcg_gen_extu_tl_i64(t2, t0);
3676 tcg_gen_extu_tl_i64(t3, t1);
3677 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3678 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
d45f89f4
AJ
3679 tcg_gen_add_i64(t2, t2, t3);
3680 tcg_temp_free_i64(t3);
71f303cd
RH
3681 gen_move_low32(cpu_LO[acc], t2);
3682 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 3683 tcg_temp_free_i64(t2);
214c465f 3684 }
6af0bf9c
FB
3685 break;
3686 case OPC_MSUB:
214c465f 3687 {
d45f89f4
AJ
3688 TCGv_i64 t2 = tcg_temp_new_i64();
3689 TCGv_i64 t3 = tcg_temp_new_i64();
3690
3691 tcg_gen_ext_tl_i64(t2, t0);
3692 tcg_gen_ext_tl_i64(t3, t1);
3693 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3694 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 3695 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 3696 tcg_temp_free_i64(t3);
71f303cd
RH
3697 gen_move_low32(cpu_LO[acc], t2);
3698 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 3699 tcg_temp_free_i64(t2);
214c465f 3700 }
6af0bf9c
FB
3701 break;
3702 case OPC_MSUBU:
214c465f 3703 {
d45f89f4
AJ
3704 TCGv_i64 t2 = tcg_temp_new_i64();
3705 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 3706
78723684
TS
3707 tcg_gen_ext32u_tl(t0, t0);
3708 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
3709 tcg_gen_extu_tl_i64(t2, t0);
3710 tcg_gen_extu_tl_i64(t3, t1);
3711 tcg_gen_mul_i64(t2, t2, t3);
4133498f 3712 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
98070ce0 3713 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4 3714 tcg_temp_free_i64(t3);
71f303cd
RH
3715 gen_move_low32(cpu_LO[acc], t2);
3716 gen_move_high32(cpu_HI[acc], t2);
d45f89f4 3717 tcg_temp_free_i64(t2);
214c465f 3718 }
6af0bf9c
FB
3719 break;
3720 default:
9d68ac14 3721 MIPS_INVAL("mul/div");
9c708c7f 3722 generate_exception_end(ctx, EXCP_RI);
78723684 3723 goto out;
6af0bf9c 3724 }
78723684
TS
3725 out:
3726 tcg_temp_free(t0);
3727 tcg_temp_free(t1);
6af0bf9c
FB
3728}
3729
e9c71dd1
TS
3730static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3731 int rd, int rs, int rt)
3732{
f157bfe1
AJ
3733 TCGv t0 = tcg_temp_new();
3734 TCGv t1 = tcg_temp_new();
e9c71dd1 3735
6c5c1e20
TS
3736 gen_load_gpr(t0, rs);
3737 gen_load_gpr(t1, rt);
e9c71dd1
TS
3738
3739 switch (opc) {
3740 case OPC_VR54XX_MULS:
895c2d04 3741 gen_helper_muls(t0, cpu_env, t0, t1);
6958549d 3742 break;
e9c71dd1 3743 case OPC_VR54XX_MULSU:
895c2d04 3744 gen_helper_mulsu(t0, cpu_env, t0, t1);
6958549d 3745 break;
e9c71dd1 3746 case OPC_VR54XX_MACC:
895c2d04 3747 gen_helper_macc(t0, cpu_env, t0, t1);
6958549d 3748 break;
e9c71dd1 3749 case OPC_VR54XX_MACCU:
895c2d04 3750 gen_helper_maccu(t0, cpu_env, t0, t1);
6958549d 3751 break;
e9c71dd1 3752 case OPC_VR54XX_MSAC:
895c2d04 3753 gen_helper_msac(t0, cpu_env, t0, t1);
6958549d 3754 break;
e9c71dd1 3755 case OPC_VR54XX_MSACU:
895c2d04 3756 gen_helper_msacu(t0, cpu_env, t0, t1);
6958549d 3757 break;
e9c71dd1 3758 case OPC_VR54XX_MULHI:
895c2d04 3759 gen_helper_mulhi(t0, cpu_env, t0, t1);
6958549d 3760 break;
e9c71dd1 3761 case OPC_VR54XX_MULHIU:
895c2d04 3762 gen_helper_mulhiu(t0, cpu_env, t0, t1);
6958549d 3763 break;
e9c71dd1 3764 case OPC_VR54XX_MULSHI:
895c2d04 3765 gen_helper_mulshi(t0, cpu_env, t0, t1);
6958549d 3766 break;
e9c71dd1 3767 case OPC_VR54XX_MULSHIU:
895c2d04 3768 gen_helper_mulshiu(t0, cpu_env, t0, t1);
6958549d 3769 break;
e9c71dd1 3770 case OPC_VR54XX_MACCHI:
895c2d04 3771 gen_helper_macchi(t0, cpu_env, t0, t1);
6958549d 3772 break;
e9c71dd1 3773 case OPC_VR54XX_MACCHIU:
895c2d04 3774 gen_helper_macchiu(t0, cpu_env, t0, t1);
6958549d 3775 break;
e9c71dd1 3776 case OPC_VR54XX_MSACHI:
895c2d04 3777 gen_helper_msachi(t0, cpu_env, t0, t1);
6958549d 3778 break;
e9c71dd1 3779 case OPC_VR54XX_MSACHIU:
895c2d04 3780 gen_helper_msachiu(t0, cpu_env, t0, t1);
6958549d 3781 break;
e9c71dd1
TS
3782 default:
3783 MIPS_INVAL("mul vr54xx");
9c708c7f 3784 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 3785 goto out;
e9c71dd1 3786 }
6c5c1e20 3787 gen_store_gpr(t0, rd);
6c5c1e20
TS
3788
3789 out:
3790 tcg_temp_free(t0);
3791 tcg_temp_free(t1);
e9c71dd1
TS
3792}
3793
7a387fff 3794static void gen_cl (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
3795 int rd, int rs)
3796{
20e1fb52 3797 TCGv t0;
6c5c1e20 3798
6af0bf9c 3799 if (rd == 0) {
ead9360e 3800 /* Treat as NOP. */
20e1fb52 3801 return;
6af0bf9c 3802 }
1a0196c5 3803 t0 = cpu_gpr[rd];
6c5c1e20 3804 gen_load_gpr(t0, rs);
1a0196c5 3805
6af0bf9c
FB
3806 switch (opc) {
3807 case OPC_CLO:
4267d3e6 3808 case R6_OPC_CLO:
1a0196c5
RH
3809#if defined(TARGET_MIPS64)
3810 case OPC_DCLO:
3811 case R6_OPC_DCLO:
3812#endif
3813 tcg_gen_not_tl(t0, t0);
6af0bf9c 3814 break;
1a0196c5
RH
3815 }
3816
3817 switch (opc) {
3818 case OPC_CLO:
3819 case R6_OPC_CLO:
6af0bf9c 3820 case OPC_CLZ:
4267d3e6 3821 case R6_OPC_CLZ:
1a0196c5
RH
3822 tcg_gen_ext32u_tl(t0, t0);
3823 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3824 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
6af0bf9c 3825 break;
d26bc211 3826#if defined(TARGET_MIPS64)
7a387fff 3827 case OPC_DCLO:
4267d3e6 3828 case R6_OPC_DCLO:
7a387fff 3829 case OPC_DCLZ:
4267d3e6 3830 case R6_OPC_DCLZ:
1a0196c5 3831 tcg_gen_clzi_i64(t0, t0, 64);
7a387fff
TS
3832 break;
3833#endif
6af0bf9c 3834 }
6af0bf9c
FB
3835}
3836
161f85e6 3837/* Godson integer instructions */
bd277fa1
RH
3838static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3839 int rd, int rs, int rt)
161f85e6 3840{
161f85e6
AJ
3841 TCGv t0, t1;
3842
3843 if (rd == 0) {
3844 /* Treat as NOP. */
161f85e6
AJ
3845 return;
3846 }
3847
3848 switch (opc) {
3849 case OPC_MULT_G_2E:
3850 case OPC_MULT_G_2F:
3851 case OPC_MULTU_G_2E:
3852 case OPC_MULTU_G_2F:
3853#if defined(TARGET_MIPS64)
3854 case OPC_DMULT_G_2E:
3855 case OPC_DMULT_G_2F:
3856 case OPC_DMULTU_G_2E:
3857 case OPC_DMULTU_G_2F:
3858#endif
3859 t0 = tcg_temp_new();
3860 t1 = tcg_temp_new();
3861 break;
3862 default:
3863 t0 = tcg_temp_local_new();
3864 t1 = tcg_temp_local_new();
3865 break;
3866 }
3867
3868 gen_load_gpr(t0, rs);
3869 gen_load_gpr(t1, rt);
3870
3871 switch (opc) {
3872 case OPC_MULT_G_2E:
3873 case OPC_MULT_G_2F:
3874 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3875 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
3876 break;
3877 case OPC_MULTU_G_2E:
3878 case OPC_MULTU_G_2F:
3879 tcg_gen_ext32u_tl(t0, t0);
3880 tcg_gen_ext32u_tl(t1, t1);
3881 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3882 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
161f85e6
AJ
3883 break;
3884 case OPC_DIV_G_2E:
3885 case OPC_DIV_G_2F:
3886 {
42a268c2
RH
3887 TCGLabel *l1 = gen_new_label();
3888 TCGLabel *l2 = gen_new_label();
3889 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
3890 tcg_gen_ext32s_tl(t0, t0);
3891 tcg_gen_ext32s_tl(t1, t1);
3892 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3893 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3894 tcg_gen_br(l3);
3895 gen_set_label(l1);
3896 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3897 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3898 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3899 tcg_gen_br(l3);
3900 gen_set_label(l2);
3901 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3902 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3903 gen_set_label(l3);
3904 }
161f85e6
AJ
3905 break;
3906 case OPC_DIVU_G_2E:
3907 case OPC_DIVU_G_2F:
3908 {
42a268c2
RH
3909 TCGLabel *l1 = gen_new_label();
3910 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
3911 tcg_gen_ext32u_tl(t0, t0);
3912 tcg_gen_ext32u_tl(t1, t1);
3913 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3914 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3915 tcg_gen_br(l2);
3916 gen_set_label(l1);
3917 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3918 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3919 gen_set_label(l2);
3920 }
161f85e6
AJ
3921 break;
3922 case OPC_MOD_G_2E:
3923 case OPC_MOD_G_2F:
3924 {
42a268c2
RH
3925 TCGLabel *l1 = gen_new_label();
3926 TCGLabel *l2 = gen_new_label();
3927 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
3928 tcg_gen_ext32u_tl(t0, t0);
3929 tcg_gen_ext32u_tl(t1, t1);
3930 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3931 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3932 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3933 gen_set_label(l1);
3934 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3935 tcg_gen_br(l3);
3936 gen_set_label(l2);
3937 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3938 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3939 gen_set_label(l3);
3940 }
161f85e6
AJ
3941 break;
3942 case OPC_MODU_G_2E:
3943 case OPC_MODU_G_2F:
3944 {
42a268c2
RH
3945 TCGLabel *l1 = gen_new_label();
3946 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
3947 tcg_gen_ext32u_tl(t0, t0);
3948 tcg_gen_ext32u_tl(t1, t1);
3949 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3950 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3951 tcg_gen_br(l2);
3952 gen_set_label(l1);
3953 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3954 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3955 gen_set_label(l2);
3956 }
161f85e6
AJ
3957 break;
3958#if defined(TARGET_MIPS64)
3959 case OPC_DMULT_G_2E:
3960 case OPC_DMULT_G_2F:
3961 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
3962 break;
3963 case OPC_DMULTU_G_2E:
3964 case OPC_DMULTU_G_2F:
3965 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
161f85e6
AJ
3966 break;
3967 case OPC_DDIV_G_2E:
3968 case OPC_DDIV_G_2F:
3969 {
42a268c2
RH
3970 TCGLabel *l1 = gen_new_label();
3971 TCGLabel *l2 = gen_new_label();
3972 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
3973 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3974 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3975 tcg_gen_br(l3);
3976 gen_set_label(l1);
3977 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3978 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3979 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3980 tcg_gen_br(l3);
3981 gen_set_label(l2);
3982 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3983 gen_set_label(l3);
3984 }
161f85e6
AJ
3985 break;
3986 case OPC_DDIVU_G_2E:
3987 case OPC_DDIVU_G_2F:
3988 {
42a268c2
RH
3989 TCGLabel *l1 = gen_new_label();
3990 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
3991 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3992 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3993 tcg_gen_br(l2);
3994 gen_set_label(l1);
3995 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3996 gen_set_label(l2);
3997 }
161f85e6
AJ
3998 break;
3999 case OPC_DMOD_G_2E:
4000 case OPC_DMOD_G_2F:
4001 {
42a268c2
RH
4002 TCGLabel *l1 = gen_new_label();
4003 TCGLabel *l2 = gen_new_label();
4004 TCGLabel *l3 = gen_new_label();
161f85e6
AJ
4005 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4006 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4007 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4008 gen_set_label(l1);
4009 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4010 tcg_gen_br(l3);
4011 gen_set_label(l2);
4012 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4013 gen_set_label(l3);
4014 }
161f85e6
AJ
4015 break;
4016 case OPC_DMODU_G_2E:
4017 case OPC_DMODU_G_2F:
4018 {
42a268c2
RH
4019 TCGLabel *l1 = gen_new_label();
4020 TCGLabel *l2 = gen_new_label();
161f85e6
AJ
4021 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4022 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4023 tcg_gen_br(l2);
4024 gen_set_label(l1);
4025 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4026 gen_set_label(l2);
4027 }
161f85e6
AJ
4028 break;
4029#endif
4030 }
4031
161f85e6
AJ
4032 tcg_temp_free(t0);
4033 tcg_temp_free(t1);
4034}
4035
bd277fa1
RH
4036/* Loongson multimedia instructions */
4037static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4038{
bd277fa1
RH
4039 uint32_t opc, shift_max;
4040 TCGv_i64 t0, t1;
4041
4042 opc = MASK_LMI(ctx->opcode);
4043 switch (opc) {
4044 case OPC_ADD_CP2:
4045 case OPC_SUB_CP2:
4046 case OPC_DADD_CP2:
4047 case OPC_DSUB_CP2:
4048 t0 = tcg_temp_local_new_i64();
4049 t1 = tcg_temp_local_new_i64();
4050 break;
4051 default:
4052 t0 = tcg_temp_new_i64();
4053 t1 = tcg_temp_new_i64();
4054 break;
4055 }
4056
b5a587b6 4057 check_cp1_enabled(ctx);
bd277fa1
RH
4058 gen_load_fpr64(ctx, t0, rs);
4059 gen_load_fpr64(ctx, t1, rt);
4060
4061#define LMI_HELPER(UP, LO) \
9d68ac14 4062 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
bd277fa1 4063#define LMI_HELPER_1(UP, LO) \
9d68ac14 4064 case OPC_##UP: gen_helper_##LO(t0, t0); break
bd277fa1 4065#define LMI_DIRECT(UP, LO, OP) \
9d68ac14 4066 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
bd277fa1
RH
4067
4068 switch (opc) {
4069 LMI_HELPER(PADDSH, paddsh);
4070 LMI_HELPER(PADDUSH, paddush);
4071 LMI_HELPER(PADDH, paddh);
4072 LMI_HELPER(PADDW, paddw);
4073 LMI_HELPER(PADDSB, paddsb);
4074 LMI_HELPER(PADDUSB, paddusb);
4075 LMI_HELPER(PADDB, paddb);
4076
4077 LMI_HELPER(PSUBSH, psubsh);
4078 LMI_HELPER(PSUBUSH, psubush);
4079 LMI_HELPER(PSUBH, psubh);
4080 LMI_HELPER(PSUBW, psubw);
4081 LMI_HELPER(PSUBSB, psubsb);
4082 LMI_HELPER(PSUBUSB, psubusb);
4083 LMI_HELPER(PSUBB, psubb);
4084
4085 LMI_HELPER(PSHUFH, pshufh);
4086 LMI_HELPER(PACKSSWH, packsswh);
4087 LMI_HELPER(PACKSSHB, packsshb);
4088 LMI_HELPER(PACKUSHB, packushb);
4089
4090 LMI_HELPER(PUNPCKLHW, punpcklhw);
4091 LMI_HELPER(PUNPCKHHW, punpckhhw);
4092 LMI_HELPER(PUNPCKLBH, punpcklbh);
4093 LMI_HELPER(PUNPCKHBH, punpckhbh);
4094 LMI_HELPER(PUNPCKLWD, punpcklwd);
4095 LMI_HELPER(PUNPCKHWD, punpckhwd);
4096
4097 LMI_HELPER(PAVGH, pavgh);
4098 LMI_HELPER(PAVGB, pavgb);
4099 LMI_HELPER(PMAXSH, pmaxsh);
4100 LMI_HELPER(PMINSH, pminsh);
4101 LMI_HELPER(PMAXUB, pmaxub);
4102 LMI_HELPER(PMINUB, pminub);
4103
4104 LMI_HELPER(PCMPEQW, pcmpeqw);
4105 LMI_HELPER(PCMPGTW, pcmpgtw);
4106 LMI_HELPER(PCMPEQH, pcmpeqh);
4107 LMI_HELPER(PCMPGTH, pcmpgth);
4108 LMI_HELPER(PCMPEQB, pcmpeqb);
4109 LMI_HELPER(PCMPGTB, pcmpgtb);
4110
4111 LMI_HELPER(PSLLW, psllw);
4112 LMI_HELPER(PSLLH, psllh);
4113 LMI_HELPER(PSRLW, psrlw);
4114 LMI_HELPER(PSRLH, psrlh);
4115 LMI_HELPER(PSRAW, psraw);
4116 LMI_HELPER(PSRAH, psrah);
4117
4118 LMI_HELPER(PMULLH, pmullh);
4119 LMI_HELPER(PMULHH, pmulhh);
4120 LMI_HELPER(PMULHUH, pmulhuh);
4121 LMI_HELPER(PMADDHW, pmaddhw);
4122
4123 LMI_HELPER(PASUBUB, pasubub);
4124 LMI_HELPER_1(BIADD, biadd);
4125 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4126
4127 LMI_DIRECT(PADDD, paddd, add);
4128 LMI_DIRECT(PSUBD, psubd, sub);
4129 LMI_DIRECT(XOR_CP2, xor, xor);
4130 LMI_DIRECT(NOR_CP2, nor, nor);
4131 LMI_DIRECT(AND_CP2, and, and);
bb7cab5f 4132 LMI_DIRECT(OR_CP2, or, or);
bd277fa1 4133
9099a36b
H
4134 case OPC_PANDN:
4135 tcg_gen_andc_i64(t0, t1, t0);
4136 break;
4137
bd277fa1
RH
4138 case OPC_PINSRH_0:
4139 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
bd277fa1
RH
4140 break;
4141 case OPC_PINSRH_1:
4142 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
bd277fa1
RH
4143 break;
4144 case OPC_PINSRH_2:
4145 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
bd277fa1
RH
4146 break;
4147 case OPC_PINSRH_3:
4148 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
bd277fa1
RH
4149 break;
4150
4151 case OPC_PEXTRH:
4152 tcg_gen_andi_i64(t1, t1, 3);
4153 tcg_gen_shli_i64(t1, t1, 4);
4154 tcg_gen_shr_i64(t0, t0, t1);
4155 tcg_gen_ext16u_i64(t0, t0);
bd277fa1
RH
4156 break;
4157
4158 case OPC_ADDU_CP2:
4159 tcg_gen_add_i64(t0, t0, t1);
4160 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
4161 break;
4162 case OPC_SUBU_CP2:
4163 tcg_gen_sub_i64(t0, t0, t1);
4164 tcg_gen_ext32s_i64(t0, t0);
bd277fa1
RH
4165 break;
4166
4167 case OPC_SLL_CP2:
bd277fa1
RH
4168 shift_max = 32;
4169 goto do_shift;
4170 case OPC_SRL_CP2:
bd277fa1
RH
4171 shift_max = 32;
4172 goto do_shift;
4173 case OPC_SRA_CP2:
bd277fa1
RH
4174 shift_max = 32;
4175 goto do_shift;
4176 case OPC_DSLL_CP2:
bd277fa1
RH
4177 shift_max = 64;
4178 goto do_shift;
4179 case OPC_DSRL_CP2:
bd277fa1
RH
4180 shift_max = 64;
4181 goto do_shift;
4182 case OPC_DSRA_CP2:
bd277fa1
RH
4183 shift_max = 64;
4184 goto do_shift;
4185 do_shift:
4186 /* Make sure shift count isn't TCG undefined behaviour. */
4187 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4188
4189 switch (opc) {
4190 case OPC_SLL_CP2:
4191 case OPC_DSLL_CP2:
4192 tcg_gen_shl_i64(t0, t0, t1);
4193 break;
4194 case OPC_SRA_CP2:
4195 case OPC_DSRA_CP2:
4196 /* Since SRA is UndefinedResult without sign-extended inputs,
4197 we can treat SRA and DSRA the same. */
4198 tcg_gen_sar_i64(t0, t0, t1);
4199 break;
4200 case OPC_SRL_CP2:
4201 /* We want to shift in zeros for SRL; zero-extend first. */
4202 tcg_gen_ext32u_i64(t0, t0);
4203 /* FALLTHRU */
4204 case OPC_DSRL_CP2:
4205 tcg_gen_shr_i64(t0, t0, t1);
4206 break;
4207 }
4208
4209 if (shift_max == 32) {
4210 tcg_gen_ext32s_i64(t0, t0);
4211 }
4212
4213 /* Shifts larger than MAX produce zero. */
4214 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4215 tcg_gen_neg_i64(t1, t1);
4216 tcg_gen_and_i64(t0, t0, t1);
4217 break;
4218
4219 case OPC_ADD_CP2:
4220 case OPC_DADD_CP2:
4221 {
4222 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 4223 TCGLabel *lab = gen_new_label();
bd277fa1
RH
4224
4225 tcg_gen_mov_i64(t2, t0);
4226 tcg_gen_add_i64(t0, t1, t2);
4227 if (opc == OPC_ADD_CP2) {
4228 tcg_gen_ext32s_i64(t0, t0);
4229 }
4230 tcg_gen_xor_i64(t1, t1, t2);
4231 tcg_gen_xor_i64(t2, t2, t0);
4232 tcg_gen_andc_i64(t1, t2, t1);
4233 tcg_temp_free_i64(t2);
4234 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4235 generate_exception(ctx, EXCP_OVERFLOW);
4236 gen_set_label(lab);
bd277fa1
RH
4237 break;
4238 }
4239
4240 case OPC_SUB_CP2:
4241 case OPC_DSUB_CP2:
4242 {
4243 TCGv_i64 t2 = tcg_temp_new_i64();
42a268c2 4244 TCGLabel *lab = gen_new_label();
bd277fa1
RH
4245
4246 tcg_gen_mov_i64(t2, t0);
4247 tcg_gen_sub_i64(t0, t1, t2);
4248 if (opc == OPC_SUB_CP2) {
4249 tcg_gen_ext32s_i64(t0, t0);
4250 }
4251 tcg_gen_xor_i64(t1, t1, t2);
4252 tcg_gen_xor_i64(t2, t2, t0);
4253 tcg_gen_and_i64(t1, t1, t2);
4254 tcg_temp_free_i64(t2);
4255 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4256 generate_exception(ctx, EXCP_OVERFLOW);
4257 gen_set_label(lab);
bd277fa1
RH
4258 break;
4259 }
4260
4261 case OPC_PMULUW:
4262 tcg_gen_ext32u_i64(t0, t0);
4263 tcg_gen_ext32u_i64(t1, t1);
4264 tcg_gen_mul_i64(t0, t0, t1);
bd277fa1
RH
4265 break;
4266
4267 case OPC_SEQU_CP2:
4268 case OPC_SEQ_CP2:
4269 case OPC_SLTU_CP2:
4270 case OPC_SLT_CP2:
4271 case OPC_SLEU_CP2:
4272 case OPC_SLE_CP2:
4273 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4274 FD field is the CC field? */
4275 default:
9d68ac14 4276 MIPS_INVAL("loongson_cp2");
9c708c7f 4277 generate_exception_end(ctx, EXCP_RI);
bd277fa1
RH
4278 return;
4279 }
4280
4281#undef LMI_HELPER
4282#undef LMI_DIRECT
4283
4284 gen_store_fpr64(ctx, t0, rd);
4285
bd277fa1
RH
4286 tcg_temp_free_i64(t0);
4287 tcg_temp_free_i64(t1);
4288}
4289
6af0bf9c 4290/* Traps */
7a387fff 4291static void gen_trap (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
4292 int rs, int rt, int16_t imm)
4293{
4294 int cond;
cdc0faa6 4295 TCGv t0 = tcg_temp_new();
1ba74fb8 4296 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
4297
4298 cond = 0;
4299 /* Load needed operands */
4300 switch (opc) {
4301 case OPC_TEQ:
4302 case OPC_TGE:
4303 case OPC_TGEU:
4304 case OPC_TLT:
4305 case OPC_TLTU:
4306 case OPC_TNE:
4307 /* Compare two registers */
4308 if (rs != rt) {
be24bb4f
TS
4309 gen_load_gpr(t0, rs);
4310 gen_load_gpr(t1, rt);
6af0bf9c
FB
4311 cond = 1;
4312 }
179e32bb 4313 break;
6af0bf9c
FB
4314 case OPC_TEQI:
4315 case OPC_TGEI:
4316 case OPC_TGEIU:
4317 case OPC_TLTI:
4318 case OPC_TLTIU:
4319 case OPC_TNEI:
4320 /* Compare register to immediate */
4321 if (rs != 0 || imm != 0) {
be24bb4f
TS
4322 gen_load_gpr(t0, rs);
4323 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
4324 cond = 1;
4325 }
4326 break;
4327 }
4328 if (cond == 0) {
4329 switch (opc) {
4330 case OPC_TEQ: /* rs == rs */
4331 case OPC_TEQI: /* r0 == 0 */
4332 case OPC_TGE: /* rs >= rs */
4333 case OPC_TGEI: /* r0 >= 0 */
4334 case OPC_TGEU: /* rs >= rs unsigned */
4335 case OPC_TGEIU: /* r0 >= 0 unsigned */
4336 /* Always trap */
9c708c7f 4337 generate_exception_end(ctx, EXCP_TRAP);
6af0bf9c
FB
4338 break;
4339 case OPC_TLT: /* rs < rs */
4340 case OPC_TLTI: /* r0 < 0 */
4341 case OPC_TLTU: /* rs < rs unsigned */
4342 case OPC_TLTIU: /* r0 < 0 unsigned */
4343 case OPC_TNE: /* rs != rs */
4344 case OPC_TNEI: /* r0 != 0 */
ead9360e 4345 /* Never trap: treat as NOP. */
cdc0faa6 4346 break;
6af0bf9c
FB
4347 }
4348 } else {
42a268c2 4349 TCGLabel *l1 = gen_new_label();
cdc0faa6 4350
6af0bf9c
FB
4351 switch (opc) {
4352 case OPC_TEQ:
4353 case OPC_TEQI:
cdc0faa6 4354 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
4355 break;
4356 case OPC_TGE:
4357 case OPC_TGEI:
cdc0faa6 4358 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
4359 break;
4360 case OPC_TGEU:
4361 case OPC_TGEIU:
cdc0faa6 4362 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
4363 break;
4364 case OPC_TLT:
4365 case OPC_TLTI:
cdc0faa6 4366 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
4367 break;
4368 case OPC_TLTU:
4369 case OPC_TLTIU:
cdc0faa6 4370 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
4371 break;
4372 case OPC_TNE:
4373 case OPC_TNEI:
cdc0faa6 4374 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 4375 break;
6af0bf9c 4376 }
cdc0faa6 4377 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
4378 gen_set_label(l1);
4379 }
be24bb4f
TS
4380 tcg_temp_free(t0);
4381 tcg_temp_free(t1);
6af0bf9c
FB
4382}
4383
90aa39a1
SF
4384static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
4385{
eeb3bba8 4386 if (unlikely(ctx->base.singlestep_enabled)) {
90aa39a1
SF
4387 return false;
4388 }
4389
4390#ifndef CONFIG_USER_ONLY
eeb3bba8 4391 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
90aa39a1
SF
4392#else
4393 return true;
4394#endif
4395}
4396
356265ae 4397static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 4398{
90aa39a1 4399 if (use_goto_tb(ctx, dest)) {
57fec1fe 4400 tcg_gen_goto_tb(n);
9b9e4393 4401 gen_save_pc(dest);
07ea28b4 4402 tcg_gen_exit_tb(ctx->base.tb, n);
6e256c93 4403 } else {
9b9e4393 4404 gen_save_pc(dest);
eeb3bba8 4405 if (ctx->base.singlestep_enabled) {
7b270ef2 4406 save_cpu_state(ctx, 0);
9c708c7f 4407 gen_helper_raise_exception_debug(cpu_env);
7b270ef2 4408 }
7f11636d 4409 tcg_gen_lookup_and_goto_ptr();
6e256c93 4410 }
c53be334
FB
4411}
4412
6af0bf9c 4413/* Branches (before delay slot) */
7a387fff 4414static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
7dca4ad0 4415 int insn_bytes,
b231c103
YK
4416 int rs, int rt, int32_t offset,
4417 int delayslot_size)
6af0bf9c 4418{
d077b6f7 4419 target_ulong btgt = -1;
3ad4bb2d 4420 int blink = 0;
2fdbad25 4421 int bcond_compute = 0;
1ba74fb8
AJ
4422 TCGv t0 = tcg_temp_new();
4423 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
4424
4425 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 4426#ifdef MIPS_DEBUG_DISAS
339cd2a8 4427 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
eeb3bba8 4428 TARGET_FMT_lx "\n", ctx->base.pc_next);
923617a3 4429#endif
9c708c7f 4430 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 4431 goto out;
3ad4bb2d 4432 }
6af0bf9c 4433
6af0bf9c
FB
4434 /* Load needed operands */
4435 switch (opc) {
4436 case OPC_BEQ:
4437 case OPC_BEQL:
4438 case OPC_BNE:
4439 case OPC_BNEL:
4440 /* Compare two registers */
4441 if (rs != rt) {
6c5c1e20
TS
4442 gen_load_gpr(t0, rs);
4443 gen_load_gpr(t1, rt);
2fdbad25 4444 bcond_compute = 1;
6af0bf9c 4445 }
eeb3bba8 4446 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c
FB
4447 break;
4448 case OPC_BGEZ:
4449 case OPC_BGEZAL:
4450 case OPC_BGEZALL:
4451 case OPC_BGEZL:
4452 case OPC_BGTZ:
4453 case OPC_BGTZL:
4454 case OPC_BLEZ:
4455 case OPC_BLEZL:
4456 case OPC_BLTZ:
4457 case OPC_BLTZAL:
4458 case OPC_BLTZALL:
4459 case OPC_BLTZL:
4460 /* Compare to zero */
4461 if (rs != 0) {
6c5c1e20 4462 gen_load_gpr(t0, rs);
2fdbad25 4463 bcond_compute = 1;
6af0bf9c 4464 }
eeb3bba8 4465 btgt = ctx->base.pc_next + insn_bytes + offset;
6af0bf9c 4466 break;
e45a93e2
JL
4467 case OPC_BPOSGE32:
4468#if defined(TARGET_MIPS64)
4469 case OPC_BPOSGE64:
4470 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4471#else
4472 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4473#endif
4474 bcond_compute = 1;
eeb3bba8 4475 btgt = ctx->base.pc_next + insn_bytes + offset;
e45a93e2 4476 break;
6af0bf9c
FB
4477 case OPC_J:
4478 case OPC_JAL:
364d4831 4479 case OPC_JALX:
6af0bf9c 4480 /* Jump to immediate */
eeb3bba8
EC
4481 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
4482 (uint32_t)offset;
6af0bf9c
FB
4483 break;
4484 case OPC_JR:
4485 case OPC_JALR:
4486 /* Jump to register */
7a387fff
TS
4487 if (offset != 0 && offset != 16) {
4488 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
cbeb0857 4489 others are reserved. */
923617a3 4490 MIPS_INVAL("jump hint");
9c708c7f 4491 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 4492 goto out;
6af0bf9c 4493 }
d077b6f7 4494 gen_load_gpr(btarget, rs);
6af0bf9c
FB
4495 break;
4496 default:
4497 MIPS_INVAL("branch/jump");
9c708c7f 4498 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 4499 goto out;
6af0bf9c 4500 }
2fdbad25 4501 if (bcond_compute == 0) {
6af0bf9c
FB
4502 /* No condition to be computed */
4503 switch (opc) {
4504 case OPC_BEQ: /* rx == rx */
4505 case OPC_BEQL: /* rx == rx likely */
4506 case OPC_BGEZ: /* 0 >= 0 */
4507 case OPC_BGEZL: /* 0 >= 0 likely */
4508 case OPC_BLEZ: /* 0 <= 0 */
4509 case OPC_BLEZL: /* 0 <= 0 likely */
4510 /* Always take */
4ad40f36 4511 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
4512 break;
4513 case OPC_BGEZAL: /* 0 >= 0 */
4514 case OPC_BGEZALL: /* 0 >= 0 likely */
4515 /* Always take and link */
4516 blink = 31;
4ad40f36 4517 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
4518 break;
4519 case OPC_BNE: /* rx != rx */
4520 case OPC_BGTZ: /* 0 > 0 */
4521 case OPC_BLTZ: /* 0 < 0 */
ead9360e 4522 /* Treat as NOP. */
6c5c1e20 4523 goto out;
eeef26cd 4524 case OPC_BLTZAL: /* 0 < 0 */
3c824109
NF
4525 /* Handle as an unconditional branch to get correct delay
4526 slot checking. */
4527 blink = 31;
eeb3bba8 4528 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
3c824109 4529 ctx->hflags |= MIPS_HFLAG_B;
3c824109 4530 break;
eeef26cd 4531 case OPC_BLTZALL: /* 0 < 0 likely */
eeb3bba8 4532 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
9898128f 4533 /* Skip the instruction in the delay slot */
eeb3bba8 4534 ctx->base.pc_next += 4;
6c5c1e20 4535 goto out;
6af0bf9c
FB
4536 case OPC_BNEL: /* rx != rx likely */
4537 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
4538 case OPC_BLTZL: /* 0 < 0 likely */
4539 /* Skip the instruction in the delay slot */
eeb3bba8 4540 ctx->base.pc_next += 4;
6c5c1e20 4541 goto out;
6af0bf9c 4542 case OPC_J:
4ad40f36 4543 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c 4544 break;
364d4831
NF
4545 case OPC_JALX:
4546 ctx->hflags |= MIPS_HFLAG_BX;
4547 /* Fallthrough */
6af0bf9c
FB
4548 case OPC_JAL:
4549 blink = 31;
4ad40f36 4550 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
4551 break;
4552 case OPC_JR:
4ad40f36 4553 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
4554 break;
4555 case OPC_JALR:
4556 blink = rt;
4ad40f36 4557 ctx->hflags |= MIPS_HFLAG_BR;
6af0bf9c
FB
4558 break;
4559 default:
4560 MIPS_INVAL("branch/jump");
9c708c7f 4561 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 4562 goto out;
6af0bf9c
FB
4563 }
4564 } else {
4565 switch (opc) {
4566 case OPC_BEQ:
e68dd28f 4567 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
4568 goto not_likely;
4569 case OPC_BEQL:
e68dd28f 4570 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6af0bf9c
FB
4571 goto likely;
4572 case OPC_BNE:
e68dd28f 4573 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
4574 goto not_likely;
4575 case OPC_BNEL:
e68dd28f 4576 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6af0bf9c
FB
4577 goto likely;
4578 case OPC_BGEZ:
e68dd28f 4579 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
4580 goto not_likely;
4581 case OPC_BGEZL:
e68dd28f 4582 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
4583 goto likely;
4584 case OPC_BGEZAL:
e68dd28f 4585 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c
FB
4586 blink = 31;
4587 goto not_likely;
4588 case OPC_BGEZALL:
e68dd28f 4589 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 4590 blink = 31;
6af0bf9c
FB
4591 goto likely;
4592 case OPC_BGTZ:
e68dd28f 4593 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
4594 goto not_likely;
4595 case OPC_BGTZL:
e68dd28f 4596 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6af0bf9c
FB
4597 goto likely;
4598 case OPC_BLEZ:
e68dd28f 4599 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
4600 goto not_likely;
4601 case OPC_BLEZL:
e68dd28f 4602 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6af0bf9c
FB
4603 goto likely;
4604 case OPC_BLTZ:
e68dd28f 4605 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c
FB
4606 goto not_likely;
4607 case OPC_BLTZL:
e68dd28f 4608 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 4609 goto likely;
e45a93e2
JL
4610 case OPC_BPOSGE32:
4611 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
e45a93e2
JL
4612 goto not_likely;
4613#if defined(TARGET_MIPS64)
4614 case OPC_BPOSGE64:
4615 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
e45a93e2
JL
4616 goto not_likely;
4617#endif
6af0bf9c 4618 case OPC_BLTZAL:
e68dd28f 4619 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 4620 blink = 31;
6af0bf9c 4621 not_likely:
4ad40f36 4622 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
4623 break;
4624 case OPC_BLTZALL:
e68dd28f 4625 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 4626 blink = 31;
6af0bf9c 4627 likely:
4ad40f36 4628 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 4629 break;
c53f4a62
TS
4630 default:
4631 MIPS_INVAL("conditional branch/jump");
9c708c7f 4632 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 4633 goto out;
6af0bf9c 4634 }
6af0bf9c 4635 }
9b9e4393 4636
d077b6f7 4637 ctx->btarget = btgt;
b231c103
YK
4638
4639 switch (delayslot_size) {
4640 case 2:
4641 ctx->hflags |= MIPS_HFLAG_BDS16;
4642 break;
4643 case 4:
4644 ctx->hflags |= MIPS_HFLAG_BDS32;
4645 break;
4646 }
4647
6af0bf9c 4648 if (blink > 0) {
b231c103 4649 int post_delay = insn_bytes + delayslot_size;
364d4831
NF
4650 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4651
eeb3bba8
EC
4652 tcg_gen_movi_tl(cpu_gpr[blink],
4653 ctx->base.pc_next + post_delay + lowbit);
6af0bf9c 4654 }
6c5c1e20
TS
4655
4656 out:
364d4831
NF
4657 if (insn_bytes == 2)
4658 ctx->hflags |= MIPS_HFLAG_B16;
6c5c1e20
TS
4659 tcg_temp_free(t0);
4660 tcg_temp_free(t1);
6af0bf9c
FB
4661}
4662
764371d2
SM
4663
4664/* nanoMIPS Branches */
4665static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
4666 int insn_bytes,
4667 int rs, int rt, int32_t offset)
4668{
4669 target_ulong btgt = -1;
4670 int bcond_compute = 0;
4671 TCGv t0 = tcg_temp_new();
4672 TCGv t1 = tcg_temp_new();
4673
4674 /* Load needed operands */
4675 switch (opc) {
4676 case OPC_BEQ:
4677 case OPC_BNE:
4678 /* Compare two registers */
4679 if (rs != rt) {
4680 gen_load_gpr(t0, rs);
4681 gen_load_gpr(t1, rt);
4682 bcond_compute = 1;
4683 }
4684 btgt = ctx->base.pc_next + insn_bytes + offset;
4685 break;
4686 case OPC_BGEZAL:
4687 /* Compare to zero */
4688 if (rs != 0) {
4689 gen_load_gpr(t0, rs);
4690 bcond_compute = 1;
4691 }
4692 btgt = ctx->base.pc_next + insn_bytes + offset;
4693 break;
4694 case OPC_BPOSGE32:
4695 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4696 bcond_compute = 1;
4697 btgt = ctx->base.pc_next + insn_bytes + offset;
4698 break;
4699 case OPC_JR:
4700 case OPC_JALR:
4701 /* Jump to register */
4702 if (offset != 0 && offset != 16) {
4703 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4704 others are reserved. */
4705 MIPS_INVAL("jump hint");
4706 generate_exception_end(ctx, EXCP_RI);
4707 goto out;
4708 }
4709 gen_load_gpr(btarget, rs);
4710 break;
4711 default:
4712 MIPS_INVAL("branch/jump");
4713 generate_exception_end(ctx, EXCP_RI);
4714 goto out;
4715 }
4716 if (bcond_compute == 0) {
4717 /* No condition to be computed */
4718 switch (opc) {
4719 case OPC_BEQ: /* rx == rx */
4720 /* Always take */
4721 ctx->hflags |= MIPS_HFLAG_B;
4722 break;
4723 case OPC_BGEZAL: /* 0 >= 0 */
4724 /* Always take and link */
4725 tcg_gen_movi_tl(cpu_gpr[31],
4726 ctx->base.pc_next + insn_bytes);
4727 ctx->hflags |= MIPS_HFLAG_B;
4728 break;
4729 case OPC_BNE: /* rx != rx */
4730 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
4731 /* Skip the instruction in the delay slot */
4732 ctx->base.pc_next += 4;
4733 goto out;
4734 case OPC_JR:
4735 ctx->hflags |= MIPS_HFLAG_BR;
4736 break;
4737 case OPC_JALR:
4738 if (rt > 0) {
4739 tcg_gen_movi_tl(cpu_gpr[rt],
4740 ctx->base.pc_next + insn_bytes);
4741 }
4742 ctx->hflags |= MIPS_HFLAG_BR;
4743 break;
4744 default:
4745 MIPS_INVAL("branch/jump");
4746 generate_exception_end(ctx, EXCP_RI);
4747 goto out;
4748 }
4749 } else {
4750 switch (opc) {
4751 case OPC_BEQ:
4752 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4753 goto not_likely;
4754 case OPC_BNE:
4755 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4756 goto not_likely;
4757 case OPC_BGEZAL:
4758 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4759 tcg_gen_movi_tl(cpu_gpr[31],
4760 ctx->base.pc_next + insn_bytes);
4761 goto not_likely;
4762 case OPC_BPOSGE32:
4763 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4764 not_likely:
4765 ctx->hflags |= MIPS_HFLAG_BC;
4766 break;
4767 default:
4768 MIPS_INVAL("conditional branch/jump");
4769 generate_exception_end(ctx, EXCP_RI);
4770 goto out;
4771 }
4772 }
4773
4774 ctx->btarget = btgt;
4775
4776 out:
4777 if (insn_bytes == 2) {
4778 ctx->hflags |= MIPS_HFLAG_B16;
4779 }
4780 tcg_temp_free(t0);
4781 tcg_temp_free(t1);
4782}
4783
4784
7a387fff
TS
4785/* special3 bitfield operations */
4786static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
356265ae 4787 int rs, int lsb, int msb)
7a387fff 4788{
a7812ae4
PB
4789 TCGv t0 = tcg_temp_new();
4790 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
4791
4792 gen_load_gpr(t1, rs);
7a387fff
TS
4793 switch (opc) {
4794 case OPC_EXT:
b7f26e52 4795 if (lsb + msb > 31) {
7a387fff 4796 goto fail;
b7f26e52 4797 }
505ad7c2 4798 if (msb != 31) {
6eebb7a4 4799 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
505ad7c2 4800 } else {
6eebb7a4
RH
4801 /* The two checks together imply that lsb == 0,
4802 so this is a simple sign-extension. */
4803 tcg_gen_ext32s_tl(t0, t1);
505ad7c2 4804 }
7a387fff 4805 break;
c6d6dd7c 4806#if defined(TARGET_MIPS64)
7a387fff 4807 case OPC_DEXTU:
b7f26e52
RH
4808 lsb += 32;
4809 goto do_dext;
4810 case OPC_DEXTM:
4811 msb += 32;
4812 goto do_dext;
7a387fff 4813 case OPC_DEXT:
b7f26e52
RH
4814 do_dext:
4815 if (lsb + msb > 63) {
4816 goto fail;
4817 }
6eebb7a4 4818 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
7a387fff 4819 break;
c6d6dd7c 4820#endif
7a387fff 4821 case OPC_INS:
b7f26e52 4822 if (lsb > msb) {
7a387fff 4823 goto fail;
b7f26e52 4824 }
6c5c1e20 4825 gen_load_gpr(t0, rt);
e0d002f1 4826 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
505ad7c2 4827 tcg_gen_ext32s_tl(t0, t0);
7a387fff 4828 break;
c6d6dd7c 4829#if defined(TARGET_MIPS64)
7a387fff 4830 case OPC_DINSU:
b7f26e52
RH
4831 lsb += 32;
4832 /* FALLTHRU */
4833 case OPC_DINSM:
4834 msb += 32;
4835 /* FALLTHRU */
7a387fff 4836 case OPC_DINS:
b7f26e52
RH
4837 if (lsb > msb) {
4838 goto fail;
4839 }
6c5c1e20 4840 gen_load_gpr(t0, rt);
e0d002f1 4841 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
7a387fff 4842 break;
c6d6dd7c 4843#endif
7a387fff
TS
4844 default:
4845fail:
4846 MIPS_INVAL("bitops");
9c708c7f 4847 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
4848 tcg_temp_free(t0);
4849 tcg_temp_free(t1);
7a387fff
TS
4850 return;
4851 }
6c5c1e20
TS
4852 gen_store_gpr(t0, rt);
4853 tcg_temp_free(t0);
4854 tcg_temp_free(t1);
7a387fff
TS
4855}
4856
49bcf33c
AJ
4857static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4858{
3a55fa47 4859 TCGv t0;
49bcf33c 4860
3a55fa47
AJ
4861 if (rd == 0) {
4862 /* If no destination, treat it as a NOP. */
3a55fa47
AJ
4863 return;
4864 }
4865
4866 t0 = tcg_temp_new();
4867 gen_load_gpr(t0, rt);
49bcf33c
AJ
4868 switch (op2) {
4869 case OPC_WSBH:
3a55fa47
AJ
4870 {
4871 TCGv t1 = tcg_temp_new();
06a57e5c 4872 TCGv t2 = tcg_const_tl(0x00FF00FF);
3a55fa47
AJ
4873
4874 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
4875 tcg_gen_and_tl(t1, t1, t2);
4876 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 4877 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 4878 tcg_gen_or_tl(t0, t0, t1);
06a57e5c 4879 tcg_temp_free(t2);
3a55fa47
AJ
4880 tcg_temp_free(t1);
4881 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4882 }
49bcf33c
AJ
4883 break;
4884 case OPC_SEB:
3a55fa47 4885 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
4886 break;
4887 case OPC_SEH:
3a55fa47 4888 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
4889 break;
4890#if defined(TARGET_MIPS64)
4891 case OPC_DSBH:
3a55fa47
AJ
4892 {
4893 TCGv t1 = tcg_temp_new();
06a57e5c 4894 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
3a55fa47
AJ
4895
4896 tcg_gen_shri_tl(t1, t0, 8);
06a57e5c
AJ
4897 tcg_gen_and_tl(t1, t1, t2);
4898 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 4899 tcg_gen_shli_tl(t0, t0, 8);
3a55fa47 4900 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 4901 tcg_temp_free(t2);
3a55fa47
AJ
4902 tcg_temp_free(t1);
4903 }
49bcf33c
AJ
4904 break;
4905 case OPC_DSHD:
3a55fa47
AJ
4906 {
4907 TCGv t1 = tcg_temp_new();
06a57e5c 4908 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
3a55fa47
AJ
4909
4910 tcg_gen_shri_tl(t1, t0, 16);
06a57e5c
AJ
4911 tcg_gen_and_tl(t1, t1, t2);
4912 tcg_gen_and_tl(t0, t0, t2);
3a55fa47 4913 tcg_gen_shli_tl(t0, t0, 16);
3a55fa47
AJ
4914 tcg_gen_or_tl(t0, t0, t1);
4915 tcg_gen_shri_tl(t1, t0, 32);
4916 tcg_gen_shli_tl(t0, t0, 32);
4917 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
06a57e5c 4918 tcg_temp_free(t2);
3a55fa47
AJ
4919 tcg_temp_free(t1);
4920 }
49bcf33c
AJ
4921 break;
4922#endif
4923 default:
4924 MIPS_INVAL("bsfhl");
9c708c7f 4925 generate_exception_end(ctx, EXCP_RI);
49bcf33c 4926 tcg_temp_free(t0);
49bcf33c
AJ
4927 return;
4928 }
49bcf33c 4929 tcg_temp_free(t0);
49bcf33c
AJ
4930}
4931
1f1b4c00
YK
4932static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4933 int imm2)
4934{
4935 TCGv t0;
4936 TCGv t1;
4937 if (rd == 0) {
4938 /* Treat as NOP. */
4939 return;
4940 }
4941 t0 = tcg_temp_new();
4942 t1 = tcg_temp_new();
4943 gen_load_gpr(t0, rs);
4944 gen_load_gpr(t1, rt);
4945 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4946 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4947 if (opc == OPC_LSA) {
4948 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4949 }
4950
4951 tcg_temp_free(t1);
4952 tcg_temp_free(t0);
4953
4954 return;
4955}
4956
821f2008
JH
4957static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
4958 int rt, int bits)
284b731a 4959{
1f1b4c00
YK
4960 TCGv t0;
4961 if (rd == 0) {
4962 /* Treat as NOP. */
4963 return;
4964 }
4965 t0 = tcg_temp_new();
821f2008
JH
4966 if (bits == 0 || bits == wordsz) {
4967 if (bits == 0) {
4968 gen_load_gpr(t0, rt);
4969 } else {
4970 gen_load_gpr(t0, rs);
4971 }
4972 switch (wordsz) {
4973 case 32:
51243852
MD
4974 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4975 break;
4976#if defined(TARGET_MIPS64)
821f2008 4977 case 64:
51243852
MD
4978 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4979 break;
4980#endif
4981 }
1f1b4c00
YK
4982 } else {
4983 TCGv t1 = tcg_temp_new();
821f2008 4984 gen_load_gpr(t0, rt);
1f1b4c00 4985 gen_load_gpr(t1, rs);
821f2008
JH
4986 switch (wordsz) {
4987 case 32:
1f1b4c00
YK
4988 {
4989 TCGv_i64 t2 = tcg_temp_new_i64();
4990 tcg_gen_concat_tl_i64(t2, t1, t0);
821f2008 4991 tcg_gen_shri_i64(t2, t2, 32 - bits);
1f1b4c00
YK
4992 gen_move_low32(cpu_gpr[rd], t2);
4993 tcg_temp_free_i64(t2);
4994 }
4995 break;
284b731a 4996#if defined(TARGET_MIPS64)
821f2008
JH
4997 case 64:
4998 tcg_gen_shli_tl(t0, t0, bits);
4999 tcg_gen_shri_tl(t1, t1, 64 - bits);
1f1b4c00
YK
5000 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5001 break;
284b731a 5002#endif
1f1b4c00
YK
5003 }
5004 tcg_temp_free(t1);
5005 }
5006
5007 tcg_temp_free(t0);
5008}
5009
821f2008
JH
5010static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5011 int bp)
5012{
5013 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5014}
5015
5016static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5017 int shift)
5018{
5019 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5020}
5021
1f1b4c00
YK
5022static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5023{
5024 TCGv t0;
5025 if (rd == 0) {
5026 /* Treat as NOP. */
5027 return;
5028 }
5029 t0 = tcg_temp_new();
5030 gen_load_gpr(t0, rt);
5031 switch (opc) {
5032 case OPC_BITSWAP:
5033 gen_helper_bitswap(cpu_gpr[rd], t0);
5034 break;
5035#if defined(TARGET_MIPS64)
5036 case OPC_DBITSWAP:
5037 gen_helper_dbitswap(cpu_gpr[rd], t0);
5038 break;
5039#endif
5040 }
5041 tcg_temp_free(t0);
284b731a
LA
5042}
5043
1f1b4c00
YK
5044#ifndef CONFIG_USER_ONLY
5045/* CP0 (MMU and control) */
5204ea79
LA
5046static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5047{
5048 TCGv_i64 t0 = tcg_temp_new_i64();
5049 TCGv_i64 t1 = tcg_temp_new_i64();
5050
5051 tcg_gen_ext_tl_i64(t0, arg);
5052 tcg_gen_ld_i64(t1, cpu_env, off);
5053#if defined(TARGET_MIPS64)
5054 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5055#else
5056 tcg_gen_concat32_i64(t1, t1, t0);
5057#endif
5058 tcg_gen_st_i64(t1, cpu_env, off);
5059 tcg_temp_free_i64(t1);
5060 tcg_temp_free_i64(t0);
5061}
5062
5063static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5064{
5065 TCGv_i64 t0 = tcg_temp_new_i64();
5066 TCGv_i64 t1 = tcg_temp_new_i64();
5067
5068 tcg_gen_ext_tl_i64(t0, arg);
5069 tcg_gen_ld_i64(t1, cpu_env, off);
5070 tcg_gen_concat32_i64(t1, t1, t0);
5071 tcg_gen_st_i64(t1, cpu_env, off);
5072 tcg_temp_free_i64(t1);
5073 tcg_temp_free_i64(t0);
5074}
5075
5076static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5077{
5078 TCGv_i64 t0 = tcg_temp_new_i64();
5079
5080 tcg_gen_ld_i64(t0, cpu_env, off);
5081#if defined(TARGET_MIPS64)
5082 tcg_gen_shri_i64(t0, t0, 30);
5083#else
5084 tcg_gen_shri_i64(t0, t0, 32);
5085#endif
5086 gen_move_low32(arg, t0);
5087 tcg_temp_free_i64(t0);
5088}
5089
5090static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5091{
5092 TCGv_i64 t0 = tcg_temp_new_i64();
5093
5094 tcg_gen_ld_i64(t0, cpu_env, off);
5095 tcg_gen_shri_i64(t0, t0, 32 + shift);
5096 gen_move_low32(arg, t0);
5097 tcg_temp_free_i64(t0);
5098}
5099
d9bea114 5100static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4f57689a 5101{
d9bea114 5102 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 5103
d9bea114
AJ
5104 tcg_gen_ld_i32(t0, cpu_env, off);
5105 tcg_gen_ext_i32_tl(arg, t0);
5106 tcg_temp_free_i32(t0);
4f57689a
TS
5107}
5108
d9bea114 5109static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4f57689a 5110{
d9bea114
AJ
5111 tcg_gen_ld_tl(arg, cpu_env, off);
5112 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
5113}
5114
d9bea114 5115static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
f1aa6320 5116{
d9bea114 5117 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 5118
d9bea114
AJ
5119 tcg_gen_trunc_tl_i32(t0, arg);
5120 tcg_gen_st_i32(t0, cpu_env, off);
5121 tcg_temp_free_i32(t0);
f1aa6320
TS
5122}
5123
c98d3d79
YK
5124#define CP0_CHECK(c) \
5125 do { \
5126 if (!(c)) { \
5127 goto cp0_unimplemented; \
5128 } \
5129 } while (0)
5130
5204ea79
LA
5131static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5132{
5133 const char *rn = "invalid";
5134
5204ea79
LA
5135 switch (reg) {
5136 case 2:
5137 switch (sel) {
5138 case 0:
59488dda 5139 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
5140 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5141 rn = "EntryLo0";
5142 break;
5143 default:
c98d3d79 5144 goto cp0_unimplemented;
5204ea79
LA
5145 }
5146 break;
5147 case 3:
5148 switch (sel) {
5149 case 0:
59488dda 5150 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
5151 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5152 rn = "EntryLo1";
5153 break;
5154 default:
c98d3d79 5155 goto cp0_unimplemented;
5204ea79
LA
5156 }
5157 break;
5158 case 17:
5159 switch (sel) {
5160 case 0:
5161 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
5162 ctx->CP0_LLAddr_shift);
5163 rn = "LLAddr";
5164 break;
f6d4dd81
YK
5165 case 1:
5166 CP0_CHECK(ctx->mrp);
5167 gen_helper_mfhc0_maar(arg, cpu_env);
5168 rn = "MAAR";
5169 break;
5204ea79 5170 default:
c98d3d79 5171 goto cp0_unimplemented;
5204ea79
LA
5172 }
5173 break;
5174 case 28:
5175 switch (sel) {
5176 case 0:
5177 case 2:
5178 case 4:
5179 case 6:
5180 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5181 rn = "TagLo";
5182 break;
5183 default:
c98d3d79 5184 goto cp0_unimplemented;
5204ea79
LA
5185 }
5186 break;
5187 default:
c98d3d79 5188 goto cp0_unimplemented;
5204ea79 5189 }
b44a7fb1 5190 trace_mips_translate_c0("mfhc0", rn, reg, sel);
5204ea79
LA
5191 return;
5192
c98d3d79 5193cp0_unimplemented:
965447ee 5194 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5204ea79
LA
5195 tcg_gen_movi_tl(arg, 0);
5196}
5197
5198static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5199{
5200 const char *rn = "invalid";
5201 uint64_t mask = ctx->PAMask >> 36;
5202
5204ea79
LA
5203 switch (reg) {
5204 case 2:
5205 switch (sel) {
5206 case 0:
59488dda 5207 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
5208 tcg_gen_andi_tl(arg, arg, mask);
5209 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5210 rn = "EntryLo0";
5211 break;
5212 default:
c98d3d79 5213 goto cp0_unimplemented;
5204ea79
LA
5214 }
5215 break;
5216 case 3:
5217 switch (sel) {
5218 case 0:
59488dda 5219 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5204ea79
LA
5220 tcg_gen_andi_tl(arg, arg, mask);
5221 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5222 rn = "EntryLo1";
5223 break;
5224 default:
c98d3d79 5225 goto cp0_unimplemented;
5204ea79
LA
5226 }
5227 break;
5228 case 17:
5229 switch (sel) {
5230 case 0:
5231 /* LLAddr is read-only (the only exception is bit 0 if LLB is
5232 supported); the CP0_LLAddr_rw_bitmask does not seem to be
5233 relevant for modern MIPS cores supporting MTHC0, therefore
5234 treating MTHC0 to LLAddr as NOP. */
5235 rn = "LLAddr";
5236 break;
f6d4dd81
YK
5237 case 1:
5238 CP0_CHECK(ctx->mrp);
5239 gen_helper_mthc0_maar(cpu_env, arg);
5240 rn = "MAAR";
5241 break;
5204ea79 5242 default:
c98d3d79 5243 goto cp0_unimplemented;
5204ea79
LA
5244 }
5245 break;
5246 case 28:
5247 switch (sel) {
5248 case 0:
5249 case 2:
5250 case 4:
5251 case 6:
5252 tcg_gen_andi_tl(arg, arg, mask);
5253 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5254 rn = "TagLo";
5255 break;
5256 default:
c98d3d79 5257 goto cp0_unimplemented;
5204ea79
LA
5258 }
5259 break;
5260 default:
c98d3d79 5261 goto cp0_unimplemented;
5204ea79 5262 }
b44a7fb1 5263 trace_mips_translate_c0("mthc0", rn, reg, sel);
5204ea79 5264
c98d3d79 5265cp0_unimplemented:
965447ee 5266 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
5204ea79
LA
5267}
5268
e98c0d17
LA
5269static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5270{
5271 if (ctx->insn_flags & ISA_MIPS32R6) {
5272 tcg_gen_movi_tl(arg, 0);
5273 } else {
5274 tcg_gen_movi_tl(arg, ~0);
5275 }
5276}
5277
d75c135e 5278static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 5279{
7a387fff 5280 const char *rn = "invalid";
873eb012 5281
e189e748 5282 if (sel != 0)
d75c135e 5283 check_insn(ctx, ISA_MIPS32);
e189e748 5284
873eb012
TS
5285 switch (reg) {
5286 case 0:
7a387fff
TS
5287 switch (sel) {
5288 case 0:
7db13fae 5289 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7a387fff
TS
5290 rn = "Index";
5291 break;
5292 case 1:
f31b035a 5293 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5294 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7a387fff 5295 rn = "MVPControl";
ead9360e 5296 break;
7a387fff 5297 case 2:
f31b035a 5298 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5299 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7a387fff 5300 rn = "MVPConf0";
ead9360e 5301 break;
7a387fff 5302 case 3:
f31b035a 5303 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5304 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7a387fff 5305 rn = "MVPConf1";
ead9360e 5306 break;
01bc435b
YK
5307 case 4:
5308 CP0_CHECK(ctx->vp);
5309 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
5310 rn = "VPControl";
5311 break;
7a387fff 5312 default:
f31b035a 5313 goto cp0_unimplemented;
7a387fff 5314 }
873eb012
TS
5315 break;
5316 case 1:
7a387fff
TS
5317 switch (sel) {
5318 case 0:
f31b035a 5319 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 5320 gen_helper_mfc0_random(arg, cpu_env);
7a387fff 5321 rn = "Random";
2423f660 5322 break;
7a387fff 5323 case 1:
f31b035a 5324 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5325 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7a387fff 5326 rn = "VPEControl";
ead9360e 5327 break;
7a387fff 5328 case 2:
f31b035a 5329 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7a387fff 5331 rn = "VPEConf0";
ead9360e 5332 break;
7a387fff 5333 case 3:
f31b035a 5334 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5335 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7a387fff 5336 rn = "VPEConf1";
ead9360e 5337 break;
7a387fff 5338 case 4:
f31b035a 5339 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5340 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7a387fff 5341 rn = "YQMask";
ead9360e 5342 break;
7a387fff 5343 case 5:
f31b035a 5344 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5345 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 5346 rn = "VPESchedule";
ead9360e 5347 break;
7a387fff 5348 case 6:
f31b035a 5349 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5350 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 5351 rn = "VPEScheFBack";
ead9360e 5352 break;
7a387fff 5353 case 7:
f31b035a 5354 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 5355 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7a387fff 5356 rn = "VPEOpt";
ead9360e 5357 break;
7a387fff 5358 default:
f31b035a 5359 goto cp0_unimplemented;
7a387fff 5360 }
873eb012
TS
5361 break;
5362 case 2:
7a387fff
TS
5363 switch (sel) {
5364 case 0:
284b731a
LA
5365 {
5366 TCGv_i64 tmp = tcg_temp_new_i64();
5367 tcg_gen_ld_i64(tmp, cpu_env,
5368 offsetof(CPUMIPSState, CP0_EntryLo0));
7207c7f9 5369#if defined(TARGET_MIPS64)
284b731a
LA
5370 if (ctx->rxi) {
5371 /* Move RI/XI fields to bits 31:30 */
5372 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5373 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5374 }
7207c7f9 5375#endif
284b731a
LA
5376 gen_move_low32(arg, tmp);
5377 tcg_temp_free_i64(tmp);
5378 }
2423f660
TS
5379 rn = "EntryLo0";
5380 break;
7a387fff 5381 case 1:
f31b035a 5382 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5383 gen_helper_mfc0_tcstatus(arg, cpu_env);
2423f660 5384 rn = "TCStatus";
ead9360e 5385 break;
7a387fff 5386 case 2:
f31b035a 5387 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5388 gen_helper_mfc0_tcbind(arg, cpu_env);
2423f660 5389 rn = "TCBind";
ead9360e 5390 break;
7a387fff 5391 case 3:
f31b035a 5392 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5393 gen_helper_mfc0_tcrestart(arg, cpu_env);
2423f660 5394 rn = "TCRestart";
ead9360e 5395 break;
7a387fff 5396 case 4:
f31b035a 5397 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5398 gen_helper_mfc0_tchalt(arg, cpu_env);
2423f660 5399 rn = "TCHalt";
ead9360e 5400 break;
7a387fff 5401 case 5:
f31b035a 5402 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5403 gen_helper_mfc0_tccontext(arg, cpu_env);
2423f660 5404 rn = "TCContext";
ead9360e 5405 break;
7a387fff 5406 case 6:
f31b035a 5407 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5408 gen_helper_mfc0_tcschedule(arg, cpu_env);
2423f660 5409 rn = "TCSchedule";
ead9360e 5410 break;
7a387fff 5411 case 7:
f31b035a 5412 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 5413 gen_helper_mfc0_tcschefback(arg, cpu_env);
2423f660 5414 rn = "TCScheFBack";
ead9360e 5415 break;
7a387fff 5416 default:
f31b035a 5417 goto cp0_unimplemented;
7a387fff 5418 }
873eb012
TS
5419 break;
5420 case 3:
7a387fff
TS
5421 switch (sel) {
5422 case 0:
284b731a
LA
5423 {
5424 TCGv_i64 tmp = tcg_temp_new_i64();
5425 tcg_gen_ld_i64(tmp, cpu_env,
5426 offsetof(CPUMIPSState, CP0_EntryLo1));
7207c7f9 5427#if defined(TARGET_MIPS64)
284b731a
LA
5428 if (ctx->rxi) {
5429 /* Move RI/XI fields to bits 31:30 */
5430 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5431 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5432 }
7207c7f9 5433#endif
284b731a
LA
5434 gen_move_low32(arg, tmp);
5435 tcg_temp_free_i64(tmp);
5436 }
2423f660
TS
5437 rn = "EntryLo1";
5438 break;
01bc435b
YK
5439 case 1:
5440 CP0_CHECK(ctx->vp);
5441 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5442 rn = "GlobalNumber";
5443 break;
7a387fff 5444 default:
f31b035a 5445 goto cp0_unimplemented;
1579a72e 5446 }
873eb012
TS
5447 break;
5448 case 4:
7a387fff
TS
5449 switch (sel) {
5450 case 0:
7db13fae 5451 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
d9bea114 5452 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
5453 rn = "Context";
5454 break;
7a387fff 5455 case 1:
d9bea114 5456// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660 5457 rn = "ContextConfig";
f31b035a 5458 goto cp0_unimplemented;
d279279e 5459 case 2:
f31b035a 5460 CP0_CHECK(ctx->ulri);
e40df9a8
JH
5461 tcg_gen_ld_tl(arg, cpu_env,
5462 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5463 tcg_gen_ext32s_tl(arg, arg);
f31b035a 5464 rn = "UserLocal";
d279279e 5465 break;
7a387fff 5466 default:
f31b035a 5467 goto cp0_unimplemented;
1579a72e 5468 }
873eb012
TS
5469 break;
5470 case 5:
7a387fff
TS
5471 switch (sel) {
5472 case 0:
7db13fae 5473 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
5474 rn = "PageMask";
5475 break;
7a387fff 5476 case 1:
d75c135e 5477 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5478 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
5479 rn = "PageGrain";
5480 break;
cec56a73
JH
5481 case 2:
5482 CP0_CHECK(ctx->sc);
5483 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
5484 tcg_gen_ext32s_tl(arg, arg);
5485 rn = "SegCtl0";
5486 break;
5487 case 3:
5488 CP0_CHECK(ctx->sc);
5489 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
5490 tcg_gen_ext32s_tl(arg, arg);
5491 rn = "SegCtl1";
5492 break;
5493 case 4:
5494 CP0_CHECK(ctx->sc);
5495 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
5496 tcg_gen_ext32s_tl(arg, arg);
5497 rn = "SegCtl2";
5498 break;
7a387fff 5499 default:
f31b035a 5500 goto cp0_unimplemented;
1579a72e 5501 }
873eb012
TS
5502 break;
5503 case 6:
7a387fff
TS
5504 switch (sel) {
5505 case 0:
7db13fae 5506 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
5507 rn = "Wired";
5508 break;
7a387fff 5509 case 1:
d75c135e 5510 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5511 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 5512 rn = "SRSConf0";
ead9360e 5513 break;
7a387fff 5514 case 2:
d75c135e 5515 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5516 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 5517 rn = "SRSConf1";
ead9360e 5518 break;
7a387fff 5519 case 3:
d75c135e 5520 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5521 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 5522 rn = "SRSConf2";
ead9360e 5523 break;
7a387fff 5524 case 4:
d75c135e 5525 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5526 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 5527 rn = "SRSConf3";
ead9360e 5528 break;
7a387fff 5529 case 5:
d75c135e 5530 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5531 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 5532 rn = "SRSConf4";
ead9360e 5533 break;
7a387fff 5534 default:
f31b035a 5535 goto cp0_unimplemented;
1579a72e 5536 }
873eb012 5537 break;
8c0fdd85 5538 case 7:
7a387fff
TS
5539 switch (sel) {
5540 case 0:
d75c135e 5541 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5542 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
5543 rn = "HWREna";
5544 break;
7a387fff 5545 default:
f31b035a 5546 goto cp0_unimplemented;
1579a72e 5547 }
8c0fdd85 5548 break;
873eb012 5549 case 8:
7a387fff
TS
5550 switch (sel) {
5551 case 0:
7db13fae 5552 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
d9bea114 5553 tcg_gen_ext32s_tl(arg, arg);
f0b3f3ae 5554 rn = "BadVAddr";
2423f660 5555 break;
aea14095 5556 case 1:
f31b035a
LA
5557 CP0_CHECK(ctx->bi);
5558 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5559 rn = "BadInstr";
aea14095
LA
5560 break;
5561 case 2:
f31b035a
LA
5562 CP0_CHECK(ctx->bp);
5563 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5564 rn = "BadInstrP";
aea14095 5565 break;
25beba9b
SM
5566 case 3:
5567 CP0_CHECK(ctx->bi);
5568 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
5569 tcg_gen_andi_tl(arg, arg, ~0xffff);
5570 rn = "BadInstrX";
5571 break;
5572 default:
f31b035a 5573 goto cp0_unimplemented;
aea14095 5574 }
873eb012
TS
5575 break;
5576 case 9:
7a387fff
TS
5577 switch (sel) {
5578 case 0:
2e70f6ef 5579 /* Mark as an IO operation because we read the time. */
eeb3bba8 5580 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 5581 gen_io_start();
bd79255d 5582 }
895c2d04 5583 gen_helper_mfc0_count(arg, cpu_env);
eeb3bba8 5584 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 5585 gen_io_end();
2e70f6ef 5586 }
55807224 5587 /* Break the TB to be able to take timer interrupts immediately
b28425ba
EC
5588 after reading count. DISAS_STOP isn't sufficient, we need to
5589 ensure we break completely out of translated code. */
eeb3bba8
EC
5590 gen_save_pc(ctx->base.pc_next + 4);
5591 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
5592 rn = "Count";
5593 break;
5594 /* 6,7 are implementation dependent */
7a387fff 5595 default:
f31b035a 5596 goto cp0_unimplemented;
2423f660 5597 }
873eb012
TS
5598 break;
5599 case 10:
7a387fff
TS
5600 switch (sel) {
5601 case 0:
7db13fae 5602 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
d9bea114 5603 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
5604 rn = "EntryHi";
5605 break;
7a387fff 5606 default:
f31b035a 5607 goto cp0_unimplemented;
1579a72e 5608 }
873eb012
TS
5609 break;
5610 case 11:
7a387fff
TS
5611 switch (sel) {
5612 case 0:
7db13fae 5613 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
5614 rn = "Compare";
5615 break;
5616 /* 6,7 are implementation dependent */
7a387fff 5617 default:
f31b035a 5618 goto cp0_unimplemented;
2423f660 5619 }
873eb012
TS
5620 break;
5621 case 12:
7a387fff
TS
5622 switch (sel) {
5623 case 0:
7db13fae 5624 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
5625 rn = "Status";
5626 break;
7a387fff 5627 case 1:
d75c135e 5628 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5629 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
5630 rn = "IntCtl";
5631 break;
7a387fff 5632 case 2:
d75c135e 5633 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5634 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
5635 rn = "SRSCtl";
5636 break;
7a387fff 5637 case 3:
d75c135e 5638 check_insn(ctx, ISA_MIPS32R2);
7db13fae 5639 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660 5640 rn = "SRSMap";
fd88b6ab 5641 break;
7a387fff 5642 default:
f31b035a 5643 goto cp0_unimplemented;
7a387fff 5644 }
873eb012
TS
5645 break;
5646 case 13:
7a387fff
TS
5647 switch (sel) {
5648 case 0:
7db13fae 5649 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
5650 rn = "Cause";
5651 break;
7a387fff 5652 default:
f31b035a 5653 goto cp0_unimplemented;
7a387fff 5654 }
873eb012
TS
5655 break;
5656 case 14:
7a387fff
TS
5657 switch (sel) {
5658 case 0:
7db13fae 5659 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
d9bea114 5660 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
5661 rn = "EPC";
5662 break;
7a387fff 5663 default:
f31b035a 5664 goto cp0_unimplemented;
1579a72e 5665 }
873eb012
TS
5666 break;
5667 case 15:
7a387fff
TS
5668 switch (sel) {
5669 case 0:
7db13fae 5670 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
5671 rn = "PRid";
5672 break;
7a387fff 5673 case 1:
d75c135e 5674 check_insn(ctx, ISA_MIPS32R2);
74dbf824
JH
5675 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
5676 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
5677 rn = "EBase";
5678 break;
c870e3f5
YK
5679 case 3:
5680 check_insn(ctx, ISA_MIPS32R2);
5681 CP0_CHECK(ctx->cmgcr);
5682 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
5683 tcg_gen_ext32s_tl(arg, arg);
5684 rn = "CMGCRBase";
5685 break;
7a387fff 5686 default:
f31b035a 5687 goto cp0_unimplemented;
7a387fff 5688 }
873eb012
TS
5689 break;
5690 case 16:
5691 switch (sel) {
5692 case 0:
7db13fae 5693 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
873eb012
TS
5694 rn = "Config";
5695 break;
5696 case 1:
7db13fae 5697 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
873eb012
TS
5698 rn = "Config1";
5699 break;
7a387fff 5700 case 2:
7db13fae 5701 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7a387fff
TS
5702 rn = "Config2";
5703 break;
5704 case 3:
7db13fae 5705 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7a387fff
TS
5706 rn = "Config3";
5707 break;
b4160af1
PJ
5708 case 4:
5709 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5710 rn = "Config4";
5711 break;
b4dd99a3
PJ
5712 case 5:
5713 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5714 rn = "Config5";
5715 break;
e397ee33
TS
5716 /* 6,7 are implementation dependent */
5717 case 6:
7db13fae 5718 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
e397ee33
TS
5719 rn = "Config6";
5720 break;
5721 case 7:
7db13fae 5722 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
e397ee33
TS
5723 rn = "Config7";
5724 break;
873eb012 5725 default:
f31b035a 5726 goto cp0_unimplemented;
873eb012
TS
5727 }
5728 break;
5729 case 17:
7a387fff
TS
5730 switch (sel) {
5731 case 0:
895c2d04 5732 gen_helper_mfc0_lladdr(arg, cpu_env);
2423f660
TS
5733 rn = "LLAddr";
5734 break;
f6d4dd81
YK
5735 case 1:
5736 CP0_CHECK(ctx->mrp);
5737 gen_helper_mfc0_maar(arg, cpu_env);
5738 rn = "MAAR";
5739 break;
5740 case 2:
5741 CP0_CHECK(ctx->mrp);
5742 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
5743 rn = "MAARI";
5744 break;
7a387fff 5745 default:
f31b035a 5746 goto cp0_unimplemented;
7a387fff 5747 }
873eb012
TS
5748 break;
5749 case 18:
7a387fff 5750 switch (sel) {
c2e19f3c
AM
5751 case 0:
5752 case 1:
5753 case 2:
5754 case 3:
5755 case 4:
5756 case 5:
5757 case 6:
5758 case 7:
fa192d49 5759 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 5760 gen_helper_1e0i(mfc0_watchlo, arg, sel);
2423f660
TS
5761 rn = "WatchLo";
5762 break;
7a387fff 5763 default:
f31b035a 5764 goto cp0_unimplemented;
7a387fff 5765 }
873eb012
TS
5766 break;
5767 case 19:
7a387fff 5768 switch (sel) {
c2e19f3c
AM
5769 case 0:
5770 case 1:
5771 case 2:
5772 case 3:
5773 case 4:
5774 case 5:
5775 case 6:
5776 case 7:
fa192d49 5777 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 5778 gen_helper_1e0i(mfc0_watchhi, arg, sel);
2423f660
TS
5779 rn = "WatchHi";
5780 break;
7a387fff 5781 default:
f31b035a 5782 goto cp0_unimplemented;
7a387fff 5783 }
873eb012 5784 break;
8c0fdd85 5785 case 20:
7a387fff
TS
5786 switch (sel) {
5787 case 0:
d26bc211 5788#if defined(TARGET_MIPS64)
d75c135e 5789 check_insn(ctx, ISA_MIPS3);
7db13fae 5790 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
d9bea114 5791 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
5792 rn = "XContext";
5793 break;
703eaf37 5794#endif
7a387fff 5795 default:
f31b035a 5796 goto cp0_unimplemented;
7a387fff 5797 }
8c0fdd85
TS
5798 break;
5799 case 21:
7a387fff 5800 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 5801 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
5802 switch (sel) {
5803 case 0:
7db13fae 5804 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
5805 rn = "Framemask";
5806 break;
7a387fff 5807 default:
f31b035a 5808 goto cp0_unimplemented;
7a387fff 5809 }
8c0fdd85
TS
5810 break;
5811 case 22:
d9bea114 5812 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
5813 rn = "'Diagnostic"; /* implementation dependent */
5814 break;
873eb012 5815 case 23:
7a387fff
TS
5816 switch (sel) {
5817 case 0:
895c2d04 5818 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
2423f660
TS
5819 rn = "Debug";
5820 break;
7a387fff 5821 case 1:
d9bea114 5822// gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
2423f660 5823 rn = "TraceControl";
3570d7f6 5824 goto cp0_unimplemented;
7a387fff 5825 case 2:
d9bea114 5826// gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
2423f660 5827 rn = "TraceControl2";
3570d7f6 5828 goto cp0_unimplemented;
7a387fff 5829 case 3:
d9bea114 5830// gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
2423f660 5831 rn = "UserTraceData";
3570d7f6 5832 goto cp0_unimplemented;
7a387fff 5833 case 4:
d9bea114 5834// gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
2423f660 5835 rn = "TraceBPC";
3570d7f6 5836 goto cp0_unimplemented;
7a387fff 5837 default:
f31b035a 5838 goto cp0_unimplemented;
7a387fff 5839 }
873eb012
TS
5840 break;
5841 case 24:
7a387fff
TS
5842 switch (sel) {
5843 case 0:
f0b3f3ae 5844 /* EJTAG support */
7db13fae 5845 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
d9bea114 5846 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
5847 rn = "DEPC";
5848 break;
7a387fff 5849 default:
f31b035a 5850 goto cp0_unimplemented;
7a387fff 5851 }
873eb012 5852 break;
8c0fdd85 5853 case 25:
7a387fff
TS
5854 switch (sel) {
5855 case 0:
7db13fae 5856 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 5857 rn = "Performance0";
7a387fff
TS
5858 break;
5859 case 1:
d9bea114 5860// gen_helper_mfc0_performance1(arg);
2423f660 5861 rn = "Performance1";
3570d7f6 5862 goto cp0_unimplemented;
7a387fff 5863 case 2:
d9bea114 5864// gen_helper_mfc0_performance2(arg);
2423f660 5865 rn = "Performance2";
3570d7f6 5866 goto cp0_unimplemented;
7a387fff 5867 case 3:
d9bea114 5868// gen_helper_mfc0_performance3(arg);
2423f660 5869 rn = "Performance3";
3570d7f6 5870 goto cp0_unimplemented;
7a387fff 5871 case 4:
d9bea114 5872// gen_helper_mfc0_performance4(arg);
2423f660 5873 rn = "Performance4";
3570d7f6 5874 goto cp0_unimplemented;
7a387fff 5875 case 5:
d9bea114 5876// gen_helper_mfc0_performance5(arg);
2423f660 5877 rn = "Performance5";
3570d7f6 5878 goto cp0_unimplemented;
7a387fff 5879 case 6:
d9bea114 5880// gen_helper_mfc0_performance6(arg);
2423f660 5881 rn = "Performance6";
3570d7f6 5882 goto cp0_unimplemented;
7a387fff 5883 case 7:
d9bea114 5884// gen_helper_mfc0_performance7(arg);
2423f660 5885 rn = "Performance7";
3570d7f6 5886 goto cp0_unimplemented;
7a387fff 5887 default:
f31b035a 5888 goto cp0_unimplemented;
7a387fff 5889 }
8c0fdd85
TS
5890 break;
5891 case 26:
0d74a222
LA
5892 switch (sel) {
5893 case 0:
5894 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
5895 rn = "ErrCtl";
5896 break;
5897 default:
5898 goto cp0_unimplemented;
5899 }
da80682b 5900 break;
8c0fdd85 5901 case 27:
7a387fff 5902 switch (sel) {
c2e19f3c
AM
5903 case 0:
5904 case 1:
5905 case 2:
5906 case 3:
d9bea114 5907 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
5908 rn = "CacheErr";
5909 break;
7a387fff 5910 default:
f31b035a 5911 goto cp0_unimplemented;
7a387fff 5912 }
8c0fdd85 5913 break;
873eb012
TS
5914 case 28:
5915 switch (sel) {
5916 case 0:
7a387fff
TS
5917 case 2:
5918 case 4:
5919 case 6:
284b731a
LA
5920 {
5921 TCGv_i64 tmp = tcg_temp_new_i64();
5922 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5923 gen_move_low32(arg, tmp);
5924 tcg_temp_free_i64(tmp);
5925 }
873eb012
TS
5926 rn = "TagLo";
5927 break;
5928 case 1:
7a387fff
TS
5929 case 3:
5930 case 5:
5931 case 7:
7db13fae 5932 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
873eb012
TS
5933 rn = "DataLo";
5934 break;
5935 default:
f31b035a 5936 goto cp0_unimplemented;
873eb012
TS
5937 }
5938 break;
8c0fdd85 5939 case 29:
7a387fff
TS
5940 switch (sel) {
5941 case 0:
5942 case 2:
5943 case 4:
5944 case 6:
7db13fae 5945 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7a387fff
TS
5946 rn = "TagHi";
5947 break;
5948 case 1:
5949 case 3:
5950 case 5:
5951 case 7:
7db13fae 5952 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7a387fff
TS
5953 rn = "DataHi";
5954 break;
5955 default:
f31b035a 5956 goto cp0_unimplemented;
7a387fff 5957 }
8c0fdd85 5958 break;
873eb012 5959 case 30:
7a387fff
TS
5960 switch (sel) {
5961 case 0:
7db13fae 5962 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
d9bea114 5963 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
5964 rn = "ErrorEPC";
5965 break;
7a387fff 5966 default:
f31b035a 5967 goto cp0_unimplemented;
7a387fff 5968 }
873eb012
TS
5969 break;
5970 case 31:
7a387fff
TS
5971 switch (sel) {
5972 case 0:
f0b3f3ae 5973 /* EJTAG support */
7db13fae 5974 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
5975 rn = "DESAVE";
5976 break;
c2e19f3c
AM
5977 case 2:
5978 case 3:
5979 case 4:
5980 case 5:
5981 case 6:
5982 case 7:
f31b035a
LA
5983 CP0_CHECK(ctx->kscrexist & (1 << sel));
5984 tcg_gen_ld_tl(arg, cpu_env,
5985 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5986 tcg_gen_ext32s_tl(arg, arg);
5987 rn = "KScratch";
e98c0d17 5988 break;
7a387fff 5989 default:
f31b035a 5990 goto cp0_unimplemented;
7a387fff 5991 }
873eb012
TS
5992 break;
5993 default:
f31b035a 5994 goto cp0_unimplemented;
873eb012 5995 }
b44a7fb1 5996 trace_mips_translate_c0("mfc0", rn, reg, sel);
873eb012
TS
5997 return;
5998
f31b035a 5999cp0_unimplemented:
965447ee 6000 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
f31b035a 6001 gen_mfc0_unimplemented(ctx, arg);
873eb012
TS
6002}
6003
d75c135e 6004static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 6005{
7a387fff
TS
6006 const char *rn = "invalid";
6007
e189e748 6008 if (sel != 0)
d75c135e 6009 check_insn(ctx, ISA_MIPS32);
e189e748 6010
eeb3bba8 6011 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6012 gen_io_start();
bd79255d 6013 }
2e70f6ef 6014
8c0fdd85
TS
6015 switch (reg) {
6016 case 0:
7a387fff
TS
6017 switch (sel) {
6018 case 0:
895c2d04 6019 gen_helper_mtc0_index(cpu_env, arg);
7a387fff
TS
6020 rn = "Index";
6021 break;
6022 case 1:
f31b035a 6023 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6024 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7a387fff 6025 rn = "MVPControl";
ead9360e 6026 break;
7a387fff 6027 case 2:
f31b035a 6028 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 6029 /* ignored */
7a387fff 6030 rn = "MVPConf0";
ead9360e 6031 break;
7a387fff 6032 case 3:
f31b035a 6033 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 6034 /* ignored */
7a387fff 6035 rn = "MVPConf1";
ead9360e 6036 break;
01bc435b
YK
6037 case 4:
6038 CP0_CHECK(ctx->vp);
6039 /* ignored */
6040 rn = "VPControl";
6041 break;
7a387fff 6042 default:
f31b035a 6043 goto cp0_unimplemented;
7a387fff 6044 }
8c0fdd85
TS
6045 break;
6046 case 1:
7a387fff
TS
6047 switch (sel) {
6048 case 0:
2423f660 6049 /* ignored */
7a387fff 6050 rn = "Random";
2423f660 6051 break;
7a387fff 6052 case 1:
f31b035a 6053 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6054 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7a387fff 6055 rn = "VPEControl";
ead9360e 6056 break;
7a387fff 6057 case 2:
f31b035a 6058 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6059 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7a387fff 6060 rn = "VPEConf0";
ead9360e 6061 break;
7a387fff 6062 case 3:
f31b035a 6063 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6064 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7a387fff 6065 rn = "VPEConf1";
ead9360e 6066 break;
7a387fff 6067 case 4:
f31b035a 6068 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6069 gen_helper_mtc0_yqmask(cpu_env, arg);
7a387fff 6070 rn = "YQMask";
ead9360e 6071 break;
7a387fff 6072 case 5:
f31b035a 6073 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
6074 tcg_gen_st_tl(arg, cpu_env,
6075 offsetof(CPUMIPSState, CP0_VPESchedule));
7a387fff 6076 rn = "VPESchedule";
ead9360e 6077 break;
7a387fff 6078 case 6:
f31b035a 6079 CP0_CHECK(ctx->insn_flags & ASE_MT);
d54a299b
LA
6080 tcg_gen_st_tl(arg, cpu_env,
6081 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7a387fff 6082 rn = "VPEScheFBack";
ead9360e 6083 break;
7a387fff 6084 case 7:
f31b035a 6085 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6086 gen_helper_mtc0_vpeopt(cpu_env, arg);
7a387fff 6087 rn = "VPEOpt";
ead9360e 6088 break;
7a387fff 6089 default:
f31b035a 6090 goto cp0_unimplemented;
7a387fff 6091 }
8c0fdd85
TS
6092 break;
6093 case 2:
7a387fff
TS
6094 switch (sel) {
6095 case 0:
895c2d04 6096 gen_helper_mtc0_entrylo0(cpu_env, arg);
2423f660
TS
6097 rn = "EntryLo0";
6098 break;
7a387fff 6099 case 1:
f31b035a 6100 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6101 gen_helper_mtc0_tcstatus(cpu_env, arg);
2423f660 6102 rn = "TCStatus";
ead9360e 6103 break;
7a387fff 6104 case 2:
f31b035a 6105 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6106 gen_helper_mtc0_tcbind(cpu_env, arg);
2423f660 6107 rn = "TCBind";
ead9360e 6108 break;
7a387fff 6109 case 3:
f31b035a 6110 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6111 gen_helper_mtc0_tcrestart(cpu_env, arg);
2423f660 6112 rn = "TCRestart";
ead9360e 6113 break;
7a387fff 6114 case 4:
f31b035a 6115 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6116 gen_helper_mtc0_tchalt(cpu_env, arg);
2423f660 6117 rn = "TCHalt";
ead9360e 6118 break;
7a387fff 6119 case 5:
f31b035a 6120 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6121 gen_helper_mtc0_tccontext(cpu_env, arg);
2423f660 6122 rn = "TCContext";
ead9360e 6123 break;
7a387fff 6124 case 6:
f31b035a 6125 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6126 gen_helper_mtc0_tcschedule(cpu_env, arg);
2423f660 6127 rn = "TCSchedule";
ead9360e 6128 break;
7a387fff 6129 case 7:
f31b035a 6130 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6131 gen_helper_mtc0_tcschefback(cpu_env, arg);
2423f660 6132 rn = "TCScheFBack";
ead9360e 6133 break;
7a387fff 6134 default:
f31b035a 6135 goto cp0_unimplemented;
7a387fff 6136 }
8c0fdd85
TS
6137 break;
6138 case 3:
7a387fff
TS
6139 switch (sel) {
6140 case 0:
895c2d04 6141 gen_helper_mtc0_entrylo1(cpu_env, arg);
2423f660
TS
6142 rn = "EntryLo1";
6143 break;
01bc435b
YK
6144 case 1:
6145 CP0_CHECK(ctx->vp);
6146 /* ignored */
6147 rn = "GlobalNumber";
6148 break;
7a387fff 6149 default:
f31b035a 6150 goto cp0_unimplemented;
876d4b07 6151 }
8c0fdd85
TS
6152 break;
6153 case 4:
7a387fff
TS
6154 switch (sel) {
6155 case 0:
895c2d04 6156 gen_helper_mtc0_context(cpu_env, arg);
2423f660
TS
6157 rn = "Context";
6158 break;
7a387fff 6159 case 1:
895c2d04 6160// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
2423f660 6161 rn = "ContextConfig";
f31b035a 6162 goto cp0_unimplemented;
d279279e 6163 case 2:
f31b035a
LA
6164 CP0_CHECK(ctx->ulri);
6165 tcg_gen_st_tl(arg, cpu_env,
6166 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6167 rn = "UserLocal";
d279279e 6168 break;
7a387fff 6169 default:
f31b035a 6170 goto cp0_unimplemented;
876d4b07 6171 }
8c0fdd85
TS
6172 break;
6173 case 5:
7a387fff
TS
6174 switch (sel) {
6175 case 0:
895c2d04 6176 gen_helper_mtc0_pagemask(cpu_env, arg);
2423f660
TS
6177 rn = "PageMask";
6178 break;
7a387fff 6179 case 1:
d75c135e 6180 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6181 gen_helper_mtc0_pagegrain(cpu_env, arg);
2423f660 6182 rn = "PageGrain";
eeb3bba8 6183 ctx->base.is_jmp = DISAS_STOP;
2423f660 6184 break;
cec56a73
JH
6185 case 2:
6186 CP0_CHECK(ctx->sc);
6187 gen_helper_mtc0_segctl0(cpu_env, arg);
6188 rn = "SegCtl0";
6189 break;
6190 case 3:
6191 CP0_CHECK(ctx->sc);
6192 gen_helper_mtc0_segctl1(cpu_env, arg);
6193 rn = "SegCtl1";
6194 break;
6195 case 4:
6196 CP0_CHECK(ctx->sc);
6197 gen_helper_mtc0_segctl2(cpu_env, arg);
6198 rn = "SegCtl2";
6199 break;
7a387fff 6200 default:
f31b035a 6201 goto cp0_unimplemented;
876d4b07 6202 }
8c0fdd85
TS
6203 break;
6204 case 6:
7a387fff
TS
6205 switch (sel) {
6206 case 0:
895c2d04 6207 gen_helper_mtc0_wired(cpu_env, arg);
2423f660
TS
6208 rn = "Wired";
6209 break;
7a387fff 6210 case 1:
d75c135e 6211 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6212 gen_helper_mtc0_srsconf0(cpu_env, arg);
2423f660 6213 rn = "SRSConf0";
ead9360e 6214 break;
7a387fff 6215 case 2:
d75c135e 6216 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6217 gen_helper_mtc0_srsconf1(cpu_env, arg);
2423f660 6218 rn = "SRSConf1";
ead9360e 6219 break;
7a387fff 6220 case 3:
d75c135e 6221 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6222 gen_helper_mtc0_srsconf2(cpu_env, arg);
2423f660 6223 rn = "SRSConf2";
ead9360e 6224 break;
7a387fff 6225 case 4:
d75c135e 6226 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6227 gen_helper_mtc0_srsconf3(cpu_env, arg);
2423f660 6228 rn = "SRSConf3";
ead9360e 6229 break;
7a387fff 6230 case 5:
d75c135e 6231 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6232 gen_helper_mtc0_srsconf4(cpu_env, arg);
2423f660 6233 rn = "SRSConf4";
ead9360e 6234 break;
7a387fff 6235 default:
f31b035a 6236 goto cp0_unimplemented;
876d4b07 6237 }
8c0fdd85
TS
6238 break;
6239 case 7:
7a387fff
TS
6240 switch (sel) {
6241 case 0:
d75c135e 6242 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6243 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 6244 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
6245 rn = "HWREna";
6246 break;
7a387fff 6247 default:
f31b035a 6248 goto cp0_unimplemented;
876d4b07 6249 }
8c0fdd85
TS
6250 break;
6251 case 8:
aea14095
LA
6252 switch (sel) {
6253 case 0:
6254 /* ignored */
6255 rn = "BadVAddr";
6256 break;
6257 case 1:
6258 /* ignored */
6259 rn = "BadInstr";
6260 break;
6261 case 2:
6262 /* ignored */
6263 rn = "BadInstrP";
6264 break;
25beba9b
SM
6265 case 3:
6266 /* ignored */
6267 rn = "BadInstrX";
6268 break;
aea14095 6269 default:
f31b035a 6270 goto cp0_unimplemented;
aea14095 6271 }
8c0fdd85
TS
6272 break;
6273 case 9:
7a387fff
TS
6274 switch (sel) {
6275 case 0:
895c2d04 6276 gen_helper_mtc0_count(cpu_env, arg);
2423f660
TS
6277 rn = "Count";
6278 break;
876d4b07 6279 /* 6,7 are implementation dependent */
7a387fff 6280 default:
f31b035a 6281 goto cp0_unimplemented;
876d4b07 6282 }
8c0fdd85
TS
6283 break;
6284 case 10:
7a387fff
TS
6285 switch (sel) {
6286 case 0:
895c2d04 6287 gen_helper_mtc0_entryhi(cpu_env, arg);
2423f660
TS
6288 rn = "EntryHi";
6289 break;
7a387fff 6290 default:
f31b035a 6291 goto cp0_unimplemented;
876d4b07 6292 }
8c0fdd85
TS
6293 break;
6294 case 11:
7a387fff
TS
6295 switch (sel) {
6296 case 0:
895c2d04 6297 gen_helper_mtc0_compare(cpu_env, arg);
2423f660
TS
6298 rn = "Compare";
6299 break;
6300 /* 6,7 are implementation dependent */
7a387fff 6301 default:
f31b035a 6302 goto cp0_unimplemented;
876d4b07 6303 }
8c0fdd85
TS
6304 break;
6305 case 12:
7a387fff
TS
6306 switch (sel) {
6307 case 0:
867abc7e 6308 save_cpu_state(ctx, 1);
895c2d04 6309 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 6310 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
6311 gen_save_pc(ctx->base.pc_next + 4);
6312 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
6313 rn = "Status";
6314 break;
7a387fff 6315 case 1:
d75c135e 6316 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6317 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 6318 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6319 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
6320 rn = "IntCtl";
6321 break;
7a387fff 6322 case 2:
d75c135e 6323 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6324 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 6325 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6326 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
6327 rn = "SRSCtl";
6328 break;
7a387fff 6329 case 3:
d75c135e 6330 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6331 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 6332 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6333 ctx->base.is_jmp = DISAS_STOP;
2423f660 6334 rn = "SRSMap";
fd88b6ab 6335 break;
7a387fff 6336 default:
f31b035a 6337 goto cp0_unimplemented;
876d4b07 6338 }
8c0fdd85
TS
6339 break;
6340 case 13:
7a387fff
TS
6341 switch (sel) {
6342 case 0:
867abc7e 6343 save_cpu_state(ctx, 1);
895c2d04 6344 gen_helper_mtc0_cause(cpu_env, arg);
b28425ba
EC
6345 /* Stop translation as we may have triggered an interrupt.
6346 * DISAS_STOP isn't sufficient, we need to ensure we break out of
6347 * translated code to check for pending interrupts. */
eeb3bba8
EC
6348 gen_save_pc(ctx->base.pc_next + 4);
6349 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
6350 rn = "Cause";
6351 break;
7a387fff 6352 default:
f31b035a 6353 goto cp0_unimplemented;
876d4b07 6354 }
8c0fdd85
TS
6355 break;
6356 case 14:
7a387fff
TS
6357 switch (sel) {
6358 case 0:
d54a299b 6359 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
6360 rn = "EPC";
6361 break;
7a387fff 6362 default:
f31b035a 6363 goto cp0_unimplemented;
876d4b07 6364 }
8c0fdd85
TS
6365 break;
6366 case 15:
7a387fff
TS
6367 switch (sel) {
6368 case 0:
2423f660
TS
6369 /* ignored */
6370 rn = "PRid";
6371 break;
7a387fff 6372 case 1:
d75c135e 6373 check_insn(ctx, ISA_MIPS32R2);
895c2d04 6374 gen_helper_mtc0_ebase(cpu_env, arg);
2423f660
TS
6375 rn = "EBase";
6376 break;
7a387fff 6377 default:
f31b035a 6378 goto cp0_unimplemented;
1579a72e 6379 }
8c0fdd85
TS
6380 break;
6381 case 16:
6382 switch (sel) {
6383 case 0:
895c2d04 6384 gen_helper_mtc0_config0(cpu_env, arg);
7a387fff 6385 rn = "Config";
2423f660 6386 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6387 ctx->base.is_jmp = DISAS_STOP;
7a387fff
TS
6388 break;
6389 case 1:
e397ee33 6390 /* ignored, read only */
7a387fff
TS
6391 rn = "Config1";
6392 break;
6393 case 2:
895c2d04 6394 gen_helper_mtc0_config2(cpu_env, arg);
7a387fff 6395 rn = "Config2";
2423f660 6396 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6397 ctx->base.is_jmp = DISAS_STOP;
8c0fdd85 6398 break;
7a387fff 6399 case 3:
90f12d73 6400 gen_helper_mtc0_config3(cpu_env, arg);
7a387fff 6401 rn = "Config3";
90f12d73 6402 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6403 ctx->base.is_jmp = DISAS_STOP;
7a387fff 6404 break;
b4160af1
PJ
6405 case 4:
6406 gen_helper_mtc0_config4(cpu_env, arg);
6407 rn = "Config4";
eeb3bba8 6408 ctx->base.is_jmp = DISAS_STOP;
b4160af1 6409 break;
b4dd99a3
PJ
6410 case 5:
6411 gen_helper_mtc0_config5(cpu_env, arg);
6412 rn = "Config5";
6413 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6414 ctx->base.is_jmp = DISAS_STOP;
b4dd99a3 6415 break;
e397ee33
TS
6416 /* 6,7 are implementation dependent */
6417 case 6:
6418 /* ignored */
6419 rn = "Config6";
6420 break;
6421 case 7:
6422 /* ignored */
6423 rn = "Config7";
6424 break;
8c0fdd85
TS
6425 default:
6426 rn = "Invalid config selector";
f31b035a 6427 goto cp0_unimplemented;
8c0fdd85
TS
6428 }
6429 break;
6430 case 17:
7a387fff
TS
6431 switch (sel) {
6432 case 0:
895c2d04 6433 gen_helper_mtc0_lladdr(cpu_env, arg);
2423f660
TS
6434 rn = "LLAddr";
6435 break;
f6d4dd81
YK
6436 case 1:
6437 CP0_CHECK(ctx->mrp);
6438 gen_helper_mtc0_maar(cpu_env, arg);
6439 rn = "MAAR";
6440 break;
6441 case 2:
6442 CP0_CHECK(ctx->mrp);
6443 gen_helper_mtc0_maari(cpu_env, arg);
6444 rn = "MAARI";
6445 break;
7a387fff 6446 default:
f31b035a 6447 goto cp0_unimplemented;
7a387fff 6448 }
8c0fdd85
TS
6449 break;
6450 case 18:
7a387fff 6451 switch (sel) {
c2e19f3c
AM
6452 case 0:
6453 case 1:
6454 case 2:
6455 case 3:
6456 case 4:
6457 case 5:
6458 case 6:
6459 case 7:
fa192d49 6460 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 6461 gen_helper_0e1i(mtc0_watchlo, arg, sel);
2423f660
TS
6462 rn = "WatchLo";
6463 break;
7a387fff 6464 default:
f31b035a 6465 goto cp0_unimplemented;
7a387fff 6466 }
8c0fdd85
TS
6467 break;
6468 case 19:
7a387fff 6469 switch (sel) {
c2e19f3c
AM
6470 case 0:
6471 case 1:
6472 case 2:
6473 case 3:
6474 case 4:
6475 case 5:
6476 case 6:
6477 case 7:
fa192d49 6478 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 6479 gen_helper_0e1i(mtc0_watchhi, arg, sel);
2423f660
TS
6480 rn = "WatchHi";
6481 break;
7a387fff 6482 default:
f31b035a 6483 goto cp0_unimplemented;
7a387fff 6484 }
8c0fdd85
TS
6485 break;
6486 case 20:
7a387fff
TS
6487 switch (sel) {
6488 case 0:
d26bc211 6489#if defined(TARGET_MIPS64)
d75c135e 6490 check_insn(ctx, ISA_MIPS3);
895c2d04 6491 gen_helper_mtc0_xcontext(cpu_env, arg);
2423f660
TS
6492 rn = "XContext";
6493 break;
703eaf37 6494#endif
7a387fff 6495 default:
f31b035a 6496 goto cp0_unimplemented;
7a387fff 6497 }
8c0fdd85
TS
6498 break;
6499 case 21:
7a387fff 6500 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 6501 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7a387fff
TS
6502 switch (sel) {
6503 case 0:
895c2d04 6504 gen_helper_mtc0_framemask(cpu_env, arg);
2423f660
TS
6505 rn = "Framemask";
6506 break;
7a387fff 6507 default:
f31b035a 6508 goto cp0_unimplemented;
7a387fff
TS
6509 }
6510 break;
8c0fdd85 6511 case 22:
7a387fff
TS
6512 /* ignored */
6513 rn = "Diagnostic"; /* implementation dependent */
2423f660 6514 break;
8c0fdd85 6515 case 23:
7a387fff
TS
6516 switch (sel) {
6517 case 0:
895c2d04 6518 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 6519 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
6520 gen_save_pc(ctx->base.pc_next + 4);
6521 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
6522 rn = "Debug";
6523 break;
7a387fff 6524 case 1:
895c2d04 6525// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
2423f660 6526 rn = "TraceControl";
8487327a 6527 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6528 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 6529 goto cp0_unimplemented;
7a387fff 6530 case 2:
895c2d04 6531// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
2423f660 6532 rn = "TraceControl2";
8487327a 6533 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6534 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 6535 goto cp0_unimplemented;
7a387fff 6536 case 3:
8487327a 6537 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6538 ctx->base.is_jmp = DISAS_STOP;
895c2d04 6539// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
2423f660 6540 rn = "UserTraceData";
8487327a 6541 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6542 ctx->base.is_jmp = DISAS_STOP;
3570d7f6 6543 goto cp0_unimplemented;
7a387fff 6544 case 4:
895c2d04 6545// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a 6546 /* Stop translation as we may have switched the execution mode */
eeb3bba8 6547 ctx->base.is_jmp = DISAS_STOP;
2423f660 6548 rn = "TraceBPC";
3570d7f6 6549 goto cp0_unimplemented;
7a387fff 6550 default:
f31b035a 6551 goto cp0_unimplemented;
7a387fff 6552 }
8c0fdd85
TS
6553 break;
6554 case 24:
7a387fff
TS
6555 switch (sel) {
6556 case 0:
f1aa6320 6557 /* EJTAG support */
d54a299b 6558 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
6559 rn = "DEPC";
6560 break;
7a387fff 6561 default:
f31b035a 6562 goto cp0_unimplemented;
7a387fff 6563 }
8c0fdd85
TS
6564 break;
6565 case 25:
7a387fff
TS
6566 switch (sel) {
6567 case 0:
895c2d04 6568 gen_helper_mtc0_performance0(cpu_env, arg);
2423f660
TS
6569 rn = "Performance0";
6570 break;
7a387fff 6571 case 1:
d9bea114 6572// gen_helper_mtc0_performance1(arg);
2423f660 6573 rn = "Performance1";
3570d7f6 6574 goto cp0_unimplemented;
7a387fff 6575 case 2:
d9bea114 6576// gen_helper_mtc0_performance2(arg);
2423f660 6577 rn = "Performance2";
3570d7f6 6578 goto cp0_unimplemented;
7a387fff 6579 case 3:
d9bea114 6580// gen_helper_mtc0_performance3(arg);
2423f660 6581 rn = "Performance3";
3570d7f6 6582 goto cp0_unimplemented;
7a387fff 6583 case 4:
d9bea114 6584// gen_helper_mtc0_performance4(arg);
2423f660 6585 rn = "Performance4";
3570d7f6 6586 goto cp0_unimplemented;
7a387fff 6587 case 5:
d9bea114 6588// gen_helper_mtc0_performance5(arg);
2423f660 6589 rn = "Performance5";
3570d7f6 6590 goto cp0_unimplemented;
7a387fff 6591 case 6:
d9bea114 6592// gen_helper_mtc0_performance6(arg);
2423f660 6593 rn = "Performance6";
3570d7f6 6594 goto cp0_unimplemented;
7a387fff 6595 case 7:
d9bea114 6596// gen_helper_mtc0_performance7(arg);
2423f660 6597 rn = "Performance7";
3570d7f6 6598 goto cp0_unimplemented;
7a387fff 6599 default:
f31b035a 6600 goto cp0_unimplemented;
7a387fff 6601 }
8c0fdd85
TS
6602 break;
6603 case 26:
0d74a222
LA
6604 switch (sel) {
6605 case 0:
6606 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 6607 ctx->base.is_jmp = DISAS_STOP;
0d74a222
LA
6608 rn = "ErrCtl";
6609 break;
6610 default:
6611 goto cp0_unimplemented;
6612 }
2423f660 6613 break;
8c0fdd85 6614 case 27:
7a387fff 6615 switch (sel) {
c2e19f3c
AM
6616 case 0:
6617 case 1:
6618 case 2:
6619 case 3:
2423f660
TS
6620 /* ignored */
6621 rn = "CacheErr";
6622 break;
7a387fff 6623 default:
f31b035a 6624 goto cp0_unimplemented;
7a387fff 6625 }
8c0fdd85
TS
6626 break;
6627 case 28:
6628 switch (sel) {
6629 case 0:
7a387fff
TS
6630 case 2:
6631 case 4:
6632 case 6:
895c2d04 6633 gen_helper_mtc0_taglo(cpu_env, arg);
8c0fdd85
TS
6634 rn = "TagLo";
6635 break;
7a387fff
TS
6636 case 1:
6637 case 3:
6638 case 5:
6639 case 7:
895c2d04 6640 gen_helper_mtc0_datalo(cpu_env, arg);
7a387fff
TS
6641 rn = "DataLo";
6642 break;
8c0fdd85 6643 default:
f31b035a 6644 goto cp0_unimplemented;
8c0fdd85
TS
6645 }
6646 break;
6647 case 29:
7a387fff
TS
6648 switch (sel) {
6649 case 0:
6650 case 2:
6651 case 4:
6652 case 6:
895c2d04 6653 gen_helper_mtc0_taghi(cpu_env, arg);
7a387fff
TS
6654 rn = "TagHi";
6655 break;
6656 case 1:
6657 case 3:
6658 case 5:
6659 case 7:
895c2d04 6660 gen_helper_mtc0_datahi(cpu_env, arg);
7a387fff
TS
6661 rn = "DataHi";
6662 break;
6663 default:
6664 rn = "invalid sel";
f31b035a 6665 goto cp0_unimplemented;
7a387fff 6666 }
8c0fdd85
TS
6667 break;
6668 case 30:
7a387fff
TS
6669 switch (sel) {
6670 case 0:
d54a299b 6671 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
6672 rn = "ErrorEPC";
6673 break;
7a387fff 6674 default:
f31b035a 6675 goto cp0_unimplemented;
7a387fff 6676 }
8c0fdd85
TS
6677 break;
6678 case 31:
7a387fff
TS
6679 switch (sel) {
6680 case 0:
f1aa6320 6681 /* EJTAG support */
7db13fae 6682 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
6683 rn = "DESAVE";
6684 break;
c2e19f3c
AM
6685 case 2:
6686 case 3:
6687 case 4:
6688 case 5:
6689 case 6:
6690 case 7:
f31b035a
LA
6691 CP0_CHECK(ctx->kscrexist & (1 << sel));
6692 tcg_gen_st_tl(arg, cpu_env,
6693 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6694 rn = "KScratch";
e98c0d17 6695 break;
7a387fff 6696 default:
f31b035a 6697 goto cp0_unimplemented;
7a387fff 6698 }
8c0fdd85
TS
6699 break;
6700 default:
f31b035a 6701 goto cp0_unimplemented;
8c0fdd85 6702 }
b44a7fb1
PMD
6703 trace_mips_translate_c0("mtc0", rn, reg, sel);
6704
bf20dc07 6705 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 6706 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6707 gen_io_end();
b28425ba 6708 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
b74cddcb 6709 * translated code to check for pending interrupts. */
eeb3bba8
EC
6710 gen_save_pc(ctx->base.pc_next + 4);
6711 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 6712 }
8c0fdd85
TS
6713 return;
6714
f31b035a 6715cp0_unimplemented:
965447ee 6716 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8c0fdd85
TS
6717}
6718
d26bc211 6719#if defined(TARGET_MIPS64)
d75c135e 6720static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
6721{
6722 const char *rn = "invalid";
6723
e189e748 6724 if (sel != 0)
d75c135e 6725 check_insn(ctx, ISA_MIPS64);
e189e748 6726
9c2149c8
TS
6727 switch (reg) {
6728 case 0:
6729 switch (sel) {
6730 case 0:
7db13fae 6731 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
9c2149c8
TS
6732 rn = "Index";
6733 break;
6734 case 1:
f31b035a 6735 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6736 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
9c2149c8 6737 rn = "MVPControl";
ead9360e 6738 break;
9c2149c8 6739 case 2:
f31b035a 6740 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6741 gen_helper_mfc0_mvpconf0(arg, cpu_env);
9c2149c8 6742 rn = "MVPConf0";
ead9360e 6743 break;
9c2149c8 6744 case 3:
f31b035a 6745 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6746 gen_helper_mfc0_mvpconf1(arg, cpu_env);
9c2149c8 6747 rn = "MVPConf1";
ead9360e 6748 break;
01bc435b
YK
6749 case 4:
6750 CP0_CHECK(ctx->vp);
6751 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6752 rn = "VPControl";
6753 break;
9c2149c8 6754 default:
f31b035a 6755 goto cp0_unimplemented;
9c2149c8
TS
6756 }
6757 break;
6758 case 1:
6759 switch (sel) {
6760 case 0:
f31b035a 6761 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
895c2d04 6762 gen_helper_mfc0_random(arg, cpu_env);
9c2149c8 6763 rn = "Random";
2423f660 6764 break;
9c2149c8 6765 case 1:
f31b035a 6766 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6767 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
9c2149c8 6768 rn = "VPEControl";
ead9360e 6769 break;
9c2149c8 6770 case 2:
f31b035a 6771 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6772 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
9c2149c8 6773 rn = "VPEConf0";
ead9360e 6774 break;
9c2149c8 6775 case 3:
f31b035a 6776 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6777 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
9c2149c8 6778 rn = "VPEConf1";
ead9360e 6779 break;
9c2149c8 6780 case 4:
f31b035a 6781 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6782 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
9c2149c8 6783 rn = "YQMask";
ead9360e 6784 break;
9c2149c8 6785 case 5:
f31b035a 6786 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6787 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 6788 rn = "VPESchedule";
ead9360e 6789 break;
9c2149c8 6790 case 6:
f31b035a 6791 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6792 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 6793 rn = "VPEScheFBack";
ead9360e 6794 break;
9c2149c8 6795 case 7:
f31b035a 6796 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 6797 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
9c2149c8 6798 rn = "VPEOpt";
ead9360e 6799 break;
9c2149c8 6800 default:
f31b035a 6801 goto cp0_unimplemented;
9c2149c8
TS
6802 }
6803 break;
6804 case 2:
6805 switch (sel) {
6806 case 0:
7db13fae 6807 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
2423f660
TS
6808 rn = "EntryLo0";
6809 break;
9c2149c8 6810 case 1:
f31b035a 6811 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6812 gen_helper_mfc0_tcstatus(arg, cpu_env);
2423f660 6813 rn = "TCStatus";
ead9360e 6814 break;
9c2149c8 6815 case 2:
f31b035a 6816 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6817 gen_helper_mfc0_tcbind(arg, cpu_env);
2423f660 6818 rn = "TCBind";
ead9360e 6819 break;
9c2149c8 6820 case 3:
f31b035a 6821 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6822 gen_helper_dmfc0_tcrestart(arg, cpu_env);
2423f660 6823 rn = "TCRestart";
ead9360e 6824 break;
9c2149c8 6825 case 4:
f31b035a 6826 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6827 gen_helper_dmfc0_tchalt(arg, cpu_env);
2423f660 6828 rn = "TCHalt";
ead9360e 6829 break;
9c2149c8 6830 case 5:
f31b035a 6831 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6832 gen_helper_dmfc0_tccontext(arg, cpu_env);
2423f660 6833 rn = "TCContext";
ead9360e 6834 break;
9c2149c8 6835 case 6:
f31b035a 6836 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6837 gen_helper_dmfc0_tcschedule(arg, cpu_env);
2423f660 6838 rn = "TCSchedule";
ead9360e 6839 break;
9c2149c8 6840 case 7:
f31b035a 6841 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 6842 gen_helper_dmfc0_tcschefback(arg, cpu_env);
2423f660 6843 rn = "TCScheFBack";
ead9360e 6844 break;
9c2149c8 6845 default:
f31b035a 6846 goto cp0_unimplemented;
9c2149c8
TS
6847 }
6848 break;
6849 case 3:
6850 switch (sel) {
6851 case 0:
7db13fae 6852 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
2423f660
TS
6853 rn = "EntryLo1";
6854 break;
01bc435b
YK
6855 case 1:
6856 CP0_CHECK(ctx->vp);
6857 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6858 rn = "GlobalNumber";
6859 break;
9c2149c8 6860 default:
f31b035a 6861 goto cp0_unimplemented;
1579a72e 6862 }
9c2149c8
TS
6863 break;
6864 case 4:
6865 switch (sel) {
6866 case 0:
7db13fae 6867 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
2423f660
TS
6868 rn = "Context";
6869 break;
9c2149c8 6870 case 1:
d9bea114 6871// gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660 6872 rn = "ContextConfig";
f31b035a 6873 goto cp0_unimplemented;
d279279e 6874 case 2:
f31b035a
LA
6875 CP0_CHECK(ctx->ulri);
6876 tcg_gen_ld_tl(arg, cpu_env,
6877 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6878 rn = "UserLocal";
d279279e 6879 break;
9c2149c8 6880 default:
f31b035a 6881 goto cp0_unimplemented;
876d4b07 6882 }
9c2149c8
TS
6883 break;
6884 case 5:
6885 switch (sel) {
6886 case 0:
7db13fae 6887 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
2423f660
TS
6888 rn = "PageMask";
6889 break;
9c2149c8 6890 case 1:
d75c135e 6891 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6892 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
2423f660
TS
6893 rn = "PageGrain";
6894 break;
cec56a73
JH
6895 case 2:
6896 CP0_CHECK(ctx->sc);
6897 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6898 rn = "SegCtl0";
6899 break;
6900 case 3:
6901 CP0_CHECK(ctx->sc);
6902 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6903 rn = "SegCtl1";
6904 break;
6905 case 4:
6906 CP0_CHECK(ctx->sc);
6907 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6908 rn = "SegCtl2";
6909 break;
9c2149c8 6910 default:
f31b035a 6911 goto cp0_unimplemented;
876d4b07 6912 }
9c2149c8
TS
6913 break;
6914 case 6:
6915 switch (sel) {
6916 case 0:
7db13fae 6917 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
2423f660
TS
6918 rn = "Wired";
6919 break;
9c2149c8 6920 case 1:
d75c135e 6921 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6922 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
2423f660 6923 rn = "SRSConf0";
ead9360e 6924 break;
9c2149c8 6925 case 2:
d75c135e 6926 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6927 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
2423f660 6928 rn = "SRSConf1";
ead9360e 6929 break;
9c2149c8 6930 case 3:
d75c135e 6931 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6932 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
2423f660 6933 rn = "SRSConf2";
ead9360e 6934 break;
9c2149c8 6935 case 4:
d75c135e 6936 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6937 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
2423f660 6938 rn = "SRSConf3";
ead9360e 6939 break;
9c2149c8 6940 case 5:
d75c135e 6941 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6942 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
2423f660 6943 rn = "SRSConf4";
ead9360e 6944 break;
9c2149c8 6945 default:
f31b035a 6946 goto cp0_unimplemented;
876d4b07 6947 }
9c2149c8
TS
6948 break;
6949 case 7:
6950 switch (sel) {
6951 case 0:
d75c135e 6952 check_insn(ctx, ISA_MIPS32R2);
7db13fae 6953 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
2423f660
TS
6954 rn = "HWREna";
6955 break;
9c2149c8 6956 default:
f31b035a 6957 goto cp0_unimplemented;
876d4b07 6958 }
9c2149c8
TS
6959 break;
6960 case 8:
6961 switch (sel) {
6962 case 0:
7db13fae 6963 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
f0b3f3ae 6964 rn = "BadVAddr";
2423f660 6965 break;
aea14095 6966 case 1:
f31b035a
LA
6967 CP0_CHECK(ctx->bi);
6968 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6969 rn = "BadInstr";
aea14095
LA
6970 break;
6971 case 2:
f31b035a
LA
6972 CP0_CHECK(ctx->bp);
6973 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6974 rn = "BadInstrP";
aea14095 6975 break;
25beba9b
SM
6976 case 3:
6977 CP0_CHECK(ctx->bi);
6978 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6979 tcg_gen_andi_tl(arg, arg, ~0xffff);
6980 rn = "BadInstrX";
6981 break;
9c2149c8 6982 default:
f31b035a 6983 goto cp0_unimplemented;
876d4b07 6984 }
9c2149c8
TS
6985 break;
6986 case 9:
6987 switch (sel) {
6988 case 0:
2e70f6ef 6989 /* Mark as an IO operation because we read the time. */
eeb3bba8 6990 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6991 gen_io_start();
bd79255d 6992 }
895c2d04 6993 gen_helper_mfc0_count(arg, cpu_env);
eeb3bba8 6994 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6995 gen_io_end();
2e70f6ef 6996 }
55807224 6997 /* Break the TB to be able to take timer interrupts immediately
b28425ba
EC
6998 after reading count. DISAS_STOP isn't sufficient, we need to
6999 ensure we break completely out of translated code. */
eeb3bba8
EC
7000 gen_save_pc(ctx->base.pc_next + 4);
7001 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
7002 rn = "Count";
7003 break;
7004 /* 6,7 are implementation dependent */
9c2149c8 7005 default:
f31b035a 7006 goto cp0_unimplemented;
876d4b07 7007 }
9c2149c8
TS
7008 break;
7009 case 10:
7010 switch (sel) {
7011 case 0:
7db13fae 7012 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
2423f660
TS
7013 rn = "EntryHi";
7014 break;
9c2149c8 7015 default:
f31b035a 7016 goto cp0_unimplemented;
876d4b07 7017 }
9c2149c8
TS
7018 break;
7019 case 11:
7020 switch (sel) {
7021 case 0:
7db13fae 7022 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
2423f660
TS
7023 rn = "Compare";
7024 break;
876d4b07 7025 /* 6,7 are implementation dependent */
9c2149c8 7026 default:
f31b035a 7027 goto cp0_unimplemented;
876d4b07 7028 }
9c2149c8
TS
7029 break;
7030 case 12:
7031 switch (sel) {
7032 case 0:
7db13fae 7033 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
2423f660
TS
7034 rn = "Status";
7035 break;
9c2149c8 7036 case 1:
d75c135e 7037 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7038 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
2423f660
TS
7039 rn = "IntCtl";
7040 break;
9c2149c8 7041 case 2:
d75c135e 7042 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7043 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
2423f660
TS
7044 rn = "SRSCtl";
7045 break;
9c2149c8 7046 case 3:
d75c135e 7047 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7048 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
2423f660
TS
7049 rn = "SRSMap";
7050 break;
9c2149c8 7051 default:
f31b035a 7052 goto cp0_unimplemented;
876d4b07 7053 }
9c2149c8
TS
7054 break;
7055 case 13:
7056 switch (sel) {
7057 case 0:
7db13fae 7058 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
2423f660
TS
7059 rn = "Cause";
7060 break;
9c2149c8 7061 default:
f31b035a 7062 goto cp0_unimplemented;
876d4b07 7063 }
9c2149c8
TS
7064 break;
7065 case 14:
7066 switch (sel) {
7067 case 0:
7db13fae 7068 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
7069 rn = "EPC";
7070 break;
9c2149c8 7071 default:
f31b035a 7072 goto cp0_unimplemented;
876d4b07 7073 }
9c2149c8
TS
7074 break;
7075 case 15:
7076 switch (sel) {
7077 case 0:
7db13fae 7078 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
2423f660
TS
7079 rn = "PRid";
7080 break;
9c2149c8 7081 case 1:
d75c135e 7082 check_insn(ctx, ISA_MIPS32R2);
74dbf824 7083 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
2423f660
TS
7084 rn = "EBase";
7085 break;
c870e3f5
YK
7086 case 3:
7087 check_insn(ctx, ISA_MIPS32R2);
7088 CP0_CHECK(ctx->cmgcr);
7089 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7090 rn = "CMGCRBase";
7091 break;
9c2149c8 7092 default:
f31b035a 7093 goto cp0_unimplemented;
876d4b07 7094 }
9c2149c8
TS
7095 break;
7096 case 16:
7097 switch (sel) {
7098 case 0:
7db13fae 7099 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
9c2149c8
TS
7100 rn = "Config";
7101 break;
7102 case 1:
7db13fae 7103 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
9c2149c8
TS
7104 rn = "Config1";
7105 break;
7106 case 2:
7db13fae 7107 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
9c2149c8
TS
7108 rn = "Config2";
7109 break;
7110 case 3:
7db13fae 7111 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
9c2149c8
TS
7112 rn = "Config3";
7113 break;
faf1f68b
LA
7114 case 4:
7115 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7116 rn = "Config4";
7117 break;
7118 case 5:
7119 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7120 rn = "Config5";
7121 break;
9c2149c8 7122 /* 6,7 are implementation dependent */
f0b3f3ae 7123 case 6:
7db13fae 7124 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
f0b3f3ae
TS
7125 rn = "Config6";
7126 break;
7127 case 7:
7db13fae 7128 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
f0b3f3ae
TS
7129 rn = "Config7";
7130 break;
9c2149c8 7131 default:
f31b035a 7132 goto cp0_unimplemented;
9c2149c8
TS
7133 }
7134 break;
7135 case 17:
7136 switch (sel) {
7137 case 0:
895c2d04 7138 gen_helper_dmfc0_lladdr(arg, cpu_env);
2423f660
TS
7139 rn = "LLAddr";
7140 break;
f6d4dd81
YK
7141 case 1:
7142 CP0_CHECK(ctx->mrp);
7143 gen_helper_dmfc0_maar(arg, cpu_env);
7144 rn = "MAAR";
7145 break;
7146 case 2:
7147 CP0_CHECK(ctx->mrp);
7148 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7149 rn = "MAARI";
7150 break;
9c2149c8 7151 default:
f31b035a 7152 goto cp0_unimplemented;
9c2149c8
TS
7153 }
7154 break;
7155 case 18:
7156 switch (sel) {
c2e19f3c
AM
7157 case 0:
7158 case 1:
7159 case 2:
7160 case 3:
7161 case 4:
7162 case 5:
7163 case 6:
7164 case 7:
fa192d49 7165 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7166 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
2423f660
TS
7167 rn = "WatchLo";
7168 break;
9c2149c8 7169 default:
f31b035a 7170 goto cp0_unimplemented;
9c2149c8
TS
7171 }
7172 break;
7173 case 19:
7174 switch (sel) {
c2e19f3c
AM
7175 case 0:
7176 case 1:
7177 case 2:
7178 case 3:
7179 case 4:
7180 case 5:
7181 case 6:
7182 case 7:
fa192d49 7183 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7184 gen_helper_1e0i(mfc0_watchhi, arg, sel);
2423f660
TS
7185 rn = "WatchHi";
7186 break;
9c2149c8 7187 default:
f31b035a 7188 goto cp0_unimplemented;
9c2149c8
TS
7189 }
7190 break;
7191 case 20:
7192 switch (sel) {
7193 case 0:
d75c135e 7194 check_insn(ctx, ISA_MIPS3);
7db13fae 7195 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
2423f660
TS
7196 rn = "XContext";
7197 break;
9c2149c8 7198 default:
f31b035a 7199 goto cp0_unimplemented;
9c2149c8
TS
7200 }
7201 break;
7202 case 21:
7203 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 7204 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
7205 switch (sel) {
7206 case 0:
7db13fae 7207 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
2423f660
TS
7208 rn = "Framemask";
7209 break;
9c2149c8 7210 default:
f31b035a 7211 goto cp0_unimplemented;
9c2149c8
TS
7212 }
7213 break;
7214 case 22:
d9bea114 7215 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
7216 rn = "'Diagnostic"; /* implementation dependent */
7217 break;
9c2149c8
TS
7218 case 23:
7219 switch (sel) {
7220 case 0:
895c2d04 7221 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
2423f660
TS
7222 rn = "Debug";
7223 break;
9c2149c8 7224 case 1:
895c2d04 7225// gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
2423f660 7226 rn = "TraceControl";
3570d7f6 7227 goto cp0_unimplemented;
9c2149c8 7228 case 2:
895c2d04 7229// gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
2423f660 7230 rn = "TraceControl2";
3570d7f6 7231 goto cp0_unimplemented;
9c2149c8 7232 case 3:
895c2d04 7233// gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
2423f660 7234 rn = "UserTraceData";
3570d7f6 7235 goto cp0_unimplemented;
9c2149c8 7236 case 4:
895c2d04 7237// gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
2423f660 7238 rn = "TraceBPC";
3570d7f6 7239 goto cp0_unimplemented;
9c2149c8 7240 default:
f31b035a 7241 goto cp0_unimplemented;
9c2149c8
TS
7242 }
7243 break;
7244 case 24:
7245 switch (sel) {
7246 case 0:
f0b3f3ae 7247 /* EJTAG support */
7db13fae 7248 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
7249 rn = "DEPC";
7250 break;
9c2149c8 7251 default:
f31b035a 7252 goto cp0_unimplemented;
9c2149c8
TS
7253 }
7254 break;
7255 case 25:
7256 switch (sel) {
7257 case 0:
7db13fae 7258 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
2423f660 7259 rn = "Performance0";
9c2149c8
TS
7260 break;
7261 case 1:
d9bea114 7262// gen_helper_dmfc0_performance1(arg);
2423f660 7263 rn = "Performance1";
3570d7f6 7264 goto cp0_unimplemented;
9c2149c8 7265 case 2:
d9bea114 7266// gen_helper_dmfc0_performance2(arg);
2423f660 7267 rn = "Performance2";
3570d7f6 7268 goto cp0_unimplemented;
9c2149c8 7269 case 3:
d9bea114 7270// gen_helper_dmfc0_performance3(arg);
2423f660 7271 rn = "Performance3";
3570d7f6 7272 goto cp0_unimplemented;
9c2149c8 7273 case 4:
d9bea114 7274// gen_helper_dmfc0_performance4(arg);
2423f660 7275 rn = "Performance4";
3570d7f6 7276 goto cp0_unimplemented;
9c2149c8 7277 case 5:
d9bea114 7278// gen_helper_dmfc0_performance5(arg);
2423f660 7279 rn = "Performance5";
3570d7f6 7280 goto cp0_unimplemented;
9c2149c8 7281 case 6:
d9bea114 7282// gen_helper_dmfc0_performance6(arg);
2423f660 7283 rn = "Performance6";
3570d7f6 7284 goto cp0_unimplemented;
9c2149c8 7285 case 7:
d9bea114 7286// gen_helper_dmfc0_performance7(arg);
2423f660 7287 rn = "Performance7";
3570d7f6 7288 goto cp0_unimplemented;
9c2149c8 7289 default:
f31b035a 7290 goto cp0_unimplemented;
9c2149c8
TS
7291 }
7292 break;
7293 case 26:
0d74a222
LA
7294 switch (sel) {
7295 case 0:
7296 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7297 rn = "ErrCtl";
7298 break;
7299 default:
7300 goto cp0_unimplemented;
7301 }
da80682b 7302 break;
9c2149c8
TS
7303 case 27:
7304 switch (sel) {
7305 /* ignored */
c2e19f3c
AM
7306 case 0:
7307 case 1:
7308 case 2:
7309 case 3:
d9bea114 7310 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
7311 rn = "CacheErr";
7312 break;
9c2149c8 7313 default:
f31b035a 7314 goto cp0_unimplemented;
9c2149c8
TS
7315 }
7316 break;
7317 case 28:
7318 switch (sel) {
7319 case 0:
7320 case 2:
7321 case 4:
7322 case 6:
7db13fae 7323 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9c2149c8
TS
7324 rn = "TagLo";
7325 break;
7326 case 1:
7327 case 3:
7328 case 5:
7329 case 7:
7db13fae 7330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9c2149c8
TS
7331 rn = "DataLo";
7332 break;
7333 default:
f31b035a 7334 goto cp0_unimplemented;
9c2149c8
TS
7335 }
7336 break;
7337 case 29:
7338 switch (sel) {
7339 case 0:
7340 case 2:
7341 case 4:
7342 case 6:
7db13fae 7343 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9c2149c8
TS
7344 rn = "TagHi";
7345 break;
7346 case 1:
7347 case 3:
7348 case 5:
7349 case 7:
7db13fae 7350 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9c2149c8
TS
7351 rn = "DataHi";
7352 break;
7353 default:
f31b035a 7354 goto cp0_unimplemented;
9c2149c8
TS
7355 }
7356 break;
7357 case 30:
7358 switch (sel) {
7359 case 0:
7db13fae 7360 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
7361 rn = "ErrorEPC";
7362 break;
9c2149c8 7363 default:
f31b035a 7364 goto cp0_unimplemented;
9c2149c8
TS
7365 }
7366 break;
7367 case 31:
7368 switch (sel) {
7369 case 0:
f0b3f3ae 7370 /* EJTAG support */
7db13fae 7371 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
7372 rn = "DESAVE";
7373 break;
c2e19f3c
AM
7374 case 2:
7375 case 3:
7376 case 4:
7377 case 5:
7378 case 6:
7379 case 7:
f31b035a
LA
7380 CP0_CHECK(ctx->kscrexist & (1 << sel));
7381 tcg_gen_ld_tl(arg, cpu_env,
7382 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7383 rn = "KScratch";
e98c0d17 7384 break;
9c2149c8 7385 default:
f31b035a 7386 goto cp0_unimplemented;
9c2149c8
TS
7387 }
7388 break;
7389 default:
f31b035a 7390 goto cp0_unimplemented;
9c2149c8 7391 }
b44a7fb1 7392 trace_mips_translate_c0("dmfc0", rn, reg, sel);
9c2149c8
TS
7393 return;
7394
f31b035a 7395cp0_unimplemented:
965447ee 7396 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
f31b035a 7397 gen_mfc0_unimplemented(ctx, arg);
9c2149c8
TS
7398}
7399
d75c135e 7400static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
7401{
7402 const char *rn = "invalid";
7403
e189e748 7404 if (sel != 0)
d75c135e 7405 check_insn(ctx, ISA_MIPS64);
e189e748 7406
eeb3bba8 7407 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 7408 gen_io_start();
bd79255d 7409 }
2e70f6ef 7410
9c2149c8
TS
7411 switch (reg) {
7412 case 0:
7413 switch (sel) {
7414 case 0:
895c2d04 7415 gen_helper_mtc0_index(cpu_env, arg);
9c2149c8
TS
7416 rn = "Index";
7417 break;
7418 case 1:
f31b035a 7419 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7420 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9c2149c8 7421 rn = "MVPControl";
ead9360e 7422 break;
9c2149c8 7423 case 2:
f31b035a 7424 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7425 /* ignored */
9c2149c8 7426 rn = "MVPConf0";
ead9360e 7427 break;
9c2149c8 7428 case 3:
f31b035a 7429 CP0_CHECK(ctx->insn_flags & ASE_MT);
ead9360e 7430 /* ignored */
9c2149c8 7431 rn = "MVPConf1";
ead9360e 7432 break;
01bc435b
YK
7433 case 4:
7434 CP0_CHECK(ctx->vp);
7435 /* ignored */
7436 rn = "VPControl";
7437 break;
9c2149c8 7438 default:
f31b035a 7439 goto cp0_unimplemented;
9c2149c8
TS
7440 }
7441 break;
7442 case 1:
7443 switch (sel) {
7444 case 0:
2423f660 7445 /* ignored */
9c2149c8 7446 rn = "Random";
2423f660 7447 break;
9c2149c8 7448 case 1:
f31b035a 7449 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7450 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9c2149c8 7451 rn = "VPEControl";
ead9360e 7452 break;
9c2149c8 7453 case 2:
f31b035a 7454 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7455 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9c2149c8 7456 rn = "VPEConf0";
ead9360e 7457 break;
9c2149c8 7458 case 3:
f31b035a 7459 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7460 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9c2149c8 7461 rn = "VPEConf1";
ead9360e 7462 break;
9c2149c8 7463 case 4:
f31b035a 7464 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7465 gen_helper_mtc0_yqmask(cpu_env, arg);
9c2149c8 7466 rn = "YQMask";
ead9360e 7467 break;
9c2149c8 7468 case 5:
f31b035a 7469 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7470 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9c2149c8 7471 rn = "VPESchedule";
ead9360e 7472 break;
9c2149c8 7473 case 6:
f31b035a 7474 CP0_CHECK(ctx->insn_flags & ASE_MT);
7db13fae 7475 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9c2149c8 7476 rn = "VPEScheFBack";
ead9360e 7477 break;
9c2149c8 7478 case 7:
f31b035a 7479 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7480 gen_helper_mtc0_vpeopt(cpu_env, arg);
9c2149c8 7481 rn = "VPEOpt";
ead9360e 7482 break;
9c2149c8 7483 default:
f31b035a 7484 goto cp0_unimplemented;
9c2149c8
TS
7485 }
7486 break;
7487 case 2:
7488 switch (sel) {
7489 case 0:
7207c7f9 7490 gen_helper_dmtc0_entrylo0(cpu_env, arg);
2423f660
TS
7491 rn = "EntryLo0";
7492 break;
9c2149c8 7493 case 1:
f31b035a 7494 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7495 gen_helper_mtc0_tcstatus(cpu_env, arg);
2423f660 7496 rn = "TCStatus";
ead9360e 7497 break;
9c2149c8 7498 case 2:
f31b035a 7499 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7500 gen_helper_mtc0_tcbind(cpu_env, arg);
2423f660 7501 rn = "TCBind";
ead9360e 7502 break;
9c2149c8 7503 case 3:
f31b035a 7504 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7505 gen_helper_mtc0_tcrestart(cpu_env, arg);
2423f660 7506 rn = "TCRestart";
ead9360e 7507 break;
9c2149c8 7508 case 4:
f31b035a 7509 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7510 gen_helper_mtc0_tchalt(cpu_env, arg);
2423f660 7511 rn = "TCHalt";
ead9360e 7512 break;
9c2149c8 7513 case 5:
f31b035a 7514 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7515 gen_helper_mtc0_tccontext(cpu_env, arg);
2423f660 7516 rn = "TCContext";
ead9360e 7517 break;
9c2149c8 7518 case 6:
f31b035a 7519 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7520 gen_helper_mtc0_tcschedule(cpu_env, arg);
2423f660 7521 rn = "TCSchedule";
ead9360e 7522 break;
9c2149c8 7523 case 7:
f31b035a 7524 CP0_CHECK(ctx->insn_flags & ASE_MT);
895c2d04 7525 gen_helper_mtc0_tcschefback(cpu_env, arg);
2423f660 7526 rn = "TCScheFBack";
ead9360e 7527 break;
9c2149c8 7528 default:
f31b035a 7529 goto cp0_unimplemented;
9c2149c8
TS
7530 }
7531 break;
7532 case 3:
7533 switch (sel) {
7534 case 0:
7207c7f9 7535 gen_helper_dmtc0_entrylo1(cpu_env, arg);
2423f660
TS
7536 rn = "EntryLo1";
7537 break;
01bc435b
YK
7538 case 1:
7539 CP0_CHECK(ctx->vp);
7540 /* ignored */
7541 rn = "GlobalNumber";
7542 break;
9c2149c8 7543 default:
f31b035a 7544 goto cp0_unimplemented;
876d4b07 7545 }
9c2149c8
TS
7546 break;
7547 case 4:
7548 switch (sel) {
7549 case 0:
895c2d04 7550 gen_helper_mtc0_context(cpu_env, arg);
2423f660
TS
7551 rn = "Context";
7552 break;
9c2149c8 7553 case 1:
895c2d04 7554// gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
2423f660 7555 rn = "ContextConfig";
f31b035a 7556 goto cp0_unimplemented;
d279279e 7557 case 2:
f31b035a
LA
7558 CP0_CHECK(ctx->ulri);
7559 tcg_gen_st_tl(arg, cpu_env,
7560 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7561 rn = "UserLocal";
d279279e 7562 break;
9c2149c8 7563 default:
f31b035a 7564 goto cp0_unimplemented;
876d4b07 7565 }
9c2149c8
TS
7566 break;
7567 case 5:
7568 switch (sel) {
7569 case 0:
895c2d04 7570 gen_helper_mtc0_pagemask(cpu_env, arg);
2423f660
TS
7571 rn = "PageMask";
7572 break;
9c2149c8 7573 case 1:
d75c135e 7574 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7575 gen_helper_mtc0_pagegrain(cpu_env, arg);
2423f660
TS
7576 rn = "PageGrain";
7577 break;
cec56a73
JH
7578 case 2:
7579 CP0_CHECK(ctx->sc);
7580 gen_helper_mtc0_segctl0(cpu_env, arg);
7581 rn = "SegCtl0";
7582 break;
7583 case 3:
7584 CP0_CHECK(ctx->sc);
7585 gen_helper_mtc0_segctl1(cpu_env, arg);
7586 rn = "SegCtl1";
7587 break;
7588 case 4:
7589 CP0_CHECK(ctx->sc);
7590 gen_helper_mtc0_segctl2(cpu_env, arg);
7591 rn = "SegCtl2";
7592 break;
9c2149c8 7593 default:
f31b035a 7594 goto cp0_unimplemented;
876d4b07 7595 }
9c2149c8
TS
7596 break;
7597 case 6:
7598 switch (sel) {
7599 case 0:
895c2d04 7600 gen_helper_mtc0_wired(cpu_env, arg);
2423f660
TS
7601 rn = "Wired";
7602 break;
9c2149c8 7603 case 1:
d75c135e 7604 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7605 gen_helper_mtc0_srsconf0(cpu_env, arg);
2423f660 7606 rn = "SRSConf0";
ead9360e 7607 break;
9c2149c8 7608 case 2:
d75c135e 7609 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7610 gen_helper_mtc0_srsconf1(cpu_env, arg);
2423f660 7611 rn = "SRSConf1";
ead9360e 7612 break;
9c2149c8 7613 case 3:
d75c135e 7614 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7615 gen_helper_mtc0_srsconf2(cpu_env, arg);
2423f660 7616 rn = "SRSConf2";
ead9360e 7617 break;
9c2149c8 7618 case 4:
d75c135e 7619 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7620 gen_helper_mtc0_srsconf3(cpu_env, arg);
2423f660 7621 rn = "SRSConf3";
ead9360e 7622 break;
9c2149c8 7623 case 5:
d75c135e 7624 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7625 gen_helper_mtc0_srsconf4(cpu_env, arg);
2423f660 7626 rn = "SRSConf4";
ead9360e 7627 break;
9c2149c8 7628 default:
f31b035a 7629 goto cp0_unimplemented;
876d4b07 7630 }
9c2149c8
TS
7631 break;
7632 case 7:
7633 switch (sel) {
7634 case 0:
d75c135e 7635 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7636 gen_helper_mtc0_hwrena(cpu_env, arg);
eeb3bba8 7637 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
7638 rn = "HWREna";
7639 break;
9c2149c8 7640 default:
f31b035a 7641 goto cp0_unimplemented;
876d4b07 7642 }
9c2149c8
TS
7643 break;
7644 case 8:
aea14095
LA
7645 switch (sel) {
7646 case 0:
7647 /* ignored */
7648 rn = "BadVAddr";
7649 break;
7650 case 1:
7651 /* ignored */
7652 rn = "BadInstr";
7653 break;
7654 case 2:
7655 /* ignored */
7656 rn = "BadInstrP";
7657 break;
25beba9b
SM
7658 case 3:
7659 /* ignored */
7660 rn = "BadInstrX";
7661 break;
aea14095 7662 default:
f31b035a 7663 goto cp0_unimplemented;
aea14095 7664 }
9c2149c8
TS
7665 break;
7666 case 9:
7667 switch (sel) {
7668 case 0:
895c2d04 7669 gen_helper_mtc0_count(cpu_env, arg);
2423f660
TS
7670 rn = "Count";
7671 break;
876d4b07 7672 /* 6,7 are implementation dependent */
9c2149c8 7673 default:
f31b035a 7674 goto cp0_unimplemented;
876d4b07
TS
7675 }
7676 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7677 ctx->base.is_jmp = DISAS_STOP;
9c2149c8
TS
7678 break;
7679 case 10:
7680 switch (sel) {
7681 case 0:
895c2d04 7682 gen_helper_mtc0_entryhi(cpu_env, arg);
2423f660
TS
7683 rn = "EntryHi";
7684 break;
9c2149c8 7685 default:
f31b035a 7686 goto cp0_unimplemented;
876d4b07 7687 }
9c2149c8
TS
7688 break;
7689 case 11:
7690 switch (sel) {
7691 case 0:
895c2d04 7692 gen_helper_mtc0_compare(cpu_env, arg);
2423f660
TS
7693 rn = "Compare";
7694 break;
876d4b07 7695 /* 6,7 are implementation dependent */
9c2149c8 7696 default:
f31b035a 7697 goto cp0_unimplemented;
876d4b07 7698 }
de9a95f0 7699 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7700 ctx->base.is_jmp = DISAS_STOP;
9c2149c8
TS
7701 break;
7702 case 12:
7703 switch (sel) {
7704 case 0:
867abc7e 7705 save_cpu_state(ctx, 1);
895c2d04 7706 gen_helper_mtc0_status(cpu_env, arg);
b28425ba 7707 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
7708 gen_save_pc(ctx->base.pc_next + 4);
7709 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
7710 rn = "Status";
7711 break;
9c2149c8 7712 case 1:
d75c135e 7713 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7714 gen_helper_mtc0_intctl(cpu_env, arg);
8487327a 7715 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7716 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
7717 rn = "IntCtl";
7718 break;
9c2149c8 7719 case 2:
d75c135e 7720 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7721 gen_helper_mtc0_srsctl(cpu_env, arg);
8487327a 7722 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7723 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
7724 rn = "SRSCtl";
7725 break;
9c2149c8 7726 case 3:
d75c135e 7727 check_insn(ctx, ISA_MIPS32R2);
7db13fae 7728 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8487327a 7729 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7730 ctx->base.is_jmp = DISAS_STOP;
2423f660
TS
7731 rn = "SRSMap";
7732 break;
7733 default:
f31b035a 7734 goto cp0_unimplemented;
876d4b07 7735 }
9c2149c8
TS
7736 break;
7737 case 13:
7738 switch (sel) {
7739 case 0:
867abc7e 7740 save_cpu_state(ctx, 1);
895c2d04 7741 gen_helper_mtc0_cause(cpu_env, arg);
b28425ba
EC
7742 /* Stop translation as we may have triggered an interrupt.
7743 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7744 * translated code to check for pending interrupts. */
eeb3bba8
EC
7745 gen_save_pc(ctx->base.pc_next + 4);
7746 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
7747 rn = "Cause";
7748 break;
9c2149c8 7749 default:
f31b035a 7750 goto cp0_unimplemented;
876d4b07 7751 }
9c2149c8
TS
7752 break;
7753 case 14:
7754 switch (sel) {
7755 case 0:
7db13fae 7756 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
2423f660
TS
7757 rn = "EPC";
7758 break;
9c2149c8 7759 default:
f31b035a 7760 goto cp0_unimplemented;
876d4b07 7761 }
9c2149c8
TS
7762 break;
7763 case 15:
7764 switch (sel) {
7765 case 0:
2423f660
TS
7766 /* ignored */
7767 rn = "PRid";
7768 break;
9c2149c8 7769 case 1:
d75c135e 7770 check_insn(ctx, ISA_MIPS32R2);
895c2d04 7771 gen_helper_mtc0_ebase(cpu_env, arg);
2423f660
TS
7772 rn = "EBase";
7773 break;
9c2149c8 7774 default:
f31b035a 7775 goto cp0_unimplemented;
876d4b07 7776 }
9c2149c8
TS
7777 break;
7778 case 16:
7779 switch (sel) {
7780 case 0:
895c2d04 7781 gen_helper_mtc0_config0(cpu_env, arg);
9c2149c8 7782 rn = "Config";
2423f660 7783 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7784 ctx->base.is_jmp = DISAS_STOP;
9c2149c8
TS
7785 break;
7786 case 1:
1fc7bf6e 7787 /* ignored, read only */
9c2149c8
TS
7788 rn = "Config1";
7789 break;
7790 case 2:
895c2d04 7791 gen_helper_mtc0_config2(cpu_env, arg);
9c2149c8 7792 rn = "Config2";
2423f660 7793 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7794 ctx->base.is_jmp = DISAS_STOP;
9c2149c8
TS
7795 break;
7796 case 3:
90f12d73 7797 gen_helper_mtc0_config3(cpu_env, arg);
9c2149c8 7798 rn = "Config3";
90f12d73 7799 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7800 ctx->base.is_jmp = DISAS_STOP;
9c2149c8 7801 break;
faf1f68b
LA
7802 case 4:
7803 /* currently ignored */
7804 rn = "Config4";
7805 break;
7806 case 5:
7807 gen_helper_mtc0_config5(cpu_env, arg);
7808 rn = "Config5";
7809 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7810 ctx->base.is_jmp = DISAS_STOP;
faf1f68b 7811 break;
9c2149c8
TS
7812 /* 6,7 are implementation dependent */
7813 default:
7814 rn = "Invalid config selector";
f31b035a 7815 goto cp0_unimplemented;
9c2149c8 7816 }
9c2149c8
TS
7817 break;
7818 case 17:
7819 switch (sel) {
7820 case 0:
895c2d04 7821 gen_helper_mtc0_lladdr(cpu_env, arg);
2423f660
TS
7822 rn = "LLAddr";
7823 break;
f6d4dd81
YK
7824 case 1:
7825 CP0_CHECK(ctx->mrp);
7826 gen_helper_mtc0_maar(cpu_env, arg);
7827 rn = "MAAR";
7828 break;
7829 case 2:
7830 CP0_CHECK(ctx->mrp);
7831 gen_helper_mtc0_maari(cpu_env, arg);
7832 rn = "MAARI";
7833 break;
9c2149c8 7834 default:
f31b035a 7835 goto cp0_unimplemented;
9c2149c8
TS
7836 }
7837 break;
7838 case 18:
7839 switch (sel) {
c2e19f3c
AM
7840 case 0:
7841 case 1:
7842 case 2:
7843 case 3:
7844 case 4:
7845 case 5:
7846 case 6:
7847 case 7:
fa192d49 7848 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7849 gen_helper_0e1i(mtc0_watchlo, arg, sel);
2423f660
TS
7850 rn = "WatchLo";
7851 break;
9c2149c8 7852 default:
f31b035a 7853 goto cp0_unimplemented;
9c2149c8
TS
7854 }
7855 break;
7856 case 19:
7857 switch (sel) {
c2e19f3c
AM
7858 case 0:
7859 case 1:
7860 case 2:
7861 case 3:
7862 case 4:
7863 case 5:
7864 case 6:
7865 case 7:
fa192d49 7866 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
895c2d04 7867 gen_helper_0e1i(mtc0_watchhi, arg, sel);
2423f660
TS
7868 rn = "WatchHi";
7869 break;
9c2149c8 7870 default:
f31b035a 7871 goto cp0_unimplemented;
9c2149c8
TS
7872 }
7873 break;
7874 case 20:
7875 switch (sel) {
7876 case 0:
d75c135e 7877 check_insn(ctx, ISA_MIPS3);
895c2d04 7878 gen_helper_mtc0_xcontext(cpu_env, arg);
2423f660
TS
7879 rn = "XContext";
7880 break;
9c2149c8 7881 default:
f31b035a 7882 goto cp0_unimplemented;
9c2149c8
TS
7883 }
7884 break;
7885 case 21:
7886 /* Officially reserved, but sel 0 is used for R1x000 framemask */
f31b035a 7887 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9c2149c8
TS
7888 switch (sel) {
7889 case 0:
895c2d04 7890 gen_helper_mtc0_framemask(cpu_env, arg);
2423f660
TS
7891 rn = "Framemask";
7892 break;
9c2149c8 7893 default:
f31b035a 7894 goto cp0_unimplemented;
9c2149c8
TS
7895 }
7896 break;
7897 case 22:
7898 /* ignored */
7899 rn = "Diagnostic"; /* implementation dependent */
876d4b07 7900 break;
9c2149c8
TS
7901 case 23:
7902 switch (sel) {
7903 case 0:
895c2d04 7904 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
b28425ba 7905 /* DISAS_STOP isn't good enough here, hflags may have changed. */
eeb3bba8
EC
7906 gen_save_pc(ctx->base.pc_next + 4);
7907 ctx->base.is_jmp = DISAS_EXIT;
2423f660
TS
7908 rn = "Debug";
7909 break;
9c2149c8 7910 case 1:
895c2d04 7911// gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8487327a 7912 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7913 ctx->base.is_jmp = DISAS_STOP;
2423f660 7914 rn = "TraceControl";
3570d7f6 7915 goto cp0_unimplemented;
9c2149c8 7916 case 2:
895c2d04 7917// gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8487327a 7918 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7919 ctx->base.is_jmp = DISAS_STOP;
2423f660 7920 rn = "TraceControl2";
3570d7f6 7921 goto cp0_unimplemented;
9c2149c8 7922 case 3:
895c2d04 7923// gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8487327a 7924 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7925 ctx->base.is_jmp = DISAS_STOP;
2423f660 7926 rn = "UserTraceData";
3570d7f6 7927 goto cp0_unimplemented;
9c2149c8 7928 case 4:
895c2d04 7929// gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8487327a 7930 /* Stop translation as we may have switched the execution mode */
eeb3bba8 7931 ctx->base.is_jmp = DISAS_STOP;
2423f660 7932 rn = "TraceBPC";
3570d7f6 7933 goto cp0_unimplemented;
9c2149c8 7934 default:
f31b035a 7935 goto cp0_unimplemented;
9c2149c8 7936 }
9c2149c8
TS
7937 break;
7938 case 24:
7939 switch (sel) {
7940 case 0:
f1aa6320 7941 /* EJTAG support */
7db13fae 7942 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
2423f660
TS
7943 rn = "DEPC";
7944 break;
9c2149c8 7945 default:
f31b035a 7946 goto cp0_unimplemented;
9c2149c8
TS
7947 }
7948 break;
7949 case 25:
7950 switch (sel) {
7951 case 0:
895c2d04 7952 gen_helper_mtc0_performance0(cpu_env, arg);
2423f660
TS
7953 rn = "Performance0";
7954 break;
9c2149c8 7955 case 1:
895c2d04 7956// gen_helper_mtc0_performance1(cpu_env, arg);
2423f660 7957 rn = "Performance1";
3570d7f6 7958 goto cp0_unimplemented;
9c2149c8 7959 case 2:
895c2d04 7960// gen_helper_mtc0_performance2(cpu_env, arg);
2423f660 7961 rn = "Performance2";
3570d7f6 7962 goto cp0_unimplemented;
9c2149c8 7963 case 3:
895c2d04 7964// gen_helper_mtc0_performance3(cpu_env, arg);
2423f660 7965 rn = "Performance3";
3570d7f6 7966 goto cp0_unimplemented;
9c2149c8 7967 case 4:
895c2d04 7968// gen_helper_mtc0_performance4(cpu_env, arg);
2423f660 7969 rn = "Performance4";
3570d7f6 7970 goto cp0_unimplemented;
9c2149c8 7971 case 5:
895c2d04 7972// gen_helper_mtc0_performance5(cpu_env, arg);
2423f660 7973 rn = "Performance5";
3570d7f6 7974 goto cp0_unimplemented;
9c2149c8 7975 case 6:
895c2d04 7976// gen_helper_mtc0_performance6(cpu_env, arg);
2423f660 7977 rn = "Performance6";
3570d7f6 7978 goto cp0_unimplemented;
9c2149c8 7979 case 7:
895c2d04 7980// gen_helper_mtc0_performance7(cpu_env, arg);
2423f660 7981 rn = "Performance7";
3570d7f6 7982 goto cp0_unimplemented;
9c2149c8 7983 default:
f31b035a 7984 goto cp0_unimplemented;
9c2149c8 7985 }
876d4b07 7986 break;
9c2149c8 7987 case 26:
0d74a222
LA
7988 switch (sel) {
7989 case 0:
7990 gen_helper_mtc0_errctl(cpu_env, arg);
eeb3bba8 7991 ctx->base.is_jmp = DISAS_STOP;
0d74a222
LA
7992 rn = "ErrCtl";
7993 break;
7994 default:
7995 goto cp0_unimplemented;
7996 }
876d4b07 7997 break;
9c2149c8
TS
7998 case 27:
7999 switch (sel) {
c2e19f3c
AM
8000 case 0:
8001 case 1:
8002 case 2:
8003 case 3:
2423f660
TS
8004 /* ignored */
8005 rn = "CacheErr";
8006 break;
9c2149c8 8007 default:
f31b035a 8008 goto cp0_unimplemented;
9c2149c8 8009 }
876d4b07 8010 break;
9c2149c8
TS
8011 case 28:
8012 switch (sel) {
8013 case 0:
8014 case 2:
8015 case 4:
8016 case 6:
895c2d04 8017 gen_helper_mtc0_taglo(cpu_env, arg);
9c2149c8
TS
8018 rn = "TagLo";
8019 break;
8020 case 1:
8021 case 3:
8022 case 5:
8023 case 7:
895c2d04 8024 gen_helper_mtc0_datalo(cpu_env, arg);
9c2149c8
TS
8025 rn = "DataLo";
8026 break;
8027 default:
f31b035a 8028 goto cp0_unimplemented;
9c2149c8
TS
8029 }
8030 break;
8031 case 29:
8032 switch (sel) {
8033 case 0:
8034 case 2:
8035 case 4:
8036 case 6:
895c2d04 8037 gen_helper_mtc0_taghi(cpu_env, arg);
9c2149c8
TS
8038 rn = "TagHi";
8039 break;
8040 case 1:
8041 case 3:
8042 case 5:
8043 case 7:
895c2d04 8044 gen_helper_mtc0_datahi(cpu_env, arg);
9c2149c8
TS
8045 rn = "DataHi";
8046 break;
8047 default:
8048 rn = "invalid sel";
f31b035a 8049 goto cp0_unimplemented;
9c2149c8 8050 }
876d4b07 8051 break;
9c2149c8
TS
8052 case 30:
8053 switch (sel) {
8054 case 0:
7db13fae 8055 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
2423f660
TS
8056 rn = "ErrorEPC";
8057 break;
9c2149c8 8058 default:
f31b035a 8059 goto cp0_unimplemented;
9c2149c8
TS
8060 }
8061 break;
8062 case 31:
8063 switch (sel) {
8064 case 0:
f1aa6320 8065 /* EJTAG support */
7db13fae 8066 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
2423f660
TS
8067 rn = "DESAVE";
8068 break;
c2e19f3c
AM
8069 case 2:
8070 case 3:
8071 case 4:
8072 case 5:
8073 case 6:
8074 case 7:
f31b035a
LA
8075 CP0_CHECK(ctx->kscrexist & (1 << sel));
8076 tcg_gen_st_tl(arg, cpu_env,
8077 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8078 rn = "KScratch";
e98c0d17 8079 break;
9c2149c8 8080 default:
f31b035a 8081 goto cp0_unimplemented;
9c2149c8 8082 }
9c2149c8
TS
8083 break;
8084 default:
f31b035a 8085 goto cp0_unimplemented;
9c2149c8 8086 }
b44a7fb1
PMD
8087 trace_mips_translate_c0("dmtc0", rn, reg, sel);
8088
bf20dc07 8089 /* For simplicity assume that all writes can cause interrupts. */
eeb3bba8 8090 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 8091 gen_io_end();
b28425ba 8092 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
b74cddcb 8093 * translated code to check for pending interrupts. */
eeb3bba8
EC
8094 gen_save_pc(ctx->base.pc_next + 4);
8095 ctx->base.is_jmp = DISAS_EXIT;
2e70f6ef 8096 }
9c2149c8
TS
8097 return;
8098
f31b035a 8099cp0_unimplemented:
965447ee 8100 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8 8101}
d26bc211 8102#endif /* TARGET_MIPS64 */
9c2149c8 8103
7db13fae 8104static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
8105 int u, int sel, int h)
8106{
8107 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 8108 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
8109
8110 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
8111 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8112 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 8113 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
8114 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8115 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 8116 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
8117 else if (u == 0) {
8118 switch (rt) {
5a25ce94
EI
8119 case 1:
8120 switch (sel) {
8121 case 1:
895c2d04 8122 gen_helper_mftc0_vpecontrol(t0, cpu_env);
5a25ce94
EI
8123 break;
8124 case 2:
895c2d04 8125 gen_helper_mftc0_vpeconf0(t0, cpu_env);
5a25ce94
EI
8126 break;
8127 default:
8128 goto die;
8129 break;
8130 }
8131 break;
ead9360e
TS
8132 case 2:
8133 switch (sel) {
8134 case 1:
895c2d04 8135 gen_helper_mftc0_tcstatus(t0, cpu_env);
ead9360e
TS
8136 break;
8137 case 2:
895c2d04 8138 gen_helper_mftc0_tcbind(t0, cpu_env);
ead9360e
TS
8139 break;
8140 case 3:
895c2d04 8141 gen_helper_mftc0_tcrestart(t0, cpu_env);
ead9360e
TS
8142 break;
8143 case 4:
895c2d04 8144 gen_helper_mftc0_tchalt(t0, cpu_env);
ead9360e
TS
8145 break;
8146 case 5:
895c2d04 8147 gen_helper_mftc0_tccontext(t0, cpu_env);
ead9360e
TS
8148 break;
8149 case 6:
895c2d04 8150 gen_helper_mftc0_tcschedule(t0, cpu_env);
ead9360e
TS
8151 break;
8152 case 7:
895c2d04 8153 gen_helper_mftc0_tcschefback(t0, cpu_env);
ead9360e
TS
8154 break;
8155 default:
d75c135e 8156 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
8157 break;
8158 }
8159 break;
8160 case 10:
8161 switch (sel) {
8162 case 0:
895c2d04 8163 gen_helper_mftc0_entryhi(t0, cpu_env);
ead9360e
TS
8164 break;
8165 default:
d75c135e 8166 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
8167 break;
8168 }
8169 case 12:
8170 switch (sel) {
8171 case 0:
895c2d04 8172 gen_helper_mftc0_status(t0, cpu_env);
ead9360e
TS
8173 break;
8174 default:
d75c135e 8175 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
8176 break;
8177 }
5a25ce94
EI
8178 case 13:
8179 switch (sel) {
8180 case 0:
895c2d04 8181 gen_helper_mftc0_cause(t0, cpu_env);
5a25ce94
EI
8182 break;
8183 default:
8184 goto die;
8185 break;
8186 }
8187 break;
8188 case 14:
8189 switch (sel) {
8190 case 0:
895c2d04 8191 gen_helper_mftc0_epc(t0, cpu_env);
5a25ce94
EI
8192 break;
8193 default:
8194 goto die;
8195 break;
8196 }
8197 break;
8198 case 15:
8199 switch (sel) {
8200 case 1:
895c2d04 8201 gen_helper_mftc0_ebase(t0, cpu_env);
5a25ce94
EI
8202 break;
8203 default:
8204 goto die;
8205 break;
8206 }
8207 break;
8208 case 16:
8209 switch (sel) {
c2e19f3c
AM
8210 case 0:
8211 case 1:
8212 case 2:
8213 case 3:
8214 case 4:
8215 case 5:
8216 case 6:
8217 case 7:
895c2d04 8218 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
5a25ce94
EI
8219 break;
8220 default:
8221 goto die;
8222 break;
8223 }
8224 break;
ead9360e
TS
8225 case 23:
8226 switch (sel) {
8227 case 0:
895c2d04 8228 gen_helper_mftc0_debug(t0, cpu_env);
ead9360e
TS
8229 break;
8230 default:
d75c135e 8231 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
8232 break;
8233 }
8234 break;
8235 default:
d75c135e 8236 gen_mfc0(ctx, t0, rt, sel);
ead9360e
TS
8237 }
8238 } else switch (sel) {
8239 /* GPR registers. */
8240 case 0:
895c2d04 8241 gen_helper_1e0i(mftgpr, t0, rt);
ead9360e
TS
8242 break;
8243 /* Auxiliary CPU registers */
8244 case 1:
8245 switch (rt) {
8246 case 0:
895c2d04 8247 gen_helper_1e0i(mftlo, t0, 0);
ead9360e
TS
8248 break;
8249 case 1:
895c2d04 8250 gen_helper_1e0i(mfthi, t0, 0);
ead9360e
TS
8251 break;
8252 case 2:
895c2d04 8253 gen_helper_1e0i(mftacx, t0, 0);
ead9360e
TS
8254 break;
8255 case 4:
895c2d04 8256 gen_helper_1e0i(mftlo, t0, 1);
ead9360e
TS
8257 break;
8258 case 5:
895c2d04 8259 gen_helper_1e0i(mfthi, t0, 1);
ead9360e
TS
8260 break;
8261 case 6:
895c2d04 8262 gen_helper_1e0i(mftacx, t0, 1);
ead9360e
TS
8263 break;
8264 case 8:
895c2d04 8265 gen_helper_1e0i(mftlo, t0, 2);
ead9360e
TS
8266 break;
8267 case 9:
895c2d04 8268 gen_helper_1e0i(mfthi, t0, 2);
ead9360e
TS
8269 break;
8270 case 10:
895c2d04 8271 gen_helper_1e0i(mftacx, t0, 2);
ead9360e
TS
8272 break;
8273 case 12:
895c2d04 8274 gen_helper_1e0i(mftlo, t0, 3);
ead9360e
TS
8275 break;
8276 case 13:
895c2d04 8277 gen_helper_1e0i(mfthi, t0, 3);
ead9360e
TS
8278 break;
8279 case 14:
895c2d04 8280 gen_helper_1e0i(mftacx, t0, 3);
ead9360e
TS
8281 break;
8282 case 16:
895c2d04 8283 gen_helper_mftdsp(t0, cpu_env);
ead9360e
TS
8284 break;
8285 default:
8286 goto die;
8287 }
8288 break;
8289 /* Floating point (COP1). */
8290 case 2:
8291 /* XXX: For now we support only a single FPU context. */
8292 if (h == 0) {
a7812ae4 8293 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 8294
7c979afd 8295 gen_load_fpr32(ctx, fp0, rt);
b6d96bed 8296 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 8297 tcg_temp_free_i32(fp0);
ead9360e 8298 } else {
a7812ae4 8299 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 8300
7f6613ce 8301 gen_load_fpr32h(ctx, fp0, rt);
b6d96bed 8302 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 8303 tcg_temp_free_i32(fp0);
ead9360e
TS
8304 }
8305 break;
8306 case 3:
8307 /* XXX: For now we support only a single FPU context. */
895c2d04 8308 gen_helper_1e0i(cfc1, t0, rt);
ead9360e
TS
8309 break;
8310 /* COP2: Not implemented. */
8311 case 4:
8312 case 5:
8313 /* fall through */
8314 default:
8315 goto die;
8316 }
b44a7fb1 8317 trace_mips_translate_tr("mftr", rt, u, sel, h);
1a3fd9c3
TS
8318 gen_store_gpr(t0, rd);
8319 tcg_temp_free(t0);
ead9360e
TS
8320 return;
8321
8322die:
1a3fd9c3 8323 tcg_temp_free(t0);
d12d51d5 8324 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9c708c7f 8325 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
8326}
8327
7db13fae 8328static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
8329 int u, int sel, int h)
8330{
8331 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 8332 TCGv t0 = tcg_temp_local_new();
ead9360e 8333
1a3fd9c3 8334 gen_load_gpr(t0, rt);
ead9360e 8335 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
8336 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8337 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
8338 /* NOP */ ;
8339 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8340 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
8341 /* NOP */ ;
8342 else if (u == 0) {
8343 switch (rd) {
5a25ce94
EI
8344 case 1:
8345 switch (sel) {
8346 case 1:
895c2d04 8347 gen_helper_mttc0_vpecontrol(cpu_env, t0);
5a25ce94
EI
8348 break;
8349 case 2:
895c2d04 8350 gen_helper_mttc0_vpeconf0(cpu_env, t0);
5a25ce94
EI
8351 break;
8352 default:
8353 goto die;
8354 break;
8355 }
8356 break;
ead9360e
TS
8357 case 2:
8358 switch (sel) {
8359 case 1:
895c2d04 8360 gen_helper_mttc0_tcstatus(cpu_env, t0);
ead9360e
TS
8361 break;
8362 case 2:
895c2d04 8363 gen_helper_mttc0_tcbind(cpu_env, t0);
ead9360e
TS
8364 break;
8365 case 3:
895c2d04 8366 gen_helper_mttc0_tcrestart(cpu_env, t0);
ead9360e
TS
8367 break;
8368 case 4:
895c2d04 8369 gen_helper_mttc0_tchalt(cpu_env, t0);
ead9360e
TS
8370 break;
8371 case 5:
895c2d04 8372 gen_helper_mttc0_tccontext(cpu_env, t0);
ead9360e
TS
8373 break;
8374 case 6:
895c2d04 8375 gen_helper_mttc0_tcschedule(cpu_env, t0);
ead9360e
TS
8376 break;
8377 case 7:
895c2d04 8378 gen_helper_mttc0_tcschefback(cpu_env, t0);
ead9360e
TS
8379 break;
8380 default:
d75c135e 8381 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
8382 break;
8383 }
8384 break;
8385 case 10:
8386 switch (sel) {
8387 case 0:
895c2d04 8388 gen_helper_mttc0_entryhi(cpu_env, t0);
ead9360e
TS
8389 break;
8390 default:
d75c135e 8391 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
8392 break;
8393 }
8394 case 12:
8395 switch (sel) {
8396 case 0:
895c2d04 8397 gen_helper_mttc0_status(cpu_env, t0);
ead9360e
TS
8398 break;
8399 default:
d75c135e 8400 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
8401 break;
8402 }
5a25ce94
EI
8403 case 13:
8404 switch (sel) {
8405 case 0:
895c2d04 8406 gen_helper_mttc0_cause(cpu_env, t0);
5a25ce94
EI
8407 break;
8408 default:
8409 goto die;
8410 break;
8411 }
8412 break;
8413 case 15:
8414 switch (sel) {
8415 case 1:
895c2d04 8416 gen_helper_mttc0_ebase(cpu_env, t0);
5a25ce94
EI
8417 break;
8418 default:
8419 goto die;
8420 break;
8421 }
8422 break;
ead9360e
TS
8423 case 23:
8424 switch (sel) {
8425 case 0:
895c2d04 8426 gen_helper_mttc0_debug(cpu_env, t0);
ead9360e
TS
8427 break;
8428 default:
d75c135e 8429 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
8430 break;
8431 }
8432 break;
8433 default:
d75c135e 8434 gen_mtc0(ctx, t0, rd, sel);
ead9360e
TS
8435 }
8436 } else switch (sel) {
8437 /* GPR registers. */
8438 case 0:
895c2d04 8439 gen_helper_0e1i(mttgpr, t0, rd);
ead9360e
TS
8440 break;
8441 /* Auxiliary CPU registers */
8442 case 1:
8443 switch (rd) {
8444 case 0:
895c2d04 8445 gen_helper_0e1i(mttlo, t0, 0);
ead9360e
TS
8446 break;
8447 case 1:
895c2d04 8448 gen_helper_0e1i(mtthi, t0, 0);
ead9360e
TS
8449 break;
8450 case 2:
895c2d04 8451 gen_helper_0e1i(mttacx, t0, 0);
ead9360e
TS
8452 break;
8453 case 4:
895c2d04 8454 gen_helper_0e1i(mttlo, t0, 1);
ead9360e
TS
8455 break;
8456 case 5:
895c2d04 8457 gen_helper_0e1i(mtthi, t0, 1);
ead9360e
TS
8458 break;
8459 case 6:
895c2d04 8460 gen_helper_0e1i(mttacx, t0, 1);
ead9360e
TS
8461 break;
8462 case 8:
895c2d04 8463 gen_helper_0e1i(mttlo, t0, 2);
ead9360e
TS
8464 break;
8465 case 9:
895c2d04 8466 gen_helper_0e1i(mtthi, t0, 2);
ead9360e
TS
8467 break;
8468 case 10:
895c2d04 8469 gen_helper_0e1i(mttacx, t0, 2);
ead9360e
TS
8470 break;
8471 case 12:
895c2d04 8472 gen_helper_0e1i(mttlo, t0, 3);
ead9360e
TS
8473 break;
8474 case 13:
895c2d04 8475 gen_helper_0e1i(mtthi, t0, 3);
ead9360e
TS
8476 break;
8477 case 14:
895c2d04 8478 gen_helper_0e1i(mttacx, t0, 3);
ead9360e
TS
8479 break;
8480 case 16:
895c2d04 8481 gen_helper_mttdsp(cpu_env, t0);
ead9360e
TS
8482 break;
8483 default:
8484 goto die;
8485 }
8486 break;
8487 /* Floating point (COP1). */
8488 case 2:
8489 /* XXX: For now we support only a single FPU context. */
8490 if (h == 0) {
a7812ae4 8491 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8492
8493 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 8494 gen_store_fpr32(ctx, fp0, rd);
a7812ae4 8495 tcg_temp_free_i32(fp0);
ead9360e 8496 } else {
a7812ae4 8497 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
8498
8499 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 8500 gen_store_fpr32h(ctx, fp0, rd);
a7812ae4 8501 tcg_temp_free_i32(fp0);
ead9360e
TS
8502 }
8503 break;
8504 case 3:
8505 /* XXX: For now we support only a single FPU context. */
736d120a
PJ
8506 {
8507 TCGv_i32 fs_tmp = tcg_const_i32(rd);
8508
8509 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8510 tcg_temp_free_i32(fs_tmp);
8511 }
4cf8a45f 8512 /* Stop translation as we may have changed hflags */
eeb3bba8 8513 ctx->base.is_jmp = DISAS_STOP;
ead9360e
TS
8514 break;
8515 /* COP2: Not implemented. */
8516 case 4:
8517 case 5:
8518 /* fall through */
8519 default:
8520 goto die;
8521 }
b44a7fb1 8522 trace_mips_translate_tr("mttr", rd, u, sel, h);
1a3fd9c3 8523 tcg_temp_free(t0);
ead9360e
TS
8524 return;
8525
8526die:
1a3fd9c3 8527 tcg_temp_free(t0);
d12d51d5 8528 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9c708c7f 8529 generate_exception_end(ctx, EXCP_RI);
ead9360e
TS
8530}
8531
7db13fae 8532static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 8533{
287c4b84 8534 const char *opn = "ldst";
6af0bf9c 8535
2e15497c 8536 check_cp0_enabled(ctx);
6af0bf9c
FB
8537 switch (opc) {
8538 case OPC_MFC0:
8539 if (rt == 0) {
ead9360e 8540 /* Treat as NOP. */
6af0bf9c
FB
8541 return;
8542 }
d75c135e 8543 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
8544 opn = "mfc0";
8545 break;
8546 case OPC_MTC0:
1a3fd9c3 8547 {
1fc7bf6e 8548 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
8549
8550 gen_load_gpr(t0, rt);
d75c135e 8551 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
8552 tcg_temp_free(t0);
8553 }
6af0bf9c
FB
8554 opn = "mtc0";
8555 break;
d26bc211 8556#if defined(TARGET_MIPS64)
9c2149c8 8557 case OPC_DMFC0:
d75c135e 8558 check_insn(ctx, ISA_MIPS3);
9c2149c8 8559 if (rt == 0) {
ead9360e 8560 /* Treat as NOP. */
9c2149c8
TS
8561 return;
8562 }
d75c135e 8563 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
8564 opn = "dmfc0";
8565 break;
8566 case OPC_DMTC0:
d75c135e 8567 check_insn(ctx, ISA_MIPS3);
1a3fd9c3 8568 {
1fc7bf6e 8569 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
8570
8571 gen_load_gpr(t0, rt);
d75c135e 8572 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
1a3fd9c3
TS
8573 tcg_temp_free(t0);
8574 }
9c2149c8
TS
8575 opn = "dmtc0";
8576 break;
534ce69f 8577#endif
5204ea79
LA
8578 case OPC_MFHC0:
8579 check_mvh(ctx);
8580 if (rt == 0) {
8581 /* Treat as NOP. */
8582 return;
8583 }
8584 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8585 opn = "mfhc0";
8586 break;
8587 case OPC_MTHC0:
8588 check_mvh(ctx);
8589 {
8590 TCGv t0 = tcg_temp_new();
8591 gen_load_gpr(t0, rt);
8592 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8593 tcg_temp_free(t0);
8594 }
8595 opn = "mthc0";
8596 break;
ead9360e 8597 case OPC_MFTR:
d75c135e 8598 check_insn(ctx, ASE_MT);
ead9360e
TS
8599 if (rd == 0) {
8600 /* Treat as NOP. */
8601 return;
8602 }
6c5c1e20 8603 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 8604 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
8605 opn = "mftr";
8606 break;
8607 case OPC_MTTR:
d75c135e 8608 check_insn(ctx, ASE_MT);
6c5c1e20 8609 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
8610 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8611 opn = "mttr";
8612 break;
6af0bf9c 8613 case OPC_TLBWI:
6af0bf9c 8614 opn = "tlbwi";
c01fccd2 8615 if (!env->tlb->helper_tlbwi)
29929e34 8616 goto die;
895c2d04 8617 gen_helper_tlbwi(cpu_env);
6af0bf9c 8618 break;
9456c2fb
LA
8619 case OPC_TLBINV:
8620 opn = "tlbinv";
8621 if (ctx->ie >= 2) {
8622 if (!env->tlb->helper_tlbinv) {
8623 goto die;
8624 }
8625 gen_helper_tlbinv(cpu_env);
8626 } /* treat as nop if TLBINV not supported */
8627 break;
8628 case OPC_TLBINVF:
8629 opn = "tlbinvf";
8630 if (ctx->ie >= 2) {
8631 if (!env->tlb->helper_tlbinvf) {
8632 goto die;
8633 }
8634 gen_helper_tlbinvf(cpu_env);
8635 } /* treat as nop if TLBINV not supported */
8636 break;
6af0bf9c 8637 case OPC_TLBWR:
6af0bf9c 8638 opn = "tlbwr";
c01fccd2 8639 if (!env->tlb->helper_tlbwr)
29929e34 8640 goto die;
895c2d04 8641 gen_helper_tlbwr(cpu_env);
6af0bf9c
FB
8642 break;
8643 case OPC_TLBP:
6af0bf9c 8644 opn = "tlbp";
c01fccd2 8645 if (!env->tlb->helper_tlbp)
29929e34 8646 goto die;
895c2d04 8647 gen_helper_tlbp(cpu_env);
6af0bf9c
FB
8648 break;
8649 case OPC_TLBR:
6af0bf9c 8650 opn = "tlbr";
c01fccd2 8651 if (!env->tlb->helper_tlbr)
29929e34 8652 goto die;
895c2d04 8653 gen_helper_tlbr(cpu_env);
6af0bf9c 8654 break;
ce9782f4 8655 case OPC_ERET: /* OPC_ERETNC */
339cd2a8
LA
8656 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8657 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8 8658 goto die;
ce9782f4
LA
8659 } else {
8660 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8661 if (ctx->opcode & (1 << bit_shift)) {
8662 /* OPC_ERETNC */
8663 opn = "eretnc";
8664 check_insn(ctx, ISA_MIPS32R5);
8665 gen_helper_eretnc(cpu_env);
8666 } else {
8667 /* OPC_ERET */
8668 opn = "eret";
8669 check_insn(ctx, ISA_MIPS2);
8670 gen_helper_eret(cpu_env);
8671 }
eeb3bba8 8672 ctx->base.is_jmp = DISAS_EXIT;
339cd2a8 8673 }
6af0bf9c
FB
8674 break;
8675 case OPC_DERET:
8676 opn = "deret";
d75c135e 8677 check_insn(ctx, ISA_MIPS32);
339cd2a8
LA
8678 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8679 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
8680 goto die;
8681 }
6af0bf9c 8682 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 8683 MIPS_INVAL(opn);
9c708c7f 8684 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 8685 } else {
895c2d04 8686 gen_helper_deret(cpu_env);
eeb3bba8 8687 ctx->base.is_jmp = DISAS_EXIT;
6af0bf9c
FB
8688 }
8689 break;
4ad40f36
FB
8690 case OPC_WAIT:
8691 opn = "wait";
d75c135e 8692 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
339cd2a8
LA
8693 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8694 (ctx->hflags & MIPS_HFLAG_BMASK)) {
339cd2a8
LA
8695 goto die;
8696 }
4ad40f36 8697 /* If we get an exception, we want to restart at next instruction */
eeb3bba8 8698 ctx->base.pc_next += 4;
4ad40f36 8699 save_cpu_state(ctx, 1);
eeb3bba8 8700 ctx->base.pc_next -= 4;
895c2d04 8701 gen_helper_wait(cpu_env);
eeb3bba8 8702 ctx->base.is_jmp = DISAS_NORETURN;
4ad40f36 8703 break;
6af0bf9c 8704 default:
29929e34 8705 die:
923617a3 8706 MIPS_INVAL(opn);
9c708c7f 8707 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
8708 return;
8709 }
2abf314d 8710 (void)opn; /* avoid a compiler warning */
6af0bf9c 8711}
f1aa6320 8712#endif /* !CONFIG_USER_ONLY */
6af0bf9c 8713
6ea83fed 8714/* CP1 Branches (before delay slot) */
d75c135e
AJ
8715static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8716 int32_t cc, int32_t offset)
6ea83fed
FB
8717{
8718 target_ulong btarget;
a7812ae4 8719 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 8720
339cd2a8 8721 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 8722 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
8723 goto out;
8724 }
8725
e189e748 8726 if (cc != 0)
d75c135e 8727 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
e189e748 8728
eeb3bba8 8729 btarget = ctx->base.pc_next + 4 + offset;
6ea83fed 8730
7a387fff
TS
8731 switch (op) {
8732 case OPC_BC1F:
d94536f4
AJ
8733 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8734 tcg_gen_not_i32(t0, t0);
8735 tcg_gen_andi_i32(t0, t0, 1);
8736 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 8737 goto not_likely;
7a387fff 8738 case OPC_BC1FL:
d94536f4
AJ
8739 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8740 tcg_gen_not_i32(t0, t0);
8741 tcg_gen_andi_i32(t0, t0, 1);
8742 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed 8743 goto likely;
7a387fff 8744 case OPC_BC1T:
d94536f4
AJ
8745 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8746 tcg_gen_andi_i32(t0, t0, 1);
8747 tcg_gen_extu_i32_tl(bcond, t0);
5a5012ec 8748 goto not_likely;
7a387fff 8749 case OPC_BC1TL:
d94536f4
AJ
8750 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8751 tcg_gen_andi_i32(t0, t0, 1);
8752 tcg_gen_extu_i32_tl(bcond, t0);
6ea83fed
FB
8753 likely:
8754 ctx->hflags |= MIPS_HFLAG_BL;
8755 break;
5a5012ec 8756 case OPC_BC1FANY2:
a16336e4 8757 {
d94536f4
AJ
8758 TCGv_i32 t1 = tcg_temp_new_i32();
8759 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8760 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 8761 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 8762 tcg_temp_free_i32(t1);
d94536f4
AJ
8763 tcg_gen_andi_i32(t0, t0, 1);
8764 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 8765 }
5a5012ec
TS
8766 goto not_likely;
8767 case OPC_BC1TANY2:
a16336e4 8768 {
d94536f4
AJ
8769 TCGv_i32 t1 = tcg_temp_new_i32();
8770 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8771 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8772 tcg_gen_or_i32(t0, t0, t1);
8773 tcg_temp_free_i32(t1);
8774 tcg_gen_andi_i32(t0, t0, 1);
8775 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 8776 }
5a5012ec
TS
8777 goto not_likely;
8778 case OPC_BC1FANY4:
a16336e4 8779 {
d94536f4
AJ
8780 TCGv_i32 t1 = tcg_temp_new_i32();
8781 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8782 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
d7f66b52 8783 tcg_gen_and_i32(t0, t0, t1);
d94536f4 8784 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
d7f66b52 8785 tcg_gen_and_i32(t0, t0, t1);
d94536f4 8786 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
d7f66b52 8787 tcg_gen_nand_i32(t0, t0, t1);
d94536f4 8788 tcg_temp_free_i32(t1);
d94536f4
AJ
8789 tcg_gen_andi_i32(t0, t0, 1);
8790 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 8791 }
5a5012ec
TS
8792 goto not_likely;
8793 case OPC_BC1TANY4:
a16336e4 8794 {
d94536f4
AJ
8795 TCGv_i32 t1 = tcg_temp_new_i32();
8796 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8797 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8798 tcg_gen_or_i32(t0, t0, t1);
8799 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8800 tcg_gen_or_i32(t0, t0, t1);
8801 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8802 tcg_gen_or_i32(t0, t0, t1);
8803 tcg_temp_free_i32(t1);
8804 tcg_gen_andi_i32(t0, t0, 1);
8805 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 8806 }
5a5012ec
TS
8807 not_likely:
8808 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
8809 break;
8810 default:
9d68ac14 8811 MIPS_INVAL("cp1 cond branch");
9c708c7f 8812 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 8813 goto out;
6ea83fed 8814 }
6ea83fed 8815 ctx->btarget = btarget;
b231c103 8816 ctx->hflags |= MIPS_HFLAG_BDS32;
6c5c1e20 8817 out:
a7812ae4 8818 tcg_temp_free_i32(t0);
6ea83fed
FB
8819}
8820
31837be3
YK
8821/* R6 CP1 Branches */
8822static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
65935f07
YK
8823 int32_t ft, int32_t offset,
8824 int delayslot_size)
31837be3
YK
8825{
8826 target_ulong btarget;
31837be3
YK
8827 TCGv_i64 t0 = tcg_temp_new_i64();
8828
8829 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8830#ifdef MIPS_DEBUG_DISAS
339cd2a8 8831 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 8832 "\n", ctx->base.pc_next);
31837be3 8833#endif
9c708c7f 8834 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
8835 goto out;
8836 }
8837
8838 gen_load_fpr64(ctx, t0, ft);
8839 tcg_gen_andi_i64(t0, t0, 1);
8840
eeb3bba8 8841 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
31837be3
YK
8842
8843 switch (op) {
8844 case OPC_BC1EQZ:
8845 tcg_gen_xori_i64(t0, t0, 1);
31837be3
YK
8846 ctx->hflags |= MIPS_HFLAG_BC;
8847 break;
8848 case OPC_BC1NEZ:
8849 /* t0 already set */
31837be3
YK
8850 ctx->hflags |= MIPS_HFLAG_BC;
8851 break;
8852 default:
9d68ac14 8853 MIPS_INVAL("cp1 cond branch");
9c708c7f 8854 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
8855 goto out;
8856 }
8857
8858 tcg_gen_trunc_i64_tl(bcond, t0);
8859
31837be3 8860 ctx->btarget = btarget;
65935f07
YK
8861
8862 switch (delayslot_size) {
8863 case 2:
8864 ctx->hflags |= MIPS_HFLAG_BDS16;
8865 break;
8866 case 4:
8867 ctx->hflags |= MIPS_HFLAG_BDS32;
8868 break;
8869 }
31837be3
YK
8870
8871out:
8872 tcg_temp_free_i64(t0);
8873}
8874
6af0bf9c 8875/* Coprocessor 1 (FPU) */
5a5012ec 8876
5a5012ec
TS
8877#define FOP(func, fmt) (((fmt) << 21) | (func))
8878
bf4120ad
NF
8879enum fopcode {
8880 OPC_ADD_S = FOP(0, FMT_S),
8881 OPC_SUB_S = FOP(1, FMT_S),
8882 OPC_MUL_S = FOP(2, FMT_S),
8883 OPC_DIV_S = FOP(3, FMT_S),
8884 OPC_SQRT_S = FOP(4, FMT_S),
8885 OPC_ABS_S = FOP(5, FMT_S),
8886 OPC_MOV_S = FOP(6, FMT_S),
8887 OPC_NEG_S = FOP(7, FMT_S),
8888 OPC_ROUND_L_S = FOP(8, FMT_S),
8889 OPC_TRUNC_L_S = FOP(9, FMT_S),
8890 OPC_CEIL_L_S = FOP(10, FMT_S),
8891 OPC_FLOOR_L_S = FOP(11, FMT_S),
8892 OPC_ROUND_W_S = FOP(12, FMT_S),
8893 OPC_TRUNC_W_S = FOP(13, FMT_S),
8894 OPC_CEIL_W_S = FOP(14, FMT_S),
8895 OPC_FLOOR_W_S = FOP(15, FMT_S),
e7f16abb 8896 OPC_SEL_S = FOP(16, FMT_S),
bf4120ad
NF
8897 OPC_MOVCF_S = FOP(17, FMT_S),
8898 OPC_MOVZ_S = FOP(18, FMT_S),
8899 OPC_MOVN_S = FOP(19, FMT_S),
e7f16abb 8900 OPC_SELEQZ_S = FOP(20, FMT_S),
bf4120ad
NF
8901 OPC_RECIP_S = FOP(21, FMT_S),
8902 OPC_RSQRT_S = FOP(22, FMT_S),
e7f16abb
LA
8903 OPC_SELNEZ_S = FOP(23, FMT_S),
8904 OPC_MADDF_S = FOP(24, FMT_S),
8905 OPC_MSUBF_S = FOP(25, FMT_S),
8906 OPC_RINT_S = FOP(26, FMT_S),
8907 OPC_CLASS_S = FOP(27, FMT_S),
8908 OPC_MIN_S = FOP(28, FMT_S),
bf4120ad 8909 OPC_RECIP2_S = FOP(28, FMT_S),
e7f16abb 8910 OPC_MINA_S = FOP(29, FMT_S),
bf4120ad 8911 OPC_RECIP1_S = FOP(29, FMT_S),
e7f16abb 8912 OPC_MAX_S = FOP(30, FMT_S),
bf4120ad 8913 OPC_RSQRT1_S = FOP(30, FMT_S),
e7f16abb 8914 OPC_MAXA_S = FOP(31, FMT_S),
bf4120ad
NF
8915 OPC_RSQRT2_S = FOP(31, FMT_S),
8916 OPC_CVT_D_S = FOP(33, FMT_S),
8917 OPC_CVT_W_S = FOP(36, FMT_S),
8918 OPC_CVT_L_S = FOP(37, FMT_S),
8919 OPC_CVT_PS_S = FOP(38, FMT_S),
8920 OPC_CMP_F_S = FOP (48, FMT_S),
8921 OPC_CMP_UN_S = FOP (49, FMT_S),
8922 OPC_CMP_EQ_S = FOP (50, FMT_S),
8923 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8924 OPC_CMP_OLT_S = FOP (52, FMT_S),
8925 OPC_CMP_ULT_S = FOP (53, FMT_S),
8926 OPC_CMP_OLE_S = FOP (54, FMT_S),
8927 OPC_CMP_ULE_S = FOP (55, FMT_S),
8928 OPC_CMP_SF_S = FOP (56, FMT_S),
8929 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8930 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8931 OPC_CMP_NGL_S = FOP (59, FMT_S),
8932 OPC_CMP_LT_S = FOP (60, FMT_S),
8933 OPC_CMP_NGE_S = FOP (61, FMT_S),
8934 OPC_CMP_LE_S = FOP (62, FMT_S),
8935 OPC_CMP_NGT_S = FOP (63, FMT_S),
8936
8937 OPC_ADD_D = FOP(0, FMT_D),
8938 OPC_SUB_D = FOP(1, FMT_D),
8939 OPC_MUL_D = FOP(2, FMT_D),
8940 OPC_DIV_D = FOP(3, FMT_D),
8941 OPC_SQRT_D = FOP(4, FMT_D),
8942 OPC_ABS_D = FOP(5, FMT_D),
8943 OPC_MOV_D = FOP(6, FMT_D),
8944 OPC_NEG_D = FOP(7, FMT_D),
8945 OPC_ROUND_L_D = FOP(8, FMT_D),
8946 OPC_TRUNC_L_D = FOP(9, FMT_D),
8947 OPC_CEIL_L_D = FOP(10, FMT_D),
8948 OPC_FLOOR_L_D = FOP(11, FMT_D),
8949 OPC_ROUND_W_D = FOP(12, FMT_D),
8950 OPC_TRUNC_W_D = FOP(13, FMT_D),
8951 OPC_CEIL_W_D = FOP(14, FMT_D),
8952 OPC_FLOOR_W_D = FOP(15, FMT_D),
e7f16abb 8953 OPC_SEL_D = FOP(16, FMT_D),
bf4120ad
NF
8954 OPC_MOVCF_D = FOP(17, FMT_D),
8955 OPC_MOVZ_D = FOP(18, FMT_D),
8956 OPC_MOVN_D = FOP(19, FMT_D),
e7f16abb 8957 OPC_SELEQZ_D = FOP(20, FMT_D),
bf4120ad
NF
8958 OPC_RECIP_D = FOP(21, FMT_D),
8959 OPC_RSQRT_D = FOP(22, FMT_D),
e7f16abb
LA
8960 OPC_SELNEZ_D = FOP(23, FMT_D),
8961 OPC_MADDF_D = FOP(24, FMT_D),
8962 OPC_MSUBF_D = FOP(25, FMT_D),
8963 OPC_RINT_D = FOP(26, FMT_D),
8964 OPC_CLASS_D = FOP(27, FMT_D),
8965 OPC_MIN_D = FOP(28, FMT_D),
bf4120ad 8966 OPC_RECIP2_D = FOP(28, FMT_D),
e7f16abb 8967 OPC_MINA_D = FOP(29, FMT_D),
bf4120ad 8968 OPC_RECIP1_D = FOP(29, FMT_D),
e7f16abb 8969 OPC_MAX_D = FOP(30, FMT_D),
bf4120ad 8970 OPC_RSQRT1_D = FOP(30, FMT_D),
e7f16abb 8971 OPC_MAXA_D = FOP(31, FMT_D),
bf4120ad
NF
8972 OPC_RSQRT2_D = FOP(31, FMT_D),
8973 OPC_CVT_S_D = FOP(32, FMT_D),
8974 OPC_CVT_W_D = FOP(36, FMT_D),
8975 OPC_CVT_L_D = FOP(37, FMT_D),
8976 OPC_CMP_F_D = FOP (48, FMT_D),
8977 OPC_CMP_UN_D = FOP (49, FMT_D),
8978 OPC_CMP_EQ_D = FOP (50, FMT_D),
8979 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8980 OPC_CMP_OLT_D = FOP (52, FMT_D),
8981 OPC_CMP_ULT_D = FOP (53, FMT_D),
8982 OPC_CMP_OLE_D = FOP (54, FMT_D),
8983 OPC_CMP_ULE_D = FOP (55, FMT_D),
8984 OPC_CMP_SF_D = FOP (56, FMT_D),
8985 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8986 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8987 OPC_CMP_NGL_D = FOP (59, FMT_D),
8988 OPC_CMP_LT_D = FOP (60, FMT_D),
8989 OPC_CMP_NGE_D = FOP (61, FMT_D),
8990 OPC_CMP_LE_D = FOP (62, FMT_D),
8991 OPC_CMP_NGT_D = FOP (63, FMT_D),
8992
8993 OPC_CVT_S_W = FOP(32, FMT_W),
8994 OPC_CVT_D_W = FOP(33, FMT_W),
8995 OPC_CVT_S_L = FOP(32, FMT_L),
8996 OPC_CVT_D_L = FOP(33, FMT_L),
8997 OPC_CVT_PS_PW = FOP(38, FMT_W),
8998
8999 OPC_ADD_PS = FOP(0, FMT_PS),
9000 OPC_SUB_PS = FOP(1, FMT_PS),
9001 OPC_MUL_PS = FOP(2, FMT_PS),
9002 OPC_DIV_PS = FOP(3, FMT_PS),
9003 OPC_ABS_PS = FOP(5, FMT_PS),
9004 OPC_MOV_PS = FOP(6, FMT_PS),
9005 OPC_NEG_PS = FOP(7, FMT_PS),
9006 OPC_MOVCF_PS = FOP(17, FMT_PS),
9007 OPC_MOVZ_PS = FOP(18, FMT_PS),
9008 OPC_MOVN_PS = FOP(19, FMT_PS),
9009 OPC_ADDR_PS = FOP(24, FMT_PS),
9010 OPC_MULR_PS = FOP(26, FMT_PS),
9011 OPC_RECIP2_PS = FOP(28, FMT_PS),
9012 OPC_RECIP1_PS = FOP(29, FMT_PS),
9013 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9014 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9015
9016 OPC_CVT_S_PU = FOP(32, FMT_PS),
9017 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9018 OPC_CVT_S_PL = FOP(40, FMT_PS),
9019 OPC_PLL_PS = FOP(44, FMT_PS),
9020 OPC_PLU_PS = FOP(45, FMT_PS),
9021 OPC_PUL_PS = FOP(46, FMT_PS),
9022 OPC_PUU_PS = FOP(47, FMT_PS),
9023 OPC_CMP_F_PS = FOP (48, FMT_PS),
9024 OPC_CMP_UN_PS = FOP (49, FMT_PS),
9025 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
9026 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
9027 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
9028 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
9029 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
9030 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
9031 OPC_CMP_SF_PS = FOP (56, FMT_PS),
9032 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
9033 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
9034 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
9035 OPC_CMP_LT_PS = FOP (60, FMT_PS),
9036 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
9037 OPC_CMP_LE_PS = FOP (62, FMT_PS),
9038 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
9039};
9040
3f493883
YK
9041enum r6_f_cmp_op {
9042 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9043 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9044 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9045 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9046 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9047 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9048 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9049 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9050 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9051 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9052 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9053 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9054 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9055 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9056 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9057 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9058 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9059 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9060 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9061 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9062 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9063 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9064
9065 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9066 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9067 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9068 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9069 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9070 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9071 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9072 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9073 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9074 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9075 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9076 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9077 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9078 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9079 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9080 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9081 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9082 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9083 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9084 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9085 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9086 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9087};
7a387fff 9088static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 9089{
72c3a3ee 9090 TCGv t0 = tcg_temp_new();
6ea83fed
FB
9091
9092 switch (opc) {
9093 case OPC_MFC1:
b6d96bed 9094 {
a7812ae4 9095 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9096
7c979afd 9097 gen_load_fpr32(ctx, fp0, fs);
b6d96bed 9098 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 9099 tcg_temp_free_i32(fp0);
6958549d 9100 }
6c5c1e20 9101 gen_store_gpr(t0, rt);
6ea83fed
FB
9102 break;
9103 case OPC_MTC1:
6c5c1e20 9104 gen_load_gpr(t0, rt);
b6d96bed 9105 {
a7812ae4 9106 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
9107
9108 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 9109 gen_store_fpr32(ctx, fp0, fs);
a7812ae4 9110 tcg_temp_free_i32(fp0);
6958549d 9111 }
6ea83fed
FB
9112 break;
9113 case OPC_CFC1:
895c2d04 9114 gen_helper_1e0i(cfc1, t0, fs);
6c5c1e20 9115 gen_store_gpr(t0, rt);
6ea83fed
FB
9116 break;
9117 case OPC_CTC1:
6c5c1e20 9118 gen_load_gpr(t0, rt);
9c708c7f 9119 save_cpu_state(ctx, 0);
736d120a
PJ
9120 {
9121 TCGv_i32 fs_tmp = tcg_const_i32(fs);
9122
9123 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9124 tcg_temp_free_i32(fs_tmp);
9125 }
4cf8a45f 9126 /* Stop translation as we may have changed hflags */
eeb3bba8 9127 ctx->base.is_jmp = DISAS_STOP;
6ea83fed 9128 break;
72c3a3ee 9129#if defined(TARGET_MIPS64)
9c2149c8 9130 case OPC_DMFC1:
72c3a3ee 9131 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 9132 gen_store_gpr(t0, rt);
5a5012ec 9133 break;
9c2149c8 9134 case OPC_DMTC1:
6c5c1e20 9135 gen_load_gpr(t0, rt);
72c3a3ee 9136 gen_store_fpr64(ctx, t0, fs);
5a5012ec 9137 break;
72c3a3ee 9138#endif
5a5012ec 9139 case OPC_MFHC1:
b6d96bed 9140 {
a7812ae4 9141 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9142
7f6613ce 9143 gen_load_fpr32h(ctx, fp0, fs);
b6d96bed 9144 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 9145 tcg_temp_free_i32(fp0);
6958549d 9146 }
6c5c1e20 9147 gen_store_gpr(t0, rt);
5a5012ec
TS
9148 break;
9149 case OPC_MTHC1:
6c5c1e20 9150 gen_load_gpr(t0, rt);
b6d96bed 9151 {
a7812ae4 9152 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
9153
9154 tcg_gen_trunc_tl_i32(fp0, t0);
7f6613ce 9155 gen_store_fpr32h(ctx, fp0, fs);
a7812ae4 9156 tcg_temp_free_i32(fp0);
6958549d 9157 }
5a5012ec 9158 break;
6ea83fed 9159 default:
9d68ac14 9160 MIPS_INVAL("cp1 move");
9c708c7f 9161 generate_exception_end(ctx, EXCP_RI);
6c5c1e20 9162 goto out;
6ea83fed 9163 }
6c5c1e20
TS
9164
9165 out:
9166 tcg_temp_free(t0);
6ea83fed
FB
9167}
9168
5a5012ec
TS
9169static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
9170{
42a268c2 9171 TCGLabel *l1;
e214b9bb 9172 TCGCond cond;
af58f9ca
AJ
9173 TCGv_i32 t0;
9174
9175 if (rd == 0) {
9176 /* Treat as NOP. */
9177 return;
9178 }
6ea83fed 9179
e214b9bb 9180 if (tf)
e214b9bb 9181 cond = TCG_COND_EQ;
27848470
TS
9182 else
9183 cond = TCG_COND_NE;
9184
af58f9ca
AJ
9185 l1 = gen_new_label();
9186 t0 = tcg_temp_new_i32();
fa31af0e 9187 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 9188 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 9189 tcg_temp_free_i32(t0);
af58f9ca
AJ
9190 if (rs == 0) {
9191 tcg_gen_movi_tl(cpu_gpr[rd], 0);
9192 } else {
9193 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
9194 }
e214b9bb 9195 gen_set_label(l1);
5a5012ec
TS
9196}
9197
7c979afd
LA
9198static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
9199 int tf)
a16336e4 9200{
a16336e4 9201 int cond;
cbc37b28 9202 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2 9203 TCGLabel *l1 = gen_new_label();
a16336e4 9204
a16336e4
TS
9205 if (tf)
9206 cond = TCG_COND_EQ;
9207 else
9208 cond = TCG_COND_NE;
9209
fa31af0e 9210 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 9211 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
9212 gen_load_fpr32(ctx, t0, fs);
9213 gen_store_fpr32(ctx, t0, fd);
a16336e4 9214 gen_set_label(l1);
cbc37b28 9215 tcg_temp_free_i32(t0);
5a5012ec 9216}
a16336e4 9217
b6d96bed 9218static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4 9219{
a16336e4 9220 int cond;
cbc37b28
AJ
9221 TCGv_i32 t0 = tcg_temp_new_i32();
9222 TCGv_i64 fp0;
42a268c2 9223 TCGLabel *l1 = gen_new_label();
a16336e4 9224
a16336e4
TS
9225 if (tf)
9226 cond = TCG_COND_EQ;
9227 else
9228 cond = TCG_COND_NE;
9229
fa31af0e 9230 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 9231 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 9232 tcg_temp_free_i32(t0);
11f94258 9233 fp0 = tcg_temp_new_i64();
9bf3eb2c 9234 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 9235 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9236 tcg_temp_free_i64(fp0);
cbc37b28 9237 gen_set_label(l1);
a16336e4
TS
9238}
9239
7f6613ce
PJ
9240static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
9241 int cc, int tf)
a16336e4
TS
9242{
9243 int cond;
cbc37b28 9244 TCGv_i32 t0 = tcg_temp_new_i32();
42a268c2
RH
9245 TCGLabel *l1 = gen_new_label();
9246 TCGLabel *l2 = gen_new_label();
a16336e4
TS
9247
9248 if (tf)
9249 cond = TCG_COND_EQ;
9250 else
9251 cond = TCG_COND_NE;
9252
fa31af0e 9253 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 9254 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7c979afd
LA
9255 gen_load_fpr32(ctx, t0, fs);
9256 gen_store_fpr32(ctx, t0, fd);
a16336e4 9257 gen_set_label(l1);
9bf3eb2c 9258
fa31af0e 9259 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
cbc37b28 9260 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7f6613ce
PJ
9261 gen_load_fpr32h(ctx, t0, fs);
9262 gen_store_fpr32h(ctx, t0, fd);
52a0e9eb 9263 tcg_temp_free_i32(t0);
a16336e4 9264 gen_set_label(l2);
a16336e4
TS
9265}
9266
e7f16abb
LA
9267static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9268 int fs)
9269{
9270 TCGv_i32 t1 = tcg_const_i32(0);
9271 TCGv_i32 fp0 = tcg_temp_new_i32();
9272 TCGv_i32 fp1 = tcg_temp_new_i32();
9273 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
9274 gen_load_fpr32(ctx, fp0, fd);
9275 gen_load_fpr32(ctx, fp1, ft);
9276 gen_load_fpr32(ctx, fp2, fs);
e7f16abb
LA
9277
9278 switch (op1) {
9279 case OPC_SEL_S:
9280 tcg_gen_andi_i32(fp0, fp0, 1);
9281 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9282 break;
9283 case OPC_SELEQZ_S:
9284 tcg_gen_andi_i32(fp1, fp1, 1);
9285 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9286 break;
9287 case OPC_SELNEZ_S:
9288 tcg_gen_andi_i32(fp1, fp1, 1);
9289 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9290 break;
9291 default:
9292 MIPS_INVAL("gen_sel_s");
9c708c7f 9293 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
9294 break;
9295 }
9296
7c979afd 9297 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
9298 tcg_temp_free_i32(fp2);
9299 tcg_temp_free_i32(fp1);
9300 tcg_temp_free_i32(fp0);
9301 tcg_temp_free_i32(t1);
9302}
9303
9304static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9305 int fs)
9306{
9307 TCGv_i64 t1 = tcg_const_i64(0);
9308 TCGv_i64 fp0 = tcg_temp_new_i64();
9309 TCGv_i64 fp1 = tcg_temp_new_i64();
9310 TCGv_i64 fp2 = tcg_temp_new_i64();
9311 gen_load_fpr64(ctx, fp0, fd);
9312 gen_load_fpr64(ctx, fp1, ft);
9313 gen_load_fpr64(ctx, fp2, fs);
9314
9315 switch (op1) {
9316 case OPC_SEL_D:
9317 tcg_gen_andi_i64(fp0, fp0, 1);
9318 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9319 break;
9320 case OPC_SELEQZ_D:
9321 tcg_gen_andi_i64(fp1, fp1, 1);
9322 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9323 break;
9324 case OPC_SELNEZ_D:
9325 tcg_gen_andi_i64(fp1, fp1, 1);
9326 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9327 break;
9328 default:
9329 MIPS_INVAL("gen_sel_d");
9c708c7f 9330 generate_exception_end(ctx, EXCP_RI);
e7f16abb
LA
9331 break;
9332 }
9333
9334 gen_store_fpr64(ctx, fp0, fd);
9335 tcg_temp_free_i64(fp2);
9336 tcg_temp_free_i64(fp1);
9337 tcg_temp_free_i64(fp0);
9338 tcg_temp_free_i64(t1);
9339}
6ea83fed 9340
bf4120ad 9341static void gen_farith (DisasContext *ctx, enum fopcode op1,
5e755519 9342 int ft, int fs, int fd, int cc)
6ea83fed 9343{
7a387fff 9344 uint32_t func = ctx->opcode & 0x3f;
bf4120ad
NF
9345 switch (op1) {
9346 case OPC_ADD_S:
b6d96bed 9347 {
a7812ae4
PB
9348 TCGv_i32 fp0 = tcg_temp_new_i32();
9349 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9350
7c979afd
LA
9351 gen_load_fpr32(ctx, fp0, fs);
9352 gen_load_fpr32(ctx, fp1, ft);
895c2d04 9353 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
a7812ae4 9354 tcg_temp_free_i32(fp1);
7c979afd 9355 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9356 tcg_temp_free_i32(fp0);
b6d96bed 9357 }
5a5012ec 9358 break;
bf4120ad 9359 case OPC_SUB_S:
b6d96bed 9360 {
a7812ae4
PB
9361 TCGv_i32 fp0 = tcg_temp_new_i32();
9362 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9363
7c979afd
LA
9364 gen_load_fpr32(ctx, fp0, fs);
9365 gen_load_fpr32(ctx, fp1, ft);
895c2d04 9366 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
a7812ae4 9367 tcg_temp_free_i32(fp1);
7c979afd 9368 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9369 tcg_temp_free_i32(fp0);
b6d96bed 9370 }
5a5012ec 9371 break;
bf4120ad 9372 case OPC_MUL_S:
b6d96bed 9373 {
a7812ae4
PB
9374 TCGv_i32 fp0 = tcg_temp_new_i32();
9375 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9376
7c979afd
LA
9377 gen_load_fpr32(ctx, fp0, fs);
9378 gen_load_fpr32(ctx, fp1, ft);
895c2d04 9379 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
a7812ae4 9380 tcg_temp_free_i32(fp1);
7c979afd 9381 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9382 tcg_temp_free_i32(fp0);
b6d96bed 9383 }
5a5012ec 9384 break;
bf4120ad 9385 case OPC_DIV_S:
b6d96bed 9386 {
a7812ae4
PB
9387 TCGv_i32 fp0 = tcg_temp_new_i32();
9388 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9389
7c979afd
LA
9390 gen_load_fpr32(ctx, fp0, fs);
9391 gen_load_fpr32(ctx, fp1, ft);
895c2d04 9392 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
a7812ae4 9393 tcg_temp_free_i32(fp1);
7c979afd 9394 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9395 tcg_temp_free_i32(fp0);
b6d96bed 9396 }
5a5012ec 9397 break;
bf4120ad 9398 case OPC_SQRT_S:
b6d96bed 9399 {
a7812ae4 9400 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9401
7c979afd 9402 gen_load_fpr32(ctx, fp0, fs);
895c2d04 9403 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
7c979afd 9404 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9405 tcg_temp_free_i32(fp0);
b6d96bed 9406 }
5a5012ec 9407 break;
bf4120ad 9408 case OPC_ABS_S:
b6d96bed 9409 {
a7812ae4 9410 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9411
7c979afd 9412 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
9413 if (ctx->abs2008) {
9414 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
9415 } else {
9416 gen_helper_float_abs_s(fp0, fp0);
9417 }
7c979afd 9418 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9419 tcg_temp_free_i32(fp0);
b6d96bed 9420 }
5a5012ec 9421 break;
bf4120ad 9422 case OPC_MOV_S:
b6d96bed 9423 {
a7812ae4 9424 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9425
7c979afd
LA
9426 gen_load_fpr32(ctx, fp0, fs);
9427 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9428 tcg_temp_free_i32(fp0);
b6d96bed 9429 }
5a5012ec 9430 break;
bf4120ad 9431 case OPC_NEG_S:
b6d96bed 9432 {
a7812ae4 9433 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9434
7c979afd 9435 gen_load_fpr32(ctx, fp0, fs);
6be77480
AM
9436 if (ctx->abs2008) {
9437 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
9438 } else {
9439 gen_helper_float_chs_s(fp0, fp0);
9440 }
7c979afd 9441 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9442 tcg_temp_free_i32(fp0);
b6d96bed 9443 }
5a5012ec 9444 break;
bf4120ad 9445 case OPC_ROUND_L_S:
5e755519 9446 check_cp1_64bitmode(ctx);
b6d96bed 9447 {
a7812ae4
PB
9448 TCGv_i32 fp32 = tcg_temp_new_i32();
9449 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9450
7c979afd 9451 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
9452 if (ctx->nan2008) {
9453 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
9454 } else {
9455 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
9456 }
a7812ae4 9457 tcg_temp_free_i32(fp32);
b6d96bed 9458 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 9459 tcg_temp_free_i64(fp64);
b6d96bed 9460 }
5a5012ec 9461 break;
bf4120ad 9462 case OPC_TRUNC_L_S:
5e755519 9463 check_cp1_64bitmode(ctx);
b6d96bed 9464 {
a7812ae4
PB
9465 TCGv_i32 fp32 = tcg_temp_new_i32();
9466 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9467
7c979afd 9468 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
9469 if (ctx->nan2008) {
9470 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
9471 } else {
9472 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
9473 }
a7812ae4 9474 tcg_temp_free_i32(fp32);
b6d96bed 9475 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 9476 tcg_temp_free_i64(fp64);
b6d96bed 9477 }
5a5012ec 9478 break;
bf4120ad 9479 case OPC_CEIL_L_S:
5e755519 9480 check_cp1_64bitmode(ctx);
b6d96bed 9481 {
a7812ae4
PB
9482 TCGv_i32 fp32 = tcg_temp_new_i32();
9483 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9484
7c979afd 9485 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
9486 if (ctx->nan2008) {
9487 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
9488 } else {
9489 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
9490 }
a7812ae4 9491 tcg_temp_free_i32(fp32);
b6d96bed 9492 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 9493 tcg_temp_free_i64(fp64);
b6d96bed 9494 }
5a5012ec 9495 break;
bf4120ad 9496 case OPC_FLOOR_L_S:
5e755519 9497 check_cp1_64bitmode(ctx);
b6d96bed 9498 {
a7812ae4
PB
9499 TCGv_i32 fp32 = tcg_temp_new_i32();
9500 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9501
7c979afd 9502 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
9503 if (ctx->nan2008) {
9504 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
9505 } else {
9506 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
9507 }
a7812ae4 9508 tcg_temp_free_i32(fp32);
b6d96bed 9509 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 9510 tcg_temp_free_i64(fp64);
b6d96bed 9511 }
5a5012ec 9512 break;
bf4120ad 9513 case OPC_ROUND_W_S:
b6d96bed 9514 {
a7812ae4 9515 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9516
7c979afd 9517 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
9518 if (ctx->nan2008) {
9519 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
9520 } else {
9521 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
9522 }
7c979afd 9523 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9524 tcg_temp_free_i32(fp0);
b6d96bed 9525 }
5a5012ec 9526 break;
bf4120ad 9527 case OPC_TRUNC_W_S:
b6d96bed 9528 {
a7812ae4 9529 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9530
7c979afd 9531 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
9532 if (ctx->nan2008) {
9533 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
9534 } else {
9535 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
9536 }
7c979afd 9537 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9538 tcg_temp_free_i32(fp0);
b6d96bed 9539 }
5a5012ec 9540 break;
bf4120ad 9541 case OPC_CEIL_W_S:
b6d96bed 9542 {
a7812ae4 9543 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9544
7c979afd 9545 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
9546 if (ctx->nan2008) {
9547 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
9548 } else {
9549 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
9550 }
7c979afd 9551 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9552 tcg_temp_free_i32(fp0);
b6d96bed 9553 }
5a5012ec 9554 break;
bf4120ad 9555 case OPC_FLOOR_W_S:
b6d96bed 9556 {
a7812ae4 9557 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9558
7c979afd 9559 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
9560 if (ctx->nan2008) {
9561 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
9562 } else {
9563 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
9564 }
7c979afd 9565 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9566 tcg_temp_free_i32(fp0);
b6d96bed 9567 }
5a5012ec 9568 break;
e7f16abb
LA
9569 case OPC_SEL_S:
9570 check_insn(ctx, ISA_MIPS32R6);
9571 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
9572 break;
9573 case OPC_SELEQZ_S:
9574 check_insn(ctx, ISA_MIPS32R6);
9575 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb
LA
9576 break;
9577 case OPC_SELNEZ_S:
9578 check_insn(ctx, ISA_MIPS32R6);
9579 gen_sel_s(ctx, op1, fd, ft, fs);
e7f16abb 9580 break;
bf4120ad 9581 case OPC_MOVCF_S:
fecd2646 9582 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7c979afd 9583 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 9584 break;
bf4120ad 9585 case OPC_MOVZ_S:
fecd2646 9586 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 9587 {
42a268c2 9588 TCGLabel *l1 = gen_new_label();
c9297f4d 9589 TCGv_i32 fp0;
a16336e4 9590
c9297f4d
AJ
9591 if (ft != 0) {
9592 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9593 }
9594 fp0 = tcg_temp_new_i32();
7c979afd
LA
9595 gen_load_fpr32(ctx, fp0, fs);
9596 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9597 tcg_temp_free_i32(fp0);
a16336e4
TS
9598 gen_set_label(l1);
9599 }
5a5012ec 9600 break;
bf4120ad 9601 case OPC_MOVN_S:
fecd2646 9602 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 9603 {
42a268c2 9604 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
9605 TCGv_i32 fp0;
9606
9607 if (ft != 0) {
9608 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9609 fp0 = tcg_temp_new_i32();
7c979afd
LA
9610 gen_load_fpr32(ctx, fp0, fs);
9611 gen_store_fpr32(ctx, fp0, fd);
c9297f4d
AJ
9612 tcg_temp_free_i32(fp0);
9613 gen_set_label(l1);
9614 }
a16336e4 9615 }
5a5012ec 9616 break;
bf4120ad 9617 case OPC_RECIP_S:
b6d96bed 9618 {
a7812ae4 9619 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9620
7c979afd 9621 gen_load_fpr32(ctx, fp0, fs);
895c2d04 9622 gen_helper_float_recip_s(fp0, cpu_env, fp0);
7c979afd 9623 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9624 tcg_temp_free_i32(fp0);
b6d96bed 9625 }
57fa1fb3 9626 break;
bf4120ad 9627 case OPC_RSQRT_S:
b6d96bed 9628 {
a7812ae4 9629 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9630
7c979afd 9631 gen_load_fpr32(ctx, fp0, fs);
895c2d04 9632 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
7c979afd 9633 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9634 tcg_temp_free_i32(fp0);
b6d96bed 9635 }
57fa1fb3 9636 break;
e7f16abb
LA
9637 case OPC_MADDF_S:
9638 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 9639 {
a7812ae4
PB
9640 TCGv_i32 fp0 = tcg_temp_new_i32();
9641 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 9642 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
9643 gen_load_fpr32(ctx, fp0, fs);
9644 gen_load_fpr32(ctx, fp1, ft);
9645 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 9646 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 9647 gen_store_fpr32(ctx, fp2, fd);
e7f16abb 9648 tcg_temp_free_i32(fp2);
a7812ae4 9649 tcg_temp_free_i32(fp1);
a7812ae4 9650 tcg_temp_free_i32(fp0);
b6d96bed 9651 }
57fa1fb3 9652 break;
e7f16abb
LA
9653 case OPC_MSUBF_S:
9654 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 9655 {
a7812ae4 9656 TCGv_i32 fp0 = tcg_temp_new_i32();
e7f16abb
LA
9657 TCGv_i32 fp1 = tcg_temp_new_i32();
9658 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
9659 gen_load_fpr32(ctx, fp0, fs);
9660 gen_load_fpr32(ctx, fp1, ft);
9661 gen_load_fpr32(ctx, fp2, fd);
e7f16abb 9662 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
7c979afd 9663 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
9664 tcg_temp_free_i32(fp2);
9665 tcg_temp_free_i32(fp1);
a7812ae4 9666 tcg_temp_free_i32(fp0);
b6d96bed 9667 }
57fa1fb3 9668 break;
e7f16abb
LA
9669 case OPC_RINT_S:
9670 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 9671 {
a7812ae4 9672 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 9673 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 9674 gen_helper_float_rint_s(fp0, cpu_env, fp0);
7c979afd 9675 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9676 tcg_temp_free_i32(fp0);
b6d96bed 9677 }
57fa1fb3 9678 break;
e7f16abb
LA
9679 case OPC_CLASS_S:
9680 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 9681 {
e7f16abb 9682 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 9683 gen_load_fpr32(ctx, fp0, fs);
af39bc8c 9684 gen_helper_float_class_s(fp0, cpu_env, fp0);
7c979afd 9685 gen_store_fpr32(ctx, fp0, fd);
e7f16abb 9686 tcg_temp_free_i32(fp0);
e7f16abb
LA
9687 }
9688 break;
9689 case OPC_MIN_S: /* OPC_RECIP2_S */
9690 if (ctx->insn_flags & ISA_MIPS32R6) {
9691 /* OPC_MIN_S */
a7812ae4
PB
9692 TCGv_i32 fp0 = tcg_temp_new_i32();
9693 TCGv_i32 fp1 = tcg_temp_new_i32();
e7f16abb 9694 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
9695 gen_load_fpr32(ctx, fp0, fs);
9696 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 9697 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
7c979afd 9698 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
9699 tcg_temp_free_i32(fp2);
9700 tcg_temp_free_i32(fp1);
9701 tcg_temp_free_i32(fp0);
e7f16abb
LA
9702 } else {
9703 /* OPC_RECIP2_S */
9704 check_cp1_64bitmode(ctx);
9705 {
9706 TCGv_i32 fp0 = tcg_temp_new_i32();
9707 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 9708
7c979afd
LA
9709 gen_load_fpr32(ctx, fp0, fs);
9710 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
9711 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9712 tcg_temp_free_i32(fp1);
7c979afd 9713 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
9714 tcg_temp_free_i32(fp0);
9715 }
e7f16abb
LA
9716 }
9717 break;
9718 case OPC_MINA_S: /* OPC_RECIP1_S */
9719 if (ctx->insn_flags & ISA_MIPS32R6) {
9720 /* OPC_MINA_S */
9721 TCGv_i32 fp0 = tcg_temp_new_i32();
9722 TCGv_i32 fp1 = tcg_temp_new_i32();
9723 TCGv_i32 fp2 = tcg_temp_new_i32();
7c979afd
LA
9724 gen_load_fpr32(ctx, fp0, fs);
9725 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 9726 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
7c979afd 9727 gen_store_fpr32(ctx, fp2, fd);
e7f16abb
LA
9728 tcg_temp_free_i32(fp2);
9729 tcg_temp_free_i32(fp1);
9730 tcg_temp_free_i32(fp0);
e7f16abb
LA
9731 } else {
9732 /* OPC_RECIP1_S */
9733 check_cp1_64bitmode(ctx);
9734 {
9735 TCGv_i32 fp0 = tcg_temp_new_i32();
9736
7c979afd 9737 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 9738 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
7c979afd 9739 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
9740 tcg_temp_free_i32(fp0);
9741 }
e7f16abb
LA
9742 }
9743 break;
9744 case OPC_MAX_S: /* OPC_RSQRT1_S */
9745 if (ctx->insn_flags & ISA_MIPS32R6) {
9746 /* OPC_MAX_S */
9747 TCGv_i32 fp0 = tcg_temp_new_i32();
9748 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
9749 gen_load_fpr32(ctx, fp0, fs);
9750 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 9751 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
7c979afd 9752 gen_store_fpr32(ctx, fp1, fd);
e7f16abb
LA
9753 tcg_temp_free_i32(fp1);
9754 tcg_temp_free_i32(fp0);
e7f16abb
LA
9755 } else {
9756 /* OPC_RSQRT1_S */
9757 check_cp1_64bitmode(ctx);
9758 {
9759 TCGv_i32 fp0 = tcg_temp_new_i32();
9760
7c979afd 9761 gen_load_fpr32(ctx, fp0, fs);
e7f16abb 9762 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
7c979afd 9763 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
9764 tcg_temp_free_i32(fp0);
9765 }
e7f16abb
LA
9766 }
9767 break;
9768 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9769 if (ctx->insn_flags & ISA_MIPS32R6) {
9770 /* OPC_MAXA_S */
9771 TCGv_i32 fp0 = tcg_temp_new_i32();
9772 TCGv_i32 fp1 = tcg_temp_new_i32();
7c979afd
LA
9773 gen_load_fpr32(ctx, fp0, fs);
9774 gen_load_fpr32(ctx, fp1, ft);
e7f16abb 9775 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
7c979afd 9776 gen_store_fpr32(ctx, fp1, fd);
a7812ae4 9777 tcg_temp_free_i32(fp1);
a7812ae4 9778 tcg_temp_free_i32(fp0);
e7f16abb
LA
9779 } else {
9780 /* OPC_RSQRT2_S */
9781 check_cp1_64bitmode(ctx);
9782 {
9783 TCGv_i32 fp0 = tcg_temp_new_i32();
9784 TCGv_i32 fp1 = tcg_temp_new_i32();
9785
7c979afd
LA
9786 gen_load_fpr32(ctx, fp0, fs);
9787 gen_load_fpr32(ctx, fp1, ft);
e7f16abb
LA
9788 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9789 tcg_temp_free_i32(fp1);
7c979afd 9790 gen_store_fpr32(ctx, fp0, fd);
e7f16abb
LA
9791 tcg_temp_free_i32(fp0);
9792 }
b6d96bed 9793 }
57fa1fb3 9794 break;
bf4120ad 9795 case OPC_CVT_D_S:
5e755519 9796 check_cp1_registers(ctx, fd);
b6d96bed 9797 {
a7812ae4
PB
9798 TCGv_i32 fp32 = tcg_temp_new_i32();
9799 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9800
7c979afd 9801 gen_load_fpr32(ctx, fp32, fs);
895c2d04 9802 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
a7812ae4 9803 tcg_temp_free_i32(fp32);
b6d96bed 9804 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 9805 tcg_temp_free_i64(fp64);
b6d96bed 9806 }
5a5012ec 9807 break;
bf4120ad 9808 case OPC_CVT_W_S:
b6d96bed 9809 {
a7812ae4 9810 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 9811
7c979afd 9812 gen_load_fpr32(ctx, fp0, fs);
87552089
AM
9813 if (ctx->nan2008) {
9814 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
9815 } else {
9816 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
9817 }
7c979afd 9818 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 9819 tcg_temp_free_i32(fp0);
b6d96bed 9820 }
5a5012ec 9821 break;
bf4120ad 9822 case OPC_CVT_L_S:
5e755519 9823 check_cp1_64bitmode(ctx);
b6d96bed 9824 {
a7812ae4
PB
9825 TCGv_i32 fp32 = tcg_temp_new_i32();
9826 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 9827
7c979afd 9828 gen_load_fpr32(ctx, fp32, fs);
87552089
AM
9829 if (ctx->nan2008) {
9830 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
9831 } else {
9832 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
9833 }
a7812ae4 9834 tcg_temp_free_i32(fp32);
b6d96bed 9835 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 9836 tcg_temp_free_i64(fp64);
b6d96bed 9837 }
5a5012ec 9838 break;
bf4120ad 9839 case OPC_CVT_PS_S:
e29c9628 9840 check_ps(ctx);
b6d96bed 9841 {
a7812ae4
PB
9842 TCGv_i64 fp64 = tcg_temp_new_i64();
9843 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9844 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed 9845
7c979afd
LA
9846 gen_load_fpr32(ctx, fp32_0, fs);
9847 gen_load_fpr32(ctx, fp32_1, ft);
13d24f49 9848 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
a7812ae4
PB
9849 tcg_temp_free_i32(fp32_1);
9850 tcg_temp_free_i32(fp32_0);
36aa55dc 9851 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 9852 tcg_temp_free_i64(fp64);
b6d96bed 9853 }
5a5012ec 9854 break;
bf4120ad
NF
9855 case OPC_CMP_F_S:
9856 case OPC_CMP_UN_S:
9857 case OPC_CMP_EQ_S:
9858 case OPC_CMP_UEQ_S:
9859 case OPC_CMP_OLT_S:
9860 case OPC_CMP_ULT_S:
9861 case OPC_CMP_OLE_S:
9862 case OPC_CMP_ULE_S:
9863 case OPC_CMP_SF_S:
9864 case OPC_CMP_NGLE_S:
9865 case OPC_CMP_SEQ_S:
9866 case OPC_CMP_NGL_S:
9867 case OPC_CMP_LT_S:
9868 case OPC_CMP_NGE_S:
9869 case OPC_CMP_LE_S:
9870 case OPC_CMP_NGT_S:
fecd2646 9871 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c
NF
9872 if (ctx->opcode & (1 << 6)) {
9873 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
8153667c
NF
9874 } else {
9875 gen_cmp_s(ctx, func-48, ft, fs, cc);
5a1e8ffb 9876 }
5a5012ec 9877 break;
bf4120ad 9878 case OPC_ADD_D:
5e755519 9879 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 9880 {
a7812ae4
PB
9881 TCGv_i64 fp0 = tcg_temp_new_i64();
9882 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
9883
9884 gen_load_fpr64(ctx, fp0, fs);
9885 gen_load_fpr64(ctx, fp1, ft);
895c2d04 9886 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
a7812ae4 9887 tcg_temp_free_i64(fp1);
b6d96bed 9888 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9889 tcg_temp_free_i64(fp0);
b6d96bed 9890 }
6ea83fed 9891 break;
bf4120ad 9892 case OPC_SUB_D:
5e755519 9893 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 9894 {
a7812ae4
PB
9895 TCGv_i64 fp0 = tcg_temp_new_i64();
9896 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
9897
9898 gen_load_fpr64(ctx, fp0, fs);
9899 gen_load_fpr64(ctx, fp1, ft);
895c2d04 9900 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
a7812ae4 9901 tcg_temp_free_i64(fp1);
b6d96bed 9902 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9903 tcg_temp_free_i64(fp0);
b6d96bed 9904 }
6ea83fed 9905 break;
bf4120ad 9906 case OPC_MUL_D:
5e755519 9907 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 9908 {
a7812ae4
PB
9909 TCGv_i64 fp0 = tcg_temp_new_i64();
9910 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
9911
9912 gen_load_fpr64(ctx, fp0, fs);
9913 gen_load_fpr64(ctx, fp1, ft);
895c2d04 9914 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
a7812ae4 9915 tcg_temp_free_i64(fp1);
b6d96bed 9916 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9917 tcg_temp_free_i64(fp0);
b6d96bed 9918 }
6ea83fed 9919 break;
bf4120ad 9920 case OPC_DIV_D:
5e755519 9921 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 9922 {
a7812ae4
PB
9923 TCGv_i64 fp0 = tcg_temp_new_i64();
9924 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
9925
9926 gen_load_fpr64(ctx, fp0, fs);
9927 gen_load_fpr64(ctx, fp1, ft);
895c2d04 9928 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
a7812ae4 9929 tcg_temp_free_i64(fp1);
b6d96bed 9930 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9931 tcg_temp_free_i64(fp0);
b6d96bed 9932 }
6ea83fed 9933 break;
bf4120ad 9934 case OPC_SQRT_D:
5e755519 9935 check_cp1_registers(ctx, fs | fd);
b6d96bed 9936 {
a7812ae4 9937 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9938
9939 gen_load_fpr64(ctx, fp0, fs);
895c2d04 9940 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
b6d96bed 9941 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9942 tcg_temp_free_i64(fp0);
b6d96bed 9943 }
6ea83fed 9944 break;
bf4120ad 9945 case OPC_ABS_D:
5e755519 9946 check_cp1_registers(ctx, fs | fd);
b6d96bed 9947 {
a7812ae4 9948 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9949
9950 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
9951 if (ctx->abs2008) {
9952 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
9953 } else {
9954 gen_helper_float_abs_d(fp0, fp0);
9955 }
b6d96bed 9956 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9957 tcg_temp_free_i64(fp0);
b6d96bed 9958 }
6ea83fed 9959 break;
bf4120ad 9960 case OPC_MOV_D:
5e755519 9961 check_cp1_registers(ctx, fs | fd);
b6d96bed 9962 {
a7812ae4 9963 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9964
9965 gen_load_fpr64(ctx, fp0, fs);
9966 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9967 tcg_temp_free_i64(fp0);
b6d96bed 9968 }
6ea83fed 9969 break;
bf4120ad 9970 case OPC_NEG_D:
5e755519 9971 check_cp1_registers(ctx, fs | fd);
b6d96bed 9972 {
a7812ae4 9973 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9974
9975 gen_load_fpr64(ctx, fp0, fs);
6be77480
AM
9976 if (ctx->abs2008) {
9977 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
9978 } else {
9979 gen_helper_float_chs_d(fp0, fp0);
9980 }
b6d96bed 9981 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9982 tcg_temp_free_i64(fp0);
b6d96bed 9983 }
6ea83fed 9984 break;
bf4120ad 9985 case OPC_ROUND_L_D:
5e755519 9986 check_cp1_64bitmode(ctx);
b6d96bed 9987 {
a7812ae4 9988 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
9989
9990 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
9991 if (ctx->nan2008) {
9992 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
9993 } else {
9994 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
9995 }
b6d96bed 9996 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 9997 tcg_temp_free_i64(fp0);
b6d96bed 9998 }
5a5012ec 9999 break;
bf4120ad 10000 case OPC_TRUNC_L_D:
5e755519 10001 check_cp1_64bitmode(ctx);
b6d96bed 10002 {
a7812ae4 10003 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10004
10005 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10006 if (ctx->nan2008) {
10007 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10008 } else {
10009 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10010 }
b6d96bed 10011 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10012 tcg_temp_free_i64(fp0);
b6d96bed 10013 }
5a5012ec 10014 break;
bf4120ad 10015 case OPC_CEIL_L_D:
5e755519 10016 check_cp1_64bitmode(ctx);
b6d96bed 10017 {
a7812ae4 10018 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10019
10020 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10021 if (ctx->nan2008) {
10022 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10023 } else {
10024 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10025 }
b6d96bed 10026 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10027 tcg_temp_free_i64(fp0);
b6d96bed 10028 }
5a5012ec 10029 break;
bf4120ad 10030 case OPC_FLOOR_L_D:
5e755519 10031 check_cp1_64bitmode(ctx);
b6d96bed 10032 {
a7812ae4 10033 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10034
10035 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10036 if (ctx->nan2008) {
10037 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10038 } else {
10039 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10040 }
b6d96bed 10041 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10042 tcg_temp_free_i64(fp0);
b6d96bed 10043 }
5a5012ec 10044 break;
bf4120ad 10045 case OPC_ROUND_W_D:
5e755519 10046 check_cp1_registers(ctx, fs);
b6d96bed 10047 {
a7812ae4
PB
10048 TCGv_i32 fp32 = tcg_temp_new_i32();
10049 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10050
10051 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10052 if (ctx->nan2008) {
10053 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10054 } else {
10055 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10056 }
a7812ae4 10057 tcg_temp_free_i64(fp64);
7c979afd 10058 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10059 tcg_temp_free_i32(fp32);
b6d96bed 10060 }
6ea83fed 10061 break;
bf4120ad 10062 case OPC_TRUNC_W_D:
5e755519 10063 check_cp1_registers(ctx, fs);
b6d96bed 10064 {
a7812ae4
PB
10065 TCGv_i32 fp32 = tcg_temp_new_i32();
10066 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10067
10068 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10069 if (ctx->nan2008) {
10070 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
10071 } else {
10072 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
10073 }
a7812ae4 10074 tcg_temp_free_i64(fp64);
7c979afd 10075 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10076 tcg_temp_free_i32(fp32);
b6d96bed 10077 }
6ea83fed 10078 break;
bf4120ad 10079 case OPC_CEIL_W_D:
5e755519 10080 check_cp1_registers(ctx, fs);
b6d96bed 10081 {
a7812ae4
PB
10082 TCGv_i32 fp32 = tcg_temp_new_i32();
10083 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10084
10085 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10086 if (ctx->nan2008) {
10087 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
10088 } else {
10089 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
10090 }
a7812ae4 10091 tcg_temp_free_i64(fp64);
7c979afd 10092 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10093 tcg_temp_free_i32(fp32);
b6d96bed 10094 }
6ea83fed 10095 break;
bf4120ad 10096 case OPC_FLOOR_W_D:
5e755519 10097 check_cp1_registers(ctx, fs);
b6d96bed 10098 {
a7812ae4
PB
10099 TCGv_i32 fp32 = tcg_temp_new_i32();
10100 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10101
10102 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10103 if (ctx->nan2008) {
10104 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
10105 } else {
10106 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
10107 }
a7812ae4 10108 tcg_temp_free_i64(fp64);
7c979afd 10109 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10110 tcg_temp_free_i32(fp32);
b6d96bed 10111 }
6ea83fed 10112 break;
e7f16abb
LA
10113 case OPC_SEL_D:
10114 check_insn(ctx, ISA_MIPS32R6);
10115 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
10116 break;
10117 case OPC_SELEQZ_D:
10118 check_insn(ctx, ISA_MIPS32R6);
10119 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb
LA
10120 break;
10121 case OPC_SELNEZ_D:
10122 check_insn(ctx, ISA_MIPS32R6);
10123 gen_sel_d(ctx, op1, fd, ft, fs);
e7f16abb 10124 break;
bf4120ad 10125 case OPC_MOVCF_D:
fecd2646 10126 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6d96bed 10127 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
dd016883 10128 break;
bf4120ad 10129 case OPC_MOVZ_D:
fecd2646 10130 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 10131 {
42a268c2 10132 TCGLabel *l1 = gen_new_label();
c9297f4d 10133 TCGv_i64 fp0;
a16336e4 10134
c9297f4d
AJ
10135 if (ft != 0) {
10136 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10137 }
10138 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10139 gen_load_fpr64(ctx, fp0, fs);
10140 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10141 tcg_temp_free_i64(fp0);
a16336e4
TS
10142 gen_set_label(l1);
10143 }
5a5012ec 10144 break;
bf4120ad 10145 case OPC_MOVN_D:
fecd2646 10146 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a16336e4 10147 {
42a268c2 10148 TCGLabel *l1 = gen_new_label();
c9297f4d
AJ
10149 TCGv_i64 fp0;
10150
10151 if (ft != 0) {
10152 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10153 fp0 = tcg_temp_new_i64();
10154 gen_load_fpr64(ctx, fp0, fs);
10155 gen_store_fpr64(ctx, fp0, fd);
10156 tcg_temp_free_i64(fp0);
10157 gen_set_label(l1);
10158 }
a16336e4 10159 }
6ea83fed 10160 break;
bf4120ad 10161 case OPC_RECIP_D:
ca6c7803 10162 check_cp1_registers(ctx, fs | fd);
b6d96bed 10163 {
a7812ae4 10164 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10165
10166 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10167 gen_helper_float_recip_d(fp0, cpu_env, fp0);
b6d96bed 10168 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10169 tcg_temp_free_i64(fp0);
b6d96bed 10170 }
57fa1fb3 10171 break;
bf4120ad 10172 case OPC_RSQRT_D:
ca6c7803 10173 check_cp1_registers(ctx, fs | fd);
b6d96bed 10174 {
a7812ae4 10175 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10176
10177 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10178 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
b6d96bed 10179 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10180 tcg_temp_free_i64(fp0);
b6d96bed 10181 }
57fa1fb3 10182 break;
e7f16abb
LA
10183 case OPC_MADDF_D:
10184 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 10185 {
a7812ae4
PB
10186 TCGv_i64 fp0 = tcg_temp_new_i64();
10187 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb 10188 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
10189 gen_load_fpr64(ctx, fp0, fs);
10190 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
10191 gen_load_fpr64(ctx, fp2, fd);
10192 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
10193 gen_store_fpr64(ctx, fp2, fd);
10194 tcg_temp_free_i64(fp2);
a7812ae4 10195 tcg_temp_free_i64(fp1);
a7812ae4 10196 tcg_temp_free_i64(fp0);
b6d96bed 10197 }
57fa1fb3 10198 break;
e7f16abb
LA
10199 case OPC_MSUBF_D:
10200 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 10201 {
a7812ae4 10202 TCGv_i64 fp0 = tcg_temp_new_i64();
e7f16abb
LA
10203 TCGv_i64 fp1 = tcg_temp_new_i64();
10204 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed 10205 gen_load_fpr64(ctx, fp0, fs);
e7f16abb
LA
10206 gen_load_fpr64(ctx, fp1, ft);
10207 gen_load_fpr64(ctx, fp2, fd);
10208 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
10209 gen_store_fpr64(ctx, fp2, fd);
10210 tcg_temp_free_i64(fp2);
10211 tcg_temp_free_i64(fp1);
a7812ae4 10212 tcg_temp_free_i64(fp0);
b6d96bed 10213 }
57fa1fb3 10214 break;
e7f16abb
LA
10215 case OPC_RINT_D:
10216 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 10217 {
a7812ae4 10218 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 10219 gen_load_fpr64(ctx, fp0, fs);
e7f16abb 10220 gen_helper_float_rint_d(fp0, cpu_env, fp0);
b6d96bed 10221 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10222 tcg_temp_free_i64(fp0);
b6d96bed 10223 }
57fa1fb3 10224 break;
e7f16abb
LA
10225 case OPC_CLASS_D:
10226 check_insn(ctx, ISA_MIPS32R6);
b6d96bed 10227 {
e7f16abb
LA
10228 TCGv_i64 fp0 = tcg_temp_new_i64();
10229 gen_load_fpr64(ctx, fp0, fs);
af39bc8c 10230 gen_helper_float_class_d(fp0, cpu_env, fp0);
e7f16abb
LA
10231 gen_store_fpr64(ctx, fp0, fd);
10232 tcg_temp_free_i64(fp0);
e7f16abb
LA
10233 }
10234 break;
10235 case OPC_MIN_D: /* OPC_RECIP2_D */
10236 if (ctx->insn_flags & ISA_MIPS32R6) {
10237 /* OPC_MIN_D */
a7812ae4
PB
10238 TCGv_i64 fp0 = tcg_temp_new_i64();
10239 TCGv_i64 fp1 = tcg_temp_new_i64();
e7f16abb
LA
10240 gen_load_fpr64(ctx, fp0, fs);
10241 gen_load_fpr64(ctx, fp1, ft);
10242 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
10243 gen_store_fpr64(ctx, fp1, fd);
10244 tcg_temp_free_i64(fp1);
10245 tcg_temp_free_i64(fp0);
e7f16abb
LA
10246 } else {
10247 /* OPC_RECIP2_D */
10248 check_cp1_64bitmode(ctx);
10249 {
10250 TCGv_i64 fp0 = tcg_temp_new_i64();
10251 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed 10252
e7f16abb
LA
10253 gen_load_fpr64(ctx, fp0, fs);
10254 gen_load_fpr64(ctx, fp1, ft);
10255 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
10256 tcg_temp_free_i64(fp1);
10257 gen_store_fpr64(ctx, fp0, fd);
10258 tcg_temp_free_i64(fp0);
10259 }
e7f16abb
LA
10260 }
10261 break;
10262 case OPC_MINA_D: /* OPC_RECIP1_D */
10263 if (ctx->insn_flags & ISA_MIPS32R6) {
10264 /* OPC_MINA_D */
10265 TCGv_i64 fp0 = tcg_temp_new_i64();
10266 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10267 gen_load_fpr64(ctx, fp0, fs);
10268 gen_load_fpr64(ctx, fp1, ft);
e7f16abb
LA
10269 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
10270 gen_store_fpr64(ctx, fp1, fd);
10271 tcg_temp_free_i64(fp1);
10272 tcg_temp_free_i64(fp0);
e7f16abb
LA
10273 } else {
10274 /* OPC_RECIP1_D */
10275 check_cp1_64bitmode(ctx);
10276 {
10277 TCGv_i64 fp0 = tcg_temp_new_i64();
10278
10279 gen_load_fpr64(ctx, fp0, fs);
10280 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
10281 gen_store_fpr64(ctx, fp0, fd);
10282 tcg_temp_free_i64(fp0);
10283 }
e7f16abb
LA
10284 }
10285 break;
10286 case OPC_MAX_D: /* OPC_RSQRT1_D */
10287 if (ctx->insn_flags & ISA_MIPS32R6) {
10288 /* OPC_MAX_D */
10289 TCGv_i64 fp0 = tcg_temp_new_i64();
10290 TCGv_i64 fp1 = tcg_temp_new_i64();
10291 gen_load_fpr64(ctx, fp0, fs);
10292 gen_load_fpr64(ctx, fp1, ft);
10293 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
10294 gen_store_fpr64(ctx, fp1, fd);
a7812ae4 10295 tcg_temp_free_i64(fp1);
a7812ae4 10296 tcg_temp_free_i64(fp0);
e7f16abb
LA
10297 } else {
10298 /* OPC_RSQRT1_D */
10299 check_cp1_64bitmode(ctx);
10300 {
10301 TCGv_i64 fp0 = tcg_temp_new_i64();
10302
10303 gen_load_fpr64(ctx, fp0, fs);
10304 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
10305 gen_store_fpr64(ctx, fp0, fd);
10306 tcg_temp_free_i64(fp0);
10307 }
e7f16abb
LA
10308 }
10309 break;
10310 case OPC_MAXA_D: /* OPC_RSQRT2_D */
10311 if (ctx->insn_flags & ISA_MIPS32R6) {
10312 /* OPC_MAXA_D */
10313 TCGv_i64 fp0 = tcg_temp_new_i64();
10314 TCGv_i64 fp1 = tcg_temp_new_i64();
10315 gen_load_fpr64(ctx, fp0, fs);
10316 gen_load_fpr64(ctx, fp1, ft);
10317 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
10318 gen_store_fpr64(ctx, fp1, fd);
10319 tcg_temp_free_i64(fp1);
10320 tcg_temp_free_i64(fp0);
e7f16abb
LA
10321 } else {
10322 /* OPC_RSQRT2_D */
10323 check_cp1_64bitmode(ctx);
10324 {
10325 TCGv_i64 fp0 = tcg_temp_new_i64();
10326 TCGv_i64 fp1 = tcg_temp_new_i64();
10327
10328 gen_load_fpr64(ctx, fp0, fs);
10329 gen_load_fpr64(ctx, fp1, ft);
10330 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
10331 tcg_temp_free_i64(fp1);
10332 gen_store_fpr64(ctx, fp0, fd);
10333 tcg_temp_free_i64(fp0);
10334 }
b6d96bed 10335 }
57fa1fb3 10336 break;
bf4120ad
NF
10337 case OPC_CMP_F_D:
10338 case OPC_CMP_UN_D:
10339 case OPC_CMP_EQ_D:
10340 case OPC_CMP_UEQ_D:
10341 case OPC_CMP_OLT_D:
10342 case OPC_CMP_ULT_D:
10343 case OPC_CMP_OLE_D:
10344 case OPC_CMP_ULE_D:
10345 case OPC_CMP_SF_D:
10346 case OPC_CMP_NGLE_D:
10347 case OPC_CMP_SEQ_D:
10348 case OPC_CMP_NGL_D:
10349 case OPC_CMP_LT_D:
10350 case OPC_CMP_NGE_D:
10351 case OPC_CMP_LE_D:
10352 case OPC_CMP_NGT_D:
fecd2646 10353 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8153667c
NF
10354 if (ctx->opcode & (1 << 6)) {
10355 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
8153667c
NF
10356 } else {
10357 gen_cmp_d(ctx, func-48, ft, fs, cc);
5a1e8ffb 10358 }
6ea83fed 10359 break;
bf4120ad 10360 case OPC_CVT_S_D:
5e755519 10361 check_cp1_registers(ctx, fs);
b6d96bed 10362 {
a7812ae4
PB
10363 TCGv_i32 fp32 = tcg_temp_new_i32();
10364 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10365
10366 gen_load_fpr64(ctx, fp64, fs);
895c2d04 10367 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
a7812ae4 10368 tcg_temp_free_i64(fp64);
7c979afd 10369 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10370 tcg_temp_free_i32(fp32);
b6d96bed 10371 }
5a5012ec 10372 break;
bf4120ad 10373 case OPC_CVT_W_D:
5e755519 10374 check_cp1_registers(ctx, fs);
b6d96bed 10375 {
a7812ae4
PB
10376 TCGv_i32 fp32 = tcg_temp_new_i32();
10377 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10378
10379 gen_load_fpr64(ctx, fp64, fs);
87552089
AM
10380 if (ctx->nan2008) {
10381 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
10382 } else {
10383 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
10384 }
a7812ae4 10385 tcg_temp_free_i64(fp64);
7c979afd 10386 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10387 tcg_temp_free_i32(fp32);
b6d96bed 10388 }
5a5012ec 10389 break;
bf4120ad 10390 case OPC_CVT_L_D:
5e755519 10391 check_cp1_64bitmode(ctx);
b6d96bed 10392 {
a7812ae4 10393 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10394
10395 gen_load_fpr64(ctx, fp0, fs);
87552089
AM
10396 if (ctx->nan2008) {
10397 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
10398 } else {
10399 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
10400 }
b6d96bed 10401 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10402 tcg_temp_free_i64(fp0);
b6d96bed 10403 }
5a5012ec 10404 break;
bf4120ad 10405 case OPC_CVT_S_W:
b6d96bed 10406 {
a7812ae4 10407 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10408
7c979afd 10409 gen_load_fpr32(ctx, fp0, fs);
895c2d04 10410 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
7c979afd 10411 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10412 tcg_temp_free_i32(fp0);
b6d96bed 10413 }
6ea83fed 10414 break;
bf4120ad 10415 case OPC_CVT_D_W:
5e755519 10416 check_cp1_registers(ctx, fd);
b6d96bed 10417 {
a7812ae4
PB
10418 TCGv_i32 fp32 = tcg_temp_new_i32();
10419 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed 10420
7c979afd 10421 gen_load_fpr32(ctx, fp32, fs);
895c2d04 10422 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
a7812ae4 10423 tcg_temp_free_i32(fp32);
b6d96bed 10424 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 10425 tcg_temp_free_i64(fp64);
b6d96bed 10426 }
5a5012ec 10427 break;
bf4120ad 10428 case OPC_CVT_S_L:
5e755519 10429 check_cp1_64bitmode(ctx);
b6d96bed 10430 {
a7812ae4
PB
10431 TCGv_i32 fp32 = tcg_temp_new_i32();
10432 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
10433
10434 gen_load_fpr64(ctx, fp64, fs);
895c2d04 10435 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
a7812ae4 10436 tcg_temp_free_i64(fp64);
7c979afd 10437 gen_store_fpr32(ctx, fp32, fd);
a7812ae4 10438 tcg_temp_free_i32(fp32);
b6d96bed 10439 }
5a5012ec 10440 break;
bf4120ad 10441 case OPC_CVT_D_L:
5e755519 10442 check_cp1_64bitmode(ctx);
b6d96bed 10443 {
a7812ae4 10444 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10445
10446 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10447 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
b6d96bed 10448 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10449 tcg_temp_free_i64(fp0);
b6d96bed 10450 }
5a5012ec 10451 break;
bf4120ad 10452 case OPC_CVT_PS_PW:
e29c9628 10453 check_ps(ctx);
b6d96bed 10454 {
a7812ae4 10455 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10456
10457 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10458 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
b6d96bed 10459 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10460 tcg_temp_free_i64(fp0);
b6d96bed 10461 }
5a5012ec 10462 break;
bf4120ad 10463 case OPC_ADD_PS:
e29c9628 10464 check_ps(ctx);
b6d96bed 10465 {
a7812ae4
PB
10466 TCGv_i64 fp0 = tcg_temp_new_i64();
10467 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10468
10469 gen_load_fpr64(ctx, fp0, fs);
10470 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10471 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 10472 tcg_temp_free_i64(fp1);
b6d96bed 10473 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10474 tcg_temp_free_i64(fp0);
b6d96bed 10475 }
6ea83fed 10476 break;
bf4120ad 10477 case OPC_SUB_PS:
e29c9628 10478 check_ps(ctx);
b6d96bed 10479 {
a7812ae4
PB
10480 TCGv_i64 fp0 = tcg_temp_new_i64();
10481 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10482
10483 gen_load_fpr64(ctx, fp0, fs);
10484 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10485 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 10486 tcg_temp_free_i64(fp1);
b6d96bed 10487 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10488 tcg_temp_free_i64(fp0);
b6d96bed 10489 }
6ea83fed 10490 break;
bf4120ad 10491 case OPC_MUL_PS:
e29c9628 10492 check_ps(ctx);
b6d96bed 10493 {
a7812ae4
PB
10494 TCGv_i64 fp0 = tcg_temp_new_i64();
10495 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10496
10497 gen_load_fpr64(ctx, fp0, fs);
10498 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10499 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 10500 tcg_temp_free_i64(fp1);
b6d96bed 10501 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10502 tcg_temp_free_i64(fp0);
b6d96bed 10503 }
6ea83fed 10504 break;
bf4120ad 10505 case OPC_ABS_PS:
e29c9628 10506 check_ps(ctx);
b6d96bed 10507 {
a7812ae4 10508 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10509
10510 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 10511 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 10512 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10513 tcg_temp_free_i64(fp0);
b6d96bed 10514 }
6ea83fed 10515 break;
bf4120ad 10516 case OPC_MOV_PS:
e29c9628 10517 check_ps(ctx);
b6d96bed 10518 {
a7812ae4 10519 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10520
10521 gen_load_fpr64(ctx, fp0, fs);
10522 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10523 tcg_temp_free_i64(fp0);
b6d96bed 10524 }
6ea83fed 10525 break;
bf4120ad 10526 case OPC_NEG_PS:
e29c9628 10527 check_ps(ctx);
b6d96bed 10528 {
a7812ae4 10529 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10530
10531 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 10532 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 10533 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10534 tcg_temp_free_i64(fp0);
b6d96bed 10535 }
6ea83fed 10536 break;
bf4120ad 10537 case OPC_MOVCF_PS:
e29c9628 10538 check_ps(ctx);
7f6613ce 10539 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6ea83fed 10540 break;
bf4120ad 10541 case OPC_MOVZ_PS:
e29c9628 10542 check_ps(ctx);
a16336e4 10543 {
42a268c2 10544 TCGLabel *l1 = gen_new_label();
30a3848b 10545 TCGv_i64 fp0;
a16336e4 10546
c9297f4d
AJ
10547 if (ft != 0)
10548 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10549 fp0 = tcg_temp_new_i64();
10550 gen_load_fpr64(ctx, fp0, fs);
10551 gen_store_fpr64(ctx, fp0, fd);
10552 tcg_temp_free_i64(fp0);
a16336e4
TS
10553 gen_set_label(l1);
10554 }
6ea83fed 10555 break;
bf4120ad 10556 case OPC_MOVN_PS:
e29c9628 10557 check_ps(ctx);
a16336e4 10558 {
42a268c2 10559 TCGLabel *l1 = gen_new_label();
30a3848b 10560 TCGv_i64 fp0;
c9297f4d
AJ
10561
10562 if (ft != 0) {
10563 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10564 fp0 = tcg_temp_new_i64();
10565 gen_load_fpr64(ctx, fp0, fs);
10566 gen_store_fpr64(ctx, fp0, fd);
10567 tcg_temp_free_i64(fp0);
10568 gen_set_label(l1);
10569 }
a16336e4 10570 }
6ea83fed 10571 break;
bf4120ad 10572 case OPC_ADDR_PS:
e29c9628 10573 check_ps(ctx);
b6d96bed 10574 {
a7812ae4
PB
10575 TCGv_i64 fp0 = tcg_temp_new_i64();
10576 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10577
10578 gen_load_fpr64(ctx, fp0, ft);
10579 gen_load_fpr64(ctx, fp1, fs);
895c2d04 10580 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 10581 tcg_temp_free_i64(fp1);
b6d96bed 10582 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10583 tcg_temp_free_i64(fp0);
b6d96bed 10584 }
fbcc6828 10585 break;
bf4120ad 10586 case OPC_MULR_PS:
e29c9628 10587 check_ps(ctx);
b6d96bed 10588 {
a7812ae4
PB
10589 TCGv_i64 fp0 = tcg_temp_new_i64();
10590 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10591
10592 gen_load_fpr64(ctx, fp0, ft);
10593 gen_load_fpr64(ctx, fp1, fs);
895c2d04 10594 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 10595 tcg_temp_free_i64(fp1);
b6d96bed 10596 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10597 tcg_temp_free_i64(fp0);
b6d96bed 10598 }
57fa1fb3 10599 break;
bf4120ad 10600 case OPC_RECIP2_PS:
e29c9628 10601 check_ps(ctx);
b6d96bed 10602 {
a7812ae4
PB
10603 TCGv_i64 fp0 = tcg_temp_new_i64();
10604 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10605
10606 gen_load_fpr64(ctx, fp0, fs);
d22d7289 10607 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10608 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 10609 tcg_temp_free_i64(fp1);
b6d96bed 10610 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10611 tcg_temp_free_i64(fp0);
b6d96bed 10612 }
57fa1fb3 10613 break;
bf4120ad 10614 case OPC_RECIP1_PS:
e29c9628 10615 check_ps(ctx);
b6d96bed 10616 {
a7812ae4 10617 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10618
10619 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10620 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
b6d96bed 10621 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10622 tcg_temp_free_i64(fp0);
b6d96bed 10623 }
57fa1fb3 10624 break;
bf4120ad 10625 case OPC_RSQRT1_PS:
e29c9628 10626 check_ps(ctx);
b6d96bed 10627 {
a7812ae4 10628 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10629
10630 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10631 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
b6d96bed 10632 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10633 tcg_temp_free_i64(fp0);
b6d96bed 10634 }
57fa1fb3 10635 break;
bf4120ad 10636 case OPC_RSQRT2_PS:
e29c9628 10637 check_ps(ctx);
b6d96bed 10638 {
a7812ae4
PB
10639 TCGv_i64 fp0 = tcg_temp_new_i64();
10640 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
10641
10642 gen_load_fpr64(ctx, fp0, fs);
10643 gen_load_fpr64(ctx, fp1, ft);
895c2d04 10644 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
a7812ae4 10645 tcg_temp_free_i64(fp1);
b6d96bed 10646 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10647 tcg_temp_free_i64(fp0);
b6d96bed 10648 }
57fa1fb3 10649 break;
bf4120ad 10650 case OPC_CVT_S_PU:
5e755519 10651 check_cp1_64bitmode(ctx);
b6d96bed 10652 {
a7812ae4 10653 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10654
7f6613ce 10655 gen_load_fpr32h(ctx, fp0, fs);
895c2d04 10656 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
7c979afd 10657 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10658 tcg_temp_free_i32(fp0);
b6d96bed 10659 }
dd016883 10660 break;
bf4120ad 10661 case OPC_CVT_PW_PS:
e29c9628 10662 check_ps(ctx);
b6d96bed 10663 {
a7812ae4 10664 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
10665
10666 gen_load_fpr64(ctx, fp0, fs);
895c2d04 10667 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
b6d96bed 10668 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10669 tcg_temp_free_i64(fp0);
b6d96bed 10670 }
6ea83fed 10671 break;
bf4120ad 10672 case OPC_CVT_S_PL:
5e755519 10673 check_cp1_64bitmode(ctx);
b6d96bed 10674 {
a7812ae4 10675 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10676
7c979afd 10677 gen_load_fpr32(ctx, fp0, fs);
895c2d04 10678 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
7c979afd 10679 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10680 tcg_temp_free_i32(fp0);
b6d96bed 10681 }
6ea83fed 10682 break;
bf4120ad 10683 case OPC_PLL_PS:
e29c9628 10684 check_ps(ctx);
b6d96bed 10685 {
a7812ae4
PB
10686 TCGv_i32 fp0 = tcg_temp_new_i32();
10687 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10688
7c979afd
LA
10689 gen_load_fpr32(ctx, fp0, fs);
10690 gen_load_fpr32(ctx, fp1, ft);
7f6613ce 10691 gen_store_fpr32h(ctx, fp0, fd);
7c979afd 10692 gen_store_fpr32(ctx, fp1, fd);
a7812ae4
PB
10693 tcg_temp_free_i32(fp0);
10694 tcg_temp_free_i32(fp1);
b6d96bed 10695 }
6ea83fed 10696 break;
bf4120ad 10697 case OPC_PLU_PS:
e29c9628 10698 check_ps(ctx);
b6d96bed 10699 {
a7812ae4
PB
10700 TCGv_i32 fp0 = tcg_temp_new_i32();
10701 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10702
7c979afd 10703 gen_load_fpr32(ctx, fp0, fs);
7f6613ce 10704 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 10705 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 10706 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
10707 tcg_temp_free_i32(fp0);
10708 tcg_temp_free_i32(fp1);
b6d96bed 10709 }
5a5012ec 10710 break;
bf4120ad 10711 case OPC_PUL_PS:
e29c9628 10712 check_ps(ctx);
b6d96bed 10713 {
a7812ae4
PB
10714 TCGv_i32 fp0 = tcg_temp_new_i32();
10715 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10716
7f6613ce 10717 gen_load_fpr32h(ctx, fp0, fs);
7c979afd
LA
10718 gen_load_fpr32(ctx, fp1, ft);
10719 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 10720 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
10721 tcg_temp_free_i32(fp0);
10722 tcg_temp_free_i32(fp1);
b6d96bed 10723 }
5a5012ec 10724 break;
bf4120ad 10725 case OPC_PUU_PS:
e29c9628 10726 check_ps(ctx);
b6d96bed 10727 {
a7812ae4
PB
10728 TCGv_i32 fp0 = tcg_temp_new_i32();
10729 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed 10730
7f6613ce
PJ
10731 gen_load_fpr32h(ctx, fp0, fs);
10732 gen_load_fpr32h(ctx, fp1, ft);
7c979afd 10733 gen_store_fpr32(ctx, fp1, fd);
7f6613ce 10734 gen_store_fpr32h(ctx, fp0, fd);
a7812ae4
PB
10735 tcg_temp_free_i32(fp0);
10736 tcg_temp_free_i32(fp1);
b6d96bed 10737 }
5a5012ec 10738 break;
bf4120ad
NF
10739 case OPC_CMP_F_PS:
10740 case OPC_CMP_UN_PS:
10741 case OPC_CMP_EQ_PS:
10742 case OPC_CMP_UEQ_PS:
10743 case OPC_CMP_OLT_PS:
10744 case OPC_CMP_ULT_PS:
10745 case OPC_CMP_OLE_PS:
10746 case OPC_CMP_ULE_PS:
10747 case OPC_CMP_SF_PS:
10748 case OPC_CMP_NGLE_PS:
10749 case OPC_CMP_SEQ_PS:
10750 case OPC_CMP_NGL_PS:
10751 case OPC_CMP_LT_PS:
10752 case OPC_CMP_NGE_PS:
10753 case OPC_CMP_LE_PS:
10754 case OPC_CMP_NGT_PS:
8153667c
NF
10755 if (ctx->opcode & (1 << 6)) {
10756 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
8153667c
NF
10757 } else {
10758 gen_cmp_ps(ctx, func-48, ft, fs, cc);
5a1e8ffb 10759 }
6ea83fed 10760 break;
5a5012ec 10761 default:
9d68ac14 10762 MIPS_INVAL("farith");
9c708c7f 10763 generate_exception_end(ctx, EXCP_RI);
6ea83fed
FB
10764 return;
10765 }
6ea83fed 10766}
6af0bf9c 10767
5a5012ec 10768/* Coprocessor 3 (FPU) */
5e755519
TS
10769static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10770 int fd, int fs, int base, int index)
7a387fff 10771{
4e2474d6 10772 TCGv t0 = tcg_temp_new();
7a387fff 10773
93b12ccc 10774 if (base == 0) {
6c5c1e20 10775 gen_load_gpr(t0, index);
93b12ccc 10776 } else if (index == 0) {
6c5c1e20 10777 gen_load_gpr(t0, base);
93b12ccc 10778 } else {
05168674 10779 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
93b12ccc 10780 }
5a5012ec 10781 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 10782 memory access. */
5a5012ec
TS
10783 switch (opc) {
10784 case OPC_LWXC1:
8c0ab41f 10785 check_cop1x(ctx);
b6d96bed 10786 {
a7812ae4 10787 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 10788
5f68f5ae 10789 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
585c88d5 10790 tcg_gen_trunc_tl_i32(fp0, t0);
7c979afd 10791 gen_store_fpr32(ctx, fp0, fd);
a7812ae4 10792 tcg_temp_free_i32(fp0);
b6d96bed 10793 }
5a5012ec
TS
10794 break;
10795 case OPC_LDXC1:
8c0ab41f
AJ
10796 check_cop1x(ctx);
10797 check_cp1_registers(ctx, fd);
b6d96bed 10798 {
a7812ae4 10799 TCGv_i64 fp0 = tcg_temp_new_i64();
5f68f5ae 10800 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 10801 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10802 tcg_temp_free_i64(fp0);
b6d96bed 10803 }
5a5012ec
TS
10804 break;
10805 case OPC_LUXC1:
8c0ab41f 10806 check_cp1_64bitmode(ctx);
6c5c1e20 10807 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 10808 {
a7812ae4 10809 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 10810
5f68f5ae 10811 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
b6d96bed 10812 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 10813 tcg_temp_free_i64(fp0);
b6d96bed 10814 }
5a5012ec
TS
10815 break;
10816 case OPC_SWXC1:
8c0ab41f 10817 check_cop1x(ctx);
b6d96bed 10818 {
a7812ae4 10819 TCGv_i32 fp0 = tcg_temp_new_i32();
7c979afd 10820 gen_load_fpr32(ctx, fp0, fs);
5f68f5ae 10821 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
a7812ae4 10822 tcg_temp_free_i32(fp0);
b6d96bed 10823 }
5a5012ec
TS
10824 break;
10825 case OPC_SDXC1:
8c0ab41f
AJ
10826 check_cop1x(ctx);
10827 check_cp1_registers(ctx, fs);
b6d96bed 10828 {
a7812ae4 10829 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 10830 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 10831 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 10832 tcg_temp_free_i64(fp0);
b6d96bed 10833 }
5a5012ec
TS
10834 break;
10835 case OPC_SUXC1:
8c0ab41f 10836 check_cp1_64bitmode(ctx);
6c5c1e20 10837 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 10838 {
a7812ae4 10839 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed 10840 gen_load_fpr64(ctx, fp0, fs);
5f68f5ae 10841 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
a7812ae4 10842 tcg_temp_free_i64(fp0);
b6d96bed 10843 }
5a5012ec 10844 break;
5a5012ec 10845 }
6c5c1e20 10846 tcg_temp_free(t0);
5a5012ec
TS
10847}
10848
5e755519
TS
10849static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10850 int fd, int fr, int fs, int ft)
5a5012ec 10851{
5a5012ec
TS
10852 switch (opc) {
10853 case OPC_ALNV_PS:
e29c9628 10854 check_ps(ctx);
a16336e4 10855 {
a7812ae4 10856 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
10857 TCGv_i32 fp = tcg_temp_new_i32();
10858 TCGv_i32 fph = tcg_temp_new_i32();
42a268c2
RH
10859 TCGLabel *l1 = gen_new_label();
10860 TCGLabel *l2 = gen_new_label();
a16336e4 10861
6c5c1e20
TS
10862 gen_load_gpr(t0, fr);
10863 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
10864
10865 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7c979afd 10866 gen_load_fpr32(ctx, fp, fs);
7f6613ce 10867 gen_load_fpr32h(ctx, fph, fs);
7c979afd 10868 gen_store_fpr32(ctx, fp, fd);
7f6613ce 10869 gen_store_fpr32h(ctx, fph, fd);
a16336e4
TS
10870 tcg_gen_br(l2);
10871 gen_set_label(l1);
6c5c1e20
TS
10872 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10873 tcg_temp_free(t0);
a16336e4 10874#ifdef TARGET_WORDS_BIGENDIAN
7c979afd 10875 gen_load_fpr32(ctx, fp, fs);
7f6613ce
PJ
10876 gen_load_fpr32h(ctx, fph, ft);
10877 gen_store_fpr32h(ctx, fp, fd);
7c979afd 10878 gen_store_fpr32(ctx, fph, fd);
a16336e4 10879#else
7f6613ce 10880 gen_load_fpr32h(ctx, fph, fs);
7c979afd
LA
10881 gen_load_fpr32(ctx, fp, ft);
10882 gen_store_fpr32(ctx, fph, fd);
7f6613ce 10883 gen_store_fpr32h(ctx, fp, fd);
a16336e4
TS
10884#endif
10885 gen_set_label(l2);
c905fdac
AJ
10886 tcg_temp_free_i32(fp);
10887 tcg_temp_free_i32(fph);
a16336e4 10888 }
5a5012ec
TS
10889 break;
10890 case OPC_MADD_S:
b8aa4598 10891 check_cop1x(ctx);
b6d96bed 10892 {
a7812ae4
PB
10893 TCGv_i32 fp0 = tcg_temp_new_i32();
10894 TCGv_i32 fp1 = tcg_temp_new_i32();
10895 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 10896
7c979afd
LA
10897 gen_load_fpr32(ctx, fp0, fs);
10898 gen_load_fpr32(ctx, fp1, ft);
10899 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 10900 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
10901 tcg_temp_free_i32(fp0);
10902 tcg_temp_free_i32(fp1);
7c979afd 10903 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 10904 tcg_temp_free_i32(fp2);
b6d96bed 10905 }
5a5012ec
TS
10906 break;
10907 case OPC_MADD_D:
b8aa4598
TS
10908 check_cop1x(ctx);
10909 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 10910 {
a7812ae4
PB
10911 TCGv_i64 fp0 = tcg_temp_new_i64();
10912 TCGv_i64 fp1 = tcg_temp_new_i64();
10913 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
10914
10915 gen_load_fpr64(ctx, fp0, fs);
10916 gen_load_fpr64(ctx, fp1, ft);
10917 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 10918 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
10919 tcg_temp_free_i64(fp0);
10920 tcg_temp_free_i64(fp1);
b6d96bed 10921 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 10922 tcg_temp_free_i64(fp2);
b6d96bed 10923 }
5a5012ec
TS
10924 break;
10925 case OPC_MADD_PS:
e29c9628 10926 check_ps(ctx);
b6d96bed 10927 {
a7812ae4
PB
10928 TCGv_i64 fp0 = tcg_temp_new_i64();
10929 TCGv_i64 fp1 = tcg_temp_new_i64();
10930 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
10931
10932 gen_load_fpr64(ctx, fp0, fs);
10933 gen_load_fpr64(ctx, fp1, ft);
10934 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 10935 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
10936 tcg_temp_free_i64(fp0);
10937 tcg_temp_free_i64(fp1);
b6d96bed 10938 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 10939 tcg_temp_free_i64(fp2);
b6d96bed 10940 }
5a5012ec
TS
10941 break;
10942 case OPC_MSUB_S:
b8aa4598 10943 check_cop1x(ctx);
b6d96bed 10944 {
a7812ae4
PB
10945 TCGv_i32 fp0 = tcg_temp_new_i32();
10946 TCGv_i32 fp1 = tcg_temp_new_i32();
10947 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 10948
7c979afd
LA
10949 gen_load_fpr32(ctx, fp0, fs);
10950 gen_load_fpr32(ctx, fp1, ft);
10951 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 10952 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
10953 tcg_temp_free_i32(fp0);
10954 tcg_temp_free_i32(fp1);
7c979afd 10955 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 10956 tcg_temp_free_i32(fp2);
b6d96bed 10957 }
5a5012ec
TS
10958 break;
10959 case OPC_MSUB_D:
b8aa4598
TS
10960 check_cop1x(ctx);
10961 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 10962 {
a7812ae4
PB
10963 TCGv_i64 fp0 = tcg_temp_new_i64();
10964 TCGv_i64 fp1 = tcg_temp_new_i64();
10965 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
10966
10967 gen_load_fpr64(ctx, fp0, fs);
10968 gen_load_fpr64(ctx, fp1, ft);
10969 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 10970 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
10971 tcg_temp_free_i64(fp0);
10972 tcg_temp_free_i64(fp1);
b6d96bed 10973 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 10974 tcg_temp_free_i64(fp2);
b6d96bed 10975 }
5a5012ec
TS
10976 break;
10977 case OPC_MSUB_PS:
e29c9628 10978 check_ps(ctx);
b6d96bed 10979 {
a7812ae4
PB
10980 TCGv_i64 fp0 = tcg_temp_new_i64();
10981 TCGv_i64 fp1 = tcg_temp_new_i64();
10982 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
10983
10984 gen_load_fpr64(ctx, fp0, fs);
10985 gen_load_fpr64(ctx, fp1, ft);
10986 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 10987 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
10988 tcg_temp_free_i64(fp0);
10989 tcg_temp_free_i64(fp1);
b6d96bed 10990 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 10991 tcg_temp_free_i64(fp2);
b6d96bed 10992 }
5a5012ec
TS
10993 break;
10994 case OPC_NMADD_S:
b8aa4598 10995 check_cop1x(ctx);
b6d96bed 10996 {
a7812ae4
PB
10997 TCGv_i32 fp0 = tcg_temp_new_i32();
10998 TCGv_i32 fp1 = tcg_temp_new_i32();
10999 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11000
7c979afd
LA
11001 gen_load_fpr32(ctx, fp0, fs);
11002 gen_load_fpr32(ctx, fp1, ft);
11003 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 11004 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11005 tcg_temp_free_i32(fp0);
11006 tcg_temp_free_i32(fp1);
7c979afd 11007 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 11008 tcg_temp_free_i32(fp2);
b6d96bed 11009 }
5a5012ec
TS
11010 break;
11011 case OPC_NMADD_D:
b8aa4598
TS
11012 check_cop1x(ctx);
11013 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11014 {
a7812ae4
PB
11015 TCGv_i64 fp0 = tcg_temp_new_i64();
11016 TCGv_i64 fp1 = tcg_temp_new_i64();
11017 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11018
11019 gen_load_fpr64(ctx, fp0, fs);
11020 gen_load_fpr64(ctx, fp1, ft);
11021 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11022 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11023 tcg_temp_free_i64(fp0);
11024 tcg_temp_free_i64(fp1);
b6d96bed 11025 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11026 tcg_temp_free_i64(fp2);
b6d96bed 11027 }
5a5012ec
TS
11028 break;
11029 case OPC_NMADD_PS:
e29c9628 11030 check_ps(ctx);
b6d96bed 11031 {
a7812ae4
PB
11032 TCGv_i64 fp0 = tcg_temp_new_i64();
11033 TCGv_i64 fp1 = tcg_temp_new_i64();
11034 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11035
11036 gen_load_fpr64(ctx, fp0, fs);
11037 gen_load_fpr64(ctx, fp1, ft);
11038 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11039 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11040 tcg_temp_free_i64(fp0);
11041 tcg_temp_free_i64(fp1);
b6d96bed 11042 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11043 tcg_temp_free_i64(fp2);
b6d96bed 11044 }
5a5012ec
TS
11045 break;
11046 case OPC_NMSUB_S:
b8aa4598 11047 check_cop1x(ctx);
b6d96bed 11048 {
a7812ae4
PB
11049 TCGv_i32 fp0 = tcg_temp_new_i32();
11050 TCGv_i32 fp1 = tcg_temp_new_i32();
11051 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed 11052
7c979afd
LA
11053 gen_load_fpr32(ctx, fp0, fs);
11054 gen_load_fpr32(ctx, fp1, ft);
11055 gen_load_fpr32(ctx, fp2, fr);
b3d6cd44 11056 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11057 tcg_temp_free_i32(fp0);
11058 tcg_temp_free_i32(fp1);
7c979afd 11059 gen_store_fpr32(ctx, fp2, fd);
a7812ae4 11060 tcg_temp_free_i32(fp2);
b6d96bed 11061 }
5a5012ec
TS
11062 break;
11063 case OPC_NMSUB_D:
b8aa4598
TS
11064 check_cop1x(ctx);
11065 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 11066 {
a7812ae4
PB
11067 TCGv_i64 fp0 = tcg_temp_new_i64();
11068 TCGv_i64 fp1 = tcg_temp_new_i64();
11069 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11070
11071 gen_load_fpr64(ctx, fp0, fs);
11072 gen_load_fpr64(ctx, fp1, ft);
11073 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11074 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11075 tcg_temp_free_i64(fp0);
11076 tcg_temp_free_i64(fp1);
b6d96bed 11077 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11078 tcg_temp_free_i64(fp2);
b6d96bed 11079 }
5a5012ec
TS
11080 break;
11081 case OPC_NMSUB_PS:
e29c9628 11082 check_ps(ctx);
b6d96bed 11083 {
a7812ae4
PB
11084 TCGv_i64 fp0 = tcg_temp_new_i64();
11085 TCGv_i64 fp1 = tcg_temp_new_i64();
11086 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
11087
11088 gen_load_fpr64(ctx, fp0, fs);
11089 gen_load_fpr64(ctx, fp1, ft);
11090 gen_load_fpr64(ctx, fp2, fr);
b3d6cd44 11091 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
a7812ae4
PB
11092 tcg_temp_free_i64(fp0);
11093 tcg_temp_free_i64(fp1);
b6d96bed 11094 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 11095 tcg_temp_free_i64(fp2);
b6d96bed 11096 }
5a5012ec 11097 break;
923617a3 11098 default:
9d68ac14 11099 MIPS_INVAL("flt3_arith");
9c708c7f 11100 generate_exception_end(ctx, EXCP_RI);
5a5012ec
TS
11101 return;
11102 }
7a387fff
TS
11103}
11104
b00c7218 11105static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
26ebe468
NF
11106{
11107 TCGv t0;
11108
b3167288
RH
11109#if !defined(CONFIG_USER_ONLY)
11110 /* The Linux kernel will emulate rdhwr if it's not supported natively.
11111 Therefore only check the ISA in system mode. */
d75c135e 11112 check_insn(ctx, ISA_MIPS32R2);
b3167288 11113#endif
26ebe468
NF
11114 t0 = tcg_temp_new();
11115
11116 switch (rd) {
11117 case 0:
895c2d04 11118 gen_helper_rdhwr_cpunum(t0, cpu_env);
26ebe468
NF
11119 gen_store_gpr(t0, rt);
11120 break;
11121 case 1:
895c2d04 11122 gen_helper_rdhwr_synci_step(t0, cpu_env);
26ebe468
NF
11123 gen_store_gpr(t0, rt);
11124 break;
11125 case 2:
eeb3bba8 11126 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
11127 gen_io_start();
11128 }
895c2d04 11129 gen_helper_rdhwr_cc(t0, cpu_env);
eeb3bba8 11130 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
d673a68d
JH
11131 gen_io_end();
11132 }
26ebe468 11133 gen_store_gpr(t0, rt);
d673a68d 11134 /* Break the TB to be able to take timer interrupts immediately
b28425ba 11135 after reading count. DISAS_STOP isn't sufficient, we need to ensure
d673a68d 11136 we break completely out of translated code. */
eeb3bba8
EC
11137 gen_save_pc(ctx->base.pc_next + 4);
11138 ctx->base.is_jmp = DISAS_EXIT;
26ebe468
NF
11139 break;
11140 case 3:
895c2d04 11141 gen_helper_rdhwr_ccres(t0, cpu_env);
26ebe468
NF
11142 gen_store_gpr(t0, rt);
11143 break;
b00c7218
YK
11144 case 4:
11145 check_insn(ctx, ISA_MIPS32R6);
11146 if (sel != 0) {
11147 /* Performance counter registers are not implemented other than
11148 * control register 0.
11149 */
11150 generate_exception(ctx, EXCP_RI);
11151 }
11152 gen_helper_rdhwr_performance(t0, cpu_env);
11153 gen_store_gpr(t0, rt);
11154 break;
11155 case 5:
11156 check_insn(ctx, ISA_MIPS32R6);
11157 gen_helper_rdhwr_xnp(t0, cpu_env);
11158 gen_store_gpr(t0, rt);
11159 break;
26ebe468
NF
11160 case 29:
11161#if defined(CONFIG_USER_ONLY)
d279279e
PJ
11162 tcg_gen_ld_tl(t0, cpu_env,
11163 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
26ebe468
NF
11164 gen_store_gpr(t0, rt);
11165 break;
11166#else
d279279e
PJ
11167 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
11168 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
11169 tcg_gen_ld_tl(t0, cpu_env,
11170 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11171 gen_store_gpr(t0, rt);
11172 } else {
9c708c7f 11173 generate_exception_end(ctx, EXCP_RI);
d279279e
PJ
11174 }
11175 break;
26ebe468
NF
11176#endif
11177 default: /* Invalid */
11178 MIPS_INVAL("rdhwr");
9c708c7f 11179 generate_exception_end(ctx, EXCP_RI);
26ebe468
NF
11180 break;
11181 }
11182 tcg_temp_free(t0);
11183}
11184
a5f53390
LA
11185static inline void clear_branch_hflags(DisasContext *ctx)
11186{
11187 ctx->hflags &= ~MIPS_HFLAG_BMASK;
eeb3bba8 11188 if (ctx->base.is_jmp == DISAS_NEXT) {
a5f53390
LA
11189 save_cpu_state(ctx, 0);
11190 } else {
11191 /* it is not safe to save ctx->hflags as hflags may be changed
11192 in execution time by the instruction in delay / forbidden slot. */
11193 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
11194 }
11195}
11196
31837be3 11197static void gen_branch(DisasContext *ctx, int insn_bytes)
c9602061
NF
11198{
11199 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 11200 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061 11201 /* Branches completion */
a5f53390 11202 clear_branch_hflags(ctx);
eeb3bba8 11203 ctx->base.is_jmp = DISAS_NORETURN;
c9602061 11204 /* FIXME: Need to clear can_do_io. */
364d4831 11205 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
339cd2a8 11206 case MIPS_HFLAG_FBNSLOT:
eeb3bba8 11207 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
339cd2a8 11208 break;
c9602061
NF
11209 case MIPS_HFLAG_B:
11210 /* unconditional branch */
364d4831
NF
11211 if (proc_hflags & MIPS_HFLAG_BX) {
11212 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
11213 }
c9602061
NF
11214 gen_goto_tb(ctx, 0, ctx->btarget);
11215 break;
11216 case MIPS_HFLAG_BL:
11217 /* blikely taken case */
c9602061
NF
11218 gen_goto_tb(ctx, 0, ctx->btarget);
11219 break;
11220 case MIPS_HFLAG_BC:
11221 /* Conditional branch */
c9602061 11222 {
42a268c2 11223 TCGLabel *l1 = gen_new_label();
c9602061
NF
11224
11225 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
eeb3bba8 11226 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
c9602061
NF
11227 gen_set_label(l1);
11228 gen_goto_tb(ctx, 0, ctx->btarget);
11229 }
11230 break;
11231 case MIPS_HFLAG_BR:
11232 /* unconditional branch to register */
d75c135e 11233 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
364d4831
NF
11234 TCGv t0 = tcg_temp_new();
11235 TCGv_i32 t1 = tcg_temp_new_i32();
11236
11237 tcg_gen_andi_tl(t0, btarget, 0x1);
11238 tcg_gen_trunc_tl_i32(t1, t0);
11239 tcg_temp_free(t0);
11240 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
11241 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
11242 tcg_gen_or_i32(hflags, hflags, t1);
11243 tcg_temp_free_i32(t1);
11244
11245 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
11246 } else {
11247 tcg_gen_mov_tl(cpu_PC, btarget);
11248 }
eeb3bba8 11249 if (ctx->base.singlestep_enabled) {
c9602061 11250 save_cpu_state(ctx, 0);
9c708c7f 11251 gen_helper_raise_exception_debug(cpu_env);
c9602061 11252 }
7f11636d 11253 tcg_gen_lookup_and_goto_ptr();
c9602061
NF
11254 break;
11255 default:
a5f53390
LA
11256 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
11257 abort();
c9602061
NF
11258 }
11259 }
11260}
11261
6893f074
YK
11262/* Compact Branches */
11263static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
11264 int rs, int rt, int32_t offset)
11265{
11266 int bcond_compute = 0;
11267 TCGv t0 = tcg_temp_new();
11268 TCGv t1 = tcg_temp_new();
65935f07 11269 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
6893f074
YK
11270
11271 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11272#ifdef MIPS_DEBUG_DISAS
11273 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
eeb3bba8 11274 "\n", ctx->base.pc_next);
6893f074 11275#endif
9c708c7f 11276 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
11277 goto out;
11278 }
11279
11280 /* Load needed operands and calculate btarget */
11281 switch (opc) {
11282 /* compact branch */
11283 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11284 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11285 gen_load_gpr(t0, rs);
11286 gen_load_gpr(t1, rt);
11287 bcond_compute = 1;
eeb3bba8 11288 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11289 if (rs <= rt && rs == 0) {
11290 /* OPC_BEQZALC, OPC_BNEZALC */
eeb3bba8 11291 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
11292 }
11293 break;
11294 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11295 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11296 gen_load_gpr(t0, rs);
11297 gen_load_gpr(t1, rt);
11298 bcond_compute = 1;
eeb3bba8 11299 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11300 break;
11301 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11302 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11303 if (rs == 0 || rs == rt) {
11304 /* OPC_BLEZALC, OPC_BGEZALC */
11305 /* OPC_BGTZALC, OPC_BLTZALC */
eeb3bba8 11306 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
11307 }
11308 gen_load_gpr(t0, rs);
11309 gen_load_gpr(t1, rt);
11310 bcond_compute = 1;
eeb3bba8 11311 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11312 break;
11313 case OPC_BC:
11314 case OPC_BALC:
eeb3bba8 11315 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11316 break;
11317 case OPC_BEQZC:
11318 case OPC_BNEZC:
11319 if (rs != 0) {
11320 /* OPC_BEQZC, OPC_BNEZC */
11321 gen_load_gpr(t0, rs);
11322 bcond_compute = 1;
eeb3bba8 11323 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
6893f074
YK
11324 } else {
11325 /* OPC_JIC, OPC_JIALC */
11326 TCGv tbase = tcg_temp_new();
11327 TCGv toffset = tcg_temp_new();
11328
11329 gen_load_gpr(tbase, rt);
11330 tcg_gen_movi_tl(toffset, offset);
11331 gen_op_addr_add(ctx, btarget, tbase, toffset);
11332 tcg_temp_free(tbase);
11333 tcg_temp_free(toffset);
11334 }
11335 break;
11336 default:
11337 MIPS_INVAL("Compact branch/jump");
9c708c7f 11338 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
11339 goto out;
11340 }
11341
11342 if (bcond_compute == 0) {
11343 /* Uncoditional compact branch */
11344 switch (opc) {
11345 case OPC_JIALC:
eeb3bba8 11346 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
11347 /* Fallthrough */
11348 case OPC_JIC:
11349 ctx->hflags |= MIPS_HFLAG_BR;
11350 break;
11351 case OPC_BALC:
eeb3bba8 11352 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
6893f074
YK
11353 /* Fallthrough */
11354 case OPC_BC:
11355 ctx->hflags |= MIPS_HFLAG_B;
11356 break;
11357 default:
11358 MIPS_INVAL("Compact branch/jump");
9c708c7f 11359 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
11360 goto out;
11361 }
11362
11363 /* Generating branch here as compact branches don't have delay slot */
11364 gen_branch(ctx, 4);
11365 } else {
11366 /* Conditional compact branch */
11367 TCGLabel *fs = gen_new_label();
11368 save_cpu_state(ctx, 0);
11369
11370 switch (opc) {
11371 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11372 if (rs == 0 && rt != 0) {
11373 /* OPC_BLEZALC */
11374 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11375 } else if (rs != 0 && rt != 0 && rs == rt) {
11376 /* OPC_BGEZALC */
11377 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11378 } else {
11379 /* OPC_BGEUC */
11380 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
11381 }
11382 break;
11383 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11384 if (rs == 0 && rt != 0) {
11385 /* OPC_BGTZALC */
11386 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11387 } else if (rs != 0 && rt != 0 && rs == rt) {
11388 /* OPC_BLTZALC */
11389 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11390 } else {
11391 /* OPC_BLTUC */
11392 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
11393 }
11394 break;
11395 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11396 if (rs == 0 && rt != 0) {
11397 /* OPC_BLEZC */
11398 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11399 } else if (rs != 0 && rt != 0 && rs == rt) {
11400 /* OPC_BGEZC */
11401 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11402 } else {
11403 /* OPC_BGEC */
11404 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
11405 }
11406 break;
11407 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11408 if (rs == 0 && rt != 0) {
11409 /* OPC_BGTZC */
11410 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11411 } else if (rs != 0 && rt != 0 && rs == rt) {
11412 /* OPC_BLTZC */
11413 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11414 } else {
11415 /* OPC_BLTC */
11416 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
11417 }
11418 break;
11419 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11420 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11421 if (rs >= rt) {
11422 /* OPC_BOVC, OPC_BNVC */
11423 TCGv t2 = tcg_temp_new();
11424 TCGv t3 = tcg_temp_new();
11425 TCGv t4 = tcg_temp_new();
11426 TCGv input_overflow = tcg_temp_new();
11427
11428 gen_load_gpr(t0, rs);
11429 gen_load_gpr(t1, rt);
11430 tcg_gen_ext32s_tl(t2, t0);
11431 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
11432 tcg_gen_ext32s_tl(t3, t1);
11433 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
11434 tcg_gen_or_tl(input_overflow, input_overflow, t4);
11435
11436 tcg_gen_add_tl(t4, t2, t3);
11437 tcg_gen_ext32s_tl(t4, t4);
11438 tcg_gen_xor_tl(t2, t2, t3);
11439 tcg_gen_xor_tl(t3, t4, t3);
11440 tcg_gen_andc_tl(t2, t3, t2);
11441 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
11442 tcg_gen_or_tl(t4, t4, input_overflow);
11443 if (opc == OPC_BOVC) {
11444 /* OPC_BOVC */
11445 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
11446 } else {
11447 /* OPC_BNVC */
11448 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
11449 }
11450 tcg_temp_free(input_overflow);
11451 tcg_temp_free(t4);
11452 tcg_temp_free(t3);
11453 tcg_temp_free(t2);
11454 } else if (rs < rt && rs == 0) {
11455 /* OPC_BEQZALC, OPC_BNEZALC */
11456 if (opc == OPC_BEQZALC) {
11457 /* OPC_BEQZALC */
11458 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
11459 } else {
11460 /* OPC_BNEZALC */
11461 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
11462 }
11463 } else {
11464 /* OPC_BEQC, OPC_BNEC */
11465 if (opc == OPC_BEQC) {
11466 /* OPC_BEQC */
11467 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
11468 } else {
11469 /* OPC_BNEC */
11470 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
11471 }
11472 }
11473 break;
11474 case OPC_BEQZC:
11475 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
11476 break;
11477 case OPC_BNEZC:
11478 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
11479 break;
11480 default:
11481 MIPS_INVAL("Compact conditional branch/jump");
9c708c7f 11482 generate_exception_end(ctx, EXCP_RI);
6893f074
YK
11483 goto out;
11484 }
11485
11486 /* Generating branch here as compact branches don't have delay slot */
11487 gen_goto_tb(ctx, 1, ctx->btarget);
11488 gen_set_label(fs);
11489
11490 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
6893f074
YK
11491 }
11492
11493out:
11494 tcg_temp_free(t0);
11495 tcg_temp_free(t1);
11496}
11497
7a387fff 11498/* ISA extensions (ASEs) */
6af0bf9c 11499/* MIPS16 extension to MIPS32 */
6ea219d0
NF
11500
11501/* MIPS16 major opcodes */
11502enum {
11503 M16_OPC_ADDIUSP = 0x00,
11504 M16_OPC_ADDIUPC = 0x01,
11505 M16_OPC_B = 0x02,
11506 M16_OPC_JAL = 0x03,
11507 M16_OPC_BEQZ = 0x04,
11508 M16_OPC_BNEQZ = 0x05,
11509 M16_OPC_SHIFT = 0x06,
11510 M16_OPC_LD = 0x07,
11511 M16_OPC_RRIA = 0x08,
11512 M16_OPC_ADDIU8 = 0x09,
11513 M16_OPC_SLTI = 0x0a,
11514 M16_OPC_SLTIU = 0x0b,
11515 M16_OPC_I8 = 0x0c,
11516 M16_OPC_LI = 0x0d,
11517 M16_OPC_CMPI = 0x0e,
11518 M16_OPC_SD = 0x0f,
11519 M16_OPC_LB = 0x10,
11520 M16_OPC_LH = 0x11,
11521 M16_OPC_LWSP = 0x12,
11522 M16_OPC_LW = 0x13,
11523 M16_OPC_LBU = 0x14,
11524 M16_OPC_LHU = 0x15,
11525 M16_OPC_LWPC = 0x16,
11526 M16_OPC_LWU = 0x17,
11527 M16_OPC_SB = 0x18,
11528 M16_OPC_SH = 0x19,
11529 M16_OPC_SWSP = 0x1a,
11530 M16_OPC_SW = 0x1b,
11531 M16_OPC_RRR = 0x1c,
11532 M16_OPC_RR = 0x1d,
11533 M16_OPC_EXTEND = 0x1e,
11534 M16_OPC_I64 = 0x1f
11535};
11536
11537/* I8 funct field */
11538enum {
11539 I8_BTEQZ = 0x0,
11540 I8_BTNEZ = 0x1,
11541 I8_SWRASP = 0x2,
11542 I8_ADJSP = 0x3,
11543 I8_SVRS = 0x4,
11544 I8_MOV32R = 0x5,
11545 I8_MOVR32 = 0x7
11546};
11547
11548/* RRR f field */
11549enum {
11550 RRR_DADDU = 0x0,
11551 RRR_ADDU = 0x1,
11552 RRR_DSUBU = 0x2,
11553 RRR_SUBU = 0x3
11554};
11555
11556/* RR funct field */
11557enum {
11558 RR_JR = 0x00,
11559 RR_SDBBP = 0x01,
11560 RR_SLT = 0x02,
11561 RR_SLTU = 0x03,
11562 RR_SLLV = 0x04,
11563 RR_BREAK = 0x05,
11564 RR_SRLV = 0x06,
11565 RR_SRAV = 0x07,
11566 RR_DSRL = 0x08,
11567 RR_CMP = 0x0a,
11568 RR_NEG = 0x0b,
11569 RR_AND = 0x0c,
11570 RR_OR = 0x0d,
11571 RR_XOR = 0x0e,
11572 RR_NOT = 0x0f,
11573 RR_MFHI = 0x10,
11574 RR_CNVT = 0x11,
11575 RR_MFLO = 0x12,
11576 RR_DSRA = 0x13,
11577 RR_DSLLV = 0x14,
11578 RR_DSRLV = 0x16,
11579 RR_DSRAV = 0x17,
11580 RR_MULT = 0x18,
11581 RR_MULTU = 0x19,
11582 RR_DIV = 0x1a,
11583 RR_DIVU = 0x1b,
11584 RR_DMULT = 0x1c,
11585 RR_DMULTU = 0x1d,
11586 RR_DDIV = 0x1e,
11587 RR_DDIVU = 0x1f
11588};
11589
11590/* I64 funct field */
11591enum {
11592 I64_LDSP = 0x0,
11593 I64_SDSP = 0x1,
11594 I64_SDRASP = 0x2,
11595 I64_DADJSP = 0x3,
11596 I64_LDPC = 0x4,
364d4831 11597 I64_DADDIU5 = 0x5,
6ea219d0
NF
11598 I64_DADDIUPC = 0x6,
11599 I64_DADDIUSP = 0x7
11600};
11601
11602/* RR ry field for CNVT */
11603enum {
11604 RR_RY_CNVT_ZEB = 0x0,
11605 RR_RY_CNVT_ZEH = 0x1,
11606 RR_RY_CNVT_ZEW = 0x2,
11607 RR_RY_CNVT_SEB = 0x4,
11608 RR_RY_CNVT_SEH = 0x5,
11609 RR_RY_CNVT_SEW = 0x6,
11610};
11611
364d4831
NF
11612static int xlat (int r)
11613{
11614 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11615
11616 return map[r];
11617}
11618
11619static void gen_mips16_save (DisasContext *ctx,
11620 int xsregs, int aregs,
11621 int do_ra, int do_s0, int do_s1,
11622 int framesize)
11623{
11624 TCGv t0 = tcg_temp_new();
11625 TCGv t1 = tcg_temp_new();
c48245f0 11626 TCGv t2 = tcg_temp_new();
364d4831
NF
11627 int args, astatic;
11628
11629 switch (aregs) {
11630 case 0:
11631 case 1:
11632 case 2:
11633 case 3:
11634 case 11:
11635 args = 0;
11636 break;
11637 case 4:
11638 case 5:
11639 case 6:
11640 case 7:
11641 args = 1;
11642 break;
11643 case 8:
11644 case 9:
11645 case 10:
11646 args = 2;
11647 break;
11648 case 12:
11649 case 13:
11650 args = 3;
11651 break;
11652 case 14:
11653 args = 4;
11654 break;
11655 default:
9c708c7f 11656 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
11657 return;
11658 }
11659
11660 switch (args) {
11661 case 4:
11662 gen_base_offset_addr(ctx, t0, 29, 12);
11663 gen_load_gpr(t1, 7);
5f68f5ae 11664 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
11665 /* Fall through */
11666 case 3:
11667 gen_base_offset_addr(ctx, t0, 29, 8);
11668 gen_load_gpr(t1, 6);
5f68f5ae 11669 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
11670 /* Fall through */
11671 case 2:
11672 gen_base_offset_addr(ctx, t0, 29, 4);
11673 gen_load_gpr(t1, 5);
5f68f5ae 11674 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
11675 /* Fall through */
11676 case 1:
11677 gen_base_offset_addr(ctx, t0, 29, 0);
11678 gen_load_gpr(t1, 4);
5f68f5ae 11679 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
364d4831
NF
11680 }
11681
11682 gen_load_gpr(t0, 29);
11683
5f68f5ae 11684#define DECR_AND_STORE(reg) do { \
c48245f0
MR
11685 tcg_gen_movi_tl(t2, -4); \
11686 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
11687 gen_load_gpr(t1, reg); \
11688 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
364d4831
NF
11689 } while (0)
11690
11691 if (do_ra) {
11692 DECR_AND_STORE(31);
11693 }
11694
11695 switch (xsregs) {
11696 case 7:
11697 DECR_AND_STORE(30);
11698 /* Fall through */
11699 case 6:
11700 DECR_AND_STORE(23);
11701 /* Fall through */
11702 case 5:
11703 DECR_AND_STORE(22);
11704 /* Fall through */
11705 case 4:
11706 DECR_AND_STORE(21);
11707 /* Fall through */
11708 case 3:
11709 DECR_AND_STORE(20);
11710 /* Fall through */
11711 case 2:
11712 DECR_AND_STORE(19);
11713 /* Fall through */
11714 case 1:
11715 DECR_AND_STORE(18);
11716 }
11717
11718 if (do_s1) {
11719 DECR_AND_STORE(17);
11720 }
11721 if (do_s0) {
11722 DECR_AND_STORE(16);
11723 }
11724
11725 switch (aregs) {
11726 case 0:
11727 case 4:
11728 case 8:
11729 case 12:
11730 case 14:
11731 astatic = 0;
11732 break;
11733 case 1:
11734 case 5:
11735 case 9:
11736 case 13:
11737 astatic = 1;
11738 break;
11739 case 2:
11740 case 6:
11741 case 10:
11742 astatic = 2;
11743 break;
11744 case 3:
11745 case 7:
11746 astatic = 3;
11747 break;
11748 case 11:
11749 astatic = 4;
11750 break;
11751 default:
9c708c7f 11752 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
11753 return;
11754 }
11755
11756 if (astatic > 0) {
11757 DECR_AND_STORE(7);
11758 if (astatic > 1) {
11759 DECR_AND_STORE(6);
11760 if (astatic > 2) {
11761 DECR_AND_STORE(5);
11762 if (astatic > 3) {
11763 DECR_AND_STORE(4);
11764 }
11765 }
11766 }
11767 }
11768#undef DECR_AND_STORE
11769
c48245f0
MR
11770 tcg_gen_movi_tl(t2, -framesize);
11771 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
11772 tcg_temp_free(t0);
11773 tcg_temp_free(t1);
c48245f0 11774 tcg_temp_free(t2);
364d4831
NF
11775}
11776
11777static void gen_mips16_restore (DisasContext *ctx,
11778 int xsregs, int aregs,
11779 int do_ra, int do_s0, int do_s1,
11780 int framesize)
11781{
11782 int astatic;
11783 TCGv t0 = tcg_temp_new();
11784 TCGv t1 = tcg_temp_new();
c48245f0 11785 TCGv t2 = tcg_temp_new();
364d4831 11786
c48245f0
MR
11787 tcg_gen_movi_tl(t2, framesize);
11788 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
364d4831 11789
5f68f5ae 11790#define DECR_AND_LOAD(reg) do { \
c48245f0
MR
11791 tcg_gen_movi_tl(t2, -4); \
11792 gen_op_addr_add(ctx, t0, t0, t2); \
5f68f5ae
AJ
11793 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11794 gen_store_gpr(t1, reg); \
364d4831
NF
11795 } while (0)
11796
11797 if (do_ra) {
11798 DECR_AND_LOAD(31);
11799 }
11800
11801 switch (xsregs) {
11802 case 7:
11803 DECR_AND_LOAD(30);
11804 /* Fall through */
11805 case 6:
11806 DECR_AND_LOAD(23);
11807 /* Fall through */
11808 case 5:
11809 DECR_AND_LOAD(22);
11810 /* Fall through */
11811 case 4:
11812 DECR_AND_LOAD(21);
11813 /* Fall through */
11814 case 3:
11815 DECR_AND_LOAD(20);
11816 /* Fall through */
11817 case 2:
11818 DECR_AND_LOAD(19);
11819 /* Fall through */
11820 case 1:
11821 DECR_AND_LOAD(18);
11822 }
11823
11824 if (do_s1) {
11825 DECR_AND_LOAD(17);
11826 }
11827 if (do_s0) {
11828 DECR_AND_LOAD(16);
11829 }
11830
11831 switch (aregs) {
11832 case 0:
11833 case 4:
11834 case 8:
11835 case 12:
11836 case 14:
11837 astatic = 0;
11838 break;
11839 case 1:
11840 case 5:
11841 case 9:
11842 case 13:
11843 astatic = 1;
11844 break;
11845 case 2:
11846 case 6:
11847 case 10:
11848 astatic = 2;
11849 break;
11850 case 3:
11851 case 7:
11852 astatic = 3;
11853 break;
11854 case 11:
11855 astatic = 4;
11856 break;
11857 default:
9c708c7f 11858 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
11859 return;
11860 }
11861
11862 if (astatic > 0) {
11863 DECR_AND_LOAD(7);
11864 if (astatic > 1) {
11865 DECR_AND_LOAD(6);
11866 if (astatic > 2) {
11867 DECR_AND_LOAD(5);
11868 if (astatic > 3) {
11869 DECR_AND_LOAD(4);
11870 }
11871 }
11872 }
11873 }
11874#undef DECR_AND_LOAD
11875
c48245f0
MR
11876 tcg_gen_movi_tl(t2, framesize);
11877 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
364d4831
NF
11878 tcg_temp_free(t0);
11879 tcg_temp_free(t1);
c48245f0 11880 tcg_temp_free(t2);
364d4831
NF
11881}
11882
11883static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11884 int is_64_bit, int extended)
11885{
11886 TCGv t0;
11887
11888 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 11889 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
11890 return;
11891 }
11892
11893 t0 = tcg_temp_new();
11894
11895 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11896 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11897 if (!is_64_bit) {
11898 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11899 }
11900
11901 tcg_temp_free(t0);
11902}
11903
0d74a222
LA
11904static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
11905 int16_t offset)
11906{
11907 TCGv_i32 t0 = tcg_const_i32(op);
11908 TCGv t1 = tcg_temp_new();
11909 gen_base_offset_addr(ctx, t1, base, offset);
11910 gen_helper_cache(cpu_env, t1, t0);
11911}
11912
364d4831 11913#if defined(TARGET_MIPS64)
d75c135e 11914static void decode_i64_mips16 (DisasContext *ctx,
364d4831
NF
11915 int ry, int funct, int16_t offset,
11916 int extended)
11917{
11918 switch (funct) {
11919 case I64_LDSP:
d9224450 11920 check_insn(ctx, ISA_MIPS3);
364d4831
NF
11921 check_mips_64(ctx);
11922 offset = extended ? offset : offset << 3;
d75c135e 11923 gen_ld(ctx, OPC_LD, ry, 29, offset);
364d4831
NF
11924 break;
11925 case I64_SDSP:
d9224450 11926 check_insn(ctx, ISA_MIPS3);
364d4831
NF
11927 check_mips_64(ctx);
11928 offset = extended ? offset : offset << 3;
5c13fdfd 11929 gen_st(ctx, OPC_SD, ry, 29, offset);
364d4831
NF
11930 break;
11931 case I64_SDRASP:
d9224450 11932 check_insn(ctx, ISA_MIPS3);
364d4831
NF
11933 check_mips_64(ctx);
11934 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
5c13fdfd 11935 gen_st(ctx, OPC_SD, 31, 29, offset);
364d4831
NF
11936 break;
11937 case I64_DADJSP:
d9224450 11938 check_insn(ctx, ISA_MIPS3);
364d4831
NF
11939 check_mips_64(ctx);
11940 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
d75c135e 11941 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
364d4831
NF
11942 break;
11943 case I64_LDPC:
d9224450
MR
11944 check_insn(ctx, ISA_MIPS3);
11945 check_mips_64(ctx);
364d4831 11946 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 11947 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
11948 } else {
11949 offset = extended ? offset : offset << 3;
d75c135e 11950 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
364d4831
NF
11951 }
11952 break;
11953 case I64_DADDIU5:
d9224450 11954 check_insn(ctx, ISA_MIPS3);
364d4831
NF
11955 check_mips_64(ctx);
11956 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
d75c135e 11957 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
364d4831
NF
11958 break;
11959 case I64_DADDIUPC:
d9224450 11960 check_insn(ctx, ISA_MIPS3);
364d4831
NF
11961 check_mips_64(ctx);
11962 offset = extended ? offset : offset << 2;
11963 gen_addiupc(ctx, ry, offset, 1, extended);
11964 break;
11965 case I64_DADDIUSP:
d9224450 11966 check_insn(ctx, ISA_MIPS3);
364d4831
NF
11967 check_mips_64(ctx);
11968 offset = extended ? offset : offset << 2;
d75c135e 11969 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
364d4831
NF
11970 break;
11971 }
11972}
11973#endif
11974
240ce26a 11975static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
364d4831 11976{
eeb3bba8 11977 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
11978 int op, rx, ry, funct, sa;
11979 int16_t imm, offset;
11980
11981 ctx->opcode = (ctx->opcode << 16) | extend;
11982 op = (ctx->opcode >> 11) & 0x1f;
11983 sa = (ctx->opcode >> 22) & 0x1f;
11984 funct = (ctx->opcode >> 8) & 0x7;
11985 rx = xlat((ctx->opcode >> 8) & 0x7);
11986 ry = xlat((ctx->opcode >> 5) & 0x7);
11987 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11988 | ((ctx->opcode >> 21) & 0x3f) << 5
11989 | (ctx->opcode & 0x1f));
11990
11991 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11992 counterparts. */
11993 switch (op) {
11994 case M16_OPC_ADDIUSP:
d75c135e 11995 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
11996 break;
11997 case M16_OPC_ADDIUPC:
11998 gen_addiupc(ctx, rx, imm, 0, 1);
11999 break;
12000 case M16_OPC_B:
b231c103 12001 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
364d4831
NF
12002 /* No delay slot, so just process as a normal instruction */
12003 break;
12004 case M16_OPC_BEQZ:
b231c103 12005 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
364d4831
NF
12006 /* No delay slot, so just process as a normal instruction */
12007 break;
12008 case M16_OPC_BNEQZ:
b231c103 12009 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
364d4831
NF
12010 /* No delay slot, so just process as a normal instruction */
12011 break;
12012 case M16_OPC_SHIFT:
12013 switch (ctx->opcode & 0x3) {
12014 case 0x0:
d75c135e 12015 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
12016 break;
12017 case 0x1:
12018#if defined(TARGET_MIPS64)
12019 check_mips_64(ctx);
d75c135e 12020 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 12021#else
9c708c7f 12022 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12023#endif
12024 break;
12025 case 0x2:
d75c135e 12026 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
12027 break;
12028 case 0x3:
d75c135e 12029 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
12030 break;
12031 }
12032 break;
12033#if defined(TARGET_MIPS64)
12034 case M16_OPC_LD:
d9224450 12035 check_insn(ctx, ISA_MIPS3);
d75de749 12036 check_mips_64(ctx);
d75c135e 12037 gen_ld(ctx, OPC_LD, ry, rx, offset);
364d4831
NF
12038 break;
12039#endif
12040 case M16_OPC_RRIA:
12041 imm = ctx->opcode & 0xf;
12042 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
12043 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
12044 imm = (int16_t) (imm << 1) >> 1;
12045 if ((ctx->opcode >> 4) & 0x1) {
12046#if defined(TARGET_MIPS64)
12047 check_mips_64(ctx);
d75c135e 12048 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 12049#else
9c708c7f 12050 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12051#endif
12052 } else {
d75c135e 12053 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
12054 }
12055 break;
12056 case M16_OPC_ADDIU8:
d75c135e 12057 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
12058 break;
12059 case M16_OPC_SLTI:
d75c135e 12060 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
12061 break;
12062 case M16_OPC_SLTIU:
d75c135e 12063 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
12064 break;
12065 case M16_OPC_I8:
12066 switch (funct) {
12067 case I8_BTEQZ:
b231c103 12068 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
364d4831
NF
12069 break;
12070 case I8_BTNEZ:
b231c103 12071 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
364d4831
NF
12072 break;
12073 case I8_SWRASP:
5c13fdfd 12074 gen_st(ctx, OPC_SW, 31, 29, imm);
364d4831
NF
12075 break;
12076 case I8_ADJSP:
d75c135e 12077 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
364d4831
NF
12078 break;
12079 case I8_SVRS:
d9224450 12080 check_insn(ctx, ISA_MIPS32);
364d4831
NF
12081 {
12082 int xsregs = (ctx->opcode >> 24) & 0x7;
12083 int aregs = (ctx->opcode >> 16) & 0xf;
12084 int do_ra = (ctx->opcode >> 6) & 0x1;
12085 int do_s0 = (ctx->opcode >> 5) & 0x1;
12086 int do_s1 = (ctx->opcode >> 4) & 0x1;
12087 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
12088 | (ctx->opcode & 0xf)) << 3;
12089
12090 if (ctx->opcode & (1 << 7)) {
12091 gen_mips16_save(ctx, xsregs, aregs,
12092 do_ra, do_s0, do_s1,
12093 framesize);
12094 } else {
12095 gen_mips16_restore(ctx, xsregs, aregs,
12096 do_ra, do_s0, do_s1,
12097 framesize);
12098 }
12099 }
12100 break;
12101 default:
9c708c7f 12102 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12103 break;
12104 }
12105 break;
12106 case M16_OPC_LI:
12107 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
12108 break;
12109 case M16_OPC_CMPI:
12110 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
12111 break;
12112#if defined(TARGET_MIPS64)
12113 case M16_OPC_SD:
d9224450
MR
12114 check_insn(ctx, ISA_MIPS3);
12115 check_mips_64(ctx);
5c13fdfd 12116 gen_st(ctx, OPC_SD, ry, rx, offset);
364d4831
NF
12117 break;
12118#endif
12119 case M16_OPC_LB:
d75c135e 12120 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
12121 break;
12122 case M16_OPC_LH:
d75c135e 12123 gen_ld(ctx, OPC_LH, ry, rx, offset);
364d4831
NF
12124 break;
12125 case M16_OPC_LWSP:
d75c135e 12126 gen_ld(ctx, OPC_LW, rx, 29, offset);
364d4831
NF
12127 break;
12128 case M16_OPC_LW:
d75c135e 12129 gen_ld(ctx, OPC_LW, ry, rx, offset);
364d4831
NF
12130 break;
12131 case M16_OPC_LBU:
d75c135e 12132 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
12133 break;
12134 case M16_OPC_LHU:
d75c135e 12135 gen_ld(ctx, OPC_LHU, ry, rx, offset);
364d4831
NF
12136 break;
12137 case M16_OPC_LWPC:
d75c135e 12138 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
364d4831
NF
12139 break;
12140#if defined(TARGET_MIPS64)
12141 case M16_OPC_LWU:
d9224450
MR
12142 check_insn(ctx, ISA_MIPS3);
12143 check_mips_64(ctx);
d75c135e 12144 gen_ld(ctx, OPC_LWU, ry, rx, offset);
364d4831
NF
12145 break;
12146#endif
12147 case M16_OPC_SB:
5c13fdfd 12148 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
12149 break;
12150 case M16_OPC_SH:
5c13fdfd 12151 gen_st(ctx, OPC_SH, ry, rx, offset);
364d4831
NF
12152 break;
12153 case M16_OPC_SWSP:
5c13fdfd 12154 gen_st(ctx, OPC_SW, rx, 29, offset);
364d4831
NF
12155 break;
12156 case M16_OPC_SW:
5c13fdfd 12157 gen_st(ctx, OPC_SW, ry, rx, offset);
364d4831
NF
12158 break;
12159#if defined(TARGET_MIPS64)
12160 case M16_OPC_I64:
d75c135e 12161 decode_i64_mips16(ctx, ry, funct, offset, 1);
364d4831
NF
12162 break;
12163#endif
12164 default:
9c708c7f 12165 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12166 break;
12167 }
12168
12169 return 4;
12170}
12171
3b3c1694
LA
12172static inline bool is_uhi(int sdbbp_code)
12173{
12174#ifdef CONFIG_USER_ONLY
12175 return false;
12176#else
12177 return semihosting_enabled() && sdbbp_code == 1;
12178#endif
12179}
12180
240ce26a 12181static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
364d4831
NF
12182{
12183 int rx, ry;
12184 int sa;
12185 int op, cnvt_op, op1, offset;
12186 int funct;
12187 int n_bytes;
12188
12189 op = (ctx->opcode >> 11) & 0x1f;
12190 sa = (ctx->opcode >> 2) & 0x7;
12191 sa = sa == 0 ? 8 : sa;
12192 rx = xlat((ctx->opcode >> 8) & 0x7);
12193 cnvt_op = (ctx->opcode >> 5) & 0x7;
12194 ry = xlat((ctx->opcode >> 5) & 0x7);
12195 op1 = offset = ctx->opcode & 0x1f;
12196
12197 n_bytes = 2;
12198
12199 switch (op) {
12200 case M16_OPC_ADDIUSP:
12201 {
12202 int16_t imm = ((uint8_t) ctx->opcode) << 2;
12203
d75c135e 12204 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
364d4831
NF
12205 }
12206 break;
12207 case M16_OPC_ADDIUPC:
12208 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
12209 break;
12210 case M16_OPC_B:
12211 offset = (ctx->opcode & 0x7ff) << 1;
12212 offset = (int16_t)(offset << 4) >> 4;
b231c103 12213 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
364d4831
NF
12214 /* No delay slot, so just process as a normal instruction */
12215 break;
12216 case M16_OPC_JAL:
eeb3bba8 12217 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
364d4831
NF
12218 offset = (((ctx->opcode & 0x1f) << 21)
12219 | ((ctx->opcode >> 5) & 0x1f) << 16
12220 | offset) << 2;
b231c103
YK
12221 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
12222 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
364d4831 12223 n_bytes = 4;
364d4831
NF
12224 break;
12225 case M16_OPC_BEQZ:
b231c103
YK
12226 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
12227 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
12228 /* No delay slot, so just process as a normal instruction */
12229 break;
12230 case M16_OPC_BNEQZ:
b231c103
YK
12231 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
12232 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
12233 /* No delay slot, so just process as a normal instruction */
12234 break;
12235 case M16_OPC_SHIFT:
12236 switch (ctx->opcode & 0x3) {
12237 case 0x0:
d75c135e 12238 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
364d4831
NF
12239 break;
12240 case 0x1:
12241#if defined(TARGET_MIPS64)
d9224450 12242 check_insn(ctx, ISA_MIPS3);
364d4831 12243 check_mips_64(ctx);
d75c135e 12244 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
364d4831 12245#else
9c708c7f 12246 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12247#endif
12248 break;
12249 case 0x2:
d75c135e 12250 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
364d4831
NF
12251 break;
12252 case 0x3:
d75c135e 12253 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
364d4831
NF
12254 break;
12255 }
12256 break;
12257#if defined(TARGET_MIPS64)
12258 case M16_OPC_LD:
d9224450 12259 check_insn(ctx, ISA_MIPS3);
364d4831 12260 check_mips_64(ctx);
d75c135e 12261 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
364d4831
NF
12262 break;
12263#endif
12264 case M16_OPC_RRIA:
12265 {
12266 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
12267
12268 if ((ctx->opcode >> 4) & 1) {
12269#if defined(TARGET_MIPS64)
d9224450 12270 check_insn(ctx, ISA_MIPS3);
364d4831 12271 check_mips_64(ctx);
d75c135e 12272 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
364d4831 12273#else
9c708c7f 12274 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12275#endif
12276 } else {
d75c135e 12277 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
364d4831
NF
12278 }
12279 }
12280 break;
12281 case M16_OPC_ADDIU8:
12282 {
12283 int16_t imm = (int8_t) ctx->opcode;
12284
d75c135e 12285 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
364d4831
NF
12286 }
12287 break;
12288 case M16_OPC_SLTI:
12289 {
12290 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 12291 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
364d4831
NF
12292 }
12293 break;
12294 case M16_OPC_SLTIU:
12295 {
12296 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 12297 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
364d4831
NF
12298 }
12299 break;
12300 case M16_OPC_I8:
12301 {
12302 int reg32;
12303
12304 funct = (ctx->opcode >> 8) & 0x7;
12305 switch (funct) {
12306 case I8_BTEQZ:
12307 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
b231c103 12308 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
12309 break;
12310 case I8_BTNEZ:
12311 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
b231c103 12312 ((int8_t)ctx->opcode) << 1, 0);
364d4831
NF
12313 break;
12314 case I8_SWRASP:
5c13fdfd 12315 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
364d4831
NF
12316 break;
12317 case I8_ADJSP:
d75c135e 12318 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
364d4831
NF
12319 ((int8_t)ctx->opcode) << 3);
12320 break;
12321 case I8_SVRS:
d9224450 12322 check_insn(ctx, ISA_MIPS32);
364d4831
NF
12323 {
12324 int do_ra = ctx->opcode & (1 << 6);
12325 int do_s0 = ctx->opcode & (1 << 5);
12326 int do_s1 = ctx->opcode & (1 << 4);
12327 int framesize = ctx->opcode & 0xf;
12328
12329 if (framesize == 0) {
12330 framesize = 128;
12331 } else {
12332 framesize = framesize << 3;
12333 }
12334
12335 if (ctx->opcode & (1 << 7)) {
12336 gen_mips16_save(ctx, 0, 0,
12337 do_ra, do_s0, do_s1, framesize);
12338 } else {
12339 gen_mips16_restore(ctx, 0, 0,
12340 do_ra, do_s0, do_s1, framesize);
12341 }
12342 }
12343 break;
12344 case I8_MOV32R:
12345 {
12346 int rz = xlat(ctx->opcode & 0x7);
12347
12348 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
12349 ((ctx->opcode >> 5) & 0x7);
d75c135e 12350 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
364d4831
NF
12351 }
12352 break;
12353 case I8_MOVR32:
12354 reg32 = ctx->opcode & 0x1f;
d75c135e 12355 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
364d4831
NF
12356 break;
12357 default:
9c708c7f 12358 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12359 break;
12360 }
12361 }
12362 break;
12363 case M16_OPC_LI:
12364 {
12365 int16_t imm = (uint8_t) ctx->opcode;
12366
d75c135e 12367 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
364d4831
NF
12368 }
12369 break;
12370 case M16_OPC_CMPI:
12371 {
12372 int16_t imm = (uint8_t) ctx->opcode;
d75c135e 12373 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
364d4831
NF
12374 }
12375 break;
12376#if defined(TARGET_MIPS64)
12377 case M16_OPC_SD:
d9224450 12378 check_insn(ctx, ISA_MIPS3);
364d4831 12379 check_mips_64(ctx);
5c13fdfd 12380 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
364d4831
NF
12381 break;
12382#endif
12383 case M16_OPC_LB:
d75c135e 12384 gen_ld(ctx, OPC_LB, ry, rx, offset);
364d4831
NF
12385 break;
12386 case M16_OPC_LH:
d75c135e 12387 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
364d4831
NF
12388 break;
12389 case M16_OPC_LWSP:
d75c135e 12390 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
12391 break;
12392 case M16_OPC_LW:
d75c135e 12393 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
364d4831
NF
12394 break;
12395 case M16_OPC_LBU:
d75c135e 12396 gen_ld(ctx, OPC_LBU, ry, rx, offset);
364d4831
NF
12397 break;
12398 case M16_OPC_LHU:
d75c135e 12399 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
364d4831
NF
12400 break;
12401 case M16_OPC_LWPC:
d75c135e 12402 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
12403 break;
12404#if defined (TARGET_MIPS64)
12405 case M16_OPC_LWU:
d9224450 12406 check_insn(ctx, ISA_MIPS3);
364d4831 12407 check_mips_64(ctx);
d75c135e 12408 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
364d4831
NF
12409 break;
12410#endif
12411 case M16_OPC_SB:
5c13fdfd 12412 gen_st(ctx, OPC_SB, ry, rx, offset);
364d4831
NF
12413 break;
12414 case M16_OPC_SH:
5c13fdfd 12415 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
364d4831
NF
12416 break;
12417 case M16_OPC_SWSP:
5c13fdfd 12418 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
364d4831
NF
12419 break;
12420 case M16_OPC_SW:
5c13fdfd 12421 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
364d4831
NF
12422 break;
12423 case M16_OPC_RRR:
12424 {
12425 int rz = xlat((ctx->opcode >> 2) & 0x7);
12426 int mips32_op;
12427
12428 switch (ctx->opcode & 0x3) {
12429 case RRR_ADDU:
12430 mips32_op = OPC_ADDU;
12431 break;
12432 case RRR_SUBU:
12433 mips32_op = OPC_SUBU;
12434 break;
12435#if defined(TARGET_MIPS64)
12436 case RRR_DADDU:
12437 mips32_op = OPC_DADDU;
d9224450 12438 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12439 check_mips_64(ctx);
12440 break;
12441 case RRR_DSUBU:
12442 mips32_op = OPC_DSUBU;
d9224450 12443 check_insn(ctx, ISA_MIPS3);
364d4831
NF
12444 check_mips_64(ctx);
12445 break;
12446#endif
12447 default:
9c708c7f 12448 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12449 goto done;
12450 }
12451
d75c135e 12452 gen_arith(ctx, mips32_op, rz, rx, ry);
364d4831
NF
12453 done:
12454 ;
12455 }
12456 break;
12457 case M16_OPC_RR:
12458 switch (op1) {
12459 case RR_JR:
12460 {
12461 int nd = (ctx->opcode >> 7) & 0x1;
12462 int link = (ctx->opcode >> 6) & 0x1;
12463 int ra = (ctx->opcode >> 5) & 0x1;
12464
d9224450
MR
12465 if (nd) {
12466 check_insn(ctx, ISA_MIPS32);
12467 }
12468
364d4831 12469 if (link) {
b231c103 12470 op = OPC_JALR;
364d4831
NF
12471 } else {
12472 op = OPC_JR;
12473 }
12474
b231c103
YK
12475 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
12476 (nd ? 0 : 2));
364d4831
NF
12477 }
12478 break;
12479 case RR_SDBBP:
3b3c1694
LA
12480 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
12481 gen_helper_do_semihosting(cpu_env);
12482 } else {
12483 /* XXX: not clear which exception should be raised
12484 * when in debug mode...
12485 */
12486 check_insn(ctx, ISA_MIPS32);
9c708c7f 12487 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 12488 }
364d4831
NF
12489 break;
12490 case RR_SLT:
d75c135e 12491 gen_slt(ctx, OPC_SLT, 24, rx, ry);
364d4831
NF
12492 break;
12493 case RR_SLTU:
d75c135e 12494 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
364d4831
NF
12495 break;
12496 case RR_BREAK:
9c708c7f 12497 generate_exception_end(ctx, EXCP_BREAK);
364d4831
NF
12498 break;
12499 case RR_SLLV:
d75c135e 12500 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
364d4831
NF
12501 break;
12502 case RR_SRLV:
d75c135e 12503 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
364d4831
NF
12504 break;
12505 case RR_SRAV:
d75c135e 12506 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
364d4831
NF
12507 break;
12508#if defined (TARGET_MIPS64)
12509 case RR_DSRL:
d9224450 12510 check_insn(ctx, ISA_MIPS3);
364d4831 12511 check_mips_64(ctx);
d75c135e 12512 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
364d4831
NF
12513 break;
12514#endif
12515 case RR_CMP:
d75c135e 12516 gen_logic(ctx, OPC_XOR, 24, rx, ry);
364d4831
NF
12517 break;
12518 case RR_NEG:
d75c135e 12519 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
364d4831
NF
12520 break;
12521 case RR_AND:
d75c135e 12522 gen_logic(ctx, OPC_AND, rx, rx, ry);
364d4831
NF
12523 break;
12524 case RR_OR:
d75c135e 12525 gen_logic(ctx, OPC_OR, rx, rx, ry);
364d4831
NF
12526 break;
12527 case RR_XOR:
d75c135e 12528 gen_logic(ctx, OPC_XOR, rx, rx, ry);
364d4831
NF
12529 break;
12530 case RR_NOT:
d75c135e 12531 gen_logic(ctx, OPC_NOR, rx, ry, 0);
364d4831
NF
12532 break;
12533 case RR_MFHI:
26135ead 12534 gen_HILO(ctx, OPC_MFHI, 0, rx);
364d4831
NF
12535 break;
12536 case RR_CNVT:
d9224450 12537 check_insn(ctx, ISA_MIPS32);
364d4831
NF
12538 switch (cnvt_op) {
12539 case RR_RY_CNVT_ZEB:
12540 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12541 break;
12542 case RR_RY_CNVT_ZEH:
12543 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12544 break;
12545 case RR_RY_CNVT_SEB:
12546 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12547 break;
12548 case RR_RY_CNVT_SEH:
12549 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12550 break;
12551#if defined (TARGET_MIPS64)
12552 case RR_RY_CNVT_ZEW:
d9224450 12553 check_insn(ctx, ISA_MIPS64);
364d4831
NF
12554 check_mips_64(ctx);
12555 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12556 break;
12557 case RR_RY_CNVT_SEW:
d9224450 12558 check_insn(ctx, ISA_MIPS64);
364d4831
NF
12559 check_mips_64(ctx);
12560 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12561 break;
12562#endif
12563 default:
9c708c7f 12564 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12565 break;
12566 }
12567 break;
12568 case RR_MFLO:
26135ead 12569 gen_HILO(ctx, OPC_MFLO, 0, rx);
364d4831
NF
12570 break;
12571#if defined (TARGET_MIPS64)
12572 case RR_DSRA:
d9224450 12573 check_insn(ctx, ISA_MIPS3);
364d4831 12574 check_mips_64(ctx);
d75c135e 12575 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
364d4831
NF
12576 break;
12577 case RR_DSLLV:
d9224450 12578 check_insn(ctx, ISA_MIPS3);
364d4831 12579 check_mips_64(ctx);
d75c135e 12580 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
364d4831
NF
12581 break;
12582 case RR_DSRLV:
d9224450 12583 check_insn(ctx, ISA_MIPS3);
364d4831 12584 check_mips_64(ctx);
d75c135e 12585 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
364d4831
NF
12586 break;
12587 case RR_DSRAV:
d9224450 12588 check_insn(ctx, ISA_MIPS3);
364d4831 12589 check_mips_64(ctx);
d75c135e 12590 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
364d4831
NF
12591 break;
12592#endif
12593 case RR_MULT:
26135ead 12594 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
364d4831
NF
12595 break;
12596 case RR_MULTU:
26135ead 12597 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
364d4831
NF
12598 break;
12599 case RR_DIV:
26135ead 12600 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
364d4831
NF
12601 break;
12602 case RR_DIVU:
26135ead 12603 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
364d4831
NF
12604 break;
12605#if defined (TARGET_MIPS64)
12606 case RR_DMULT:
d9224450 12607 check_insn(ctx, ISA_MIPS3);
364d4831 12608 check_mips_64(ctx);
26135ead 12609 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
364d4831
NF
12610 break;
12611 case RR_DMULTU:
d9224450 12612 check_insn(ctx, ISA_MIPS3);
364d4831 12613 check_mips_64(ctx);
26135ead 12614 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
364d4831
NF
12615 break;
12616 case RR_DDIV:
d9224450 12617 check_insn(ctx, ISA_MIPS3);
364d4831 12618 check_mips_64(ctx);
26135ead 12619 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
364d4831
NF
12620 break;
12621 case RR_DDIVU:
d9224450 12622 check_insn(ctx, ISA_MIPS3);
364d4831 12623 check_mips_64(ctx);
26135ead 12624 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
364d4831
NF
12625 break;
12626#endif
12627 default:
9c708c7f 12628 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12629 break;
12630 }
12631 break;
12632 case M16_OPC_EXTEND:
240ce26a 12633 decode_extended_mips16_opc(env, ctx);
364d4831
NF
12634 n_bytes = 4;
12635 break;
12636#if defined(TARGET_MIPS64)
12637 case M16_OPC_I64:
12638 funct = (ctx->opcode >> 8) & 0x7;
d75c135e 12639 decode_i64_mips16(ctx, ry, funct, offset, 0);
364d4831
NF
12640 break;
12641#endif
12642 default:
9c708c7f 12643 generate_exception_end(ctx, EXCP_RI);
364d4831
NF
12644 break;
12645 }
12646
12647 return n_bytes;
12648}
12649
211da992 12650/* microMIPS extension to MIPS32/MIPS64 */
6af0bf9c 12651
211da992
CWR
12652/*
12653 * microMIPS32/microMIPS64 major opcodes
12654 *
12655 * 1. MIPS Architecture for Programmers Volume II-B:
12656 * The microMIPS32 Instruction Set (Revision 3.05)
12657 *
12658 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
12659 *
12660 * 2. MIPS Architecture For Programmers Volume II-A:
12661 * The MIPS64 Instruction Set (Revision 3.51)
12662 */
6af0bf9c 12663
3c824109
NF
12664enum {
12665 POOL32A = 0x00,
12666 POOL16A = 0x01,
12667 LBU16 = 0x02,
12668 MOVE16 = 0x03,
12669 ADDI32 = 0x04,
3a1f4268
YK
12670 R6_LUI = 0x04,
12671 AUI = 0x04,
3c824109
NF
12672 LBU32 = 0x05,
12673 SB32 = 0x06,
12674 LB32 = 0x07,
12675
12676 POOL32B = 0x08,
12677 POOL16B = 0x09,
12678 LHU16 = 0x0a,
12679 ANDI16 = 0x0b,
12680 ADDIU32 = 0x0c,
12681 LHU32 = 0x0d,
12682 SH32 = 0x0e,
12683 LH32 = 0x0f,
12684
12685 POOL32I = 0x10,
12686 POOL16C = 0x11,
12687 LWSP16 = 0x12,
12688 POOL16D = 0x13,
12689 ORI32 = 0x14,
12690 POOL32F = 0x15,
211da992
CWR
12691 POOL32S = 0x16, /* MIPS64 */
12692 DADDIU32 = 0x17, /* MIPS64 */
3c824109
NF
12693
12694 POOL32C = 0x18,
12695 LWGP16 = 0x19,
12696 LW16 = 0x1a,
12697 POOL16E = 0x1b,
12698 XORI32 = 0x1c,
12699 JALS32 = 0x1d,
3a1f4268
YK
12700 BOVC = 0x1d,
12701 BEQC = 0x1d,
12702 BEQZALC = 0x1d,
3c824109 12703 ADDIUPC = 0x1e,
3a1f4268
YK
12704 PCREL = 0x1e,
12705 BNVC = 0x1f,
12706 BNEC = 0x1f,
12707 BNEZALC = 0x1f,
3c824109 12708
3a1f4268
YK
12709 R6_BEQZC = 0x20,
12710 JIC = 0x20,
3c824109
NF
12711 POOL16F = 0x21,
12712 SB16 = 0x22,
12713 BEQZ16 = 0x23,
3a1f4268 12714 BEQZC16 = 0x23,
3c824109
NF
12715 SLTI32 = 0x24,
12716 BEQ32 = 0x25,
3a1f4268 12717 BC = 0x25,
3c824109
NF
12718 SWC132 = 0x26,
12719 LWC132 = 0x27,
12720
3a1f4268 12721 /* 0x29 is reserved */
3c824109 12722 RES_29 = 0x29,
3a1f4268
YK
12723 R6_BNEZC = 0x28,
12724 JIALC = 0x28,
3c824109
NF
12725 SH16 = 0x2a,
12726 BNEZ16 = 0x2b,
3a1f4268 12727 BNEZC16 = 0x2b,
3c824109
NF
12728 SLTIU32 = 0x2c,
12729 BNE32 = 0x2d,
3a1f4268 12730 BALC = 0x2d,
3c824109
NF
12731 SDC132 = 0x2e,
12732 LDC132 = 0x2f,
12733
3a1f4268 12734 /* 0x31 is reserved */
3c824109 12735 RES_31 = 0x31,
3a1f4268
YK
12736 BLEZALC = 0x30,
12737 BGEZALC = 0x30,
12738 BGEUC = 0x30,
3c824109
NF
12739 SWSP16 = 0x32,
12740 B16 = 0x33,
3a1f4268 12741 BC16 = 0x33,
3c824109
NF
12742 ANDI32 = 0x34,
12743 J32 = 0x35,
3a1f4268
YK
12744 BGTZC = 0x35,
12745 BLTZC = 0x35,
12746 BLTC = 0x35,
211da992
CWR
12747 SD32 = 0x36, /* MIPS64 */
12748 LD32 = 0x37, /* MIPS64 */
3c824109 12749
3a1f4268 12750 /* 0x39 is reserved */
3c824109 12751 RES_39 = 0x39,
3a1f4268
YK
12752 BGTZALC = 0x38,
12753 BLTZALC = 0x38,
12754 BLTUC = 0x38,
3c824109
NF
12755 SW16 = 0x3a,
12756 LI16 = 0x3b,
12757 JALX32 = 0x3c,
12758 JAL32 = 0x3d,
3a1f4268
YK
12759 BLEZC = 0x3d,
12760 BGEZC = 0x3d,
12761 BGEC = 0x3d,
3c824109
NF
12762 SW32 = 0x3e,
12763 LW32 = 0x3f
12764};
12765
3a1f4268
YK
12766/* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
12767enum {
12768 ADDIUPC_00 = 0x00,
c38a1d52
AR
12769 ADDIUPC_01 = 0x01,
12770 ADDIUPC_02 = 0x02,
12771 ADDIUPC_03 = 0x03,
12772 ADDIUPC_04 = 0x04,
12773 ADDIUPC_05 = 0x05,
12774 ADDIUPC_06 = 0x06,
3a1f4268
YK
12775 ADDIUPC_07 = 0x07,
12776 AUIPC = 0x1e,
12777 ALUIPC = 0x1f,
12778 LWPC_08 = 0x08,
c38a1d52
AR
12779 LWPC_09 = 0x09,
12780 LWPC_0A = 0x0A,
12781 LWPC_0B = 0x0B,
12782 LWPC_0C = 0x0C,
12783 LWPC_0D = 0x0D,
12784 LWPC_0E = 0x0E,
3a1f4268
YK
12785 LWPC_0F = 0x0F,
12786};
12787
3c824109
NF
12788/* POOL32A encoding of minor opcode field */
12789
12790enum {
12791 /* These opcodes are distinguished only by bits 9..6; those bits are
12792 * what are recorded below. */
12793 SLL32 = 0x0,
12794 SRL32 = 0x1,
12795 SRA = 0x2,
12796 ROTR = 0x3,
3a1f4268
YK
12797 SELEQZ = 0x5,
12798 SELNEZ = 0x6,
b00c7218 12799 R6_RDHWR = 0x7,
3c824109
NF
12800
12801 SLLV = 0x0,
12802 SRLV = 0x1,
12803 SRAV = 0x2,
12804 ROTRV = 0x3,
12805 ADD = 0x4,
12806 ADDU32 = 0x5,
12807 SUB = 0x6,
12808 SUBU32 = 0x7,
12809 MUL = 0x8,
12810 AND = 0x9,
12811 OR32 = 0xa,
12812 NOR = 0xb,
12813 XOR32 = 0xc,
12814 SLT = 0xd,
12815 SLTU = 0xe,
12816
12817 MOVN = 0x0,
3a1f4268 12818 R6_MUL = 0x0,
3c824109 12819 MOVZ = 0x1,
3a1f4268
YK
12820 MUH = 0x1,
12821 MULU = 0x2,
12822 MUHU = 0x3,
3c824109 12823 LWXS = 0x4,
3a1f4268
YK
12824 R6_DIV = 0x4,
12825 MOD = 0x5,
12826 R6_DIVU = 0x6,
12827 MODU = 0x7,
3c824109
NF
12828
12829 /* The following can be distinguished by their lower 6 bits. */
dbd8af98 12830 BREAK32 = 0x07,
3c824109 12831 INS = 0x0c,
3a1f4268
YK
12832 LSA = 0x0f,
12833 ALIGN = 0x1f,
3c824109 12834 EXT = 0x2c,
bb238210
YK
12835 POOL32AXF = 0x3c,
12836 SIGRIE = 0x3f
3c824109
NF
12837};
12838
12839/* POOL32AXF encoding of minor opcode field extension */
12840
d132c79f
CWR
12841/*
12842 * 1. MIPS Architecture for Programmers Volume II-B:
12843 * The microMIPS32 Instruction Set (Revision 3.05)
12844 *
12845 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12846 *
12847 * 2. MIPS Architecture for Programmers VolumeIV-e:
12848 * The MIPS DSP Application-Specific Extension
12849 * to the microMIPS32 Architecture (Revision 2.34)
12850 *
12851 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12852 */
12853
3c824109
NF
12854enum {
12855 /* bits 11..6 */
12856 TEQ = 0x00,
12857 TGE = 0x08,
12858 TGEU = 0x10,
12859 TLT = 0x20,
12860 TLTU = 0x28,
12861 TNE = 0x30,
12862
12863 MFC0 = 0x03,
12864 MTC0 = 0x0b,
12865
d132c79f
CWR
12866 /* begin of microMIPS32 DSP */
12867
3c824109
NF
12868 /* bits 13..12 for 0x01 */
12869 MFHI_ACC = 0x0,
12870 MFLO_ACC = 0x1,
12871 MTHI_ACC = 0x2,
12872 MTLO_ACC = 0x3,
12873
12874 /* bits 13..12 for 0x2a */
12875 MADD_ACC = 0x0,
12876 MADDU_ACC = 0x1,
12877 MSUB_ACC = 0x2,
12878 MSUBU_ACC = 0x3,
12879
12880 /* bits 13..12 for 0x32 */
12881 MULT_ACC = 0x0,
6801038b 12882 MULTU_ACC = 0x1,
3c824109 12883
d132c79f
CWR
12884 /* end of microMIPS32 DSP */
12885
3c824109 12886 /* bits 15..12 for 0x2c */
3a1f4268 12887 BITSWAP = 0x0,
3c824109
NF
12888 SEB = 0x2,
12889 SEH = 0x3,
12890 CLO = 0x4,
12891 CLZ = 0x5,
12892 RDHWR = 0x6,
12893 WSBH = 0x7,
12894 MULT = 0x8,
12895 MULTU = 0x9,
12896 DIV = 0xa,
12897 DIVU = 0xb,
12898 MADD = 0xc,
12899 MADDU = 0xd,
12900 MSUB = 0xe,
12901 MSUBU = 0xf,
12902
12903 /* bits 15..12 for 0x34 */
12904 MFC2 = 0x4,
12905 MTC2 = 0x5,
12906 MFHC2 = 0x8,
12907 MTHC2 = 0x9,
12908 CFC2 = 0xc,
12909 CTC2 = 0xd,
12910
12911 /* bits 15..12 for 0x3c */
12912 JALR = 0x0,
12913 JR = 0x0, /* alias */
3a1f4268
YK
12914 JALRC = 0x0,
12915 JRC = 0x0,
3c824109 12916 JALR_HB = 0x1,
3a1f4268 12917 JALRC_HB = 0x1,
3c824109
NF
12918 JALRS = 0x4,
12919 JALRS_HB = 0x5,
12920
12921 /* bits 15..12 for 0x05 */
12922 RDPGPR = 0xe,
12923 WRPGPR = 0xf,
12924
12925 /* bits 15..12 for 0x0d */
12926 TLBP = 0x0,
12927 TLBR = 0x1,
12928 TLBWI = 0x2,
12929 TLBWR = 0x3,
e60ec063
YK
12930 TLBINV = 0x4,
12931 TLBINVF = 0x5,
3c824109
NF
12932 WAIT = 0x9,
12933 IRET = 0xd,
12934 DERET = 0xe,
12935 ERET = 0xf,
12936
12937 /* bits 15..12 for 0x15 */
12938 DMT = 0x0,
12939 DVPE = 0x1,
12940 EMT = 0x2,
12941 EVPE = 0x3,
12942
12943 /* bits 15..12 for 0x1d */
12944 DI = 0x4,
12945 EI = 0x5,
12946
12947 /* bits 15..12 for 0x2d */
12948 SYNC = 0x6,
12949 SYSCALL = 0x8,
12950 SDBBP = 0xd,
12951
12952 /* bits 15..12 for 0x35 */
12953 MFHI32 = 0x0,
12954 MFLO32 = 0x1,
12955 MTHI32 = 0x2,
12956 MTLO32 = 0x3,
12957};
12958
12959/* POOL32B encoding of minor opcode field (bits 15..12) */
12960
12961enum {
12962 LWC2 = 0x0,
12963 LWP = 0x1,
12964 LDP = 0x4,
12965 LWM32 = 0x5,
12966 CACHE = 0x6,
12967 LDM = 0x7,
12968 SWC2 = 0x8,
12969 SWP = 0x9,
12970 SDP = 0xc,
12971 SWM32 = 0xd,
12972 SDM = 0xf
12973};
12974
12975/* POOL32C encoding of minor opcode field (bits 15..12) */
12976
12977enum {
12978 LWL = 0x0,
12979 SWL = 0x8,
12980 LWR = 0x1,
12981 SWR = 0x9,
12982 PREF = 0x2,
8fffc646 12983 ST_EVA = 0xa,
3c824109
NF
12984 LL = 0x3,
12985 SC = 0xb,
12986 LDL = 0x4,
12987 SDL = 0xc,
12988 LDR = 0x5,
12989 SDR = 0xd,
8fffc646 12990 LD_EVA = 0x6,
3c824109
NF
12991 LWU = 0xe,
12992 LLD = 0x7,
12993 SCD = 0xf
12994};
12995
8fffc646
JH
12996/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
12997
12998enum {
12999 LBUE = 0x0,
13000 LHUE = 0x1,
13001 LWLE = 0x2,
13002 LWRE = 0x3,
13003 LBE = 0x4,
13004 LHE = 0x5,
13005 LLE = 0x6,
13006 LWE = 0x7,
13007};
13008
13009/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
13010
13011enum {
13012 SWLE = 0x0,
13013 SWRE = 0x1,
13014 PREFE = 0x2,
13015 CACHEE = 0x3,
13016 SBE = 0x4,
13017 SHE = 0x5,
13018 SCE = 0x6,
13019 SWE = 0x7,
13020};
13021
3c824109
NF
13022/* POOL32F encoding of minor opcode field (bits 5..0) */
13023
13024enum {
13025 /* These are the bit 7..6 values */
13026 ADD_FMT = 0x0,
3c824109
NF
13027
13028 SUB_FMT = 0x1,
3c824109
NF
13029
13030 MUL_FMT = 0x2,
13031
13032 DIV_FMT = 0x3,
13033
13034 /* These are the bit 8..6 values */
3a1f4268 13035 MOVN_FMT = 0x0,
3c824109
NF
13036 RSQRT2_FMT = 0x0,
13037 MOVF_FMT = 0x0,
3a1f4268
YK
13038 RINT_FMT = 0x0,
13039 SELNEZ_FMT = 0x0,
3c824109 13040
3a1f4268 13041 MOVZ_FMT = 0x1,
3c824109
NF
13042 LWXC1 = 0x1,
13043 MOVT_FMT = 0x1,
3a1f4268
YK
13044 CLASS_FMT = 0x1,
13045 SELEQZ_FMT = 0x1,
3c824109
NF
13046
13047 PLL_PS = 0x2,
13048 SWXC1 = 0x2,
3a1f4268 13049 SEL_FMT = 0x2,
3c824109
NF
13050
13051 PLU_PS = 0x3,
13052 LDXC1 = 0x3,
13053
3a1f4268 13054 MOVN_FMT_04 = 0x4,
3c824109
NF
13055 PUL_PS = 0x4,
13056 SDXC1 = 0x4,
13057 RECIP2_FMT = 0x4,
13058
3a1f4268 13059 MOVZ_FMT_05 = 0x05,
3c824109
NF
13060 PUU_PS = 0x5,
13061 LUXC1 = 0x5,
13062
13063 CVT_PS_S = 0x6,
13064 SUXC1 = 0x6,
13065 ADDR_PS = 0x6,
13066 PREFX = 0x6,
3a1f4268 13067 MADDF_FMT = 0x6,
3c824109
NF
13068
13069 MULR_PS = 0x7,
3a1f4268 13070 MSUBF_FMT = 0x7,
3c824109
NF
13071
13072 MADD_S = 0x01,
13073 MADD_D = 0x09,
13074 MADD_PS = 0x11,
13075 ALNV_PS = 0x19,
13076 MSUB_S = 0x21,
13077 MSUB_D = 0x29,
13078 MSUB_PS = 0x31,
13079
13080 NMADD_S = 0x02,
13081 NMADD_D = 0x0a,
13082 NMADD_PS = 0x12,
13083 NMSUB_S = 0x22,
13084 NMSUB_D = 0x2a,
13085 NMSUB_PS = 0x32,
13086
3a1f4268
YK
13087 MIN_FMT = 0x3,
13088 MAX_FMT = 0xb,
13089 MINA_FMT = 0x23,
13090 MAXA_FMT = 0x2b,
3c824109
NF
13091 POOL32FXF = 0x3b,
13092
13093 CABS_COND_FMT = 0x1c, /* MIPS3D */
3a1f4268
YK
13094 C_COND_FMT = 0x3c,
13095
13096 CMP_CONDN_S = 0x5,
13097 CMP_CONDN_D = 0x15
3c824109
NF
13098};
13099
13100/* POOL32Fxf encoding of minor opcode extension field */
13101
13102enum {
13103 CVT_L = 0x04,
13104 RSQRT_FMT = 0x08,
13105 FLOOR_L = 0x0c,
13106 CVT_PW_PS = 0x1c,
13107 CVT_W = 0x24,
13108 SQRT_FMT = 0x28,
13109 FLOOR_W = 0x2c,
13110 CVT_PS_PW = 0x3c,
13111 CFC1 = 0x40,
13112 RECIP_FMT = 0x48,
13113 CEIL_L = 0x4c,
13114 CTC1 = 0x60,
13115 CEIL_W = 0x6c,
13116 MFC1 = 0x80,
13117 CVT_S_PL = 0x84,
13118 TRUNC_L = 0x8c,
13119 MTC1 = 0xa0,
13120 CVT_S_PU = 0xa4,
13121 TRUNC_W = 0xac,
13122 MFHC1 = 0xc0,
13123 ROUND_L = 0xcc,
13124 MTHC1 = 0xe0,
13125 ROUND_W = 0xec,
13126
13127 MOV_FMT = 0x01,
13128 MOVF = 0x05,
13129 ABS_FMT = 0x0d,
13130 RSQRT1_FMT = 0x1d,
13131 MOVT = 0x25,
13132 NEG_FMT = 0x2d,
13133 CVT_D = 0x4d,
13134 RECIP1_FMT = 0x5d,
13135 CVT_S = 0x6d
13136};
13137
13138/* POOL32I encoding of minor opcode field (bits 25..21) */
13139
13140enum {
13141 BLTZ = 0x00,
13142 BLTZAL = 0x01,
13143 BGEZ = 0x02,
13144 BGEZAL = 0x03,
13145 BLEZ = 0x04,
13146 BNEZC = 0x05,
13147 BGTZ = 0x06,
13148 BEQZC = 0x07,
13149 TLTI = 0x08,
3a1f4268 13150 BC1EQZC = 0x08,
3c824109 13151 TGEI = 0x09,
3a1f4268 13152 BC1NEZC = 0x09,
3c824109 13153 TLTIU = 0x0a,
3a1f4268 13154 BC2EQZC = 0x0a,
3c824109 13155 TGEIU = 0x0b,
3a1f4268 13156 BC2NEZC = 0x0a,
3c824109 13157 TNEI = 0x0c,
3a1f4268 13158 R6_SYNCI = 0x0c,
3c824109
NF
13159 LUI = 0x0d,
13160 TEQI = 0x0e,
13161 SYNCI = 0x10,
13162 BLTZALS = 0x11,
13163 BGEZALS = 0x13,
13164 BC2F = 0x14,
13165 BC2T = 0x15,
13166 BPOSGE64 = 0x1a,
13167 BPOSGE32 = 0x1b,
13168 /* These overlap and are distinguished by bit16 of the instruction */
13169 BC1F = 0x1c,
13170 BC1T = 0x1d,
13171 BC1ANY2F = 0x1c,
13172 BC1ANY2T = 0x1d,
13173 BC1ANY4F = 0x1e,
13174 BC1ANY4T = 0x1f
13175};
13176
13177/* POOL16A encoding of minor opcode field */
13178
13179enum {
13180 ADDU16 = 0x0,
13181 SUBU16 = 0x1
13182};
13183
13184/* POOL16B encoding of minor opcode field */
13185
13186enum {
13187 SLL16 = 0x0,
13188 SRL16 = 0x1
13189};
13190
13191/* POOL16C encoding of minor opcode field */
13192
13193enum {
13194 NOT16 = 0x00,
13195 XOR16 = 0x04,
13196 AND16 = 0x08,
13197 OR16 = 0x0c,
13198 LWM16 = 0x10,
13199 SWM16 = 0x14,
13200 JR16 = 0x18,
13201 JRC16 = 0x1a,
13202 JALR16 = 0x1c,
13203 JALR16S = 0x1e,
13204 MFHI16 = 0x20,
13205 MFLO16 = 0x24,
13206 BREAK16 = 0x28,
13207 SDBBP16 = 0x2c,
13208 JRADDIUSP = 0x30
13209};
13210
3a1f4268
YK
13211/* R6 POOL16C encoding of minor opcode field (bits 0..5) */
13212
13213enum {
13214 R6_NOT16 = 0x00,
13215 R6_AND16 = 0x01,
13216 R6_LWM16 = 0x02,
13217 R6_JRC16 = 0x03,
13218 MOVEP = 0x04,
c38a1d52
AR
13219 MOVEP_05 = 0x05,
13220 MOVEP_06 = 0x06,
3a1f4268
YK
13221 MOVEP_07 = 0x07,
13222 R6_XOR16 = 0x08,
13223 R6_OR16 = 0x09,
13224 R6_SWM16 = 0x0a,
13225 JALRC16 = 0x0b,
13226 MOVEP_0C = 0x0c,
c38a1d52
AR
13227 MOVEP_0D = 0x0d,
13228 MOVEP_0E = 0x0e,
3a1f4268
YK
13229 MOVEP_0F = 0x0f,
13230 JRCADDIUSP = 0x13,
13231 R6_BREAK16 = 0x1b,
13232 R6_SDBBP16 = 0x3b
13233};
13234
3c824109
NF
13235/* POOL16D encoding of minor opcode field */
13236
13237enum {
13238 ADDIUS5 = 0x0,
13239 ADDIUSP = 0x1
13240};
13241
13242/* POOL16E encoding of minor opcode field */
13243
13244enum {
13245 ADDIUR2 = 0x0,
13246 ADDIUR1SP = 0x1
13247};
13248
13249static int mmreg (int r)
13250{
13251 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13252
13253 return map[r];
13254}
13255
13256/* Used for 16-bit store instructions. */
13257static int mmreg2 (int r)
13258{
13259 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
13260
13261 return map[r];
13262}
13263
13264#define uMIPS_RD(op) ((op >> 7) & 0x7)
13265#define uMIPS_RS(op) ((op >> 4) & 0x7)
13266#define uMIPS_RS2(op) uMIPS_RS(op)
13267#define uMIPS_RS1(op) ((op >> 1) & 0x7)
13268#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
13269#define uMIPS_RS5(op) (op & 0x1f)
13270
13271/* Signed immediate */
13272#define SIMM(op, start, width) \
13273 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
13274 << (32-width)) \
13275 >> (32-width))
13276/* Zero-extended immediate */
13277#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
13278
d75c135e 13279static void gen_addiur1sp(DisasContext *ctx)
3c824109
NF
13280{
13281 int rd = mmreg(uMIPS_RD(ctx->opcode));
13282
d75c135e 13283 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
3c824109
NF
13284}
13285
d75c135e 13286static void gen_addiur2(DisasContext *ctx)
3c824109
NF
13287{
13288 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
13289 int rd = mmreg(uMIPS_RD(ctx->opcode));
13290 int rs = mmreg(uMIPS_RS(ctx->opcode));
13291
d75c135e 13292 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
3c824109
NF
13293}
13294
d75c135e 13295static void gen_addiusp(DisasContext *ctx)
3c824109
NF
13296{
13297 int encoded = ZIMM(ctx->opcode, 1, 9);
13298 int decoded;
13299
13300 if (encoded <= 1) {
13301 decoded = 256 + encoded;
13302 } else if (encoded <= 255) {
13303 decoded = encoded;
13304 } else if (encoded <= 509) {
13305 decoded = encoded - 512;
13306 } else {
13307 decoded = encoded - 768;
13308 }
13309
d75c135e 13310 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
3c824109
NF
13311}
13312
d75c135e 13313static void gen_addius5(DisasContext *ctx)
3c824109
NF
13314{
13315 int imm = SIMM(ctx->opcode, 1, 4);
13316 int rd = (ctx->opcode >> 5) & 0x1f;
13317
d75c135e 13318 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
3c824109
NF
13319}
13320
d75c135e 13321static void gen_andi16(DisasContext *ctx)
3c824109
NF
13322{
13323 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
13324 31, 32, 63, 64, 255, 32768, 65535 };
13325 int rd = mmreg(uMIPS_RD(ctx->opcode));
13326 int rs = mmreg(uMIPS_RS(ctx->opcode));
13327 int encoded = ZIMM(ctx->opcode, 0, 4);
13328
d75c135e 13329 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
3c824109
NF
13330}
13331
13332static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
13333 int base, int16_t offset)
13334{
13335 TCGv t0, t1;
13336 TCGv_i32 t2;
13337
13338 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 13339 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
13340 return;
13341 }
13342
13343 t0 = tcg_temp_new();
13344
13345 gen_base_offset_addr(ctx, t0, base, offset);
13346
13347 t1 = tcg_const_tl(reglist);
13348 t2 = tcg_const_i32(ctx->mem_idx);
6af0bf9c 13349
3c824109
NF
13350 save_cpu_state(ctx, 1);
13351 switch (opc) {
13352 case LWM32:
895c2d04 13353 gen_helper_lwm(cpu_env, t0, t1, t2);
3c824109
NF
13354 break;
13355 case SWM32:
895c2d04 13356 gen_helper_swm(cpu_env, t0, t1, t2);
3c824109
NF
13357 break;
13358#ifdef TARGET_MIPS64
13359 case LDM:
895c2d04 13360 gen_helper_ldm(cpu_env, t0, t1, t2);
3c824109
NF
13361 break;
13362 case SDM:
895c2d04 13363 gen_helper_sdm(cpu_env, t0, t1, t2);
3c824109 13364 break;
6af0bf9c 13365#endif
3c824109 13366 }
3c824109 13367 tcg_temp_free(t0);
33087598 13368 tcg_temp_free(t1);
3c824109
NF
13369 tcg_temp_free_i32(t2);
13370}
6af0bf9c 13371
3c824109 13372
240ce26a 13373static void gen_pool16c_insn(DisasContext *ctx)
6af0bf9c 13374{
3c824109
NF
13375 int rd = mmreg((ctx->opcode >> 3) & 0x7);
13376 int rs = mmreg(ctx->opcode & 0x7);
6af0bf9c 13377
3c824109
NF
13378 switch (((ctx->opcode) >> 4) & 0x3f) {
13379 case NOT16 + 0:
13380 case NOT16 + 1:
13381 case NOT16 + 2:
13382 case NOT16 + 3:
d75c135e 13383 gen_logic(ctx, OPC_NOR, rd, rs, 0);
3c824109
NF
13384 break;
13385 case XOR16 + 0:
13386 case XOR16 + 1:
13387 case XOR16 + 2:
13388 case XOR16 + 3:
d75c135e 13389 gen_logic(ctx, OPC_XOR, rd, rd, rs);
3c824109
NF
13390 break;
13391 case AND16 + 0:
13392 case AND16 + 1:
13393 case AND16 + 2:
13394 case AND16 + 3:
d75c135e 13395 gen_logic(ctx, OPC_AND, rd, rd, rs);
3c824109
NF
13396 break;
13397 case OR16 + 0:
13398 case OR16 + 1:
13399 case OR16 + 2:
13400 case OR16 + 3:
d75c135e 13401 gen_logic(ctx, OPC_OR, rd, rd, rs);
3c824109
NF
13402 break;
13403 case LWM16 + 0:
13404 case LWM16 + 1:
13405 case LWM16 + 2:
13406 case LWM16 + 3:
13407 {
13408 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13409 int offset = ZIMM(ctx->opcode, 0, 4);
13410
13411 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
13412 29, offset << 2);
13413 }
13414 break;
13415 case SWM16 + 0:
13416 case SWM16 + 1:
13417 case SWM16 + 2:
13418 case SWM16 + 3:
13419 {
13420 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13421 int offset = ZIMM(ctx->opcode, 0, 4);
13422
13423 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
13424 29, offset << 2);
13425 }
13426 break;
13427 case JR16 + 0:
13428 case JR16 + 1:
13429 {
13430 int reg = ctx->opcode & 0x1f;
13431
b231c103 13432 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
3c824109 13433 }
3c824109
NF
13434 break;
13435 case JRC16 + 0:
13436 case JRC16 + 1:
13437 {
13438 int reg = ctx->opcode & 0x1f;
b231c103 13439 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
3c824109
NF
13440 /* Let normal delay slot handling in our caller take us
13441 to the branch target. */
13442 }
13443 break;
13444 case JALR16 + 0:
13445 case JALR16 + 1:
b231c103
YK
13446 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
13447 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13448 break;
3c824109
NF
13449 case JALR16S + 0:
13450 case JALR16S + 1:
b231c103
YK
13451 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
13452 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
13453 break;
13454 case MFHI16 + 0:
13455 case MFHI16 + 1:
26135ead 13456 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
13457 break;
13458 case MFLO16 + 0:
13459 case MFLO16 + 1:
26135ead 13460 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
3c824109
NF
13461 break;
13462 case BREAK16:
9c708c7f 13463 generate_exception_end(ctx, EXCP_BREAK);
3c824109
NF
13464 break;
13465 case SDBBP16:
3b3c1694
LA
13466 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
13467 gen_helper_do_semihosting(cpu_env);
13468 } else {
13469 /* XXX: not clear which exception should be raised
13470 * when in debug mode...
13471 */
13472 check_insn(ctx, ISA_MIPS32);
9c708c7f 13473 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 13474 }
3c824109
NF
13475 break;
13476 case JRADDIUSP + 0:
13477 case JRADDIUSP + 1:
13478 {
13479 int imm = ZIMM(ctx->opcode, 0, 5);
b231c103 13480 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
d75c135e 13481 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
3c824109
NF
13482 /* Let normal delay slot handling in our caller take us
13483 to the branch target. */
13484 }
13485 break;
13486 default:
9c708c7f 13487 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
13488 break;
13489 }
13490}
13491
ed7ce6c0
YK
13492static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
13493 int enc_rs)
13494{
13495 int rd, rs, re, rt;
13496 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
13497 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
13498 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
13499 rd = rd_enc[enc_dest];
13500 re = re_enc[enc_dest];
13501 rs = rs_rt_enc[enc_rs];
13502 rt = rs_rt_enc[enc_rt];
13503 if (rs) {
13504 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
13505 } else {
13506 tcg_gen_movi_tl(cpu_gpr[rd], 0);
13507 }
13508 if (rt) {
13509 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
13510 } else {
13511 tcg_gen_movi_tl(cpu_gpr[re], 0);
13512 }
13513}
13514
13515static void gen_pool16c_r6_insn(DisasContext *ctx)
13516{
13517 int rt = mmreg((ctx->opcode >> 7) & 0x7);
13518 int rs = mmreg((ctx->opcode >> 4) & 0x7);
13519
13520 switch (ctx->opcode & 0xf) {
13521 case R6_NOT16:
13522 gen_logic(ctx, OPC_NOR, rt, rs, 0);
13523 break;
13524 case R6_AND16:
13525 gen_logic(ctx, OPC_AND, rt, rt, rs);
13526 break;
13527 case R6_LWM16:
13528 {
13529 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13530 int offset = extract32(ctx->opcode, 4, 4);
13531 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
13532 }
13533 break;
13534 case R6_JRC16: /* JRCADDIUSP */
13535 if ((ctx->opcode >> 4) & 1) {
13536 /* JRCADDIUSP */
13537 int imm = extract32(ctx->opcode, 5, 5);
13538 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13539 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13540 } else {
13541 /* JRC16 */
e1555d7d 13542 rs = extract32(ctx->opcode, 5, 5);
ed7ce6c0
YK
13543 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
13544 }
13545 break;
c38a1d52
AR
13546 case MOVEP:
13547 case MOVEP_05:
13548 case MOVEP_06:
13549 case MOVEP_07:
13550 case MOVEP_0C:
13551 case MOVEP_0D:
13552 case MOVEP_0E:
13553 case MOVEP_0F:
ed7ce6c0
YK
13554 {
13555 int enc_dest = uMIPS_RD(ctx->opcode);
13556 int enc_rt = uMIPS_RS2(ctx->opcode);
13557 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
13558 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
13559 }
13560 break;
13561 case R6_XOR16:
13562 gen_logic(ctx, OPC_XOR, rt, rt, rs);
13563 break;
13564 case R6_OR16:
13565 gen_logic(ctx, OPC_OR, rt, rt, rs);
13566 break;
13567 case R6_SWM16:
13568 {
13569 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13570 int offset = extract32(ctx->opcode, 4, 4);
13571 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
13572 }
13573 break;
13574 case JALRC16: /* BREAK16, SDBBP16 */
13575 switch (ctx->opcode & 0x3f) {
13576 case JALRC16:
13577 case JALRC16 + 0x20:
13578 /* JALRC16 */
13579 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
13580 31, 0, 0);
13581 break;
13582 case R6_BREAK16:
13583 /* BREAK16 */
13584 generate_exception(ctx, EXCP_BREAK);
13585 break;
13586 case R6_SDBBP16:
13587 /* SDBBP16 */
060ebfef
LA
13588 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
13589 gen_helper_do_semihosting(cpu_env);
ed7ce6c0 13590 } else {
060ebfef
LA
13591 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13592 generate_exception(ctx, EXCP_RI);
13593 } else {
13594 generate_exception(ctx, EXCP_DBp);
13595 }
ed7ce6c0
YK
13596 }
13597 break;
13598 }
13599 break;
13600 default:
13601 generate_exception(ctx, EXCP_RI);
13602 break;
13603 }
13604}
13605
3c824109
NF
13606static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
13607{
13608 TCGv t0 = tcg_temp_new();
13609 TCGv t1 = tcg_temp_new();
13610
13611 gen_load_gpr(t0, base);
13612
13613 if (index != 0) {
13614 gen_load_gpr(t1, index);
13615 tcg_gen_shli_tl(t1, t1, 2);
13616 gen_op_addr_add(ctx, t0, t1, t0);
13617 }
13618
5f68f5ae 13619 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
13620 gen_store_gpr(t1, rd);
13621
13622 tcg_temp_free(t0);
13623 tcg_temp_free(t1);
13624}
13625
13626static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
13627 int base, int16_t offset)
13628{
3c824109
NF
13629 TCGv t0, t1;
13630
36c6711b 13631 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
9c708c7f 13632 generate_exception_end(ctx, EXCP_RI);
d796321b
FB
13633 return;
13634 }
13635
3c824109
NF
13636 t0 = tcg_temp_new();
13637 t1 = tcg_temp_new();
8e9ade68 13638
3c824109
NF
13639 gen_base_offset_addr(ctx, t0, base, offset);
13640
13641 switch (opc) {
13642 case LWP:
36c6711b 13643 if (rd == base) {
9c708c7f 13644 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
13645 return;
13646 }
5f68f5ae 13647 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109
NF
13648 gen_store_gpr(t1, rd);
13649 tcg_gen_movi_tl(t1, 4);
13650 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 13651 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
3c824109 13652 gen_store_gpr(t1, rd+1);
3c824109
NF
13653 break;
13654 case SWP:
3c824109 13655 gen_load_gpr(t1, rd);
5f68f5ae 13656 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
13657 tcg_gen_movi_tl(t1, 4);
13658 gen_op_addr_add(ctx, t0, t0, t1);
13659 gen_load_gpr(t1, rd+1);
5f68f5ae 13660 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
3c824109
NF
13661 break;
13662#ifdef TARGET_MIPS64
13663 case LDP:
36c6711b 13664 if (rd == base) {
9c708c7f 13665 generate_exception_end(ctx, EXCP_RI);
36c6711b
EJ
13666 return;
13667 }
5f68f5ae 13668 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
13669 gen_store_gpr(t1, rd);
13670 tcg_gen_movi_tl(t1, 8);
13671 gen_op_addr_add(ctx, t0, t0, t1);
5f68f5ae 13672 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109 13673 gen_store_gpr(t1, rd+1);
3c824109
NF
13674 break;
13675 case SDP:
3c824109 13676 gen_load_gpr(t1, rd);
5f68f5ae 13677 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
13678 tcg_gen_movi_tl(t1, 8);
13679 gen_op_addr_add(ctx, t0, t0, t1);
13680 gen_load_gpr(t1, rd+1);
5f68f5ae 13681 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
3c824109
NF
13682 break;
13683#endif
6af0bf9c 13684 }
3c824109
NF
13685 tcg_temp_free(t0);
13686 tcg_temp_free(t1);
13687}
618b0fe9 13688
d208ac0c
LA
13689static void gen_sync(int stype)
13690{
13691 TCGBar tcg_mo = TCG_BAR_SC;
13692
13693 switch (stype) {
13694 case 0x4: /* SYNC_WMB */
13695 tcg_mo |= TCG_MO_ST_ST;
13696 break;
13697 case 0x10: /* SYNC_MB */
13698 tcg_mo |= TCG_MO_ALL;
13699 break;
13700 case 0x11: /* SYNC_ACQUIRE */
13701 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
13702 break;
13703 case 0x12: /* SYNC_RELEASE */
13704 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
13705 break;
13706 case 0x13: /* SYNC_RMB */
13707 tcg_mo |= TCG_MO_LD_LD;
13708 break;
13709 default:
13710 tcg_mo |= TCG_MO_ALL;
13711 break;
13712 }
13713
13714 tcg_gen_mb(tcg_mo);
13715}
13716
240ce26a 13717static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
3c824109
NF
13718{
13719 int extension = (ctx->opcode >> 6) & 0x3f;
13720 int minor = (ctx->opcode >> 12) & 0xf;
13721 uint32_t mips32_op;
13722
13723 switch (extension) {
13724 case TEQ:
13725 mips32_op = OPC_TEQ;
13726 goto do_trap;
13727 case TGE:
13728 mips32_op = OPC_TGE;
13729 goto do_trap;
13730 case TGEU:
13731 mips32_op = OPC_TGEU;
13732 goto do_trap;
13733 case TLT:
13734 mips32_op = OPC_TLT;
13735 goto do_trap;
13736 case TLTU:
13737 mips32_op = OPC_TLTU;
13738 goto do_trap;
13739 case TNE:
13740 mips32_op = OPC_TNE;
13741 do_trap:
13742 gen_trap(ctx, mips32_op, rs, rt, -1);
13743 break;
13744#ifndef CONFIG_USER_ONLY
13745 case MFC0:
13746 case MFC0 + 32:
2e15497c 13747 check_cp0_enabled(ctx);
3c824109
NF
13748 if (rt == 0) {
13749 /* Treat as NOP. */
13750 break;
13751 }
d75c135e 13752 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
13753 break;
13754 case MTC0:
13755 case MTC0 + 32:
2e15497c 13756 check_cp0_enabled(ctx);
3c824109
NF
13757 {
13758 TCGv t0 = tcg_temp_new();
618b0fe9 13759
3c824109 13760 gen_load_gpr(t0, rt);
d75c135e 13761 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
3c824109
NF
13762 tcg_temp_free(t0);
13763 }
13764 break;
13765#endif
a1fc6246
LA
13766 case 0x2a:
13767 switch (minor & 3) {
13768 case MADD_ACC:
13769 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
13770 break;
13771 case MADDU_ACC:
13772 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
13773 break;
13774 case MSUB_ACC:
13775 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
13776 break;
13777 case MSUBU_ACC:
13778 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
13779 break;
13780 default:
13781 goto pool32axf_invalid;
13782 }
13783 break;
13784 case 0x32:
13785 switch (minor & 3) {
13786 case MULT_ACC:
13787 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
13788 break;
13789 case MULTU_ACC:
13790 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
13791 break;
13792 default:
13793 goto pool32axf_invalid;
13794 }
13795 break;
3c824109
NF
13796 case 0x2c:
13797 switch (minor) {
e0332095
YK
13798 case BITSWAP:
13799 check_insn(ctx, ISA_MIPS32R6);
13800 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
13801 break;
3c824109
NF
13802 case SEB:
13803 gen_bshfl(ctx, OPC_SEB, rs, rt);
13804 break;
13805 case SEH:
13806 gen_bshfl(ctx, OPC_SEH, rs, rt);
13807 break;
13808 case CLO:
13809 mips32_op = OPC_CLO;
13810 goto do_cl;
13811 case CLZ:
13812 mips32_op = OPC_CLZ;
13813 do_cl:
d75c135e 13814 check_insn(ctx, ISA_MIPS32);
3c824109
NF
13815 gen_cl(ctx, mips32_op, rt, rs);
13816 break;
13817 case RDHWR:
b00c7218
YK
13818 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13819 gen_rdhwr(ctx, rt, rs, 0);
3c824109
NF
13820 break;
13821 case WSBH:
13822 gen_bshfl(ctx, OPC_WSBH, rs, rt);
13823 break;
13824 case MULT:
9e8f441a 13825 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 13826 mips32_op = OPC_MULT;
26135ead 13827 goto do_mul;
3c824109 13828 case MULTU:
9e8f441a 13829 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 13830 mips32_op = OPC_MULTU;
26135ead 13831 goto do_mul;
3c824109 13832 case DIV:
9e8f441a 13833 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 13834 mips32_op = OPC_DIV;
26135ead 13835 goto do_div;
3c824109 13836 case DIVU:
9e8f441a 13837 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 13838 mips32_op = OPC_DIVU;
26135ead
RS
13839 goto do_div;
13840 do_div:
13841 check_insn(ctx, ISA_MIPS32);
13842 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13843 break;
3c824109 13844 case MADD:
9e8f441a 13845 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 13846 mips32_op = OPC_MADD;
26135ead 13847 goto do_mul;
3c824109 13848 case MADDU:
9e8f441a 13849 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 13850 mips32_op = OPC_MADDU;
26135ead 13851 goto do_mul;
3c824109 13852 case MSUB:
9e8f441a 13853 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 13854 mips32_op = OPC_MSUB;
26135ead 13855 goto do_mul;
3c824109 13856 case MSUBU:
9e8f441a 13857 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 13858 mips32_op = OPC_MSUBU;
26135ead 13859 do_mul:
d75c135e 13860 check_insn(ctx, ISA_MIPS32);
a1fc6246 13861 gen_muldiv(ctx, mips32_op, 0, rs, rt);
3c824109
NF
13862 break;
13863 default:
13864 goto pool32axf_invalid;
13865 }
13866 break;
13867 case 0x34:
13868 switch (minor) {
13869 case MFC2:
13870 case MTC2:
13871 case MFHC2:
13872 case MTHC2:
13873 case CFC2:
13874 case CTC2:
13875 generate_exception_err(ctx, EXCP_CpU, 2);
13876 break;
13877 default:
13878 goto pool32axf_invalid;
13879 }
13880 break;
13881 case 0x3c:
13882 switch (minor) {
65935f07
YK
13883 case JALR: /* JALRC */
13884 case JALR_HB: /* JALRC_HB */
13885 if (ctx->insn_flags & ISA_MIPS32R6) {
13886 /* JALRC, JALRC_HB */
13887 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13888 } else {
13889 /* JALR, JALR_HB */
13890 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13891 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13892 }
3c824109
NF
13893 break;
13894 case JALRS:
13895 case JALRS_HB:
9e8f441a 13896 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
13897 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13898 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109
NF
13899 break;
13900 default:
13901 goto pool32axf_invalid;
13902 }
13903 break;
13904 case 0x05:
13905 switch (minor) {
13906 case RDPGPR:
2e15497c 13907 check_cp0_enabled(ctx);
d75c135e 13908 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 13909 gen_load_srsgpr(rs, rt);
3c824109
NF
13910 break;
13911 case WRPGPR:
2e15497c 13912 check_cp0_enabled(ctx);
d75c135e 13913 check_insn(ctx, ISA_MIPS32R2);
1bf5902d 13914 gen_store_srsgpr(rs, rt);
3c824109
NF
13915 break;
13916 default:
13917 goto pool32axf_invalid;
13918 }
13919 break;
13920#ifndef CONFIG_USER_ONLY
13921 case 0x0d:
13922 switch (minor) {
13923 case TLBP:
13924 mips32_op = OPC_TLBP;
13925 goto do_cp0;
13926 case TLBR:
13927 mips32_op = OPC_TLBR;
13928 goto do_cp0;
13929 case TLBWI:
13930 mips32_op = OPC_TLBWI;
13931 goto do_cp0;
13932 case TLBWR:
13933 mips32_op = OPC_TLBWR;
13934 goto do_cp0;
e60ec063
YK
13935 case TLBINV:
13936 mips32_op = OPC_TLBINV;
13937 goto do_cp0;
13938 case TLBINVF:
13939 mips32_op = OPC_TLBINVF;
13940 goto do_cp0;
3c824109
NF
13941 case WAIT:
13942 mips32_op = OPC_WAIT;
13943 goto do_cp0;
13944 case DERET:
13945 mips32_op = OPC_DERET;
13946 goto do_cp0;
13947 case ERET:
13948 mips32_op = OPC_ERET;
13949 do_cp0:
13950 gen_cp0(env, ctx, mips32_op, rt, rs);
13951 break;
13952 default:
13953 goto pool32axf_invalid;
13954 }
13955 break;
13956 case 0x1d:
13957 switch (minor) {
13958 case DI:
2e15497c 13959 check_cp0_enabled(ctx);
3c824109
NF
13960 {
13961 TCGv t0 = tcg_temp_new();
13962
13963 save_cpu_state(ctx, 1);
895c2d04 13964 gen_helper_di(t0, cpu_env);
3c824109
NF
13965 gen_store_gpr(t0, rs);
13966 /* Stop translation as we may have switched the execution mode */
eeb3bba8 13967 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
13968 tcg_temp_free(t0);
13969 }
13970 break;
13971 case EI:
2e15497c 13972 check_cp0_enabled(ctx);
3c824109
NF
13973 {
13974 TCGv t0 = tcg_temp_new();
13975
13976 save_cpu_state(ctx, 1);
895c2d04 13977 gen_helper_ei(t0, cpu_env);
3c824109 13978 gen_store_gpr(t0, rs);
b28425ba 13979 /* DISAS_STOP isn't sufficient, we need to ensure we break out
b74cddcb 13980 of translated code to check for pending interrupts. */
eeb3bba8
EC
13981 gen_save_pc(ctx->base.pc_next + 4);
13982 ctx->base.is_jmp = DISAS_EXIT;
3c824109
NF
13983 tcg_temp_free(t0);
13984 }
13985 break;
13986 default:
13987 goto pool32axf_invalid;
13988 }
13989 break;
13990#endif
13991 case 0x2d:
13992 switch (minor) {
13993 case SYNC:
d208ac0c 13994 gen_sync(extract32(ctx->opcode, 16, 5));
3c824109
NF
13995 break;
13996 case SYSCALL:
9c708c7f 13997 generate_exception_end(ctx, EXCP_SYSCALL);
3c824109
NF
13998 break;
13999 case SDBBP:
3b3c1694
LA
14000 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
14001 gen_helper_do_semihosting(cpu_env);
14002 } else {
14003 check_insn(ctx, ISA_MIPS32);
e0332095 14004 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 14005 generate_exception_end(ctx, EXCP_RI);
e0332095 14006 } else {
9c708c7f 14007 generate_exception_end(ctx, EXCP_DBp);
e0332095 14008 }
3b3c1694 14009 }
3c824109
NF
14010 break;
14011 default:
14012 goto pool32axf_invalid;
14013 }
14014 break;
a1fc6246 14015 case 0x01:
26135ead 14016 switch (minor & 3) {
a1fc6246 14017 case MFHI_ACC:
26135ead 14018 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
3c824109 14019 break;
a1fc6246 14020 case MFLO_ACC:
26135ead 14021 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
3c824109 14022 break;
a1fc6246 14023 case MTHI_ACC:
26135ead 14024 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
3c824109 14025 break;
a1fc6246 14026 case MTLO_ACC:
26135ead 14027 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
3c824109
NF
14028 break;
14029 default:
14030 goto pool32axf_invalid;
14031 }
14032 break;
a1fc6246 14033 case 0x35:
9e8f441a 14034 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a1fc6246
LA
14035 switch (minor) {
14036 case MFHI32:
14037 gen_HILO(ctx, OPC_MFHI, 0, rs);
14038 break;
14039 case MFLO32:
14040 gen_HILO(ctx, OPC_MFLO, 0, rs);
14041 break;
14042 case MTHI32:
14043 gen_HILO(ctx, OPC_MTHI, 0, rs);
14044 break;
14045 case MTLO32:
14046 gen_HILO(ctx, OPC_MTLO, 0, rs);
14047 break;
14048 default:
14049 goto pool32axf_invalid;
14050 }
14051 break;
3c824109
NF
14052 default:
14053 pool32axf_invalid:
14054 MIPS_INVAL("pool32axf");
9c708c7f 14055 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
14056 break;
14057 }
14058}
14059
14060/* Values for microMIPS fmt field. Variable-width, depending on which
14061 formats the instruction supports. */
14062
14063enum {
14064 FMT_SD_S = 0,
14065 FMT_SD_D = 1,
14066
14067 FMT_SDPS_S = 0,
14068 FMT_SDPS_D = 1,
14069 FMT_SDPS_PS = 2,
14070
14071 FMT_SWL_S = 0,
14072 FMT_SWL_W = 1,
14073 FMT_SWL_L = 2,
14074
14075 FMT_DWL_D = 0,
14076 FMT_DWL_W = 1,
14077 FMT_DWL_L = 2
14078};
14079
d75c135e 14080static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
3c824109
NF
14081{
14082 int extension = (ctx->opcode >> 6) & 0x3ff;
14083 uint32_t mips32_op;
14084
14085#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
14086#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
14087#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
14088
14089 switch (extension) {
14090 case FLOAT_1BIT_FMT(CFC1, 0):
14091 mips32_op = OPC_CFC1;
14092 goto do_cp1;
14093 case FLOAT_1BIT_FMT(CTC1, 0):
14094 mips32_op = OPC_CTC1;
14095 goto do_cp1;
14096 case FLOAT_1BIT_FMT(MFC1, 0):
14097 mips32_op = OPC_MFC1;
14098 goto do_cp1;
14099 case FLOAT_1BIT_FMT(MTC1, 0):
14100 mips32_op = OPC_MTC1;
14101 goto do_cp1;
14102 case FLOAT_1BIT_FMT(MFHC1, 0):
14103 mips32_op = OPC_MFHC1;
14104 goto do_cp1;
14105 case FLOAT_1BIT_FMT(MTHC1, 0):
14106 mips32_op = OPC_MTHC1;
14107 do_cp1:
14108 gen_cp1(ctx, mips32_op, rt, rs);
14109 break;
14110
14111 /* Reciprocal square root */
14112 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
14113 mips32_op = OPC_RSQRT_S;
14114 goto do_unaryfp;
14115 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
14116 mips32_op = OPC_RSQRT_D;
14117 goto do_unaryfp;
14118
14119 /* Square root */
14120 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
14121 mips32_op = OPC_SQRT_S;
14122 goto do_unaryfp;
14123 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
14124 mips32_op = OPC_SQRT_D;
14125 goto do_unaryfp;
14126
14127 /* Reciprocal */
14128 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
14129 mips32_op = OPC_RECIP_S;
14130 goto do_unaryfp;
14131 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
14132 mips32_op = OPC_RECIP_D;
14133 goto do_unaryfp;
14134
14135 /* Floor */
14136 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
14137 mips32_op = OPC_FLOOR_L_S;
14138 goto do_unaryfp;
14139 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
14140 mips32_op = OPC_FLOOR_L_D;
14141 goto do_unaryfp;
14142 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
14143 mips32_op = OPC_FLOOR_W_S;
14144 goto do_unaryfp;
14145 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
14146 mips32_op = OPC_FLOOR_W_D;
14147 goto do_unaryfp;
14148
14149 /* Ceiling */
14150 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
14151 mips32_op = OPC_CEIL_L_S;
14152 goto do_unaryfp;
14153 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
14154 mips32_op = OPC_CEIL_L_D;
14155 goto do_unaryfp;
14156 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
14157 mips32_op = OPC_CEIL_W_S;
14158 goto do_unaryfp;
14159 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
14160 mips32_op = OPC_CEIL_W_D;
14161 goto do_unaryfp;
14162
14163 /* Truncation */
14164 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
14165 mips32_op = OPC_TRUNC_L_S;
14166 goto do_unaryfp;
14167 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
14168 mips32_op = OPC_TRUNC_L_D;
14169 goto do_unaryfp;
14170 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
14171 mips32_op = OPC_TRUNC_W_S;
14172 goto do_unaryfp;
14173 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
14174 mips32_op = OPC_TRUNC_W_D;
14175 goto do_unaryfp;
14176
14177 /* Round */
14178 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
14179 mips32_op = OPC_ROUND_L_S;
14180 goto do_unaryfp;
14181 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
14182 mips32_op = OPC_ROUND_L_D;
14183 goto do_unaryfp;
14184 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
14185 mips32_op = OPC_ROUND_W_S;
14186 goto do_unaryfp;
14187 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
14188 mips32_op = OPC_ROUND_W_D;
14189 goto do_unaryfp;
14190
14191 /* Integer to floating-point conversion */
14192 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
14193 mips32_op = OPC_CVT_L_S;
14194 goto do_unaryfp;
14195 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
14196 mips32_op = OPC_CVT_L_D;
14197 goto do_unaryfp;
14198 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
14199 mips32_op = OPC_CVT_W_S;
14200 goto do_unaryfp;
14201 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
14202 mips32_op = OPC_CVT_W_D;
14203 goto do_unaryfp;
14204
14205 /* Paired-foo conversions */
14206 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
14207 mips32_op = OPC_CVT_S_PL;
14208 goto do_unaryfp;
14209 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
14210 mips32_op = OPC_CVT_S_PU;
14211 goto do_unaryfp;
14212 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
14213 mips32_op = OPC_CVT_PW_PS;
14214 goto do_unaryfp;
14215 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
14216 mips32_op = OPC_CVT_PS_PW;
14217 goto do_unaryfp;
14218
14219 /* Floating-point moves */
14220 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
14221 mips32_op = OPC_MOV_S;
14222 goto do_unaryfp;
14223 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
14224 mips32_op = OPC_MOV_D;
14225 goto do_unaryfp;
14226 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
14227 mips32_op = OPC_MOV_PS;
14228 goto do_unaryfp;
14229
14230 /* Absolute value */
14231 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
14232 mips32_op = OPC_ABS_S;
14233 goto do_unaryfp;
14234 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
14235 mips32_op = OPC_ABS_D;
14236 goto do_unaryfp;
14237 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
14238 mips32_op = OPC_ABS_PS;
14239 goto do_unaryfp;
14240
14241 /* Negation */
14242 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
14243 mips32_op = OPC_NEG_S;
14244 goto do_unaryfp;
14245 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
14246 mips32_op = OPC_NEG_D;
14247 goto do_unaryfp;
14248 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
14249 mips32_op = OPC_NEG_PS;
14250 goto do_unaryfp;
14251
14252 /* Reciprocal square root step */
14253 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
14254 mips32_op = OPC_RSQRT1_S;
14255 goto do_unaryfp;
14256 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
14257 mips32_op = OPC_RSQRT1_D;
14258 goto do_unaryfp;
14259 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
14260 mips32_op = OPC_RSQRT1_PS;
14261 goto do_unaryfp;
14262
14263 /* Reciprocal step */
14264 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
14265 mips32_op = OPC_RECIP1_S;
14266 goto do_unaryfp;
14267 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
14268 mips32_op = OPC_RECIP1_S;
14269 goto do_unaryfp;
14270 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
14271 mips32_op = OPC_RECIP1_PS;
14272 goto do_unaryfp;
14273
14274 /* Conversions from double */
14275 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
14276 mips32_op = OPC_CVT_D_S;
14277 goto do_unaryfp;
14278 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
14279 mips32_op = OPC_CVT_D_W;
14280 goto do_unaryfp;
14281 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
14282 mips32_op = OPC_CVT_D_L;
14283 goto do_unaryfp;
14284
14285 /* Conversions from single */
14286 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
14287 mips32_op = OPC_CVT_S_D;
14288 goto do_unaryfp;
14289 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
14290 mips32_op = OPC_CVT_S_W;
14291 goto do_unaryfp;
14292 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
14293 mips32_op = OPC_CVT_S_L;
14294 do_unaryfp:
14295 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
14296 break;
14297
14298 /* Conditional moves on floating-point codes */
14299 case COND_FLOAT_MOV(MOVT, 0):
14300 case COND_FLOAT_MOV(MOVT, 1):
14301 case COND_FLOAT_MOV(MOVT, 2):
14302 case COND_FLOAT_MOV(MOVT, 3):
14303 case COND_FLOAT_MOV(MOVT, 4):
14304 case COND_FLOAT_MOV(MOVT, 5):
14305 case COND_FLOAT_MOV(MOVT, 6):
14306 case COND_FLOAT_MOV(MOVT, 7):
9e8f441a 14307 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14308 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
14309 break;
14310 case COND_FLOAT_MOV(MOVF, 0):
14311 case COND_FLOAT_MOV(MOVF, 1):
14312 case COND_FLOAT_MOV(MOVF, 2):
14313 case COND_FLOAT_MOV(MOVF, 3):
14314 case COND_FLOAT_MOV(MOVF, 4):
14315 case COND_FLOAT_MOV(MOVF, 5):
14316 case COND_FLOAT_MOV(MOVF, 6):
14317 case COND_FLOAT_MOV(MOVF, 7):
9e8f441a 14318 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14319 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
14320 break;
14321 default:
14322 MIPS_INVAL("pool32fxf");
9c708c7f 14323 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
14324 break;
14325 }
14326}
14327
f60eeb0c 14328static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
14329{
14330 int32_t offset;
14331 uint16_t insn;
14332 int rt, rs, rd, rr;
14333 int16_t imm;
8fffc646 14334 uint32_t op, minor, minor2, mips32_op;
3c824109
NF
14335 uint32_t cond, fmt, cc;
14336
eeb3bba8 14337 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
3c824109
NF
14338 ctx->opcode = (ctx->opcode << 16) | insn;
14339
14340 rt = (ctx->opcode >> 21) & 0x1f;
14341 rs = (ctx->opcode >> 16) & 0x1f;
14342 rd = (ctx->opcode >> 11) & 0x1f;
14343 rr = (ctx->opcode >> 6) & 0x1f;
14344 imm = (int16_t) ctx->opcode;
14345
14346 op = (ctx->opcode >> 26) & 0x3f;
14347 switch (op) {
14348 case POOL32A:
14349 minor = ctx->opcode & 0x3f;
14350 switch (minor) {
14351 case 0x00:
14352 minor = (ctx->opcode >> 6) & 0xf;
14353 switch (minor) {
14354 case SLL32:
14355 mips32_op = OPC_SLL;
14356 goto do_shifti;
14357 case SRA:
14358 mips32_op = OPC_SRA;
14359 goto do_shifti;
14360 case SRL32:
14361 mips32_op = OPC_SRL;
14362 goto do_shifti;
14363 case ROTR:
14364 mips32_op = OPC_ROTR;
14365 do_shifti:
d75c135e 14366 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
3c824109 14367 break;
e0332095
YK
14368 case SELEQZ:
14369 check_insn(ctx, ISA_MIPS32R6);
14370 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
14371 break;
14372 case SELNEZ:
14373 check_insn(ctx, ISA_MIPS32R6);
14374 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
14375 break;
b00c7218
YK
14376 case R6_RDHWR:
14377 check_insn(ctx, ISA_MIPS32R6);
14378 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
14379 break;
3c824109
NF
14380 default:
14381 goto pool32a_invalid;
14382 }
14383 break;
14384 case 0x10:
14385 minor = (ctx->opcode >> 6) & 0xf;
14386 switch (minor) {
14387 /* Arithmetic */
14388 case ADD:
14389 mips32_op = OPC_ADD;
14390 goto do_arith;
14391 case ADDU32:
14392 mips32_op = OPC_ADDU;
14393 goto do_arith;
14394 case SUB:
14395 mips32_op = OPC_SUB;
14396 goto do_arith;
14397 case SUBU32:
14398 mips32_op = OPC_SUBU;
14399 goto do_arith;
14400 case MUL:
9e8f441a 14401 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14402 mips32_op = OPC_MUL;
14403 do_arith:
d75c135e 14404 gen_arith(ctx, mips32_op, rd, rs, rt);
3c824109
NF
14405 break;
14406 /* Shifts */
14407 case SLLV:
14408 mips32_op = OPC_SLLV;
14409 goto do_shift;
14410 case SRLV:
14411 mips32_op = OPC_SRLV;
14412 goto do_shift;
14413 case SRAV:
14414 mips32_op = OPC_SRAV;
14415 goto do_shift;
14416 case ROTRV:
14417 mips32_op = OPC_ROTRV;
14418 do_shift:
d75c135e 14419 gen_shift(ctx, mips32_op, rd, rs, rt);
3c824109
NF
14420 break;
14421 /* Logical operations */
14422 case AND:
14423 mips32_op = OPC_AND;
14424 goto do_logic;
14425 case OR32:
14426 mips32_op = OPC_OR;
14427 goto do_logic;
14428 case NOR:
14429 mips32_op = OPC_NOR;
14430 goto do_logic;
14431 case XOR32:
14432 mips32_op = OPC_XOR;
14433 do_logic:
d75c135e 14434 gen_logic(ctx, mips32_op, rd, rs, rt);
3c824109
NF
14435 break;
14436 /* Set less than */
14437 case SLT:
14438 mips32_op = OPC_SLT;
14439 goto do_slt;
14440 case SLTU:
14441 mips32_op = OPC_SLTU;
14442 do_slt:
d75c135e 14443 gen_slt(ctx, mips32_op, rd, rs, rt);
3c824109
NF
14444 break;
14445 default:
14446 goto pool32a_invalid;
14447 }
14448 break;
14449 case 0x18:
14450 minor = (ctx->opcode >> 6) & 0xf;
14451 switch (minor) {
14452 /* Conditional moves */
e0332095
YK
14453 case MOVN: /* MUL */
14454 if (ctx->insn_flags & ISA_MIPS32R6) {
14455 /* MUL */
14456 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
14457 } else {
14458 /* MOVN */
14459 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
14460 }
14461 break;
14462 case MOVZ: /* MUH */
14463 if (ctx->insn_flags & ISA_MIPS32R6) {
14464 /* MUH */
14465 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
14466 } else {
14467 /* MOVZ */
14468 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
14469 }
14470 break;
14471 case MULU:
14472 check_insn(ctx, ISA_MIPS32R6);
14473 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
14474 break;
14475 case MUHU:
14476 check_insn(ctx, ISA_MIPS32R6);
14477 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
14478 break;
14479 case LWXS: /* DIV */
14480 if (ctx->insn_flags & ISA_MIPS32R6) {
14481 /* DIV */
14482 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
14483 } else {
14484 /* LWXS */
14485 gen_ldxs(ctx, rs, rt, rd);
14486 }
14487 break;
14488 case MOD:
14489 check_insn(ctx, ISA_MIPS32R6);
14490 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
14491 break;
14492 case R6_DIVU:
14493 check_insn(ctx, ISA_MIPS32R6);
14494 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
3c824109 14495 break;
e0332095
YK
14496 case MODU:
14497 check_insn(ctx, ISA_MIPS32R6);
14498 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
3c824109
NF
14499 break;
14500 default:
14501 goto pool32a_invalid;
14502 }
14503 break;
14504 case INS:
14505 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
14506 return;
e0332095
YK
14507 case LSA:
14508 check_insn(ctx, ISA_MIPS32R6);
14509 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
14510 extract32(ctx->opcode, 9, 2));
14511 break;
14512 case ALIGN:
14513 check_insn(ctx, ISA_MIPS32R6);
821f2008 14514 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
e0332095 14515 break;
3c824109
NF
14516 case EXT:
14517 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
14518 return;
14519 case POOL32AXF:
240ce26a 14520 gen_pool32axf(env, ctx, rt, rs);
3c824109 14521 break;
dbd8af98 14522 case BREAK32:
9c708c7f 14523 generate_exception_end(ctx, EXCP_BREAK);
3c824109 14524 break;
bb238210
YK
14525 case SIGRIE:
14526 check_insn(ctx, ISA_MIPS32R6);
14527 generate_exception_end(ctx, EXCP_RI);
14528 break;
3c824109
NF
14529 default:
14530 pool32a_invalid:
14531 MIPS_INVAL("pool32a");
9c708c7f 14532 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
14533 break;
14534 }
14535 break;
14536 case POOL32B:
14537 minor = (ctx->opcode >> 12) & 0xf;
14538 switch (minor) {
14539 case CACHE:
2e15497c 14540 check_cp0_enabled(ctx);
0d74a222
LA
14541 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
14542 gen_cache_operation(ctx, rt, rs, imm);
14543 }
3c824109
NF
14544 break;
14545 case LWC2:
14546 case SWC2:
14547 /* COP2: Not implemented. */
14548 generate_exception_err(ctx, EXCP_CpU, 2);
14549 break;
3c824109
NF
14550#ifdef TARGET_MIPS64
14551 case LDP:
14552 case SDP:
d9224450
MR
14553 check_insn(ctx, ISA_MIPS3);
14554 check_mips_64(ctx);
3c824109 14555#endif
146dd620 14556 /* fall through */
d9224450
MR
14557 case LWP:
14558 case SWP:
3c824109
NF
14559 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14560 break;
3c824109
NF
14561#ifdef TARGET_MIPS64
14562 case LDM:
14563 case SDM:
d9224450
MR
14564 check_insn(ctx, ISA_MIPS3);
14565 check_mips_64(ctx);
3c824109 14566#endif
146dd620 14567 /* fall through */
d9224450
MR
14568 case LWM32:
14569 case SWM32:
3c824109
NF
14570 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14571 break;
14572 default:
14573 MIPS_INVAL("pool32b");
9c708c7f 14574 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
14575 break;
14576 }
14577 break;
14578 case POOL32F:
5ab5c041 14579 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3c824109
NF
14580 minor = ctx->opcode & 0x3f;
14581 check_cp1_enabled(ctx);
14582 switch (minor) {
14583 case ALNV_PS:
9e8f441a 14584 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14585 mips32_op = OPC_ALNV_PS;
14586 goto do_madd;
14587 case MADD_S:
9e8f441a 14588 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14589 mips32_op = OPC_MADD_S;
14590 goto do_madd;
14591 case MADD_D:
9e8f441a 14592 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14593 mips32_op = OPC_MADD_D;
14594 goto do_madd;
14595 case MADD_PS:
9e8f441a 14596 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14597 mips32_op = OPC_MADD_PS;
14598 goto do_madd;
14599 case MSUB_S:
9e8f441a 14600 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14601 mips32_op = OPC_MSUB_S;
14602 goto do_madd;
14603 case MSUB_D:
9e8f441a 14604 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14605 mips32_op = OPC_MSUB_D;
14606 goto do_madd;
14607 case MSUB_PS:
9e8f441a 14608 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14609 mips32_op = OPC_MSUB_PS;
14610 goto do_madd;
14611 case NMADD_S:
9e8f441a 14612 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14613 mips32_op = OPC_NMADD_S;
14614 goto do_madd;
14615 case NMADD_D:
9e8f441a 14616 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14617 mips32_op = OPC_NMADD_D;
14618 goto do_madd;
14619 case NMADD_PS:
9e8f441a 14620 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14621 mips32_op = OPC_NMADD_PS;
14622 goto do_madd;
14623 case NMSUB_S:
9e8f441a 14624 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14625 mips32_op = OPC_NMSUB_S;
14626 goto do_madd;
14627 case NMSUB_D:
9e8f441a 14628 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14629 mips32_op = OPC_NMSUB_D;
14630 goto do_madd;
14631 case NMSUB_PS:
9e8f441a 14632 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14633 mips32_op = OPC_NMSUB_PS;
14634 do_madd:
14635 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
14636 break;
14637 case CABS_COND_FMT:
9e8f441a 14638 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14639 cond = (ctx->opcode >> 6) & 0xf;
14640 cc = (ctx->opcode >> 13) & 0x7;
14641 fmt = (ctx->opcode >> 10) & 0x3;
14642 switch (fmt) {
14643 case 0x0:
14644 gen_cmpabs_s(ctx, cond, rt, rs, cc);
14645 break;
14646 case 0x1:
14647 gen_cmpabs_d(ctx, cond, rt, rs, cc);
14648 break;
14649 case 0x2:
14650 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
14651 break;
14652 default:
14653 goto pool32f_invalid;
14654 }
14655 break;
14656 case C_COND_FMT:
9e8f441a 14657 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14658 cond = (ctx->opcode >> 6) & 0xf;
14659 cc = (ctx->opcode >> 13) & 0x7;
14660 fmt = (ctx->opcode >> 10) & 0x3;
14661 switch (fmt) {
14662 case 0x0:
14663 gen_cmp_s(ctx, cond, rt, rs, cc);
14664 break;
14665 case 0x1:
14666 gen_cmp_d(ctx, cond, rt, rs, cc);
14667 break;
14668 case 0x2:
14669 gen_cmp_ps(ctx, cond, rt, rs, cc);
14670 break;
14671 default:
14672 goto pool32f_invalid;
14673 }
14674 break;
2a24a7ba
YK
14675 case CMP_CONDN_S:
14676 check_insn(ctx, ISA_MIPS32R6);
14677 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14678 break;
14679 case CMP_CONDN_D:
14680 check_insn(ctx, ISA_MIPS32R6);
14681 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14682 break;
3c824109 14683 case POOL32FXF:
d75c135e 14684 gen_pool32fxf(ctx, rt, rs);
3c824109
NF
14685 break;
14686 case 0x00:
14687 /* PLL foo */
14688 switch ((ctx->opcode >> 6) & 0x7) {
14689 case PLL_PS:
14690 mips32_op = OPC_PLL_PS;
14691 goto do_ps;
14692 case PLU_PS:
14693 mips32_op = OPC_PLU_PS;
14694 goto do_ps;
14695 case PUL_PS:
14696 mips32_op = OPC_PUL_PS;
14697 goto do_ps;
14698 case PUU_PS:
14699 mips32_op = OPC_PUU_PS;
14700 goto do_ps;
14701 case CVT_PS_S:
9e8f441a 14702 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14703 mips32_op = OPC_CVT_PS_S;
14704 do_ps:
14705 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14706 break;
14707 default:
14708 goto pool32f_invalid;
14709 }
14710 break;
2a24a7ba
YK
14711 case MIN_FMT:
14712 check_insn(ctx, ISA_MIPS32R6);
14713 switch ((ctx->opcode >> 9) & 0x3) {
14714 case FMT_SDPS_S:
14715 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
14716 break;
14717 case FMT_SDPS_D:
14718 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
14719 break;
14720 default:
14721 goto pool32f_invalid;
14722 }
14723 break;
3c824109
NF
14724 case 0x08:
14725 /* [LS][WDU]XC1 */
14726 switch ((ctx->opcode >> 6) & 0x7) {
14727 case LWXC1:
9e8f441a 14728 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14729 mips32_op = OPC_LWXC1;
14730 goto do_ldst_cp1;
14731 case SWXC1:
9e8f441a 14732 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14733 mips32_op = OPC_SWXC1;
14734 goto do_ldst_cp1;
14735 case LDXC1:
9e8f441a 14736 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14737 mips32_op = OPC_LDXC1;
14738 goto do_ldst_cp1;
14739 case SDXC1:
9e8f441a 14740 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14741 mips32_op = OPC_SDXC1;
14742 goto do_ldst_cp1;
14743 case LUXC1:
9e8f441a 14744 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14745 mips32_op = OPC_LUXC1;
14746 goto do_ldst_cp1;
14747 case SUXC1:
9e8f441a 14748 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14749 mips32_op = OPC_SUXC1;
14750 do_ldst_cp1:
14751 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
14752 break;
14753 default:
14754 goto pool32f_invalid;
14755 }
14756 break;
2a24a7ba
YK
14757 case MAX_FMT:
14758 check_insn(ctx, ISA_MIPS32R6);
14759 switch ((ctx->opcode >> 9) & 0x3) {
14760 case FMT_SDPS_S:
14761 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
14762 break;
14763 case FMT_SDPS_D:
14764 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
14765 break;
14766 default:
14767 goto pool32f_invalid;
14768 }
14769 break;
3c824109
NF
14770 case 0x18:
14771 /* 3D insns */
9e8f441a 14772 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14773 fmt = (ctx->opcode >> 9) & 0x3;
14774 switch ((ctx->opcode >> 6) & 0x7) {
14775 case RSQRT2_FMT:
14776 switch (fmt) {
14777 case FMT_SDPS_S:
14778 mips32_op = OPC_RSQRT2_S;
14779 goto do_3d;
14780 case FMT_SDPS_D:
14781 mips32_op = OPC_RSQRT2_D;
14782 goto do_3d;
14783 case FMT_SDPS_PS:
14784 mips32_op = OPC_RSQRT2_PS;
14785 goto do_3d;
14786 default:
14787 goto pool32f_invalid;
14788 }
14789 break;
14790 case RECIP2_FMT:
14791 switch (fmt) {
14792 case FMT_SDPS_S:
14793 mips32_op = OPC_RECIP2_S;
14794 goto do_3d;
14795 case FMT_SDPS_D:
14796 mips32_op = OPC_RECIP2_D;
14797 goto do_3d;
14798 case FMT_SDPS_PS:
14799 mips32_op = OPC_RECIP2_PS;
14800 goto do_3d;
14801 default:
14802 goto pool32f_invalid;
14803 }
14804 break;
14805 case ADDR_PS:
14806 mips32_op = OPC_ADDR_PS;
14807 goto do_3d;
14808 case MULR_PS:
14809 mips32_op = OPC_MULR_PS;
14810 do_3d:
14811 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14812 break;
14813 default:
14814 goto pool32f_invalid;
14815 }
14816 break;
14817 case 0x20:
2a24a7ba 14818 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
3c824109
NF
14819 cc = (ctx->opcode >> 13) & 0x7;
14820 fmt = (ctx->opcode >> 9) & 0x3;
14821 switch ((ctx->opcode >> 6) & 0x7) {
2a24a7ba
YK
14822 case MOVF_FMT: /* RINT_FMT */
14823 if (ctx->insn_flags & ISA_MIPS32R6) {
14824 /* RINT_FMT */
14825 switch (fmt) {
14826 case FMT_SDPS_S:
14827 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
14828 break;
14829 case FMT_SDPS_D:
14830 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
14831 break;
14832 default:
14833 goto pool32f_invalid;
14834 }
14835 } else {
14836 /* MOVF_FMT */
14837 switch (fmt) {
14838 case FMT_SDPS_S:
14839 gen_movcf_s(ctx, rs, rt, cc, 0);
14840 break;
14841 case FMT_SDPS_D:
14842 gen_movcf_d(ctx, rs, rt, cc, 0);
14843 break;
14844 case FMT_SDPS_PS:
14845 check_ps(ctx);
14846 gen_movcf_ps(ctx, rs, rt, cc, 0);
14847 break;
14848 default:
14849 goto pool32f_invalid;
14850 }
3c824109
NF
14851 }
14852 break;
2a24a7ba
YK
14853 case MOVT_FMT: /* CLASS_FMT */
14854 if (ctx->insn_flags & ISA_MIPS32R6) {
14855 /* CLASS_FMT */
14856 switch (fmt) {
14857 case FMT_SDPS_S:
14858 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14859 break;
14860 case FMT_SDPS_D:
14861 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14862 break;
14863 default:
14864 goto pool32f_invalid;
14865 }
14866 } else {
14867 /* MOVT_FMT */
14868 switch (fmt) {
14869 case FMT_SDPS_S:
14870 gen_movcf_s(ctx, rs, rt, cc, 1);
14871 break;
14872 case FMT_SDPS_D:
14873 gen_movcf_d(ctx, rs, rt, cc, 1);
14874 break;
14875 case FMT_SDPS_PS:
14876 check_ps(ctx);
14877 gen_movcf_ps(ctx, rs, rt, cc, 1);
14878 break;
14879 default:
14880 goto pool32f_invalid;
14881 }
3c824109
NF
14882 }
14883 break;
14884 case PREFX:
9e8f441a 14885 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14886 break;
14887 default:
14888 goto pool32f_invalid;
14889 }
14890 break;
14891#define FINSN_3ARG_SDPS(prfx) \
14892 switch ((ctx->opcode >> 8) & 0x3) { \
14893 case FMT_SDPS_S: \
14894 mips32_op = OPC_##prfx##_S; \
14895 goto do_fpop; \
14896 case FMT_SDPS_D: \
14897 mips32_op = OPC_##prfx##_D; \
14898 goto do_fpop; \
14899 case FMT_SDPS_PS: \
e29c9628 14900 check_ps(ctx); \
3c824109
NF
14901 mips32_op = OPC_##prfx##_PS; \
14902 goto do_fpop; \
14903 default: \
14904 goto pool32f_invalid; \
14905 }
2a24a7ba
YK
14906 case MINA_FMT:
14907 check_insn(ctx, ISA_MIPS32R6);
14908 switch ((ctx->opcode >> 9) & 0x3) {
14909 case FMT_SDPS_S:
14910 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14911 break;
14912 case FMT_SDPS_D:
14913 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14914 break;
14915 default:
14916 goto pool32f_invalid;
14917 }
14918 break;
14919 case MAXA_FMT:
14920 check_insn(ctx, ISA_MIPS32R6);
14921 switch ((ctx->opcode >> 9) & 0x3) {
14922 case FMT_SDPS_S:
14923 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14924 break;
14925 case FMT_SDPS_D:
14926 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14927 break;
14928 default:
14929 goto pool32f_invalid;
14930 }
14931 break;
3c824109
NF
14932 case 0x30:
14933 /* regular FP ops */
14934 switch ((ctx->opcode >> 6) & 0x3) {
14935 case ADD_FMT:
14936 FINSN_3ARG_SDPS(ADD);
14937 break;
14938 case SUB_FMT:
14939 FINSN_3ARG_SDPS(SUB);
14940 break;
14941 case MUL_FMT:
14942 FINSN_3ARG_SDPS(MUL);
14943 break;
14944 case DIV_FMT:
14945 fmt = (ctx->opcode >> 8) & 0x3;
14946 if (fmt == 1) {
14947 mips32_op = OPC_DIV_D;
14948 } else if (fmt == 0) {
14949 mips32_op = OPC_DIV_S;
14950 } else {
14951 goto pool32f_invalid;
14952 }
14953 goto do_fpop;
14954 default:
14955 goto pool32f_invalid;
14956 }
14957 break;
14958 case 0x38:
14959 /* cmovs */
2a24a7ba
YK
14960 switch ((ctx->opcode >> 6) & 0x7) {
14961 case MOVN_FMT: /* SELNEZ_FMT */
14962 if (ctx->insn_flags & ISA_MIPS32R6) {
14963 /* SELNEZ_FMT */
14964 switch ((ctx->opcode >> 9) & 0x3) {
14965 case FMT_SDPS_S:
14966 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
14967 break;
14968 case FMT_SDPS_D:
14969 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
14970 break;
14971 default:
14972 goto pool32f_invalid;
14973 }
14974 } else {
14975 /* MOVN_FMT */
14976 FINSN_3ARG_SDPS(MOVN);
14977 }
14978 break;
14979 case MOVN_FMT_04:
14980 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
14981 FINSN_3ARG_SDPS(MOVN);
14982 break;
2a24a7ba
YK
14983 case MOVZ_FMT: /* SELEQZ_FMT */
14984 if (ctx->insn_flags & ISA_MIPS32R6) {
14985 /* SELEQZ_FMT */
14986 switch ((ctx->opcode >> 9) & 0x3) {
14987 case FMT_SDPS_S:
14988 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
14989 break;
14990 case FMT_SDPS_D:
14991 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
14992 break;
14993 default:
14994 goto pool32f_invalid;
14995 }
14996 } else {
14997 /* MOVZ_FMT */
14998 FINSN_3ARG_SDPS(MOVZ);
14999 }
15000 break;
15001 case MOVZ_FMT_05:
15002 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15003 FINSN_3ARG_SDPS(MOVZ);
15004 break;
2a24a7ba
YK
15005 case SEL_FMT:
15006 check_insn(ctx, ISA_MIPS32R6);
15007 switch ((ctx->opcode >> 9) & 0x3) {
15008 case FMT_SDPS_S:
15009 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
15010 break;
15011 case FMT_SDPS_D:
15012 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
15013 break;
15014 default:
15015 goto pool32f_invalid;
15016 }
15017 break;
15018 case MADDF_FMT:
15019 check_insn(ctx, ISA_MIPS32R6);
15020 switch ((ctx->opcode >> 9) & 0x3) {
15021 case FMT_SDPS_S:
15022 mips32_op = OPC_MADDF_S;
15023 goto do_fpop;
15024 case FMT_SDPS_D:
15025 mips32_op = OPC_MADDF_D;
15026 goto do_fpop;
15027 default:
15028 goto pool32f_invalid;
15029 }
15030 break;
15031 case MSUBF_FMT:
15032 check_insn(ctx, ISA_MIPS32R6);
15033 switch ((ctx->opcode >> 9) & 0x3) {
15034 case FMT_SDPS_S:
15035 mips32_op = OPC_MSUBF_S;
15036 goto do_fpop;
15037 case FMT_SDPS_D:
15038 mips32_op = OPC_MSUBF_D;
15039 goto do_fpop;
15040 default:
15041 goto pool32f_invalid;
15042 }
15043 break;
3c824109
NF
15044 default:
15045 goto pool32f_invalid;
15046 }
15047 break;
15048 do_fpop:
15049 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15050 break;
15051 default:
15052 pool32f_invalid:
15053 MIPS_INVAL("pool32f");
9c708c7f 15054 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15055 break;
15056 }
15057 } else {
15058 generate_exception_err(ctx, EXCP_CpU, 1);
15059 }
15060 break;
15061 case POOL32I:
15062 minor = (ctx->opcode >> 21) & 0x1f;
15063 switch (minor) {
15064 case BLTZ:
9e8f441a 15065 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15066 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
15067 break;
3c824109 15068 case BLTZAL:
9e8f441a 15069 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15070 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
15071 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15072 break;
3c824109 15073 case BLTZALS:
9e8f441a 15074 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15075 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
15076 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15077 break;
3c824109 15078 case BGEZ:
9e8f441a 15079 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15080 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
15081 break;
3c824109 15082 case BGEZAL:
9e8f441a 15083 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15084 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
15085 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15086 break;
3c824109 15087 case BGEZALS:
9e8f441a 15088 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15089 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
15090 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15091 break;
3c824109 15092 case BLEZ:
9e8f441a 15093 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103
YK
15094 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
15095 break;
3c824109 15096 case BGTZ:
9e8f441a 15097 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b231c103 15098 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
3c824109
NF
15099 break;
15100
15101 /* Traps */
65935f07
YK
15102 case TLTI: /* BC1EQZC */
15103 if (ctx->insn_flags & ISA_MIPS32R6) {
15104 /* BC1EQZC */
15105 check_cp1_enabled(ctx);
15106 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
15107 } else {
15108 /* TLTI */
15109 mips32_op = OPC_TLTI;
15110 goto do_trapi;
15111 }
15112 break;
15113 case TGEI: /* BC1NEZC */
15114 if (ctx->insn_flags & ISA_MIPS32R6) {
15115 /* BC1NEZC */
15116 check_cp1_enabled(ctx);
15117 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
15118 } else {
15119 /* TGEI */
15120 mips32_op = OPC_TGEI;
15121 goto do_trapi;
15122 }
15123 break;
3c824109 15124 case TLTIU:
9e8f441a 15125 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15126 mips32_op = OPC_TLTIU;
15127 goto do_trapi;
15128 case TGEIU:
9e8f441a 15129 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15130 mips32_op = OPC_TGEIU;
15131 goto do_trapi;
3b4a5489
YK
15132 case TNEI: /* SYNCI */
15133 if (ctx->insn_flags & ISA_MIPS32R6) {
15134 /* SYNCI */
15135 /* Break the TB to be able to sync copied instructions
15136 immediately */
eeb3bba8 15137 ctx->base.is_jmp = DISAS_STOP;
3b4a5489
YK
15138 } else {
15139 /* TNEI */
15140 mips32_op = OPC_TNEI;
15141 goto do_trapi;
15142 }
15143 break;
3c824109 15144 case TEQI:
9e8f441a 15145 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15146 mips32_op = OPC_TEQI;
15147 do_trapi:
15148 gen_trap(ctx, mips32_op, rs, -1, imm);
15149 break;
15150
15151 case BNEZC:
15152 case BEQZC:
9e8f441a 15153 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15154 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
b231c103 15155 4, rs, 0, imm << 1, 0);
3c824109
NF
15156 /* Compact branches don't have a delay slot, so just let
15157 the normal delay slot handling take us to the branch
15158 target. */
15159 break;
15160 case LUI:
9e8f441a 15161 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5e88759a 15162 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
3c824109
NF
15163 break;
15164 case SYNCI:
9e8f441a 15165 check_insn_opc_removed(ctx, ISA_MIPS32R6);
a83bddd6
DZ
15166 /* Break the TB to be able to sync copied instructions
15167 immediately */
eeb3bba8 15168 ctx->base.is_jmp = DISAS_STOP;
3c824109
NF
15169 break;
15170 case BC2F:
15171 case BC2T:
9e8f441a 15172 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15173 /* COP2: Not implemented. */
15174 generate_exception_err(ctx, EXCP_CpU, 2);
15175 break;
15176 case BC1F:
9e8f441a 15177 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15178 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
15179 goto do_cp1branch;
15180 case BC1T:
9e8f441a 15181 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15182 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
15183 goto do_cp1branch;
15184 case BC1ANY4F:
9e8f441a 15185 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15186 mips32_op = OPC_BC1FANY4;
15187 goto do_cp1mips3d;
15188 case BC1ANY4T:
9e8f441a 15189 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109
NF
15190 mips32_op = OPC_BC1TANY4;
15191 do_cp1mips3d:
15192 check_cop1x(ctx);
d75c135e 15193 check_insn(ctx, ASE_MIPS3D);
3c824109
NF
15194 /* Fall through */
15195 do_cp1branch:
272f458d
MR
15196 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
15197 check_cp1_enabled(ctx);
15198 gen_compute_branch1(ctx, mips32_op,
15199 (ctx->opcode >> 18) & 0x7, imm << 1);
15200 } else {
15201 generate_exception_err(ctx, EXCP_CpU, 1);
15202 }
3c824109
NF
15203 break;
15204 case BPOSGE64:
15205 case BPOSGE32:
15206 /* MIPS DSP: not implemented */
15207 /* Fall through */
15208 default:
15209 MIPS_INVAL("pool32i");
9c708c7f 15210 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15211 break;
15212 }
15213 break;
15214 case POOL32C:
15215 minor = (ctx->opcode >> 12) & 0xf;
3b4a5489
YK
15216 offset = sextract32(ctx->opcode, 0,
15217 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
3c824109
NF
15218 switch (minor) {
15219 case LWL:
9e8f441a 15220 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15221 mips32_op = OPC_LWL;
5c13fdfd 15222 goto do_ld_lr;
3c824109 15223 case SWL:
9e8f441a 15224 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15225 mips32_op = OPC_SWL;
5c13fdfd 15226 goto do_st_lr;
3c824109 15227 case LWR:
9e8f441a 15228 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15229 mips32_op = OPC_LWR;
5c13fdfd 15230 goto do_ld_lr;
3c824109 15231 case SWR:
9e8f441a 15232 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15233 mips32_op = OPC_SWR;
5c13fdfd 15234 goto do_st_lr;
3c824109
NF
15235#if defined(TARGET_MIPS64)
15236 case LDL:
d9224450
MR
15237 check_insn(ctx, ISA_MIPS3);
15238 check_mips_64(ctx);
9e8f441a 15239 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15240 mips32_op = OPC_LDL;
5c13fdfd 15241 goto do_ld_lr;
3c824109 15242 case SDL:
d9224450
MR
15243 check_insn(ctx, ISA_MIPS3);
15244 check_mips_64(ctx);
9e8f441a 15245 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15246 mips32_op = OPC_SDL;
5c13fdfd 15247 goto do_st_lr;
3c824109 15248 case LDR:
d9224450
MR
15249 check_insn(ctx, ISA_MIPS3);
15250 check_mips_64(ctx);
9e8f441a 15251 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15252 mips32_op = OPC_LDR;
5c13fdfd 15253 goto do_ld_lr;
3c824109 15254 case SDR:
d9224450
MR
15255 check_insn(ctx, ISA_MIPS3);
15256 check_mips_64(ctx);
9e8f441a 15257 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15258 mips32_op = OPC_SDR;
5c13fdfd 15259 goto do_st_lr;
3c824109 15260 case LWU:
d9224450
MR
15261 check_insn(ctx, ISA_MIPS3);
15262 check_mips_64(ctx);
3c824109 15263 mips32_op = OPC_LWU;
5c13fdfd 15264 goto do_ld_lr;
3c824109 15265 case LLD:
d9224450
MR
15266 check_insn(ctx, ISA_MIPS3);
15267 check_mips_64(ctx);
3c824109 15268 mips32_op = OPC_LLD;
5c13fdfd 15269 goto do_ld_lr;
3c824109
NF
15270#endif
15271 case LL:
15272 mips32_op = OPC_LL;
5c13fdfd
AJ
15273 goto do_ld_lr;
15274 do_ld_lr:
3b4a5489 15275 gen_ld(ctx, mips32_op, rt, rs, offset);
5c13fdfd
AJ
15276 break;
15277 do_st_lr:
8fffc646 15278 gen_st(ctx, mips32_op, rt, rs, offset);
3c824109
NF
15279 break;
15280 case SC:
3b4a5489 15281 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
3c824109
NF
15282 break;
15283#if defined(TARGET_MIPS64)
15284 case SCD:
d9224450
MR
15285 check_insn(ctx, ISA_MIPS3);
15286 check_mips_64(ctx);
3b4a5489 15287 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
3c824109
NF
15288 break;
15289#endif
8fffc646
JH
15290 case LD_EVA:
15291 if (!ctx->eva) {
15292 MIPS_INVAL("pool32c ld-eva");
15293 generate_exception_end(ctx, EXCP_RI);
15294 break;
15295 }
15296 check_cp0_enabled(ctx);
15297
15298 minor2 = (ctx->opcode >> 9) & 0x7;
15299 offset = sextract32(ctx->opcode, 0, 9);
15300 switch (minor2) {
15301 case LBUE:
15302 mips32_op = OPC_LBUE;
15303 goto do_ld_lr;
15304 case LHUE:
15305 mips32_op = OPC_LHUE;
15306 goto do_ld_lr;
15307 case LWLE:
15308 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15309 mips32_op = OPC_LWLE;
15310 goto do_ld_lr;
15311 case LWRE:
15312 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15313 mips32_op = OPC_LWRE;
15314 goto do_ld_lr;
15315 case LBE:
15316 mips32_op = OPC_LBE;
15317 goto do_ld_lr;
15318 case LHE:
15319 mips32_op = OPC_LHE;
15320 goto do_ld_lr;
15321 case LLE:
15322 mips32_op = OPC_LLE;
15323 goto do_ld_lr;
15324 case LWE:
15325 mips32_op = OPC_LWE;
15326 goto do_ld_lr;
15327 };
15328 break;
15329 case ST_EVA:
15330 if (!ctx->eva) {
15331 MIPS_INVAL("pool32c st-eva");
15332 generate_exception_end(ctx, EXCP_RI);
15333 break;
15334 }
15335 check_cp0_enabled(ctx);
15336
15337 minor2 = (ctx->opcode >> 9) & 0x7;
15338 offset = sextract32(ctx->opcode, 0, 9);
15339 switch (minor2) {
15340 case SWLE:
15341 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15342 mips32_op = OPC_SWLE;
15343 goto do_st_lr;
15344 case SWRE:
15345 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15346 mips32_op = OPC_SWRE;
15347 goto do_st_lr;
15348 case PREFE:
15349 /* Treat as no-op */
15350 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
15351 /* hint codes 24-31 are reserved and signal RI */
15352 generate_exception(ctx, EXCP_RI);
15353 }
15354 break;
15355 case CACHEE:
15356 /* Treat as no-op */
15357 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15358 gen_cache_operation(ctx, rt, rs, offset);
15359 }
15360 break;
15361 case SBE:
15362 mips32_op = OPC_SBE;
15363 goto do_st_lr;
15364 case SHE:
15365 mips32_op = OPC_SHE;
15366 goto do_st_lr;
15367 case SCE:
15368 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
15369 break;
15370 case SWE:
15371 mips32_op = OPC_SWE;
15372 goto do_st_lr;
15373 };
15374 break;
3c824109
NF
15375 case PREF:
15376 /* Treat as no-op */
3b4a5489
YK
15377 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
15378 /* hint codes 24-31 are reserved and signal RI */
15379 generate_exception(ctx, EXCP_RI);
15380 }
3c824109
NF
15381 break;
15382 default:
15383 MIPS_INVAL("pool32c");
9c708c7f 15384 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15385 break;
15386 }
15387 break;
ab39ee45
YK
15388 case ADDI32: /* AUI, LUI */
15389 if (ctx->insn_flags & ISA_MIPS32R6) {
15390 /* AUI, LUI */
15391 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
15392 } else {
15393 /* ADDI32 */
15394 mips32_op = OPC_ADDI;
15395 goto do_addi;
15396 }
15397 break;
3c824109
NF
15398 case ADDIU32:
15399 mips32_op = OPC_ADDIU;
15400 do_addi:
d75c135e 15401 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
15402 break;
15403
15404 /* Logical operations */
15405 case ORI32:
15406 mips32_op = OPC_ORI;
15407 goto do_logici;
15408 case XORI32:
15409 mips32_op = OPC_XORI;
15410 goto do_logici;
15411 case ANDI32:
15412 mips32_op = OPC_ANDI;
15413 do_logici:
d75c135e 15414 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
15415 break;
15416
15417 /* Set less than immediate */
15418 case SLTI32:
15419 mips32_op = OPC_SLTI;
15420 goto do_slti;
15421 case SLTIU32:
15422 mips32_op = OPC_SLTIU;
15423 do_slti:
d75c135e 15424 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
3c824109
NF
15425 break;
15426 case JALX32:
9e8f441a 15427 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15428 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103
YK
15429 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
15430 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
3c824109 15431 break;
65935f07
YK
15432 case JALS32: /* BOVC, BEQC, BEQZALC */
15433 if (ctx->insn_flags & ISA_MIPS32R6) {
15434 if (rs >= rt) {
15435 /* BOVC */
15436 mips32_op = OPC_BOVC;
15437 } else if (rs < rt && rs == 0) {
15438 /* BEQZALC */
15439 mips32_op = OPC_BEQZALC;
15440 } else {
15441 /* BEQC */
15442 mips32_op = OPC_BEQC;
15443 }
15444 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15445 } else {
15446 /* JALS32 */
15447 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
15448 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
15449 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15450 }
3c824109 15451 break;
65935f07
YK
15452 case BEQ32: /* BC */
15453 if (ctx->insn_flags & ISA_MIPS32R6) {
15454 /* BC */
15455 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
15456 sextract32(ctx->opcode << 1, 0, 27));
15457 } else {
15458 /* BEQ32 */
15459 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
15460 }
3c824109 15461 break;
65935f07
YK
15462 case BNE32: /* BALC */
15463 if (ctx->insn_flags & ISA_MIPS32R6) {
15464 /* BALC */
15465 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
15466 sextract32(ctx->opcode << 1, 0, 27));
15467 } else {
15468 /* BNE32 */
15469 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
15470 }
3c824109 15471 break;
65935f07
YK
15472 case J32: /* BGTZC, BLTZC, BLTC */
15473 if (ctx->insn_flags & ISA_MIPS32R6) {
15474 if (rs == 0 && rt != 0) {
15475 /* BGTZC */
15476 mips32_op = OPC_BGTZC;
15477 } else if (rs != 0 && rt != 0 && rs == rt) {
15478 /* BLTZC */
15479 mips32_op = OPC_BLTZC;
15480 } else {
15481 /* BLTC */
15482 mips32_op = OPC_BLTC;
15483 }
15484 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15485 } else {
15486 /* J32 */
15487 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
15488 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15489 }
3c824109 15490 break;
65935f07
YK
15491 case JAL32: /* BLEZC, BGEZC, BGEC */
15492 if (ctx->insn_flags & ISA_MIPS32R6) {
15493 if (rs == 0 && rt != 0) {
15494 /* BLEZC */
15495 mips32_op = OPC_BLEZC;
15496 } else if (rs != 0 && rt != 0 && rs == rt) {
15497 /* BGEZC */
15498 mips32_op = OPC_BGEZC;
15499 } else {
15500 /* BGEC */
15501 mips32_op = OPC_BGEC;
15502 }
15503 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15504 } else {
15505 /* JAL32 */
15506 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
15507 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15508 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15509 }
3c824109
NF
15510 break;
15511 /* Floating point (COP1) */
15512 case LWC132:
15513 mips32_op = OPC_LWC1;
15514 goto do_cop1;
15515 case LDC132:
15516 mips32_op = OPC_LDC1;
15517 goto do_cop1;
15518 case SWC132:
15519 mips32_op = OPC_SWC1;
15520 goto do_cop1;
15521 case SDC132:
15522 mips32_op = OPC_SDC1;
15523 do_cop1:
5ab5c041 15524 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
3c824109 15525 break;
ab39ee45
YK
15526 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15527 if (ctx->insn_flags & ISA_MIPS32R6) {
15528 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15529 switch ((ctx->opcode >> 16) & 0x1f) {
c38a1d52
AR
15530 case ADDIUPC_00:
15531 case ADDIUPC_01:
15532 case ADDIUPC_02:
15533 case ADDIUPC_03:
15534 case ADDIUPC_04:
15535 case ADDIUPC_05:
15536 case ADDIUPC_06:
15537 case ADDIUPC_07:
eeb3bba8 15538 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
15539 break;
15540 case AUIPC:
eeb3bba8 15541 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
ab39ee45
YK
15542 break;
15543 case ALUIPC:
eeb3bba8 15544 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
ab39ee45 15545 break;
c38a1d52
AR
15546 case LWPC_08:
15547 case LWPC_09:
15548 case LWPC_0A:
15549 case LWPC_0B:
15550 case LWPC_0C:
15551 case LWPC_0D:
15552 case LWPC_0E:
15553 case LWPC_0F:
eeb3bba8 15554 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
ab39ee45
YK
15555 break;
15556 default:
15557 generate_exception(ctx, EXCP_RI);
15558 break;
15559 }
15560 } else {
15561 /* ADDIUPC */
3c824109 15562 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
e1555d7d 15563 offset = SIMM(ctx->opcode, 0, 23) << 2;
3c824109
NF
15564
15565 gen_addiupc(ctx, reg, offset, 0, 0);
15566 }
15567 break;
65935f07
YK
15568 case BNVC: /* BNEC, BNEZALC */
15569 check_insn(ctx, ISA_MIPS32R6);
15570 if (rs >= rt) {
15571 /* BNVC */
15572 mips32_op = OPC_BNVC;
15573 } else if (rs < rt && rs == 0) {
15574 /* BNEZALC */
15575 mips32_op = OPC_BNEZALC;
15576 } else {
15577 /* BNEC */
15578 mips32_op = OPC_BNEC;
15579 }
15580 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15581 break;
15582 case R6_BNEZC: /* JIALC */
15583 check_insn(ctx, ISA_MIPS32R6);
15584 if (rt != 0) {
15585 /* BNEZC */
15586 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
15587 sextract32(ctx->opcode << 1, 0, 22));
15588 } else {
15589 /* JIALC */
15590 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
15591 }
15592 break;
15593 case R6_BEQZC: /* JIC */
15594 check_insn(ctx, ISA_MIPS32R6);
15595 if (rt != 0) {
15596 /* BEQZC */
15597 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
15598 sextract32(ctx->opcode << 1, 0, 22));
15599 } else {
15600 /* JIC */
15601 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
15602 }
15603 break;
15604 case BLEZALC: /* BGEZALC, BGEUC */
15605 check_insn(ctx, ISA_MIPS32R6);
15606 if (rs == 0 && rt != 0) {
15607 /* BLEZALC */
15608 mips32_op = OPC_BLEZALC;
15609 } else if (rs != 0 && rt != 0 && rs == rt) {
15610 /* BGEZALC */
15611 mips32_op = OPC_BGEZALC;
15612 } else {
15613 /* BGEUC */
15614 mips32_op = OPC_BGEUC;
15615 }
15616 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15617 break;
15618 case BGTZALC: /* BLTZALC, BLTUC */
15619 check_insn(ctx, ISA_MIPS32R6);
15620 if (rs == 0 && rt != 0) {
15621 /* BGTZALC */
15622 mips32_op = OPC_BGTZALC;
15623 } else if (rs != 0 && rt != 0 && rs == rt) {
15624 /* BLTZALC */
15625 mips32_op = OPC_BLTZALC;
15626 } else {
15627 /* BLTUC */
15628 mips32_op = OPC_BLTUC;
15629 }
15630 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15631 break;
3c824109
NF
15632 /* Loads and stores */
15633 case LB32:
15634 mips32_op = OPC_LB;
5c13fdfd 15635 goto do_ld;
3c824109
NF
15636 case LBU32:
15637 mips32_op = OPC_LBU;
5c13fdfd 15638 goto do_ld;
3c824109
NF
15639 case LH32:
15640 mips32_op = OPC_LH;
5c13fdfd 15641 goto do_ld;
3c824109
NF
15642 case LHU32:
15643 mips32_op = OPC_LHU;
5c13fdfd 15644 goto do_ld;
3c824109
NF
15645 case LW32:
15646 mips32_op = OPC_LW;
5c13fdfd 15647 goto do_ld;
3c824109
NF
15648#ifdef TARGET_MIPS64
15649 case LD32:
d9224450
MR
15650 check_insn(ctx, ISA_MIPS3);
15651 check_mips_64(ctx);
3c824109 15652 mips32_op = OPC_LD;
5c13fdfd 15653 goto do_ld;
3c824109 15654 case SD32:
d9224450
MR
15655 check_insn(ctx, ISA_MIPS3);
15656 check_mips_64(ctx);
3c824109 15657 mips32_op = OPC_SD;
5c13fdfd 15658 goto do_st;
3c824109
NF
15659#endif
15660 case SB32:
15661 mips32_op = OPC_SB;
5c13fdfd 15662 goto do_st;
3c824109
NF
15663 case SH32:
15664 mips32_op = OPC_SH;
5c13fdfd 15665 goto do_st;
3c824109
NF
15666 case SW32:
15667 mips32_op = OPC_SW;
5c13fdfd
AJ
15668 goto do_st;
15669 do_ld:
d75c135e 15670 gen_ld(ctx, mips32_op, rt, rs, imm);
5c13fdfd
AJ
15671 break;
15672 do_st:
15673 gen_st(ctx, mips32_op, rt, rs, imm);
3c824109
NF
15674 break;
15675 default:
9c708c7f 15676 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15677 break;
15678 }
15679}
15680
240ce26a 15681static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
3c824109
NF
15682{
15683 uint32_t op;
15684
15685 /* make sure instructions are on a halfword boundary */
eeb3bba8
EC
15686 if (ctx->base.pc_next & 0x1) {
15687 env->CP0_BadVAddr = ctx->base.pc_next;
9c708c7f 15688 generate_exception_end(ctx, EXCP_AdEL);
3c824109
NF
15689 return 2;
15690 }
15691
15692 op = (ctx->opcode >> 10) & 0x3f;
15693 /* Enforce properly-sized instructions in a delay slot */
b231c103
YK
15694 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
15695 switch (op & 0x7) { /* MSB-3..MSB-5 */
15696 case 0:
15697 /* POOL32A, POOL32B, POOL32I, POOL32C */
15698 case 4:
15699 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
15700 case 5:
15701 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
15702 case 6:
15703 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
15704 case 7:
15705 /* LB32, LH32, LWC132, LDC132, LW32 */
15706 if (ctx->hflags & MIPS_HFLAG_BDS16) {
9c708c7f 15707 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15708 return 2;
15709 }
15710 break;
b231c103
YK
15711 case 1:
15712 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
15713 case 2:
15714 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
15715 case 3:
15716 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
15717 if (ctx->hflags & MIPS_HFLAG_BDS32) {
9c708c7f 15718 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15719 return 2;
15720 }
15721 break;
3c824109
NF
15722 }
15723 }
b231c103 15724
3c824109
NF
15725 switch (op) {
15726 case POOL16A:
15727 {
15728 int rd = mmreg(uMIPS_RD(ctx->opcode));
15729 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
15730 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
15731 uint32_t opc = 0;
15732
15733 switch (ctx->opcode & 0x1) {
15734 case ADDU16:
15735 opc = OPC_ADDU;
15736 break;
15737 case SUBU16:
15738 opc = OPC_SUBU;
15739 break;
15740 }
ed7ce6c0
YK
15741 if (ctx->insn_flags & ISA_MIPS32R6) {
15742 /* In the Release 6 the register number location in
15743 * the instruction encoding has changed.
15744 */
15745 gen_arith(ctx, opc, rs1, rd, rs2);
15746 } else {
15747 gen_arith(ctx, opc, rd, rs1, rs2);
15748 }
3c824109
NF
15749 }
15750 break;
15751 case POOL16B:
15752 {
15753 int rd = mmreg(uMIPS_RD(ctx->opcode));
15754 int rs = mmreg(uMIPS_RS(ctx->opcode));
15755 int amount = (ctx->opcode >> 1) & 0x7;
15756 uint32_t opc = 0;
15757 amount = amount == 0 ? 8 : amount;
15758
15759 switch (ctx->opcode & 0x1) {
15760 case SLL16:
15761 opc = OPC_SLL;
15762 break;
15763 case SRL16:
15764 opc = OPC_SRL;
15765 break;
15766 }
15767
d75c135e 15768 gen_shift_imm(ctx, opc, rd, rs, amount);
3c824109
NF
15769 }
15770 break;
15771 case POOL16C:
ed7ce6c0
YK
15772 if (ctx->insn_flags & ISA_MIPS32R6) {
15773 gen_pool16c_r6_insn(ctx);
15774 } else {
15775 gen_pool16c_insn(ctx);
15776 }
3c824109
NF
15777 break;
15778 case LWGP16:
15779 {
15780 int rd = mmreg(uMIPS_RD(ctx->opcode));
15781 int rb = 28; /* GP */
15782 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
15783
d75c135e 15784 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
15785 }
15786 break;
15787 case POOL16F:
9e8f441a 15788 check_insn_opc_removed(ctx, ISA_MIPS32R6);
3c824109 15789 if (ctx->opcode & 1) {
9c708c7f 15790 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15791 } else {
15792 /* MOVEP */
15793 int enc_dest = uMIPS_RD(ctx->opcode);
15794 int enc_rt = uMIPS_RS2(ctx->opcode);
15795 int enc_rs = uMIPS_RS1(ctx->opcode);
ed7ce6c0 15796 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
3c824109
NF
15797 }
15798 break;
15799 case LBU16:
15800 {
15801 int rd = mmreg(uMIPS_RD(ctx->opcode));
15802 int rb = mmreg(uMIPS_RS(ctx->opcode));
15803 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15804 offset = (offset == 0xf ? -1 : offset);
15805
d75c135e 15806 gen_ld(ctx, OPC_LBU, rd, rb, offset);
3c824109
NF
15807 }
15808 break;
15809 case LHU16:
15810 {
15811 int rd = mmreg(uMIPS_RD(ctx->opcode));
15812 int rb = mmreg(uMIPS_RS(ctx->opcode));
15813 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15814
d75c135e 15815 gen_ld(ctx, OPC_LHU, rd, rb, offset);
3c824109
NF
15816 }
15817 break;
15818 case LWSP16:
15819 {
15820 int rd = (ctx->opcode >> 5) & 0x1f;
15821 int rb = 29; /* SP */
15822 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15823
d75c135e 15824 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
15825 }
15826 break;
15827 case LW16:
15828 {
15829 int rd = mmreg(uMIPS_RD(ctx->opcode));
15830 int rb = mmreg(uMIPS_RS(ctx->opcode));
15831 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15832
d75c135e 15833 gen_ld(ctx, OPC_LW, rd, rb, offset);
3c824109
NF
15834 }
15835 break;
15836 case SB16:
15837 {
15838 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15839 int rb = mmreg(uMIPS_RS(ctx->opcode));
15840 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15841
5c13fdfd 15842 gen_st(ctx, OPC_SB, rd, rb, offset);
3c824109
NF
15843 }
15844 break;
15845 case SH16:
15846 {
15847 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15848 int rb = mmreg(uMIPS_RS(ctx->opcode));
15849 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15850
5c13fdfd 15851 gen_st(ctx, OPC_SH, rd, rb, offset);
3c824109
NF
15852 }
15853 break;
15854 case SWSP16:
15855 {
15856 int rd = (ctx->opcode >> 5) & 0x1f;
15857 int rb = 29; /* SP */
15858 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15859
5c13fdfd 15860 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
15861 }
15862 break;
15863 case SW16:
15864 {
15865 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15866 int rb = mmreg(uMIPS_RS(ctx->opcode));
15867 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15868
5c13fdfd 15869 gen_st(ctx, OPC_SW, rd, rb, offset);
3c824109
NF
15870 }
15871 break;
15872 case MOVE16:
15873 {
15874 int rd = uMIPS_RD5(ctx->opcode);
15875 int rs = uMIPS_RS5(ctx->opcode);
15876
7215d7e7 15877 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
3c824109
NF
15878 }
15879 break;
15880 case ANDI16:
d75c135e 15881 gen_andi16(ctx);
3c824109
NF
15882 break;
15883 case POOL16D:
15884 switch (ctx->opcode & 0x1) {
15885 case ADDIUS5:
d75c135e 15886 gen_addius5(ctx);
3c824109
NF
15887 break;
15888 case ADDIUSP:
d75c135e 15889 gen_addiusp(ctx);
3c824109
NF
15890 break;
15891 }
15892 break;
15893 case POOL16E:
15894 switch (ctx->opcode & 0x1) {
15895 case ADDIUR2:
d75c135e 15896 gen_addiur2(ctx);
3c824109
NF
15897 break;
15898 case ADDIUR1SP:
d75c135e 15899 gen_addiur1sp(ctx);
3c824109
NF
15900 break;
15901 }
15902 break;
65935f07 15903 case B16: /* BC16 */
3c824109 15904 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
65935f07
YK
15905 sextract32(ctx->opcode, 0, 10) << 1,
15906 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
3c824109 15907 break;
65935f07
YK
15908 case BNEZ16: /* BNEZC16 */
15909 case BEQZ16: /* BEQZC16 */
3c824109
NF
15910 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
15911 mmreg(uMIPS_RD(ctx->opcode)),
65935f07
YK
15912 0, sextract32(ctx->opcode, 0, 7) << 1,
15913 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15914
3c824109
NF
15915 break;
15916 case LI16:
15917 {
15918 int reg = mmreg(uMIPS_RD(ctx->opcode));
15919 int imm = ZIMM(ctx->opcode, 0, 7);
15920
15921 imm = (imm == 0x7f ? -1 : imm);
15922 tcg_gen_movi_tl(cpu_gpr[reg], imm);
15923 }
15924 break;
3c824109 15925 case RES_29:
3c824109 15926 case RES_31:
3c824109 15927 case RES_39:
9c708c7f 15928 generate_exception_end(ctx, EXCP_RI);
3c824109
NF
15929 break;
15930 default:
f60eeb0c 15931 decode_micromips32_opc(env, ctx);
3c824109
NF
15932 return 4;
15933 }
15934
15935 return 2;
15936}
15937
261c95a0
YK
15938/*
15939 *
15940 * nanoMIPS opcodes
15941 *
15942 */
15943
15944/* MAJOR, P16, and P32 pools opcodes */
15945enum {
15946 NM_P_ADDIU = 0x00,
15947 NM_ADDIUPC = 0x01,
15948 NM_MOVE_BALC = 0x02,
15949 NM_P16_MV = 0x04,
15950 NM_LW16 = 0x05,
15951 NM_BC16 = 0x06,
15952 NM_P16_SR = 0x07,
15953
15954 NM_POOL32A = 0x08,
15955 NM_P_BAL = 0x0a,
15956 NM_P16_SHIFT = 0x0c,
15957 NM_LWSP16 = 0x0d,
15958 NM_BALC16 = 0x0e,
15959 NM_P16_4X4 = 0x0f,
15960
15961 NM_P_GP_W = 0x10,
15962 NM_P_GP_BH = 0x11,
15963 NM_P_J = 0x12,
15964 NM_P16C = 0x14,
15965 NM_LWGP16 = 0x15,
15966 NM_P16_LB = 0x17,
15967
15968 NM_P48I = 0x18,
15969 NM_P16_A1 = 0x1c,
15970 NM_LW4X4 = 0x1d,
15971 NM_P16_LH = 0x1f,
15972
15973 NM_P_U12 = 0x20,
15974 NM_P_LS_U12 = 0x21,
15975 NM_P_BR1 = 0x22,
15976 NM_P16_A2 = 0x24,
15977 NM_SW16 = 0x25,
15978 NM_BEQZC16 = 0x26,
15979
15980 NM_POOL32F = 0x28,
15981 NM_P_LS_S9 = 0x29,
15982 NM_P_BR2 = 0x2a,
15983
15984 NM_P16_ADDU = 0x2c,
15985 NM_SWSP16 = 0x2d,
15986 NM_BNEZC16 = 0x2e,
15987 NM_MOVEP = 0x2f,
15988
15989 NM_POOL32S = 0x30,
15990 NM_P_BRI = 0x32,
15991 NM_LI16 = 0x34,
15992 NM_SWGP16 = 0x35,
15993 NM_P16_BR = 0x36,
15994
15995 NM_P_LUI = 0x38,
15996 NM_ANDI16 = 0x3c,
15997 NM_SW4X4 = 0x3d,
15998 NM_MOVEPREV = 0x3f,
15999};
16000
16001/* POOL32A instruction pool */
16002enum {
16003 NM_POOL32A0 = 0x00,
16004 NM_SPECIAL2 = 0x01,
16005 NM_COP2_1 = 0x02,
16006 NM_UDI = 0x03,
16007 NM_POOL32A5 = 0x05,
16008 NM_POOL32A7 = 0x07,
16009};
16010
16011/* P.GP.W instruction pool */
16012enum {
16013 NM_ADDIUGP_W = 0x00,
16014 NM_LWGP = 0x02,
16015 NM_SWGP = 0x03,
16016};
16017
16018/* P48I instruction pool */
16019enum {
16020 NM_LI48 = 0x00,
16021 NM_ADDIU48 = 0x01,
16022 NM_ADDIUGP48 = 0x02,
16023 NM_ADDIUPC48 = 0x03,
16024 NM_LWPC48 = 0x0b,
16025 NM_SWPC48 = 0x0f,
16026};
16027
16028/* P.U12 instruction pool */
16029enum {
16030 NM_ORI = 0x00,
16031 NM_XORI = 0x01,
16032 NM_ANDI = 0x02,
16033 NM_P_SR = 0x03,
16034 NM_SLTI = 0x04,
16035 NM_SLTIU = 0x05,
16036 NM_SEQI = 0x06,
16037 NM_ADDIUNEG = 0x08,
16038 NM_P_SHIFT = 0x0c,
16039 NM_P_ROTX = 0x0d,
16040 NM_P_INS = 0x0e,
16041 NM_P_EXT = 0x0f,
16042};
16043
16044/* POOL32F instruction pool */
16045enum {
16046 NM_POOL32F_0 = 0x00,
16047 NM_POOL32F_3 = 0x03,
16048 NM_POOL32F_5 = 0x05,
16049};
16050
16051/* POOL32S instruction pool */
16052enum {
16053 NM_POOL32S_0 = 0x00,
16054 NM_POOL32S_4 = 0x04,
16055};
16056
16057/* P.LUI instruction pool */
16058enum {
16059 NM_LUI = 0x00,
16060 NM_ALUIPC = 0x01,
16061};
16062
16063/* P.GP.BH instruction pool */
16064enum {
16065 NM_LBGP = 0x00,
16066 NM_SBGP = 0x01,
16067 NM_LBUGP = 0x02,
16068 NM_ADDIUGP_B = 0x03,
16069 NM_P_GP_LH = 0x04,
16070 NM_P_GP_SH = 0x05,
16071 NM_P_GP_CP1 = 0x06,
16072};
16073
16074/* P.LS.U12 instruction pool */
16075enum {
16076 NM_LB = 0x00,
16077 NM_SB = 0x01,
16078 NM_LBU = 0x02,
16079 NM_P_PREFU12 = 0x03,
16080 NM_LH = 0x04,
16081 NM_SH = 0x05,
16082 NM_LHU = 0x06,
16083 NM_LWU = 0x07,
16084 NM_LW = 0x08,
16085 NM_SW = 0x09,
16086 NM_LWC1 = 0x0a,
16087 NM_SWC1 = 0x0b,
16088 NM_LDC1 = 0x0e,
16089 NM_SDC1 = 0x0f,
16090};
16091
16092/* P.LS.S9 instruction pool */
16093enum {
16094 NM_P_LS_S0 = 0x00,
16095 NM_P_LS_S1 = 0x01,
16096 NM_P_LS_E0 = 0x02,
16097 NM_P_LS_WM = 0x04,
16098 NM_P_LS_UAWM = 0x05,
16099};
16100
16101/* P.BAL instruction pool */
16102enum {
16103 NM_BC = 0x00,
16104 NM_BALC = 0x01,
16105};
16106
16107/* P.J instruction pool */
16108enum {
16109 NM_JALRC = 0x00,
16110 NM_JALRC_HB = 0x01,
16111 NM_P_BALRSC = 0x08,
16112};
16113
16114/* P.BR1 instruction pool */
16115enum {
16116 NM_BEQC = 0x00,
16117 NM_P_BR3A = 0x01,
16118 NM_BGEC = 0x02,
16119 NM_BGEUC = 0x03,
16120};
16121
16122/* P.BR2 instruction pool */
16123enum {
16124 NM_BNEC = 0x00,
16125 NM_BLTC = 0x02,
16126 NM_BLTUC = 0x03,
16127};
16128
16129/* P.BRI instruction pool */
16130enum {
16131 NM_BEQIC = 0x00,
16132 NM_BBEQZC = 0x01,
16133 NM_BGEIC = 0x02,
16134 NM_BGEIUC = 0x03,
16135 NM_BNEIC = 0x04,
16136 NM_BBNEZC = 0x05,
16137 NM_BLTIC = 0x06,
16138 NM_BLTIUC = 0x07,
16139};
16140
16141/* P16.SHIFT instruction pool */
16142enum {
16143 NM_SLL16 = 0x00,
16144 NM_SRL16 = 0x01,
16145};
16146
16147/* POOL16C instruction pool */
16148enum {
16149 NM_POOL16C_0 = 0x00,
16150 NM_LWXS16 = 0x01,
16151};
16152
16153/* P16.A1 instruction pool */
16154enum {
16155 NM_ADDIUR1SP = 0x01,
16156};
16157
16158/* P16.A2 instruction pool */
16159enum {
16160 NM_ADDIUR2 = 0x00,
16161 NM_P_ADDIURS5 = 0x01,
16162};
16163
16164/* P16.ADDU instruction pool */
16165enum {
16166 NM_ADDU16 = 0x00,
16167 NM_SUBU16 = 0x01,
16168};
16169
16170/* P16.SR instruction pool */
16171enum {
16172 NM_SAVE16 = 0x00,
16173 NM_RESTORE_JRC16 = 0x01,
16174};
16175
16176/* P16.4X4 instruction pool */
16177enum {
16178 NM_ADDU4X4 = 0x00,
16179 NM_MUL4X4 = 0x01,
16180};
16181
16182/* P16.LB instruction pool */
16183enum {
16184 NM_LB16 = 0x00,
16185 NM_SB16 = 0x01,
16186 NM_LBU16 = 0x02,
16187};
16188
16189/* P16.LH instruction pool */
16190enum {
16191 NM_LH16 = 0x00,
16192 NM_SH16 = 0x01,
16193 NM_LHU16 = 0x02,
16194};
16195
16196/* P.RI instruction pool */
16197enum {
16198 NM_SIGRIE = 0x00,
16199 NM_P_SYSCALL = 0x01,
16200 NM_BREAK = 0x02,
16201 NM_SDBBP = 0x03,
16202};
16203
16204/* POOL32A0 instruction pool */
16205enum {
16206 NM_P_TRAP = 0x00,
16207 NM_SEB = 0x01,
16208 NM_SLLV = 0x02,
16209 NM_MUL = 0x03,
16210 NM_MFC0 = 0x06,
16211 NM_MFHC0 = 0x07,
16212 NM_SEH = 0x09,
16213 NM_SRLV = 0x0a,
16214 NM_MUH = 0x0b,
16215 NM_MTC0 = 0x0e,
16216 NM_MTHC0 = 0x0f,
16217 NM_SRAV = 0x12,
16218 NM_MULU = 0x13,
16219 NM_ROTRV = 0x1a,
16220 NM_MUHU = 0x1b,
16221 NM_ADD = 0x22,
16222 NM_DIV = 0x23,
16223 NM_ADDU = 0x2a,
16224 NM_MOD = 0x2b,
16225 NM_SUB = 0x32,
16226 NM_DIVU = 0x33,
16227 NM_RDHWR = 0x38,
16228 NM_SUBU = 0x3a,
16229 NM_MODU = 0x3b,
16230 NM_P_CMOVE = 0x42,
16231 NM_FORK = 0x45,
16232 NM_MFTR = 0x46,
16233 NM_MFHTR = 0x47,
16234 NM_AND = 0x4a,
16235 NM_YIELD = 0x4d,
16236 NM_MTTR = 0x4e,
16237 NM_MTHTR = 0x4f,
16238 NM_OR = 0x52,
16239 NM_D_E_MT_VPE = 0x56,
16240 NM_NOR = 0x5a,
16241 NM_XOR = 0x62,
16242 NM_SLT = 0x6a,
16243 NM_P_SLTU = 0x72,
16244 NM_SOV = 0x7a,
16245};
16246
b3979b6f
SM
16247/* POOL32A5 instruction pool */
16248enum {
16249 NM_CMP_EQ_PH = 0x00,
16250 NM_CMP_LT_PH = 0x08,
16251 NM_CMP_LE_PH = 0x10,
16252 NM_CMPGU_EQ_QB = 0x18,
16253 NM_CMPGU_LT_QB = 0x20,
16254 NM_CMPGU_LE_QB = 0x28,
16255 NM_CMPGDU_EQ_QB = 0x30,
16256 NM_CMPGDU_LT_QB = 0x38,
16257 NM_CMPGDU_LE_QB = 0x40,
16258 NM_CMPU_EQ_QB = 0x48,
16259 NM_CMPU_LT_QB = 0x50,
16260 NM_CMPU_LE_QB = 0x58,
16261 NM_ADDQ_S_W = 0x60,
16262 NM_SUBQ_S_W = 0x68,
16263 NM_ADDSC = 0x70,
16264 NM_ADDWC = 0x78,
16265
16266 NM_ADDQ_S_PH = 0x01,
16267 NM_ADDQH_R_PH = 0x09,
16268 NM_ADDQH_R_W = 0x11,
16269 NM_ADDU_S_QB = 0x19,
16270 NM_ADDU_S_PH = 0x21,
16271 NM_ADDUH_R_QB = 0x29,
16272 NM_SHRAV_R_PH = 0x31,
16273 NM_SHRAV_R_QB = 0x39,
16274 NM_SUBQ_S_PH = 0x41,
16275 NM_SUBQH_R_PH = 0x49,
16276 NM_SUBQH_R_W = 0x51,
16277 NM_SUBU_S_QB = 0x59,
16278 NM_SUBU_S_PH = 0x61,
16279 NM_SUBUH_R_QB = 0x69,
16280 NM_SHLLV_S_PH = 0x71,
16281 NM_PRECR_SRA_R_PH_W = 0x79,
16282
16283 NM_MULEU_S_PH_QBL = 0x12,
16284 NM_MULEU_S_PH_QBR = 0x1a,
16285 NM_MULQ_RS_PH = 0x22,
16286 NM_MULQ_S_PH = 0x2a,
16287 NM_MULQ_RS_W = 0x32,
16288 NM_MULQ_S_W = 0x3a,
16289 NM_APPEND = 0x42,
16290 NM_MODSUB = 0x52,
16291 NM_SHRAV_R_W = 0x5a,
16292 NM_SHRLV_PH = 0x62,
16293 NM_SHRLV_QB = 0x6a,
16294 NM_SHLLV_QB = 0x72,
16295 NM_SHLLV_S_W = 0x7a,
16296
16297 NM_SHILO = 0x03,
16298
16299 NM_MULEQ_S_W_PHL = 0x04,
16300 NM_MULEQ_S_W_PHR = 0x0c,
16301
16302 NM_MUL_S_PH = 0x05,
16303 NM_PRECR_QB_PH = 0x0d,
16304 NM_PRECRQ_QB_PH = 0x15,
16305 NM_PRECRQ_PH_W = 0x1d,
16306 NM_PRECRQ_RS_PH_W = 0x25,
16307 NM_PRECRQU_S_QB_PH = 0x2d,
16308 NM_PACKRL_PH = 0x35,
16309 NM_PICK_QB = 0x3d,
16310 NM_PICK_PH = 0x45,
16311
16312 NM_SHRA_R_W = 0x5e,
16313 NM_SHRA_R_PH = 0x66,
16314 NM_SHLL_S_PH = 0x76,
16315 NM_SHLL_S_W = 0x7e,
16316
16317 NM_REPL_PH = 0x07
16318};
16319
261c95a0
YK
16320/* POOL32A7 instruction pool */
16321enum {
16322 NM_P_LSX = 0x00,
16323 NM_LSA = 0x01,
16324 NM_EXTW = 0x03,
16325 NM_POOL32AXF = 0x07,
16326};
16327
16328/* P.SR instruction pool */
16329enum {
16330 NM_PP_SR = 0x00,
16331 NM_P_SR_F = 0x01,
16332};
16333
16334/* P.SHIFT instruction pool */
16335enum {
16336 NM_P_SLL = 0x00,
16337 NM_SRL = 0x02,
16338 NM_SRA = 0x04,
16339 NM_ROTR = 0x06,
16340};
16341
16342/* P.ROTX instruction pool */
16343enum {
16344 NM_ROTX = 0x00,
16345};
16346
16347/* P.INS instruction pool */
16348enum {
16349 NM_INS = 0x00,
16350};
16351
16352/* P.EXT instruction pool */
16353enum {
16354 NM_EXT = 0x00,
16355};
16356
16357/* POOL32F_0 (fmt) instruction pool */
16358enum {
16359 NM_RINT_S = 0x04,
16360 NM_RINT_D = 0x44,
16361 NM_ADD_S = 0x06,
16362 NM_SELEQZ_S = 0x07,
16363 NM_SELEQZ_D = 0x47,
16364 NM_CLASS_S = 0x0c,
16365 NM_CLASS_D = 0x4c,
16366 NM_SUB_S = 0x0e,
16367 NM_SELNEZ_S = 0x0f,
16368 NM_SELNEZ_D = 0x4f,
16369 NM_MUL_S = 0x16,
16370 NM_SEL_S = 0x17,
16371 NM_SEL_D = 0x57,
16372 NM_DIV_S = 0x1e,
16373 NM_ADD_D = 0x26,
16374 NM_SUB_D = 0x2e,
16375 NM_MUL_D = 0x36,
16376 NM_MADDF_S = 0x37,
16377 NM_MADDF_D = 0x77,
16378 NM_DIV_D = 0x3e,
16379 NM_MSUBF_S = 0x3f,
16380 NM_MSUBF_D = 0x7f,
16381};
16382
16383/* POOL32F_3 instruction pool */
16384enum {
16385 NM_MIN_FMT = 0x00,
16386 NM_MAX_FMT = 0x01,
16387 NM_MINA_FMT = 0x04,
16388 NM_MAXA_FMT = 0x05,
16389 NM_POOL32FXF = 0x07,
16390};
16391
16392/* POOL32F_5 instruction pool */
16393enum {
16394 NM_CMP_CONDN_S = 0x00,
16395 NM_CMP_CONDN_D = 0x02,
16396};
16397
16398/* P.GP.LH instruction pool */
16399enum {
16400 NM_LHGP = 0x00,
16401 NM_LHUGP = 0x01,
16402};
16403
16404/* P.GP.SH instruction pool */
16405enum {
16406 NM_SHGP = 0x00,
16407};
16408
16409/* P.GP.CP1 instruction pool */
16410enum {
16411 NM_LWC1GP = 0x00,
16412 NM_SWC1GP = 0x01,
16413 NM_LDC1GP = 0x02,
16414 NM_SDC1GP = 0x03,
16415};
16416
16417/* P.LS.S0 instruction pool */
16418enum {
16419 NM_LBS9 = 0x00,
16420 NM_LHS9 = 0x04,
16421 NM_LWS9 = 0x08,
16422 NM_LDS9 = 0x0c,
16423
16424 NM_SBS9 = 0x01,
16425 NM_SHS9 = 0x05,
16426 NM_SWS9 = 0x09,
16427 NM_SDS9 = 0x0d,
16428
16429 NM_LBUS9 = 0x02,
16430 NM_LHUS9 = 0x06,
16431 NM_LWC1S9 = 0x0a,
16432 NM_LDC1S9 = 0x0e,
16433
16434 NM_P_PREFS9 = 0x03,
16435 NM_LWUS9 = 0x07,
16436 NM_SWC1S9 = 0x0b,
16437 NM_SDC1S9 = 0x0f,
16438};
16439
16440/* P.LS.S1 instruction pool */
16441enum {
16442 NM_ASET_ACLR = 0x02,
16443 NM_UALH = 0x04,
16444 NM_UASH = 0x05,
16445 NM_CACHE = 0x07,
16446 NM_P_LL = 0x0a,
16447 NM_P_SC = 0x0b,
16448};
16449
16450/* P.LS.WM instruction pool */
16451enum {
16452 NM_LWM = 0x00,
16453 NM_SWM = 0x01,
16454};
16455
16456/* P.LS.UAWM instruction pool */
16457enum {
16458 NM_UALWM = 0x00,
16459 NM_UASWM = 0x01,
16460};
16461
16462/* P.BR3A instruction pool */
16463enum {
16464 NM_BC1EQZC = 0x00,
16465 NM_BC1NEZC = 0x01,
16466 NM_BC2EQZC = 0x02,
16467 NM_BC2NEZC = 0x03,
16468 NM_BPOSGE32C = 0x04,
16469};
16470
16471/* P16.RI instruction pool */
16472enum {
16473 NM_P16_SYSCALL = 0x01,
16474 NM_BREAK16 = 0x02,
16475 NM_SDBBP16 = 0x03,
16476};
16477
16478/* POOL16C_0 instruction pool */
16479enum {
16480 NM_POOL16C_00 = 0x00,
16481};
16482
16483/* P16.JRC instruction pool */
16484enum {
16485 NM_JRC = 0x00,
16486 NM_JALRC16 = 0x01,
16487};
16488
16489/* P.SYSCALL instruction pool */
16490enum {
16491 NM_SYSCALL = 0x00,
16492 NM_HYPCALL = 0x01,
16493};
16494
16495/* P.TRAP instruction pool */
16496enum {
16497 NM_TEQ = 0x00,
16498 NM_TNE = 0x01,
16499};
16500
16501/* P.CMOVE instruction pool */
16502enum {
16503 NM_MOVZ = 0x00,
16504 NM_MOVN = 0x01,
16505};
16506
16507/* POOL32Axf instruction pool */
16508enum {
b3979b6f
SM
16509 NM_POOL32AXF_1 = 0x01,
16510 NM_POOL32AXF_2 = 0x02,
261c95a0
YK
16511 NM_POOL32AXF_4 = 0x04,
16512 NM_POOL32AXF_5 = 0x05,
b3979b6f
SM
16513 NM_POOL32AXF_7 = 0x07,
16514};
16515
16516/* POOL32Axf_1 instruction pool */
16517enum {
16518 NM_POOL32AXF_1_0 = 0x00,
16519 NM_POOL32AXF_1_1 = 0x01,
16520 NM_POOL32AXF_1_3 = 0x03,
16521 NM_POOL32AXF_1_4 = 0x04,
16522 NM_POOL32AXF_1_5 = 0x05,
16523 NM_POOL32AXF_1_7 = 0x07,
16524};
16525
16526/* POOL32Axf_2 instruction pool */
16527enum {
16528 NM_POOL32AXF_2_0_7 = 0x00,
16529 NM_POOL32AXF_2_8_15 = 0x01,
16530 NM_POOL32AXF_2_16_23 = 0x02,
16531 NM_POOL32AXF_2_24_31 = 0x03,
16532};
16533
16534/* POOL32Axf_7 instruction pool */
16535enum {
16536 NM_SHRA_R_QB = 0x0,
16537 NM_SHRL_PH = 0x1,
16538 NM_REPL_QB = 0x2,
16539};
16540
16541/* POOL32Axf_1_0 instruction pool */
16542enum {
16543 NM_MFHI = 0x0,
16544 NM_MFLO = 0x1,
16545 NM_MTHI = 0x2,
16546 NM_MTLO = 0x3,
16547};
16548
16549/* POOL32Axf_1_1 instruction pool */
16550enum {
16551 NM_MTHLIP = 0x0,
16552 NM_SHILOV = 0x1,
16553};
16554
16555/* POOL32Axf_1_3 instruction pool */
16556enum {
16557 NM_RDDSP = 0x0,
16558 NM_WRDSP = 0x1,
16559 NM_EXTP = 0x2,
16560 NM_EXTPDP = 0x3,
16561};
16562
16563/* POOL32Axf_1_4 instruction pool */
16564enum {
16565 NM_SHLL_QB = 0x0,
16566 NM_SHRL_QB = 0x1,
16567};
16568
16569/* POOL32Axf_1_5 instruction pool */
16570enum {
16571 NM_MAQ_S_W_PHR = 0x0,
16572 NM_MAQ_S_W_PHL = 0x1,
16573 NM_MAQ_SA_W_PHR = 0x2,
16574 NM_MAQ_SA_W_PHL = 0x3,
16575};
16576
16577/* POOL32Axf_1_7 instruction pool */
16578enum {
16579 NM_EXTR_W = 0x0,
16580 NM_EXTR_R_W = 0x1,
16581 NM_EXTR_RS_W = 0x2,
16582 NM_EXTR_S_H = 0x3,
16583};
16584
16585/* POOL32Axf_2_0_7 instruction pool */
16586enum {
16587 NM_DPA_W_PH = 0x0,
16588 NM_DPAQ_S_W_PH = 0x1,
16589 NM_DPS_W_PH = 0x2,
16590 NM_DPSQ_S_W_PH = 0x3,
16591 NM_BALIGN = 0x4,
16592 NM_MADD = 0x5,
16593 NM_MULT = 0x6,
16594 NM_EXTRV_W = 0x7,
16595};
16596
16597/* POOL32Axf_2_8_15 instruction pool */
16598enum {
16599 NM_DPAX_W_PH = 0x0,
16600 NM_DPAQ_SA_L_W = 0x1,
16601 NM_DPSX_W_PH = 0x2,
16602 NM_DPSQ_SA_L_W = 0x3,
16603 NM_MADDU = 0x5,
16604 NM_MULTU = 0x6,
16605 NM_EXTRV_R_W = 0x7,
16606};
16607
16608/* POOL32Axf_2_16_23 instruction pool */
16609enum {
16610 NM_DPAU_H_QBL = 0x0,
16611 NM_DPAQX_S_W_PH = 0x1,
16612 NM_DPSU_H_QBL = 0x2,
16613 NM_DPSQX_S_W_PH = 0x3,
16614 NM_EXTPV = 0x4,
16615 NM_MSUB = 0x5,
16616 NM_MULSA_W_PH = 0x6,
16617 NM_EXTRV_RS_W = 0x7,
16618};
16619
16620/* POOL32Axf_2_24_31 instruction pool */
16621enum {
16622 NM_DPAU_H_QBR = 0x0,
16623 NM_DPAQX_SA_W_PH = 0x1,
16624 NM_DPSU_H_QBR = 0x2,
16625 NM_DPSQX_SA_W_PH = 0x3,
16626 NM_EXTPDPV = 0x4,
16627 NM_MSUBU = 0x5,
16628 NM_MULSAQ_S_W_PH = 0x6,
16629 NM_EXTRV_S_H = 0x7,
261c95a0
YK
16630};
16631
16632/* POOL32Axf_{4, 5} instruction pool */
16633enum {
16634 NM_CLO = 0x25,
16635 NM_CLZ = 0x2d,
16636
16637 NM_TLBP = 0x01,
16638 NM_TLBR = 0x09,
16639 NM_TLBWI = 0x11,
16640 NM_TLBWR = 0x19,
16641 NM_TLBINV = 0x03,
16642 NM_TLBINVF = 0x0b,
16643 NM_DI = 0x23,
16644 NM_EI = 0x2b,
16645 NM_RDPGPR = 0x70,
16646 NM_WRPGPR = 0x78,
16647 NM_WAIT = 0x61,
16648 NM_DERET = 0x71,
16649 NM_ERETX = 0x79,
b3979b6f
SM
16650
16651 /* nanoMIPS DSP instructions */
16652 NM_ABSQ_S_QB = 0x00,
16653 NM_ABSQ_S_PH = 0x08,
16654 NM_ABSQ_S_W = 0x10,
16655 NM_PRECEQ_W_PHL = 0x28,
16656 NM_PRECEQ_W_PHR = 0x30,
16657 NM_PRECEQU_PH_QBL = 0x38,
16658 NM_PRECEQU_PH_QBR = 0x48,
16659 NM_PRECEU_PH_QBL = 0x58,
16660 NM_PRECEU_PH_QBR = 0x68,
16661 NM_PRECEQU_PH_QBLA = 0x39,
16662 NM_PRECEQU_PH_QBRA = 0x49,
16663 NM_PRECEU_PH_QBLA = 0x59,
16664 NM_PRECEU_PH_QBRA = 0x69,
16665 NM_REPLV_PH = 0x01,
16666 NM_REPLV_QB = 0x09,
16667 NM_BITREV = 0x18,
16668 NM_INSV = 0x20,
16669 NM_RADDU_W_QB = 0x78,
16670
16671 NM_BITSWAP = 0x05,
16672 NM_WSBH = 0x3d,
261c95a0
YK
16673};
16674
16675/* PP.SR instruction pool */
16676enum {
16677 NM_SAVE = 0x00,
16678 NM_RESTORE = 0x02,
16679 NM_RESTORE_JRC = 0x03,
16680};
16681
16682/* P.SR.F instruction pool */
16683enum {
16684 NM_SAVEF = 0x00,
16685 NM_RESTOREF = 0x01,
16686};
16687
16688/* P16.SYSCALL instruction pool */
16689enum {
16690 NM_SYSCALL16 = 0x00,
16691 NM_HYPCALL16 = 0x01,
16692};
16693
16694/* POOL16C_00 instruction pool */
16695enum {
16696 NM_NOT16 = 0x00,
16697 NM_XOR16 = 0x01,
16698 NM_AND16 = 0x02,
16699 NM_OR16 = 0x03,
16700};
16701
16702/* PP.LSX and PP.LSXS instruction pool */
16703enum {
16704 NM_LBX = 0x00,
16705 NM_LHX = 0x04,
16706 NM_LWX = 0x08,
16707 NM_LDX = 0x0c,
16708
16709 NM_SBX = 0x01,
16710 NM_SHX = 0x05,
16711 NM_SWX = 0x09,
16712 NM_SDX = 0x0d,
16713
16714 NM_LBUX = 0x02,
16715 NM_LHUX = 0x06,
16716 NM_LWC1X = 0x0a,
16717 NM_LDC1X = 0x0e,
16718
16719 NM_LWUX = 0x07,
16720 NM_SWC1X = 0x0b,
16721 NM_SDC1X = 0x0f,
16722
16723 NM_LHXS = 0x04,
16724 NM_LWXS = 0x08,
16725 NM_LDXS = 0x0c,
16726
16727 NM_SHXS = 0x05,
16728 NM_SWXS = 0x09,
16729 NM_SDXS = 0x0d,
16730
16731 NM_LHUXS = 0x06,
16732 NM_LWC1XS = 0x0a,
16733 NM_LDC1XS = 0x0e,
16734
16735 NM_LWUXS = 0x07,
16736 NM_SWC1XS = 0x0b,
16737 NM_SDC1XS = 0x0f,
16738};
16739
16740/* ERETx instruction pool */
16741enum {
16742 NM_ERET = 0x00,
16743 NM_ERETNC = 0x01,
16744};
16745
16746/* POOL32FxF_{0, 1} insturction pool */
16747enum {
16748 NM_CFC1 = 0x40,
16749 NM_CTC1 = 0x60,
16750 NM_MFC1 = 0x80,
16751 NM_MTC1 = 0xa0,
16752 NM_MFHC1 = 0xc0,
16753 NM_MTHC1 = 0xe0,
16754
16755 NM_CVT_S_PL = 0x84,
16756 NM_CVT_S_PU = 0xa4,
16757
16758 NM_CVT_L_S = 0x004,
16759 NM_CVT_L_D = 0x104,
16760 NM_CVT_W_S = 0x024,
16761 NM_CVT_W_D = 0x124,
16762
16763 NM_RSQRT_S = 0x008,
16764 NM_RSQRT_D = 0x108,
16765
16766 NM_SQRT_S = 0x028,
16767 NM_SQRT_D = 0x128,
16768
16769 NM_RECIP_S = 0x048,
16770 NM_RECIP_D = 0x148,
16771
16772 NM_FLOOR_L_S = 0x00c,
16773 NM_FLOOR_L_D = 0x10c,
16774
16775 NM_FLOOR_W_S = 0x02c,
16776 NM_FLOOR_W_D = 0x12c,
16777
16778 NM_CEIL_L_S = 0x04c,
16779 NM_CEIL_L_D = 0x14c,
16780 NM_CEIL_W_S = 0x06c,
16781 NM_CEIL_W_D = 0x16c,
16782 NM_TRUNC_L_S = 0x08c,
16783 NM_TRUNC_L_D = 0x18c,
16784 NM_TRUNC_W_S = 0x0ac,
16785 NM_TRUNC_W_D = 0x1ac,
16786 NM_ROUND_L_S = 0x0cc,
16787 NM_ROUND_L_D = 0x1cc,
16788 NM_ROUND_W_S = 0x0ec,
16789 NM_ROUND_W_D = 0x1ec,
16790
16791 NM_MOV_S = 0x01,
16792 NM_MOV_D = 0x81,
16793 NM_ABS_S = 0x0d,
16794 NM_ABS_D = 0x8d,
16795 NM_NEG_S = 0x2d,
16796 NM_NEG_D = 0xad,
16797 NM_CVT_D_S = 0x04d,
16798 NM_CVT_D_W = 0x0cd,
16799 NM_CVT_D_L = 0x14d,
16800 NM_CVT_S_D = 0x06d,
16801 NM_CVT_S_W = 0x0ed,
16802 NM_CVT_S_L = 0x16d,
16803};
16804
16805/* P.LL instruction pool */
16806enum {
16807 NM_LL = 0x00,
16808 NM_LLWP = 0x01,
16809};
16810
16811/* P.SC instruction pool */
16812enum {
16813 NM_SC = 0x00,
16814 NM_SCWP = 0x01,
16815};
16816
16817/* P.DVP instruction pool */
16818enum {
16819 NM_DVP = 0x00,
16820 NM_EVP = 0x01,
16821};
16822
c533c0f4
AM
16823
16824/*
16825 *
16826 * nanoMIPS decoding engine
16827 *
16828 */
16829
6bfa9f4c
AM
16830
16831/* extraction utilities */
16832
16833#define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
16834#define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
16835#define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
16836#define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
16837#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
16838#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
16839
ea4ca3c2
YK
16840/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
16841static inline int decode_gpr_gpr3(int r)
16842{
16843 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
16844
16845 return map[r & 0x7];
16846}
16847
8bdb7029
YK
16848/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
16849static inline int decode_gpr_gpr3_src_store(int r)
16850{
16851 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
16852
16853 return map[r & 0x7];
16854}
16855
ea4ca3c2
YK
16856/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
16857static inline int decode_gpr_gpr4(int r)
16858{
16859 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
16860 16, 17, 18, 19, 20, 21, 22, 23 };
16861
16862 return map[r & 0xf];
16863}
16864
8bdb7029
YK
16865/* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
16866static inline int decode_gpr_gpr4_zero(int r)
16867{
16868 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
16869 16, 17, 18, 19, 20, 21, 22, 23 };
16870
16871 return map[r & 0xf];
16872}
16873
6bfa9f4c 16874
80845edf
YK
16875/* extraction utilities */
16876
16877#define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
16878#define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
16879#define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
16880#define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
16881#define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
16882#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
16883
16884
bf0718c5
SM
16885static void gen_adjust_sp(DisasContext *ctx, int u)
16886{
16887 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
16888}
16889
16890static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
16891 uint8_t gp, uint16_t u)
16892{
16893 int counter = 0;
16894 TCGv va = tcg_temp_new();
16895 TCGv t0 = tcg_temp_new();
16896
16897 while (counter != count) {
16898 bool use_gp = gp && (counter == count - 1);
16899 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
16900 int this_offset = -((counter + 1) << 2);
16901 gen_base_offset_addr(ctx, va, 29, this_offset);
16902 gen_load_gpr(t0, this_rt);
16903 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
16904 (MO_TEUL | ctx->default_tcg_memop_mask));
16905 counter++;
16906 }
16907
16908 /* adjust stack pointer */
16909 gen_adjust_sp(ctx, -u);
16910
16911 tcg_temp_free(t0);
16912 tcg_temp_free(va);
16913}
16914
16915static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
16916 uint8_t gp, uint16_t u)
16917{
16918 int counter = 0;
16919 TCGv va = tcg_temp_new();
16920 TCGv t0 = tcg_temp_new();
16921
16922 while (counter != count) {
16923 bool use_gp = gp && (counter == count - 1);
16924 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
16925 int this_offset = u - ((counter + 1) << 2);
16926 gen_base_offset_addr(ctx, va, 29, this_offset);
16927 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
16928 ctx->default_tcg_memop_mask);
16929 tcg_gen_ext32s_tl(t0, t0);
16930 gen_store_gpr(t0, this_rt);
16931 counter++;
16932 }
16933
16934 /* adjust stack pointer */
16935 gen_adjust_sp(ctx, u);
16936
16937 tcg_temp_free(t0);
16938 tcg_temp_free(va);
16939}
16940
80845edf
YK
16941static void gen_pool16c_nanomips_insn(DisasContext *ctx)
16942{
16943 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
16944 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
16945
16946 switch (extract32(ctx->opcode, 2, 2)) {
16947 case NM_NOT16:
16948 gen_logic(ctx, OPC_NOR, rt, rs, 0);
16949 break;
16950 case NM_AND16:
16951 gen_logic(ctx, OPC_AND, rt, rt, rs);
16952 break;
16953 case NM_XOR16:
16954 gen_logic(ctx, OPC_XOR, rt, rt, rs);
16955 break;
16956 case NM_OR16:
16957 gen_logic(ctx, OPC_OR, rt, rt, rs);
16958 break;
16959 }
16960}
16961
e0cf0e65
YK
16962static void gen_pool32a0_nanomips_insn(DisasContext *ctx)
16963{
16964 int rt = extract32(ctx->opcode, 21, 5);
16965 int rs = extract32(ctx->opcode, 16, 5);
16966 int rd = extract32(ctx->opcode, 11, 5);
16967
16968 switch (extract32(ctx->opcode, 3, 7)) {
16969 case NM_P_TRAP:
16970 switch (extract32(ctx->opcode, 10, 1)) {
16971 case NM_TEQ:
16972 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
16973 break;
16974 case NM_TNE:
16975 gen_trap(ctx, OPC_TNE, rs, rt, -1);
16976 break;
16977 }
16978 break;
16979 case NM_RDHWR:
16980 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16981 break;
16982 case NM_SEB:
16983 gen_bshfl(ctx, OPC_SEB, rs, rt);
16984 break;
16985 case NM_SEH:
16986 gen_bshfl(ctx, OPC_SEH, rs, rt);
16987 break;
16988 case NM_SLLV:
16989 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
16990 break;
16991 case NM_SRLV:
16992 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
16993 break;
16994 case NM_SRAV:
16995 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
16996 break;
16997 case NM_ROTRV:
16998 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
16999 break;
17000 case NM_ADD:
17001 gen_arith(ctx, OPC_ADD, rd, rs, rt);
17002 break;
17003 case NM_ADDU:
17004 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
17005 break;
17006 case NM_SUB:
17007 gen_arith(ctx, OPC_SUB, rd, rs, rt);
17008 break;
17009 case NM_SUBU:
17010 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
17011 break;
17012 case NM_P_CMOVE:
17013 switch (extract32(ctx->opcode, 10, 1)) {
17014 case NM_MOVZ:
17015 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
17016 break;
17017 case NM_MOVN:
17018 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
17019 break;
17020 }
17021 break;
17022 case NM_AND:
17023 gen_logic(ctx, OPC_AND, rd, rs, rt);
17024 break;
17025 case NM_OR:
17026 gen_logic(ctx, OPC_OR, rd, rs, rt);
17027 break;
17028 case NM_NOR:
17029 gen_logic(ctx, OPC_NOR, rd, rs, rt);
17030 break;
17031 case NM_XOR:
17032 gen_logic(ctx, OPC_XOR, rd, rs, rt);
17033 break;
17034 case NM_SLT:
17035 gen_slt(ctx, OPC_SLT, rd, rs, rt);
17036 break;
17037 case NM_P_SLTU:
17038 if (rd == 0) {
17039 /* P_DVP */
17040#ifndef CONFIG_USER_ONLY
17041 TCGv t0 = tcg_temp_new();
17042 switch (extract32(ctx->opcode, 10, 1)) {
17043 case NM_DVP:
17044 if (ctx->vp) {
17045 check_cp0_enabled(ctx);
17046 gen_helper_dvp(t0, cpu_env);
17047 gen_store_gpr(t0, rt);
17048 }
17049 break;
17050 case NM_EVP:
17051 if (ctx->vp) {
17052 check_cp0_enabled(ctx);
17053 gen_helper_evp(t0, cpu_env);
17054 gen_store_gpr(t0, rt);
17055 }
17056 break;
17057 }
17058 tcg_temp_free(t0);
17059#endif
17060 } else {
17061 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
17062 }
17063 break;
17064 case NM_SOV:
17065 {
17066 TCGv t0 = tcg_temp_new();
17067 TCGv t1 = tcg_temp_new();
17068 TCGv t2 = tcg_temp_new();
17069
17070 gen_load_gpr(t1, rs);
17071 gen_load_gpr(t2, rt);
17072 tcg_gen_add_tl(t0, t1, t2);
17073 tcg_gen_ext32s_tl(t0, t0);
17074 tcg_gen_xor_tl(t1, t1, t2);
17075 tcg_gen_xor_tl(t2, t0, t2);
17076 tcg_gen_andc_tl(t1, t2, t1);
17077
17078 /* operands of same sign, result different sign */
17079 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
17080 gen_store_gpr(t0, rd);
17081
17082 tcg_temp_free(t0);
17083 tcg_temp_free(t1);
17084 tcg_temp_free(t2);
17085 }
17086 break;
17087 case NM_MUL:
17088 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
17089 break;
17090 case NM_MUH:
17091 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
17092 break;
17093 case NM_MULU:
17094 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
17095 break;
17096 case NM_MUHU:
17097 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
17098 break;
17099 case NM_DIV:
17100 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
17101 break;
17102 case NM_MOD:
17103 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
17104 break;
17105 case NM_DIVU:
17106 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
17107 break;
17108 case NM_MODU:
17109 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
17110 break;
17111#ifndef CONFIG_USER_ONLY
17112 case NM_MFC0:
17113 check_cp0_enabled(ctx);
17114 if (rt == 0) {
17115 /* Treat as NOP. */
17116 break;
17117 }
17118 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
17119 break;
17120 case NM_MTC0:
17121 check_cp0_enabled(ctx);
17122 {
17123 TCGv t0 = tcg_temp_new();
17124
17125 gen_load_gpr(t0, rt);
17126 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
17127 tcg_temp_free(t0);
17128 }
17129 break;
17130#endif
17131 default:
17132 generate_exception_end(ctx, EXCP_RI);
17133 break;
17134 }
17135}
17136
64224187
YK
17137static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
17138{
17139#ifndef CONFIG_USER_ONLY
17140 int rt = extract32(ctx->opcode, 21, 5);
17141 int rs = extract32(ctx->opcode, 16, 5);
17142#endif
17143
17144 switch (extract32(ctx->opcode, 6, 3)) {
17145 case NM_POOL32AXF_4:
17146 case NM_POOL32AXF_5:
17147 switch (extract32(ctx->opcode, 9, 7)) {
17148#ifndef CONFIG_USER_ONLY
17149 case NM_TLBP:
17150 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
17151 break;
17152 case NM_TLBR:
17153 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
17154 break;
17155 case NM_TLBWI:
17156 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
17157 break;
17158 case NM_TLBWR:
17159 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
17160 break;
17161 case NM_TLBINV:
17162 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
17163 break;
17164 case NM_TLBINVF:
17165 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
17166 break;
17167 case NM_DI:
17168 check_cp0_enabled(ctx);
17169 {
17170 TCGv t0 = tcg_temp_new();
17171
17172 save_cpu_state(ctx, 1);
17173 gen_helper_di(t0, cpu_env);
17174 gen_store_gpr(t0, rt);
17175 /* Stop translation as we may have switched the execution mode */
17176 ctx->base.is_jmp = DISAS_STOP;
17177 tcg_temp_free(t0);
17178 }
17179 break;
17180 case NM_EI:
17181 check_cp0_enabled(ctx);
17182 {
17183 TCGv t0 = tcg_temp_new();
17184
17185 save_cpu_state(ctx, 1);
17186 gen_helper_ei(t0, cpu_env);
17187 gen_store_gpr(t0, rt);
17188 /* Stop translation as we may have switched the execution mode */
17189 ctx->base.is_jmp = DISAS_STOP;
17190 tcg_temp_free(t0);
17191 }
17192 break;
17193 case NM_RDPGPR:
17194 gen_load_srsgpr(rs, rt);
17195 break;
17196 case NM_WRPGPR:
17197 gen_store_srsgpr(rs, rt);
17198 break;
17199 case NM_WAIT:
17200 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
17201 break;
17202 case NM_DERET:
17203 gen_cp0(env, ctx, OPC_DERET, 0, 0);
17204 break;
17205 case NM_ERETX:
17206 gen_cp0(env, ctx, OPC_ERET, 0, 0);
17207 break;
17208#endif
17209 default:
17210 generate_exception_end(ctx, EXCP_RI);
17211 break;
17212 }
17213 break;
17214 default:
17215 generate_exception_end(ctx, EXCP_RI);
17216 break;
17217 }
17218}
17219
eac52664
YK
17220
17221static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
17222{
17223 TCGv t0, t1;
17224 t0 = tcg_temp_new();
17225 t1 = tcg_temp_new();
17226
17227 gen_load_gpr(t0, rs);
17228 gen_load_gpr(t1, rt);
17229
17230 if ((extract32(ctx->opcode, 6, 1)) == 1) {
17231 /* PP.LSXS instructions require shifting */
17232 switch (extract32(ctx->opcode, 7, 4)) {
17233 case NM_LHXS:
17234 case NM_SHXS:
17235 case NM_LHUXS:
17236 tcg_gen_shli_tl(t0, t0, 1);
17237 break;
17238 case NM_LWXS:
17239 case NM_SWXS:
17240 case NM_LWC1XS:
17241 case NM_SWC1XS:
17242 tcg_gen_shli_tl(t0, t0, 2);
17243 break;
17244 case NM_LDC1XS:
17245 case NM_SDC1XS:
17246 tcg_gen_shli_tl(t0, t0, 3);
17247 break;
17248 }
17249 }
17250 gen_op_addr_add(ctx, t0, t0, t1);
17251
17252 switch (extract32(ctx->opcode, 7, 4)) {
17253 case NM_LBX:
17254 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
17255 MO_SB);
17256 gen_store_gpr(t0, rd);
17257 break;
17258 case NM_LHX:
17259 /*case NM_LHXS:*/
17260 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
17261 MO_TESW);
17262 gen_store_gpr(t0, rd);
17263 break;
17264 case NM_LWX:
17265 /*case NM_LWXS:*/
17266 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
17267 MO_TESL);
17268 gen_store_gpr(t0, rd);
17269 break;
17270 case NM_LBUX:
17271 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
17272 MO_UB);
17273 gen_store_gpr(t0, rd);
17274 break;
17275 case NM_LHUX:
17276 /*case NM_LHUXS:*/
17277 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
17278 MO_TEUW);
17279 gen_store_gpr(t0, rd);
17280 break;
17281 case NM_SBX:
17282 gen_load_gpr(t1, rd);
17283 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
17284 MO_8);
17285 break;
17286 case NM_SHX:
17287 /*case NM_SHXS:*/
17288 gen_load_gpr(t1, rd);
17289 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
17290 MO_TEUW);
17291 break;
17292 case NM_SWX:
17293 /*case NM_SWXS:*/
17294 gen_load_gpr(t1, rd);
17295 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
17296 MO_TEUL);
17297 break;
17298 case NM_LWC1X:
17299 /*case NM_LWC1XS:*/
17300 case NM_LDC1X:
17301 /*case NM_LDC1XS:*/
17302 case NM_SWC1X:
17303 /*case NM_SWC1XS:*/
17304 case NM_SDC1X:
17305 /*case NM_SDC1XS:*/
17306 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
17307 check_cp1_enabled(ctx);
17308 switch (extract32(ctx->opcode, 7, 4)) {
17309 case NM_LWC1X:
17310 /*case NM_LWC1XS:*/
17311 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
17312 break;
17313 case NM_LDC1X:
17314 /*case NM_LDC1XS:*/
17315 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
17316 break;
17317 case NM_SWC1X:
17318 /*case NM_SWC1XS:*/
17319 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
17320 break;
17321 case NM_SDC1X:
17322 /*case NM_SDC1XS:*/
17323 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
17324 break;
17325 }
17326 } else {
17327 generate_exception_err(ctx, EXCP_CpU, 1);
17328 }
17329 break;
17330 default:
17331 generate_exception_end(ctx, EXCP_RI);
17332 break;
17333 }
17334
17335 tcg_temp_free(t0);
17336 tcg_temp_free(t1);
17337}
17338
579b8ea9
YK
17339static void gen_pool32f_nanomips_insn(DisasContext *ctx)
17340{
17341 int rt, rs, rd;
17342
17343 rt = extract32(ctx->opcode, 21, 5);
17344 rs = extract32(ctx->opcode, 16, 5);
17345 rd = extract32(ctx->opcode, 11, 5);
17346
17347 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
17348 generate_exception_end(ctx, EXCP_RI);
17349 return;
17350 }
17351 check_cp1_enabled(ctx);
17352 switch (extract32(ctx->opcode, 0, 3)) {
17353 case NM_POOL32F_0:
17354 switch (extract32(ctx->opcode, 3, 7)) {
17355 case NM_RINT_S:
17356 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
17357 break;
17358 case NM_RINT_D:
17359 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
17360 break;
17361 case NM_CLASS_S:
17362 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
17363 break;
17364 case NM_CLASS_D:
17365 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
17366 break;
17367 case NM_ADD_S:
17368 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
17369 break;
17370 case NM_ADD_D:
17371 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
17372 break;
17373 case NM_SUB_S:
17374 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
17375 break;
17376 case NM_SUB_D:
17377 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
17378 break;
17379 case NM_MUL_S:
17380 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
17381 break;
17382 case NM_MUL_D:
17383 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
17384 break;
17385 case NM_DIV_S:
17386 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
17387 break;
17388 case NM_DIV_D:
17389 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
17390 break;
17391 case NM_SELEQZ_S:
17392 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
17393 break;
17394 case NM_SELEQZ_D:
17395 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
17396 break;
17397 case NM_SELNEZ_S:
17398 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
17399 break;
17400 case NM_SELNEZ_D:
17401 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
17402 break;
17403 case NM_SEL_S:
17404 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
17405 break;
17406 case NM_SEL_D:
17407 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
17408 break;
17409 case NM_MADDF_S:
17410 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
17411 break;
17412 case NM_MADDF_D:
17413 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
17414 break;
17415 case NM_MSUBF_S:
17416 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
17417 break;
17418 case NM_MSUBF_D:
17419 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
17420 break;
17421 default:
17422 generate_exception_end(ctx, EXCP_RI);
17423 break;
17424 }
17425 break;
17426 case NM_POOL32F_3:
17427 switch (extract32(ctx->opcode, 3, 3)) {
17428 case NM_MIN_FMT:
17429 switch (extract32(ctx->opcode, 9, 1)) {
17430 case FMT_SDPS_S:
17431 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
17432 break;
17433 case FMT_SDPS_D:
17434 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
17435 break;
17436 }
17437 break;
17438 case NM_MAX_FMT:
17439 switch (extract32(ctx->opcode, 9, 1)) {
17440 case FMT_SDPS_S:
17441 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
17442 break;
17443 case FMT_SDPS_D:
17444 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
17445 break;
17446 }
17447 break;
17448 case NM_MINA_FMT:
17449 switch (extract32(ctx->opcode, 9, 1)) {
17450 case FMT_SDPS_S:
17451 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
17452 break;
17453 case FMT_SDPS_D:
17454 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
17455 break;
17456 }
17457 break;
17458 case NM_MAXA_FMT:
17459 switch (extract32(ctx->opcode, 9, 1)) {
17460 case FMT_SDPS_S:
17461 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
17462 break;
17463 case FMT_SDPS_D:
17464 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
17465 break;
17466 }
17467 break;
17468 case NM_POOL32FXF:
17469 switch (extract32(ctx->opcode, 6, 8)) {
17470 case NM_CFC1:
17471 gen_cp1(ctx, OPC_CFC1, rt, rs);
17472 break;
17473 case NM_CTC1:
17474 gen_cp1(ctx, OPC_CTC1, rt, rs);
17475 break;
17476 case NM_MFC1:
17477 gen_cp1(ctx, OPC_MFC1, rt, rs);
17478 break;
17479 case NM_MTC1:
17480 gen_cp1(ctx, OPC_MTC1, rt, rs);
17481 break;
17482 case NM_MFHC1:
17483 gen_cp1(ctx, OPC_MFHC1, rt, rs);
17484 break;
17485 case NM_MTHC1:
17486 gen_cp1(ctx, OPC_MTHC1, rt, rs);
17487 break;
17488 case NM_CVT_S_PL:
17489 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
17490 break;
17491 case NM_CVT_S_PU:
17492 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
17493 break;
17494 default:
17495 switch (extract32(ctx->opcode, 6, 9)) {
17496 case NM_CVT_L_S:
17497 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
17498 break;
17499 case NM_CVT_L_D:
17500 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
17501 break;
17502 case NM_CVT_W_S:
17503 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
17504 break;
17505 case NM_CVT_W_D:
17506 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
17507 break;
17508 case NM_RSQRT_S:
17509 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
17510 break;
17511 case NM_RSQRT_D:
17512 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
17513 break;
17514 case NM_SQRT_S:
17515 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
17516 break;
17517 case NM_SQRT_D:
17518 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
17519 break;
17520 case NM_RECIP_S:
17521 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
17522 break;
17523 case NM_RECIP_D:
17524 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
17525 break;
17526 case NM_FLOOR_L_S:
17527 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
17528 break;
17529 case NM_FLOOR_L_D:
17530 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
17531 break;
17532 case NM_FLOOR_W_S:
17533 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
17534 break;
17535 case NM_FLOOR_W_D:
17536 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
17537 break;
17538 case NM_CEIL_L_S:
17539 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
17540 break;
17541 case NM_CEIL_L_D:
17542 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
17543 break;
17544 case NM_CEIL_W_S:
17545 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
17546 break;
17547 case NM_CEIL_W_D:
17548 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
17549 break;
17550 case NM_TRUNC_L_S:
17551 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
17552 break;
17553 case NM_TRUNC_L_D:
17554 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
17555 break;
17556 case NM_TRUNC_W_S:
17557 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
17558 break;
17559 case NM_TRUNC_W_D:
17560 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
17561 break;
17562 case NM_ROUND_L_S:
17563 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
17564 break;
17565 case NM_ROUND_L_D:
17566 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
17567 break;
17568 case NM_ROUND_W_S:
17569 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
17570 break;
17571 case NM_ROUND_W_D:
17572 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
17573 break;
17574 case NM_MOV_S:
17575 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
17576 break;
17577 case NM_MOV_D:
17578 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
17579 break;
17580 case NM_ABS_S:
17581 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
17582 break;
17583 case NM_ABS_D:
17584 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
17585 break;
17586 case NM_NEG_S:
17587 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
17588 break;
17589 case NM_NEG_D:
17590 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
17591 break;
17592 case NM_CVT_D_S:
17593 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
17594 break;
17595 case NM_CVT_D_W:
17596 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
17597 break;
17598 case NM_CVT_D_L:
17599 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
17600 break;
17601 case NM_CVT_S_D:
17602 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
17603 break;
17604 case NM_CVT_S_W:
17605 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
17606 break;
17607 case NM_CVT_S_L:
17608 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
17609 break;
17610 default:
17611 generate_exception_end(ctx, EXCP_RI);
17612 break;
17613 }
17614 break;
17615 }
17616 break;
17617 }
17618 break;
17619 case NM_POOL32F_5:
17620 switch (extract32(ctx->opcode, 3, 3)) {
17621 case NM_CMP_CONDN_S:
17622 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
17623 break;
17624 case NM_CMP_CONDN_D:
17625 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
17626 break;
17627 default:
17628 generate_exception_end(ctx, EXCP_RI);
17629 break;
17630 }
17631 break;
17632 default:
17633 generate_exception_end(ctx, EXCP_RI);
17634 break;
17635 }
17636}
17637
c0280983
YK
17638static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
17639{
17640 uint16_t insn;
17641 uint32_t op;
eac52664 17642 int rt, rs, rd;
c0280983
YK
17643 int offset;
17644 int imm;
17645
17646 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
17647 ctx->opcode = (ctx->opcode << 16) | insn;
17648
17649 rt = extract32(ctx->opcode, 21, 5);
17650 rs = extract32(ctx->opcode, 16, 5);
eac52664 17651 rd = extract32(ctx->opcode, 11, 5);
c0280983
YK
17652
17653 op = extract32(ctx->opcode, 26, 6);
17654 switch (op) {
17655 case NM_P_ADDIU:
17656 if (rt == 0) {
17657 /* P.RI */
17658 switch (extract32(ctx->opcode, 19, 2)) {
17659 case NM_SIGRIE:
17660 default:
17661 generate_exception_end(ctx, EXCP_RI);
17662 break;
17663 case NM_P_SYSCALL:
17664 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
17665 generate_exception_end(ctx, EXCP_SYSCALL);
17666 } else {
17667 generate_exception_end(ctx, EXCP_RI);
17668 }
17669 break;
17670 case NM_BREAK:
17671 generate_exception_end(ctx, EXCP_BREAK);
17672 break;
17673 case NM_SDBBP:
17674 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
17675 gen_helper_do_semihosting(cpu_env);
17676 } else {
17677 if (ctx->hflags & MIPS_HFLAG_SBRI) {
17678 generate_exception_end(ctx, EXCP_RI);
17679 } else {
17680 generate_exception_end(ctx, EXCP_DBp);
17681 }
17682 }
17683 break;
17684 }
17685 } else {
17686 /* NM_ADDIU */
17687 imm = extract32(ctx->opcode, 0, 16);
17688 if (rs != 0) {
17689 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
17690 } else {
17691 tcg_gen_movi_tl(cpu_gpr[rt], imm);
17692 }
17693 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
17694 }
17695 break;
17696 case NM_ADDIUPC:
17697 if (rt != 0) {
17698 offset = sextract32(ctx->opcode, 0, 1) << 21 |
17699 extract32(ctx->opcode, 1, 20) << 1;
17700 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
17701 tcg_gen_movi_tl(cpu_gpr[rt], addr);
17702 }
17703 break;
17704 case NM_POOL32A:
e0cf0e65
YK
17705 switch (ctx->opcode & 0x07) {
17706 case NM_POOL32A0:
17707 gen_pool32a0_nanomips_insn(ctx);
17708 break;
17709 case NM_POOL32A7:
64224187 17710 switch (extract32(ctx->opcode, 3, 3)) {
eac52664
YK
17711 case NM_P_LSX:
17712 gen_p_lsx(ctx, rd, rs, rt);
17713 break;
17714 case NM_LSA:
17715 /* In nanoMIPS, the shift field directly encodes the shift
17716 * amount, meaning that the supported shift values are in
17717 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
17718 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
17719 extract32(ctx->opcode, 9, 2) - 1);
17720 break;
821f2008
JH
17721 case NM_EXTW:
17722 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
17723 break;
64224187
YK
17724 case NM_POOL32AXF:
17725 gen_pool32axf_nanomips_insn(env, ctx);
17726 break;
17727 default:
17728 generate_exception_end(ctx, EXCP_RI);
17729 break;
17730 }
e0cf0e65
YK
17731 break;
17732 default:
17733 generate_exception_end(ctx, EXCP_RI);
17734 break;
17735 }
c0280983
YK
17736 break;
17737 case NM_P_GP_W:
17738 switch (ctx->opcode & 0x03) {
17739 case NM_ADDIUGP_W:
17740 if (rt != 0) {
17741 offset = extract32(ctx->opcode, 0, 21);
17742 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
17743 }
17744 break;
17745 case NM_LWGP:
17746 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
17747 break;
17748 case NM_SWGP:
17749 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
17750 break;
17751 default:
17752 generate_exception_end(ctx, EXCP_RI);
17753 break;
17754 }
17755 break;
17756 case NM_P48I:
7ef009b2
YK
17757 {
17758 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
17759 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
17760 switch (extract32(ctx->opcode, 16, 5)) {
17761 case NM_LI48:
17762 if (rt != 0) {
17763 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
17764 }
17765 break;
17766 case NM_ADDIU48:
17767 if (rt != 0) {
17768 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
17769 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
17770 }
17771 break;
17772 case NM_ADDIUGP48:
17773 if (rt != 0) {
17774 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
17775 }
17776 break;
17777 case NM_ADDIUPC48:
17778 if (rt != 0) {
17779 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
17780 addr_off);
17781
17782 tcg_gen_movi_tl(cpu_gpr[rt], addr);
17783 }
17784 break;
17785 case NM_LWPC48:
17786 if (rt != 0) {
17787 TCGv t0;
17788 t0 = tcg_temp_new();
17789
17790 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
17791 addr_off);
17792
17793 tcg_gen_movi_tl(t0, addr);
17794 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
17795 tcg_temp_free(t0);
17796 }
17797 break;
17798 case NM_SWPC48:
17799 {
17800 TCGv t0, t1;
17801 t0 = tcg_temp_new();
17802 t1 = tcg_temp_new();
17803
17804 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
17805 addr_off);
17806
17807 tcg_gen_movi_tl(t0, addr);
17808 gen_load_gpr(t1, rt);
17809
17810 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
17811
17812 tcg_temp_free(t0);
17813 tcg_temp_free(t1);
17814 }
17815 break;
17816 default:
17817 generate_exception_end(ctx, EXCP_RI);
17818 break;
17819 }
17820 return 6;
17821 }
c0280983
YK
17822 case NM_P_U12:
17823 switch (extract32(ctx->opcode, 12, 4)) {
17824 case NM_ORI:
17825 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
17826 break;
17827 case NM_XORI:
17828 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
17829 break;
17830 case NM_ANDI:
17831 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
17832 break;
17833 case NM_P_SR:
17834 switch (extract32(ctx->opcode, 20, 1)) {
17835 case NM_PP_SR:
17836 switch (ctx->opcode & 3) {
17837 case NM_SAVE:
17838 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
17839 extract32(ctx->opcode, 2, 1),
17840 extract32(ctx->opcode, 3, 9) << 3);
17841 break;
17842 case NM_RESTORE:
17843 case NM_RESTORE_JRC:
17844 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
17845 extract32(ctx->opcode, 2, 1),
17846 extract32(ctx->opcode, 3, 9) << 3);
17847 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
17848 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
17849 }
17850 break;
17851 default:
17852 generate_exception_end(ctx, EXCP_RI);
17853 break;
17854 }
17855 break;
17856 case NM_P_SR_F:
17857 generate_exception_end(ctx, EXCP_RI);
17858 break;
17859 }
17860 break;
17861 case NM_SLTI:
17862 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
17863 break;
17864 case NM_SLTIU:
17865 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
17866 break;
17867 case NM_SEQI:
17868 {
17869 TCGv t0 = tcg_temp_new();
17870
17871 imm = extract32(ctx->opcode, 0, 12);
17872 gen_load_gpr(t0, rs);
17873 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
17874 gen_store_gpr(t0, rt);
17875
17876 tcg_temp_free(t0);
17877 }
17878 break;
17879 case NM_ADDIUNEG:
17880 imm = (int16_t) extract32(ctx->opcode, 0, 12);
17881 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
17882 break;
17883 case NM_P_SHIFT:
17884 {
17885 int shift = extract32(ctx->opcode, 0, 5);
17886 switch (extract32(ctx->opcode, 5, 4)) {
17887 case NM_P_SLL:
17888 if (rt == 0 && shift == 0) {
17889 /* NOP */
17890 } else if (rt == 0 && shift == 3) {
17891 /* EHB - treat as NOP */
17892 } else if (rt == 0 && shift == 5) {
17893 /* PAUSE - treat as NOP */
17894 } else if (rt == 0 && shift == 6) {
17895 /* SYNC */
17896 gen_sync(extract32(ctx->opcode, 16, 5));
17897 } else {
17898 /* SLL */
17899 gen_shift_imm(ctx, OPC_SLL, rt, rs,
17900 extract32(ctx->opcode, 0, 5));
17901 }
17902 break;
17903 case NM_SRL:
17904 gen_shift_imm(ctx, OPC_SRL, rt, rs,
17905 extract32(ctx->opcode, 0, 5));
17906 break;
17907 case NM_SRA:
17908 gen_shift_imm(ctx, OPC_SRA, rt, rs,
17909 extract32(ctx->opcode, 0, 5));
17910 break;
17911 case NM_ROTR:
17912 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
17913 extract32(ctx->opcode, 0, 5));
17914 break;
17915 }
17916 }
17917 break;
17918 case NM_P_ROTX:
e222f506
MF
17919 if (rt != 0) {
17920 TCGv t0 = tcg_temp_new();
17921 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
17922 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
17923 << 1);
17924 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
17925
17926 gen_load_gpr(t0, rs);
17927 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
17928 tcg_temp_free(t0);
17929
17930 tcg_temp_free_i32(shift);
17931 tcg_temp_free_i32(shiftx);
17932 tcg_temp_free_i32(stripe);
17933 }
c0280983
YK
17934 break;
17935 case NM_P_INS:
17936 switch (((ctx->opcode >> 10) & 2) |
17937 (extract32(ctx->opcode, 5, 1))) {
17938 case NM_INS:
17939 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
17940 extract32(ctx->opcode, 6, 5));
17941 break;
17942 default:
17943 generate_exception_end(ctx, EXCP_RI);
17944 break;
17945 }
17946 break;
17947 case NM_P_EXT:
17948 switch (((ctx->opcode >> 10) & 2) |
17949 (extract32(ctx->opcode, 5, 1))) {
17950 case NM_EXT:
17951 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
17952 extract32(ctx->opcode, 6, 5));
17953 break;
17954 default:
17955 generate_exception_end(ctx, EXCP_RI);
17956 break;
17957 }
17958 break;
17959 default:
17960 generate_exception_end(ctx, EXCP_RI);
17961 break;
17962 }
17963 break;
17964 case NM_POOL32F:
579b8ea9 17965 gen_pool32f_nanomips_insn(ctx);
c0280983
YK
17966 break;
17967 case NM_POOL32S:
17968 break;
17969 case NM_P_LUI:
17970 switch (extract32(ctx->opcode, 1, 1)) {
17971 case NM_LUI:
17972 if (rt != 0) {
17973 tcg_gen_movi_tl(cpu_gpr[rt],
17974 sextract32(ctx->opcode, 0, 1) << 31 |
17975 extract32(ctx->opcode, 2, 10) << 21 |
17976 extract32(ctx->opcode, 12, 9) << 12);
17977 }
17978 break;
17979 case NM_ALUIPC:
17980 if (rt != 0) {
17981 offset = sextract32(ctx->opcode, 0, 1) << 31 |
17982 extract32(ctx->opcode, 2, 10) << 21 |
17983 extract32(ctx->opcode, 12, 9) << 12;
17984 target_long addr;
17985 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
17986 tcg_gen_movi_tl(cpu_gpr[rt], addr);
17987 }
17988 break;
17989 }
17990 break;
17991 case NM_P_GP_BH:
8f1d9b6d
YK
17992 {
17993 uint32_t u = extract32(ctx->opcode, 0, 18);
17994
17995 switch (extract32(ctx->opcode, 18, 3)) {
17996 case NM_LBGP:
17997 gen_ld(ctx, OPC_LB, rt, 28, u);
17998 break;
17999 case NM_SBGP:
18000 gen_st(ctx, OPC_SB, rt, 28, u);
18001 break;
18002 case NM_LBUGP:
18003 gen_ld(ctx, OPC_LBU, rt, 28, u);
18004 break;
18005 case NM_ADDIUGP_B:
18006 if (rt != 0) {
18007 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
18008 }
18009 break;
18010 case NM_P_GP_LH:
18011 u &= ~1;
18012 switch (ctx->opcode & 1) {
18013 case NM_LHGP:
18014 gen_ld(ctx, OPC_LH, rt, 28, u);
18015 break;
18016 case NM_LHUGP:
18017 gen_ld(ctx, OPC_LHU, rt, 28, u);
18018 break;
18019 }
18020 break;
18021 case NM_P_GP_SH:
18022 u &= ~1;
18023 switch (ctx->opcode & 1) {
18024 case NM_SHGP:
18025 gen_st(ctx, OPC_SH, rt, 28, u);
18026 break;
18027 default:
18028 generate_exception_end(ctx, EXCP_RI);
18029 break;
18030 }
18031 break;
18032 case NM_P_GP_CP1:
18033 u &= ~0x3;
18034 switch (ctx->opcode & 0x3) {
18035 case NM_LWC1GP:
18036 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
18037 break;
18038 case NM_LDC1GP:
18039 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
18040 break;
18041 case NM_SWC1GP:
18042 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
18043 break;
18044 case NM_SDC1GP:
18045 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
18046 break;
18047 }
18048 break;
18049 default:
18050 generate_exception_end(ctx, EXCP_RI);
18051 break;
18052 }
18053 }
c0280983
YK
18054 break;
18055 case NM_P_LS_U12:
8f1d9b6d
YK
18056 {
18057 uint32_t u = extract32(ctx->opcode, 0, 12);
18058
18059 switch (extract32(ctx->opcode, 12, 4)) {
18060 case NM_P_PREFU12:
18061 if (rt == 31) {
18062 /* SYNCI */
18063 /* Break the TB to be able to sync copied instructions
18064 immediately */
18065 ctx->base.is_jmp = DISAS_STOP;
18066 } else {
18067 /* PREF */
18068 /* Treat as NOP. */
18069 }
18070 break;
18071 case NM_LB:
18072 gen_ld(ctx, OPC_LB, rt, rs, u);
18073 break;
18074 case NM_LH:
18075 gen_ld(ctx, OPC_LH, rt, rs, u);
18076 break;
18077 case NM_LW:
18078 gen_ld(ctx, OPC_LW, rt, rs, u);
18079 break;
18080 case NM_LBU:
18081 gen_ld(ctx, OPC_LBU, rt, rs, u);
18082 break;
18083 case NM_LHU:
18084 gen_ld(ctx, OPC_LHU, rt, rs, u);
18085 break;
18086 case NM_SB:
18087 gen_st(ctx, OPC_SB, rt, rs, u);
18088 break;
18089 case NM_SH:
18090 gen_st(ctx, OPC_SH, rt, rs, u);
18091 break;
18092 case NM_SW:
18093 gen_st(ctx, OPC_SW, rt, rs, u);
18094 break;
18095 case NM_LWC1:
18096 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
18097 break;
18098 case NM_LDC1:
18099 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
18100 break;
18101 case NM_SWC1:
18102 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
18103 break;
18104 case NM_SDC1:
18105 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
18106 break;
18107 default:
18108 generate_exception_end(ctx, EXCP_RI);
18109 break;
18110 }
18111 }
c0280983
YK
18112 break;
18113 case NM_P_LS_S9:
8f1d9b6d
YK
18114 {
18115 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
18116 extract32(ctx->opcode, 0, 8);
18117
18118 switch (extract32(ctx->opcode, 8, 3)) {
18119 case NM_P_LS_S0:
18120 switch (extract32(ctx->opcode, 11, 4)) {
18121 case NM_LBS9:
18122 gen_ld(ctx, OPC_LB, rt, rs, s);
18123 break;
18124 case NM_LHS9:
18125 gen_ld(ctx, OPC_LH, rt, rs, s);
18126 break;
18127 case NM_LWS9:
18128 gen_ld(ctx, OPC_LW, rt, rs, s);
18129 break;
18130 case NM_LBUS9:
18131 gen_ld(ctx, OPC_LBU, rt, rs, s);
18132 break;
18133 case NM_LHUS9:
18134 gen_ld(ctx, OPC_LHU, rt, rs, s);
18135 break;
18136 case NM_SBS9:
18137 gen_st(ctx, OPC_SB, rt, rs, s);
18138 break;
18139 case NM_SHS9:
18140 gen_st(ctx, OPC_SH, rt, rs, s);
18141 break;
18142 case NM_SWS9:
18143 gen_st(ctx, OPC_SW, rt, rs, s);
18144 break;
18145 case NM_LWC1S9:
18146 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
18147 break;
18148 case NM_LDC1S9:
18149 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
18150 break;
18151 case NM_SWC1S9:
18152 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
18153 break;
18154 case NM_SDC1S9:
18155 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
18156 break;
18157 case NM_P_PREFS9:
18158 if (rt == 31) {
18159 /* SYNCI */
18160 /* Break the TB to be able to sync copied instructions
18161 immediately */
18162 ctx->base.is_jmp = DISAS_STOP;
18163 } else {
18164 /* PREF */
18165 /* Treat as NOP. */
18166 }
18167 break;
18168 default:
18169 generate_exception_end(ctx, EXCP_RI);
18170 break;
18171 }
18172 break;
18173 case NM_P_LS_S1:
18174 switch (extract32(ctx->opcode, 11, 4)) {
18175 case NM_UALH:
18176 case NM_UASH:
18177 {
18178 TCGv t0 = tcg_temp_new();
18179 TCGv t1 = tcg_temp_new();
18180
18181 gen_base_offset_addr(ctx, t0, rs, s);
18182
18183 switch (extract32(ctx->opcode, 11, 4)) {
18184 case NM_UALH:
18185 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
18186 MO_UNALN);
18187 gen_store_gpr(t0, rt);
18188 break;
18189 case NM_UASH:
18190 gen_load_gpr(t1, rt);
18191 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
18192 MO_UNALN);
18193 break;
18194 }
18195 tcg_temp_free(t0);
18196 tcg_temp_free(t1);
18197 }
18198 break;
18199 case NM_P_LL:
18200 switch (ctx->opcode & 0x03) {
18201 case NM_LL:
18202 gen_ld(ctx, OPC_LL, rt, rs, s);
18203 break;
18204 case NM_LLWP:
0b16dcd1
AR
18205 check_xnp(ctx);
18206 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
18207 break;
18208 }
18209 break;
18210 case NM_P_SC:
18211 switch (ctx->opcode & 0x03) {
18212 case NM_SC:
18213 gen_st_cond(ctx, OPC_SC, rt, rs, s);
18214 break;
18215 case NM_SCWP:
0b16dcd1
AR
18216 check_xnp(ctx);
18217 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
8f1d9b6d
YK
18218 break;
18219 }
18220 break;
18221 case NM_CACHE:
18222 check_cp0_enabled(ctx);
18223 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
18224 gen_cache_operation(ctx, rt, rs, s);
18225 }
18226 break;
18227 }
18228 break;
18229 case NM_P_LS_WM:
18230 case NM_P_LS_UAWM:
18231 {
18232 int count = extract32(ctx->opcode, 12, 3);
18233 int counter = 0;
18234
18235 offset = sextract32(ctx->opcode, 15, 1) << 8 |
18236 extract32(ctx->opcode, 0, 8);
18237 TCGv va = tcg_temp_new();
18238 TCGv t1 = tcg_temp_new();
18239 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
18240 NM_P_LS_UAWM ? MO_UNALN : 0;
18241
18242 count = (count == 0) ? 8 : count;
18243 while (counter != count) {
18244 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
18245 int this_offset = offset + (counter << 2);
18246
18247 gen_base_offset_addr(ctx, va, rs, this_offset);
18248
18249 switch (extract32(ctx->opcode, 11, 1)) {
18250 case NM_LWM:
18251 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
18252 memop | MO_TESL);
18253 gen_store_gpr(t1, this_rt);
18254 if ((this_rt == rs) &&
18255 (counter != (count - 1))) {
18256 /* UNPREDICTABLE */
18257 }
18258 break;
18259 case NM_SWM:
18260 this_rt = (rt == 0) ? 0 : this_rt;
18261 gen_load_gpr(t1, this_rt);
18262 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
18263 memop | MO_TEUL);
18264 break;
18265 }
18266 counter++;
18267 }
18268 tcg_temp_free(va);
18269 tcg_temp_free(t1);
18270 }
18271 break;
18272 default:
18273 generate_exception_end(ctx, EXCP_RI);
18274 break;
18275 }
18276 }
c0280983
YK
18277 break;
18278 case NM_MOVE_BALC:
18279 break;
18280 case NM_P_BAL:
18281 break;
18282 case NM_P_J:
18283 break;
18284 case NM_P_BR1:
18285 break;
18286 case NM_P_BR2:
18287 break;
18288 case NM_P_BRI:
18289 break;
18290 default:
18291 generate_exception_end(ctx, EXCP_RI);
18292 break;
18293 }
18294 return 4;
18295}
18296
c533c0f4
AM
18297static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
18298{
ea4ca3c2
YK
18299 uint32_t op;
18300 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
18301 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
18302 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
8bdb7029 18303 int offset;
ea4ca3c2
YK
18304 int imm;
18305
18306 /* make sure instructions are on a halfword boundary */
18307 if (ctx->base.pc_next & 0x1) {
18308 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
18309 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
18310 tcg_temp_free(tmp);
18311 generate_exception_end(ctx, EXCP_AdEL);
18312 return 2;
18313 }
18314
18315 op = extract32(ctx->opcode, 10, 6);
18316 switch (op) {
18317 case NM_P16_MV:
8869ad02
YK
18318 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
18319 if (rt != 0) {
18320 /* MOVE */
18321 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
18322 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
18323 } else {
18324 /* P16.RI */
18325 switch (extract32(ctx->opcode, 3, 2)) {
18326 case NM_P16_SYSCALL:
18327 if (extract32(ctx->opcode, 2, 1) == 0) {
18328 generate_exception_end(ctx, EXCP_SYSCALL);
18329 } else {
18330 generate_exception_end(ctx, EXCP_RI);
18331 }
18332 break;
18333 case NM_BREAK16:
18334 generate_exception_end(ctx, EXCP_BREAK);
18335 break;
18336 case NM_SDBBP16:
18337 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
18338 gen_helper_do_semihosting(cpu_env);
18339 } else {
18340 if (ctx->hflags & MIPS_HFLAG_SBRI) {
18341 generate_exception_end(ctx, EXCP_RI);
18342 } else {
18343 generate_exception_end(ctx, EXCP_DBp);
18344 }
18345 }
18346 break;
18347 default:
18348 generate_exception_end(ctx, EXCP_RI);
18349 break;
18350 }
18351 }
ea4ca3c2
YK
18352 break;
18353 case NM_P16_SHIFT:
c46562fb
YK
18354 {
18355 int shift = extract32(ctx->opcode, 0, 3);
18356 uint32_t opc = 0;
18357 shift = (shift == 0) ? 8 : shift;
18358
18359 switch (extract32(ctx->opcode, 3, 1)) {
18360 case NM_SLL16:
18361 opc = OPC_SLL;
18362 break;
18363 case NM_SRL16:
18364 opc = OPC_SRL;
18365 break;
18366 }
18367 gen_shift_imm(ctx, opc, rt, rs, shift);
18368 }
ea4ca3c2
YK
18369 break;
18370 case NM_P16C:
8bdb7029
YK
18371 switch (ctx->opcode & 1) {
18372 case NM_POOL16C_0:
80845edf 18373 gen_pool16c_nanomips_insn(ctx);
8bdb7029
YK
18374 break;
18375 case NM_LWXS16:
18376 gen_ldxs(ctx, rt, rs, rd);
18377 break;
18378 }
ea4ca3c2
YK
18379 break;
18380 case NM_P16_A1:
18381 switch (extract32(ctx->opcode, 6, 1)) {
18382 case NM_ADDIUR1SP:
18383 imm = extract32(ctx->opcode, 0, 6) << 2;
18384 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
18385 break;
18386 default:
18387 generate_exception_end(ctx, EXCP_RI);
18388 break;
18389 }
18390 break;
18391 case NM_P16_A2:
18392 switch (extract32(ctx->opcode, 3, 1)) {
18393 case NM_ADDIUR2:
18394 imm = extract32(ctx->opcode, 0, 3) << 2;
18395 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
18396 break;
18397 case NM_P_ADDIURS5:
18398 rt = extract32(ctx->opcode, 5, 5);
18399 if (rt != 0) {
18400 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
18401 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
18402 (extract32(ctx->opcode, 0, 3));
18403 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
18404 }
18405 break;
18406 }
18407 break;
18408 case NM_P16_ADDU:
18409 switch (ctx->opcode & 0x1) {
18410 case NM_ADDU16:
18411 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18412 break;
18413 case NM_SUBU16:
18414 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18415 break;
18416 }
18417 break;
18418 case NM_P16_4X4:
18419 rt = (extract32(ctx->opcode, 9, 1) << 3) |
18420 extract32(ctx->opcode, 5, 3);
18421 rs = (extract32(ctx->opcode, 4, 1) << 3) |
18422 extract32(ctx->opcode, 0, 3);
18423 rt = decode_gpr_gpr4(rt);
18424 rs = decode_gpr_gpr4(rs);
18425 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
18426 (extract32(ctx->opcode, 3, 1))) {
18427 case NM_ADDU4X4:
18428 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
18429 break;
18430 case NM_MUL4X4:
18431 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
18432 break;
18433 default:
18434 generate_exception_end(ctx, EXCP_RI);
18435 break;
18436 }
18437 break;
18438 case NM_LI16:
8869ad02
YK
18439 {
18440 int imm = extract32(ctx->opcode, 0, 7);
18441 imm = (imm == 0x7f ? -1 : imm);
18442 if (rt != 0) {
18443 tcg_gen_movi_tl(cpu_gpr[rt], imm);
18444 }
18445 }
ea4ca3c2
YK
18446 break;
18447 case NM_ANDI16:
80845edf
YK
18448 {
18449 uint32_t u = extract32(ctx->opcode, 0, 4);
18450 u = (u == 12) ? 0xff :
18451 (u == 13) ? 0xffff : u;
18452 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
18453 }
ea4ca3c2
YK
18454 break;
18455 case NM_P16_LB:
8bdb7029
YK
18456 offset = extract32(ctx->opcode, 0, 2);
18457 switch (extract32(ctx->opcode, 2, 2)) {
18458 case NM_LB16:
18459 gen_ld(ctx, OPC_LB, rt, rs, offset);
18460 break;
18461 case NM_SB16:
18462 rt = decode_gpr_gpr3_src_store(
18463 NANOMIPS_EXTRACT_RD(ctx->opcode));
18464 gen_st(ctx, OPC_SB, rt, rs, offset);
18465 break;
18466 case NM_LBU16:
18467 gen_ld(ctx, OPC_LBU, rt, rs, offset);
18468 break;
18469 default:
18470 generate_exception_end(ctx, EXCP_RI);
18471 break;
18472 }
ea4ca3c2
YK
18473 break;
18474 case NM_P16_LH:
8bdb7029
YK
18475 offset = extract32(ctx->opcode, 1, 2) << 1;
18476 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
18477 case NM_LH16:
18478 gen_ld(ctx, OPC_LH, rt, rs, offset);
18479 break;
18480 case NM_SH16:
18481 rt = decode_gpr_gpr3_src_store(
18482 NANOMIPS_EXTRACT_RD(ctx->opcode));
18483 gen_st(ctx, OPC_SH, rt, rs, offset);
18484 break;
18485 case NM_LHU16:
18486 gen_ld(ctx, OPC_LHU, rt, rs, offset);
18487 break;
18488 default:
18489 generate_exception_end(ctx, EXCP_RI);
18490 break;
18491 }
ea4ca3c2
YK
18492 break;
18493 case NM_LW16:
8bdb7029
YK
18494 offset = extract32(ctx->opcode, 0, 4) << 2;
18495 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
18496 break;
18497 case NM_LWSP16:
8bdb7029
YK
18498 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
18499 offset = extract32(ctx->opcode, 0, 5) << 2;
18500 gen_ld(ctx, OPC_LW, rt, 29, offset);
ea4ca3c2
YK
18501 break;
18502 case NM_LW4X4:
8bdb7029
YK
18503 rt = (extract32(ctx->opcode, 9, 1) << 3) |
18504 extract32(ctx->opcode, 5, 3);
18505 rs = (extract32(ctx->opcode, 4, 1) << 3) |
18506 extract32(ctx->opcode, 0, 3);
18507 offset = (extract32(ctx->opcode, 3, 1) << 3) |
18508 (extract32(ctx->opcode, 8, 1) << 2);
18509 rt = decode_gpr_gpr4(rt);
18510 rs = decode_gpr_gpr4(rs);
18511 gen_ld(ctx, OPC_LW, rt, rs, offset);
ea4ca3c2
YK
18512 break;
18513 case NM_SW4X4:
8bdb7029
YK
18514 rt = (extract32(ctx->opcode, 9, 1) << 3) |
18515 extract32(ctx->opcode, 5, 3);
18516 rs = (extract32(ctx->opcode, 4, 1) << 3) |
18517 extract32(ctx->opcode, 0, 3);
18518 offset = (extract32(ctx->opcode, 3, 1) << 3) |
18519 (extract32(ctx->opcode, 8, 1) << 2);
18520 rt = decode_gpr_gpr4_zero(rt);
18521 rs = decode_gpr_gpr4(rs);
18522 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
18523 break;
18524 case NM_LWGP16:
8bdb7029
YK
18525 offset = extract32(ctx->opcode, 0, 7) << 2;
18526 gen_ld(ctx, OPC_LW, rt, 28, offset);
ea4ca3c2
YK
18527 break;
18528 case NM_SWSP16:
8bdb7029
YK
18529 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
18530 offset = extract32(ctx->opcode, 0, 5) << 2;
18531 gen_st(ctx, OPC_SW, rt, 29, offset);
ea4ca3c2
YK
18532 break;
18533 case NM_SW16:
8bdb7029
YK
18534 rt = decode_gpr_gpr3_src_store(
18535 NANOMIPS_EXTRACT_RD(ctx->opcode));
18536 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
18537 offset = extract32(ctx->opcode, 0, 4) << 2;
18538 gen_st(ctx, OPC_SW, rt, rs, offset);
ea4ca3c2
YK
18539 break;
18540 case NM_SWGP16:
8bdb7029
YK
18541 rt = decode_gpr_gpr3_src_store(
18542 NANOMIPS_EXTRACT_RD(ctx->opcode));
18543 offset = extract32(ctx->opcode, 0, 7) << 2;
18544 gen_st(ctx, OPC_SW, rt, 28, offset);
ea4ca3c2
YK
18545 break;
18546 case NM_BC16:
764371d2
SM
18547 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
18548 (sextract32(ctx->opcode, 0, 1) << 10) |
18549 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
18550 break;
18551 case NM_BALC16:
764371d2
SM
18552 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
18553 (sextract32(ctx->opcode, 0, 1) << 10) |
18554 (extract32(ctx->opcode, 1, 9) << 1));
ea4ca3c2
YK
18555 break;
18556 case NM_BEQZC16:
764371d2
SM
18557 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
18558 (sextract32(ctx->opcode, 0, 1) << 7) |
18559 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
18560 break;
18561 case NM_BNEZC16:
764371d2
SM
18562 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
18563 (sextract32(ctx->opcode, 0, 1) << 7) |
18564 (extract32(ctx->opcode, 1, 6) << 1));
ea4ca3c2
YK
18565 break;
18566 case NM_P16_BR:
764371d2
SM
18567 switch (ctx->opcode & 0xf) {
18568 case 0:
18569 /* P16.JRC */
18570 switch (extract32(ctx->opcode, 4, 1)) {
18571 case NM_JRC:
18572 gen_compute_branch_nm(ctx, OPC_JR, 2,
18573 extract32(ctx->opcode, 5, 5), 0, 0);
18574 break;
18575 case NM_JALRC16:
18576 gen_compute_branch_nm(ctx, OPC_JALR, 2,
18577 extract32(ctx->opcode, 5, 5), 31, 0);
18578 break;
18579 }
18580 break;
18581 default:
18582 {
18583 /* P16.BRI */
18584 uint32_t opc = extract32(ctx->opcode, 4, 3) <
18585 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
18586 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
18587 extract32(ctx->opcode, 0, 4) << 1);
18588 }
18589 break;
18590 }
ea4ca3c2
YK
18591 break;
18592 case NM_P16_SR:
bf0718c5
SM
18593 {
18594 int count = extract32(ctx->opcode, 0, 4);
18595 int u = extract32(ctx->opcode, 4, 4) << 4;
18596
18597 rt = 30 + extract32(ctx->opcode, 9, 1);
18598 switch (extract32(ctx->opcode, 8, 1)) {
18599 case NM_SAVE16:
18600 gen_save(ctx, rt, count, 0, u);
18601 break;
18602 case NM_RESTORE_JRC16:
18603 gen_restore(ctx, rt, count, 0, u);
18604 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
18605 break;
18606 }
18607 }
ea4ca3c2
YK
18608 break;
18609 case NM_MOVEP:
ea4ca3c2 18610 case NM_MOVEPREV:
4d18232c
YK
18611 {
18612 static const int gpr2reg1[] = {4, 5, 6, 7};
18613 static const int gpr2reg2[] = {5, 6, 7, 8};
18614 int re;
18615 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
18616 extract32(ctx->opcode, 8, 1);
18617 int r1 = gpr2reg1[rd2];
18618 int r2 = gpr2reg2[rd2];
18619 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
18620 extract32(ctx->opcode, 0, 3);
18621 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
18622 extract32(ctx->opcode, 5, 3);
18623 TCGv t0 = tcg_temp_new();
18624 TCGv t1 = tcg_temp_new();
18625 if (op == NM_MOVEP) {
18626 rd = r1;
18627 re = r2;
18628 rs = decode_gpr_gpr4_zero(r3);
18629 rt = decode_gpr_gpr4_zero(r4);
18630 } else {
18631 rd = decode_gpr_gpr4(r3);
18632 re = decode_gpr_gpr4(r4);
18633 rs = r1;
18634 rt = r2;
18635 }
18636 gen_load_gpr(t0, rs);
18637 gen_load_gpr(t1, rt);
18638 tcg_gen_mov_tl(cpu_gpr[rd], t0);
18639 tcg_gen_mov_tl(cpu_gpr[re], t1);
18640 tcg_temp_free(t0);
18641 tcg_temp_free(t1);
18642 }
ea4ca3c2
YK
18643 break;
18644 default:
c0280983 18645 return decode_nanomips_32_48_opc(env, ctx);
ea4ca3c2
YK
18646 }
18647
c533c0f4
AM
18648 return 2;
18649}
18650
18651
3c824109
NF
18652/* SmartMIPS extension to MIPS32 */
18653
18654#if defined(TARGET_MIPS64)
18655
18656/* MDMX extension to MIPS64 */
18657
18658#endif
18659
9b1a1d68 18660/* MIPSDSP functions. */
d75c135e 18661static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
9b1a1d68
JL
18662 int rd, int base, int offset)
18663{
9b1a1d68
JL
18664 TCGv t0;
18665
9b1a1d68
JL
18666 check_dsp(ctx);
18667 t0 = tcg_temp_new();
18668
18669 if (base == 0) {
18670 gen_load_gpr(t0, offset);
18671 } else if (offset == 0) {
18672 gen_load_gpr(t0, base);
18673 } else {
18674 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
18675 }
18676
9b1a1d68
JL
18677 switch (opc) {
18678 case OPC_LBUX:
5f68f5ae 18679 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
9b1a1d68 18680 gen_store_gpr(t0, rd);
9b1a1d68
JL
18681 break;
18682 case OPC_LHX:
5f68f5ae 18683 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
9b1a1d68 18684 gen_store_gpr(t0, rd);
9b1a1d68
JL
18685 break;
18686 case OPC_LWX:
5f68f5ae 18687 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9b1a1d68 18688 gen_store_gpr(t0, rd);
9b1a1d68
JL
18689 break;
18690#if defined(TARGET_MIPS64)
18691 case OPC_LDX:
5f68f5ae 18692 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
9b1a1d68 18693 gen_store_gpr(t0, rd);
9b1a1d68
JL
18694 break;
18695#endif
18696 }
9b1a1d68
JL
18697 tcg_temp_free(t0);
18698}
18699
461c08df
JL
18700static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
18701 int ret, int v1, int v2)
18702{
461c08df
JL
18703 TCGv v1_t;
18704 TCGv v2_t;
18705
18706 if (ret == 0) {
18707 /* Treat as NOP. */
461c08df
JL
18708 return;
18709 }
18710
18711 v1_t = tcg_temp_new();
18712 v2_t = tcg_temp_new();
18713
18714 gen_load_gpr(v1_t, v1);
18715 gen_load_gpr(v2_t, v2);
18716
18717 switch (op1) {
18718 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
18719 case OPC_MULT_G_2E:
18720 check_dspr2(ctx);
18721 switch (op2) {
18722 case OPC_ADDUH_QB:
18723 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
18724 break;
18725 case OPC_ADDUH_R_QB:
18726 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
18727 break;
18728 case OPC_ADDQH_PH:
18729 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
18730 break;
18731 case OPC_ADDQH_R_PH:
18732 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
18733 break;
18734 case OPC_ADDQH_W:
18735 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
18736 break;
18737 case OPC_ADDQH_R_W:
18738 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
18739 break;
18740 case OPC_SUBUH_QB:
18741 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
18742 break;
18743 case OPC_SUBUH_R_QB:
18744 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
18745 break;
18746 case OPC_SUBQH_PH:
18747 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
18748 break;
18749 case OPC_SUBQH_R_PH:
18750 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
18751 break;
18752 case OPC_SUBQH_W:
18753 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
18754 break;
18755 case OPC_SUBQH_R_W:
18756 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
18757 break;
18758 }
18759 break;
18760 case OPC_ABSQ_S_PH_DSP:
18761 switch (op2) {
18762 case OPC_ABSQ_S_QB:
18763 check_dspr2(ctx);
18764 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
18765 break;
18766 case OPC_ABSQ_S_PH:
18767 check_dsp(ctx);
18768 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
18769 break;
18770 case OPC_ABSQ_S_W:
18771 check_dsp(ctx);
18772 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
18773 break;
18774 case OPC_PRECEQ_W_PHL:
18775 check_dsp(ctx);
18776 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
18777 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18778 break;
18779 case OPC_PRECEQ_W_PHR:
18780 check_dsp(ctx);
18781 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
18782 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
18783 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18784 break;
18785 case OPC_PRECEQU_PH_QBL:
18786 check_dsp(ctx);
18787 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
18788 break;
18789 case OPC_PRECEQU_PH_QBR:
18790 check_dsp(ctx);
18791 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
18792 break;
18793 case OPC_PRECEQU_PH_QBLA:
18794 check_dsp(ctx);
18795 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
18796 break;
18797 case OPC_PRECEQU_PH_QBRA:
18798 check_dsp(ctx);
18799 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
18800 break;
18801 case OPC_PRECEU_PH_QBL:
18802 check_dsp(ctx);
18803 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
18804 break;
18805 case OPC_PRECEU_PH_QBR:
18806 check_dsp(ctx);
18807 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
18808 break;
18809 case OPC_PRECEU_PH_QBLA:
18810 check_dsp(ctx);
18811 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
18812 break;
18813 case OPC_PRECEU_PH_QBRA:
18814 check_dsp(ctx);
18815 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
18816 break;
18817 }
18818 break;
18819 case OPC_ADDU_QB_DSP:
18820 switch (op2) {
18821 case OPC_ADDQ_PH:
18822 check_dsp(ctx);
18823 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18824 break;
18825 case OPC_ADDQ_S_PH:
18826 check_dsp(ctx);
18827 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18828 break;
18829 case OPC_ADDQ_S_W:
18830 check_dsp(ctx);
18831 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18832 break;
18833 case OPC_ADDU_QB:
18834 check_dsp(ctx);
18835 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18836 break;
18837 case OPC_ADDU_S_QB:
18838 check_dsp(ctx);
18839 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18840 break;
18841 case OPC_ADDU_PH:
18842 check_dspr2(ctx);
18843 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18844 break;
18845 case OPC_ADDU_S_PH:
18846 check_dspr2(ctx);
18847 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18848 break;
18849 case OPC_SUBQ_PH:
18850 check_dsp(ctx);
18851 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18852 break;
18853 case OPC_SUBQ_S_PH:
18854 check_dsp(ctx);
18855 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18856 break;
18857 case OPC_SUBQ_S_W:
18858 check_dsp(ctx);
18859 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18860 break;
18861 case OPC_SUBU_QB:
18862 check_dsp(ctx);
18863 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18864 break;
18865 case OPC_SUBU_S_QB:
18866 check_dsp(ctx);
18867 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18868 break;
18869 case OPC_SUBU_PH:
18870 check_dspr2(ctx);
18871 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18872 break;
18873 case OPC_SUBU_S_PH:
18874 check_dspr2(ctx);
18875 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18876 break;
18877 case OPC_ADDSC:
18878 check_dsp(ctx);
18879 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18880 break;
18881 case OPC_ADDWC:
18882 check_dsp(ctx);
18883 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18884 break;
18885 case OPC_MODSUB:
18886 check_dsp(ctx);
18887 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
18888 break;
18889 case OPC_RADDU_W_QB:
18890 check_dsp(ctx);
18891 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
18892 break;
18893 }
18894 break;
18895 case OPC_CMPU_EQ_QB_DSP:
18896 switch (op2) {
18897 case OPC_PRECR_QB_PH:
18898 check_dspr2(ctx);
18899 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
18900 break;
18901 case OPC_PRECRQ_QB_PH:
18902 check_dsp(ctx);
18903 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
18904 break;
18905 case OPC_PRECR_SRA_PH_W:
18906 check_dspr2(ctx);
18907 {
18908 TCGv_i32 sa_t = tcg_const_i32(v2);
18909 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
18910 cpu_gpr[ret]);
18911 tcg_temp_free_i32(sa_t);
18912 break;
18913 }
18914 case OPC_PRECR_SRA_R_PH_W:
18915 check_dspr2(ctx);
18916 {
18917 TCGv_i32 sa_t = tcg_const_i32(v2);
18918 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
18919 cpu_gpr[ret]);
18920 tcg_temp_free_i32(sa_t);
18921 break;
18922 }
18923 case OPC_PRECRQ_PH_W:
18924 check_dsp(ctx);
18925 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
18926 break;
18927 case OPC_PRECRQ_RS_PH_W:
18928 check_dsp(ctx);
18929 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18930 break;
18931 case OPC_PRECRQU_S_QB_PH:
18932 check_dsp(ctx);
18933 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
18934 break;
18935 }
18936 break;
18937#ifdef TARGET_MIPS64
18938 case OPC_ABSQ_S_QH_DSP:
18939 switch (op2) {
18940 case OPC_PRECEQ_L_PWL:
18941 check_dsp(ctx);
18942 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
18943 break;
18944 case OPC_PRECEQ_L_PWR:
18945 check_dsp(ctx);
18946 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
18947 break;
18948 case OPC_PRECEQ_PW_QHL:
18949 check_dsp(ctx);
18950 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
18951 break;
18952 case OPC_PRECEQ_PW_QHR:
18953 check_dsp(ctx);
18954 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
18955 break;
18956 case OPC_PRECEQ_PW_QHLA:
18957 check_dsp(ctx);
18958 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
18959 break;
18960 case OPC_PRECEQ_PW_QHRA:
18961 check_dsp(ctx);
18962 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
18963 break;
18964 case OPC_PRECEQU_QH_OBL:
18965 check_dsp(ctx);
18966 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
18967 break;
18968 case OPC_PRECEQU_QH_OBR:
18969 check_dsp(ctx);
18970 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
18971 break;
18972 case OPC_PRECEQU_QH_OBLA:
18973 check_dsp(ctx);
18974 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
18975 break;
18976 case OPC_PRECEQU_QH_OBRA:
18977 check_dsp(ctx);
18978 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
18979 break;
18980 case OPC_PRECEU_QH_OBL:
18981 check_dsp(ctx);
18982 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
18983 break;
18984 case OPC_PRECEU_QH_OBR:
18985 check_dsp(ctx);
18986 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
18987 break;
18988 case OPC_PRECEU_QH_OBLA:
18989 check_dsp(ctx);
18990 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
18991 break;
18992 case OPC_PRECEU_QH_OBRA:
18993 check_dsp(ctx);
18994 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
18995 break;
18996 case OPC_ABSQ_S_OB:
18997 check_dspr2(ctx);
18998 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
18999 break;
19000 case OPC_ABSQ_S_PW:
19001 check_dsp(ctx);
19002 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
19003 break;
19004 case OPC_ABSQ_S_QH:
19005 check_dsp(ctx);
19006 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
19007 break;
19008 }
19009 break;
19010 case OPC_ADDU_OB_DSP:
19011 switch (op2) {
19012 case OPC_RADDU_L_OB:
19013 check_dsp(ctx);
19014 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
19015 break;
19016 case OPC_SUBQ_PW:
19017 check_dsp(ctx);
19018 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19019 break;
19020 case OPC_SUBQ_S_PW:
19021 check_dsp(ctx);
19022 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19023 break;
19024 case OPC_SUBQ_QH:
19025 check_dsp(ctx);
19026 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19027 break;
19028 case OPC_SUBQ_S_QH:
19029 check_dsp(ctx);
19030 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19031 break;
19032 case OPC_SUBU_OB:
19033 check_dsp(ctx);
19034 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19035 break;
19036 case OPC_SUBU_S_OB:
19037 check_dsp(ctx);
19038 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19039 break;
19040 case OPC_SUBU_QH:
19041 check_dspr2(ctx);
19042 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19043 break;
19044 case OPC_SUBU_S_QH:
19045 check_dspr2(ctx);
19046 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19047 break;
19048 case OPC_SUBUH_OB:
19049 check_dspr2(ctx);
19050 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
19051 break;
19052 case OPC_SUBUH_R_OB:
19053 check_dspr2(ctx);
19054 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
19055 break;
19056 case OPC_ADDQ_PW:
19057 check_dsp(ctx);
19058 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19059 break;
19060 case OPC_ADDQ_S_PW:
19061 check_dsp(ctx);
19062 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19063 break;
19064 case OPC_ADDQ_QH:
19065 check_dsp(ctx);
19066 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19067 break;
19068 case OPC_ADDQ_S_QH:
19069 check_dsp(ctx);
19070 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19071 break;
19072 case OPC_ADDU_OB:
19073 check_dsp(ctx);
19074 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19075 break;
19076 case OPC_ADDU_S_OB:
19077 check_dsp(ctx);
19078 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19079 break;
19080 case OPC_ADDU_QH:
19081 check_dspr2(ctx);
19082 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19083 break;
19084 case OPC_ADDU_S_QH:
19085 check_dspr2(ctx);
19086 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19087 break;
19088 case OPC_ADDUH_OB:
19089 check_dspr2(ctx);
19090 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
19091 break;
19092 case OPC_ADDUH_R_OB:
19093 check_dspr2(ctx);
19094 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
19095 break;
19096 }
19097 break;
19098 case OPC_CMPU_EQ_OB_DSP:
19099 switch (op2) {
19100 case OPC_PRECR_OB_QH:
19101 check_dspr2(ctx);
19102 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
19103 break;
19104 case OPC_PRECR_SRA_QH_PW:
19105 check_dspr2(ctx);
19106 {
19107 TCGv_i32 ret_t = tcg_const_i32(ret);
19108 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
19109 tcg_temp_free_i32(ret_t);
19110 break;
19111 }
19112 case OPC_PRECR_SRA_R_QH_PW:
19113 check_dspr2(ctx);
19114 {
19115 TCGv_i32 sa_v = tcg_const_i32(ret);
19116 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
19117 tcg_temp_free_i32(sa_v);
19118 break;
19119 }
19120 case OPC_PRECRQ_OB_QH:
19121 check_dsp(ctx);
19122 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
19123 break;
19124 case OPC_PRECRQ_PW_L:
19125 check_dsp(ctx);
19126 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
19127 break;
19128 case OPC_PRECRQ_QH_PW:
19129 check_dsp(ctx);
19130 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
19131 break;
19132 case OPC_PRECRQ_RS_QH_PW:
19133 check_dsp(ctx);
19134 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19135 break;
19136 case OPC_PRECRQU_S_OB_QH:
19137 check_dsp(ctx);
19138 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19139 break;
19140 }
19141 break;
19142#endif
19143 }
19144
19145 tcg_temp_free(v1_t);
19146 tcg_temp_free(v2_t);
461c08df 19147}
9b1a1d68 19148
77c5fa8b
JL
19149static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
19150 int ret, int v1, int v2)
19151{
19152 uint32_t op2;
77c5fa8b
JL
19153 TCGv t0;
19154 TCGv v1_t;
19155 TCGv v2_t;
19156
19157 if (ret == 0) {
19158 /* Treat as NOP. */
77c5fa8b
JL
19159 return;
19160 }
19161
19162 t0 = tcg_temp_new();
19163 v1_t = tcg_temp_new();
19164 v2_t = tcg_temp_new();
19165
19166 tcg_gen_movi_tl(t0, v1);
19167 gen_load_gpr(v1_t, v1);
19168 gen_load_gpr(v2_t, v2);
19169
19170 switch (opc) {
19171 case OPC_SHLL_QB_DSP:
19172 {
19173 op2 = MASK_SHLL_QB(ctx->opcode);
19174 switch (op2) {
19175 case OPC_SHLL_QB:
19176 check_dsp(ctx);
19177 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
19178 break;
19179 case OPC_SHLLV_QB:
19180 check_dsp(ctx);
19181 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19182 break;
19183 case OPC_SHLL_PH:
19184 check_dsp(ctx);
19185 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
19186 break;
19187 case OPC_SHLLV_PH:
19188 check_dsp(ctx);
19189 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19190 break;
19191 case OPC_SHLL_S_PH:
19192 check_dsp(ctx);
19193 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
19194 break;
19195 case OPC_SHLLV_S_PH:
19196 check_dsp(ctx);
19197 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19198 break;
19199 case OPC_SHLL_S_W:
19200 check_dsp(ctx);
19201 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
19202 break;
19203 case OPC_SHLLV_S_W:
19204 check_dsp(ctx);
19205 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19206 break;
19207 case OPC_SHRL_QB:
19208 check_dsp(ctx);
19209 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
19210 break;
19211 case OPC_SHRLV_QB:
19212 check_dsp(ctx);
19213 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
19214 break;
19215 case OPC_SHRL_PH:
19216 check_dspr2(ctx);
19217 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
19218 break;
19219 case OPC_SHRLV_PH:
19220 check_dspr2(ctx);
19221 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
19222 break;
19223 case OPC_SHRA_QB:
19224 check_dspr2(ctx);
19225 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
19226 break;
19227 case OPC_SHRA_R_QB:
19228 check_dspr2(ctx);
19229 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
19230 break;
19231 case OPC_SHRAV_QB:
19232 check_dspr2(ctx);
19233 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
19234 break;
19235 case OPC_SHRAV_R_QB:
19236 check_dspr2(ctx);
19237 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
19238 break;
19239 case OPC_SHRA_PH:
19240 check_dsp(ctx);
19241 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
19242 break;
19243 case OPC_SHRA_R_PH:
19244 check_dsp(ctx);
19245 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
19246 break;
19247 case OPC_SHRAV_PH:
19248 check_dsp(ctx);
19249 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
19250 break;
19251 case OPC_SHRAV_R_PH:
19252 check_dsp(ctx);
19253 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
19254 break;
19255 case OPC_SHRA_R_W:
19256 check_dsp(ctx);
19257 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
19258 break;
19259 case OPC_SHRAV_R_W:
19260 check_dsp(ctx);
19261 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
19262 break;
19263 default: /* Invalid */
19264 MIPS_INVAL("MASK SHLL.QB");
9c708c7f 19265 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
19266 break;
19267 }
19268 break;
19269 }
19270#ifdef TARGET_MIPS64
19271 case OPC_SHLL_OB_DSP:
19272 op2 = MASK_SHLL_OB(ctx->opcode);
19273 switch (op2) {
19274 case OPC_SHLL_PW:
19275 check_dsp(ctx);
19276 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
19277 break;
19278 case OPC_SHLLV_PW:
19279 check_dsp(ctx);
19280 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
19281 break;
19282 case OPC_SHLL_S_PW:
19283 check_dsp(ctx);
19284 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
19285 break;
19286 case OPC_SHLLV_S_PW:
19287 check_dsp(ctx);
19288 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
19289 break;
19290 case OPC_SHLL_OB:
19291 check_dsp(ctx);
19292 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
19293 break;
19294 case OPC_SHLLV_OB:
19295 check_dsp(ctx);
19296 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
19297 break;
19298 case OPC_SHLL_QH:
19299 check_dsp(ctx);
19300 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
19301 break;
19302 case OPC_SHLLV_QH:
19303 check_dsp(ctx);
19304 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
19305 break;
19306 case OPC_SHLL_S_QH:
19307 check_dsp(ctx);
19308 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
19309 break;
19310 case OPC_SHLLV_S_QH:
19311 check_dsp(ctx);
19312 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
19313 break;
19314 case OPC_SHRA_OB:
19315 check_dspr2(ctx);
19316 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
19317 break;
19318 case OPC_SHRAV_OB:
19319 check_dspr2(ctx);
19320 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
19321 break;
19322 case OPC_SHRA_R_OB:
19323 check_dspr2(ctx);
19324 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
19325 break;
19326 case OPC_SHRAV_R_OB:
19327 check_dspr2(ctx);
19328 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
19329 break;
19330 case OPC_SHRA_PW:
19331 check_dsp(ctx);
19332 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
19333 break;
19334 case OPC_SHRAV_PW:
19335 check_dsp(ctx);
19336 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
19337 break;
19338 case OPC_SHRA_R_PW:
19339 check_dsp(ctx);
19340 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
19341 break;
19342 case OPC_SHRAV_R_PW:
19343 check_dsp(ctx);
19344 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
19345 break;
19346 case OPC_SHRA_QH:
19347 check_dsp(ctx);
19348 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
19349 break;
19350 case OPC_SHRAV_QH:
19351 check_dsp(ctx);
19352 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
19353 break;
19354 case OPC_SHRA_R_QH:
19355 check_dsp(ctx);
19356 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
19357 break;
19358 case OPC_SHRAV_R_QH:
19359 check_dsp(ctx);
19360 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
19361 break;
19362 case OPC_SHRL_OB:
19363 check_dsp(ctx);
19364 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
19365 break;
19366 case OPC_SHRLV_OB:
19367 check_dsp(ctx);
19368 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
19369 break;
19370 case OPC_SHRL_QH:
19371 check_dspr2(ctx);
19372 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
19373 break;
19374 case OPC_SHRLV_QH:
19375 check_dspr2(ctx);
19376 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
19377 break;
19378 default: /* Invalid */
19379 MIPS_INVAL("MASK SHLL.OB");
9c708c7f 19380 generate_exception_end(ctx, EXCP_RI);
77c5fa8b
JL
19381 break;
19382 }
19383 break;
19384#endif
19385 }
19386
19387 tcg_temp_free(t0);
19388 tcg_temp_free(v1_t);
19389 tcg_temp_free(v2_t);
77c5fa8b
JL
19390}
19391
a22260ae
JL
19392static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
19393 int ret, int v1, int v2, int check_ret)
19394{
a22260ae
JL
19395 TCGv_i32 t0;
19396 TCGv v1_t;
19397 TCGv v2_t;
19398
19399 if ((ret == 0) && (check_ret == 1)) {
19400 /* Treat as NOP. */
a22260ae
JL
19401 return;
19402 }
19403
19404 t0 = tcg_temp_new_i32();
19405 v1_t = tcg_temp_new();
19406 v2_t = tcg_temp_new();
19407
19408 tcg_gen_movi_i32(t0, ret);
19409 gen_load_gpr(v1_t, v1);
19410 gen_load_gpr(v2_t, v2);
19411
19412 switch (op1) {
19413 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
19414 * the same mask and op1. */
19415 case OPC_MULT_G_2E:
639eadb9 19416 check_dspr2(ctx);
a22260ae
JL
19417 switch (op2) {
19418 case OPC_MUL_PH:
19419 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19420 break;
19421 case OPC_MUL_S_PH:
19422 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19423 break;
19424 case OPC_MULQ_S_W:
19425 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19426 break;
19427 case OPC_MULQ_RS_W:
19428 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19429 break;
19430 }
19431 break;
19432 case OPC_DPA_W_PH_DSP:
19433 switch (op2) {
19434 case OPC_DPAU_H_QBL:
19435 check_dsp(ctx);
19436 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
19437 break;
19438 case OPC_DPAU_H_QBR:
19439 check_dsp(ctx);
19440 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
19441 break;
19442 case OPC_DPSU_H_QBL:
19443 check_dsp(ctx);
19444 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
19445 break;
19446 case OPC_DPSU_H_QBR:
19447 check_dsp(ctx);
19448 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
19449 break;
19450 case OPC_DPA_W_PH:
19451 check_dspr2(ctx);
19452 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
19453 break;
19454 case OPC_DPAX_W_PH:
19455 check_dspr2(ctx);
19456 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
19457 break;
19458 case OPC_DPAQ_S_W_PH:
19459 check_dsp(ctx);
19460 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
19461 break;
19462 case OPC_DPAQX_S_W_PH:
19463 check_dspr2(ctx);
19464 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
19465 break;
19466 case OPC_DPAQX_SA_W_PH:
19467 check_dspr2(ctx);
19468 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
19469 break;
19470 case OPC_DPS_W_PH:
19471 check_dspr2(ctx);
19472 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
19473 break;
19474 case OPC_DPSX_W_PH:
19475 check_dspr2(ctx);
19476 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
19477 break;
19478 case OPC_DPSQ_S_W_PH:
19479 check_dsp(ctx);
19480 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
19481 break;
19482 case OPC_DPSQX_S_W_PH:
19483 check_dspr2(ctx);
19484 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
19485 break;
19486 case OPC_DPSQX_SA_W_PH:
19487 check_dspr2(ctx);
19488 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
19489 break;
19490 case OPC_MULSAQ_S_W_PH:
19491 check_dsp(ctx);
19492 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
19493 break;
19494 case OPC_DPAQ_SA_L_W:
19495 check_dsp(ctx);
19496 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
19497 break;
19498 case OPC_DPSQ_SA_L_W:
19499 check_dsp(ctx);
19500 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
19501 break;
19502 case OPC_MAQ_S_W_PHL:
19503 check_dsp(ctx);
19504 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
19505 break;
19506 case OPC_MAQ_S_W_PHR:
19507 check_dsp(ctx);
19508 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
19509 break;
19510 case OPC_MAQ_SA_W_PHL:
19511 check_dsp(ctx);
19512 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
19513 break;
19514 case OPC_MAQ_SA_W_PHR:
19515 check_dsp(ctx);
19516 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
19517 break;
19518 case OPC_MULSA_W_PH:
19519 check_dspr2(ctx);
19520 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
19521 break;
19522 }
19523 break;
19524#ifdef TARGET_MIPS64
19525 case OPC_DPAQ_W_QH_DSP:
19526 {
19527 int ac = ret & 0x03;
19528 tcg_gen_movi_i32(t0, ac);
19529
19530 switch (op2) {
19531 case OPC_DMADD:
19532 check_dsp(ctx);
19533 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
19534 break;
19535 case OPC_DMADDU:
19536 check_dsp(ctx);
19537 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
19538 break;
19539 case OPC_DMSUB:
19540 check_dsp(ctx);
19541 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
19542 break;
19543 case OPC_DMSUBU:
19544 check_dsp(ctx);
19545 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
19546 break;
19547 case OPC_DPA_W_QH:
19548 check_dspr2(ctx);
19549 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
19550 break;
19551 case OPC_DPAQ_S_W_QH:
19552 check_dsp(ctx);
19553 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
19554 break;
19555 case OPC_DPAQ_SA_L_PW:
19556 check_dsp(ctx);
19557 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
19558 break;
19559 case OPC_DPAU_H_OBL:
19560 check_dsp(ctx);
19561 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
19562 break;
19563 case OPC_DPAU_H_OBR:
19564 check_dsp(ctx);
19565 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
19566 break;
19567 case OPC_DPS_W_QH:
19568 check_dspr2(ctx);
19569 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
19570 break;
19571 case OPC_DPSQ_S_W_QH:
19572 check_dsp(ctx);
19573 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
19574 break;
19575 case OPC_DPSQ_SA_L_PW:
19576 check_dsp(ctx);
19577 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
19578 break;
19579 case OPC_DPSU_H_OBL:
19580 check_dsp(ctx);
19581 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
19582 break;
19583 case OPC_DPSU_H_OBR:
19584 check_dsp(ctx);
19585 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
19586 break;
19587 case OPC_MAQ_S_L_PWL:
19588 check_dsp(ctx);
19589 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
19590 break;
19591 case OPC_MAQ_S_L_PWR:
19592 check_dsp(ctx);
19593 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
19594 break;
19595 case OPC_MAQ_S_W_QHLL:
19596 check_dsp(ctx);
19597 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
19598 break;
19599 case OPC_MAQ_SA_W_QHLL:
19600 check_dsp(ctx);
19601 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
19602 break;
19603 case OPC_MAQ_S_W_QHLR:
19604 check_dsp(ctx);
19605 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
19606 break;
19607 case OPC_MAQ_SA_W_QHLR:
19608 check_dsp(ctx);
19609 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
19610 break;
19611 case OPC_MAQ_S_W_QHRL:
19612 check_dsp(ctx);
19613 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
19614 break;
19615 case OPC_MAQ_SA_W_QHRL:
19616 check_dsp(ctx);
19617 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
19618 break;
19619 case OPC_MAQ_S_W_QHRR:
19620 check_dsp(ctx);
19621 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
19622 break;
19623 case OPC_MAQ_SA_W_QHRR:
19624 check_dsp(ctx);
19625 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
19626 break;
19627 case OPC_MULSAQ_S_L_PW:
19628 check_dsp(ctx);
19629 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
19630 break;
19631 case OPC_MULSAQ_S_W_QH:
19632 check_dsp(ctx);
19633 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
19634 break;
19635 }
19636 }
19637 break;
19638#endif
19639 case OPC_ADDU_QB_DSP:
19640 switch (op2) {
19641 case OPC_MULEU_S_PH_QBL:
19642 check_dsp(ctx);
19643 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19644 break;
19645 case OPC_MULEU_S_PH_QBR:
19646 check_dsp(ctx);
19647 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19648 break;
19649 case OPC_MULQ_RS_PH:
19650 check_dsp(ctx);
19651 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19652 break;
19653 case OPC_MULEQ_S_W_PHL:
19654 check_dsp(ctx);
19655 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19656 break;
19657 case OPC_MULEQ_S_W_PHR:
19658 check_dsp(ctx);
19659 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19660 break;
19661 case OPC_MULQ_S_PH:
19662 check_dspr2(ctx);
19663 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19664 break;
19665 }
19666 break;
19667#ifdef TARGET_MIPS64
19668 case OPC_ADDU_OB_DSP:
19669 switch (op2) {
19670 case OPC_MULEQ_S_PW_QHL:
19671 check_dsp(ctx);
19672 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19673 break;
19674 case OPC_MULEQ_S_PW_QHR:
19675 check_dsp(ctx);
19676 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19677 break;
19678 case OPC_MULEU_S_QH_OBL:
19679 check_dsp(ctx);
19680 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19681 break;
19682 case OPC_MULEU_S_QH_OBR:
19683 check_dsp(ctx);
19684 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19685 break;
19686 case OPC_MULQ_RS_QH:
19687 check_dsp(ctx);
19688 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19689 break;
19690 }
19691 break;
19692#endif
19693 }
19694
19695 tcg_temp_free_i32(t0);
19696 tcg_temp_free(v1_t);
19697 tcg_temp_free(v2_t);
a22260ae
JL
19698}
19699
d75c135e 19700static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
1cb6686c
JL
19701 int ret, int val)
19702{
1cb6686c
JL
19703 int16_t imm;
19704 TCGv t0;
19705 TCGv val_t;
19706
19707 if (ret == 0) {
19708 /* Treat as NOP. */
1cb6686c
JL
19709 return;
19710 }
19711
19712 t0 = tcg_temp_new();
19713 val_t = tcg_temp_new();
19714 gen_load_gpr(val_t, val);
19715
19716 switch (op1) {
19717 case OPC_ABSQ_S_PH_DSP:
19718 switch (op2) {
19719 case OPC_BITREV:
19720 check_dsp(ctx);
19721 gen_helper_bitrev(cpu_gpr[ret], val_t);
19722 break;
19723 case OPC_REPL_QB:
19724 check_dsp(ctx);
19725 {
19726 target_long result;
19727 imm = (ctx->opcode >> 16) & 0xFF;
19728 result = (uint32_t)imm << 24 |
19729 (uint32_t)imm << 16 |
19730 (uint32_t)imm << 8 |
19731 (uint32_t)imm;
19732 result = (int32_t)result;
19733 tcg_gen_movi_tl(cpu_gpr[ret], result);
19734 }
19735 break;
19736 case OPC_REPLV_QB:
19737 check_dsp(ctx);
19738 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
19739 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
19740 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19741 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
19742 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19743 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19744 break;
19745 case OPC_REPL_PH:
19746 check_dsp(ctx);
19747 {
19748 imm = (ctx->opcode >> 16) & 0x03FF;
c4aaba92 19749 imm = (int16_t)(imm << 6) >> 6;
1cb6686c
JL
19750 tcg_gen_movi_tl(cpu_gpr[ret], \
19751 (target_long)((int32_t)imm << 16 | \
c4aaba92 19752 (uint16_t)imm));
1cb6686c
JL
19753 }
19754 break;
19755 case OPC_REPLV_PH:
19756 check_dsp(ctx);
19757 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
19758 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
19759 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19760 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19761 break;
19762 }
19763 break;
19764#ifdef TARGET_MIPS64
19765 case OPC_ABSQ_S_QH_DSP:
19766 switch (op2) {
19767 case OPC_REPL_OB:
19768 check_dsp(ctx);
19769 {
19770 target_long temp;
19771
19772 imm = (ctx->opcode >> 16) & 0xFF;
19773 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
19774 temp = (temp << 16) | temp;
19775 temp = (temp << 32) | temp;
19776 tcg_gen_movi_tl(cpu_gpr[ret], temp);
19777 break;
19778 }
19779 case OPC_REPL_PW:
19780 check_dsp(ctx);
19781 {
19782 target_long temp;
19783
19784 imm = (ctx->opcode >> 16) & 0x03FF;
19785 imm = (int16_t)(imm << 6) >> 6;
19786 temp = ((target_long)imm << 32) \
19787 | ((target_long)imm & 0xFFFFFFFF);
19788 tcg_gen_movi_tl(cpu_gpr[ret], temp);
19789 break;
19790 }
19791 case OPC_REPL_QH:
19792 check_dsp(ctx);
19793 {
19794 target_long temp;
19795
19796 imm = (ctx->opcode >> 16) & 0x03FF;
19797 imm = (int16_t)(imm << 6) >> 6;
19798
19799 temp = ((uint64_t)(uint16_t)imm << 48) |
19800 ((uint64_t)(uint16_t)imm << 32) |
19801 ((uint64_t)(uint16_t)imm << 16) |
19802 (uint64_t)(uint16_t)imm;
19803 tcg_gen_movi_tl(cpu_gpr[ret], temp);
19804 break;
19805 }
19806 case OPC_REPLV_OB:
19807 check_dsp(ctx);
19808 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
19809 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
19810 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19811 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
19812 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19813 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
19814 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19815 break;
19816 case OPC_REPLV_PW:
19817 check_dsp(ctx);
19818 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
19819 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
19820 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19821 break;
19822 case OPC_REPLV_QH:
19823 check_dsp(ctx);
19824 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
19825 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
19826 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19827 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
19828 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19829 break;
19830 }
19831 break;
19832#endif
19833 }
19834 tcg_temp_free(t0);
19835 tcg_temp_free(val_t);
1cb6686c
JL
19836}
19837
26690560
JL
19838static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
19839 uint32_t op1, uint32_t op2,
19840 int ret, int v1, int v2, int check_ret)
19841{
26690560
JL
19842 TCGv t1;
19843 TCGv v1_t;
19844 TCGv v2_t;
19845
19846 if ((ret == 0) && (check_ret == 1)) {
19847 /* Treat as NOP. */
26690560
JL
19848 return;
19849 }
19850
26690560
JL
19851 t1 = tcg_temp_new();
19852 v1_t = tcg_temp_new();
19853 v2_t = tcg_temp_new();
19854
19855 gen_load_gpr(v1_t, v1);
19856 gen_load_gpr(v2_t, v2);
19857
19858 switch (op1) {
26690560
JL
19859 case OPC_CMPU_EQ_QB_DSP:
19860 switch (op2) {
19861 case OPC_CMPU_EQ_QB:
19862 check_dsp(ctx);
19863 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
19864 break;
19865 case OPC_CMPU_LT_QB:
19866 check_dsp(ctx);
19867 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
19868 break;
19869 case OPC_CMPU_LE_QB:
19870 check_dsp(ctx);
19871 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
19872 break;
19873 case OPC_CMPGU_EQ_QB:
19874 check_dsp(ctx);
19875 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
19876 break;
19877 case OPC_CMPGU_LT_QB:
19878 check_dsp(ctx);
19879 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
19880 break;
19881 case OPC_CMPGU_LE_QB:
19882 check_dsp(ctx);
19883 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
19884 break;
19885 case OPC_CMPGDU_EQ_QB:
19886 check_dspr2(ctx);
19887 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
19888 tcg_gen_mov_tl(cpu_gpr[ret], t1);
19889 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
19890 tcg_gen_shli_tl(t1, t1, 24);
19891 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
19892 break;
19893 case OPC_CMPGDU_LT_QB:
19894 check_dspr2(ctx);
19895 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
19896 tcg_gen_mov_tl(cpu_gpr[ret], t1);
19897 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
19898 tcg_gen_shli_tl(t1, t1, 24);
19899 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
19900 break;
19901 case OPC_CMPGDU_LE_QB:
19902 check_dspr2(ctx);
19903 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
19904 tcg_gen_mov_tl(cpu_gpr[ret], t1);
19905 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
19906 tcg_gen_shli_tl(t1, t1, 24);
19907 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
19908 break;
19909 case OPC_CMP_EQ_PH:
19910 check_dsp(ctx);
19911 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
19912 break;
19913 case OPC_CMP_LT_PH:
19914 check_dsp(ctx);
19915 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
19916 break;
19917 case OPC_CMP_LE_PH:
19918 check_dsp(ctx);
19919 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
19920 break;
19921 case OPC_PICK_QB:
19922 check_dsp(ctx);
19923 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19924 break;
19925 case OPC_PICK_PH:
19926 check_dsp(ctx);
19927 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19928 break;
19929 case OPC_PACKRL_PH:
19930 check_dsp(ctx);
19931 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
19932 break;
19933 }
19934 break;
19935#ifdef TARGET_MIPS64
19936 case OPC_CMPU_EQ_OB_DSP:
19937 switch (op2) {
19938 case OPC_CMP_EQ_PW:
19939 check_dsp(ctx);
19940 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
19941 break;
19942 case OPC_CMP_LT_PW:
19943 check_dsp(ctx);
19944 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
19945 break;
19946 case OPC_CMP_LE_PW:
19947 check_dsp(ctx);
19948 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
19949 break;
19950 case OPC_CMP_EQ_QH:
19951 check_dsp(ctx);
19952 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
19953 break;
19954 case OPC_CMP_LT_QH:
19955 check_dsp(ctx);
19956 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
19957 break;
19958 case OPC_CMP_LE_QH:
19959 check_dsp(ctx);
19960 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
19961 break;
19962 case OPC_CMPGDU_EQ_OB:
19963 check_dspr2(ctx);
19964 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19965 break;
19966 case OPC_CMPGDU_LT_OB:
19967 check_dspr2(ctx);
19968 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19969 break;
19970 case OPC_CMPGDU_LE_OB:
19971 check_dspr2(ctx);
19972 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
19973 break;
19974 case OPC_CMPGU_EQ_OB:
19975 check_dsp(ctx);
19976 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
19977 break;
19978 case OPC_CMPGU_LT_OB:
19979 check_dsp(ctx);
19980 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
19981 break;
19982 case OPC_CMPGU_LE_OB:
19983 check_dsp(ctx);
19984 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
19985 break;
19986 case OPC_CMPU_EQ_OB:
19987 check_dsp(ctx);
19988 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
19989 break;
19990 case OPC_CMPU_LT_OB:
19991 check_dsp(ctx);
19992 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
19993 break;
19994 case OPC_CMPU_LE_OB:
19995 check_dsp(ctx);
19996 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
19997 break;
19998 case OPC_PACKRL_PW:
19999 check_dsp(ctx);
20000 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
20001 break;
20002 case OPC_PICK_OB:
20003 check_dsp(ctx);
20004 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20005 break;
20006 case OPC_PICK_PW:
20007 check_dsp(ctx);
20008 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20009 break;
20010 case OPC_PICK_QH:
20011 check_dsp(ctx);
20012 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20013 break;
20014 }
20015 break;
df6126a7
AJ
20016#endif
20017 }
20018
20019 tcg_temp_free(t1);
20020 tcg_temp_free(v1_t);
20021 tcg_temp_free(v2_t);
df6126a7
AJ
20022}
20023
20024static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
20025 uint32_t op1, int rt, int rs, int sa)
20026{
df6126a7
AJ
20027 TCGv t0;
20028
20029 check_dspr2(ctx);
20030
20031 if (rt == 0) {
20032 /* Treat as NOP. */
df6126a7
AJ
20033 return;
20034 }
20035
20036 t0 = tcg_temp_new();
20037 gen_load_gpr(t0, rs);
20038
20039 switch (op1) {
20040 case OPC_APPEND_DSP:
20041 switch (MASK_APPEND(ctx->opcode)) {
20042 case OPC_APPEND:
20043 if (sa != 0) {
20044 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
20045 }
20046 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20047 break;
20048 case OPC_PREPEND:
20049 if (sa != 0) {
20050 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
20051 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
20052 tcg_gen_shli_tl(t0, t0, 32 - sa);
20053 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
20054 }
20055 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20056 break;
20057 case OPC_BALIGN:
20058 sa &= 3;
20059 if (sa != 0 && sa != 2) {
20060 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
20061 tcg_gen_ext32u_tl(t0, t0);
20062 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
20063 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
20064 }
20065 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20066 break;
20067 default: /* Invalid */
20068 MIPS_INVAL("MASK APPEND");
9c708c7f 20069 generate_exception_end(ctx, EXCP_RI);
df6126a7
AJ
20070 break;
20071 }
20072 break;
20073#ifdef TARGET_MIPS64
26690560 20074 case OPC_DAPPEND_DSP:
df6126a7 20075 switch (MASK_DAPPEND(ctx->opcode)) {
26690560 20076 case OPC_DAPPEND:
df6126a7
AJ
20077 if (sa != 0) {
20078 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
20079 }
26690560
JL
20080 break;
20081 case OPC_PREPENDD:
df6126a7
AJ
20082 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
20083 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
20084 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
26690560
JL
20085 break;
20086 case OPC_PREPENDW:
df6126a7
AJ
20087 if (sa != 0) {
20088 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
20089 tcg_gen_shli_tl(t0, t0, 64 - sa);
20090 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
20091 }
26690560
JL
20092 break;
20093 case OPC_DBALIGN:
df6126a7
AJ
20094 sa &= 7;
20095 if (sa != 0 && sa != 2 && sa != 4) {
20096 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
20097 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
20098 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
20099 }
26690560
JL
20100 break;
20101 default: /* Invalid */
20102 MIPS_INVAL("MASK DAPPEND");
9c708c7f 20103 generate_exception_end(ctx, EXCP_RI);
26690560
JL
20104 break;
20105 }
20106 break;
20107#endif
20108 }
df6126a7 20109 tcg_temp_free(t0);
26690560
JL
20110}
20111
b53371ed
JL
20112static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
20113 int ret, int v1, int v2, int check_ret)
20114
20115{
b53371ed
JL
20116 TCGv t0;
20117 TCGv t1;
20118 TCGv v1_t;
20119 TCGv v2_t;
20120 int16_t imm;
20121
20122 if ((ret == 0) && (check_ret == 1)) {
20123 /* Treat as NOP. */
b53371ed
JL
20124 return;
20125 }
20126
20127 t0 = tcg_temp_new();
20128 t1 = tcg_temp_new();
20129 v1_t = tcg_temp_new();
20130 v2_t = tcg_temp_new();
20131
20132 gen_load_gpr(v1_t, v1);
20133 gen_load_gpr(v2_t, v2);
20134
20135 switch (op1) {
20136 case OPC_EXTR_W_DSP:
20137 check_dsp(ctx);
20138 switch (op2) {
20139 case OPC_EXTR_W:
20140 tcg_gen_movi_tl(t0, v2);
20141 tcg_gen_movi_tl(t1, v1);
20142 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
20143 break;
20144 case OPC_EXTR_R_W:
20145 tcg_gen_movi_tl(t0, v2);
20146 tcg_gen_movi_tl(t1, v1);
20147 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
20148 break;
20149 case OPC_EXTR_RS_W:
20150 tcg_gen_movi_tl(t0, v2);
20151 tcg_gen_movi_tl(t1, v1);
20152 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
20153 break;
20154 case OPC_EXTR_S_H:
20155 tcg_gen_movi_tl(t0, v2);
20156 tcg_gen_movi_tl(t1, v1);
20157 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
20158 break;
20159 case OPC_EXTRV_S_H:
20160 tcg_gen_movi_tl(t0, v2);
20161 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
20162 break;
20163 case OPC_EXTRV_W:
20164 tcg_gen_movi_tl(t0, v2);
20165 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
20166 break;
20167 case OPC_EXTRV_R_W:
20168 tcg_gen_movi_tl(t0, v2);
20169 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
20170 break;
20171 case OPC_EXTRV_RS_W:
20172 tcg_gen_movi_tl(t0, v2);
20173 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
20174 break;
20175 case OPC_EXTP:
20176 tcg_gen_movi_tl(t0, v2);
20177 tcg_gen_movi_tl(t1, v1);
20178 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
20179 break;
20180 case OPC_EXTPV:
20181 tcg_gen_movi_tl(t0, v2);
20182 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
20183 break;
20184 case OPC_EXTPDP:
20185 tcg_gen_movi_tl(t0, v2);
20186 tcg_gen_movi_tl(t1, v1);
20187 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
20188 break;
20189 case OPC_EXTPDPV:
20190 tcg_gen_movi_tl(t0, v2);
20191 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
20192 break;
20193 case OPC_SHILO:
20194 imm = (ctx->opcode >> 20) & 0x3F;
20195 tcg_gen_movi_tl(t0, ret);
20196 tcg_gen_movi_tl(t1, imm);
20197 gen_helper_shilo(t0, t1, cpu_env);
20198 break;
20199 case OPC_SHILOV:
20200 tcg_gen_movi_tl(t0, ret);
20201 gen_helper_shilo(t0, v1_t, cpu_env);
20202 break;
20203 case OPC_MTHLIP:
20204 tcg_gen_movi_tl(t0, ret);
20205 gen_helper_mthlip(t0, v1_t, cpu_env);
20206 break;
20207 case OPC_WRDSP:
20208 imm = (ctx->opcode >> 11) & 0x3FF;
20209 tcg_gen_movi_tl(t0, imm);
20210 gen_helper_wrdsp(v1_t, t0, cpu_env);
20211 break;
20212 case OPC_RDDSP:
20213 imm = (ctx->opcode >> 16) & 0x03FF;
20214 tcg_gen_movi_tl(t0, imm);
20215 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
20216 break;
20217 }
20218 break;
20219#ifdef TARGET_MIPS64
20220 case OPC_DEXTR_W_DSP:
20221 check_dsp(ctx);
20222 switch (op2) {
20223 case OPC_DMTHLIP:
20224 tcg_gen_movi_tl(t0, ret);
20225 gen_helper_dmthlip(v1_t, t0, cpu_env);
20226 break;
20227 case OPC_DSHILO:
20228 {
20229 int shift = (ctx->opcode >> 19) & 0x7F;
20230 int ac = (ctx->opcode >> 11) & 0x03;
20231 tcg_gen_movi_tl(t0, shift);
20232 tcg_gen_movi_tl(t1, ac);
20233 gen_helper_dshilo(t0, t1, cpu_env);
20234 break;
20235 }
20236 case OPC_DSHILOV:
20237 {
20238 int ac = (ctx->opcode >> 11) & 0x03;
20239 tcg_gen_movi_tl(t0, ac);
20240 gen_helper_dshilo(v1_t, t0, cpu_env);
20241 break;
20242 }
20243 case OPC_DEXTP:
20244 tcg_gen_movi_tl(t0, v2);
20245 tcg_gen_movi_tl(t1, v1);
20246
20247 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
20248 break;
20249 case OPC_DEXTPV:
20250 tcg_gen_movi_tl(t0, v2);
20251 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
20252 break;
20253 case OPC_DEXTPDP:
20254 tcg_gen_movi_tl(t0, v2);
20255 tcg_gen_movi_tl(t1, v1);
20256 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
20257 break;
20258 case OPC_DEXTPDPV:
20259 tcg_gen_movi_tl(t0, v2);
20260 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
20261 break;
20262 case OPC_DEXTR_L:
20263 tcg_gen_movi_tl(t0, v2);
20264 tcg_gen_movi_tl(t1, v1);
20265 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
20266 break;
20267 case OPC_DEXTR_R_L:
20268 tcg_gen_movi_tl(t0, v2);
20269 tcg_gen_movi_tl(t1, v1);
20270 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
20271 break;
20272 case OPC_DEXTR_RS_L:
20273 tcg_gen_movi_tl(t0, v2);
20274 tcg_gen_movi_tl(t1, v1);
20275 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
20276 break;
20277 case OPC_DEXTR_W:
20278 tcg_gen_movi_tl(t0, v2);
20279 tcg_gen_movi_tl(t1, v1);
20280 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
20281 break;
20282 case OPC_DEXTR_R_W:
20283 tcg_gen_movi_tl(t0, v2);
20284 tcg_gen_movi_tl(t1, v1);
20285 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
20286 break;
20287 case OPC_DEXTR_RS_W:
20288 tcg_gen_movi_tl(t0, v2);
20289 tcg_gen_movi_tl(t1, v1);
20290 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
20291 break;
20292 case OPC_DEXTR_S_H:
20293 tcg_gen_movi_tl(t0, v2);
20294 tcg_gen_movi_tl(t1, v1);
20295 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
20296 break;
20297 case OPC_DEXTRV_S_H:
20298 tcg_gen_movi_tl(t0, v2);
20299 tcg_gen_movi_tl(t1, v1);
20300 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
20301 break;
20302 case OPC_DEXTRV_L:
20303 tcg_gen_movi_tl(t0, v2);
20304 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
20305 break;
20306 case OPC_DEXTRV_R_L:
20307 tcg_gen_movi_tl(t0, v2);
20308 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
20309 break;
20310 case OPC_DEXTRV_RS_L:
20311 tcg_gen_movi_tl(t0, v2);
20312 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
20313 break;
20314 case OPC_DEXTRV_W:
20315 tcg_gen_movi_tl(t0, v2);
20316 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
20317 break;
20318 case OPC_DEXTRV_R_W:
20319 tcg_gen_movi_tl(t0, v2);
20320 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
20321 break;
20322 case OPC_DEXTRV_RS_W:
20323 tcg_gen_movi_tl(t0, v2);
20324 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
20325 break;
20326 }
20327 break;
20328#endif
20329 }
20330
20331 tcg_temp_free(t0);
20332 tcg_temp_free(t1);
20333 tcg_temp_free(v1_t);
20334 tcg_temp_free(v2_t);
b53371ed
JL
20335}
20336
9b1a1d68
JL
20337/* End MIPSDSP functions. */
20338
10dc65db
LA
20339static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
20340{
4267d3e6 20341 int rs, rt, rd, sa;
b42ee5e1 20342 uint32_t op1, op2;
10dc65db
LA
20343
20344 rs = (ctx->opcode >> 21) & 0x1f;
20345 rt = (ctx->opcode >> 16) & 0x1f;
20346 rd = (ctx->opcode >> 11) & 0x1f;
4267d3e6 20347 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
20348
20349 op1 = MASK_SPECIAL(ctx->opcode);
20350 switch (op1) {
d4ea6acd 20351 case OPC_LSA:
1f1b4c00 20352 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 20353 break;
c2e19f3c
AM
20354 case OPC_MULT:
20355 case OPC_MULTU:
20356 case OPC_DIV:
20357 case OPC_DIVU:
b42ee5e1
LA
20358 op2 = MASK_R6_MULDIV(ctx->opcode);
20359 switch (op2) {
20360 case R6_OPC_MUL:
20361 case R6_OPC_MUH:
20362 case R6_OPC_MULU:
20363 case R6_OPC_MUHU:
20364 case R6_OPC_DIV:
20365 case R6_OPC_MOD:
20366 case R6_OPC_DIVU:
20367 case R6_OPC_MODU:
20368 gen_r6_muldiv(ctx, op2, rd, rs, rt);
20369 break;
20370 default:
20371 MIPS_INVAL("special_r6 muldiv");
9c708c7f 20372 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
20373 break;
20374 }
20375 break;
10dc65db
LA
20376 case OPC_SELEQZ:
20377 case OPC_SELNEZ:
20378 gen_cond_move(ctx, op1, rd, rs, rt);
20379 break;
4267d3e6
LA
20380 case R6_OPC_CLO:
20381 case R6_OPC_CLZ:
20382 if (rt == 0 && sa == 1) {
20383 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
20384 We need additionally to check other fields */
20385 gen_cl(ctx, op1, rd, rs);
20386 } else {
9c708c7f 20387 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
20388 }
20389 break;
20390 case R6_OPC_SDBBP:
3b3c1694
LA
20391 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
20392 gen_helper_do_semihosting(cpu_env);
faf1f68b 20393 } else {
3b3c1694 20394 if (ctx->hflags & MIPS_HFLAG_SBRI) {
9c708c7f 20395 generate_exception_end(ctx, EXCP_RI);
3b3c1694 20396 } else {
9c708c7f 20397 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 20398 }
faf1f68b 20399 }
4267d3e6 20400 break;
b42ee5e1 20401#if defined(TARGET_MIPS64)
d4ea6acd
LA
20402 case OPC_DLSA:
20403 check_mips_64(ctx);
1f1b4c00 20404 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
d4ea6acd 20405 break;
4267d3e6
LA
20406 case R6_OPC_DCLO:
20407 case R6_OPC_DCLZ:
20408 if (rt == 0 && sa == 1) {
20409 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
20410 We need additionally to check other fields */
20411 check_mips_64(ctx);
20412 gen_cl(ctx, op1, rd, rs);
20413 } else {
9c708c7f 20414 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
20415 }
20416 break;
c2e19f3c
AM
20417 case OPC_DMULT:
20418 case OPC_DMULTU:
20419 case OPC_DDIV:
20420 case OPC_DDIVU:
20421
b42ee5e1
LA
20422 op2 = MASK_R6_MULDIV(ctx->opcode);
20423 switch (op2) {
20424 case R6_OPC_DMUL:
20425 case R6_OPC_DMUH:
20426 case R6_OPC_DMULU:
20427 case R6_OPC_DMUHU:
20428 case R6_OPC_DDIV:
20429 case R6_OPC_DMOD:
20430 case R6_OPC_DDIVU:
20431 case R6_OPC_DMODU:
20432 check_mips_64(ctx);
20433 gen_r6_muldiv(ctx, op2, rd, rs, rt);
20434 break;
20435 default:
20436 MIPS_INVAL("special_r6 muldiv");
9c708c7f 20437 generate_exception_end(ctx, EXCP_RI);
b42ee5e1
LA
20438 break;
20439 }
20440 break;
20441#endif
10dc65db
LA
20442 default: /* Invalid */
20443 MIPS_INVAL("special_r6");
9c708c7f 20444 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
20445 break;
20446 }
20447}
20448
20449static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
20450{
b42ee5e1 20451 int rs, rt, rd, sa;
10dc65db
LA
20452 uint32_t op1;
20453
20454 rs = (ctx->opcode >> 21) & 0x1f;
20455 rt = (ctx->opcode >> 16) & 0x1f;
20456 rd = (ctx->opcode >> 11) & 0x1f;
b42ee5e1 20457 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
20458
20459 op1 = MASK_SPECIAL(ctx->opcode);
20460 switch (op1) {
20461 case OPC_MOVN: /* Conditional move */
20462 case OPC_MOVZ:
20463 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
20464 INSN_LOONGSON2E | INSN_LOONGSON2F);
20465 gen_cond_move(ctx, op1, rd, rs, rt);
20466 break;
20467 case OPC_MFHI: /* Move from HI/LO */
20468 case OPC_MFLO:
20469 gen_HILO(ctx, op1, rs & 3, rd);
20470 break;
20471 case OPC_MTHI:
20472 case OPC_MTLO: /* Move to HI/LO */
20473 gen_HILO(ctx, op1, rd & 3, rs);
20474 break;
20475 case OPC_MOVCI:
20476 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
20477 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
20478 check_cp1_enabled(ctx);
20479 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
20480 (ctx->opcode >> 16) & 1);
20481 } else {
20482 generate_exception_err(ctx, EXCP_CpU, 1);
20483 }
20484 break;
b42ee5e1
LA
20485 case OPC_MULT:
20486 case OPC_MULTU:
20487 if (sa) {
20488 check_insn(ctx, INSN_VR54XX);
20489 op1 = MASK_MUL_VR54XX(ctx->opcode);
20490 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
20491 } else {
20492 gen_muldiv(ctx, op1, rd & 3, rs, rt);
20493 }
20494 break;
20495 case OPC_DIV:
20496 case OPC_DIVU:
20497 gen_muldiv(ctx, op1, 0, rs, rt);
20498 break;
20499#if defined(TARGET_MIPS64)
c2e19f3c
AM
20500 case OPC_DMULT:
20501 case OPC_DMULTU:
20502 case OPC_DDIV:
20503 case OPC_DDIVU:
b42ee5e1
LA
20504 check_insn(ctx, ISA_MIPS3);
20505 check_mips_64(ctx);
20506 gen_muldiv(ctx, op1, 0, rs, rt);
20507 break;
20508#endif
0aefa333 20509 case OPC_JR:
b231c103 20510 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
0aefa333 20511 break;
4267d3e6
LA
20512 case OPC_SPIM:
20513#ifdef MIPS_STRICT_STANDARD
20514 MIPS_INVAL("SPIM");
9c708c7f 20515 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
20516#else
20517 /* Implemented as RI exception for now. */
20518 MIPS_INVAL("spim (unofficial)");
9c708c7f 20519 generate_exception_end(ctx, EXCP_RI);
4267d3e6
LA
20520#endif
20521 break;
10dc65db
LA
20522 default: /* Invalid */
20523 MIPS_INVAL("special_legacy");
9c708c7f 20524 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
20525 break;
20526 }
20527}
20528
099e5b4d 20529static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
3c824109 20530{
3c824109 20531 int rs, rt, rd, sa;
099e5b4d 20532 uint32_t op1;
3c824109 20533
3c824109
NF
20534 rs = (ctx->opcode >> 21) & 0x1f;
20535 rt = (ctx->opcode >> 16) & 0x1f;
20536 rd = (ctx->opcode >> 11) & 0x1f;
20537 sa = (ctx->opcode >> 6) & 0x1f;
099e5b4d
LA
20538
20539 op1 = MASK_SPECIAL(ctx->opcode);
20540 switch (op1) {
20541 case OPC_SLL: /* Shift with immediate */
339cd2a8
LA
20542 if (sa == 5 && rd == 0 &&
20543 rs == 0 && rt == 0) { /* PAUSE */
20544 if ((ctx->insn_flags & ISA_MIPS32R6) &&
20545 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9c708c7f 20546 generate_exception_end(ctx, EXCP_RI);
339cd2a8
LA
20547 break;
20548 }
20549 }
20550 /* Fallthrough */
099e5b4d
LA
20551 case OPC_SRA:
20552 gen_shift_imm(ctx, op1, rd, rt, sa);
20553 break;
20554 case OPC_SRL:
20555 switch ((ctx->opcode >> 21) & 0x1f) {
20556 case 1:
20557 /* rotr is decoded as srl on non-R2 CPUs */
20558 if (ctx->insn_flags & ISA_MIPS32R2) {
20559 op1 = OPC_ROTR;
ea63e2c3 20560 }
099e5b4d
LA
20561 /* Fallthrough */
20562 case 0:
20563 gen_shift_imm(ctx, op1, rd, rt, sa);
ea63e2c3 20564 break;
099e5b4d 20565 default:
9c708c7f 20566 generate_exception_end(ctx, EXCP_RI);
ea63e2c3 20567 break;
099e5b4d
LA
20568 }
20569 break;
c2e19f3c
AM
20570 case OPC_ADD:
20571 case OPC_ADDU:
20572 case OPC_SUB:
20573 case OPC_SUBU:
099e5b4d
LA
20574 gen_arith(ctx, op1, rd, rs, rt);
20575 break;
20576 case OPC_SLLV: /* Shifts */
20577 case OPC_SRAV:
20578 gen_shift(ctx, op1, rd, rs, rt);
20579 break;
20580 case OPC_SRLV:
20581 switch ((ctx->opcode >> 6) & 0x1f) {
20582 case 1:
20583 /* rotrv is decoded as srlv on non-R2 CPUs */
20584 if (ctx->insn_flags & ISA_MIPS32R2) {
20585 op1 = OPC_ROTRV;
26135ead 20586 }
099e5b4d
LA
20587 /* Fallthrough */
20588 case 0:
20589 gen_shift(ctx, op1, rd, rs, rt);
26135ead 20590 break;
099e5b4d 20591 default:
9c708c7f 20592 generate_exception_end(ctx, EXCP_RI);
6af0bf9c 20593 break;
099e5b4d
LA
20594 }
20595 break;
20596 case OPC_SLT: /* Set on less than */
20597 case OPC_SLTU:
20598 gen_slt(ctx, op1, rd, rs, rt);
20599 break;
20600 case OPC_AND: /* Logic*/
20601 case OPC_OR:
20602 case OPC_NOR:
20603 case OPC_XOR:
20604 gen_logic(ctx, op1, rd, rs, rt);
20605 break;
0aefa333 20606 case OPC_JALR:
b231c103 20607 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
099e5b4d 20608 break;
c2e19f3c
AM
20609 case OPC_TGE: /* Traps */
20610 case OPC_TGEU:
20611 case OPC_TLT:
20612 case OPC_TLTU:
20613 case OPC_TEQ:
099e5b4d 20614 case OPC_TNE:
d9224450 20615 check_insn(ctx, ISA_MIPS2);
099e5b4d
LA
20616 gen_trap(ctx, op1, rs, rt, -1);
20617 break;
d4ea6acd 20618 case OPC_LSA: /* OPC_PMON */
f7685877
YK
20619 if ((ctx->insn_flags & ISA_MIPS32R6) ||
20620 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
d4ea6acd
LA
20621 decode_opc_special_r6(env, ctx);
20622 } else {
20623 /* Pmon entry point, also R4010 selsl */
b48cfdff 20624#ifdef MIPS_STRICT_STANDARD
d4ea6acd 20625 MIPS_INVAL("PMON / selsl");
9c708c7f 20626 generate_exception_end(ctx, EXCP_RI);
b48cfdff 20627#else
d4ea6acd 20628 gen_helper_0e0i(pmon, sa);
b48cfdff 20629#endif
d4ea6acd 20630 }
099e5b4d
LA
20631 break;
20632 case OPC_SYSCALL:
9c708c7f 20633 generate_exception_end(ctx, EXCP_SYSCALL);
099e5b4d
LA
20634 break;
20635 case OPC_BREAK:
9c708c7f 20636 generate_exception_end(ctx, EXCP_BREAK);
099e5b4d 20637 break;
099e5b4d 20638 case OPC_SYNC:
d9224450 20639 check_insn(ctx, ISA_MIPS2);
d208ac0c 20640 gen_sync(extract32(ctx->opcode, 6, 5));
099e5b4d 20641 break;
4ad40f36 20642
d26bc211 20643#if defined(TARGET_MIPS64)
099e5b4d
LA
20644 /* MIPS64 specific opcodes */
20645 case OPC_DSLL:
20646 case OPC_DSRA:
20647 case OPC_DSLL32:
20648 case OPC_DSRA32:
20649 check_insn(ctx, ISA_MIPS3);
20650 check_mips_64(ctx);
20651 gen_shift_imm(ctx, op1, rd, rt, sa);
20652 break;
20653 case OPC_DSRL:
20654 switch ((ctx->opcode >> 21) & 0x1f) {
20655 case 1:
20656 /* drotr is decoded as dsrl on non-R2 CPUs */
20657 if (ctx->insn_flags & ISA_MIPS32R2) {
20658 op1 = OPC_DROTR;
ea63e2c3 20659 }
099e5b4d
LA
20660 /* Fallthrough */
20661 case 0:
d75c135e 20662 check_insn(ctx, ISA_MIPS3);
e189e748 20663 check_mips_64(ctx);
099e5b4d 20664 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 20665 break;
099e5b4d 20666 default:
9c708c7f 20667 generate_exception_end(ctx, EXCP_RI);
460f00c4 20668 break;
099e5b4d
LA
20669 }
20670 break;
20671 case OPC_DSRL32:
20672 switch ((ctx->opcode >> 21) & 0x1f) {
20673 case 1:
20674 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
20675 if (ctx->insn_flags & ISA_MIPS32R2) {
20676 op1 = OPC_DROTR32;
ea63e2c3 20677 }
099e5b4d
LA
20678 /* Fallthrough */
20679 case 0:
d75c135e 20680 check_insn(ctx, ISA_MIPS3);
e189e748 20681 check_mips_64(ctx);
099e5b4d 20682 gen_shift_imm(ctx, op1, rd, rt, sa);
7a387fff 20683 break;
099e5b4d 20684 default:
9c708c7f 20685 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
20686 break;
20687 }
20688 break;
c2e19f3c
AM
20689 case OPC_DADD:
20690 case OPC_DADDU:
20691 case OPC_DSUB:
20692 case OPC_DSUBU:
099e5b4d
LA
20693 check_insn(ctx, ISA_MIPS3);
20694 check_mips_64(ctx);
20695 gen_arith(ctx, op1, rd, rs, rt);
20696 break;
20697 case OPC_DSLLV:
20698 case OPC_DSRAV:
20699 check_insn(ctx, ISA_MIPS3);
20700 check_mips_64(ctx);
20701 gen_shift(ctx, op1, rd, rs, rt);
20702 break;
20703 case OPC_DSRLV:
20704 switch ((ctx->opcode >> 6) & 0x1f) {
20705 case 1:
20706 /* drotrv is decoded as dsrlv on non-R2 CPUs */
20707 if (ctx->insn_flags & ISA_MIPS32R2) {
20708 op1 = OPC_DROTRV;
6af0bf9c 20709 }
099e5b4d
LA
20710 /* Fallthrough */
20711 case 0:
20712 check_insn(ctx, ISA_MIPS3);
e189e748 20713 check_mips_64(ctx);
099e5b4d 20714 gen_shift(ctx, op1, rd, rs, rt);
161f85e6 20715 break;
099e5b4d 20716 default:
9c708c7f 20717 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
20718 break;
20719 }
20720 break;
f7685877
YK
20721 case OPC_DLSA:
20722 if ((ctx->insn_flags & ISA_MIPS32R6) ||
20723 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
20724 decode_opc_special_r6(env, ctx);
20725 }
20726 break;
099e5b4d 20727#endif
10dc65db
LA
20728 default:
20729 if (ctx->insn_flags & ISA_MIPS32R6) {
20730 decode_opc_special_r6(env, ctx);
20731 } else {
20732 decode_opc_special_legacy(env, ctx);
20733 }
20734 }
20735}
20736
10dc65db 20737static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
20738{
20739 int rs, rt, rd;
20740 uint32_t op1;
6c5c1e20 20741
4267d3e6
LA
20742 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20743
099e5b4d
LA
20744 rs = (ctx->opcode >> 21) & 0x1f;
20745 rt = (ctx->opcode >> 16) & 0x1f;
20746 rd = (ctx->opcode >> 11) & 0x1f;
20747
20748 op1 = MASK_SPECIAL2(ctx->opcode);
20749 switch (op1) {
c2e19f3c
AM
20750 case OPC_MADD: /* Multiply and add/sub */
20751 case OPC_MADDU:
20752 case OPC_MSUB:
20753 case OPC_MSUBU:
099e5b4d
LA
20754 check_insn(ctx, ISA_MIPS32);
20755 gen_muldiv(ctx, op1, rd & 3, rs, rt);
20756 break;
20757 case OPC_MUL:
099e5b4d
LA
20758 gen_arith(ctx, op1, rd, rs, rt);
20759 break;
fac5a073
LA
20760 case OPC_DIV_G_2F:
20761 case OPC_DIVU_G_2F:
20762 case OPC_MULT_G_2F:
20763 case OPC_MULTU_G_2F:
20764 case OPC_MOD_G_2F:
20765 case OPC_MODU_G_2F:
20766 check_insn(ctx, INSN_LOONGSON2F);
20767 gen_loongson_integer(ctx, op1, rd, rs, rt);
20768 break;
099e5b4d
LA
20769 case OPC_CLO:
20770 case OPC_CLZ:
20771 check_insn(ctx, ISA_MIPS32);
20772 gen_cl(ctx, op1, rd, rs);
20773 break;
20774 case OPC_SDBBP:
3b3c1694
LA
20775 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
20776 gen_helper_do_semihosting(cpu_env);
20777 } else {
20778 /* XXX: not clear which exception should be raised
20779 * when in debug mode...
20780 */
20781 check_insn(ctx, ISA_MIPS32);
9c708c7f 20782 generate_exception_end(ctx, EXCP_DBp);
3b3c1694 20783 }
099e5b4d 20784 break;
9b1a1d68 20785#if defined(TARGET_MIPS64)
099e5b4d
LA
20786 case OPC_DCLO:
20787 case OPC_DCLZ:
20788 check_insn(ctx, ISA_MIPS64);
20789 check_mips_64(ctx);
20790 gen_cl(ctx, op1, rd, rs);
20791 break;
4267d3e6
LA
20792 case OPC_DMULT_G_2F:
20793 case OPC_DMULTU_G_2F:
20794 case OPC_DDIV_G_2F:
20795 case OPC_DDIVU_G_2F:
20796 case OPC_DMOD_G_2F:
20797 case OPC_DMODU_G_2F:
20798 check_insn(ctx, INSN_LOONGSON2F);
20799 gen_loongson_integer(ctx, op1, rd, rs, rt);
20800 break;
10dc65db 20801#endif
4267d3e6
LA
20802 default: /* Invalid */
20803 MIPS_INVAL("special2_legacy");
9c708c7f 20804 generate_exception_end(ctx, EXCP_RI);
4267d3e6 20805 break;
10dc65db
LA
20806 }
20807}
20808
20809static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
20810{
15eacb9b
YK
20811 int rs, rt, rd, sa;
20812 uint32_t op1, op2;
10dc65db
LA
20813 int16_t imm;
20814
20815 rs = (ctx->opcode >> 21) & 0x1f;
20816 rt = (ctx->opcode >> 16) & 0x1f;
15eacb9b
YK
20817 rd = (ctx->opcode >> 11) & 0x1f;
20818 sa = (ctx->opcode >> 6) & 0x1f;
10dc65db
LA
20819 imm = (int16_t)ctx->opcode >> 7;
20820
20821 op1 = MASK_SPECIAL3(ctx->opcode);
20822 switch (op1) {
bf7910c6
LA
20823 case R6_OPC_PREF:
20824 if (rt >= 24) {
20825 /* hint codes 24-31 are reserved and signal RI */
9c708c7f 20826 generate_exception_end(ctx, EXCP_RI);
bf7910c6
LA
20827 }
20828 /* Treat as NOP. */
20829 break;
20830 case R6_OPC_CACHE:
40d48212 20831 check_cp0_enabled(ctx);
0d74a222
LA
20832 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
20833 gen_cache_operation(ctx, rt, rs, imm);
20834 }
bf7910c6 20835 break;
10dc65db
LA
20836 case R6_OPC_SC:
20837 gen_st_cond(ctx, op1, rt, rs, imm);
20838 break;
20839 case R6_OPC_LL:
20840 gen_ld(ctx, op1, rt, rs, imm);
20841 break;
15eacb9b
YK
20842 case OPC_BSHFL:
20843 {
20844 if (rd == 0) {
20845 /* Treat as NOP. */
20846 break;
20847 }
15eacb9b
YK
20848 op2 = MASK_BSHFL(ctx->opcode);
20849 switch (op2) {
c2e19f3c
AM
20850 case OPC_ALIGN:
20851 case OPC_ALIGN_END:
821f2008 20852 gen_align(ctx, 32, rd, rs, rt, sa & 3);
15eacb9b
YK
20853 break;
20854 case OPC_BITSWAP:
1f1b4c00 20855 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
20856 break;
20857 }
15eacb9b
YK
20858 }
20859 break;
bf7910c6
LA
20860#if defined(TARGET_MIPS64)
20861 case R6_OPC_SCD:
20862 gen_st_cond(ctx, op1, rt, rs, imm);
20863 break;
20864 case R6_OPC_LLD:
20865 gen_ld(ctx, op1, rt, rs, imm);
20866 break;
15eacb9b
YK
20867 case OPC_DBSHFL:
20868 check_mips_64(ctx);
20869 {
20870 if (rd == 0) {
20871 /* Treat as NOP. */
20872 break;
20873 }
15eacb9b
YK
20874 op2 = MASK_DBSHFL(ctx->opcode);
20875 switch (op2) {
c2e19f3c
AM
20876 case OPC_DALIGN:
20877 case OPC_DALIGN_END:
821f2008 20878 gen_align(ctx, 64, rd, rs, rt, sa & 7);
15eacb9b
YK
20879 break;
20880 case OPC_DBITSWAP:
1f1b4c00 20881 gen_bitswap(ctx, op2, rd, rt);
15eacb9b
YK
20882 break;
20883 }
1f1b4c00 20884
15eacb9b
YK
20885 }
20886 break;
bf7910c6 20887#endif
10dc65db
LA
20888 default: /* Invalid */
20889 MIPS_INVAL("special3_r6");
9c708c7f 20890 generate_exception_end(ctx, EXCP_RI);
10dc65db
LA
20891 break;
20892 }
20893}
20894
20895static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
20896{
fac5a073 20897 int rs, rt, rd;
099e5b4d 20898 uint32_t op1, op2;
099e5b4d
LA
20899
20900 rs = (ctx->opcode >> 21) & 0x1f;
20901 rt = (ctx->opcode >> 16) & 0x1f;
20902 rd = (ctx->opcode >> 11) & 0x1f;
099e5b4d
LA
20903
20904 op1 = MASK_SPECIAL3(ctx->opcode);
20905 switch (op1) {
c2e19f3c
AM
20906 case OPC_DIV_G_2E:
20907 case OPC_DIVU_G_2E:
20908 case OPC_MOD_G_2E:
20909 case OPC_MODU_G_2E:
20910 case OPC_MULT_G_2E:
20911 case OPC_MULTU_G_2E:
099e5b4d
LA
20912 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
20913 * the same mask and op1. */
20914 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
20915 op2 = MASK_ADDUH_QB(ctx->opcode);
461c08df 20916 switch (op2) {
099e5b4d
LA
20917 case OPC_ADDUH_QB:
20918 case OPC_ADDUH_R_QB:
20919 case OPC_ADDQH_PH:
20920 case OPC_ADDQH_R_PH:
20921 case OPC_ADDQH_W:
20922 case OPC_ADDQH_R_W:
20923 case OPC_SUBUH_QB:
20924 case OPC_SUBUH_R_QB:
20925 case OPC_SUBQH_PH:
20926 case OPC_SUBQH_R_PH:
20927 case OPC_SUBQH_W:
20928 case OPC_SUBQH_R_W:
461c08df
JL
20929 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
20930 break;
099e5b4d
LA
20931 case OPC_MUL_PH:
20932 case OPC_MUL_S_PH:
20933 case OPC_MULQ_S_W:
20934 case OPC_MULQ_RS_W:
20935 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 20936 break;
461c08df 20937 default:
099e5b4d 20938 MIPS_INVAL("MASK ADDUH.QB");
9c708c7f 20939 generate_exception_end(ctx, EXCP_RI);
461c08df
JL
20940 break;
20941 }
099e5b4d
LA
20942 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
20943 gen_loongson_integer(ctx, op1, rd, rs, rt);
20944 } else {
9c708c7f 20945 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
20946 }
20947 break;
20948 case OPC_LX_DSP:
20949 op2 = MASK_LX(ctx->opcode);
20950 switch (op2) {
20951#if defined(TARGET_MIPS64)
20952 case OPC_LDX:
20953#endif
20954 case OPC_LBUX:
20955 case OPC_LHX:
20956 case OPC_LWX:
20957 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
20958 break;
20959 default: /* Invalid */
20960 MIPS_INVAL("MASK LX");
9c708c7f 20961 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
20962 break;
20963 }
20964 break;
20965 case OPC_ABSQ_S_PH_DSP:
20966 op2 = MASK_ABSQ_S_PH(ctx->opcode);
20967 switch (op2) {
20968 case OPC_ABSQ_S_QB:
20969 case OPC_ABSQ_S_PH:
20970 case OPC_ABSQ_S_W:
20971 case OPC_PRECEQ_W_PHL:
20972 case OPC_PRECEQ_W_PHR:
20973 case OPC_PRECEQU_PH_QBL:
20974 case OPC_PRECEQU_PH_QBR:
20975 case OPC_PRECEQU_PH_QBLA:
20976 case OPC_PRECEQU_PH_QBRA:
20977 case OPC_PRECEU_PH_QBL:
20978 case OPC_PRECEU_PH_QBR:
20979 case OPC_PRECEU_PH_QBLA:
20980 case OPC_PRECEU_PH_QBRA:
20981 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
20982 break;
20983 case OPC_BITREV:
20984 case OPC_REPL_QB:
20985 case OPC_REPLV_QB:
20986 case OPC_REPL_PH:
20987 case OPC_REPLV_PH:
20988 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
20989 break;
20990 default:
20991 MIPS_INVAL("MASK ABSQ_S.PH");
9c708c7f 20992 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
20993 break;
20994 }
20995 break;
20996 case OPC_ADDU_QB_DSP:
20997 op2 = MASK_ADDU_QB(ctx->opcode);
20998 switch (op2) {
20999 case OPC_ADDQ_PH:
21000 case OPC_ADDQ_S_PH:
21001 case OPC_ADDQ_S_W:
21002 case OPC_ADDU_QB:
21003 case OPC_ADDU_S_QB:
21004 case OPC_ADDU_PH:
21005 case OPC_ADDU_S_PH:
21006 case OPC_SUBQ_PH:
21007 case OPC_SUBQ_S_PH:
21008 case OPC_SUBQ_S_W:
21009 case OPC_SUBU_QB:
21010 case OPC_SUBU_S_QB:
21011 case OPC_SUBU_PH:
21012 case OPC_SUBU_S_PH:
21013 case OPC_ADDSC:
21014 case OPC_ADDWC:
21015 case OPC_MODSUB:
21016 case OPC_RADDU_W_QB:
21017 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
21018 break;
21019 case OPC_MULEU_S_PH_QBL:
21020 case OPC_MULEU_S_PH_QBR:
21021 case OPC_MULQ_RS_PH:
21022 case OPC_MULEQ_S_W_PHL:
21023 case OPC_MULEQ_S_W_PHR:
21024 case OPC_MULQ_S_PH:
21025 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
21026 break;
21027 default: /* Invalid */
21028 MIPS_INVAL("MASK ADDU.QB");
9c708c7f 21029 generate_exception_end(ctx, EXCP_RI);
461c08df 21030 break;
461c08df 21031
099e5b4d
LA
21032 }
21033 break;
21034 case OPC_CMPU_EQ_QB_DSP:
21035 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
21036 switch (op2) {
21037 case OPC_PRECR_SRA_PH_W:
21038 case OPC_PRECR_SRA_R_PH_W:
21039 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
461c08df 21040 break;
099e5b4d
LA
21041 case OPC_PRECR_QB_PH:
21042 case OPC_PRECRQ_QB_PH:
21043 case OPC_PRECRQ_PH_W:
21044 case OPC_PRECRQ_RS_PH_W:
21045 case OPC_PRECRQU_S_QB_PH:
21046 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
461c08df 21047 break;
099e5b4d
LA
21048 case OPC_CMPU_EQ_QB:
21049 case OPC_CMPU_LT_QB:
21050 case OPC_CMPU_LE_QB:
21051 case OPC_CMP_EQ_PH:
21052 case OPC_CMP_LT_PH:
21053 case OPC_CMP_LE_PH:
21054 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
77c5fa8b 21055 break;
099e5b4d
LA
21056 case OPC_CMPGU_EQ_QB:
21057 case OPC_CMPGU_LT_QB:
21058 case OPC_CMPGU_LE_QB:
21059 case OPC_CMPGDU_EQ_QB:
21060 case OPC_CMPGDU_LT_QB:
21061 case OPC_CMPGDU_LE_QB:
21062 case OPC_PICK_QB:
21063 case OPC_PICK_PH:
21064 case OPC_PACKRL_PH:
21065 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
21066 break;
21067 default: /* Invalid */
21068 MIPS_INVAL("MASK CMPU.EQ.QB");
9c708c7f 21069 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
21070 break;
21071 }
21072 break;
21073 case OPC_SHLL_QB_DSP:
21074 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
21075 break;
21076 case OPC_DPA_W_PH_DSP:
21077 op2 = MASK_DPA_W_PH(ctx->opcode);
21078 switch (op2) {
21079 case OPC_DPAU_H_QBL:
21080 case OPC_DPAU_H_QBR:
21081 case OPC_DPSU_H_QBL:
21082 case OPC_DPSU_H_QBR:
21083 case OPC_DPA_W_PH:
21084 case OPC_DPAX_W_PH:
21085 case OPC_DPAQ_S_W_PH:
21086 case OPC_DPAQX_S_W_PH:
21087 case OPC_DPAQX_SA_W_PH:
21088 case OPC_DPS_W_PH:
21089 case OPC_DPSX_W_PH:
21090 case OPC_DPSQ_S_W_PH:
21091 case OPC_DPSQX_S_W_PH:
21092 case OPC_DPSQX_SA_W_PH:
21093 case OPC_MULSAQ_S_W_PH:
21094 case OPC_DPAQ_SA_L_W:
21095 case OPC_DPSQ_SA_L_W:
21096 case OPC_MAQ_S_W_PHL:
21097 case OPC_MAQ_S_W_PHR:
21098 case OPC_MAQ_SA_W_PHL:
21099 case OPC_MAQ_SA_W_PHR:
21100 case OPC_MULSA_W_PH:
21101 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
21102 break;
21103 default: /* Invalid */
21104 MIPS_INVAL("MASK DPAW.PH");
9c708c7f 21105 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
21106 break;
21107 }
21108 break;
21109 case OPC_INSV_DSP:
21110 op2 = MASK_INSV(ctx->opcode);
21111 switch (op2) {
21112 case OPC_INSV:
21113 check_dsp(ctx);
21114 {
21115 TCGv t0, t1;
21116
21117 if (rt == 0) {
099e5b4d
LA
21118 break;
21119 }
21120
21121 t0 = tcg_temp_new();
21122 t1 = tcg_temp_new();
21123
21124 gen_load_gpr(t0, rt);
21125 gen_load_gpr(t1, rs);
21126
21127 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
21128
21129 tcg_temp_free(t0);
21130 tcg_temp_free(t1);
a22260ae
JL
21131 break;
21132 }
099e5b4d
LA
21133 default: /* Invalid */
21134 MIPS_INVAL("MASK INSV");
9c708c7f 21135 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
21136 break;
21137 }
21138 break;
21139 case OPC_APPEND_DSP:
21140 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
21141 break;
21142 case OPC_EXTR_W_DSP:
21143 op2 = MASK_EXTR_W(ctx->opcode);
21144 switch (op2) {
21145 case OPC_EXTR_W:
21146 case OPC_EXTR_R_W:
21147 case OPC_EXTR_RS_W:
21148 case OPC_EXTR_S_H:
21149 case OPC_EXTRV_S_H:
21150 case OPC_EXTRV_W:
21151 case OPC_EXTRV_R_W:
21152 case OPC_EXTRV_RS_W:
21153 case OPC_EXTP:
21154 case OPC_EXTPV:
21155 case OPC_EXTPDP:
21156 case OPC_EXTPDPV:
21157 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
21158 break;
21159 case OPC_RDDSP:
21160 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
21161 break;
21162 case OPC_SHILO:
21163 case OPC_SHILOV:
21164 case OPC_MTHLIP:
21165 case OPC_WRDSP:
21166 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
21167 break;
21168 default: /* Invalid */
21169 MIPS_INVAL("MASK EXTR.W");
9c708c7f 21170 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
21171 break;
21172 }
21173 break;
099e5b4d 21174#if defined(TARGET_MIPS64)
c2e19f3c
AM
21175 case OPC_DDIV_G_2E:
21176 case OPC_DDIVU_G_2E:
21177 case OPC_DMULT_G_2E:
21178 case OPC_DMULTU_G_2E:
21179 case OPC_DMOD_G_2E:
21180 case OPC_DMODU_G_2E:
fac5a073
LA
21181 check_insn(ctx, INSN_LOONGSON2E);
21182 gen_loongson_integer(ctx, op1, rd, rs, rt);
099e5b4d 21183 break;
099e5b4d
LA
21184 case OPC_ABSQ_S_QH_DSP:
21185 op2 = MASK_ABSQ_S_QH(ctx->opcode);
21186 switch (op2) {
21187 case OPC_PRECEQ_L_PWL:
21188 case OPC_PRECEQ_L_PWR:
21189 case OPC_PRECEQ_PW_QHL:
21190 case OPC_PRECEQ_PW_QHR:
21191 case OPC_PRECEQ_PW_QHLA:
21192 case OPC_PRECEQ_PW_QHRA:
21193 case OPC_PRECEQU_QH_OBL:
21194 case OPC_PRECEQU_QH_OBR:
21195 case OPC_PRECEQU_QH_OBLA:
21196 case OPC_PRECEQU_QH_OBRA:
21197 case OPC_PRECEU_QH_OBL:
21198 case OPC_PRECEU_QH_OBR:
21199 case OPC_PRECEU_QH_OBLA:
21200 case OPC_PRECEU_QH_OBRA:
21201 case OPC_ABSQ_S_OB:
21202 case OPC_ABSQ_S_PW:
21203 case OPC_ABSQ_S_QH:
21204 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
21205 break;
21206 case OPC_REPL_OB:
21207 case OPC_REPL_PW:
21208 case OPC_REPL_QH:
21209 case OPC_REPLV_OB:
21210 case OPC_REPLV_PW:
21211 case OPC_REPLV_QH:
21212 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
21213 break;
21214 default: /* Invalid */
21215 MIPS_INVAL("MASK ABSQ_S.QH");
9c708c7f 21216 generate_exception_end(ctx, EXCP_RI);
099e5b4d
LA
21217 break;
21218 }
21219 break;
21220 case OPC_ADDU_OB_DSP:
21221 op2 = MASK_ADDU_OB(ctx->opcode);
21222 switch (op2) {
21223 case OPC_RADDU_L_OB:
21224 case OPC_SUBQ_PW:
21225 case OPC_SUBQ_S_PW:
21226 case OPC_SUBQ_QH:
21227 case OPC_SUBQ_S_QH:
21228 case OPC_SUBU_OB:
21229 case OPC_SUBU_S_OB:
21230 case OPC_SUBU_QH:
21231 case OPC_SUBU_S_QH:
21232 case OPC_SUBUH_OB:
21233 case OPC_SUBUH_R_OB:
21234 case OPC_ADDQ_PW:
21235 case OPC_ADDQ_S_PW:
21236 case OPC_ADDQ_QH:
21237 case OPC_ADDQ_S_QH:
21238 case OPC_ADDU_OB:
21239 case OPC_ADDU_S_OB:
21240 case OPC_ADDU_QH:
21241 case OPC_ADDU_S_QH:
21242 case OPC_ADDUH_OB:
21243 case OPC_ADDUH_R_OB:
21244 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
a22260ae 21245 break;
099e5b4d
LA
21246 case OPC_MULEQ_S_PW_QHL:
21247 case OPC_MULEQ_S_PW_QHR:
21248 case OPC_MULEU_S_QH_OBL:
21249 case OPC_MULEU_S_QH_OBR:
21250 case OPC_MULQ_RS_QH:
21251 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
1cb6686c 21252 break;
099e5b4d
LA
21253 default: /* Invalid */
21254 MIPS_INVAL("MASK ADDU.OB");
9c708c7f 21255 generate_exception_end(ctx, EXCP_RI);
26690560 21256 break;
099e5b4d
LA
21257 }
21258 break;
21259 case OPC_CMPU_EQ_OB_DSP:
21260 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
21261 switch (op2) {
21262 case OPC_PRECR_SRA_QH_PW:
21263 case OPC_PRECR_SRA_R_QH_PW:
21264 /* Return value is rt. */
21265 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
b53371ed 21266 break;
099e5b4d
LA
21267 case OPC_PRECR_OB_QH:
21268 case OPC_PRECRQ_OB_QH:
21269 case OPC_PRECRQ_PW_L:
21270 case OPC_PRECRQ_QH_PW:
21271 case OPC_PRECRQ_RS_QH_PW:
21272 case OPC_PRECRQU_S_OB_QH:
21273 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
4368b29a 21274 break;
099e5b4d
LA
21275 case OPC_CMPU_EQ_OB:
21276 case OPC_CMPU_LT_OB:
21277 case OPC_CMPU_LE_OB:
21278 case OPC_CMP_EQ_QH:
21279 case OPC_CMP_LT_QH:
21280 case OPC_CMP_LE_QH:
21281 case OPC_CMP_EQ_PW:
21282 case OPC_CMP_LT_PW:
21283 case OPC_CMP_LE_PW:
21284 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
7a387fff 21285 break;
099e5b4d
LA
21286 case OPC_CMPGDU_EQ_OB:
21287 case OPC_CMPGDU_LT_OB:
21288 case OPC_CMPGDU_LE_OB:
21289 case OPC_CMPGU_EQ_OB:
21290 case OPC_CMPGU_LT_OB:
21291 case OPC_CMPGU_LE_OB:
21292 case OPC_PACKRL_PW:
21293 case OPC_PICK_OB:
21294 case OPC_PICK_PW:
21295 case OPC_PICK_QH:
21296 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
c6d6dd7c 21297 break;
099e5b4d
LA
21298 default: /* Invalid */
21299 MIPS_INVAL("MASK CMPU_EQ.OB");
9c708c7f 21300 generate_exception_end(ctx, EXCP_RI);
161f85e6 21301 break;
099e5b4d
LA
21302 }
21303 break;
21304 case OPC_DAPPEND_DSP:
21305 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
21306 break;
21307 case OPC_DEXTR_W_DSP:
21308 op2 = MASK_DEXTR_W(ctx->opcode);
21309 switch (op2) {
21310 case OPC_DEXTP:
21311 case OPC_DEXTPDP:
21312 case OPC_DEXTPDPV:
21313 case OPC_DEXTPV:
21314 case OPC_DEXTR_L:
21315 case OPC_DEXTR_R_L:
21316 case OPC_DEXTR_RS_L:
21317 case OPC_DEXTR_W:
21318 case OPC_DEXTR_R_W:
21319 case OPC_DEXTR_RS_W:
21320 case OPC_DEXTR_S_H:
21321 case OPC_DEXTRV_L:
21322 case OPC_DEXTRV_R_L:
21323 case OPC_DEXTRV_RS_L:
21324 case OPC_DEXTRV_S_H:
21325 case OPC_DEXTRV_W:
21326 case OPC_DEXTRV_R_W:
21327 case OPC_DEXTRV_RS_W:
21328 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
461c08df 21329 break;
099e5b4d
LA
21330 case OPC_DMTHLIP:
21331 case OPC_DSHILO:
21332 case OPC_DSHILOV:
21333 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
461c08df 21334 break;
099e5b4d
LA
21335 default: /* Invalid */
21336 MIPS_INVAL("MASK EXTR.W");
9c708c7f 21337 generate_exception_end(ctx, EXCP_RI);
461c08df 21338 break;
099e5b4d
LA
21339 }
21340 break;
21341 case OPC_DPAQ_W_QH_DSP:
21342 op2 = MASK_DPAQ_W_QH(ctx->opcode);
21343 switch (op2) {
21344 case OPC_DPAU_H_OBL:
21345 case OPC_DPAU_H_OBR:
21346 case OPC_DPSU_H_OBL:
21347 case OPC_DPSU_H_OBR:
21348 case OPC_DPA_W_QH:
21349 case OPC_DPAQ_S_W_QH:
21350 case OPC_DPS_W_QH:
21351 case OPC_DPSQ_S_W_QH:
21352 case OPC_MULSAQ_S_W_QH:
21353 case OPC_DPAQ_SA_L_PW:
21354 case OPC_DPSQ_SA_L_PW:
21355 case OPC_MULSAQ_S_L_PW:
21356 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
21357 break;
21358 case OPC_MAQ_S_W_QHLL:
21359 case OPC_MAQ_S_W_QHLR:
21360 case OPC_MAQ_S_W_QHRL:
21361 case OPC_MAQ_S_W_QHRR:
21362 case OPC_MAQ_SA_W_QHLL:
21363 case OPC_MAQ_SA_W_QHLR:
21364 case OPC_MAQ_SA_W_QHRL:
21365 case OPC_MAQ_SA_W_QHRR:
21366 case OPC_MAQ_S_L_PWL:
21367 case OPC_MAQ_S_L_PWR:
21368 case OPC_DMADD:
21369 case OPC_DMADDU:
21370 case OPC_DMSUB:
21371 case OPC_DMSUBU:
21372 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26690560 21373 break;
099e5b4d
LA
21374 default: /* Invalid */
21375 MIPS_INVAL("MASK DPAQ.W.QH");
9c708c7f 21376 generate_exception_end(ctx, EXCP_RI);
b53371ed 21377 break;
099e5b4d
LA
21378 }
21379 break;
21380 case OPC_DINSV_DSP:
21381 op2 = MASK_INSV(ctx->opcode);
21382 switch (op2) {
21383 case OPC_DINSV:
21384 {
21385 TCGv t0, t1;
21386
21387 if (rt == 0) {
a22260ae
JL
21388 break;
21389 }
099e5b4d 21390 check_dsp(ctx);
1cb6686c 21391
099e5b4d
LA
21392 t0 = tcg_temp_new();
21393 t1 = tcg_temp_new();
1cb6686c 21394
099e5b4d
LA
21395 gen_load_gpr(t0, rt);
21396 gen_load_gpr(t1, rs);
1cb6686c 21397
099e5b4d 21398 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
62eb3b9a 21399
099e5b4d
LA
21400 tcg_temp_free(t0);
21401 tcg_temp_free(t1);
77c5fa8b 21402 break;
099e5b4d 21403 }
7a387fff 21404 default: /* Invalid */
099e5b4d 21405 MIPS_INVAL("MASK DINSV");
9c708c7f 21406 generate_exception_end(ctx, EXCP_RI);
7a387fff
TS
21407 break;
21408 }
21409 break;
099e5b4d
LA
21410 case OPC_SHLL_OB_DSP:
21411 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
21412 break;
21413#endif
fac5a073
LA
21414 default: /* Invalid */
21415 MIPS_INVAL("special3_legacy");
9c708c7f 21416 generate_exception_end(ctx, EXCP_RI);
fac5a073
LA
21417 break;
21418 }
21419}
21420
21421static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
21422{
21423 int rs, rt, rd, sa;
21424 uint32_t op1, op2;
76964147 21425 int16_t imm;
fac5a073
LA
21426
21427 rs = (ctx->opcode >> 21) & 0x1f;
21428 rt = (ctx->opcode >> 16) & 0x1f;
21429 rd = (ctx->opcode >> 11) & 0x1f;
21430 sa = (ctx->opcode >> 6) & 0x1f;
76964147 21431 imm = sextract32(ctx->opcode, 7, 9);
fac5a073
LA
21432
21433 op1 = MASK_SPECIAL3(ctx->opcode);
76964147
JH
21434
21435 /*
21436 * EVA loads and stores overlap Loongson 2E instructions decoded by
21437 * decode_opc_special3_legacy(), so be careful to allow their decoding when
21438 * EVA is absent.
21439 */
21440 if (ctx->eva) {
21441 switch (op1) {
c2e19f3c
AM
21442 case OPC_LWLE:
21443 case OPC_LWRE:
76964147
JH
21444 check_insn_opc_removed(ctx, ISA_MIPS32R6);
21445 /* fall through */
c2e19f3c
AM
21446 case OPC_LBUE:
21447 case OPC_LHUE:
21448 case OPC_LBE:
21449 case OPC_LHE:
21450 case OPC_LLE:
21451 case OPC_LWE:
76964147
JH
21452 check_cp0_enabled(ctx);
21453 gen_ld(ctx, op1, rt, rs, imm);
21454 return;
c2e19f3c
AM
21455 case OPC_SWLE:
21456 case OPC_SWRE:
76964147
JH
21457 check_insn_opc_removed(ctx, ISA_MIPS32R6);
21458 /* fall through */
c2e19f3c
AM
21459 case OPC_SBE:
21460 case OPC_SHE:
76964147
JH
21461 case OPC_SWE:
21462 check_cp0_enabled(ctx);
21463 gen_st(ctx, op1, rt, rs, imm);
21464 return;
21465 case OPC_SCE:
21466 check_cp0_enabled(ctx);
21467 gen_st_cond(ctx, op1, rt, rs, imm);
21468 return;
21469 case OPC_CACHEE:
21470 check_cp0_enabled(ctx);
21471 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21472 gen_cache_operation(ctx, rt, rs, imm);
21473 }
21474 /* Treat as NOP. */
21475 return;
21476 case OPC_PREFE:
21477 check_cp0_enabled(ctx);
21478 /* Treat as NOP. */
21479 return;
21480 }
21481 }
21482
fac5a073
LA
21483 switch (op1) {
21484 case OPC_EXT:
21485 case OPC_INS:
21486 check_insn(ctx, ISA_MIPS32R2);
21487 gen_bitops(ctx, op1, rt, rs, sa, rd);
21488 break;
21489 case OPC_BSHFL:
fac5a073 21490 op2 = MASK_BSHFL(ctx->opcode);
15eacb9b 21491 switch (op2) {
c2e19f3c
AM
21492 case OPC_ALIGN:
21493 case OPC_ALIGN_END:
15eacb9b
YK
21494 case OPC_BITSWAP:
21495 check_insn(ctx, ISA_MIPS32R6);
21496 decode_opc_special3_r6(env, ctx);
21497 break;
21498 default:
21499 check_insn(ctx, ISA_MIPS32R2);
21500 gen_bshfl(ctx, op2, rt, rd);
21501 break;
21502 }
fac5a073
LA
21503 break;
21504#if defined(TARGET_MIPS64)
c2e19f3c
AM
21505 case OPC_DEXTM:
21506 case OPC_DEXTU:
21507 case OPC_DEXT:
21508 case OPC_DINSM:
21509 case OPC_DINSU:
21510 case OPC_DINS:
fac5a073
LA
21511 check_insn(ctx, ISA_MIPS64R2);
21512 check_mips_64(ctx);
21513 gen_bitops(ctx, op1, rt, rs, sa, rd);
21514 break;
21515 case OPC_DBSHFL:
fac5a073 21516 op2 = MASK_DBSHFL(ctx->opcode);
15eacb9b 21517 switch (op2) {
c2e19f3c
AM
21518 case OPC_DALIGN:
21519 case OPC_DALIGN_END:
15eacb9b
YK
21520 case OPC_DBITSWAP:
21521 check_insn(ctx, ISA_MIPS32R6);
21522 decode_opc_special3_r6(env, ctx);
21523 break;
21524 default:
21525 check_insn(ctx, ISA_MIPS64R2);
21526 check_mips_64(ctx);
21527 op2 = MASK_DBSHFL(ctx->opcode);
21528 gen_bshfl(ctx, op2, rt, rd);
21529 break;
21530 }
fac5a073
LA
21531 break;
21532#endif
21533 case OPC_RDHWR:
b00c7218 21534 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
fac5a073
LA
21535 break;
21536 case OPC_FORK:
21537 check_insn(ctx, ASE_MT);
21538 {
21539 TCGv t0 = tcg_temp_new();
21540 TCGv t1 = tcg_temp_new();
21541
21542 gen_load_gpr(t0, rt);
21543 gen_load_gpr(t1, rs);
21544 gen_helper_fork(t0, t1);
21545 tcg_temp_free(t0);
21546 tcg_temp_free(t1);
21547 }
21548 break;
21549 case OPC_YIELD:
21550 check_insn(ctx, ASE_MT);
21551 {
21552 TCGv t0 = tcg_temp_new();
21553
fac5a073
LA
21554 gen_load_gpr(t0, rs);
21555 gen_helper_yield(t0, cpu_env, t0);
21556 gen_store_gpr(t0, rd);
21557 tcg_temp_free(t0);
21558 }
21559 break;
10dc65db
LA
21560 default:
21561 if (ctx->insn_flags & ISA_MIPS32R6) {
21562 decode_opc_special3_r6(env, ctx);
21563 } else {
21564 decode_opc_special3_legacy(env, ctx);
21565 }
099e5b4d
LA
21566 }
21567}
21568
863f264d
YK
21569/* MIPS SIMD Architecture (MSA) */
21570static inline int check_msa_access(DisasContext *ctx)
21571{
21572 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
21573 !(ctx->hflags & MIPS_HFLAG_F64))) {
9c708c7f 21574 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
21575 return 0;
21576 }
21577
21578 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
21579 if (ctx->insn_flags & ASE_MSA) {
9c708c7f 21580 generate_exception_end(ctx, EXCP_MSADIS);
863f264d
YK
21581 return 0;
21582 } else {
9c708c7f 21583 generate_exception_end(ctx, EXCP_RI);
863f264d
YK
21584 return 0;
21585 }
21586 }
21587 return 1;
21588}
21589
5692c6e1
YK
21590static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
21591{
21592 /* generates tcg ops to check if any element is 0 */
21593 /* Note this function only works with MSA_WRLEN = 128 */
21594 uint64_t eval_zero_or_big = 0;
21595 uint64_t eval_big = 0;
21596 TCGv_i64 t0 = tcg_temp_new_i64();
21597 TCGv_i64 t1 = tcg_temp_new_i64();
21598 switch (df) {
21599 case DF_BYTE:
21600 eval_zero_or_big = 0x0101010101010101ULL;
21601 eval_big = 0x8080808080808080ULL;
21602 break;
21603 case DF_HALF:
21604 eval_zero_or_big = 0x0001000100010001ULL;
21605 eval_big = 0x8000800080008000ULL;
21606 break;
21607 case DF_WORD:
21608 eval_zero_or_big = 0x0000000100000001ULL;
21609 eval_big = 0x8000000080000000ULL;
21610 break;
21611 case DF_DOUBLE:
21612 eval_zero_or_big = 0x0000000000000001ULL;
21613 eval_big = 0x8000000000000000ULL;
21614 break;
21615 }
21616 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
21617 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
21618 tcg_gen_andi_i64(t0, t0, eval_big);
21619 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
21620 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
21621 tcg_gen_andi_i64(t1, t1, eval_big);
21622 tcg_gen_or_i64(t0, t0, t1);
21623 /* if all bits are zero then all elements are not zero */
21624 /* if some bit is non-zero then some element is zero */
21625 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
21626 tcg_gen_trunc_i64_tl(tresult, t0);
21627 tcg_temp_free_i64(t0);
21628 tcg_temp_free_i64(t1);
21629}
21630
21631static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
21632{
21633 uint8_t df = (ctx->opcode >> 21) & 0x3;
21634 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
21635 int64_t s16 = (int16_t)ctx->opcode;
21636
21637 check_msa_access(ctx);
21638
075a1fe7 21639 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9c708c7f 21640 generate_exception_end(ctx, EXCP_RI);
5692c6e1
YK
21641 return;
21642 }
21643 switch (op1) {
21644 case OPC_BZ_V:
21645 case OPC_BNZ_V:
21646 {
21647 TCGv_i64 t0 = tcg_temp_new_i64();
21648 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
21649 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
21650 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
21651 tcg_gen_trunc_i64_tl(bcond, t0);
21652 tcg_temp_free_i64(t0);
21653 }
21654 break;
21655 case OPC_BZ_B:
21656 case OPC_BZ_H:
21657 case OPC_BZ_W:
21658 case OPC_BZ_D:
21659 gen_check_zero_element(bcond, df, wt);
21660 break;
21661 case OPC_BNZ_B:
21662 case OPC_BNZ_H:
21663 case OPC_BNZ_W:
21664 case OPC_BNZ_D:
21665 gen_check_zero_element(bcond, df, wt);
21666 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
21667 break;
21668 }
21669
eeb3bba8 21670 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
5692c6e1
YK
21671
21672 ctx->hflags |= MIPS_HFLAG_BC;
21673 ctx->hflags |= MIPS_HFLAG_BDS32;
21674}
21675
4c789546
YK
21676static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
21677{
21678#define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
21679 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
21680 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
21681 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
21682
21683 TCGv_i32 twd = tcg_const_i32(wd);
21684 TCGv_i32 tws = tcg_const_i32(ws);
21685 TCGv_i32 ti8 = tcg_const_i32(i8);
21686
21687 switch (MASK_MSA_I8(ctx->opcode)) {
21688 case OPC_ANDI_B:
21689 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
21690 break;
21691 case OPC_ORI_B:
21692 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
21693 break;
21694 case OPC_NORI_B:
21695 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
21696 break;
21697 case OPC_XORI_B:
21698 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
21699 break;
21700 case OPC_BMNZI_B:
21701 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
21702 break;
21703 case OPC_BMZI_B:
21704 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
21705 break;
21706 case OPC_BSELI_B:
21707 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
21708 break;
21709 case OPC_SHF_B:
21710 case OPC_SHF_H:
21711 case OPC_SHF_W:
21712 {
21713 uint8_t df = (ctx->opcode >> 24) & 0x3;
21714 if (df == DF_DOUBLE) {
9c708c7f 21715 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
21716 } else {
21717 TCGv_i32 tdf = tcg_const_i32(df);
21718 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
21719 tcg_temp_free_i32(tdf);
21720 }
21721 }
21722 break;
21723 default:
21724 MIPS_INVAL("MSA instruction");
9c708c7f 21725 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
21726 break;
21727 }
21728
21729 tcg_temp_free_i32(twd);
21730 tcg_temp_free_i32(tws);
21731 tcg_temp_free_i32(ti8);
21732}
21733
80e71591
YK
21734static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
21735{
21736#define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
21737 uint8_t df = (ctx->opcode >> 21) & 0x3;
21738 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
21739 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
21740 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
21741 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
21742
21743 TCGv_i32 tdf = tcg_const_i32(df);
21744 TCGv_i32 twd = tcg_const_i32(wd);
21745 TCGv_i32 tws = tcg_const_i32(ws);
21746 TCGv_i32 timm = tcg_temp_new_i32();
21747 tcg_gen_movi_i32(timm, u5);
21748
21749 switch (MASK_MSA_I5(ctx->opcode)) {
21750 case OPC_ADDVI_df:
21751 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
21752 break;
21753 case OPC_SUBVI_df:
21754 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
21755 break;
21756 case OPC_MAXI_S_df:
21757 tcg_gen_movi_i32(timm, s5);
21758 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
21759 break;
21760 case OPC_MAXI_U_df:
21761 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
21762 break;
21763 case OPC_MINI_S_df:
21764 tcg_gen_movi_i32(timm, s5);
21765 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
21766 break;
21767 case OPC_MINI_U_df:
21768 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
21769 break;
21770 case OPC_CEQI_df:
21771 tcg_gen_movi_i32(timm, s5);
21772 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
21773 break;
21774 case OPC_CLTI_S_df:
21775 tcg_gen_movi_i32(timm, s5);
21776 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
21777 break;
21778 case OPC_CLTI_U_df:
21779 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
21780 break;
21781 case OPC_CLEI_S_df:
21782 tcg_gen_movi_i32(timm, s5);
21783 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
21784 break;
21785 case OPC_CLEI_U_df:
21786 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
21787 break;
21788 case OPC_LDI_df:
21789 {
21790 int32_t s10 = sextract32(ctx->opcode, 11, 10);
21791 tcg_gen_movi_i32(timm, s10);
21792 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
21793 }
21794 break;
21795 default:
21796 MIPS_INVAL("MSA instruction");
9c708c7f 21797 generate_exception_end(ctx, EXCP_RI);
80e71591
YK
21798 break;
21799 }
21800
21801 tcg_temp_free_i32(tdf);
21802 tcg_temp_free_i32(twd);
21803 tcg_temp_free_i32(tws);
21804 tcg_temp_free_i32(timm);
21805}
21806
d4cf28de
YK
21807static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
21808{
21809#define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
21810 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
21811 uint32_t df = 0, m = 0;
21812 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
21813 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
21814
21815 TCGv_i32 tdf;
21816 TCGv_i32 tm;
21817 TCGv_i32 twd;
21818 TCGv_i32 tws;
21819
21820 if ((dfm & 0x40) == 0x00) {
21821 m = dfm & 0x3f;
21822 df = DF_DOUBLE;
21823 } else if ((dfm & 0x60) == 0x40) {
21824 m = dfm & 0x1f;
21825 df = DF_WORD;
21826 } else if ((dfm & 0x70) == 0x60) {
21827 m = dfm & 0x0f;
21828 df = DF_HALF;
21829 } else if ((dfm & 0x78) == 0x70) {
21830 m = dfm & 0x7;
21831 df = DF_BYTE;
21832 } else {
9c708c7f 21833 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
21834 return;
21835 }
21836
21837 tdf = tcg_const_i32(df);
21838 tm = tcg_const_i32(m);
21839 twd = tcg_const_i32(wd);
21840 tws = tcg_const_i32(ws);
21841
21842 switch (MASK_MSA_BIT(ctx->opcode)) {
21843 case OPC_SLLI_df:
21844 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
21845 break;
21846 case OPC_SRAI_df:
21847 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
21848 break;
21849 case OPC_SRLI_df:
21850 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
21851 break;
21852 case OPC_BCLRI_df:
21853 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
21854 break;
21855 case OPC_BSETI_df:
21856 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
21857 break;
21858 case OPC_BNEGI_df:
21859 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
21860 break;
21861 case OPC_BINSLI_df:
21862 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
21863 break;
21864 case OPC_BINSRI_df:
21865 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
21866 break;
21867 case OPC_SAT_S_df:
21868 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
21869 break;
21870 case OPC_SAT_U_df:
21871 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
21872 break;
21873 case OPC_SRARI_df:
21874 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
21875 break;
21876 case OPC_SRLRI_df:
21877 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
21878 break;
21879 default:
21880 MIPS_INVAL("MSA instruction");
9c708c7f 21881 generate_exception_end(ctx, EXCP_RI);
d4cf28de
YK
21882 break;
21883 }
21884
21885 tcg_temp_free_i32(tdf);
21886 tcg_temp_free_i32(tm);
21887 tcg_temp_free_i32(twd);
21888 tcg_temp_free_i32(tws);
21889}
21890
28f99f08
YK
21891static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
21892{
21893#define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
21894 uint8_t df = (ctx->opcode >> 21) & 0x3;
21895 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
21896 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
21897 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
21898
21899 TCGv_i32 tdf = tcg_const_i32(df);
21900 TCGv_i32 twd = tcg_const_i32(wd);
21901 TCGv_i32 tws = tcg_const_i32(ws);
21902 TCGv_i32 twt = tcg_const_i32(wt);
21903
21904 switch (MASK_MSA_3R(ctx->opcode)) {
21905 case OPC_SLL_df:
21906 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
21907 break;
21908 case OPC_ADDV_df:
21909 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
21910 break;
21911 case OPC_CEQ_df:
21912 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
21913 break;
21914 case OPC_ADD_A_df:
21915 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
21916 break;
21917 case OPC_SUBS_S_df:
21918 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
21919 break;
21920 case OPC_MULV_df:
21921 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
21922 break;
21923 case OPC_SLD_df:
21924 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
21925 break;
21926 case OPC_VSHF_df:
21927 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
21928 break;
21929 case OPC_SRA_df:
21930 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
21931 break;
21932 case OPC_SUBV_df:
21933 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
21934 break;
21935 case OPC_ADDS_A_df:
21936 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
21937 break;
21938 case OPC_SUBS_U_df:
21939 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
21940 break;
21941 case OPC_MADDV_df:
21942 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
21943 break;
21944 case OPC_SPLAT_df:
21945 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
21946 break;
21947 case OPC_SRAR_df:
21948 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
21949 break;
21950 case OPC_SRL_df:
21951 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
21952 break;
21953 case OPC_MAX_S_df:
21954 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
21955 break;
21956 case OPC_CLT_S_df:
21957 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
21958 break;
21959 case OPC_ADDS_S_df:
21960 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
21961 break;
21962 case OPC_SUBSUS_U_df:
21963 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
21964 break;
21965 case OPC_MSUBV_df:
21966 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
21967 break;
21968 case OPC_PCKEV_df:
21969 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
21970 break;
21971 case OPC_SRLR_df:
21972 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
21973 break;
21974 case OPC_BCLR_df:
21975 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
21976 break;
21977 case OPC_MAX_U_df:
21978 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
21979 break;
21980 case OPC_CLT_U_df:
21981 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
21982 break;
21983 case OPC_ADDS_U_df:
21984 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
21985 break;
21986 case OPC_SUBSUU_S_df:
21987 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
21988 break;
21989 case OPC_PCKOD_df:
21990 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
21991 break;
21992 case OPC_BSET_df:
21993 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
21994 break;
21995 case OPC_MIN_S_df:
21996 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
21997 break;
21998 case OPC_CLE_S_df:
21999 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
22000 break;
22001 case OPC_AVE_S_df:
22002 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
22003 break;
22004 case OPC_ASUB_S_df:
22005 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
22006 break;
22007 case OPC_DIV_S_df:
22008 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
22009 break;
22010 case OPC_ILVL_df:
22011 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
22012 break;
22013 case OPC_BNEG_df:
22014 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
22015 break;
22016 case OPC_MIN_U_df:
22017 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
22018 break;
22019 case OPC_CLE_U_df:
22020 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
22021 break;
22022 case OPC_AVE_U_df:
22023 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
22024 break;
22025 case OPC_ASUB_U_df:
22026 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
22027 break;
22028 case OPC_DIV_U_df:
22029 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
22030 break;
22031 case OPC_ILVR_df:
22032 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
22033 break;
22034 case OPC_BINSL_df:
22035 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
22036 break;
22037 case OPC_MAX_A_df:
22038 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
22039 break;
22040 case OPC_AVER_S_df:
22041 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
22042 break;
22043 case OPC_MOD_S_df:
22044 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
22045 break;
22046 case OPC_ILVEV_df:
22047 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
22048 break;
22049 case OPC_BINSR_df:
22050 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
22051 break;
22052 case OPC_MIN_A_df:
22053 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
22054 break;
22055 case OPC_AVER_U_df:
22056 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
22057 break;
22058 case OPC_MOD_U_df:
22059 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
22060 break;
22061 case OPC_ILVOD_df:
22062 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
22063 break;
22064
22065 case OPC_DOTP_S_df:
22066 case OPC_DOTP_U_df:
22067 case OPC_DPADD_S_df:
22068 case OPC_DPADD_U_df:
22069 case OPC_DPSUB_S_df:
22070 case OPC_HADD_S_df:
22071 case OPC_DPSUB_U_df:
22072 case OPC_HADD_U_df:
22073 case OPC_HSUB_S_df:
22074 case OPC_HSUB_U_df:
22075 if (df == DF_BYTE) {
9c708c7f
PD
22076 generate_exception_end(ctx, EXCP_RI);
22077 break;
28f99f08
YK
22078 }
22079 switch (MASK_MSA_3R(ctx->opcode)) {
22080 case OPC_DOTP_S_df:
22081 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
22082 break;
22083 case OPC_DOTP_U_df:
22084 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
22085 break;
22086 case OPC_DPADD_S_df:
22087 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
22088 break;
22089 case OPC_DPADD_U_df:
22090 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
22091 break;
22092 case OPC_DPSUB_S_df:
22093 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
22094 break;
22095 case OPC_HADD_S_df:
22096 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
22097 break;
22098 case OPC_DPSUB_U_df:
22099 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
22100 break;
22101 case OPC_HADD_U_df:
22102 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
22103 break;
22104 case OPC_HSUB_S_df:
22105 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
22106 break;
22107 case OPC_HSUB_U_df:
22108 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
22109 break;
22110 }
22111 break;
22112 default:
22113 MIPS_INVAL("MSA instruction");
9c708c7f 22114 generate_exception_end(ctx, EXCP_RI);
28f99f08
YK
22115 break;
22116 }
22117 tcg_temp_free_i32(twd);
22118 tcg_temp_free_i32(tws);
22119 tcg_temp_free_i32(twt);
22120 tcg_temp_free_i32(tdf);
22121}
22122
1e608ec1
YK
22123static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
22124{
22125#define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
22126 uint8_t source = (ctx->opcode >> 11) & 0x1f;
22127 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
22128 TCGv telm = tcg_temp_new();
22129 TCGv_i32 tsr = tcg_const_i32(source);
22130 TCGv_i32 tdt = tcg_const_i32(dest);
22131
22132 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
22133 case OPC_CTCMSA:
22134 gen_load_gpr(telm, source);
22135 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
22136 break;
22137 case OPC_CFCMSA:
22138 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
22139 gen_store_gpr(telm, dest);
22140 break;
22141 case OPC_MOVE_V:
22142 gen_helper_msa_move_v(cpu_env, tdt, tsr);
22143 break;
22144 default:
22145 MIPS_INVAL("MSA instruction");
9c708c7f 22146 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
22147 break;
22148 }
22149
22150 tcg_temp_free(telm);
22151 tcg_temp_free_i32(tdt);
22152 tcg_temp_free_i32(tsr);
22153}
22154
22155static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
22156 uint32_t n)
22157{
22158#define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
22159 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
22160 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
22161
22162 TCGv_i32 tws = tcg_const_i32(ws);
22163 TCGv_i32 twd = tcg_const_i32(wd);
22164 TCGv_i32 tn = tcg_const_i32(n);
22165 TCGv_i32 tdf = tcg_const_i32(df);
22166
22167 switch (MASK_MSA_ELM(ctx->opcode)) {
22168 case OPC_SLDI_df:
22169 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
22170 break;
22171 case OPC_SPLATI_df:
22172 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
22173 break;
22174 case OPC_INSVE_df:
22175 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
22176 break;
22177 case OPC_COPY_S_df:
22178 case OPC_COPY_U_df:
22179 case OPC_INSERT_df:
22180#if !defined(TARGET_MIPS64)
22181 /* Double format valid only for MIPS64 */
22182 if (df == DF_DOUBLE) {
9c708c7f 22183 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
22184 break;
22185 }
22186#endif
22187 switch (MASK_MSA_ELM(ctx->opcode)) {
22188 case OPC_COPY_S_df:
cab48881
MD
22189 if (likely(wd != 0)) {
22190 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
22191 }
1e608ec1
YK
22192 break;
22193 case OPC_COPY_U_df:
cab48881
MD
22194 if (likely(wd != 0)) {
22195 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
22196 }
1e608ec1
YK
22197 break;
22198 case OPC_INSERT_df:
22199 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
22200 break;
22201 }
22202 break;
22203 default:
22204 MIPS_INVAL("MSA instruction");
9c708c7f 22205 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
22206 }
22207 tcg_temp_free_i32(twd);
22208 tcg_temp_free_i32(tws);
22209 tcg_temp_free_i32(tn);
22210 tcg_temp_free_i32(tdf);
22211}
22212
22213static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
22214{
22215 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
22216 uint32_t df = 0, n = 0;
22217
22218 if ((dfn & 0x30) == 0x00) {
22219 n = dfn & 0x0f;
22220 df = DF_BYTE;
22221 } else if ((dfn & 0x38) == 0x20) {
22222 n = dfn & 0x07;
22223 df = DF_HALF;
22224 } else if ((dfn & 0x3c) == 0x30) {
22225 n = dfn & 0x03;
22226 df = DF_WORD;
22227 } else if ((dfn & 0x3e) == 0x38) {
22228 n = dfn & 0x01;
22229 df = DF_DOUBLE;
22230 } else if (dfn == 0x3E) {
22231 /* CTCMSA, CFCMSA, MOVE.V */
22232 gen_msa_elm_3e(env, ctx);
22233 return;
22234 } else {
9c708c7f 22235 generate_exception_end(ctx, EXCP_RI);
1e608ec1
YK
22236 return;
22237 }
22238
22239 gen_msa_elm_df(env, ctx, df, n);
22240}
22241
7d05b9c8
YK
22242static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
22243{
22244#define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
22245 uint8_t df = (ctx->opcode >> 21) & 0x1;
22246 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
22247 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
22248 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
22249
22250 TCGv_i32 twd = tcg_const_i32(wd);
22251 TCGv_i32 tws = tcg_const_i32(ws);
22252 TCGv_i32 twt = tcg_const_i32(wt);
22253 TCGv_i32 tdf = tcg_temp_new_i32();
22254
22255 /* adjust df value for floating-point instruction */
22256 tcg_gen_movi_i32(tdf, df + 2);
22257
22258 switch (MASK_MSA_3RF(ctx->opcode)) {
22259 case OPC_FCAF_df:
22260 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
22261 break;
22262 case OPC_FADD_df:
22263 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
22264 break;
22265 case OPC_FCUN_df:
22266 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
22267 break;
22268 case OPC_FSUB_df:
22269 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
22270 break;
22271 case OPC_FCOR_df:
22272 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
22273 break;
22274 case OPC_FCEQ_df:
22275 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
22276 break;
22277 case OPC_FMUL_df:
22278 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
22279 break;
22280 case OPC_FCUNE_df:
22281 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
22282 break;
22283 case OPC_FCUEQ_df:
22284 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
22285 break;
22286 case OPC_FDIV_df:
22287 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
22288 break;
22289 case OPC_FCNE_df:
22290 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
22291 break;
22292 case OPC_FCLT_df:
22293 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
22294 break;
22295 case OPC_FMADD_df:
22296 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
22297 break;
22298 case OPC_MUL_Q_df:
22299 tcg_gen_movi_i32(tdf, df + 1);
22300 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
22301 break;
22302 case OPC_FCULT_df:
22303 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
22304 break;
22305 case OPC_FMSUB_df:
22306 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
22307 break;
22308 case OPC_MADD_Q_df:
22309 tcg_gen_movi_i32(tdf, df + 1);
22310 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
22311 break;
22312 case OPC_FCLE_df:
22313 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
22314 break;
22315 case OPC_MSUB_Q_df:
22316 tcg_gen_movi_i32(tdf, df + 1);
22317 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
22318 break;
22319 case OPC_FCULE_df:
22320 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
22321 break;
22322 case OPC_FEXP2_df:
22323 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
22324 break;
22325 case OPC_FSAF_df:
22326 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
22327 break;
22328 case OPC_FEXDO_df:
22329 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
22330 break;
22331 case OPC_FSUN_df:
22332 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
22333 break;
22334 case OPC_FSOR_df:
22335 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
22336 break;
22337 case OPC_FSEQ_df:
22338 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
22339 break;
22340 case OPC_FTQ_df:
22341 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
22342 break;
22343 case OPC_FSUNE_df:
22344 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
22345 break;
22346 case OPC_FSUEQ_df:
22347 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
22348 break;
22349 case OPC_FSNE_df:
22350 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
22351 break;
22352 case OPC_FSLT_df:
22353 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
22354 break;
22355 case OPC_FMIN_df:
22356 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
22357 break;
22358 case OPC_MULR_Q_df:
22359 tcg_gen_movi_i32(tdf, df + 1);
22360 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
22361 break;
22362 case OPC_FSULT_df:
22363 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
22364 break;
22365 case OPC_FMIN_A_df:
22366 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
22367 break;
22368 case OPC_MADDR_Q_df:
22369 tcg_gen_movi_i32(tdf, df + 1);
22370 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
22371 break;
22372 case OPC_FSLE_df:
22373 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
22374 break;
22375 case OPC_FMAX_df:
22376 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
22377 break;
22378 case OPC_MSUBR_Q_df:
22379 tcg_gen_movi_i32(tdf, df + 1);
22380 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
22381 break;
22382 case OPC_FSULE_df:
22383 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
22384 break;
22385 case OPC_FMAX_A_df:
22386 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
22387 break;
22388 default:
22389 MIPS_INVAL("MSA instruction");
9c708c7f 22390 generate_exception_end(ctx, EXCP_RI);
7d05b9c8
YK
22391 break;
22392 }
22393
22394 tcg_temp_free_i32(twd);
22395 tcg_temp_free_i32(tws);
22396 tcg_temp_free_i32(twt);
22397 tcg_temp_free_i32(tdf);
22398}
22399
cbe50b9a
YK
22400static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
22401{
22402#define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
22403 (op & (0x7 << 18)))
22404 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
22405 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
22406 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
22407 uint8_t df = (ctx->opcode >> 16) & 0x3;
22408 TCGv_i32 twd = tcg_const_i32(wd);
22409 TCGv_i32 tws = tcg_const_i32(ws);
22410 TCGv_i32 twt = tcg_const_i32(wt);
22411 TCGv_i32 tdf = tcg_const_i32(df);
22412
22413 switch (MASK_MSA_2R(ctx->opcode)) {
22414 case OPC_FILL_df:
22415#if !defined(TARGET_MIPS64)
22416 /* Double format valid only for MIPS64 */
22417 if (df == DF_DOUBLE) {
9c708c7f 22418 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
22419 break;
22420 }
22421#endif
22422 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
22423 break;
22424 case OPC_PCNT_df:
22425 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
22426 break;
22427 case OPC_NLOC_df:
22428 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
22429 break;
22430 case OPC_NLZC_df:
22431 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
22432 break;
22433 default:
22434 MIPS_INVAL("MSA instruction");
9c708c7f 22435 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
22436 break;
22437 }
22438
22439 tcg_temp_free_i32(twd);
22440 tcg_temp_free_i32(tws);
22441 tcg_temp_free_i32(twt);
22442 tcg_temp_free_i32(tdf);
22443}
22444
3bdeb688
YK
22445static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
22446{
22447#define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
22448 (op & (0xf << 17)))
22449 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
22450 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
22451 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
22452 uint8_t df = (ctx->opcode >> 16) & 0x1;
22453 TCGv_i32 twd = tcg_const_i32(wd);
22454 TCGv_i32 tws = tcg_const_i32(ws);
22455 TCGv_i32 twt = tcg_const_i32(wt);
22456 /* adjust df value for floating-point instruction */
22457 TCGv_i32 tdf = tcg_const_i32(df + 2);
22458
22459 switch (MASK_MSA_2RF(ctx->opcode)) {
22460 case OPC_FCLASS_df:
22461 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
22462 break;
22463 case OPC_FTRUNC_S_df:
22464 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
22465 break;
22466 case OPC_FTRUNC_U_df:
22467 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
22468 break;
22469 case OPC_FSQRT_df:
22470 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
22471 break;
22472 case OPC_FRSQRT_df:
22473 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
22474 break;
22475 case OPC_FRCP_df:
22476 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
22477 break;
22478 case OPC_FRINT_df:
22479 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
22480 break;
22481 case OPC_FLOG2_df:
22482 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
22483 break;
22484 case OPC_FEXUPL_df:
22485 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
22486 break;
22487 case OPC_FEXUPR_df:
22488 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
22489 break;
22490 case OPC_FFQL_df:
22491 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
22492 break;
22493 case OPC_FFQR_df:
22494 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
22495 break;
22496 case OPC_FTINT_S_df:
22497 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
22498 break;
22499 case OPC_FTINT_U_df:
22500 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
22501 break;
22502 case OPC_FFINT_S_df:
22503 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
22504 break;
22505 case OPC_FFINT_U_df:
22506 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
22507 break;
22508 }
22509
22510 tcg_temp_free_i32(twd);
22511 tcg_temp_free_i32(tws);
22512 tcg_temp_free_i32(twt);
22513 tcg_temp_free_i32(tdf);
22514}
22515
cbe50b9a
YK
22516static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
22517{
22518#define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
22519 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
22520 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
22521 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
22522 TCGv_i32 twd = tcg_const_i32(wd);
22523 TCGv_i32 tws = tcg_const_i32(ws);
22524 TCGv_i32 twt = tcg_const_i32(wt);
22525
22526 switch (MASK_MSA_VEC(ctx->opcode)) {
22527 case OPC_AND_V:
22528 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
22529 break;
22530 case OPC_OR_V:
22531 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
22532 break;
22533 case OPC_NOR_V:
22534 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
22535 break;
22536 case OPC_XOR_V:
22537 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
22538 break;
22539 case OPC_BMNZ_V:
22540 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
22541 break;
22542 case OPC_BMZ_V:
22543 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
22544 break;
22545 case OPC_BSEL_V:
22546 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
22547 break;
22548 default:
22549 MIPS_INVAL("MSA instruction");
9c708c7f 22550 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
22551 break;
22552 }
22553
22554 tcg_temp_free_i32(twd);
22555 tcg_temp_free_i32(tws);
22556 tcg_temp_free_i32(twt);
22557}
22558
22559static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
22560{
22561 switch (MASK_MSA_VEC(ctx->opcode)) {
22562 case OPC_AND_V:
22563 case OPC_OR_V:
22564 case OPC_NOR_V:
22565 case OPC_XOR_V:
22566 case OPC_BMNZ_V:
22567 case OPC_BMZ_V:
22568 case OPC_BSEL_V:
22569 gen_msa_vec_v(env, ctx);
22570 break;
22571 case OPC_MSA_2R:
22572 gen_msa_2r(env, ctx);
22573 break;
3bdeb688
YK
22574 case OPC_MSA_2RF:
22575 gen_msa_2rf(env, ctx);
22576 break;
cbe50b9a
YK
22577 default:
22578 MIPS_INVAL("MSA instruction");
9c708c7f 22579 generate_exception_end(ctx, EXCP_RI);
cbe50b9a
YK
22580 break;
22581 }
22582}
22583
4c789546
YK
22584static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
22585{
22586 uint32_t opcode = ctx->opcode;
22587 check_insn(ctx, ASE_MSA);
22588 check_msa_access(ctx);
22589
22590 switch (MASK_MSA_MINOR(opcode)) {
22591 case OPC_MSA_I8_00:
22592 case OPC_MSA_I8_01:
22593 case OPC_MSA_I8_02:
22594 gen_msa_i8(env, ctx);
22595 break;
80e71591
YK
22596 case OPC_MSA_I5_06:
22597 case OPC_MSA_I5_07:
22598 gen_msa_i5(env, ctx);
22599 break;
d4cf28de
YK
22600 case OPC_MSA_BIT_09:
22601 case OPC_MSA_BIT_0A:
22602 gen_msa_bit(env, ctx);
22603 break;
28f99f08
YK
22604 case OPC_MSA_3R_0D:
22605 case OPC_MSA_3R_0E:
22606 case OPC_MSA_3R_0F:
22607 case OPC_MSA_3R_10:
22608 case OPC_MSA_3R_11:
22609 case OPC_MSA_3R_12:
22610 case OPC_MSA_3R_13:
22611 case OPC_MSA_3R_14:
22612 case OPC_MSA_3R_15:
22613 gen_msa_3r(env, ctx);
22614 break;
1e608ec1
YK
22615 case OPC_MSA_ELM:
22616 gen_msa_elm(env, ctx);
22617 break;
7d05b9c8
YK
22618 case OPC_MSA_3RF_1A:
22619 case OPC_MSA_3RF_1B:
22620 case OPC_MSA_3RF_1C:
22621 gen_msa_3rf(env, ctx);
22622 break;
cbe50b9a
YK
22623 case OPC_MSA_VEC:
22624 gen_msa_vec(env, ctx);
22625 break;
f7685877
YK
22626 case OPC_LD_B:
22627 case OPC_LD_H:
22628 case OPC_LD_W:
22629 case OPC_LD_D:
22630 case OPC_ST_B:
22631 case OPC_ST_H:
22632 case OPC_ST_W:
22633 case OPC_ST_D:
22634 {
22635 int32_t s10 = sextract32(ctx->opcode, 16, 10);
22636 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
22637 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
22638 uint8_t df = (ctx->opcode >> 0) & 0x3;
22639
f7685877 22640 TCGv_i32 twd = tcg_const_i32(wd);
adc370a4
YK
22641 TCGv taddr = tcg_temp_new();
22642 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
f7685877
YK
22643
22644 switch (MASK_MSA_MINOR(opcode)) {
22645 case OPC_LD_B:
adc370a4
YK
22646 gen_helper_msa_ld_b(cpu_env, twd, taddr);
22647 break;
f7685877 22648 case OPC_LD_H:
adc370a4
YK
22649 gen_helper_msa_ld_h(cpu_env, twd, taddr);
22650 break;
f7685877 22651 case OPC_LD_W:
adc370a4
YK
22652 gen_helper_msa_ld_w(cpu_env, twd, taddr);
22653 break;
f7685877 22654 case OPC_LD_D:
adc370a4 22655 gen_helper_msa_ld_d(cpu_env, twd, taddr);
f7685877
YK
22656 break;
22657 case OPC_ST_B:
adc370a4
YK
22658 gen_helper_msa_st_b(cpu_env, twd, taddr);
22659 break;
f7685877 22660 case OPC_ST_H:
adc370a4
YK
22661 gen_helper_msa_st_h(cpu_env, twd, taddr);
22662 break;
f7685877 22663 case OPC_ST_W:
adc370a4
YK
22664 gen_helper_msa_st_w(cpu_env, twd, taddr);
22665 break;
f7685877 22666 case OPC_ST_D:
adc370a4 22667 gen_helper_msa_st_d(cpu_env, twd, taddr);
f7685877
YK
22668 break;
22669 }
22670
22671 tcg_temp_free_i32(twd);
adc370a4 22672 tcg_temp_free(taddr);
f7685877
YK
22673 }
22674 break;
4c789546
YK
22675 default:
22676 MIPS_INVAL("MSA instruction");
9c708c7f 22677 generate_exception_end(ctx, EXCP_RI);
4c789546
YK
22678 break;
22679 }
22680
22681}
22682
d2bfa6e6 22683static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
099e5b4d
LA
22684{
22685 int32_t offset;
22686 int rs, rt, rd, sa;
22687 uint32_t op, op1;
22688 int16_t imm;
22689
22690 /* make sure instructions are on a word boundary */
eeb3bba8
EC
22691 if (ctx->base.pc_next & 0x3) {
22692 env->CP0_BadVAddr = ctx->base.pc_next;
aea14095 22693 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
099e5b4d
LA
22694 return;
22695 }
22696
22697 /* Handle blikely not taken case */
22698 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
42a268c2 22699 TCGLabel *l1 = gen_new_label();
099e5b4d 22700
099e5b4d
LA
22701 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
22702 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
eeb3bba8 22703 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
099e5b4d
LA
22704 gen_set_label(l1);
22705 }
22706
099e5b4d
LA
22707 op = MASK_OP_MAJOR(ctx->opcode);
22708 rs = (ctx->opcode >> 21) & 0x1f;
22709 rt = (ctx->opcode >> 16) & 0x1f;
22710 rd = (ctx->opcode >> 11) & 0x1f;
22711 sa = (ctx->opcode >> 6) & 0x1f;
22712 imm = (int16_t)ctx->opcode;
22713 switch (op) {
22714 case OPC_SPECIAL:
22715 decode_opc_special(env, ctx);
22716 break;
22717 case OPC_SPECIAL2:
4267d3e6 22718 decode_opc_special2_legacy(env, ctx);
099e5b4d
LA
22719 break;
22720 case OPC_SPECIAL3:
22721 decode_opc_special3(env, ctx);
22722 break;
7a387fff
TS
22723 case OPC_REGIMM:
22724 op1 = MASK_REGIMM(ctx->opcode);
22725 switch (op1) {
fecd2646
LA
22726 case OPC_BLTZL: /* REGIMM branches */
22727 case OPC_BGEZL:
22728 case OPC_BLTZALL:
22729 case OPC_BGEZALL:
d9224450 22730 check_insn(ctx, ISA_MIPS2);
fecd2646 22731 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 22732 /* Fallthrough */
fecd2646
LA
22733 case OPC_BLTZ:
22734 case OPC_BGEZ:
b231c103 22735 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 22736 break;
fecd2646
LA
22737 case OPC_BLTZAL:
22738 case OPC_BGEZAL:
0aefa333
YK
22739 if (ctx->insn_flags & ISA_MIPS32R6) {
22740 if (rs == 0) {
22741 /* OPC_NAL, OPC_BAL */
b231c103 22742 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
0aefa333 22743 } else {
9c708c7f 22744 generate_exception_end(ctx, EXCP_RI);
0aefa333
YK
22745 }
22746 } else {
b231c103 22747 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
0aefa333 22748 }
c9602061 22749 break;
c2e19f3c
AM
22750 case OPC_TGEI: /* REGIMM traps */
22751 case OPC_TGEIU:
22752 case OPC_TLTI:
22753 case OPC_TLTIU:
22754 case OPC_TEQI:
22755
7a387fff 22756 case OPC_TNEI:
d9224450 22757 check_insn(ctx, ISA_MIPS2);
fecd2646 22758 check_insn_opc_removed(ctx, ISA_MIPS32R6);
7a387fff
TS
22759 gen_trap(ctx, op1, rs, -1, imm);
22760 break;
bb238210
YK
22761 case OPC_SIGRIE:
22762 check_insn(ctx, ISA_MIPS32R6);
22763 generate_exception_end(ctx, EXCP_RI);
22764 break;
7a387fff 22765 case OPC_SYNCI:
d75c135e 22766 check_insn(ctx, ISA_MIPS32R2);
a83bddd6
DZ
22767 /* Break the TB to be able to sync copied instructions
22768 immediately */
eeb3bba8 22769 ctx->base.is_jmp = DISAS_STOP;
6af0bf9c 22770 break;
e45a93e2
JL
22771 case OPC_BPOSGE32: /* MIPS DSP branch */
22772#if defined(TARGET_MIPS64)
22773 case OPC_BPOSGE64:
22774#endif
22775 check_dsp(ctx);
b231c103 22776 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
e45a93e2 22777 break;
d4ea6acd
LA
22778#if defined(TARGET_MIPS64)
22779 case OPC_DAHI:
22780 check_insn(ctx, ISA_MIPS32R6);
22781 check_mips_64(ctx);
22782 if (rs != 0) {
22783 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
22784 }
d4ea6acd
LA
22785 break;
22786 case OPC_DATI:
22787 check_insn(ctx, ISA_MIPS32R6);
22788 check_mips_64(ctx);
22789 if (rs != 0) {
22790 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
22791 }
d4ea6acd
LA
22792 break;
22793#endif
6af0bf9c 22794 default: /* Invalid */
923617a3 22795 MIPS_INVAL("regimm");
9c708c7f 22796 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
22797 break;
22798 }
22799 break;
7a387fff 22800 case OPC_CP0:
387a8fe5 22801 check_cp0_enabled(ctx);
7a387fff 22802 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 22803 switch (op1) {
7a387fff
TS
22804 case OPC_MFC0:
22805 case OPC_MTC0:
ead9360e
TS
22806 case OPC_MFTR:
22807 case OPC_MTTR:
5204ea79
LA
22808 case OPC_MFHC0:
22809 case OPC_MTHC0:
d26bc211 22810#if defined(TARGET_MIPS64)
7a387fff
TS
22811 case OPC_DMFC0:
22812 case OPC_DMTC0:
22813#endif
f1aa6320 22814#ifndef CONFIG_USER_ONLY
932e71cd 22815 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 22816#endif /* !CONFIG_USER_ONLY */
7a387fff 22817 break;
c38a1d52
AR
22818 case OPC_C0:
22819 case OPC_C0_1:
22820 case OPC_C0_2:
22821 case OPC_C0_3:
22822 case OPC_C0_4:
22823 case OPC_C0_5:
22824 case OPC_C0_6:
22825 case OPC_C0_7:
22826 case OPC_C0_8:
22827 case OPC_C0_9:
22828 case OPC_C0_A:
22829 case OPC_C0_B:
22830 case OPC_C0_C:
22831 case OPC_C0_D:
22832 case OPC_C0_E:
22833 case OPC_C0_F:
f1aa6320 22834#ifndef CONFIG_USER_ONLY
932e71cd 22835 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 22836#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
22837 break;
22838 case OPC_MFMC0:
8706c382 22839#ifndef CONFIG_USER_ONLY
932e71cd 22840 {
099e5b4d 22841 uint32_t op2;
35fbce2c 22842 TCGv t0 = tcg_temp_new();
6c5c1e20 22843
0eaef5aa 22844 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
22845 switch (op2) {
22846 case OPC_DMT:
d75c135e 22847 check_insn(ctx, ASE_MT);
9ed5726c 22848 gen_helper_dmt(t0);
35fbce2c 22849 gen_store_gpr(t0, rt);
6c5c1e20
TS
22850 break;
22851 case OPC_EMT:
d75c135e 22852 check_insn(ctx, ASE_MT);
9ed5726c 22853 gen_helper_emt(t0);
35fbce2c 22854 gen_store_gpr(t0, rt);
da80682b 22855 break;
6c5c1e20 22856 case OPC_DVPE:
d75c135e 22857 check_insn(ctx, ASE_MT);
895c2d04 22858 gen_helper_dvpe(t0, cpu_env);
35fbce2c 22859 gen_store_gpr(t0, rt);
6c5c1e20
TS
22860 break;
22861 case OPC_EVPE:
d75c135e 22862 check_insn(ctx, ASE_MT);
895c2d04 22863 gen_helper_evpe(t0, cpu_env);
35fbce2c 22864 gen_store_gpr(t0, rt);
6c5c1e20 22865 break;
01bc435b
YK
22866 case OPC_DVP:
22867 check_insn(ctx, ISA_MIPS32R6);
22868 if (ctx->vp) {
22869 gen_helper_dvp(t0, cpu_env);
22870 gen_store_gpr(t0, rt);
22871 }
22872 break;
22873 case OPC_EVP:
22874 check_insn(ctx, ISA_MIPS32R6);
22875 if (ctx->vp) {
22876 gen_helper_evp(t0, cpu_env);
22877 gen_store_gpr(t0, rt);
22878 }
22879 break;
6c5c1e20 22880 case OPC_DI:
d75c135e 22881 check_insn(ctx, ISA_MIPS32R2);
867abc7e 22882 save_cpu_state(ctx, 1);
895c2d04 22883 gen_helper_di(t0, cpu_env);
35fbce2c 22884 gen_store_gpr(t0, rt);
d2bfa6e6
MR
22885 /* Stop translation as we may have switched
22886 the execution mode. */
eeb3bba8 22887 ctx->base.is_jmp = DISAS_STOP;
6c5c1e20
TS
22888 break;
22889 case OPC_EI:
d75c135e 22890 check_insn(ctx, ISA_MIPS32R2);
867abc7e 22891 save_cpu_state(ctx, 1);
895c2d04 22892 gen_helper_ei(t0, cpu_env);
35fbce2c 22893 gen_store_gpr(t0, rt);
b28425ba
EC
22894 /* DISAS_STOP isn't sufficient, we need to ensure we break
22895 out of translated code to check for pending interrupts */
eeb3bba8
EC
22896 gen_save_pc(ctx->base.pc_next + 4);
22897 ctx->base.is_jmp = DISAS_EXIT;
6c5c1e20
TS
22898 break;
22899 default: /* Invalid */
22900 MIPS_INVAL("mfmc0");
9c708c7f 22901 generate_exception_end(ctx, EXCP_RI);
6c5c1e20
TS
22902 break;
22903 }
6c5c1e20 22904 tcg_temp_free(t0);
7a387fff 22905 }
0eaef5aa 22906#endif /* !CONFIG_USER_ONLY */
6af0bf9c 22907 break;
7a387fff 22908 case OPC_RDPGPR:
d75c135e 22909 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 22910 gen_load_srsgpr(rt, rd);
ead9360e 22911 break;
7a387fff 22912 case OPC_WRPGPR:
d75c135e 22913 check_insn(ctx, ISA_MIPS32R2);
be24bb4f 22914 gen_store_srsgpr(rt, rd);
38121543 22915 break;
6af0bf9c 22916 default:
923617a3 22917 MIPS_INVAL("cp0");
9c708c7f 22918 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
22919 break;
22920 }
22921 break;
31837be3
YK
22922 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
22923 if (ctx->insn_flags & ISA_MIPS32R6) {
22924 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
22925 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
22926 } else {
22927 /* OPC_ADDI */
22928 /* Arithmetic with immediate opcode */
22929 gen_arith_imm(ctx, op, rt, rs, imm);
22930 }
22931 break;
324d9e32 22932 case OPC_ADDIU:
d75c135e 22933 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 22934 break;
324d9e32
AJ
22935 case OPC_SLTI: /* Set on less than with immediate opcode */
22936 case OPC_SLTIU:
d75c135e 22937 gen_slt_imm(ctx, op, rt, rs, imm);
324d9e32
AJ
22938 break;
22939 case OPC_ANDI: /* Arithmetic with immediate opcode */
d4ea6acd 22940 case OPC_LUI: /* OPC_AUI */
324d9e32
AJ
22941 case OPC_ORI:
22942 case OPC_XORI:
d75c135e 22943 gen_logic_imm(ctx, op, rt, rs, imm);
324d9e32 22944 break;
c2e19f3c
AM
22945 case OPC_J: /* Jump */
22946 case OPC_JAL:
7a387fff 22947 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 22948 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
c9602061 22949 break;
31837be3
YK
22950 /* Branch */
22951 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
22952 if (ctx->insn_flags & ISA_MIPS32R6) {
22953 if (rt == 0) {
9c708c7f 22954 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
22955 break;
22956 }
22957 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
22958 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
22959 } else {
22960 /* OPC_BLEZL */
b231c103 22961 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
22962 }
22963 break;
22964 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
22965 if (ctx->insn_flags & ISA_MIPS32R6) {
22966 if (rt == 0) {
9c708c7f 22967 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
22968 break;
22969 }
22970 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
22971 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
22972 } else {
22973 /* OPC_BGTZL */
b231c103 22974 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
22975 }
22976 break;
22977 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
22978 if (rt == 0) {
22979 /* OPC_BLEZ */
b231c103 22980 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
22981 } else {
22982 check_insn(ctx, ISA_MIPS32R6);
22983 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
22984 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
22985 }
22986 break;
22987 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
22988 if (rt == 0) {
22989 /* OPC_BGTZ */
b231c103 22990 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
31837be3
YK
22991 } else {
22992 check_insn(ctx, ISA_MIPS32R6);
22993 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
22994 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
22995 }
22996 break;
22997 case OPC_BEQL:
22998 case OPC_BNEL:
d9224450 22999 check_insn(ctx, ISA_MIPS2);
fecd2646 23000 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 23001 /* Fallthrough */
31837be3
YK
23002 case OPC_BEQ:
23003 case OPC_BNE:
b231c103 23004 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
c9602061 23005 break;
d9224450
MR
23006 case OPC_LL: /* Load and stores */
23007 check_insn(ctx, ISA_MIPS2);
23008 /* Fallthrough */
23009 case OPC_LWL:
fecd2646
LA
23010 case OPC_LWR:
23011 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d9224450 23012 /* Fallthrough */
c2e19f3c
AM
23013 case OPC_LB:
23014 case OPC_LH:
23015 case OPC_LW:
23016 case OPC_LWPC:
23017 case OPC_LBU:
23018 case OPC_LHU:
d75c135e 23019 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 23020 break;
fecd2646 23021 case OPC_SWL:
7a387fff 23022 case OPC_SWR:
fecd2646 23023 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 23024 /* fall through */
c2e19f3c
AM
23025 case OPC_SB:
23026 case OPC_SH:
fecd2646 23027 case OPC_SW:
5c13fdfd 23028 gen_st(ctx, op, rt, rs, imm);
7a387fff 23029 break;
d66c7132 23030 case OPC_SC:
d9224450 23031 check_insn(ctx, ISA_MIPS2);
4368b29a 23032 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d66c7132
AJ
23033 gen_st_cond(ctx, op, rt, rs, imm);
23034 break;
7a387fff 23035 case OPC_CACHE:
bf7910c6 23036 check_insn_opc_removed(ctx, ISA_MIPS32R6);
2e15497c 23037 check_cp0_enabled(ctx);
d75c135e 23038 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
0d74a222
LA
23039 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23040 gen_cache_operation(ctx, rt, rs, imm);
23041 }
ead9360e 23042 /* Treat as NOP. */
34ae7b51 23043 break;
7a387fff 23044 case OPC_PREF:
bf7910c6 23045 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d75c135e 23046 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
ead9360e 23047 /* Treat as NOP. */
6af0bf9c 23048 break;
4ad40f36 23049
923617a3 23050 /* Floating point (COP1). */
7a387fff
TS
23051 case OPC_LWC1:
23052 case OPC_LDC1:
23053 case OPC_SWC1:
23054 case OPC_SDC1:
5ab5c041 23055 gen_cop1_ldst(ctx, op, rt, rs, imm);
6ea83fed
FB
23056 break;
23057
7a387fff 23058 case OPC_CP1:
5692c6e1
YK
23059 op1 = MASK_CP1(ctx->opcode);
23060
23061 switch (op1) {
23062 case OPC_MFHC1:
23063 case OPC_MTHC1:
5e755519 23064 check_cp1_enabled(ctx);
5692c6e1 23065 check_insn(ctx, ISA_MIPS32R2);
146dd620 23066 /* fall through */
5692c6e1
YK
23067 case OPC_MFC1:
23068 case OPC_CFC1:
23069 case OPC_MTC1:
23070 case OPC_CTC1:
23071 check_cp1_enabled(ctx);
23072 gen_cp1(ctx, op1, rt, rd);
23073 break;
d26bc211 23074#if defined(TARGET_MIPS64)
5692c6e1
YK
23075 case OPC_DMFC1:
23076 case OPC_DMTC1:
23077 check_cp1_enabled(ctx);
23078 check_insn(ctx, ISA_MIPS3);
d9224450 23079 check_mips_64(ctx);
5692c6e1
YK
23080 gen_cp1(ctx, op1, rt, rd);
23081 break;
e189e748 23082#endif
5692c6e1
YK
23083 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
23084 check_cp1_enabled(ctx);
23085 if (ctx->insn_flags & ISA_MIPS32R6) {
23086 /* OPC_BC1EQZ */
31837be3 23087 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 23088 rt, imm << 2, 4);
5692c6e1
YK
23089 } else {
23090 /* OPC_BC1ANY2 */
b8aa4598 23091 check_cop1x(ctx);
d75c135e 23092 check_insn(ctx, ASE_MIPS3D);
d75c135e 23093 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
5a5012ec 23094 (rt >> 2) & 0x7, imm << 2);
5692c6e1
YK
23095 }
23096 break;
23097 case OPC_BC1NEZ:
23098 check_cp1_enabled(ctx);
23099 check_insn(ctx, ISA_MIPS32R6);
23100 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
65935f07 23101 rt, imm << 2, 4);
5692c6e1
YK
23102 break;
23103 case OPC_BC1ANY4:
23104 check_cp1_enabled(ctx);
23105 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23106 check_cop1x(ctx);
23107 check_insn(ctx, ASE_MIPS3D);
23108 /* fall through */
23109 case OPC_BC1:
23110 check_cp1_enabled(ctx);
23111 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23112 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
23113 (rt >> 2) & 0x7, imm << 2);
23114 break;
23115 case OPC_PS_FMT:
e29c9628 23116 check_ps(ctx);
b6f3b233 23117 /* fall through */
5692c6e1
YK
23118 case OPC_S_FMT:
23119 case OPC_D_FMT:
23120 check_cp1_enabled(ctx);
23121 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
23122 (imm >> 8) & 0x7);
23123 break;
23124 case OPC_W_FMT:
23125 case OPC_L_FMT:
23126 {
23127 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
23128 check_cp1_enabled(ctx);
23129 if (ctx->insn_flags & ISA_MIPS32R6) {
23130 switch (r6_op) {
23131 case R6_OPC_CMP_AF_S:
23132 case R6_OPC_CMP_UN_S:
23133 case R6_OPC_CMP_EQ_S:
23134 case R6_OPC_CMP_UEQ_S:
23135 case R6_OPC_CMP_LT_S:
23136 case R6_OPC_CMP_ULT_S:
23137 case R6_OPC_CMP_LE_S:
23138 case R6_OPC_CMP_ULE_S:
23139 case R6_OPC_CMP_SAF_S:
23140 case R6_OPC_CMP_SUN_S:
23141 case R6_OPC_CMP_SEQ_S:
23142 case R6_OPC_CMP_SEUQ_S:
23143 case R6_OPC_CMP_SLT_S:
23144 case R6_OPC_CMP_SULT_S:
23145 case R6_OPC_CMP_SLE_S:
23146 case R6_OPC_CMP_SULE_S:
23147 case R6_OPC_CMP_OR_S:
23148 case R6_OPC_CMP_UNE_S:
23149 case R6_OPC_CMP_NE_S:
23150 case R6_OPC_CMP_SOR_S:
23151 case R6_OPC_CMP_SUNE_S:
23152 case R6_OPC_CMP_SNE_S:
23153 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
23154 break;
23155 case R6_OPC_CMP_AF_D:
23156 case R6_OPC_CMP_UN_D:
23157 case R6_OPC_CMP_EQ_D:
23158 case R6_OPC_CMP_UEQ_D:
23159 case R6_OPC_CMP_LT_D:
23160 case R6_OPC_CMP_ULT_D:
23161 case R6_OPC_CMP_LE_D:
23162 case R6_OPC_CMP_ULE_D:
23163 case R6_OPC_CMP_SAF_D:
23164 case R6_OPC_CMP_SUN_D:
23165 case R6_OPC_CMP_SEQ_D:
23166 case R6_OPC_CMP_SEUQ_D:
23167 case R6_OPC_CMP_SLT_D:
23168 case R6_OPC_CMP_SULT_D:
23169 case R6_OPC_CMP_SLE_D:
23170 case R6_OPC_CMP_SULE_D:
23171 case R6_OPC_CMP_OR_D:
23172 case R6_OPC_CMP_UNE_D:
23173 case R6_OPC_CMP_NE_D:
23174 case R6_OPC_CMP_SOR_D:
23175 case R6_OPC_CMP_SUNE_D:
23176 case R6_OPC_CMP_SNE_D:
23177 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
23178 break;
23179 default:
d2bfa6e6
MR
23180 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
23181 rt, rd, sa, (imm >> 8) & 0x7);
23182
5692c6e1 23183 break;
3f493883 23184 }
5692c6e1
YK
23185 } else {
23186 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
23187 (imm >> 8) & 0x7);
36d23958 23188 }
5692c6e1
YK
23189 break;
23190 }
23191 case OPC_BZ_V:
23192 case OPC_BNZ_V:
23193 case OPC_BZ_B:
23194 case OPC_BZ_H:
23195 case OPC_BZ_W:
23196 case OPC_BZ_D:
23197 case OPC_BNZ_B:
23198 case OPC_BNZ_H:
23199 case OPC_BNZ_W:
23200 case OPC_BNZ_D:
23201 check_insn(ctx, ASE_MSA);
23202 gen_msa_branch(env, ctx, op1);
23203 break;
23204 default:
23205 MIPS_INVAL("cp1");
9c708c7f 23206 generate_exception_end(ctx, EXCP_RI);
5692c6e1 23207 break;
6ea83fed 23208 }
4ad40f36
FB
23209 break;
23210
31837be3
YK
23211 /* Compact branches [R6] and COP2 [non-R6] */
23212 case OPC_BC: /* OPC_LWC2 */
23213 case OPC_BALC: /* OPC_SWC2 */
23214 if (ctx->insn_flags & ISA_MIPS32R6) {
23215 /* OPC_BC, OPC_BALC */
23216 gen_compute_compact_branch(ctx, op, 0, 0,
23217 sextract32(ctx->opcode << 2, 0, 28));
23218 } else {
23219 /* OPC_LWC2, OPC_SWC2 */
23220 /* COP2: Not implemented. */
23221 generate_exception_err(ctx, EXCP_CpU, 2);
23222 }
23223 break;
23224 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
23225 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
23226 if (ctx->insn_flags & ISA_MIPS32R6) {
23227 if (rs != 0) {
23228 /* OPC_BEQZC, OPC_BNEZC */
23229 gen_compute_compact_branch(ctx, op, rs, 0,
23230 sextract32(ctx->opcode << 2, 0, 23));
23231 } else {
23232 /* OPC_JIC, OPC_JIALC */
23233 gen_compute_compact_branch(ctx, op, 0, rt, imm);
23234 }
23235 } else {
23236 /* OPC_LWC2, OPC_SWC2 */
23237 /* COP2: Not implemented. */
23238 generate_exception_err(ctx, EXCP_CpU, 2);
23239 }
4ad40f36 23240 break;
bd277fa1 23241 case OPC_CP2:
d75c135e 23242 check_insn(ctx, INSN_LOONGSON2F);
bd277fa1
RH
23243 /* Note that these instructions use different fields. */
23244 gen_loongson_multimedia(ctx, sa, rd, rt);
23245 break;
4ad40f36 23246
7a387fff 23247 case OPC_CP3:
fecd2646 23248 check_insn_opc_removed(ctx, ISA_MIPS32R6);
5ab5c041 23249 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 23250 check_cp1_enabled(ctx);
36d23958
TS
23251 op1 = MASK_CP3(ctx->opcode);
23252 switch (op1) {
d9224450
MR
23253 case OPC_LUXC1:
23254 case OPC_SUXC1:
23255 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
23256 /* Fallthrough */
5a5012ec
TS
23257 case OPC_LWXC1:
23258 case OPC_LDXC1:
5a5012ec
TS
23259 case OPC_SWXC1:
23260 case OPC_SDXC1:
d9224450 23261 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
93b12ccc 23262 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 23263 break;
e0c84da7 23264 case OPC_PREFX:
d9224450 23265 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
ead9360e 23266 /* Treat as NOP. */
e0c84da7 23267 break;
5a5012ec 23268 case OPC_ALNV_PS:
d9224450
MR
23269 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
23270 /* Fallthrough */
5a5012ec
TS
23271 case OPC_MADD_S:
23272 case OPC_MADD_D:
23273 case OPC_MADD_PS:
23274 case OPC_MSUB_S:
23275 case OPC_MSUB_D:
23276 case OPC_MSUB_PS:
23277 case OPC_NMADD_S:
23278 case OPC_NMADD_D:
23279 case OPC_NMADD_PS:
23280 case OPC_NMSUB_S:
23281 case OPC_NMSUB_D:
23282 case OPC_NMSUB_PS:
d9224450 23283 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
5a5012ec
TS
23284 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
23285 break;
36d23958 23286 default:
923617a3 23287 MIPS_INVAL("cp3");
9c708c7f 23288 generate_exception_end(ctx, EXCP_RI);
36d23958
TS
23289 break;
23290 }
23291 } else {
e397ee33 23292 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 23293 }
4ad40f36
FB
23294 break;
23295
d26bc211 23296#if defined(TARGET_MIPS64)
7a387fff 23297 /* MIPS64 opcodes */
c2e19f3c
AM
23298 case OPC_LDL:
23299 case OPC_LDR:
bf7910c6 23300 case OPC_LLD:
fecd2646 23301 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 23302 /* fall through */
fecd2646 23303 case OPC_LWU:
7a387fff 23304 case OPC_LD:
d75c135e 23305 check_insn(ctx, ISA_MIPS3);
5c13fdfd 23306 check_mips_64(ctx);
d75c135e 23307 gen_ld(ctx, op, rt, rs, imm);
5c13fdfd 23308 break;
c2e19f3c
AM
23309 case OPC_SDL:
23310 case OPC_SDR:
fecd2646 23311 check_insn_opc_removed(ctx, ISA_MIPS32R6);
b6f3b233 23312 /* fall through */
7a387fff 23313 case OPC_SD:
d75c135e 23314 check_insn(ctx, ISA_MIPS3);
e189e748 23315 check_mips_64(ctx);
5c13fdfd 23316 gen_st(ctx, op, rt, rs, imm);
7a387fff 23317 break;
d66c7132 23318 case OPC_SCD:
bf7910c6 23319 check_insn_opc_removed(ctx, ISA_MIPS32R6);
d75c135e 23320 check_insn(ctx, ISA_MIPS3);
d66c7132
AJ
23321 check_mips_64(ctx);
23322 gen_st_cond(ctx, op, rt, rs, imm);
23323 break;
31837be3
YK
23324 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
23325 if (ctx->insn_flags & ISA_MIPS32R6) {
23326 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
23327 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
23328 } else {
23329 /* OPC_DADDI */
23330 check_insn(ctx, ISA_MIPS3);
23331 check_mips_64(ctx);
23332 gen_arith_imm(ctx, op, rt, rs, imm);
23333 }
23334 break;
324d9e32 23335 case OPC_DADDIU:
d75c135e 23336 check_insn(ctx, ISA_MIPS3);
e189e748 23337 check_mips_64(ctx);
d75c135e 23338 gen_arith_imm(ctx, op, rt, rs, imm);
7a387fff 23339 break;
31837be3
YK
23340#else
23341 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
23342 if (ctx->insn_flags & ISA_MIPS32R6) {
23343 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
23344 } else {
23345 MIPS_INVAL("major opcode");
9c708c7f 23346 generate_exception_end(ctx, EXCP_RI);
31837be3
YK
23347 }
23348 break;
6af0bf9c 23349#endif
d4ea6acd
LA
23350 case OPC_DAUI: /* OPC_JALX */
23351 if (ctx->insn_flags & ISA_MIPS32R6) {
23352#if defined(TARGET_MIPS64)
23353 /* OPC_DAUI */
23354 check_mips_64(ctx);
db77d852
LA
23355 if (rs == 0) {
23356 generate_exception(ctx, EXCP_RI);
23357 } else if (rt != 0) {
d4ea6acd
LA
23358 TCGv t0 = tcg_temp_new();
23359 gen_load_gpr(t0, rs);
23360 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
23361 tcg_temp_free(t0);
23362 }
d4ea6acd 23363#else
9c708c7f 23364 generate_exception_end(ctx, EXCP_RI);
d4ea6acd
LA
23365 MIPS_INVAL("major opcode");
23366#endif
23367 } else {
23368 /* OPC_JALX */
23369 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
23370 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
b231c103 23371 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
d4ea6acd 23372 }
364d4831 23373 break;
4c789546 23374 case OPC_MSA: /* OPC_MDMX */
7a387fff 23375 /* MDMX: Not implemented. */
4c789546 23376 gen_msa(env, ctx);
d4ea6acd
LA
23377 break;
23378 case OPC_PCREL:
23379 check_insn(ctx, ISA_MIPS32R6);
eeb3bba8 23380 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
d4ea6acd 23381 break;
6af0bf9c 23382 default: /* Invalid */
923617a3 23383 MIPS_INVAL("major opcode");
9c708c7f 23384 generate_exception_end(ctx, EXCP_RI);
6af0bf9c
FB
23385 break;
23386 }
6af0bf9c
FB
23387}
23388
18f440ed 23389static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
6af0bf9c 23390{
18f440ed 23391 DisasContext *ctx = container_of(dcbase, DisasContext, base);
9c489ea6 23392 CPUMIPSState *env = cs->env_ptr;
12be9258 23393
18f440ed 23394 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
12be9258
EC
23395 ctx->saved_pc = -1;
23396 ctx->insn_flags = env->insn_flags;
23397 ctx->CP0_Config1 = env->CP0_Config1;
ab77fc61
DN
23398 ctx->CP0_Config3 = env->CP0_Config3;
23399 ctx->CP0_Config5 = env->CP0_Config5;
12be9258
EC
23400 ctx->btarget = 0;
23401 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
23402 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
23403 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
23404 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
23405 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
23406 ctx->PAMask = env->PAMask;
23407 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
23408 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
23409 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
23410 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
23411 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
4ad40f36 23412 /* Restore delay slot state from the tb context. */
12be9258
EC
23413 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
23414 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
23415 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
e29c9628 23416 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
12be9258
EC
23417 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
23418 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
23419 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
23420 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
23421 restore_cpu_state(env, ctx);
932e71cd 23422#ifdef CONFIG_USER_ONLY
12be9258 23423 ctx->mem_idx = MIPS_HFLAG_UM;
932e71cd 23424#else
12be9258 23425 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
932e71cd 23426#endif
12be9258
EC
23427 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
23428 MO_UNALN : MO_ALIGN;
190ce7fb 23429
18f440ed
EC
23430 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
23431 ctx->hflags);
23432}
12be9258 23433
18f440ed
EC
23434static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
23435{
23436}
b933066a 23437
18f440ed
EC
23438static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
23439{
23440 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 23441
18f440ed
EC
23442 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
23443 ctx->btarget);
23444}
31837be3 23445
18f440ed
EC
23446static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
23447 const CPUBreakpoint *bp)
23448{
23449 DisasContext *ctx = container_of(dcbase, DisasContext, base);
c9602061 23450
18f440ed
EC
23451 save_cpu_state(ctx, 1);
23452 ctx->base.is_jmp = DISAS_NORETURN;
23453 gen_helper_raise_exception_debug(cpu_env);
23454 /* The address covered by the breakpoint must be included in
23455 [tb->pc, tb->pc + tb->size) in order to for it to be
23456 properly cleared -- thus we increment the PC here so that
23457 the logic setting tb->size below does the right thing. */
23458 ctx->base.pc_next += 4;
23459 return true;
23460}
4ad40f36 23461
18f440ed
EC
23462static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
23463{
23464 CPUMIPSState *env = cs->env_ptr;
23465 DisasContext *ctx = container_of(dcbase, DisasContext, base);
23466 int insn_bytes;
23467 int is_slot;
4ad40f36 23468
18f440ed 23469 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
c533c0f4
AM
23470 if (ctx->insn_flags & ISA_NANOMIPS32) {
23471 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
23472 insn_bytes = decode_nanomips_opc(env, ctx);
23473 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
18f440ed
EC
23474 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
23475 insn_bytes = 4;
23476 decode_opc(env, ctx);
23477 } else if (ctx->insn_flags & ASE_MICROMIPS) {
23478 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
23479 insn_bytes = decode_micromips_opc(env, ctx);
23480 } else if (ctx->insn_flags & ASE_MIPS16) {
23481 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
23482 insn_bytes = decode_mips16_opc(env, ctx);
23483 } else {
23484 generate_exception_end(ctx, EXCP_RI);
23485 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
23486 return;
23487 }
faf7aaa9 23488
18f440ed
EC
23489 if (ctx->hflags & MIPS_HFLAG_BMASK) {
23490 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
23491 MIPS_HFLAG_FBNSLOT))) {
23492 /* force to generate branch as there is neither delay nor
23493 forbidden slot */
23494 is_slot = 1;
23495 }
23496 if ((ctx->hflags & MIPS_HFLAG_M16) &&
23497 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
23498 /* Force to generate branch as microMIPS R6 doesn't restrict
23499 branches in the forbidden slot. */
23500 is_slot = 1;
eeb3bba8 23501 }
18f440ed
EC
23502 }
23503 if (is_slot) {
23504 gen_branch(ctx, insn_bytes);
23505 }
23506 ctx->base.pc_next += insn_bytes;
1b530a6d 23507
18f440ed
EC
23508 if (ctx->base.is_jmp != DISAS_NEXT) {
23509 return;
6af0bf9c 23510 }
18f440ed
EC
23511 /* Execute a branch and its delay slot as a single instruction.
23512 This is what GDB expects and is consistent with what the
23513 hardware does (e.g. if a delay slot instruction faults, the
23514 reported PC is the PC of the branch). */
23515 if (ctx->base.singlestep_enabled &&
23516 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
23517 ctx->base.is_jmp = DISAS_TOO_MANY;
23518 }
23519 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
23520 ctx->base.is_jmp = DISAS_TOO_MANY;
ed2803da 23521 }
18f440ed
EC
23522}
23523
23524static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
23525{
23526 DisasContext *ctx = container_of(dcbase, DisasContext, base);
23527
12be9258
EC
23528 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
23529 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
9c708c7f 23530 gen_helper_raise_exception_debug(cpu_env);
16c00cb2 23531 } else {
12be9258 23532 switch (ctx->base.is_jmp) {
b28425ba 23533 case DISAS_STOP:
12be9258 23534 gen_save_pc(ctx->base.pc_next);
cd314a7d 23535 tcg_gen_lookup_and_goto_ptr();
df1561e2 23536 break;
b28425ba 23537 case DISAS_NEXT:
18f440ed 23538 case DISAS_TOO_MANY:
12be9258
EC
23539 save_cpu_state(ctx, 0);
23540 gen_goto_tb(ctx, 0, ctx->base.pc_next);
16c00cb2 23541 break;
b28425ba 23542 case DISAS_EXIT:
07ea28b4 23543 tcg_gen_exit_tb(NULL, 0);
16c00cb2 23544 break;
b28425ba 23545 case DISAS_NORETURN:
5a5012ec 23546 break;
18f440ed
EC
23547 default:
23548 g_assert_not_reached();
6958549d 23549 }
6af0bf9c 23550 }
18f440ed
EC
23551}
23552
23553static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
23554{
23555 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
23556 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
23557}
23558
23559static const TranslatorOps mips_tr_ops = {
23560 .init_disas_context = mips_tr_init_disas_context,
23561 .tb_start = mips_tr_tb_start,
23562 .insn_start = mips_tr_insn_start,
23563 .breakpoint_check = mips_tr_breakpoint_check,
23564 .translate_insn = mips_tr_translate_insn,
23565 .tb_stop = mips_tr_tb_stop,
23566 .disas_log = mips_tr_disas_log,
23567};
23568
23569void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
23570{
23571 DisasContext ctx;
23572
23573 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
6af0bf9c
FB
23574}
23575
7db13fae 23576static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
8706c382 23577 int flags)
6ea83fed
FB
23578{
23579 int i;
5e755519 23580 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 23581
2a5612e6
SW
23582#define printfpr(fp) \
23583 do { \
23584 if (is_fpu64) \
23585 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
23586 " fd:%13g fs:%13g psu: %13g\n", \
23587 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
23588 (double)(fp)->fd, \
23589 (double)(fp)->fs[FP_ENDIAN_IDX], \
23590 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
23591 else { \
23592 fpr_t tmp; \
23593 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
23594 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
23595 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
23596 " fd:%13g fs:%13g psu:%13g\n", \
23597 tmp.w[FP_ENDIAN_IDX], tmp.d, \
23598 (double)tmp.fd, \
23599 (double)tmp.fs[FP_ENDIAN_IDX], \
23600 (double)tmp.fs[!FP_ENDIAN_IDX]); \
23601 } \
6ea83fed
FB
23602 } while(0)
23603
5a5012ec 23604
9a78eead
SW
23605 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
23606 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
f01be154 23607 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
23608 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
23609 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 23610 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
23611 }
23612
23613#undef printfpr
23614}
23615
878096ee
AF
23616void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
23617 int flags)
6af0bf9c 23618{
878096ee
AF
23619 MIPSCPU *cpu = MIPS_CPU(cs);
23620 CPUMIPSState *env = &cpu->env;
6af0bf9c 23621 int i;
3b46e624 23622
a7200c9f
SW
23623 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
23624 " LO=0x" TARGET_FMT_lx " ds %04x "
23625 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
3d5be870
TS
23626 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
23627 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
23628 for (i = 0; i < 32; i++) {
23629 if ((i & 3) == 0)
23630 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 23631 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
23632 if ((i & 3) == 3)
23633 cpu_fprintf(f, "\n");
23634 }
568b600d 23635
3594c774 23636 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 23637 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
284b731a
LA
23638 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
23639 PRIx64 "\n",
5499b6ff 23640 env->CP0_Config0, env->CP0_Config1, env->lladdr);
27e1fb13
MR
23641 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
23642 env->CP0_Config2, env->CP0_Config3);
23643 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
23644 env->CP0_Config4, env->CP0_Config5);
1cc5af69 23645 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
7a387fff 23646 fpu_dump_state(env, f, cpu_fprintf, flags);
1cc5af69 23647 }
6af0bf9c
FB
23648}
23649
78ce64f4 23650void mips_tcg_init(void)
39454628 23651{
f01be154 23652 int i;
39454628 23653
f764718d 23654 cpu_gpr[0] = NULL;
bb928dbe 23655 for (i = 1; i < 32; i++)
e1ccc054 23656 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
7db13fae 23657 offsetof(CPUMIPSState, active_tc.gpr[i]),
4b2eb8d2 23658 regnames[i]);
d73ee8a2 23659
863f264d
YK
23660 for (i = 0; i < 32; i++) {
23661 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
23662 msa_wr_d[i * 2] =
e1ccc054 23663 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
cb269f27
YK
23664 /* The scalar floating-point unit (FPU) registers are mapped on
23665 * the MSA vector registers. */
23666 fpu_f64[i] = msa_wr_d[i * 2];
863f264d
YK
23667 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
23668 msa_wr_d[i * 2 + 1] =
e1ccc054 23669 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
863f264d
YK
23670 }
23671
e1ccc054 23672 cpu_PC = tcg_global_mem_new(cpu_env,
7db13fae 23673 offsetof(CPUMIPSState, active_tc.PC), "PC");
4b2eb8d2 23674 for (i = 0; i < MIPS_DSP_ACC; i++) {
e1ccc054 23675 cpu_HI[i] = tcg_global_mem_new(cpu_env,
7db13fae 23676 offsetof(CPUMIPSState, active_tc.HI[i]),
4b2eb8d2 23677 regnames_HI[i]);
e1ccc054 23678 cpu_LO[i] = tcg_global_mem_new(cpu_env,
7db13fae 23679 offsetof(CPUMIPSState, active_tc.LO[i]),
4b2eb8d2 23680 regnames_LO[i]);
4b2eb8d2 23681 }
e1ccc054 23682 cpu_dspctrl = tcg_global_mem_new(cpu_env,
7db13fae 23683 offsetof(CPUMIPSState, active_tc.DSPControl),
4b2eb8d2 23684 "DSPControl");
e1ccc054 23685 bcond = tcg_global_mem_new(cpu_env,
7db13fae 23686 offsetof(CPUMIPSState, bcond), "bcond");
e1ccc054 23687 btarget = tcg_global_mem_new(cpu_env,
7db13fae 23688 offsetof(CPUMIPSState, btarget), "btarget");
e1ccc054 23689 hflags = tcg_global_mem_new_i32(cpu_env,
7db13fae 23690 offsetof(CPUMIPSState, hflags), "hflags");
41db4607 23691
e1ccc054 23692 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
7db13fae 23693 offsetof(CPUMIPSState, active_fpu.fcr0),
a7812ae4 23694 "fcr0");
e1ccc054 23695 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
7db13fae 23696 offsetof(CPUMIPSState, active_fpu.fcr31),
a7812ae4 23697 "fcr31");
39454628
TS
23698}
23699
5b27a92d 23700#include "translate_init.inc.c"
aaed909a 23701
27e38392
PMD
23702void cpu_mips_realize_env(CPUMIPSState *env)
23703{
23704 env->exception_base = (int32_t)0xBFC00000;
23705
23706#ifndef CONFIG_USER_ONLY
23707 mmu_init(env, env->cpu_model);
23708#endif
23709 fpu_init(env, env->cpu_model);
23710 mvp_init(env, env->cpu_model);
23711}
23712
a7519f2b 23713bool cpu_supports_cps_smp(const char *cpu_type)
bff384a4 23714{
a7519f2b
IM
23715 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
23716 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
bff384a4
LA
23717}
23718
a7519f2b 23719bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
bed9e5ce 23720{
a7519f2b
IM
23721 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
23722 return (mcc->cpu_def->insn_flags & isa) != 0;
bed9e5ce
PB
23723}
23724
89777fd1
LA
23725void cpu_set_exception_base(int vp_index, target_ulong address)
23726{
23727 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
23728 vp->env.exception_base = address;
23729}
23730
1bba0dc9 23731void cpu_state_reset(CPUMIPSState *env)
6ae81775 23732{
55e5c285
AF
23733 MIPSCPU *cpu = mips_env_get_cpu(env);
23734 CPUState *cs = CPU(cpu);
6ae81775 23735
51cc2e78
BS
23736 /* Reset registers to their default values */
23737 env->CP0_PRid = env->cpu_model->CP0_PRid;
23738 env->CP0_Config0 = env->cpu_model->CP0_Config0;
23739#ifdef TARGET_WORDS_BIGENDIAN
23740 env->CP0_Config0 |= (1 << CP0C0_BE);
23741#endif
23742 env->CP0_Config1 = env->cpu_model->CP0_Config1;
23743 env->CP0_Config2 = env->cpu_model->CP0_Config2;
23744 env->CP0_Config3 = env->cpu_model->CP0_Config3;
b4160af1
PJ
23745 env->CP0_Config4 = env->cpu_model->CP0_Config4;
23746 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
b4dd99a3
PJ
23747 env->CP0_Config5 = env->cpu_model->CP0_Config5;
23748 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
51cc2e78
BS
23749 env->CP0_Config6 = env->cpu_model->CP0_Config6;
23750 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
23751 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
23752 << env->cpu_model->CP0_LLAddr_shift;
23753 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
23754 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
23755 env->CCRes = env->cpu_model->CCRes;
23756 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
23757 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
23758 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
23759 env->current_tc = 0;
23760 env->SEGBITS = env->cpu_model->SEGBITS;
23761 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
23762#if defined(TARGET_MIPS64)
23763 if (env->cpu_model->insn_flags & ISA_MIPS3) {
23764 env->SEGMask |= 3ULL << 62;
23765 }
23766#endif
23767 env->PABITS = env->cpu_model->PABITS;
51cc2e78
BS
23768 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
23769 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
23770 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
23771 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
23772 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
23773 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
23774 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
23775 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
23776 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
23777 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
7207c7f9
LA
23778 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
23779 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
74dbf824 23780 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
f1cb0951 23781 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
599bc5e8 23782 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
ba5c79f2 23783 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
863f264d 23784 env->msair = env->cpu_model->MSAIR;
51cc2e78
BS
23785 env->insn_flags = env->cpu_model->insn_flags;
23786
0eaef5aa 23787#if defined(CONFIG_USER_ONLY)
03e6e501 23788 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
68473f15
RH
23789# ifdef TARGET_MIPS64
23790 /* Enable 64-bit register mode. */
23791 env->CP0_Status |= (1 << CP0St_PX);
23792# endif
23793# ifdef TARGET_ABI_MIPSN64
23794 /* Enable 64-bit address mode. */
23795 env->CP0_Status |= (1 << CP0St_UX);
23796# endif
94159135
MI
23797 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
23798 hardware registers. */
23799 env->CP0_HWREna |= 0x0000000F;
91a75935 23800 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
03e6e501 23801 env->CP0_Status |= (1 << CP0St_CU1);
91a75935 23802 }
6f0af304
PJ
23803 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
23804 env->CP0_Status |= (1 << CP0St_MX);
853c3240 23805 }
4d66261f
PJ
23806# if defined(TARGET_MIPS64)
23807 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
23808 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
23809 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
68473f15
RH
23810 env->CP0_Status |= (1 << CP0St_FR);
23811 }
4d66261f 23812# endif
932e71cd
AJ
23813#else
23814 if (env->hflags & MIPS_HFLAG_BMASK) {
23815 /* If the exception was raised from a delay slot,
23816 come back to the jump. */
c3577479
MR
23817 env->CP0_ErrorEPC = (env->active_tc.PC
23818 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
aa328add 23819 } else {
932e71cd
AJ
23820 env->CP0_ErrorEPC = env->active_tc.PC;
23821 }
89777fd1 23822 env->active_tc.PC = env->exception_base;
51cc2e78
BS
23823 env->CP0_Random = env->tlb->nb_tlb - 1;
23824 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd 23825 env->CP0_Wired = 0;
01bc435b 23826 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
0a2672b7 23827 env->CP0_EBase = (cs->cpu_index & 0x3FF);
d3d93c6c 23828 if (mips_um_ksegs_enabled()) {
0a2672b7
JH
23829 env->CP0_EBase |= 0x40000000;
23830 } else {
74dbf824 23831 env->CP0_EBase |= (int32_t)0x80000000;
0a2672b7 23832 }
c870e3f5
YK
23833 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
23834 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
23835 }
a0c80608
PB
23836 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
23837 0x3ff : 0xff;
932e71cd
AJ
23838 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
23839 /* vectored interrupts not implemented, timer on int 7,
23840 no performance counters. */
23841 env->CP0_IntCtl = 0xe0000000;
23842 {
23843 int i;
23844
23845 for (i = 0; i < 7; i++) {
23846 env->CP0_WatchLo[i] = 0;
23847 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 23848 }
932e71cd
AJ
23849 env->CP0_WatchLo[7] = 0;
23850 env->CP0_WatchHi[7] = 0;
fd88b6ab 23851 }
932e71cd
AJ
23852 /* Count register increments in debug mode, EJTAG version 1 */
23853 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9e56e756 23854
4b69c7e2
JH
23855 cpu_mips_store_count(env, 1);
23856
9e56e756
EI
23857 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
23858 int i;
23859
23860 /* Only TC0 on VPE 0 starts as active. */
23861 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
55e5c285 23862 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
9e56e756
EI
23863 env->tcs[i].CP0_TCHalt = 1;
23864 }
23865 env->active_tc.CP0_TCHalt = 1;
259186a7 23866 cs->halted = 1;
9e56e756 23867
55e5c285 23868 if (cs->cpu_index == 0) {
9e56e756
EI
23869 /* VPE0 starts up enabled. */
23870 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
23871 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
23872
23873 /* TC0 starts up unhalted. */
259186a7 23874 cs->halted = 0;
9e56e756
EI
23875 env->active_tc.CP0_TCHalt = 0;
23876 env->tcs[0].CP0_TCHalt = 0;
23877 /* With thread 0 active. */
23878 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
23879 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
23880 }
23881 }
cec56a73
JH
23882
23883 /*
23884 * Configure default legacy segmentation control. We use this regardless of
23885 * whether segmentation control is presented to the guest.
23886 */
23887 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
23888 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
23889 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
23890 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
23891 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
23892 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
23893 (2 << CP0SC_C);
23894 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
23895 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
23896 (3 << CP0SC_C)) << 16;
23897 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
23898 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
23899 (1 << CP0SC_EU) | (2 << CP0SC_C);
23900 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
23901 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
23902 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
23903 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
23904 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
51cc2e78 23905#endif
ddc584bd
LA
23906 if ((env->insn_flags & ISA_MIPS32R6) &&
23907 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
23908 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
23909 env->CP0_Status |= (1 << CP0St_FR);
23910 }
23911
0bbc0396
SM
23912 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
23913 /* microMIPS on reset when Config3.ISA is 3 */
0305d194
YK
23914 env->hflags |= MIPS_HFLAG_M16;
23915 }
23916
863f264d
YK
23917 /* MSA */
23918 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
23919 msa_reset(env);
23920 }
23921
03e6e501 23922 compute_hflags(env);
599bc5e8 23923 restore_fp_status(env);
e117f526 23924 restore_pamask(env);
27103424 23925 cs->exception_index = EXCP_NONE;
3b3c1694
LA
23926
23927 if (semihosting_get_argc()) {
23928 /* UHI interface can be used to obtain argc and argv */
23929 env->active_tc.gpr[4] = -1;
23930 }
6af0bf9c 23931}
d2856f1a 23932
bad729e2
RH
23933void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
23934 target_ulong *data)
d2856f1a 23935{
bad729e2 23936 env->active_tc.PC = data[0];
d2856f1a 23937 env->hflags &= ~MIPS_HFLAG_BMASK;
bad729e2 23938 env->hflags |= data[1];
4636401d
AJ
23939 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
23940 case MIPS_HFLAG_BR:
23941 break;
23942 case MIPS_HFLAG_BC:
23943 case MIPS_HFLAG_BL:
23944 case MIPS_HFLAG_B:
bad729e2 23945 env->btarget = data[2];
4636401d
AJ
23946 break;
23947 }
d2856f1a 23948}